From 9c12180bbaeda533f163785cb8750c3e9e0795bc Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Fri, 4 Jul 2025 11:30:20 +0200 Subject: [PATCH 1/7] fix: allow MMs to have multiple places --- src/config/constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/constants.js b/src/config/constants.js index 0b7de032..47e4d2ed 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -354,7 +354,7 @@ export const GROUPS_DROPDOWN_PER_PAGE = 1000000 // make sure we are getting all /** * The list of challenge types which can have multiple prizes */ -export const CHALLENGE_TYPES_WITH_MULTIPLE_PRIZES = ['Challenge'] +export const CHALLENGE_TYPES_WITH_MULTIPLE_PRIZES = ['Challenge', 'Marathon Match'] /** * All the repeating messages. From e551d124df1f9c7da63ba94bb19c0d6a038e26d3 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Fri, 25 Jul 2025 23:45:19 +0200 Subject: [PATCH 2/7] feat: modifications on copilot addition to project --- src/components/Users/Users.module.scss | 11 +- src/components/Users/index.js | 9 +- src/components/Users/user-add.modal.js | 238 +++++++++++++++---------- 3 files changed, 155 insertions(+), 103 deletions(-) diff --git a/src/components/Users/Users.module.scss b/src/components/Users/Users.module.scss index 7451b0c6..a37c2395 100644 --- a/src/components/Users/Users.module.scss +++ b/src/components/Users/Users.module.scss @@ -40,6 +40,11 @@ } } +.textContent { + font-size: 18px; + margin-top: 25px; +} + .row { display: flex; @@ -400,7 +405,7 @@ justify-content: center; } -.addButtonContainer { +.addButtonContainer, .buttonWrapper { display: flex; justify-content: flex-start; height: 30px; @@ -412,10 +417,6 @@ } } -.addUserContentContainer { - -} - .tcRadioButton { .tc-radioButton-label { @include roboto-light(); diff --git a/src/components/Users/index.js b/src/components/Users/index.js index 5ddc2e67..46ab4af6 100644 --- a/src/components/Users/index.js +++ b/src/components/Users/index.js @@ -63,8 +63,12 @@ class Users extends Component { }) } - resetAddUserState () { + resetAddUserState (doReloadList) { this.setState({ showAddUserModal: false }) + + if (doReloadList) { + + } } resetInviteUserState () { @@ -225,6 +229,9 @@ class Users extends Component { addNewProjectMember={this.props.addNewProjectMember} onMemberInvited={this.props.addNewProjectInvite} onClose={this.resetAddUserState} + projectOption={this.state.projectOption} + projectMembers={projectMembers} + updateProjectMember={updateProjectMember} /> ) } diff --git a/src/components/Users/user-add.modal.js b/src/components/Users/user-add.modal.js index 58b68d20..c6849115 100644 --- a/src/components/Users/user-add.modal.js +++ b/src/components/Users/user-add.modal.js @@ -6,7 +6,7 @@ import Modal from '../Modal' import SelectUserAutocomplete from '../SelectUserAutocomplete' import { PROJECT_ROLES } from '../../config/constants' import PrimaryButton from '../Buttons/PrimaryButton' -import { addUserToProject, inviteUserToProject } from '../../services/projects' +import { addUserToProject, inviteUserToProject, updateProjectMemberRole } from '../../services/projects' import styles from './Users.module.scss' @@ -14,12 +14,22 @@ const theme = { container: styles.modalContainer } -const UserAddModalContent = ({ projectId, addNewProjectMember, onMemberInvited, onClose }) => { +const UserAddModalContent = ({ + projectMembers, + projectOption, + projectId, + addNewProjectMember, + onMemberInvited, + onClose, + updateProjectMember +}) => { const [userToAdd, setUserToAdd] = useState(null) const [userPermissionToAdd, setUserPermissionToAdd] = useState(PROJECT_ROLES.READ) const [showSelectUserError, setShowSelectUserError] = useState(false) const [addUserError, setAddUserError] = useState(null) const [isAdding, setIsAdding] = useState(false) + const [isUserAddingFailed, setUserAddingFailed] = useState(false) + const [existingRole, setExistingRole] = useState('') const onUpdateUserToAdd = (option) => { if (option && option.value) { @@ -52,8 +62,12 @@ const UserAddModalContent = ({ projectId, addNewProjectMember, onMemberInvited, }) if (failed) { const error = get(failed, '0.message', 'User cannot be invited') + const errorCode = get(failed, '0.error') + const role = get(failed, '0.role') setAddUserError(error) setIsAdding(false) + setUserAddingFailed(errorCode === 'ALREADY_MEMBER') + setExistingRole(role) } else if (rest.message) { setAddUserError(rest.message) setIsAdding(false) @@ -74,113 +88,140 @@ const UserAddModalContent = ({ projectId, addNewProjectMember, onMemberInvited, } } + const onConfirmCopilotRoleChange = async () => { + const member = projectMembers.find(item => item.userId === userToAdd.userId) + const response = await updateProjectMemberRole(projectId, member.id, 'copilot') + updateProjectMember(response) + onClose(true) + } + + const onCancelCopilotRoleChange = () => { + setUserAddingFailed(false) + setAddUserError('') + } + return ( -
-
Add User
-
-
-
- Member* : -
-
- + { + isUserAddingFailed && (existingRole === 'observer' || existingRole === 'customer' || existingRole === 'copilot') && ( +
+
{`The copilot ${userToAdd.handle} is part of ${projectOption.label} project with ${existingRole} role.`}
+
+ +
- {showSelectUserError && ( -
-
Please select a member.
-
- )} -
-
- -
-
-
- setUserPermissionToAdd(PROJECT_ROLES.READ)} - /> - + ) + } + { + !isUserAddingFailed && ( +
+
Add User
+
+
+
+ Member* : +
+
+ +
-
-
-
- setUserPermissionToAdd(PROJECT_ROLES.WRITE)} - /> - + {showSelectUserError && ( +
+
Please select a member.
+
+ )} +
+
+ +
+
+
+ setUserPermissionToAdd(PROJECT_ROLES.READ)} + /> + +
+
+
+
+ setUserPermissionToAdd(PROJECT_ROLES.WRITE)} + /> + +
+
+
+
+ setUserPermissionToAdd(PROJECT_ROLES.MANAGER)} + /> + +
+
+
+
+ setUserPermissionToAdd(PROJECT_ROLES.COPILOT)} + /> + +
+
+ {addUserError && ( +
{addUserError}
+ )}
-
-
- setUserPermissionToAdd(PROJECT_ROLES.MANAGER)} +
+
+ -
-
-
-
- setUserPermissionToAdd(PROJECT_ROLES.COPILOT)} +
+ -
- {addUserError && ( -
{addUserError}
- )} -
-
-
- -
-
- -
-
-
+ ) + } ) } @@ -188,7 +229,10 @@ UserAddModalContent.propTypes = { projectId: PropTypes.number.isRequired, addNewProjectMember: PropTypes.func.isRequired, onMemberInvited: PropTypes.func.isRequired, - onClose: PropTypes.func.isRequired + onClose: PropTypes.func.isRequired, + projectOption: PropTypes.any.isRequired, + projectMembers: PropTypes.array.isRequired, + updateProjectMember: PropTypes.func.isRequired } export default UserAddModalContent From 537a94b828b6c12ee6f5f9a67030161bcf6e0bc7 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Mon, 28 Jul 2025 13:08:26 +0200 Subject: [PATCH 3/7] fix: action string --- src/components/Users/user-add.modal.js | 5 +++-- src/services/projects.js | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/Users/user-add.modal.js b/src/components/Users/user-add.modal.js index c6849115..346fc3cd 100644 --- a/src/components/Users/user-add.modal.js +++ b/src/components/Users/user-add.modal.js @@ -90,7 +90,8 @@ const UserAddModalContent = ({ const onConfirmCopilotRoleChange = async () => { const member = projectMembers.find(item => item.userId === userToAdd.userId) - const response = await updateProjectMemberRole(projectId, member.id, 'copilot') + const action = member.role === 'manager' ? 'complete-copilot-requests' : '' + const response = await updateProjectMemberRole(projectId, member.id, 'copilot', action) updateProjectMember(response) onClose(true) } @@ -103,7 +104,7 @@ const UserAddModalContent = ({ return ( { - isUserAddingFailed && (existingRole === 'observer' || existingRole === 'customer' || existingRole === 'copilot') && ( + isUserAddingFailed && (existingRole === 'observer' || existingRole === 'customer' || existingRole === 'copilot' || existingRole === 'manager') && (
{`The copilot ${userToAdd.handle} is part of ${projectOption.label} project with ${existingRole} role.`}
diff --git a/src/services/projects.js b/src/services/projects.js index a3cf43c0..1a03221c 100644 --- a/src/services/projects.js +++ b/src/services/projects.js @@ -103,9 +103,10 @@ export async function fetchProjectPhases (id) { * @param newRole the new role * @returns {Promise<*>} */ -export async function updateProjectMemberRole (projectId, memberRecordId, newRole) { +export async function updateProjectMemberRole (projectId, memberRecordId, newRole, action) { const response = await axiosInstance.patch(`${PROJECTS_API_URL}/${projectId}/members/${memberRecordId}`, { - role: newRole + role: newRole, + action }) return _.get(response, 'data') } From 59cb7d70258058003a6e67c4752edce4e3d23b66 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Mon, 28 Jul 2025 13:15:06 +0200 Subject: [PATCH 4/7] fix: action string --- src/components/Users/index.js | 6 +----- src/components/Users/user-add.modal.js | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/components/Users/index.js b/src/components/Users/index.js index 46ab4af6..cfbe5671 100644 --- a/src/components/Users/index.js +++ b/src/components/Users/index.js @@ -63,12 +63,8 @@ class Users extends Component { }) } - resetAddUserState (doReloadList) { + resetAddUserState () { this.setState({ showAddUserModal: false }) - - if (doReloadList) { - - } } resetInviteUserState () { diff --git a/src/components/Users/user-add.modal.js b/src/components/Users/user-add.modal.js index 346fc3cd..12a269e4 100644 --- a/src/components/Users/user-add.modal.js +++ b/src/components/Users/user-add.modal.js @@ -93,7 +93,7 @@ const UserAddModalContent = ({ const action = member.role === 'manager' ? 'complete-copilot-requests' : '' const response = await updateProjectMemberRole(projectId, member.id, 'copilot', action) updateProjectMember(response) - onClose(true) + onClose() } const onCancelCopilotRoleChange = () => { @@ -104,7 +104,7 @@ const UserAddModalContent = ({ return ( { - isUserAddingFailed && (existingRole === 'observer' || existingRole === 'customer' || existingRole === 'copilot' || existingRole === 'manager') && ( + isUserAddingFailed && (['observer', 'customer', 'copilot', 'manager'].includes(existingRole)) && (
{`The copilot ${userToAdd.handle} is part of ${projectOption.label} project with ${existingRole} role.`}
From 27fc0b84d68464158bd80b3253dbd91434c4212b Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Thu, 31 Jul 2025 22:09:08 +0200 Subject: [PATCH 5/7] fix: show error when invite comes from an closed opportunity --- src/containers/ProjectInvitations/index.js | 26 +++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/containers/ProjectInvitations/index.js b/src/containers/ProjectInvitations/index.js index 58e6f20d..fc9c4e49 100644 --- a/src/containers/ProjectInvitations/index.js +++ b/src/containers/ProjectInvitations/index.js @@ -46,16 +46,22 @@ const ProjectInvitations = ({ match, auth, isProjectLoading, history, projectDet const updateInvite = useCallback(async (status, source) => { setIsUpdating(status) - await updateProjectMemberInvite(projectId, invitation.id, status, source) - - // await for the project details to propagate - await delay(1000) - await loadProjectInvites(projectId) - toastr.success('Success', `Successfully ${status} the invitation.`) - - // await for the project details to fetch - await delay(1000) - history.push(status === PROJECT_MEMBER_INVITE_STATUS_ACCEPTED ? `/projects/${projectId}/challenges` : '/projects') + try { + await updateProjectMemberInvite(projectId, invitation.id, status, source) + + // await for the project details to propagate + await delay(1000) + await loadProjectInvites(projectId) + toastr.success('Success', `Successfully ${status} the invitation.`) + + // await for the project details to fetch + await delay(1000) + history.push(status === PROJECT_MEMBER_INVITE_STATUS_ACCEPTED ? `/projects/${projectId}/challenges` : '/projects') + } catch (e) { + toastr.error('Error', e.response.data.message) + await delay(1000) + history.push('/projects') + } }, [projectId, invitation, loadProjectInvites, history]) const acceptInvite = useCallback(() => updateInvite(PROJECT_MEMBER_INVITE_STATUS_ACCEPTED, source), [updateInvite, source]) From 887e1ff07703073d4b0ebbec676ea4edaab0dbcb Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Fri, 1 Aug 2025 21:25:16 +0200 Subject: [PATCH 6/7] fix: added projectId query param to request form url --- src/components/ChallengesComponent/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ChallengesComponent/index.js b/src/components/ChallengesComponent/index.js index dd932641..038461b1 100644 --- a/src/components/ChallengesComponent/index.js +++ b/src/components/ChallengesComponent/index.js @@ -98,7 +98,7 @@ const ChallengesComponent = ({ )} From 25c01d655ce95ad9311812f57c9cc000c60e76b3 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Fri, 1 Aug 2025 21:25:43 +0200 Subject: [PATCH 7/7] fix: added projectId query param to request form url --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e5ee2959..5eefc91f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -152,7 +152,7 @@ workflows: context: org-global filters: &filters-dev branches: - only: ["develop", "PM-803_wm-regression-fixes", "PM-902_show-all-projects-on-challenge-page", "pm-1355_1"] + only: ["develop", "PM-803_wm-regression-fixes", "PM-902_show-all-projects-on-challenge-page", "pm-1365"] # Production builds are exectuted only on tagged commits to the # master branch.