@firecms/core 3.0.0-canary.283 → 3.0.0-canary.284
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/EntityEditView.d.ts +2 -2
- package/dist/form/EntityForm.d.ts +3 -1
- package/dist/form/index.d.ts +2 -1
- package/dist/index.es.js +121 -97
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +119 -95
- package/dist/index.umd.js.map +1 -1
- package/dist/types/collections.d.ts +7 -0
- package/package.json +5 -5
- package/src/core/EntityEditView.tsx +13 -10
- package/src/core/EntityEditViewFormActions.tsx +33 -18
- package/src/form/EntityForm.tsx +49 -25
- package/src/form/EntityFormActions.tsx +30 -15
- package/src/form/components/ErrorFocus.tsx +22 -29
- package/src/form/index.tsx +5 -1
- package/src/types/collections.ts +8 -0
- package/src/util/entity_cache.ts +0 -1
|
@@ -44,9 +44,9 @@ export interface EntityEditViewProps<M extends Record<string, any>> {
|
|
|
44
44
|
* an entity is opened.
|
|
45
45
|
*/
|
|
46
46
|
export declare function EntityEditView<M extends Record<string, any>, USER extends User>({ entityId, ...props }: EntityEditViewProps<M>): import("react/jsx-runtime").JSX.Element;
|
|
47
|
-
export declare function EntityEditViewInner<M extends Record<string, any>>({ path, fullIdPath, entityId, selectedTab: selectedTabProp, collection, parentCollectionIds, onValuesModified, onSaved, onTabChange, entity,
|
|
47
|
+
export declare function EntityEditViewInner<M extends Record<string, any>>({ path, fullIdPath, entityId, selectedTab: selectedTabProp, collection, parentCollectionIds, onValuesModified, onSaved, onTabChange, entity, initialDirtyValues, dataLoading, layout, barActions, status, setStatus, formProps, canEdit }: EntityEditViewProps<M> & {
|
|
48
48
|
entity?: Entity<M>;
|
|
49
|
-
|
|
49
|
+
initialDirtyValues?: Partial<M>;
|
|
50
50
|
dataLoading: boolean;
|
|
51
51
|
status: EntityStatus;
|
|
52
52
|
setStatus: (status: EntityStatus) => void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { Entity, EntityCollection, EntityCustomViewParams, EntityStatus, FormContext } from "../types";
|
|
2
|
+
import { AuthController, Entity, EntityCollection, EntityCustomViewParams, EntityStatus, EntityValues, FormContext, PropertyConfig } from "../types";
|
|
3
3
|
import { FormexController } from "@firecms/formex";
|
|
4
4
|
import { ValidationError } from "yup";
|
|
5
5
|
import { EntityFormActionsProps } from "./EntityFormActions";
|
|
@@ -46,5 +46,7 @@ export type EntityFormProps<M extends Record<string, any>> = {
|
|
|
46
46
|
Builder?: React.ComponentType<EntityCustomViewParams<M>>;
|
|
47
47
|
children?: React.ReactNode;
|
|
48
48
|
};
|
|
49
|
+
export declare function extractTouchedValues(values: any, touched: Record<string, boolean>): Record<string, any>;
|
|
49
50
|
export declare function EntityForm<M extends Record<string, any>>({ path, fullIdPath, entityId: entityIdProp, collection, onValuesModified, onIdChange, onSaved, entity, initialDirtyValues, onFormContextReady, forceActionsAtTheBottom, initialStatus, className, onStatusChange, onEntityChange, openEntityMode, formex: formexProp, disabled: disabledProp, Builder, EntityFormActionsComponent, showDefaultActions, showEntityPath, children }: EntityFormProps<M>): import("react/jsx-runtime").JSX.Element;
|
|
51
|
+
export declare function getInitialEntityValues<M extends object>(authController: AuthController, collection: EntityCollection, path: string, status: "new" | "existing" | "copy", entity: Entity<M> | undefined, propertyConfigs?: Record<string, PropertyConfig>): Partial<EntityValues<M>>;
|
|
50
52
|
export declare function yupToFormErrors(yupError: ValidationError): Record<string, any>;
|
package/dist/form/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { EntityForm, yupToFormErrors, } from "./EntityForm";
|
|
2
|
+
export type { EntityFormProps } from "./EntityForm";
|
|
2
3
|
export { SelectFieldBinding } from "./field_bindings/SelectFieldBinding";
|
|
3
4
|
export { MultiSelectFieldBinding } from "./field_bindings/MultiSelectFieldBinding";
|
|
4
5
|
export { ArrayOfReferencesFieldBinding } from "./field_bindings/ArrayOfReferencesFieldBinding";
|
package/dist/index.es.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx, Fragment, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { c } from "react-compiler-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import React__default, { useRef, useEffect, useContext, useCallback, useMemo, useState, createElement, createRef, createContext, forwardRef, useLayoutEffect
|
|
4
|
+
import React__default, { useRef, useEffect, useContext, useCallback, useMemo, useState, createElement, createRef, createContext, forwardRef, useLayoutEffect } from "react";
|
|
5
5
|
import { getColorSchemeForSeed, CHIP_COLORS, FunctionsIcon, CircleIcon, iconKeys, coolIconKeys, Icon, Tooltip, ErrorIcon, Typography, IconButton, ContentCopyIcon, OpenInNewIcon, DescriptionIcon, cls, Skeleton, Chip, defaultBorderMixin, KeyboardTabIcon, Checkbox, AccountCircleIcon, Markdown, TextareaAutosize, focusedDisabled, MultiSelect, MultiSelectItem, Select, SelectItem, BooleanSwitch, DateTimeField, paperMixin, EditIcon, DoNotDisturbOnIcon, Menu, MenuItem, MoreVertIcon, CircularProgress, SearchBar, Badge, ArrowUpwardIcon, Popover, FilterListIcon, Button, CenteredView, AssignmentIcon, Label, CloseIcon, TextField, BooleanSwitchWithLabel, useOutsideAlerter, Dialog, DialogTitle, DialogContent, DialogActions, FileCopyIcon, DeleteIcon, AddIcon, StarIcon, Collapse, ExpandablePanel, ArrowForwardIcon, Card, cardMixin, cardClickableMixin, Container, LoadingButton, Alert, CheckIcon, NotesIcon, InfoIcon, fieldBackgroundMixin, RemoveIcon, fieldBackgroundDisabledMixin, fieldBackgroundHoverMixin, ArrowDropDownIcon, FilterListOffIcon, SearchIcon, Avatar, DarkModeIcon, LightModeIcon, BrightnessMediumIcon, LogoutIcon, HandleIcon, KeyboardArrowUpIcon, KeyboardArrowDownIcon, debounce, Sheet, Tab, Tabs, CodeIcon, OpenInFullIcon, ViewStreamIcon, RepeatIcon, BallotIcon, ScheduleIcon, AddLinkIcon, LinkIcon, DriveFolderUploadIcon, UploadFileIcon, FormatListNumberedIcon, NumbersIcon, PersonIcon, ListAltIcon, ListIcon, FlagIcon, MailIcon, HttpIcon, FormatQuoteIcon, SubjectIcon, ShortTextIcon, MenuIcon, ChevronLeftIcon } from "@firecms/ui";
|
|
6
6
|
import { SnackbarProvider as SnackbarProvider$1, useSnackbar } from "notistack";
|
|
7
7
|
import hash from "object-hash";
|
|
8
|
-
import { getIn, useFormex, setIn, useCreateFormex, Formex, Field } from "@firecms/formex";
|
|
8
|
+
import { getIn, useFormex, setIn, useCreateFormex, flattenKeys, Formex, Field } from "@firecms/formex";
|
|
9
9
|
import { useNavigate, useLocation, Link, NavLink, Routes, Route, createBrowserRouter, RouterProvider } from "react-router-dom";
|
|
10
10
|
import Fuse from "fuse.js";
|
|
11
11
|
import equal from "react-fast-compare";
|
|
@@ -14989,61 +14989,60 @@ function CustomIdField({
|
|
|
14989
14989
|
] });
|
|
14990
14990
|
}
|
|
14991
14991
|
const ErrorFocus = (t0) => {
|
|
14992
|
-
const $ = c(
|
|
14992
|
+
const $ = c(10);
|
|
14993
14993
|
const {
|
|
14994
14994
|
containerRef
|
|
14995
14995
|
} = t0;
|
|
14996
14996
|
const {
|
|
14997
|
-
isSubmitting,
|
|
14998
14997
|
isValidating,
|
|
14999
|
-
errors
|
|
14998
|
+
errors,
|
|
14999
|
+
version
|
|
15000
15000
|
} = useFormex();
|
|
15001
|
+
const prevVersion = useRef(version);
|
|
15001
15002
|
let t1;
|
|
15002
|
-
|
|
15003
|
-
if ($[0] !== containerRef || $[1] !== errors || $[2] !== isSubmitting || $[3] !== isValidating) {
|
|
15003
|
+
if ($[0] !== containerRef?.current || $[1] !== errors || $[2] !== isValidating || $[3] !== version) {
|
|
15004
15004
|
t1 = () => {
|
|
15005
|
+
if (version === prevVersion.current) {
|
|
15006
|
+
return;
|
|
15007
|
+
}
|
|
15005
15008
|
const keys = Object.keys(errors);
|
|
15006
|
-
if (keys.length > 0
|
|
15009
|
+
if (!isValidating && keys.length > 0) {
|
|
15007
15010
|
const errorElement = containerRef?.current?.querySelector(`#form_field_${keys[0]}`);
|
|
15008
|
-
if (errorElement
|
|
15009
|
-
|
|
15010
|
-
|
|
15011
|
-
|
|
15012
|
-
|
|
15013
|
-
top: scrollableParent.scrollTop + top - 196,
|
|
15014
|
-
behavior: "smooth"
|
|
15015
|
-
});
|
|
15016
|
-
}
|
|
15011
|
+
if (errorElement) {
|
|
15012
|
+
errorElement.scrollIntoView({
|
|
15013
|
+
behavior: "smooth",
|
|
15014
|
+
block: "center"
|
|
15015
|
+
});
|
|
15017
15016
|
const input = errorElement.querySelector("input");
|
|
15018
15017
|
if (input) {
|
|
15019
15018
|
input.focus();
|
|
15020
15019
|
}
|
|
15021
15020
|
}
|
|
15021
|
+
prevVersion.current = version;
|
|
15022
15022
|
}
|
|
15023
15023
|
};
|
|
15024
|
-
|
|
15025
|
-
$[0] = containerRef;
|
|
15024
|
+
$[0] = containerRef?.current;
|
|
15026
15025
|
$[1] = errors;
|
|
15027
|
-
$[2] =
|
|
15028
|
-
$[3] =
|
|
15026
|
+
$[2] = isValidating;
|
|
15027
|
+
$[3] = version;
|
|
15029
15028
|
$[4] = t1;
|
|
15030
|
-
$[5] = t2;
|
|
15031
15029
|
} else {
|
|
15032
15030
|
t1 = $[4];
|
|
15033
|
-
|
|
15031
|
+
}
|
|
15032
|
+
let t2;
|
|
15033
|
+
if ($[5] !== containerRef || $[6] !== errors || $[7] !== isValidating || $[8] !== version) {
|
|
15034
|
+
t2 = [isValidating, errors, containerRef, version];
|
|
15035
|
+
$[5] = containerRef;
|
|
15036
|
+
$[6] = errors;
|
|
15037
|
+
$[7] = isValidating;
|
|
15038
|
+
$[8] = version;
|
|
15039
|
+
$[9] = t2;
|
|
15040
|
+
} else {
|
|
15041
|
+
t2 = $[9];
|
|
15034
15042
|
}
|
|
15035
15043
|
useEffect(t1, t2);
|
|
15036
15044
|
return null;
|
|
15037
15045
|
};
|
|
15038
|
-
const isScrollable = (ele) => {
|
|
15039
|
-
const hasScrollableContent = ele && ele.scrollHeight > ele.clientHeight;
|
|
15040
|
-
const overflowYStyle = ele ? window.getComputedStyle(ele).overflowY : null;
|
|
15041
|
-
const isOverflowHidden = overflowYStyle && overflowYStyle.indexOf("hidden") !== -1;
|
|
15042
|
-
return hasScrollableContent && !isOverflowHidden;
|
|
15043
|
-
};
|
|
15044
|
-
const getScrollableParent = (ele) => {
|
|
15045
|
-
return !ele || ele === document.body ? document.body : isScrollable(ele) ? ele : getScrollableParent(ele.parentNode);
|
|
15046
|
-
};
|
|
15047
15046
|
function EntityFormActions(t0) {
|
|
15048
15047
|
const $ = c(16);
|
|
15049
15048
|
const {
|
|
@@ -15064,7 +15063,7 @@ function EntityFormActions(t0) {
|
|
|
15064
15063
|
const context = useFireCMSContext();
|
|
15065
15064
|
const sideEntityController = useSideEntityController();
|
|
15066
15065
|
let t1;
|
|
15067
|
-
if ($[0] !== collection || $[1] !== context || $[2] !== disabled || $[3] !== entity || $[4] !== formContext || $[5] !== formex
|
|
15066
|
+
if ($[0] !== collection || $[1] !== context || $[2] !== disabled || $[3] !== entity || $[4] !== formContext || $[5] !== formex || $[6] !== fullIdPath || $[7] !== fullPath || $[8] !== layout || $[9] !== navigateBack || $[10] !== openEntityMode || $[11] !== pluginActions || $[12] !== savingError || $[13] !== sideEntityController || $[14] !== status) {
|
|
15068
15067
|
t1 = layout === "bottom" ? buildBottomActions$1({
|
|
15069
15068
|
fullPath,
|
|
15070
15069
|
fullIdPath,
|
|
@@ -15073,13 +15072,13 @@ function EntityFormActions(t0) {
|
|
|
15073
15072
|
collection,
|
|
15074
15073
|
context,
|
|
15075
15074
|
sideEntityController,
|
|
15076
|
-
isSubmitting: formex.isSubmitting,
|
|
15077
15075
|
disabled,
|
|
15078
15076
|
status,
|
|
15079
15077
|
pluginActions,
|
|
15080
15078
|
openEntityMode,
|
|
15081
15079
|
navigateBack,
|
|
15082
|
-
formContext
|
|
15080
|
+
formContext,
|
|
15081
|
+
formex
|
|
15083
15082
|
}) : buildSideActions$1({
|
|
15084
15083
|
fullPath,
|
|
15085
15084
|
fullIdPath,
|
|
@@ -15088,18 +15087,18 @@ function EntityFormActions(t0) {
|
|
|
15088
15087
|
collection,
|
|
15089
15088
|
context,
|
|
15090
15089
|
sideEntityController,
|
|
15091
|
-
isSubmitting: formex.isSubmitting,
|
|
15092
15090
|
disabled,
|
|
15093
15091
|
status,
|
|
15094
15092
|
pluginActions,
|
|
15095
|
-
openEntityMode
|
|
15093
|
+
openEntityMode,
|
|
15094
|
+
formex
|
|
15096
15095
|
});
|
|
15097
15096
|
$[0] = collection;
|
|
15098
15097
|
$[1] = context;
|
|
15099
15098
|
$[2] = disabled;
|
|
15100
15099
|
$[3] = entity;
|
|
15101
15100
|
$[4] = formContext;
|
|
15102
|
-
$[5] = formex
|
|
15101
|
+
$[5] = formex;
|
|
15103
15102
|
$[6] = fullIdPath;
|
|
15104
15103
|
$[7] = fullPath;
|
|
15105
15104
|
$[8] = layout;
|
|
@@ -15124,14 +15123,15 @@ function buildBottomActions$1({
|
|
|
15124
15123
|
collection,
|
|
15125
15124
|
context,
|
|
15126
15125
|
sideEntityController,
|
|
15127
|
-
isSubmitting,
|
|
15128
15126
|
disabled,
|
|
15129
15127
|
status,
|
|
15130
15128
|
pluginActions,
|
|
15131
15129
|
openEntityMode,
|
|
15132
15130
|
navigateBack,
|
|
15133
|
-
formContext
|
|
15131
|
+
formContext,
|
|
15132
|
+
formex
|
|
15134
15133
|
}) {
|
|
15134
|
+
const hasErrors = Object.keys(formex.errors).length > 0 && formex.submitCount > 0;
|
|
15135
15135
|
return /* @__PURE__ */ jsxs(DialogActions, { position: "absolute", children: [
|
|
15136
15136
|
savingError && /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Typography, { color: "error", children: savingError.message }) }),
|
|
15137
15137
|
entity && (formActions ?? []).length > 0 && /* @__PURE__ */ jsx("div", { className: "flex-grow flex overflow-auto no-scrollbar", children: (formActions ?? []).map((action) => /* @__PURE__ */ jsx(IconButton, { color: "primary", onClick: (event) => {
|
|
@@ -15150,8 +15150,8 @@ function buildBottomActions$1({
|
|
|
15150
15150
|
});
|
|
15151
15151
|
}, children: action.icon }, action.name)) }),
|
|
15152
15152
|
pluginActions,
|
|
15153
|
-
/* @__PURE__ */ jsx(Button, { variant: "text", disabled: disabled || isSubmitting, color: "primary", type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
|
|
15154
|
-
/* @__PURE__ */ jsxs(Button, { variant: "filled", color: "primary", type: "submit", disabled: disabled || isSubmitting, children: [
|
|
15153
|
+
/* @__PURE__ */ jsx(Button, { variant: "text", disabled: disabled || formex.isSubmitting, color: "primary", type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
|
|
15154
|
+
/* @__PURE__ */ jsxs(Button, { variant: "filled", color: "primary", type: "submit", disabled: disabled || formex.isSubmitting, startIcon: hasErrors ? /* @__PURE__ */ jsx(ErrorIcon, {}) : void 0, children: [
|
|
15155
15155
|
status === "existing" && "Save",
|
|
15156
15156
|
status === "copy" && "Create copy",
|
|
15157
15157
|
status === "new" && "Create"
|
|
@@ -15168,22 +15168,35 @@ function buildSideActions$1({
|
|
|
15168
15168
|
collection,
|
|
15169
15169
|
context,
|
|
15170
15170
|
sideEntityController,
|
|
15171
|
-
isSubmitting,
|
|
15172
15171
|
disabled,
|
|
15173
15172
|
status,
|
|
15174
|
-
pluginActions
|
|
15173
|
+
pluginActions,
|
|
15174
|
+
formex
|
|
15175
15175
|
}) {
|
|
15176
|
+
const hasErrors = Object.keys(formex.errors).length > 0 && formex.submitCount > 0;
|
|
15176
15177
|
return /* @__PURE__ */ jsxs("div", { className: cls("overflow-auto h-full flex flex-col gap-2 w-80 2xl:w-96 px-4 py-16 sticky top-0 border-l", defaultBorderMixin), children: [
|
|
15177
|
-
/* @__PURE__ */ jsxs(LoadingButton, { fullWidth: true, variant: "filled", color: "primary", type: "submit", size: "large", disabled: disabled || isSubmitting, children: [
|
|
15178
|
+
/* @__PURE__ */ jsxs(LoadingButton, { fullWidth: true, variant: "filled", color: "primary", type: "submit", size: "large", startIcon: hasErrors ? /* @__PURE__ */ jsx(ErrorIcon, {}) : void 0, disabled: disabled || formex.isSubmitting, children: [
|
|
15178
15179
|
status === "existing" && "Save",
|
|
15179
15180
|
status === "copy" && "Create copy",
|
|
15180
15181
|
status === "new" && "Create"
|
|
15181
15182
|
] }),
|
|
15182
|
-
/* @__PURE__ */ jsx(Button, { fullWidth: true, variant: "text", disabled: disabled || isSubmitting, type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
|
|
15183
|
+
/* @__PURE__ */ jsx(Button, { fullWidth: true, variant: "text", disabled: disabled || formex.isSubmitting, type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
|
|
15183
15184
|
pluginActions,
|
|
15184
15185
|
savingError && /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Typography, { color: "error", children: savingError.message }) })
|
|
15185
15186
|
] });
|
|
15186
15187
|
}
|
|
15188
|
+
function extractTouchedValues(values, touched) {
|
|
15189
|
+
let acc = {};
|
|
15190
|
+
if (!touched || typeof touched !== "object") {
|
|
15191
|
+
return acc;
|
|
15192
|
+
}
|
|
15193
|
+
Object.entries(touched).forEach(([key, value]) => {
|
|
15194
|
+
if (value) {
|
|
15195
|
+
acc = setIn(acc, key, getIn(values, key));
|
|
15196
|
+
}
|
|
15197
|
+
});
|
|
15198
|
+
return acc;
|
|
15199
|
+
}
|
|
15187
15200
|
function EntityForm({
|
|
15188
15201
|
path,
|
|
15189
15202
|
fullIdPath,
|
|
@@ -15241,7 +15254,7 @@ function EntityForm({
|
|
|
15241
15254
|
const customizationController = useCustomizationController();
|
|
15242
15255
|
const context = useFireCMSContext();
|
|
15243
15256
|
const analyticsController = useAnalyticsController();
|
|
15244
|
-
const [underlyingChanges
|
|
15257
|
+
const [underlyingChanges] = useState({});
|
|
15245
15258
|
const [customIdLoading, setCustomIdLoading] = useState(false);
|
|
15246
15259
|
const mustSetCustomId = (status === "new" || status === "copy") && Boolean(collection.customId) && collection.customId !== "optional";
|
|
15247
15260
|
const initialEntityId = useMemo(() => {
|
|
@@ -15289,16 +15302,30 @@ function EntityForm({
|
|
|
15289
15302
|
formexController.setSubmitting(false);
|
|
15290
15303
|
});
|
|
15291
15304
|
};
|
|
15305
|
+
const baseInitialValues = getInitialEntityValues(authController, collection, path, status, entity, customizationController.propertyConfigs);
|
|
15306
|
+
const initialValues = initialDirtyValues ? mergeDeep(baseInitialValues, initialDirtyValues) : baseInitialValues;
|
|
15307
|
+
const initialDirty = Boolean(initialDirtyValues) && initialDirtyValues && Object.keys(initialDirtyValues).length > 0;
|
|
15292
15308
|
const formex = formexProp ?? useCreateFormex({
|
|
15293
|
-
initialValues
|
|
15294
|
-
initialDirty
|
|
15309
|
+
initialValues,
|
|
15310
|
+
initialDirty,
|
|
15311
|
+
initialTouched: initialDirtyValues ? flattenKeys(initialDirtyValues).reduce((previousValue, currentValue) => ({
|
|
15312
|
+
...previousValue,
|
|
15313
|
+
[currentValue]: true
|
|
15314
|
+
}), {}) : {},
|
|
15295
15315
|
onSubmit,
|
|
15296
15316
|
onReset: () => {
|
|
15297
15317
|
clearDirtyCache();
|
|
15298
15318
|
onValuesModified?.(false);
|
|
15299
15319
|
},
|
|
15300
|
-
|
|
15301
|
-
|
|
15320
|
+
onValuesChangeDeferred: (values_0, controller) => {
|
|
15321
|
+
const key = status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId;
|
|
15322
|
+
if (controller.dirty) {
|
|
15323
|
+
const touchedValues = extractTouchedValues(values_0, controller.touched);
|
|
15324
|
+
saveEntityToCache(key, touchedValues);
|
|
15325
|
+
}
|
|
15326
|
+
},
|
|
15327
|
+
validation: (values_1) => {
|
|
15328
|
+
return validationSchema?.validate(values_1, {
|
|
15302
15329
|
abortEarly: false
|
|
15303
15330
|
}).then(() => {
|
|
15304
15331
|
return {};
|
|
@@ -15381,7 +15408,7 @@ function EntityForm({
|
|
|
15381
15408
|
console.error(e_3);
|
|
15382
15409
|
}, [entityId, path, snackbarController]);
|
|
15383
15410
|
const saveEntity = ({
|
|
15384
|
-
values:
|
|
15411
|
+
values: values_2,
|
|
15385
15412
|
previousValues,
|
|
15386
15413
|
entityId: entityId_0,
|
|
15387
15414
|
collection: collection_0,
|
|
@@ -15390,7 +15417,7 @@ function EntityForm({
|
|
|
15390
15417
|
return saveEntityWithCallbacks({
|
|
15391
15418
|
path: path_0,
|
|
15392
15419
|
entityId: entityId_0,
|
|
15393
|
-
values:
|
|
15420
|
+
values: values_2,
|
|
15394
15421
|
previousValues,
|
|
15395
15422
|
collection: collection_0,
|
|
15396
15423
|
status,
|
|
@@ -15406,34 +15433,34 @@ function EntityForm({
|
|
|
15406
15433
|
collection: collection_1,
|
|
15407
15434
|
path: path_1,
|
|
15408
15435
|
entityId: entityId_1,
|
|
15409
|
-
values:
|
|
15436
|
+
values: values_3,
|
|
15410
15437
|
previousValues: previousValues_0,
|
|
15411
15438
|
autoSave: autoSave_0
|
|
15412
15439
|
}) => {
|
|
15413
15440
|
if (!status) return;
|
|
15414
15441
|
if (autoSave_0) {
|
|
15415
|
-
setValuesToBeSaved(
|
|
15442
|
+
setValuesToBeSaved(values_3);
|
|
15416
15443
|
} else {
|
|
15417
15444
|
return saveEntity({
|
|
15418
15445
|
collection: collection_1,
|
|
15419
15446
|
path: path_1,
|
|
15420
15447
|
entityId: entityId_1,
|
|
15421
|
-
values:
|
|
15448
|
+
values: values_3,
|
|
15422
15449
|
previousValues: previousValues_0
|
|
15423
15450
|
});
|
|
15424
15451
|
}
|
|
15425
15452
|
};
|
|
15426
15453
|
const lastSavedValues = useRef(entity?.values);
|
|
15427
|
-
const save = (
|
|
15428
|
-
lastSavedValues.current =
|
|
15454
|
+
const save = (values_4) => {
|
|
15455
|
+
lastSavedValues.current = values_4;
|
|
15429
15456
|
return onSaveEntityRequest({
|
|
15430
15457
|
collection: resolvedCollection,
|
|
15431
15458
|
path,
|
|
15432
15459
|
entityId,
|
|
15433
|
-
values:
|
|
15460
|
+
values: values_4,
|
|
15434
15461
|
previousValues: entity?.values,
|
|
15435
15462
|
autoSave: autoSave ?? false
|
|
15436
|
-
}).then((
|
|
15463
|
+
}).then(() => {
|
|
15437
15464
|
const eventName = status === "new" ? "new_entity_saved" : status === "copy" ? "entity_copied" : status === "existing" ? "entity_edited" : "unmapped_event";
|
|
15438
15465
|
analyticsController.onAnalyticsEvent?.(eventName, {
|
|
15439
15466
|
path
|
|
@@ -15467,7 +15494,8 @@ function EntityForm({
|
|
|
15467
15494
|
type: "error",
|
|
15468
15495
|
message: "Error updating id, check the console"
|
|
15469
15496
|
});
|
|
15470
|
-
|
|
15497
|
+
console.error(error);
|
|
15498
|
+
}, [snackbarController]);
|
|
15471
15499
|
const pluginActions = [];
|
|
15472
15500
|
const plugins = customizationController.plugins;
|
|
15473
15501
|
const actionsDisabled = disabled || formex.isSubmitting || status === "existing" && !formex.dirty || Boolean(disabledProp);
|
|
@@ -15516,20 +15544,12 @@ function EntityForm({
|
|
|
15516
15544
|
onValuesModified?.(modified);
|
|
15517
15545
|
}
|
|
15518
15546
|
}, [formex.dirty]);
|
|
15519
|
-
const deferredValues = useDeferredValue(formex.values);
|
|
15520
15547
|
const modified = formex.dirty;
|
|
15521
15548
|
const uniqueFieldValidator = useCallback(({
|
|
15522
15549
|
name,
|
|
15523
|
-
value
|
|
15524
|
-
property
|
|
15550
|
+
value
|
|
15525
15551
|
}) => dataSource.checkUniqueField(path, name, value, entityId, collection), [dataSource, path, entityId]);
|
|
15526
15552
|
const validationSchema = useMemo(() => entityId ? getYupEntitySchema(entityId, resolvedCollection.properties, uniqueFieldValidator) : void 0, [entityId, resolvedCollection.properties, uniqueFieldValidator]);
|
|
15527
|
-
useEffect(() => {
|
|
15528
|
-
const key = status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId;
|
|
15529
|
-
if (modified) {
|
|
15530
|
-
saveEntityToCache(key, deferredValues);
|
|
15531
|
-
}
|
|
15532
|
-
}, [deferredValues, modified, path, entityId, status]);
|
|
15533
15553
|
useOnAutoSave(autoSave, formex, lastSavedValues, save);
|
|
15534
15554
|
useEffect(() => {
|
|
15535
15555
|
if (!autoSave && !formex.isSubmitting && underlyingChanges && entity) {
|
|
@@ -15548,18 +15568,18 @@ function EntityForm({
|
|
|
15548
15568
|
return /* @__PURE__ */ jsx(Builder, { collection, entity, modifiedValues: formex.values, formContext });
|
|
15549
15569
|
}
|
|
15550
15570
|
return /* @__PURE__ */ jsx(FormLayout, { children: formFieldKeys.map((key_1) => {
|
|
15551
|
-
const
|
|
15552
|
-
if (
|
|
15571
|
+
const property = resolvedCollection.properties[key_1];
|
|
15572
|
+
if (property) {
|
|
15553
15573
|
const underlyingValueHasChanged = !!underlyingChanges && Object.keys(underlyingChanges).includes(key_1) && formex.touched[key_1];
|
|
15554
|
-
const disabled_0 = disabledProp || !autoSave && formex.isSubmitting || isReadOnly(
|
|
15555
|
-
const hidden = isHidden(
|
|
15574
|
+
const disabled_0 = disabledProp || !autoSave && formex.isSubmitting || isReadOnly(property) || Boolean(property.disabled);
|
|
15575
|
+
const hidden = isHidden(property);
|
|
15556
15576
|
if (hidden) return null;
|
|
15557
|
-
const widthPercentage =
|
|
15577
|
+
const widthPercentage = property.widthPercentage ?? 100;
|
|
15558
15578
|
const cmsFormFieldProps = {
|
|
15559
15579
|
propertyKey: key_1,
|
|
15560
15580
|
disabled: disabled_0,
|
|
15561
|
-
property
|
|
15562
|
-
includeDescription:
|
|
15581
|
+
property,
|
|
15582
|
+
includeDescription: property.description || property.longDescription,
|
|
15563
15583
|
underlyingValueHasChanged: underlyingValueHasChanged && !autoSave,
|
|
15564
15584
|
context: formContext,
|
|
15565
15585
|
partOfArray: false,
|
|
@@ -15615,7 +15635,7 @@ function EntityForm({
|
|
|
15615
15635
|
}
|
|
15616
15636
|
const dialogActions = /* @__PURE__ */ jsx(EntityFormActionsComponent, { collection: resolvedCollection, path, fullPath: path, fullIdPath, entity, layout: forceActionsAtTheBottom ? "bottom" : "side", savingError, formex, disabled: actionsDisabled, status, pluginActions: pluginActions ?? [], openEntityMode, showDefaultActions, navigateBack, formContext });
|
|
15617
15637
|
return /* @__PURE__ */ jsx(Formex, { value: formex, children: /* @__PURE__ */ jsxs("form", { onSubmit: formex.handleSubmit, onReset: () => formex.resetForm({
|
|
15618
|
-
values:
|
|
15638
|
+
values: baseInitialValues
|
|
15619
15639
|
}), noValidate: true, className: cls("flex-1 flex flex-row w-full overflow-y-auto justify-center", className), children: [
|
|
15620
15640
|
/* @__PURE__ */ jsx("div", { id: `form_${path}`, className: cls("relative flex flex-row max-w-4xl lg:max-w-3xl xl:max-w-4xl 2xl:max-w-6xl w-full h-fit"), children: /* @__PURE__ */ jsxs("div", { className: cls("flex flex-col w-full pt-12 pb-16 px-4 sm:px-8 md:px-10"), children: [
|
|
15621
15641
|
formex.dirty ? /* @__PURE__ */ jsx(Tooltip, { title: "Local unsaved changes", className: "self-end sticky top-4 z-10", children: /* @__PURE__ */ jsx(Chip, { size: "small", colorScheme: "orangeDarker", children: /* @__PURE__ */ jsx(EditIcon, { size: "smallest" }) }) }) : /* @__PURE__ */ jsx(Tooltip, { title: "In sync with the database", className: "self-end sticky top-4 z-10", children: /* @__PURE__ */ jsx(Chip, { size: "small", children: /* @__PURE__ */ jsx(CheckIcon, { size: "smallest" }) }) }),
|
|
@@ -22828,14 +22848,14 @@ function EntityEditViewFormActions({
|
|
|
22828
22848
|
collection,
|
|
22829
22849
|
context,
|
|
22830
22850
|
sideEntityController,
|
|
22831
|
-
isSubmitting: formex.isSubmitting,
|
|
22832
22851
|
disabled,
|
|
22833
22852
|
status,
|
|
22834
22853
|
sideDialogContext,
|
|
22835
22854
|
pluginActions,
|
|
22836
22855
|
openEntityMode,
|
|
22837
22856
|
navigateBack,
|
|
22838
|
-
formContext
|
|
22857
|
+
formContext,
|
|
22858
|
+
formex
|
|
22839
22859
|
}) : buildSideActions({
|
|
22840
22860
|
savingError,
|
|
22841
22861
|
entity,
|
|
@@ -22843,14 +22863,14 @@ function EntityEditViewFormActions({
|
|
|
22843
22863
|
collection,
|
|
22844
22864
|
context,
|
|
22845
22865
|
sideEntityController,
|
|
22846
|
-
isSubmitting: formex.isSubmitting,
|
|
22847
22866
|
sideDialogContext,
|
|
22848
22867
|
disabled,
|
|
22849
22868
|
status,
|
|
22850
22869
|
pluginActions,
|
|
22851
22870
|
openEntityMode,
|
|
22852
22871
|
navigateBack,
|
|
22853
|
-
formContext
|
|
22872
|
+
formContext,
|
|
22873
|
+
formex
|
|
22854
22874
|
});
|
|
22855
22875
|
}
|
|
22856
22876
|
function buildBottomActions({
|
|
@@ -22860,15 +22880,16 @@ function buildBottomActions({
|
|
|
22860
22880
|
collection,
|
|
22861
22881
|
context,
|
|
22862
22882
|
sideEntityController,
|
|
22863
|
-
isSubmitting,
|
|
22864
22883
|
disabled,
|
|
22865
22884
|
status,
|
|
22866
22885
|
sideDialogContext,
|
|
22867
22886
|
pluginActions,
|
|
22868
22887
|
openEntityMode,
|
|
22869
22888
|
navigateBack,
|
|
22870
|
-
formContext
|
|
22889
|
+
formContext,
|
|
22890
|
+
formex
|
|
22871
22891
|
}) {
|
|
22892
|
+
const hasErrors = Object.keys(formex.errors).length > 0 && formex.submitCount > 0;
|
|
22872
22893
|
const canClose = openEntityMode === "side_panel";
|
|
22873
22894
|
return /* @__PURE__ */ jsxs(DialogActions, { position: "absolute", children: [
|
|
22874
22895
|
savingError && /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Typography, { color: "error", children: savingError.message }) }),
|
|
@@ -22888,15 +22909,16 @@ function buildBottomActions({
|
|
|
22888
22909
|
return /* @__PURE__ */ jsx(EntityActionButton, { action, enabled: isEnabled, props }, action.key);
|
|
22889
22910
|
}) }),
|
|
22890
22911
|
pluginActions,
|
|
22891
|
-
/* @__PURE__ */ jsx(
|
|
22892
|
-
/* @__PURE__ */
|
|
22912
|
+
hasErrors ? /* @__PURE__ */ jsx(ErrorTooltip, { title: "This form has errors", children: /* @__PURE__ */ jsx(ErrorIcon, { className: "ml-4", color: "error", size: "smallest" }) }) : null,
|
|
22913
|
+
/* @__PURE__ */ jsx(Button, { variant: "text", color: "primary", disabled: disabled || formex.isSubmitting, type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
|
|
22914
|
+
/* @__PURE__ */ jsxs(Button, { variant: canClose ? "text" : "filled", color: "primary", type: "submit", disabled: disabled || formex.isSubmitting, onClick: () => {
|
|
22893
22915
|
sideDialogContext.setPendingClose(false);
|
|
22894
22916
|
}, children: [
|
|
22895
22917
|
status === "existing" && "Save",
|
|
22896
22918
|
status === "copy" && "Create copy",
|
|
22897
22919
|
status === "new" && "Create"
|
|
22898
22920
|
] }),
|
|
22899
|
-
canClose && /* @__PURE__ */ jsxs(LoadingButton, { variant: "filled", color: "primary", type: "submit", loading: isSubmitting, disabled, onClick: () => {
|
|
22921
|
+
canClose && /* @__PURE__ */ jsxs(LoadingButton, { variant: "filled", color: "primary", type: "submit", loading: formex.isSubmitting, disabled, onClick: () => {
|
|
22900
22922
|
sideDialogContext.setPendingClose?.(true);
|
|
22901
22923
|
}, children: [
|
|
22902
22924
|
status === "existing" && "Save and close",
|
|
@@ -22912,24 +22934,25 @@ function buildSideActions({
|
|
|
22912
22934
|
collection,
|
|
22913
22935
|
context,
|
|
22914
22936
|
sideEntityController,
|
|
22915
|
-
isSubmitting,
|
|
22916
22937
|
disabled,
|
|
22917
22938
|
status,
|
|
22918
22939
|
sideDialogContext,
|
|
22919
22940
|
pluginActions,
|
|
22920
22941
|
openEntityMode,
|
|
22921
22942
|
navigateBack,
|
|
22922
|
-
formContext
|
|
22943
|
+
formContext,
|
|
22944
|
+
formex
|
|
22923
22945
|
}) {
|
|
22946
|
+
const hasErrors = Object.keys(formex.errors).length > 0 && formex.submitCount > 0;
|
|
22924
22947
|
return /* @__PURE__ */ jsxs("div", { className: cls("overflow-auto h-full flex flex-col gap-2 w-80 2xl:w-96 px-4 py-16 sticky top-0 border-l", defaultBorderMixin), children: [
|
|
22925
|
-
/* @__PURE__ */ jsxs(LoadingButton, { fullWidth: true, variant: "filled", color: "primary", type: "submit", size: "large", disabled: disabled || isSubmitting, onClick: () => {
|
|
22948
|
+
/* @__PURE__ */ jsxs(LoadingButton, { fullWidth: true, variant: "filled", color: "primary", type: "submit", size: "large", startIcon: hasErrors ? /* @__PURE__ */ jsx(ErrorIcon, {}) : void 0, disabled: disabled || formex.isSubmitting, onClick: () => {
|
|
22926
22949
|
sideDialogContext.setPendingClose?.(false);
|
|
22927
22950
|
}, children: [
|
|
22928
22951
|
status === "existing" && "Save",
|
|
22929
22952
|
status === "copy" && "Create copy",
|
|
22930
22953
|
status === "new" && "Create"
|
|
22931
22954
|
] }),
|
|
22932
|
-
/* @__PURE__ */ jsx(Button, { fullWidth: true, variant: "text", disabled: disabled || isSubmitting, type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
|
|
22955
|
+
/* @__PURE__ */ jsx(Button, { fullWidth: true, variant: "text", disabled: disabled || formex.isSubmitting, type: "reset", children: status === "existing" ? "Discard" : "Clear" }),
|
|
22933
22956
|
pluginActions,
|
|
22934
22957
|
formActions.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-row flex-wrap mt-2", children: formActions.map((action) => {
|
|
22935
22958
|
const props = {
|
|
@@ -23157,7 +23180,8 @@ function EntityEditView({
|
|
|
23157
23180
|
databaseId: props.databaseId,
|
|
23158
23181
|
useCache: false
|
|
23159
23182
|
});
|
|
23160
|
-
const
|
|
23183
|
+
const enableLocalChangesBackup = props.collection.enableLocalChangesBackup !== void 0 ? props.collection.enableLocalChangesBackup : true;
|
|
23184
|
+
const initialDirtyValues = enableLocalChangesBackup ? entityId ? getEntityFromCache(props.path + "/" + entityId) : getEntityFromCache(props.path + "#new") : void 0;
|
|
23161
23185
|
const authController = useAuthController();
|
|
23162
23186
|
const initialStatus = props.copy ? "copy" : entityId ? "existing" : "new";
|
|
23163
23187
|
const [status, setStatus] = useState(initialStatus);
|
|
@@ -23168,13 +23192,13 @@ function EntityEditView({
|
|
|
23168
23192
|
return entity ? canEditEntity(props.collection, authController, props.path, entity ?? null) : void 0;
|
|
23169
23193
|
}
|
|
23170
23194
|
}, [authController, entity, status]);
|
|
23171
|
-
if (dataLoading && !
|
|
23195
|
+
if (dataLoading && !initialDirtyValues || (!entity || canEdit === void 0) && (status === "existing" || status === "copy")) {
|
|
23172
23196
|
return /* @__PURE__ */ jsx(CircularProgressCenter, {});
|
|
23173
23197
|
}
|
|
23174
|
-
if (entityId && !entity && !
|
|
23198
|
+
if (entityId && !entity && !initialDirtyValues) {
|
|
23175
23199
|
console.error(`Entity with id ${entityId} not found in collection ${props.path}`);
|
|
23176
23200
|
}
|
|
23177
|
-
return /* @__PURE__ */ jsx(EntityEditViewInner, { ...props, entityId, entity,
|
|
23201
|
+
return /* @__PURE__ */ jsx(EntityEditViewInner, { ...props, entityId, entity, initialDirtyValues, dataLoading, status, setStatus, canEdit });
|
|
23178
23202
|
}
|
|
23179
23203
|
function EntityEditViewInner({
|
|
23180
23204
|
path,
|
|
@@ -23187,7 +23211,7 @@ function EntityEditViewInner({
|
|
|
23187
23211
|
onSaved,
|
|
23188
23212
|
onTabChange,
|
|
23189
23213
|
entity,
|
|
23190
|
-
|
|
23214
|
+
initialDirtyValues,
|
|
23191
23215
|
dataLoading,
|
|
23192
23216
|
layout = "side_panel",
|
|
23193
23217
|
barActions,
|
|
@@ -23315,7 +23339,7 @@ function EntityEditViewInner({
|
|
|
23315
23339
|
/* @__PURE__ */ jsx(EntityView, { className: "px-8 h-full overflow-auto", entity, path, collection }),
|
|
23316
23340
|
/* @__PURE__ */ jsx("div", { className: "h-16" })
|
|
23317
23341
|
] }) }) : null;
|
|
23318
|
-
const entityView = /* @__PURE__ */ jsx(EntityForm, { fullIdPath, collection, path, entityId: entityId ?? usedEntity?.id, onValuesModified, entity, initialDirtyValues
|
|
23342
|
+
const entityView = /* @__PURE__ */ jsx(EntityForm, { fullIdPath, collection, path, entityId: entityId ?? usedEntity?.id, onValuesModified, entity, initialDirtyValues, openEntityMode: layout, forceActionsAtTheBottom: actionsAtTheBottom, initialStatus: status, className: cls((!mainViewVisible || !canEdit) && !selectedSecondaryForm ? "hidden" : "", formProps?.className), EntityFormActionsComponent: EntityEditViewFormActions, disabled: !canEdit, ...formProps, onEntityChange: (entity_0) => {
|
|
23319
23343
|
setUsedEntity(entity_0);
|
|
23320
23344
|
formProps?.onEntityChange?.(entity_0);
|
|
23321
23345
|
}, onStatusChange: (status_0) => {
|