@@ -2,17 +2,42 @@ import _ from 'lodash'
22import React , { Component } from 'react'
33import PT from 'prop-types'
44import cn from 'classnames'
5+ import { connect } from 'react-redux'
56
67import './FillProjectDetails.scss'
78import ProjectBasicDetailsForm from '../components/ProjectBasicDetailsForm'
89import 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
125197FillProjectDetails . defaultProps = {
126- shouldUpdateTemplate : false
198+ shouldUpdateTemplate : false ,
127199}
128200
129201FillProjectDetails . 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