From e6f13e0c15eaa31f26e69c614c397050b1c71559 Mon Sep 17 00:00:00 2001 From: Vasilica Olariu Date: Wed, 9 Apr 2025 15:52:34 +0300 Subject: [PATCH] PM-973 - fetch project invites sepparately --- src/actions/projects.js | 18 ++++++++++++-- src/components/ProjectCard/index.js | 5 ++-- src/config/constants.js | 5 ++++ src/containers/Challenges/index.js | 2 +- src/containers/ProjectInvitations/index.js | 16 ++++++------ src/containers/Projects/index.js | 3 ++- src/reducers/projects.js | 29 +++++++++++++++++++++- src/services/projects.js | 9 +++++++ 8 files changed, 72 insertions(+), 15 deletions(-) diff --git a/src/actions/projects.js b/src/actions/projects.js index 56f803ee..dfc6bf9b 100644 --- a/src/actions/projects.js +++ b/src/actions/projects.js @@ -20,7 +20,8 @@ import { UPDATE_PROJECT_FAILURE, ADD_PROJECT_ATTACHMENT_SUCCESS, UPDATE_PROJECT_ATTACHMENT_SUCCESS, - REMOVE_PROJECT_ATTACHMENT_SUCCESS + REMOVE_PROJECT_ATTACHMENT_SUCCESS, + LOAD_PROJECT_INVITES } from '../config/constants' import { fetchProjectById, @@ -30,7 +31,8 @@ import { createProjectApi, fetchBillingAccounts, fetchMemberProjects, - updateProjectApi + updateProjectApi, + getProjectInvites } from '../services/projects' import { checkAdmin, checkManager } from '../util/tc' @@ -171,6 +173,18 @@ export function loadProjectTypes () { } } +/** + * Loads project invites + */ +export function loadProjectInvites (projectId) { + return (dispatch) => { + return dispatch({ + type: LOAD_PROJECT_INVITES, + payload: getProjectInvites(projectId) + }) + } +} + /** * Creates a project */ diff --git a/src/components/ProjectCard/index.js b/src/components/ProjectCard/index.js index 9d3d7675..97376dc4 100644 --- a/src/components/ProjectCard/index.js +++ b/src/components/ProjectCard/index.js @@ -8,11 +8,11 @@ import { PROJECT_STATUSES } from '../../config/constants' import styles from './ProjectCard.module.scss' -const ProjectCard = ({ projectName, projectStatus, projectId, selected }) => { +const ProjectCard = ({ projectName, projectStatus, projectId, selected, isInvited }) => { return (
@@ -28,6 +28,7 @@ ProjectCard.propTypes = { projectStatus: PT.string.isRequired, projectId: PT.number.isRequired, projectName: PT.string.isRequired, + isInvited: PT.bool.isRequired, selected: PT.bool } diff --git a/src/config/constants.js b/src/config/constants.js index befe6681..8729c02c 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -181,6 +181,11 @@ export const LOAD_PROJECT_TYPES_SUCCESS = 'LOAD_PROJECT_TYPES_SUCCESS' export const LOAD_PROJECT_TYPES_PENDING = 'LOAD_PROJECT_TYPES_PENDING' export const LOAD_PROJECT_TYPES_FAILURE = 'LOAD_PROJECT_TYPES_FAILURE' +export const LOAD_PROJECT_INVITES = 'LOAD_PROJECT_INVITES' +export const LOAD_PROJECT_INVITES_SUCCESS = 'LOAD_PROJECT_INVITES_SUCCESS' +export const LOAD_PROJECT_INVITES_PENDING = 'LOAD_PROJECT_INVITES_PENDING' +export const LOAD_PROJECT_INVITES_FAILURE = 'LOAD_PROJECT_INVITES_FAILURE' + export const CREATE_PROJECT = 'CREATE_PROJECT' export const CREATE_PROJECT_PENDING = 'CREATE_PROJECT_PENDING' export const CREATE_PROJECT_SUCCESS = 'CREATE_PROJECT_SUCCESS' diff --git a/src/containers/Challenges/index.js b/src/containers/Challenges/index.js index 8b5d5868..5f874be5 100644 --- a/src/containers/Challenges/index.js +++ b/src/containers/Challenges/index.js @@ -60,7 +60,7 @@ class Challenges extends Component { const { auth } = this.props if (checkIsUserInvited(auth.token, this.props.projectDetail)) { - this.props.history.push(`/projects/${this.props.projectDetail.id}/invitation`) + this.props.history.push(`/projects/${this.props.projectId}/invitation`) } } diff --git a/src/containers/ProjectInvitations/index.js b/src/containers/ProjectInvitations/index.js index d39eb0ae..6c764010 100644 --- a/src/containers/ProjectInvitations/index.js +++ b/src/containers/ProjectInvitations/index.js @@ -5,7 +5,7 @@ import { withRouter } from 'react-router-dom' import { toastr } from 'react-redux-toastr' import { checkIsUserInvited } from '../../util/tc' import { isEmpty } from 'lodash' -import { loadProject } from '../../actions/projects' +import { loadProjectInvites } from '../../actions/projects' import ConfirmationModal from '../../components/Modal/ConfirmationModal' import styles from './ProjectInvitations.module.scss' @@ -17,7 +17,7 @@ const theme = { container: styles.modalContainer } -const ProjectInvitations = ({ match, auth, isProjectLoading, history, projectDetail, loadProject }) => { +const ProjectInvitations = ({ match, auth, isProjectLoading, history, projectDetail, loadProjectInvites }) => { const automaticAction = useMemo(() => [PROJECT_MEMBER_INVITE_STATUS_ACCEPTED, PROJECT_MEMBER_INVITE_STATUS_REFUSED].includes(match.params.action) ? match.params.action : undefined, [match.params]) const projectId = useMemo(() => parseInt(match.params.projectId), [match.params]) const invitation = useMemo(() => checkIsUserInvited(auth.token, projectDetail), [auth.token, projectDetail]) @@ -32,7 +32,7 @@ const ProjectInvitations = ({ match, auth, isProjectLoading, history, projectDet if (isProjectLoading || isEmpty(projectDetail)) { if (!isProjectLoading) { - loadProject(projectId) + loadProjectInvites(projectId) } return } @@ -48,13 +48,13 @@ const ProjectInvitations = ({ match, auth, isProjectLoading, history, projectDet // await for the project details to propagate await delay(1000) - await loadProject(projectId) + 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') - }, [projectId, invitation, loadProject, history]) + }, [projectId, invitation, loadProjectInvites, history]) const acceptInvite = useCallback(() => updateInvite(PROJECT_MEMBER_INVITE_STATUS_ACCEPTED), [updateInvite]) const declineInvite = useCallback(() => updateInvite(PROJECT_MEMBER_INVITE_STATUS_REFUSED), [updateInvite]) @@ -104,20 +104,20 @@ ProjectInvitations.propTypes = { auth: PropTypes.object.isRequired, isProjectLoading: PropTypes.bool, history: PropTypes.object, - loadProject: PropTypes.func.isRequired, + loadProjectInvites: PropTypes.func.isRequired, projectDetail: PropTypes.object } const mapStateToProps = ({ projects, auth }) => { return { projectDetail: projects.projectDetail, - isProjectLoading: projects.isLoading, + isProjectLoading: projects.isLoading || projects.isProjectInvitationsLoading, auth } } const mapDispatchToProps = { - loadProject + loadProjectInvites } export default withRouter( diff --git a/src/containers/Projects/index.js b/src/containers/Projects/index.js index e3dd4167..e34ca088 100644 --- a/src/containers/Projects/index.js +++ b/src/containers/Projects/index.js @@ -5,7 +5,7 @@ import { withRouter, Link } from 'react-router-dom' import { connect } from 'react-redux' import PropTypes from 'prop-types' import Loader from '../../components/Loader' -import { checkAdminOrCopilot, checkManager } from '../../util/tc' +import { checkAdminOrCopilot, checkIsUserInvited, checkManager } from '../../util/tc' import { PrimaryButton } from '../../components/Buttons' import Select from '../../components/Select' import ProjectCard from '../../components/ProjectCard' @@ -112,6 +112,7 @@ const Projects = ({ projects, auth, isLoading, projectsCount, loadProjects, load {projects.map(p => (
  • } + */ +export async function getProjectInvites (projectId) { + const response = await axiosInstance.get(`${PROJECTS_API_URL}/${projectId}/invites`) + return _.get(response, 'data') +} + /** * Get project attachment * @param projectId project id