364 lines
9.7 KiB
Vue
364 lines
9.7 KiB
Vue
<!-- Element used to display Blocks in a ContentForm -->
|
|
<template>
|
|
<div class="content-element">
|
|
<!-- Element Chooser if element has chooser type or no type -->
|
|
<content-block-element-chooser-widget
|
|
:class="['content-element__component', 'content-element__chooser']"
|
|
v-bind="element"
|
|
v-if="isChooser"
|
|
@change-type="changeType"
|
|
@remove="$emit('remove', false)"
|
|
/>
|
|
|
|
<!-- Content Forms -->
|
|
<content-form-section
|
|
:title="title"
|
|
:actions="actions"
|
|
v-else
|
|
@top="$emit('top')"
|
|
@up="$emit('up')"
|
|
@down="$emit('down')"
|
|
@bottom="$emit('bottom')"
|
|
@remove="$emit('remove')"
|
|
>
|
|
<div class="content-element__section">
|
|
<!-- Form depending on type of element -->
|
|
<component
|
|
:class="['content-element__component']"
|
|
v-bind="element"
|
|
:is="component"
|
|
@change-text="changeText"
|
|
@link-change-url="changeUrl"
|
|
@change-url="changeUrl"
|
|
@switch-to-document="switchToDocument"
|
|
@assignment-change-title="changeAssignmentTitle"
|
|
@assignment-change-assignment="changeAssignmentAssignment"
|
|
@assignment-change-solution="changeAssignmentSolution"
|
|
/>
|
|
</div>
|
|
</content-form-section>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineAsyncComponent } from 'vue';
|
|
import ContentFormSection from '@/components/content-block-form/ContentFormSection.vue';
|
|
import ContentElementActions from '@/components/content-block-form/ContentElementActions.vue';
|
|
|
|
const TrashIcon = defineAsyncComponent(() => import('@/components/icons/TrashIcon.vue'));
|
|
const ContentBlockElementChooserWidget = defineAsyncComponent(
|
|
() => import('@/components/content-forms/ContentBlockElementChooserWidget.vue')
|
|
);
|
|
const LinkForm = defineAsyncComponent(() => import('@/components/content-forms/LinkForm.vue'));
|
|
const VideoForm = defineAsyncComponent(() => import('@/components/content-forms/VideoForm.vue'));
|
|
const ImageForm = defineAsyncComponent(() => import('@/components/content-forms/ImageForm.vue'));
|
|
const DocumentForm = defineAsyncComponent(() => import('@/components/content-forms/DocumentForm.vue'));
|
|
const AssignmentForm = defineAsyncComponent(() => import('@/components/content-forms/AssignmentForm.vue'));
|
|
const TextForm = defineAsyncComponent(
|
|
() => import(/* webpackChunkName: "content-forms" */ '@/components/content-forms/TipTap.vue')
|
|
);
|
|
const SubtitleForm = defineAsyncComponent(() => import('@/components/content-forms/SubtitleForm.vue'));
|
|
const SolutionForm = defineAsyncComponent(() => import('@/components/content-forms/SolutionForm.vue'));
|
|
// readonly blocks
|
|
const Assignment = defineAsyncComponent(() => import('@/components/content-blocks/assignment/Assignment.vue'));
|
|
const SurveyBlock = defineAsyncComponent(() => import('@/components/content-blocks/SurveyBlock.vue'));
|
|
const Solution = defineAsyncComponent(() => import('@/components/content-blocks/Solution.vue'));
|
|
const ImageBlock = defineAsyncComponent(() => import('@/components/content-blocks/ImageBlock.vue'));
|
|
const Instruction = defineAsyncComponent(() => import('@/components/content-blocks/Instruction.vue'));
|
|
const ModuleRoomSlug = defineAsyncComponent(() => import('@/components/content-blocks/ModuleRoomSlug.vue'));
|
|
const CmsDocumentBlock = defineAsyncComponent(() => import('@/components/content-blocks/CmsDocumentBlock.vue'));
|
|
const ThinglinkBlock = defineAsyncComponent(() => import('@/components/content-blocks/ThinglinkBlock.vue'));
|
|
const InfogramBlock = defineAsyncComponent(() => import('@/components/content-blocks/InfogramBlock.vue'));
|
|
const CHOOSER = 'content-block-element-chooser-widget';
|
|
|
|
export default {
|
|
props: {
|
|
element: {
|
|
type: Object,
|
|
default: null,
|
|
},
|
|
// is this element at the top level, or is it nested? we assume top level
|
|
topLevel: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
firstElement: {
|
|
type: Boolean,
|
|
required: true,
|
|
},
|
|
lastElement: {
|
|
type: Boolean,
|
|
required: true,
|
|
},
|
|
},
|
|
|
|
components: {
|
|
ContentElementActions,
|
|
ContentFormSection,
|
|
TrashIcon,
|
|
ContentBlockElementChooserWidget,
|
|
LinkForm,
|
|
VideoForm,
|
|
ImageForm,
|
|
DocumentForm,
|
|
AssignmentForm,
|
|
TextForm,
|
|
SubtitleForm,
|
|
SurveyBlock,
|
|
Solution,
|
|
ImageBlock,
|
|
Instruction,
|
|
ModuleRoomSlug,
|
|
CmsDocumentBlock,
|
|
InfogramBlock,
|
|
ThinglinkBlock,
|
|
Assignment,
|
|
SolutionForm,
|
|
},
|
|
computed: {
|
|
actions() {
|
|
return {
|
|
up: !this.firstElement,
|
|
down: !this.lastElement,
|
|
extended: this.topLevel,
|
|
};
|
|
},
|
|
isChooser() {
|
|
return this.component === CHOOSER;
|
|
},
|
|
type() {
|
|
return this.getType(this.element);
|
|
},
|
|
component() {
|
|
return this.type.component;
|
|
},
|
|
title() {
|
|
return this.type.title;
|
|
},
|
|
icon() {
|
|
return this.type.icon;
|
|
},
|
|
},
|
|
|
|
methods: {
|
|
getType(element) {
|
|
switch (element.type) {
|
|
case 'subtitle':
|
|
return {
|
|
component: 'subtitle-form',
|
|
title: 'Untertitel',
|
|
icon: 'title-icon',
|
|
};
|
|
case 'link_block':
|
|
return {
|
|
component: 'link-form',
|
|
title: 'Link',
|
|
icon: 'link-icon',
|
|
};
|
|
case 'video_block':
|
|
return {
|
|
component: 'video-form',
|
|
title: 'Video',
|
|
icon: 'video-icon',
|
|
};
|
|
case 'image_url_block':
|
|
return {
|
|
component: 'image-form',
|
|
title: 'Bild',
|
|
icon: 'image-icon',
|
|
};
|
|
case 'text_block':
|
|
return {
|
|
component: 'text-form',
|
|
title: 'Text',
|
|
icon: 'text-icon',
|
|
};
|
|
case 'assignment':
|
|
return {
|
|
component: 'assignment-form',
|
|
title: 'Aufgabe & Ergebnis',
|
|
icon: 'speech-bubble-icon',
|
|
};
|
|
case 'document_block':
|
|
return {
|
|
component: 'document-form',
|
|
title: 'Dokument',
|
|
icon: 'document-icon',
|
|
};
|
|
case 'survey':
|
|
return {
|
|
component: 'survey-block',
|
|
title: 'Übung',
|
|
};
|
|
case 'solution':
|
|
return {
|
|
component: 'solution-form',
|
|
title: 'Lösung',
|
|
};
|
|
case 'image_block':
|
|
return {
|
|
component: 'image-block',
|
|
title: 'Bild',
|
|
};
|
|
case 'instruction':
|
|
return {
|
|
component: 'instruction',
|
|
title: 'Instruktion',
|
|
};
|
|
case 'module_room_slug':
|
|
return {
|
|
component: 'module-room-slug',
|
|
title: 'Raum',
|
|
};
|
|
case 'cms_document_block':
|
|
return {
|
|
component: 'cms-document-block',
|
|
title: 'Dokument',
|
|
};
|
|
case 'thinglink_block':
|
|
return {
|
|
component: 'thinglink-block',
|
|
title: 'Interaktive Grafik',
|
|
};
|
|
case 'infogram_block':
|
|
return {
|
|
component: 'infogram-block',
|
|
title: 'Interaktive Grafik',
|
|
};
|
|
}
|
|
return {
|
|
component: CHOOSER,
|
|
title: '',
|
|
icon: '',
|
|
};
|
|
},
|
|
_updateProperty(value, key) {
|
|
// const content = this.localContentBlock.contents[index];
|
|
const content = this.element;
|
|
this.update({
|
|
...content,
|
|
value: {
|
|
...content.value,
|
|
[key]: value,
|
|
},
|
|
});
|
|
},
|
|
changeUrl(value) {
|
|
this._updateProperty(value, 'url');
|
|
},
|
|
changeText(value) {
|
|
this._updateProperty(value, 'text');
|
|
},
|
|
changeAssignmentTitle(value) {
|
|
this._updateProperty(value, 'title');
|
|
},
|
|
changeAssignmentAssignment(value) {
|
|
this._updateProperty(value, 'assignment');
|
|
},
|
|
changeAssignmentSolution(value) {
|
|
this._updateProperty(value, 'solution');
|
|
},
|
|
changeType({ type, convertToList }, value) {
|
|
let el = {
|
|
type: type,
|
|
value: Object.assign({}, value),
|
|
};
|
|
switch (type) {
|
|
case 'subtitle':
|
|
el = {
|
|
...el,
|
|
value: {
|
|
text: '',
|
|
},
|
|
};
|
|
break;
|
|
case 'text_block':
|
|
el = {
|
|
...el,
|
|
value: {
|
|
text: '',
|
|
},
|
|
};
|
|
break;
|
|
case 'link_block':
|
|
el = {
|
|
...el,
|
|
value: {
|
|
text: '',
|
|
url: '',
|
|
},
|
|
};
|
|
break;
|
|
case 'video_block':
|
|
el = {
|
|
...el,
|
|
value: {
|
|
url: '',
|
|
},
|
|
};
|
|
break;
|
|
case 'document_block':
|
|
el = {
|
|
...el,
|
|
value: Object.assign(
|
|
{
|
|
url: '',
|
|
},
|
|
value
|
|
),
|
|
};
|
|
break;
|
|
case 'image_url_block':
|
|
el = {
|
|
...el,
|
|
value: {
|
|
url: '',
|
|
},
|
|
};
|
|
break;
|
|
}
|
|
|
|
if (convertToList) {
|
|
el = {
|
|
type: 'content_list_item',
|
|
contents: [el],
|
|
};
|
|
}
|
|
this.update(el);
|
|
},
|
|
update(element) {
|
|
this.$emit('update', element);
|
|
},
|
|
switchToDocument(value) {
|
|
this.changeType('document_block', value);
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
@import 'styles/helpers';
|
|
|
|
.content-element {
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
&__actions {
|
|
display: inline-flex;
|
|
justify-self: flex-end;
|
|
align-self: flex-end;
|
|
}
|
|
|
|
&__section {
|
|
display: grid;
|
|
//grid-template-columns: 1fr 50px;
|
|
grid-auto-rows: auto;
|
|
/*width: 95%; // reserve space for scrollbar*/
|
|
}
|
|
|
|
&__chooser {
|
|
grid-column: 1 / span 2;
|
|
}
|
|
}
|
|
</style>
|