Fix field validation

This commit is contained in:
philipp lang 2024-02-19 03:27:46 +01:00
parent 1fc676a5fa
commit 1bdc9b8c9c
10 changed files with 62 additions and 52 deletions

View File

@ -232,7 +232,7 @@ function reload() {
reload(); reload();
watch( watch(
() => props.value, () => props.value,
(value) => reload() (value) => reload(),
); );
const { back, next, backable, nextable } = useNav(active, v.value.sections.length); const { back, next, backable, nextable } = useNav(active, v.value.sections.length);

View File

@ -3,8 +3,10 @@
<div class="grid grid-cols-1 gap-2"> <div class="grid grid-cols-1 gap-2">
<label :for="field.key" class="p-0 block leading-none relative flex items-start"> <label :for="field.key" class="p-0 block leading-none relative flex items-start">
<input :id="field.key" v-model="inner" type="checkbox" :name="field.key" class="peer absolute invisible" /> <input :id="field.key" v-model="inner" type="checkbox" :name="field.key" class="peer absolute invisible" />
<span class="border-neutral-400 border-4 border-solid peer-checked:border-primary absolute left-0 w-6 h-6 rounded block top-0"></span> <span
<span class="peer-checked:bg-primary left-[0.5rem] top-[0.5rem] w-2 h-2 absolute rounded block top-0"></span> class="border-neutral-400 border-4 border-solid peer-checked:border-primary absolute left-0 w-6 h-6 rounded block top-0"></span>
<span
class="peer-checked:bg-primary left-[0.5rem] top-[0.5rem] w-2 h-2 absolute rounded block top-0"></span>
<span class="pl-8 pt-1 @sm:pt-0 text-gray-600 text-sm @sm:text-base"> <span class="pl-8 pt-1 @sm:pt-0 text-gray-600 text-sm @sm:text-base">
<span v-text="field.description"></span> <span v-text="field.description"></span>
<span v-show="field.required" class="text-red-800">*</span> <span v-show="field.required" class="text-red-800">*</span>
@ -15,7 +17,7 @@
</template> </template>
<script setup> <script setup>
import {computed} from 'vue'; import { computed } from 'vue';
const emit = defineEmits(['update:modelValue']); const emit = defineEmits(['update:modelValue']);
const props = defineProps({ const props = defineProps({
@ -26,7 +28,7 @@ const props = defineProps({
field: { field: {
required: true, required: true,
validator: (value) => validator: (value) =>
hasKeys(value, ['required', 'type', 'key', 'columns', 'name', 'default', 'description']) && hasKeys(value, [...globalFieldRules(), 'required', 'description']) &&
typeof value.required === 'boolean' && typeof value.required === 'boolean' &&
typeof value.key === 'string' && typeof value.key === 'string' &&
value.key.length > 0 && value.key.length > 0 &&

View File

@ -1,9 +1,12 @@
<template> <template>
<div class="relative"> <div class="relative">
<div class="grid grid-cols-1 gap-2 mt-3"> <div class="grid grid-cols-1 gap-2 mt-3">
<label v-for="(option, index) in field.options" :key="index" :for="`${field.key}-${index}`" class="block relative flex items-start"> <label v-for="(option, index) in field.options" :key="index" :for="`${field.key}-${index}`"
<input :id="`${field.key}-${index}`" v-model="inner" type="checkbox" :name="field.key" :value="option" class="peer absolute invisible" /> class="block relative flex items-start">
<span class="border-neutral-400 border-4 border-solid peer-checked:border-primary absolute left-0 w-6 h-6 rounded block"></span> <input :id="`${field.key}-${index}`" v-model="inner" type="checkbox" :name="field.key" :value="option"
class="peer absolute invisible" />
<span
class="border-neutral-400 border-4 border-solid peer-checked:border-primary absolute left-0 w-6 h-6 rounded block"></span>
<span class="peer-checked:bg-primary left-[0.5rem] top-[0.5rem] w-2 h-2 absolute rounded block"></span> <span class="peer-checked:bg-primary left-[0.5rem] top-[0.5rem] w-2 h-2 absolute rounded block"></span>
<span class="pl-8 pt-1 @sm:pt-0 text-gray-600 text-sm @sm:text-base" v-text="option"></span> <span class="pl-8 pt-1 @sm:pt-0 text-gray-600 text-sm @sm:text-base" v-text="option"></span>
</label> </label>
@ -14,7 +17,7 @@
</template> </template>
<script setup> <script setup>
import {computed} from 'vue'; import { computed } from 'vue';
import FieldLabel from '../FieldLabel.vue'; import FieldLabel from '../FieldLabel.vue';
const emit = defineEmits(['update:modelValue']); const emit = defineEmits(['update:modelValue']);
@ -26,7 +29,7 @@ const props = defineProps({
field: { field: {
required: true, required: true,
validator: (value) => validator: (value) =>
hasKeys(value, ['required', 'type', 'key', 'columns', 'name', 'default', 'options']) && hasKeys(value, [...globalFieldRules(), 'required', 'options']) &&
typeof value.required === 'boolean' && typeof value.required === 'boolean' &&
typeof value.key === 'string' && typeof value.key === 'string' &&
value.key.length > 0 && value.key.length > 0 &&

View File

@ -1,20 +1,13 @@
<template> <template>
<label class="w-full border border-solid border-gray-500 focus-within:border-primary rounded-lg relative flex"> <label class="w-full border border-solid border-gray-500 focus-within:border-primary rounded-lg relative flex">
<input <input :id="field.key" v-model="inner" :name="field.key" type="date" :max="max" placeholder=""
:id="field.key" class="bg-white rounded-lg focus:outline-none text-gray-600 text-left py-1 px-2 @sm:py-2 text-sm @sm:text-base @sm:px-3 w-full" />
v-model="inner"
:name="field.key"
type="date"
:max="max"
placeholder=""
class="bg-white rounded-lg focus:outline-none text-gray-600 text-left py-1 px-2 @sm:py-2 text-sm @sm:text-base @sm:px-3 w-full"
/>
<field-label :name="field.name" :required="field.required"></field-label> <field-label :name="field.name" :required="field.required"></field-label>
</label> </label>
</template> </template>
<script setup> <script setup>
import {computed} from 'vue'; import { computed } from 'vue';
import FieldLabel from '../FieldLabel.vue'; import FieldLabel from '../FieldLabel.vue';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
@ -27,7 +20,7 @@ const props = defineProps({
field: { field: {
required: true, required: true,
validator: (value) => validator: (value) =>
hasKeys(value, ['required', 'type', 'key', 'columns', 'name', 'default', 'max_today']) && hasKeys(value, [...globalFieldRules(), 'required', 'max_today']) &&
typeof value.required === 'boolean' && typeof value.required === 'boolean' &&
typeof value.max_today === 'boolean' && typeof value.max_today === 'boolean' &&
typeof value.key === 'string' && typeof value.key === 'string' &&

View File

@ -1,6 +1,9 @@
<template> <template>
<label class="w-full border border-solid border-gray-500 focus-within:border-primary rounded-lg relative flex" :for="field.key"> <label class="w-full border border-solid border-gray-500 focus-within:border-primary rounded-lg relative flex"
<select :name="field.key" :id="field.key" class="bg-white rounded-lg focus:outline-none text-gray-600 text-left peer py-1 px-2 @sm:py-2 text-sm @sm:text-base @sm:px-3 w-full" v-model="inner"> :for="field.key">
<select :name="field.key" :id="field.key"
class="bg-white rounded-lg focus:outline-none text-gray-600 text-left peer py-1 px-2 @sm:py-2 text-sm @sm:text-base @sm:px-3 w-full"
v-model="inner">
<option :value="null">-- kein --</option> <option :value="null">-- kein --</option>
<option v-for="(option, index) in field.options" :key="index" :value="option" v-text="option"></option> <option v-for="(option, index) in field.options" :key="index" :value="option" v-text="option"></option>
</select> </select>
@ -9,7 +12,7 @@
</template> </template>
<script setup> <script setup>
import {computed} from 'vue'; import { computed } from 'vue';
import FieldLabel from '../FieldLabel.vue'; import FieldLabel from '../FieldLabel.vue';
const emit = defineEmits(['update:modelValue']); const emit = defineEmits(['update:modelValue']);
@ -21,7 +24,7 @@ const props = defineProps({
field: { field: {
required: true, required: true,
validator: (value) => validator: (value) =>
hasKeys(value, ['required', 'type', 'key', 'columns', 'name', 'default', 'options']) && hasKeys(value, [...globalFieldRules(), 'required', 'options']) &&
typeof value.required === 'boolean' && typeof value.required === 'boolean' &&
typeof value.key === 'string' && typeof value.key === 'string' &&
value.key.length > 0 && value.key.length > 0 &&

View File

@ -1,12 +1,8 @@
<template> <template>
<label class="w-full border border-solid border-gray-500 focus-within:border-primary rounded-lg relative flex" :for="field.key"> <label class="w-full border border-solid border-gray-500 focus-within:border-primary rounded-lg relative flex"
<select :for="field.key">
:id="field.key" <select :id="field.key" v-model="inner" :disabled="disabled" :name="field.key"
v-model="inner" class="bg-white rounded-lg focus:outline-none text-gray-600 text-left peer py-1 px-2 @sm:py-2 text-sm @sm:text-base @sm:px-3 w-full">
:disabled="disabled"
:name="field.key"
class="bg-white rounded-lg focus:outline-none text-gray-600 text-left peer py-1 px-2 @sm:py-2 text-sm @sm:text-base @sm:px-3 w-full"
>
<option :value="null">-- kein --</option> <option :value="null">-- kein --</option>
<option v-for="(option, index) in options" :key="index" :value="option.id" v-text="option.name"></option> <option v-for="(option, index) in options" :key="index" :value="option.id" v-text="option.name"></option>
</select> </select>
@ -15,7 +11,7 @@
</template> </template>
<script setup> <script setup>
import {computed, ref, watch} from 'vue'; import { computed, ref, watch } from 'vue';
import FieldLabel from '../FieldLabel.vue'; import FieldLabel from '../FieldLabel.vue';
const emit = defineEmits(['update:modelValue']); const emit = defineEmits(['update:modelValue']);
@ -27,7 +23,7 @@ const props = defineProps({
field: { field: {
required: true, required: true,
validator: (value) => validator: (value) =>
hasKeys(value, ['required', 'type', 'key', 'columns', 'name', 'default', 'parent_field', 'parent_group']) && hasKeys(value, [...globalFieldRules(), 'required', 'parent_field', 'parent_group']) &&
typeof value.required === 'boolean' && typeof value.required === 'boolean' &&
typeof value.key === 'string' && typeof value.key === 'string' &&
value.key.length > 0 && value.key.length > 0 &&
@ -84,7 +80,7 @@ if (props.field.parent_field) {
if (oldValue !== newValue) { if (oldValue !== newValue) {
refreshOptions(); refreshOptions();
} }
} },
); );
} }
</script> </script>

View File

@ -1,9 +1,12 @@
<template> <template>
<div class="relative"> <div class="relative">
<div class="grid grid-cols-1 gap-2 mt-3"> <div class="grid grid-cols-1 gap-2 mt-3">
<label v-for="(option, index) in field.options" :key="index" :for="`${field.key}-${index}`" class="block relative flex items-center"> <label v-for="(option, index) in field.options" :key="index" :for="`${field.key}-${index}`"
<input :id="`${field.key}-${index}`" v-model="inner" type="radio" :name="field.key" :value="option" class="peer absolute invisible" /> class="block relative flex items-center">
<span class="border-neutral-400 border-4 border-solid peer-checked:border-primary absolute left-0 w-6 h-6 rounded-full block"></span> <input :id="`${field.key}-${index}`" v-model="inner" type="radio" :name="field.key" :value="option"
class="peer absolute invisible" />
<span
class="border-neutral-400 border-4 border-solid peer-checked:border-primary absolute left-0 w-6 h-6 rounded-full block"></span>
<span class="peer-checked:bg-primary left-2 w-2 h-2 absolute rounded-full block"></span> <span class="peer-checked:bg-primary left-2 w-2 h-2 absolute rounded-full block"></span>
<span class="pl-8 text-gray-600 text-sm @sm:text-base" v-text="option"></span> <span class="pl-8 text-gray-600 text-sm @sm:text-base" v-text="option"></span>
</label> </label>
@ -14,7 +17,7 @@
</template> </template>
<script setup> <script setup>
import {computed} from 'vue'; import { computed } from 'vue';
import FieldLabel from '../FieldLabel.vue'; import FieldLabel from '../FieldLabel.vue';
const emit = defineEmits(['update:modelValue']); const emit = defineEmits(['update:modelValue']);
@ -26,7 +29,7 @@ const props = defineProps({
field: { field: {
required: true, required: true,
validator: (value) => validator: (value) =>
hasKeys(value, ['required', 'type', 'key', 'columns', 'name', 'default', 'options']) && hasKeys(value, [...globalFieldRules(), 'required', 'options']) &&
typeof value.required === 'boolean' && typeof value.required === 'boolean' &&
typeof value.key === 'string' && typeof value.key === 'string' &&
value.key.length > 0 && value.key.length > 0 &&

View File

@ -19,7 +19,7 @@ const props = defineProps({
field: { field: {
required: true, required: true,
validator: (value) => validator: (value) =>
hasKeys(value, ['required', 'type', 'key', 'columns', 'name', 'default']) && hasKeys(value, [...globalFieldRules(), 'required']) &&
typeof value.required === 'boolean' && typeof value.required === 'boolean' &&
typeof value.key === 'string' && typeof value.key === 'string' &&
value.key.length > 0 && value.key.length > 0 &&

View File

@ -1,18 +1,13 @@
<template> <template>
<label class="w-full border border-solid border-gray-500 focus-within:border-primary rounded-lg relative flex"> <label class="w-full border border-solid border-gray-500 focus-within:border-primary rounded-lg relative flex">
<textarea <textarea :id="field.key" v-model="inner" :name="field.key" :rows="field.rows"
:id="field.key" class="bg-white rounded-lg focus:outline-none text-gray-600 text-left py-1 px-2 @sm:py-2 text-sm @sm:text-base @sm:px-3 w-full" />
v-model="inner"
:name="field.key"
:rows="field.rows"
class="bg-white rounded-lg focus:outline-none text-gray-600 text-left py-1 px-2 @sm:py-2 text-sm @sm:text-base @sm:px-3 w-full"
/>
<field-label :name="field.name" :required="field.required"></field-label> <field-label :name="field.name" :required="field.required"></field-label>
</label> </label>
</template> </template>
<script setup> <script setup>
import {computed} from 'vue'; import { computed } from 'vue';
import FieldLabel from '../FieldLabel.vue'; import FieldLabel from '../FieldLabel.vue';
const emit = defineEmits(['update:modelValue']); const emit = defineEmits(['update:modelValue']);
@ -24,7 +19,7 @@ const props = defineProps({
field: { field: {
required: true, required: true,
validator: (value) => validator: (value) =>
hasKeys(value, ['required', 'type', 'key', 'columns', 'name', 'default', 'rows']) && hasKeys(value, [...globalFieldRules(), 'required', 'rows']) &&
typeof value.required === 'boolean' && typeof value.required === 'boolean' &&
typeof value.key === 'string' && typeof value.key === 'string' &&
value.key.length > 0 && value.key.length > 0 &&

View File

@ -12,7 +12,22 @@ window.axios = axios;
axios.defaults.baseURL = window.document.querySelector('[name="adrema_base_url"]').content; axios.defaults.baseURL = window.document.querySelector('[name="adrema_base_url"]').content;
window.hasKeys = function (object, expected) { window.hasKeys = function (object, expected) {
return typeof object === 'object' && JSON.stringify(Object.keys(object).sort()) === JSON.stringify(expected.sort()); if (typeof object !== 'object') {
return false;
}
var givenKeys = JSON.stringify(Object.keys(object).sort());
var expectedKeys = JSON.stringify(expected.sort());
if (givenKeys !== expectedKeys) {
console.log('Fields ' + givenKeys + ' dont match ' + expectedKeys);
return false;
}
return true;
};
window.globalFieldRules = function () {
return ['default', 'nami_type', 'for_members', 'key', 'columns', 'name', 'type'];
}; };
EventForm.styles = [classes, carousel, carouselStyle]; EventForm.styles = [classes, carousel, carouselStyle];