-
Notifications
You must be signed in to change notification settings - Fork 52
[PROD RELEASE] - BA selection UI exposed to PMs #1641
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3b7fbe2
bbe6312
997d8f0
3c464c0
c8c1075
70f514e
e04fae1
50d6f0a
b0d0f48
9f1728f
00f7089
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,15 +6,15 @@ import Modal from '../Modal' | |
import SelectUserAutocomplete from '../SelectUserAutocomplete' | ||
import { PROJECT_ROLES } from '../../config/constants' | ||
import PrimaryButton from '../Buttons/PrimaryButton' | ||
import { addUserToProject } from '../../services/projects' | ||
import { addUserToProject, inviteUserToProject } from '../../services/projects' | ||
|
||
import styles from './Users.module.scss' | ||
|
||
const theme = { | ||
container: styles.modalContainer | ||
} | ||
|
||
const UserAddModalContent = ({ projectId, addNewProjectMember, onClose }) => { | ||
const UserAddModalContent = ({ projectId, addNewProjectMember, onMemberInvited, onClose }) => { | ||
const [userToAdd, setUserToAdd] = useState(null) | ||
const [userPermissionToAdd, setUserPermissionToAdd] = useState(PROJECT_ROLES.READ) | ||
const [showSelectUserError, setShowSelectUserError] = useState(false) | ||
|
@@ -45,10 +45,28 @@ const UserAddModalContent = ({ projectId, addNewProjectMember, onClose }) => { | |
setAddUserError(null) | ||
|
||
try { | ||
const newUserInfo = await addUserToProject(projectId, userToAdd.userId, userPermissionToAdd) | ||
newUserInfo.handle = userToAdd.handle | ||
addNewProjectMember(newUserInfo) | ||
onClose() | ||
if (userPermissionToAdd === PROJECT_ROLES.COPILOT) { | ||
const { success: invitations = [], failed, ...rest } = await inviteUserToProject(projectId, { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider checking if |
||
handles: [userToAdd.handle], | ||
role: userPermissionToAdd | ||
}) | ||
if (failed) { | ||
const error = get(failed, '0.message', 'User cannot be invited') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The error message has been changed from 'Unable to invite user' to 'User cannot be invited'. Ensure that this change aligns with the user experience and error messaging guidelines. |
||
setAddUserError(error) | ||
setIsAdding(false) | ||
} else if (rest.message) { | ||
setAddUserError(rest.message) | ||
setIsAdding(false) | ||
} else { | ||
onMemberInvited(invitations[0] || {}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure that |
||
onClose() | ||
} | ||
} else { | ||
const newUserInfo = await addUserToProject(projectId, userToAdd.userId, userPermissionToAdd) | ||
newUserInfo.handle = userToAdd.handle | ||
addNewProjectMember(newUserInfo) | ||
onClose() | ||
} | ||
} catch (e) { | ||
const error = get(e, 'response.data.message', 'Unable to add user') | ||
setAddUserError(error) | ||
|
@@ -169,6 +187,7 @@ const UserAddModalContent = ({ projectId, addNewProjectMember, onClose }) => { | |
UserAddModalContent.propTypes = { | ||
projectId: PropTypes.number.isRequired, | ||
addNewProjectMember: PropTypes.func.isRequired, | ||
onMemberInvited: PropTypes.func.isRequired, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new prop |
||
onClose: PropTypes.func.isRequired | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ import _ from 'lodash' | |
import PT from 'prop-types' | ||
import UsersComponent from '../../components/Users' | ||
import { PROJECT_ROLES } from '../../config/constants' | ||
import { fetchProjectById } from '../../services/projects' | ||
import { fetchInviteMembers, fetchProjectById } from '../../services/projects' | ||
import { checkAdmin, checkManager } from '../../util/tc' | ||
|
||
import { | ||
|
@@ -80,12 +80,18 @@ class Users extends Component { | |
} | ||
|
||
loadProject (projectId) { | ||
fetchProjectById(projectId).then((project) => { | ||
fetchProjectById(projectId).then(async (project) => { | ||
const projectMembers = _.get(project, 'members') | ||
const invitedMembers = _.get(project, 'invites') | ||
const invitedUserIds = _.filter(_.map(invitedMembers, 'userId')) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider checking if |
||
const invitedUsers = await fetchInviteMembers(invitedUserIds) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure that |
||
|
||
this.setState({ | ||
projectMembers, | ||
invitedMembers | ||
invitedMembers: invitedMembers.map(m => ({ | ||
...m, | ||
email: m.email || invitedUsers[m.userId].handle | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The change from |
||
})) | ||
}) | ||
const { loggedInUser } = this.props | ||
this.updateLoginUserRoleInProject(projectMembers, loggedInUser) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,8 @@ import { | |
GENERIC_PROJECT_MILESTONE_PRODUCT_TYPE, | ||
PHASE_PRODUCT_CHALLENGE_ID_FIELD, | ||
PHASE_PRODUCT_TEMPLATE_ID, | ||
PROJECTS_API_URL | ||
PROJECTS_API_URL, | ||
MEMBERS_API_URL | ||
} from '../config/constants' | ||
import { paginationHeaders } from '../util/pagination' | ||
import { createProjectMemberInvite } from './projectMemberInvites' | ||
|
@@ -68,6 +69,19 @@ export async function fetchProjectById (id) { | |
return _.get(response, 'data') | ||
} | ||
|
||
/** | ||
* This fetches the user corresponding to the given userIds | ||
* @param {*} userIds | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The parameter |
||
*/ | ||
export async function fetchInviteMembers (userIds) { | ||
const url = `${MEMBERS_API_URL}?${userIds.map(id => `userIds[]=${id}`).join('&')}` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider adding error handling for the API request to ensure that any network or server errors are properly managed and do not cause the application to crash. |
||
const { data = [] } = await axiosInstance.get(url) | ||
return data.reduce((acc, member) => { | ||
acc[member.userId] = member | ||
return acc | ||
}, {}) | ||
} | ||
|
||
/** | ||
* Api request for fetching project phases | ||
* @param id Project id | ||
|
@@ -118,11 +132,8 @@ export async function addUserToProject (projectId, userId, role) { | |
* @param role | ||
* @returns {Promise<*>} | ||
*/ | ||
export async function inviteUserToProject (projectId, email, role) { | ||
return createProjectMemberInvite(projectId, { | ||
emails: [email], | ||
role: role | ||
}) | ||
export async function inviteUserToProject (projectId, params) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function |
||
return createProjectMemberInvite(projectId, params) | ||
} | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change introduces a fallback to
user.handle
ifuser.email
is not available whenisInvite
is true. Consider checking if bothuser.email
anduser.handle
are defined before using them to prevent potential issues with undefined values. For example, you could useuser.email ? user.email : user.handle
to ensure thatuser.handle
is only used whenuser.email
is not available.