@@ -3,7 +3,7 @@ import _ from 'lodash'
33import cn from 'classnames'
44import Panel from '../../../../components/Panel/Panel'
55import DeleteFeatureModal from './DeleteFeatureModal'
6- import { Formsy , TCFormFields , SwitchButton } from 'appirio-tech-react-components'
6+ import { Icons , Formsy , TCFormFields , SwitchButton } from 'appirio-tech-react-components'
77
88require ( './FeatureForm.scss' )
99
@@ -12,38 +12,41 @@ class CustomFeatureForm extends Component {
1212 constructor ( props ) {
1313 super ( props )
1414 this . toggleFeature = this . toggleFeature . bind ( this )
15- this . state = { showDeleteModal : false }
15+ this . state = { showDeleteModal : false , editMode : false }
1616 this . onSave = this . onSave . bind ( this )
17+ this . editFeature = this . editFeature . bind ( this )
1718 this . onDelete = this . onDelete . bind ( this )
1819 this . onDeleteIntent = this . onDeleteIntent . bind ( this )
1920 this . onCancelDelete = this . onCancelDelete . bind ( this )
21+ this . onChange = this . onChange . bind ( this )
2022 }
2123
2224 componentWillMount ( ) {
2325 this . componentWillReceiveProps ( this . props )
2426 }
2527
2628 componentWillReceiveProps ( nextProps ) {
27- const previousData = this . state . data || { }
2829 this . setState ( {
29- data : nextProps . featureData || previousData ,
30- isActive : ! ! nextProps . featureData
30+ data : nextProps . featureData ,
31+ isAdded : ! ! nextProps . featureData ,
32+ isActive : ! ! nextProps . featureData && ! nextProps . featureData . disabled ,
33+ showDeleteModal : false
3134 } )
3235 }
3336
3437 toggleFeature ( ) {
35- const { removeFeature , addFeature, featureData , isEdittable } = this . props
38+ const { addFeature, isEdittable } = this . props
3639 if ( isEdittable ) {
37- if ( this . state . isActive ) {
38- // remove feature
39- removeFeature ( featureData . id )
40- } else {
41- // add feature
42- addFeature ( this . state . data )
43- }
40+ addFeature ( { ...this . state . data , disabled : ! ! this . state . isActive } )
4441 }
4542 }
4643
44+ editFeature ( ) {
45+ this . setState ( {
46+ editMode : true
47+ } )
48+ }
49+
4750 onDelete ( data ) {
4851 this . props . removeFeature ( data . id )
4952 }
@@ -59,59 +62,82 @@ class CustomFeatureForm extends Component {
5962 onSave ( data ) {
6063 const { featureData } = this . props
6164 this . props . addFeature ( _ . merge ( {
62- id : data . title . toLowerCase ( ) . replace ( ' ' , '_' ) ,
65+ id : data . title . toLowerCase ( ) . replace ( / \s / g , '_' ) ,
6366 categoryId : 'custom' ,
6467 notes : ''
6568 } , featureData , data ) )
69+ // assumes addFeature to be a synchronous call, otherwise it could lead to inconsistent UI state
70+ // e.g. if async addFeature fails, it would close the edit mode
71+ // this call is needed here because debounce call (for notes change) is closing the edit mode if
72+ // we do set the editMode in componentWillReceiveProps method
73+ this . setState ( { editMode : false } )
74+ }
75+
76+ onChange ( fieldName , value ) {
77+ const { featureData } = this . props
78+ // following check is needed to prevent adding the feature again after removing
79+ // because forms' onChange event gets fire with only form data when we lose focus from the form
80+ // alternative to this check is to put the change handler on textarea instead of form
81+ if ( featureData ) { // feature is already added
82+ const data = { }
83+ data [ fieldName ] = value
84+ this . props . updateFeature ( _ . merge ( { } , featureData , data ) )
85+ }
6686 }
6787
6888 render ( ) {
69- const { isEdittable, onCancel, featureData } = this . props
70- const { data, isActive, showDeleteModal } = this . state
71- const submitButton = ! isActive
72- ? < button type = "submit" className = "tc-btn tc-btn-primary tc-btn-md" disabled = { ! isEdittable } > Save Feature</ button >
73- : < button type = "submit" className = "tc-btn tc-btn-default tc-btn-md" disabled = { ! isEdittable } > Delete Custom Feature</ button >
74- const formAction = isActive ? this . onDeleteIntent : this . onSave
89+ const { isEdittable, onCancel } = this . props
90+ const { data, isAdded, editMode, isActive, showDeleteModal } = this . state
91+ // const _debouncedOnChange = _.debounce(this.onChange, 2000, { trailing: true, maxWait: 10000 })
7592 const formClasses = cn ( 'feature-form' , {
7693 'modal-active' : showDeleteModal
7794 } )
7895 return (
7996 < Panel className = { formClasses } >
80- < div className = "feature-title-row" >
81- < span className = "title" > { _ . get ( data , 'title' , 'Define a new feature' ) } </ span >
82- < SwitchButton
83- disabled = { ! isEdittable }
84- onChange = { this . toggleFeature }
85- name = "featue-active"
86- checked = { isActive ? 'checked' : null }
87- />
88- </ div >
97+ { ( isAdded && ! editMode ) &&
98+ < div className = "feature-title-row" >
99+ < span className = "title" > { _ . get ( data , 'title' , 'Define a new feature' ) } </ span >
100+ < div className = "feature-actions" >
101+ { isAdded &&
102+ < SwitchButton
103+ disabled = { ! isEdittable }
104+ onChange = { this . toggleFeature }
105+ name = "featue-active"
106+ checked = { isActive ? 'checked' : null }
107+ label = "Enable Feature"
108+ />
109+ }
110+ < div className = "separator" />
111+ < button className = "clean feature-edit-action" onClick = { this . editFeature } > < Icons . IconUIPencil /> </ button >
112+ < button className = "clean feature-delete-action" onClick = { this . onDeleteIntent } > < Icons . IconUITrashSimple /> </ button >
113+ </ div >
114+ </ div >
115+ }
89116 < div className = "feature-form-content" >
90- < Formsy . Form className = "custom-feature-form" disabled = { ! isEdittable } onValidSubmit = { formAction } >
91- { ! isActive &&
117+ < Formsy . Form className = "custom-feature-form" disabled = { ! isEdittable } onValidSubmit = { this . onSave } >
118+ { ( ! isAdded || editMode ) &&
92119 < TCFormFields . TextInput
93120 name = "title"
94121 label = "Feature name"
95122 validations = "minLength:1" required
96123 validationError = "Feature name is required"
97124 wrapperClass = "row"
98- // placeholder="My awesome feature"
99125 value = { _ . get ( data , 'title' , '' ) }
100126 />
101127 }
102- { ! isActive ?
128+ { ( isActive && ! editMode ) ?
103129 < TCFormFields . Textarea
104- name = "description "
105- label = "Feature description "
106- wrapperClass = "feature-description "
107- // placeholder="Briefly describe the feature, including how it will be used, and provide examples that will help designers and developers understand it."
108- value = { _ . get ( data , 'description' , '' ) }
130+ name = "notes "
131+ label = "Feature Notes "
132+ wrapperClass = "feature-notes "
133+ value = { _ . get ( data , 'notes' , '' ) }
134+ onChange = { this . onChange }
109135 />
110- : < p className = "feature-description" > { featureData . description } </ p >
136+ : null
111137 }
112138 < div className = "feature-form-actions" >
113- { ! isActive && < button type = "button" className = "tc-btn tc-btn-default tc-btn-md" onClick = { onCancel } > Cancel</ button > }
114- { submitButton }
139+ { ( ! isAdded || editMode ) && < button type = "button" className = "tc-btn tc-btn-default tc-btn-md" onClick = { onCancel } > Cancel</ button > }
140+ { ( ! isAdded || editMode ) && < button type = "submit" className = "tc-btn tc-btn-primary tc-btn-md" disabled = { ! isEdittable } > Save Feature </ button > }
115141 </ div >
116142 </ Formsy . Form >
117143 </ div >
0 commit comments