Add useFormFields composable (#691)

* Extract use-form-fields into separate composable

* Use new composable on fields detail
This commit is contained in:
Rijk van Zanten
2020-06-09 14:44:13 -04:00
committed by GitHub
parent 6777ba94c3
commit 7f43356b6a
4 changed files with 92 additions and 76 deletions

View File

@@ -23,13 +23,10 @@ import { defineComponent, PropType, computed, ref } from '@vue/composition-api';
import { useFieldsStore } from '@/stores/fields';
import { Field } from '@/stores/fields/types';
import { useElementSize } from '@/composables/use-element-size';
import { isEmpty } from '@/utils/is-empty';
import { clone } from 'lodash';
import { FormField as TFormField } from './types';
import interfaces from '@/interfaces';
import marked from 'marked';
import getDefaultInterfaceForType from '@/utils/get-default-interface-for-type';
import FormField from './form-field.vue';
import useFormFields from '@/composables/use-form-fields';
type FieldValues = {
[field: string]: any;
@@ -46,7 +43,7 @@ export default defineComponent({
default: undefined,
},
fields: {
type: Array as PropType<TFormField[]>,
type: Array as PropType<Field[]>,
default: undefined,
},
initialValues: {
@@ -111,76 +108,7 @@ export default defineComponent({
throw new Error('[v-form]: You need to pass either the collection or fields prop.');
});
const formFields = computed(() => {
let formFields = [...fields.value];
/**
* @NOTE
*
* This can be optimized by combining a bunch of these maps and filters
*/
// Filter out the fields that are marked hidden on detail
formFields = formFields.filter((field) => {
const hiddenDetail = field.hidden_detail;
if (isEmpty(hiddenDetail)) return true;
return hiddenDetail === false;
});
// Sort the fields on the sort column value
formFields = formFields.sort((a, b) => {
if (a.sort == b.sort) return 0;
if (a.sort === null || a.sort === undefined) return 1;
if (b.sort === null || b.sort === undefined) return -1;
return a.sort > b.sort ? 1 : -1;
});
// Make sure all form fields have a width associated with it
formFields = formFields.map((field) => {
if (!field.width) {
field.width = 'full';
}
return field;
});
formFields = formFields.map((field) => {
const interfaceUsed = interfaces.find((int) => int.id === field.interface);
const interfaceExists = interfaceUsed !== undefined;
if (interfaceExists === false) {
field.interface = getDefaultInterfaceForType(field.type);
}
if (interfaceUsed?.hideLabel === true) {
(field as TFormField).hideLabel = true;
}
if (interfaceUsed?.hideLoader === true) {
(field as TFormField).hideLoader = true;
}
return field;
});
// Change the class to half-right if the current element is preceded by another half width field
// this makes them align side by side
formFields = formFields.map((field, index, formFields) => {
if (index === 0) return field;
if (field.width === 'half') {
const prevField = formFields[index - 1];
if (prevField.width === 'half') {
field.width = 'half-right';
}
}
return field;
});
return formFields;
});
const { formFields } = useFormFields(fields);
const { width } = useElementSize(el);

View File

@@ -0,0 +1,4 @@
import useFormFields from './use-form-fields';
export { useFormFields };
export default useFormFields;

View File

@@ -0,0 +1,81 @@
import { computed, Ref } from '@vue/composition-api';
import { isEmpty } from '@/utils/is-empty';
import getDefaultInterfaceForType from '@/utils/get-default-interface-for-type';
import interfaces from '@/interfaces';
import { FormField } from '@/components/v-form/types';
import { Field } from '@/stores/fields/types';
export default function useFormFields(fields: Ref<Field[]>) {
const formFields = computed(() => {
let formFields = [...fields.value];
/**
* @TODO
*
* This can be optimized by combining a bunch of these maps and filters
*/
// Filter out the fields that are marked hidden on detail
formFields = formFields.filter((field) => {
const hiddenDetail = field.hidden_detail;
if (isEmpty(hiddenDetail)) return true;
return hiddenDetail === false;
});
// Sort the fields on the sort column value
formFields = formFields.sort((a, b) => {
if (a.sort == b.sort) return 0;
if (a.sort === null || a.sort === undefined) return 1;
if (b.sort === null || b.sort === undefined) return -1;
return a.sort > b.sort ? 1 : -1;
});
// Make sure all form fields have a width associated with it
formFields = formFields.map((field) => {
if (!field.width) {
field.width = 'full';
}
return field;
});
formFields = formFields.map((field) => {
const interfaceUsed = interfaces.find((int) => int.id === field.interface);
const interfaceExists = interfaceUsed !== undefined;
if (interfaceExists === false) {
field.interface = getDefaultInterfaceForType(field.type);
}
if (interfaceUsed?.hideLabel === true) {
(field as FormField).hideLabel = true;
}
if (interfaceUsed?.hideLoader === true) {
(field as FormField).hideLoader = true;
}
return field;
});
// Change the class to half-right if the current element is preceded by another half width field
// this makes them align side by side
formFields = formFields.map((field, index, formFields) => {
if (index === 0) return field;
if (field.width === 'half') {
const prevField = formFields[index - 1];
if (prevField.width === 'half') {
field.width = 'half-right';
}
}
return field;
});
return formFields;
});
return { formFields };
}

View File

@@ -135,6 +135,7 @@ import useFieldsStore from '@/stores/fields';
import { Field } from '@/stores/fields/types';
import FileInfoDrawerDetail from './components/file-info-drawer-detail.vue';
import marked from 'marked';
import useFormFields from '@/composables/use-form-fields';
type Values = {
[field: string]: any;
@@ -193,12 +194,14 @@ export default defineComponent({
// These are the fields that will be prevented from showing up in the form
const fieldsBlacklist: string[] = ['type', 'width', 'height', 'filesize', 'checksum'];
const formFields = computed(() => {
const fieldsFiltered = computed(() => {
return fieldsStore
.getFieldsForCollection('directus_files')
.filter((field: Field) => fieldsBlacklist.includes(field.field) === false);
});
const { formFields } = useFormFields(fieldsFiltered);
const confirmLeave = ref(false);
const leaveTo = ref<string | null>(null);