203 lines
5.4 KiB
Vue
203 lines
5.4 KiB
Vue
<template>
|
|
<div class="content-block__container">
|
|
<div class="content-block" :class="specialClass">
|
|
<div class="content-block__actions">
|
|
<a @click="toggleVisibility()" v-if="canManageContent" class="content-block__action-button">
|
|
<eye-icon class="content-block__action-icon"></eye-icon>
|
|
</a>
|
|
<visibility-popover
|
|
@hide-me="showVisibility = false"
|
|
:show="showVisibility"
|
|
:content-block="contentBlock"
|
|
class="content-block__visibility-menu"
|
|
></visibility-popover>
|
|
<a @click="editContentBlock()" v-if="contentBlock.mine" class="content-block__action-button">
|
|
<pen-icon class="content-block__action-icon"></pen-icon>
|
|
</a>
|
|
<a @click="deleteContentBlock(contentBlock.id)" v-if="contentBlock.mine" class="content-block__action-button">
|
|
<trash-icon class="content-block__action-icon"></trash-icon>
|
|
</a>
|
|
</div>
|
|
|
|
<h4 class="content-block__title">{{contentBlock.title}}</h4>
|
|
|
|
<component v-for="component in contentBlock.contents"
|
|
:key="component.id"
|
|
:is="component.type"
|
|
v-bind="component">
|
|
</component>
|
|
|
|
</div>
|
|
|
|
<add-content-block-button :after="contentBlock.id"></add-content-block-button>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<script>
|
|
import TextBlock from '@/components/content-blocks/TextBlock';
|
|
import BasicKnowledgeWidget from '@/components/content-blocks/BasicKnowledgeWidget';
|
|
import Task from '@/components/content-blocks/Task';
|
|
import ImageBlock from '@/components/content-blocks/ImageBlock';
|
|
import ImageUrlBlock from '@/components/content-blocks/ImageUrlBlock';
|
|
import VideoBlock from '@/components/content-blocks/VideoBlock';
|
|
import LinkBlock from '@/components/content-blocks/LinkBlock';
|
|
import DocumentBlock from '@/components/content-blocks/DocumentBlock';
|
|
import Assignment from '@/components/content-blocks/assignment/Assignment';
|
|
import AddContentBlockButton from '@/components/AddContentBlockButton';
|
|
import VisibilityPopover from '@/components/VisibilityPopover';
|
|
import EyeIcon from '@/components/icons/EyeIcon';
|
|
import PenIcon from '@/components/icons/PenIcon';
|
|
import TrashIcon from '@/components/icons/TrashIcon';
|
|
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
|
import CHAPTER_QUERY from '@/graphql/gql/chapterQuery.gql';
|
|
import DELETE_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/deleteContentBlock.gql';
|
|
|
|
export default {
|
|
props: ['contentBlock', 'parent'],
|
|
|
|
components: {
|
|
'text_block': TextBlock,
|
|
'basic_knowledge': BasicKnowledgeWidget,
|
|
'image_block': ImageBlock,
|
|
'image_url_block': ImageUrlBlock,
|
|
'video_block': VideoBlock,
|
|
'link_block': LinkBlock,
|
|
'document_block': DocumentBlock,
|
|
Assignment,
|
|
Task,
|
|
AddContentBlockButton,
|
|
VisibilityPopover,
|
|
EyeIcon,
|
|
PenIcon,
|
|
TrashIcon
|
|
},
|
|
|
|
computed: {
|
|
specialClass() {
|
|
return `content-block--${this.contentBlock.type.toLowerCase()}`
|
|
},
|
|
canManageContent() {
|
|
return this.me.permissions.includes('users.can_manage_school_class_content');
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
toggleVisibility() {
|
|
this.showVisibility = !this.showVisibility;
|
|
},
|
|
editContentBlock() {
|
|
this.$store.dispatch('editContentBlock', this.contentBlock.id);
|
|
},
|
|
deleteContentBlock(id) {
|
|
const parent = this.parent;
|
|
this.$apollo.mutate({
|
|
mutation: DELETE_CONTENT_BLOCK_MUTATION,
|
|
variables: {
|
|
input: {
|
|
id: id
|
|
}
|
|
},
|
|
update(store, {data: {deleteContentBlock: {success}}}) {
|
|
try {
|
|
if (success) {
|
|
const query = CHAPTER_QUERY;
|
|
const variables = {
|
|
id: parent
|
|
};
|
|
const data = store.readQuery({query, variables});
|
|
data.chapter.contentBlocks.edges.splice(data.chapter.contentBlocks.edges.findIndex(edge => edge.node.id === id), 1);
|
|
store.writeQuery({query, variables, data});
|
|
}
|
|
} catch (e) {
|
|
// Query did not exist in the cache, and apollo throws a generic Error. Do nothing
|
|
}
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
apollo: {
|
|
me: {
|
|
query: ME_QUERY,
|
|
},
|
|
},
|
|
|
|
data() {
|
|
return {
|
|
showVisibility: false,
|
|
me: {
|
|
permissions: []
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
@import "@/styles/_variables.scss";
|
|
@import "@/styles/_mixins.scss";
|
|
|
|
.content-block {
|
|
margin-bottom: 2.5em;
|
|
position: relative;
|
|
|
|
&__title {
|
|
line-height: 1.5;
|
|
}
|
|
|
|
&__actions {
|
|
position: absolute;
|
|
left: -70px;
|
|
top: -4px;
|
|
display: grid;
|
|
}
|
|
|
|
&__action-button {
|
|
cursor: pointer;
|
|
}
|
|
|
|
&__action-icon {
|
|
width: 40px;
|
|
height: 40px;
|
|
fill: $color-grey;
|
|
}
|
|
|
|
&__visibility-menu {
|
|
top: 40px;
|
|
}
|
|
|
|
&--base_communication {
|
|
@include content-box($color-accent-1);
|
|
}
|
|
|
|
&--task {
|
|
@include content-box($color-brand);
|
|
}
|
|
|
|
&--base_society {
|
|
@include content-box($color-accent-2);
|
|
}
|
|
|
|
/deep/ p {
|
|
line-height: 1.5;
|
|
margin-bottom: 1em;
|
|
|
|
&:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
}
|
|
|
|
/deep/ ul {
|
|
padding-left: 25px;
|
|
}
|
|
|
|
/deep/ li {
|
|
list-style: disc;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
}
|
|
</style>
|