Skip to content

Commit 4b4df98

Browse files
committed
Style repository path
1 parent b3b41f4 commit 4b4df98

File tree

4 files changed

+159
-170
lines changed

4 files changed

+159
-170
lines changed

LICENSE

-26
Original file line numberDiff line numberDiff line change
@@ -27,29 +27,3 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2727
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2828
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2929
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30-
31-
---
32-
33-
This software makes use of octicons (https://github.com/primer/octicons) licensed under
34-
35-
MIT License
36-
37-
Copyright (c) 2019 GitHub Inc.
38-
39-
Permission is hereby granted, free of charge, to any person obtaining a copy
40-
of this software and associated documentation files (the "Software"), to deal
41-
in the Software without restriction, including without limitation the rights
42-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
43-
copies of the Software, and to permit persons to whom the Software is
44-
furnished to do so, subject to the following conditions:
45-
46-
The above copyright notice and this permission notice shall be included in all
47-
copies or substantial portions of the Software.
48-
49-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
52-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
53-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
54-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
55-
SOFTWARE.

src/components/PathHeader.tsx

+78-64
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,46 @@
1+
import * as React from 'react';
12
import { Dialog, showDialog, UseSignal } from '@jupyterlab/apputils';
23
import { PathExt } from '@jupyterlab/coreutils';
3-
import { FileDialog, FileBrowserModel } from '@jupyterlab/filebrowser';
4+
import { FileBrowserModel, FileDialog } from '@jupyterlab/filebrowser';
45
import { DefaultIconReact } from '@jupyterlab/ui-components';
5-
import * as React from 'react';
66
import { classes } from 'typestyle';
77
import {
88
gitPullStyle,
99
gitPushStyle,
10+
noRepoPathStyle,
1011
pinIconStyle,
1112
repoPathStyle,
13+
repoPinStyle,
1214
repoRefreshStyle,
1315
repoStyle,
14-
repoPinStyle,
15-
repoPinnedStyle
16+
separatorStyle,
17+
toolBarStyle
1618
} from '../style/PathHeaderStyle';
19+
import { IGitExtension } from '../tokens';
1720
import { GitCredentialsForm } from '../widgets/CredentialsBox';
1821
import { GitPullPushDialog, Operation } from '../widgets/gitPushPull';
19-
import { IGitExtension } from '../tokens';
2022

23+
/**
24+
* Properties of the PathHeader React component
25+
*/
2126
export interface IPathHeaderProps {
27+
/**
28+
* Git extension model
29+
*/
2230
model: IGitExtension;
31+
/**
32+
* File browser model
33+
*/
2334
fileBrowserModel: FileBrowserModel;
35+
/**
36+
* Refresh UI callback
37+
*/
2438
refresh: () => Promise<void>;
2539
}
2640

2741
/**
2842
* Displays the error dialog when the Git Push/Pull operation fails.
43+
*
2944
* @param title the title of the error dialog
3045
* @param body the message to be shown in the body of the modal.
3146
*/
@@ -86,7 +101,8 @@ async function selectGitRepository(
86101
model.pathRepository = folder.path;
87102
} else if (fileModel.path !== folder.path) {
88103
// Change current filebrowser path
89-
fileModel.cd('/' + folder.path);
104+
// => will be propagated to path repository
105+
fileModel.cd(`/${folder.path}`);
90106
}
91107
}
92108
}
@@ -107,14 +123,9 @@ export const PathHeader: React.FunctionComponent<IPathHeaderProps> = (
107123
});
108124
});
109125

110-
const pinStyles = [repoPinStyle, 'jp-Icon-16'];
111-
if (pin) {
112-
pinStyles.push(repoPinnedStyle);
113-
}
114-
115126
return (
116-
<div>
117-
<div className={repoStyle}>
127+
<React.Fragment>
128+
<div className={toolBarStyle}>
118129
<button
119130
className={classes(gitPullStyle, 'jp-Icon-16')}
120131
title={'Pull latest changes'}
@@ -143,58 +154,61 @@ export const PathHeader: React.FunctionComponent<IPathHeaderProps> = (
143154
onClick={() => props.refresh()}
144155
/>
145156
</div>
146-
<div>
147-
<UseSignal
148-
signal={props.model.repositoryChanged}
149-
initialArgs={{
150-
name: 'pathRepository',
151-
oldValue: null,
152-
newValue: props.model.pathRepository
153-
}}
154-
>
155-
{(_, change) => {
156-
const pathStyles = [repoPathStyle];
157-
let pinTitle = 'the repository path';
158-
if (props.model.repositoryPinned) {
159-
pinTitle = 'Unpin ' + pinTitle;
160-
} else {
161-
pinTitle = 'Pin ' + pinTitle;
162-
}
157+
<UseSignal
158+
signal={props.model.repositoryChanged}
159+
initialArgs={{
160+
name: 'pathRepository',
161+
oldValue: null,
162+
newValue: props.model.pathRepository
163+
}}
164+
>
165+
{(_, change) => {
166+
const pathStyles = [repoPathStyle];
167+
if (!change.newValue) {
168+
pathStyles.push(noRepoPathStyle);
169+
}
163170

164-
return (
165-
<React.Fragment>
166-
<label className={repoPinStyle} title={pinTitle}>
167-
<input
168-
type="checkbox"
169-
checked={props.model.repositoryPinned}
170-
onChange={() => {
171-
props.model.repositoryPinned = !props.model
172-
.repositoryPinned;
173-
setPin(props.model.repositoryPinned);
174-
}}
175-
/>
176-
<DefaultIconReact
177-
className={pinIconStyle}
178-
tag="span"
179-
name="git-pin"
180-
/>
181-
</label>
182-
<span
183-
className={classes(...pathStyles)}
184-
title={change.newValue}
185-
onClick={() => {
186-
selectGitRepository(props.model, props.fileBrowserModel);
171+
let pinTitle = 'the repository path';
172+
if (pin) {
173+
pinTitle = 'Unpin ' + pinTitle;
174+
} else {
175+
pinTitle = 'Pin ' + pinTitle;
176+
}
177+
178+
return (
179+
<div className={repoStyle}>
180+
<label className={repoPinStyle} title={pinTitle}>
181+
<input
182+
type="checkbox"
183+
checked={pin}
184+
onChange={() => {
185+
props.model.repositoryPinned = !props.model
186+
.repositoryPinned;
187+
setPin(props.model.repositoryPinned);
187188
}}
188-
>
189-
{PathExt.basename(
190-
change.newValue || 'Click to select a Git repository.'
191-
)}
192-
</span>
193-
</React.Fragment>
194-
);
195-
}}
196-
</UseSignal>
197-
</div>
198-
</div>
189+
/>
190+
<DefaultIconReact
191+
className={pinIconStyle}
192+
tag="span"
193+
name="git-pin"
194+
/>
195+
</label>
196+
<span
197+
className={classes(...pathStyles)}
198+
title={change.newValue}
199+
onClick={() => {
200+
selectGitRepository(props.model, props.fileBrowserModel);
201+
}}
202+
>
203+
{change.newValue
204+
? PathExt.basename(change.newValue)
205+
: 'Click to select a Git repository.'}
206+
</span>
207+
</div>
208+
);
209+
}}
210+
</UseSignal>
211+
<div className={separatorStyle} />
212+
</React.Fragment>
199213
);
200214
};

src/style/PathHeaderStyle.ts

+73-77
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,15 @@
11
import { style } from 'typestyle';
22

3-
export const pinIconStyle = style({
4-
position: 'absolute',
5-
cursor: 'pointer',
6-
top: 0,
7-
left: 0,
8-
right: 0,
9-
bottom: 0
10-
});
3+
// Toolbar styles
114

12-
export const repoStyle = style({
5+
export const toolBarStyle = style({
136
display: 'flex',
147
flexDirection: 'row',
158
backgroundColor: 'var(--jp-layout-color1)',
169
lineHeight: 'var(--jp-private-running-item-height)',
1710
minHeight: '35px'
1811
});
1912

20-
export const repoPinStyle = style({
21-
background: 'var(--jp-layout-color1)',
22-
position: 'relative',
23-
display: 'inline-block',
24-
width: '24px',
25-
height: '24px',
26-
margin: 'auto 5px auto 5px',
27-
28-
$nest: {
29-
input: {
30-
opacity: 0,
31-
height: 0,
32-
width: 0,
33-
34-
$nest: {
35-
'&:checked': {
36-
opacity: 10
37-
}
38-
}
39-
},
40-
41-
'input:checked + svg': {
42-
fill: 'var(--jp-brand-color1)'
43-
},
44-
45-
'&:hover': {
46-
backgroundColor: 'var(--jp-layout-color2)'
47-
}
48-
}
49-
// // width: 'var(--jp-private-running-button-width)',
50-
51-
// border: 'none',
52-
// boxSizing: 'border-box',
53-
// outline: 'none',
54-
// // padding: '0px 6px',
55-
56-
// $nest: {
57-
// '&:active': {
58-
// backgroundColor: 'var(--jp-layout-color3)'
59-
// }
60-
// }
61-
});
62-
63-
export const repoPinnedStyle = style({
64-
$nest: {
65-
'.jp-icon3': {
66-
fill: 'var(--jp-brand-color1)'
67-
}
68-
}
69-
});
70-
71-
export const repoPathStyle = style({
72-
fontSize: 'var(--jp-ui-font-size1)',
73-
marginRight: '4px',
74-
paddingLeft: '4px',
75-
textOverflow: 'ellipsis',
76-
overflow: 'hidden',
77-
whiteSpace: 'nowrap',
78-
verticalAlign: 'middle',
79-
lineHeight: '33px',
80-
81-
$nest: {
82-
'&:hover': {
83-
backgroundColor: 'var(--jp-layout-color2)'
84-
}
85-
}
86-
});
87-
8813
export const repoRefreshStyle = style({
8914
width: 'var(--jp-private-running-button-width)',
9015
background: 'var(--jp-layout-color1)',
@@ -156,3 +81,74 @@ export const gitPullStyle = style({
15681
}
15782
}
15883
});
84+
85+
// Path styles
86+
87+
export const repoStyle = style({
88+
display: 'flex',
89+
flexDirection: 'row',
90+
margin: '4px 12px'
91+
});
92+
93+
export const pinIconStyle = style({
94+
position: 'absolute',
95+
cursor: 'pointer',
96+
top: 0,
97+
left: 0,
98+
right: 0,
99+
bottom: 0,
100+
margin: '4px'
101+
});
102+
103+
export const repoPinStyle = style({
104+
background: 'var(--jp-layout-color1)',
105+
position: 'relative',
106+
display: 'inline-block',
107+
width: '24px',
108+
height: '24px',
109+
flex: '0 0 auto',
110+
111+
$nest: {
112+
input: {
113+
opacity: 0,
114+
height: 0,
115+
width: 0
116+
},
117+
118+
'input:checked + span': {
119+
transform: 'rotate(-45deg)'
120+
},
121+
122+
'&:hover': {
123+
backgroundColor: 'var(--jp-layout-color2)'
124+
}
125+
}
126+
});
127+
128+
export const repoPathStyle = style({
129+
flex: '1 1 auto',
130+
fontSize: 'var(--jp-ui-font-size1)',
131+
padding: '0px 4px 0px 4px',
132+
textOverflow: 'ellipsis',
133+
overflow: 'hidden',
134+
whiteSpace: 'nowrap',
135+
verticalAlign: 'middle',
136+
lineHeight: '24px',
137+
138+
$nest: {
139+
'&:hover': {
140+
backgroundColor: 'var(--jp-layout-color2)'
141+
}
142+
}
143+
});
144+
145+
export const noRepoPathStyle = style({
146+
color: 'var(--jp-ui-font-color2)'
147+
});
148+
149+
// Separator line style
150+
151+
export const separatorStyle = style({
152+
flex: '0 0 auto',
153+
borderBottom: 'var(--jp-border-width) solid var(--jp-border-color2)'
154+
});

0 commit comments

Comments
 (0)