Files
mixtape/zero.Backoffice.UI/app/modules/pages/picker/ui-pagepicker.vue
T
2022-01-12 23:52:37 +01:00

212 lines
4.8 KiB
Vue

<template>
<div class="ui-pagepicker" :class="{'is-disabled': disabled }">
<input ref="input" type="hidden" :value="value" />
<div class="ui-pagepicker-previews" v-if="previews.length > 0">
<div v-for="preview in previews" class="ui-pagepicker-preview">
<ui-select-button :icon="preview.icon" :label="preview.name" :description="preview.text" :disabled="disabled" @click="pick(preview.id)" :tokens="{ id: preview.id }" />
<ui-icon-button v-if="!disabled" @click="remove(preview.id)" icon="fth-x" title="@ui.close" />
</div>
</div>
<ui-select-button v-if="canAdd" icon="fth-plus" :label="limit > 1 ? '@ui.add' : '@ui.select'" @click="pick()" :disabled="disabled" />
</div>
</template>
<script lang="ts">
import api from '../api';
import * as overlays from '../../../services/overlay';
export default {
name: 'uiPagepicker',
props: {
value: {
type: [String, Array],
default: null
},
model: Object,
limit: {
type: Number,
default: 1
},
disabledIds: {
type: [Array, Function],
default: []
},
disabled: {
type: Boolean,
default: false
},
rootId: {
type: [String, Function],
default: null
},
options: {
type: Object,
default: () => { }
}
},
data: () => ({
previews: []
}),
watch: {
value()
{
this.updatePreviews();
}
},
computed: {
multiple()
{
return this.limit > 1;
},
canAdd()
{
let count = Array.isArray(this.value) ? this.value.length : (!this.value ? 0 : 1);
return !this.disabled && count < this.limit;
}
},
mounted()
{
this.updatePreviews();
},
methods: {
onChange(value)
{
this.$emit('change', value);
this.$emit('input', value);
this.$emit('update:value', value);
// TODO this does not trigger the forms dirty flag
},
async updatePreviews()
{
if (!this.value || (Array.isArray(this.value) && !this.value.length))
{
this.previews = [];
return;
}
let ids = Array.isArray(this.value) ? this.value : [this.value];
const result = await api.getPreviews(ids);
this.previews = result.data;
},
remove(id)
{
if (Array.isArray(this.value))
{
let index = this.value.indexOf(id);
this.value.splice(index, 1);
this.onChange(this.value);
}
else
{
this.onChange(this.limit > 1 ? [] : null);
}
},
async pick(id)
{
if (this.disabled)
{
return;
}
let disabledIds = [];
if (!!this.value && !Array.isArray(this.value))
{
disabledIds = [this.value];
}
else if (Array.isArray(this.value))
{
disabledIds = this.value;
}
disabledIds.push(this.model.id);
if (typeof this.disabledIds === 'function')
{
let moreDisabledIds = this.disabledIds(this.model) || [];
disabledIds.push(...moreDisabledIds);
}
else if (this.disabledIds.length > 0)
{
disabledIds.push(...this.disabledIds);
}
const result = await overlays.open({
title: '@page.picker.headline',
closeLabel: '@ui.close',
component: () => import('./overlay.vue'),
display: 'editor',
model: this.multiple ? id : this.value,
rootId: typeof this.rootId === 'function' ? this.rootId(this.model) : this.rootId,
disabledIds: disabledIds
});
if (result.eventType == 'confirm')
{
if (this.multiple)
{
if (!this.value || !Array.isArray(this.value))
{
this.onChange([result.value.id]);
}
else if (this.value.indexOf(result.value.id) < 0)
{
if (id)
{
this.remove(id);
}
this.value.push(result.value.id);
this.onChange(this.value);
}
}
else
{
this.onChange(result.value ? result.value.id : null);
}
}
}
}
}
</script>
<style lang="scss">
.ui-pagepicker-preview
{
display: flex;
justify-content: space-between;
align-items: center;
.ui-icon-button
{
height: 24px;
width: 24px;
//background: none;
i
{
font-size: 13px;
}
}
}
.ui-pagepicker-previews + .ui-select-button,
.ui-pagepicker-preview + .ui-pagepicker-preview
{
margin-top: 10px;
}
</style>