Add field management
This commit is contained in:
parent
8bf0019c98
commit
104b04b639
|
@ -1,18 +1 @@
|
||||||
<?xml version="1.0" ?>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512" xml:space="preserve"><path d="M51.2 353.28 0 512l158.72-51.2zm35.96-36.788L336.96 66.69 445.57 175.3l-249.8 249.802zM504.32 79.36 432.64 7.68c-10.24-10.24-25.6-10.24-35.84 0l-23.04 23.04 107.52 107.52 23.04-23.04c10.24-10.24 10.24-25.6 0-35.84z"/></svg>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polygon points="51.2,353.28 0,512 158.72,460.8 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<rect x="89.73" y="169.097" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -95.8575 260.3719)" width="353.277" height="153.599"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path d="M504.32,79.36L432.64,7.68c-10.24-10.24-25.6-10.24-35.84,0l-23.04,23.04l107.52,107.52l23.04-23.04 C514.56,104.96,514.56,89.6,504.32,79.36z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 660 B After Width: | Height: | Size: 357 B |
|
@ -1,81 +1,122 @@
|
||||||
<template>
|
<template>
|
||||||
|
<ui-popup :heading="`Vorlage ${inner.id ? 'bearbeiten' : 'erstellen'}`" full @close="$emit('cancel')">
|
||||||
|
<ui-popup v-if="singleField !== null && singleField.model === null" heading="Feldtyp auswählen" @close="singleField = null">
|
||||||
|
<div class="mt-3 grid gap-3 grid-cols-3">
|
||||||
|
<a v-for="(field, index) in props.meta.fields" :key="index" class="py-2 px-3 border rounded bg-zinc-800 hover:bg-zinc-700 transition" href="#" @click.prevent="setFieldType(field)">
|
||||||
|
<span v-text="field.name"></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</ui-popup>
|
||||||
|
<template #actions>
|
||||||
|
<a href="#" @click.prevent="$emit('submit', inner)">
|
||||||
|
<ui-sprite src="save" class="text-zinc-400 w-6 h-6"></ui-sprite>
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
<form class="grid gap-3 mt-4 grid-cols-[1fr_max-content] items-start" @submit.prevent="submit">
|
<form class="grid gap-3 mt-4 grid-cols-[1fr_max-content] items-start" @submit.prevent="submit">
|
||||||
<div class="grid gap-3">
|
<div class="grid gap-3">
|
||||||
<f-text id="name" v-model="inner.name" name="name" label="Name" required></f-text>
|
<f-text id="name" v-model="inner.name" name="name" label="Name" required></f-text>
|
||||||
<ui-box heading="Sektionen" container-class="grid gap-3">
|
<asideform v-if="singleSection !== null" :heading="`Sektion ${singleSection.index !== null ? 'bearbeiten' : 'erstellen'}`" @close="singleSection = null" @submit="storeSection">
|
||||||
<template #in-title>
|
<f-text :id="`sectionform-name`" v-model="singleSection.model.name" label="Name" :name="`sectionform-name`"></f-text>
|
||||||
<ui-icon-button class="ml-3 btn-primary" icon="plus" @click="addSection">Sektion hinzufügen</ui-icon-button>
|
<f-textarea :id="`sectionform-intro`" v-model="singleSection.model.intro" label="Einleitung" :name="`sectionform-intro`"></f-textarea>
|
||||||
</template>
|
</asideform>
|
||||||
<div class="rounded-sm overflow-hidden divide-y divide-primary-600">
|
<asideform
|
||||||
<section v-for="(section, sindex) in inner.config.sections" :key="sindex">
|
v-if="singleField !== null && singleField.model !== null"
|
||||||
<header class="flex items-center hover:cursor-pointer justify-between bg-primary-700 py-1 px-2 text-primary-200 text-sm" @click="sectionVisible = sindex">
|
:heading="`Feld ${singleField.index !== null ? 'bearbeiten' : 'erstellen'}`"
|
||||||
<span v-text="section.name ? section.name : ' '"></span>
|
@close="singleField = null"
|
||||||
<ui-sprite src="chevron" class="w-3 h-3" :class="{'rotate-180': sectionVisible === sindex}"></ui-sprite>
|
@submit="storeField"
|
||||||
</header>
|
>
|
||||||
<main v-show="sectionVisible === sindex" class="p-1">
|
<f-text id="fieldname" v-model="singleField.model.name" label="Name" size="sm" name="fieldname"></f-text>
|
||||||
<f-text :id="`section-${sindex}-name`" v-model="section.name" label="Name" size="sm" :name="`section-${sindex}-name`"></f-text>
|
<f-switch id="fieldrequired" v-model="singleField.model.required" label="Erforderlich" size="sm" name="fieldrequired" inline></f-switch>
|
||||||
<f-textarea :id="`section-${sindex}-intro`" v-model="section.intro" label="Einleitung" size="sm" :name="`section-${sindex}-intro`"></f-textarea>
|
</asideform>
|
||||||
<ui-icon-button class="mt-2 btn-primary" icon="plus" @click="addField(section)">Feld hinzufügen</ui-icon-button>
|
|
||||||
<div v-for="(field, findex) in section.fields" :key="`${sindex}-${findex}`" class="grid gap-1">
|
|
||||||
<f-select
|
|
||||||
:id="`fieldtype-${sindex}-${findex}`"
|
|
||||||
:model-value="field.type"
|
|
||||||
:name="`fieldtype-${sindex}-${findex}`"
|
|
||||||
:options="props.meta.fields"
|
|
||||||
label="Typ"
|
|
||||||
size="sm"
|
|
||||||
@update:modelValue="setFieldType(section, findex, $event)"
|
|
||||||
></f-select>
|
|
||||||
<template v-if="field.type">
|
|
||||||
<f-text :id="`section-${sindex}-${findex}-name`" v-model="field.name" label="Name" size="sm" :name="`section-${sindex}-${findex}-name`"></f-text>
|
|
||||||
<f-switch
|
|
||||||
:id="`section-${sindex}-${findex}-required`"
|
|
||||||
v-model="field.required"
|
|
||||||
label="Erforderlich"
|
|
||||||
size="sm"
|
|
||||||
:name="`section-${sindex}-${findex}-required`"
|
|
||||||
inline
|
|
||||||
></f-switch>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</ui-box>
|
|
||||||
</div>
|
</div>
|
||||||
<ui-box heading="Vorschau" container-class="grid gap-3" class="w-[800px]">
|
<ui-box heading="Vorschau" container-class="grid gap-3" class="w-[800px]">
|
||||||
<event-form style="--primary: yellow; --secondary: green; --font: #ff6600; --circle: #111111" :value="previewString"></event-form>
|
<event-form
|
||||||
|
editable
|
||||||
|
style="--primary: hsl(181, 75%, 26%); --secondary: hsl(181, 75%, 35%); --font: hsl(181, 84%, 78%); --circle: hsl(181, 86%, 16%)"
|
||||||
|
:value="previewString"
|
||||||
|
@editSection="editSection($event.detail[0])"
|
||||||
|
@addSection="addSection"
|
||||||
|
@addField="addField($event.detail[0])"
|
||||||
|
@editField="editField($event.detail[0], $event.detail[1])"
|
||||||
|
@deleteField="deleteField($event.detail[0], $event.detail[1])"
|
||||||
|
></event-form>
|
||||||
</ui-box>
|
</ui-box>
|
||||||
</form>
|
</form>
|
||||||
|
</ui-popup>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {computed, ref} from 'vue';
|
import {computed, ref} from 'vue';
|
||||||
import '!/eventform/dist/main.js';
|
import '!/eventform/dist/main.js';
|
||||||
|
import Asideform from './Asideform.vue';
|
||||||
|
|
||||||
const sectionVisible = ref(-1);
|
const sectionVisible = ref(-1);
|
||||||
|
const singleSection = ref(null);
|
||||||
|
const singleField = ref(null);
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {},
|
modelValue: {},
|
||||||
meta: {},
|
meta: {},
|
||||||
});
|
});
|
||||||
|
const emit = defineEmits(['submit', 'cancel']);
|
||||||
|
|
||||||
|
function editSection(sectionIndex) {
|
||||||
|
singleSection.value = {
|
||||||
|
model: {...inner.value.config.sections[sectionIndex]},
|
||||||
|
index: sectionIndex,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const inner = ref(JSON.parse(JSON.stringify(props.modelValue)));
|
const inner = ref(JSON.parse(JSON.stringify(props.modelValue)));
|
||||||
|
const innerMeta = ref(JSON.parse(JSON.stringify(props.meta)));
|
||||||
|
|
||||||
function addSection() {
|
function addSection() {
|
||||||
sectionVisible.value = inner.value.config.sections.push({...props.meta.section_default}) - 1;
|
singleSection.value = {
|
||||||
|
model: JSON.parse(JSON.stringify(innerMeta.value.section_default)),
|
||||||
|
index: null,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function addField(section) {
|
function editField(sindex, findex) {
|
||||||
section.fields = [...section.fields, {name: null, type: null}];
|
singleField.value = {
|
||||||
|
model: JSON.parse(JSON.stringify(inner.value.config.sections[sindex].fields[findex])),
|
||||||
|
sectionIndex: sindex,
|
||||||
|
index: findex,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function setFieldType(section, findex, type) {
|
function storeSection() {
|
||||||
if (type === null) {
|
if (singleSection.value.index !== null) {
|
||||||
section.fields[findex].type = null;
|
inner.value.config.sections.splice(singleSection.value.index, 1, singleSection.value.model);
|
||||||
return;
|
} else {
|
||||||
|
inner.value.config.sections.push(singleSection.value.model);
|
||||||
}
|
}
|
||||||
section.fields[findex] = {...props.meta.fields.find((f) => f.id === type).default};
|
singleSection.value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function storeField() {
|
||||||
|
if (singleField.value.index !== null) {
|
||||||
|
inner.value.config.sections[singleField.value.sectionIndex].fields.splice(singleField.value.index, 1, singleField.value.model);
|
||||||
|
} else {
|
||||||
|
inner.value.config.sections[singleField.value.sectionIndex].fields.push(singleField.value.model);
|
||||||
|
}
|
||||||
|
singleField.value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteField(sindex, findex) {
|
||||||
|
inner.value.config.sections[sindex].fields.splice(findex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addField(sectionIndex) {
|
||||||
|
singleField.value = {
|
||||||
|
model: null,
|
||||||
|
sectionIndex: sectionIndex,
|
||||||
|
index: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function setFieldType(field) {
|
||||||
|
singleField.value.model = JSON.parse(JSON.stringify(field.default));
|
||||||
}
|
}
|
||||||
|
|
||||||
const previewString = computed(() => (inner.value && inner.value ? JSON.stringify(inner.value.config) : '{}'));
|
const previewString = computed(() => (inner.value && inner.value ? JSON.stringify(inner.value.config) : '{}'));
|
||||||
|
|
|
@ -4,14 +4,7 @@
|
||||||
<page-toolbar-button color="primary" icon="plus" @click="create">Vorlage erstellen</page-toolbar-button>
|
<page-toolbar-button color="primary" icon="plus" @click="create">Vorlage erstellen</page-toolbar-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<ui-popup v-if="single !== null" :heading="`Vorlage ${single.id ? 'bearbeiten' : 'erstellen'}`" full @close="cancel">
|
<form-builder v-if="single !== null" :model-value="single" :meta="meta" @submit="innerSubmit" @cancel="cancel"></form-builder>
|
||||||
<form-builder v-model="single" :meta="meta"></form-builder>
|
|
||||||
<template #actions>
|
|
||||||
<a href="#" @click.prevent="submit">
|
|
||||||
<ui-sprite src="save" class="text-zinc-400 w-6 h-6"></ui-sprite>
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
</ui-popup>
|
|
||||||
<table cellspacing="0" cellpadding="0" border="0" class="custom-table custom-table-sm">
|
<table cellspacing="0" cellpadding="0" border="0" class="custom-table custom-table-sm">
|
||||||
<thead>
|
<thead>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
|
@ -39,4 +32,10 @@ import FormBuilder from './FormBuilder.vue';
|
||||||
|
|
||||||
const props = defineProps(indexProps);
|
const props = defineProps(indexProps);
|
||||||
var {meta, data, reloadPage, create, single, edit, cancel, submit} = useIndex(props.data, 'invoice');
|
var {meta, data, reloadPage, create, single, edit, cancel, submit} = useIndex(props.data, 'invoice');
|
||||||
|
|
||||||
|
function innerSubmit(payload) {
|
||||||
|
single.value = payload;
|
||||||
|
|
||||||
|
submit();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue