From 0676faad6e8d0f40fcf44688c39165947f764666 Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 14 Mar 2024 13:02:58 +0200 Subject: [PATCH 1/4] Added new type of event, hybrid Added new gavelLogin property to registration model to store the user unique login link to the gavel platform Modified project reviewing logic for partners Removed registration checkilist default value generator Updated registration status update to not depend on the type of event Added link rendering for PageHeader component Updated scoring rendering to be more user friendly Added maxLength property to TextAreaInput to limit the amount of characters that the field can take Modified Select component to accept array values for single choice selects Added error display for TextAreaInput to show an error when the length of the text goes over the limit specified Created utility to generate project URLs Fixed multiple warnings, reference, syntax and type errors Deleted unnused commented code and console logs Updated shareProject URL generator for ProjectDetail component Updated multiple depreciated properties from used packages Updated project filters to show reviewed/pending projects on partner review page Update project grid sorting, to show projects in a decending order based on the scores received Fixed participant and project export to return valid data Added lockedPages to PartnerDashboard to lock disabled features based on the event schedule Prettified multiple files Modified logic of TravelGrantStatusBlock, VisaInvitationBlock and Organizer dashboard to be locked when the event is online Disabled results tab from organizer page and marked as experimental to improve it Added length constraints for the ChallengeForm text input fields Disabled travel grant features Added gavel tools to organizer participant management, under /admin to allow superAdmins to add gavel login information for participants to get their login for gavel Removed native gavel features, replaced with original gavel app Added filtering rule to organizer project tables, to see only projects who have a team Removed /map from participant dashboard until the map feature is fixed Removed project_score redux selector, to avoid allowing participants to see the project scores that exist Updated project submission form for participants to show their public project URL Modified participant /reviewing page to show gavelLogin or an error if the gavelLogin is not available Disabled recruiting for partner accounts to fix existing issues Modified registration custom questions schema to include question labels Added missing key prop to multiple iterable DOM elements Removed the file API from the dashboard actions Added new event helpers to find if reviewing is open, reviewing is past and if challenges are enabled Added validation schema for custom questions of link type Limited length of challenge name to only 50 characters --- azure-pipelines-production.yml | 258 +++++++++-------- backend/common/services/sendgrid.js | 5 +- .../28-add-gavel-login-to-registrations.js | 26 ++ backend/migrations/index.js | 1 + backend/modules/event/controller.js | 9 + backend/modules/event/graphql.js | 5 +- backend/modules/event/model.js | 9 +- backend/modules/project/controller.js | 64 ++++- backend/modules/project/model.js | 2 +- backend/modules/project/routes.js | 18 +- backend/modules/project_score/controller.js | 62 +--- backend/modules/project_score/routes.js | 2 - backend/modules/recruitment/controller.js | 5 +- backend/modules/registration/controller.js | 109 ++++--- backend/modules/registration/helpers.js | 7 +- backend/modules/registration/model.js | 3 + backend/modules/registration/routes.js | 51 ++-- frontend/src/components/UserMenu/index.js | 28 +- .../UserMenu/userMenu_deprecated/index.js | 260 ----------------- .../components/generic/PageHeader/index.js | 41 +-- .../components/generic/RadioScore/index.js | 18 +- .../components/inputs/MarkdownInput/index.js | 3 +- .../src/components/inputs/Select/index.js | 5 +- .../components/inputs/TextAreaInput/index.js | 93 ++++-- .../modals/EditProjectModal/index.js | 6 + .../modals/ProjectReviewModal/index.js | 12 +- .../projects/ProjectDetail/ShareProject.js | 9 +- .../projects/ProjectDetail/index.js | 19 +- .../ChallengesField/index.js | 3 +- .../components/projects/ProjectsGrid/index.js | 198 ++++++++----- .../projects/ProjectsGridItem/index.js | 123 ++++---- .../components/tables/AttendeeTable/index.js | 43 +-- .../components/tables/ProjectsTable/index.js | 128 +++------ frontend/src/graphql/queries/registrations.js | 2 +- .../default/events/CreateEventCard.js | 104 +++---- .../default/events/Organizer.js | 266 +++++++++--------- .../default/events/Participant.js | 191 +++++++------ .../renderDashboard/default/events/Partner.js | 65 +++-- .../default/Blocks/ReviewingPeriodBlock.js | 41 +-- .../default/Blocks/TravelGrantStatusBlock.js | 2 +- .../default/Blocks/VisaInvitationBlock.js | 2 +- .../generalPages/default/index.js | 35 +-- .../pages/_dashboard/renderDashboard/index.js | 19 +- .../edit/challenges/ChallengesForm.js | 9 +- .../organiser/edit/configuration/index.js | 14 +- .../edit/questions/CustomSectionList/index.js | 26 +- .../organiser/edit/questions/index.js | 60 ---- .../organiser/edit/submission/index.js | 2 +- .../renderDashboard/organiser/index.js | 21 +- .../organiser/participants/admin/index.js | 62 +++- .../organiser/participants/index.js | 2 +- .../organiser/projects/by-challenge/index.js | 17 +- .../organiser/projects/by-track/index.js | 17 +- .../projects/finalist-selection/index.js | 16 +- .../organiser/projects/index.js | 28 +- .../organiser/projects/winners/index.js | 5 +- .../renderDashboard/participant/index.js | 26 +- .../participant/project/ProjectsList.js | 53 +--- .../participant/project/SubmissionForm.js | 42 ++- .../participant/project/index.js | 1 + .../participant/reviewing/CompareProjects.js | 6 +- .../participant/reviewing/FirstProject.js | 3 +- .../participant/reviewing/index.js | 191 +++++++++++-- .../participant/team/teams/index.js | 4 +- .../renderDashboard/partner/index.js | 60 ++-- .../default/SearchResults/index.js | 17 +- .../partnerrecruitment/default/index.js | 43 +-- .../partner/partnerrecruitment/index.js | 61 ++-- .../renderDashboard/partner/projects/index.js | 109 ++----- frontend/src/pages/_events/slug/context.js | 1 - .../register/RegistrationSection/index.js | 2 +- .../src/pages/_events/slug/register/index.js | 2 + .../_projects/slug/challenge/token/index.js | 8 +- .../slug/view/projectId/EvaluationForm.js | 37 +-- .../_projects/slug/view/projectId/index.js | 120 +------- frontend/src/redux/dashboard/actions.js | 24 +- frontend/src/redux/dashboard/reducer.js | 20 +- frontend/src/redux/dashboard/selectors.js | 19 +- frontend/src/routes.js | 13 +- frontend/src/services/projects.js | 4 + frontend/src/services/registrations.js | 9 +- frontend/src/utils/dataModifiers.js | 10 + shared/constants/event-types.js | 4 + shared/constants/project-schema.js | 6 +- .../constants/registration-fields-custom.js | 11 + shared/helpers/events.js | 8 +- shared/schemas/Challenge.js | 2 +- shared/schemas/CustomAnswer.js | 6 + 88 files changed, 1706 insertions(+), 1847 deletions(-) create mode 100644 backend/migrations/28-add-gavel-login-to-registrations.js delete mode 100644 frontend/src/components/UserMenu/userMenu_deprecated/index.js diff --git a/azure-pipelines-production.yml b/azure-pipelines-production.yml index 3cbbe3a15..4812b96b3 100644 --- a/azure-pipelines-production.yml +++ b/azure-pipelines-production.yml @@ -1,137 +1,133 @@ trigger: -- none + - none pool: - vmImage: ubuntu-latest + vmImage: ubuntu-latest stages: -- stage: Build - displayName: Build stage - jobs: - - job: Build - steps: - - - task: DownloadSecureFile@1 - displayName: 'download PROD Africa backend' - inputs: - secureFile: 'BACKEND_ENV_FILE_AFRICA' # string. Required. Secure File. - - - task: CopyFiles@2 - displayName: 'copy PROD Africa backend' - inputs: - SourceFolder: '$(Agent.TempDirectory)' - Contents: BACKEND_ENV_FILE_AFRICA - TargetFolder: './backend' - - - script: mv ./backend/BACKEND_ENV_FILE_AFRICA ./backend/.env - displayName: 'rename PROD Africa .env' - - task: DownloadSecureFile@1 - displayName: 'download PROD Africa frontend' - inputs: - secureFile: 'FRONTEND_ENV_FILE_AFRICA' # string. Required. Secure File. - - - task: CopyFiles@2 - displayName: 'copy PROD Africa frontend' - inputs: - SourceFolder: '$(Agent.TempDirectory)' - Contents: FRONTEND_ENV_FILE_AFRICA - TargetFolder: './frontend' - - - script: mv ./frontend/FRONTEND_ENV_FILE_AFRICA ./frontend/.env - displayName: 'rename PROD Africa .env' - - - script: ls -a ./frontend - displayName: 'ls' - - - script: ls -Rn - displayName: 'ls' - - - - task: NodeTool@0 - inputs: - versionSpec: '12.20.1' - displayName: 'Install Node.js' - - - task: Bash@3 - inputs: - targetType: 'inline' - script: | - node -v - npm -v - npm install - npm run build - - - task: ArchiveFiles@2 - displayName: 'Archive files' - inputs: - rootFolderOrFile: '$(System.DefaultWorkingDirectory)' - includeRootFolder: false - archiveType: zip - archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip - replaceExistingArchive: true - - upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip - artifact: drop - - - - deployment: VMDeploy_AFRICA - dependsOn: Build - displayName: Web deploy Africa - environment: - name: PROD - resourceType: VirtualMachine - tags: africa - strategy: - runOnce: - preDeploy: + - stage: Build_africa + displayName: Build stage africa + jobs: + - job: Build_africa steps: - - task: DownloadPipelineArtifact@2 - inputs: - buildType: 'current' - artifactName: drop - targetPath: '$(Pipeline.Workspace)/drop' - - - script: echo initialize, cleanup, backup, install certs - - deploy: - steps: - - task: Bash@3 - inputs: - targetType: 'inline' - script: | - Modify deployment script based on the app type - echo "Starting deployment script run" - - - - task: ExtractFiles@1 - inputs: - archiveFilePatterns: '$(Pipeline.Workspace)/drop/$(Build.BuildId).zip' - destinationFolder: '$(Pipeline.Workspace)/japp' - cleanDestinationFolder: true - overwriteExistingFiles: true - - - task: DeleteFiles@1 - inputs: - SourceFolder: '$(Pipeline.Workspace)/drop' - Contents: '$(Build.BuildId).zip' - - - task: Bash@3 - inputs: - targetType: 'inline' - script: | - pm2 restart index - sudo systemctl restart nginx - - - routeTraffic: - steps: - - script: echo routing traffic - postRouteTraffic: - steps: - - script: echo health check post-route traffic - on: - failure: - steps: - - script: echo Restore from backup! This is on failure - success: - steps: - - script: echo Notify! This is on success \ No newline at end of file + - task: DownloadSecureFile@1 + displayName: 'download PROD Africa backend' + inputs: + secureFile: 'BACKEND_ENV_FILE_AFRICA' # string. Required. Secure File. + + - task: CopyFiles@2 + displayName: 'copy PROD Africa backend' + inputs: + SourceFolder: '$(Agent.TempDirectory)' + Contents: BACKEND_ENV_FILE_AFRICA + TargetFolder: './backend' + + - script: mv ./backend/BACKEND_ENV_FILE_AFRICA ./backend/.env + displayName: 'rename PROD Africa .env' + - task: DownloadSecureFile@1 + displayName: 'download PROD Africa frontend' + inputs: + secureFile: 'FRONTEND_ENV_FILE_AFRICA' # string. Required. Secure File. + + - task: CopyFiles@2 + displayName: 'copy PROD Africa frontend' + inputs: + SourceFolder: '$(Agent.TempDirectory)' + Contents: FRONTEND_ENV_FILE_AFRICA + TargetFolder: './frontend' + + - script: mv ./frontend/FRONTEND_ENV_FILE_AFRICA ./frontend/.env + displayName: 'rename PROD Africa .env' + + - script: ls -a ./frontend + displayName: 'ls' + + - script: ls -Rn + displayName: 'ls' + + - task: NodeTool@0 + inputs: + versionSpec: '12.20.1' + displayName: 'Install Node.js' + + - task: Bash@3 + inputs: + targetType: 'inline' + script: | + node -v + npm -v + npm install + npm run build + + - task: ArchiveFiles@2 + displayName: 'Archive files' + inputs: + rootFolderOrFile: '$(System.DefaultWorkingDirectory)' + includeRootFolder: false + archiveType: zip + archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip + replaceExistingArchive: true + - upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip + artifact: drop_africa + + - deployment: VMDeploy_AFRICA + dependsOn: Build_africa + displayName: DEPLOY AFRICA + environment: + name: PROD + resourceType: VirtualMachine + tags: africa + strategy: + runOnce: + preDeploy: + steps: + - task: DownloadPipelineArtifact@2 + inputs: + buildType: 'current' + artifactName: drop_africa + targetPath: '$(Pipeline.Workspace)/drop' + + - script: echo initialize, cleanup, backup, install certs + + deploy: + steps: + - task: Bash@3 + inputs: + targetType: 'inline' + script: | + Modify deployment script based on the app type + echo "Starting deployment script run" + + - task: ExtractFiles@1 + inputs: + archiveFilePatterns: '$(Pipeline.Workspace)/drop_africa/$(Build.BuildId).zip' + destinationFolder: '$(Pipeline.Workspace)/japp' + cleanDestinationFolder: true + overwriteExistingFiles: true + + - task: DeleteFiles@1 + inputs: + SourceFolder: '$(Pipeline.Workspace)/drop_africa' + Contents: '$(Build.BuildId).zip' + + - task: Bash@3 + inputs: + targetType: 'inline' + script: | + cd /home/azureuser/azagent/_work/1/japp + pm2 restart index + sudo systemctl restart nginx + + routeTraffic: + steps: + - script: echo routing traffic + postRouteTraffic: + steps: + - script: echo health check post-route traffic + on: + failure: + steps: + - script: echo Restore from backup! This is on failure + success: + steps: + - script: echo Notify! This is on success diff --git a/backend/common/services/sendgrid.js b/backend/common/services/sendgrid.js index 1f76afa29..604ce21ac 100644 --- a/backend/common/services/sendgrid.js +++ b/backend/common/services/sendgrid.js @@ -164,7 +164,10 @@ const SendgridService = { header_image_url = event.coverImage.url } let msg - if (event.eventType === EventTypes.physical.id) { + if ( + event.eventType === EventTypes.physical.id || + event.eventType === EventTypes.hybrid.id + ) { msg = SendgridService.buildTemplateMessage( user.email, global.gConfig.SENDGRID_GENERIC_TEMPLATE, diff --git a/backend/migrations/28-add-gavel-login-to-registrations.js b/backend/migrations/28-add-gavel-login-to-registrations.js new file mode 100644 index 000000000..fcb757f75 --- /dev/null +++ b/backend/migrations/28-add-gavel-login-to-registrations.js @@ -0,0 +1,26 @@ +const mongoose = require('mongoose') +const Promise = require('bluebird') + +module.exports = { + index: 28, + name: '28-add-gavel-login-to-registrations', + description: 'Add gavel login link to registrations', + run: async () => { + const addGavelLogin = await mongoose.model('Registration').updateMany( + { gavelLogin: { $exists: false } }, + { + $set: { + gavelLogin: '', + }, + }, + ) + + console.log( + 'Done adding gavel login link to registrations', + addGavelLogin.n, + addGavelLogin.nModified, + ) + + return Promise.resolve() + }, +} diff --git a/backend/migrations/index.js b/backend/migrations/index.js index 771df796c..9eb493d56 100644 --- a/backend/migrations/index.js +++ b/backend/migrations/index.js @@ -31,6 +31,7 @@ const migrations = [ require('./25-add-emailConfig-to-event'), require('./26-fix-empty-senderEmail-in-event'), require('./27-add-experimental-flag-to-events'), + require('./28-add-gavel-login-to-registrations'), ] const run = async () => { diff --git a/backend/modules/event/controller.js b/backend/modules/event/controller.js index 88f17f2c5..cc924d480 100644 --- a/backend/modules/event/controller.js +++ b/backend/modules/event/controller.js @@ -42,6 +42,15 @@ controller.isEventOnline = id => { }) } +controller.isEventHybrid = id => { + Event.findById(id).then(event => { + if (event.eventType === 'hybrid') { + return true + } + return false + }) +} + controller.getUnapprovedEvents = () => { return Event.find({ approved: false }) } diff --git a/backend/modules/event/graphql.js b/backend/modules/event/graphql.js index 67eb99c50..f4c6bcf2f 100644 --- a/backend/modules/event/graphql.js +++ b/backend/modules/event/graphql.js @@ -714,7 +714,10 @@ const Resolvers = { ) }, _eventLocationFormatted: parent => { - if (parent.eventType === 'physical') { + if ( + parent.eventType === 'physical' || + parent.eventType === 'hybrid' + ) { return `${parent.eventLocation.city}, ${parent.eventLocation.country}` } return 'Online' diff --git a/backend/modules/event/model.js b/backend/modules/event/model.js index 2dd6a5108..a072f21e8 100644 --- a/backend/modules/event/model.js +++ b/backend/modules/event/model.js @@ -105,9 +105,12 @@ const EventSchema = new mongoose.Schema({ type: AddressSchema.mongoose, required: [ function () { - return this.eventType === EventTypes.physical.id + return ( + this.eventType === EventTypes.physical.id || + this.eventType === EventTypes.hybrid.id + ) }, - `is required for physical events`, + `is required for physical or hydrid events`, ], }, tracksEnabled: false, @@ -326,7 +329,7 @@ const EventSchema = new mongoose.Schema({ }, senderName: { type: String, - default: '', + default: 'Junction team', trim: true, maxLength: 100, }, diff --git a/backend/modules/project/controller.js b/backend/modules/project/controller.js index 8aed6abe9..703df6431 100644 --- a/backend/modules/project/controller.js +++ b/backend/modules/project/controller.js @@ -1,3 +1,4 @@ +const _ = require('lodash') const yup = require('yup') const bcrypt = require('bcrypt') const Promise = require('bluebird') @@ -5,7 +6,6 @@ const { ProjectSchema } = require('@hackjunction/shared') const Project = require('./model') const { ForbiddenError } = require('../../common/errors/errors') const TeamController = require('../team/controller') -const upload = require('../../misc/gridfs').upload const controller = {} @@ -60,9 +60,7 @@ controller.createProjectForEventAndTeam = async (event, team, data) => { controller.updateProjectForEventAndTeam = async (event, team, data) => { const schema = yup.object().shape(ProjectSchema(event)) - console.log('data :>> ', data) const validatedData = await schema.validate(data, { stripUnknown: true }) - console.log('validatedData :>> ', validatedData) const projects = await controller.getProjectsByEventAndTeam( event._id, team._id, @@ -75,11 +73,11 @@ controller.updateProjectForEventAndTeam = async (event, team, data) => { controller.generateChallengeLink = async (event, challengeSlug) => { const hashed = await bcrypt.hash(challengeSlug, global.gConfig.HASH_SALT) - // console.log('inhere challenge :>> ') return { hash: hashed, - link: `${global.gConfig.FRONTEND_URL}/projects/${event.slug - }/challenge/${encodeURIComponent(hashed)}`, + link: `${global.gConfig.FRONTEND_URL}/projects/${ + event.slug + }/challenge/${encodeURIComponent(hashed)}`, } } @@ -88,8 +86,9 @@ controller.generateTrackLink = async (event, trackSlug) => { // console.log('inhere track :>> ') return { hash: hashed, - link: `${global.gConfig.FRONTEND_URL}/projects/${event.slug - }/tracks/${encodeURIComponent(hashed)}`, + link: `${global.gConfig.FRONTEND_URL}/projects/${ + event.slug + }/tracks/${encodeURIComponent(hashed)}`, } } @@ -175,7 +174,14 @@ controller.validateToken = async (event, token) => { if (Challengematches.length === 0 && Trackmatches === 0) { throw new ForbiddenError('Invalid token') } - return true + console.log('Matches :>> ', Challengematches, Trackmatches) + if ( + (Array.isArray(Challengematches) && Challengematches.length > 0) || + (Array.isArray(Trackmatches) && Trackmatches.length > 0) + ) { + return true + } + return false } controller.getFinalProjects = async event => { @@ -211,3 +217,43 @@ controller.getFinalists = event => { return Project.find({ _id: { $in: event.finalists } }) } module.exports = controller + +controller.getDataForPartnerReviewing = async (event, user) => { + const data = {} + const teams = await TeamController.getAllTeamsForEvent(event._id) + const projects = await controller.getProjectPreviewsByEvent(event._id) + const projectsWithExistingTeamsAndFinal = _.filter(projects, project => { + if (project.status === 'final') { + const teamFound = _.find(teams, team => { + return `${team._id}` === `${project.team}` + }) + if (teamFound) { + return project + } + } + }) + + if (event.scoreCriteriaSettings.reviewAnyChallenge) { + data.projects = projectsWithExistingTeamsAndFinal + } else { + const challengeOrg = _.find( + event.recruiters, + recruiter => recruiter.recruiterId === user.sub, + ) + if (challengeOrg) { + const challengeData = _.find( + event.challenges, + challenge => challenge.partner === challengeOrg.organization, + ) + const projectsFilteredByChallenge = _.filter( + projectsWithExistingTeamsAndFinal, + project => _.includes(project.challenges, challengeData.slug), + ) + data.projects = projectsFilteredByChallenge + data.challenge = challengeData + } else { + data.projects = [] + } + } + return data +} diff --git a/backend/modules/project/model.js b/backend/modules/project/model.js index 4b89337ad..53754c608 100644 --- a/backend/modules/project/model.js +++ b/backend/modules/project/model.js @@ -125,7 +125,7 @@ ProjectSchema.post('save', async function (doc, next) { */ case ReviewingMethods.gavelPeerReview.id: { GavelController.ensureGavelProject(doc) - console.log("saved as gavel project") + console.log('saved as gavel project') break } default: { diff --git a/backend/modules/project/routes.js b/backend/modules/project/routes.js index 8a6c1d9c9..ca8a9b860 100644 --- a/backend/modules/project/routes.js +++ b/backend/modules/project/routes.js @@ -1,5 +1,4 @@ const express = require('express') - const router = express.Router() const asyncHandler = require('express-async-handler') @@ -12,6 +11,7 @@ const { canSubmitProject, isEventOrganiser, getEventFromParams, + isEventPartner, } = require('../../common/middleware/events') router.route('/id/:projectId').get( @@ -36,6 +36,22 @@ router }), ) +router + .route('/:slug/partner-review') + /** Get projects for partner review, only if their status is final, have a team and based on challenges */ + .get( + hasToken, + isEventPartner, + getEventFromParams, + asyncHandler(async (req, res) => { + const data = await ProjectController.getDataForPartnerReviewing( + req.event, + req.user, + ) + return res.status(200).json(data) + }), + ) + router .route('/:slug/validate') /** Validate project before submission on UI, non-blocking (doesn't prevent saving to db) */ diff --git a/backend/modules/project_score/controller.js b/backend/modules/project_score/controller.js index 438843085..07aa8029a 100644 --- a/backend/modules/project_score/controller.js +++ b/backend/modules/project_score/controller.js @@ -1,3 +1,4 @@ +const _ = require('lodash') const Event = require('../event/model') const Project = require('../project/model') const { ProjectScore } = require('./model') @@ -25,7 +26,6 @@ controller.addProjectScore = async score => { } projectScore.averageScore = averageScore } - console.log('ProjectScore from controller', projectScore) return projectScore.save() } @@ -54,7 +54,6 @@ controller.updateProjectScore = async (id, updatedProjectScore) => { } projectScore.averageScore = averageScore } - console.log('updated project with token score', projectScore) await projectScore.save() return projectScore } @@ -71,7 +70,7 @@ controller.getScoresByEventAndTeamId = (eventId, teamId) => { }) } -controller.getScoreByProjectId = ( +controller.getScoreByProjectId = async ( projectId, challenge = null, track = null, @@ -88,6 +87,18 @@ controller.getScoreByProjectId = ( return ProjectScore.find(query) } +controller.getScoreForProjectByReviewerId = async (projectId, reviewerId) => { + const testProjectScore = await controller.getScoreByProjectId(projectId) + if (testProjectScore && testProjectScore.length > 0) { + testProjectScore[0].reviewers.forEach(reviewer => {}) + const scoreFromReviewer = _.find( + testProjectScore[0].reviewers, + reviewerScore => reviewerScore.userId === reviewerId, + ) + return scoreFromReviewer + } +} + controller.getPublicScores = async eventId => { return ProjectScore.find({ event: eventId }) .populate({ path: 'event', select: 'name' }) @@ -101,11 +112,8 @@ const limitDecimals = (number, decimalPlaces) => { const averageScoreCalculation = (reviewers, globalScore) => { const allScores = reviewers.map(review => review.score) - console.log('All scores from reviewers', allScores) allScores.push(globalScore) - console.log('All scores with global score', allScores) let scoreCount = allScores.length - console.log('Score count', scoreCount) const scoreSum = allScores.reduce((acc, current) => { if (current && current > 0) { @@ -116,15 +124,10 @@ const averageScoreCalculation = (reviewers, globalScore) => { } }, 0) - console.log('Score sum', scoreSum) - console.log('Score count after', scoreCount) let finalScore = scoreSum / scoreCount if (!Number.isInteger(finalScore)) { finalScore = limitDecimals(finalScore, 2) - console.log('Not an integer') } - console.log('Score to submit', finalScore) - console.log('Score type', typeof finalScore) return finalScore } @@ -139,39 +142,6 @@ controller.updateProjectScoreWithReviewers = async ( projectScore.track = updatedProjectScore.track projectScore.challenge = updatedProjectScore.challenge projectScore.reviewers = updatedProjectScore.reviewers - console.log( - 'Updated project score from controller BEFORE save', - projectScore, - ) - - // const allScores = projectScore.reviewers.map(review => review.score) - // console.log('All scores from reviewers', allScores) - // allScores.push(projectScore.score) - // console.log('All scores with global score', allScores) - // let scoreCount = allScores.length - // console.log('Score count', scoreCount) - - // const scoreSum = allScores.reduce((acc, current) => { - // if (current && current > 0) { - // return acc + current - // } else { - // scoreCount = scoreCount - 1 - // return acc - // } - // }, 0) - // function limitDecimals(number, decimalPlaces) { - // const multiplier = Math.pow(10, decimalPlaces) - // return Math.floor(number * multiplier) / multiplier - // } - // console.log('Score sum', scoreSum) - // console.log('Score count after', scoreCount) - // let finalScore = scoreSum / scoreCount - // if (!Number.isInteger(finalScore)) { - // finalScore = limitDecimals(finalScore, 2) - // console.log('Not an integer') - // } - // console.log('Score to submit', finalScore) - // console.log('Score type', typeof finalScore) projectScore.averageScore = projectScore.score @@ -191,10 +161,6 @@ controller.updateProjectScoreWithReviewers = async ( // projectScore.averageScore = projectScore.score + await projectScore.save() - console.log( - 'Updated project score from controller AFTER save', - projectScore, - ) return projectScore } diff --git a/backend/modules/project_score/routes.js b/backend/modules/project_score/routes.js index 20d04aa88..25b0635ce 100644 --- a/backend/modules/project_score/routes.js +++ b/backend/modules/project_score/routes.js @@ -14,7 +14,6 @@ const { isEventPartner, isOrganiserOrCanSubmitProject, } = require('../../common/middleware/events') -const { registrationAccepted } = require('../email-task/types') const addProjectScore = asyncHandler(async (req, res) => { console.log('addProjectScore is running') @@ -127,7 +126,6 @@ router.get( getScoreByProjectId, ) - router.post('/event/:slug', hasToken, isEventOrganiser, addProjectScore) router.put('/event/:slug/:id', hasToken, isEventOrganiser, updateProjectScore) diff --git a/backend/modules/recruitment/controller.js b/backend/modules/recruitment/controller.js index 1ee843222..36e79963c 100644 --- a/backend/modules/recruitment/controller.js +++ b/backend/modules/recruitment/controller.js @@ -33,7 +33,6 @@ controller.queryProfiles = async (query = {}, user) => { } console.log(34) } else if (query.filters && query.filters.length) { - const whereFields = query.filters.map(filter => { //console.log("query.filter", filter.value) const formatted = MongoUtils.ensureObjectId(filter.value) @@ -116,7 +115,7 @@ controller.queryProfiles = async (query = {}, user) => { //console.log(110) } // userQuery.$and = userQuery.$and.concat([matcher]) - console.log('userquery', JSON.stringify(userQuery), "pag", pagination,) + console.log('userquery', JSON.stringify(userQuery), 'pag', pagination) //console.log("query", userQuery, "pag", pagination, "reg", JSON.stringify(userQuery.registrations)) return UserController.queryProfiles({ query: userQuery, @@ -127,7 +126,7 @@ controller.queryProfiles = async (query = {}, user) => { return controller.createRecruitmentProfile(profile, false) }), ).then(profiles => { - + console.log('profiles', profiles) return { data: profiles, count: results.count } }) }) diff --git a/backend/modules/registration/controller.js b/backend/modules/registration/controller.js index b58191082..dfb9bd055 100644 --- a/backend/modules/registration/controller.js +++ b/backend/modules/registration/controller.js @@ -15,7 +15,7 @@ const Registration = require('./model') const { NotFoundError, ForbiddenError } = require('../../common/errors/errors') const RegistrationHelpers = require('./helpers') const EmailTaskController = require('../email-task/controller') -const { checklistItemsOnline, checklistItemsPhysical } = require('./checklists') +// const { checklistItemsOnline, checklistItemsPhysical } = require('./checklists') const STATUSES = RegistrationStatuses.asObject const TRAVEL_GRANT_STATUSES = RegistrationTravelGrantStatuses.asObject @@ -28,56 +28,49 @@ controller.getUserRegistrations = user => { } controller.createRegistration = async (user, event, data) => { - console.log("user", user) const answers = await RegistrationHelpers.registrationFromUser(data) const registration = new Registration({ event: event._id.toString(), user: user.sub, answers, }) - if (event.eventType === 'online') { - registration.checklist = { - items: checklistItemsOnline(), - } - } else { - registration.checklist = { - items: checklistItemsPhysical(), - } - } + // if (event.eventType === 'online') { + // registration.checklist = { + // items: checklistItemsOnline(), + // } + // } else { + // registration.checklist = { + // items: checklistItemsPhysical(), + // } + // } registration.status = RegistrationStatuses.asObject.incomplete.id - console.log("createRegistration", registration) + console.log('createRegistration', registration) return registration.save() - /* .catch(function (err) { - console.log(err.name, err.errors) - }) */ } controller.createPartnerRegistration = async (user, event, data) => { - console.log("user", user) + console.log('user', user) const answers = await RegistrationHelpers.registrationFromUser(data) const registration = new Registration({ event: event._id.toString(), user: user, answers, }) - if (event.eventType === 'online') { - registration.checklist = { - items: checklistItemsOnline(), - } - } else { - registration.checklist = { - items: checklistItemsPhysical(), - } - } + // if (event.eventType === 'online') { + // registration.checklist = { + // items: checklistItemsOnline(), + // } + // } else { + // registration.checklist = { + // items: checklistItemsPhysical(), + // } + // } registration.status = RegistrationStatuses.asObject.incomplete.id - console.log("createRegistration", registration) + console.log('create registration for partner', registration) return registration.save() - /* .catch(function (err) { - console.log(err.name, err.errors) - }) */ } -controller.getRegistration = (userId, eventId) => { +controller.getRegistration = async (userId, eventId) => { return Registration.findOne({ event: eventId, user: userId, @@ -99,7 +92,6 @@ controller.updateRegistration = (user, event, data) => { await RegistrationHelpers.validateAnswers(data, event) // answers are valid if (answers) { - return Registration.updateAllowed(registration, { answers }) } return false @@ -120,15 +112,20 @@ controller.finishRegistration = (user, event, data) => { registration.status === RegistrationStatuses.asObject.incomplete.id ) { - if (event.eventType === EventTypes.physical.id) { - registration.status = - RegistrationStatuses.asObject.pending.id - } + registration.status = + RegistrationStatuses.asObject.pending.id + // if ( + // event.eventType === EventTypes.physical.id || + // event.eventType === EventTypes.hybrid.id + // ) { + // registration.status = + // RegistrationStatuses.asObject.pending.id + // } // TODO we most likely don't want to do this here? Get desired state from event? - if (event.eventType === EventTypes.online.id) { - registration.status = - RegistrationStatuses.asObject.checkedIn.id - } + // if (event.eventType === EventTypes.online.id) { + // registration.status = + // RegistrationStatuses.asObject.checkedIn.id + // } } return Registration.updateAllowed(registration, { answers }) } @@ -460,7 +457,7 @@ controller.rejectPendingTravelGrants = eventId => { controller.getFullRegistration = (eventId, registrationId) => { const query = mongoose.Types.ObjectId.isValid(registrationId) && - registrationId.indexOf('|') === -1 + registrationId.indexOf('|') === -1 ? { _id: registrationId } : { user: registrationId } return Registration.findOne(query) @@ -525,4 +522,36 @@ controller.rejectSoftRejected = async eventId => { return rejected } +controller.addGavelLoginToRegistrations = async (eventId, gavelData) => { + console.log('Gavel data received', gavelData, typeof gavelData) + let updateCount = 0 + const registrations = await Registration.find({ + event: eventId, + status: RegistrationStatuses.asObject.checkedIn.id, + }) + console.log('Registrations found', registrations.length) + console.log('Registrations data', registrations) + const registrationCount = registrations.length + + gavelData.forEach(gavel => { + const registration = registrations.find( + r => r._id.toString() === gavel.registration, + ) + if (registration) { + registration.gavelLogin = gavel.link + updateCount++ + console.log('Registration full data', registration) + registration.save() + } + }) + + console.log( + 'Modified counts, updated/total', + updateCount, + registrationCount, + ) + // Go through gavelData and assign the login URL to their corresponding registration + // const registration = await Registration +} + module.exports = controller diff --git a/backend/modules/registration/helpers.js b/backend/modules/registration/helpers.js index e8f5647fa..ae8c9a48f 100644 --- a/backend/modules/registration/helpers.js +++ b/backend/modules/registration/helpers.js @@ -56,7 +56,6 @@ const RegistrationHelpers = { .validate(data, { stripUknown: true }) .catch(e => { // TODO proper log - console.log('error in validateAnswers', e) return minSchema .validate(data, { stripUknown: true }) .catch(ee => { @@ -89,12 +88,8 @@ const RegistrationHelpers = { }) const schema = yup.object().shape(validationSchema) - console.log('users', d) - const data = schema.validate(d, { stripUknown: true }).catch(e => { - console.log('RFU', e) - }) - console.log('got data', data) + const data = schema.validate(d, { stripUknown: true }).catch(e => {}) return data }, buildAggregation: (eventId, userId, qp) => { diff --git a/backend/modules/registration/model.js b/backend/modules/registration/model.js index 3ae3e9c50..d753645de 100644 --- a/backend/modules/registration/model.js +++ b/backend/modules/registration/model.js @@ -79,6 +79,9 @@ const RegistrationSchema = new mongoose.Schema({ travelGrantAmount: { type: Number, }, + gavelLogin: { + type: String, + }, }) /* Only allow a single registration per event per user */ diff --git a/backend/modules/registration/routes.js b/backend/modules/registration/routes.js index ef0367778..5706d9e93 100644 --- a/backend/modules/registration/routes.js +++ b/backend/modules/registration/routes.js @@ -32,15 +32,13 @@ const getRegistration = asyncHandler(async (req, res) => { }) const createRegistration = asyncHandler(async (req, res) => { - console.log("creating registration with data:", - "user: ", req.user, - "event ", req.event, - "data ", req.body) + console.log('creating registration from routes') const registration = await RegistrationController.createRegistration( req.user, req.event, req.body, ) + console.log('registration complete') return res.status(201).json(registration) }) @@ -217,31 +215,39 @@ const bulkRejectRegistrations = asyncHandler(async (req, res) => { }) const addPartnerToRegistrated = asyncHandler(async (req, res) => { - - console.log("addPartnerToRegistrated", req.body) + console.log('addPartnerToRegistrated', req.body) //TODO: should check if the user is registered already first try { - const hasRegistration = await RegistrationController.getRegistration(req.body.userId, req.event._id) + const hasRegistration = await RegistrationController.getRegistration( + req.body.userId, + req.event._id, + ) return res.status(200).json(hasRegistration) } catch (e) { - console.log("hasRegistration", e) - const registration = await RegistrationController.createPartnerRegistration( - req.body.userId, //switch to actual user - req.event, //slug - req.body.profile, /*data: { + console.log('hasRegistration', e) + const registration = + await RegistrationController.createPartnerRegistration( + req.body.userId, //switch to actual user + req.event, //slug + req.body.profile /*data: { firstName: 'seppo', lastName: 'pykälä', email: 'samu.rotko@gmail.com' - }*/ - ) + }*/, + ) return res.status(200).json(registration) } +}) +const addGavelLoginToRegistrations = asyncHandler(async (req, res) => { + console.log('Event id', req.event._id) + console.log('From routes, for gavel login', req.body) + await RegistrationController.addGavelLoginToRegistrations( + req.event._id.toString(), + req.body, + ) - - - - + return res.status(200).json([]) }) router.route('/').get(hasToken, getUserRegistrations) @@ -388,4 +394,13 @@ router addPartnerToRegistrated, ) +router + .route('/:slug/gavel') + .post( + hasToken, + hasPermission(Auth.Permissions.MANAGE_EVENT), + isEventOrganiser, + addGavelLoginToRegistrations, + ) + module.exports = router diff --git a/frontend/src/components/UserMenu/index.js b/frontend/src/components/UserMenu/index.js index 39b83b167..945ba4595 100644 --- a/frontend/src/components/UserMenu/index.js +++ b/frontend/src/components/UserMenu/index.js @@ -2,12 +2,7 @@ import React, { useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { push } from 'connected-react-router' import { makeStyles } from '@material-ui/core/styles' -import { - Box, - ListItem, - ListItemText, - Grid, -} from '@material-ui/core' +import { Box, ListItem, ListItemText, Grid } from '@material-ui/core' import * as AuthSelectors from 'redux/auth/selectors' import JunctionTheme from 'junctionTheme.js' import Button from 'components/generic/Button' @@ -45,17 +40,12 @@ export default () => { const idTokenPayload = useSelector(AuthSelectors.getIdTokenPayload) const userId = idTokenPayload?.sub - const [profile] = useMyProfilePreview() const dispatch = useDispatch() const classes = useStyles() - - if (!userId) { return ( - - - - ) } - - return ( - - + - - - + - - - + ) -} \ No newline at end of file +} diff --git a/frontend/src/pages/_dashboard/renderDashboard/default/events/Organizer.js b/frontend/src/pages/_dashboard/renderDashboard/default/events/Organizer.js index a3dc38afb..cf5b256bc 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/default/events/Organizer.js +++ b/frontend/src/pages/_dashboard/renderDashboard/default/events/Organizer.js @@ -16,8 +16,7 @@ import * as UserActions from 'redux/user/actions' import CreateEventCard from './CreateEventCard' import TextInput from '../../../../../components/inputs/TextInput' - - +import { debugGroup } from 'utils/debuggingTools' //TODO: make this to use theme colors and make prettier const useStyles = makeStyles({ @@ -66,49 +65,48 @@ export default () => { var date = new Date() const isodate = date.toISOString() - const [searchTerm, setSearchTerm] = React.useState('') + const [searchTerm, setSearchTerm] = useState('') const [searchResults, setSearchResults] = useState(organizerEvents) const [name, setName] = useState('') const [error, setError] = useState() const [loading, setLoading] = useState(false) const hasError = Boolean(error) - - const isOrganizer = useSelector(AuthSelectors.idTokenData)?.roles?.some(r => - ["Organiser", "AssistantOrganiser", "SuperAdmin"].includes(r) + ['Organiser', 'AssistantOrganiser', 'SuperAdmin'].includes(r), ) - - useEffect(() => { - if (hasError) { - if (name.length < 5) { - setError(t('Name_must_five_')) - } else if (name.length >= 50) { - setError(t('Name_must_under_')) - } else if (name === "default") { - setError(t('Name_not_default_')) - } else { - setError() - } - } - }, [name, hasError, t]) - - const checkName = useCallback(() => { - if (name.length < 5) { - setError(t('Name_must_five_')) - return false - } else if (name.length >= 50) { - setError(t('Name_must_under_')) - return false - } else if (name === "default") { - setError(t('Name_not_default_')) - return false - } - return true - }, [name.length, t]) - - console.log("organizerEvents", organizerEvents) + // useEffect(() => { + // if (hasError) { + // if (name.length < 5) { + // setError(t('Name_must_five_')) + // } else if (name.length >= 50) { + // setError(t('Name_must_under_')) + // } else if (name === 'default') { + // setError(t('Name_not_default_')) + // } else { + // setError() + // } + // } + // }, [name, hasError, t]) + + // const checkName = useCallback(() => { + // if (name.length < 5) { + // setError(t('Name_must_five_')) + // return false + // } else if (name.length >= 50) { + // setError(t('Name_must_under_')) + // return false + // } else if (name === 'default') { + // setError(t('Name_not_default_')) + // return false + // } + // return true + // }, [name.length, t]) + + console.log('organizerEvents', organizerEvents) + + //TODO implement pagination to improve performance of organize tab useEffect(() => { const results = organizerEvents.filter( @@ -119,108 +117,100 @@ export default () => { setSearchResults(results) }, [organizerEvents, searchTerm]) - //TODO: super slow on superadmin. fix the rendering - return (organizerEvents.length === 0 || !isOrganizer) ? - ( - ( - <> - - - - - - - - - ) - ) - : - ( - <> - - - - - - - - - - - + return organizerEvents.length === 0 || !isOrganizer ? ( + <> + + + + + + + + ) : ( + <> + + + + + - - - {searchResults.map(event => ( - -
- {event.published && event.approved ? ( - - Published! - - ) : null} - {event.published && !event.approved ? ( - - Waiting approval - - ) : null} - {!event.published ? ( - - Not published - - ) : null} -
- - - dispatch(push('/events/' + event.slug)) - } - > - {t('See_more_')} - , - , - ]} - /> - -
- ))} + + -
- - ) - - -} \ No newline at end of file +
+ + + {searchResults.map(event => ( + +
+ {event.published && event.approved ? ( + + Published! + + ) : null} + {event.published && !event.approved ? ( + + Waiting approval + + ) : null} + {!event.published ? ( + + Not published + + ) : null} +
+ + + dispatch( + push('/events/' + event.slug), + ) + } + > + {t('See_more_')} + , + , + ]} + /> +
+ ))} +
+
+ + ) +} diff --git a/frontend/src/pages/_dashboard/renderDashboard/default/events/Participant.js b/frontend/src/pages/_dashboard/renderDashboard/default/events/Participant.js index 001ac223b..314b1fb6d 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/default/events/Participant.js +++ b/frontend/src/pages/_dashboard/renderDashboard/default/events/Participant.js @@ -14,13 +14,10 @@ import Button from 'components/generic/Button' import PageWrapper from 'components/layouts/PageWrapper' import Container from 'components/generic/Container' - import * as AuthSelectors from 'redux/auth/selectors' import * as DashboardSelectors from 'redux/dashboard/selectors' import * as UserActions from 'redux/user/actions' - - export default () => { const userId = useSelector(AuthSelectors.getUserId) const activeEvents = useSelector(DashboardSelectors.activeEvents) @@ -28,11 +25,9 @@ export default () => { const [registrations, loading, error] = useRegistrationsByUser(userId) //useSelector(UserSelectors.registrations) - - - console.log("activeEvents", activeEvents) - console.log("pastEvents", pastEvents) - console.log("registrations", registrations) + console.log('activeEvents', activeEvents) + console.log('pastEvents', pastEvents) + console.log('registrations', registrations) const dispatch = useDispatch() const { t } = useTranslation() @@ -40,7 +35,6 @@ export default () => { const isodate = date.toISOString() function renderEvents() { - return ( <> { - - {registrations.length === 0 && ( - - {t('Looks_like_register_')} - - )} + {Array.isArray(registrations) && + registrations.length === 0 && ( + + {t('Looks_like_register_')} + + )} {registrations?.map(registration => ( @@ -64,45 +58,63 @@ export default () => { { - dispatch(UserActions.setAccessRight('participant'))//TODO: make this a schema - dispatch(push(`/dashboard/event/${event?.slug}`)) - } - } + dispatch( + UserActions.setAccessRight( + 'participant', + ), + ) //TODO: make this a schema + dispatch( + push( + `/dashboard/event/${event?.slug}`, + ), + ) + }} /> ))}
- -

Upcoming Events

+

Upcoming Events

- {activeEvents?.filter(event => - registrations?.map(e => e.event?.slug).indexOf(event?.slug) === -1 - ) + {activeEvents + ?.filter( + event => + registrations + ?.map(e => e.event?.slug) + .indexOf(event?.slug) === -1, + ) .map(event => { const canApply = isodate < event.registrationEndTime && isodate > event.registrationStartTime const eventStarted = isodate > event.startTime - console.log("button render", event.slug, canApply && !event.galleryOpen, event.galleryOpen && eventStarted) + console.log( + 'button render', + event.slug, + canApply && !event.galleryOpen, + event.galleryOpen && eventStarted, + ) return ( - dispatch(push('/events/' + event.slug)) - } - > - {t('See_more_')} - - ), + , canApply && ( ), - event.galleryOpen && eventStarted && ( - - ), - - - - - - + event.galleryOpen && + eventStarted && ( + + ), ]} - />) - } - ) - } + /> + ) + })} - + -

Past Events

+

Past Events

@@ -161,38 +172,43 @@ export default () => { - dispatch(push('/events/' + event.slug)) - } - > - {t('See_more_')} - - ), - + , event.galleryOpen && eventStarted && ( ), ]} - />) - } - ) - } + /> + ) + })} - + , ]} - />) + /> + ) })} - + ) } @@ -94,12 +110,7 @@ export default () => { return ( ( - - {renderEvents()} - - ) - } + render={() => {renderEvents()}} /> ) -} \ No newline at end of file +} diff --git a/frontend/src/pages/_dashboard/renderDashboard/generalPages/default/Blocks/ReviewingPeriodBlock.js b/frontend/src/pages/_dashboard/renderDashboard/generalPages/default/Blocks/ReviewingPeriodBlock.js index b9ebd44d2..461b73462 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/generalPages/default/Blocks/ReviewingPeriodBlock.js +++ b/frontend/src/pages/_dashboard/renderDashboard/generalPages/default/Blocks/ReviewingPeriodBlock.js @@ -21,23 +21,30 @@ export default () => { dispatch(DashboardActions.updateAnnotator(event.slug)) } }, [event, dispatch]) - if (event.reviewMethod === 'manualReview' && EventHelpers.isVotingOpen(event, moment)) return ( - - - Reviewing period - Reviewing period is open! - - Reviewing ends {moment(event.reviewingEndTime).fromNow()} - - - Sit back and relax while we review your project! - - - - + if ( + event.reviewMethod === 'gavelPeerReview' && + EventHelpers.isReviewingOpen(event, moment) ) + return ( + + + Reviewing period + + Reviewing period is open! + + + Reviewing ends{' '} + {moment(event.reviewingEndTime).fromNow()} + + + Sit back and relax while your project is reviewed! + + + + + ) - if (!EventHelpers.isVotingOpen(event, moment)) return null + if (!EventHelpers.isReviewingOpen(event, moment)) return null return ( @@ -55,7 +62,9 @@ export default () => { + + )} ) } diff --git a/frontend/src/pages/_dashboard/renderDashboard/organiser/participants/index.js b/frontend/src/pages/_dashboard/renderDashboard/organiser/participants/index.js index fd2e2ff59..d22c0fc85 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/organiser/participants/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/organiser/participants/index.js @@ -8,7 +8,7 @@ import PageHeader from 'components/generic/PageHeader' import DefaultTab from './default' import TeamsTab from './teams' import AssignedTab from './assigned' -import TravelTab from './travel' +// import TravelTab from './travel' import AdminTab from './admin' export default () => { diff --git a/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/by-challenge/index.js b/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/by-challenge/index.js index 53d2edbd0..1d327c177 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/by-challenge/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/by-challenge/index.js @@ -18,9 +18,24 @@ import * as OrganiserSelectors from 'redux/organiser/selectors' export default () => { const event = useSelector(OrganiserSelectors.event) const projects = useSelector(OrganiserSelectors.projects) + const teams = useSelector(OrganiserSelectors.teams) const getProjectsForChallenge = slug => { - return projects.filter(project => { + const projectsWithTeam = projects + .map(project => { + const teamFound = teams.find(team => { + console.log(team._id, project.team) + return team._id === project.team + }) + if (teamFound) { + project.teamCode = teamFound.code + } else { + project.teamCode = 'No team' + } + return project + }) + .filter(project => project.teamCode !== 'No team') + return projectsWithTeam.filter(project => { return project.challenges && project.challenges.indexOf(slug) !== -1 }) } diff --git a/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/by-track/index.js b/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/by-track/index.js index 29238b6fc..051d4fc99 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/by-track/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/by-track/index.js @@ -17,9 +17,24 @@ import TrackLink from './TrackLink' export default () => { const event = useSelector(OrganiserSelectors.event) const projects = useSelector(OrganiserSelectors.projects) + const teams = useSelector(OrganiserSelectors.teams) const getProjectsForTrack = slug => { - return projects.filter(project => project.track === slug) + const projectsWithTeam = projects + .map(project => { + const teamFound = teams.find(team => { + console.log(team._id, project.team) + return team._id === project.team + }) + if (teamFound) { + project.teamCode = teamFound.code + } else { + project.teamCode = 'No team' + } + return project + }) + .filter(project => project.teamCode !== 'No team') + return projectsWithTeam.filter(project => project.track === slug) } return ( diff --git a/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/finalist-selection/index.js b/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/finalist-selection/index.js index fc8066909..67c764476 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/finalist-selection/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/finalist-selection/index.js @@ -1,4 +1,4 @@ -import React, { useState } from 'react' +import React, { useEffect, useState } from 'react' import { Grid, @@ -45,18 +45,18 @@ export default () => { const idToken = useSelector(AuthSelectors.getIdToken) const [loading, setLoading] = useState(false) - const [checked, setChecked] = React.useState([]) - const [left, setLeft] = React.useState([]) - const [filteredLeft, setFilteredLeft] = React.useState([]) + const [checked, setChecked] = useState([]) + const [left, setLeft] = useState([]) + const [filteredLeft, setFilteredLeft] = useState([]) - const [right, setRight] = React.useState([]) - const [filter, setFilter] = React.useState('') + const [right, setRight] = useState([]) + const [filter, setFilter] = useState('') const debouncedFilter = useDebounce(filter, 300) const leftChecked = intersection(checked, left) const rightChecked = intersection(checked, right) - React.useEffect(() => { + useEffect(() => { const newLeft = projects ?.filter(project => !event?.finalists?.includes(project._id)) @@ -70,7 +70,7 @@ export default () => { ) }, [projects, event]) - React.useEffect(() => { + useEffect(() => { if (debouncedFilter) { const availableProjects = projects.filter(p => left.includes(p._id)) setFilteredLeft( diff --git a/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/index.js b/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/index.js index 7d87972b8..ce2be0e7f 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/index.js @@ -11,8 +11,8 @@ import PageHeader from 'components/generic/PageHeader' import DefaultTab from './default' import ChallengesTab from './by-challenge' import TracksTab from './by-track' -import GavelTab from './gavel' -import AnnotatorsTab from './annotators' +// import GavelTab from './gavel' +// import AnnotatorsTab from './annotators' import WinnersTab from './winners' import FinalistSelectionTab from './finalist-selection' import VotingTokensTab from './votingTokens' @@ -51,19 +51,19 @@ export default () => { }) } - data.push({ - path: '/gavel', - key: 'gavel', - label: 'Gavel voting', - component: GavelTab, - }) + // data.push({ + // path: '/gavel', + // key: 'gavel', + // label: 'Gavel voting', + // component: GavelTab, + // }) - data.push({ - path: '/annotators', - key: 'annotators', - label: 'Gavel annotators', - component: AnnotatorsTab, - }) + // data.push({ + // path: '/annotators', + // key: 'annotators', + // label: 'Gavel annotators', + // component: AnnotatorsTab, + // }) if ( event?.overallReviewMethod === diff --git a/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/winners/index.js b/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/winners/index.js index b160d164d..1b777b90a 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/winners/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/organiser/projects/winners/index.js @@ -16,6 +16,7 @@ import EventsService from 'services/events' import WinnerVoteService from 'services/winnerVote' import VotingTokenService from 'services/votingToken' +import { debugGroup } from 'utils/debuggingTools' export default () => { const event = useSelector(OrganiserSelectors.event) @@ -86,15 +87,13 @@ export default () => { return ( <> - {total}
Participant votes: {scoreFromUsers}
Token votes: {scoreFromTokenVoters} - ) } - console.log('resus are', results) + debugGroup('Results', results) return ( diff --git a/frontend/src/pages/_dashboard/renderDashboard/participant/index.js b/frontend/src/pages/_dashboard/renderDashboard/participant/index.js index 0e2b74838..16a5c73cb 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/participant/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/participant/index.js @@ -78,13 +78,6 @@ export default ({ useEffect(() => { setAlerts(originalAlerts) setAlertCount(originalAlertCount) - console.log( - 'set alerts', - alerts, - originalAlerts, - alertCount, - originalAlertCount, - ) }, [originalAlerts, originalAlertCount]) return ( @@ -121,14 +114,6 @@ export default ({ return DefaultPage({ alerts }) }, }, - { - key: 'map', - path: '/map', - exact: false, - icon: , - label: 'Map', - component: MapPage, - }, { key: 'finals', path: '/finalist-voting', @@ -195,11 +180,11 @@ export default ({ key: 'challenges', path: '/challenges', exact: true, + hidden: !shownPages.challengesEnabled, icon: , label: 'Challenges', component: ChallengesIndex, }, - { key: 'calendar', path: '/calendar', @@ -210,6 +195,15 @@ export default ({ component: CalendarPage, }, // Experimental + { + key: 'map', + hidden: !shownPages.experimental, + path: '/map', + exact: false, + icon: , + label: 'Map', + component: MapPage, + }, { key: 'chat', hidden: !shownPages.experimental, diff --git a/frontend/src/pages/_dashboard/renderDashboard/participant/project/ProjectsList.js b/frontend/src/pages/_dashboard/renderDashboard/participant/project/ProjectsList.js index f1bf146a9..dced7d63b 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/participant/project/ProjectsList.js +++ b/frontend/src/pages/_dashboard/renderDashboard/participant/project/ProjectsList.js @@ -4,19 +4,13 @@ import { Paper, Typography, Chip, Box, Grid } from '@material-ui/core' import * as DashboardSelectors from 'redux/dashboard/selectors' -import ProjectScoreModal from 'components/modals/ProjectScoreModal' import Button from 'components/generic/Button' export default props => { const event = useSelector(DashboardSelectors.event) const projects = useSelector(DashboardSelectors.projects) - const projectScores = useSelector(DashboardSelectors.projectScores) - const projectSelectedCallback = props.projectSelectedCallback - const [selectedProjectScore, setSelectedProjectStore] = useState(null) - const [projectScoreModalOpen, setProjectScoreModalOpen] = useState(false) - const [challengeAndTrackSlugState, setChallengeAndTrackSlugState] = useState({}) @@ -35,42 +29,6 @@ export default props => { } setChallengeAndTrackSlugState(challengeAndTrackSlugToNameMap) }, [event]) - - useEffect(() => { - if (projectScoreModalOpen) { - setSelectedProjectStore( - projectScores.find(s => s._id === selectedProjectScore._id), - ) - } - }, [projectScoreModalOpen, projectScores, selectedProjectScore]) - - // const showProjectScore = project => { - // const score = projectScores.find( - // score => score.project._id === project._id, - // ) - // setSelectedProjectStore(score) - // setProjectScoreModalOpen(true) - // } - - // Checks whether there are more unique challenges that the competitor has not submitted - // a solution to yet. - // const canAddMoreSubmissions = () => { - // if (event && event.challenges && projects) { - // const challengesWithSubmittedProjects = [].concat.apply( - // [], - // projects.map(project => project.challenges), - // ) - // return ( - // event.challenges.filter( - // challenge => - // challengesWithSubmittedProjects.indexOf( - // challenge.slug, - // ) < 0, - // ).length > 0 - // ) - // } - // return false - // } const ProjectCard = props => { const project = props.project return ( @@ -114,13 +72,6 @@ export default props => { > Edit Submission - {/**/} @@ -167,11 +118,11 @@ export default props => { ) } - setProjectScoreModalOpen(false)} - /> + /> */} ) } diff --git a/frontend/src/pages/_dashboard/renderDashboard/participant/project/SubmissionForm.js b/frontend/src/pages/_dashboard/renderDashboard/participant/project/SubmissionForm.js index 361c55602..bf9b45239 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/participant/project/SubmissionForm.js +++ b/frontend/src/pages/_dashboard/renderDashboard/participant/project/SubmissionForm.js @@ -12,14 +12,13 @@ import * as DashboardActions from 'redux/dashboard/actions' import * as SnackbarActions from 'redux/snackbar/actions' import * as AuthSelectors from 'redux/auth/selectors' import { makeStyles } from '@material-ui/core/styles' -import { useTranslation } from 'react-i18next' import SubmissionFormCustomInput from 'components/inputs/SubmissionFormCustomInput' import BottomBar from 'components/inputs/BottomBar' import NameField from 'components/projects/ProjectSubmissionFields/NameField' import _ from 'lodash' import StatusField from 'components/projects/ProjectSubmissionFields/StatusField' import ProjectFieldsComponents from 'constants/projectFields' -import { debugGroup } from 'utils/debuggingTools' +import { projectURLgenerator } from 'utils/dataModifiers' const useStyles = makeStyles(theme => ({ uppercase: { 'text-transform': 'uppercase' }, @@ -27,22 +26,19 @@ const useStyles = makeStyles(theme => ({ // TODO make the form labels and hints customizable const SubmissionForm = props => { - debugGroup('SubmissionForm >>', props) const id = props.id + const projectURL = projectURLgenerator(props?.eventSlug, id) const handleProjectSelected = props.handleProjectSelected const classes = useStyles() const dispatch = useDispatch() const event = useSelector(DashboardSelectors.event) const idTokenData = useSelector(AuthSelectors.idTokenData) - const idToken = useSelector(AuthSelectors.getIdToken) - const { t } = useTranslation() const projects = useSelector(DashboardSelectors.projects) const projectLoading = useSelector(DashboardSelectors.projectsLoading) const [project, setProject] = useState(null) const [projectStatus, setProjectStatus] = useState('') useEffect(() => { - debugGroup('useEffect in submissionForm', [project, id]) if (projects && projects.length > 0 && id) { const foundProject = projects.find(p => p._id === id) setProject(foundProject) @@ -94,7 +90,10 @@ const SubmissionForm = props => { }, [event]) const locationEnabled = useMemo(() => { - return event.eventType === EventTypes.physical.id + return ( + event.eventType === EventTypes.physical.id || + event.eventType === EventTypes.hybrid.id + ) }, [event]) const valuesFormatter = values => { @@ -104,6 +103,7 @@ const SubmissionForm = props => { event.submissionFormQuestions.forEach(section => { const sec = section.name section.questions.forEach(question => { + const label = question?.label const que = question.name const value = values[que] const custom = { @@ -111,11 +111,11 @@ const SubmissionForm = props => { key: que, value: value, } + if (label) custom['label'] = label formData['submissionFormAnswers'].push(custom) }) }) } - console.log('formData after formatting:>> ', formData) return formData } @@ -166,10 +166,27 @@ const SubmissionForm = props => { > {projectStatus} - - Remember to update the project status to final if you - want this project to be graded! - + {projectStatus !== 'final' ? ( + + Remember to update the project status to final if + you want this project to be graded! + + ) : ( + projectURL && ( + <> + + Your project's public URL is: + + + {projectURL} + + + ) + )} @@ -276,7 +293,6 @@ const SubmissionForm = props => { ) } } catch (error) { - console.error('An error occurred:', error) dispatch( SnackbarActions.error('Oops, something went wrong...', { autoHideDuration: 10000, diff --git a/frontend/src/pages/_dashboard/renderDashboard/participant/project/index.js b/frontend/src/pages/_dashboard/renderDashboard/participant/project/index.js index 437d42134..1edf7859e 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/participant/project/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/participant/project/index.js @@ -223,6 +223,7 @@ export default () => { )} diff --git a/frontend/src/pages/_dashboard/renderDashboard/participant/reviewing/CompareProjects.js b/frontend/src/pages/_dashboard/renderDashboard/participant/reviewing/CompareProjects.js index cdd023b84..afcdffc31 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/participant/reviewing/CompareProjects.js +++ b/frontend/src/pages/_dashboard/renderDashboard/participant/reviewing/CompareProjects.js @@ -102,7 +102,8 @@ export default ({ annotator, prevId, nextId, isFirstChoice }) => { { { { const dispatch = useDispatch() const team = useSelector(DashboardSelectors.team) const event = useSelector(DashboardSelectors.event) + const registration = useSelector(DashboardSelectors.registration) const annotator = useSelector(DashboardSelectors.annotator) const annotatorError = useSelector(DashboardSelectors.annotatorError) const annotatorLoading = useSelector(DashboardSelectors.annotatorLoading) @@ -40,32 +44,169 @@ export default () => { ) } - if (!annotator) { - return + if (registration?.gavelLogin) { + return ( +
+ + + { + if (completed) { + return ( + { + if (!completed) { + return ( + <> + + The reviewing + period is open! + Time left:{' '} + { + formatted.hours + } + : + { + formatted.minutes + } + : + { + formatted.seconds + } + + + Once you click + "Start + reviewing", a + new tab will + open on your + browser were you + can start + reviewing the + projects. + + +

+ Copy this link + if for some + reason the + button doesn't + work: + { + registration?.gavelLogin + } +

+ + ) + } else { + return ( + + The reviewing period + is over! Thanks for + participating! + + ) + } + }} + /> + ) + } else { + return ( + <> + + The reviewing period begins in{' '} + {formatted.hours}: + {formatted.minutes}: + {formatted.seconds} + + + Come back here then! + + + ) + } + }} + /> +
+
+ ) } - if (!annotator.active) { - return - } + return - if (!annotator.prev && annotator.next) { - return - } + // if (!annotator) { + // return + // } - if (annotator.prev && annotator.next) { - return ( - - ) - } + // if (!annotator.active) { + // return + // } + + // if (!annotator.prev && annotator.next) { + // return + // } + + // if (annotator.prev && annotator.next) { + // return ( + // + // ) + // } - return + // return } - console.log("annotator", annotator, annotatorError) + // console.log("annotator", annotator, annotatorError) return ( {renderContent()} diff --git a/frontend/src/pages/_dashboard/renderDashboard/participant/team/teams/index.js b/frontend/src/pages/_dashboard/renderDashboard/participant/team/teams/index.js index a409ebfc9..822652da4 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/participant/team/teams/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/participant/team/teams/index.js @@ -21,7 +21,7 @@ export default () => { const dispatch = useDispatch() const event = useSelector(DashboardSelectors.event) const { slug } = event - + //TODO create pagination component const teams = useSelector(DashboardSelectors.teams) const hasTeam = useSelector(DashboardSelectors.hasTeam) const [selected, setSelected] = useState(false) @@ -90,8 +90,6 @@ export default () => { }, [currentPage]) const renderPagination = () => { - console.log('props', currentPage, totalResults, totalPages) - return ( ({ sidebarTop: { padding: theme.spacing(3), @@ -45,7 +46,13 @@ const useStyles = makeStyles(theme => ({ }, })) -export default ({ event, originalAlertCount, originalAlerts, shownPages }) => { +export default ({ + event, + originalAlertCount, + originalAlerts, + shownPages, + lockedPages, +}) => { const classes = useStyles() const { t } = useTranslation() const match = useRouteMatch() @@ -53,11 +60,6 @@ export default ({ event, originalAlertCount, originalAlerts, shownPages }) => { const [alertCount, setAlertCount] = useState(originalAlertCount) const [alerts, setAlerts] = useState(originalAlerts) - // const event = useSelector(DashboardSelectors.event) - - console.log('props', originalAlertCount, originalAlerts, shownPages) - console.log(originalAlertCount, alertCount) - return ( { component: () => { setAlertCount(0) if (shownPages?.experimental) { - return

Test

+ return

Experimental enabled

} return DefaultPage({ alerts }) }, }, - { - key: 'map', - path: '/map', - exact: false, - icon: , - label: 'Map', - component: MapPage, - }, { key: 'Review', - path: '/Review', - hidden: !shownPages?.reviewingByScoreCriteria, + path: '/review', + // hidden: !shownPages?.reviewingByScoreCriteria, + locked: lockedPages.reviewing, + lockedDescription: 'Reviewing closed', exact: false, icon: , label: 'Review', @@ -119,7 +115,7 @@ export default ({ event, originalAlertCount, originalAlerts, shownPages }) => { }, }, { - key: 'calendar', + key: 'meetings', path: '/calendar', exact: true, hidden: !shownPages?.meetings, @@ -127,6 +123,15 @@ export default ({ event, originalAlertCount, originalAlerts, shownPages }) => { label: 'Meetings', component: CalendarPage, }, + { + key: 'hackerpack', + path: '/hackerpack', + exact: true, + icon: , + hidden: !shownPages?.hackerPack, + label: t('Hackerpack_'), + component: HackerpackPage, + }, { key: 'recruitment', path: '/recruitment', @@ -134,17 +139,18 @@ export default ({ event, originalAlertCount, originalAlerts, shownPages }) => { icon: , label: 'Recruitment', component: RecruitmentPage, + locked: true, + lockedDescription: 'Currently unavailable', }, //Experimental { - key: 'hackerpack', - path: '/hackerpack', - exact: true, - icon: , - hidden: - !shownPages?.experimental && !shownPages?.hackerPack, - label: t('Hackerpack_'), - component: HackerpackPage, + key: 'map', + path: '/map', + exact: false, + icon: , + hidden: !shownPages?.experimental, + label: 'Map', + component: MapPage, }, { key: 'challenges', diff --git a/frontend/src/pages/_dashboard/renderDashboard/partner/partnerrecruitment/default/SearchResults/index.js b/frontend/src/pages/_dashboard/renderDashboard/partner/partnerrecruitment/default/SearchResults/index.js index 2e1a0a813..6450ed5ba 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/partner/partnerrecruitment/default/SearchResults/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/partner/partnerrecruitment/default/SearchResults/index.js @@ -2,7 +2,7 @@ import React, { useEffect } from 'react' import Empty from 'components/generic/Empty' import ResultCard from './ResultCard' import { useDispatch, useSelector } from 'react-redux' -import { useRouteMatch } from 'react-router' +// import { useRouteMatch } from 'react-router' import { Grid, Box, Typography, CircularProgress } from '@material-ui/core' import * as RecruitmentSelectors from 'redux/recruitment/selectors' @@ -11,10 +11,11 @@ import * as DashboardActions from 'redux/dashboard/actions' import { useTranslation } from 'react-i18next' import Pagination from './Pagination' import LoadingCard from './LoadingCard' +import { debugGroup } from 'utils/debuggingTools' export default ({ items, organisation }) => { const dispatch = useDispatch() - const match = useRouteMatch() + // const match = useRouteMatch() const searchResults = items ?? useSelector(RecruitmentSelectors.searchResults) const searchResultsCount = useSelector( @@ -26,9 +27,15 @@ export default ({ items, organisation }) => { const page = useSelector(RecruitmentSelectors.page) const paginationEnabled = !items const isFavorited = !!items - const { slug } = match.params + // const { slug } = match.params const { t } = useTranslation() + debugGroup('RecruitmentSearchResults', [ + useSelector(RecruitmentSelectors.searchResults), + searchResults, + searchResultsCount, + ]) + useEffect(() => { //dispatch(DashboardActions.updateEvent(slug)) dispatch(RecruitmentActions.updateSearchResults()) @@ -50,7 +57,7 @@ export default ({ items, organisation }) => { xs={12} sm={6} md={4} - //lg={3} + //lg={3} >
@@ -84,7 +91,7 @@ export default ({ items, organisation }) => { xs={12} sm={6} md={4} - //lg={3} + //lg={3} > diff --git a/frontend/src/pages/_dashboard/renderDashboard/partner/partnerrecruitment/default/index.js b/frontend/src/pages/_dashboard/renderDashboard/partner/partnerrecruitment/default/index.js index a28120fe8..484d08108 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/partner/partnerrecruitment/default/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/partner/partnerrecruitment/default/index.js @@ -1,8 +1,6 @@ - - import React, { useEffect, useState } from 'react' -import { makeStyles } from '@material-ui/core/styles' +// import { makeStyles } from '@material-ui/core/styles' import { Box } from '@material-ui/core' import { useSelector, useDispatch } from 'react-redux' @@ -20,25 +18,26 @@ import * as AuthSelectors from 'redux/auth/selectors' import ToggleFavorites from './ToggleFavorites' import { useTranslation } from 'react-i18next' import { useToggle } from 'hooks/customHooks' +import { debugGroup } from 'utils/debuggingTools' -const useStyles = makeStyles(theme => ({ - root: { - flex: 1, - backgroundColor: theme.palette.background.default, - padding: theme.spacing(3), - }, -})) +// const useStyles = makeStyles(theme => ({ +// root: { +// flex: 1, +// backgroundColor: theme.palette.background.default, +// padding: theme.spacing(3), +// }, +// })) export default () => { const { t } = useTranslation() - const classes = useStyles() + // const classes = useStyles() const dispatch = useDispatch() const idTokenData = useSelector(AuthSelectors.idTokenData) const favorites = useSelector(RecruitmentSelectors.favorites) - const event = useSelector(DashboardSelectors.event)._id + const eventId = useSelector(DashboardSelectors.event)._id const recEvents = useSelector(UserSelectors.userProfileRecruiterEvents) - const [recruiterOrganisation, SetRecruiterOrganisation] = useState("") + const [recruiterOrganisation, SetRecruiterOrganisation] = useState('') const [showFavorites, toggleFavorites] = useToggle(false) useEffect(() => { @@ -55,14 +54,14 @@ export default () => { //dispatch(RecruitmentActions.updateEvents()) const organisation = recEvents.find(e => { - return e.eventId === event + return e.eventId === eventId }).organisation SetRecruiterOrganisation(organisation) dispatch(RecruitmentActions.updateActionHistory(organisation)) }, [dispatch]) - + debugGroup('Recruitment', [recruiterOrganisation, recEvents]) return ( <> @@ -74,20 +73,24 @@ export default () => { justifyContent="flex-end" mb={2} > - -
+ {showFavorites ? ( - + ) : ( <> - + )} @@ -96,5 +99,3 @@ export default () => { ) } - - diff --git a/frontend/src/pages/_dashboard/renderDashboard/partner/partnerrecruitment/index.js b/frontend/src/pages/_dashboard/renderDashboard/partner/partnerrecruitment/index.js index 89ce8d54c..b679e9c9a 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/partner/partnerrecruitment/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/partner/partnerrecruitment/index.js @@ -1,7 +1,13 @@ import React, { useEffect, useLayoutEffect } from 'react' import { useRouteMatch } from 'react-router' import { useDispatch } from 'react-redux' -import { Switch, Route, Redirect, useLocation, useParams } from 'react-router-dom' +import { + Switch, + Route, + Redirect, + useLocation, + useParams, +} from 'react-router-dom' import PageWrapper from 'components/layouts/PageWrapper' import * as RecruitmentActions from 'redux/recruitment/actions' @@ -9,15 +15,14 @@ import * as RecruitmentActions from 'redux/recruitment/actions' import GlobalNavBar from 'components/navbars/GlobalNavBar' import SearchPage from './default' -import AdminPage from './admin' +// import AdminPage from './admin' import DetailPage from './id' export default () => { - const dispatch = useDispatch() - const location = useLocation() + // const dispatch = useDispatch() + // const location = useLocation() const match = useRouteMatch() - //console.log(match.url) return ( @@ -29,47 +34,16 @@ export default () => { path={`${match.url}/:id`} component={DetailPage} /> + {/* */} ) } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // import React, { useEffect, useRef } from 'react' // import FormControl from '@material-ui/core/FormControl' // import FormGroup from '@material-ui/core/FormGroup' @@ -82,9 +56,6 @@ export default () => { // export default () => { - - - // return ( // <> // {/* button for DEV to swithc between participant / partner view */} @@ -101,4 +72,4 @@ export default () => { // // // ) -// } \ No newline at end of file +// } diff --git a/frontend/src/pages/_dashboard/renderDashboard/partner/projects/index.js b/frontend/src/pages/_dashboard/renderDashboard/partner/projects/index.js index 63cb6f63f..ea246726b 100644 --- a/frontend/src/pages/_dashboard/renderDashboard/partner/projects/index.js +++ b/frontend/src/pages/_dashboard/renderDashboard/partner/projects/index.js @@ -7,7 +7,6 @@ import PageHeader from 'components/generic/PageHeader' import ProjectsGrid from 'components/projects/ProjectsGrid' import ProjectsService from 'services/projects' -import Filter from 'components/Team/Filter' import _ from 'lodash' import ProjectDetail from 'components/projects/ProjectDetail' @@ -17,7 +16,6 @@ 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' -import ScoreForm from 'pages/_projects/slug/view/projectId/ScoreForm' const projectScoreBase = { project: '', @@ -37,16 +35,12 @@ export default ({ event }) => { const idToken = useSelector(AuthSelectors.getIdToken) const userId = useSelector(AuthSelectors.getUserId) const userProfile = useSelector(userSelectors.userProfile) - const allFilterLabel = 'All projects' const dispatch = useDispatch() const { slug } = event const [data, setData] = useState({}) const [projects, setProjects] = useState([]) - const [draftsProjects, setDraftsProjects] = useState([]) - const [finalProjects, setFinalProjects] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(false) - const [filter, setFilter] = useState(allFilterLabel) const [selected, setSelected] = useState(null) const [scoreExists, setScoreExists] = useState(false) @@ -55,10 +49,7 @@ export default ({ event }) => { const resetProjectData = () => { setSelected(null) setScoreExists(false) - } - - const onFilterChange = filter => { - setFilter(filter) + setProjectScore(projectScoreBase) } if (event.scoreCriteriaSettings === undefined) { @@ -68,46 +59,21 @@ export default ({ event }) => { const fetchProjects = useCallback(async () => { setLoading(true) try { - const dataOt = await ProjectsService.getProjectsByEvent(slug) - const partnerData = _.find( - event.recruiters, - recruiter => recruiter.recruiterId === userId, + const dataOt = await ProjectsService.getProjectsByEventAsPartner( + idToken, + slug, ) - let challengeOrg - let filteredProjects = [] const data = { event, - } - if (event.scoreCriteriaSettings.reviewAnyChallenge) { - data.projects = dataOt - } else if (partnerData) { - challengeOrg = _.find( - event.challenges, - challenge => challenge.partner === partnerData.organization, - ) - if (challengeOrg) { - data.challenge = challengeOrg - filteredProjects = _.filter(dataOt, project => - _.includes(project.challenges, challengeOrg.slug), - ) - if (filteredProjects.length > 0) { - data.projects = filteredProjects - } - } + ...dataOt, } setData(data) - setDraftsProjects( - data.projects.filter(project => project.status === 'draft'), - ) - setFinalProjects( - data.projects.filter(project => project.status === 'final'), - ) setProjects(data.projects) } catch (err) { - console.log("err", err) setError(true) + } finally { + setLoading(false) } - setLoading(false) }, [slug, idToken, projectScore]) const handleSubmit = async (values, { setSubmitting, resetForm }) => { @@ -153,7 +119,6 @@ export default ({ event }) => { submissionValues, ) } else { - console.log("no score") await ProjectScoresService.addScoreByEventSlugAndProjectIdAndPartnerAccount( idToken, event.slug, @@ -182,6 +147,7 @@ export default ({ event }) => { return null } + //TODO perform this on the backend useEffect(() => { if (idToken && selected && event) { ProjectScoresService.getScoreByEventSlugAndProjectIdAndPartnerAccount( @@ -189,7 +155,6 @@ export default ({ event }) => { event.slug, selected._id, ).then(score => { - console.log('Score', score) if (score[0]) { const reviewerData = _.find( score[0].reviewers, @@ -221,17 +186,6 @@ export default ({ event }) => { } }, [event, idToken, selected]) - const projectsToRender = filter => { - switch (filter) { - case 'draft': - return draftsProjects - case 'final': - return finalProjects - default: - return projects - } - } - const renderProjects = inputData => { return ( <> @@ -241,31 +195,25 @@ export default ({ event }) => { heading={inputData?.challenge.name} subheading={`By ${inputData?.challenge.partner}`} alignment="left" - details={`${inputData?.projects.length} project${inputData?.projects.length > 1 || + details={`${inputData?.projects.length} project${ + inputData?.projects.length > 1 || inputData?.projects.length < 1 - ? 's' - : '' - }`} + ? 's' + : '' + }`} /> )} - @@ -284,22 +232,15 @@ export default ({ event }) => { {idToken ? ( {scoreCriteriaBase && - scoreCriteriaBase.length > 0 ? ( - - ) : ( - - )} + scoreCriteriaBase.length > 0 && ( + + )} ) : null} diff --git a/frontend/src/pages/_events/slug/context.js b/frontend/src/pages/_events/slug/context.js index 4a978bbf0..74b2c024b 100644 --- a/frontend/src/pages/_events/slug/context.js +++ b/frontend/src/pages/_events/slug/context.js @@ -194,7 +194,6 @@ export const EventDetailProvider = ({ children }) => { }) const createRegistration = useCallback( formData => { - console.log('creatin regigiigi', idToken, slug, formData) return RegistrationsService.createRegistration( idToken, slug, diff --git a/frontend/src/pages/_events/slug/register/RegistrationSection/index.js b/frontend/src/pages/_events/slug/register/RegistrationSection/index.js index 90785f101..691c72ce1 100644 --- a/frontend/src/pages/_events/slug/register/RegistrationSection/index.js +++ b/frontend/src/pages/_events/slug/register/RegistrationSection/index.js @@ -107,7 +107,7 @@ export default props => {
diff --git a/frontend/src/pages/_events/slug/register/index.js b/frontend/src/pages/_events/slug/register/index.js index d1ea8ca73..7d26f5076 100644 --- a/frontend/src/pages/_events/slug/register/index.js +++ b/frontend/src/pages/_events/slug/register/index.js @@ -269,8 +269,10 @@ export default RequiresPermission(() => { const sec = section.name section.questions.forEach(question => { const que = question.name + const label = question?.label || 'custom question' const value = formData[sec][que] const custom = { + label: label, section: sec, key: que, value: value + '', diff --git a/frontend/src/pages/_projects/slug/challenge/token/index.js b/frontend/src/pages/_projects/slug/challenge/token/index.js index e715d8fcb..2e4440fc6 100644 --- a/frontend/src/pages/_projects/slug/challenge/token/index.js +++ b/frontend/src/pages/_projects/slug/challenge/token/index.js @@ -7,7 +7,6 @@ import PageWrapper from 'components/layouts/PageWrapper' import Container from 'components/generic/Container' import PageHeader from 'components/generic/PageHeader' import ProjectsGrid from 'components/projects/ProjectsGrid' -import { makeStyles } from '@material-ui/core/styles' import ProjectsService from 'services/projects' import Filter from 'components/Team/Filter' @@ -17,12 +16,8 @@ import _ from 'lodash' export default ({ event }) => { const baseFilter = { value: 'final', label: 'Final projects' } const match = useRouteMatch() - console.log('match', match) - console.log('match URL', match.url) const dispatch = useDispatch() const { slug } = event - const { reviewMethod } = event - console.log('event data', event) const { token } = match.params const [data, setData] = useState({}) const [projects, setProjects] = useState([]) @@ -111,7 +106,8 @@ export default ({ event }) => { onSelect={project => dispatch(push(`${match.url}/view/${project._id}`)) } - showScore={reviewMethod === 'manualReview'} + showScore={true} + showReviewers={true} token={token} /> diff --git a/frontend/src/pages/_projects/slug/view/projectId/EvaluationForm.js b/frontend/src/pages/_projects/slug/view/projectId/EvaluationForm.js index 069a2974d..d0af0a652 100644 --- a/frontend/src/pages/_projects/slug/view/projectId/EvaluationForm.js +++ b/frontend/src/pages/_projects/slug/view/projectId/EvaluationForm.js @@ -1,6 +1,5 @@ -import React, { useState } from 'react' -import { Formik, Form, Field, ErrorMessage } from 'formik' -import Button from 'components/generic/Button' +import React from 'react' +import { Formik, Form, Field } from 'formik' import { Box, Typography } from '@material-ui/core' import RadioScore from 'components/generic/RadioScore' import TextAreaInput from 'components/inputs/TextAreaInput' @@ -8,15 +7,7 @@ import FormControl from 'components/inputs/FormControl' import BottomBar from 'components/inputs/BottomBar' import _ from 'lodash' -const EvaluationForm = ({ - event, - project, - submit = () => {}, - score, - scoreCriteria, -}) => { - console.log('Score from eval form', score) - +const EvaluationForm = ({ submit = () => {}, score, scoreCriteria }) => { const allScoresSet = evalScores => { const scoreList = evalScores.map(value => { return value?.score ? value.score : null @@ -26,16 +17,13 @@ const EvaluationForm = ({ const calculateScore = (criterias, decimalPlaces) => { const multiplier = Math.pow(10, decimalPlaces) - console.log('Multiplier', multiplier) const scoreAverage = criterias.reduce((acc, curr) => { if (!curr.score) return acc return curr.score + acc }, 0) / criterias.length - console.log('Score average before format', scoreAverage) const scoreAverageFormatted = Math.floor(scoreAverage * multiplier) / multiplier - console.log('Score average', scoreAverageFormatted) return scoreAverageFormatted } @@ -54,23 +42,14 @@ const EvaluationForm = ({ score.scoreCriteria = scoreFiltered } - // if (score.scoreCriteria.map) { - return ( <> {formikProps => { - console.log('formikProps from EvaluationForm', formikProps) return (
@@ -93,10 +72,6 @@ const EvaluationForm = ({ { criteria, label }, index, ) => { - console.log( - 'Field value at evaluationForm', - field.value, - ) return ( form.setFieldTouched(field.name) } + minRows={2} + maxLength={500} /> )} diff --git a/frontend/src/pages/_projects/slug/view/projectId/index.js b/frontend/src/pages/_projects/slug/view/projectId/index.js index c6060cba3..75ebee171 100644 --- a/frontend/src/pages/_projects/slug/view/projectId/index.js +++ b/frontend/src/pages/_projects/slug/view/projectId/index.js @@ -1,77 +1,22 @@ import React, { useState, useEffect, useCallback } from 'react' import { goBack } from 'connected-react-router' -import { useDispatch, useSelector } from 'react-redux' +import { useDispatch } from 'react-redux' import { useRouteMatch } from 'react-router' import PageWrapper from 'components/layouts/PageWrapper' import ProjectDetail from 'components/projects/ProjectDetail' import ShareProject from 'components/projects/ProjectDetail/ShareProject' -import ScoreForm from './ScoreForm' -import Container from 'components/generic/Container' -import * as AuthSelectors from 'redux/auth/selectors' -import * as UserSelectors from 'redux/user/selectors' import moment from 'moment-timezone' import { EventHelpers } from '@hackjunction/shared' - -import * as SnackbarActions from 'redux/snackbar/actions' - import ProjectsService from 'services/projects' -import ProjectScoresService from 'services/projectScores' -import { set } from 'object-path' -import EvaluationForm from './EvaluationForm' import _ from 'lodash' export default ({ event, showFullTeam }) => { - const scoreCriteriaBase = event.scoreCriteriaSettings?.scoreCriteria const dispatch = useDispatch() - const userId = useSelector(AuthSelectors.getUserId) const match = useRouteMatch() - const { projectId, token } = match.params - const { slug } = event - const [scoreExists, setScoreExists] = useState(false) + const { projectId } = match.params const [project, setProject] = useState() const [loading, setLoading] = useState(true) const [error, setError] = useState(false) - const [validToken, setValidToken] = useState(false) - - useEffect(() => { - if (token && project && event) { - ProjectsService.validateToken(slug, token).then(v => { - if (v) setValidToken(v) - }) - } - }, [event, project, slug, token]) - - const [projectScore, setProjectScore] = useState({ - project: '', - event: '', - status: 'submitted', - score: 0, - maxScore: 10, - message: '', - scoreCriteria: [], - reviewers: [], - }) - - useEffect(() => { - if (token && project && event) { - ProjectScoresService.getScoreByEventSlugAndProjectIdAndPartnerToken( - token, - event.slug, - project._id, - ).then(score => { - console.log('Score', score) - if (score[0]) { - setProjectScore(score[0]) - setScoreExists(true) - } else { - setProjectScore({ - ...projectScore, - scoreCriteria: scoreCriteriaBase, - }) - } - }) - } - }, [event, token, project]) const fetchProject = useCallback(async () => { setLoading(true) @@ -79,7 +24,6 @@ export default ({ event, showFullTeam }) => { const project = await ProjectsService.getPublicProjectById( projectId, ) - console.log('Project details', project) setProject(project) } catch (err) { setError(true) @@ -88,45 +32,6 @@ export default ({ event, showFullTeam }) => { } }, [projectId]) - const handleSubmit = async (values, { setSubmitting, resetForm }) => { - values.project = project._id - values.event = event._id - console.log('values', values) - try { - if (userId) { - _.includes(values.reviewers, userId) - ? console.log('User already in reviewers list') - : values.reviewers.push(userId) - } - if (scoreExists) { - await ProjectScoresService.updateScoreByEventSlugAndPartnerToken( - token, - event.slug, - values, - ) - setProjectScore(values) - } else { - await ProjectScoresService.addScoreByEventSlugAndPartnerToken( - token, - event.slug, - values, - ) - setProjectScore(values) - } - - dispatch(SnackbarActions.success(`Score saved.`)) - resetForm() - } catch (e) { - dispatch( - SnackbarActions.error( - `Score could not be saved. Error: ${e.message}`, - ), - ) - } finally { - setSubmitting(false) - } - } - const onBack = useCallback(() => { dispatch(goBack()) }, [dispatch]) @@ -143,26 +48,7 @@ export default ({ event, showFullTeam }) => { showFullTeam={showFullTeam} showTableLocation={!EventHelpers.isEventOver(event, moment)} /> - {validToken ? ( - - {scoreCriteriaBase && scoreCriteriaBase.length > 0 ? ( - - ) : ( - - )} - - ) : null} + ) diff --git a/frontend/src/redux/dashboard/actions.js b/frontend/src/redux/dashboard/actions.js index 4fef90bf9..4e693d0d9 100644 --- a/frontend/src/redux/dashboard/actions.js +++ b/frontend/src/redux/dashboard/actions.js @@ -480,15 +480,11 @@ export const updateProjects = slug => async (dispatch, getState) => { export const createProject = (slug, data) => async (dispatch, getState) => { try { const idToken = AuthSelectors.getIdToken(getState()) - const fileData = await fileAttachmentFinder(data, idToken) + // const fileData = await fileAttachmentFinder(data, idToken) - if (fileData) { - await ProjectsService.createProjectForEventAndTeam( - idToken, - slug, - fileData, - ) - } + // if (fileData) { + // } + await ProjectsService.createProjectForEventAndTeam(idToken, slug, data) const projects = await ProjectsService.getProjectsForEventAndTeam( idToken, slug, @@ -656,15 +652,11 @@ export const deleteFileForProject = fileId => async (dispatch, getState) => { export const editProject = (slug, data) => async (dispatch, getState) => { try { const idToken = AuthSelectors.getIdToken(getState()) - const fileData = await fileAttachmentFinder(data, idToken) + // const fileData = await fileAttachmentFinder(data, idToken) - if (fileData) { - await ProjectsService.updateProjectForEventAndTeam( - idToken, - slug, - fileData, - ) - } + // if (fileData) { + // } + await ProjectsService.updateProjectForEventAndTeam(idToken, slug, data) const projects = await ProjectsService.getProjectsForEventAndTeam( idToken, slug, diff --git a/frontend/src/redux/dashboard/reducer.js b/frontend/src/redux/dashboard/reducer.js index 4d8f0e4ff..6fe5db813 100644 --- a/frontend/src/redux/dashboard/reducer.js +++ b/frontend/src/redux/dashboard/reducer.js @@ -51,12 +51,12 @@ const initialState = { error: false, updated: 0, }, - project_scores: { - data: [], - loading: true, - error: false, - updated: 0, - }, + // project_scores: { + // data: [], + // loading: true, + // error: false, + // updated: 0, + // }, } const updateEventHandler = buildHandler('event') @@ -66,7 +66,7 @@ const eventRecruitersHandler = buildHandler('recruiters', 'userId') const updateTeamHandler = buildHandler('team') const updateProjectsHandler = buildHandler('projects', '_id') const updateAnnotatorHandler = buildHandler('annotator') -const updateProjectScoresHandler = buildHandler('project_scores') +// const updateProjectScoresHandler = buildHandler('project_scores') const updateTeamsHandler = buildHandler('teams') const updateSelectedTeamHandler = buildHandler('selected_team') // const updateSeletecUserHandler = buildHandler('selected_candidate') @@ -95,9 +95,9 @@ export default function reducer(state = initialState, action) { case ActionTypes.UPDATE_ANNOTATOR: { return updateAnnotatorHandler(state, action) } - case ActionTypes.UPDATE_PROJECT_SCORES: { - return updateProjectScoresHandler(state, action) - } + // case ActionTypes.UPDATE_PROJECT_SCORES: { + // // return updateProjectScoresHandler(state, action) + // } case ActionTypes.EDIT_REGISTRATION: { return editRegistration(state, action.payload) } diff --git a/frontend/src/redux/dashboard/selectors.js b/frontend/src/redux/dashboard/selectors.js index b79c6cb05..78bd16784 100644 --- a/frontend/src/redux/dashboard/selectors.js +++ b/frontend/src/redux/dashboard/selectors.js @@ -58,12 +58,12 @@ export const annotatorLoading = state => state.dashboard.annotator.loading export const annotatorError = state => state.dashboard.annotator.error export const annotatorUpdated = state => state.dashboard.annotator.updated -export const projectScores = state => state.dashboard.project_scores.data -export const projectScoresLoading = state => - state.dashboard.project_scores.loading -export const projectScoresError = state => state.dashboard.project_scores.error -export const projectScoresUpdated = state => - state.dashboard.project_scores.updated +// export const projectScores = state => state.dashboard.project_scores.data +// export const projectScoresLoading = state => +// state.dashboard.project_scores.loading +// export const projectScoresError = state => state.dashboard.project_scores.error +// export const projectScoresUpdated = state => +// state.dashboard.project_scores.updated export const annotatorVoteCount = createSelector(annotator, annotator => { if (!annotator) return 0 @@ -146,7 +146,7 @@ export const isTeamValid = createSelector(team, team => { export const lockedPages = createSelector(event, event => { return { submissions: !EventHelpers.isSubmissionsOpen(event, moment), - reviewing: EventHelpers.isVotingPast(event, moment), + reviewing: !EventHelpers.isReviewingOpen(event, moment), team: EventHelpers.isSubmissionsPast(event, moment), finalistVoting: !EventHelpers.isFinalistVotingOpen(event, moment), } @@ -161,7 +161,8 @@ export const shownPages = createSelector( return { submissions: registration?.status === STATUSES.checkedIn.id, eventID: - event?.eventType === EventTypes.physical.id && + (event?.eventType === EventTypes.physical.id || + event?.eventType === EventTypes.hybrid.id) && [ STATUSES.confirmed.id, STATUSES.confirmedToHub.id, @@ -177,12 +178,14 @@ export const shownPages = createSelector( registration?.status === STATUSES.checkedIn.id && event?.overallReviewMethod !== 'noOverallWinner', hackerPack: + (event?.hackerpacksEnabled ?? false) && [ STATUSES.checkedIn.id, STATUSES.confirmed.id, STATUSES.confirmedToHub.id, ].indexOf(registration?.status) !== -1, meetings: EventHelpers.areMeetingsEnabled(event), + challengesEnabled: event?.challengesEnabled, reviewingByScoreCriteria: event?.reviewMethod === ReviewingMethods.manualReview.id, //Experimental diff --git a/frontend/src/routes.js b/frontend/src/routes.js index 9979dc7c2..cb8465f48 100644 --- a/frontend/src/routes.js +++ b/frontend/src/routes.js @@ -18,14 +18,18 @@ import RequiresRole from 'hocs/RequiresRole' /** Lazy-load the access-restricted pages */ const DashboardRouter = lazy(() => import('./pages/_dashboard')) -const OrganiserRouter = lazy(() => import('./pages/_dashboard/renderDashboard/organiser/router')) +const OrganiserRouter = lazy(() => + import('./pages/_dashboard/renderDashboard/organiser/router'), +) const AccountRouter = lazy(() => import('./pages/_account')) //TODO: switch the recruitment view and router -const RecruitmentRouter = lazy(() => import('./pages/_dashboard/renderDashboard/partner/partnerrecruitment'))//import('./pages/_recruitment'))// +const RecruitmentRouter = lazy(() => + import('./pages/_dashboard/renderDashboard/partner/partnerrecruitment'), +) //import('./pages/_recruitment'))// const ProjectsRouter = lazy(() => import('./pages/_projects')) const AdminRouter = lazy(() => import('./pages/_admin')) const SandboxRouter = lazy(() => import('./pages/_sandbox')) -const FilesRouter = lazy(() => import('./pages/_sandbox/files')) +// const FilesRouter = lazy(() => import('./pages/_sandbox/files')) const routes = [ { @@ -76,7 +80,8 @@ const routes = [ ]),*/ exact: false, }, - {//default after login + { + //default after login path: '/dashboard', component: RequiresPermission(DashboardRouter), exact: false, diff --git a/frontend/src/services/projects.js b/frontend/src/services/projects.js index 4ca7541be..552061bc2 100644 --- a/frontend/src/services/projects.js +++ b/frontend/src/services/projects.js @@ -13,6 +13,10 @@ ProjectsService.getProjectsByEvent = eventSlug => { return _axios.get(`/projects/${eventSlug}`) } +ProjectsService.getProjectsByEventAsPartner = (idToken, eventSlug) => { + return _axios.get(`/projects/${eventSlug}/partner-review`, config(idToken)) +} + ProjectsService.getPublicProjectById = projectId => { return _axios.get(`/projects/id/${projectId}`) } diff --git a/frontend/src/services/registrations.js b/frontend/src/services/registrations.js index fc612675d..36f0f019a 100644 --- a/frontend/src/services/registrations.js +++ b/frontend/src/services/registrations.js @@ -215,11 +215,12 @@ RegistrationsService.adminNotifyAcceptedTravelGrants = (idToken, slug) => { ) } -RegistrationsService.addPartnerToRegistrated = (idToken, - user, - slug, - data) => { +RegistrationsService.addPartnerToRegistrated = (idToken, user, slug, data) => { return _axios.post(`${BASE_ROUTE}/${slug}/partner`, user, config(idToken)) } +RegistrationsService.addGavelLoginToRegistrations = (idToken, slug, data) => { + return _axios.post(`${BASE_ROUTE}/${slug}/gavel`, data, config(idToken)) +} + export default RegistrationsService diff --git a/frontend/src/utils/dataModifiers.js b/frontend/src/utils/dataModifiers.js index bb7fa0713..da7eee689 100644 --- a/frontend/src/utils/dataModifiers.js +++ b/frontend/src/utils/dataModifiers.js @@ -18,3 +18,13 @@ export const removeNumbers = (str, replace = '') => { export const generateSlug = (str, replaceNumValue = '') => { return getSlug(removeNumbers(str, replaceNumValue)) } + +export const projectURLgenerator = (eventSlug, projectId) => { + //Utility to generate public project URL, with the shape /projects/:eventSlug/view/:projectId + const originURL = window.location.origin + let projectURL + if (!!projectId && !!eventSlug && !!originURL) { + projectURL = `${originURL}/projects/${eventSlug}/view/${projectId}` + } + return projectURL +} diff --git a/shared/constants/event-types.js b/shared/constants/event-types.js index 5959aeefc..c00aa9d0e 100644 --- a/shared/constants/event-types.js +++ b/shared/constants/event-types.js @@ -7,6 +7,10 @@ const EventTypes = { id: 'online', label: 'Online event', }, + hybrid: { + id: 'hybrid', + label: 'Hybrid event', + }, } module.exports = EventTypes diff --git a/shared/constants/project-schema.js b/shared/constants/project-schema.js index 70466d731..755e3a7cd 100644 --- a/shared/constants/project-schema.js +++ b/shared/constants/project-schema.js @@ -35,6 +35,7 @@ const ProjectSchema = { yup .object() .shape({ + label: yup.string(), section: yup.string(), key: yup.string(), value: yup.string(), @@ -96,7 +97,10 @@ const buildProjectSchema = event => { ) } - if (event.eventType === EventTypes.physical.id) { + if ( + event.eventType === EventTypes.physical.id || + event.eventType === EventTypes.hybrid.id + ) { schema.location = yup.string().max(100).label('Table location') } diff --git a/shared/constants/registration-fields-custom.js b/shared/constants/registration-fields-custom.js index 31b49b10c..5df7b3c34 100644 --- a/shared/constants/registration-fields-custom.js +++ b/shared/constants/registration-fields-custom.js @@ -23,6 +23,17 @@ const RegistrationFieldsCustom = { return required ? base.required() : base }, }, + link: { + id: 'link', + validationSchema: (required, question) => { + const base = yup + .string() + .min(required ? 1 : 0) + .max(300) + .label(question.label) + return required ? base.required() : base + }, + }, boolean: { id: 'boolean', validationSchema: (required, question) => { diff --git a/shared/helpers/events.js b/shared/helpers/events.js index e30fea153..855e6345b 100644 --- a/shared/helpers/events.js +++ b/shared/helpers/events.js @@ -52,7 +52,7 @@ const EventHelpers = { if (!event) return false return !nowIsBefore(event.submissionsEndTime, moment) }, - isVotingOpen: (event, moment) => { + isReviewingOpen: (event, moment) => { if (!event) return false return nowIsBetween( event.reviewingStartTime, @@ -67,7 +67,7 @@ const EventHelpers = { event.finalsActive ) }, - isVotingPast: (event, moment) => { + isReviewingPast: (event, moment) => { if (!event) return true return !nowIsBefore(event.reviewingEndTime, moment) }, @@ -112,6 +112,10 @@ const EventHelpers = { if (!event) return true return event.meetingsEnabled }, + areChallengesEnabled: event => { + if (!event) return false + return event.challengesEnabled + }, } module.exports = EventHelpers diff --git a/shared/schemas/Challenge.js b/shared/schemas/Challenge.js index ab17e3311..ee6bdd2e2 100644 --- a/shared/schemas/Challenge.js +++ b/shared/schemas/Challenge.js @@ -11,7 +11,7 @@ const ChallengeSchema = new mongoose.Schema({ name: { type: String, required: true, - length: 100, + length: 50, }, partner: { type: String, diff --git a/shared/schemas/CustomAnswer.js b/shared/schemas/CustomAnswer.js index 6ad309f95..7fac85246 100644 --- a/shared/schemas/CustomAnswer.js +++ b/shared/schemas/CustomAnswer.js @@ -2,6 +2,9 @@ const mongoose = require('mongoose') const { GraphQLObjectType, GraphQLString } = require('graphql') const mongooseSchema = new mongoose.Schema({ + label: { + type: String, + }, section: { type: String, }, @@ -16,6 +19,9 @@ const mongooseSchema = new mongoose.Schema({ const graphqlSchema = new GraphQLObjectType({ name: 'CustomAnswer', fields: () => ({ + label: { + type: GraphQLString, + }, section: { type: GraphQLString, }, From 5ba424e90724421e8e3d4abed6189d0ee69122db Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 14 Mar 2024 13:30:38 +0200 Subject: [PATCH 2/4] Added verification to registration gavel login controller to validate that the data received has the right format --- backend/modules/registration/controller.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/backend/modules/registration/controller.js b/backend/modules/registration/controller.js index dfb9bd055..1f7ac5d0b 100644 --- a/backend/modules/registration/controller.js +++ b/backend/modules/registration/controller.js @@ -524,6 +524,14 @@ controller.rejectSoftRejected = async eventId => { controller.addGavelLoginToRegistrations = async (eventId, gavelData) => { console.log('Gavel data received', gavelData, typeof gavelData) + gavelData.forEach(gavel => { + if ( + typeof gavel.registration !== 'string' || + typeof gavel.link !== 'string' + ) { + throw new Error('Gavel data is invalid') + } + }) let updateCount = 0 const registrations = await Registration.find({ event: eventId, @@ -550,8 +558,6 @@ controller.addGavelLoginToRegistrations = async (eventId, gavelData) => { updateCount, registrationCount, ) - // Go through gavelData and assign the login URL to their corresponding registration - // const registration = await Registration } module.exports = controller From 0d8418eccf2b94315b6d66c3c5320bb5a92acbda Mon Sep 17 00:00:00 2001 From: Javier Hernandez Date: Thu, 14 Mar 2024 13:33:03 +0200 Subject: [PATCH 3/4] Delete azure-pipelines-production.yml --- azure-pipelines-production.yml | 133 --------------------------------- 1 file changed, 133 deletions(-) delete mode 100644 azure-pipelines-production.yml diff --git a/azure-pipelines-production.yml b/azure-pipelines-production.yml deleted file mode 100644 index 4812b96b3..000000000 --- a/azure-pipelines-production.yml +++ /dev/null @@ -1,133 +0,0 @@ -trigger: - - none - -pool: - vmImage: ubuntu-latest - -stages: - - stage: Build_africa - displayName: Build stage africa - jobs: - - job: Build_africa - steps: - - task: DownloadSecureFile@1 - displayName: 'download PROD Africa backend' - inputs: - secureFile: 'BACKEND_ENV_FILE_AFRICA' # string. Required. Secure File. - - - task: CopyFiles@2 - displayName: 'copy PROD Africa backend' - inputs: - SourceFolder: '$(Agent.TempDirectory)' - Contents: BACKEND_ENV_FILE_AFRICA - TargetFolder: './backend' - - - script: mv ./backend/BACKEND_ENV_FILE_AFRICA ./backend/.env - displayName: 'rename PROD Africa .env' - - task: DownloadSecureFile@1 - displayName: 'download PROD Africa frontend' - inputs: - secureFile: 'FRONTEND_ENV_FILE_AFRICA' # string. Required. Secure File. - - - task: CopyFiles@2 - displayName: 'copy PROD Africa frontend' - inputs: - SourceFolder: '$(Agent.TempDirectory)' - Contents: FRONTEND_ENV_FILE_AFRICA - TargetFolder: './frontend' - - - script: mv ./frontend/FRONTEND_ENV_FILE_AFRICA ./frontend/.env - displayName: 'rename PROD Africa .env' - - - script: ls -a ./frontend - displayName: 'ls' - - - script: ls -Rn - displayName: 'ls' - - - task: NodeTool@0 - inputs: - versionSpec: '12.20.1' - displayName: 'Install Node.js' - - - task: Bash@3 - inputs: - targetType: 'inline' - script: | - node -v - npm -v - npm install - npm run build - - - task: ArchiveFiles@2 - displayName: 'Archive files' - inputs: - rootFolderOrFile: '$(System.DefaultWorkingDirectory)' - includeRootFolder: false - archiveType: zip - archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip - replaceExistingArchive: true - - upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip - artifact: drop_africa - - - deployment: VMDeploy_AFRICA - dependsOn: Build_africa - displayName: DEPLOY AFRICA - environment: - name: PROD - resourceType: VirtualMachine - tags: africa - strategy: - runOnce: - preDeploy: - steps: - - task: DownloadPipelineArtifact@2 - inputs: - buildType: 'current' - artifactName: drop_africa - targetPath: '$(Pipeline.Workspace)/drop' - - - script: echo initialize, cleanup, backup, install certs - - deploy: - steps: - - task: Bash@3 - inputs: - targetType: 'inline' - script: | - Modify deployment script based on the app type - echo "Starting deployment script run" - - - task: ExtractFiles@1 - inputs: - archiveFilePatterns: '$(Pipeline.Workspace)/drop_africa/$(Build.BuildId).zip' - destinationFolder: '$(Pipeline.Workspace)/japp' - cleanDestinationFolder: true - overwriteExistingFiles: true - - - task: DeleteFiles@1 - inputs: - SourceFolder: '$(Pipeline.Workspace)/drop_africa' - Contents: '$(Build.BuildId).zip' - - - task: Bash@3 - inputs: - targetType: 'inline' - script: | - cd /home/azureuser/azagent/_work/1/japp - pm2 restart index - sudo systemctl restart nginx - - routeTraffic: - steps: - - script: echo routing traffic - postRouteTraffic: - steps: - - script: echo health check post-route traffic - on: - failure: - steps: - - script: echo Restore from backup! This is on failure - success: - steps: - - script: echo Notify! This is on success From 121677118a6896fd24b320236810142346277575 Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 14 Mar 2024 13:56:12 +0200 Subject: [PATCH 4/4] Added styleModifier function to ProjectGridItem to render projects appropiately --- .../projects/ProjectsGridItem/index.js | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/projects/ProjectsGridItem/index.js b/frontend/src/components/projects/ProjectsGridItem/index.js index b4045fda9..3f1c6dcfa 100644 --- a/frontend/src/components/projects/ProjectsGridItem/index.js +++ b/frontend/src/components/projects/ProjectsGridItem/index.js @@ -118,6 +118,24 @@ const ProjectsGridItem = ({ } } + const styling = { + punchlineMaxLength: 150, + } + + const stylingModifiers = styleRules => { + if (showTableLocation) { + styleRules.punchlineMaxLength = styleRules.punchlineMaxLength - 25 + } + if (showScore) { + styleRules.punchlineMaxLength = styleRules.punchlineMaxLength - 25 + } + if (showReviewers) { + styleRules.punchlineMaxLength = styleRules.punchlineMaxLength - 50 + } + } + + stylingModifiers(styling) + return ( {project?.punchline && ( + {showTableLocation && showScore} {_.truncate(project.punchline, { - length: 150, + length: styling.punchlineMaxLength, })} )}