mirror of
https://github.com/directus/directus.git
synced 2026-01-27 14:28:12 -05:00
script[setup]: interfaces/list (#18423)
This commit is contained in:
@@ -82,274 +82,211 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { defineComponent, PropType, computed, ref, toRefs } from 'vue';
|
||||
import { computed, ref, toRefs } from 'vue';
|
||||
import { Field } from '@directus/types';
|
||||
import Draggable from 'vuedraggable';
|
||||
import { i18n } from '@/lang';
|
||||
import { renderStringTemplate } from '@/utils/render-string-template';
|
||||
import { hideDragImage } from '@/utils/hide-drag-image';
|
||||
import formatTitle from '@directus/format-title';
|
||||
import { isEqual, sortBy } from 'lodash';
|
||||
|
||||
export default defineComponent({
|
||||
components: { Draggable },
|
||||
props: {
|
||||
value: {
|
||||
type: Array as PropType<Record<string, any>[]>,
|
||||
default: null,
|
||||
},
|
||||
fields: {
|
||||
type: Array as PropType<Partial<Field>[]>,
|
||||
default: () => [],
|
||||
},
|
||||
template: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
addLabel: {
|
||||
type: String,
|
||||
default: () => i18n.global.t('create_new'),
|
||||
},
|
||||
sort: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
headerPlaceholder: {
|
||||
type: String,
|
||||
default: () => i18n.global.t('empty_item'),
|
||||
},
|
||||
collection: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: () => i18n.global.t('no_items'),
|
||||
},
|
||||
direction: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
emits: ['input'],
|
||||
setup(props, { emit }) {
|
||||
const { t } = useI18n();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
value: Record<string, unknown>[] | null;
|
||||
fields?: Partial<Field>[];
|
||||
template?: string;
|
||||
addLabel?: string;
|
||||
sort?: string;
|
||||
limit?: number;
|
||||
disabled?: boolean;
|
||||
headerPlaceholder?: string;
|
||||
collection?: string;
|
||||
placeholder?: string;
|
||||
direction?: string;
|
||||
}>(),
|
||||
{
|
||||
fields: () => [],
|
||||
addLabel: () => i18n.global.t('create_new'),
|
||||
headerPlaceholder: () => i18n.global.t('empty_item'),
|
||||
placeholder: () => i18n.global.t('no_items'),
|
||||
}
|
||||
);
|
||||
|
||||
const active = ref<number | null>(null);
|
||||
const drawerOpen = computed(() => active.value !== null);
|
||||
const { value } = toRefs(props);
|
||||
const emit = defineEmits<{
|
||||
(e: 'input', value: Record<string, unknown>[] | null): void;
|
||||
}>();
|
||||
|
||||
const templateWithDefaults = computed(() =>
|
||||
props.fields?.[0]?.field ? props.template || `{{${props.fields[0].field}}}` : ''
|
||||
);
|
||||
const { t } = useI18n();
|
||||
|
||||
const showAddNew = computed(() => {
|
||||
if (props.disabled) return false;
|
||||
if (props.value === null) return true;
|
||||
if (props.limit === null) return true;
|
||||
if (Array.isArray(props.value) && props.value.length < props.limit) return true;
|
||||
return false;
|
||||
});
|
||||
const active = ref<number | null>(null);
|
||||
const drawerOpen = computed(() => active.value !== null);
|
||||
const { value } = toRefs(props);
|
||||
|
||||
const activeItem = computed(() => (active.value !== null ? edits.value : null));
|
||||
const templateWithDefaults = computed(() =>
|
||||
props.fields?.[0]?.field ? props.template || `{{${props.fields[0].field}}}` : ''
|
||||
);
|
||||
|
||||
const isSaveDisabled = computed(() => {
|
||||
for (const field of props.fields) {
|
||||
if (
|
||||
field.meta?.required &&
|
||||
field.field &&
|
||||
(edits.value[field.field] === null || edits.value[field.field] === undefined)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const showAddNew = computed(() => {
|
||||
if (props.disabled) return false;
|
||||
if (props.value === null) return true;
|
||||
if (props.limit === undefined) return true;
|
||||
if (Array.isArray(props.value) && props.value.length < props.limit) return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
const activeItem = computed(() => (active.value !== null ? edits.value : null));
|
||||
|
||||
const { displayValue } = renderStringTemplate(templateWithDefaults, activeItem);
|
||||
const isSaveDisabled = computed(() => {
|
||||
for (const field of props.fields) {
|
||||
if (
|
||||
field.meta?.required &&
|
||||
field.field &&
|
||||
(edits.value[field.field] === null || edits.value[field.field] === undefined)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const defaults = computed(() => {
|
||||
const values: Record<string, any> = {};
|
||||
return false;
|
||||
});
|
||||
|
||||
for (const field of props.fields) {
|
||||
if (field.schema?.default_value !== undefined && field.schema?.default_value !== null) {
|
||||
values[field.field!] = field.schema.default_value;
|
||||
}
|
||||
}
|
||||
const { displayValue } = renderStringTemplate(templateWithDefaults, activeItem);
|
||||
|
||||
return values;
|
||||
});
|
||||
const defaults = computed(() => {
|
||||
const values: Record<string, any> = {};
|
||||
|
||||
const fieldsWithNames = computed(() =>
|
||||
props.fields?.map((field) => {
|
||||
return {
|
||||
...field,
|
||||
name: formatTitle(field.name ?? field.field!),
|
||||
};
|
||||
})
|
||||
);
|
||||
for (const field of props.fields) {
|
||||
if (field.schema?.default_value !== undefined && field.schema?.default_value !== null) {
|
||||
values[field.field!] = field.schema.default_value;
|
||||
}
|
||||
}
|
||||
|
||||
const internalValue = computed({
|
||||
get: () => {
|
||||
if (props.fields && props.sort) return sortBy(value.value, props.sort);
|
||||
return value.value;
|
||||
},
|
||||
set: (newVal) => {
|
||||
value.value = props.fields && props.sort ? sortBy(value.value, props.sort) : newVal;
|
||||
},
|
||||
});
|
||||
|
||||
const isNewItem = ref(false);
|
||||
const edits = ref({} as Record<string, any>);
|
||||
const confirmDiscard = ref(false);
|
||||
return values;
|
||||
});
|
||||
|
||||
const fieldsWithNames = computed(() =>
|
||||
props.fields?.map((field) => {
|
||||
return {
|
||||
t,
|
||||
internalValue,
|
||||
updateValues,
|
||||
removeItem,
|
||||
addNew,
|
||||
showAddNew,
|
||||
hideDragImage,
|
||||
active,
|
||||
drawerOpen,
|
||||
displayValue,
|
||||
activeItem,
|
||||
isSaveDisabled,
|
||||
closeDrawer,
|
||||
onSort,
|
||||
templateWithDefaults,
|
||||
defaults,
|
||||
fieldsWithNames,
|
||||
isNewItem,
|
||||
edits,
|
||||
confirmDiscard,
|
||||
openItem,
|
||||
saveItem,
|
||||
trackEdits,
|
||||
checkDiscard,
|
||||
discardAndLeave,
|
||||
...field,
|
||||
name: formatTitle(field.name ?? field.field!),
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
function openItem(index: number) {
|
||||
isNewItem.value = false;
|
||||
|
||||
edits.value = { ...internalValue.value[index] };
|
||||
active.value = index;
|
||||
}
|
||||
|
||||
function saveItem(index: number) {
|
||||
isNewItem.value = false;
|
||||
|
||||
updateValues(index, edits.value);
|
||||
closeDrawer();
|
||||
}
|
||||
|
||||
function trackEdits(updatedValues: any) {
|
||||
const combinedValues = Object.assign({}, defaults.value, updatedValues);
|
||||
Object.assign(edits.value, combinedValues);
|
||||
}
|
||||
|
||||
function checkDiscard() {
|
||||
if (active.value !== null && !isEqual(edits.value, internalValue.value[active.value])) {
|
||||
confirmDiscard.value = true;
|
||||
} else {
|
||||
closeDrawer();
|
||||
}
|
||||
}
|
||||
|
||||
function discardAndLeave() {
|
||||
closeDrawer();
|
||||
confirmDiscard.value = false;
|
||||
}
|
||||
|
||||
function updateValues(index: number, updatedValues: any) {
|
||||
const newValue = internalValue.value.map((item: any, i: number) => {
|
||||
if (i === index) {
|
||||
return updatedValues;
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
if (props.fields && props.sort) {
|
||||
emitValue(sortBy(newValue, props.sort));
|
||||
} else {
|
||||
emitValue(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
function removeItem(item: Record<string, any>) {
|
||||
if (value.value) {
|
||||
emitValue(internalValue.value.filter((i) => i !== item));
|
||||
} else {
|
||||
emitValue(null);
|
||||
}
|
||||
}
|
||||
|
||||
function addNew() {
|
||||
isNewItem.value = true;
|
||||
|
||||
const newDefaults: any = {};
|
||||
|
||||
props.fields.forEach((field) => {
|
||||
newDefaults[field.field!] = field.schema?.default_value;
|
||||
});
|
||||
|
||||
if (Array.isArray(internalValue.value)) {
|
||||
emitValue([...internalValue.value, newDefaults]);
|
||||
} else {
|
||||
if (internalValue.value != null) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
'The repeater interface expects an array as value, but the given value is no array. Overriding given value.'
|
||||
);
|
||||
}
|
||||
|
||||
emitValue([newDefaults]);
|
||||
}
|
||||
|
||||
edits.value = { ...newDefaults };
|
||||
active.value = (internalValue.value || []).length;
|
||||
}
|
||||
|
||||
function emitValue(value: null | any[]) {
|
||||
if (!value || value.length === 0) {
|
||||
return emit('input', null);
|
||||
}
|
||||
|
||||
return emit('input', value);
|
||||
}
|
||||
|
||||
function onSort(sortedItems: any[]) {
|
||||
if (sortedItems === null || sortedItems.length === 0) {
|
||||
return emit('input', null);
|
||||
}
|
||||
|
||||
return emit('input', sortedItems);
|
||||
}
|
||||
|
||||
function closeDrawer() {
|
||||
if (isNewItem.value) {
|
||||
emitValue(internalValue.value.slice(0, -1));
|
||||
}
|
||||
|
||||
edits.value = {};
|
||||
active.value = null;
|
||||
}
|
||||
const internalValue = computed({
|
||||
get: () => {
|
||||
if (props.fields && props.sort) return sortBy(value.value, props.sort);
|
||||
return value.value;
|
||||
},
|
||||
set: (newVal) => {
|
||||
value.value = props.fields && props.sort ? sortBy(value.value, props.sort) : newVal;
|
||||
},
|
||||
});
|
||||
|
||||
const isNewItem = ref(false);
|
||||
const edits = ref({} as Record<string, any>);
|
||||
const confirmDiscard = ref(false);
|
||||
|
||||
function openItem(index: number) {
|
||||
isNewItem.value = false;
|
||||
|
||||
edits.value = { ...internalValue.value?.[index] };
|
||||
active.value = index;
|
||||
}
|
||||
|
||||
function saveItem(index: number) {
|
||||
isNewItem.value = false;
|
||||
|
||||
updateValues(index, edits.value);
|
||||
closeDrawer();
|
||||
}
|
||||
|
||||
function trackEdits(updatedValues: any) {
|
||||
const combinedValues = Object.assign({}, defaults.value, updatedValues);
|
||||
Object.assign(edits.value, combinedValues);
|
||||
}
|
||||
|
||||
function checkDiscard() {
|
||||
if (active.value !== null && !isEqual(edits.value, internalValue.value?.[active.value])) {
|
||||
confirmDiscard.value = true;
|
||||
} else {
|
||||
closeDrawer();
|
||||
}
|
||||
}
|
||||
|
||||
function discardAndLeave() {
|
||||
closeDrawer();
|
||||
confirmDiscard.value = false;
|
||||
}
|
||||
|
||||
function updateValues(index: number, updatedValues: any) {
|
||||
const newValue = internalValue.value?.map((item: any, i: number) => {
|
||||
if (i === index) {
|
||||
return updatedValues;
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
if (props.fields && props.sort) {
|
||||
emitValue(sortBy(newValue, props.sort));
|
||||
} else {
|
||||
emitValue(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
function removeItem(item: Record<string, any>) {
|
||||
if (value.value) {
|
||||
emitValue(internalValue.value?.filter((i) => i !== item));
|
||||
} else {
|
||||
emitValue();
|
||||
}
|
||||
}
|
||||
|
||||
function addNew() {
|
||||
isNewItem.value = true;
|
||||
|
||||
const newDefaults: any = {};
|
||||
|
||||
props.fields.forEach((field) => {
|
||||
newDefaults[field.field!] = field.schema?.default_value;
|
||||
});
|
||||
|
||||
if (Array.isArray(internalValue.value)) {
|
||||
emitValue([...internalValue.value, newDefaults]);
|
||||
} else {
|
||||
if (internalValue.value != null) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
'The repeater interface expects an array as value, but the given value is no array. Overriding given value.'
|
||||
);
|
||||
}
|
||||
|
||||
emitValue([newDefaults]);
|
||||
}
|
||||
|
||||
edits.value = { ...newDefaults };
|
||||
active.value = (internalValue.value || []).length;
|
||||
}
|
||||
|
||||
function emitValue(value?: Record<string, unknown>[]) {
|
||||
if (!value || value.length === 0) {
|
||||
return emit('input', null);
|
||||
}
|
||||
|
||||
return emit('input', value);
|
||||
}
|
||||
|
||||
function closeDrawer() {
|
||||
if (isNewItem.value) {
|
||||
emitValue(internalValue.value?.slice(0, -1));
|
||||
}
|
||||
|
||||
edits.value = {};
|
||||
active.value = null;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -367,7 +304,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
.drag-handle {
|
||||
cursor: grap;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.drawer-item-content {
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<p class="type-label">{{ t('interfaces.list.edit_fields') }}</p>
|
||||
<repeater
|
||||
:value="repeaterValue"
|
||||
:template="`{{ field }} — {{ interface }}`"
|
||||
template="{{ field }} — {{ interface }}"
|
||||
:fields="repeaterFields"
|
||||
@input="repeaterValue = $event"
|
||||
/>
|
||||
@@ -37,203 +37,196 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { defineComponent, PropType, computed } from 'vue';
|
||||
import Repeater from './list.vue';
|
||||
import { Field, FieldMeta } from '@directus/types';
|
||||
<script setup lang="ts">
|
||||
import { FIELD_TYPES_SELECT } from '@/constants';
|
||||
import { DeepPartial } from '@directus/types';
|
||||
import { translate } from '@/utils/translate-object-values';
|
||||
import { DeepPartial, Field, FieldMeta } from '@directus/types';
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import Repeater from './list.vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { Repeater },
|
||||
props: {
|
||||
value: {
|
||||
type: Object as PropType<Record<string, any>>,
|
||||
default: null,
|
||||
const props = defineProps<{
|
||||
value: Record<string, any> | null;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'input', value: Record<string, any>[] | null): void;
|
||||
}>();
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const repeaterValue = computed({
|
||||
get() {
|
||||
return props.value?.fields?.map((field: Field) => field.meta);
|
||||
},
|
||||
set(newVal: FieldMeta[] | null) {
|
||||
const fields = (newVal || []).map((meta: Record<string, any>) => ({
|
||||
field: meta.field,
|
||||
name: meta.name || meta.field,
|
||||
type: meta.type,
|
||||
meta,
|
||||
}));
|
||||
|
||||
emit('input', {
|
||||
...(props.value || {}),
|
||||
fields,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const repeaterFields: DeepPartial<Field>[] = [
|
||||
{
|
||||
name: t('field', 1),
|
||||
field: 'field',
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'input',
|
||||
width: 'half',
|
||||
sort: 2,
|
||||
required: true,
|
||||
options: {
|
||||
dbSafe: true,
|
||||
font: 'monospace',
|
||||
placeholder: t('field_name_placeholder'),
|
||||
},
|
||||
},
|
||||
schema: null,
|
||||
},
|
||||
{
|
||||
name: t('field_width'),
|
||||
field: 'width',
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'select-dropdown',
|
||||
width: 'half',
|
||||
sort: 3,
|
||||
options: {
|
||||
choices: [
|
||||
{
|
||||
value: 'half',
|
||||
text: t('half_width'),
|
||||
},
|
||||
{
|
||||
value: 'full',
|
||||
text: t('full_width'),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
schema: null,
|
||||
},
|
||||
{
|
||||
name: t('type'),
|
||||
field: 'type',
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'select-dropdown',
|
||||
width: 'half',
|
||||
sort: 4,
|
||||
options: {
|
||||
choices: translate(FIELD_TYPES_SELECT),
|
||||
},
|
||||
},
|
||||
schema: null,
|
||||
},
|
||||
{
|
||||
name: t('interface_label'),
|
||||
field: 'interface',
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'system-interface',
|
||||
width: 'half',
|
||||
sort: 5,
|
||||
options: {
|
||||
typeField: 'type',
|
||||
},
|
||||
},
|
||||
schema: null,
|
||||
},
|
||||
{
|
||||
name: t('note'),
|
||||
field: 'note',
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'system-input-translated-string',
|
||||
width: 'full',
|
||||
sort: 6,
|
||||
options: {
|
||||
placeholder: t('interfaces.list.field_note_placeholder'),
|
||||
},
|
||||
},
|
||||
schema: null,
|
||||
},
|
||||
{
|
||||
name: t('required'),
|
||||
field: 'required',
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
interface: 'boolean',
|
||||
sort: 7,
|
||||
options: {
|
||||
label: t('requires_value'),
|
||||
},
|
||||
width: 'half',
|
||||
},
|
||||
},
|
||||
emits: ['input'],
|
||||
setup(props, { emit }) {
|
||||
const { t } = useI18n();
|
||||
|
||||
const repeaterValue = computed({
|
||||
get() {
|
||||
return props.value?.fields?.map((field: Field) => field.meta);
|
||||
{
|
||||
name: t('options'),
|
||||
field: 'options',
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'system-interface-options',
|
||||
width: 'full',
|
||||
sort: 8,
|
||||
options: {
|
||||
interfaceField: 'interface',
|
||||
},
|
||||
set(newVal: FieldMeta[] | null) {
|
||||
const fields = (newVal || []).map((meta: Record<string, any>) => ({
|
||||
field: meta.field,
|
||||
name: meta.name || meta.field,
|
||||
type: meta.type,
|
||||
meta,
|
||||
}));
|
||||
|
||||
emit('input', {
|
||||
...(props.value || {}),
|
||||
fields: fields,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const repeaterFields: DeepPartial<Field>[] = [
|
||||
{
|
||||
name: t('field', 1),
|
||||
field: 'field',
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'input',
|
||||
width: 'half',
|
||||
sort: 2,
|
||||
required: true,
|
||||
options: {
|
||||
dbSafe: true,
|
||||
font: 'monospace',
|
||||
placeholder: t('field_name_placeholder'),
|
||||
},
|
||||
},
|
||||
schema: null,
|
||||
},
|
||||
{
|
||||
name: t('field_width'),
|
||||
field: 'width',
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'select-dropdown',
|
||||
width: 'half',
|
||||
sort: 3,
|
||||
options: {
|
||||
choices: [
|
||||
{
|
||||
value: 'half',
|
||||
text: t('half_width'),
|
||||
},
|
||||
{
|
||||
value: 'full',
|
||||
text: t('full_width'),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
schema: null,
|
||||
},
|
||||
{
|
||||
name: t('type'),
|
||||
field: 'type',
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'select-dropdown',
|
||||
width: 'half',
|
||||
sort: 4,
|
||||
options: {
|
||||
choices: translate(FIELD_TYPES_SELECT),
|
||||
},
|
||||
},
|
||||
schema: null,
|
||||
},
|
||||
{
|
||||
name: t('interface_label'),
|
||||
field: 'interface',
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'system-interface',
|
||||
width: 'half',
|
||||
sort: 5,
|
||||
options: {
|
||||
typeField: 'type',
|
||||
},
|
||||
},
|
||||
schema: null,
|
||||
},
|
||||
{
|
||||
name: t('note'),
|
||||
field: 'note',
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'system-input-translated-string',
|
||||
width: 'full',
|
||||
sort: 6,
|
||||
options: {
|
||||
placeholder: t('interfaces.list.field_note_placeholder'),
|
||||
},
|
||||
},
|
||||
schema: null,
|
||||
},
|
||||
{
|
||||
name: t('required'),
|
||||
field: 'required',
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
interface: 'boolean',
|
||||
sort: 7,
|
||||
options: {
|
||||
label: t('requires_value'),
|
||||
},
|
||||
width: 'half',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: t('options'),
|
||||
field: 'options',
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'system-interface-options',
|
||||
width: 'full',
|
||||
sort: 8,
|
||||
options: {
|
||||
interfaceField: 'interface',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const template = computed({
|
||||
get() {
|
||||
return props.value?.template;
|
||||
},
|
||||
set(newTemplate: string) {
|
||||
emit('input', {
|
||||
...(props.value || {}),
|
||||
template: newTemplate,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const addLabel = computed({
|
||||
get() {
|
||||
return props.value?.addLabel;
|
||||
},
|
||||
set(newAddLabel: string) {
|
||||
emit('input', {
|
||||
...(props.value || {}),
|
||||
addLabel: newAddLabel,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const sort = computed({
|
||||
get() {
|
||||
return props.value?.sort;
|
||||
},
|
||||
set(newSort: string) {
|
||||
emit('input', {
|
||||
...(props.value || {}),
|
||||
sort: newSort,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const sortFields = computed(() => {
|
||||
if (!repeaterValue.value) return [];
|
||||
|
||||
return repeaterValue.value.map((val) => {
|
||||
return { text: val.field, value: val.field };
|
||||
});
|
||||
});
|
||||
|
||||
return { t, repeaterValue, repeaterFields, template, addLabel, sort, sortFields };
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const template = computed({
|
||||
get() {
|
||||
return props.value?.template;
|
||||
},
|
||||
set(newTemplate: string) {
|
||||
emit('input', {
|
||||
...(props.value || {}),
|
||||
template: newTemplate,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const addLabel = computed({
|
||||
get() {
|
||||
return props.value?.addLabel;
|
||||
},
|
||||
set(newAddLabel: string) {
|
||||
emit('input', {
|
||||
...(props.value || {}),
|
||||
addLabel: newAddLabel,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const sort = computed({
|
||||
get() {
|
||||
return props.value?.sort;
|
||||
},
|
||||
set(newSort: string) {
|
||||
emit('input', {
|
||||
...(props.value || {}),
|
||||
sort: newSort,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const sortFields = computed(() => {
|
||||
if (!repeaterValue.value) return [];
|
||||
|
||||
return repeaterValue.value.map((val) => {
|
||||
return { text: val.field, value: val.field };
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user