From 7f43356b6a90ba73bdef0a3c07a59da7e47dedc4 Mon Sep 17 00:00:00 2001 From: Rijk van Zanten Date: Tue, 9 Jun 2020 14:44:13 -0400 Subject: [PATCH] Add useFormFields composable (#691) * Extract use-form-fields into separate composable * Use new composable on fields detail --- src/components/v-form/v-form.vue | 78 +----------------- src/composables/use-form-fields/index.ts | 4 + .../use-form-fields/use-form-fields.ts | 81 +++++++++++++++++++ src/modules/files/routes/detail/detail.vue | 5 +- 4 files changed, 92 insertions(+), 76 deletions(-) create mode 100644 src/composables/use-form-fields/index.ts create mode 100644 src/composables/use-form-fields/use-form-fields.ts diff --git a/src/components/v-form/v-form.vue b/src/components/v-form/v-form.vue index 98de152103..8d343e4928 100644 --- a/src/components/v-form/v-form.vue +++ b/src/components/v-form/v-form.vue @@ -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, + type: Array as PropType, 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); diff --git a/src/composables/use-form-fields/index.ts b/src/composables/use-form-fields/index.ts new file mode 100644 index 0000000000..ede96c2125 --- /dev/null +++ b/src/composables/use-form-fields/index.ts @@ -0,0 +1,4 @@ +import useFormFields from './use-form-fields'; + +export { useFormFields }; +export default useFormFields; diff --git a/src/composables/use-form-fields/use-form-fields.ts b/src/composables/use-form-fields/use-form-fields.ts new file mode 100644 index 0000000000..a5eb4b63ff --- /dev/null +++ b/src/composables/use-form-fields/use-form-fields.ts @@ -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) { + 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 }; +} diff --git a/src/modules/files/routes/detail/detail.vue b/src/modules/files/routes/detail/detail.vue index 134d7aa197..a210228153 100644 --- a/src/modules/files/routes/detail/detail.vue +++ b/src/modules/files/routes/detail/detail.vue @@ -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(null);