Skip to content

Commit 1c07f6f

Browse files
authored
Improve commit amend selection (#994)
* Improve commit amend selection * Add vertical more icon Refactor commit message component * Fix test * Add documentation * Fix ResetRevertDialog
1 parent feb26f3 commit 1c07f6f

File tree

12 files changed

+547
-279
lines changed

12 files changed

+547
-279
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@
7676
"nbdime-jupyterlab": "^2.1.0",
7777
"react": "^17.0.1",
7878
"react-dom": "^17.0.1",
79-
"react-textarea-autosize": "^7.1.2",
8079
"react-virtualized-auto-sizer": "^1.0.2",
8180
"react-window": "^1.8.5",
8281
"typestyle": "^2.0.1"

src/components/CommitBox.tsx

Lines changed: 177 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,47 @@
11
import { TranslationBundle } from '@jupyterlab/translation';
2+
import { checkIcon } from '@jupyterlab/ui-components';
23
import { CommandRegistry } from '@lumino/commands';
4+
import Button from '@material-ui/core/Button';
5+
import ButtonGroup from '@material-ui/core/ButtonGroup';
6+
import ClickAwayListener from '@material-ui/core/ClickAwayListener';
7+
import Grow from '@material-ui/core/Grow';
8+
import MenuItem from '@material-ui/core/MenuItem';
9+
import MenuList from '@material-ui/core/MenuList';
10+
import Paper from '@material-ui/core/Paper';
11+
import Popper from '@material-ui/core/Popper';
312
import * as React from 'react';
4-
import TextareaAutosize from 'react-textarea-autosize';
13+
import { classes } from 'typestyle';
14+
import { listItemIconClass } from '../style/BranchMenu';
515
import {
616
commitButtonClass,
7-
commitDescriptionClass,
817
commitFormClass,
9-
commitSummaryClass,
10-
commitInputWrapperClass
18+
commitPaperClass,
19+
commitRoot,
20+
commitVariantSelector,
21+
disabledStyle
1122
} from '../style/CommitBox';
23+
import { verticalMoreIcon } from '../style/icons';
24+
import {
25+
listItemBoldTitleClass,
26+
listItemContentClass,
27+
listItemDescClass
28+
} from '../style/NewBranchDialog';
1229
import { CommandIDs } from '../tokens';
30+
import { CommitMessage } from './CommitMessage';
31+
32+
/**
33+
* Commit action
34+
*/
35+
interface ICommitVariant {
36+
/**
37+
* Action title
38+
*/
39+
title: string;
40+
/**
41+
* Action description
42+
*/
43+
description: string;
44+
}
1345

1446
/**
1547
* Interface describing component properties.
@@ -46,7 +78,7 @@ export interface ICommitBoxProps {
4678
description: string;
4779

4880
/**
49-
* Whether the "amend" checkbox is checked
81+
* Whether commit is amending the previous one or not
5082
*/
5183
amend: boolean;
5284

@@ -79,10 +111,23 @@ export interface ICommitBoxProps {
79111
onCommit: () => Promise<void>;
80112
}
81113

114+
/**
115+
* CommitBox state
116+
*/
117+
export interface ICommitBoxState {
118+
/**
119+
* Whether the commit variant menu is opened or not.
120+
*/
121+
open: boolean;
122+
}
123+
82124
/**
83125
* React component for entering a commit message.
84126
*/
85-
export class CommitBox extends React.Component<ICommitBoxProps> {
127+
export class CommitBox extends React.Component<
128+
ICommitBoxProps,
129+
ICommitBoxState
130+
> {
86131
/**
87132
* Returns a React component for entering a commit message.
88133
*
@@ -91,6 +136,25 @@ export class CommitBox extends React.Component<ICommitBoxProps> {
91136
*/
92137
constructor(props: ICommitBoxProps) {
93138
super(props);
139+
this._options.push(
140+
{
141+
title: this.props.trans.__('Create a new commit'),
142+
description: this.props.trans.__(
143+
'New commit will be created and show up as a next one after the previous commit (default).'
144+
)
145+
},
146+
{
147+
title: this.props.trans.__('Amend previous commit'),
148+
description: this.props.trans.__(
149+
'Staged changes will be added to the previous commit and its date will be updated.'
150+
)
151+
}
152+
);
153+
this._anchorRef = React.createRef<HTMLDivElement>();
154+
155+
this.state = {
156+
open: false
157+
};
94158
}
95159

96160
componentDidMount(): void {
@@ -122,58 +186,92 @@ export class CommitBox extends React.Component<ICommitBoxProps> {
122186
shortcutHint
123187
);
124188
return (
125-
<form className={[commitFormClass, 'jp-git-CommitBox'].join(' ')}>
126-
<input
127-
className={commitSummaryClass}
128-
type="text"
129-
placeholder={summaryPlaceholder}
130-
title={
131-
this.props.amend
132-
? this.props.trans.__(
133-
'Amending the commit will re-use the previous commit summary'
134-
)
135-
: this.props.trans.__(
136-
'Enter a commit message summary (a single line, preferably less than 50 characters)'
137-
)
138-
}
139-
value={this.props.summary}
140-
onChange={this._onSummaryChange}
141-
onKeyPress={this._onSummaryKeyPress}
189+
<div className={classes(commitFormClass, 'jp-git-CommitBox')}>
190+
<CommitMessage
191+
trans={this.props.trans}
192+
summary={this.props.summary}
193+
summaryPlaceholder={summaryPlaceholder}
194+
description={this.props.description}
142195
disabled={this.props.amend}
196+
setSummary={this.props.setSummary}
197+
setDescription={this.props.setDescription}
143198
/>
144-
<TextareaAutosize
145-
className={commitDescriptionClass}
146-
minRows={5}
147-
placeholder={this.props.trans.__('Description (optional)')}
148-
title={
149-
this.props.amend
150-
? this.props.trans.__(
151-
'Amending the commit will re-use the previous commit summary'
152-
)
153-
: this.props.trans.__('Enter a commit message description')
154-
}
155-
value={this.props.description}
156-
onChange={this._onDescriptionChange}
157-
disabled={this.props.amend}
158-
/>
159-
<div className={commitInputWrapperClass}>
160-
<input
161-
className={commitButtonClass}
162-
type="button"
199+
<ButtonGroup ref={this._anchorRef} fullWidth={true} size="small">
200+
<Button
201+
classes={{
202+
root: commitButtonClass,
203+
disabled: disabledStyle
204+
}}
163205
title={title}
164-
value={this.props.label}
165206
disabled={disabled}
166207
onClick={this.props.onCommit}
167-
/>
168-
<input
169-
type="checkbox"
170-
id="commit-amend"
171-
onChange={this._onAmendChange}
172-
checked={this.props.amend}
173-
/>
174-
<label htmlFor="commit-amend">Amend</label>
175-
</div>
176-
</form>
208+
>
209+
{this.props.label}
210+
</Button>
211+
<Button
212+
classes={{
213+
root: commitButtonClass
214+
}}
215+
className={commitVariantSelector}
216+
size="small"
217+
aria-controls={this.state.open ? 'split-button-menu' : undefined}
218+
aria-expanded={this.state.open ? 'true' : undefined}
219+
aria-label="select commit variant"
220+
aria-haspopup="menu"
221+
onClick={this._handleToggle}
222+
>
223+
<verticalMoreIcon.react tag="span" />
224+
</Button>
225+
</ButtonGroup>
226+
<Popper
227+
open={this.state.open}
228+
anchorEl={this._anchorRef.current}
229+
role={undefined}
230+
transition
231+
disablePortal
232+
>
233+
{({ TransitionProps }) => (
234+
<Grow {...TransitionProps}>
235+
<Paper
236+
classes={{ root: commitRoot }}
237+
className={commitPaperClass}
238+
>
239+
<ClickAwayListener onClickAway={this._handleClose}>
240+
<MenuList id="split-button-menu">
241+
{this._options.map((option, index) => (
242+
<MenuItem
243+
key={option.title}
244+
classes={{ root: commitRoot }}
245+
selected={this.props.amend ? index === 1 : index === 0}
246+
onClick={event =>
247+
this._handleMenuItemClick(event, index)
248+
}
249+
>
250+
{(this.props.amend ? index === 1 : index === 0) ? (
251+
<checkIcon.react
252+
className={listItemIconClass}
253+
tag="span"
254+
/>
255+
) : (
256+
<span className={listItemIconClass} />
257+
)}
258+
<div className={listItemContentClass}>
259+
<p className={listItemBoldTitleClass}>
260+
{option.title}
261+
</p>
262+
<p className={listItemDescClass}>
263+
{option.description}
264+
</p>
265+
</div>
266+
</MenuItem>
267+
))}
268+
</MenuList>
269+
</ClickAwayListener>
270+
</Paper>
271+
</Grow>
272+
)}
273+
</Popper>
274+
</div>
177275
);
178276
}
179277

@@ -198,45 +296,39 @@ export class CommitBox extends React.Component<ICommitBoxProps> {
198296
};
199297

200298
/**
201-
* Callback invoked upon updating a commit message description.
202-
*
203-
* @param event - event object
299+
* Close the commit variant menu if needed.
204300
*/
205-
private _onDescriptionChange = (event: any): void => {
206-
this.props.setDescription(event.target.value);
207-
};
301+
private _handleClose = (
302+
event: React.MouseEvent<Document, MouseEvent>
303+
): void => {
304+
if (
305+
this._anchorRef.current &&
306+
this._anchorRef.current.contains(event.target as HTMLElement)
307+
) {
308+
return;
309+
}
208310

209-
/**
210-
* Callback invoked upon updating a commit message summary.
211-
*
212-
* @param event - event object
213-
*/
214-
private _onSummaryChange = (event: any): void => {
215-
this.props.setSummary(event.target.value);
311+
this.setState({ open: false });
216312
};
217313

218314
/**
219-
* Callback invoked when the amend checkbox is toggled
220-
*
221-
* @param event - event object
315+
* Handle commit variant menu item click
222316
*/
223-
private _onAmendChange = (event: any): void => {
224-
this.props.setAmend(event.target.checked);
317+
private _handleMenuItemClick = (
318+
event: React.MouseEvent<HTMLLIElement, MouseEvent>,
319+
index: number
320+
): void => {
321+
this.setState({
322+
open: false
323+
});
324+
this.props.setAmend(index === 1);
225325
};
226326

227327
/**
228-
* Callback invoked upon a `'keypress'` event when entering a commit message summary.
229-
*
230-
* ## Notes
231-
*
232-
* - Prevents triggering a `'submit'` action when hitting the `ENTER` key while entering a commit message summary.
233-
*
234-
* @param event - event object
328+
* Toggle state of the commit variant menu visibility
235329
*/
236-
private _onSummaryKeyPress = (event: React.KeyboardEvent): void => {
237-
if (event.key === 'Enter') {
238-
event.preventDefault();
239-
}
330+
private _handleToggle = (): void => {
331+
this.setState({ open: !this.state.open });
240332
};
241333

242334
/**
@@ -255,4 +347,7 @@ export class CommitBox extends React.Component<ICommitBoxProps> {
255347
this.props.onCommit();
256348
}
257349
};
350+
351+
private _anchorRef: React.RefObject<HTMLDivElement>;
352+
private _options: ICommitVariant[] = [];
258353
}

0 commit comments

Comments
 (0)