From 9a58126c7c3c44bc23087e57e45404b0596c3851 Mon Sep 17 00:00:00 2001 From: Gerald Schmittinger Date: Wed, 14 May 2025 00:27:28 +0200 Subject: [PATCH] fix: UI-imperfecties & diverse bugs omtrent het verwijderen en editeren van leerpaden opgelost --- .../data/content/learning-path-repository.ts | 16 ----- .../learning-paths/learning-path-service.ts | 9 ++- .../src/components/ButtonWithConfirmation.vue | 61 +++++++++++++++++++ frontend/src/i18n/locale/en.json | 7 ++- .../LearningObjectPreviewCard.vue | 9 ++- .../LearningPathPreviewCard.vue | 52 +++++++++++++--- 6 files changed, 126 insertions(+), 28 deletions(-) diff --git a/backend/src/data/content/learning-path-repository.ts b/backend/src/data/content/learning-path-repository.ts index 81b0df99..992011d5 100644 --- a/backend/src/data/content/learning-path-repository.ts +++ b/backend/src/data/content/learning-path-repository.ts @@ -4,7 +4,6 @@ import { Language } from '@dwengo-1/common/util/language'; import { LearningPathNode } from '../../entities/content/learning-path-node.entity.js'; import { RequiredEntityData } from '@mikro-orm/core'; import { LearningPathTransition } from '../../entities/content/learning-path-transition.entity.js'; -import { EntityAlreadyExistsException } from '../../exceptions/entity-already-exists-exception.js'; export class LearningPathRepository extends DwengoEntityRepository { public async findByHruidAndLanguage(hruid: string, language: Language): Promise { @@ -53,21 +52,6 @@ export class LearningPathRepository extends DwengoEntityRepository return this.em.create(LearningPathTransition, transitionData); } - public async saveLearningPathNodesAndTransitions( - path: LearningPath, - nodes: LearningPathNode[], - transitions: LearningPathTransition[], - options?: { preventOverwrite?: boolean } - ): Promise { - if (options?.preventOverwrite && (await this.findOne(path))) { - throw new EntityAlreadyExistsException('A learning path with this hruid/language combination already exists.'); - } - const em = this.getEntityManager(); - await em.persistAndFlush(path); - await Promise.all(nodes.map(async (it) => em.persistAndFlush(it))); - await Promise.all(transitions.map(async (it) => em.persistAndFlush(it))); - } - /** * Deletes the learning path with the given hruid and language. * @returns the deleted learning path or null if it was not found. diff --git a/backend/src/services/learning-paths/learning-path-service.ts b/backend/src/services/learning-paths/learning-path-service.ts index 7ee60ac3..1c83b3dc 100644 --- a/backend/src/services/learning-paths/learning-path-service.ts +++ b/backend/src/services/learning-paths/learning-path-service.ts @@ -134,8 +134,14 @@ const learningPathService = { */ async createNewLearningPath(dto: LearningPath, admins: TeacherDTO[]): Promise { const repo = getLearningPathRepository(); + const path = mapToLearningPath(dto, admins); - await repo.save(path, { preventOverwrite: true }); + try { + await repo.save(path, { preventOverwrite: true }); + } catch (e: unknown) { + repo.getEntityManager().clear(); + throw e; + } return path; }, @@ -146,6 +152,7 @@ const learningPathService = { */ async deleteLearningPath(id: LearningPathIdentifier): Promise { const repo = getLearningPathRepository(); + const deletedPath = await repo.deleteByHruidAndLanguage(id.hruid, id.language); if (deletedPath) { return deletedPath; diff --git a/frontend/src/components/ButtonWithConfirmation.vue b/frontend/src/components/ButtonWithConfirmation.vue index e69de29b..96370acd 100644 --- a/frontend/src/components/ButtonWithConfirmation.vue +++ b/frontend/src/components/ButtonWithConfirmation.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/frontend/src/i18n/locale/en.json b/frontend/src/i18n/locale/en.json index 77175d78..cb5d5988 100644 --- a/frontend/src/i18n/locale/en.json +++ b/frontend/src/i18n/locale/en.json @@ -139,5 +139,10 @@ "editLearningPath": "Edit learning path", "newLearningPath": "Create a new learning path", "saveChanges": "Save changes", - "newLearningObject": "Upload learning object" + "newLearningObject": "Upload learning object", + "confirmDialogTitle": "Please confirm", + "learningPathDeleteQuery": "Are you sure you want to delete this learning path?", + "learningObjectDeleteQuery": "Are you sure you want to delete this learning object?", + "learningPathCantModifyId": "The HRUID or language of a learning path cannot be modified.", + "error": "Error" } diff --git a/frontend/src/views/own-learning-content/learning-objects/LearningObjectPreviewCard.vue b/frontend/src/views/own-learning-content/learning-objects/LearningObjectPreviewCard.vue index 3f475863..38e2b141 100644 --- a/frontend/src/views/own-learning-content/learning-objects/LearningObjectPreviewCard.vue +++ b/frontend/src/views/own-learning-content/learning-objects/LearningObjectPreviewCard.vue @@ -2,6 +2,7 @@ import type { LearningObject } from '@/data-objects/learning-objects/learning-object'; import UsingQueryResult from '@/components/UsingQueryResult.vue'; import LearningObjectContentView from '../../learning-paths/learning-object/content/LearningObjectContentView.vue'; + import ButtonWithConfirmation from '@/components/ButtonWithConfirmation.vue'; import { useDeleteLearningObjectMutation, useLearningObjectHTMLQuery } from '@/queries/learning-objects'; import { useI18n } from 'vue-i18n'; @@ -41,7 +42,13 @@ diff --git a/frontend/src/views/own-learning-content/learning-paths/LearningPathPreviewCard.vue b/frontend/src/views/own-learning-content/learning-paths/LearningPathPreviewCard.vue index 1c7f09c1..50553b4a 100644 --- a/frontend/src/views/own-learning-content/learning-paths/LearningPathPreviewCard.vue +++ b/frontend/src/views/own-learning-content/learning-paths/LearningPathPreviewCard.vue @@ -2,10 +2,12 @@ import { useI18n } from 'vue-i18n'; import { computed, ref, watch, type Ref } from 'vue'; import JsonEditorVue from 'json-editor-vue' + import ButtonWithConfirmation from '@/components/ButtonWithConfirmation.vue' import { useDeleteLearningPathMutation, usePostLearningPathMutation, usePutLearningPathMutation } from '@/queries/learning-paths'; import { Language } from '@/data-objects/language'; import type { LearningPath } from '@dwengo-1/common/interfaces/learning-content'; import type { AxiosError } from 'axios'; +import { parse } from 'uuid'; const { t } = useI18n(); @@ -63,7 +65,7 @@ } } - function deleteLearningObject(): void { + function deleteLearningPath(): void { if (props.selectedLearningPath) { mutate({ hruid: props.selectedLearningPath.hruid, @@ -72,8 +74,28 @@ } } - function extractErrorMessage(error: AxiosError | null): string | undefined { - return (error?.response?.data as {error: string}).error ?? error?.message; + function extractErrorMessage(error: AxiosError): string { + return (error.response?.data as {error: string}).error ?? error.message; + } + + const isIdModified = computed(() => + props.selectedLearningPath !== undefined && ( + props.selectedLearningPath.hruid !== parsedLearningPath.value.hruid + || props.selectedLearningPath.language !== parsedLearningPath.value.language + ) + ); + + function getErrorMessage(): string | null { + if (postError.value) { + return t(extractErrorMessage(postError.value)); + } else if (putError.value) { + return t(extractErrorMessage(putError.value)); + } else if (deleteError.value) { + return t(extractErrorMessage(deleteError.value)); + } else if (isIdModified.value) { + return t('learningPathCantModifyId'); + } + return null; } @@ -84,22 +106,34 @@