1- import { ISettingRegistry } from '@jupyterlab/coreutils' ;
2-
31import * as React from 'react' ;
42import TextareaAutosize from 'react-textarea-autosize' ;
53import { classes } from 'typestyle' ;
6-
74import {
85 stagedCommitButtonDisabledStyle ,
96 stagedCommitButtonReadyStyle ,
@@ -13,102 +10,184 @@ import {
1310 textInputStyle
1411} from '../style/BranchHeaderStyle' ;
1512
13+ /**
14+ * Interface describing component properties.
15+ */
1616export interface ICommitBoxProps {
17+ /**
18+ * Boolean indicating whether files currently exist which have changes to commit.
19+ */
1720 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 > ;
2029}
2130
31+ /**
32+ * Interface describing component state.
33+ */
2234export interface ICommitBoxState {
2335 /**
24- * Commit message
36+ * Commit message summary.
37+ */
38+ summary : string ;
39+
40+ /**
41+ * Commit message description.
2542 */
26- value : string ;
43+ description : string ;
2744}
2845
46+ /**
47+ * React component for entering a commit message.
48+ */
2949export class CommitBox extends React . Component <
3050 ICommitBoxProps ,
3151 ICommitBoxState
3252> {
53+ /**
54+ * Returns a React component for entering a commit message.
55+ *
56+ * @param props - component properties
57+ * @returns React component
58+ */
3359 constructor ( props : ICommitBoxProps ) {
3460 super ( props ) ;
3561 this . state = {
36- value : ''
62+ summary : '' ,
63+ description : ''
3764 } ;
3865 }
3966
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+ */
7572 render ( ) {
7673 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+ />
8182 < TextareaAutosize
8283 className = { classes ( textInputStyle , stagedCommitMessageStyle ) }
83- disabled = { ! this . props . hasFiles }
8484 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 }
8889 />
8990 < input
90- className = { this . commitButtonStyle ( this . props . hasFiles ) }
91+ className = { this . _commitButtonStyle ( ) }
9192 type = "button"
9293 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 }
9896 />
9997 </ form >
10098 ) ;
10199 }
102100
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 ;
112112 }
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+ } ) ;
113192 } ;
114193}
0 commit comments