Refactor LearningContent component

This commit is contained in:
Ramon Wenger 2022-12-08 17:04:56 +01:00
parent aa6054a84e
commit 865e0d80f6
9 changed files with 204 additions and 67 deletions

View File

@ -4,12 +4,16 @@ import { useCircleStore } from "@/stores/circle";
import type { LearningContent } from "@/types";
import * as log from "loglevel";
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");
const route = useRoute();
const circleStore = useCircleStore();
const props = defineProps<{
@ -23,71 +27,45 @@ const block = computed(() => {
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>
<template>
<div v-if="block">
<LearningContentContainer
:title="learningContent.title"
:next-button-text="$t('learningContent.completeAndContinue')"
:exit-text="$t('general.backToCircle')"
@exit="circleStore.closeLearningContent(props.learningContent)"
@next="circleStore.continueFromLearningContent(props.learningContent)"
>
<div class="content">
<div
v-if="
block.type === 'exercise' ||
block.type === 'test' ||
block.type === 'learningmodule'
"
class="h-screen"
>
<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>
<LearningContentContainer
v-if="block"
:title="learningContent.title"
:next-button-text="$t('learningContent.completeAndContinue')"
:exit-text="$t('general.backToCircle')"
@exit="circleStore.closeLearningContent(props.learningContent)"
@next="circleStore.continueFromLearningContent(props.learningContent)"
>
<div class="content">
<component
:is="component"
:value="block.value"
:content="learningContent"
></component>
</div>
</LearningContentContainer>
</template>
<style lang="scss" scoped>

View File

@ -3,14 +3,14 @@ import * as log from "loglevel";
log.debug("LeariningContentContainer.vue setup");
const props = defineProps<{
defineProps<{
exitText: string;
title: string;
nextButtonText: string;
showBackButton?: boolean;
}>();
const emit = defineEmits(["back", "next", "exit"]);
defineEmits(["back", "next", "exit"]);
</script>
<template>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>