Add edit route for custom content blocks
This commit is contained in:
parent
fdb408de84
commit
f563483b79
|
|
@ -85,6 +85,7 @@
|
|||
import {CONTENT_TYPE} from '@/consts/types';
|
||||
import PopoverLink from '@/components/ui/PopoverLink';
|
||||
import {removeAtIndex} from '@/graphql/immutable-operations';
|
||||
import {EDIT_CONTENT_BLOCK_PAGE} from '@/router/module.names';
|
||||
const ContentComponent = () => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/ContentComponent');
|
||||
|
||||
const instruments = {
|
||||
|
|
@ -207,7 +208,13 @@
|
|||
},
|
||||
methods: {
|
||||
editContentBlock(contentBlock) {
|
||||
this.$store.dispatch('editContentBlock', contentBlock.id);
|
||||
const route = {
|
||||
name: EDIT_CONTENT_BLOCK_PAGE,
|
||||
params: {
|
||||
id: contentBlock.id
|
||||
}
|
||||
};
|
||||
this.$router.push(route);
|
||||
},
|
||||
deleteContentBlock(contentBlock) {
|
||||
const parent = this.parent;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,308 @@
|
|||
<template>
|
||||
<div class="content-block-form content-list__parent">
|
||||
<div class="content-block-form__content">
|
||||
<h1
|
||||
class="heading-1 content-block-form__heading"
|
||||
data-cy="content-block-form-heading"
|
||||
>
|
||||
{{ title }}
|
||||
</h1>
|
||||
|
||||
<!-- Assignment toggle / checkbox -->
|
||||
<toggle
|
||||
:bordered="false"
|
||||
:checked="localContentBlock.isAssignment"
|
||||
class="content-block-form__task-toggle"
|
||||
label="Inhaltsblock als Auftrag formatieren"
|
||||
@input="localContentBlock.isAssignment=$event"
|
||||
/>
|
||||
|
||||
<!-- Form for title of content block -->
|
||||
<content-form-section title="Titel">
|
||||
<input-with-label
|
||||
:value="localContentBlock.title"
|
||||
label="Name"
|
||||
placeholder="z.B. Auftrag 3"
|
||||
@input="localContentBlock.title=$event"
|
||||
/>
|
||||
</content-form-section>
|
||||
|
||||
<!-- Add content at top of content block -->
|
||||
<add-content-link
|
||||
class="content-block-form__segment"
|
||||
@click="addBlock(-1)"
|
||||
/>
|
||||
<!-- Loop for outer contents layer -->
|
||||
<div
|
||||
class="content-list content-list--creator content-block-form__segment"
|
||||
v-for="(block, outer) in localContentBlock.contents"
|
||||
:key="block.id"
|
||||
>
|
||||
<!-- If the block is a content list -->
|
||||
<ol
|
||||
class="content-list__item content-block-form__segment"
|
||||
data-cy="content-list-item"
|
||||
v-if="block.type === 'content_list_item'"
|
||||
>
|
||||
<li
|
||||
class="content-block-form__segment"
|
||||
v-for="(content, index) in block.contents"
|
||||
:key="content.id"
|
||||
>
|
||||
<content-element
|
||||
:element="content"
|
||||
class="content-block-form__segment"
|
||||
@update="update(index, $event, outer)"
|
||||
@remove="remove(outer, index)"
|
||||
@up="up(outer, index)"
|
||||
@down="down(outer, index)"
|
||||
/>
|
||||
|
||||
<add-content-link
|
||||
class="content-block-form__add-button"
|
||||
@click="addBlock(outer, index)"
|
||||
/>
|
||||
</li>
|
||||
</ol>
|
||||
<!-- If the block is a single element -->
|
||||
<content-element
|
||||
:element="block"
|
||||
class="content-block-form__segment"
|
||||
v-else
|
||||
@update="update(outer, $event)"
|
||||
@remove="remove(outer)"
|
||||
@up="up(outer)"
|
||||
@down="down(outer)"
|
||||
/>
|
||||
|
||||
<!-- Add element after the looped item -->
|
||||
<add-content-link
|
||||
class="content-block-form__segment"
|
||||
@click="addBlock(outer)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Save and Cancel buttons -->
|
||||
<footer class="content-block-form__footer">
|
||||
<button
|
||||
:disabled="!isValid"
|
||||
class="button button--primary"
|
||||
@click="save(localContentBlock)"
|
||||
>
|
||||
Speichern
|
||||
</button>
|
||||
<a
|
||||
class="button"
|
||||
@click="$emit('back')"
|
||||
>Abbrechen</a>
|
||||
</footer>
|
||||
</div><!-- -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Toggle from '@/components/ui/Toggle';
|
||||
import ContentFormSection from '@/components/content-block-form/ContentFormSection';
|
||||
import InputWithLabel from '@/components/ui/InputWithLabel';
|
||||
import AddContentLink from '@/components/content-block-form/AddContentLink';
|
||||
|
||||
import ContentElement from '@/components/content-block-form/ContentElement';
|
||||
import {removeAtIndex, replaceAtIndex, swapElements} from '@/graphql/immutable-operations';
|
||||
|
||||
import {CHOOSER, transformInnerContents} from '@/components/content-block-form/helpers';
|
||||
|
||||
|
||||
export default {
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
contentBlock: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ContentElement,
|
||||
AddContentLink,
|
||||
InputWithLabel,
|
||||
ContentFormSection,
|
||||
Toggle,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
localContentBlock: Object.assign({}, {
|
||||
title: this.contentBlock.title,
|
||||
// contents: [...this.contentBlock.contents],
|
||||
contents: transformInnerContents([...this.contentBlock.contents]),
|
||||
id: this.contentBlock.id || undefined,
|
||||
isAssignment: this.contentBlock.type && this.contentBlock.type.toLowerCase() === 'task',
|
||||
}),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isValid() {
|
||||
return this.localContentBlock.title > '';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
update(index, element, parent) {
|
||||
if (parent === undefined) {
|
||||
// element is top level
|
||||
this.localContentBlock.contents = [
|
||||
...this.localContentBlock.contents.slice(0, index),
|
||||
element,
|
||||
...this.localContentBlock.contents.slice(index + 1)
|
||||
];
|
||||
} else {
|
||||
const parentBlock = this.localContentBlock.contents[parent];
|
||||
|
||||
this.localContentBlock.contents = [
|
||||
...this.localContentBlock.contents.slice(0, parent),
|
||||
{
|
||||
...parentBlock,
|
||||
contents: [
|
||||
...parentBlock.contents.slice(0, index),
|
||||
element,
|
||||
...parentBlock.contents.slice(index + 1),
|
||||
]
|
||||
},
|
||||
...this.localContentBlock.contents.slice(parent + 1)
|
||||
];
|
||||
}
|
||||
},
|
||||
addBlock(afterOuterIndex, innerIndex) {
|
||||
if (innerIndex !== undefined) {
|
||||
const block = this.localContentBlock.contents[afterOuterIndex];
|
||||
this.localContentBlock.contents = [
|
||||
...this.localContentBlock.contents.slice(0, afterOuterIndex),
|
||||
{
|
||||
...block,
|
||||
contents: [
|
||||
...block.contents.slice(0, innerIndex + 1),
|
||||
{
|
||||
id: -1,
|
||||
type: CHOOSER,
|
||||
},
|
||||
...block.contents.slice(innerIndex + 1)
|
||||
]
|
||||
},
|
||||
...this.localContentBlock.contents.slice(afterOuterIndex + 1)
|
||||
];
|
||||
} else {
|
||||
this.localContentBlock.contents = [
|
||||
...this.localContentBlock.contents.slice(0, afterOuterIndex+1),
|
||||
{
|
||||
id: -1,
|
||||
type: CHOOSER,
|
||||
includeListOption: true
|
||||
},
|
||||
...this.localContentBlock.contents.slice(afterOuterIndex+1)
|
||||
];
|
||||
}
|
||||
},
|
||||
remove(outer, inner) {
|
||||
this.$modal.open('confirm')
|
||||
.then(() => {
|
||||
this.executeRemoval(outer, inner);
|
||||
})
|
||||
.catch(() => {
|
||||
|
||||
});
|
||||
},
|
||||
shift(outer, inner, distance) {
|
||||
if (inner === undefined) {
|
||||
this.localContentBlock.contents = swapElements(this.localContentBlock.contents, outer, outer + distance);
|
||||
} else {
|
||||
const {contents} = this.localContentBlock;
|
||||
const outerElement = contents[outer];
|
||||
const newOuterElement = {
|
||||
...outerElement,
|
||||
contents: swapElements(outerElement.contents, inner, inner + distance)
|
||||
};
|
||||
this.localContentBlock.contents = replaceAtIndex(contents, outer, newOuterElement);
|
||||
}
|
||||
},
|
||||
up(outer, inner){
|
||||
this.shift(outer, inner, -1);
|
||||
},
|
||||
down(outer, inner){
|
||||
this.shift(outer, inner, 1);
|
||||
},
|
||||
executeRemoval(outer, inner) {
|
||||
if (inner === undefined) {
|
||||
// not a list item container, just remove the element from the outer array
|
||||
this.localContentBlock.contents = removeAtIndex(this.localContentBlock.contents, outer);
|
||||
} else {
|
||||
let prevInnerContents = this.localContentBlock.contents[outer].contents;
|
||||
let innerContents = removeAtIndex(prevInnerContents, inner);
|
||||
|
||||
if (innerContents.length) {
|
||||
/*
|
||||
there is still an element inside the outer element after removal,
|
||||
so we replace the previous element in the outer array with the new one with fewer contents
|
||||
*/
|
||||
let element = {
|
||||
...this.localContentBlock.contents[outer],
|
||||
contents: innerContents
|
||||
};
|
||||
this.localContentBlock.contents = replaceAtIndex(this.localContentBlock.contents, outer, element);
|
||||
} else {
|
||||
// inner contents is now empty, remove the whole element from the outer array
|
||||
this.localContentBlock.contents = removeAtIndex(this.localContentBlock.contents, outer);
|
||||
}
|
||||
}
|
||||
},
|
||||
save(contentBlock) {
|
||||
this.$emit('save', contentBlock);
|
||||
},
|
||||
}
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
|
||||
.content-block-form {
|
||||
width: 800px;
|
||||
max-width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 800px;
|
||||
grid-template-rows: 1fr auto;
|
||||
grid-template-areas:
|
||||
'content'
|
||||
'footer';
|
||||
|
||||
&__heading {
|
||||
@include heading-1;
|
||||
}
|
||||
|
||||
&__task-toggle {
|
||||
margin-bottom: $large-spacing;
|
||||
}
|
||||
|
||||
&__add-button {
|
||||
}
|
||||
|
||||
&__segment {
|
||||
margin-bottom: $large-spacing;
|
||||
:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__content {
|
||||
grid-area: content;
|
||||
overflow-x: visible;
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
margin-top: auto;
|
||||
grid-area: footer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
import store from '@/store/index';
|
||||
|
||||
import EDIT_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/mutateContentBlock.gql';
|
||||
import EDIT_CONTENT_BLOCK_MUTATION from 'gql/mutations/editContentBlock.gql';
|
||||
import MODULE_DETAILS_QUERY from '@/graphql/gql/queries/modules/moduleDetailsQuery.gql';
|
||||
import CONTENT_BLOCK_QUERY from '@/graphql/gql/queries/contentBlockQuery.gql';
|
||||
import { setUserBlockType } from '@/helpers/content-block';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
import {setUserBlockType} from '@/helpers/content-block';
|
||||
import NEW_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/addContentBlock.gql';
|
||||
import MODULE_DETAILS_QUERY from '@/graphql/gql/queries/modules/moduleDetailsQuery.gql';
|
||||
|
||||
export const CHOOSER = 'content-block-element-chooser-widget';
|
||||
export const chooserFilter = value => value.type !== CHOOSER;
|
||||
|
||||
export const cleanUpContents = (contents) => {
|
||||
let filteredContents = contents
|
||||
.filter(chooserFilter); // only use items that are not chooser elements
|
||||
|
||||
return filteredContents.map(content => {
|
||||
// if the element has a contents property, it's a list of contents, filter them
|
||||
if (content.contents) {
|
||||
return {
|
||||
...content,
|
||||
contents: content.contents.filter(chooserFilter)
|
||||
};
|
||||
}
|
||||
// else just return it
|
||||
return content;
|
||||
});
|
||||
};
|
||||
|
||||
// transform value prop to contents, to better handle the input type on the server
|
||||
export const transformInnerContents = (contents) => {
|
||||
let ret = [];
|
||||
for (let content of contents) {
|
||||
if (Array.isArray(content.value)) {
|
||||
const {value, ...contentWithoutValue} = content;
|
||||
ret.push({
|
||||
...contentWithoutValue,
|
||||
contents: value
|
||||
});
|
||||
} else {
|
||||
ret.push(content);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
|
@ -5,7 +5,7 @@ import {
|
|||
OBJECTIVE_GROUP_TYPE,
|
||||
OBJECTIVE_TYPE
|
||||
} from '@/consts/types';
|
||||
import CHANGE_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/mutateContentBlock.gql';
|
||||
import EDIT_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/editContentBlock.gql';
|
||||
import UPDATE_OBJECTIVE_VISIBILITY_MUTATION from '@/graphql/gql/mutations/updateObjectiveVisibility.gql';
|
||||
import UPDATE_OBJECTIVE_GROUP_VISIBILITY_MUTATION from '@/graphql/gql/mutations/updateObjectiveGroupVisibility.gql';
|
||||
import UPDATE_CHAPTER_VISIBILITY_MUTATION from '@/graphql/gql/mutations/updateChapterVisibility.gql';
|
||||
|
|
@ -14,7 +14,7 @@ export const createVisibilityMutation = (type, id, visibility) => {
|
|||
let mutation, variables;
|
||||
switch (type) {
|
||||
case CONTENT_TYPE:
|
||||
mutation = CHANGE_CONTENT_BLOCK_MUTATION;
|
||||
mutation = EDIT_CONTENT_BLOCK_MUTATION;
|
||||
variables = {
|
||||
input: {
|
||||
id,
|
||||
|
|
|
|||
|
|
@ -1,108 +1,20 @@
|
|||
<template>
|
||||
<div class="create-content-block content-list__parent">
|
||||
<div class="create-content-block__content">
|
||||
<h1 class="heading-1 create-content-block__heading">
|
||||
Inhaltsblock erfassen
|
||||
</h1>
|
||||
|
||||
<toggle
|
||||
:bordered="false"
|
||||
:checked="contentBlock.isAssignment"
|
||||
class="create-content-block__task-toggle"
|
||||
label="Inhaltsblock als Auftrag formatieren"
|
||||
@input="contentBlock.isAssignment=$event"
|
||||
/>
|
||||
|
||||
<content-form-section title="Titel">
|
||||
<input-with-label
|
||||
:value="contentBlock.title"
|
||||
label="Name"
|
||||
placeholder="z.B. Auftrag 3"
|
||||
@input="contentBlock.title=$event"
|
||||
/>
|
||||
</content-form-section>
|
||||
|
||||
<add-content-link
|
||||
class="create-content-block__segment"
|
||||
@click="addBlock(-1)"
|
||||
/>
|
||||
<div
|
||||
class="content-list content-list--creator create-content-block__segment"
|
||||
v-for="(block, outer) in contentBlock.contents"
|
||||
:key="block.id"
|
||||
>
|
||||
<ol
|
||||
class="content-list__item create-content-block__segment"
|
||||
v-if="block.type === 'content_list_item'"
|
||||
>
|
||||
<li
|
||||
class="create-content-block__segment"
|
||||
v-for="(content, index) in block.contents"
|
||||
:key="content.id"
|
||||
>
|
||||
<content-element
|
||||
:element="content"
|
||||
class="create-content-block__segment"
|
||||
@update="update(index, $event, outer)"
|
||||
@remove="remove(outer, index)"
|
||||
@up="up(outer, index)"
|
||||
@down="down(outer, index)"
|
||||
/>
|
||||
|
||||
<add-content-link
|
||||
class="create-content-block__add-button"
|
||||
@click="addBlock(outer, index)"
|
||||
/>
|
||||
</li>
|
||||
</ol>
|
||||
<content-element
|
||||
:element="block"
|
||||
class="create-content-block__segment"
|
||||
v-else
|
||||
@update="update(outer, $event)"
|
||||
@remove="remove(outer)"
|
||||
@up="up(outer)"
|
||||
@down="down(outer)"
|
||||
/>
|
||||
|
||||
<add-content-link
|
||||
class="create-content-block__segment"
|
||||
@click="addBlock(outer)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<footer class="create-content-block__footer">
|
||||
<button
|
||||
:disabled="!isValid"
|
||||
class="button button--primary"
|
||||
@click="save(contentBlock)"
|
||||
>
|
||||
Speichern
|
||||
</button>
|
||||
<a
|
||||
class="button"
|
||||
@click="goToModule"
|
||||
>Abbrechen</a>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
<content-block-form
|
||||
title="Inhaltsblock erfassen"
|
||||
:content-block="contentBlock"
|
||||
@back="goToModule"
|
||||
@save="save"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue';
|
||||
import Toggle from '@/components/ui/Toggle';
|
||||
import ContentFormSection from '@/components/content-block-form/ContentFormSection';
|
||||
import InputWithLabel from '@/components/ui/InputWithLabel';
|
||||
import AddContentLink from '@/components/content-block-form/AddContentLink';
|
||||
import ContentElement from '@/components/content-block-form/ContentElement';
|
||||
|
||||
import NEW_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/addContentBlock.gql';
|
||||
import ContentBlockForm from '@/components/content-block-form/ContentBlockForm';
|
||||
import {setUserBlockType} from '@/helpers/content-block';
|
||||
import NEW_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/addContentBlock.gql';
|
||||
import MODULE_DETAILS_QUERY from '@/graphql/gql/queries/modules/moduleDetailsQuery.gql';
|
||||
import {insertAtIndex, removeAtIndex, replaceAtIndex, swapElements} from '@/graphql/immutable-operations';
|
||||
|
||||
const CHOOSER = 'content-block-element-chooser-widget';
|
||||
const chooserFilter = value => value.type !== CHOOSER;
|
||||
import {cleanUpContents} from '@/components/content-block-form/helpers';
|
||||
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
|
|
@ -117,161 +29,32 @@
|
|||
},
|
||||
|
||||
components: {
|
||||
ContentElement,
|
||||
AddContentLink,
|
||||
InputWithLabel,
|
||||
ContentFormSection,
|
||||
Toggle,
|
||||
ContentBlockForm,
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
contentBlock: {
|
||||
title: '',
|
||||
isAssignment: false,
|
||||
contents: [
|
||||
{}
|
||||
]},
|
||||
contents: [
|
||||
]},
|
||||
}),
|
||||
|
||||
computed: {
|
||||
isValid() {
|
||||
return this.contentBlock.title > '';
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
update(index, element, parent) {
|
||||
if (parent === undefined) {
|
||||
this.contentBlock.contents = [
|
||||
...this.contentBlock.contents.slice(0, index),
|
||||
element,
|
||||
...this.contentBlock.contents.slice(index + 1)
|
||||
];
|
||||
} else {
|
||||
const parentBlock = this.contentBlock.contents[parent];
|
||||
this.contentBlock.contents = [
|
||||
...this.contentBlock.contents.slice(0, parent),
|
||||
{
|
||||
...parentBlock,
|
||||
contents: [
|
||||
...parentBlock.contents.slice(0, index),
|
||||
element,
|
||||
...parentBlock.contents.slice(index + 1),
|
||||
]
|
||||
},
|
||||
...this.contentBlock.contents.slice(parent + 1)
|
||||
];
|
||||
}
|
||||
},
|
||||
addBlock(afterOuterIndex, innerIndex) {
|
||||
if (innerIndex !== undefined) {
|
||||
const block = this.contentBlock.contents[afterOuterIndex];
|
||||
this.contentBlock.contents = [
|
||||
...this.contentBlock.contents.slice(0, afterOuterIndex),
|
||||
{
|
||||
...block,
|
||||
contents: [
|
||||
...block.contents.slice(0, innerIndex + 1),
|
||||
{
|
||||
id: -1,
|
||||
type: CHOOSER,
|
||||
},
|
||||
...block.contents.slice(innerIndex + 1)
|
||||
]
|
||||
},
|
||||
...this.contentBlock.contents.slice(afterOuterIndex + 1)
|
||||
];
|
||||
} else {
|
||||
this.contentBlock.contents = [
|
||||
...this.contentBlock.contents.slice(0, afterOuterIndex+1),
|
||||
{
|
||||
id: -1,
|
||||
type: CHOOSER,
|
||||
includeListOption: true
|
||||
},
|
||||
...this.contentBlock.contents.slice(afterOuterIndex+1)
|
||||
];
|
||||
}
|
||||
},
|
||||
remove(outer, inner) {
|
||||
this.$modal.open('confirm')
|
||||
.then(() => {
|
||||
this.executeRemoval(outer, inner);
|
||||
})
|
||||
.catch(() => {
|
||||
|
||||
});
|
||||
},
|
||||
shift(outer, inner, distance) {
|
||||
if (inner === undefined) {
|
||||
this.contentBlock.contents = swapElements(this.contentBlock.contents, outer, outer + distance);
|
||||
} else {
|
||||
const {contents} = this.contentBlock;
|
||||
const outerElement = contents[outer];
|
||||
const newOuterElement = {
|
||||
...outerElement,
|
||||
contents: swapElements(outerElement.contents, inner, inner + distance)
|
||||
};
|
||||
this.contentBlock.contents = replaceAtIndex(contents, outer, newOuterElement);
|
||||
}
|
||||
},
|
||||
up(outer, inner){
|
||||
this.shift(outer, inner, -1);
|
||||
},
|
||||
down(outer, inner){
|
||||
this.shift(outer, inner, 1);
|
||||
},
|
||||
executeRemoval(outer, inner) {
|
||||
if (inner === undefined) {
|
||||
// not a list item container, just remove the element from the outer array
|
||||
this.contentBlock.contents = removeAtIndex(this.contentBlock.contents, outer);
|
||||
} else {
|
||||
let prevInnerContents = this.contentBlock.contents[outer].contents;
|
||||
let innerContents = removeAtIndex(prevInnerContents, inner);
|
||||
|
||||
if (innerContents.length) {
|
||||
/*
|
||||
there is still an element inside the outer element after removal,
|
||||
so we replace the previous element in the outer array with the new one with fewer contents
|
||||
*/
|
||||
let element = {
|
||||
...this.contentBlock.contents[outer],
|
||||
contents: innerContents
|
||||
};
|
||||
this.contentBlock.contents = replaceAtIndex(this.contentBlock.contents, outer, element);
|
||||
} else {
|
||||
// inner contents is now empty, remove the whole element from the outer array
|
||||
this.contentBlock.contents = removeAtIndex(this.contentBlock.contents, outer);
|
||||
}
|
||||
}
|
||||
},
|
||||
save({title, contents, isAssignment}) {
|
||||
let filteredContents = contents
|
||||
.filter(chooserFilter); // only use items that are not chooser elements
|
||||
|
||||
let mappedContents = filteredContents.map(content => {
|
||||
// if the element has a contents property, it's a list of contents, filter them
|
||||
if (content.contents) {
|
||||
return {
|
||||
...content,
|
||||
contents: content.contents.filter(chooserFilter)
|
||||
};
|
||||
}
|
||||
// else just return it
|
||||
return content;
|
||||
});
|
||||
let cleanedContents = cleanUpContents(contents);
|
||||
const contentBlock = {
|
||||
title: title,
|
||||
contents: mappedContents,
|
||||
contents: cleanedContents,
|
||||
type: setUserBlockType(isAssignment),
|
||||
};
|
||||
let input;
|
||||
const { parent, after, slug} = this.$route.params;
|
||||
const { parent, after, slug } = this.$route.params;
|
||||
if(after) {
|
||||
input = {
|
||||
contentBlock,
|
||||
after
|
||||
};
|
||||
};
|
||||
} else {
|
||||
input = {
|
||||
contentBlock,
|
||||
|
|
@ -295,51 +78,8 @@
|
|||
// use the history, so the scroll position is preserved
|
||||
this.$router.go(-1);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
|
||||
.create-content-block {
|
||||
width: 800px;
|
||||
max-width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 800px;
|
||||
grid-template-rows: 1fr auto;
|
||||
grid-template-areas:
|
||||
'content'
|
||||
'footer';
|
||||
|
||||
&__heading {
|
||||
@include heading-1;
|
||||
}
|
||||
|
||||
&__task-toggle {
|
||||
margin-bottom: $large-spacing;
|
||||
}
|
||||
|
||||
&__add-button {
|
||||
}
|
||||
|
||||
&__segment {
|
||||
margin-bottom: $large-spacing;
|
||||
:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__content {
|
||||
grid-area: content;
|
||||
overflow-x: visible;
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
margin-top: auto;
|
||||
grid-area: footer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
<template>
|
||||
<component
|
||||
:is="component"
|
||||
v-bind="componentProps"
|
||||
@save="save"
|
||||
@back="goToModule"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CONTENT_BLOCK_QUERY from '@/graphql/gql/queries/contentBlockQuery.gql';
|
||||
import ContentBlockForm from '@/components/content-block-form/ContentBlockForm';
|
||||
|
||||
import EDIT_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/editContentBlock.gql';
|
||||
import MODULE_DETAILS_QUERY from '@/graphql/gql/queries/modules/moduleDetailsQuery.gql';
|
||||
import {setUserBlockType} from '@/helpers/content-block';
|
||||
import {cleanUpContents} from '@/components/content-block-form/helpers';
|
||||
|
||||
// import ContentBlockForm from '@/components/content-block-form/ContentBlockForm';
|
||||
|
||||
|
||||
export default {
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
},
|
||||
components: {ContentBlockForm},
|
||||
|
||||
data: ()=>({
|
||||
contentBlock: null,
|
||||
}),
|
||||
|
||||
computed: {
|
||||
// only display component once the prop is loaded
|
||||
component() {
|
||||
if (this.contentBlock) {
|
||||
return 'content-block-form';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
componentProps() {
|
||||
return {
|
||||
title: 'Inhalte bearbeiten',
|
||||
contentBlock: this.contentBlock
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
apollo: {
|
||||
contentBlock: {
|
||||
query: CONTENT_BLOCK_QUERY,
|
||||
variables() {
|
||||
return {
|
||||
id: this.id
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
save({title, contents, isAssignment, id}) {
|
||||
let cleanedContents = cleanUpContents(contents);
|
||||
const contentBlock = {
|
||||
title: title,
|
||||
contents: cleanedContents,
|
||||
type: setUserBlockType(isAssignment),
|
||||
};
|
||||
const { slug } = this.$route.params;
|
||||
const input = {
|
||||
id,
|
||||
contentBlock
|
||||
};
|
||||
this.$apollo.mutate({
|
||||
mutation: EDIT_CONTENT_BLOCK_MUTATION,
|
||||
variables: {
|
||||
input
|
||||
},
|
||||
refetchQueries: [{
|
||||
query: MODULE_DETAILS_QUERY,
|
||||
variables: { slug }
|
||||
}]
|
||||
}).then(this.goToModule);
|
||||
},
|
||||
goToModule() {
|
||||
// use the history, so the scroll position is preserved
|
||||
this.$router.go(-1);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
</script>
|
||||
|
|
@ -6,3 +6,4 @@ export const SNAPSHOT_LIST = 'snapshot-list';
|
|||
export const SNAPSHOT_DETAIL = 'snapshot-detail';
|
||||
export const CREATE_CONTENT_BLOCK_AFTER_PAGE = 'create-content-block-after';
|
||||
export const CREATE_CONTENT_BLOCK_UNDER_PARENT_PAGE = 'create-content-block-under-parent';
|
||||
export const EDIT_CONTENT_BLOCK_PAGE = 'edit-content-block';
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@ import {
|
|||
SNAPSHOT_LIST,
|
||||
SUBMISSIONS_PAGE,
|
||||
VISIBILITY_PAGE,
|
||||
CREATE_CONTENT_BLOCK_AFTER_PAGE, CREATE_CONTENT_BLOCK_UNDER_PARENT_PAGE,
|
||||
CREATE_CONTENT_BLOCK_AFTER_PAGE,
|
||||
CREATE_CONTENT_BLOCK_UNDER_PARENT_PAGE, EDIT_CONTENT_BLOCK_PAGE,
|
||||
} from '@/router/module.names';
|
||||
import {LAYOUT_SIMPLE} from '@/router/core.constants';
|
||||
import createContentBlock from '@/pages/createContentBlock';
|
||||
import editContentBlock from '@/pages/editContentBlock';
|
||||
|
||||
const moduleBase = () => import(/* webpackChunkName: "modules" */'@/pages/module/module-base');
|
||||
const module = () => import(/* webpackChunkName: "modules" */'@/pages/module/module');
|
||||
|
|
@ -18,14 +20,15 @@ const settingsPage = () => import(/* webpackChunkName: "modules" */'@/pages/modu
|
|||
const snapshots = () => import(/* webpackChunkName: "modules" */'@/pages/snapshot/snapshots');
|
||||
const snapshot = () => import(/* webpackChunkName: "modules" */'@/pages/snapshot/snapshot');
|
||||
|
||||
const contentBlockFormMeta = {
|
||||
// layout: LAYOUT_SIMPLE,
|
||||
hideFooter: true,
|
||||
hideHeader: true,
|
||||
showSubNavigation: true
|
||||
};
|
||||
const createContentBlockRouteFragment = {
|
||||
component: createContentBlock,
|
||||
meta: {
|
||||
// layout: LAYOUT_SIMPLE,
|
||||
hideFooter: true,
|
||||
hideHeader: true,
|
||||
showSubNavigation: true
|
||||
},
|
||||
meta: contentBlockFormMeta,
|
||||
props: true
|
||||
};
|
||||
|
||||
|
|
@ -85,6 +88,13 @@ export default [
|
|||
fullWidth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'edit/:id',
|
||||
meta: contentBlockFormMeta,
|
||||
props: true,
|
||||
component: editContentBlock,
|
||||
name: EDIT_CONTENT_BLOCK_PAGE
|
||||
},
|
||||
{
|
||||
...createContentBlockRouteFragment,
|
||||
path: 'add-after/:after',
|
||||
|
|
|
|||
Loading…
Reference in New Issue