Merge branch 'dev' into fix/questions-toon-enkel-groep
This commit is contained in:
		
						commit
						73ca508ff3
					
				
					 5 changed files with 118 additions and 62 deletions
				
			
		|  | @ -1,12 +1,13 @@ | |||
| import { getAssignmentRepository, getGroupRepository, getSubmissionRepository } from '../data/repositories.js'; | ||||
| import { getSubmissionRepository } from '../data/repositories.js'; | ||||
| import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; | ||||
| import { NotFoundException } from '../exceptions/not-found-exception.js'; | ||||
| import { mapToSubmission, mapToSubmissionDTO } from '../interfaces/submission.js'; | ||||
| import { SubmissionDTO } from '@dwengo-1/common/interfaces/submission'; | ||||
| import { fetchStudent } from './students.js'; | ||||
| import { getExistingGroupFromGroupDTO } from './groups.js'; | ||||
| import { fetchGroup, getExistingGroupFromGroupDTO } from './groups.js'; | ||||
| import { Submission } from '../entities/assignments/submission.entity.js'; | ||||
| import { Language } from '@dwengo-1/common/util/language'; | ||||
| import { fetchAssignment } from './assignments.js'; | ||||
| 
 | ||||
| export async function fetchSubmission(loId: LearningObjectIdentifier, submissionNumber: number): Promise<Submission> { | ||||
|     const submissionRepository = getSubmissionRepository(); | ||||
|  | @ -64,15 +65,18 @@ export async function getSubmissionsForLearningObjectAndAssignment( | |||
|     groupId?: number | ||||
| ): Promise<SubmissionDTO[]> { | ||||
|     const loId = new LearningObjectIdentifier(learningObjectHruid, language, version); | ||||
|     const assignment = await getAssignmentRepository().findByClassIdAndAssignmentId(classId, assignmentId); | ||||
| 
 | ||||
|     let submissions: Submission[]; | ||||
|     if (groupId !== undefined) { | ||||
|         const group = await getGroupRepository().findByAssignmentAndGroupNumber(assignment!, groupId); | ||||
|         submissions = await getSubmissionRepository().findAllSubmissionsForLearningObjectAndGroup(loId, group!); | ||||
|     } else { | ||||
|         submissions = await getSubmissionRepository().findAllSubmissionsForLearningObjectAndAssignment(loId, assignment!); | ||||
|     try { | ||||
|         let submissions: Submission[]; | ||||
|         if (groupId !== undefined) { | ||||
|             const group = await fetchGroup(classId, assignmentId, groupId); | ||||
|             submissions = await getSubmissionRepository().findAllSubmissionsForLearningObjectAndGroup(loId, group); | ||||
|         } else { | ||||
|             const assignment = await fetchAssignment(classId, assignmentId); | ||||
|             submissions = await getSubmissionRepository().findAllSubmissionsForLearningObjectAndAssignment(loId, assignment); | ||||
|         } | ||||
|         return submissions.map((s) => mapToSubmissionDTO(s)); | ||||
|     } catch (_) { | ||||
|         return []; | ||||
|     } | ||||
| 
 | ||||
|     return submissions.map((s) => mapToSubmissionDTO(s)); | ||||
| } | ||||
|  |  | |||
|  | @ -34,19 +34,21 @@ | |||
|                 </template> | ||||
|             </v-list-item> | ||||
|             <v-divider></v-divider> | ||||
|             <v-expansion-panels v-model="expanded"> | ||||
|                 <using-query-result | ||||
|                     :query-result="allLearningPathsResult" | ||||
|                     v-slot="learningPaths: { data: LearningPath[] }" | ||||
|                 > | ||||
|                     <DiscussionSideBarElement | ||||
|                         v-for="learningPath in learningPaths.data" | ||||
|                         :path="learningPath" | ||||
|                         :activeObjectId="'' as string" | ||||
|                         :key="learningPath.hruid" | ||||
|                     /> | ||||
|                 </using-query-result> | ||||
|             </v-expansion-panels> | ||||
|             <div class="nav-scroll-area"> | ||||
|                 <v-expansion-panels v-model="expanded"> | ||||
|                     <using-query-result | ||||
|                         :query-result="allLearningPathsResult" | ||||
|                         v-slot="learningPaths: { data: LearningPath[] }" | ||||
|                     > | ||||
|                         <DiscussionSideBarElement | ||||
|                             v-for="learningPath in learningPaths.data" | ||||
|                             :path="learningPath" | ||||
|                             :activeObjectId="'' as string" | ||||
|                             :key="learningPath.hruid" | ||||
|                         /> | ||||
|                     </using-query-result> | ||||
|                 </v-expansion-panels> | ||||
|             </div> | ||||
|         </div> | ||||
|     </v-navigation-drawer> | ||||
|     <div class="control-bar-above-content"> | ||||
|  | @ -67,4 +69,10 @@ | |||
|         padding-top: 2%; | ||||
|         font-size: 36px; | ||||
|     } | ||||
| 
 | ||||
|     .nav-scroll-area { | ||||
|         overflow-y: auto; | ||||
|         flex-grow: 1; | ||||
|         min-height: 0; | ||||
|     } | ||||
| </style> | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ | |||
|     import authService from "@/services/auth/auth-service.ts"; | ||||
|     import { LearningPathNode } from "@/data-objects/learning-paths/learning-path-node.ts"; | ||||
|     import LearningPathGroupSelector from "@/views/learning-paths/LearningPathGroupSelector.vue"; | ||||
|     import { useQuestionsGroupQuery, useQuestionsQuery } from "@/queries/questions"; | ||||
|     import { useQuestionsQuery } from "@/queries/questions"; | ||||
|     import type { QuestionsResponse } from "@/controllers/questions"; | ||||
|     import type { LearningObjectIdentifierDTO } from "@dwengo-1/common/interfaces/learning-content"; | ||||
|     import QandA from "@/components/QandA.vue"; | ||||
|  | @ -163,11 +163,6 @@ | |||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     const loID: LearningObjectIdentifierDTO = { | ||||
|         hruid: props.learningObjectHruid as string, | ||||
|         language: props.language, | ||||
|     }; | ||||
| 
 | ||||
|     const discussionLink = computed( | ||||
|         () => | ||||
|             "/discussion" + | ||||
|  | @ -237,7 +232,7 @@ | |||
|                     </template> | ||||
|                 </v-list-item> | ||||
|                 <v-divider></v-divider> | ||||
|                 <div> | ||||
|                 <div class="nav-scroll-area"> | ||||
|                     <using-query-result | ||||
|                         :query-result="learningObjectListQueryResult" | ||||
|                         v-slot="learningObjects: { data: LearningObject[] }" | ||||
|  | @ -430,4 +425,10 @@ | |||
|     .discussion-link a:hover { | ||||
|         text-decoration: underline; | ||||
|     } | ||||
| 
 | ||||
|     .nav-scroll-area { | ||||
|         overflow-y: auto; | ||||
|         flex-grow: 1; | ||||
|         min-height: 0; | ||||
|     } | ||||
| </style> | ||||
|  |  | |||
|  | @ -18,6 +18,15 @@ | |||
|         version: number; | ||||
|         group: { forGroup: number; assignmentNo: number; classId: string }; | ||||
|     }>(); | ||||
| 
 | ||||
|     function parseContent(content: string): SubmissionData { | ||||
|         if (content === "") { | ||||
|             return []; | ||||
|         } | ||||
| 
 | ||||
|         return JSON.parse(content); | ||||
|     } | ||||
| 
 | ||||
|     const emit = defineEmits<(e: "update:submissionData", value: SubmissionData) => void>(); | ||||
| 
 | ||||
|     const submissionQuery = useSubmissionsQuery( | ||||
|  | @ -35,7 +44,7 @@ | |||
|     } | ||||
| 
 | ||||
|     function emitSubmission(submission: SubmissionDTO): void { | ||||
|         emitSubmissionData(JSON.parse(submission.content)); | ||||
|         emitSubmissionData(parseContent(submission.content)); | ||||
|     } | ||||
| 
 | ||||
|     watch(submissionQuery.data, () => { | ||||
|  | @ -47,12 +56,13 @@ | |||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     const lastSubmission = computed<SubmissionData>(() => { | ||||
|     const lastSubmission = computed<SubmissionData | undefined>(() => { | ||||
|         const submissions = submissionQuery.data.value; | ||||
|         if (!submissions || submissions.length === 0) { | ||||
|             return undefined; | ||||
|         } | ||||
|         return JSON.parse(submissions[submissions.length - 1].content); | ||||
| 
 | ||||
|         return parseContent(submissions[submissions.length - 1].content); | ||||
|     }); | ||||
| 
 | ||||
|     const showSubmissionTable = computed(() => props.submissionData !== undefined && props.submissionData.length > 0); | ||||
|  |  | |||
|  | @ -89,6 +89,15 @@ | |||
|                 props.selectedLearningPath.language !== parsedLearningPath.value.language), | ||||
|     ); | ||||
| 
 | ||||
|     const selectedLearningPathLink = computed(() => { | ||||
|         if (!props.selectedLearningPath) { | ||||
|             return undefined; | ||||
|         } | ||||
|         const { hruid, language } = props.selectedLearningPath; | ||||
|         const startNode = props.selectedLearningPath.nodes.find((it) => it.start_node); | ||||
|         return `/learningPath/${hruid}/${language}/${startNode.learningobject_hruid}`; | ||||
|     }); | ||||
| 
 | ||||
|     function getErrorMessage(): string | null { | ||||
|         if (postError.value) { | ||||
|             return t(extractErrorMessage(postError.value)); | ||||
|  | @ -104,7 +113,43 @@ | |||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|     <v-card :title="props.selectedLearningPath ? t('editLearningPath') : t('newLearningPath')"> | ||||
|     <v-card> | ||||
|         <template v-slot:title> | ||||
|             <div class="title-container"> | ||||
|                 <span class="title">{{ | ||||
|                     props.selectedLearningPath ? t("editLearningPath") : t("newLearningPath") | ||||
|                 }}</span> | ||||
|                 <span class="actions"> | ||||
|                     <v-btn | ||||
|                         @click="uploadLearningPath" | ||||
|                         prependIcon="mdi mdi-check" | ||||
|                         :loading="isPostPending || isPutPending" | ||||
|                         :disabled="parsedLearningPath.hruid === DEFAULT_LEARNING_PATH.hruid || isIdModified" | ||||
|                         variant="text" | ||||
|                     > | ||||
|                         {{ props.selectedLearningPath ? t("saveChanges") : t("create") }} | ||||
|                     </v-btn> | ||||
|                     <button-with-confirmation | ||||
|                         @confirm="deleteLearningPath" | ||||
|                         :disabled="!props.selectedLearningPath" | ||||
|                         :text="t('delete')" | ||||
|                         color="red" | ||||
|                         prependIcon="mdi mdi-delete" | ||||
|                         :confirmQueryText="t('learningPathDeleteQuery')" | ||||
|                         variant="text" | ||||
|                     /> | ||||
|                     <v-btn | ||||
|                         :href="selectedLearningPathLink" | ||||
|                         target="_blank" | ||||
|                         prepend-icon="mdi mdi-open-in-new" | ||||
|                         :disabled="!props.selectedLearningPath" | ||||
|                         variant="text" | ||||
|                     > | ||||
|                         {{ t("open") }} | ||||
|                     </v-btn> | ||||
|                 </span> | ||||
|             </div> | ||||
|         </template> | ||||
|         <template v-slot:text> | ||||
|             <json-editor-vue v-model="learningPath"></json-editor-vue> | ||||
|             <v-alert | ||||
|  | @ -115,33 +160,21 @@ | |||
|                 :text="getErrorMessage()!" | ||||
|             ></v-alert> | ||||
|         </template> | ||||
|         <template v-slot:actions> | ||||
|             <v-btn | ||||
|                 @click="uploadLearningPath" | ||||
|                 prependIcon="mdi mdi-check" | ||||
|                 :loading="isPostPending || isPutPending" | ||||
|                 :disabled="parsedLearningPath.hruid === DEFAULT_LEARNING_PATH.hruid || isIdModified" | ||||
|             > | ||||
|                 {{ props.selectedLearningPath ? t("saveChanges") : t("create") }} | ||||
|             </v-btn> | ||||
|             <button-with-confirmation | ||||
|                 @confirm="deleteLearningPath" | ||||
|                 :disabled="!props.selectedLearningPath" | ||||
|                 :text="t('delete')" | ||||
|                 color="red" | ||||
|                 prependIcon="mdi mdi-delete" | ||||
|                 :confirmQueryText="t('learningPathDeleteQuery')" | ||||
|             /> | ||||
|             <v-btn | ||||
|                 :href="`/learningPath/${props.selectedLearningPath?.hruid}/${props.selectedLearningPath?.language}/start`" | ||||
|                 target="_blank" | ||||
|                 prepend-icon="mdi mdi-open-in-new" | ||||
|                 :disabled="!props.selectedLearningPath" | ||||
|             > | ||||
|                 {{ t("open") }} | ||||
|             </v-btn> | ||||
|         </template> | ||||
|     </v-card> | ||||
| </template> | ||||
| 
 | ||||
| <style scoped></style> | ||||
| <style scoped> | ||||
|     .title-container { | ||||
|         display: flex; | ||||
|         flex-direction: row; | ||||
|         flex-wrap: wrap; | ||||
|     } | ||||
|     .title { | ||||
|         flex: 1; | ||||
|     } | ||||
|     .actions { | ||||
|         display: flex; | ||||
|         flex-wrap: wrap; | ||||
|         gap: 10px; | ||||
|     } | ||||
| </style> | ||||
|  |  | |||
		Reference in a new issue