Load MediaCenter data from api
This commit is contained in:
parent
8941f4ad24
commit
18c3e28ba1
|
|
@ -0,0 +1,33 @@
|
|||
<script setup lang="ts">
|
||||
import MediaLink from '@/components/mediacenter/MediaLink.vue'
|
||||
|
||||
export interface Props {
|
||||
title: string
|
||||
description: string
|
||||
linkText: string
|
||||
url: string
|
||||
icon: string
|
||||
openWindow?: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
icon: '',
|
||||
description: '',
|
||||
openWindow: false,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="border-gray-500 border flex p-4 items-center">
|
||||
<img class="mr-6" :src="icon" />
|
||||
<div>
|
||||
<h4 class="mb-2 text-bold">{{ title }}</h4>
|
||||
<p class="mb-2">{{ description }}</p>
|
||||
<media-link :to="url" :blank="openWindow" class="link">
|
||||
<span class="inline">{{ linkText }}</span>
|
||||
</media-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<script setup lang="ts">
|
||||
// https://router.vuejs.org/guide/advanced/extending-router-link.html
|
||||
// https://vueschool.io/articles/vuejs-tutorials/extending-vue-router-links-in-vue-3/
|
||||
|
||||
import { RouterLink } from 'vue-router'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
...RouterLink.props, // @ts-ignore
|
||||
blank: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
|
||||
const isExternalLink = computed(() => typeof props.to === 'string' && props.to.startsWith('http'))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<a v-if="isExternalLink" :target="props.blank ? '_blank' : '_self'" rel="noopener" :href="props.to">
|
||||
<slot />
|
||||
</a>
|
||||
<router-link v-else :target="props.blank ? '_blank' : '_self'" rel="noopener" v-bind="props">
|
||||
<slot />
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
|
||||
import MediaLink from "@/components/mediacenter/MediaLink.vue";
|
||||
|
||||
export interface Props {
|
||||
title: string,
|
||||
description: string,
|
||||
linkText: string,
|
||||
url: string,
|
||||
icon: string,
|
||||
openWindow?: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
icon: '',
|
||||
description: '',
|
||||
openWindow: false
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="border-gray-500 border flex p-4 items-center">
|
||||
<img
|
||||
class="mr-6"
|
||||
:src="icon" />
|
||||
<div>
|
||||
<h4 class="mb-2 text-bold">{{title}}</h4>
|
||||
<p class="mb-2">{{description}}</p>
|
||||
<media-link
|
||||
:to="url"
|
||||
:blank="openWindow"
|
||||
class="link"
|
||||
>
|
||||
<span class="inline">{{linkText}}</span>
|
||||
</media-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
// https://router.vuejs.org/guide/advanced/extending-router-link.html
|
||||
// https://vueschool.io/articles/vuejs-tutorials/extending-vue-router-links-in-vue-3/
|
||||
|
||||
import { RouterLink, useLink } from 'vue-router'
|
||||
import {computed} from "vue";
|
||||
|
||||
const props = defineProps(
|
||||
{
|
||||
...RouterLink.props, // @ts-ignore
|
||||
blank: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const isExternalLink = computed(() => typeof props.to === 'string' && props.to.startsWith('http'));
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<a v-if="isExternalLink"
|
||||
:target="props.blank ? '_blank' : '_self'"
|
||||
rel="noopener"
|
||||
:href="props.to">
|
||||
<slot />
|
||||
</a>
|
||||
<router-link
|
||||
v-else
|
||||
:target="props.blank ? '_blank' : '_self'"
|
||||
rel="noopener"
|
||||
v-bind="props"
|
||||
>
|
||||
<slot />
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import CockpitView from '@/views/CockpitView.vue'
|
||||
import LoginView from '@/views/LoginView.vue'
|
||||
import MediaMainView from '@/views/MediaMainView.vue'
|
||||
import { redirectToLoginIfRequired, updateLoggedIn } from '@/router/guards'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
|
||||
|
|
@ -26,26 +25,27 @@ 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/MediaMainView.vue')
|
||||
component: () => import('@/views/MediaMainView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'handlungsfelder',
|
||||
component: () => import('@/views/HandlungsfelderOverview.vue')
|
||||
component: () => import('@/views/HandlungsfelderOverview.vue'),
|
||||
},
|
||||
{
|
||||
path: 'handlungsfeld',
|
||||
component: () => import('@/views/Handlungsfeld.vue')
|
||||
component: () => import('@/views/Handlungsfeld.vue'),
|
||||
},
|
||||
{
|
||||
path: 'handlungsfeldlist',
|
||||
component: () => import('@/views/MediaList.vue')
|
||||
component: () => import('@/views/MediaList.vue'),
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/messages',
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import type {
|
|||
LearningSequence,
|
||||
LearningUnit,
|
||||
LearningUnitQuestion,
|
||||
LearningWagtailPage,
|
||||
CourseWagtailPage,
|
||||
} from '@/types'
|
||||
import type { LearningPath } from '@/services/learningPath'
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ 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;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as _ from 'lodash'
|
||||
|
||||
import type { CircleCompletion, LearningContent, LearningPathChild, LearningWagtailPage, Topic } from '@/types'
|
||||
import type { CircleCompletion, LearningContent, LearningPathChild, CourseWagtailPage, Topic } from '@/types'
|
||||
import { Circle } from '@/services/circle'
|
||||
|
||||
function getLastCompleted(learningPathKey: string, completionData: CircleCompletion[]) {
|
||||
|
|
@ -9,7 +9,7 @@ function getLastCompleted(learningPathKey: string, completionData: CircleComplet
|
|||
})
|
||||
}
|
||||
|
||||
export class LearningPath implements LearningWagtailPage {
|
||||
export class LearningPath implements CourseWagtailPage {
|
||||
readonly type = 'learnpath.LearningPath'
|
||||
public topics: Topic[]
|
||||
public circles: Circle[]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useMediaCenterStore = defineStore({
|
||||
id: 'mediacenter',
|
||||
state: () => {
|
||||
return {
|
||||
selectedLearningPath: { id: 1, name: 'Alle Lehrgänge' },
|
||||
availableLearningPaths: [
|
||||
{ id: 1, name: 'Alle Lehrgänge' },
|
||||
{ id: 2, name: 'Versicherungsvermittler/in' }
|
||||
]
|
||||
}
|
||||
},
|
||||
getters: {},
|
||||
actions: {},
|
||||
})
|
||||
|
|
@ -47,7 +47,7 @@ export interface CircleJobSituation {
|
|||
id: string;
|
||||
}
|
||||
|
||||
export interface LearningWagtailPage {
|
||||
export interface CourseWagtailPage {
|
||||
readonly id: number;
|
||||
readonly title: string;
|
||||
readonly slug: string;
|
||||
|
|
@ -55,7 +55,7 @@ export interface LearningWagtailPage {
|
|||
completed?: boolean;
|
||||
}
|
||||
|
||||
export interface LearningContent extends LearningWagtailPage {
|
||||
export interface LearningContent extends CourseWagtailPage {
|
||||
type: 'learnpath.LearningContent';
|
||||
minutes: number;
|
||||
contents: (LearningContentBlock | VideoBlock | PodcastBlock | DocumentBlock)[];
|
||||
|
|
@ -66,13 +66,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;
|
||||
|
|
@ -81,7 +81,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[];
|
||||
|
|
@ -90,13 +90,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[];
|
||||
|
|
@ -127,3 +127,55 @@ 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';
|
||||
introduction_text: string;
|
||||
description: string;
|
||||
course_category: CourseCategory;
|
||||
body: MediaContentCollection[];
|
||||
}
|
||||
|
||||
export interface MediaLibraryPage extends CourseWagtailPage {
|
||||
type: 'media_library.MediaLibraryPage';
|
||||
course: Course;
|
||||
children: MediaCategoryPage[];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import * as log from 'loglevel';
|
||||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||
import {reactive, ref, watch} from "vue";
|
||||
import {useMediaCenterStore} from "@/stores/mediacenter";
|
||||
import {useMediaCenterStore} from "@/stores/mediaCenter";
|
||||
|
||||
log.debug('HandlungsfelderOverview created');
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,25 @@
|
|||
<script setup lang="ts">
|
||||
import * as log from 'loglevel';
|
||||
import * as log from 'loglevel'
|
||||
import { onMounted } from 'vue'
|
||||
import { useMediaCenterStore } from '@/stores/mediaCenter'
|
||||
|
||||
log.debug('ShopView created');
|
||||
log.debug('MediaCenterView created')
|
||||
|
||||
const props = defineProps<{
|
||||
mediaCenterPageSlug: string
|
||||
}>()
|
||||
|
||||
const mediaCenterStore = useMediaCenterStore()
|
||||
|
||||
onMounted(async () => {
|
||||
log.debug('MediaCenterView mounted', props.mediaCenterPageSlug)
|
||||
|
||||
try {
|
||||
await mediaCenterStore.loadMediaCenterPage(props.mediaCenterPageSlug)
|
||||
} catch (error) {
|
||||
log.error(error)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -22,5 +39,4 @@ log.debug('ShopView created');
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
@ -3,7 +3,7 @@ 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";
|
||||
import {useMediaCenterStore} from "@/stores/mediaCenter";
|
||||
|
||||
log.debug('MediaMainView created');
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue