@firecms/core 3.0.0-canary.286 → 3.0.0-canary.287

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/index.umd.js CHANGED
@@ -1052,6 +1052,12 @@
1052
1052
  };
1053
1053
  });
1054
1054
  };
1055
+ function getLocalChangesBackup(collection) {
1056
+ if (!collection.localChangesBackup) {
1057
+ return "manual_apply";
1058
+ }
1059
+ return collection.localChangesBackup;
1060
+ }
1055
1061
  const kebabCaseRegex = /[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g;
1056
1062
  const toKebabCase = (str) => {
1057
1063
  const regExpMatchArray = str.match(kebabCaseRegex);
@@ -9755,7 +9761,6 @@
9755
9761
  return value;
9756
9762
  }
9757
9763
  function saveEntityToCache(path, data) {
9758
- entityCache.set(path, data);
9759
9764
  if (isLocalStorageAvailable) {
9760
9765
  try {
9761
9766
  const key = LOCAL_STORAGE_PREFIX + path;
@@ -9766,17 +9771,22 @@
9766
9771
  }
9767
9772
  }
9768
9773
  }
9769
- function getEntityFromCache(path, useLocalStorage = true) {
9770
- if (entityCache.has(path)) {
9771
- return entityCache.get(path);
9772
- }
9773
- if (isLocalStorageAvailable && useLocalStorage) {
9774
+ function removeEntityFromMemoryCache(path) {
9775
+ entityCache.delete(path);
9776
+ }
9777
+ function saveEntityToMemoryCache(path, data) {
9778
+ entityCache.set(path, data);
9779
+ }
9780
+ function getEntityFromMemoryCache(path) {
9781
+ return entityCache.get(path);
9782
+ }
9783
+ function getEntityFromCache(path) {
9784
+ if (isLocalStorageAvailable) {
9774
9785
  try {
9775
9786
  const key = LOCAL_STORAGE_PREFIX + path;
9776
9787
  const entityString = localStorage.getItem(key);
9777
9788
  if (entityString) {
9778
9789
  const entity = JSON.parse(entityString, customReviver);
9779
- entityCache.set(path, entity);
9780
9790
  return entity;
9781
9791
  }
9782
9792
  } catch (error) {
@@ -9785,12 +9795,7 @@
9785
9795
  }
9786
9796
  return void 0;
9787
9797
  }
9788
- function hasEntityInCache(path) {
9789
- return entityCache.has(path);
9790
- }
9791
9798
  function removeEntityFromCache(path) {
9792
- console.debug("Removing entity from cache", path);
9793
- entityCache.delete(path);
9794
9799
  if (isLocalStorageAvailable) {
9795
9800
  try {
9796
9801
  const key = LOCAL_STORAGE_PREFIX + path;
@@ -9827,8 +9832,8 @@
9827
9832
  const hasCollapsedActions = actions.some((a) => a.collapsed || a.collapsed === void 0);
9828
9833
  const collapsedActions = actions.filter((a_0) => a_0.collapsed || a_0.collapsed === void 0);
9829
9834
  const uncollapsedActions = actions.filter((a_1) => a_1.collapsed === false);
9830
- const enableLocalChangesBackup = collection?.enableLocalChangesBackup !== void 0 ? collection?.enableLocalChangesBackup : true;
9831
- const hasDraft = enableLocalChangesBackup ? hasEntityInCache(fullPath + "/" + entity.id) : false;
9835
+ const enableLocalChangesBackup = collection ? getLocalChangesBackup(collection) : false;
9836
+ const hasDraft = enableLocalChangesBackup ? getEntityFromCache(fullPath + "/" + entity.id) : false;
9832
9837
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls("h-full flex items-center justify-center flex-col bg-surface-50 dark:bg-surface-900 bg-opacity-90 dark:bg-opacity-90 z-10", frozen ? "sticky left-0" : ""), onClick: React.useCallback((event) => {
9833
9838
  event.stopPropagation();
9834
9839
  }, []), style: {
@@ -15163,6 +15168,273 @@
15163
15168
  savingError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { color: "error", children: savingError.message }) })
15164
15169
  ] });
15165
15170
  }
15171
+ function LocalChangesMenu(t0) {
15172
+ const $ = reactCompilerRuntime.c(43);
15173
+ const {
15174
+ localChangesData,
15175
+ formex: formex$1,
15176
+ onClearLocalChanges,
15177
+ cacheKey,
15178
+ properties
15179
+ } = t0;
15180
+ const snackbarController = useSnackbarController();
15181
+ const [previewDialogOpen, setPreviewDialogOpen] = React.useState(false);
15182
+ const [open, setOpen] = React.useState(false);
15183
+ let t1;
15184
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
15185
+ t1 = () => {
15186
+ setOpen(true);
15187
+ };
15188
+ $[0] = t1;
15189
+ } else {
15190
+ t1 = $[0];
15191
+ }
15192
+ const handleOpenMenu = t1;
15193
+ let t2;
15194
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
15195
+ t2 = () => {
15196
+ setOpen(false);
15197
+ };
15198
+ $[1] = t2;
15199
+ } else {
15200
+ t2 = $[1];
15201
+ }
15202
+ const handleCloseMenu = t2;
15203
+ let t3;
15204
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
15205
+ t3 = () => {
15206
+ setPreviewDialogOpen(true);
15207
+ handleCloseMenu();
15208
+ };
15209
+ $[2] = t3;
15210
+ } else {
15211
+ t3 = $[2];
15212
+ }
15213
+ const handlePreview = t3;
15214
+ let t4;
15215
+ if ($[3] !== formex$1 || $[4] !== localChangesData || $[5] !== onClearLocalChanges || $[6] !== snackbarController) {
15216
+ t4 = () => {
15217
+ const mergedValues = mergeDeep(formex$1.values, localChangesData);
15218
+ const touched = {
15219
+ ...formex$1.touched
15220
+ };
15221
+ const newTouched = formex.flattenKeys(localChangesData);
15222
+ newTouched.forEach((key) => {
15223
+ touched[key] = true;
15224
+ });
15225
+ formex$1.setTouched(touched);
15226
+ formex$1.setValues(mergedValues);
15227
+ snackbarController.open({
15228
+ type: "info",
15229
+ message: "Local changes applied to the form"
15230
+ });
15231
+ handleCloseMenu();
15232
+ onClearLocalChanges?.();
15233
+ };
15234
+ $[3] = formex$1;
15235
+ $[4] = localChangesData;
15236
+ $[5] = onClearLocalChanges;
15237
+ $[6] = snackbarController;
15238
+ $[7] = t4;
15239
+ } else {
15240
+ t4 = $[7];
15241
+ }
15242
+ const handleApply = t4;
15243
+ let t5;
15244
+ if ($[8] !== cacheKey || $[9] !== onClearLocalChanges || $[10] !== snackbarController) {
15245
+ t5 = () => {
15246
+ removeEntityFromCache(cacheKey);
15247
+ snackbarController.open({
15248
+ type: "info",
15249
+ message: "Local changes discarded"
15250
+ });
15251
+ handleCloseMenu();
15252
+ onClearLocalChanges?.();
15253
+ };
15254
+ $[8] = cacheKey;
15255
+ $[9] = onClearLocalChanges;
15256
+ $[10] = snackbarController;
15257
+ $[11] = t5;
15258
+ } else {
15259
+ t5 = $[11];
15260
+ }
15261
+ const handleDiscard = t5;
15262
+ let t6;
15263
+ if ($[12] === Symbol.for("react.memo_cache_sentinel")) {
15264
+ t6 = /* @__PURE__ */ jsxRuntime.jsx(ui.WarningIcon, { size: "smallest", className: "mr-1 text-yellow-600 dark:text-yellow-400" });
15265
+ $[12] = t6;
15266
+ } else {
15267
+ t6 = $[12];
15268
+ }
15269
+ let t7;
15270
+ if ($[13] === Symbol.for("react.memo_cache_sentinel")) {
15271
+ t7 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { size: "small", className: "font-semibold text-xs rounded-full px-4 py-1 bg-yellow-200 dark:bg-yellow-900 hover:bg-yellow-300 dark:hover:bg-yellow-800 text-yellow-800 dark:text-yellow-200", onClick: handleOpenMenu, children: [
15272
+ t6,
15273
+ "Unsaved Local changes",
15274
+ /* @__PURE__ */ jsxRuntime.jsx(ui.KeyboardArrowDownIcon, { size: "smallest" })
15275
+ ] });
15276
+ $[13] = t7;
15277
+ } else {
15278
+ t7 = $[13];
15279
+ }
15280
+ let t8;
15281
+ if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
15282
+ t8 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-xs px-4 py-4 text-sm text-gray-700 dark:text-gray-300", children: "This document was edited locally and has unsaved changes." });
15283
+ $[14] = t8;
15284
+ } else {
15285
+ t8 = $[14];
15286
+ }
15287
+ let t9;
15288
+ if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
15289
+ t9 = /* @__PURE__ */ jsxRuntime.jsxs(ui.MenuItem, { dense: true, onClick: handlePreview, children: [
15290
+ /* @__PURE__ */ jsxRuntime.jsx(ui.VisibilityIcon, { size: "small" }),
15291
+ "Preview Changes"
15292
+ ] });
15293
+ $[15] = t9;
15294
+ } else {
15295
+ t9 = $[15];
15296
+ }
15297
+ let t10;
15298
+ if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
15299
+ t10 = /* @__PURE__ */ jsxRuntime.jsx(ui.CheckIcon, { size: "small" });
15300
+ $[16] = t10;
15301
+ } else {
15302
+ t10 = $[16];
15303
+ }
15304
+ let t11;
15305
+ if ($[17] !== handleApply) {
15306
+ t11 = /* @__PURE__ */ jsxRuntime.jsxs(ui.MenuItem, { dense: true, onClick: handleApply, children: [
15307
+ t10,
15308
+ "Apply Changes"
15309
+ ] });
15310
+ $[17] = handleApply;
15311
+ $[18] = t11;
15312
+ } else {
15313
+ t11 = $[18];
15314
+ }
15315
+ let t12;
15316
+ if ($[19] === Symbol.for("react.memo_cache_sentinel")) {
15317
+ t12 = /* @__PURE__ */ jsxRuntime.jsx(ui.CancelIcon, { size: "small" });
15318
+ $[19] = t12;
15319
+ } else {
15320
+ t12 = $[19];
15321
+ }
15322
+ let t13;
15323
+ if ($[20] !== handleDiscard) {
15324
+ t13 = /* @__PURE__ */ jsxRuntime.jsxs(ui.MenuItem, { dense: true, onClick: handleDiscard, children: [
15325
+ t12,
15326
+ "Discard Local Changes"
15327
+ ] });
15328
+ $[20] = handleDiscard;
15329
+ $[21] = t13;
15330
+ } else {
15331
+ t13 = $[21];
15332
+ }
15333
+ let t14;
15334
+ if ($[22] !== open || $[23] !== t11 || $[24] !== t13) {
15335
+ t14 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Menu, { trigger: t7, open, onOpenChange: setOpen, children: [
15336
+ t8,
15337
+ t9,
15338
+ t11,
15339
+ t13
15340
+ ] });
15341
+ $[22] = open;
15342
+ $[23] = t11;
15343
+ $[24] = t13;
15344
+ $[25] = t14;
15345
+ } else {
15346
+ t14 = $[25];
15347
+ }
15348
+ let t15;
15349
+ let t16;
15350
+ if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
15351
+ t15 = /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-2xl mb-4", children: "Preview Local Changes" });
15352
+ t16 = /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-4", children: "These are the local changes that will be applied to the form." });
15353
+ $[26] = t15;
15354
+ $[27] = t16;
15355
+ } else {
15356
+ t15 = $[26];
15357
+ t16 = $[27];
15358
+ }
15359
+ let t17;
15360
+ if ($[28] !== localChangesData || $[29] !== properties) {
15361
+ t17 = formex.flattenKeys(localChangesData).map((key_0) => {
15362
+ const value = formex.getIn(localChangesData, key_0);
15363
+ const property = getPropertyInPath(properties, key_0);
15364
+ if (!property) {
15365
+ return null;
15366
+ }
15367
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-12 gap-x-4 px-4 py-3 items-center", children: [
15368
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-3 text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "text-gray-500 dark:text-gray-400 break-words", children: property.name || key_0 }) }),
15369
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-9", children: /* @__PURE__ */ jsxRuntime.jsx(PropertyPreview, { propertyKey: key_0, value, property, size: "small" }) })
15370
+ ] }, key_0);
15371
+ });
15372
+ $[28] = localChangesData;
15373
+ $[29] = properties;
15374
+ $[30] = t17;
15375
+ } else {
15376
+ t17 = $[30];
15377
+ }
15378
+ let t18;
15379
+ if ($[31] !== t17) {
15380
+ t18 = /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogContent, { children: [
15381
+ t15,
15382
+ t16,
15383
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `border rounded-lg divide-y divide-surface-200 divide-surface-opacity-40 dark:divide-surface-700 dark:divide-opacity-40 ${ui.defaultBorderMixin}`, children: t17 })
15384
+ ] });
15385
+ $[31] = t17;
15386
+ $[32] = t18;
15387
+ } else {
15388
+ t18 = $[32];
15389
+ }
15390
+ let t19;
15391
+ if ($[33] === Symbol.for("react.memo_cache_sentinel")) {
15392
+ t19 = /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { onClick: () => setPreviewDialogOpen(false), children: "Close" });
15393
+ $[33] = t19;
15394
+ } else {
15395
+ t19 = $[33];
15396
+ }
15397
+ let t20;
15398
+ if ($[34] !== handleApply) {
15399
+ t20 = /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogActions, { children: [
15400
+ t19,
15401
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "filled", onClick: () => {
15402
+ handleApply();
15403
+ setPreviewDialogOpen(false);
15404
+ }, children: "Apply changes" })
15405
+ ] });
15406
+ $[34] = handleApply;
15407
+ $[35] = t20;
15408
+ } else {
15409
+ t20 = $[35];
15410
+ }
15411
+ let t21;
15412
+ if ($[36] !== previewDialogOpen || $[37] !== t18 || $[38] !== t20) {
15413
+ t21 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Dialog, { open: previewDialogOpen, onOpenChange: setPreviewDialogOpen, maxWidth: "4xl", children: [
15414
+ t18,
15415
+ t20
15416
+ ] });
15417
+ $[36] = previewDialogOpen;
15418
+ $[37] = t18;
15419
+ $[38] = t20;
15420
+ $[39] = t21;
15421
+ } else {
15422
+ t21 = $[39];
15423
+ }
15424
+ let t22;
15425
+ if ($[40] !== t14 || $[41] !== t21) {
15426
+ t22 = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15427
+ t14,
15428
+ t21
15429
+ ] });
15430
+ $[40] = t14;
15431
+ $[41] = t21;
15432
+ $[42] = t22;
15433
+ } else {
15434
+ t22 = $[42];
15435
+ }
15436
+ return t22;
15437
+ }
15166
15438
  function extractTouchedValues(values, touched) {
15167
15439
  let acc = {};
15168
15440
  if (!touched || typeof touched !== "object") {
@@ -15250,6 +15522,12 @@
15250
15522
  const [entityIdError, setEntityIdError] = React.useState(false);
15251
15523
  const [savingError, setSavingError] = React.useState();
15252
15524
  const autoSave = collection.formAutoSave && !collection.customId;
15525
+ const baseInitialValues = React.useMemo(() => getInitialEntityValues(authController, collection, path, status, entity, customizationController.propertyConfigs), [authController, collection, path, status, entity, customizationController.propertyConfigs]);
15526
+ const localChangesDataRaw = React.useMemo(() => entityId ? getEntityFromCache(path + "/" + entityId) : getEntityFromCache(path + "#new"), [entityId, path]);
15527
+ const [localChangesCleared, setLocalChangesCleared] = React.useState(false);
15528
+ const localChangesBackup = getLocalChangesBackup(collection);
15529
+ const autoApplyLocalChanges = localChangesBackup === "auto_apply";
15530
+ const manualApplyLocalChanges = localChangesBackup === "manual_apply";
15253
15531
  const onSubmit = (values, formexController) => {
15254
15532
  if (mustSetCustomId && !entityId) {
15255
15533
  console.error("Missing custom Id");
@@ -15280,12 +15558,31 @@
15280
15558
  formexController.setSubmitting(false);
15281
15559
  });
15282
15560
  };
15283
- const baseInitialValues = getInitialEntityValues(authController, collection, path, status, entity, customizationController.propertyConfigs);
15284
- const initialValues = initialDirtyValues ? mergeDeep(baseInitialValues, initialDirtyValues) : baseInitialValues;
15285
- const initialDirty = Boolean(initialDirtyValues) && initialDirtyValues && Object.keys(initialDirtyValues).length > 0;
15561
+ const [initialValues_0, initialDirty_0] = React.useMemo(() => {
15562
+ const initialValuesWithLocalChanges = autoApplyLocalChanges && localChangesDataRaw ? mergeDeep(baseInitialValues, localChangesDataRaw) : baseInitialValues;
15563
+ const initialValues = initialDirtyValues ? mergeDeep(initialValuesWithLocalChanges, initialDirtyValues) : initialValuesWithLocalChanges;
15564
+ const initialDirty = Boolean(initialDirtyValues) && initialDirtyValues && Object.keys(initialDirtyValues).length > 0;
15565
+ return [initialValues, initialDirty];
15566
+ }, [autoApplyLocalChanges, localChangesDataRaw, baseInitialValues, initialDirtyValues]);
15567
+ const localChangesData = React.useMemo(() => {
15568
+ if (!localChangesDataRaw) {
15569
+ return void 0;
15570
+ }
15571
+ let filteredChanges = {};
15572
+ const flattenedKeys = formex.flattenKeys(localChangesDataRaw);
15573
+ flattenedKeys.forEach((key) => {
15574
+ const localValue = formex.getIn(localChangesDataRaw, key);
15575
+ const initialValue = formex.getIn(initialValues_0, key);
15576
+ if (!equal(localValue, initialValue)) {
15577
+ filteredChanges = formex.setIn(filteredChanges, key, localValue);
15578
+ }
15579
+ });
15580
+ return filteredChanges;
15581
+ }, [localChangesDataRaw, initialValues_0]);
15582
+ const hasLocalChanges = !localChangesCleared && localChangesData && Object.keys(localChangesData).length > 0;
15286
15583
  const formex$1 = formexProp ?? formex.useCreateFormex({
15287
- initialValues,
15288
- initialDirty,
15584
+ initialValues: initialValues_0,
15585
+ initialDirty: initialDirty_0,
15289
15586
  initialTouched: initialDirtyValues ? formex.flattenKeys(initialDirtyValues).reduce((previousValue, currentValue) => ({
15290
15587
  ...previousValue,
15291
15588
  [currentValue]: true
@@ -15293,13 +15590,13 @@
15293
15590
  onSubmit,
15294
15591
  onReset: () => {
15295
15592
  clearDirtyCache();
15296
- onValuesModified?.(false);
15593
+ onValuesModified?.(false, initialValues_0);
15297
15594
  },
15298
15595
  onValuesChangeDeferred: (values_0, controller) => {
15299
- const key = status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId;
15596
+ const key_0 = status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId;
15300
15597
  if (controller.dirty) {
15301
15598
  const touchedValues = extractTouchedValues(values_0, controller.touched);
15302
- saveEntityToCache(key, touchedValues);
15599
+ saveEntityToCache(key_0, touchedValues);
15303
15600
  }
15304
15601
  },
15305
15602
  validation: (values_1) => {
@@ -15352,14 +15649,16 @@
15352
15649
  }, [snackbarController]);
15353
15650
  function clearDirtyCache() {
15354
15651
  if (status === "new" || status === "copy") {
15652
+ removeEntityFromMemoryCache(path + "#new");
15355
15653
  removeEntityFromCache(path + "#new");
15356
15654
  } else {
15655
+ removeEntityFromMemoryCache(path + "/" + entityId);
15357
15656
  removeEntityFromCache(path + "/" + entityId);
15358
15657
  }
15359
15658
  }
15360
15659
  const onSaveSuccess = (updatedEntity) => {
15361
15660
  clearDirtyCache();
15362
- onValuesModified?.(false);
15661
+ onValuesModified?.(false, updatedEntity.values);
15363
15662
  if (!autoSave) snackbarController.open({
15364
15663
  type: "success",
15365
15664
  message: `${collection.singularName ?? collection.name}: Saved correctly`
@@ -15519,7 +15818,7 @@
15519
15818
  }, [doOnIdUpdate]);
15520
15819
  React.useEffect(() => {
15521
15820
  if (!autoSave) {
15522
- onValuesModified?.(modified);
15821
+ onValuesModified?.(modified, formex$1.values);
15523
15822
  }
15524
15823
  }, [formex$1.dirty]);
15525
15824
  const modified = formex$1.dirty;
@@ -15531,11 +15830,11 @@
15531
15830
  useOnAutoSave(autoSave, formex$1, lastSavedValues, save);
15532
15831
  React.useEffect(() => {
15533
15832
  if (!autoSave && !formex$1.isSubmitting && underlyingChanges && entity) {
15534
- Object.entries(underlyingChanges).forEach(([key_0, value_0]) => {
15535
- const formValue = formex$1.values[key_0];
15536
- if (!equal(value_0, formValue) && !formex$1.touched[key_0]) {
15537
- console.debug("Updated value from the datasource:", key_0, value_0);
15538
- formex$1.setFieldValue(key_0, value_0 !== void 0 ? value_0 : null);
15833
+ Object.entries(underlyingChanges).forEach(([key_1, value_0]) => {
15834
+ const formValue = formex$1.values[key_1];
15835
+ if (!equal(value_0, formValue) && !formex$1.touched[key_1]) {
15836
+ console.debug("Updated value from the datasource:", key_1, value_0);
15837
+ formex$1.setFieldValue(key_1, value_0 !== void 0 ? value_0 : null);
15539
15838
  }
15540
15839
  });
15541
15840
  }
@@ -15545,16 +15844,16 @@
15545
15844
  if (Builder) {
15546
15845
  return /* @__PURE__ */ jsxRuntime.jsx(Builder, { collection, entity, modifiedValues: formex$1.values, formContext });
15547
15846
  }
15548
- return /* @__PURE__ */ jsxRuntime.jsx(FormLayout, { children: formFieldKeys.map((key_1) => {
15549
- const property = resolvedCollection.properties[key_1];
15847
+ return /* @__PURE__ */ jsxRuntime.jsx(FormLayout, { children: formFieldKeys.map((key_2) => {
15848
+ const property = resolvedCollection.properties[key_2];
15550
15849
  if (property) {
15551
- const underlyingValueHasChanged = !!underlyingChanges && Object.keys(underlyingChanges).includes(key_1) && formex$1.touched[key_1];
15850
+ const underlyingValueHasChanged = !!underlyingChanges && Object.keys(underlyingChanges).includes(key_2) && formex$1.touched[key_2];
15552
15851
  const disabled_0 = disabledProp || !autoSave && formex$1.isSubmitting || isReadOnly(property) || Boolean(property.disabled);
15553
15852
  const hidden = isHidden(property);
15554
15853
  if (hidden) return null;
15555
15854
  const widthPercentage = property.widthPercentage ?? 100;
15556
15855
  const cmsFormFieldProps = {
15557
- propertyKey: key_1,
15856
+ propertyKey: key_2,
15558
15857
  disabled: disabled_0,
15559
15858
  property,
15560
15859
  includeDescription: property.description || property.longDescription,
@@ -15564,9 +15863,9 @@
15564
15863
  minimalistView: false,
15565
15864
  autoFocus: false
15566
15865
  };
15567
- return /* @__PURE__ */ jsxRuntime.jsx(FormEntry, { propertyKey: key_1, widthPercentage, children: /* @__PURE__ */ jsxRuntime.jsx(PropertyFieldBinding, { ...cmsFormFieldProps }) }, `field_${key_1}`);
15866
+ return /* @__PURE__ */ jsxRuntime.jsx(FormEntry, { propertyKey: key_2, widthPercentage, children: /* @__PURE__ */ jsxRuntime.jsx(PropertyFieldBinding, { ...cmsFormFieldProps }) }, `field_${key_2}`);
15568
15867
  }
15569
- const additionalField = resolvedCollection.additionalFields?.find((f) => f.key === key_1);
15868
+ const additionalField = resolvedCollection.additionalFields?.find((f) => f.key === key_2);
15570
15869
  if (additionalField && entity) {
15571
15870
  const Builder_0 = additionalField.Builder;
15572
15871
  if (!Builder_0 && !additionalField.value) {
@@ -15577,11 +15876,11 @@
15577
15876
  context
15578
15877
  })?.toString() });
15579
15878
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full", children: [
15580
- /* @__PURE__ */ jsxRuntime.jsx(LabelWithIconAndTooltip, { propertyKey: key_1, icon: /* @__PURE__ */ jsxRuntime.jsx(ui.NotesIcon, { size: "small" }), title: additionalField.name, className: "text-text-secondary dark:text-text-secondary-dark ml-3.5" }),
15879
+ /* @__PURE__ */ jsxRuntime.jsx(LabelWithIconAndTooltip, { propertyKey: key_2, icon: /* @__PURE__ */ jsxRuntime.jsx(ui.NotesIcon, { size: "small" }), title: additionalField.name, className: "text-text-secondary dark:text-text-secondary-dark ml-3.5" }),
15581
15880
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: ui.cls(ui.paperMixin, "w-full min-h-14 p-4 md:p-6 overflow-x-scroll no-scrollbar"), children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { children: child }) })
15582
- ] }, `additional_${key_1}`);
15881
+ ] }, `additional_${key_2}`);
15583
15882
  }
15584
- console.warn(`Property ${key_1} not found in collection ${resolvedCollection.name} in properties or additional fields. Skipping.`);
15883
+ console.warn(`Property ${key_2} not found in collection ${resolvedCollection.name} in properties or additional fields. Skipping.`);
15585
15884
  return null;
15586
15885
  }).filter(Boolean) });
15587
15886
  };
@@ -15616,7 +15915,10 @@
15616
15915
  values: baseInitialValues
15617
15916
  }), noValidate: true, className: ui.cls("flex-1 flex flex-row w-full overflow-y-auto justify-center", className), children: [
15618
15917
  /* @__PURE__ */ jsxRuntime.jsx("div", { id: `form_${path}`, className: ui.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__ */ jsxRuntime.jsxs("div", { className: ui.cls("flex flex-col w-full pt-12 pb-16 px-4 sm:px-8 md:px-10"), children: [
15619
- formex$1.dirty ? /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "Local unsaved changes", className: "self-end sticky top-4 z-10", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Chip, { size: "small", colorScheme: "orangeDarker", children: /* @__PURE__ */ jsxRuntime.jsx(ui.EditIcon, { size: "smallest" }) }) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "In sync with the database", className: "self-end sticky top-4 z-10", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Chip, { size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(ui.CheckIcon, { size: "smallest" }) }) }),
15918
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-row gap-4 self-end sticky top-4 z-10", children: [
15919
+ manualApplyLocalChanges && hasLocalChanges && /* @__PURE__ */ jsxRuntime.jsx(LocalChangesMenu, { cacheKey: status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId, properties: resolvedCollection.properties, localChangesData, formex: formex$1, onClearLocalChanges: () => setLocalChangesCleared(true) }),
15920
+ formex$1.dirty ? /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "There are local unsaved changes", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Chip, { size: "small", colorScheme: "orangeDarker", children: /* @__PURE__ */ jsxRuntime.jsx(ui.EditIcon, { size: "smallest" }) }) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "The current form is in sync with the database", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Chip, { size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(ui.CheckIcon, { size: "smallest" }) }) })
15921
+ ] }),
15620
15922
  formView
15621
15923
  ] }) }),
15622
15924
  dialogActions
@@ -20426,7 +20728,7 @@
20426
20728
  /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "subtitle2", children: "So empty..." }),
20427
20729
  /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { color: "primary", variant: "outlined", onClick: onNewClick, className: "mt-4", children: [
20428
20730
  /* @__PURE__ */ jsxRuntime.jsx(ui.AddIcon, {}),
20429
- "Create your first entity"
20731
+ "Create your first entry"
20430
20732
  ] })
20431
20733
  ] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "label", children: "No results with the applied filter/sort" }), hoverRow, inlineEditing: checkInlineEditing(), AdditionalHeaderWidget: buildAdditionalHeaderWidget, AddColumnComponent: addColumnComponentInternal, getIdColumnWidth, additionalIDHeaderWidget: /* @__PURE__ */ jsxRuntime.jsx(EntityIdHeaderWidget, { path: fullPath, fullIdPath: fullIdPath ?? fullPath, collection }), openEntityMode }, `collection_table_${fullPath}`),
20432
20734
  popupCell && /* @__PURE__ */ jsxRuntime.jsx(PopupFormField, { open: Boolean(popupCell), onClose: onPopupClose, cellRect: popupCell?.cellRect, propertyKey: popupCell?.propertyKey, collection, entityId: popupCell.entityId, tableKey: tableKey.current, customFieldValidator: uniqueFieldValidator, path: resolvedFullPath, onCellValueChange: onValueChange, container: containerRef.current }, `popup_form_${popupCell?.propertyKey}_${popupCell?.entityId}`),
@@ -23085,6 +23387,7 @@
23085
23387
  function createFormexStub(values) {
23086
23388
  const errorMessage = "You are in a read-only context. You cannot modify the formex controller.";
23087
23389
  return {
23390
+ debugId: "",
23088
23391
  values,
23089
23392
  initialValues: values,
23090
23393
  touched: {},
@@ -23099,6 +23402,9 @@
23099
23402
  setValues: () => {
23100
23403
  throw new Error(errorMessage);
23101
23404
  },
23405
+ setTouched(touched) {
23406
+ throw new Error(errorMessage);
23407
+ },
23102
23408
  setFieldValue: () => {
23103
23409
  throw new Error(errorMessage);
23104
23410
  },
@@ -23158,8 +23464,7 @@
23158
23464
  databaseId: props.databaseId,
23159
23465
  useCache: false
23160
23466
  });
23161
- const enableLocalChangesBackup = props.collection.enableLocalChangesBackup !== void 0 ? props.collection.enableLocalChangesBackup : true;
23162
- const initialDirtyValues = entityId ? getEntityFromCache(props.path + "/" + entityId, enableLocalChangesBackup) : getEntityFromCache(props.path + "#new", enableLocalChangesBackup);
23467
+ const initialDirtyValues = entityId ? getEntityFromMemoryCache(props.path + "/" + entityId) : getEntityFromMemoryCache(props.path + "#new");
23163
23468
  const authController = useAuthController();
23164
23469
  const initialStatus = props.copy ? "copy" : entityId ? "existing" : "new";
23165
23470
  const [status, setStatus] = React.useState(initialStatus);
@@ -23318,6 +23623,7 @@
23318
23623
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-16" })
23319
23624
  ] }) }) : null;
23320
23625
  const entityView = /* @__PURE__ */ jsxRuntime.jsx(EntityForm, { fullIdPath, collection, path, entityId: entityId ?? usedEntity?.id, onValuesModified, entity, initialDirtyValues, openEntityMode: layout, forceActionsAtTheBottom: actionsAtTheBottom, initialStatus: status, className: ui.cls((!mainViewVisible || !canEdit) && !selectedSecondaryForm ? "hidden" : "", formProps?.className), EntityFormActionsComponent: EntityEditViewFormActions, disabled: !canEdit, ...formProps, onEntityChange: (entity_0) => {
23626
+ console.log("333 EntityEditView onEntityChange:", entity_0);
23321
23627
  setUsedEntity(entity_0);
23322
23628
  formProps?.onEntityChange?.(entity_0);
23323
23629
  }, onStatusChange: (status_0) => {
@@ -23340,7 +23646,12 @@
23340
23646
  const shouldShowTopBar = Boolean(barActions) || hasAdditionalViews;
23341
23647
  let result = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-col h-full w-full bg-white dark:bg-surface-900", children: [
23342
23648
  shouldShowTopBar && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls("h-14 items-center flex overflow-visible overflow-x-scroll w-full no-scrollbar h-14 border-b pl-2 pr-2 pt-1 flex bg-surface-50 dark:bg-surface-900", ui.defaultBorderMixin), children: [
23343
- barActions,
23649
+ barActions?.({
23650
+ path: fullIdPath ?? path,
23651
+ entityId,
23652
+ values: formContext?.values ?? usedEntity?.values ?? {},
23653
+ status
23654
+ }),
23344
23655
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-grow" }),
23345
23656
  pluginActionsTop,
23346
23657
  globalLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "self-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.CircularProgress, { size: "small" }) }),
@@ -23443,9 +23754,14 @@
23443
23754
  if (!props || !collection) {
23444
23755
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full" });
23445
23756
  }
23446
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { children: /* @__PURE__ */ jsxRuntime.jsx(EntityEditView, { ...props, fullIdPath, layout: "side_panel", collection, parentCollectionIds, onValuesModified, onSaved: onUpdate, barActions: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
23757
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { children: /* @__PURE__ */ jsxRuntime.jsx(EntityEditView, { ...props, fullIdPath, layout: "side_panel", collection, parentCollectionIds, onValuesModified, onSaved: onUpdate, barActions: ({
23758
+ status,
23759
+ values
23760
+ }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
23447
23761
  /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { className: "self-center", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(ui.CloseIcon, { size: "small" }) }),
23448
23762
  allowFullScreen && /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { className: "self-center", onClick: () => {
23763
+ const key = status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId;
23764
+ saveEntityToMemoryCache(key, values);
23449
23765
  if (entityId) navigate(location.pathname);
23450
23766
  else navigate(location.pathname + "#new");
23451
23767
  }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.OpenInFullIcon, { size: "small" }) })
@@ -26225,6 +26541,7 @@
26225
26541
  exports2.getIdIcon = getIdIcon;
26226
26542
  exports2.getLabelOrConfigFrom = getLabelOrConfigFrom;
26227
26543
  exports2.getLastSegment = getLastSegment;
26544
+ exports2.getLocalChangesBackup = getLocalChangesBackup;
26228
26545
  exports2.getPropertiesWithPropertiesOrder = getPropertiesWithPropertiesOrder;
26229
26546
  exports2.getPropertyInPath = getPropertyInPath;
26230
26547
  exports2.getRandomId = getRandomId;