Files
mixtape/zero.Web.UI/App/editor/fields/nested.vue
T

157 lines
3.4 KiB
Vue
Raw Normal View History

2020-06-25 16:15:23 +02:00
<template>
2020-06-30 12:12:31 +02:00
<div class="editor-nested" :depth="depth">
2020-09-10 15:16:45 +02:00
<div class="ui-pick-previews" v-if="items.length">
<div v-for="(item, index) in items" class="ui-pick-preview">
2020-10-20 13:27:17 +02:00
<ui-select-button :icon="getIcon(item)" :label="getName(item)" :description="getDescription(item)" :disabled="disabled" @click="editItem(item)" />
2020-09-17 11:26:23 +02:00
<ui-icon-button v-if="!disabled" icon="fth-x" title="@ui.close" @click="removeItem(index)" :disabled="disabled" />
2020-06-25 16:15:23 +02:00
</div>
</div>
2020-10-20 13:27:17 +02:00
<ui-select-button v-if="limit > items.length" icon="fth-plus" :label="addLabel || '@ui.add'" @click="addItem" :disabled="disabled" />
2020-06-25 16:15:23 +02:00
</div>
</template>
<script>
2020-11-01 22:20:29 +01:00
import UiEditor from 'zero/editor/editor.vue';
import UiEditorOverlay from 'zero/editor/editor-overlay.vue';
import Overlay from 'zero/helpers/overlay.js';
2020-11-01 23:23:36 +01:00
import Editor from 'zero/core/editor.ts';
2020-06-29 18:20:43 +02:00
2020-06-25 16:15:23 +02:00
export default {
2020-06-29 18:20:43 +02:00
components: { UiEditor },
2020-06-25 16:15:23 +02:00
props: {
2020-10-20 13:27:17 +02:00
value: [Array, Object],
meta: Object,
depth: Number,
disabled: Boolean,
editor: {
2020-11-01 23:23:36 +01:00
type: Object,
2020-10-20 13:27:17 +02:00
required: true
2020-06-25 16:15:23 +02:00
},
2020-10-20 13:27:17 +02:00
limit: {
2020-06-30 12:12:31 +02:00
type: Number,
2020-10-20 13:27:17 +02:00
default: 100
2020-06-30 12:12:31 +02:00
},
2020-10-20 13:27:17 +02:00
title: String,
addLabel: String,
itemLabel: Function,
itemDescription: Function,
itemIcon: [String, Function],
template: {
type: Object,
required: true
}
},
watch: {
value: {
deep: true,
handler(val)
{
this.setup();
}
}
2020-06-25 16:15:23 +02:00
},
data: () => ({
2020-09-10 16:12:06 +02:00
items: [],
2020-09-29 14:15:22 +02:00
multiple: false
2020-06-25 16:15:23 +02:00
}),
2020-06-30 12:12:31 +02:00
mounted()
{
2020-10-20 13:27:17 +02:00
this.setup();
2020-06-30 12:12:31 +02:00
},
2020-06-25 16:15:23 +02:00
methods: {
2020-10-20 13:27:17 +02:00
setup()
{
this.items = JSON.parse(JSON.stringify(this.value)) || [];
this.multiple = this.limit > 1;
if (!this.multiple)
{
this.items = this.items ? [this.items] : [];
}
},
2020-06-30 12:12:31 +02:00
getNewItem()
{
2020-10-20 13:27:17 +02:00
return JSON.parse(JSON.stringify(this.template || {}));
2020-06-30 12:12:31 +02:00
},
2020-06-25 16:15:23 +02:00
addItem()
{
2020-09-10 16:12:06 +02:00
if (this.limit <= this.items.length)
{
return;
}
2020-09-10 15:16:45 +02:00
this.editItem(this.getNewItem(), true);
this.onChange();
2020-06-29 18:20:43 +02:00
},
2020-09-10 15:16:45 +02:00
editItem(item, isAdd)
2020-06-29 18:20:43 +02:00
{
2020-09-10 15:16:45 +02:00
// open editing overlay
return Overlay.open({
component: UiEditorOverlay,
display: 'editor',
2020-10-20 13:27:17 +02:00
editor: this.editor,
title: this.title || '@ui.edit.title',
2020-09-10 15:16:45 +02:00
model: item,
width: 1100,
create: isAdd
}).then(value =>
{
if (isAdd)
{
this.items.push(value);
}
else
{
const index = this.items.indexOf(item);
this.removeItem(index);
this.items.splice(index, 0, value);
}
this.onChange();
});
2020-06-29 18:20:43 +02:00
},
removeItem(index)
{
this.items.splice(index, 1);
this.onChange();
2020-06-29 18:20:43 +02:00
},
onChange()
2020-06-29 18:20:43 +02:00
{
2020-09-29 14:15:22 +02:00
this.$emit('input', this.multiple ? this.items : (this.items.length > 0 ? this.items[0] : null));
},
getName(item)
{
2020-10-20 13:27:17 +02:00
return typeof this.itemLabel === 'function' ? this.itemLabel(item) : 'Item';
},
getDescription(item)
{
2020-10-20 13:27:17 +02:00
return typeof this.itemDescription === 'function' ? this.itemDescription(item) : '';
},
getIcon(item)
{
return typeof this.itemIcon === 'function' ? this.itemIcon(item) : this.itemIcon;
2020-06-25 16:15:23 +02:00
}
}
}
2020-09-10 15:16:45 +02:00
</script>