Skip to content

Commit cead9f6

Browse files
author
Vikas Agarwal
committed
Merge branch 'dev' into feature/permalink_for_feeds_messages
* dev: Github issue#880, Features changes are not reflected in side panel without saving the changes -- Fixed issue with change alert being shown even after saving the changes. Github issue#880, Features changes are not reflected in side panel without saving the changes -- Initial commit to update features value in formsy form model Github issue#802, can add more screen -- Utilized the on the fly update of other form sections on every form change event. Updated SpecQuestion component to use dirty project value for numberOfScreens question
2 parents 715de01 + b837273 commit cead9f6

File tree

4 files changed

+87
-28
lines changed

4 files changed

+87
-28
lines changed

src/projects/detail/components/EditProjectForm.jsx

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,42 @@ import React, { Component, PropTypes } from 'react'
22
import { withRouter } from 'react-router'
33
import Modal from 'react-modal'
44
import _ from 'lodash'
5+
import { unflatten } from 'flat'
56
import update from 'react-addons-update'
67
import FeaturePicker from './FeatureSelector/FeaturePicker'
78
import { Formsy, Icons } from 'appirio-tech-react-components'
89

910
import SpecSection from './SpecSection'
11+
import { HOC as hoc } from 'formsy-react'
12+
13+
const FeaturePickerModal = ({ project, isEdittable, showFeaturesDialog, hideFeaturesDialog, saveFeatures, setValue }) => {
14+
const setFormValue = (features, featureSeeAttached=false) => {
15+
const featureObj = {
16+
value: features,
17+
seeAttached: featureSeeAttached
18+
}
19+
setValue(featureObj)
20+
saveFeatures(features, featureSeeAttached)
21+
}
22+
return (
23+
<Modal
24+
isOpen={ showFeaturesDialog }
25+
className="feature-selection-dialog"
26+
overlayClassName="feature-selection-dialog-overlay"
27+
onRequestClose={ hideFeaturesDialog }
28+
>
29+
<FeaturePicker
30+
features={ _.get(project, 'details.appDefinition.features.value', []) }
31+
isEdittable={isEdittable} onSave={ setFormValue }
32+
/>
33+
<div onClick={ hideFeaturesDialog } className="feature-selection-dialog-close">
34+
Save and close <Icons.XMarkIcon />
35+
</div>
36+
</Modal>
37+
)
38+
}
39+
40+
const FeaturePickerFormField = hoc(FeaturePickerModal)
1041

1142
class EditProjectForm extends Component {
1243

@@ -34,8 +65,15 @@ class EditProjectForm extends Component {
3465
}
3566

3667
componentWillReceiveProps(nextProps) {
37-
// we receipt property updates from PROJECT_DIRTY REDUX state
38-
if (nextProps.project.isDirty) return
68+
// we received property updates from PROJECT_DIRTY REDUX state
69+
if (nextProps.project.isDirty) {
70+
this.setState({
71+
// sets a new state variable with dirty project
72+
// any component who wants to listen for unsaved changes in project form can listen to this state variable
73+
dirtyProject : Object.assign({}, nextProps.project)
74+
})
75+
return
76+
}
3977
let updatedProject = Object.assign({}, nextProps.project)
4078
if (this.state.isFeaturesDirty && !this.state.isSaving) {
4179
updatedProject = update(updatedProject, {
@@ -127,10 +165,9 @@ class EditProjectForm extends Component {
127165
}
128166

129167
submit(model) {
130-
console.log('submit', this.isChanged())
131-
if (this.state.isFeaturesDirty) {
132-
model.details.appDefinition.features = this.state.project.details.appDefinition.features
133-
}
168+
// if (this.state.isFeaturesDirty) {
169+
// model.details.appDefinition.features = this.state.project.details.appDefinition.features
170+
// }
134171
this.setState({isSaving: true })
135172
this.props.submitHandler(model)
136173
}
@@ -143,20 +180,21 @@ class EditProjectForm extends Component {
143180
*/
144181
handleChange(change) {
145182
// removed check for isChanged argument to fire the PROJECT_DIRTY event for every change in the form
146-
this.props.fireProjectDirty(change)
183+
this.props.fireProjectDirty(unflatten(change))
147184
}
148185

149186

150187
render() {
151188
const { isEdittable, sections } = this.props
152-
const { project } = this.state
189+
const { project, dirtyProject } = this.state
153190
const renderSection = (section, idx) => {
154191
const anySectionInvalid = _.some(this.props.sections, (s) => s.isInvalid)
155192
return (
156193
<div key={idx}>
157194
<SpecSection
158195
{...section}
159196
project={project}
197+
dirtyProject={dirtyProject}
160198
sectionNumber={idx + 1}
161199
resetFeatures={this.onFeaturesSaveAttachedClick}
162200
showFeaturesDialog={this.showFeaturesDialog}
@@ -183,21 +221,17 @@ class EditProjectForm extends Component {
183221
onChange={ this.handleChange }
184222
>
185223
{sections.map(renderSection)}
186-
</Formsy.Form>
187-
<Modal
188-
isOpen={ this.state.showFeaturesDialog }
189-
className="feature-selection-dialog"
190-
overlayClassName="feature-selection-dialog-overlay"
191-
onRequestClose={ this.hideFeaturesDialog }
192-
>
193-
<FeaturePicker
194-
features={ _.get(project, 'details.appDefinition.features.value', []) }
195-
isEdittable={isEdittable} onSave={ this.saveFeatures }
224+
<FeaturePickerFormField
225+
name='details.appDefinition.features'
226+
project={ project }
227+
isEdittable={ isEdittable }
228+
showFeaturesDialog={ this.state.showFeaturesDialog }
229+
hideFeaturesDialog={ this.hideFeaturesDialog }
230+
saveFeatures={ this.saveFeatures }
231+
value={ _.get(project, 'details.appDefinition.features', {})}
196232
/>
197-
<div onClick={ this.hideFeaturesDialog } className="feature-selection-dialog-close">
198-
Save and close <Icons.XMarkIcon />
199-
</div>
200-
</Modal>
233+
</Formsy.Form>
234+
201235
</div>
202236
)
203237
}

src/projects/detail/components/SpecQuestions.jsx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const getIcon = icon => {
2626
}
2727
}
2828

29-
const SpecQuestions = ({questions, project, resetFeatures, showFeaturesDialog, isRequired}) => {
29+
const SpecQuestions = ({questions, project, dirtyProject, resetFeatures, showFeaturesDialog, isRequired}) => {
3030

3131
const renderQ = (q, index) => {
3232
// let child = null
@@ -36,9 +36,9 @@ const SpecQuestions = ({questions, project, resetFeatures, showFeaturesDialog, i
3636
label: q.label,
3737
value: _.get(project, q.fieldName, '')
3838
}
39-
4039
if (q.fieldName === 'details.appDefinition.numberScreens') {
41-
const screens = _.get(project, 'details.appScreens.screens', [])
40+
const p = dirtyProject ? dirtyProject : project
41+
const screens = _.get(p, 'details.appScreens.screens', [])
4242
const definedScreens = screens.length
4343
_.each(q.options, (option) => {
4444
let maxValue = 0
@@ -145,9 +145,26 @@ const SpecQuestions = ({questions, project, resetFeatures, showFeaturesDialog, i
145145
}
146146

147147
SpecQuestions.propTypes = {
148+
/**
149+
* Original project object for which questions are to be rendered
150+
*/
148151
project: PropTypes.object.isRequired,
152+
/**
153+
* Dirty project with all unsaved changes
154+
*/
155+
dirtyProject: PropTypes.object,
156+
/**
157+
* Callback to be called when user clicks on Add/Edit Features button in feature picker component
158+
*/
149159
showFeaturesDialog: PropTypes.func.isRequired,
160+
/**
161+
* Call back to be called when user resets features from feature picker.
162+
* NOTE: It seems it is not used as of now by feature picker component
163+
*/
150164
resetFeatures: PropTypes.func.isRequired,
165+
/**
166+
* Array of questions to be rendered. This comes from the spec template for the product
167+
*/
151168
questions: PropTypes.arrayOf(PropTypes.object).isRequired
152169
}
153170

src/projects/detail/components/SpecSection.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { PROJECT_STATUS_DRAFT, PROJECT_NAME_MAX_LENGTH, PROJECT_REF_CODE_MAX_LEN
1010
const SpecSection = props => {
1111
const {
1212
project,
13+
dirtyProject,
1314
resetFeatures,
1415
showFeaturesDialog,
1516
id,
@@ -61,6 +62,7 @@ const SpecSection = props => {
6162
resetFeatures={resetFeatures}
6263
questions={props.questions}
6364
project={project}
65+
dirtyProject={dirtyProject}
6466
isRequired={props.required}
6567
/>
6668
)

src/projects/reducers/project.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { unflatten } from 'flat'
21
import {
32
LOAD_PROJECT_PENDING, LOAD_PROJECT_SUCCESS, LOAD_PROJECT_FAILURE, LOAD_DIRECT_PROJECT_SUCCESS,
43
CREATE_PROJECT_PENDING, CREATE_PROJECT_SUCCESS, CREATE_PROJECT_FAILURE, CLEAR_LOADED_PROJECT,
@@ -193,9 +192,16 @@ export const projectState = function (state=initialState, action) {
193192
})
194193
}
195194

196-
case PROJECT_DIRTY: {
195+
case PROJECT_DIRTY: {// payload contains only changed values from the project form
197196
return Object.assign({}, state, {
198-
project: _.merge({}, state.project, unflatten(action.payload), { isDirty : true})
197+
project: _.mergeWith({}, state.project, action.payload, { isDirty : true},
198+
// customizer to override screens array with changed values
199+
(objValue, srcValue, key) => {
200+
if (key === 'screens' || key === 'features') {
201+
return srcValue// srcValue contains the changed values from action payload
202+
}
203+
}
204+
)
199205
})
200206
}
201207

0 commit comments

Comments
 (0)