diff --git a/package-lock.json b/package-lock.json index b2af04034..8e0325a5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@sentry/browser": "^8.0.0", "@sentry/node": "^8.0.0", "@sentry/tracing": "^7.0.0", - "@vitejs/plugin-react-swc": "^3.6.0", + "@vitejs/plugin-react-swc": "^3.7.1", "axios": "^1.7.2", "buffer": "^6.0.3", "chart.js": "^3.4.0", @@ -122,6 +122,9 @@ }, "engines": { "node": ">=14.7" + }, + "optionalDependencies": { + "@rollup/rollup-darwin-arm64": "4.24.0" } }, "node_modules/@ampproject/remapping": { @@ -4204,6 +4207,149 @@ "node": ">= 8.0.0" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.20.0.tgz", + "integrity": "sha512-TSpWzflCc4VGAUJZlPpgAJE1+V60MePDQnBd7PPkpuEmOy8i87aL6tinFGKBFKuEDikYpig72QzdT3QPYIi+oA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.20.0.tgz", + "integrity": "sha512-u00Ro/nok7oGzVuh/FMYfNoGqxU5CPWz1mxV85S2w9LxHR8OoMQBuSk+3BKVIDYgkpeOET5yXkx90OYFc+ytpQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.20.0.tgz", + "integrity": "sha512-xbrMDdlev53vNXexEa6l0LffojxhqDTBeL+VUxuuIXys4x6xyvbKq5XqTXBCEUA8ty8iEJblHvFaWRJTk/icAQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.20.0.tgz", + "integrity": "sha512-jMYvxZwGmoHFBTbr12Xc6wOdc2xA5tF5F2q6t7Rcfab68TT0n+r7dgawD4qhPEvasDsVpQi+MgDzj2faOLsZjA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.20.0.tgz", + "integrity": "sha512-1asSTl4HKuIHIB1GcdFHNNZhxAYEdqML/MW4QmPS4G0ivbEcBr1JKlFLKsIRqjSwOBkdItn3/ZDlyvZ/N6KPlw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.20.0.tgz", + "integrity": "sha512-COBb8Bkx56KldOYJfMf6wKeYJrtJ9vEgBRAOkfw6Ens0tnmzPqvlpjZiLgkhg6cA3DGzCmLmmd319pmHvKWWlQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.20.0.tgz", + "integrity": "sha512-+it+mBSyMslVQa8wSPvBx53fYuZK/oLTu5RJoXogjk6x7Q7sz1GNRsXWjn6SwyJm8E/oMjNVwPhmNdIjwP135Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.20.0.tgz", + "integrity": "sha512-yAMvqhPfGKsAxHN8I4+jE0CpLWD8cv4z7CK7BMmhjDuz606Q2tFKkWRY8bHR9JQXYcoLfopo5TTqzxgPUjUMfw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.20.0.tgz", + "integrity": "sha512-qmuxFpfmi/2SUkAw95TtNq/w/I7Gpjurx609OOOV7U4vhvUhBcftcmXwl3rqAek+ADBwSjIC4IVNLiszoj3dPA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.20.0.tgz", + "integrity": "sha512-I0BtGXddHSHjV1mqTNkgUZLnS3WtsqebAXv11D5BZE/gfw5KoyXSAXVqyJximQXNvNzUo4GKlCK/dIwXlz+jlg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.20.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.20.0.tgz", @@ -4230,6 +4376,45 @@ "linux" ] }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.20.0.tgz", + "integrity": "sha512-psegMvP+Ik/Bg7QRJbv8w8PAytPA7Uo8fpFjXyCRHWm6Nt42L+JtoqH8eDQ5hRP7/XW2UiIriy1Z46jf0Oa1kA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.20.0.tgz", + "integrity": "sha512-GabekH3w4lgAJpVxkk7hUzUf2hICSQO0a/BLFA11/RMxQT92MabKAqyubzDZmMOC/hcJNlc+rrypzNzYl4Dx7A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.20.0.tgz", + "integrity": "sha512-aJ1EJSuTdGnM6qbVC4B5DSmozPTqIag9fSzXRNNo+humQLG89XpPgdt16Ia56ORD7s+H8Pmyx44uczDQ0yDzpg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -4918,86 +5103,6 @@ } } }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.36", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.36.tgz", - "integrity": "sha512-8vDczXzCgv3ceTPhEivlpGprN44YlrCK1nbfU9g2TrhV/Aiqi09W/eM5zLesdoM1Z3mJl492gc/8nlTkpDdusw==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.7.36", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.36.tgz", - "integrity": "sha512-Pa2Gao7+Wf5m3SsK4abKRtd48AtoUnJInvaC3d077swBfgZjbjUbQvcpdc2dOeQtWwo49rFqUZJonMsL0jnPgQ==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.7.36", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.36.tgz", - "integrity": "sha512-3YsMWd7V+WZEjbfBnLkkz/olcRBa8nyoK0iIOnNARJBMcYaJxjkJSMZpmSojCnIVwvjA1N83CPAbUL+W+fCnHg==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.7.36", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.36.tgz", - "integrity": "sha512-lqM3aBB7kJazJYOwHeA5OGNLqXoQPZ/76b3dV+XcjN1GhD0CcXz6mW5PRYVin6OSN1eKrKBKJjtDA1mqADDEvw==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.7.36", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.36.tgz", - "integrity": "sha512-bqei2YDzvUfG0pth5W2xJaj0eG4XWYk0d/NJ75vBX6bkIzK6dC8iuKQ41jOfUWonnrAs7rTDDJW0sTn/evvRdw==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@swc/core-linux-x64-gnu": { "version": "1.7.36", "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.36.tgz", @@ -5030,54 +5135,6 @@ "node": ">=10" } }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.7.36", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.36.tgz", - "integrity": "sha512-k7+dmb13a/zPw+E4XYfPmLZFWJgcOcBRKIjYl9nQErtYsgsg3Ji6TBbsvJVETy23lNHyewZ17V5Vq6NzaG0hzg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.7.36", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.36.tgz", - "integrity": "sha512-ridD3ay6YM2PEYHZXXFN+edYEv0FOynaqOBP+NSnGNHA35azItIjoIe+KNi4WltGtAjpKCHSpjGCNfna12wdYQ==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.7.36", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.36.tgz", - "integrity": "sha512-j1z2Z1Ln9d0E3dHsPkC1K9XDh0ojhRPwV+GfRTu4D61PE+aYhYLvbJC6xPvL4/204QrStRS7eDu3m+BcDp3rgQ==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -16505,6 +16562,19 @@ "fsevents": "~2.3.2" } }, + "node_modules/rollup/node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.20.0.tgz", + "integrity": "sha512-uFVfvzvsdGtlSLuL0ZlvPJvl6ZmrH4CBwLGEFPe7hUmf7htGAN+aXo43R/V6LATyxlKVC/m6UsLb7jbG+LG39Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", diff --git a/package.json b/package.json index e4caa11b1..50ddbeee7 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "@sentry/browser": "^8.0.0", "@sentry/node": "^8.0.0", "@sentry/tracing": "^7.0.0", - "@vitejs/plugin-react-swc": "^3.6.0", + "@vitejs/plugin-react-swc": "^3.7.1", "axios": "^1.7.2", "buffer": "^6.0.3", "chart.js": "^3.4.0", @@ -156,6 +156,9 @@ "util": "^0.12.4", "vite-plugin-eslint": "^1.8.1" }, + "optionalDependencies": { + "@rollup/rollup-darwin-arm64": "4.24.0" + }, "browserslist": { "production": [ ">0.2%", diff --git a/src/client/pages/FeedbackTarget/FeedbackTarget.jsx b/src/client/pages/FeedbackTarget/FeedbackTarget.jsx index f360d0d6e..71393ff27 100644 --- a/src/client/pages/FeedbackTarget/FeedbackTarget.jsx +++ b/src/client/pages/FeedbackTarget/FeedbackTarget.jsx @@ -17,10 +17,26 @@ const FeedbackTarget = () => { const { authorizedUser } = useAuthorizedUser() const { organisations, isLoading: organisationsLoading } = useOrganisations() + function getPriority(org) { + let weight = 0 + if (org.access.admin) { + weight += 100 + } + if (org.access.write) { + weight += 10 + } + if (org.access.read) { + weight += 1 + } + return weight + } const organisation = isLoading || organisationsLoading || !courseUnit ? null - : organisations?.find(org => courseUnit.organisations[0].id === org.id) + : organisations + ?.filter(org => courseUnit.organisations.map(o => o.id)?.includes(org.id)) + ?.sort((a, b) => getPriority(b) - getPriority(a)) // admin, write, read + ?.at(0) if (isLoading) { return diff --git a/src/client/pages/FeedbackTarget/tabs/Results/ExportFeedbacksMenu.jsx b/src/client/pages/FeedbackTarget/tabs/Results/ExportFeedbacksMenu.jsx index 2c03bf71a..cca6a4247 100644 --- a/src/client/pages/FeedbackTarget/tabs/Results/ExportFeedbacksMenu.jsx +++ b/src/client/pages/FeedbackTarget/tabs/Results/ExportFeedbacksMenu.jsx @@ -24,11 +24,21 @@ const getHeaders = (questions, feedbacks, language) => { } const getData = (questions, feedbacks, language) => { - const options = flatMap(questions, q => - ['MULTIPLE_CHOICE', 'SINGLE_CHOICE'].includes(q.type) ? (q.data?.options ?? []) : [] - ) + //Filter to choice questions only + const choiceQuestions = questions.filter(q => ['MULTIPLE_CHOICE', 'SINGLE_CHOICE'].includes(q.type)) + + // optionIds are not unique, so we need to create unique ids for options by adding questionId to the beginning of the id and set it as questionOptionId + choiceQuestions.forEach(question => { + if (question.data && question.data.options) { + question.data.options.forEach(option => { + option.questionOptionId = `${question.id}_${option.id}` + }) + } + }) + + const options = flatMap(choiceQuestions, q => q.data?.options ?? []) - const optionById = keyBy(options, ({ id }) => id) + const optionById = keyBy(options, ({ questionOptionId }) => questionOptionId) const data = feedbacks.map(f => { const feedback = f.data @@ -40,13 +50,15 @@ const getData = (questions, feedbacks, language) => { if (Array.isArray(d.data)) { return d.data .map(optionId => { - const option = optionById[optionId] + const questionOptionId = `${q.id}_${optionId}` + const option = optionById[questionOptionId] return getLanguageValue(option?.label, language) }) .join(', ') } - const option = optionById[d.data] + const questionOptionId = `${q.id}_${d.data}` + const option = optionById[questionOptionId] return getLanguageValue(option?.label, language) } diff --git a/src/client/pages/FeedbackTarget/tabs/Results/QuestionResults/QuestionResults.jsx b/src/client/pages/FeedbackTarget/tabs/Results/QuestionResults/QuestionResults.jsx index f79605f7d..be7e576cb 100644 --- a/src/client/pages/FeedbackTarget/tabs/Results/QuestionResults/QuestionResults.jsx +++ b/src/client/pages/FeedbackTarget/tabs/Results/QuestionResults/QuestionResults.jsx @@ -39,7 +39,9 @@ const getQuestionsWithFeedback = (questions, questionOrder, feedbacks) => { ) // filter short answers which are not a number, or answers that are blank .filter(answer => { const isNumber = !Number.isNaN(parseInt(answer.data, 10)) - return isNumber || answer.data?.trim?.().length > 1 + const isArray = Array.isArray(answer.data) + const arrayLength = isArray ? answer.data.length : 0 + return isNumber || arrayLength > 0 || answer.data?.trim?.().length > 1 }) const feedbackDataByQuestionId = groupBy(feedbackData, ({ questionId }) => questionId ?? '_') diff --git a/src/client/pages/MyFeedbacks/FeedbackTargetItem.jsx b/src/client/pages/MyFeedbacks/FeedbackTargetItem.jsx index d9969d75f..3a32658a9 100644 --- a/src/client/pages/MyFeedbacks/FeedbackTargetItem.jsx +++ b/src/client/pages/MyFeedbacks/FeedbackTargetItem.jsx @@ -21,7 +21,7 @@ import { getStartAndEndString } from '../../util/getDateRangeString' import feedbackTargetIsEnded from '../../util/feedbackTargetIsEnded' import feedbackTargetCourseIsOngoing from '../../util/feedbackTargetCourseIsOngoing' import feedbackTargetNotGivingFeedback from '../../util/feedbackTargetNotGivingFeedback' -import { SHOW_FEEDBACKS_TO_STUDENTS_ONLY_AFTER_ENDING, SHOW_COURSE_CODES_WITH_COURSE_NAMES } from '../../util/common' +import { SHOW_FEEDBACKS_TO_STUDENTS_ONLY_AFTER_ENDING } from '../../util/common' import { getCourseCode } from '../../util/courseIdentifiers' const NoFeedbackActions = ({ editPath, noFeedbackAllowed, onNotGivingFeedback }) => { @@ -273,13 +273,6 @@ const PeriodInfoAddition = ({ isEnded }) => { return null } -const getCourseDisplayName = (translatedName, courseCode, isOrganisationSurvey) => { - if (SHOW_COURSE_CODES_WITH_COURSE_NAMES && !isOrganisationSurvey) { - return `${courseCode} ${translatedName}` - } - return `${translatedName}` -} - const FeedbackTargetItem = ({ feedbackTarget, divider }) => { const { t, i18n } = useTranslation() const queryClient = useQueryClient() @@ -296,11 +289,6 @@ const FeedbackTargetItem = ({ feedbackTarget, divider }) => { const courseName = getCourseName(feedbackTarget, t) const visibleCourseCode = getCourseCode(courseUnit) const translatedName = getLanguageValue(courseName, i18n.language) - const courseDisplayName = getCourseDisplayName( - translatedName, - feedbackTarget.courseUnit.courseCode, - feedbackTarget.courseUnit.userCreated - ) const editPath = `/targets/${id}/feedback` const viewPath = `/targets/${id}/results` @@ -337,7 +325,7 @@ const FeedbackTargetItem = ({ feedbackTarget, divider }) => { disableGutters > - {visibleCourseCode} {courseDisplayName} + {visibleCourseCode} {translatedName} diff --git a/src/server/models/user.js b/src/server/models/user.js index fa77e23e1..17c1667da 100644 --- a/src/server/models/user.js +++ b/src/server/models/user.js @@ -51,8 +51,22 @@ class User extends Model { const organisationIds = rows.flatMap(row => Object.values(row)) + function getPriority(org) { + let weight = 0 + if (org.access.admin) { + weight += 100 + } + if (org.access.write) { + weight += 10 + } + if (org.access.read) { + weight += 1 + } + return weight + } const organisationAccess = organisations .filter(({ organisation }) => organisationIds.includes(organisation.id)) + ?.sort((a, b) => getPriority(a) - getPriority(b)) // read, write, admin. Reduce on next line practically takes the last value .reduce((finalAccess, org) => ({ ...finalAccess, ...org.access }), {}) return organisationAccess ?? null diff --git a/src/server/services/feedbackTargets/getAccess.js b/src/server/services/feedbackTargets/getAccess.js index 6b568e373..db52d145a 100644 --- a/src/server/services/feedbackTargets/getAccess.js +++ b/src/server/services/feedbackTargets/getAccess.js @@ -4,23 +4,48 @@ const getAccess = async ({ userFeedbackTarget, user, feedbackTarget }) => { if (user.dataValues.isAdmin) return Access.ADMIN const accessStatus = userFeedbackTarget?.accessStatus - + let uftAccess = null if (accessStatus) { - return Access.For(accessStatus) + uftAccess = Access.For(accessStatus) } // User not directly associated. Lets check if they have access through organisation const organisationAccess = await user.getOrganisationAccessByCourseUnitId(feedbackTarget.courseUnitId) - if (!organisationAccess) { - return null + let orgAccess = null + if (organisationAccess) { + if (organisationAccess.admin) { + orgAccess = Access.ORGANISATION_ADMIN + } else if (organisationAccess.read) { + orgAccess = Access.ORGANISATION_READ + } } - if (organisationAccess.admin) { - return Access.ORGANISATION_ADMIN + // only direct access, return that + if (uftAccess !== null && orgAccess === null) { + return uftAccess + } + // access only through organisation, return that + if (uftAccess === null && orgAccess !== null) { + return orgAccess + } + // both direct access and access through organisation, return highest + if (uftAccess !== null && orgAccess !== null) { + if (orgAccess === Access.ORGANISATION_ADMIN) { + if (uftAccess === Access.ADMIN || uftAccess === Access.RESPONSIBLE_TEACHER) { + return uftAccess + } + return orgAccess + } + if (orgAccess === Access.ORGANISATION_READ) { + if (uftAccess === Access.STUDENT) { + return orgAccess + } + return uftAccess + } } - return Access.ORGANISATION_READ + return null } module.exports = { getAccess } diff --git a/src/server/services/summary/getCourseUnitGroupSummary.js b/src/server/services/summary/getCourseUnitGroupSummary.js index 7bc36d0ad..2a12bbda7 100644 --- a/src/server/services/summary/getCourseUnitGroupSummary.js +++ b/src/server/services/summary/getCourseUnitGroupSummary.js @@ -91,7 +91,6 @@ const getCourseUnitGroupSummaries = async ({ user, courseCode, startDate, endDat const allOrgIds = cuOrgIds.concat(curOrgIds) const hasOrgAccess = Object.values(orgAccess).some(o => allOrgIds.includes(o.organisation.id)) - if (!user.isAdmin && !hasOrgAccess) { const hasCurAccess = feedbackTargets.some(fbt => accessibleCurIds.includes(fbt.courseRealisation.id)) if (!hasCurAccess) {