1
- import { ISettingRegistry } from '@jupyterlab/coreutils' ;
2
-
3
1
import * as React from 'react' ;
4
2
import TextareaAutosize from 'react-textarea-autosize' ;
5
3
import { classes } from 'typestyle' ;
6
-
7
4
import {
8
5
stagedCommitButtonDisabledStyle ,
9
6
stagedCommitButtonReadyStyle ,
@@ -13,102 +10,184 @@ import {
13
10
textInputStyle
14
11
} from '../style/BranchHeaderStyle' ;
15
12
13
+ /**
14
+ * Interface describing component properties.
15
+ */
16
16
export interface ICommitBoxProps {
17
+ /**
18
+ * Boolean indicating whether files currently exist which have changes to commit.
19
+ */
17
20
hasFiles : boolean ;
18
- commitFunc : ( message : string ) => Promise < void > ;
19
- settings : ISettingRegistry . ISettings ;
21
+
22
+ /**
23
+ * Callback to invoke in order to commit changes.
24
+ *
25
+ * @param msg - commit message
26
+ * @returns a promise which commits changes
27
+ */
28
+ onCommit : ( msg : string ) => Promise < void > ;
20
29
}
21
30
31
+ /**
32
+ * Interface describing component state.
33
+ */
22
34
export interface ICommitBoxState {
23
35
/**
24
- * Commit message
36
+ * Commit message summary.
37
+ */
38
+ summary : string ;
39
+
40
+ /**
41
+ * Commit message description.
25
42
*/
26
- value : string ;
43
+ description : string ;
27
44
}
28
45
46
+ /**
47
+ * React component for entering a commit message.
48
+ */
29
49
export class CommitBox extends React . Component <
30
50
ICommitBoxProps ,
31
51
ICommitBoxState
32
52
> {
53
+ /**
54
+ * Returns a React component for entering a commit message.
55
+ *
56
+ * @param props - component properties
57
+ * @returns React component
58
+ */
33
59
constructor ( props : ICommitBoxProps ) {
34
60
super ( props ) ;
35
61
this . state = {
36
- value : ''
62
+ summary : '' ,
63
+ description : ''
37
64
} ;
38
65
}
39
66
40
- /** Prevent enter key triggered 'submit' action during commit message input */
41
- onKeyPress ( event : any ) : void {
42
- if ( event . which === 13 ) {
43
- event . preventDefault ( ) ;
44
- this . setState ( { value : this . state . value + '\n' } ) ;
45
- }
46
- }
47
-
48
- /** Initalize commit message input box */
49
- initializeInput = ( ) : void => {
50
- this . setState ( {
51
- value : ''
52
- } ) ;
53
- } ;
54
-
55
- /** Handle input inside commit message box */
56
- handleChange = ( event : any ) : void => {
57
- this . setState ( {
58
- value : event . target . value
59
- } ) ;
60
- } ;
61
-
62
- /** Update state of commit message input box */
63
- commitButtonStyle = ( hasStagedFiles : boolean ) => {
64
- if ( hasStagedFiles ) {
65
- if ( this . state . value . length === 0 ) {
66
- return classes ( stagedCommitButtonStyle , stagedCommitButtonReadyStyle ) ;
67
- } else {
68
- return stagedCommitButtonStyle ;
69
- }
70
- } else {
71
- return classes ( stagedCommitButtonStyle , stagedCommitButtonDisabledStyle ) ;
72
- }
73
- } ;
74
-
67
+ /**
68
+ * Renders the component.
69
+ *
70
+ * @returns fragment
71
+ */
75
72
render ( ) {
76
73
return (
77
- < form
78
- className = { stagedCommitStyle }
79
- onKeyPress = { event => this . onKeyPress ( event ) }
80
- >
74
+ < form className = { stagedCommitStyle } >
75
+ < textarea
76
+ className = { classes ( textInputStyle , stagedCommitMessageStyle ) }
77
+ placeholder = { 'Summary (required)' }
78
+ value = { this . state . summary }
79
+ onChange = { this . _onSummaryChange }
80
+ onKeyPress = { this . _onSummaryKeyPress }
81
+ />
81
82
< TextareaAutosize
82
83
className = { classes ( textInputStyle , stagedCommitMessageStyle ) }
83
- disabled = { ! this . props . hasFiles }
84
84
minRows = { 2 }
85
- onChange = { this . handleChange }
86
- placeholder = { this . _placeholder ( ) }
87
- value = { this . state . value }
85
+ placeholder = { 'Description' }
86
+ value = { this . state . description }
87
+ onChange = { this . _onDescriptionChange }
88
+ onKeyPress = { this . _onDescriptionKeyPress }
88
89
/>
89
90
< input
90
- className = { this . commitButtonStyle ( this . props . hasFiles ) }
91
+ className = { this . _commitButtonStyle ( ) }
91
92
type = "button"
92
93
title = "Commit"
93
- disabled = { ! ( this . props . hasFiles && this . state . value ) }
94
- onClick = { ( ) => {
95
- this . props . commitFunc ( this . state . value ) ;
96
- this . initializeInput ( ) ;
97
- } }
94
+ disabled = { ! ( this . props . hasFiles && this . state . summary ) }
95
+ onClick = { this . _onCommitClick }
98
96
/>
99
97
</ form >
100
98
) ;
101
99
}
102
100
103
- protected _placeholder = ( ) : string => {
104
- if ( this . props . settings . composite [ 'simpleStaging' ] ) {
105
- return this . props . hasFiles
106
- ? 'Input message to commit selected changes'
107
- : 'Select changes to enable commit' ;
108
- } else {
109
- return this . props . hasFiles
110
- ? 'Input message to commit staged changes'
111
- : 'Stage your changes before commit' ;
101
+ /**
102
+ * Returns classes for toggling the commit button.
103
+ *
104
+ * @returns classes to apply
105
+ */
106
+ private _commitButtonStyle = ( ) : string => {
107
+ if ( this . props . hasFiles ) {
108
+ if ( this . state . summary . length === 0 ) {
109
+ return classes ( stagedCommitButtonStyle , stagedCommitButtonReadyStyle ) ;
110
+ }
111
+ return stagedCommitButtonStyle ;
112
112
}
113
+ return classes ( stagedCommitButtonStyle , stagedCommitButtonDisabledStyle ) ;
114
+ } ;
115
+
116
+ /**
117
+ * Callback invoked upon clicking a commit message submit button.
118
+ *
119
+ * @param event - event object
120
+ */
121
+ private _onCommitClick = ( ) => {
122
+ const msg = this . state . summary + '\n' + this . state . description + '\n' ;
123
+ this . props . onCommit ( msg ) ;
124
+
125
+ // NOTE: we assume here that committing changes always works and we can safely clear component state
126
+ this . _reset ( ) ;
127
+ } ;
128
+
129
+ /**
130
+ * Callback invoked upon updating a commit message description.
131
+ *
132
+ * @param event - event object
133
+ */
134
+ private _onDescriptionChange = ( event : any ) : void => {
135
+ this . setState ( {
136
+ description : event . target . value
137
+ } ) ;
138
+ } ;
139
+
140
+ /**
141
+ * Callback invoked upon a `'keypress'` event when entering a commit message description.
142
+ *
143
+ * ## Notes
144
+ *
145
+ * - Prevents triggering a `'submit'` action when hitting the `ENTER` key while entering a commit message description.
146
+ *
147
+ * @param event - event object
148
+ */
149
+ private _onDescriptionKeyPress ( event : any ) : void {
150
+ if ( event . which === 13 ) {
151
+ event . preventDefault ( ) ;
152
+ this . setState ( {
153
+ description : this . state . description + '\n'
154
+ } ) ;
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Callback invoked upon updating a commit message summary.
160
+ *
161
+ * @param event - event object
162
+ */
163
+ private _onSummaryChange = ( event : any ) : void => {
164
+ this . setState ( {
165
+ summary : event . target . value
166
+ } ) ;
167
+ } ;
168
+
169
+ /**
170
+ * Callback invoked upon a `'keypress'` event when entering a commit message summary.
171
+ *
172
+ * ## Notes
173
+ *
174
+ * - Prevents triggering a `'submit'` action when hitting the `ENTER` key while entering a commit message summary.
175
+ *
176
+ * @param event - event object
177
+ */
178
+ private _onSummaryKeyPress ( event : any ) : void {
179
+ if ( event . which === 13 ) {
180
+ event . preventDefault ( ) ;
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Resets component state (e.g., in order to re-initialize the commit message input box).
186
+ */
187
+ private _reset = ( ) : void => {
188
+ this . setState ( {
189
+ summary : '' ,
190
+ description : ''
191
+ } ) ;
113
192
} ;
114
193
}
0 commit comments