@@ -6,20 +6,30 @@ import Modal from '../Modal'
66import SelectUserAutocomplete from '../SelectUserAutocomplete'
77import { PROJECT_ROLES } from '../../config/constants'
88import PrimaryButton from '../Buttons/PrimaryButton'
9- import { addUserToProject , inviteUserToProject } from '../../services/projects'
9+ import { addUserToProject , inviteUserToProject , updateProjectMemberRole } from '../../services/projects'
1010
1111import styles from './Users.module.scss'
1212
1313const theme = {
1414 container : styles . modalContainer
1515}
1616
17- const UserAddModalContent = ( { projectId, addNewProjectMember, onMemberInvited, onClose } ) => {
17+ const UserAddModalContent = ( {
18+ projectMembers,
19+ projectOption,
20+ projectId,
21+ addNewProjectMember,
22+ onMemberInvited,
23+ onClose,
24+ updateProjectMember
25+ } ) => {
1826 const [ userToAdd , setUserToAdd ] = useState ( null )
1927 const [ userPermissionToAdd , setUserPermissionToAdd ] = useState ( PROJECT_ROLES . READ )
2028 const [ showSelectUserError , setShowSelectUserError ] = useState ( false )
2129 const [ addUserError , setAddUserError ] = useState ( null )
2230 const [ isAdding , setIsAdding ] = useState ( false )
31+ const [ isUserAddingFailed , setUserAddingFailed ] = useState ( false )
32+ const [ existingRole , setExistingRole ] = useState ( '' )
2333
2434 const onUpdateUserToAdd = ( option ) => {
2535 if ( option && option . value ) {
@@ -52,8 +62,12 @@ const UserAddModalContent = ({ projectId, addNewProjectMember, onMemberInvited,
5262 } )
5363 if ( failed ) {
5464 const error = get ( failed , '0.message' , 'User cannot be invited' )
65+ const errorCode = get ( failed , '0.error' )
66+ const role = get ( failed , '0.role' )
5567 setAddUserError ( error )
5668 setIsAdding ( false )
69+ setUserAddingFailed ( errorCode === 'ALREADY_MEMBER' )
70+ setExistingRole ( role )
5771 } else if ( rest . message ) {
5872 setAddUserError ( rest . message )
5973 setIsAdding ( false )
@@ -74,121 +88,151 @@ const UserAddModalContent = ({ projectId, addNewProjectMember, onMemberInvited,
7488 }
7589 }
7690
91+ const onConfirmCopilotRoleChange = async ( ) => {
92+ const member = projectMembers . find ( item => item . userId === userToAdd . userId )
93+ const response = await updateProjectMemberRole ( projectId , member . id , 'copilot' )
94+ updateProjectMember ( response )
95+ onClose ( true )
96+ }
97+
98+ const onCancelCopilotRoleChange = ( ) => {
99+ setUserAddingFailed ( false )
100+ setAddUserError ( '' )
101+ }
102+
77103 return (
78104 < Modal theme = { theme } onCancel = { onClose } >
79- < div className = { cn ( styles . contentContainer , styles . confirm ) } >
80- < div className = { styles . title } > Add User</ div >
81- < div className = { styles . addUserContentContainer } >
82- < div className = { styles . row } >
83- < div className = { cn ( styles . field , styles . col1 , styles . addUserTitle ) } >
84- Member< span className = { styles . required } > *</ span > :
85- </ div >
86- < div className = { cn ( styles . field , styles . col2 ) } >
87- < SelectUserAutocomplete
88- value = { userToAdd ? { label : userToAdd . handle , value : userToAdd . userId . toString ( ) } : null }
89- onChange = { onUpdateUserToAdd }
90- />
105+ {
106+ isUserAddingFailed && ( existingRole === 'observer' || existingRole === 'customer' || existingRole === 'copilot' ) && (
107+ < div className = { cn ( styles . contentContainer , styles . confirm ) } >
108+ < div className = { styles . textContent } > { `The copilot ${ userToAdd . handle } is part of ${ projectOption . label } project with ${ existingRole } role.` } </ div >
109+ < div className = { styles . buttonWrapper } >
110+ < PrimaryButton onClick = { onConfirmCopilotRoleChange } text = { 'Confirm' } type = { 'info' } />
111+ < PrimaryButton onClick = { onCancelCopilotRoleChange } text = { 'Cancel' } type = { 'disabled' } />
91112 </ div >
92113 </ div >
93- { showSelectUserError && (
94- < div className = { styles . row } >
95- < div className = { styles . errorMesssage } > Please select a member.</ div >
96- </ div >
97- ) }
98- < div className = { styles . row } >
99- < div className = { cn ( styles . field , styles . col1 , styles . addUserTitle ) } >
100- < label htmlFor = 'memberToAdd' > Role :</ label >
101- </ div >
102- < div className = { cn ( styles . col5 ) } >
103- < div className = { styles . tcRadioButton } >
104- < input
105- name = { `add-user-radio` }
106- type = 'radio'
107- id = { `read-add-user` }
108- checked = { userPermissionToAdd === PROJECT_ROLES . READ }
109- onChange = { ( ) => setUserPermissionToAdd ( PROJECT_ROLES . READ ) }
110- />
111- < label htmlFor = { `read-add-user` } >
112- < div > Read</ div >
113- < input type = 'hidden' />
114- </ label >
114+ )
115+ }
116+ {
117+ ! isUserAddingFailed && (
118+ < div className = { cn ( styles . contentContainer , styles . confirm ) } >
119+ < div className = { styles . title } > Add User</ div >
120+ < div className = { styles . addUserContentContainer } >
121+ < div className = { styles . row } >
122+ < div className = { cn ( styles . field , styles . col1 , styles . addUserTitle ) } >
123+ Member< span className = { styles . required } > *</ span > :
124+ </ div >
125+ < div className = { cn ( styles . field , styles . col2 ) } >
126+ < SelectUserAutocomplete
127+ value = { userToAdd ? { label : userToAdd . handle , value : userToAdd . userId . toString ( ) } : null }
128+ onChange = { onUpdateUserToAdd }
129+ />
130+ </ div >
115131 </ div >
116- </ div >
117- < div className = { cn ( styles . col5 ) } >
118- < div className = { styles . tcRadioButton } >
119- < input
120- name = { `add-user-radio` }
121- type = 'radio'
122- id = { `write-add-user` }
123- checked = { userPermissionToAdd === PROJECT_ROLES . WRITE }
124- onChange = { ( ) => setUserPermissionToAdd ( PROJECT_ROLES . WRITE ) }
125- />
126- < label htmlFor = { `write-add-user` } >
127- < div > Write</ div >
128- < input type = 'hidden' />
129- </ label >
132+ { showSelectUserError && (
133+ < div className = { styles . row } >
134+ < div className = { styles . errorMesssage } > Please select a member.</ div >
135+ </ div >
136+ ) }
137+ < div className = { styles . row } >
138+ < div className = { cn ( styles . field , styles . col1 , styles . addUserTitle ) } >
139+ < label htmlFor = 'memberToAdd' > Role :</ label >
140+ </ div >
141+ < div className = { cn ( styles . col5 ) } >
142+ < div className = { styles . tcRadioButton } >
143+ < input
144+ name = { `add-user-radio` }
145+ type = 'radio'
146+ id = { `read-add-user` }
147+ checked = { userPermissionToAdd === PROJECT_ROLES . READ }
148+ onChange = { ( ) => setUserPermissionToAdd ( PROJECT_ROLES . READ ) }
149+ />
150+ < label htmlFor = { `read-add-user` } >
151+ < div > Read</ div >
152+ < input type = 'hidden' />
153+ </ label >
154+ </ div >
155+ </ div >
156+ < div className = { cn ( styles . col5 ) } >
157+ < div className = { styles . tcRadioButton } >
158+ < input
159+ name = { `add-user-radio` }
160+ type = 'radio'
161+ id = { `write-add-user` }
162+ checked = { userPermissionToAdd === PROJECT_ROLES . WRITE }
163+ onChange = { ( ) => setUserPermissionToAdd ( PROJECT_ROLES . WRITE ) }
164+ />
165+ < label htmlFor = { `write-add-user` } >
166+ < div > Write</ div >
167+ < input type = 'hidden' />
168+ </ label >
169+ </ div >
170+ </ div >
171+ < div className = { cn ( styles . col5 ) } >
172+ < div className = { styles . tcRadioButton } >
173+ < input
174+ name = { `add-user-radio` }
175+ type = 'radio'
176+ id = { `full-access-add-user` }
177+ checked = { userPermissionToAdd === PROJECT_ROLES . MANAGER }
178+ onChange = { ( ) => setUserPermissionToAdd ( PROJECT_ROLES . MANAGER ) }
179+ />
180+ < label htmlFor = { `full-access-add-user` } >
181+ < div > Full Access</ div >
182+ < input type = 'hidden' />
183+ </ label >
184+ </ div >
185+ </ div >
186+ < div className = { cn ( styles . col5 ) } >
187+ < div className = { styles . tcRadioButton } >
188+ < input
189+ name = { `add-user-radio` }
190+ type = 'radio'
191+ id = { `copilot-add-user` }
192+ checked = { userPermissionToAdd === PROJECT_ROLES . COPILOT }
193+ onChange = { ( ) => setUserPermissionToAdd ( PROJECT_ROLES . COPILOT ) }
194+ />
195+ < label htmlFor = { `copilot-add-user` } >
196+ < div > Copilot</ div >
197+ < input type = 'hidden' />
198+ </ label >
199+ </ div >
200+ </ div >
130201 </ div >
202+ { addUserError && (
203+ < div className = { styles . errorMesssage } > { addUserError } </ div >
204+ ) }
131205 </ div >
132- < div className = { cn ( styles . col5 ) } >
133- < div className = { styles . tcRadioButton } >
134- < input
135- name = { `add-user-radio` }
136- type = 'radio'
137- id = { `full-access-add-user` }
138- checked = { userPermissionToAdd === PROJECT_ROLES . MANAGER }
139- onChange = { ( ) => setUserPermissionToAdd ( PROJECT_ROLES . MANAGER ) }
206+ < div className = { styles . buttonGroup } >
207+ < div className = { styles . buttonSizeA } >
208+ < PrimaryButton
209+ text = { 'Close' }
210+ type = { 'info' }
211+ onClick = { onClose }
140212 />
141- < label htmlFor = { `full-access-add-user` } >
142- < div > Full Access</ div >
143- < input type = 'hidden' />
144- </ label >
145213 </ div >
146- </ div >
147- < div className = { cn ( styles . col5 ) } >
148- < div className = { styles . tcRadioButton } >
149- < input
150- name = { `add-user-radio` }
151- type = 'radio'
152- id = { `copilot-add-user` }
153- checked = { userPermissionToAdd === PROJECT_ROLES . COPILOT }
154- onChange = { ( ) => setUserPermissionToAdd ( PROJECT_ROLES . COPILOT ) }
214+ < div className = { styles . buttonSizeA } >
215+ < PrimaryButton
216+ text = { isAdding ? 'Adding user...' : 'Add User' }
217+ type = { 'info' }
218+ onClick = { onAddUserConfirmClick }
155219 />
156- < label htmlFor = { `copilot-add-user` } >
157- < div > Copilot</ div >
158- < input type = 'hidden' />
159- </ label >
160220 </ div >
161221 </ div >
162222 </ div >
163- { addUserError && (
164- < div className = { styles . errorMesssage } > { addUserError } </ div >
165- ) }
166- </ div >
167- < div className = { styles . buttonGroup } >
168- < div className = { styles . buttonSizeA } >
169- < PrimaryButton
170- text = { 'Close' }
171- type = { 'info' }
172- onClick = { onClose }
173- />
174- </ div >
175- < div className = { styles . buttonSizeA } >
176- < PrimaryButton
177- text = { isAdding ? 'Adding user...' : 'Add User' }
178- type = { 'info' }
179- onClick = { onAddUserConfirmClick }
180- />
181- </ div >
182- </ div >
183- </ div >
223+ )
224+ }
184225 </ Modal >
185226 )
186227}
187228UserAddModalContent . propTypes = {
188229 projectId : PropTypes . number . isRequired ,
189230 addNewProjectMember : PropTypes . func . isRequired ,
190231 onMemberInvited : PropTypes . func . isRequired ,
191- onClose : PropTypes . func . isRequired
232+ onClose : PropTypes . func . isRequired ,
233+ projectOption : PropTypes . any . isRequired ,
234+ projectMembers : PropTypes . array . isRequired ,
235+ updateProjectMember : PropTypes . func . isRequired
192236}
193237
194238export default UserAddModalContent
0 commit comments