Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ class CustomFeatureForm extends Component {
}

toggleFeature() {
const { addFeature, isEdittable } = this.props
const { toggleFeature, isEdittable } = this.props
if (isEdittable) {
addFeature({ ...this.state.data, disabled: !!this.state.isActive })
toggleFeature(this.state.data.id, !!this.state.isActive)
}
}

Expand Down Expand Up @@ -65,22 +65,22 @@ class CustomFeatureForm extends Component {
id: data.title.toLowerCase().replace(/\s/g, '_'),
categoryId: 'custom',
notes: ''
}, featureData, data))
}, featureData, { title : data.title.trim() }))
// assumes addFeature to be a synchronous call, otherwise it could lead to inconsistent UI state
// e.g. if async addFeature fails, it would close the edit mode
// this call is needed here because debounce call (for notes change) is closing the edit mode if
// we do set the editMode in componentWillReceiveProps method
this.setState({ editMode : false })
}

onChange(fieldName, value) {
onChange(data){
const { featureData } = this.props
// following check is needed to prevent adding the feature again after removing
// because forms' onChange event gets fire with only form data when we lose focus from the form
// alternative to this check is to put the change handler on textarea instead of form
if (featureData) {// feature is already added
const data = {}
data[fieldName] = value
// trim the notes (as of now only notes field is auto updated)
data.notes = data.notes.trim()
this.props.updateFeature(_.merge({}, featureData, data))
}
}
Expand Down Expand Up @@ -114,12 +114,12 @@ class CustomFeatureForm extends Component {
</div>
}
<div className="feature-form-content">
<Formsy.Form className="custom-feature-form" disabled={!isEdittable} onValidSubmit={ this.onSave }>
<Formsy.Form className="custom-feature-form" disabled={!isEdittable} onChange={ this.onChange } onValidSubmit={ this.onSave }>
{ (!isAdded || editMode) &&
<TCFormFields.TextInput
name="title"
label="Feature name"
validations="minLength:1" required
validations="isRequired" required
validationError="Feature name is required"
wrapperClass="row"
value={ _.get(data, 'title', '') }
Expand All @@ -131,7 +131,6 @@ class CustomFeatureForm extends Component {
label="Feature Notes"
wrapperClass="feature-notes"
value={ _.get(data, 'notes', '') }
onChange={ this.onChange }
/>
: null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ class DefaultFeatureForm extends Component {
}

toggleFeature() {
const { removeFeature, addFeature, featureDesc, isEdittable } = this.props
const { toggleFeature, addFeature, featureDesc, isEdittable } = this.props
if (isEdittable) {
if (this.state.isActive) {
// remove feature
removeFeature(featureDesc.id)
toggleFeature(featureDesc.id, true)
} else {
// add feature
addFeature({
Expand All @@ -50,13 +50,15 @@ class DefaultFeatureForm extends Component {

onChange(data) {
const { featureData } = this.props
// trim the notes (as of now only notes field is auto updated)
data.notes = data.notes.trim()
this.props.updateFeature(_.merge({}, featureData, data))
}

render() {
const { featureDesc, featureData, isEdittable } = this.props
const { isActive } = this.state
const _debouncedOnChange = _.debounce(this.onChange, 2000, { trailing: true, maxWait: 10000 })
// const _debouncedOnChange = _.debounce(this.onChange, 2000, { trailing: true, maxWait: 10000 })
return (
<div className="feature-form">
<div className="feature-title-row flex space-between">
Expand All @@ -72,7 +74,7 @@ class DefaultFeatureForm extends Component {
<p className="feature-description">{ featureDesc.description }</p>
{
isActive ?
<Formsy.Form className="predefined-feature-form" disabled={!isEdittable} onChange={ _debouncedOnChange }>
<Formsy.Form className="predefined-feature-form" disabled={!isEdittable} onChange={ this.onChange }>
<TCFormFields.Textarea
name="notes"
wrapperClass="feature-notes"
Expand Down
48 changes: 29 additions & 19 deletions src/projects/detail/components/FeatureSelector/FeaturePicker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,8 @@ class FeaturePicker extends Component {
}
this.addFeature = this.addFeature.bind(this)
this.removeFeature = this.removeFeature.bind(this)
this.selectFeature = this.selectFeature.bind(this)
this.toggleFeature = this.toggleFeature.bind(this)
this.selectFeature = this.selectFeature.bind(this)
this.updateSelectedFeature = this.updateSelectedFeature.bind(this)
this.renderCustomFeatureForm = this.renderCustomFeatureForm.bind(this)
this.renderDefaultFeatureForm = this.renderDefaultFeatureForm.bind(this)
Expand All @@ -232,11 +232,6 @@ class FeaturePicker extends Component {
})
}

toggleFeature(featureId) {
const idx = _.findIndex(this.state.activeFeatureList, f => f.id === featureId)
idx > -1 ? this.removeFeature(featureId) : this.addFeature(featureId)
}

renderCustomFeatureForm() {
this.setState({
selectedFeatureId: null,
Expand All @@ -262,27 +257,40 @@ class FeaturePicker extends Component {
this.props.onSave(newState.activeFeatureList)
}

addFeature(feature) {
let newState
const featureIndex = _.findIndex(this.state.activeFeatureList, (f) => f.id === feature.id )
// if feature is already added and is custom feature, update feature
if (feature.categoryId === 'custom' && featureIndex >= 0) {
newState = update(this.state, {
toggleFeature(featureId, disable) {
const featureIndex = _.findIndex(this.state.activeFeatureList, (f) => f.id === featureId )
if (featureIndex >= 0) {
const feature = this.state.activeFeatureList[featureIndex]
let featureListQuery
// separate update query for custom and standard features
// when disabling, we remove standard feature from the list while update custom feature with disabled flag
if (feature.categoryId === 'custom') {
feature.disabled = disable
featureListQuery = { $splice : [[featureIndex, 1, feature]] }
} else {
featureListQuery = { $splice: [[featureIndex, 1]] }
}
const newState = update(this.state, {
activeFeatureCount: { $set: this.state.activeFeatureCount - 1 },
activeFeatureList: { $splice : [[featureIndex, 1, feature]] },
selectedFeatureId: { $set : feature.id }
})
} else {// add standard feature
newState = update(this.state, {
activeFeatureCount: {$set: this.state.activeFeatureCount + 1},
activeFeatureList: { $push : [feature] },
activeFeatureList: featureListQuery,
selectedFeatureId: { $set : feature.id }
})
this.setState(newState)
this.props.onSave(newState.activeFeatureList)
}
}

addFeature(feature) {
const newState = update(this.state, {
activeFeatureCount: {$set: this.state.activeFeatureCount + 1},
activeFeatureList: { $push : [feature] },
selectedFeatureId: { $set : feature.id }
})
this.setState(newState)
this.props.onSave(newState.activeFeatureList)
}

// removeFeature is only called for custom feature
removeFeature(featureId) {
// lookup index
const idx = _.findIndex(this.state.activeFeatureList, f => f.id === featureId )
Expand Down Expand Up @@ -328,6 +336,7 @@ class FeaturePicker extends Component {
featureDesc={selectedFeature}
featureData={selectedFeatureData}
updateFeature={this.updateSelectedFeature}
toggleFeature={ this.toggleFeature }
addFeature={this.addFeature}
removeFeature={this.removeFeature}
/>)
Expand Down Expand Up @@ -360,6 +369,7 @@ class FeaturePicker extends Component {
isEdittable={isEdittable}
featureData={selectedFeatureData}
updateFeature={this.updateSelectedFeature}
toggleFeature={ this. toggleFeature }
addFeature={this.addFeature}
removeFeature={this.removeFeature}
onCancel={this.renderDefaultFeatureForm}
Expand Down