Show and disable content element actions based on context
This commit is contained in:
parent
ec5d942f5d
commit
3d57f42821
|
|
@ -9,3 +9,9 @@ export interface ContentBlock {
|
||||||
isAssignment: boolean;
|
isAssignment: boolean;
|
||||||
type: types;
|
type: types;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ActionOptions {
|
||||||
|
up?: boolean,
|
||||||
|
down?: boolean,
|
||||||
|
extended?: boolean
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
<add-content-link
|
<add-content-link
|
||||||
@click="addBlock(-1)"
|
@click="addBlock(-1)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Loop for outer contents layer -->
|
<!-- Loop for outer contents layer -->
|
||||||
<div
|
<div
|
||||||
class="content-list content-list--creator content-block-form__segment"
|
class="content-list content-list--creator content-block-form__segment"
|
||||||
|
|
@ -45,6 +46,7 @@
|
||||||
>
|
>
|
||||||
<content-element-actions
|
<content-element-actions
|
||||||
class="content-block-form__actions"
|
class="content-block-form__actions"
|
||||||
|
:actions="{extended: true, up: outer>0, down: outer<localContentBlock.contents.length }"
|
||||||
@remove="remove(outer)"
|
@remove="remove(outer)"
|
||||||
@move-up="up(outer)"
|
@move-up="up(outer)"
|
||||||
@move-down="down(outer)"
|
@move-down="down(outer)"
|
||||||
|
|
@ -61,8 +63,11 @@
|
||||||
:key="content.id"
|
:key="content.id"
|
||||||
>
|
>
|
||||||
<content-element
|
<content-element
|
||||||
|
:first-element="index===0"
|
||||||
|
:last-element="index===block.contents.length-1"
|
||||||
:element="content"
|
:element="content"
|
||||||
class="content-block-form__segment"
|
class="content-block-form__segment"
|
||||||
|
:top-level="false"
|
||||||
@update="update(index, $event, outer)"
|
@update="update(index, $event, outer)"
|
||||||
@remove="remove(outer, index, $event)"
|
@remove="remove(outer, index, $event)"
|
||||||
@up="up(outer, index)"
|
@up="up(outer, index)"
|
||||||
|
|
@ -78,10 +83,14 @@
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- If the block is a single element -->
|
<!-- If the block is a single element -->
|
||||||
<content-element
|
<content-element
|
||||||
:element="block"
|
:element="block"
|
||||||
class="content-block-form__segment"
|
class="content-block-form__segment"
|
||||||
|
:top-level="true"
|
||||||
|
:first-element="outer===0"
|
||||||
|
:last-element="outer===localContentBlock.contents.length-1"
|
||||||
v-else
|
v-else
|
||||||
@update="update(outer, $event)"
|
@update="update(outer, $event)"
|
||||||
@remove="remove(outer, undefined, $event)"
|
@remove="remove(outer, undefined, $event)"
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,11 @@
|
||||||
@change-type="changeType"
|
@change-type="changeType"
|
||||||
@remove="$emit('remove', false)"
|
@remove="$emit('remove', false)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Content Forms -->
|
<!-- Content Forms -->
|
||||||
<content-form-section
|
<content-form-section
|
||||||
:title="title"
|
:title="title"
|
||||||
:has-actions="true"
|
:actions="actions"
|
||||||
v-else
|
v-else
|
||||||
@top="$emit('top')"
|
@top="$emit('top')"
|
||||||
@up="$emit('up')"
|
@up="$emit('up')"
|
||||||
|
|
@ -44,6 +45,7 @@
|
||||||
<script>
|
<script>
|
||||||
import ContentFormSection from '@/components/content-block-form/ContentFormSection';
|
import ContentFormSection from '@/components/content-block-form/ContentFormSection';
|
||||||
import ContentElementActions from '@/components/content-block-form/ContentElementActions';
|
import ContentElementActions from '@/components/content-block-form/ContentElementActions';
|
||||||
|
|
||||||
const TrashIcon = () => import(/* webpackChunkName: "icons" */'@/components/icons/TrashIcon');
|
const TrashIcon = () => import(/* webpackChunkName: "icons" */'@/components/icons/TrashIcon');
|
||||||
const ContentBlockElementChooserWidget = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/ContentBlockElementChooserWidget');
|
const ContentBlockElementChooserWidget = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/ContentBlockElementChooserWidget');
|
||||||
const LinkForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/LinkForm');
|
const LinkForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/LinkForm');
|
||||||
|
|
@ -60,8 +62,21 @@
|
||||||
props: {
|
props: {
|
||||||
element: {
|
element: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null
|
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: {
|
components: {
|
||||||
|
|
@ -75,10 +90,17 @@
|
||||||
DocumentForm,
|
DocumentForm,
|
||||||
AssignmentForm,
|
AssignmentForm,
|
||||||
TextForm,
|
TextForm,
|
||||||
SubtitleForm
|
SubtitleForm,
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
actions() {
|
||||||
|
return {
|
||||||
|
up: !this.firstElement,
|
||||||
|
down: !this.lastElement,
|
||||||
|
extended: this.topLevel,
|
||||||
|
};
|
||||||
|
},
|
||||||
isChooser() {
|
isChooser() {
|
||||||
return this.component === CHOOSER;
|
return this.component === CHOOSER;
|
||||||
},
|
},
|
||||||
|
|
@ -93,7 +115,7 @@
|
||||||
},
|
},
|
||||||
icon() {
|
icon() {
|
||||||
return this.type.icon;
|
return this.type.icon;
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -103,49 +125,49 @@
|
||||||
return {
|
return {
|
||||||
component: 'subtitle-form',
|
component: 'subtitle-form',
|
||||||
title: 'Untertitel',
|
title: 'Untertitel',
|
||||||
icon: 'title-icon'
|
icon: 'title-icon',
|
||||||
};
|
};
|
||||||
case 'link_block':
|
case 'link_block':
|
||||||
return {
|
return {
|
||||||
component: 'link-form',
|
component: 'link-form',
|
||||||
title: 'Link',
|
title: 'Link',
|
||||||
icon: 'link-icon'
|
icon: 'link-icon',
|
||||||
};
|
};
|
||||||
case 'video_block':
|
case 'video_block':
|
||||||
return {
|
return {
|
||||||
component: 'video-form',
|
component: 'video-form',
|
||||||
title: 'Video',
|
title: 'Video',
|
||||||
icon: 'video-icon'
|
icon: 'video-icon',
|
||||||
};
|
};
|
||||||
case 'image_url_block':
|
case 'image_url_block':
|
||||||
return {
|
return {
|
||||||
component: 'image-form',
|
component: 'image-form',
|
||||||
title: 'Bild',
|
title: 'Bild',
|
||||||
icon: 'image-icon'
|
icon: 'image-icon',
|
||||||
};
|
};
|
||||||
case 'text_block':
|
case 'text_block':
|
||||||
return {
|
return {
|
||||||
component: 'text-form',
|
component: 'text-form',
|
||||||
title: 'Text',
|
title: 'Text',
|
||||||
icon: 'text-icon'
|
icon: 'text-icon',
|
||||||
};
|
};
|
||||||
case 'assignment':
|
case 'assignment':
|
||||||
return {
|
return {
|
||||||
component: 'assignment-form',
|
component: 'assignment-form',
|
||||||
title: 'Aufgabe & Ergebnis',
|
title: 'Aufgabe & Ergebnis',
|
||||||
icon: 'speech-bubble-icon'
|
icon: 'speech-bubble-icon',
|
||||||
};
|
};
|
||||||
case 'document_block':
|
case 'document_block':
|
||||||
return {
|
return {
|
||||||
component: 'document-form',
|
component: 'document-form',
|
||||||
title: 'Dokument',
|
title: 'Dokument',
|
||||||
icon: 'document-icon'
|
icon: 'document-icon',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
component: CHOOSER,
|
component: CHOOSER,
|
||||||
title: '',
|
title: '',
|
||||||
icon: ''
|
icon: '',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
_updateProperty(value, key) {
|
_updateProperty(value, key) {
|
||||||
|
|
@ -231,7 +253,7 @@
|
||||||
if (convertToList) {
|
if (convertToList) {
|
||||||
el = {
|
el = {
|
||||||
type: 'content_list_item',
|
type: 'content_list_item',
|
||||||
contents: [el]
|
contents: [el],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.update(el);
|
this.update(el);
|
||||||
|
|
@ -242,7 +264,7 @@
|
||||||
switchToDocument(value) {
|
switchToDocument(value) {
|
||||||
this.changeType('document_block', value);
|
this.changeType('document_block', value);
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,14 @@
|
||||||
:large="true"
|
:large="true"
|
||||||
icon="arrow-thin-top"
|
icon="arrow-thin-top"
|
||||||
text="Ganz nach oben verschieben"
|
text="Ganz nach oben verschieben"
|
||||||
|
:disabled="!actions.up"
|
||||||
|
v-if="actions.extended"
|
||||||
@click="emitAndClose('move-top')"
|
@click="emitAndClose('move-top')"
|
||||||
/>
|
/>
|
||||||
<button-with-icon-and-text
|
<button-with-icon-and-text
|
||||||
class="content-element-actions__button"
|
class="content-element-actions__button"
|
||||||
:large="true"
|
:large="true"
|
||||||
|
:disabled="!actions.up"
|
||||||
icon="arrow-thin-up"
|
icon="arrow-thin-up"
|
||||||
text="Nach oben verschieben"
|
text="Nach oben verschieben"
|
||||||
@click="emitAndClose('move-up')"
|
@click="emitAndClose('move-up')"
|
||||||
|
|
@ -30,6 +33,7 @@
|
||||||
<button-with-icon-and-text
|
<button-with-icon-and-text
|
||||||
class="content-element-actions__button"
|
class="content-element-actions__button"
|
||||||
:large="true"
|
:large="true"
|
||||||
|
:disabled="!actions.down"
|
||||||
icon="arrow-thin-down"
|
icon="arrow-thin-down"
|
||||||
text="Nach unten verschieben"
|
text="Nach unten verschieben"
|
||||||
@click="emitAndClose('move-down')"
|
@click="emitAndClose('move-down')"
|
||||||
|
|
@ -37,8 +41,10 @@
|
||||||
<button-with-icon-and-text
|
<button-with-icon-and-text
|
||||||
class="content-element-actions__button"
|
class="content-element-actions__button"
|
||||||
:large="true"
|
:large="true"
|
||||||
|
:disabled="!actions.down"
|
||||||
icon="arrow-thin-bottom"
|
icon="arrow-thin-bottom"
|
||||||
text="Ganz nach unten verschieben"
|
text="Ganz nach unten verschieben"
|
||||||
|
v-if="actions.extended"
|
||||||
@click="emitAndClose('move-bottom')"
|
@click="emitAndClose('move-bottom')"
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -56,20 +62,31 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
import WidgetPopover from '@/components/ui/WidgetPopover';
|
import Vue from 'vue';
|
||||||
import Ellipses from '@/components/icons/Ellipses';
|
import WidgetPopover from '@/components/ui/WidgetPopover.vue';
|
||||||
import ButtonWithIconAndText from '@/components/ui/ButtonWithIconAndText';
|
import Ellipses from '@/components/icons/Ellipses.vue';
|
||||||
|
import ButtonWithIconAndText from '@/components/ui/ButtonWithIconAndText.vue';
|
||||||
|
import {ActionOptions} from "@/@types";
|
||||||
|
|
||||||
export default {
|
interface Data {
|
||||||
|
show: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
props: {
|
||||||
|
actions: {
|
||||||
|
type: Object as () => ActionOptions
|
||||||
|
},
|
||||||
|
},
|
||||||
components: {ButtonWithIconAndText, Ellipses, WidgetPopover},
|
components: {ButtonWithIconAndText, Ellipses, WidgetPopover},
|
||||||
|
|
||||||
data: () => ({
|
data: (): Data => ({
|
||||||
show: false,
|
show: false,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
toggle(show) {
|
toggle(show: boolean) {
|
||||||
this.show = show;
|
this.show = show;
|
||||||
},
|
},
|
||||||
close() {
|
close() {
|
||||||
|
|
@ -91,12 +108,12 @@
|
||||||
this.$emit('move-bottom');
|
this.$emit('move-bottom');
|
||||||
this.close();
|
this.close();
|
||||||
},
|
},
|
||||||
emitAndClose(event) {
|
emitAndClose(event: string) {
|
||||||
this.$emit(event);
|
this.$emit(event);
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@
|
||||||
|
|
||||||
<content-element-actions
|
<content-element-actions
|
||||||
class="content-form-section__actions"
|
class="content-form-section__actions"
|
||||||
v-if="hasActions"
|
:actions="actions"
|
||||||
|
v-if="actions"
|
||||||
@remove="$emit('remove')"
|
@remove="$emit('remove')"
|
||||||
@move-top="$emit('top')"
|
@move-top="$emit('top')"
|
||||||
@move-up="$emit('up')"
|
@move-up="$emit('up')"
|
||||||
|
|
@ -22,9 +23,11 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
import formElementIcons from '@/components/ui/form-element-icons';
|
import formElementIcons from '@/components/ui/form-element-icons.js';
|
||||||
import ContentElementActions from '@/components/content-block-form/ContentElementActions';
|
import ContentElementActions from '@/components/content-block-form/ContentElementActions.vue';
|
||||||
|
import {ActionOptions} from "@/@types";
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -36,9 +39,9 @@
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
hasActions: {
|
actions: {
|
||||||
type: Boolean,
|
type: Object as () => ActionOptions,
|
||||||
default: false
|
default: () => {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<a
|
<button
|
||||||
:class="[ 'button-with-icon-and-text', {'button-with-icon-and-text--large': large}]"
|
:class="['button', 'button-with-icon-and-text', {'button-with-icon-and-text--large': large}]"
|
||||||
|
:disabled="disabled"
|
||||||
@click="$emit('click')"
|
@click="$emit('click')"
|
||||||
>
|
>
|
||||||
<component
|
<component
|
||||||
|
|
@ -8,7 +9,7 @@
|
||||||
:is="icon"
|
:is="icon"
|
||||||
/>
|
/>
|
||||||
<span class="button-with-icon-and-text__text">{{ text }}</span>
|
<span class="button-with-icon-and-text__text">{{ text }}</span>
|
||||||
</a>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -27,6 +28,10 @@
|
||||||
large: {
|
large: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -43,6 +48,13 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
border: 0;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background-color: transparent;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
&__icon {
|
&__icon {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue