From 99a3031b474978770c6c0640740ae9c7fc2c68c7 Mon Sep 17 00:00:00 2001 From: wickathou Date: Sat, 1 Jun 2024 19:44:24 +0300 Subject: [PATCH 1/3] Fixed overwrite of projectScores from badly implemented logic Modified projectScore logic to prevent value overwrite from stale data Improved error messages from partner reviewer pages and actions Added notification for score criteria and challenges organizer pages to inform users about risks of making changes when the reviewing is ongoing or past Removed project score from project table Added validation to project grid item to show feedback information only if it is available Fixed issue on organizer projects tab not showing team member information when the user reloads the page Fixed project review submission for partners to prevent passing stale data Improved project review page performance and stability by removing unnecesary useEffects Removed unnused and commented code --- backend/modules/project_score/controller.js | 72 ++++-- backend/modules/project_score/routes.js | 46 ++-- .../layouts/MaterialTabsLayout/index.js | 2 - .../modals/EditProjectModal/index.js | 190 +------------- .../projects/ProjectsGridItem/index.js | 28 ++- .../components/tables/ProjectsTable/index.js | 12 - .../src/components/tables/TeamsTable/index.js | 12 +- .../organiser/edit/challenges/index.js | 17 ++ .../organiser/edit/scoreCriteria/index.js | 27 +- .../organiser/projects/index.js | 2 + .../renderDashboard/partner/projects/index.js | 231 +++++++++--------- .../_projects/slug/challenge/token/index.js | 4 - .../slug/view/projectId/EvaluationForm.js | 3 +- frontend/src/services/projectScores.js | 22 +- 14 files changed, 270 insertions(+), 398 deletions(-) diff --git a/backend/modules/project_score/controller.js b/backend/modules/project_score/controller.js index 07aa8029a..8a89d2224 100644 --- a/backend/modules/project_score/controller.js +++ b/backend/modules/project_score/controller.js @@ -2,19 +2,29 @@ const _ = require('lodash') const Event = require('../event/model') const Project = require('../project/model') const { ProjectScore } = require('./model') -const { NotFoundError } = require('../../common/errors/errors') +const { + NotFoundError, + AlreadyExistsError, +} = require('../../common/errors/errors') const controller = {} -controller.addProjectScore = async score => { - await Project.findById(score.project).orFail( +controller.addProjectScore = async (projectId, projectScoreByReviewer) => { + const projectScoreFound = await ProjectScore.findOne({ project: projectId }) + if (projectScoreFound) { + return controller.updateProjectScoreWithReviewers( + projectScoreFound._id, + projectScoreByReviewer, + ) + } + const projectData = await Project.findById(projectId).orFail( new NotFoundError('The given project does not exist.'), ) - await Event.findById(score.event).orFail( - new NotFoundError('The given event does not exist.'), - ) - const projectScore = new ProjectScore({ ...score }) - projectScore.averageScore = projectScore.score + const projectScore = new ProjectScore({ + reviewers: [projectScoreByReviewer], + project: projectId, + event: projectData.event, + }) if (projectScore.reviewers && projectScore.reviewers.length > 0) { const averageScore = averageScoreCalculation( @@ -22,11 +32,14 @@ controller.addProjectScore = async score => { projectScore.score, ) if (!averageScore) { - throw new Error('Score average calculation failed') + throw new Error( + 'Score average calculation failed, make sure all criteria are filled in', + ) } projectScore.averageScore = averageScore } - return projectScore.save() + projectScore.save() + return projectScore } controller.updateProjectScore = async (id, updatedProjectScore) => { @@ -112,7 +125,9 @@ const limitDecimals = (number, decimalPlaces) => { const averageScoreCalculation = (reviewers, globalScore) => { const allScores = reviewers.map(review => review.score) - allScores.push(globalScore) + if (globalScore) { + allScores.push(globalScore) + } let scoreCount = allScores.length const scoreSum = allScores.reduce((acc, current) => { @@ -132,17 +147,27 @@ const averageScoreCalculation = (reviewers, globalScore) => { } controller.updateProjectScoreWithReviewers = async ( - id, + projectScoreId, updatedProjectScore, ) => { - const projectScore = await ProjectScore.findById(id).orFail( - new NotFoundError('The given ProjectScore does not exist.'), + const projectScore = await ProjectScore.findById(projectScoreId).orFail( + new NotFoundError( + 'The given ProjectScore does not exist, refresh and try again.', + ), ) - projectScore.status = updatedProjectScore.status - projectScore.track = updatedProjectScore.track - projectScore.challenge = updatedProjectScore.challenge - projectScore.reviewers = updatedProjectScore.reviewers - + const reviewerFoundIndex = _.findIndex(projectScore.reviewers, { + userId: updatedProjectScore.userId, + }) + if (reviewerFoundIndex !== -1) { + projectScore.reviewers[reviewerFoundIndex].score = + updatedProjectScore.score + projectScore.reviewers[reviewerFoundIndex].scoreCriteria = + updatedProjectScore.scoreCriteria + projectScore.reviewers[reviewerFoundIndex].message = + updatedProjectScore.message + } else { + projectScore.reviewers.push(updatedProjectScore) + } projectScore.averageScore = projectScore.score if (projectScore.reviewers && projectScore.reviewers.length > 0) { @@ -151,15 +176,12 @@ controller.updateProjectScoreWithReviewers = async ( projectScore.score, ) if (!averageScore) { - throw new Error('Score average calculation failed') + throw new Error( + 'Score average calculation failed, make sure all criteria are filled in', + ) } projectScore.averageScore = averageScore } - - //scores from reviewers + scores from global, divide by total count of scores - - // projectScore.averageScore = projectScore.score + - await projectScore.save() return projectScore } diff --git a/backend/modules/project_score/routes.js b/backend/modules/project_score/routes.js index 25b0635ce..b9b9c8142 100644 --- a/backend/modules/project_score/routes.js +++ b/backend/modules/project_score/routes.js @@ -16,18 +16,20 @@ const { } = require('../../common/middleware/events') const addProjectScore = asyncHandler(async (req, res) => { - console.log('addProjectScore is running') + const { projectId } = req.params try { - if (req.params.track) { - req.body.track = req.params.track._id - } - if (req.params.challenge) { - req.body.challenge = req.params.challenge._id - } - const score = await ProjectScoreController.addProjectScore(req.body) + // if (req.params.track) { + // req.body.track = req.params.track._id + // } + // if (req.params.challenge) { + // req.body.challenge = req.params.challenge._id + // } + const score = await ProjectScoreController.addProjectScore( + projectId, + req.body, + ) return res.status(200).json(score) } catch (e) { - console.error(e) return res.status(500).json({ message: 'Add project score encountered an unknown error. Please check your request and try again.', @@ -86,20 +88,20 @@ const getPublicScores = asyncHandler(async (req, res) => { }) const updateProjectScoreWithReviewers = asyncHandler(async (req, res) => { - console.log('Received on bcknd') + const { slug, projectScoreId } = req.params try { - if (req.params.track) { - req.body.track = req.params.track._id - } - if (req.params.challenge) { - req.body.challenge = req.params.challenge._id - } - const score = + // if (req.params.track) { + // req.body.track = req.params.track._id + // } + // if (req.params.challenge) { + // req.body.challenge = req.params.challenge._id + // } + const projectScore = await ProjectScoreController.updateProjectScoreWithReviewers( - req.params.id, + projectScoreId, req.body, ) - return res.status(200).json(score) + return res.status(200).json(projectScore) } catch (e) { return res.status(500).json({ message: @@ -122,7 +124,6 @@ router.get( '/event/:slug/project/:projectId', hasToken, isOrganiserOrCanSubmitProject, - //isEventOrganiser, getScoreByProjectId, ) @@ -160,15 +161,14 @@ router.get( ) router.post( - '/review/event/:slug/:id', + '/review/event/:slug/:projectId', hasToken, isEventPartner, - // getEventFromParams, addProjectScore, ) router.put( - '/review/event/:slug/:id', + '/review/event/:slug/:projectScoreId', hasToken, isEventPartner, updateProjectScoreWithReviewers, diff --git a/frontend/src/components/layouts/MaterialTabsLayout/index.js b/frontend/src/components/layouts/MaterialTabsLayout/index.js index 1a0103710..a9cd562f2 100644 --- a/frontend/src/components/layouts/MaterialTabsLayout/index.js +++ b/frontend/src/components/layouts/MaterialTabsLayout/index.js @@ -106,7 +106,6 @@ export default ({ tabs, location, baseRoute, transparent = false }) => { {tabs.map(({ key, path, component }, index) => { - return ( { /> ) })} - diff --git a/frontend/src/components/modals/EditProjectModal/index.js b/frontend/src/components/modals/EditProjectModal/index.js index 26a4700c6..4feafbd30 100644 --- a/frontend/src/components/modals/EditProjectModal/index.js +++ b/frontend/src/components/modals/EditProjectModal/index.js @@ -1,9 +1,8 @@ -import { useDispatch, useSelector } from 'react-redux' -import React, { useState, useEffect, useMemo } from 'react' +import { useSelector } from 'react-redux' +import React, { useState, useMemo } from 'react' import * as AuthSelectors from 'redux/auth/selectors' import * as OrganiserSelectors from 'redux/organiser/selectors' -import * as SnackbarActions from 'redux/snackbar/actions' import { Dialog, List, @@ -14,11 +13,6 @@ import { Typography, ExpansionPanelDetails, Box, - TextField, - InputLabel, - FormControl, - Select, - MenuItem, Checkbox, } from '@material-ui/core' import PageWrapper from 'components/layouts/PageWrapper' @@ -27,15 +21,10 @@ import PageHeader from 'components/generic/PageHeader' import ExpandMoreIcon from '@material-ui/icons/ExpandMore' import TeamsTable from 'components/tables/TeamsTable' -import ProjectScoresService from 'services/projectScores' import EventsService from 'services/events' - -import { Formik, Form, Field, ErrorMessage } from 'formik' -import Button from 'components/generic/Button' import { projectURLgenerator } from 'utils/dataModifiers' export default ({ project, onClose = () => {}, onEdited = () => {} }) => { - const dispatch = useDispatch() const idToken = useSelector(AuthSelectors.getIdToken) const event = useSelector(OrganiserSelectors.event) const teams = useSelector(OrganiserSelectors.teams) @@ -44,30 +33,7 @@ export default ({ project, onClose = () => {}, onEdited = () => {} }) => { projectURL = projectURLgenerator(event.slug, project._id) } const [finalistChecked, setFinalistChecked] = useState(false) - const [projectScores, setProjectScores] = useState([ - { - project: '', - event: '', - status: 'submitted', - score: 0, - maxScore: 10, - message: '', - track: 'null', - challenge: 'null', - }, - ]) - useEffect(() => { - if (project && event) { - ProjectScoresService.getScoreByEventSlugAndProjectId( - idToken, - event.slug, - project._id, - ).then(score => { - if (score) setProjectScores(score) - }) - setFinalistChecked(event.finalists.includes(project._id)) - } - }, [event, idToken, project]) + const team = useMemo(() => { if (teams && project) { return [teams.find(team => team._id === project.team)] @@ -173,156 +139,6 @@ export default ({ project, onClose = () => {}, onEdited = () => {} }) => { - - - } - aria-controls="panel3a-content" - id="panel3a-header" - > - Project Score - - - {projectScores.map(projectScore => ( - { - values.project = project._id - values.event = event._id - values.track = - projectScore.track - values.challenge = - projectScore.challenge - try { - if (projectScore._id) { - await ProjectScoresService.updateScoreByEventSlug( - idToken, - event.slug, - values, - ) - } else { - await ProjectScoresService.addScoreByEventSlug( - idToken, - event.slug, - values, - ) - } - dispatch( - SnackbarActions.success( - 'Score saved successfully.', - ), - ) - } catch (e) { - dispatch( - SnackbarActions.error( - `Score could not be saved. Error: ${e.message}`, - ), - ) - } finally { - setSubmitting(false) - } - }} - > - {({ isSubmitting }) => ( -
- - {({ field }) => ( - - - Status{' '} - {projectScore.track - ? 'in track ' + - projectScore.track - : null}{' '} - {projectScore.challenge - ? 'in challenge ' + - projectScore.challenge - : null} - - - - )} - - - - {({ field }) => ( - - )} - - - - {({ field }) => ( - - )} - - - - {({ field }) => ( - - )} - - - - - - )} -
- ))} -
-
{event.overallReviewMethod === 'finalsManualSelection' ? ( 0) { + const findReviewMessages = () => { + const returnArray = [] + const reviewMap = project?.scoreData?.reviewers?.map( + reviewer => { + if (reviewer?.message?.length > 0) { + returnArray.push(reviewer.message) + } + }, + ) + return returnArray + } + const feedbackMessages = findReviewMessages() + if (feedbackMessages?.length > 0) { + messageCount = feedbackMessages.length + message = _.last(feedbackMessages) + } + } } const statusTag = status => { @@ -220,6 +239,7 @@ const ProjectsGridItem = ({ {message && ( + Latest feedback{' '} {_.truncate(message, { length: 20 })} )} @@ -229,7 +249,7 @@ const ProjectsGridItem = ({ -
+
{onClickMore && ( )}
diff --git a/frontend/src/components/tables/ProjectsTable/index.js b/frontend/src/components/tables/ProjectsTable/index.js index afbb2b1ec..18b8dc12a 100644 --- a/frontend/src/components/tables/ProjectsTable/index.js +++ b/frontend/src/components/tables/ProjectsTable/index.js @@ -101,18 +101,6 @@ const ProjectsTable = ({ projects }) => { setSelected(selectedRows) } - // debugGroup( - // 'Projects to export', - // selected.map(item => { - // const returnObject = { - // ...flattenObject(item.original), - // projectId: item.original._id, - // projectURL: projectURLgenerator(event.slug, item.original._id), - // } - // return returnObject - // }), - // ) - return ( <> { const searchParams = new URLSearchParams(location.search) const query = new URLSearchParams(location.search) - const hasModal = query.has('modal') const activeModal = query.get('modal') - // TODO add expansion - // const [expandedRows, setExpandedRows] = useState({ 1: true }) const openSingleTeamEdit = row => { const search = `?${new URLSearchParams({ @@ -115,8 +111,6 @@ export default ({ loading, teams = [], simplifiedView = false }) => { }, []) }, [teamsFiltered]) - - const columns = useMemo(() => { return [ { @@ -188,7 +182,9 @@ export default ({ loading, teams = [], simplifiedView = false }) => { @@ -310,9 +306,7 @@ export default ({ loading, teams = [], simplifiedView = false }) => { key: 'edit-team', label: 'Edit team', action: rows => { - openSingleTeamEdit(rows[0]) - }, }, ]} diff --git a/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/challenges/index.js b/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/challenges/index.js index b9552897c..152226f14 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/challenges/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/challenges/index.js @@ -7,11 +7,28 @@ import FormControl from 'components/inputs/FormControl' import BooleanInput from 'components/inputs/BooleanInput' import ChallengesForm from './ChallengesForm' +import { useSelector } from 'react-redux' +import * as OrganiserSelectors from 'redux/organiser/selectors' +import { EventHelpers } from '@hackjunction/shared' +import moment from 'moment-timezone' export default () => { + const event = useSelector(OrganiserSelectors.event) + const isReviewingOpen = EventHelpers.isReviewingOpen(event, moment) + const isReviewingPast = EventHelpers.isReviewingPast(event, moment) return ( + {(isReviewingOpen || isReviewingPast) && ( +

+ Warning: Reviewing is now{' '} + {isReviewingOpen + ? 'open' + : isReviewingPast && 'completed'}{' '} + and if you make changes to the challenges, it might + cause unexpected problems. Modify at your own risk! +

+ )} ( diff --git a/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/scoreCriteria/index.js b/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/scoreCriteria/index.js index 1a50194cc..bb45ee4c8 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/scoreCriteria/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/scoreCriteria/index.js @@ -1,17 +1,19 @@ -import React, { useEffect, useMemo, useState } from 'react' -import { FastField, useFormikContext } from 'formik' +import React from 'react' +import { FastField } from 'formik' import { Grid, Typography } from '@material-ui/core' import FormControl from 'components/inputs/FormControl' -import CustomSectionList from '../questions/CustomSectionList' import * as OrganiserSelectors from 'redux/organiser/selectors' import { useSelector } from 'react-redux' import _ from 'lodash' -import { useTranslation } from 'react-i18next' -import Button from 'components/generic/Button' -import Switch from '../../../../../../components/generic/Switch' +import Switch from 'components/generic/Switch' import EditableOptions from '../submission/components/EditableOptions' +import { EventHelpers } from '@hackjunction/shared' +import moment from 'moment-timezone' export default () => { + const event = useSelector(OrganiserSelectors.event) + const isReviewingOpen = EventHelpers.isReviewingOpen(event, moment) + const isReviewingPast = EventHelpers.isReviewingPast(event, moment) return ( {
+ {/* Create a P element that looks like a warning */} + {(isReviewingOpen || isReviewingPast) && ( +

+ Warning: Reviewing is now{' '} + {isReviewingOpen + ? 'open' + : isReviewingPast && 'completed'}{' '} + and if you make changes to the score criteria, it might + cause unexpected problems. Modify at your own risk! +

+ )} ( { if (event.slug) { dispatch(OrganiserActions.updateTeamsForEvent(event.slug)) dispatch(OrganiserActions.updateProjects(event.slug)) + dispatch(OrganiserActions.updateRegistrationsForEvent(event.slug)) + dispatch(OrganiserActions.updateTeamsForEvent(event.slug)) } }, [event, location]) diff --git a/frontend/src/pages/_dashboard/renderDashboard/partner/projects/index.js b/frontend/src/pages/_dashboard/renderDashboard/partner/projects/index.js index 493f8d1f1..0e12e5a5a 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/partner/projects/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/partner/projects/index.js @@ -11,30 +11,22 @@ import _ from 'lodash' import ProjectDetail from 'components/projects/ProjectDetail' import * as AuthSelectors from 'redux/auth/selectors' -import * as userSelectors from 'redux/user/selectors' import ProjectScoresService from 'services/projectScores' import EvaluationForm from 'pages/_projects/slug/view/projectId/EvaluationForm' import Empty from 'components/generic/Empty' import * as SnackbarActions from 'redux/snackbar/actions' -const projectScoreBase = { - project: '', - event: '', - status: 'submitted', - score: 0, - maxScore: 10, - message: '', - scoreCriteria: [], - reviewers: [], -} - //TODO simplify this component and the reviewer score process //TODO make this and track one into a component export default ({ event }) => { - const scoreCriteriaBase = event.scoreCriteriaSettings?.scoreCriteria + const scoreCriteriaBase = [ + ...event?.scoreCriteriaSettings?.scoreCriteria.map(criteria => ({ + ...criteria, + })), + ] + const idToken = useSelector(AuthSelectors.getIdToken) const userId = useSelector(AuthSelectors.getUserId) - const userProfile = useSelector(userSelectors.userProfile) const dispatch = useDispatch() const { slug } = event const [data, setData] = useState({}) @@ -43,8 +35,7 @@ export default ({ event }) => { const [error, setError] = useState(false) const [selected, setSelected] = useState(null) - const [scoreExists, setScoreExists] = useState(false) - const [projectScore, setProjectScore] = useState(projectScoreBase) + const [projectScore, setProjectScore] = useState({}) const resetProjectData = () => { if (Array.isArray(scoreCriteriaBase) && scoreCriteriaBase.length > 0) { @@ -55,91 +46,90 @@ export default ({ event }) => { }) } setSelected(null) - setScoreExists(false) - setProjectScore(projectScoreBase) + setProjectScore({}) } - if (event.scoreCriteriaSettings === undefined) { + if (event?.scoreCriteriaSettings === undefined) { return } - const fetchProjects = useCallback(async () => { - setLoading(true) - try { - const dataOt = await ProjectsService.getProjectsByEventAsPartner( - idToken, - slug, - ) - const data = { - event, - ...dataOt, + const fetchProjects = useCallback( + async (idToken, slug) => { + setLoading(true) + try { + const dataOt = + await ProjectsService.getProjectsByEventAsPartner( + idToken, + slug, + ) + const data = { + event, + ...dataOt, + } + setData(data) + setProjects(data?.projects) + } catch (err) { + dispatch( + SnackbarActions.error( + `Error found when loading projects: ${err.message}`, + ), + ) + setError(true) + } finally { + setLoading(false) } - setData(data) - setProjects(data?.projects) - } catch (err) { - dispatch(SnackbarActions.error(`Error found: ${err.message}`)) - setError(true) - } finally { - setLoading(false) - } - }, [slug, idToken, projectScore]) + }, + [slug, idToken], + ) const handleSubmit = async (values, { setSubmitting, resetForm }) => { - const submissionValues = { ...values } - submissionValues.project = selected._id - submissionValues.event = event._id - let reviewerData - if (userId) { - reviewerData = _.find( - submissionValues.reviewers, - reviewer => reviewer.userId === userId, + const { projectScoreId, score, scoreCriteria, message } = values + if (score < 1) { + return dispatch( + SnackbarActions.error( + `You must assign a value for all criteria before submitting.`, + ), ) - if (reviewerData) { - if (reviewerData.firstname !== userProfile?.firstName) { - reviewerData.firstname = userProfile.firstName - } - if (reviewerData.avatar !== userProfile?.avatar) { - reviewerData.avatar = userProfile.avatar - } - reviewerData.score = submissionValues.score - reviewerData.scoreCriteria = submissionValues.scoreCriteria - reviewerData.message = submissionValues.message - } else { - reviewerData = { - userId: userId, - avatar: userProfile?.avatar, - firstname: userProfile?.firstName, - score: submissionValues.score, - scoreCriteria: submissionValues.scoreCriteria, - message: submissionValues.message, - } - submissionValues.reviewers.push(reviewerData) - } - delete submissionValues.score - delete submissionValues.scoreCriteria - delete submissionValues.message + } + const reviewData = { + userId, + score, + scoreCriteria, + message, } try { - if (scoreExists) { + if (projectScoreId) { await ProjectScoresService.updateScoreByEventSlugAndProjectIdAndPartnerAccount( idToken, - event.slug, - submissionValues, + slug, + projectScoreId, + reviewData, ) } else { + const projectId = selected._id await ProjectScoresService.addScoreByEventSlugAndProjectIdAndPartnerAccount( idToken, - event.slug, - submissionValues, + slug, + projectId, + reviewData, ) } - setProjectScore(values) - dispatch(SnackbarActions.success(`Score saved.`)) + dispatch( + SnackbarActions.success( + `Score saved${ + selected?.name && + ' for ' + _.truncate(selected?.name, { length: 15 }) + } `, + ), + ) resetForm() + resetProjectData() } catch (e) { dispatch( SnackbarActions.error( - `Score could not be saved. Error: ${e.message}`, + `Score could not be saved. Error: ${ + e.response.data.error || e.message + }`, ), ) } finally { @@ -148,51 +138,62 @@ export default ({ event }) => { } useEffect(() => { - fetchProjects() - }, [selected, projectScore]) - - if (!data) { - return null - } + if (idToken && event) { + if (!selected) { + fetchProjects(idToken, slug) + } else if (selected) { + fetchProjectScore(idToken, slug, selected._id) + } + } + }, [event, idToken, selected]) - //TODO perform this on the backend - useEffect(() => { - if (idToken && selected && event) { + const fetchProjectScore = useCallback( + async (idToken, slug, projectId) => { ProjectScoresService.getScoreByEventSlugAndProjectIdAndPartnerAccount( idToken, - event.slug, - selected._id, - ).then(score => { - if (score[0]) { - const reviewerData = _.find( - score[0].reviewers, - reviewer => reviewer.userId === userId, - ) - if (reviewerData) { - setProjectScore({ - ...score[0], - score: reviewerData.score, - scoreCriteria: reviewerData.scoreCriteria, - message: reviewerData.message, - }) + slug, + projectId, + ) + .then(score => { + if (score[0]) { + const reviewerData = _.find( + score[0].reviewers, + reviewer => reviewer.userId === userId, + ) + if (reviewerData) { + setProjectScore({ + projectScoreId: score[0]._id, + score: reviewerData.score, + scoreCriteria: reviewerData.scoreCriteria, + message: reviewerData.message, + }) + } else { + setProjectScore({ + projectScoreId: score[0]._id, + score: 0, + scoreCriteria: scoreCriteriaBase, + message: '', + }) + } } else { setProjectScore({ - ...score[0], - score: 0, + ...projectScore, scoreCriteria: scoreCriteriaBase, - message: '', }) } - setScoreExists(true) - } else { - setProjectScore({ - ...projectScore, - scoreCriteria: scoreCriteriaBase, - }) - } - }) - } - }, [event, idToken, selected]) + }) + .catch(e => { + dispatch( + SnackbarActions.error( + `Score could not be loaded. Error: ${ + e.response.data.error || e.message + }`, + ), + ) + }) + }, + [selected], + ) const renderProjects = inputData => { return ( diff --git a/frontend/src/pages/_projects/slug/challenge/token/index.js b/frontend/src/pages/_projects/slug/challenge/token/index.js index 2e4440fc6..026d8d99a 100644 --- a/frontend/src/pages/_projects/slug/challenge/token/index.js +++ b/frontend/src/pages/_projects/slug/challenge/token/index.js @@ -56,10 +56,6 @@ export default ({ event }) => { fetchProjects() }, [fetchProjects]) - if (!data) { - return null - } - const projectsToRender = filter => { switch (filter) { case 'draft': diff --git a/frontend/src/pages/_projects/slug/view/projectId/EvaluationForm.js b/frontend/src/pages/_projects/slug/view/projectId/EvaluationForm.js index d0af0a652..30b408e51 100644 --- a/frontend/src/pages/_projects/slug/view/projectId/EvaluationForm.js +++ b/frontend/src/pages/_projects/slug/view/projectId/EvaluationForm.js @@ -27,9 +27,11 @@ const EvaluationForm = ({ submit = () => {}, score, scoreCriteria }) => { return scoreAverageFormatted } + //TODO Update scoreCriteria from backend, when the event scoreCriteria is updated if ( scoreCriteria && scoreCriteria.length > 0 && + score.scoreCriteria && score.scoreCriteria.length > 0 ) { const scoreFiltered = score.scoreCriteria.filter(criteria => @@ -38,7 +40,6 @@ const EvaluationForm = ({ submit = () => {}, score, scoreCriteria }) => { criteria.criteria, ), ) - score.scoreCriteria = scoreFiltered } diff --git a/frontend/src/services/projectScores.js b/frontend/src/services/projectScores.js index 5d6f057c1..28078a4e7 100644 --- a/frontend/src/services/projectScores.js +++ b/frontend/src/services/projectScores.js @@ -25,6 +25,7 @@ ProjectScoresService.getScoreByEventSlugAndProjectId = ( ) } +//TODO delete this endpoint ProjectScoresService.addScoreByEventSlug = ( idToken, eventSlug, @@ -61,6 +62,7 @@ ProjectScoresService.getScoreByEventSlugAndProjectIdAndPartnerToken = ( ) } +//TODO delete this endpoint ProjectScoresService.addScoreByEventSlugAndPartnerToken = ( token, eventSlug, @@ -99,12 +101,13 @@ ProjectScoresService.getScoreByEventSlugAndProjectIdAndPartnerAccount = ( ProjectScoresService.addScoreByEventSlugAndProjectIdAndPartnerAccount = ( idToken, eventSlug, - projectScore, + projectId, + projectScoreByReviewer, ) => { - console.log('Adding new score from partner account', projectScore._id) + console.log('Adding new score from partner account') return _axios.post( - `/project-scores/review/event/${eventSlug}/${projectScore._id}`, - projectScore, + `/project-scores/review/event/${eventSlug}/${projectId}`, + projectScoreByReviewer, config(idToken), ) } @@ -112,17 +115,18 @@ ProjectScoresService.addScoreByEventSlugAndProjectIdAndPartnerAccount = ( ProjectScoresService.updateScoreByEventSlugAndProjectIdAndPartnerAccount = ( idToken, eventSlug, - // projectId, - projectScore, + projectScoreId, + projectScoreByReviewer, ) => { console.log('Updating working', { idToken, eventSlug, - projectScore, + projectScoreId, + projectScoreByReviewer, }) return _axios.put( - `/project-scores/review/event/${eventSlug}/${projectScore._id}`, - projectScore, + `/project-scores/review/event/${eventSlug}/${projectScoreId}`, + projectScoreByReviewer, config(idToken), ) } From 7b590279bb94d27729481b8f0e7323081d05d99c Mon Sep 17 00:00:00 2001 From: wickathou Date: Sat, 1 Jun 2024 19:51:40 +0300 Subject: [PATCH 2/3] Removed copilot comment --- .../renderDashboard/organiser/edit/scoreCriteria/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/scoreCriteria/index.js b/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/scoreCriteria/index.js index bb45ee4c8..91d79b062 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/scoreCriteria/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/organiser/edit/scoreCriteria/index.js @@ -126,7 +126,6 @@ export default () => {
- {/* Create a P element that looks like a warning */} {(isReviewingOpen || isReviewingPast) && (

Warning: Reviewing is now{' '} From e71cc0ebcc08f21b4cdbcdff5e8b16f592b56ee5 Mon Sep 17 00:00:00 2001 From: wickathou Date: Sat, 1 Jun 2024 20:17:23 +0300 Subject: [PATCH 3/3] Fixed issue showing feedback messages when only the score visibility is enabled --- frontend/src/components/projects/ProjectsGridItem/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/projects/ProjectsGridItem/index.js b/frontend/src/components/projects/ProjectsGridItem/index.js index 4ebbeeb52..79fc265a4 100644 --- a/frontend/src/components/projects/ProjectsGridItem/index.js +++ b/frontend/src/components/projects/ProjectsGridItem/index.js @@ -237,7 +237,7 @@ const ProjectsGridItem = ({ Score {score} - {message && ( + {showReviewers && message && ( Latest feedback{' '} {_.truncate(message, { length: 20 })}