Take MediaCategoryDetail data from api

This commit is contained in:
Daniel Egger 2022-09-23 17:47:19 +02:00
parent 18c3e28ba1
commit 5667921518
12 changed files with 288 additions and 261 deletions

View File

@ -162,7 +162,7 @@ const profileDropdownData = [
Shop Shop
</router-link> </router-link>
<router-link <router-link
to="/mediacenter/overview" to="/mediacenter/versicherungsvermittlerin-media/overview"
class="nav-item" class="nav-item"
:class="{ 'nav-item--active': isInRoutePath(['/mediacenter']) }" :class="{ 'nav-item--active': isInRoutePath(['/mediacenter']) }"
> >

View File

@ -31,15 +31,16 @@ const router = createRouter({
children: [ children: [
{ {
path: 'overview', path: 'overview',
component: () => import('@/views/MediaMainView.vue'), component: () => import('@/views/MediaCenterMainView.vue'),
},
{
path: 'handlungsfelder/:mediaCategorySlug',
props: true,
component: () => import('@/views/MediaCategoryDetailView.vue'),
}, },
{ {
path: 'handlungsfelder', path: 'handlungsfelder',
component: () => import('@/views/HandlungsfelderOverview.vue'), component: () => import('@/views/MediaCenterCategoryOverview.vue'),
},
{
path: 'handlungsfeld',
component: () => import('@/views/Handlungsfeld.vue'),
}, },
{ {
path: 'handlungsfeldlist', path: 'handlungsfeldlist',

View File

@ -168,8 +168,15 @@ export interface MediaContentCollection {
export interface MediaCategoryPage extends CourseWagtailPage { export interface MediaCategoryPage extends CourseWagtailPage {
type: 'media_library.MediaCategoryPage'; type: 'media_library.MediaCategoryPage';
overview_icon: string;
introduction_text: string; introduction_text: string;
description: string; description_title: string;
description_text: string;
items: {
type: 'item';
value: string;
id: string;
}
course_category: CourseCategory; course_category: CourseCategory;
body: MediaContentCollection[]; body: MediaContentCollection[];
} }

View File

@ -1,104 +0,0 @@
<script setup lang="ts">
import * as log from 'loglevel';
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
import {reactive, ref, watch} from "vue";
import {useMediaCenterStore} from "@/stores/mediaCenter";
log.debug('HandlungsfelderOverview created');
const fields = [
{
name: 'Fahrzeug',
icon: 'icon-hf-fahrzeug'
},
{
name: 'Reisen',
icon: 'icon-hf-reisen'
},
{
name: 'Einkommenssicherung',
icon: 'icon-hf-einkommenssicherung'
},
{
name: 'Gesundheit',
icon: 'icon-hf-fahrzeug'
},
{
name: 'Haushalt',
icon: 'icon-hf-reisen'
},
{
name: 'Sparen',
icon: 'icon-hf-einkommenssicherung'
},
{
name: 'Pensionierung',
icon: 'icon-hf-fahrzeug'
},
{
name: 'KMU',
icon: 'icon-hf-reisen'
},
{
name: 'Wohneigentum',
icon: 'icon-hf-einkommenssicherung'
},
{
name: 'Rechtsstreitigkeiten',
icon: 'icon-hf-fahrzeug'
},
{
name: 'Erben / Vererben',
icon: 'icon-hf-reisen'
},
{
name: 'Selbstständigkeit',
icon: 'icon-hf-einkommenssicherung'
},
]
const mediaStore = useMediaCenterStore();
const dropdownSelected = ref(mediaStore.selectedLearningPath);
watch(dropdownSelected, (newValue) => mediaStore.$patch({
selectedLearningPath: newValue
})
)
</script>
<template>
<div class="mx-auto max-w-5xl">
<div class="flex flex-col lg:flex-row items-center justify-between mb-10">
<h1>Handlungsfelder</h1>
<ItDropdownSelect
v-model="dropdownSelected"
:items="mediaStore.availableLearningPaths"></ItDropdownSelect>
</div>
<div>
<ul class="grid gap-5 grid-cols-1 lg:grid-cols-4">
<li
class="bg-white p-4 w-58"
v-for="field in fields"
:key="field.name"
>
<router-link to="/mediacenter/handlungsfeld">
<img
class="m-auto"
:src="`/static/icons/demo/${field.icon}.svg`"/>
<h3 class="text-base text-center">{{field.name}}</h3>
</router-link>
</li>
</ul>
</div>
</div>
</template>
<style scoped>
.it-icon-hf > * {
@apply m-auto;
}
</style>

View File

@ -1,22 +1,19 @@
<script setup lang="ts"> <script setup lang="ts">
import * as log from 'loglevel'; import * as log from 'loglevel'
import LinkCard from "@/components/mediacenter/LinkCard.vue"; import LinkCard from '@/components/mediacenter/LinkCard.vue'
import HandlungsfeldLayout from "@/views/HandlungsfeldLayout.vue"; import HandlungsfeldLayout from '@/views/HandlungsfeldLayout.vue'
import MediaLink from "@/components/mediacenter/MediaLink.vue"; import MediaLink from '@/components/mediacenter/MediaLink.vue'
import { useMediaCenterStore } from '@/stores/mediaCenter'
log.debug('Handlungsfeld created'); import { computed } from 'vue'
const field = { const field = {
title: 'Fahrzeug', 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.', 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', icon: '/static/icons/demo/icon-hf-fahrzeug-big.svg',
summary: { 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.', 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: [ items: ['Motorfahrzeughaftpflichtversicherung', 'Motorfahrzeugkaskoversicherung', 'Insassenunfallversicherung'],
'Motorfahrzeughaftpflichtversicherung',
'Motorfahrzeugkaskoversicherung',
'Insassenunfallversicherung'
]
}, },
items: [ items: [
{ {
@ -30,7 +27,7 @@ const field = {
iconUrl: '/static/icons/demo/icon-hf-book.png', iconUrl: '/static/icons/demo/icon-hf-book.png',
linkText: 'PDF anzeigen', linkText: 'PDF anzeigen',
link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf', link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf',
openWindow: true openWindow: true,
}, },
{ {
title: 'Die Motorfahrzeughaftpflicht', title: 'Die Motorfahrzeughaftpflicht',
@ -38,7 +35,7 @@ const field = {
description: 'Buch «Sach- und Vermögensversicherungen» Kapitel 16', description: 'Buch «Sach- und Vermögensversicherungen» Kapitel 16',
linkText: 'PDF anzeigen', linkText: 'PDF anzeigen',
link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf', link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf',
openWindow: true openWindow: true,
}, },
{ {
title: 'Die Motorfahrzeughaftpflicht', title: 'Die Motorfahrzeughaftpflicht',
@ -46,7 +43,7 @@ const field = {
description: 'Buch «Sach- und Vermögensversicherungen» Kapitel 16', description: 'Buch «Sach- und Vermögensversicherungen» Kapitel 16',
linkText: 'PDF anzeigen', linkText: 'PDF anzeigen',
link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf', link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf',
openWindow: true openWindow: true,
}, },
{ {
title: 'Die Motorfahrzeughaftpflicht', title: 'Die Motorfahrzeughaftpflicht',
@ -54,7 +51,7 @@ const field = {
description: 'Buch «Sach- und Vermögensversicherungen» Kapitel 16', description: 'Buch «Sach- und Vermögensversicherungen» Kapitel 16',
linkText: 'PDF anzeigen', linkText: 'PDF anzeigen',
link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf', link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf',
openWindow: true openWindow: true,
}, },
{ {
title: 'Die Motorfahrzeughaftpflicht', title: 'Die Motorfahrzeughaftpflicht',
@ -62,9 +59,9 @@ const field = {
description: 'Buch «Sach- und Vermögensversicherungen» Kapitel 16', description: 'Buch «Sach- und Vermögensversicherungen» Kapitel 16',
linkText: 'PDF anzeigen', linkText: 'PDF anzeigen',
link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf', link: '/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf',
openWindow: true openWindow: true,
}, },
] ],
}, },
{ {
title: 'Links', title: 'Links',
@ -77,7 +74,7 @@ const field = {
description: '', description: '',
linkText: 'Link öffnen', linkText: 'Link öffnen',
link: 'https://www.nbi-ngf.ch/h', link: 'https://www.nbi-ngf.ch/h',
openWindow: true openWindow: true,
}, },
{ {
title: 'Adressen der Strassenverkehrsämter', title: 'Adressen der Strassenverkehrsämter',
@ -85,9 +82,9 @@ const field = {
description: '', description: '',
linkText: 'Link öffnen', linkText: 'Link öffnen',
link: 'https://asa.ch/strassenverkehrsaemter/adressen/', link: 'https://asa.ch/strassenverkehrsaemter/adressen/',
openWindow: true openWindow: true,
}, },
] ],
}, },
{ {
title: 'Verankerung im Lernpfad', title: 'Verankerung im Lernpfad',
@ -100,7 +97,7 @@ const field = {
description: '', description: '',
linkText: 'Lerineinheit anzeigen', linkText: 'Lerineinheit anzeigen',
link: 'http://localhost:8000/learn/versicherungsvermittlerin/versicherungsvermittlerin-circle-analyse', link: 'http://localhost:8000/learn/versicherungsvermittlerin/versicherungsvermittlerin-circle-analyse',
openWindow: false openWindow: false,
}, },
{ {
title: 'Circle: Einstieg Lernsequenz: Anwenden', title: 'Circle: Einstieg Lernsequenz: Anwenden',
@ -108,7 +105,7 @@ const field = {
description: '', description: '',
linkText: 'Lerineinheit anzeigen', linkText: 'Lerineinheit anzeigen',
link: 'http://localhost:8000/learn/versicherungsvermittlerin/versicherungsvermittlerin-circle-analyse', link: 'http://localhost:8000/learn/versicherungsvermittlerin/versicherungsvermittlerin-circle-analyse',
openWindow: false openWindow: false,
}, },
{ {
title: 'Circle: Einstieg Lernsequenz: Anwenden', title: 'Circle: Einstieg Lernsequenz: Anwenden',
@ -116,7 +113,7 @@ const field = {
description: '', description: '',
linkText: 'Lerineinheit anzeigen', linkText: 'Lerineinheit anzeigen',
link: 'http://localhost:8000/learn/versicherungsvermittlerin/versicherungsvermittlerin-circle-analyse', link: 'http://localhost:8000/learn/versicherungsvermittlerin/versicherungsvermittlerin-circle-analyse',
openWindow: false openWindow: false,
}, },
{ {
title: 'Circle: Einstieg Lernsequenz: Anwenden', title: 'Circle: Einstieg Lernsequenz: Anwenden',
@ -124,11 +121,11 @@ const field = {
description: '', description: '',
linkText: 'Lerineinheit anzeigen', linkText: 'Lerineinheit anzeigen',
link: 'http://localhost:8000/learn/versicherungsvermittlerin/versicherungsvermittlerin-circle-analyse', link: 'http://localhost:8000/learn/versicherungsvermittlerin/versicherungsvermittlerin-circle-analyse',
openWindow: false openWindow: false,
}, },
] ],
}, },
{ {
title: 'Querverweise', title: 'Querverweise',
type: 'realtiveLinks', type: 'realtiveLinks',
moreLink: '', moreLink: '',
@ -139,7 +136,7 @@ const field = {
description: 'Lernmedium: Verkehrsrechtsschutz Buch «Sach- und Vermögensversicherungen/Kapitel 12.3»', description: 'Lernmedium: Verkehrsrechtsschutz Buch «Sach- und Vermögensversicherungen/Kapitel 12.3»',
linkText: 'Handlungsfeldanzeigen', linkText: 'Handlungsfeldanzeigen',
link: 'http://localhost:8000/mediacenter/handlungsfeld', link: 'http://localhost:8000/mediacenter/handlungsfeld',
openWindow: false openWindow: false,
}, },
{ {
title: 'Rechtsstreigkeiten', title: 'Rechtsstreigkeiten',
@ -147,18 +144,30 @@ const field = {
description: 'Lernmedium: Verkehrsrechtsschutz Buch «Sach- und Vermögensversicherungen/Kapitel 12.3»', description: 'Lernmedium: Verkehrsrechtsschutz Buch «Sach- und Vermögensversicherungen/Kapitel 12.3»',
linkText: 'Handlungsfeldanzeigen', linkText: 'Handlungsfeldanzeigen',
link: 'http://localhost:8000/mediacenter/handlungsfeld', link: 'http://localhost:8000/mediacenter/handlungsfeld',
openWindow: false openWindow: false,
}, },
] ],
}, },
] ],
} }
const maxCardItems = 4; const props = defineProps<{
const maxListItems = 6; 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 => { const displayAsCard = (itemType: string): boolean => {
return itemType === 'learnmedia' || itemType === 'realtiveLinks'; return itemType === 'learnmedia' || itemType === 'realtiveLinks'
} }
const hasMoreItems = (items: object[], maxItems: number): boolean => { const hasMoreItems = (items: object[], maxItems: number): boolean => {
@ -166,81 +175,75 @@ const hasMoreItems = (items: object[], maxItems: number): boolean => {
} }
const getMaxDisplayItems = (items: object[], maxItems: number) => { const getMaxDisplayItems = (items: object[], maxItems: number) => {
return items.slice(0, maxItems); return items.slice(0, maxItems)
} }
const getMaxDisplayItemsForType = (itemType: string, items: object[]) => { const getMaxDisplayItemsForType = (itemType: string, items: object[]) => {
return displayAsCard(itemType) ? getMaxDisplayItems(items, maxCardItems) : getMaxDisplayItems(items, maxListItems); return displayAsCard(itemType) ? getMaxDisplayItems(items, maxCardItems) : getMaxDisplayItems(items, maxListItems)
} }
const hasMoreItemsForType = (itemType: string, items: object[]) => { const hasMoreItemsForType = (itemType: string, items: object[]) => {
const maxItems = displayAsCard(itemType) ? maxCardItems : maxListItems; const maxItems = displayAsCard(itemType) ? maxCardItems : maxListItems
return hasMoreItems(items, maxItems); return hasMoreItems(items, maxItems)
} }
</script> </script>
<template> <template>
<Teleport to="body"> <Teleport to="body" v-if="mediaStore.mediaCenterPage && mediaCategory">
<HandlungsfeldLayout> <HandlungsfeldLayout>
<template #header> <template #header>
<div class="flex justify-between"> <div class="flex justify-between">
<div class="w-5/12"> <div class="w-5/12">
<h3 class="font-normal text-large mb-3">Handlungsfeld</h3> <h3 class="font-normal text-large mb-3">Handlungsfeld</h3>
<h1 class="mb-4 lg:mb-8">{{field.title}}</h1> <h1 class="mb-4 lg:mb-8">{{ mediaCategory.title }}</h1>
<p>{{field.description}}</p> <p>{{ mediaCategory.introduction_text }}</p>
</div> </div>
<img <img class="w-5/12" :src="field.icon" />
class="w-5/12"
:src="field.icon"/>
</div> </div>
</template> </template>
<template #body> <template #body>
<section class="mb-20"> <section class="mb-20">
<h2 class="mb-4">Das erwartet dich in diesem Handlungsfeld</h2> <h2 class="mb-4">{{ mediaCategory.description_title }}</h2>
<p class="mb-4 lg:w-2/3">{{field.summary.text}}</p> <p class="mb-4 lg:w-2/3">{{ mediaCategory.description_text }}</p>
<ul> <ul>
<li <li v-for="item in mediaCategory.items" :key="item" class="mb-2 h-10 leading-10 flex items-center">
v-for="item in field.summary.items"
:key="item"
class="mb-2 h-10 leading-10 flex items-center">
<span class="text-sky-500 bg-[url('/static/icons/icon-check.svg')] bg-no-repeat h-10 w-10 mr-2"></span> <span class="text-sky-500 bg-[url('/static/icons/icon-check.svg')] bg-no-repeat h-10 w-10 mr-2"></span>
{{item}} {{ item.value }}
</li> </li>
</ul> </ul>
</section> </section>
<section <section class="mb-20" v-for="item in field.items" :key="item.title">
class="mb-20" <h2 class="mb-4">{{ item.title }}</h2>
v-for="item in field.items" :key="item.title"> <ul
<h2 class="mb-4">{{item.title}}</h2> :class="{
<ul :class="{ 'grid gap-4 grid-cols-1 lg:grid-cols-2': displayAsCard(item.type),
'grid gap-4 grid-cols-1 lg:grid-cols-2': displayAsCard(item.type), 'border-t': !displayAsCard(item.type),
'border-t': !displayAsCard(item.type), 'mb-6': hasMoreItemsForType(item.type, item.items),
'mb-6': hasMoreItemsForType(item.type, item.items) }"
}"> >
<li v-for="subItem in getMaxDisplayItemsForType(item.type, item.items)" :key="subItem.link"> <li v-for="subItem in getMaxDisplayItemsForType(item.type, item.items)" :key="subItem.link">
<LinkCard <LinkCard
v-if="displayAsCard(item.type)" v-if="displayAsCard(item.type)"
:title="subItem.title" :title="subItem.title"
:icon="subItem.iconUrl" :icon="subItem.iconUrl"
:description="subItem.description" :description="subItem.description"
:url="subItem.link" :url="subItem.link"
:link-text="subItem.linkText" :link-text="subItem.linkText"
:open-window="subItem.openWindow" :open-window="subItem.openWindow"
/> />
<div v-else class="flex items-center justify-between border-b py-4"> <div v-else class="flex items-center justify-between border-b py-4">
<h4 class="text-bold">{{subItem.title}}</h4> <h4 class="text-bold">{{ subItem.title }}</h4>
<media-link <media-link :blank="subItem.openWindow" :to="subItem.link" class="link">{{
:blank="subItem.openWindow" subItem.linkText
:to="subItem.link" }}</media-link>
class="link">{{subItem.linkText}}</media-link> </div>
</div>
</li> </li>
</ul> </ul>
<router-link <router-link
v-if="hasMoreItemsForType(item.type, item.items)" v-if="hasMoreItemsForType(item.type, item.items)"
to="/mediacenter/handlungsfeldlist" class="flex items-center"> to="/mediacenter/handlungsfeldlist"
class="flex items-center"
>
<span>Alle anschauen</span> <span>Alle anschauen</span>
<it-icon-arrow-right></it-icon-arrow-right> <it-icon-arrow-right></it-icon-arrow-right>
</router-link> </router-link>
@ -252,7 +255,7 @@ const hasMoreItemsForType = (itemType: string, items: object[]) => {
<style scoped> <style scoped>
.it-icon-hf { .it-icon-hf {
color: blue color: blue;
} }
.it-icon-hf > * { .it-icon-hf > * {
@apply m-auto; @apply m-auto;

View File

@ -0,0 +1,92 @@
<script setup lang="ts">
import * as log from 'loglevel'
import { ref, watch } from 'vue'
import { useMediaCenterStore } from '@/stores/mediaCenter'
log.debug('HandlungsfelderOverview created')
const fields = [
{
name: 'Fahrzeug',
icon: 'icon-hf-fahrzeug',
},
{
name: 'Reisen',
icon: 'icon-hf-reisen',
},
{
name: 'Einkommenssicherung',
icon: 'icon-hf-einkommenssicherung',
},
{
name: 'Gesundheit',
icon: 'icon-hf-fahrzeug',
},
{
name: 'Haushalt',
icon: 'icon-hf-reisen',
},
{
name: 'Sparen',
icon: 'icon-hf-einkommenssicherung',
},
{
name: 'Pensionierung',
icon: 'icon-hf-fahrzeug',
},
{
name: 'KMU',
icon: 'icon-hf-reisen',
},
{
name: 'Wohneigentum',
icon: 'icon-hf-einkommenssicherung',
},
{
name: 'Rechtsstreitigkeiten',
icon: 'icon-hf-fahrzeug',
},
{
name: 'Erben / Vererben',
icon: 'icon-hf-reisen',
},
{
name: 'Selbstständigkeit',
icon: 'icon-hf-einkommenssicherung',
},
]
const mediaStore = useMediaCenterStore()
const dropdownSelected = ref(mediaStore.selectedLearningPath)
watch(dropdownSelected, (newValue) =>
mediaStore.$patch({
selectedLearningPath: newValue,
})
)
</script>
<template>
<div class="mx-auto max-w-5xl">
<div class="flex flex-col lg:flex-row items-center justify-between mb-10">
<h1>Handlungsfelder</h1>
<!-- <ItDropdownSelect v-model="dropdownSelected" :items="mediaStore.availableLearningPaths"></ItDropdownSelect>-->
</div>
<div v-if="mediaStore.mediaCenterPage">
<ul class="grid gap-5 grid-cols-1 lg:grid-cols-4">
<li class="bg-white p-4" v-for="cat in mediaStore.mediaCenterPage.children" :key="cat.id">
<router-link :to="`/mediacenter/${mediaStore.mediaCenterPage.slug}/handlungsfelder/${cat.slug}`">
<img class="m-auto" :src="`/static/icons/demo/${cat.overview_icon}.svg`" />
<h3 class="text-base text-center">{{ cat.title }}</h3>
</router-link>
</li>
</ul>
</div>
</div>
</template>
<style scoped>
.it-icon-hf > * {
@apply m-auto;
}
</style>

View File

@ -0,0 +1,50 @@
<script setup lang="ts">
import * as log from 'loglevel'
import OverviewCard from '@/components/mediacenter/OverviewCard.vue'
import { ref, watch } from 'vue'
import { useMediaCenterStore } from '@/stores/mediaCenter'
log.debug('MediaMainView created')
const mediaStore = useMediaCenterStore()
const dropdownSelected = ref(mediaStore.selectedLearningPath)
watch(dropdownSelected, (newValue) =>
mediaStore.$patch({
selectedLearningPath: newValue,
})
)
</script>
<template>
<div class="mx-auto max-w-5xl">
<div class="flex flex-col lg:flex-row items-center justify-between mb-10">
<h1>Mediathek</h1>
<!-- <ItDropdownSelect-->
<!-- v-model="dropdownSelected"-->
<!-- :items="mediaStore.availableLearningPaths"></ItDropdownSelect>-->
</div>
<OverviewCard
v-if="mediaStore.mediaCenterPage"
title="Handlungsfelder"
call2-action="Anschauen"
:link="`/mediacenter/${mediaStore.mediaCenterPage.slug}/handlungsfelder`"
description="Finde alle Ressourcen der Handlungsfelder wie Lernmedien, Links und andere nützliche Informationen."
icon="handlungsfelder-overview"
class="mb-6"
>
</OverviewCard>
<OverviewCard
v-if="mediaStore.mediaCenterPage"
title="Lernmedien"
call2-action="Anschauen"
:link="`/mediacenter/${mediaStore.mediaCenterPage.slug}/lernmedien`"
description="Finde eine vollständige Liste der Bücher und anderen Medien, auf die im Kurs verwiesen wird."
icon="lernmedien-overview"
class="mb-6"
>
</OverviewCard>
</div>
</template>
<style scoped></style>

View File

@ -1,48 +0,0 @@
<script setup lang="ts">
import * as log from 'loglevel';
import OverviewCard from '@/components/mediacenter/OverviewCard.vue';
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
import {watch, ref} from "vue";
import {useMediaCenterStore} from "@/stores/mediaCenter";
log.debug('MediaMainView created');
const mediaStore = useMediaCenterStore();
const dropdownSelected = ref(mediaStore.selectedLearningPath);
watch(dropdownSelected, (newValue) => mediaStore.$patch({
selectedLearningPath: newValue
})
)
</script>
<template>
<div class="mx-auto max-w-5xl">
<div class="flex flex-col lg:flex-row items-center justify-between mb-10">
<h1>Mediathek</h1>
<ItDropdownSelect
v-model="dropdownSelected"
:items="mediaStore.availableLearningPaths"></ItDropdownSelect>
</div>
<OverviewCard
title="Handlungsfelder"
call2-action="Anschauen"
link="/mediacenter/handlungsfelder"
description="Finde alle Ressourcen der Handlungsfelder wie Lernmedien, Links und andere nützliche Informationen."
icon="handlungsfelder-overview"
class="mb-6">
</OverviewCard>
<OverviewCard
title="Lernmedien"
call2-action="Anschauen"
link="/mediacenter/lernmedien"
description="Finde eine vollständige Liste der Bücher und anderen Medien, auf die im Kurs verwiesen wird."
icon="lernmedien-overview"
class="mb-6">
</OverviewCard>
</div>
</template>
<style scoped>
</style>

View File

@ -15,13 +15,23 @@ def create_default_media_library():
parent=course_page, parent=course_page,
) )
for cat in course.coursecategory_set.all(): icons = ['icon-hf-fahrzeug', 'icon-hf-reisen', 'icon-hf-einkommenssicherung', ]
for idx, cat in enumerate(course.coursecategory_set.all()):
overview_icon = icons[(idx + 2) % len(icons)]
introduction_text = ''' introduction_text = '''
Das Auto ist für viele der grösste Stolz! Es birgt aber auch ein grosses Gefahrenpotenzial. 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, 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. die der Fahrzeugbesitzer und die Fahrzeugbesitzerin in einem grösseren Schadenfall oft nur schwer selbst aufbringen kann.'''.strip()
'''.strip() description_title = 'Das erwartet dich in diesem Handlungsfeld'
description = 'Supi' description_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.'''.strip()
items = [
('item', 'Motorfahrzeughaftpflichtversicherung'),
('item', 'Motorfahrzeugkaskoversicherung'),
('item', 'Insassenunfallversicherung'),
]
body_data = json.dumps([ body_data = json.dumps([
create_document_collection(), create_document_collection(),
create_link_collection( create_link_collection(
@ -32,10 +42,13 @@ def create_default_media_library():
) )
]) ])
media_category = MediaCategoryPageFactory( media_category = MediaCategoryPageFactory(
overview_icon=overview_icon,
title=cat.name, title=cat.name,
course_category=cat, course_category=cat,
parent=media_lib_page, parent=media_lib_page,
introduction_text=introduction_text, introduction_text=introduction_text,
description=description, description_title=description_title,
description_text=description_text,
items=items,
body=body_data, body=body_data,
) )

View File

@ -1,15 +1,16 @@
# Generated by Django 3.2.13 on 2022-09-23 12:42 # Generated by Django 3.2.13 on 2022-09-23 15:27
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
import taggit.managers import taggit.managers
import vbv_lernwelt.media_library.content_blocks
import wagtail.blocks import wagtail.blocks
import wagtail.documents.blocks import wagtail.documents.blocks
import wagtail.fields import wagtail.fields
import wagtail.models.collections import wagtail.models.collections
import wagtail.search.index import wagtail.search.index
from django.conf import settings
from django.db import migrations, models
import vbv_lernwelt.media_library.content_blocks
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -17,10 +18,10 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('wagtailcore', '0069_log_entry_jsonfield'),
('taggit', '0004_alter_taggeditem_content_type_alter_taggeditem_tag'),
('course', '0001_initial'), ('course', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('taggit', '0004_alter_taggeditem_content_type_alter_taggeditem_tag'),
('wagtailcore', '0069_log_entry_jsonfield'),
] ]
operations = [ operations = [
@ -48,7 +49,10 @@ class Migration(migrations.Migration):
fields=[ fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')),
('introduction_text', models.TextField(default='')), ('introduction_text', models.TextField(default='')),
('description', wagtail.fields.RichTextField(default='')), ('description_title', models.TextField(default='Das erwartet dich in diesem Handlungsfeld')),
('description_text', models.TextField(default='')),
('items', wagtail.fields.StreamField([('item', wagtail.blocks.TextBlock())], use_json_field=True)),
('overview_icon', models.CharField(default='icon-hf-fahrzeug', max_length=255)),
('body', wagtail.fields.StreamField([('content_collection', wagtail.blocks.StructBlock([('title', wagtail.blocks.TextBlock()), ('contents', wagtail.blocks.StreamBlock([('Links', wagtail.blocks.StructBlock([('title', wagtail.blocks.TextBlock(blank=False, null=False)), ('description', wagtail.blocks.TextBlock(default='')), ('link_display_text', wagtail.blocks.CharBlock(default='Link öffnen', max_length=255)), ('url', wagtail.blocks.URLBlock())])), ('Documents', wagtail.documents.blocks.DocumentChooserBlock()), ('Ankers', vbv_lernwelt.media_library.content_blocks.AnchorBlock()), ('CrossReference', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock(default='')), ('link_display_text', wagtail.blocks.CharBlock(default='Link öffnen', max_length=255)), ('category', wagtail.blocks.PageChooserBlock(page_type=['media_library.MediaCategoryPage']))]))]))]))], null=True, use_json_field=True)), ('body', wagtail.fields.StreamField([('content_collection', wagtail.blocks.StructBlock([('title', wagtail.blocks.TextBlock()), ('contents', wagtail.blocks.StreamBlock([('Links', wagtail.blocks.StructBlock([('title', wagtail.blocks.TextBlock(blank=False, null=False)), ('description', wagtail.blocks.TextBlock(default='')), ('link_display_text', wagtail.blocks.CharBlock(default='Link öffnen', max_length=255)), ('url', wagtail.blocks.URLBlock())])), ('Documents', wagtail.documents.blocks.DocumentChooserBlock()), ('Ankers', vbv_lernwelt.media_library.content_blocks.AnchorBlock()), ('CrossReference', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock(default='')), ('link_display_text', wagtail.blocks.CharBlock(default='Link öffnen', max_length=255)), ('category', wagtail.blocks.PageChooserBlock(page_type=['media_library.MediaCategoryPage']))]))]))]))], null=True, use_json_field=True)),
('course_category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='course.coursecategory')), ('course_category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='course.coursecategory')),
], ],

View File

@ -1,8 +1,9 @@
from django.db import models from django.db import models
from django.utils.text import slugify from django.utils.text import slugify
from wagtail import fields from wagtail import fields, blocks
from wagtail.admin.panels import FieldPanel, StreamFieldPanel from wagtail.admin.panels import FieldPanel, StreamFieldPanel
from wagtail.documents.models import AbstractDocument, Document from wagtail.documents.models import AbstractDocument, Document
from wagtail.fields import StreamField
from wagtail.models import Page from wagtail.models import Page
from vbv_lernwelt.core.model_utils import find_available_slug from vbv_lernwelt.core.model_utils import find_available_slug
@ -40,7 +41,13 @@ class MediaCategoryPage(Page):
course_category = models.ForeignKey('course.CourseCategory', on_delete=models.CASCADE) course_category = models.ForeignKey('course.CourseCategory', on_delete=models.CASCADE)
parent_page_types = ['media_library.MediaLibraryPage'] parent_page_types = ['media_library.MediaLibraryPage']
introduction_text = models.TextField(default='') introduction_text = models.TextField(default='')
description = fields.RichTextField(default='') description_title = models.TextField(default='Das erwartet dich in diesem Handlungsfeld')
description_text = models.TextField(default='')
items = StreamField([
('item', blocks.TextBlock()),
], use_json_field=True)
overview_icon = models.CharField(max_length=255, default="icon-hf-fahrzeug")
body = fields.StreamField( body = fields.StreamField(
[('content_collection', MediaContentCollection())], [('content_collection', MediaContentCollection())],
@ -49,10 +56,12 @@ class MediaCategoryPage(Page):
) )
content_panels = [ content_panels = [
FieldPanel('title', classname="full title"), FieldPanel('title'),
FieldPanel('course_category'), FieldPanel('course_category'),
FieldPanel('introduction_text', classname="introduction text"), FieldPanel('introduction_text'),
FieldPanel('description', classname="introduction text"), FieldPanel('description_title'),
FieldPanel('description_text'),
FieldPanel('items'),
StreamFieldPanel('body') StreamFieldPanel('body')
] ]
@ -66,7 +75,7 @@ class MediaCategoryPage(Page):
cls, field_names=[ cls, field_names=[
'id', 'title', 'slug', 'type', 'translation_key', 'id', 'title', 'slug', 'type', 'translation_key',
'course_category', 'course_category',
'introduction_text', 'description', 'body', 'introduction_text', 'overview_icon', 'description_title', 'description_text', 'items', 'body',
] ]
) )

View File

@ -55,7 +55,7 @@ class MediaContentCollectionFactory(wagtail_factories.StructBlockFactory):
class MediaCategoryPageFactory(wagtail_factories.PageFactory): class MediaCategoryPageFactory(wagtail_factories.PageFactory):
title = 'Fahrzeug' title = 'Fahrzeug'
introduction_text = 'Das Auto ist für viele der grösste Stolz! Es birgt aber ...' introduction_text = 'Das Auto ist für viele der grösste Stolz! Es birgt aber ...'
description = 'Das erwartet dich in diesem Handlungsfeld' description_title = 'Das erwartet dich in diesem Handlungsfeld'
class Meta: class Meta:
model = MediaCategoryPage model = MediaCategoryPage