mirror of
https://github.com/zhigang1992/firecms.git
synced 2026-06-19 18:03:20 +08:00
Enhanced Firestore sync in form fields
This commit is contained in:
@@ -51,12 +51,11 @@ export default function EntityForm<S extends EntitySchema>({
|
||||
const [customId, setCustomId] = React.useState<string | undefined>(undefined);
|
||||
const [customIdError, setCustomIdError] = React.useState<boolean>(false);
|
||||
const [savingError, setSavingError] = React.useState<any>();
|
||||
|
||||
/**
|
||||
* 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<EntityValues<S>>();
|
||||
|
||||
let baseValues: EntityValues<S>;
|
||||
if (status === EntityStatus.new) {
|
||||
baseValues = (initEntityValues(schema));
|
||||
@@ -70,6 +69,8 @@ export default function EntityForm<S extends EntitySchema>({
|
||||
|
||||
function saveValues(values: EntityValues<S>, actions: FormikHelpers<EntityValues<S>>) {
|
||||
|
||||
console.log("Saving values", values);
|
||||
|
||||
if (mustSetCustomId && !customId) {
|
||||
console.error("Missing custom Id");
|
||||
setCustomIdError(true);
|
||||
@@ -93,6 +94,7 @@ export default function EntityForm<S extends EntitySchema>({
|
||||
}
|
||||
|
||||
onEntitySave(collectionPath, id, values)
|
||||
.then(_ => actions.setTouched({}))
|
||||
.catch(e => {
|
||||
console.error(e);
|
||||
setSavingError(e);
|
||||
@@ -103,24 +105,33 @@ export default function EntityForm<S extends EntitySchema>({
|
||||
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={baseValues as EntityValues<S>}
|
||||
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) {
|
||||
|
||||
@@ -23,12 +23,14 @@ export default function DisabledField<S extends EntitySchema>({ field, property,
|
||||
</FormHelperText>
|
||||
|
||||
<Paper elevation={0} className={classes.paper} variant={"outlined"}>
|
||||
|
||||
{hasValue &&
|
||||
<PreviewComponent value={value}
|
||||
property={property}
|
||||
small={false}/>}
|
||||
|
||||
{!hasValue && <Box m={1}>No value set</Box>}
|
||||
{!hasValue && <Box>No value set</Box>}
|
||||
|
||||
</Paper>
|
||||
|
||||
{includeDescription && property.description &&
|
||||
|
||||
@@ -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<string | string[]> ;
|
||||
|
||||
@@ -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<StorageFieldItem[]>(initialValue);
|
||||
const [initialValue, setInitialValue] = React.useState<string| string[]>(value);
|
||||
const [internalValue, setInternalValue] = React.useState<StorageFieldItem[]>(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"}>
|
||||
|
||||
<Box position={"absolute"}
|
||||
top={4}
|
||||
right={4}
|
||||
top={-8}
|
||||
right={-8}
|
||||
style={{ zIndex: 100 }}>
|
||||
<IconButton
|
||||
style={{ backgroundColor: "white" }}
|
||||
|
||||
@@ -23,7 +23,6 @@ import ArrayDefaultField from "./fields/ArrayDefaultField";
|
||||
import ArrayMapField from "./fields/ArrayMapField";
|
||||
import DisabledField from "./fields/DisabledField";
|
||||
import { CMSFieldProps } from "./form_props";
|
||||
import { Alert } from "@material-ui/lab";
|
||||
|
||||
|
||||
function buildField<P extends Property<T>, T = any>(name: string,
|
||||
@@ -49,11 +48,9 @@ function buildField<P extends Property<T>, T = any>(name: string,
|
||||
</Field>
|
||||
|
||||
{underlyingValueHasChanged &&
|
||||
<Alert>
|
||||
<FormHelperText>
|
||||
This value has been updated in Firestore
|
||||
</FormHelperText>
|
||||
</Alert>}
|
||||
<FormHelperText>
|
||||
This value has been updated in Firestore
|
||||
</FormHelperText>}
|
||||
|
||||
</React.Fragment>;
|
||||
}
|
||||
@@ -129,7 +126,8 @@ export function createCustomIdField(schema: EntitySchema, formType: EntityStatus
|
||||
};
|
||||
|
||||
return (
|
||||
<FormControl fullWidth error={error} {...fieldProps}>
|
||||
<FormControl fullWidth error={error} {...fieldProps}
|
||||
key={"custom-id-field"}>
|
||||
|
||||
{hasEnumValues && schema.customId &&
|
||||
<React.Fragment>
|
||||
@@ -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]) =>
|
||||
<MenuItem
|
||||
value={key}>{`${key} - ${label}`}</MenuItem>)}
|
||||
key={`custom-id-item-${key}`}
|
||||
value={key}>
|
||||
{`${key} - ${label}`}
|
||||
</MenuItem>)}
|
||||
</MuiSelect>
|
||||
</React.Fragment>}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user