diff --git a/client/src/components/MainNavigationBar.vue b/client/src/components/MainNavigationBar.vue index b4400703..eec08156 100644 --- a/client/src/components/MainNavigationBar.vue +++ b/client/src/components/MainNavigationBar.vue @@ -162,7 +162,7 @@ const profileDropdownData = [ Shop diff --git a/client/src/components/circle/CircleOverview.vue b/client/src/components/circle/CircleOverview.vue index 094a1bbd..4b9fb922 100644 --- a/client/src/components/circle/CircleOverview.vue +++ b/client/src/components/circle/CircleOverview.vue @@ -1,9 +1,9 @@ + + + + diff --git a/client/src/components/mediaCenter/MediaLink.vue b/client/src/components/mediaCenter/MediaLink.vue new file mode 100644 index 00000000..b50bd294 --- /dev/null +++ b/client/src/components/mediaCenter/MediaLink.vue @@ -0,0 +1,28 @@ + + + diff --git a/client/src/components/mediaCenter/OverviewCard.vue b/client/src/components/mediaCenter/OverviewCard.vue new file mode 100644 index 00000000..f5c2bd54 --- /dev/null +++ b/client/src/components/mediaCenter/OverviewCard.vue @@ -0,0 +1,39 @@ + + + + + diff --git a/client/src/components/ui/ItDropdown.vue b/client/src/components/ui/ItDropdown.vue index dbe526dc..7343453c 100644 --- a/client/src/components/ui/ItDropdown.vue +++ b/client/src/components/ui/ItDropdown.vue @@ -1,6 +1,5 @@ + + diff --git a/client/src/i18n.ts b/client/src/i18n.ts index 308f5170..e0ed3316 100644 --- a/client/src/i18n.ts +++ b/client/src/i18n.ts @@ -1,5 +1,5 @@ import { nextTick } from 'vue' -import { createI18n } from 'vue-i18n/index' +import { createI18n } from 'vue-i18n' // https://vue-i18n.intlify.dev/guide/advanced/lazy.html export const SUPPORT_LOCALES = ['de', 'fr', 'it'] diff --git a/client/src/router/index.ts b/client/src/router/index.ts index af8feacc..5572547a 100644 --- a/client/src/router/index.ts +++ b/client/src/router/index.ts @@ -25,8 +25,28 @@ const router = createRouter({ component: () => import('@/views/ShopView.vue'), }, { - path: '/mediacenter', - component: () => import('@/views/MediaView.vue'), + path: '/mediacenter/:mediaCenterPageSlug', + props: true, + component: () => import('@/views/MediaCenterView.vue'), + children: [ + { + path: 'overview', + component: () => import('@/views/MediaCenterMainView.vue'), + }, + { + path: 'handlungsfelder/:mediaCategorySlug', + props: true, + component: () => import('@/views/MediaCategoryDetailView.vue'), + }, + { + path: 'handlungsfelder', + component: () => import('@/views/MediaCenterCategoryOverview.vue'), + }, + { + path: 'handlungsfeldlist', + component: () => import('@/views/MediaList.vue'), + }, + ], }, { path: '/messages', diff --git a/client/src/services/__tests__/circle.spec.ts b/client/src/services/__tests__/circle.spec.ts index cc321a72..06adf021 100644 --- a/client/src/services/__tests__/circle.spec.ts +++ b/client/src/services/__tests__/circle.spec.ts @@ -4,9 +4,9 @@ import { Circle } from '../circle' describe('Circle.parseJson', () => { it('can parse circle from api response', () => { - const cirleData = data.children.find((c) => c.slug === 'unit-test-circle') + const cirleData = data.children.find((c) => c.slug === 'test-lehrgang-lp-circle-analyse') const circle = Circle.fromJson(cirleData, undefined) expect(circle.learningSequences.length).toBe(3) - expect(circle.flatLearningContents.length).toBe(8) + expect(circle.flatLearningContents.length).toBe(7) }) }) diff --git a/client/src/services/__tests__/learningPath.spec.ts b/client/src/services/__tests__/learningPath.spec.ts index a2a32dfe..fbae25e9 100644 --- a/client/src/services/__tests__/learningPath.spec.ts +++ b/client/src/services/__tests__/learningPath.spec.ts @@ -8,7 +8,7 @@ describe('LearningPath.parseJson', () => { expect(learningPath.circles.length).toBe(2) expect(learningPath.circles[0].title).toBe('Basis') - expect(learningPath.circles[1].title).toBe('Unit-Test Circle') + expect(learningPath.circles[1].title).toBe('Analyse') expect(learningPath.topics.length).toBe(2) }) diff --git a/client/src/services/__tests__/learning_path_json.json b/client/src/services/__tests__/learning_path_json.json index 97136646..ea5d2cb3 100644 --- a/client/src/services/__tests__/learning_path_json.json +++ b/client/src/services/__tests__/learning_path_json.json @@ -1,314 +1,297 @@ { - "id": 409, - "title": "Unit-Test Lernpfad", - "slug": "unit-test-lernpfad", + "id": 372, + "title": "Test Lernpfad", + "slug": "test-lehrgang-lp", "type": "learnpath.LearningPath", - "translation_key": "9f50de84-036c-4986-ab3e-1a83a374910a", + "translation_key": "42e559ca-970f-4a08-9e5e-63860585ee1e", "children": [ { - "id": 410, + "id": 373, "title": "Basis", - "slug": "basis-1", + "slug": "test-lehrgang-lp-topic-basis", "type": "learnpath.Topic", - "translation_key": "fbc1431c-46b0-4f77-93ee-4f10e0e59c03", + "translation_key": "d68c1544-cf22-4a59-a81c-8cb977440cd0", "is_visible": false }, { - "id": 411, + "id": 374, "title": "Basis", - "slug": "basis-2", + "slug": "test-lehrgang-lp-circle-basis", "type": "learnpath.Circle", - "translation_key": "d30cb8f8-6bb5-4e7a-8123-a370b7668a85", + "translation_key": "ec62a2af-6f74-4031-b971-c3287bbbc573", "children": [ { - "id": 412, + "id": 375, "title": "Starten", - "slug": "starten", + "slug": "test-lehrgang-lp-circle-basis-ls-starten", "type": "learnpath.LearningSequence", - "translation_key": "1c5cd2a1-a39e-496e-b856-342f34d2b21c", + "translation_key": "c5fdada9-036d-4516-a50f-6656a1c6b009", "icon": "it-icon-ls-start" }, { - "id": 413, - "title": "Einleitung Circle \"Basis\"", - "slug": "einleitung-circle-basis-1", + "id": 376, + "title": "Einf\u00fchrung", + "slug": "test-lehrgang-lp-circle-basis-lc-einf\u00fchrung", "type": "learnpath.LearningContent", - "translation_key": "48d4ace9-b0cf-4e23-98d2-012c1b91100e", + "translation_key": "01de5131-28ce-4b1f-805f-8643384bfd6b", "minutes": 15, "contents": [ { - "type": "video", + "type": "document", "value": { - "description": "Basis Video", - "url": "https://www.youtube.com/embed/qhPIfxS2hvI" + "description": "Beispiel Dokument", + "url": null }, - "id": "ee431ded-edc4-4984-9dd8-ab1d869d82ae" + "id": "bd05f721-3e9d-4a11-8fe2-7c04e2365f52" } ] }, { - "id": 414, + "id": 377, "title": "Beenden", - "slug": "beenden", + "slug": "test-lehrgang-lp-circle-basis-ls-beenden", "type": "learnpath.LearningSequence", - "translation_key": "eaeaf0c7-b2b7-41a9-a77f-b392f83291eb", + "translation_key": "128c0162-025f-41be-9842-60016a77cdbc", "icon": "it-icon-ls-end" }, { - "id": 415, - "title": "Kompetenzprofil anschauen", - "slug": "kompetenzprofil-anschauen-8", + "id": 378, + "title": "Jetzt kann es losgehen!", + "slug": "test-lehrgang-lp-circle-basis-lc-jetzt-kann-es-losgehen", "type": "learnpath.LearningContent", - "translation_key": "784772fc-d2ac-4df2-8ca1-61a45fbfe001", + "translation_key": "271896b9-6082-4fd4-9d70-6093ec9cc6ea", "minutes": 30, "contents": [ { "type": "document", "value": { - "description": "Beispiel Kompetenz" + "description": "Beispiel Dokument", + "url": null }, - "id": "09acb23d-cb20-4d0f-963b-61db9ac0b037" - } - ] - }, - { - "id": 416, - "title": "Circle \"Analyse\" abschliessen", - "slug": "circle-analyse-abschliessen-8", - "type": "learnpath.LearningContent", - "translation_key": "e1bf9081-cf6b-4426-a16d-8213aba9795e", - "minutes": 30, - "contents": [ - { - "type": "document", - "value": { - "description": "Beispiel Kompetenz" - }, - "id": "fa835da9-6238-40fb-a718-2d21d420926f" + "id": "204fc13b-a9ae-40de-8e09-f1e922c4fdd9" } ] } ], - "description": "Basis von Unit-Test Lernpfad", + "description": "Basis", "job_situations": [], "goals": [], "experts": [] }, { - "id": 417, - "title": "Gewinnen von Kunden", - "slug": "gewinnen-von-kunden-1", + "id": 379, + "title": "Beraten der Kunden", + "slug": "test-lehrgang-lp-topic-beraten-der-kunden", "type": "learnpath.Topic", - "translation_key": "4b2aa669-4cd9-43f1-9605-8575e5e7e760", + "translation_key": "91918780-75f8-4db3-8fb8-91b63f08b9b9", "is_visible": true }, { - "id": 418, - "title": "Unit-Test Circle", - "slug": "unit-test-circle", + "id": 380, + "title": "Analyse", + "slug": "test-lehrgang-lp-circle-analyse", "type": "learnpath.Circle", - "translation_key": "8433f8fe-7074-4c8a-a93a-b62e042f06ca", + "translation_key": "50f11be3-a56d-412d-be25-3d272fb5df40", "children": [ { - "id": 419, + "id": 381, "title": "Starten", - "slug": "starten", + "slug": "test-lehrgang-lp-circle-analyse-ls-starten", "type": "learnpath.LearningSequence", - "translation_key": "065ab931-122a-4e4d-a570-f8e6352a0550", + "translation_key": "07ac0eb9-3671-4b62-8053-1d0c43a1f0fb", "icon": "it-icon-ls-start" }, { - "id": 420, - "title": "Einleitung Circle \"Unit-Test Circle\"", - "slug": "einleitung-circle-unit-test-circle", + "id": 382, + "title": "Einleitung Circle \"Analyse\"", + "slug": "test-lehrgang-lp-circle-analyse-lc-einleitung-circle-analyse", "type": "learnpath.LearningContent", - "translation_key": "ec97ed44-a2ee-46b4-b6ba-3cce4c6f627e", + "translation_key": "00ed0ab2-fdb0-4ee6-a7d2-42a219b849a8", "minutes": 15, "contents": [ { - "type": "video", + "type": "document", "value": { - "description": "In dieser Circle zeigt dir ein Fachexperte anhand von Kundensituationen, wie du erfolgreichden Kundenbedarf ermitteln, analysieren, priorisieren und anschliessend zusammenfassen kannst.", - "url": "https://www.youtube.com/embed/qhPIfxS2hvI" + "description": "Beispiel Dokument", + "url": null }, - "id": "01ed1388-e82f-49a4-aafc-2d24891ec64a" + "id": "892a9a4a-8e1e-4f7e-8c35-9bf3bbe5371b" } ] }, { - "id": 421, + "id": 383, "title": "Beobachten", - "slug": "beobachten", + "slug": "test-lehrgang-lp-circle-analyse-ls-beobachten", "type": "learnpath.LearningSequence", - "translation_key": "8fed5f78-2d39-4a78-9dfc-f65551a81a7b", + "translation_key": "4cb08bc2-d101-43cc-b006-8f2bbb1a0579", "icon": "it-icon-ls-watch" }, { - "id": 422, - "title": "Absicherung der Familie", - "slug": "absicherung-der-familie", + "id": 384, + "title": "Fahrzeug", + "slug": "test-lehrgang-lp-circle-analyse-lu-fahrzeug", "type": "learnpath.LearningUnit", - "translation_key": "fe50e509-b679-40f8-bddf-844c473e1e8a", + "translation_key": "8f4afa40-c27e-48f7-a2d7-0e713479a55e", + "course_category": { + "id": 15, + "title": "Fahrzeug", + "general": false + }, "children": [ { - "id": 423, - "title": "Ich bin in der Lage, mit geeigneten Fragestellungen die Deckung von Versicherungen zu erfassen.", - "slug": "ich-bin-in-der-lage-mit-geeigneten-fragestellungen-die-deckung-von-versicherungen-zu-erfassen", - "type": "learnpath.LearningUnitQuestion", - "translation_key": "7a1631e9-56b2-48fd-b9ff-1eafba9f96da" + "id": 397, + "title": "Innerhalb des Handlungsfelds \u00abFahrzeug\u00bb bin ich f\u00e4hig, die Ziele und Pl\u00e4ne des Kunden zu ergr\u00fcnden (SOLL).", + "slug": "test-lehrgang-competence-crit-y13-fahrzeug", + "type": "competence.PerformanceCriteria", + "translation_key": "e9d49552-7d18-418a-94b6-ebb4ee6bf187", + "competence_id": "Y1.3" }, { - "id": 424, - "title": "Zweite passende Frage zu 'Absicherung der Familie'", - "slug": "zweite-passende-frage-zu-absicherung-der-familie", - "type": "learnpath.LearningUnitQuestion", - "translation_key": "f5aea045-f428-4b06-8b51-1857626250a8" + "id": 398, + "title": "Innerhalb des Handlungsfelds \u00abFahrzeug\u00bb bin ich f\u00e4hig, die IST-Situation des Kunden mit der geeigneten Gespr\u00e4chs-/Fragetechnik zu erfassen.", + "slug": "test-lehrgang-competence-crit-y21-fahrzeug", + "type": "competence.PerformanceCriteria", + "translation_key": "5f257b35-c6ca-49e4-9401-a5d02d53926d", + "competence_id": "Y2.1" } ] }, { - "id": 425, - "title": "Ermittlung des Kundenbedarfs", - "slug": "ermittlung-des-kundenbedarfs-14", + "id": 385, + "title": "Rafael Fasel wechselt sein Auto", + "slug": "test-lehrgang-lp-circle-analyse-lc-rafael-fasel-wechselt-sein-auto", "type": "learnpath.LearningContent", - "translation_key": "ffd613f5-830c-4bc0-860b-fc194e2d7d1c", + "translation_key": "fda4f870-9307-414d-b07f-eea607a9afb7", "minutes": 30, "contents": [ { - "type": "podcast", + "type": "online_training", "value": { - "description": "Die Ermittlung des Kundenbedarfs muss in einem eingehenden Gespr\u00e4ch herausgefunden werden. H\u00f6re dazu auch diesen Podcast an.", - "url": "https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/325190984&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true" + "description": "In diesem Online-Training lernst du, wie du den Kundenbedarf ermittelst.", + "url": "" }, - "id": "642c0906-3bd3-4030-be3f-8b1acce08930" + "id": "700a0f64-0892-4fa5-9e08-3bd34e99edeb" } ] }, { - "id": 426, - "title": "Kundenbed\u00fcrfnisse erkennen", - "slug": "kundenbed\u00fcrfnisse-erkennen-7", + "id": 386, + "title": "Fachcheck Fahrzeug", + "slug": "test-lehrgang-lp-circle-analyse-lc-fachcheck-fahrzeug", "type": "learnpath.LearningContent", - "translation_key": "b36bd615-053c-4054-a5be-080005140a98", + "translation_key": "dce0847f-4593-4bba-bd0c-a09c71eb0344", "minutes": 30, "contents": [ { - "type": "competence", + "type": "test", "value": { - "description": "Beispiel Kompetenz" + "description": "Beispiel Test", + "url": null }, - "id": "6b85361b-cc27-4454-aa20-72b31ad92a3f" + "id": "9f674aaa-ebf0-4a01-adcc-c0c46394fb10" } ] }, { - "id": 427, - "title": "Was braucht eine Familie?", - "slug": "was-braucht-eine-familie-7", + "id": 387, + "title": "Reisen", + "slug": "test-lehrgang-lp-circle-analyse-lu-reisen", + "type": "learnpath.LearningUnit", + "translation_key": "c3f6d33f-8dbc-4d88-9a81-3c602c4f9cc8", + "course_category": { + "id": 16, + "title": "Reisen", + "general": false + }, + "children": [ + { + "id": 399, + "title": "Innerhalb des Handlungsfelds \u00abReisen\u00bb bin ich f\u00e4hig, die Ziele und Pl\u00e4ne des Kunden zu ergr\u00fcnden (SOLL).", + "slug": "test-lehrgang-competence-crit-y13-reisen", + "type": "competence.PerformanceCriteria", + "translation_key": "1e488b69-8a3e-4acc-9547-48c103e0d038", + "competence_id": "Y1.3" + } + ] + }, + { + "id": 388, + "title": "Reiseversicherung", + "slug": "test-lehrgang-lp-circle-analyse-lc-reiseversicherung", "type": "learnpath.LearningContent", - "translation_key": "b4d2ec6c-12b3-48bc-b159-f5b9e06637cf", - "minutes": 60, + "translation_key": "ff513aae-efe1-4974-b67f-7a292b8aef86", + "minutes": 240, "contents": [ { "type": "exercise", "value": { - "description": "Beispiel Aufgabe", - "url": "/static/media/web_based_trainings/story-01-a-01-patrizia-marco-sichern-sich-ab-einstieg/scormcontent/index.html" + "description": "Beispiel \u00dcbung", + "url": null }, - "id": "b7e661b1-9e39-4482-8b23-c24dad1ef648" + "id": "f35f213e-1a33-49fe-97c5-26e15161719f" } ] }, { - "id": 428, - "title": "Reisen", - "slug": "reisen", - "type": "learnpath.LearningUnit", - "translation_key": "07a52671-a50e-46fc-b685-947aadb3e4d4", - "children": [ - { - "id": 429, - "title": "Passende Frage zu \"Reisen\"", - "slug": "passende-frage-zu-reisen", - "type": "learnpath.LearningUnitQuestion", - "translation_key": "00491fd6-f1f5-4a52-b13d-0197bc875296" - } - ] - }, - { - "id": 430, - "title": "Reiseversicherung", - "slug": "reiseversicherung-7", + "id": 389, + "title": "Emma und Ayla campen durch Amerika", + "slug": "test-lehrgang-lp-circle-analyse-lc-emma-und-ayla-campen-durch-amerika", "type": "learnpath.LearningContent", - "translation_key": "08dacac1-1853-4e07-8a6d-b7e2ee610398", - "minutes": 240, - "contents": [ - { - "type": "competence", - "value": { - "description": "Beispiel Kompetenz" - }, - "id": "6532e206-8737-45d9-9c2a-3ad44c372449" - } - ] - }, - { - "id": 431, - "title": "Sorgenfrei reisen", - "slug": "sorgenfrei-reisen-7", - "type": "learnpath.LearningContent", - "translation_key": "d8e9ec02-cae6-4494-91e0-707591456afb", + "translation_key": "a77b0f9d-9a70-47bd-8e62-7580d70a4306", "minutes": 120, "contents": [ { "type": "exercise", "value": { - "description": "Beispiel Aufgabe", + "description": "Beispiel \u00dcbung", "url": "/static/media/web_based_trainings/story-06-a-01-emma-und-ayla-campen-durch-amerika-einstieg/scormcontent/index.html" }, - "id": "87333833-ad07-4c86-a846-46232668e8e1" + "id": "60f087ff-fa3a-4da2-820f-4fcdf449f70d" } ] }, { - "id": 432, + "id": 390, "title": "Beenden", - "slug": "beenden", + "slug": "test-lehrgang-lp-circle-analyse-ls-beenden", "type": "learnpath.LearningSequence", - "translation_key": "a3ee459e-ab98-483f-95c9-ba85eb10c105", + "translation_key": "06f1e998-b827-41cc-8129-d72d731719c1", "icon": "it-icon-ls-end" }, { - "id": 433, + "id": 391, "title": "Kompetenzprofil anschauen", - "slug": "kompetenzprofil-anschauen-9", + "slug": "test-lehrgang-lp-circle-analyse-lc-kompetenzprofil-anschauen", "type": "learnpath.LearningContent", - "translation_key": "0e16dd46-14cf-43ac-888f-f03beded7fa1", + "translation_key": "6cc47dc1-a74f-4cbf-afa6-23885891c82f", "minutes": 30, "contents": [ { "type": "document", "value": { - "description": "Beispiel Kompetenz" + "description": "Beispiel Dokument", + "url": null }, - "id": "4b729c72-aee8-4944-b5fb-d0bfd317a339" + "id": "3f685055-4e3e-4ca9-93af-bac19236931d" } ] }, { - "id": 434, + "id": 392, "title": "Circle \"Analyse\" abschliessen", - "slug": "circle-analyse-abschliessen-9", + "slug": "test-lehrgang-lp-circle-analyse-lc-circle-analyse-abschliessen", "type": "learnpath.LearningContent", - "translation_key": "53703784-c71f-4bad-a3e7-e014f0fded12", + "translation_key": "9b32e2cd-1368-4885-a79b-906b45ba04bc", "minutes": 30, "contents": [ { "type": "document", "value": { - "description": "Beispiel Kompetenz" + "description": "Beispiel Dokument", + "url": null }, - "id": "8bc53dfd-bb9b-4ae5-bd3c-74b7eef0eafd" + "id": "650b7b15-b522-4df7-ac5b-6a654f12334f" } ] } @@ -317,25 +300,25 @@ "job_situations": [ { "type": "job_situation", - "value": "Absicherung der Familie", - "id": "f715a46f-53df-4205-8257-30cff62f337c" + "value": "Autoversicherung", + "id": "c5a6b365-0a18-47d5-b6e1-6cb8b8ec7d35" }, { "type": "job_situation", - "value": "Reisen", - "id": "f2174789-eab4-4059-961d-699b3c333110" + "value": "Autokauf", + "id": "e969d2a2-b383-482c-a721-88552af086a6" } ], "goals": [ { "type": "goal", "value": "... die heutige Versicherungssituation von Privat- oder Gesch\u00e4ftskunden einzusch\u00e4tzen.", - "id": "41acaebc-38de-4929-a4af-aaed43a1e5f3" + "id": "d9ad8aed-d7d6-42c7-b6d4-65102c8ddf10" }, { "type": "goal", "value": "... deinem Kunden seine optimale L\u00f6sung aufzuzeigen", - "id": "cb1d556b-dac1-4edc-a3e5-97307b49c55c" + "id": "2506950c-45cb-474f-acb9-45e83e9ebe1b" } ], "experts": [ @@ -348,9 +331,14 @@ "photo": null, "biography": "" }, - "id": "479878e7-2d30-46a4-8d6b-bfe77268bbae" + "id": "b7b0ff2e-f840-4d74-99c1-c7a5ee6dc14e" } ] } - ] -} + ], + "course": { + "id": -1, + "title": "Test Lerngang", + "category_name": "Handlungsfeld" + } +} \ No newline at end of file diff --git a/client/src/services/__tests__/request_learning_path_json.py b/client/src/services/__tests__/request_learning_path_json.py index 023dcf9b..dfd4b62d 100644 --- a/client/src/services/__tests__/request_learning_path_json.py +++ b/client/src/services/__tests__/request_learning_path_json.py @@ -16,7 +16,7 @@ def main(): ) response = client.get( - 'http://localhost:8000/api/learnpath/page/unit-test-lernpfad/', + 'http://localhost:8000/api/course/page/test-lehrgang-lp/', ) print(response.status_code) print(response.json()) diff --git a/client/src/services/circle.ts b/client/src/services/circle.ts index abb767cb..5b46e33c 100644 --- a/client/src/services/circle.ts +++ b/client/src/services/circle.ts @@ -1,13 +1,14 @@ import type { CircleChild, - CircleCompletion, CircleGoal, CircleJobSituation, + CourseCompletion, + CourseCompletionStatus, + CourseWagtailPage, LearningContent, LearningSequence, LearningUnit, LearningUnitQuestion, - LearningWagtailPage, } from '@/types' import type { LearningPath } from '@/services/learningPath' @@ -23,6 +24,7 @@ function _createEmptyLearningUnit(parentLearningSequence: LearningSequence): Lea parentLearningSequence: parentLearningSequence, children: [], last: true, + completion_status: 'unknown', } } @@ -109,10 +111,10 @@ export function parseLearningSequences (circle: Circle, children: CircleChild[]) return result; } -export class Circle implements LearningWagtailPage { +export class Circle implements CourseWagtailPage { readonly type = 'learnpath.Circle'; readonly learningSequences: LearningSequence[]; - readonly completed: boolean; + completion_status: CourseCompletionStatus = 'unknown' nextCircle?: Circle; previousCircle?: Circle; @@ -129,7 +131,6 @@ export class Circle implements LearningWagtailPage { public readonly parentLearningPath?: LearningPath, ) { this.learningSequences = parseLearningSequences(this, this.children); - this.completed = false; } public static fromJson(json: any, learningPath?: LearningPath): Circle { @@ -187,7 +188,7 @@ export class Circle implements LearningWagtailPage { public someFinishedInLearningSequence(translationKey: string): boolean { if (translationKey) { return this.flatChildren.filter((lc) => { - return lc.completed && lc.parentLearningSequence?.translation_key === translationKey; + return lc.completion_status === 'success' && lc.parentLearningSequence?.translation_key === translationKey; }).length > 0; } @@ -197,7 +198,7 @@ export class Circle implements LearningWagtailPage { public allFinishedInLearningSequence(translationKey: string): boolean { if (translationKey) { const finishedContents = this.flatChildren.filter((lc) => { - return lc.completed && lc.parentLearningSequence?.translation_key === translationKey; + return lc.completion_status === 'success' && lc.parentLearningSequence?.translation_key === translationKey; }).length; const totalContents = this.flatChildren.filter((lc) => { @@ -209,15 +210,15 @@ export class Circle implements LearningWagtailPage { return false; } - public parseCompletionData(completionData: CircleCompletion[]) { + public parseCompletionData(completionData: CourseCompletion[]) { this.flatChildren.forEach((page) => { const pageIndex = completionData.findIndex((e) => { return e.page_key === page.translation_key; }); if (pageIndex >= 0) { - page.completed = completionData[pageIndex].completed; + page.completion_status = completionData[pageIndex].completion_status; } else { - page.completed = undefined; + page.completion_status = 'unknown'; } }); diff --git a/client/src/services/learningPath.ts b/client/src/services/learningPath.ts index c3b38fa4..e595dc0d 100644 --- a/client/src/services/learningPath.ts +++ b/client/src/services/learningPath.ts @@ -1,22 +1,30 @@ import * as _ from 'lodash' -import type { CircleCompletion, LearningContent, LearningPathChild, LearningWagtailPage, Topic } from '@/types' +import type { + CourseCompletion, + CourseCompletionStatus, + CourseWagtailPage, + LearningContent, + LearningPathChild, + Topic, +} from '@/types' import { Circle } from '@/services/circle' -function getLastCompleted(learningPathKey: string, completionData: CircleCompletion[]) { - return _.orderBy(completionData, ['updated_at'], 'desc').find((c: CircleCompletion) => { - return c.completed && c.learning_path_key === learningPathKey && c.page_type === 'learnpath.LearningContent' +function getLastCompleted(courseId: number, completionData: CourseCompletion[]) { + return _.orderBy(completionData, ['updated_at'], 'desc').find((c: CourseCompletion) => { + return c.completion_status === 'success' && c.course === courseId && c.page_type === 'learnpath.LearningContent' }) } -export class LearningPath implements LearningWagtailPage { +export class LearningPath implements CourseWagtailPage { readonly type = 'learnpath.LearningPath' public topics: Topic[] public circles: Circle[] public nextLearningContent?: LearningContent + readonly completion_status: CourseCompletionStatus = 'unknown' - public static fromJson(json: any, completionData: CircleCompletion[]): LearningPath { - return new LearningPath(json.id, json.slug, json.title, json.translation_key, json.children, completionData) + public static fromJson(json: any, completionData: CourseCompletion[]): LearningPath { + return new LearningPath(json.id, json.slug, json.title, json.translation_key, json.course.id, json.children, completionData) } constructor( @@ -24,8 +32,9 @@ export class LearningPath implements LearningWagtailPage { public readonly slug: string, public readonly title: string, public readonly translation_key: string, + public readonly courseId: number, public children: LearningPathChild[], - completionData?: any + completionData?: CourseCompletion[] ) { // parse children this.topics = [] @@ -42,7 +51,9 @@ export class LearningPath implements LearningWagtailPage { } if (page.type === 'learnpath.Circle') { const circle = Circle.fromJson(page, this) - circle.parseCompletionData(completionData) + if (completionData) { + circle.parseCompletionData(completionData) + } if (topic) { topic.circles.push(circle) } @@ -59,17 +70,21 @@ export class LearningPath implements LearningWagtailPage { this.topics.push(topic) } - this.calcNextLearningContent(completionData) + if (completionData) { + this.calcNextLearningContent(completionData) + } } - public calcNextLearningContent(completionData: CircleCompletion[]): void { + public calcNextLearningContent(completionData: CourseCompletion[]): void { this.nextLearningContent = undefined - const lastCompletedLearningContent = getLastCompleted(this.translation_key, completionData) + const lastCompletedLearningContent = getLastCompleted(this.courseId, completionData) if (lastCompletedLearningContent) { const lastCircle = this.circles.find( - (circle) => circle.translation_key === lastCompletedLearningContent.circle_key + (circle) => { + return circle.flatLearningContents.find((learningContent) => learningContent.translation_key === lastCompletedLearningContent.page_key) + } ) if (lastCircle) { const lastLearningContent = lastCircle.flatLearningContents.find( diff --git a/client/src/stores/circle.ts b/client/src/stores/circle.ts index 9fff1755..e44235c8 100644 --- a/client/src/stores/circle.ts +++ b/client/src/stores/circle.ts @@ -2,13 +2,14 @@ import * as log from 'loglevel' import { defineStore } from 'pinia' -import type { LearningContent, LearningUnit, LearningUnitQuestion } from '@/types' +import type { CourseCompletionStatus, LearningContent, LearningUnit, LearningUnitQuestion } from '@/types' import type { Circle } from '@/services/circle' import { itPost } from '@/fetchHelpers' import { useLearningPathStore } from '@/stores/learningPath' export type CircleStoreState = { circle: Circle | undefined + page: 'INDEX' | 'OVERVIEW' } export const useCircleStore = defineStore({ @@ -16,6 +17,7 @@ export const useCircleStore = defineStore({ state: () => { return { circle: undefined, + page: 'INDEX', } as CircleStoreState; }, getters: { @@ -61,12 +63,12 @@ export const useCircleStore = defineStore({ return learningUnit }, - async markCompletion(page: LearningContent | LearningUnitQuestion, flag = true) { + async markCompletion(page: LearningContent | LearningUnitQuestion, completion_status:CourseCompletionStatus='success') { try { - page.completed = flag; - const completionData = await itPost('/api/completion/circle/mark/', { + page.completion_status = completion_status; + const completionData = await itPost('/api/course/completion/mark/', { page_key: page.translation_key, - completed: page.completed, + completion_status: page.completion_status, }); if (this.circle) { this.circle.parseCompletionData(completionData); @@ -100,10 +102,10 @@ export const useCircleStore = defineStore({ }, calcSelfEvaluationStatus(learningUnit: LearningUnit) { if (learningUnit.children.length > 0) { - if (learningUnit.children.every((q) => q.completed)) { + if (learningUnit.children.every((q) => q.completion_status === 'success')) { return true; } - if (learningUnit.children.some((q) => q.completed !== undefined)) { + if (learningUnit.children.some((q) => q.completion_status === 'fail')) { return false; } } @@ -111,7 +113,7 @@ export const useCircleStore = defineStore({ }, continueFromLearningContent(currentLearningContent: LearningContent) { if (currentLearningContent) { - this.markCompletion(currentLearningContent, true); + this.markCompletion(currentLearningContent, 'success'); const nextLearningContent = currentLearningContent.nextLearningContent; const currentParent = currentLearningContent.parentLearningUnit; diff --git a/client/src/stores/learningPath.ts b/client/src/stores/learningPath.ts index b2e3b598..778c25c8 100644 --- a/client/src/stores/learningPath.ts +++ b/client/src/stores/learningPath.ts @@ -4,6 +4,7 @@ import { LearningPath } from '@/services/learningPath' export type LearningPathStoreState = { learningPath: LearningPath | undefined + page: 'INDEX' | 'OVERVIEW' } export const useLearningPathStore = defineStore({ @@ -11,6 +12,7 @@ export const useLearningPathStore = defineStore({ state: () => { return { learningPath: undefined, + page: 'INDEX', } as LearningPathStoreState; }, getters: {}, @@ -19,8 +21,8 @@ export const useLearningPathStore = defineStore({ if (this.learningPath && !reload) { return this.learningPath; } - const learningPathData = await itGet(`/api/learnpath/page/${slug}/`); - const completionData = await itGet(`/api/completion/learning_path/${learningPathData.translation_key}/`); + const learningPathData = await itGet(`/api/course/page/${slug}/`); + const completionData = await itGet(`/api/course/completion/${learningPathData.course.id}/`); if (!learningPathData) { throw `No learning path found with: ${slug}`; diff --git a/client/src/stores/mediaCenter.ts b/client/src/stores/mediaCenter.ts new file mode 100644 index 00000000..6797b2d8 --- /dev/null +++ b/client/src/stores/mediaCenter.ts @@ -0,0 +1,39 @@ +import { defineStore } from 'pinia' +import { itGet } from '@/fetchHelpers' +import type { MediaLibraryPage } from '@/types' + +export type MediaCenterStoreState = { + mediaCenterPage: MediaLibraryPage | undefined + selectedLearningPath: { id: number; name: string } + availableLearningPaths: { id: number; name: string }[] +} + +export const useMediaCenterStore = defineStore({ + id: 'mediaCenter', + state: () => { + return { + mediaCenterPage: undefined, + selectedLearningPath: { id: 1, name: 'Alle Lehrgänge' }, + availableLearningPaths: [ + { id: 1, name: 'Alle Lehrgänge' }, + { id: 2, name: 'Versicherungsvermittler/in' }, + ], + } as MediaCenterStoreState + }, + getters: {}, + actions: { + async loadMediaCenterPage(slug: string, reload = false) { + if (this.mediaCenterPage && !reload) { + return this.mediaCenterPage + } + const mediaCenterPageData = await itGet(`/api/course/page/${slug}/`) + + if (!mediaCenterPageData) { + throw `No mediaCenterPageData found with: ${slug}` + } + + this.mediaCenterPage = mediaCenterPageData + return this.mediaCenterPage + }, + }, +}) diff --git a/client/src/types.ts b/client/src/types.ts index 949ec873..03d68ce4 100644 --- a/client/src/types.ts +++ b/client/src/types.ts @@ -1,8 +1,17 @@ import type { Circle } from '@/services/circle' -export type LearningContentType = 'assignment' | 'book' | 'document' | - 'exercise' | 'media_library' | 'online_training' | - 'resource' | 'test' | 'video'; +export type CourseCompletionStatus = 'unknown' | 'fail' | 'success' + +export type LearningContentType = + | 'assignment' + | 'book' + | 'document' + | 'exercise' + | 'media_library' + | 'online_training' + | 'resource' + | 'test' + | 'video' export interface LearningContentBlock { type: LearningContentType @@ -106,15 +115,15 @@ export interface CircleJobSituation { id: string; } -export interface LearningWagtailPage { +export interface CourseWagtailPage { readonly id: number; readonly title: string; readonly slug: string; readonly translation_key: string; - completed?: boolean; + completion_status: CourseCompletionStatus; } -export interface LearningContent extends LearningWagtailPage { +export interface LearningContent extends CourseWagtailPage { type: 'learnpath.LearningContent'; minutes: number; contents: (AssignmentBlock | BookBlock | DocumentBlock | ExerciseBlock | MediaLibraryBlock | OnlineTrainingBlock | ResourceBlock | TestBlock | VideoBlock)[]; @@ -125,13 +134,13 @@ export interface LearningContent extends LearningWagtailPage { previousLearningContent?: LearningContent; } -export interface LearningUnitQuestion extends LearningWagtailPage { +export interface LearningUnitQuestion extends CourseWagtailPage { type: 'learnpath.LearningUnitQuestion'; parentLearningSequence?: LearningSequence; parentLearningUnit?: LearningUnit; } -export interface LearningUnit extends LearningWagtailPage { +export interface LearningUnit extends CourseWagtailPage { type: 'learnpath.LearningUnit'; learningContents: LearningContent[]; minutes: number; @@ -140,7 +149,7 @@ export interface LearningUnit extends LearningWagtailPage { last?: boolean; } -export interface LearningSequence extends LearningWagtailPage { +export interface LearningSequence extends CourseWagtailPage { type: 'learnpath.LearningSequence'; icon: string; learningUnits: LearningUnit[]; @@ -149,13 +158,13 @@ export interface LearningSequence extends LearningWagtailPage { export type CircleChild = LearningContent | LearningUnit | LearningSequence | LearningUnitQuestion; -export interface WagtailCircle extends LearningWagtailPage { +export interface WagtailCircle extends CourseWagtailPage { type: 'learnpath.Circle'; children: CircleChild[]; description: string; } -export interface Topic extends LearningWagtailPage { +export interface Topic extends CourseWagtailPage { type: 'learnpath.Topic'; is_visible: boolean; circles: Circle[]; @@ -163,17 +172,17 @@ export interface Topic extends LearningWagtailPage { export type LearningPathChild = Topic | WagtailCircle; -export interface CircleCompletion { +export interface CourseCompletion { id: number; created_at: string; updated_at: string; user: number; page_key: string; page_type: string; - circle_key: string; - learning_path_key: string; - completed: boolean; - json_data: any; + page_slug: string; + course: number; + completion_status: CourseCompletionStatus; + additional_json_data: any; } export interface CircleDiagramData { @@ -186,3 +195,62 @@ export interface CircleDiagramData { arrowEndAngle: number done: boolean } + + +export interface Course { + id: number; + name: string; + category_name: string; +} + +export interface CourseCategory { + id: number; + name: string; + general: boolean; +} + +export interface MediaDocument { + type: "Documents"; + value: number; + id: string; +} + +export interface MediaLink { + type: "Links"; + id: string; + value: { + title: string; + description: string; + link_display_text: string; + url: string; + } +} + +export interface MediaContentCollection { + type: "content_collection"; + value: { + title: string; + contents: (MediaDocument | MediaLink)[]; + } +} + +export interface MediaCategoryPage extends CourseWagtailPage { + type: 'media_library.MediaCategoryPage'; + overview_icon: string; + introduction_text: string; + description_title: string; + description_text: string; + items: { + type: 'item'; + value: string; + id: string; + } + course_category: CourseCategory; + body: MediaContentCollection[]; +} + +export interface MediaLibraryPage extends CourseWagtailPage { + type: 'media_library.MediaLibraryPage'; + course: Course; + children: MediaCategoryPage[]; +} diff --git a/client/src/views/CircleView.vue b/client/src/views/CircleView.vue index 88aed09e..63b72a79 100644 --- a/client/src/views/CircleView.vue +++ b/client/src/views/CircleView.vue @@ -3,7 +3,6 @@ import * as log from 'loglevel' import LearningSequence from '@/components/circle/LearningSequence.vue' import CircleOverview from '@/components/circle/CircleOverview.vue' import CircleDiagram from '@/components/circle/CircleDiagram.vue' -import LearningContent from '@/components/circle/LearningContent.vue' import { computed, onMounted } from 'vue' import { useCircleStore } from '@/stores/circle' @@ -65,10 +64,7 @@ onMounted(async () => { /> -
- -
-
+
diff --git a/client/src/views/CockpitView.vue b/client/src/views/CockpitView.vue index 66eced16..cb1bcf74 100644 --- a/client/src/views/CockpitView.vue +++ b/client/src/views/CockpitView.vue @@ -16,7 +16,7 @@ const userStore = useUserStore()

Versicherungsvermittler/in

- Weiter geht's + Weiter geht's
diff --git a/client/src/views/HandlungsfeldLayout.vue b/client/src/views/HandlungsfeldLayout.vue new file mode 100644 index 00000000..9c5ca177 --- /dev/null +++ b/client/src/views/HandlungsfeldLayout.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/client/src/views/LearningContentView.vue b/client/src/views/LearningContentView.vue index 17af144b..8def7bc6 100644 --- a/client/src/views/LearningContentView.vue +++ b/client/src/views/LearningContentView.vue @@ -4,7 +4,7 @@ import { onMounted, reactive, watch } from 'vue' import { useCircleStore } from '@/stores/circle' import { useAppStore } from '@/stores/app' import LearningContent from '@/components/circle/LearningContent.vue' -import { LearningContent as LearningContentType } from '@/types' +import type { LearningContent as LearningContentType } from '@/types' log.debug('LearningContentView created') diff --git a/client/src/views/LearningPathView.vue b/client/src/views/LearningPathView.vue index 902856ba..90f9717e 100644 --- a/client/src/views/LearningPathView.vue +++ b/client/src/views/LearningPathView.vue @@ -7,7 +7,7 @@ import { useUserStore } from '@/stores/user' import LearningPathDiagram from '@/components/circle/LearningPathDiagram.vue' import LearningPathViewVertical from '@/views/LearningPathViewVertical.vue' -import { LearningPath } from '@/services/learningPath' +import type { LearningPath } from '@/services/learningPath' log.debug('LearningPathView created') @@ -28,7 +28,7 @@ onMounted(async () => { } }) -const createContinueUrl = (learningPath: LearningPath) => { +const createContinueUrl = (learningPath: LearningPath): [string, boolean] => { if (learningPath.nextLearningContent) { const circle = learningPath.nextLearningContent.parentCircle const lsShortSlug = learningPath.nextLearningContent.parentLearningSequence?.slug.replace(`${circle.slug}-`, '') @@ -77,14 +77,14 @@ const createContinueUrl = (learningPath: LearningPath) => { class="bg-white m-6 lg:m-12 p-8 flex flex-col lg:flex-row divide-y lg:divide-y-0 lg:divide-x divide-gray-500 justify-start" >
-

Willkommmen zurück, {{ userStore.first_name }}

+

Willkommmen zurück, {{ userStore.first_name }}

-
+
Nächster Schritt

{{ learningPathStore.learningPath.nextLearningContent.parentCircle.title }}: - {{ learningPathStore.learningPath.nextLearningContent.parentLearningSequence.title }} + {{ learningPathStore.learningPath.nextLearningContent.parentLearningSequence?.title }}

+import * as log from 'loglevel' +import LinkCard from '@/components/mediaCenter/LinkCard.vue' +import HandlungsfeldLayout from '@/views/HandlungsfeldLayout.vue' +import MediaLink from '@/components/mediaCenter/MediaLink.vue' +import { useMediaCenterStore } from '@/stores/mediaCenter' +import { computed } from 'vue' + +const field = { + title: 'Fahrzeug', + description: + 'Das Auto ist für viele der grösste Stolz! Es birgt aber auch ein grosses Gefahrenpotenzial. Dabei geht es bei den heutigen Fahrzeugpreisen und Reparaturkosten rasch um namhafte Summen, die der Fahrzeugbesitzer und die Fahrzeugbesitzerin in einem grösseren Schadenfall oft nur schwer selbst aufbringen kann.', + icon: '/static/icons/demo/icon-hf-fahrzeug-big.svg', + summary: { + text: 'In diesem berufstypischem Handlungsfeld lernst du alles rund um Motorfahrzeugversicherungen, wie man sein Auto optimal schützen kann, wie du vorgehst bei einem Fahrzeugwechsel, welche Aspekte du bei einer Offerte beachten musst und wie du dem Kunden die Lösung präsentierst.', + items: ['Motorfahrzeughaftpflichtversicherung', 'Motorfahrzeugkaskoversicherung', 'Insassenunfallversicherung'], + }, + items: [ + { + title: 'Lernmedien', + type: 'learnmedia', + moreLink: '', + items: [ + { + title: 'Die Motorfahrzeughaftpflicht', + description: 'Buch «Sach- und Vermögensversicherungen» – Kapitel 16', + iconUrl: '/static/icons/demo/icon-hf-book.png', + linkText: 'PDF anzeigen', + link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf', + openWindow: true, + }, + { + title: 'Die Motorfahrzeughaftpflicht', + iconUrl: '/static/icons/demo/icon-hf-book.png', + description: 'Buch «Sach- und Vermögensversicherungen» – Kapitel 16', + linkText: 'PDF anzeigen', + link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf', + openWindow: true, + }, + { + title: 'Die Motorfahrzeughaftpflicht', + iconUrl: '/static/icons/demo/icon-hf-book.png', + description: 'Buch «Sach- und Vermögensversicherungen» – Kapitel 16', + linkText: 'PDF anzeigen', + link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf', + openWindow: true, + }, + { + title: 'Die Motorfahrzeughaftpflicht', + iconUrl: '/static/icons/demo/icon-hf-book.png', + description: 'Buch «Sach- und Vermögensversicherungen» – Kapitel 16', + linkText: 'PDF anzeigen', + link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf', + openWindow: true, + }, + { + title: 'Die Motorfahrzeughaftpflicht', + iconUrl: '/static/icons/demo/icon-hf-book.png', + description: 'Buch «Sach- und Vermögensversicherungen» – Kapitel 16', + linkText: 'PDF anzeigen', + link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf', + openWindow: true, + }, + ], + }, + { + title: 'Links', + type: 'externalLinks', + moreLink: '', + items: [ + { + title: 'Nationales Versicherungsbüro', + iconUrl: '', + description: '', + linkText: 'Link öffnen', + link: 'https://www.nbi-ngf.ch/h', + openWindow: true, + }, + { + title: 'Adressen der Strassenverkehrsämter', + iconUrl: '', + description: '', + linkText: 'Link öffnen', + link: 'https://asa.ch/strassenverkehrsaemter/adressen/', + openWindow: true, + }, + ], + }, + { + title: 'Verankerung im Lernpfad', + type: 'internalLinks', + moreLink: '', + items: [ + { + title: 'Circle: Einstieg – Lernsequenz: Anwenden', + iconUrl: '', + description: '', + linkText: 'Lerineinheit anzeigen', + link: 'http://localhost:8000/learn/versicherungsvermittlerin/versicherungsvermittlerin-circle-analyse', + openWindow: false, + }, + { + title: 'Circle: Einstieg – Lernsequenz: Anwenden', + iconUrl: '', + description: '', + linkText: 'Lerineinheit anzeigen', + link: 'http://localhost:8000/learn/versicherungsvermittlerin/versicherungsvermittlerin-circle-analyse', + openWindow: false, + }, + { + title: 'Circle: Einstieg – Lernsequenz: Anwenden', + iconUrl: '', + description: '', + linkText: 'Lerineinheit anzeigen', + link: 'http://localhost:8000/learn/versicherungsvermittlerin/versicherungsvermittlerin-circle-analyse', + openWindow: false, + }, + { + title: 'Circle: Einstieg – Lernsequenz: Anwenden', + iconUrl: '', + description: '', + linkText: 'Lerineinheit anzeigen', + link: 'http://localhost:8000/learn/versicherungsvermittlerin/versicherungsvermittlerin-circle-analyse', + openWindow: false, + }, + ], + }, + { + title: 'Querverweise', + type: 'realtiveLinks', + moreLink: '', + items: [ + { + title: 'Rechtsstreigkeiten', + iconUrl: '/static/icons/demo/icon-hf-einkommenssicherung.svg', + description: 'Lernmedium: Verkehrsrechtsschutz – Buch «Sach- und Vermögensversicherungen/Kapitel 12.3»', + linkText: 'Handlungsfeldanzeigen', + link: 'http://localhost:8000/mediacenter/handlungsfeld', + openWindow: false, + }, + { + title: 'Rechtsstreigkeiten', + iconUrl: '/static/icons/demo/icon-hf-einkommenssicherung.svg', + description: 'Lernmedium: Verkehrsrechtsschutz – Buch «Sach- und Vermögensversicherungen/Kapitel 12.3»', + linkText: 'Handlungsfeldanzeigen', + link: 'http://localhost:8000/mediacenter/handlungsfeld', + openWindow: false, + }, + ], + }, + ], +} + +const props = defineProps<{ + mediaCategorySlug: string +}>() + +log.debug('MediaCategoryDetailView created', props.mediaCategorySlug) + +const mediaStore = useMediaCenterStore() + +const mediaCategory = computed(() => { + return mediaStore.mediaCenterPage?.children.find((category) => category.slug === props.mediaCategorySlug) +}) + +const maxCardItems = 4 +const maxListItems = 6 + +const displayAsCard = (itemType: string): boolean => { + return itemType === 'learnmedia' || itemType === 'realtiveLinks' +} + +const hasMoreItems = (items: object[], maxItems: number): boolean => { + return items.length > maxItems +} + +const getMaxDisplayItems = (items: object[], maxItems: number) => { + return items.slice(0, maxItems) +} + +const getMaxDisplayItemsForType = (itemType: string, items: object[]) => { + return displayAsCard(itemType) ? getMaxDisplayItems(items, maxCardItems) : getMaxDisplayItems(items, maxListItems) +} + +const hasMoreItemsForType = (itemType: string, items: object[]) => { + const maxItems = displayAsCard(itemType) ? maxCardItems : maxListItems + return hasMoreItems(items, maxItems) +} + + + + + diff --git a/client/src/views/MediaCenterCategoryOverview.vue b/client/src/views/MediaCenterCategoryOverview.vue new file mode 100644 index 00000000..b47cc0ed --- /dev/null +++ b/client/src/views/MediaCenterCategoryOverview.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/client/src/views/MediaCenterMainView.vue b/client/src/views/MediaCenterMainView.vue new file mode 100644 index 00000000..1e8ff969 --- /dev/null +++ b/client/src/views/MediaCenterMainView.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/client/src/views/MediaCenterView.vue b/client/src/views/MediaCenterView.vue new file mode 100644 index 00000000..d32c7697 --- /dev/null +++ b/client/src/views/MediaCenterView.vue @@ -0,0 +1,42 @@ + + + + + diff --git a/client/src/views/MediaList.vue b/client/src/views/MediaList.vue new file mode 100644 index 00000000..364f149f --- /dev/null +++ b/client/src/views/MediaList.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/client/src/views/MediaView.vue b/client/src/views/MediaView.vue deleted file mode 100644 index 6439a274..00000000 --- a/client/src/views/MediaView.vue +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/client/src/views/StyleGuideView.vue b/client/src/views/StyleGuideView.vue index 3cbd7786..6c7eab0d 100644 --- a/client/src/views/StyleGuideView.vue +++ b/client/src/views/StyleGuideView.vue @@ -1,10 +1,10 @@