Refactor content component form

This commit is contained in:
Ramon Wenger 2022-01-13 22:03:42 +01:00
parent f56f7178f3
commit 5b548e9d6a
4 changed files with 217 additions and 186 deletions

View File

@ -0,0 +1,175 @@
<template>
<div class="content-element">
<component
:is="type(element)"
:class="{'content-element__chooser': type(element) === 'content-block-element-chooser-widget'}"
v-bind="element"
class="content-element__component"
@change-type="changeType($event)"
@link-change-url="changeText"
@link-change-text="changeText"
@text-change-value="changeText"
@document-change-url="changeUrl"
@image-change-url="changeUrl"
@video-change-url="changeUrl"
@switch-to-document="switchToDocument"
@assignment-change-title="changeAssignmentTitle"
@assignment-change-assignment="changeAssignmentAssignment"
/>
<a
class="contents-form__remove icon-button"
@click="$emit('remove')">
<trash-icon
class="contents-form__trash-icon icon-button__icon"
v-if="type(element) !== 'content-block-element-chooser-widget'"/>
</a>
</div>
</template>
<script>
const TrashIcon = () => import(/* webpackChunkName: "icons" */'@/components/icons/TrashIcon');
const ContentBlockElementChooserWidget = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/ContentBlockElementChooserWidget');
const LinkForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/LinkForm');
const VideoForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/VideoForm');
const ImageForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/ImageForm');
const DocumentForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/DocumentForm');
const AssignmentForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/AssignmentForm');
const TextForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/TextForm');
export default {
props: {
element: {
type: Object,
default: null
}
},
components: {
TrashIcon,
ContentBlockElementChooserWidget,
LinkForm,
VideoForm,
ImageForm,
DocumentForm,
AssignmentForm,
TextForm,
},
methods: {
type(element) {
switch (element.type) {
case 'link_block':
return 'link-form';
case 'video_block':
return 'video-form';
case 'image_url_block':
return 'image-form';
case 'text_block':
return 'text-form';
case 'assignment':
return 'assignment-form';
case 'document_block':
return 'document-form';
}
return 'content-block-element-chooser-widget';
},
_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');
},
changeType(type, value) {
let el = {
type: type,
value: Object.assign({}, value),
};
switch (type) {
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;
}
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: grid;
grid-template-columns: 1fr 50px;
grid-auto-rows: auto;
/*width: 95%; // reserve space for scrollbar*/
&__chooser {
grid-column: 1 / span 2;
}
}
</style>

View File

@ -27,37 +27,10 @@
:key="index"
class="contents-form__element"
v-for="(element, index) in localContentBlock.contents">
<component
:is="type(element)"
:class="{'contents-form__chooser': type(element) === 'content-block-element-chooser-widget'}"
v-bind="element"
:index="index"
class="contents-form__element-component"
@change-type="changeType"
@link-change-url="changeLinkUrl"
@link-change-text="changeLinkText"
@text-change-value="changeTextValue"
@document-change-url="changeDocumentUrl"
@image-change-url="changeImageUrl"
@video-change-url="changeVideoUrl"
@switch-to-document="switchToDocument"
@assignment-change-title="changeAssignmentTitle"
@assignment-change-assignment="changeAssignmentAssignment"
/>
<a
class="contents-form__remove icon-button"
@click="removeElement(index)">
<trash-icon
class="contents-form__trash-icon icon-button__icon"
v-if="type(element) !== 'content-block-element-chooser-widget'"/>
</a>
<content-element
:element="element"
@update="update(index, $event)"
@remove="remove(index)"/>
<add-content-element
:index="index"
@ -84,49 +57,35 @@
<script>
import {meQuery} from '@/graphql/queries';
const ContentBlockElementChooserWidget = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/ContentBlockElementChooserWidget');
const ModalInput = () => import(/* webpackChunkName: "content-forms" */'@/components/ModalInput');
const AddContentElement = () => import(/* webpackChunkName: "content-forms" */'@/components/AddContentElement');
const LinkForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/LinkForm');
const VideoForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/VideoForm');
const ImageForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/ImageForm');
const DocumentForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/DocumentForm');
const AssignmentForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/AssignmentForm');
const TextForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/TextForm');
const ContentElement = () => import(/* webpackChunkName: "content-forms" */'@/components/content-block-form/ContentElement');
const Modal = () => import('@/components/Modal');
const TrashIcon = () => import(/* webpackChunkName: "icons" */'@/components/icons/TrashIcon');
const Checkbox = () => import('@/components/ui/Checkbox');
export default {
props: {
'content-block': Object,
'block-type': {
contentBlock: Object,
blockType: {
type: String,
default: 'ContentBlock',
},
'show-task-selection': {
showTaskSelection: {
type: Boolean,
default: false,
},
'disable-save': {
disableSave: {
type: Boolean,
default: false,
},
},
components: {
ContentElement,
Modal,
ContentBlockElementChooserWidget,
ModalInput,
AddContentElement,
LinkForm,
VideoForm,
ImageForm,
DocumentForm,
AssignmentForm,
TextForm,
TrashIcon,
Checkbox,
},
@ -157,119 +116,11 @@
},
methods: {
type(element) {
switch (element.type) {
case 'link_block':
return 'link-form';
case 'video_block':
return 'video-form';
case 'image_url_block':
return 'image-form';
case 'text_block':
return 'text-form';
case 'assignment':
return 'assignment-form';
case 'document_block':
return 'document-form';
}
return 'content-block-element-chooser-widget';
setContentBlockType(checked, localContentBlock) {
this.localContentBlock.isAssignment = checked;
},
_updateProperty(value, index, key) {
const content = this.localContentBlock.contents[index];
this.localContentBlock.contents.splice(index, 1, {
...content,
value: {
...content.value,
[key]: value,
},
});
},
changeLinkUrl(value, index) {
this._updateProperty(value, index, 'url');
},
changeLinkText(value, index) {
this._updateProperty(value, index, 'text');
},
changeVideoUrl(value, index) {
this._updateProperty(value, index, 'url');
},
changeImageUrl(value, index) {
this._updateProperty(value, index, 'url');
},
changeDocumentUrl(value, index) {
this._updateProperty(value, index, 'url');
},
changeTextValue(value, index) {
this._updateProperty(value, index, 'text');
},
changeAssignmentTitle(value, index) {
this._updateProperty(value, index, 'title');
},
changeAssignmentAssignment(value, index) {
this._updateProperty(value, index, 'assignment');
},
removeElement(index) {
this.localContentBlock.contents.splice(index, 1);
},
addElement(index) {
this.localContentBlock.contents.splice(index + 1, 0, {
hideAssignment: this.blockType !== 'ContentBlock',
});
},
updateTitle(title) {
this.localContentBlock.title = title;
this.error = false;
},
changeType(index, type, value) {
let el = {
type: type,
value: Object.assign({}, value),
};
switch (type) {
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;
}
this.localContentBlock.contents.splice(index, 1, el);
update(index, element) {
this.localContentBlock.contents.splice(index, 1, element);
},
save() {
if (!this.disableSave) {
@ -280,27 +131,31 @@
this.$emit('save', this.localContentBlock);
}
},
setContentBlockType(checked, localContentBlock) {
this.localContentBlock.isAssignment = checked;
updateTitle(title) {
this.localContentBlock.title = title;
this.error = false;
},
switchToDocument(index, value) {
this.changeType(index, 'document_block', value);
addElement(index) {
this.localContentBlock.contents.splice(index + 1, 0, {
hideAssignment: this.blockType !== 'ContentBlock',
});
},
remove(index) {
this.localContentBlock.contents.splice(index, 1);
},
},
};
</script>
<style scoped lang="scss">
@import "@/styles/_variables.scss";
@import "~styles/helpers";
.contents-form {
/* top level does not exist, because of the modal */
&__element {
display: grid;
grid-template-columns: 1fr 50px;
grid-auto-rows: auto;
/*width: 95%; // reserve space for scrollbar*/
}
&__element-component {
@ -313,10 +168,6 @@
&__trash-icon {
}
&__chooser {
grid-column: 1 / span 2;
}
&__add {
grid-column: 1 / span 2;
}

View File

@ -20,7 +20,7 @@
props: {
startingIndex: {
type: Number,
default: 1
default: 0
},
items: {
type: Array,

View File

@ -5,28 +5,28 @@
<div
class="content-block-element-chooser-widget__link content-block-element-chooser-widget__link--link"
data-cy="choose-link-widget"
@click="$emit('change-type', index, 'link_block')">
@click="changeType('link_block')">
<link-icon class="content-block-element-chooser-widget__link-icon"/>
<div class="content-block-element-chooser-widget__link-title">Link</div>
</div>
<div
class="content-block-element-chooser-widget__link content-block-element-chooser-widget__link--video"
data-cy="choose-video-widget"
@click="$emit('change-type', index, 'video_block')">
@click="changeType('video_block')">
<video-icon class="content-block-element-chooser-widget__link-icon"/>
<div class="content-block-element-chooser-widget__link-title">Video</div>
</div>
<div
class="content-block-element-chooser-widget__link content-block-element-chooser-widget__link--image"
data-cy="choose-image-widget"
@click="$emit('change-type', index, 'image_url_block')">
@click="changeType('image_url_block')">
<image-icon class="content-block-element-chooser-widget__link-icon"/>
<div class="content-block-element-chooser-widget__link-title">Bild</div>
</div>
<div
class="content-block-element-chooser-widget__link content-block-element-chooser-widget__link--text"
data-cy="choose-text-widget"
@click="$emit('change-type', index, 'text_block')">
@click="changeType('text_block')">
<text-icon class="content-block-element-chooser-widget__link-icon"/>
<div class="content-block-element-chooser-widget__link-title">Text</div>
</div>
@ -34,14 +34,14 @@
class="content-block-element-chooser-widget__link content-block-element-chooser-widget__link--assignment"
data-cy="choose-assignment-widget"
v-if="!hideAssignment"
@click="$emit('change-type', index, 'assignment')">
@click="changeType('assignment')">
<speech-bubble-icon class="content-block-element-chooser-widget__link-icon"/>
<div class="content-block-element-chooser-widget__link-title">Aufgabe&nbsp;& Ergebnis</div>
</div>
<div
class="content-block-element-chooser-widget__link content-block-element-chooser-widget__link--document"
data-cy="choose-document-widget"
@click="$emit('change-type', index, 'document_block')">
@click="changeType('document_block')">
<document-icon class="content-block-element-chooser-widget__link-icon"/>
<div class="content-block-element-chooser-widget__link-title">Dokument</div>
</div>
@ -73,13 +73,18 @@
TextIcon,
SpeechBubbleIcon,
DocumentIcon
}
},
methods: {
changeType(type) {
this.$emit('change-type', type);
}
},
};
</script>
<style scoped lang="scss">
@import "@/styles/_variables.scss";
@import "@/styles/_functions.scss";
@import "~styles/helpers";
.content-block-element-chooser-widget {
display: -ms-grid;