From beba79626858aee4f37846b25c7b10dd7139bb6f Mon Sep 17 00:00:00 2001 From: francesco Date: Wed, 24 Jun 2020 01:03:50 +0200 Subject: [PATCH] Enhanced Firestore sync in form fields --- src/form/EntityForm.tsx | 27 ++++++++++++++++++-------- src/form/fields/DisabledField.tsx | 4 +++- src/form/fields/StorageUploadField.tsx | 18 ++++++++++++----- src/form/index.tsx | 17 ++++++++-------- 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/form/EntityForm.tsx b/src/form/EntityForm.tsx index 00583e5..3d9909e 100644 --- a/src/form/EntityForm.tsx +++ b/src/form/EntityForm.tsx @@ -51,12 +51,11 @@ export default function EntityForm({ const [customId, setCustomId] = React.useState(undefined); const [customIdError, setCustomIdError] = React.useState(false); const [savingError, setSavingError] = React.useState(); + /** * Base values are the ones this view is initialized from, we use them to * compare them with underlying changes in Firestore */ - // const [baseValues, setBaseValues] = React.useState>(); - let baseValues: EntityValues; if (status === EntityStatus.new) { baseValues = (initEntityValues(schema)); @@ -70,6 +69,8 @@ export default function EntityForm({ function saveValues(values: EntityValues, actions: FormikHelpers>) { + console.log("Saving values", values); + if (mustSetCustomId && !customId) { console.error("Missing custom Id"); setCustomIdError(true); @@ -93,6 +94,7 @@ export default function EntityForm({ } onEntitySave(collectionPath, id, values) + .then(_ => actions.setTouched({})) .catch(e => { console.error(e); setSavingError(e); @@ -103,24 +105,33 @@ export default function EntityForm({ } - return ( } onSubmit={saveValues} validationSchema={getYupObjectSchema(schema.properties)} > - {({ values, setFieldValue, errors, touched, handleChange, handleBlur, handleSubmit, isSubmitting }) => { + {({ values, touched, setFieldValue, setFieldTouched, handleSubmit, isSubmitting }) => { let underlyingValuesChanged: [string, unknown][] = []; if (baseValues && entity) { - underlyingValuesChanged = Object.entries(entity.values).filter(([key, value]) => !deepEqual(baseValues[key], value)); + + underlyingValuesChanged = Object.entries(entity.values) + .filter(([key, value]) => !deepEqual(baseValues[key], value)); + // we update the form fields from the Firestore data // if they were not touched - Object.entries(entity.values).forEach(([key, value]) => { - if (!deepEqual(values[key], value) && !touched[key]) - setFieldValue(key, value); + const objectKeys = Object.entries(schema.properties) + .map(([key, property]) => key); + objectKeys.forEach((key) => { + const firestoreValue = entity.values[key]; + const formValue = values[key]; + if (!deepEqual(firestoreValue, formValue) && !touched[key]) { + setFieldValue(key, !!firestoreValue ? firestoreValue : null); + setFieldTouched(key, false); + } }); + } function createFormFields(schema: EntitySchema) { diff --git a/src/form/fields/DisabledField.tsx b/src/form/fields/DisabledField.tsx index 1d41c0a..8462ebb 100644 --- a/src/form/fields/DisabledField.tsx +++ b/src/form/fields/DisabledField.tsx @@ -23,12 +23,14 @@ export default function DisabledField({ field, property, + {hasValue && } - {!hasValue && No value set} + {!hasValue && No value set} + {includeDescription && property.description && diff --git a/src/form/fields/StorageUploadField.tsx b/src/form/fields/StorageUploadField.tsx index fb5f413..042794b 100644 --- a/src/form/fields/StorageUploadField.tsx +++ b/src/form/fields/StorageUploadField.tsx @@ -29,6 +29,7 @@ import { CMSFieldProps } from "../form_props"; import { useDropzone } from "react-dropzone"; import ClearIcon from "@material-ui/icons/Clear"; import PreviewComponent from "../../preview/PreviewComponent"; +import deepEqual from "deep-equal"; type StorageUploadFieldProps = CMSFieldProps ; @@ -58,6 +59,8 @@ export default function StorageUploadField({ const value = multipleFilesSupported ? (Array.isArray(field.value) ? field.value : []) : field.value; + console.log("StorageUploadField", value); + return ( @@ -117,7 +120,7 @@ export function StorageUpload({ const classes = formStyles(); - const initialValue: StorageFieldItem[] = multipleFilesSupported ? + const internalInitialValue: StorageFieldItem[] = multipleFilesSupported ? (value as string[]).map(v => ( { storagePath: v @@ -126,7 +129,12 @@ export function StorageUpload({ storagePath: value as string }]; - const [internalValue, setInternalValue] = React.useState(initialValue); + const [initialValue, setInitialValue] = React.useState(value); + const [internalValue, setInternalValue] = React.useState(internalInitialValue); + if (!deepEqual(initialValue, value)) { + setInitialValue(value) + setInternalValue(internalInitialValue); + } function removeDuplicates(items: StorageFieldItem[]) { return items.filter( @@ -222,7 +230,7 @@ export function StorageUpload({ flexDirection="row" flexWrap="wrap" alignItems="center" - minHeight={220}> + minHeight={250}> {internalValue.map(entry => { if (entry.storagePath) { @@ -378,8 +386,8 @@ export function StorageItemPreview({ variant={"outlined"}> , T = any>(name: string, @@ -49,11 +48,9 @@ function buildField

, T = any>(name: string, {underlyingValueHasChanged && - - - This value has been updated in Firestore - - } + + This value has been updated in Firestore + } ; } @@ -129,7 +126,8 @@ export function createCustomIdField(schema: EntitySchema, formType: EntityStatus }; return ( - + {hasEnumValues && schema.customId && @@ -141,7 +139,10 @@ export function createCustomIdField(schema: EntitySchema, formType: EntityStatus onChange={(event: any) => onChange(event.target.value)}> {Object.entries(schema.customId).map(([key, label]) => {`${key} - ${label}`})} + key={`custom-id-item-${key}`} + value={key}> + {`${key} - ${label}`} + )} }