diff --git a/frontend/package.json b/frontend/package.json index 0826edae..58287e14 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -21,6 +21,7 @@ "@tanstack/vue-query": "^5.69.0", "@vueuse/core": "^13.1.0", "axios": "^1.8.2", + "json-editor-vue": "^0.18.1", "oidc-client-ts": "^3.1.0", "rollup": "^4.40.0", "uuid": "^11.1.0", diff --git a/frontend/src/components/MenuBar.vue b/frontend/src/components/MenuBar.vue index a58be2f8..d8eccacb 100644 --- a/frontend/src/components/MenuBar.vue +++ b/frontend/src/components/MenuBar.vue @@ -7,8 +7,10 @@ // Import assets import dwengoLogo from "../../../assets/img/dwengo-groen-zwart.svg"; +import { useLocale } from "vuetify"; const { t, locale } = useI18n(); + const { current: vuetifyLocale } = useLocale(); const role = auth.authState.activeRole; const _router = useRouter(); // Zonder '_' gaf dit een linter error voor unused variable @@ -31,6 +33,7 @@ // Logic to change the language of the website to the selected language function changeLanguage(langCode: string): void { locale.value = langCode; + vuetifyLocale.value = langCode; localStorage.setItem("user-lang", langCode); } diff --git a/frontend/src/controllers/learning-paths.ts b/frontend/src/controllers/learning-paths.ts index 697826bc..f8b82bef 100644 --- a/frontend/src/controllers/learning-paths.ts +++ b/frontend/src/controllers/learning-paths.ts @@ -37,9 +37,8 @@ export class LearningPathController extends BaseController { return dtos.map((dto) => LearningPath.fromDTO(dto)); } - async getAllByAdmin(admin: string): Promise { - const dtos = await this.get("/", { admin }); - return dtos.map((dto) => LearningPath.fromDTO(dto)); + async getAllByAdminRaw(admin: string): Promise { + return await this.get("/", { admin }); } async postLearningPath(learningPath: LearningPathDTO): Promise { diff --git a/frontend/src/i18n/locale/en.json b/frontend/src/i18n/locale/en.json index e4042d09..47acd255 100644 --- a/frontend/src/i18n/locale/en.json +++ b/frontend/src/i18n/locale/en.json @@ -121,5 +121,18 @@ "invite": "invite", "assignmentIndicator": "ASSIGNMENT", "searchAllLearningPathsTitle": "Search all learning paths", - "searchAllLearningPathsDescription": "You didn't find what you were looking for? Click here to search our whole database of available learning paths." + "searchAllLearningPathsDescription": "You didn't find what you were looking for? Click here to search our whole database of available learning paths.", + "learningObjects": "Learning objects", + "learningPaths": "Learning paths", + "hruid": "HRUID", + "language": "Language", + "version": "Version", + "previewFor": "Preview for ", + "upload": "Upload", + "learningObjectUploadTitle": "Upload a learning object", + "uploadFailed": "Upload failed", + "invalidZip": "This is not a valid zip file.", + "emptyZip": "This zip file is empty", + "missingMetadata": "This learning object is missing a metadata.json file.", + "missingContent": "This learning object is missing a content.* file." } diff --git a/frontend/src/main.ts b/frontend/src/main.ts index b5315634..f6f90716 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -7,15 +7,20 @@ import * as components from "vuetify/components"; import * as directives from "vuetify/directives"; import i18n from "./i18n/i18n.ts"; +// JSON-editor +import JsonEditorVue from 'json-editor-vue'; + // Components import App from "./App.vue"; import router from "./router"; import { aliases, mdi } from "vuetify/iconsets/mdi"; import { VueQueryPlugin, QueryClient } from "@tanstack/vue-query"; +import { de, en, fr, nl } from "vuetify/locale"; const app = createApp(App); app.use(router); +app.use(JsonEditorVue, {}) const link = document.createElement("link"); link.rel = "stylesheet"; @@ -32,6 +37,11 @@ const vuetify = createVuetify({ mdi, }, }, + locale: { + locale: i18n.global.locale, + fallback: 'en', + messages: { nl, en, de, fr } + } }); const queryClient = new QueryClient({ diff --git a/frontend/src/queries/learning-objects.ts b/frontend/src/queries/learning-objects.ts index e06f21c5..2ed8bc52 100644 --- a/frontend/src/queries/learning-objects.ts +++ b/frontend/src/queries/learning-objects.ts @@ -5,7 +5,6 @@ import { getLearningObjectController } from "@/controllers/controllers.ts"; import type { LearningObject } from "@/data-objects/learning-objects/learning-object.ts"; import type { LearningPath } from "@/data-objects/learning-paths/learning-path.ts"; import type { AxiosError } from "axios"; -import type { LearningObjectIdentifierDTO } from "@dwengo-1/common/interfaces/learning-content"; export const LEARNING_OBJECT_KEY = "learningObject"; const learningObjectController = getLearningObjectController(); diff --git a/frontend/src/queries/learning-paths.ts b/frontend/src/queries/learning-paths.ts index 1f088c9d..d24b6fc5 100644 --- a/frontend/src/queries/learning-paths.ts +++ b/frontend/src/queries/learning-paths.ts @@ -1,8 +1,10 @@ import { type MaybeRefOrGetter, toValue } from "vue"; import type { Language } from "@/data-objects/language.ts"; -import { useQuery, type UseQueryReturnType } from "@tanstack/vue-query"; +import { useMutation, useQuery, useQueryClient, type UseMutationReturnType, type UseQueryReturnType } from "@tanstack/vue-query"; import { getLearningPathController } from "@/controllers/controllers"; import type { LearningPath } from "@/data-objects/learning-paths/learning-path.ts"; +import type { AxiosError } from "axios"; +import type { LearningPathDTO } from "@/data-objects/learning-paths/learning-path-dto"; export const LEARNING_PATH_KEY = "learningPath"; const learningPathController = getLearningPathController(); @@ -32,6 +34,46 @@ export function useGetAllLearningPathsByThemeQuery( }); } +export function useGetAllLearningPathsByAdminQuery( + admin: MaybeRefOrGetter +): UseQueryReturnType { + return useQuery({ + queryKey: [LEARNING_PATH_KEY, "getAllByAdmin", admin], + queryFn: async () => learningPathController.getAllByAdminRaw(toValue(admin)!), + enabled: () => Boolean(toValue(admin)) + }); +} + +export function usePostLearningPathMutation(): + UseMutationReturnType { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async ({ learningPath }) => learningPathController.postLearningPath(learningPath), + onSuccess: async () => queryClient.invalidateQueries({ queryKey: [LEARNING_PATH_KEY] }) + }); +} + +export function usePutLearningPathMutation(): + UseMutationReturnType { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async ({ learningPath }) => learningPathController.putLearningPath(learningPath), + onSuccess: async () => queryClient.invalidateQueries({ queryKey: [LEARNING_PATH_KEY] }) + }); +} + +export function useDeleteLearningPathMutation(): + UseMutationReturnType { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async ({ hruid, language }) => learningPathController.deleteLearningPath(hruid, language), + onSuccess: async () => queryClient.invalidateQueries({ queryKey: [LEARNING_PATH_KEY] }) + }); +} + export function useSearchLearningPathQuery( query: MaybeRefOrGetter, language: MaybeRefOrGetter, diff --git a/frontend/src/views/own-learning-content/OwnLearningContentPage.vue b/frontend/src/views/own-learning-content/OwnLearningContentPage.vue index 609c8433..02a2e90d 100644 --- a/frontend/src/views/own-learning-content/OwnLearningContentPage.vue +++ b/frontend/src/views/own-learning-content/OwnLearningContentPage.vue @@ -1,18 +1,23 @@ @@ -34,7 +39,12 @@ import { useI18n } from "vue-i18n"; - + + + @@ -45,8 +55,10 @@ import { useI18n } from "vue-i18n"; display: flex; flex-direction: column; height: 100%; + padding: 20px 30px; } .main-content { - flex: 1; + flex: 1 1; + height: 100%; } diff --git a/frontend/src/views/own-learning-content/OwnLearningPathsView.vue b/frontend/src/views/own-learning-content/OwnLearningPathsView.vue deleted file mode 100644 index b199202e..00000000 --- a/frontend/src/views/own-learning-content/OwnLearningPathsView.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - - - diff --git a/frontend/src/views/own-learning-content/learning-objects/LearningObjectPreviewCard.vue b/frontend/src/views/own-learning-content/learning-objects/LearningObjectPreviewCard.vue new file mode 100644 index 00000000..3f475863 --- /dev/null +++ b/frontend/src/views/own-learning-content/learning-objects/LearningObjectPreviewCard.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/frontend/src/views/own-learning-content/LearningObjectUploadButton.vue b/frontend/src/views/own-learning-content/learning-objects/LearningObjectUploadButton.vue similarity index 85% rename from frontend/src/views/own-learning-content/LearningObjectUploadButton.vue rename to frontend/src/views/own-learning-content/learning-objects/LearningObjectUploadButton.vue index 34211467..4507401b 100644 --- a/frontend/src/views/own-learning-content/LearningObjectUploadButton.vue +++ b/frontend/src/views/own-learning-content/learning-objects/LearningObjectUploadButton.vue @@ -32,17 +32,14 @@