Show and disable content element actions based on context

This commit is contained in:
Ramon Wenger 2022-02-28 14:02:53 +01:00
parent ec5d942f5d
commit 3d57f42821
6 changed files with 103 additions and 34 deletions

View File

@ -9,3 +9,9 @@ export interface ContentBlock {
isAssignment: boolean; isAssignment: boolean;
type: types; type: types;
} }
export interface ActionOptions {
up?: boolean,
down?: boolean,
extended?: boolean
}

View File

@ -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)"

View File

@ -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>

View File

@ -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">

View File

@ -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: {

View File

@ -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;