Skip to content

Commit b10c94f

Browse files
committed
Progressive Registration
Progressive Registration
1 parent 309ef03 commit b10c94f

File tree

5 files changed

+542
-155
lines changed

5 files changed

+542
-155
lines changed

src/projects/create/components/FillProjectDetails.js

Lines changed: 206 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,42 @@ import _ from 'lodash'
22
import React, { Component } from 'react'
33
import PT from 'prop-types'
44
import cn from 'classnames'
5+
import { connect } from 'react-redux'
56

67
import './FillProjectDetails.scss'
78
import ProjectBasicDetailsForm from '../components/ProjectBasicDetailsForm'
89
import HeaderWithProgress from './HeaderWithProgress'
10+
import UpdateUserInfo from './UpdateUserInfo'
11+
import { formatProfileSettings } from '../../../routes/settings/helpers/settings'
12+
import {
13+
getProfileSettings,
14+
saveProfileSettings,
15+
uploadProfilePhoto,
16+
} from '../../../routes/settings/actions/index'
17+
import {
18+
ROLE_TOPCODER_USER,
19+
ROLE_CONNECT_COPILOT,
20+
ROLE_CONNECT_MANAGER,
21+
ROLE_CONNECT_ACCOUNT_MANAGER,
22+
ROLE_CONNECT_COPILOT_MANAGER,
23+
ROLE_ADMINISTRATOR,
24+
ROLE_CONNECT_ADMIN,
25+
ROLE_BUSINESS_DEVELOPMENT_REPRESENTATIVE,
26+
ROLE_PRESALES,
27+
ROLE_ACCOUNT_EXECUTIVE,
28+
ROLE_PROGRAM_MANAGER,
29+
ROLE_SOLUTION_ARCHITECT,
30+
ROLE_PROJECT_MANAGER,
31+
} from '../../../config/constants'
932

10-
class FillProjectDetails extends Component {
33+
class FillProjectDetails extends Component {
1134
constructor(props) {
1235
super(props)
1336
this.createMarkup = this.createMarkup.bind(this)
1437
this.handleStepChange = this.handleStepChange.bind(this)
15-
this.state = { project: {}, currentWizardStep: null }
38+
this.openUserSettings = this.openUserSettings.bind(this)
39+
this.closeUserSettings = this.closeUserSettings.bind(this)
40+
this.state = { project: {}, currentWizardStep: null, showUpdateUser: false }
1641
}
1742

1843
componentWillMount() {
@@ -24,27 +49,60 @@ class FillProjectDetails extends Component {
2449
}
2550

2651
handleStepChange(currentWizardStep) {
27-
this.setState({currentWizardStep})
52+
this.setState({ currentWizardStep })
2853
}
2954

3055
shouldComponentUpdate(nextProps, nextState) {
3156
return !(
32-
_.isEqual(nextProps.project, this.props.project)
33-
&& _.isEqual(nextProps.dirtyProject, this.props.dirtyProject)
34-
&& _.isEqual(nextState.project, this.state.project)
35-
&& _.isEqual(nextProps.error, this.props.error)
36-
&& _.isEqual(nextState.currentWizardStep, this.state.currentWizardStep)
37-
&& _.isEqual(nextProps.projectTemplates, this.props.projectTemplates)
57+
_.isEqual(nextProps.project, this.props.project) &&
58+
_.isEqual(nextProps.dirtyProject, this.props.dirtyProject) &&
59+
_.isEqual(nextState.project, this.state.project) &&
60+
_.isEqual(nextProps.error, this.props.error) &&
61+
_.isEqual(nextState.currentWizardStep, this.state.currentWizardStep) &&
62+
_.isEqual(nextState.showUpdateUser, this.state.showUpdateUser) &&
63+
_.isEqual(nextProps.projectTemplates, this.props.projectTemplates) &&
64+
_.isEqual(nextProps.isMissingUserInfo, this.props.isMissingUserInfo) &&
65+
_.isEqual(
66+
nextProps.isLoadedProfileSetting,
67+
this.props.isLoadedProfileSetting
68+
)
3869
)
3970
}
4071

4172
createMarkup(projectTemplate) {
42-
return {__html: _.get(projectTemplate, 'scope.formTitle', `Let's setup your ${ projectTemplate.name } project`) }
73+
return {
74+
__html: _.get(
75+
projectTemplate,
76+
'scope.formTitle',
77+
`Let's setup your ${projectTemplate.name} project`
78+
),
79+
}
80+
}
81+
82+
openUserSettings() {
83+
this.setState({ showUpdateUser: true })
84+
}
85+
86+
closeUserSettings() {
87+
this.setState({ showUpdateUser: false })
4388
}
4489

4590
render() {
46-
const { project, processing, submitBtnText, projectTemplates, dirtyProject, productTemplates, productCategories, shouldUpdateTemplate } = this.props
47-
const { currentWizardStep } = this.state
91+
const {
92+
project,
93+
processing,
94+
submitBtnText,
95+
projectTemplates,
96+
dirtyProject,
97+
productTemplates,
98+
productCategories,
99+
shouldUpdateTemplate,
100+
getProfileSettings,
101+
profileSettings,
102+
isMissingUserInfo,
103+
isLoadedProfileSetting,
104+
} = this.props
105+
const { currentWizardStep, showUpdateUser } = this.state
48106
const projectTemplateId = _.get(project, 'templateId')
49107
const projectTemplate = _.find(projectTemplates, { id: projectTemplateId })
50108
const formDisclaimer = _.get(projectTemplate, 'scope.formDisclaimer')
@@ -56,13 +114,17 @@ class FillProjectDetails extends Component {
56114
if (!_.get(template, 'wizard.enabled')) {
57115
header = (
58116
<div className="text-header-wrapper">
59-
<h1 dangerouslySetInnerHTML = {this.createMarkup(projectTemplate)} />
117+
<h1 dangerouslySetInnerHTML={this.createMarkup(projectTemplate)} />
60118
</div>
61119
)
62120
} else {
63-
const currentSection = currentWizardStep && template.sections[currentWizardStep.sectionIndex]
121+
const currentSection =
122+
currentWizardStep && template.sections[currentWizardStep.sectionIndex]
64123

65-
if (!currentSection || currentSection && !currentSection.hideFormHeader) {
124+
if (
125+
!currentSection ||
126+
(currentSection && !currentSection.hideFormHeader)
127+
) {
66128
header = (
67129
<HeaderWithProgress
68130
template={template}
@@ -77,53 +139,63 @@ class FillProjectDetails extends Component {
77139
return (
78140
<div
79141
className={cn('FillProjectDetailsWrapper', {
80-
[`form-theme-${template.theme}`]: template.theme
142+
[`form-theme-${template.theme}`]: template.theme,
81143
})}
82144
>
83-
<div className="FillProjectDetails">
84-
<div className="header">
85-
{header}
86-
</div>
87-
<section className="two-col-content content">
88-
<div className="container">
89-
<div className="left-area">
90-
<div className="left-area-content">
91-
<ProjectBasicDetailsForm
92-
project={project}
93-
dirtyProject={dirtyProject}
94-
template={template}
95-
isEditable
96-
submitHandler={this.props.onCreateProject}
97-
addAttachment={this.props.addAttachment}
98-
updateAttachment={this.props.updateAttachment}
99-
removeAttachment={this.props.removeAttachment}
100-
attachmentsStorePath={this.props.attachmentsStorePath}
101-
canManageAttachments={this.props.canManageAttachments}
102-
saving={processing}
103-
onProjectChange={this.props.onProjectChange}
104-
submitBtnText={ submitBtnText }
105-
productTemplates={productTemplates}
106-
onStepChange={this.handleStepChange}
107-
productCategories={productCategories}
108-
shouldUpdateTemplate={shouldUpdateTemplate}
109-
/>
110-
</div>
111-
{formDisclaimer && (
112-
<div className="left-area-footer">
113-
<span>{formDisclaimer}</span>
145+
{showUpdateUser ? (
146+
<UpdateUserInfo
147+
{...this.props}
148+
closeUserSettings={this.closeUserSettings}
149+
/>
150+
) : (
151+
<div className="FillProjectDetails">
152+
<div className="header">{header}</div>
153+
<section className="two-col-content content">
154+
<div className="container">
155+
<div className="left-area">
156+
<div className="left-area-content">
157+
<ProjectBasicDetailsForm
158+
getProfileSettings={getProfileSettings}
159+
profileSettings={profileSettings}
160+
project={project}
161+
dirtyProject={dirtyProject}
162+
template={template}
163+
isEditable
164+
submitHandler={this.props.onCreateProject}
165+
addAttachment={this.props.addAttachment}
166+
updateAttachment={this.props.updateAttachment}
167+
removeAttachment={this.props.removeAttachment}
168+
attachmentsStorePath={this.props.attachmentsStorePath}
169+
canManageAttachments={this.props.canManageAttachments}
170+
saving={processing}
171+
onProjectChange={this.props.onProjectChange}
172+
submitBtnText={submitBtnText}
173+
productTemplates={productTemplates}
174+
onStepChange={this.handleStepChange}
175+
productCategories={productCategories}
176+
shouldUpdateTemplate={shouldUpdateTemplate}
177+
isMissingUserInfo={isMissingUserInfo}
178+
isLoadedProfileSetting={isLoadedProfileSetting}
179+
openUserSettings={this.openUserSettings}
180+
/>
114181
</div>
115-
)}
182+
{formDisclaimer && (
183+
<div className="left-area-footer">
184+
<span>{formDisclaimer}</span>
185+
</div>
186+
)}
187+
</div>
116188
</div>
117-
</div>
118-
</section>
119-
</div>
189+
</section>
190+
</div>
191+
)}
120192
</div>
121193
)
122194
}
123195
}
124196

125197
FillProjectDetails.defaultProps = {
126-
shouldUpdateTemplate: false
198+
shouldUpdateTemplate: false,
127199
}
128200

129201
FillProjectDetails.propTypes = {
@@ -138,11 +210,88 @@ FillProjectDetails.propTypes = {
138210
userRoles: PT.arrayOf(PT.string),
139211
processing: PT.bool,
140212
templates: PT.array.isRequired,
141-
error: PT.oneOfType([
142-
PT.bool,
143-
PT.object
144-
]),
213+
error: PT.oneOfType([PT.bool, PT.object]),
145214
shouldUpdateTemplate: PT.bool,
215+
profileSettings: PT.object.isRequired,
216+
getProfileSettings: PT.func.isRequired,
217+
isMissingUserInfo: PT.bool.isRequired,
218+
isLoadedProfileSetting: PT.bool.isRequired,
219+
}
220+
221+
const mapStateToProps = ({ settings, loadUser }) => {
222+
const powerUserRoles = [
223+
ROLE_CONNECT_COPILOT,
224+
ROLE_CONNECT_MANAGER,
225+
ROLE_CONNECT_ACCOUNT_MANAGER,
226+
ROLE_CONNECT_ADMIN,
227+
ROLE_ADMINISTRATOR,
228+
ROLE_CONNECT_COPILOT_MANAGER,
229+
]
230+
const managerRoles = [
231+
ROLE_ADMINISTRATOR,
232+
ROLE_CONNECT_ADMIN,
233+
ROLE_CONNECT_MANAGER,
234+
]
235+
const topCoderRoles = [
236+
ROLE_TOPCODER_USER,
237+
ROLE_CONNECT_COPILOT,
238+
ROLE_CONNECT_MANAGER,
239+
ROLE_CONNECT_ACCOUNT_MANAGER,
240+
ROLE_CONNECT_ADMIN,
241+
ROLE_ADMINISTRATOR,
242+
ROLE_CONNECT_COPILOT_MANAGER,
243+
ROLE_BUSINESS_DEVELOPMENT_REPRESENTATIVE,
244+
ROLE_PRESALES,
245+
ROLE_ACCOUNT_EXECUTIVE,
246+
ROLE_PROGRAM_MANAGER,
247+
ROLE_SOLUTION_ARCHITECT,
248+
ROLE_PROJECT_MANAGER,
249+
]
250+
const isTopcoderUser =
251+
_.intersection(loadUser.user.roles, topCoderRoles).length > 0
252+
let isMissingUserInfo = true
253+
const profileSettings = formatProfileSettings(settings.profile.traits)
254+
if (isTopcoderUser) {
255+
isMissingUserInfo =
256+
!profileSettings.firstName ||
257+
!profileSettings.lastName ||
258+
!profileSettings.country ||
259+
!profileSettings.timeZone ||
260+
!profileSettings.workingHourStart ||
261+
!profileSettings.workingHourEnd
262+
} else {
263+
isMissingUserInfo =
264+
!profileSettings.firstName ||
265+
!profileSettings.lastName ||
266+
!profileSettings.title ||
267+
!profileSettings.companyName ||
268+
!profileSettings.businessEmail ||
269+
!profileSettings.businessPhone
270+
}
271+
272+
return {
273+
profileSettings: {
274+
...settings.profile,
275+
settings: profileSettings,
276+
},
277+
isLoadedProfileSetting: !_.isEmpty(profileSettings),
278+
user: loadUser.user,
279+
isCustomer:
280+
_.intersection(loadUser.user.roles, powerUserRoles).length === 0,
281+
isManager: _.intersection(loadUser.user.roles, managerRoles).length > 0,
282+
isCopilot: _.some(
283+
loadUser.user.roles,
284+
(role) => role === ROLE_CONNECT_COPILOT
285+
),
286+
isTopcoderUser,
287+
isMissingUserInfo,
288+
}
289+
}
290+
291+
const mapDispatchToProps = {
292+
getProfileSettings,
293+
saveProfileSettings,
294+
uploadProfilePhoto,
146295
}
147296

148-
export default FillProjectDetails
297+
export default connect(mapStateToProps, mapDispatchToProps)(FillProjectDetails)

0 commit comments

Comments
 (0)