2020-07-11 03:13:11 +02:00
|
|
|
<template>
|
2023-04-08 02:01:42 +02:00
|
|
|
<XModalWindow
|
|
|
|
ref="dialog"
|
|
|
|
:width="450"
|
|
|
|
:can-close="false"
|
|
|
|
:with-ok-button="true"
|
|
|
|
:ok-button-disabled="false"
|
|
|
|
@click="cancel()"
|
|
|
|
@ok="ok()"
|
|
|
|
@close="cancel()"
|
2024-04-13 17:08:46 +02:00
|
|
|
@closed="emit('closed')"
|
2023-04-08 02:01:42 +02:00
|
|
|
>
|
|
|
|
<template #header>
|
|
|
|
{{ title }}
|
|
|
|
</template>
|
2021-12-02 12:09:12 +01:00
|
|
|
|
2023-04-08 02:01:42 +02:00
|
|
|
<MkSpacer :margin-min="20" :margin-max="32">
|
2023-08-10 22:25:21 +02:00
|
|
|
<div class="_formRoot">
|
2023-04-08 02:01:42 +02:00
|
|
|
<template
|
2024-04-13 17:08:46 +02:00
|
|
|
v-for="[formItem, formItemName] in unHiddenForms()"
|
2023-04-08 02:01:42 +02:00
|
|
|
>
|
|
|
|
<FormInput
|
2024-04-13 17:08:46 +02:00
|
|
|
v-if="formItem.type === 'number'"
|
|
|
|
v-model="values[formItemName]"
|
2023-04-08 02:01:42 +02:00
|
|
|
type="number"
|
2024-04-13 17:08:46 +02:00
|
|
|
:step="formItem.step || 1"
|
2023-04-08 02:01:42 +02:00
|
|
|
class="_formBlock"
|
|
|
|
>
|
|
|
|
<template #label
|
2024-04-13 17:08:46 +02:00
|
|
|
><span v-text="formItem.label || formItemName"></span
|
|
|
|
><span v-if="formItem.required === false">
|
2023-04-08 02:01:42 +02:00
|
|
|
({{ i18n.ts.optional }})</span
|
|
|
|
></template
|
|
|
|
>
|
2024-04-13 17:08:46 +02:00
|
|
|
<template v-if="formItem.description" #caption>{{
|
|
|
|
formItem.description
|
2023-04-08 02:01:42 +02:00
|
|
|
}}</template>
|
|
|
|
</FormInput>
|
|
|
|
<FormInput
|
|
|
|
v-else-if="
|
2024-04-13 17:08:46 +02:00
|
|
|
formItem.type === 'string' &&
|
|
|
|
!formItem.multiline
|
2023-04-08 02:01:42 +02:00
|
|
|
"
|
2024-04-13 17:08:46 +02:00
|
|
|
v-model="values[formItemName]"
|
2023-04-08 02:01:42 +02:00
|
|
|
type="text"
|
|
|
|
class="_formBlock"
|
|
|
|
>
|
|
|
|
<template #label
|
2024-04-13 17:08:46 +02:00
|
|
|
><span v-text="formItem.label || formItemName"></span
|
|
|
|
><span v-if="formItem.required === false">
|
2023-04-08 02:01:42 +02:00
|
|
|
({{ i18n.ts.optional }})</span
|
|
|
|
></template
|
|
|
|
>
|
2024-04-13 17:08:46 +02:00
|
|
|
<template v-if="formItem.description" #caption>{{
|
|
|
|
formItem.description
|
2023-04-08 02:01:42 +02:00
|
|
|
}}</template>
|
|
|
|
</FormInput>
|
2024-04-13 17:21:31 +02:00
|
|
|
<FormInput
|
|
|
|
v-else-if="
|
|
|
|
formItem.type === 'email' ||
|
|
|
|
formItem.type === 'password' ||
|
|
|
|
formItem.type === 'url' ||
|
|
|
|
formItem.type === 'date' ||
|
|
|
|
formItem.type === 'time' ||
|
|
|
|
formItem.type === 'search'
|
|
|
|
"
|
|
|
|
v-model="values[formItemName]"
|
|
|
|
:type="formItem.type"
|
|
|
|
class="_formBlock"
|
|
|
|
>
|
|
|
|
<template #label
|
|
|
|
><span v-text="formItem.label || formItemName"></span
|
|
|
|
><span v-if="formItem.required === false">
|
|
|
|
({{ i18n.ts.optional }})</span
|
|
|
|
></template
|
|
|
|
>
|
|
|
|
<template v-if="formItem.description" #caption>{{
|
|
|
|
formItem.description
|
|
|
|
}}</template>
|
|
|
|
</FormInput>
|
2023-04-08 02:01:42 +02:00
|
|
|
<FormTextarea
|
|
|
|
v-else-if="
|
2024-04-13 17:08:46 +02:00
|
|
|
formItem.type === 'string' && formItem.multiline
|
2023-04-08 02:01:42 +02:00
|
|
|
"
|
2024-04-13 17:08:46 +02:00
|
|
|
v-model="values[formItemName]"
|
2023-04-08 02:01:42 +02:00
|
|
|
class="_formBlock"
|
|
|
|
>
|
|
|
|
<template #label
|
2024-04-13 17:08:46 +02:00
|
|
|
><span v-text="formItem.label || formItemName"></span
|
|
|
|
><span v-if="formItem.required === false">
|
2023-04-08 02:01:42 +02:00
|
|
|
({{ i18n.ts.optional }})</span
|
|
|
|
></template
|
|
|
|
>
|
2024-04-13 17:08:46 +02:00
|
|
|
<template v-if="formItem.description" #caption>{{
|
|
|
|
formItem.description
|
2023-04-08 02:01:42 +02:00
|
|
|
}}</template>
|
|
|
|
</FormTextarea>
|
|
|
|
<FormSwitch
|
2024-04-13 17:08:46 +02:00
|
|
|
v-else-if="formItem.type === 'boolean'"
|
|
|
|
v-model="values[formItemName]"
|
2023-04-08 02:01:42 +02:00
|
|
|
class="_formBlock"
|
|
|
|
>
|
2024-04-13 17:08:46 +02:00
|
|
|
<span v-text="formItem.label || formItemName"></span>
|
|
|
|
<template v-if="formItem.description" #caption>{{
|
|
|
|
formItem.description
|
2023-04-08 02:01:42 +02:00
|
|
|
}}</template>
|
|
|
|
</FormSwitch>
|
|
|
|
<FormSelect
|
2024-04-13 17:08:46 +02:00
|
|
|
v-else-if="formItem.type === 'enum'"
|
|
|
|
v-model="values[formItemName]"
|
2023-04-08 02:01:42 +02:00
|
|
|
class="_formBlock"
|
|
|
|
>
|
2024-04-13 17:08:46 +02:00
|
|
|
<template #label>
|
|
|
|
<span v-text="formItem.label || formItemName"></span>
|
|
|
|
<span v-if="formItem.required === false">
|
2023-04-08 02:01:42 +02:00
|
|
|
({{ i18n.ts.optional }})</span
|
|
|
|
>
|
2024-04-13 17:08:46 +02:00
|
|
|
</template>
|
2023-04-08 02:01:42 +02:00
|
|
|
<option
|
2024-04-13 17:08:46 +02:00
|
|
|
v-for="item in formItem.enum"
|
2023-04-08 02:01:42 +02:00
|
|
|
:key="item.value"
|
|
|
|
:value="item.value"
|
|
|
|
>
|
|
|
|
{{ item.label }}
|
|
|
|
</option>
|
|
|
|
</FormSelect>
|
|
|
|
<FormRadios
|
2024-04-13 17:08:46 +02:00
|
|
|
v-else-if="formItem.type === 'radio'"
|
|
|
|
v-model="values[formItemName]"
|
2023-04-08 02:01:42 +02:00
|
|
|
class="_formBlock"
|
|
|
|
>
|
|
|
|
<template #label
|
2024-04-13 17:08:46 +02:00
|
|
|
><span v-text="formItem.label || formItemName"></span
|
|
|
|
><span v-if="formItem.required === false">
|
2023-04-08 02:01:42 +02:00
|
|
|
({{ i18n.ts.optional }})</span
|
|
|
|
></template
|
|
|
|
>
|
|
|
|
<option
|
2024-04-13 17:08:46 +02:00
|
|
|
v-for="item in formItem.options"
|
2023-04-08 02:01:42 +02:00
|
|
|
:key="item.value"
|
|
|
|
:value="item.value"
|
|
|
|
>
|
|
|
|
{{ item.label }}
|
|
|
|
</option>
|
|
|
|
</FormRadios>
|
|
|
|
<FormRange
|
2024-04-13 17:08:46 +02:00
|
|
|
v-else-if="formItem.type === 'range'"
|
|
|
|
v-model="values[formItemName]"
|
|
|
|
:min="formItem.min"
|
|
|
|
:max="formItem.max"
|
|
|
|
:step="formItem.step"
|
|
|
|
:text-converter="formItem.textConverter"
|
2023-04-08 02:01:42 +02:00
|
|
|
class="_formBlock"
|
|
|
|
>
|
|
|
|
<template #label
|
2024-04-13 17:08:46 +02:00
|
|
|
><span v-text="formItem.label || formItemName"></span
|
|
|
|
><span v-if="formItem.required === false">
|
2023-04-08 02:01:42 +02:00
|
|
|
({{ i18n.ts.optional }})</span
|
|
|
|
></template
|
|
|
|
>
|
2024-04-13 17:08:46 +02:00
|
|
|
<template v-if="formItem.description" #caption>{{
|
|
|
|
formItem.description
|
2023-04-08 02:01:42 +02:00
|
|
|
}}</template>
|
|
|
|
</FormRange>
|
|
|
|
<MkButton
|
2024-04-13 17:08:46 +02:00
|
|
|
v-else-if="formItem.type === 'button'"
|
2023-04-08 02:01:42 +02:00
|
|
|
class="_formBlock"
|
2024-04-13 17:08:46 +02:00
|
|
|
@click="formItem.action($event, values)"
|
2023-04-08 02:01:42 +02:00
|
|
|
>
|
2024-04-13 17:08:46 +02:00
|
|
|
<span v-text="formItem.content || formItemName"></span>
|
2023-04-08 02:01:42 +02:00
|
|
|
</MkButton>
|
|
|
|
</template>
|
|
|
|
</div>
|
|
|
|
</MkSpacer>
|
|
|
|
</XModalWindow>
|
2020-07-11 03:13:11 +02:00
|
|
|
</template>
|
|
|
|
|
2024-04-13 17:08:46 +02:00
|
|
|
<script lang="ts" setup>
|
|
|
|
import { ref } from "vue";
|
2023-04-08 02:01:42 +02:00
|
|
|
import FormInput from "./form/input.vue";
|
|
|
|
import FormTextarea from "./form/textarea.vue";
|
|
|
|
import FormSwitch from "./form/switch.vue";
|
|
|
|
import FormSelect from "./form/select.vue";
|
|
|
|
import FormRange from "./form/range.vue";
|
|
|
|
import MkButton from "./MkButton.vue";
|
|
|
|
import FormRadios from "./form/radios.vue";
|
|
|
|
import XModalWindow from "@/components/MkModalWindow.vue";
|
|
|
|
import { i18n } from "@/i18n";
|
2024-04-13 17:08:46 +02:00
|
|
|
import type { FormItemType } from "@/types/form";
|
2020-07-11 03:13:11 +02:00
|
|
|
|
2024-04-13 17:08:46 +02:00
|
|
|
const props = defineProps<{
|
|
|
|
title: string;
|
|
|
|
form: Record<string, FormItemType>;
|
|
|
|
}>();
|
2020-07-11 03:13:11 +02:00
|
|
|
|
2024-04-13 17:08:46 +02:00
|
|
|
// biome-ignore lint/suspicious/noExplicitAny: To prevent overly complex types we have to use any here
|
|
|
|
type ValueType = Record<string, any>;
|
|
|
|
|
|
|
|
const emit = defineEmits<{
|
|
|
|
done: [
|
|
|
|
status: {
|
|
|
|
result?: Record<string, FormItemType["default"]>;
|
|
|
|
canceled?: true;
|
2020-07-11 03:13:11 +02:00
|
|
|
},
|
2024-04-13 17:08:46 +02:00
|
|
|
];
|
|
|
|
closed: [];
|
|
|
|
}>();
|
2020-07-11 03:13:11 +02:00
|
|
|
|
2024-04-13 17:08:46 +02:00
|
|
|
const values = ref<ValueType>({});
|
|
|
|
const dialog = ref<InstanceType<typeof XModalWindow> | null>(null);
|
2020-10-17 13:12:00 +02:00
|
|
|
|
2024-04-13 17:08:46 +02:00
|
|
|
for (const item in props.form) {
|
|
|
|
values.value[item] = props.form[item].default ?? null;
|
|
|
|
}
|
2020-07-11 03:13:11 +02:00
|
|
|
|
2024-04-13 17:08:46 +02:00
|
|
|
function unHiddenForms(): [FormItemType, string][] {
|
|
|
|
return Object.keys(props.form)
|
|
|
|
.filter((itemName) => !props.form[itemName].hidden)
|
|
|
|
.map((itemName) => [props.form[itemName], itemName]);
|
|
|
|
}
|
2020-07-11 03:13:11 +02:00
|
|
|
|
2024-04-13 17:08:46 +02:00
|
|
|
function ok() {
|
|
|
|
emit("done", {
|
|
|
|
result: values.value,
|
|
|
|
});
|
|
|
|
dialog.value!.close();
|
|
|
|
}
|
2020-10-17 13:12:00 +02:00
|
|
|
|
2024-04-13 17:08:46 +02:00
|
|
|
function cancel() {
|
|
|
|
emit("done", {
|
|
|
|
canceled: true,
|
|
|
|
});
|
|
|
|
dialog.value!.close();
|
|
|
|
}
|
2020-07-11 03:13:11 +02:00
|
|
|
</script>
|