@firecms/entity_history 3.0.0-canary.239 → 3.0.0-canary.241
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/README.md +2 -2
- package/dist/index.es.js +92 -81
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +92 -81
- package/dist/index.umd.js.map +1 -1
- package/package.json +5 -5
- package/src/components/EntityHistoryEntry.tsx +13 -10
- package/src/components/EntityHistoryView.tsx +35 -23
- package/src/useEntityHistoryPlugin.tsx +1 -2
package/README.md
CHANGED
@@ -27,7 +27,7 @@ To use the plugin, import `useEntityHistoryPlugin` and add it to your `FirebaseC
|
|
27
27
|
|
28
28
|
```tsx
|
29
29
|
import React from "react";
|
30
|
-
import {
|
30
|
+
import { FireCMS } from "@firecms/core";
|
31
31
|
import { useEntityHistoryPlugin } from "@firecms/entity_history";
|
32
32
|
|
33
33
|
|
@@ -36,7 +36,7 @@ export default function App() {
|
|
36
36
|
// Basic setup with default options
|
37
37
|
const entityHistoryPlugin = useEntityHistoryPlugin();
|
38
38
|
|
39
|
-
return <
|
39
|
+
return <FireCMS
|
40
40
|
name={"My Online Shop"}
|
41
41
|
plugins={[entityHistoryPlugin]}
|
42
42
|
authentication={myAuthenticator}
|
package/dist/index.es.js
CHANGED
@@ -143,18 +143,18 @@ function EntityHistoryEntry({
|
|
143
143
|
}, children: /* @__PURE__ */ jsx(KeyboardTabIcon, {}) }) }),
|
144
144
|
/* @__PURE__ */ jsx("div", { className: "flex flex-col grow w-full m-1 shrink min-w-0", children: previewKeys && previewKeys.map((key) => {
|
145
145
|
const childProperty = getPropertyInPath(resolvedCollection.properties, key);
|
146
|
-
if (!childProperty) return null;
|
147
146
|
const valueInPath = getValueInPath(entity.values, key);
|
147
|
+
const element = childProperty ? entity ? /* @__PURE__ */ jsx(PropertyPreview, { propertyKey: key, value: valueInPath, property: childProperty, size: "small" }) : /* @__PURE__ */ jsx(SkeletonPropertyComponent, { property: childProperty, size: "small" }) : /* @__PURE__ */ jsx(Typography, { variant: "body2", children: typeof valueInPath === "string" ? valueInPath : JSON.stringify(valueInPath) });
|
148
148
|
return /* @__PURE__ */ jsxs("div", { className: "flex w-full my-1 items-center", children: [
|
149
149
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", className: "min-w-[140px] md:min-w-[200px] w-1/5 pr-8 overflow-hidden text-ellipsis text-right", children: key }),
|
150
|
-
/* @__PURE__ */ jsx("div", { className: "w-4/5", children:
|
150
|
+
/* @__PURE__ */ jsx("div", { className: "w-4/5", children: element })
|
151
151
|
] }, "ref_prev_" + key);
|
152
152
|
}) })
|
153
153
|
] })
|
154
154
|
] });
|
155
155
|
}
|
156
156
|
function EntityHistoryView(t0) {
|
157
|
-
const $ = c(
|
157
|
+
const $ = c(53);
|
158
158
|
const {
|
159
159
|
entity,
|
160
160
|
collection,
|
@@ -165,7 +165,7 @@ function EntityHistoryView(t0) {
|
|
165
165
|
const dirty = formContext?.formex.dirty;
|
166
166
|
const dataSource = useDataSource();
|
167
167
|
const pathAndId = entity ? entity?.path + "/" + entity?.id : void 0;
|
168
|
-
const [
|
168
|
+
const [revertVersionDialog, setRevertVersionDialog] = useState(void 0);
|
169
169
|
let t1;
|
170
170
|
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
171
171
|
t1 = [];
|
@@ -283,28 +283,39 @@ function EntityHistoryView(t0) {
|
|
283
283
|
return t62;
|
284
284
|
}
|
285
285
|
let t6;
|
286
|
-
if ($[14] !== authController
|
287
|
-
t6 = function doRevert2(
|
286
|
+
if ($[14] !== authController || $[15] !== collection || $[16] !== dataSource || $[17] !== entity || $[18] !== formContext || $[19] !== snackbarController) {
|
287
|
+
t6 = function doRevert2(revertVersion) {
|
288
|
+
if (!entity) {
|
289
|
+
throw new Error("No entity to revert");
|
290
|
+
}
|
288
291
|
const revertValues = {
|
289
|
-
...
|
292
|
+
...revertVersion.values,
|
290
293
|
__metadata: {
|
291
|
-
...
|
294
|
+
...revertVersion.values?.__metadata,
|
292
295
|
reverted: true,
|
293
296
|
updated_on: /* @__PURE__ */ new Date(),
|
294
297
|
updated_by: authController.user?.uid ?? null
|
295
298
|
}
|
296
299
|
};
|
297
|
-
|
298
|
-
path:
|
299
|
-
entityId:
|
300
|
+
const saveReverted = dataSource.saveEntity({
|
301
|
+
path: entity.path,
|
302
|
+
entityId: entity.id,
|
303
|
+
values: revertValues,
|
304
|
+
collection,
|
305
|
+
status: "existing"
|
306
|
+
});
|
307
|
+
const saveRevertedHistory = dataSource.saveEntity({
|
308
|
+
path: revertVersion.path,
|
309
|
+
entityId: revertVersion.id,
|
300
310
|
values: revertValues,
|
301
311
|
collection,
|
302
312
|
status: "existing"
|
303
|
-
})
|
313
|
+
});
|
314
|
+
return Promise.all([saveReverted, saveRevertedHistory]).then(() => {
|
304
315
|
formContext.formex.resetForm({
|
305
|
-
values:
|
316
|
+
values: revertVersion.values
|
306
317
|
});
|
307
|
-
|
318
|
+
setRevertVersionDialog(void 0);
|
308
319
|
snackbarController.open({
|
309
320
|
message: "Reverted version",
|
310
321
|
type: "info"
|
@@ -317,45 +328,46 @@ function EntityHistoryView(t0) {
|
|
317
328
|
});
|
318
329
|
});
|
319
330
|
};
|
320
|
-
$[14] = authController
|
331
|
+
$[14] = authController;
|
321
332
|
$[15] = collection;
|
322
333
|
$[16] = dataSource;
|
323
|
-
$[17] =
|
324
|
-
$[18] =
|
325
|
-
$[19] =
|
334
|
+
$[17] = entity;
|
335
|
+
$[18] = formContext;
|
336
|
+
$[19] = snackbarController;
|
337
|
+
$[20] = t6;
|
326
338
|
} else {
|
327
|
-
t6 = $[
|
339
|
+
t6 = $[20];
|
328
340
|
}
|
329
341
|
const doRevert = t6;
|
330
342
|
let t7;
|
331
|
-
if ($[
|
343
|
+
if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
|
332
344
|
t7 = cls("relative flex-1 h-full overflow-auto w-full flex flex-col gap-4 p-8");
|
333
|
-
$[
|
345
|
+
$[21] = t7;
|
334
346
|
} else {
|
335
|
-
t7 = $[
|
347
|
+
t7 = $[21];
|
336
348
|
}
|
337
349
|
let t8;
|
338
|
-
if ($[
|
350
|
+
if ($[22] === Symbol.for("react.memo_cache_sentinel")) {
|
339
351
|
t8 = /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "mt-24 ml-4", children: "History" });
|
340
|
-
$[
|
352
|
+
$[22] = t8;
|
341
353
|
} else {
|
342
|
-
t8 = $[
|
354
|
+
t8 = $[22];
|
343
355
|
}
|
344
356
|
let t9;
|
345
|
-
if ($[
|
357
|
+
if ($[23] !== revisions.length) {
|
346
358
|
t9 = revisions.length === 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
347
359
|
/* @__PURE__ */ jsx(Label, { className: "ml-4 mt-8", children: "No history available" }),
|
348
360
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "ml-4", children: "When you save an entity, a new version is created and stored in the history." })
|
349
361
|
] });
|
350
|
-
$[
|
351
|
-
$[
|
362
|
+
$[23] = revisions.length;
|
363
|
+
$[24] = t9;
|
352
364
|
} else {
|
353
|
-
t9 = $[
|
365
|
+
t9 = $[24];
|
354
366
|
}
|
355
367
|
let t10;
|
356
|
-
if ($[
|
368
|
+
if ($[25] !== collection || $[26] !== dirty || $[27] !== revisions || $[28] !== snackbarController) {
|
357
369
|
let t112;
|
358
|
-
if ($[
|
370
|
+
if ($[30] !== collection || $[31] !== dirty || $[32] !== snackbarController) {
|
359
371
|
t112 = (revision, index) => {
|
360
372
|
const previewKeys = revision.values?.__metadata?.changed_fields;
|
361
373
|
return /* @__PURE__ */ jsx("div", { className: "flex flex-cols gap-2 w-full", children: /* @__PURE__ */ jsx(EntityHistoryEntry, { size: "large", entity: revision, collection, previewKeys, actions: /* @__PURE__ */ jsx(Tooltip, { title: "Revert to this version", className: "m-2 grow-0 self-start", children: /* @__PURE__ */ jsx(IconButton, { onClick: () => {
|
@@ -365,102 +377,102 @@ function EntityHistoryView(t0) {
|
|
365
377
|
type: "warning"
|
366
378
|
});
|
367
379
|
} else {
|
368
|
-
|
380
|
+
setRevertVersionDialog(revision);
|
369
381
|
}
|
370
382
|
}, children: /* @__PURE__ */ jsx(HistoryIcon, {}) }) }) }) }, index);
|
371
383
|
};
|
372
|
-
$[
|
373
|
-
$[
|
374
|
-
$[
|
375
|
-
$[
|
384
|
+
$[30] = collection;
|
385
|
+
$[31] = dirty;
|
386
|
+
$[32] = snackbarController;
|
387
|
+
$[33] = t112;
|
376
388
|
} else {
|
377
|
-
t112 = $[
|
389
|
+
t112 = $[33];
|
378
390
|
}
|
379
391
|
t10 = revisions.map(t112);
|
380
|
-
$[
|
381
|
-
$[
|
382
|
-
$[
|
383
|
-
$[
|
384
|
-
$[
|
392
|
+
$[25] = collection;
|
393
|
+
$[26] = dirty;
|
394
|
+
$[27] = revisions;
|
395
|
+
$[28] = snackbarController;
|
396
|
+
$[29] = t10;
|
385
397
|
} else {
|
386
|
-
t10 = $[
|
398
|
+
t10 = $[29];
|
387
399
|
}
|
388
400
|
let t11;
|
389
|
-
if ($[
|
401
|
+
if ($[34] !== hasMore || $[35] !== isLoading || $[36] !== revisions.length) {
|
390
402
|
t11 = revisions.length > 0 && /* @__PURE__ */ jsxs("div", { ref: loadMoreRef, className: "py-4 text-center", children: [
|
391
403
|
isLoading && /* @__PURE__ */ jsx(Label, { children: "Loading more..." }),
|
392
404
|
!hasMore && revisions.length > 5 && /* @__PURE__ */ jsx(Label, { children: "No more history available" })
|
393
405
|
] });
|
394
|
-
$[
|
395
|
-
$[
|
396
|
-
$[
|
397
|
-
$[
|
406
|
+
$[34] = hasMore;
|
407
|
+
$[35] = isLoading;
|
408
|
+
$[36] = revisions.length;
|
409
|
+
$[37] = t11;
|
398
410
|
} else {
|
399
|
-
t11 = $[
|
411
|
+
t11 = $[37];
|
400
412
|
}
|
401
413
|
let t12;
|
402
|
-
if ($[
|
414
|
+
if ($[38] !== t10 || $[39] !== t11 || $[40] !== t9) {
|
403
415
|
t12 = /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 max-w-6xl mx-auto w-full", children: [
|
404
416
|
t8,
|
405
417
|
t9,
|
406
418
|
t10,
|
407
419
|
t11
|
408
420
|
] });
|
409
|
-
$[
|
410
|
-
$[
|
411
|
-
$[
|
412
|
-
$[
|
421
|
+
$[38] = t10;
|
422
|
+
$[39] = t11;
|
423
|
+
$[40] = t9;
|
424
|
+
$[41] = t12;
|
413
425
|
} else {
|
414
|
-
t12 = $[
|
426
|
+
t12 = $[41];
|
415
427
|
}
|
416
|
-
const t13 = Boolean(
|
428
|
+
const t13 = Boolean(revertVersionDialog);
|
417
429
|
let t14;
|
418
|
-
if ($[
|
430
|
+
if ($[42] !== doRevert || $[43] !== revertVersionDialog) {
|
419
431
|
t14 = function() {
|
420
|
-
if (!
|
432
|
+
if (!revertVersionDialog) {
|
421
433
|
return;
|
422
434
|
}
|
423
|
-
doRevert(
|
435
|
+
doRevert(revertVersionDialog);
|
424
436
|
};
|
425
|
-
$[
|
426
|
-
$[
|
427
|
-
$[
|
437
|
+
$[42] = doRevert;
|
438
|
+
$[43] = revertVersionDialog;
|
439
|
+
$[44] = t14;
|
428
440
|
} else {
|
429
|
-
t14 = $[
|
441
|
+
t14 = $[44];
|
430
442
|
}
|
431
443
|
let t15;
|
432
444
|
let t16;
|
433
|
-
if ($[
|
445
|
+
if ($[45] === Symbol.for("react.memo_cache_sentinel")) {
|
434
446
|
t15 = function() {
|
435
|
-
|
447
|
+
setRevertVersionDialog(void 0);
|
436
448
|
};
|
437
449
|
t16 = /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: "Revert data to this version?" });
|
438
|
-
$[
|
439
|
-
$[
|
450
|
+
$[45] = t15;
|
451
|
+
$[46] = t16;
|
440
452
|
} else {
|
441
|
-
t15 = $[
|
442
|
-
t16 = $[
|
453
|
+
t15 = $[45];
|
454
|
+
t16 = $[46];
|
443
455
|
}
|
444
456
|
let t17;
|
445
|
-
if ($[
|
457
|
+
if ($[47] !== t13 || $[48] !== t14) {
|
446
458
|
t17 = /* @__PURE__ */ jsx(ConfirmationDialog, { open: t13, onAccept: t14, onCancel: t15, title: t16 });
|
447
|
-
$[
|
448
|
-
$[
|
449
|
-
$[
|
459
|
+
$[47] = t13;
|
460
|
+
$[48] = t14;
|
461
|
+
$[49] = t17;
|
450
462
|
} else {
|
451
|
-
t17 = $[
|
463
|
+
t17 = $[49];
|
452
464
|
}
|
453
465
|
let t18;
|
454
|
-
if ($[
|
466
|
+
if ($[50] !== t12 || $[51] !== t17) {
|
455
467
|
t18 = /* @__PURE__ */ jsxs("div", { ref: containerRef, className: t7, children: [
|
456
468
|
t12,
|
457
469
|
t17
|
458
470
|
] });
|
459
|
-
$[
|
460
|
-
$[
|
461
|
-
$[
|
471
|
+
$[50] = t12;
|
472
|
+
$[51] = t17;
|
473
|
+
$[52] = t18;
|
462
474
|
} else {
|
463
|
-
t18 = $[
|
475
|
+
t18 = $[52];
|
464
476
|
}
|
465
477
|
return t18;
|
466
478
|
}
|
@@ -529,10 +541,9 @@ function useEntityHistoryPlugin(props) {
|
|
529
541
|
defaultEnabled = false
|
530
542
|
} = props ?? {};
|
531
543
|
const modifyCollection = useCallback((collection) => {
|
532
|
-
if (collection.history === true || defaultEnabled) {
|
544
|
+
if (collection.history === true || defaultEnabled && collection.history !== false) {
|
533
545
|
return {
|
534
546
|
...collection,
|
535
|
-
history: true,
|
536
547
|
entityViews: [...collection.entityViews ?? [], {
|
537
548
|
key: "__history",
|
538
549
|
name: "History",
|
package/dist/index.es.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.es.js","sources":["../src/HistoryControllerProvider.tsx","../src/components/UserChip.tsx","../src/components/EntityHistoryEntry.tsx","../src/components/EntityHistoryView.tsx","../src/entity_history_callbacks.ts","../src/useEntityHistoryPlugin.tsx"],"sourcesContent":["import React, { PropsWithChildren, useContext } from \"react\";\nimport equal from \"react-fast-compare\"\n\nimport { User } from \"@firecms/core\";\n\nexport type HistoryConfigController = {\n /**\n * Function to get a user by uid.\n * @param uid\n */\n getUser?: (uid: string) => User | null;\n}\n\nexport const HistoryControllerContext = React.createContext<HistoryConfigController>({} as any);\nexport const useHistoryController = (): HistoryConfigController => useContext(HistoryControllerContext);\n\n\nexport interface HistoryControllerProviderProps {\n\n getUser?: (uid: string) => User | null;\n\n}\n\nexport const HistoryControllerProvider = React.memo(\n function HistoryControllerProvider({\n children,\n getUser,\n }: PropsWithChildren<HistoryControllerProviderProps>) {\n\n return (\n <HistoryControllerContext.Provider\n value={{\n getUser,\n }}>\n\n {children}\n\n </HistoryControllerContext.Provider>\n );\n }, equal);\n","import { User } from \"@firecms/core\";\nimport { Chip, Tooltip } from \"@firecms/ui\";\n\nexport function UserChip({ user }: { user: User }) {\n return (\n <Tooltip title={user.email ?? user.uid}>\n <Chip size={\"small\"} className={\"flex items-center\"}>\n {user.photoURL && <img\n className={\"rounded-full w-6 h-6 mr-2\"}\n src={user.photoURL} alt={user.displayName ?? \"User picture\"}/>}\n <span>{user.displayName ?? user.email ?? user.uid}</span>\n </Chip>\n </Tooltip>\n );\n}\n","import * as React from \"react\";\n\nimport { Chip, cls, defaultBorderMixin, IconButton, KeyboardTabIcon, Tooltip, Typography } from \"@firecms/ui\";\nimport {\n Entity,\n EntityCollection,\n getPropertyInPath,\n getValueInPath,\n PreviewSize,\n PropertyPreview,\n resolveCollection,\n ResolvedProperty,\n SkeletonPropertyComponent,\n useAuthController,\n useCustomizationController,\n useNavigationController,\n useSideEntityController\n} from \"@firecms/core\";\nimport { useHistoryController } from \"../HistoryControllerProvider\";\nimport { UserChip } from \"./UserChip\";\n\nexport type EntityPreviewProps = {\n size: PreviewSize,\n actions?: React.ReactNode,\n collection?: EntityCollection,\n hover?: boolean;\n previewKeys?: string[],\n disabled?: boolean,\n entity: Entity<any>,\n onClick?: (e: React.SyntheticEvent) => void;\n};\n\n/**\n * This view is used to display a preview of an entity.\n * It is used by default in reference fields and whenever a reference is displayed.\n */\nexport function EntityHistoryEntry({\n actions,\n disabled,\n hover,\n collection: collectionProp,\n previewKeys,\n onClick,\n size,\n entity\n }: EntityPreviewProps) {\n\n const authController = useAuthController();\n const customizationController = useCustomizationController();\n\n const navigationController = useNavigationController();\n const sideEntityController = useSideEntityController();\n\n const collection = collectionProp ?? navigationController.getCollection(entity.path);\n const updatedOn = entity.values?.[\"__metadata\"]?.[\"updated_on\"];\n if (!collection) {\n throw Error(`Couldn't find the corresponding collection view for the path: ${entity.path}`);\n }\n\n const updatedBy = entity.values?.[\"__metadata\"]?.[\"updated_by\"];\n const { getUser } = useHistoryController();\n const user = getUser?.(updatedBy);\n\n const resolvedCollection = React.useMemo(() => resolveCollection({\n collection,\n path: entity.path,\n values: entity.values,\n propertyConfigs: customizationController.propertyConfigs,\n authController\n }), [collection]);\n\n return <div className={\"w-full flex flex-col gap-2 mt-4\"}>\n <div className={\"ml-4 flex items-center gap-4\"}>\n <Typography variant={\"body2\"} color={\"secondary\"}>{updatedOn.toLocaleString()}</Typography>\n {!user && updatedBy && <Chip size={\"small\"}>{updatedBy}</Chip>}\n {user && <UserChip user={user}/>}\n </div>\n <div\n className={cls(\n \"bg-white dark:bg-surface-900\",\n \"min-h-[42px]\",\n \"w-full\",\n \"items-center\",\n hover ? \"hover:bg-surface-accent-50 dark:hover:bg-surface-800 group-hover:bg-surface-accent-50 dark:group-hover:bg-surface-800\" : \"\",\n size === \"small\" ? \"p-1\" : \"px-2 py-1\",\n \"flex border rounded-lg\",\n onClick ? \"cursor-pointer\" : \"\",\n defaultBorderMixin\n )}>\n\n\n {actions}\n\n {entity &&\n <Tooltip title={\"See details for this revision\"}\n className={\"my-2 grow-0 shrink-0 self-start\"}>\n <IconButton\n color={\"inherit\"}\n className={\"\"}\n onClick={(e) => {\n\n sideEntityController.open({\n entityId: entity.id,\n path: entity.path,\n allowFullScreen: false,\n collection: {\n ...collection,\n subcollections: undefined,\n entityViews: undefined,\n permissions: {\n create: false,\n delete: false,\n edit: false,\n read: true\n }\n },\n updateUrl: true\n });\n }}>\n <KeyboardTabIcon/>\n </IconButton>\n </Tooltip>}\n\n <div className={\"flex flex-col grow w-full m-1 shrink min-w-0\"}>\n\n {previewKeys && previewKeys.map((key) => {\n const childProperty = getPropertyInPath(resolvedCollection.properties, key);\n if (!childProperty) return null;\n\n const valueInPath = getValueInPath(entity.values, key);\n return (\n <div key={\"ref_prev_\" + key}\n className=\"flex w-full my-1 items-center\">\n <Typography variant={\"caption\"}\n color={\"secondary\"}\n className=\"min-w-[140px] md:min-w-[200px] w-1/5 pr-8 overflow-hidden text-ellipsis text-right\">\n {key}\n </Typography>\n <div className=\"w-4/5\">\n {\n entity\n ? <PropertyPreview\n propertyKey={key as string}\n value={valueInPath}\n property={childProperty as ResolvedProperty}\n size={\"small\"}/>\n : <SkeletonPropertyComponent\n property={childProperty as ResolvedProperty}\n size={\"small\"}/>\n }\n </div>\n </div>\n );\n })}\n\n </div>\n\n </div>\n </div>\n}\n\n","import { useEffect, useRef, useState } from \"react\";\nimport {\n ConfirmationDialog,\n Entity,\n EntityCustomViewParams,\n useAuthController,\n useDataSource,\n useSnackbarController\n} from \"@firecms/core\";\nimport { cls, HistoryIcon, IconButton, Label, Tooltip, Typography } from \"@firecms/ui\";\nimport { EntityHistoryEntry } from \"./EntityHistoryEntry\";\n\nexport function EntityHistoryView({\n entity,\n collection,\n formContext\n }: EntityCustomViewParams) {\n\n const authController = useAuthController();\n const snackbarController = useSnackbarController();\n const dirty = formContext?.formex.dirty;\n\n const dataSource = useDataSource();\n const pathAndId = entity ? entity?.path + \"/\" + entity?.id : undefined;\n\n const [revertVersion, setRevertVersion] = useState<Entity | undefined>(undefined);\n const [revisions, setRevisions] = useState<Entity[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n\n const PAGE_SIZE = 5;\n const [limit, setLimit] = useState(PAGE_SIZE);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const observerRef = useRef<IntersectionObserver | null>(null);\n const loadMoreRef = useRef<HTMLDivElement>(null);\n\n // Load revisions with the current limit\n useEffect(() => {\n if (!pathAndId) return;\n\n setIsLoading(true); // Set loading true when fetching starts\n const listener = dataSource.listenCollection?.({\n path: pathAndId + \"/__history\",\n order: \"desc\",\n orderBy: \"__metadata.updated_on\",\n limit: limit,\n startAfter: undefined,\n onUpdate: (entities) => {\n setRevisions(entities);\n setHasMore(entities.length === limit && entities.length >= PAGE_SIZE); // Ensure we fetched a full page to consider hasMore\n setIsLoading(false);\n },\n onError: (error) => {\n console.error(\"Error fetching history:\", error);\n setIsLoading(false);\n setHasMore(false); // Stop trying if there's an error\n }\n });\n return () => {\n if (typeof listener === \"function\") {\n listener();\n }\n };\n }, [pathAndId, limit, dataSource]);\n\n // Setup intersection observer for infinite scroll\n useEffect(() => {\n const currentContainer = containerRef.current;\n const currentLoadMore = loadMoreRef.current;\n\n // Conditions for active observation\n if (!currentContainer || !currentLoadMore || !hasMore || isLoading) {\n // If we shouldn't be observing, ensure any existing observer is disconnected\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n return;\n }\n\n // Options for the IntersectionObserver\n const options = {\n root: currentContainer,\n rootMargin: \"0px 0px 200px 0px\", // Trigger 200px before the sentinel is at the bottom edge\n threshold: 0.01 // Trigger if even a small part is visible within the rootMargin\n };\n\n // The callback for when the sentinel's intersection state changes\n const handleObserver = (entries: IntersectionObserverEntry[]) => {\n const target = entries[0];\n if (target.isIntersecting && hasMore && !isLoading) {\n // No need to setIsLoading(true) here, it's done in the data fetching useEffect\n setLimit(prev => prev + PAGE_SIZE);\n }\n };\n\n const observer = new IntersectionObserver(handleObserver, options);\n observer.observe(currentLoadMore);\n observerRef.current = observer; // Store the new observer\n\n // Cleanup function for this effect instance\n return () => {\n observer.disconnect(); // Disconnect the observer created in *this* effect run\n if (observerRef.current === observer) {\n observerRef.current = null;\n }\n };\n // Re-run if hasMore, isLoading changes, or if revisions.length changes (which might make loadMoreRef available/unavailable)\n }, [hasMore, isLoading, revisions.length]);\n\n if (!entity) {\n return <div className=\"flex items-center justify-center h-full\">\n <Label>History is only available for existing entities</Label>\n </div>\n }\n\n function doRevert(revertVersion: Entity) {\n const revertValues = {\n ...revertVersion.values,\n __metadata: {\n ...revertVersion.values?.[\"__metadata\"],\n reverted: true,\n updated_on: new Date(),\n updated_by: authController.user?.uid ?? null,\n }\n };\n return dataSource.saveEntity({\n path: revertVersion.path,\n entityId: revertVersion.id,\n values: revertValues,\n collection,\n status: \"existing\"\n }).then(() => {\n formContext.formex.resetForm({\n values: revertVersion.values\n });\n setRevertVersion(undefined);\n snackbarController.open({\n message: \"Reverted version\",\n type: \"info\"\n });\n }\n ).catch((error) => {\n console.error(\"Error reverting entity:\", error);\n snackbarController.open({\n message: \"Error reverting entity\",\n type: \"error\"\n });\n });\n\n }\n\n return <div\n ref={containerRef}\n className={cls(\"relative flex-1 h-full overflow-auto w-full flex flex-col gap-4 p-8\")}>\n <div className=\"flex flex-col gap-2 max-w-6xl mx-auto w-full\">\n\n <Typography variant={\"h5\"} className={\"mt-24 ml-4\"}>\n History\n </Typography>\n\n {revisions.length === 0 && <>\n <Label className={\"ml-4 mt-8\"}>\n No history available\n </Label>\n <Typography variant={\"caption\"} className={\"ml-4\"}>\n When you save an entity, a new version is created and stored in the history.\n </Typography>\n </>}\n\n {revisions.map((revision, index) => {\n const previewKeys = revision.values?.[\"__metadata\"]?.[\"changed_fields\"];\n return <div key={index} className=\"flex flex-cols gap-2 w-full\">\n <EntityHistoryEntry size={\"large\"}\n entity={revision}\n collection={collection}\n previewKeys={previewKeys}\n actions={\n <Tooltip title={\"Revert to this version\"}\n className={\"m-2 grow-0 self-start\"}>\n <IconButton\n onClick={() => {\n if (dirty) {\n snackbarController.open({\n message: \"Please save or discard your changes before reverting\",\n type: \"warning\"\n });\n } else {\n setRevertVersion(revision);\n }\n }}>\n <HistoryIcon/>\n </IconButton>\n </Tooltip>}\n />\n </div>\n })}\n\n {/* Load more sentinel element */}\n {revisions.length > 0 && (\n <div\n ref={loadMoreRef}\n className=\"py-4 text-center\"\n >\n {isLoading && <Label>Loading more...</Label>}\n {!hasMore && revisions.length > PAGE_SIZE && <Label>No more history available</Label>}\n </div>\n )}\n </div>\n\n <ConfirmationDialog open={Boolean(revertVersion)}\n onAccept={function (): void {\n if (!revertVersion) return;\n doRevert(revertVersion);\n }}\n onCancel={function (): void {\n setRevertVersion(undefined);\n }}\n title={<Typography variant={\"subtitle2\"}>Revert data to this version?</Typography>}/>\n </div>\n}\n","import { EntityCallbacks } from \"@firecms/core\";\nimport equal from \"react-fast-compare\"\n\nexport const entityHistoryCallbacks: EntityCallbacks = {\n onSaveSuccess: async (props) => {\n\n const changedFields = props.previousValues ? findChangedFields(props.previousValues, props.values) : null;\n const uid = props.context.authController.user?.uid;\n props.context.dataSource.saveEntity({\n path: props.path + \"/\" + props.entityId + \"/__history\",\n values: {\n ...props.values,\n __metadata: {\n changed_fields: changedFields,\n updated_on: new Date(),\n updated_by: uid,\n }\n },\n status: \"new\"\n }).then(() => {\n console.debug(\"History saved for\", props.path, props.entityId);\n });\n }\n}\n\nfunction findChangedFields<M extends object>(oldValues: M, newValues: M, prefix: string = \"\"): string[] {\n const changedFields: string[] = [];\n\n // Handle null/undefined cases\n if (equal(oldValues, newValues)) return changedFields;\n if (!oldValues || !newValues) return [prefix || \".\"];\n\n // Get all unique keys from both objects\n const allKeys = new Set([\n ...Object.keys(oldValues),\n ...Object.keys(newValues)\n ]);\n\n for (const key of allKeys) {\n const oldValue = oldValues[key as keyof M];\n const newValue = newValues[key as keyof M];\n const currentPath = prefix ? `${prefix}.${key}` : key;\n\n // If key exists only in one object\n if ((key in oldValues) !== (key in newValues)) {\n changedFields.push(currentPath);\n continue;\n }\n\n // If values are identical (deep equality)\n if (equal(oldValue, newValue)) continue;\n\n // Handle arrays\n if (Array.isArray(oldValue) && Array.isArray(newValue)) {\n if (oldValue.length !== newValue.length) {\n changedFields.push(currentPath);\n } else {\n // Check if any array element changed\n for (let i = 0; i < oldValue.length; i++) {\n if (\n typeof oldValue[i] === \"object\" && oldValue[i] !== null &&\n typeof newValue[i] === \"object\" && newValue[i] !== null\n ) {\n const nestedChanges = findChangedFields(\n oldValue[i] as object,\n newValue[i] as object,\n `${currentPath}[${i}]`\n );\n if (nestedChanges.length > 0) {\n changedFields.push(currentPath);\n break;\n }\n } else if (!equal(oldValue[i], newValue[i])) {\n changedFields.push(currentPath);\n break;\n }\n }\n }\n }\n // Handle nested objects\n else if (\n typeof oldValue === \"object\" && oldValue !== null &&\n typeof newValue === \"object\" && newValue !== null\n ) {\n const nestedChanges = findChangedFields(\n oldValue as object,\n newValue as object,\n currentPath\n );\n changedFields.push(...nestedChanges);\n }\n // Handle primitives\n else {\n changedFields.push(currentPath);\n }\n }\n\n return changedFields;\n}\n","import { useCallback, useMemo } from \"react\";\nimport { EntityCollection, FireCMSPlugin, mergeCallbacks, User } from \"@firecms/core\";\nimport { EntityHistoryView } from \"./components/EntityHistoryView\";\nimport { HistoryIcon } from \"@firecms/ui\";\nimport { entityHistoryCallbacks } from \"./entity_history_callbacks\";\nimport { HistoryControllerProvider } from \"./HistoryControllerProvider\";\n\n/**\n * This plugin adds a history view to the entity side panel.\n */\nexport function useEntityHistoryPlugin(props?: EntityHistoryPluginProps): FireCMSPlugin<any, any, any, EntityHistoryPluginProps> {\n\n const { defaultEnabled = false } = props ?? {};\n\n const modifyCollection = useCallback((collection: EntityCollection) => {\n if (collection.history === true || defaultEnabled) {\n return {\n ...collection,\n history: true,\n entityViews: [\n ...(collection.entityViews ?? []),\n {\n key: \"__history\",\n name: \"History\",\n tabComponent: <HistoryIcon size={\"small\"}/>,\n Builder: EntityHistoryView,\n position: \"start\"\n }\n ],\n callbacks: mergeCallbacks(collection.callbacks, entityHistoryCallbacks)\n } satisfies EntityCollection;\n }\n return collection;\n }, []);\n\n return useMemo(() => ({\n key: \"entity_history\",\n provider: {\n Component: HistoryControllerProvider,\n props: {\n getUser: props?.getUser\n }\n },\n collection: {\n modifyCollection\n }\n } satisfies FireCMSPlugin), [props]);\n}\n\nexport type EntityHistoryPluginProps = {\n /**\n * If true, the history view will be enabled to all collections by default.\n * Each collection can override this value by setting the `history` property.\n */\n defaultEnabled?: boolean;\n\n /**\n * Function to get the user object from the uid.\n * @param uid\n */\n getUser?: (uid: string) => User | null;\n}\n"],"names":["HistoryControllerContext","React","createContext","useHistoryController","useContext","HistoryControllerProvider","memo","t0","$","_c","children","getUser","t1","t2","equal","UserChip","user","email","uid","displayName","photoURL","t3","t4","t5","t6","EntityHistoryEntry","actions","disabled","hover","collection","collectionProp","previewKeys","onClick","size","entity","authController","useAuthController","customizationController","useCustomizationController","navigationController","useNavigationController","sideEntityController","useSideEntityController","getCollection","path","updatedOn","values","Error","updatedBy","resolvedCollection","useMemo","resolveCollection","propertyConfigs","toLocaleString","cls","defaultBorderMixin","e","open","entityId","id","allowFullScreen","subcollections","undefined","entityViews","permissions","create","delete","edit","read","updateUrl","map","key","childProperty","getPropertyInPath","properties","valueInPath","getValueInPath","EntityHistoryView","formContext","snackbarController","useSnackbarController","dirty","formex","dataSource","useDataSource","pathAndId","revertVersion","setRevertVersion","useState","Symbol","for","revisions","setRevisions","isLoading","setIsLoading","hasMore","setHasMore","limit","setLimit","containerRef","useRef","observerRef","loadMoreRef","listener","listenCollection","order","orderBy","startAfter","onUpdate","entities","length","onError","error","useEffect","currentContainer","current","currentLoadMore","disconnect","options","root","rootMargin","threshold","handleObserver","entries","target","isIntersecting","prev","observer","IntersectionObserver","observe","doRevert","revertVersion_0","revertValues","__metadata","reverted","updated_on","Date","updated_by","saveEntity","status","then","resetForm","message","type","catch","error_0","t7","t8","t9","t10","t11","revision","index","changed_fields","t12","t13","Boolean","t14","t15","t16","t17","t18","entityHistoryCallbacks","onSaveSuccess","props","changedFields","previousValues","findChangedFields","context","console","debug","oldValues","newValues","prefix","allKeys","Set","Object","keys","oldValue","newValue","currentPath","push","Array","isArray","i","nestedChanges","useEntityHistoryPlugin","defaultEnabled","modifyCollection","useCallback","history","name","tabComponent","Builder","position","callbacks","mergeCallbacks","provider","Component"],"mappings":"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"}
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../src/HistoryControllerProvider.tsx","../src/components/UserChip.tsx","../src/components/EntityHistoryEntry.tsx","../src/components/EntityHistoryView.tsx","../src/entity_history_callbacks.ts","../src/useEntityHistoryPlugin.tsx"],"sourcesContent":["import React, { PropsWithChildren, useContext } from \"react\";\nimport equal from \"react-fast-compare\"\n\nimport { User } from \"@firecms/core\";\n\nexport type HistoryConfigController = {\n /**\n * Function to get a user by uid.\n * @param uid\n */\n getUser?: (uid: string) => User | null;\n}\n\nexport const HistoryControllerContext = React.createContext<HistoryConfigController>({} as any);\nexport const useHistoryController = (): HistoryConfigController => useContext(HistoryControllerContext);\n\n\nexport interface HistoryControllerProviderProps {\n\n getUser?: (uid: string) => User | null;\n\n}\n\nexport const HistoryControllerProvider = React.memo(\n function HistoryControllerProvider({\n children,\n getUser,\n }: PropsWithChildren<HistoryControllerProviderProps>) {\n\n return (\n <HistoryControllerContext.Provider\n value={{\n getUser,\n }}>\n\n {children}\n\n </HistoryControllerContext.Provider>\n );\n }, equal);\n","import { User } from \"@firecms/core\";\nimport { Chip, Tooltip } from \"@firecms/ui\";\n\nexport function UserChip({ user }: { user: User }) {\n return (\n <Tooltip title={user.email ?? user.uid}>\n <Chip size={\"small\"} className={\"flex items-center\"}>\n {user.photoURL && <img\n className={\"rounded-full w-6 h-6 mr-2\"}\n src={user.photoURL} alt={user.displayName ?? \"User picture\"}/>}\n <span>{user.displayName ?? user.email ?? user.uid}</span>\n </Chip>\n </Tooltip>\n );\n}\n","import * as React from \"react\";\n\nimport { Chip, cls, defaultBorderMixin, IconButton, KeyboardTabIcon, Tooltip, Typography } from \"@firecms/ui\";\nimport {\n Entity,\n EntityCollection,\n getPropertyInPath,\n getValueInPath,\n PreviewSize,\n PropertyPreview,\n resolveCollection,\n ResolvedProperty,\n SkeletonPropertyComponent,\n useAuthController,\n useCustomizationController,\n useNavigationController,\n useSideEntityController\n} from \"@firecms/core\";\nimport { useHistoryController } from \"../HistoryControllerProvider\";\nimport { UserChip } from \"./UserChip\";\n\nexport type EntityPreviewProps = {\n size: PreviewSize,\n actions?: React.ReactNode,\n collection?: EntityCollection,\n hover?: boolean;\n previewKeys?: string[],\n disabled?: boolean,\n entity: Entity<any>,\n onClick?: (e: React.SyntheticEvent) => void;\n};\n\n/**\n * This view is used to display a preview of an entity.\n * It is used by default in reference fields and whenever a reference is displayed.\n */\nexport function EntityHistoryEntry({\n actions,\n disabled,\n hover,\n collection: collectionProp,\n previewKeys,\n onClick,\n size,\n entity\n }: EntityPreviewProps) {\n\n const authController = useAuthController();\n const customizationController = useCustomizationController();\n\n const navigationController = useNavigationController();\n const sideEntityController = useSideEntityController();\n\n const collection = collectionProp ?? navigationController.getCollection(entity.path);\n const updatedOn = entity.values?.[\"__metadata\"]?.[\"updated_on\"];\n if (!collection) {\n throw Error(`Couldn't find the corresponding collection view for the path: ${entity.path}`);\n }\n\n const updatedBy = entity.values?.[\"__metadata\"]?.[\"updated_by\"];\n const { getUser } = useHistoryController();\n const user = getUser?.(updatedBy);\n\n const resolvedCollection = React.useMemo(() => resolveCollection({\n collection,\n path: entity.path,\n values: entity.values,\n propertyConfigs: customizationController.propertyConfigs,\n authController\n }), [collection]);\n\n return <div className={\"w-full flex flex-col gap-2 mt-4\"}>\n <div className={\"ml-4 flex items-center gap-4\"}>\n <Typography variant={\"body2\"} color={\"secondary\"}>{updatedOn.toLocaleString()}</Typography>\n {!user && updatedBy && <Chip size={\"small\"}>{updatedBy}</Chip>}\n {user && <UserChip user={user}/>}\n </div>\n <div\n className={cls(\n \"bg-white dark:bg-surface-900\",\n \"min-h-[42px]\",\n \"w-full\",\n \"items-center\",\n hover ? \"hover:bg-surface-accent-50 dark:hover:bg-surface-800 group-hover:bg-surface-accent-50 dark:group-hover:bg-surface-800\" : \"\",\n size === \"small\" ? \"p-1\" : \"px-2 py-1\",\n \"flex border rounded-lg\",\n onClick ? \"cursor-pointer\" : \"\",\n defaultBorderMixin\n )}>\n\n\n {actions}\n\n {entity &&\n <Tooltip title={\"See details for this revision\"}\n className={\"my-2 grow-0 shrink-0 self-start\"}>\n <IconButton\n color={\"inherit\"}\n className={\"\"}\n onClick={(e) => {\n\n sideEntityController.open({\n entityId: entity.id,\n path: entity.path,\n allowFullScreen: false,\n collection: {\n ...collection,\n subcollections: undefined,\n entityViews: undefined,\n permissions: {\n create: false,\n delete: false,\n edit: false,\n read: true\n }\n },\n updateUrl: true\n });\n }}>\n <KeyboardTabIcon/>\n </IconButton>\n </Tooltip>}\n\n <div className={\"flex flex-col grow w-full m-1 shrink min-w-0\"}>\n\n {previewKeys && previewKeys.map((key) => {\n const childProperty = getPropertyInPath(resolvedCollection.properties, key);\n\n const valueInPath = getValueInPath(entity.values, key);\n const element = childProperty ? (entity\n ? <PropertyPreview\n propertyKey={key as string}\n value={valueInPath}\n property={childProperty as ResolvedProperty}\n size={\"small\"}/>\n : <SkeletonPropertyComponent\n property={childProperty as ResolvedProperty}\n size={\"small\"}/>) :\n <Typography variant={\"body2\"}>\n {typeof valueInPath === \"string\" ? valueInPath : JSON.stringify(valueInPath)}\n </Typography>;\n return (\n <div key={\"ref_prev_\" + key}\n className=\"flex w-full my-1 items-center\">\n <Typography variant={\"caption\"}\n color={\"secondary\"}\n className=\"min-w-[140px] md:min-w-[200px] w-1/5 pr-8 overflow-hidden text-ellipsis text-right\">\n {key}\n </Typography>\n <div className=\"w-4/5\">\n {\n element\n }\n </div>\n </div>\n );\n })}\n\n </div>\n\n </div>\n </div>\n}\n\n","import { useEffect, useRef, useState } from \"react\";\nimport {\n ConfirmationDialog,\n Entity,\n EntityCustomViewParams,\n useAuthController,\n useDataSource,\n useSnackbarController\n} from \"@firecms/core\";\nimport { cls, HistoryIcon, IconButton, Label, Tooltip, Typography } from \"@firecms/ui\";\nimport { EntityHistoryEntry } from \"./EntityHistoryEntry\";\n\nexport function EntityHistoryView({\n entity,\n collection,\n formContext\n }: EntityCustomViewParams) {\n\n const authController = useAuthController();\n const snackbarController = useSnackbarController();\n const dirty = formContext?.formex.dirty;\n\n const dataSource = useDataSource();\n const pathAndId = entity ? entity?.path + \"/\" + entity?.id : undefined;\n\n const [revertVersionDialog, setRevertVersionDialog] = useState<Entity | undefined>(undefined);\n const [revisions, setRevisions] = useState<Entity[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n\n const PAGE_SIZE = 5;\n const [limit, setLimit] = useState(PAGE_SIZE);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const observerRef = useRef<IntersectionObserver | null>(null);\n const loadMoreRef = useRef<HTMLDivElement>(null);\n\n // Load revisions with the current limit\n useEffect(() => {\n if (!pathAndId) return;\n\n setIsLoading(true); // Set loading true when fetching starts\n const listener = dataSource.listenCollection?.({\n path: pathAndId + \"/__history\",\n order: \"desc\",\n orderBy: \"__metadata.updated_on\",\n limit: limit,\n startAfter: undefined,\n onUpdate: (entities) => {\n setRevisions(entities);\n setHasMore(entities.length === limit && entities.length >= PAGE_SIZE); // Ensure we fetched a full page to consider hasMore\n setIsLoading(false);\n },\n onError: (error) => {\n console.error(\"Error fetching history:\", error);\n setIsLoading(false);\n setHasMore(false); // Stop trying if there's an error\n }\n });\n return () => {\n if (typeof listener === \"function\") {\n listener();\n }\n };\n }, [pathAndId, limit, dataSource]);\n\n // Setup intersection observer for infinite scroll\n useEffect(() => {\n const currentContainer = containerRef.current;\n const currentLoadMore = loadMoreRef.current;\n\n // Conditions for active observation\n if (!currentContainer || !currentLoadMore || !hasMore || isLoading) {\n // If we shouldn't be observing, ensure any existing observer is disconnected\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n return;\n }\n\n // Options for the IntersectionObserver\n const options = {\n root: currentContainer,\n rootMargin: \"0px 0px 200px 0px\", // Trigger 200px before the sentinel is at the bottom edge\n threshold: 0.01 // Trigger if even a small part is visible within the rootMargin\n };\n\n // The callback for when the sentinel's intersection state changes\n const handleObserver = (entries: IntersectionObserverEntry[]) => {\n const target = entries[0];\n if (target.isIntersecting && hasMore && !isLoading) {\n // No need to setIsLoading(true) here, it's done in the data fetching useEffect\n setLimit(prev => prev + PAGE_SIZE);\n }\n };\n\n const observer = new IntersectionObserver(handleObserver, options);\n observer.observe(currentLoadMore);\n observerRef.current = observer; // Store the new observer\n\n // Cleanup function for this effect instance\n return () => {\n observer.disconnect(); // Disconnect the observer created in *this* effect run\n if (observerRef.current === observer) {\n observerRef.current = null;\n }\n };\n // Re-run if hasMore, isLoading changes, or if revisions.length changes (which might make loadMoreRef available/unavailable)\n }, [hasMore, isLoading, revisions.length]);\n\n if (!entity) {\n return <div className=\"flex items-center justify-center h-full\">\n <Label>History is only available for existing entities</Label>\n </div>\n }\n\n function doRevert(revertVersion: Entity) {\n if (!entity) {\n throw new Error(\"No entity to revert\");\n }\n const revertValues = {\n ...revertVersion.values,\n __metadata: {\n ...revertVersion.values?.[\"__metadata\"],\n reverted: true,\n updated_on: new Date(),\n updated_by: authController.user?.uid ?? null,\n }\n };\n const saveReverted = dataSource.saveEntity({\n path: entity.path,\n entityId: entity.id,\n values: revertValues,\n collection,\n status: \"existing\"\n });\n const saveRevertedHistory = dataSource.saveEntity({\n path: revertVersion.path,\n entityId: revertVersion.id,\n values: revertValues,\n collection,\n status: \"existing\"\n });\n return Promise.all([saveReverted, saveRevertedHistory])\n .then(() => {\n formContext.formex.resetForm({\n values: revertVersion.values\n });\n setRevertVersionDialog(undefined);\n snackbarController.open({\n message: \"Reverted version\",\n type: \"info\"\n });\n }\n ).catch((error) => {\n console.error(\"Error reverting entity:\", error);\n snackbarController.open({\n message: \"Error reverting entity\",\n type: \"error\"\n });\n });\n\n }\n\n return <div\n ref={containerRef}\n className={cls(\"relative flex-1 h-full overflow-auto w-full flex flex-col gap-4 p-8\")}>\n <div className=\"flex flex-col gap-2 max-w-6xl mx-auto w-full\">\n\n <Typography variant={\"h5\"} className={\"mt-24 ml-4\"}>\n History\n </Typography>\n\n {revisions.length === 0 && <>\n <Label className={\"ml-4 mt-8\"}>\n No history available\n </Label>\n <Typography variant={\"caption\"} className={\"ml-4\"}>\n When you save an entity, a new version is created and stored in the history.\n </Typography>\n </>}\n\n {revisions.map((revision, index) => {\n const previewKeys = revision.values?.[\"__metadata\"]?.[\"changed_fields\"];\n return <div key={index} className=\"flex flex-cols gap-2 w-full\">\n <EntityHistoryEntry size={\"large\"}\n entity={revision}\n collection={collection}\n previewKeys={previewKeys}\n actions={\n <Tooltip title={\"Revert to this version\"}\n className={\"m-2 grow-0 self-start\"}>\n <IconButton\n onClick={() => {\n if (dirty) {\n snackbarController.open({\n message: \"Please save or discard your changes before reverting\",\n type: \"warning\"\n });\n } else {\n setRevertVersionDialog(revision);\n }\n }}>\n <HistoryIcon/>\n </IconButton>\n </Tooltip>}\n />\n </div>\n })}\n\n {/* Load more sentinel element */}\n {revisions.length > 0 && (\n <div\n ref={loadMoreRef}\n className=\"py-4 text-center\"\n >\n {isLoading && <Label>Loading more...</Label>}\n {!hasMore && revisions.length > PAGE_SIZE && <Label>No more history available</Label>}\n </div>\n )}\n </div>\n\n <ConfirmationDialog open={Boolean(revertVersionDialog)}\n onAccept={function (): void {\n if (!revertVersionDialog) return;\n doRevert(revertVersionDialog);\n }}\n onCancel={function (): void {\n setRevertVersionDialog(undefined);\n }}\n title={<Typography variant={\"subtitle2\"}>Revert data to this version?</Typography>}/>\n </div>\n}\n","import { EntityCallbacks } from \"@firecms/core\";\nimport equal from \"react-fast-compare\"\n\nexport const entityHistoryCallbacks: EntityCallbacks = {\n onSaveSuccess: async (props) => {\n\n const changedFields = props.previousValues ? findChangedFields(props.previousValues, props.values) : null;\n const uid = props.context.authController.user?.uid;\n props.context.dataSource.saveEntity({\n path: props.path + \"/\" + props.entityId + \"/__history\",\n values: {\n ...props.values,\n __metadata: {\n changed_fields: changedFields,\n updated_on: new Date(),\n updated_by: uid,\n }\n },\n status: \"new\"\n }).then(() => {\n console.debug(\"History saved for\", props.path, props.entityId);\n });\n }\n}\n\nfunction findChangedFields<M extends object>(oldValues: M, newValues: M, prefix: string = \"\"): string[] {\n const changedFields: string[] = [];\n\n // Handle null/undefined cases\n if (equal(oldValues, newValues)) return changedFields;\n if (!oldValues || !newValues) return [prefix || \".\"];\n\n // Get all unique keys from both objects\n const allKeys = new Set([\n ...Object.keys(oldValues),\n ...Object.keys(newValues)\n ]);\n\n for (const key of allKeys) {\n const oldValue = oldValues[key as keyof M];\n const newValue = newValues[key as keyof M];\n const currentPath = prefix ? `${prefix}.${key}` : key;\n\n // If key exists only in one object\n if ((key in oldValues) !== (key in newValues)) {\n changedFields.push(currentPath);\n continue;\n }\n\n // If values are identical (deep equality)\n if (equal(oldValue, newValue)) continue;\n\n // Handle arrays\n if (Array.isArray(oldValue) && Array.isArray(newValue)) {\n if (oldValue.length !== newValue.length) {\n changedFields.push(currentPath);\n } else {\n // Check if any array element changed\n for (let i = 0; i < oldValue.length; i++) {\n if (\n typeof oldValue[i] === \"object\" && oldValue[i] !== null &&\n typeof newValue[i] === \"object\" && newValue[i] !== null\n ) {\n const nestedChanges = findChangedFields(\n oldValue[i] as object,\n newValue[i] as object,\n `${currentPath}[${i}]`\n );\n if (nestedChanges.length > 0) {\n changedFields.push(currentPath);\n break;\n }\n } else if (!equal(oldValue[i], newValue[i])) {\n changedFields.push(currentPath);\n break;\n }\n }\n }\n }\n // Handle nested objects\n else if (\n typeof oldValue === \"object\" && oldValue !== null &&\n typeof newValue === \"object\" && newValue !== null\n ) {\n const nestedChanges = findChangedFields(\n oldValue as object,\n newValue as object,\n currentPath\n );\n changedFields.push(...nestedChanges);\n }\n // Handle primitives\n else {\n changedFields.push(currentPath);\n }\n }\n\n return changedFields;\n}\n","import { useCallback, useMemo } from \"react\";\nimport { EntityCollection, FireCMSPlugin, mergeCallbacks, User } from \"@firecms/core\";\nimport { EntityHistoryView } from \"./components/EntityHistoryView\";\nimport { HistoryIcon } from \"@firecms/ui\";\nimport { entityHistoryCallbacks } from \"./entity_history_callbacks\";\nimport { HistoryControllerProvider } from \"./HistoryControllerProvider\";\n\n/**\n * This plugin adds a history view to the entity side panel.\n */\nexport function useEntityHistoryPlugin(props?: EntityHistoryPluginProps): FireCMSPlugin<any, any, any, EntityHistoryPluginProps> {\n\n const { defaultEnabled = false } = props ?? {};\n\n const modifyCollection = useCallback((collection: EntityCollection) => {\n if (collection.history === true || (defaultEnabled && collection.history !== false)) {\n return {\n ...collection,\n entityViews: [\n ...(collection.entityViews ?? []),\n {\n key: \"__history\",\n name: \"History\",\n tabComponent: <HistoryIcon size={\"small\"}/>,\n Builder: EntityHistoryView,\n position: \"start\"\n }\n ],\n callbacks: mergeCallbacks(collection.callbacks, entityHistoryCallbacks)\n } satisfies EntityCollection;\n }\n return collection;\n }, []);\n\n return useMemo(() => ({\n key: \"entity_history\",\n provider: {\n Component: HistoryControllerProvider,\n props: {\n getUser: props?.getUser\n }\n },\n collection: {\n modifyCollection\n }\n } satisfies FireCMSPlugin), [props]);\n}\n\nexport type EntityHistoryPluginProps = {\n /**\n * If true, the history view will be enabled to all collections by default.\n * Each collection can override this value by setting the `history` property.\n */\n defaultEnabled?: boolean;\n\n /**\n * Function to get the user object from the uid.\n * @param uid\n */\n getUser?: (uid: string) => User | null;\n}\n"],"names":["HistoryControllerContext","React","createContext","useHistoryController","useContext","HistoryControllerProvider","memo","t0","$","_c","children","getUser","t1","t2","equal","UserChip","user","email","uid","displayName","photoURL","t3","t4","t5","t6","EntityHistoryEntry","actions","disabled","hover","collection","collectionProp","previewKeys","onClick","size","entity","authController","useAuthController","customizationController","useCustomizationController","navigationController","useNavigationController","sideEntityController","useSideEntityController","getCollection","path","updatedOn","values","Error","updatedBy","resolvedCollection","useMemo","resolveCollection","propertyConfigs","toLocaleString","cls","defaultBorderMixin","e","open","entityId","id","allowFullScreen","subcollections","undefined","entityViews","permissions","create","delete","edit","read","updateUrl","map","key","childProperty","getPropertyInPath","properties","valueInPath","getValueInPath","element","JSON","stringify","EntityHistoryView","formContext","snackbarController","useSnackbarController","dirty","formex","dataSource","useDataSource","pathAndId","revertVersionDialog","setRevertVersionDialog","useState","Symbol","for","revisions","setRevisions","isLoading","setIsLoading","hasMore","setHasMore","limit","setLimit","containerRef","useRef","observerRef","loadMoreRef","listener","listenCollection","order","orderBy","startAfter","onUpdate","entities","length","onError","error","useEffect","currentContainer","current","currentLoadMore","disconnect","options","root","rootMargin","threshold","handleObserver","entries","target","isIntersecting","prev","observer","IntersectionObserver","observe","doRevert","revertVersion","revertValues","__metadata","reverted","updated_on","Date","updated_by","saveReverted","saveEntity","status","saveRevertedHistory","Promise","all","then","resetForm","message","type","catch","error_0","t7","t8","t9","t10","t11","revision","index","changed_fields","t12","t13","Boolean","t14","t15","t16","t17","t18","entityHistoryCallbacks","onSaveSuccess","props","changedFields","previousValues","findChangedFields","context","console","debug","oldValues","newValues","prefix","allKeys","Set","Object","keys","oldValue","newValue","currentPath","push","Array","isArray","i","nestedChanges","useEntityHistoryPlugin","defaultEnabled","modifyCollection","useCallback","history","name","tabComponent","Builder","position","callbacks","mergeCallbacks","provider","Component"],"mappings":"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"}
|
package/dist/index.umd.js
CHANGED
@@ -157,18 +157,18 @@
|
|
157
157
|
}, children: /* @__PURE__ */ jsxRuntime.jsx(ui.KeyboardTabIcon, {}) }) }),
|
158
158
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col grow w-full m-1 shrink min-w-0", children: previewKeys && previewKeys.map((key) => {
|
159
159
|
const childProperty = core.getPropertyInPath(resolvedCollection.properties, key);
|
160
|
-
if (!childProperty) return null;
|
161
160
|
const valueInPath = core.getValueInPath(entity.values, key);
|
161
|
+
const element = childProperty ? entity ? /* @__PURE__ */ jsxRuntime.jsx(core.PropertyPreview, { propertyKey: key, value: valueInPath, property: childProperty, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(core.SkeletonPropertyComponent, { property: childProperty, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "body2", children: typeof valueInPath === "string" ? valueInPath : JSON.stringify(valueInPath) });
|
162
162
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full my-1 items-center", children: [
|
163
163
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", className: "min-w-[140px] md:min-w-[200px] w-1/5 pr-8 overflow-hidden text-ellipsis text-right", children: key }),
|
164
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-4/5", children:
|
164
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-4/5", children: element })
|
165
165
|
] }, "ref_prev_" + key);
|
166
166
|
}) })
|
167
167
|
] })
|
168
168
|
] });
|
169
169
|
}
|
170
170
|
function EntityHistoryView(t0) {
|
171
|
-
const $ = reactCompilerRuntime.c(
|
171
|
+
const $ = reactCompilerRuntime.c(53);
|
172
172
|
const {
|
173
173
|
entity,
|
174
174
|
collection,
|
@@ -179,7 +179,7 @@
|
|
179
179
|
const dirty = formContext?.formex.dirty;
|
180
180
|
const dataSource = core.useDataSource();
|
181
181
|
const pathAndId = entity ? entity?.path + "/" + entity?.id : void 0;
|
182
|
-
const [
|
182
|
+
const [revertVersionDialog, setRevertVersionDialog] = React.useState(void 0);
|
183
183
|
let t1;
|
184
184
|
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
185
185
|
t1 = [];
|
@@ -297,28 +297,39 @@
|
|
297
297
|
return t62;
|
298
298
|
}
|
299
299
|
let t6;
|
300
|
-
if ($[14] !== authController
|
301
|
-
t6 = function doRevert2(
|
300
|
+
if ($[14] !== authController || $[15] !== collection || $[16] !== dataSource || $[17] !== entity || $[18] !== formContext || $[19] !== snackbarController) {
|
301
|
+
t6 = function doRevert2(revertVersion) {
|
302
|
+
if (!entity) {
|
303
|
+
throw new Error("No entity to revert");
|
304
|
+
}
|
302
305
|
const revertValues = {
|
303
|
-
...
|
306
|
+
...revertVersion.values,
|
304
307
|
__metadata: {
|
305
|
-
...
|
308
|
+
...revertVersion.values?.__metadata,
|
306
309
|
reverted: true,
|
307
310
|
updated_on: /* @__PURE__ */ new Date(),
|
308
311
|
updated_by: authController.user?.uid ?? null
|
309
312
|
}
|
310
313
|
};
|
311
|
-
|
312
|
-
path:
|
313
|
-
entityId:
|
314
|
+
const saveReverted = dataSource.saveEntity({
|
315
|
+
path: entity.path,
|
316
|
+
entityId: entity.id,
|
317
|
+
values: revertValues,
|
318
|
+
collection,
|
319
|
+
status: "existing"
|
320
|
+
});
|
321
|
+
const saveRevertedHistory = dataSource.saveEntity({
|
322
|
+
path: revertVersion.path,
|
323
|
+
entityId: revertVersion.id,
|
314
324
|
values: revertValues,
|
315
325
|
collection,
|
316
326
|
status: "existing"
|
317
|
-
})
|
327
|
+
});
|
328
|
+
return Promise.all([saveReverted, saveRevertedHistory]).then(() => {
|
318
329
|
formContext.formex.resetForm({
|
319
|
-
values:
|
330
|
+
values: revertVersion.values
|
320
331
|
});
|
321
|
-
|
332
|
+
setRevertVersionDialog(void 0);
|
322
333
|
snackbarController.open({
|
323
334
|
message: "Reverted version",
|
324
335
|
type: "info"
|
@@ -331,45 +342,46 @@
|
|
331
342
|
});
|
332
343
|
});
|
333
344
|
};
|
334
|
-
$[14] = authController
|
345
|
+
$[14] = authController;
|
335
346
|
$[15] = collection;
|
336
347
|
$[16] = dataSource;
|
337
|
-
$[17] =
|
338
|
-
$[18] =
|
339
|
-
$[19] =
|
348
|
+
$[17] = entity;
|
349
|
+
$[18] = formContext;
|
350
|
+
$[19] = snackbarController;
|
351
|
+
$[20] = t6;
|
340
352
|
} else {
|
341
|
-
t6 = $[
|
353
|
+
t6 = $[20];
|
342
354
|
}
|
343
355
|
const doRevert = t6;
|
344
356
|
let t7;
|
345
|
-
if ($[
|
357
|
+
if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
|
346
358
|
t7 = ui.cls("relative flex-1 h-full overflow-auto w-full flex flex-col gap-4 p-8");
|
347
|
-
$[
|
359
|
+
$[21] = t7;
|
348
360
|
} else {
|
349
|
-
t7 = $[
|
361
|
+
t7 = $[21];
|
350
362
|
}
|
351
363
|
let t8;
|
352
|
-
if ($[
|
364
|
+
if ($[22] === Symbol.for("react.memo_cache_sentinel")) {
|
353
365
|
t8 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "h5", className: "mt-24 ml-4", children: "History" });
|
354
|
-
$[
|
366
|
+
$[22] = t8;
|
355
367
|
} else {
|
356
|
-
t8 = $[
|
368
|
+
t8 = $[22];
|
357
369
|
}
|
358
370
|
let t9;
|
359
|
-
if ($[
|
371
|
+
if ($[23] !== revisions.length) {
|
360
372
|
t9 = revisions.length === 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
361
373
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { className: "ml-4 mt-8", children: "No history available" }),
|
362
374
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "ml-4", children: "When you save an entity, a new version is created and stored in the history." })
|
363
375
|
] });
|
364
|
-
$[
|
365
|
-
$[
|
376
|
+
$[23] = revisions.length;
|
377
|
+
$[24] = t9;
|
366
378
|
} else {
|
367
|
-
t9 = $[
|
379
|
+
t9 = $[24];
|
368
380
|
}
|
369
381
|
let t10;
|
370
|
-
if ($[
|
382
|
+
if ($[25] !== collection || $[26] !== dirty || $[27] !== revisions || $[28] !== snackbarController) {
|
371
383
|
let t112;
|
372
|
-
if ($[
|
384
|
+
if ($[30] !== collection || $[31] !== dirty || $[32] !== snackbarController) {
|
373
385
|
t112 = (revision, index) => {
|
374
386
|
const previewKeys = revision.values?.__metadata?.changed_fields;
|
375
387
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-cols gap-2 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(EntityHistoryEntry, { size: "large", entity: revision, collection, previewKeys, actions: /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "Revert to this version", className: "m-2 grow-0 self-start", children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: () => {
|
@@ -379,102 +391,102 @@
|
|
379
391
|
type: "warning"
|
380
392
|
});
|
381
393
|
} else {
|
382
|
-
|
394
|
+
setRevertVersionDialog(revision);
|
383
395
|
}
|
384
396
|
}, children: /* @__PURE__ */ jsxRuntime.jsx(ui.HistoryIcon, {}) }) }) }) }, index);
|
385
397
|
};
|
386
|
-
$[
|
387
|
-
$[
|
388
|
-
$[
|
389
|
-
$[
|
398
|
+
$[30] = collection;
|
399
|
+
$[31] = dirty;
|
400
|
+
$[32] = snackbarController;
|
401
|
+
$[33] = t112;
|
390
402
|
} else {
|
391
|
-
t112 = $[
|
403
|
+
t112 = $[33];
|
392
404
|
}
|
393
405
|
t10 = revisions.map(t112);
|
394
|
-
$[
|
395
|
-
$[
|
396
|
-
$[
|
397
|
-
$[
|
398
|
-
$[
|
406
|
+
$[25] = collection;
|
407
|
+
$[26] = dirty;
|
408
|
+
$[27] = revisions;
|
409
|
+
$[28] = snackbarController;
|
410
|
+
$[29] = t10;
|
399
411
|
} else {
|
400
|
-
t10 = $[
|
412
|
+
t10 = $[29];
|
401
413
|
}
|
402
414
|
let t11;
|
403
|
-
if ($[
|
415
|
+
if ($[34] !== hasMore || $[35] !== isLoading || $[36] !== revisions.length) {
|
404
416
|
t11 = revisions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: loadMoreRef, className: "py-4 text-center", children: [
|
405
417
|
isLoading && /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Loading more..." }),
|
406
418
|
!hasMore && revisions.length > 5 && /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "No more history available" })
|
407
419
|
] });
|
408
|
-
$[
|
409
|
-
$[
|
410
|
-
$[
|
411
|
-
$[
|
420
|
+
$[34] = hasMore;
|
421
|
+
$[35] = isLoading;
|
422
|
+
$[36] = revisions.length;
|
423
|
+
$[37] = t11;
|
412
424
|
} else {
|
413
|
-
t11 = $[
|
425
|
+
t11 = $[37];
|
414
426
|
}
|
415
427
|
let t12;
|
416
|
-
if ($[
|
428
|
+
if ($[38] !== t10 || $[39] !== t11 || $[40] !== t9) {
|
417
429
|
t12 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 max-w-6xl mx-auto w-full", children: [
|
418
430
|
t8,
|
419
431
|
t9,
|
420
432
|
t10,
|
421
433
|
t11
|
422
434
|
] });
|
423
|
-
$[
|
424
|
-
$[
|
425
|
-
$[
|
426
|
-
$[
|
435
|
+
$[38] = t10;
|
436
|
+
$[39] = t11;
|
437
|
+
$[40] = t9;
|
438
|
+
$[41] = t12;
|
427
439
|
} else {
|
428
|
-
t12 = $[
|
440
|
+
t12 = $[41];
|
429
441
|
}
|
430
|
-
const t13 = Boolean(
|
442
|
+
const t13 = Boolean(revertVersionDialog);
|
431
443
|
let t14;
|
432
|
-
if ($[
|
444
|
+
if ($[42] !== doRevert || $[43] !== revertVersionDialog) {
|
433
445
|
t14 = function() {
|
434
|
-
if (!
|
446
|
+
if (!revertVersionDialog) {
|
435
447
|
return;
|
436
448
|
}
|
437
|
-
doRevert(
|
449
|
+
doRevert(revertVersionDialog);
|
438
450
|
};
|
439
|
-
$[
|
440
|
-
$[
|
441
|
-
$[
|
451
|
+
$[42] = doRevert;
|
452
|
+
$[43] = revertVersionDialog;
|
453
|
+
$[44] = t14;
|
442
454
|
} else {
|
443
|
-
t14 = $[
|
455
|
+
t14 = $[44];
|
444
456
|
}
|
445
457
|
let t15;
|
446
458
|
let t16;
|
447
|
-
if ($[
|
459
|
+
if ($[45] === Symbol.for("react.memo_cache_sentinel")) {
|
448
460
|
t15 = function() {
|
449
|
-
|
461
|
+
setRevertVersionDialog(void 0);
|
450
462
|
};
|
451
463
|
t16 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "subtitle2", children: "Revert data to this version?" });
|
452
|
-
$[
|
453
|
-
$[
|
464
|
+
$[45] = t15;
|
465
|
+
$[46] = t16;
|
454
466
|
} else {
|
455
|
-
t15 = $[
|
456
|
-
t16 = $[
|
467
|
+
t15 = $[45];
|
468
|
+
t16 = $[46];
|
457
469
|
}
|
458
470
|
let t17;
|
459
|
-
if ($[
|
471
|
+
if ($[47] !== t13 || $[48] !== t14) {
|
460
472
|
t17 = /* @__PURE__ */ jsxRuntime.jsx(core.ConfirmationDialog, { open: t13, onAccept: t14, onCancel: t15, title: t16 });
|
461
|
-
$[
|
462
|
-
$[
|
463
|
-
$[
|
473
|
+
$[47] = t13;
|
474
|
+
$[48] = t14;
|
475
|
+
$[49] = t17;
|
464
476
|
} else {
|
465
|
-
t17 = $[
|
477
|
+
t17 = $[49];
|
466
478
|
}
|
467
479
|
let t18;
|
468
|
-
if ($[
|
480
|
+
if ($[50] !== t12 || $[51] !== t17) {
|
469
481
|
t18 = /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: t7, children: [
|
470
482
|
t12,
|
471
483
|
t17
|
472
484
|
] });
|
473
|
-
$[
|
474
|
-
$[
|
475
|
-
$[
|
485
|
+
$[50] = t12;
|
486
|
+
$[51] = t17;
|
487
|
+
$[52] = t18;
|
476
488
|
} else {
|
477
|
-
t18 = $[
|
489
|
+
t18 = $[52];
|
478
490
|
}
|
479
491
|
return t18;
|
480
492
|
}
|
@@ -543,10 +555,9 @@
|
|
543
555
|
defaultEnabled = false
|
544
556
|
} = props ?? {};
|
545
557
|
const modifyCollection = React.useCallback((collection) => {
|
546
|
-
if (collection.history === true || defaultEnabled) {
|
558
|
+
if (collection.history === true || defaultEnabled && collection.history !== false) {
|
547
559
|
return {
|
548
560
|
...collection,
|
549
|
-
history: true,
|
550
561
|
entityViews: [...collection.entityViews ?? [], {
|
551
562
|
key: "__history",
|
552
563
|
name: "History",
|
package/dist/index.umd.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.umd.js","sources":["../src/HistoryControllerProvider.tsx","../src/components/UserChip.tsx","../src/components/EntityHistoryEntry.tsx","../src/components/EntityHistoryView.tsx","../src/entity_history_callbacks.ts","../src/useEntityHistoryPlugin.tsx"],"sourcesContent":["import React, { PropsWithChildren, useContext } from \"react\";\nimport equal from \"react-fast-compare\"\n\nimport { User } from \"@firecms/core\";\n\nexport type HistoryConfigController = {\n /**\n * Function to get a user by uid.\n * @param uid\n */\n getUser?: (uid: string) => User | null;\n}\n\nexport const HistoryControllerContext = React.createContext<HistoryConfigController>({} as any);\nexport const useHistoryController = (): HistoryConfigController => useContext(HistoryControllerContext);\n\n\nexport interface HistoryControllerProviderProps {\n\n getUser?: (uid: string) => User | null;\n\n}\n\nexport const HistoryControllerProvider = React.memo(\n function HistoryControllerProvider({\n children,\n getUser,\n }: PropsWithChildren<HistoryControllerProviderProps>) {\n\n return (\n <HistoryControllerContext.Provider\n value={{\n getUser,\n }}>\n\n {children}\n\n </HistoryControllerContext.Provider>\n );\n }, equal);\n","import { User } from \"@firecms/core\";\nimport { Chip, Tooltip } from \"@firecms/ui\";\n\nexport function UserChip({ user }: { user: User }) {\n return (\n <Tooltip title={user.email ?? user.uid}>\n <Chip size={\"small\"} className={\"flex items-center\"}>\n {user.photoURL && <img\n className={\"rounded-full w-6 h-6 mr-2\"}\n src={user.photoURL} alt={user.displayName ?? \"User picture\"}/>}\n <span>{user.displayName ?? user.email ?? user.uid}</span>\n </Chip>\n </Tooltip>\n );\n}\n","import * as React from \"react\";\n\nimport { Chip, cls, defaultBorderMixin, IconButton, KeyboardTabIcon, Tooltip, Typography } from \"@firecms/ui\";\nimport {\n Entity,\n EntityCollection,\n getPropertyInPath,\n getValueInPath,\n PreviewSize,\n PropertyPreview,\n resolveCollection,\n ResolvedProperty,\n SkeletonPropertyComponent,\n useAuthController,\n useCustomizationController,\n useNavigationController,\n useSideEntityController\n} from \"@firecms/core\";\nimport { useHistoryController } from \"../HistoryControllerProvider\";\nimport { UserChip } from \"./UserChip\";\n\nexport type EntityPreviewProps = {\n size: PreviewSize,\n actions?: React.ReactNode,\n collection?: EntityCollection,\n hover?: boolean;\n previewKeys?: string[],\n disabled?: boolean,\n entity: Entity<any>,\n onClick?: (e: React.SyntheticEvent) => void;\n};\n\n/**\n * This view is used to display a preview of an entity.\n * It is used by default in reference fields and whenever a reference is displayed.\n */\nexport function EntityHistoryEntry({\n actions,\n disabled,\n hover,\n collection: collectionProp,\n previewKeys,\n onClick,\n size,\n entity\n }: EntityPreviewProps) {\n\n const authController = useAuthController();\n const customizationController = useCustomizationController();\n\n const navigationController = useNavigationController();\n const sideEntityController = useSideEntityController();\n\n const collection = collectionProp ?? navigationController.getCollection(entity.path);\n const updatedOn = entity.values?.[\"__metadata\"]?.[\"updated_on\"];\n if (!collection) {\n throw Error(`Couldn't find the corresponding collection view for the path: ${entity.path}`);\n }\n\n const updatedBy = entity.values?.[\"__metadata\"]?.[\"updated_by\"];\n const { getUser } = useHistoryController();\n const user = getUser?.(updatedBy);\n\n const resolvedCollection = React.useMemo(() => resolveCollection({\n collection,\n path: entity.path,\n values: entity.values,\n propertyConfigs: customizationController.propertyConfigs,\n authController\n }), [collection]);\n\n return <div className={\"w-full flex flex-col gap-2 mt-4\"}>\n <div className={\"ml-4 flex items-center gap-4\"}>\n <Typography variant={\"body2\"} color={\"secondary\"}>{updatedOn.toLocaleString()}</Typography>\n {!user && updatedBy && <Chip size={\"small\"}>{updatedBy}</Chip>}\n {user && <UserChip user={user}/>}\n </div>\n <div\n className={cls(\n \"bg-white dark:bg-surface-900\",\n \"min-h-[42px]\",\n \"w-full\",\n \"items-center\",\n hover ? \"hover:bg-surface-accent-50 dark:hover:bg-surface-800 group-hover:bg-surface-accent-50 dark:group-hover:bg-surface-800\" : \"\",\n size === \"small\" ? \"p-1\" : \"px-2 py-1\",\n \"flex border rounded-lg\",\n onClick ? \"cursor-pointer\" : \"\",\n defaultBorderMixin\n )}>\n\n\n {actions}\n\n {entity &&\n <Tooltip title={\"See details for this revision\"}\n className={\"my-2 grow-0 shrink-0 self-start\"}>\n <IconButton\n color={\"inherit\"}\n className={\"\"}\n onClick={(e) => {\n\n sideEntityController.open({\n entityId: entity.id,\n path: entity.path,\n allowFullScreen: false,\n collection: {\n ...collection,\n subcollections: undefined,\n entityViews: undefined,\n permissions: {\n create: false,\n delete: false,\n edit: false,\n read: true\n }\n },\n updateUrl: true\n });\n }}>\n <KeyboardTabIcon/>\n </IconButton>\n </Tooltip>}\n\n <div className={\"flex flex-col grow w-full m-1 shrink min-w-0\"}>\n\n {previewKeys && previewKeys.map((key) => {\n const childProperty = getPropertyInPath(resolvedCollection.properties, key);\n if (!childProperty) return null;\n\n const valueInPath = getValueInPath(entity.values, key);\n return (\n <div key={\"ref_prev_\" + key}\n className=\"flex w-full my-1 items-center\">\n <Typography variant={\"caption\"}\n color={\"secondary\"}\n className=\"min-w-[140px] md:min-w-[200px] w-1/5 pr-8 overflow-hidden text-ellipsis text-right\">\n {key}\n </Typography>\n <div className=\"w-4/5\">\n {\n entity\n ? <PropertyPreview\n propertyKey={key as string}\n value={valueInPath}\n property={childProperty as ResolvedProperty}\n size={\"small\"}/>\n : <SkeletonPropertyComponent\n property={childProperty as ResolvedProperty}\n size={\"small\"}/>\n }\n </div>\n </div>\n );\n })}\n\n </div>\n\n </div>\n </div>\n}\n\n","import { useEffect, useRef, useState } from \"react\";\nimport {\n ConfirmationDialog,\n Entity,\n EntityCustomViewParams,\n useAuthController,\n useDataSource,\n useSnackbarController\n} from \"@firecms/core\";\nimport { cls, HistoryIcon, IconButton, Label, Tooltip, Typography } from \"@firecms/ui\";\nimport { EntityHistoryEntry } from \"./EntityHistoryEntry\";\n\nexport function EntityHistoryView({\n entity,\n collection,\n formContext\n }: EntityCustomViewParams) {\n\n const authController = useAuthController();\n const snackbarController = useSnackbarController();\n const dirty = formContext?.formex.dirty;\n\n const dataSource = useDataSource();\n const pathAndId = entity ? entity?.path + \"/\" + entity?.id : undefined;\n\n const [revertVersion, setRevertVersion] = useState<Entity | undefined>(undefined);\n const [revisions, setRevisions] = useState<Entity[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n\n const PAGE_SIZE = 5;\n const [limit, setLimit] = useState(PAGE_SIZE);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const observerRef = useRef<IntersectionObserver | null>(null);\n const loadMoreRef = useRef<HTMLDivElement>(null);\n\n // Load revisions with the current limit\n useEffect(() => {\n if (!pathAndId) return;\n\n setIsLoading(true); // Set loading true when fetching starts\n const listener = dataSource.listenCollection?.({\n path: pathAndId + \"/__history\",\n order: \"desc\",\n orderBy: \"__metadata.updated_on\",\n limit: limit,\n startAfter: undefined,\n onUpdate: (entities) => {\n setRevisions(entities);\n setHasMore(entities.length === limit && entities.length >= PAGE_SIZE); // Ensure we fetched a full page to consider hasMore\n setIsLoading(false);\n },\n onError: (error) => {\n console.error(\"Error fetching history:\", error);\n setIsLoading(false);\n setHasMore(false); // Stop trying if there's an error\n }\n });\n return () => {\n if (typeof listener === \"function\") {\n listener();\n }\n };\n }, [pathAndId, limit, dataSource]);\n\n // Setup intersection observer for infinite scroll\n useEffect(() => {\n const currentContainer = containerRef.current;\n const currentLoadMore = loadMoreRef.current;\n\n // Conditions for active observation\n if (!currentContainer || !currentLoadMore || !hasMore || isLoading) {\n // If we shouldn't be observing, ensure any existing observer is disconnected\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n return;\n }\n\n // Options for the IntersectionObserver\n const options = {\n root: currentContainer,\n rootMargin: \"0px 0px 200px 0px\", // Trigger 200px before the sentinel is at the bottom edge\n threshold: 0.01 // Trigger if even a small part is visible within the rootMargin\n };\n\n // The callback for when the sentinel's intersection state changes\n const handleObserver = (entries: IntersectionObserverEntry[]) => {\n const target = entries[0];\n if (target.isIntersecting && hasMore && !isLoading) {\n // No need to setIsLoading(true) here, it's done in the data fetching useEffect\n setLimit(prev => prev + PAGE_SIZE);\n }\n };\n\n const observer = new IntersectionObserver(handleObserver, options);\n observer.observe(currentLoadMore);\n observerRef.current = observer; // Store the new observer\n\n // Cleanup function for this effect instance\n return () => {\n observer.disconnect(); // Disconnect the observer created in *this* effect run\n if (observerRef.current === observer) {\n observerRef.current = null;\n }\n };\n // Re-run if hasMore, isLoading changes, or if revisions.length changes (which might make loadMoreRef available/unavailable)\n }, [hasMore, isLoading, revisions.length]);\n\n if (!entity) {\n return <div className=\"flex items-center justify-center h-full\">\n <Label>History is only available for existing entities</Label>\n </div>\n }\n\n function doRevert(revertVersion: Entity) {\n const revertValues = {\n ...revertVersion.values,\n __metadata: {\n ...revertVersion.values?.[\"__metadata\"],\n reverted: true,\n updated_on: new Date(),\n updated_by: authController.user?.uid ?? null,\n }\n };\n return dataSource.saveEntity({\n path: revertVersion.path,\n entityId: revertVersion.id,\n values: revertValues,\n collection,\n status: \"existing\"\n }).then(() => {\n formContext.formex.resetForm({\n values: revertVersion.values\n });\n setRevertVersion(undefined);\n snackbarController.open({\n message: \"Reverted version\",\n type: \"info\"\n });\n }\n ).catch((error) => {\n console.error(\"Error reverting entity:\", error);\n snackbarController.open({\n message: \"Error reverting entity\",\n type: \"error\"\n });\n });\n\n }\n\n return <div\n ref={containerRef}\n className={cls(\"relative flex-1 h-full overflow-auto w-full flex flex-col gap-4 p-8\")}>\n <div className=\"flex flex-col gap-2 max-w-6xl mx-auto w-full\">\n\n <Typography variant={\"h5\"} className={\"mt-24 ml-4\"}>\n History\n </Typography>\n\n {revisions.length === 0 && <>\n <Label className={\"ml-4 mt-8\"}>\n No history available\n </Label>\n <Typography variant={\"caption\"} className={\"ml-4\"}>\n When you save an entity, a new version is created and stored in the history.\n </Typography>\n </>}\n\n {revisions.map((revision, index) => {\n const previewKeys = revision.values?.[\"__metadata\"]?.[\"changed_fields\"];\n return <div key={index} className=\"flex flex-cols gap-2 w-full\">\n <EntityHistoryEntry size={\"large\"}\n entity={revision}\n collection={collection}\n previewKeys={previewKeys}\n actions={\n <Tooltip title={\"Revert to this version\"}\n className={\"m-2 grow-0 self-start\"}>\n <IconButton\n onClick={() => {\n if (dirty) {\n snackbarController.open({\n message: \"Please save or discard your changes before reverting\",\n type: \"warning\"\n });\n } else {\n setRevertVersion(revision);\n }\n }}>\n <HistoryIcon/>\n </IconButton>\n </Tooltip>}\n />\n </div>\n })}\n\n {/* Load more sentinel element */}\n {revisions.length > 0 && (\n <div\n ref={loadMoreRef}\n className=\"py-4 text-center\"\n >\n {isLoading && <Label>Loading more...</Label>}\n {!hasMore && revisions.length > PAGE_SIZE && <Label>No more history available</Label>}\n </div>\n )}\n </div>\n\n <ConfirmationDialog open={Boolean(revertVersion)}\n onAccept={function (): void {\n if (!revertVersion) return;\n doRevert(revertVersion);\n }}\n onCancel={function (): void {\n setRevertVersion(undefined);\n }}\n title={<Typography variant={\"subtitle2\"}>Revert data to this version?</Typography>}/>\n </div>\n}\n","import { EntityCallbacks } from \"@firecms/core\";\nimport equal from \"react-fast-compare\"\n\nexport const entityHistoryCallbacks: EntityCallbacks = {\n onSaveSuccess: async (props) => {\n\n const changedFields = props.previousValues ? findChangedFields(props.previousValues, props.values) : null;\n const uid = props.context.authController.user?.uid;\n props.context.dataSource.saveEntity({\n path: props.path + \"/\" + props.entityId + \"/__history\",\n values: {\n ...props.values,\n __metadata: {\n changed_fields: changedFields,\n updated_on: new Date(),\n updated_by: uid,\n }\n },\n status: \"new\"\n }).then(() => {\n console.debug(\"History saved for\", props.path, props.entityId);\n });\n }\n}\n\nfunction findChangedFields<M extends object>(oldValues: M, newValues: M, prefix: string = \"\"): string[] {\n const changedFields: string[] = [];\n\n // Handle null/undefined cases\n if (equal(oldValues, newValues)) return changedFields;\n if (!oldValues || !newValues) return [prefix || \".\"];\n\n // Get all unique keys from both objects\n const allKeys = new Set([\n ...Object.keys(oldValues),\n ...Object.keys(newValues)\n ]);\n\n for (const key of allKeys) {\n const oldValue = oldValues[key as keyof M];\n const newValue = newValues[key as keyof M];\n const currentPath = prefix ? `${prefix}.${key}` : key;\n\n // If key exists only in one object\n if ((key in oldValues) !== (key in newValues)) {\n changedFields.push(currentPath);\n continue;\n }\n\n // If values are identical (deep equality)\n if (equal(oldValue, newValue)) continue;\n\n // Handle arrays\n if (Array.isArray(oldValue) && Array.isArray(newValue)) {\n if (oldValue.length !== newValue.length) {\n changedFields.push(currentPath);\n } else {\n // Check if any array element changed\n for (let i = 0; i < oldValue.length; i++) {\n if (\n typeof oldValue[i] === \"object\" && oldValue[i] !== null &&\n typeof newValue[i] === \"object\" && newValue[i] !== null\n ) {\n const nestedChanges = findChangedFields(\n oldValue[i] as object,\n newValue[i] as object,\n `${currentPath}[${i}]`\n );\n if (nestedChanges.length > 0) {\n changedFields.push(currentPath);\n break;\n }\n } else if (!equal(oldValue[i], newValue[i])) {\n changedFields.push(currentPath);\n break;\n }\n }\n }\n }\n // Handle nested objects\n else if (\n typeof oldValue === \"object\" && oldValue !== null &&\n typeof newValue === \"object\" && newValue !== null\n ) {\n const nestedChanges = findChangedFields(\n oldValue as object,\n newValue as object,\n currentPath\n );\n changedFields.push(...nestedChanges);\n }\n // Handle primitives\n else {\n changedFields.push(currentPath);\n }\n }\n\n return changedFields;\n}\n","import { useCallback, useMemo } from \"react\";\nimport { EntityCollection, FireCMSPlugin, mergeCallbacks, User } from \"@firecms/core\";\nimport { EntityHistoryView } from \"./components/EntityHistoryView\";\nimport { HistoryIcon } from \"@firecms/ui\";\nimport { entityHistoryCallbacks } from \"./entity_history_callbacks\";\nimport { HistoryControllerProvider } from \"./HistoryControllerProvider\";\n\n/**\n * This plugin adds a history view to the entity side panel.\n */\nexport function useEntityHistoryPlugin(props?: EntityHistoryPluginProps): FireCMSPlugin<any, any, any, EntityHistoryPluginProps> {\n\n const { defaultEnabled = false } = props ?? {};\n\n const modifyCollection = useCallback((collection: EntityCollection) => {\n if (collection.history === true || defaultEnabled) {\n return {\n ...collection,\n history: true,\n entityViews: [\n ...(collection.entityViews ?? []),\n {\n key: \"__history\",\n name: \"History\",\n tabComponent: <HistoryIcon size={\"small\"}/>,\n Builder: EntityHistoryView,\n position: \"start\"\n }\n ],\n callbacks: mergeCallbacks(collection.callbacks, entityHistoryCallbacks)\n } satisfies EntityCollection;\n }\n return collection;\n }, []);\n\n return useMemo(() => ({\n key: \"entity_history\",\n provider: {\n Component: HistoryControllerProvider,\n props: {\n getUser: props?.getUser\n }\n },\n collection: {\n modifyCollection\n }\n } satisfies FireCMSPlugin), [props]);\n}\n\nexport type EntityHistoryPluginProps = {\n /**\n * If true, the history view will be enabled to all collections by default.\n * Each collection can override this value by setting the `history` property.\n */\n defaultEnabled?: boolean;\n\n /**\n * Function to get the user object from the uid.\n * @param uid\n */\n getUser?: (uid: string) => User | null;\n}\n"],"names":["HistoryControllerContext","React","createContext","useHistoryController","useContext","HistoryControllerProvider","memo","t0","$","_c","children","getUser","t1","t2","equal","UserChip","user","email","uid","displayName","photoURL","jsx","t3","t4","t5","jsxs","Chip","t6","Tooltip","EntityHistoryEntry","actions","disabled","hover","collection","collectionProp","previewKeys","onClick","size","entity","authController","useAuthController","customizationController","useCustomizationController","navigationController","useNavigationController","sideEntityController","useSideEntityController","getCollection","path","updatedOn","values","Error","updatedBy","resolvedCollection","useMemo","resolveCollection","propertyConfigs","Typography","toLocaleString","cls","defaultBorderMixin","IconButton","e","open","entityId","id","allowFullScreen","subcollections","undefined","entityViews","permissions","create","delete","edit","read","updateUrl","KeyboardTabIcon","map","key","childProperty","getPropertyInPath","properties","valueInPath","getValueInPath","PropertyPreview","SkeletonPropertyComponent","EntityHistoryView","formContext","snackbarController","useSnackbarController","dirty","formex","dataSource","useDataSource","pathAndId","revertVersion","setRevertVersion","useState","Symbol","for","revisions","setRevisions","isLoading","setIsLoading","hasMore","setHasMore","limit","setLimit","containerRef","useRef","observerRef","loadMoreRef","listener","listenCollection","order","orderBy","startAfter","onUpdate","entities","length","onError","error","useEffect","currentContainer","current","currentLoadMore","disconnect","options","root","rootMargin","threshold","handleObserver","entries","target","isIntersecting","prev","observer","IntersectionObserver","observe","Label","doRevert","revertVersion_0","revertValues","__metadata","reverted","updated_on","Date","updated_by","saveEntity","status","then","resetForm","message","type","catch","error_0","t7","t8","t9","Fragment","t10","t11","revision","index","changed_fields","HistoryIcon","t12","t13","Boolean","t14","t15","t16","t17","ConfirmationDialog","t18","entityHistoryCallbacks","onSaveSuccess","props","changedFields","previousValues","findChangedFields","context","console","debug","oldValues","newValues","prefix","allKeys","Set","Object","keys","oldValue","newValue","currentPath","push","Array","isArray","i","nestedChanges","useEntityHistoryPlugin","defaultEnabled","modifyCollection","useCallback","history","name","tabComponent","Builder","position","callbacks","mergeCallbacks","provider","Component"],"mappings":"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"}
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/HistoryControllerProvider.tsx","../src/components/UserChip.tsx","../src/components/EntityHistoryEntry.tsx","../src/components/EntityHistoryView.tsx","../src/entity_history_callbacks.ts","../src/useEntityHistoryPlugin.tsx"],"sourcesContent":["import React, { PropsWithChildren, useContext } from \"react\";\nimport equal from \"react-fast-compare\"\n\nimport { User } from \"@firecms/core\";\n\nexport type HistoryConfigController = {\n /**\n * Function to get a user by uid.\n * @param uid\n */\n getUser?: (uid: string) => User | null;\n}\n\nexport const HistoryControllerContext = React.createContext<HistoryConfigController>({} as any);\nexport const useHistoryController = (): HistoryConfigController => useContext(HistoryControllerContext);\n\n\nexport interface HistoryControllerProviderProps {\n\n getUser?: (uid: string) => User | null;\n\n}\n\nexport const HistoryControllerProvider = React.memo(\n function HistoryControllerProvider({\n children,\n getUser,\n }: PropsWithChildren<HistoryControllerProviderProps>) {\n\n return (\n <HistoryControllerContext.Provider\n value={{\n getUser,\n }}>\n\n {children}\n\n </HistoryControllerContext.Provider>\n );\n }, equal);\n","import { User } from \"@firecms/core\";\nimport { Chip, Tooltip } from \"@firecms/ui\";\n\nexport function UserChip({ user }: { user: User }) {\n return (\n <Tooltip title={user.email ?? user.uid}>\n <Chip size={\"small\"} className={\"flex items-center\"}>\n {user.photoURL && <img\n className={\"rounded-full w-6 h-6 mr-2\"}\n src={user.photoURL} alt={user.displayName ?? \"User picture\"}/>}\n <span>{user.displayName ?? user.email ?? user.uid}</span>\n </Chip>\n </Tooltip>\n );\n}\n","import * as React from \"react\";\n\nimport { Chip, cls, defaultBorderMixin, IconButton, KeyboardTabIcon, Tooltip, Typography } from \"@firecms/ui\";\nimport {\n Entity,\n EntityCollection,\n getPropertyInPath,\n getValueInPath,\n PreviewSize,\n PropertyPreview,\n resolveCollection,\n ResolvedProperty,\n SkeletonPropertyComponent,\n useAuthController,\n useCustomizationController,\n useNavigationController,\n useSideEntityController\n} from \"@firecms/core\";\nimport { useHistoryController } from \"../HistoryControllerProvider\";\nimport { UserChip } from \"./UserChip\";\n\nexport type EntityPreviewProps = {\n size: PreviewSize,\n actions?: React.ReactNode,\n collection?: EntityCollection,\n hover?: boolean;\n previewKeys?: string[],\n disabled?: boolean,\n entity: Entity<any>,\n onClick?: (e: React.SyntheticEvent) => void;\n};\n\n/**\n * This view is used to display a preview of an entity.\n * It is used by default in reference fields and whenever a reference is displayed.\n */\nexport function EntityHistoryEntry({\n actions,\n disabled,\n hover,\n collection: collectionProp,\n previewKeys,\n onClick,\n size,\n entity\n }: EntityPreviewProps) {\n\n const authController = useAuthController();\n const customizationController = useCustomizationController();\n\n const navigationController = useNavigationController();\n const sideEntityController = useSideEntityController();\n\n const collection = collectionProp ?? navigationController.getCollection(entity.path);\n const updatedOn = entity.values?.[\"__metadata\"]?.[\"updated_on\"];\n if (!collection) {\n throw Error(`Couldn't find the corresponding collection view for the path: ${entity.path}`);\n }\n\n const updatedBy = entity.values?.[\"__metadata\"]?.[\"updated_by\"];\n const { getUser } = useHistoryController();\n const user = getUser?.(updatedBy);\n\n const resolvedCollection = React.useMemo(() => resolveCollection({\n collection,\n path: entity.path,\n values: entity.values,\n propertyConfigs: customizationController.propertyConfigs,\n authController\n }), [collection]);\n\n return <div className={\"w-full flex flex-col gap-2 mt-4\"}>\n <div className={\"ml-4 flex items-center gap-4\"}>\n <Typography variant={\"body2\"} color={\"secondary\"}>{updatedOn.toLocaleString()}</Typography>\n {!user && updatedBy && <Chip size={\"small\"}>{updatedBy}</Chip>}\n {user && <UserChip user={user}/>}\n </div>\n <div\n className={cls(\n \"bg-white dark:bg-surface-900\",\n \"min-h-[42px]\",\n \"w-full\",\n \"items-center\",\n hover ? \"hover:bg-surface-accent-50 dark:hover:bg-surface-800 group-hover:bg-surface-accent-50 dark:group-hover:bg-surface-800\" : \"\",\n size === \"small\" ? \"p-1\" : \"px-2 py-1\",\n \"flex border rounded-lg\",\n onClick ? \"cursor-pointer\" : \"\",\n defaultBorderMixin\n )}>\n\n\n {actions}\n\n {entity &&\n <Tooltip title={\"See details for this revision\"}\n className={\"my-2 grow-0 shrink-0 self-start\"}>\n <IconButton\n color={\"inherit\"}\n className={\"\"}\n onClick={(e) => {\n\n sideEntityController.open({\n entityId: entity.id,\n path: entity.path,\n allowFullScreen: false,\n collection: {\n ...collection,\n subcollections: undefined,\n entityViews: undefined,\n permissions: {\n create: false,\n delete: false,\n edit: false,\n read: true\n }\n },\n updateUrl: true\n });\n }}>\n <KeyboardTabIcon/>\n </IconButton>\n </Tooltip>}\n\n <div className={\"flex flex-col grow w-full m-1 shrink min-w-0\"}>\n\n {previewKeys && previewKeys.map((key) => {\n const childProperty = getPropertyInPath(resolvedCollection.properties, key);\n\n const valueInPath = getValueInPath(entity.values, key);\n const element = childProperty ? (entity\n ? <PropertyPreview\n propertyKey={key as string}\n value={valueInPath}\n property={childProperty as ResolvedProperty}\n size={\"small\"}/>\n : <SkeletonPropertyComponent\n property={childProperty as ResolvedProperty}\n size={\"small\"}/>) :\n <Typography variant={\"body2\"}>\n {typeof valueInPath === \"string\" ? valueInPath : JSON.stringify(valueInPath)}\n </Typography>;\n return (\n <div key={\"ref_prev_\" + key}\n className=\"flex w-full my-1 items-center\">\n <Typography variant={\"caption\"}\n color={\"secondary\"}\n className=\"min-w-[140px] md:min-w-[200px] w-1/5 pr-8 overflow-hidden text-ellipsis text-right\">\n {key}\n </Typography>\n <div className=\"w-4/5\">\n {\n element\n }\n </div>\n </div>\n );\n })}\n\n </div>\n\n </div>\n </div>\n}\n\n","import { useEffect, useRef, useState } from \"react\";\nimport {\n ConfirmationDialog,\n Entity,\n EntityCustomViewParams,\n useAuthController,\n useDataSource,\n useSnackbarController\n} from \"@firecms/core\";\nimport { cls, HistoryIcon, IconButton, Label, Tooltip, Typography } from \"@firecms/ui\";\nimport { EntityHistoryEntry } from \"./EntityHistoryEntry\";\n\nexport function EntityHistoryView({\n entity,\n collection,\n formContext\n }: EntityCustomViewParams) {\n\n const authController = useAuthController();\n const snackbarController = useSnackbarController();\n const dirty = formContext?.formex.dirty;\n\n const dataSource = useDataSource();\n const pathAndId = entity ? entity?.path + \"/\" + entity?.id : undefined;\n\n const [revertVersionDialog, setRevertVersionDialog] = useState<Entity | undefined>(undefined);\n const [revisions, setRevisions] = useState<Entity[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n\n const PAGE_SIZE = 5;\n const [limit, setLimit] = useState(PAGE_SIZE);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const observerRef = useRef<IntersectionObserver | null>(null);\n const loadMoreRef = useRef<HTMLDivElement>(null);\n\n // Load revisions with the current limit\n useEffect(() => {\n if (!pathAndId) return;\n\n setIsLoading(true); // Set loading true when fetching starts\n const listener = dataSource.listenCollection?.({\n path: pathAndId + \"/__history\",\n order: \"desc\",\n orderBy: \"__metadata.updated_on\",\n limit: limit,\n startAfter: undefined,\n onUpdate: (entities) => {\n setRevisions(entities);\n setHasMore(entities.length === limit && entities.length >= PAGE_SIZE); // Ensure we fetched a full page to consider hasMore\n setIsLoading(false);\n },\n onError: (error) => {\n console.error(\"Error fetching history:\", error);\n setIsLoading(false);\n setHasMore(false); // Stop trying if there's an error\n }\n });\n return () => {\n if (typeof listener === \"function\") {\n listener();\n }\n };\n }, [pathAndId, limit, dataSource]);\n\n // Setup intersection observer for infinite scroll\n useEffect(() => {\n const currentContainer = containerRef.current;\n const currentLoadMore = loadMoreRef.current;\n\n // Conditions for active observation\n if (!currentContainer || !currentLoadMore || !hasMore || isLoading) {\n // If we shouldn't be observing, ensure any existing observer is disconnected\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n return;\n }\n\n // Options for the IntersectionObserver\n const options = {\n root: currentContainer,\n rootMargin: \"0px 0px 200px 0px\", // Trigger 200px before the sentinel is at the bottom edge\n threshold: 0.01 // Trigger if even a small part is visible within the rootMargin\n };\n\n // The callback for when the sentinel's intersection state changes\n const handleObserver = (entries: IntersectionObserverEntry[]) => {\n const target = entries[0];\n if (target.isIntersecting && hasMore && !isLoading) {\n // No need to setIsLoading(true) here, it's done in the data fetching useEffect\n setLimit(prev => prev + PAGE_SIZE);\n }\n };\n\n const observer = new IntersectionObserver(handleObserver, options);\n observer.observe(currentLoadMore);\n observerRef.current = observer; // Store the new observer\n\n // Cleanup function for this effect instance\n return () => {\n observer.disconnect(); // Disconnect the observer created in *this* effect run\n if (observerRef.current === observer) {\n observerRef.current = null;\n }\n };\n // Re-run if hasMore, isLoading changes, or if revisions.length changes (which might make loadMoreRef available/unavailable)\n }, [hasMore, isLoading, revisions.length]);\n\n if (!entity) {\n return <div className=\"flex items-center justify-center h-full\">\n <Label>History is only available for existing entities</Label>\n </div>\n }\n\n function doRevert(revertVersion: Entity) {\n if (!entity) {\n throw new Error(\"No entity to revert\");\n }\n const revertValues = {\n ...revertVersion.values,\n __metadata: {\n ...revertVersion.values?.[\"__metadata\"],\n reverted: true,\n updated_on: new Date(),\n updated_by: authController.user?.uid ?? null,\n }\n };\n const saveReverted = dataSource.saveEntity({\n path: entity.path,\n entityId: entity.id,\n values: revertValues,\n collection,\n status: \"existing\"\n });\n const saveRevertedHistory = dataSource.saveEntity({\n path: revertVersion.path,\n entityId: revertVersion.id,\n values: revertValues,\n collection,\n status: \"existing\"\n });\n return Promise.all([saveReverted, saveRevertedHistory])\n .then(() => {\n formContext.formex.resetForm({\n values: revertVersion.values\n });\n setRevertVersionDialog(undefined);\n snackbarController.open({\n message: \"Reverted version\",\n type: \"info\"\n });\n }\n ).catch((error) => {\n console.error(\"Error reverting entity:\", error);\n snackbarController.open({\n message: \"Error reverting entity\",\n type: \"error\"\n });\n });\n\n }\n\n return <div\n ref={containerRef}\n className={cls(\"relative flex-1 h-full overflow-auto w-full flex flex-col gap-4 p-8\")}>\n <div className=\"flex flex-col gap-2 max-w-6xl mx-auto w-full\">\n\n <Typography variant={\"h5\"} className={\"mt-24 ml-4\"}>\n History\n </Typography>\n\n {revisions.length === 0 && <>\n <Label className={\"ml-4 mt-8\"}>\n No history available\n </Label>\n <Typography variant={\"caption\"} className={\"ml-4\"}>\n When you save an entity, a new version is created and stored in the history.\n </Typography>\n </>}\n\n {revisions.map((revision, index) => {\n const previewKeys = revision.values?.[\"__metadata\"]?.[\"changed_fields\"];\n return <div key={index} className=\"flex flex-cols gap-2 w-full\">\n <EntityHistoryEntry size={\"large\"}\n entity={revision}\n collection={collection}\n previewKeys={previewKeys}\n actions={\n <Tooltip title={\"Revert to this version\"}\n className={\"m-2 grow-0 self-start\"}>\n <IconButton\n onClick={() => {\n if (dirty) {\n snackbarController.open({\n message: \"Please save or discard your changes before reverting\",\n type: \"warning\"\n });\n } else {\n setRevertVersionDialog(revision);\n }\n }}>\n <HistoryIcon/>\n </IconButton>\n </Tooltip>}\n />\n </div>\n })}\n\n {/* Load more sentinel element */}\n {revisions.length > 0 && (\n <div\n ref={loadMoreRef}\n className=\"py-4 text-center\"\n >\n {isLoading && <Label>Loading more...</Label>}\n {!hasMore && revisions.length > PAGE_SIZE && <Label>No more history available</Label>}\n </div>\n )}\n </div>\n\n <ConfirmationDialog open={Boolean(revertVersionDialog)}\n onAccept={function (): void {\n if (!revertVersionDialog) return;\n doRevert(revertVersionDialog);\n }}\n onCancel={function (): void {\n setRevertVersionDialog(undefined);\n }}\n title={<Typography variant={\"subtitle2\"}>Revert data to this version?</Typography>}/>\n </div>\n}\n","import { EntityCallbacks } from \"@firecms/core\";\nimport equal from \"react-fast-compare\"\n\nexport const entityHistoryCallbacks: EntityCallbacks = {\n onSaveSuccess: async (props) => {\n\n const changedFields = props.previousValues ? findChangedFields(props.previousValues, props.values) : null;\n const uid = props.context.authController.user?.uid;\n props.context.dataSource.saveEntity({\n path: props.path + \"/\" + props.entityId + \"/__history\",\n values: {\n ...props.values,\n __metadata: {\n changed_fields: changedFields,\n updated_on: new Date(),\n updated_by: uid,\n }\n },\n status: \"new\"\n }).then(() => {\n console.debug(\"History saved for\", props.path, props.entityId);\n });\n }\n}\n\nfunction findChangedFields<M extends object>(oldValues: M, newValues: M, prefix: string = \"\"): string[] {\n const changedFields: string[] = [];\n\n // Handle null/undefined cases\n if (equal(oldValues, newValues)) return changedFields;\n if (!oldValues || !newValues) return [prefix || \".\"];\n\n // Get all unique keys from both objects\n const allKeys = new Set([\n ...Object.keys(oldValues),\n ...Object.keys(newValues)\n ]);\n\n for (const key of allKeys) {\n const oldValue = oldValues[key as keyof M];\n const newValue = newValues[key as keyof M];\n const currentPath = prefix ? `${prefix}.${key}` : key;\n\n // If key exists only in one object\n if ((key in oldValues) !== (key in newValues)) {\n changedFields.push(currentPath);\n continue;\n }\n\n // If values are identical (deep equality)\n if (equal(oldValue, newValue)) continue;\n\n // Handle arrays\n if (Array.isArray(oldValue) && Array.isArray(newValue)) {\n if (oldValue.length !== newValue.length) {\n changedFields.push(currentPath);\n } else {\n // Check if any array element changed\n for (let i = 0; i < oldValue.length; i++) {\n if (\n typeof oldValue[i] === \"object\" && oldValue[i] !== null &&\n typeof newValue[i] === \"object\" && newValue[i] !== null\n ) {\n const nestedChanges = findChangedFields(\n oldValue[i] as object,\n newValue[i] as object,\n `${currentPath}[${i}]`\n );\n if (nestedChanges.length > 0) {\n changedFields.push(currentPath);\n break;\n }\n } else if (!equal(oldValue[i], newValue[i])) {\n changedFields.push(currentPath);\n break;\n }\n }\n }\n }\n // Handle nested objects\n else if (\n typeof oldValue === \"object\" && oldValue !== null &&\n typeof newValue === \"object\" && newValue !== null\n ) {\n const nestedChanges = findChangedFields(\n oldValue as object,\n newValue as object,\n currentPath\n );\n changedFields.push(...nestedChanges);\n }\n // Handle primitives\n else {\n changedFields.push(currentPath);\n }\n }\n\n return changedFields;\n}\n","import { useCallback, useMemo } from \"react\";\nimport { EntityCollection, FireCMSPlugin, mergeCallbacks, User } from \"@firecms/core\";\nimport { EntityHistoryView } from \"./components/EntityHistoryView\";\nimport { HistoryIcon } from \"@firecms/ui\";\nimport { entityHistoryCallbacks } from \"./entity_history_callbacks\";\nimport { HistoryControllerProvider } from \"./HistoryControllerProvider\";\n\n/**\n * This plugin adds a history view to the entity side panel.\n */\nexport function useEntityHistoryPlugin(props?: EntityHistoryPluginProps): FireCMSPlugin<any, any, any, EntityHistoryPluginProps> {\n\n const { defaultEnabled = false } = props ?? {};\n\n const modifyCollection = useCallback((collection: EntityCollection) => {\n if (collection.history === true || (defaultEnabled && collection.history !== false)) {\n return {\n ...collection,\n entityViews: [\n ...(collection.entityViews ?? []),\n {\n key: \"__history\",\n name: \"History\",\n tabComponent: <HistoryIcon size={\"small\"}/>,\n Builder: EntityHistoryView,\n position: \"start\"\n }\n ],\n callbacks: mergeCallbacks(collection.callbacks, entityHistoryCallbacks)\n } satisfies EntityCollection;\n }\n return collection;\n }, []);\n\n return useMemo(() => ({\n key: \"entity_history\",\n provider: {\n Component: HistoryControllerProvider,\n props: {\n getUser: props?.getUser\n }\n },\n collection: {\n modifyCollection\n }\n } satisfies FireCMSPlugin), [props]);\n}\n\nexport type EntityHistoryPluginProps = {\n /**\n * If true, the history view will be enabled to all collections by default.\n * Each collection can override this value by setting the `history` property.\n */\n defaultEnabled?: boolean;\n\n /**\n * Function to get the user object from the uid.\n * @param uid\n */\n getUser?: (uid: string) => User | null;\n}\n"],"names":["HistoryControllerContext","React","createContext","useHistoryController","useContext","HistoryControllerProvider","memo","t0","$","_c","children","getUser","t1","t2","equal","UserChip","user","email","uid","displayName","photoURL","jsx","t3","t4","t5","jsxs","Chip","t6","Tooltip","EntityHistoryEntry","actions","disabled","hover","collection","collectionProp","previewKeys","onClick","size","entity","authController","useAuthController","customizationController","useCustomizationController","navigationController","useNavigationController","sideEntityController","useSideEntityController","getCollection","path","updatedOn","values","Error","updatedBy","resolvedCollection","useMemo","resolveCollection","propertyConfigs","Typography","toLocaleString","cls","defaultBorderMixin","IconButton","e","open","entityId","id","allowFullScreen","subcollections","undefined","entityViews","permissions","create","delete","edit","read","updateUrl","KeyboardTabIcon","map","key","childProperty","getPropertyInPath","properties","valueInPath","getValueInPath","element","PropertyPreview","SkeletonPropertyComponent","JSON","stringify","EntityHistoryView","formContext","snackbarController","useSnackbarController","dirty","formex","dataSource","useDataSource","pathAndId","revertVersionDialog","setRevertVersionDialog","useState","Symbol","for","revisions","setRevisions","isLoading","setIsLoading","hasMore","setHasMore","limit","setLimit","containerRef","useRef","observerRef","loadMoreRef","listener","listenCollection","order","orderBy","startAfter","onUpdate","entities","length","onError","error","useEffect","currentContainer","current","currentLoadMore","disconnect","options","root","rootMargin","threshold","handleObserver","entries","target","isIntersecting","prev","observer","IntersectionObserver","observe","Label","doRevert","revertVersion","revertValues","__metadata","reverted","updated_on","Date","updated_by","saveReverted","saveEntity","status","saveRevertedHistory","Promise","all","then","resetForm","message","type","catch","error_0","t7","t8","t9","Fragment","t10","t11","revision","index","changed_fields","HistoryIcon","t12","t13","Boolean","t14","t15","t16","t17","ConfirmationDialog","t18","entityHistoryCallbacks","onSaveSuccess","props","changedFields","previousValues","findChangedFields","context","console","debug","oldValues","newValues","prefix","allKeys","Set","Object","keys","oldValue","newValue","currentPath","push","Array","isArray","i","nestedChanges","useEntityHistoryPlugin","defaultEnabled","modifyCollection","useCallback","history","name","tabComponent","Builder","position","callbacks","mergeCallbacks","provider","Component"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAaO,QAAMA,2BAA2BC,MAAMC,cAAuC,CAAS,CAAA;AACjFC,QAAAA,uBAAuBA,MAAA;AAAA,WAA+BC,MAAAA,WAAAJ,wBAAmC;AAAA,EAAC;AAS1FK,QAAAA,4BAA4BJ,MAAMK,KAC3C,SAAAD,2BAAAE,IAAA;AAAAC,UAAAA,IAAAC,uBAAA,CAAA;AAAmC,UAAA;AAAA,MAAAC;AAAAA,MAAAC;AAAAA,IAAAA,IAAAJ;AAGoDK,QAAAA;AAAAJ,QAAAA,SAAAG,SAAA;AAIpE,WAAA;AAAA,QAAAA;AAAAA,MAAA;AAENH,aAAAG;AAAAH,aAAAI;AAAAA,IAAAA,OAAA;AAAAA,WAAAJ,EAAA,CAAA;AAAA,IAAA;AAAAK,QAAAA;AAAA,QAAAL,EAAAE,CAAAA,MAAAA,YAAAF,SAAAI,IAAA;AAHLC,0CAAA,yBAAA,UAAA,EACW,OAAAD,IAIC,UAEZ;AAAoCJ,aAAAE;AAAAF,aAAAI;AAAAJ,aAAAK;AAAAA,IAAAA,OAAA;AAAAA,WAAAL,EAAA,CAAA;AAAA,IAAA;AAPpCK,WAAAA;AAAAA,EAOoC,GAEzCC,KAAK;ACpCL,WAAAC,SAAAR,IAAA;AAAAC,UAAAA,IAAAC,uBAAA,EAAA;AAAkB,UAAA;AAAA,MAAAO;AAAAA,IAAAA,IAAAT;AAEDK,UAAAA,KAAAI,KAAIC,SAAUD,KAAIE;AAAIL,QAAAA;AAAAL,QAAAA,EAAAQ,CAAAA,MAAAA,KAAAG,eAAAX,EAAA,CAAA,MAAAQ,KAAAI,UAAA;AAE7BP,WAAAG,KAAII,YAAaC,2BAAA,IAAA,OAAA,EACH,WAAA,6BACN,KAAAL,KAAII,UAAgB,KAAAJ,KAAIG,eAAgB,gBAAiB;AAAA,QAAA,CAAA,IAAAH,KAAAG;AAAA,QAAA,CAAA,IAAAH,KAAAI;AAAAZ,aAAAK;AAAAA,IAAAA,OAAA;AAAAA,WAAAL,EAAA,CAAA;AAAA,IAAA;AAC3D,UAAAc,KAAAN,KAAIG,eAAgBH,KAAIC,SAAUD,KAAIE;AAAIK,QAAAA;AAAAf,QAAAA,SAAAc,IAAA;oDAA1CA,UAA2C,GAAA,CAAA;AAAOd,aAAAc;AAAAd,aAAAe;AAAAA,IAAAA,OAAA;AAAAA,WAAAf,EAAA,CAAA;AAAA,IAAA;AAAAgB,QAAAA;AAAA,QAAAhB,EAAAK,CAAAA,MAAAA,MAAAL,SAAAe,IAAA;AAJ7DC,WAACC,2BAAAA,KAAAC,GAAAA,MAAA,EAAW,MAAA,SAAoB,WAAA,qBAC3Bb,UAAAA;AAAAA,QAAAA;AAAAA,QAGDU;AAAAA,MAAAA,GACJ;AAAOf,aAAAK;AAAAL,aAAAe;AAAAf,aAAAgB;AAAAA,IAAAA,OAAA;AAAAA,WAAAhB,EAAA,CAAA;AAAA,IAAA;AAAAmB,QAAAA;AAAA,QAAAnB,EAAAI,CAAAA,MAAAA,MAAAJ,SAAAgB,IAAA;AANXG,WAACN,2BAAA,IAAAO,YAAA,EAAe,OAAAhB,IACZY,UAMJ,IAAA;AAAUhB,aAAAI;AAAAJ,aAAAgB;AAAAhB,cAAAmB;AAAAA,IAAAA,OAAA;AAAAA,WAAAnB,EAAA,EAAA;AAAA,IAAA;AAPVmB,WAAAA;AAAAA,EAOU;ACwBX,WAASE,mBAAmB;AAAA,IACIC;AAAAA,IACAC;AAAAA,IACAC;AAAAA,IACAC,YAAYC;AAAAA,IACZC;AAAAA,IACAC;AAAAA,IACAC;AAAAA,IACAC;AAAAA,EACgB,GAAG;AAEtD,UAAMC,iBAAiBC,KAAAA,kBAAkB;AACzC,UAAMC,0BAA0BC,KAAAA,2BAA2B;AAE3D,UAAMC,uBAAuBC,KAAAA,wBAAwB;AACrD,UAAMC,uBAAuBC,KAAAA,wBAAwB;AAErD,UAAMb,aAAaC,kBAAkBS,qBAAqBI,cAAcT,OAAOU,IAAI;AACnF,UAAMC,YAAYX,OAAOY,SAAS,YAAY,IAAI,YAAY;AAC9D,QAAI,CAACjB,YAAY;AACb,YAAMkB,MAAM,iEAAiEb,OAAOU,IAAI,EAAE;AAAA,IAAA;AAG9F,UAAMI,YAAYd,OAAOY,SAAS,YAAY,IAAI,YAAY;AACxD,UAAA;AAAA,MAAEvC;AAAAA,QAAYR,qBAAqB;AACnCa,UAAAA,OAAOL,UAAUyC,SAAS;AAEhC,UAAMC,qBAAqBpD,iBAAMqD,QAAQ,MAAMC,KAAAA,kBAAkB;AAAA,MAC7DtB;AAAAA,MACAe,MAAMV,OAAOU;AAAAA,MACbE,QAAQZ,OAAOY;AAAAA,MACfM,iBAAiBf,wBAAwBe;AAAAA,MACzCjB;AAAAA,IAAAA,CACH,GAAG,CAACN,UAAU,CAAC;AAET,WAAAR,2BAAA,KAAC,OAAI,EAAA,WAAW,mCACnB,UAAA;AAAA,MAACA,2BAAAA,KAAA,OAAA,EAAI,WAAW,gCACZ,UAAA;AAAA,QAAAJ,2BAAAA,IAACoC,iBAAW,SAAS,SAAS,OAAO,aAAcR,UAAAA,UAAUS,kBAAiB;AAAA,QAC7E,CAAC1C,QAAQoC,4CAAc1B,GAAK,MAAA,EAAA,MAAM,SAAU0B,UAAU,WAAA;AAAA,QACtDpC,QAASK,2BAAA,IAAA,UAAA,EAAS,KAAa,CAAA;AAAA,MAAA,GACpC;AAAA,MACAI,gCAAC,SACG,WAAWkC,GAAAA,IACP,gCACA,gBACA,UACA,gBACA3B,QAAQ,0HAA0H,IAClIK,SAAS,UAAU,QAAQ,aAC3B,0BACAD,UAAU,mBAAmB,IAC7BwB,qBACJ,GAGC9B,UAAAA;AAAAA,QAAAA;AAAAA,QAEAQ,UACGjB,2BAAA,IAACO,YAAQ,EAAA,OAAO,iCACP,WAAW,mCAChB,UAACP,2BAAA,IAAAwC,GAAA,YAAA,EACG,OAAO,WACP,WAAW,IACX,SAAUC,CAAM,MAAA;AAEZjB,+BAAqBkB,KAAK;AAAA,YACtBC,UAAU1B,OAAO2B;AAAAA,YACjBjB,MAAMV,OAAOU;AAAAA,YACbkB,iBAAiB;AAAA,YACjBjC,YAAY;AAAA,cACR,GAAGA;AAAAA,cACHkC,gBAAgBC;AAAAA,cAChBC,aAAaD;AAAAA,cACbE,aAAa;AAAA,gBACTC,QAAQ;AAAA,gBACRC,QAAQ;AAAA,gBACRC,MAAM;AAAA,gBACNC,MAAM;AAAA,cAAA;AAAA,YAEd;AAAA,YACAC,WAAW;AAAA,UAAA,CACd;AAAA,QAAA,GAEL,UAAAtD,2BAAAA,IAACuD,GAAAA,iBAAe,CAAA,CAAA,EAAA,CACpB,EACJ,CAAA;AAAA,uCAEH,OAAI,EAAA,WAAW,gDAEXzC,UAAeA,eAAAA,YAAY0C,IAAKC,CAAQ,QAAA;AACrC,gBAAMC,gBAAgBC,KAAAA,kBAAkB3B,mBAAmB4B,YAAYH,GAAG;AAE1E,gBAAMI,cAAcC,KAAAA,eAAe7C,OAAOY,QAAQ4B,GAAG;AACrD,gBAAMM,UAAUL,gBAAiBzC,SACvBjB,2BAAA,IAACgE,wBACC,aAAaP,KACb,OAAOI,aACP,UAAUH,eACV,MAAM,SAAQ,IACf1D,2BAAA,IAAAiE,gCAAA,EACC,UAAUP,eACV,MAAM,QAAU,CAAA,IACxB1D,2BAAAA,IAACoC,GAAAA,cAAW,SAAS,SAChB,UAAOyB,OAAAA,gBAAgB,WAAWA,cAAcK,KAAKC,UAAUN,WAAW,GAC/E;AAEA,iBAAAzD,2BAAA,KAAC,OACI,EAAA,WAAU,iCACX,UAAA;AAAA,YAAAJ,2BAAAA,IAACoC,iBAAW,SAAS,WACT,OAAO,aACP,WAAU,sFACjBqB,UACL,IAAA,CAAA;AAAA,YACCzD,2BAAA,IAAA,OAAA,EAAI,WAAU,SAEP+D,UAER,QAAA,CAAA;AAAA,UAAA,EAAA,GAXM,cAAcN,GAYxB;AAAA,QAAA,CAEP,EAEL,CAAA;AAAA,MAAA,EAEJ,CAAA;AAAA,IAAA,GACJ;AAAA,EACJ;ACtJO,WAAAW,kBAAAlF,IAAA;AAAAC,UAAAA,IAAAC,uBAAA,EAAA;AAA2B,UAAA;AAAA,MAAA6B;AAAAA,MAAAL;AAAAA,MAAAyD;AAAAA,IAAAA,IAAAnF;AAM9B,UAAAgC,iBAAuBC,KAAAA,kBAAkB;AACzC,UAAAmD,qBAA2BC,KAAAA,sBAAsB;AACjDC,UAAAA,QAAcH,aAAWI,OAAAD;AAEzB,UAAAE,aAAmBC,KAAAA,cAAc;AACjC,UAAAC,YAAkB3D,SAASA,QAAMU,OAAS,MAAMV,QAAM2B,KAAIG;AAE1D,UAAA,CAAA8B,qBAAAC,sBAAA,IAAsDC,MAAAA,SAAAhC,MAAsC;AAAExD,QAAAA;AAAA,QAAAJ,EAAA,CAAA,MAAA6F,OAAAC,IAAA,2BAAA,GAAA;AACzC1F,WAAA,CAAA;AAAEJ,aAAAI;AAAAA,IAAAA,OAAA;AAAAA,WAAAJ,EAAA,CAAA;AAAA,IAAA;AAAvD,UAAA,CAAA+F,WAAAC,YAAA,IAAkCJ,MAAAA,SAAmBxF,EAAE;AACvD,UAAA,CAAA6F,WAAAC,YAAA,IAAkCN,MAAAA,cAAc;AAChD,UAAA,CAAAO,SAAAC,UAAA,IAA8BR,MAAAA,aAAa;AAG3C,UAAA,CAAAS,OAAAC,QAAA,IAA0BV,MAAAA,UAAkB;AAE5CW,UAAAA,eAAqBC,aAAA,IAA2B;AAChDC,UAAAA,cAAoBD,aAAA,IAAwC;AAC5DE,UAAAA,cAAoBF,aAAA,IAA2B;AAAEnG,QAAAA;AAAAS,QAAAA;AAAAd,QAAAA,EAAAuF,CAAAA,MAAAA,cAAAvF,SAAAqG,SAAArG,EAAA,CAAA,MAAAyF,WAAA;AAGvCpF,WAAAA,MAAA;AAAA,YAAA,CACDoF,WAAS;AAAA;AAAA,QAAA;AAEdS,yBAAiB;AACjBS,cAAAA,WAAiBpB,WAAUqB,mBAAA;AAAA,UAAApE,MACjBiD,YAAY;AAAA,UAAYoB,OACvB;AAAA,UAAMC,SACJ;AAAA,UAAuBT;AAAAA,UAAAU,YAAAnD;AAAAA,UAAAoD,UAAAC,CAAA,aAAA;AAI5BjB,yBAAaiB,QAAQ;AACrBb,uBAAWa,SAAQC,WAAYb,SAASY,SAAQC,UAAA,CAAoB;AACpEhB,8BAAkB;AAAA,UAAC;AAAA,UAAAiB,SAAAC,CAAA,UAAA;AAGnBA,oBAAAA,MAAc,2BAA2BA,KAAK;AAC9ClB,8BAAkB;AAClBE,4BAAgB;AAAA,UAAA;AAAA,QAAC,CAAA;AAEtB,eAAA,MAAA;AAEK,cAAA,OAAOO,aAAa,YAAU;AACrB,qBAAA;AAAA,UAAA;AAAA,QAAC;AAAA,MAAA;AAGlBlB,WAAAA,CAAAA,WAAWY,OAAOd,UAAU;AAACvF,aAAAuF;AAAAvF,aAAAqG;AAAArG,aAAAyF;AAAAzF,aAAAK;AAAAL,aAAAc;AAAAA,IAAAA,OAAA;AAAAT,WAAAL,EAAA,CAAA;AAAAc,WAAAd,EAAA,CAAA;AAAA,IAAA;AA1BjCqH,UAAAA,UAAUhH,IA0BPS,EAA8B;AAACC,QAAAA;AAAA,QAAAf,EAAAmG,CAAAA,MAAAA,WAAAnG,SAAAiG,WAAA;AAGxBlF,WAAAA,MAAA;AACN,cAAAuG,mBAAyBf,aAAYgB;AACrC,cAAAC,kBAAwBd,YAAWa;AAAS,YAGxC,CAACD,oBAAgB,CAAKE,mBAAoBrB,CAAAA,WAAWF,WAAS;AAAA,cAE1DQ,YAAWc,SAAA;AACXd,wBAAWc,QAAAE,WAAoB;AAC/BhB,wBAAWc,UAAA;AAAA,UAAA;AAAA;AAAA,QAAA;AAMnB,cAAAG,UAAA;AAAA,UAAAC,MACUL;AAAAA,UAAgBM,YACV;AAAA,UAAmBC,WAAA;AAAA,QAAA;AAKnC,cAAAC,iBAAAC,CAAA,YAAA;AACIC,gBAAAA,SAAeD,QAAO,CAAA;AAAI,cACtBC,OAAMC,kBAAmB9B,YAAYF,WAAS;AAEtCiC,qBAAAA,CAAAA,SAASA,QAAgB;AAAA,UAAA;AAAA,QAAC;AAI1C,cAAAC,WAAAC,IAAAA,qBAA0CN,gBAAgBJ,OAAO;AACjES,iBAAQE,QAASb,eAAe;AAChCf,oBAAWc,UAAWY;AAAQ,eAAA,MAAA;AAI1BA,mBAAQV,WAAY;AAChBhB,cAAAA,YAAWc,YAAaY,UAAQ;AAChC1B,wBAAWc,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAItBvH,aAAAmG;AAAAnG,aAAAiG;AAAAjG,aAAAe;AAAAA,IAAAA,OAAA;AAAAA,WAAAf,EAAA,CAAA;AAAA,IAAA;AAAAgB,QAAAA;AAAA,QAAAhB,EAAA,CAAA,MAAAmG,WAAAnG,EAAA,EAAA,MAAAiG,aAAAjG,EAAA,EAAA,MAAA+F,UAAAmB,QAAA;AAAElG,YAACmF,SAASF,WAAWF,UAASmB,MAAA;AAAQlH,aAAAmG;AAAAnG,cAAAiG;AAAA,QAAA,EAAA,IAAAF,UAAAmB;AAAAlH,cAAAgB;AAAAA,IAAAA,OAAA;AAAAA,WAAAhB,EAAA,EAAA;AAAA,IAAA;AA1CzCqH,UAAAA,UAAUtG,IA0CPC,EAAsC;AAAC,QAAA,CAErCc,QAAM;AAAAX,UAAAA;AAAA,UAAAnB,EAAA,EAAA,MAAA6F,OAAAC,IAAA,2BAAA,GAAA;AACA3E,6CAED,OAFgB,EAAA,WAAA,2CAClB,UAACN,2BAAA,IAAAyH,GAAA,OAAA,EAAM,6DAA+C,EAC1D,CAAA;AAAMtI,gBAAAmB;AAAAA,MAAAA,OAAA;AAAAA,cAAAnB,EAAA,EAAA;AAAA,MAAA;AAFCmB,aAAAA;AAAAA,IAAAA;AAEDA,QAAAA;AAAAnB,QAAAA,UAAA+B,kBAAA/B,EAAAyB,EAAAA,MAAAA,cAAAzB,EAAAuF,EAAAA,MAAAA,cAAAvF,EAAA,EAAA,MAAA8B,UAAA9B,UAAAkF,eAAAlF,EAAA,EAAA,MAAAmF,oBAAA;AAGV,WAAA,SAAAoD,UAAAC,eAAA;AAAA,YAAA,CACS1G,QAAM;AAAAa,gBAAAA,IAAAA,MACS,qBAAqB;AAAA,QAAA;AAEzC,cAAA8F,eAAA;AAAA,UAAA,GACOD,cAAa9F;AAAAA,UAAAgG,YAAA;AAAA,YAAA,GAETF,cAAa9F,QAAAgG;AAAAA,YAAAC,UAAA;AAAA,YAAAC,gCAAAC,KAAA;AAAA,YAAAC,YAGJ/G,eAAcvB,MAAAE,OAAA;AAAA,UAAA;AAAA,QAAkB;AAGpDqI,cAAAA,eAAqBxD,WAAUyD,WAAA;AAAA,UAAAxG,MACrBV,OAAMU;AAAAA,UAAAgB,UACF1B,OAAM2B;AAAAA,UAAAf,QACR+F;AAAAA,UAAYhH;AAAAA,UAAAwH,QAEZ;AAAA,QAAA,CACX;AACDC,cAAAA,sBAA4B3D,WAAUyD,WAAA;AAAA,UAAAxG,MAC5BgG,cAAahG;AAAAA,UAAAgB,UACTgF,cAAa/E;AAAAA,UAAAf,QACf+F;AAAAA,UAAYhH;AAAAA,UAAAwH,QAEZ;AAAA,QAAA,CACX;AACME,eAAAA,QAAAC,IAAaL,CAAAA,cAAcG,mBAAmB,CAAC,EAACG,KAAA,MAAA;AAE3CnE,sBAAWI,OAAAgE,UAAA;AAAA,YAAA5G,QACC8F,cAAa9F;AAAAA,UAAAA,CACxB;AACDiD,iCAAsB/B,MAAU;AAChCuB,6BAAkB5B,KAAA;AAAA,YAAAgG,SACL;AAAA,YAAkBC,MACrB;AAAA,UAAA,CACT;AAAA,QAAA,CAET,EAACC,MAAAC,CAAA,YAAA;AACGtC,kBAAAA,MAAc,2BAA2BA,OAAK;AAC9CjC,6BAAkB5B,KAAA;AAAA,YAAAgG,SACL;AAAA,YAAwBC,MAC3B;AAAA,UAAA,CACT;AAAA,QAAA,CACJ;AAAA,MAAC;AAETxJ,cAAA+B;AAAA/B,cAAAyB;AAAAzB,cAAAuF;AAAAvF,cAAA8B;AAAA9B,cAAAkF;AAAAlF,cAAAmF;AAAAnF,cAAAmB;AAAAA,IAAAA,OAAA;AAAAA,WAAAnB,EAAA,EAAA;AAAA,IAAA;AA9CD,UAAAuI,WAAApH;AA8CCwI,QAAAA;AAAA,QAAA3J,EAAA,EAAA,MAAA6F,OAAAC,IAAA,2BAAA,GAAA;AAIc6D,WAAAxG,OAAI,qEAAqE;AAACnD,cAAA2J;AAAAA,IAAAA,OAAA;AAAAA,WAAA3J,EAAA,EAAA;AAAA,IAAA;AAAA4J,QAAAA;AAAA,QAAA5J,EAAA,EAAA,MAAA6F,OAAAC,IAAA,2BAAA,GAAA;AAGjF8D,0CAAC3G,GAAoB,YAAA,EAAA,SAAA,MAAiB,WAAA,cAAc,UAEpD,WAAA;AAAajD,cAAA4J;AAAAA,IAAAA,OAAA;AAAAA,WAAA5J,EAAA,EAAA;AAAA,IAAA;AAAA6J,QAAAA;AAAA,QAAA7J,EAAA,EAAA,MAAA+F,UAAAmB,QAAA;AAEZnB,WAAAA,UAASmB,gBACNjG,2BAAAA,KAAA6I,WAAAA,UAAA,EAAA,UAAA;AAAA,QAACjJ,2BAAA,IAAAyH,GAAA,OAAA,EAAiB,WAAA,aAAa,UAE/B,wBAAA;AAAA,uCACCrF,GAAAA,YAAoB,EAAA,SAAA,WAAsB,WAAA,QAAQ,UAEnD,+EAAA,CAAA;AAAA,MAAA,GAAa;AACd,QAAA,EAAA,IAAA8C,UAAAmB;AAAAlH,cAAA6J;AAAAA,IAAAA,OAAA;AAAAA,WAAA7J,EAAA,EAAA;AAAA,IAAA;AAAA+J,QAAAA;AAAA,QAAA/J,EAAA,EAAA,MAAAyB,cAAAzB,EAAAqF,EAAAA,MAAAA,SAAArF,EAAA+F,EAAAA,MAAAA,aAAA/F,UAAAmF,oBAAA;AAAA6E,UAAAA;AAAAhK,UAAAA,EAAAyB,EAAAA,MAAAA,cAAAzB,UAAAqF,SAAArF,EAAA,EAAA,MAAAmF,oBAAA;AAEY6E,eAAAA,CAAAC,UAAAC,UAAA;AACXvI,gBAAAA,cAAoBsI,SAAQvH,QAAAgG,YAAAyB;AACrB,iBAAAtJ,2BAAA,IAAA,SAA2B,WAAA,+BAC9B,yCAAC,oBAAyB,EAAA,MAAA,SACEoJ,QAAAA,UACIxI,YACCE,aAET,SAAAd,2BAAA,IAACO,cAAe,OAAA,0BACI,WAAA,yBAChB,UAAAP,2BAAAA,IAACwC,GAAAA,YACY,EAAA,SAAA,MAAA;AAAA,gBACDgC,OAAK;AACLF,iCAAkB5B,KAAA;AAAA,gBAAAgG,SACL;AAAA,gBAAsDC,MACzD;AAAA,cAAA,CACT;AAAA,YAAA,OAAC;AAEF7D,qCAAuBsE,QAAQ;AAAA,YAAA;AAAA,UAAC,GAGxC,UAACpJ,+BAAAuJ,GAAAA,aAAA,IACL,CAAA,GACJ,EAAA,CAAU,UAEtC;AAAA,QAAM;AACTpK,gBAAAyB;AAAAzB,gBAAAqF;AAAArF,gBAAAmF;AAAAnF,gBAAAgK;AAAAA,MAAAA,OAAA;AAAAA,eAAAhK,EAAA,EAAA;AAAA,MAAA;AA1BA+F,YAAAA,UAAS1B,IAAK2F,IA0Bd;AAAChK,cAAAyB;AAAAzB,cAAAqF;AAAArF,cAAA+F;AAAA/F,cAAAmF;AAAAnF,cAAA+J;AAAAA,IAAAA,OAAA;AAAAA,YAAA/J,EAAA,EAAA;AAAA,IAAA;AAAAgK,QAAAA;AAAA,QAAAhK,EAAA,EAAA,MAAAmG,WAAAnG,EAAA,EAAA,MAAAiG,aAAAjG,EAAA,EAAA,MAAA+F,UAAAmB,QAAA;AAGDnB,YAAAA,UAASmB,cACNjG,2BAAAA,KAAA,SACSyF,kBACK,WAAA,oBAETT,UAAAA;AAAAA,QAAa,aAAApF,2BAAAA,IAACyH,GAAAA,SAAM,UAAe,kBAAA,CAAA;AAAA,QACnC,CAACnC,WAAWJ,UAASmB,SAAA,KAAuBrG,2BAAAA,IAACyH,YAAM,UAAyB,4BAAA,CAAA;AAAA,MAAA,GACjF;AACHtI,cAAAmG;AAAAnG,cAAAiG;AAAA,QAAA,EAAA,IAAAF,UAAAmB;AAAAlH,cAAAgK;AAAAA,IAAAA,OAAA;AAAAA,YAAAhK,EAAA,EAAA;AAAA,IAAA;AAAAqK,QAAAA;AAAArK,QAAAA,EAAA+J,EAAAA,MAAAA,OAAA/J,UAAAgK,OAAAhK,EAAA,EAAA,MAAA6J,IAAA;mDApDU,EAAA,WAAA,gDAEXD,UAAAA;AAAAA,QAAAA;AAAAA,QAICC;AAAAA,QASAE;AAAAA,QA6BAC;AAAAA,MAAAA,GASL;AAAMhK,cAAA+J;AAAA/J,cAAAgK;AAAAhK,cAAA6J;AAAA7J,cAAAqK;AAAAA,IAAAA,OAAA;AAAAA,YAAArK,EAAA,EAAA;AAAA,IAAA;AAEoBsK,UAAAA,MAAAC,QAAQ7E,mBAAmB;AAAC8E,QAAAA;AAAA,QAAAxK,EAAAuI,EAAAA,MAAAA,YAAAvI,UAAA0F,qBAAA;AACxB8E,uBAAA;AAAA,YAAA,CACD9E,qBAAmB;AAAA;AAAA,QAAA;AACxB6C,iBAAS7C,mBAAmB;AAAA,MAAC;AAChC1F,cAAAuI;AAAAvI,cAAA0F;AAAA1F,cAAAwK;AAAAA,IAAAA,OAAA;AAAAA,YAAAxK,EAAA,EAAA;AAAA,IAAA;AAAAyK,QAAAA;AAAAC,QAAAA;AAAA,QAAA1K,EAAA,EAAA,MAAA6F,OAAAC,IAAA,2BAAA,GAAA;AACS2E,uBAAA;AACN9E,+BAAsB/B,MAAU;AAAA,MAAC;AAE9B8G,YAAC7J,2BAAA,IAAAoC,eAAA,EAAoB,SAAA,aAAa,UAA4B,gCAAA;AAAajD,cAAAyK;AAAAzK,cAAA0K;AAAAA,IAAAA,OAAA;AAAAD,YAAAzK,EAAA,EAAA;AAAA0K,YAAA1K,EAAA,EAAA;AAAA,IAAA;AAAA2K,QAAAA;AAAA,QAAA3K,EAAAsK,EAAAA,MAAAA,OAAAtK,UAAAwK,KAAA;AARtG,YAAA3J,2BAAA,IAAC+J,2BAAyB,MAAAN,KACI,UAAAE,KAIA,UAAAC,KAGH,OAAAC,IAA8E,CAAA;AAAA1K,cAAAsK;AAAAtK,cAAAwK;AAAAxK,cAAA2K;AAAAA,IAAAA,OAAA;AAAAA,YAAA3K,EAAA,EAAA;AAAA,IAAA;AAAA6K,QAAAA;AAAA,QAAA7K,EAAAqK,EAAAA,MAAAA,OAAArK,UAAA2K,KAAA;AAlEtGE,YAAA5J,2BAAAA,KAAA,OAAA,EACEsF,mBACM,WAAAoD,IACXU,UAAAA;AAAAA,QAAAA;AAAAA,QAuDAM;AAAAA,MAAAA,GASJ;AAAM3K,cAAAqK;AAAArK,cAAA2K;AAAA3K,cAAA6K;AAAAA,IAAAA,OAAA;AAAAA,YAAA7K,EAAA,EAAA;AAAA,IAAA;AAnEC6K,WAAAA;AAAAA,EAmED;ACrOH,QAAMC,yBAA0C;AAAA,IACnDC,eAAe,OAAOC,UAAU;AAEtBC,YAAAA,gBAAgBD,MAAME,iBAAiBC,kBAAkBH,MAAME,gBAAgBF,MAAMtI,MAAM,IAAI;AACrG,YAAMhC,MAAMsK,MAAMI,QAAQrJ,eAAevB,MAAME;AACzC0K,YAAAA,QAAQ7F,WAAWyD,WAAW;AAAA,QAChCxG,MAAMwI,MAAMxI,OAAO,MAAMwI,MAAMxH,WAAW;AAAA,QAC1Cd,QAAQ;AAAA,UACJ,GAAGsI,MAAMtI;AAAAA,UACTgG,YAAY;AAAA,YACRyB,gBAAgBc;AAAAA,YAChBrC,gCAAgBC,KAAK;AAAA,YACrBC,YAAYpI;AAAAA,UAAAA;AAAAA,QAEpB;AAAA,QACAuI,QAAQ;AAAA,MAAA,CACX,EAAEI,KAAK,MAAM;AACVgC,gBAAQC,MAAM,qBAAqBN,MAAMxI,MAAMwI,MAAMxH,QAAQ;AAAA,MAAA,CAChE;AAAA,IAAA;AAAA,EAET;AAEA,WAAS2H,kBAAoCI,WAAcC,WAAcC,SAAiB,IAAc;AACpG,UAAMR,gBAA0B,CAAE;AAGlC,QAAI3K,MAAMiL,WAAWC,SAAS,EAAUP,QAAAA;AACxC,QAAI,CAACM,aAAa,CAACC,UAAkB,QAAA,CAACC,UAAU,GAAG;AAGnD,UAAMC,UAAU,oBAAIC,IAAI,CACpB,GAAGC,OAAOC,KAAKN,SAAS,GACxB,GAAGK,OAAOC,KAAKL,SAAS,CAAC,CAC5B;AAED,eAAWlH,OAAOoH,SAAS;AACjBI,YAAAA,WAAWP,UAAUjH,GAAc;AACnCyH,YAAAA,WAAWP,UAAUlH,GAAc;AACzC,YAAM0H,cAAcP,SAAS,GAAGA,MAAM,IAAInH,GAAG,KAAKA;AAG7CA,UAAAA,OAAOiH,cAAgBjH,OAAOkH,WAAY;AAC3CP,sBAAcgB,KAAKD,WAAW;AAC9B;AAAA,MAAA;AAIA1L,UAAAA,MAAMwL,UAAUC,QAAQ,EAAG;AAG/B,UAAIG,MAAMC,QAAQL,QAAQ,KAAKI,MAAMC,QAAQJ,QAAQ,GAAG;AAChDD,YAAAA,SAAS5E,WAAW6E,SAAS7E,QAAQ;AACrC+D,wBAAcgB,KAAKD,WAAW;AAAA,QAAA,OAC3B;AAEH,mBAASI,IAAI,GAAGA,IAAIN,SAAS5E,QAAQkF,KAAK;AACtC,gBACI,OAAON,SAASM,CAAC,MAAM,YAAYN,SAASM,CAAC,MAAM,QACnD,OAAOL,SAASK,CAAC,MAAM,YAAYL,SAASK,CAAC,MAAM,MACrD;AACE,oBAAMC,gBAAgBlB,kBAClBW,SAASM,CAAC,GACVL,SAASK,CAAC,GACV,GAAGJ,WAAW,IAAII,CAAC,GACvB;AACIC,kBAAAA,cAAcnF,SAAS,GAAG;AAC1B+D,8BAAcgB,KAAKD,WAAW;AAC9B;AAAA,cAAA;AAAA,YACJ,WACO,CAAC1L,MAAMwL,SAASM,CAAC,GAAGL,SAASK,CAAC,CAAC,GAAG;AACzCnB,4BAAcgB,KAAKD,WAAW;AAC9B;AAAA,YAAA;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ,WAIA,OAAOF,aAAa,YAAYA,aAAa,QAC7C,OAAOC,aAAa,YAAYA,aAAa,MAC/C;AACE,cAAMM,gBAAgBlB,kBAClBW,UACAC,UACAC,WACJ;AACcC,sBAAAA,KAAK,GAAGI,aAAa;AAAA,MAAA,OAGlC;AACDpB,sBAAcgB,KAAKD,WAAW;AAAA,MAAA;AAAA,IAClC;AAGGf,WAAAA;AAAAA,EACX;ACxFO,WAASqB,uBAAuBtB,OAA0F;AAEvH,UAAA;AAAA,MAAEuB,iBAAiB;AAAA,IAAM,IAAIvB,SAAS,CAAC;AAEvCwB,UAAAA,mBAAmBC,kBAAY,CAAChL,eAAiC;AACnE,UAAIA,WAAWiL,YAAY,QAASH,kBAAkB9K,WAAWiL,YAAY,OAAQ;AAC1E,eAAA;AAAA,UACH,GAAGjL;AAAAA,UACHoC,aAAa,CACT,GAAIpC,WAAWoC,eAAe,CAAA,GAC9B;AAAA,YACIS,KAAK;AAAA,YACLqI,MAAM;AAAA,YACNC,cAAc/L,2BAAAA,IAACuJ,GAAAA,aAAY,EAAA,MAAM,QAAU,CAAA;AAAA,YAC3CyC,SAAS5H;AAAAA,YACT6H,UAAU;AAAA,UAAA,CACb;AAAA,UAELC,WAAWC,KAAAA,eAAevL,WAAWsL,WAAWjC,sBAAsB;AAAA,QAC1E;AAAA,MAAA;AAEGrJ,aAAAA;AAAAA,IACX,GAAG,EAAE;AAEL,WAAOqB,cAAQ,OAAO;AAAA,MAClBwB,KAAK;AAAA,MACL2I,UAAU;AAAA,QACNC,WAAWrN;AAAAA,QACXmL,OAAO;AAAA,UACH7K,SAAS6K,OAAO7K;AAAAA,QAAAA;AAAAA,MAExB;AAAA,MACAsB,YAAY;AAAA,QACR+K;AAAAA,MAAAA;AAAAA,IACJ,IACwB,CAACxB,KAAK,CAAC;AAAA,EACvC;;;;;;;"}
|
package/package.json
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
{
|
2
2
|
"name": "@firecms/entity_history",
|
3
3
|
"type": "module",
|
4
|
-
"version": "3.0.0-canary.
|
4
|
+
"version": "3.0.0-canary.241",
|
5
5
|
"access": "public",
|
6
6
|
"main": "./dist/index.umd.js",
|
7
7
|
"module": "./dist/index.es.js",
|
8
8
|
"types": "./dist/index.d.ts",
|
9
9
|
"source": "src/index.ts",
|
10
10
|
"dependencies": {
|
11
|
-
"@firecms/core": "^3.0.0-canary.
|
12
|
-
"@firecms/formex": "^3.0.0-canary.
|
13
|
-
"@firecms/ui": "^3.0.0-canary.
|
11
|
+
"@firecms/core": "^3.0.0-canary.241",
|
12
|
+
"@firecms/formex": "^3.0.0-canary.241",
|
13
|
+
"@firecms/ui": "^3.0.0-canary.241"
|
14
14
|
},
|
15
15
|
"peerDependencies": {
|
16
16
|
"react": ">=18.0.0",
|
@@ -82,5 +82,5 @@
|
|
82
82
|
"publishConfig": {
|
83
83
|
"access": "public"
|
84
84
|
},
|
85
|
-
"gitHead": "
|
85
|
+
"gitHead": "5d3c3928250947d0363073d612a8c15f9bc10459"
|
86
86
|
}
|
@@ -125,9 +125,20 @@ export function EntityHistoryEntry({
|
|
125
125
|
|
126
126
|
{previewKeys && previewKeys.map((key) => {
|
127
127
|
const childProperty = getPropertyInPath(resolvedCollection.properties, key);
|
128
|
-
if (!childProperty) return null;
|
129
128
|
|
130
129
|
const valueInPath = getValueInPath(entity.values, key);
|
130
|
+
const element = childProperty ? (entity
|
131
|
+
? <PropertyPreview
|
132
|
+
propertyKey={key as string}
|
133
|
+
value={valueInPath}
|
134
|
+
property={childProperty as ResolvedProperty}
|
135
|
+
size={"small"}/>
|
136
|
+
: <SkeletonPropertyComponent
|
137
|
+
property={childProperty as ResolvedProperty}
|
138
|
+
size={"small"}/>) :
|
139
|
+
<Typography variant={"body2"}>
|
140
|
+
{typeof valueInPath === "string" ? valueInPath : JSON.stringify(valueInPath)}
|
141
|
+
</Typography>;
|
131
142
|
return (
|
132
143
|
<div key={"ref_prev_" + key}
|
133
144
|
className="flex w-full my-1 items-center">
|
@@ -138,15 +149,7 @@ export function EntityHistoryEntry({
|
|
138
149
|
</Typography>
|
139
150
|
<div className="w-4/5">
|
140
151
|
{
|
141
|
-
|
142
|
-
? <PropertyPreview
|
143
|
-
propertyKey={key as string}
|
144
|
-
value={valueInPath}
|
145
|
-
property={childProperty as ResolvedProperty}
|
146
|
-
size={"small"}/>
|
147
|
-
: <SkeletonPropertyComponent
|
148
|
-
property={childProperty as ResolvedProperty}
|
149
|
-
size={"small"}/>
|
152
|
+
element
|
150
153
|
}
|
151
154
|
</div>
|
152
155
|
</div>
|
@@ -23,7 +23,7 @@ export function EntityHistoryView({
|
|
23
23
|
const dataSource = useDataSource();
|
24
24
|
const pathAndId = entity ? entity?.path + "/" + entity?.id : undefined;
|
25
25
|
|
26
|
-
const [
|
26
|
+
const [revertVersionDialog, setRevertVersionDialog] = useState<Entity | undefined>(undefined);
|
27
27
|
const [revisions, setRevisions] = useState<Entity[]>([]);
|
28
28
|
const [isLoading, setIsLoading] = useState(false);
|
29
29
|
const [hasMore, setHasMore] = useState(true);
|
@@ -116,6 +116,9 @@ export function EntityHistoryView({
|
|
116
116
|
}
|
117
117
|
|
118
118
|
function doRevert(revertVersion: Entity) {
|
119
|
+
if (!entity) {
|
120
|
+
throw new Error("No entity to revert");
|
121
|
+
}
|
119
122
|
const revertValues = {
|
120
123
|
...revertVersion.values,
|
121
124
|
__metadata: {
|
@@ -125,29 +128,38 @@ export function EntityHistoryView({
|
|
125
128
|
updated_by: authController.user?.uid ?? null,
|
126
129
|
}
|
127
130
|
};
|
128
|
-
|
131
|
+
const saveReverted = dataSource.saveEntity({
|
132
|
+
path: entity.path,
|
133
|
+
entityId: entity.id,
|
134
|
+
values: revertValues,
|
135
|
+
collection,
|
136
|
+
status: "existing"
|
137
|
+
});
|
138
|
+
const saveRevertedHistory = dataSource.saveEntity({
|
129
139
|
path: revertVersion.path,
|
130
140
|
entityId: revertVersion.id,
|
131
141
|
values: revertValues,
|
132
142
|
collection,
|
133
143
|
status: "existing"
|
134
|
-
}).then(() => {
|
135
|
-
formContext.formex.resetForm({
|
136
|
-
values: revertVersion.values
|
137
|
-
});
|
138
|
-
setRevertVersion(undefined);
|
139
|
-
snackbarController.open({
|
140
|
-
message: "Reverted version",
|
141
|
-
type: "info"
|
142
|
-
});
|
143
|
-
}
|
144
|
-
).catch((error) => {
|
145
|
-
console.error("Error reverting entity:", error);
|
146
|
-
snackbarController.open({
|
147
|
-
message: "Error reverting entity",
|
148
|
-
type: "error"
|
149
|
-
});
|
150
144
|
});
|
145
|
+
return Promise.all([saveReverted, saveRevertedHistory])
|
146
|
+
.then(() => {
|
147
|
+
formContext.formex.resetForm({
|
148
|
+
values: revertVersion.values
|
149
|
+
});
|
150
|
+
setRevertVersionDialog(undefined);
|
151
|
+
snackbarController.open({
|
152
|
+
message: "Reverted version",
|
153
|
+
type: "info"
|
154
|
+
});
|
155
|
+
}
|
156
|
+
).catch((error) => {
|
157
|
+
console.error("Error reverting entity:", error);
|
158
|
+
snackbarController.open({
|
159
|
+
message: "Error reverting entity",
|
160
|
+
type: "error"
|
161
|
+
});
|
162
|
+
});
|
151
163
|
|
152
164
|
}
|
153
165
|
|
@@ -187,7 +199,7 @@ export function EntityHistoryView({
|
|
187
199
|
type: "warning"
|
188
200
|
});
|
189
201
|
} else {
|
190
|
-
|
202
|
+
setRevertVersionDialog(revision);
|
191
203
|
}
|
192
204
|
}}>
|
193
205
|
<HistoryIcon/>
|
@@ -209,13 +221,13 @@ export function EntityHistoryView({
|
|
209
221
|
)}
|
210
222
|
</div>
|
211
223
|
|
212
|
-
<ConfirmationDialog open={Boolean(
|
224
|
+
<ConfirmationDialog open={Boolean(revertVersionDialog)}
|
213
225
|
onAccept={function (): void {
|
214
|
-
if (!
|
215
|
-
doRevert(
|
226
|
+
if (!revertVersionDialog) return;
|
227
|
+
doRevert(revertVersionDialog);
|
216
228
|
}}
|
217
229
|
onCancel={function (): void {
|
218
|
-
|
230
|
+
setRevertVersionDialog(undefined);
|
219
231
|
}}
|
220
232
|
title={<Typography variant={"subtitle2"}>Revert data to this version?</Typography>}/>
|
221
233
|
</div>
|
@@ -13,10 +13,9 @@ export function useEntityHistoryPlugin(props?: EntityHistoryPluginProps): FireCM
|
|
13
13
|
const { defaultEnabled = false } = props ?? {};
|
14
14
|
|
15
15
|
const modifyCollection = useCallback((collection: EntityCollection) => {
|
16
|
-
if (collection.history === true || defaultEnabled) {
|
16
|
+
if (collection.history === true || (defaultEnabled && collection.history !== false)) {
|
17
17
|
return {
|
18
18
|
...collection,
|
19
|
-
history: true,
|
20
19
|
entityViews: [
|
21
20
|
...(collection.entityViews ?? []),
|
22
21
|
{
|