Refactor LearningContent component
This commit is contained in:
parent
aa6054a84e
commit
865e0d80f6
|
|
@ -4,12 +4,16 @@ import { useCircleStore } from "@/stores/circle";
|
||||||
import type { LearningContent } from "@/types";
|
import type { LearningContent } from "@/types";
|
||||||
import * as log from "loglevel";
|
import * as log from "loglevel";
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
|
||||||
|
import DescriptionBlock from "@/components/learningPath/blocks/DescriptionBlock.vue";
|
||||||
|
import DescriptionTextBlock from "@/components/learningPath/blocks/DescriptionTextBlock.vue";
|
||||||
|
import FeedbackBlock from "@/components/learningPath/blocks/FeedbackBlock.vue";
|
||||||
|
import IframeBlock from "@/components/learningPath/blocks/IframeBlock.vue";
|
||||||
|
import PlaceholderBlock from "@/components/learningPath/blocks/PlaceholderBlock.vue";
|
||||||
|
import VideoBlock from "@/components/learningPath/blocks/VideoBlock.vue";
|
||||||
|
|
||||||
log.debug("LearningContent.vue setup");
|
log.debug("LearningContent.vue setup");
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
|
|
||||||
const circleStore = useCircleStore();
|
const circleStore = useCircleStore();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
|
@ -23,71 +27,45 @@ const block = computed(() => {
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// can't use the type as component name, as some are reserved HTML components, e.g. video
|
||||||
|
const COMPONENTS: Record<string, InstanceType<typeof VideoBlock>> = {
|
||||||
|
placeholder: PlaceholderBlock,
|
||||||
|
video: VideoBlock,
|
||||||
|
assignment: DescriptionTextBlock,
|
||||||
|
resource: DescriptionTextBlock,
|
||||||
|
exercise: IframeBlock,
|
||||||
|
test: IframeBlock,
|
||||||
|
learningmodule: IframeBlock,
|
||||||
|
feedback: FeedbackBlock,
|
||||||
|
};
|
||||||
|
const DEFAULT_BLOCK = DescriptionBlock;
|
||||||
|
|
||||||
|
const component = computed(() => {
|
||||||
|
if (block.value) {
|
||||||
|
return COMPONENTS[block.value.type] || DEFAULT_BLOCK;
|
||||||
|
}
|
||||||
|
return DEFAULT_BLOCK;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="block">
|
<LearningContentContainer
|
||||||
<LearningContentContainer
|
v-if="block"
|
||||||
:title="learningContent.title"
|
:title="learningContent.title"
|
||||||
:next-button-text="$t('learningContent.completeAndContinue')"
|
:next-button-text="$t('learningContent.completeAndContinue')"
|
||||||
:exit-text="$t('general.backToCircle')"
|
:exit-text="$t('general.backToCircle')"
|
||||||
@exit="circleStore.closeLearningContent(props.learningContent)"
|
@exit="circleStore.closeLearningContent(props.learningContent)"
|
||||||
@next="circleStore.continueFromLearningContent(props.learningContent)"
|
@next="circleStore.continueFromLearningContent(props.learningContent)"
|
||||||
>
|
>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div
|
<component
|
||||||
v-if="
|
:is="component"
|
||||||
block.type === 'exercise' ||
|
:value="block.value"
|
||||||
block.type === 'test' ||
|
:content="learningContent"
|
||||||
block.type === 'learningmodule'
|
></component>
|
||||||
"
|
</div>
|
||||||
class="h-screen"
|
</LearningContentContainer>
|
||||||
>
|
|
||||||
<iframe width="100%" height="100%" scrolling="no" :src="block.value.url" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else class="container-medium">
|
|
||||||
<div v-if="block.type === 'video'">
|
|
||||||
<iframe
|
|
||||||
class="mt-8 w-full aspect-video"
|
|
||||||
:src="block.value.url"
|
|
||||||
:title="learningContent.title"
|
|
||||||
frameborder="0"
|
|
||||||
allow="accelerometer; encrypted-media; gyroscope; picture-in-picture"
|
|
||||||
allowfullscreen
|
|
||||||
></iframe>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else-if="block.type === 'media_library'" class="mt-4 lg:mt-12">
|
|
||||||
<h1>{{ learningContent.title }}</h1>
|
|
||||||
|
|
||||||
<p class="text-large my-4 lg:my-8">{{ block.value.description }}</p>
|
|
||||||
<router-link
|
|
||||||
:to="`${block.value.url}?back=${route.path}`"
|
|
||||||
class="button btn-primary"
|
|
||||||
>
|
|
||||||
Mediathek öffnen
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-else-if="block.type === 'resource' || block.type === 'assignment'"
|
|
||||||
class="mt-4 lg:mt-12"
|
|
||||||
>
|
|
||||||
<p class="text-large my-4">{{ block.value.description }}</p>
|
|
||||||
<div class="resource-text" v-html="block.value.text"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else-if="block.type === 'placeholder'" class="mt-4 lg:mt-12">
|
|
||||||
<p class="text-large my-4">{{ block.value.description }}</p>
|
|
||||||
<h1>{{ learningContent.title }}</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else class="text-large my-4">{{ block.value.description }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</LearningContentContainer>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,14 @@ import * as log from "loglevel";
|
||||||
|
|
||||||
log.debug("LeariningContentContainer.vue setup");
|
log.debug("LeariningContentContainer.vue setup");
|
||||||
|
|
||||||
const props = defineProps<{
|
defineProps<{
|
||||||
exitText: string;
|
exitText: string;
|
||||||
title: string;
|
title: string;
|
||||||
nextButtonText: string;
|
nextButtonText: string;
|
||||||
showBackButton?: boolean;
|
showBackButton?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits(["back", "next", "exit"]);
|
defineEmits(["back", "next", "exit"]);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<template>
|
||||||
|
<div class="container-medium">
|
||||||
|
<div class="mt-4 lg:mt-12">
|
||||||
|
<p class="text-large my-4">{{ value.description }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { LearningContent } from "@/types";
|
||||||
|
|
||||||
|
interface Value {
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
value: Value;
|
||||||
|
content: LearningContent;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
<template>
|
||||||
|
<div class="container-medium">
|
||||||
|
<div class="mt-4 lg:mt-12">
|
||||||
|
<p class="text-large my-4">{{ value.description }}</p>
|
||||||
|
<div class="resource-text" v-html="value.text"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { LearningContent } from "@/types";
|
||||||
|
|
||||||
|
interface Value {
|
||||||
|
description: string;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
value: Value;
|
||||||
|
content: LearningContent;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<template>
|
||||||
|
<div class="container-medium">
|
||||||
|
<div class="mt-4 lg:mt-12">
|
||||||
|
<Feedback :page="content" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import Feedback from "@/components/Feedback.vue";
|
||||||
|
import type { LearningContent } from "@/types";
|
||||||
|
|
||||||
|
interface Value {
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
value: Value;
|
||||||
|
content: LearningContent;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="h-screen"
|
||||||
|
>
|
||||||
|
<iframe width="100%" height="100%" scrolling="no" :src="value.url" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { LearningContent } from "@/types";
|
||||||
|
|
||||||
|
interface Value {
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
value: Value;
|
||||||
|
content: LearningContent;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<template>
|
||||||
|
<div class="container-medium">
|
||||||
|
<div class="mt-4 lg:mt-12">
|
||||||
|
<h1>{{ content.title }}</h1>
|
||||||
|
|
||||||
|
<p class="text-large my-4 lg:my-8">{{ value.description }}</p>
|
||||||
|
<router-link :to="`${value.url}?back=${route.path}`" class="button btn-primary">
|
||||||
|
Mediathek öffnen
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { LearningContent } from "@/types";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
|
interface Value {
|
||||||
|
description: string;
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
value: Value;
|
||||||
|
content: LearningContent;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<template>
|
||||||
|
<div class="container-medium">
|
||||||
|
<div class="mt-4 lg:mt-12">
|
||||||
|
<p class="text-large my-4">{{ value.description }}</p>
|
||||||
|
<h1>{{ content.title }}</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { LearningContent } from "@/types";
|
||||||
|
|
||||||
|
interface Value {
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
value: Value;
|
||||||
|
content: LearningContent;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<template>
|
||||||
|
<div class="container-medium">
|
||||||
|
<iframe
|
||||||
|
class="mt-8 w-full aspect-video"
|
||||||
|
:src="value.url"
|
||||||
|
:title="content.title"
|
||||||
|
frameborder="0"
|
||||||
|
allow="accelerometer; encrypted-media; gyroscope; picture-in-picture"
|
||||||
|
allowfullscreen
|
||||||
|
>
|
||||||
|
</iframe>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { LearningContent } from "@/types";
|
||||||
|
|
||||||
|
interface Value {
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
value: Value;
|
||||||
|
content: LearningContent;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
Loading…
Reference in New Issue