@firecms/entity_history 3.0.0-canary.240 → 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 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 { FirebaseCMSApp } from "@firecms/core";
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 <FirebaseCMSApp
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: entity ? /* @__PURE__ */ jsx(PropertyPreview, { propertyKey: key, value: valueInPath, property: childProperty, size: "small" }) : /* @__PURE__ */ jsx(SkeletonPropertyComponent, { property: childProperty, size: "small" }) })
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(52);
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 [revertVersion, setRevertVersion] = useState(void 0);
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.user?.uid || $[15] !== collection || $[16] !== dataSource || $[17] !== formContext.formex || $[18] !== snackbarController) {
287
- t6 = function doRevert2(revertVersion_0) {
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
- ...revertVersion_0.values,
292
+ ...revertVersion.values,
290
293
  __metadata: {
291
- ...revertVersion_0.values?.__metadata,
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
- return dataSource.saveEntity({
298
- path: revertVersion_0.path,
299
- entityId: revertVersion_0.id,
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
- }).then(() => {
313
+ });
314
+ return Promise.all([saveReverted, saveRevertedHistory]).then(() => {
304
315
  formContext.formex.resetForm({
305
- values: revertVersion_0.values
316
+ values: revertVersion.values
306
317
  });
307
- setRevertVersion(void 0);
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.user?.uid;
331
+ $[14] = authController;
321
332
  $[15] = collection;
322
333
  $[16] = dataSource;
323
- $[17] = formContext.formex;
324
- $[18] = snackbarController;
325
- $[19] = t6;
334
+ $[17] = entity;
335
+ $[18] = formContext;
336
+ $[19] = snackbarController;
337
+ $[20] = t6;
326
338
  } else {
327
- t6 = $[19];
339
+ t6 = $[20];
328
340
  }
329
341
  const doRevert = t6;
330
342
  let t7;
331
- if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
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
- $[20] = t7;
345
+ $[21] = t7;
334
346
  } else {
335
- t7 = $[20];
347
+ t7 = $[21];
336
348
  }
337
349
  let t8;
338
- if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
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
- $[21] = t8;
352
+ $[22] = t8;
341
353
  } else {
342
- t8 = $[21];
354
+ t8 = $[22];
343
355
  }
344
356
  let t9;
345
- if ($[22] !== revisions.length) {
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
- $[22] = revisions.length;
351
- $[23] = t9;
362
+ $[23] = revisions.length;
363
+ $[24] = t9;
352
364
  } else {
353
- t9 = $[23];
365
+ t9 = $[24];
354
366
  }
355
367
  let t10;
356
- if ($[24] !== collection || $[25] !== dirty || $[26] !== revisions || $[27] !== snackbarController) {
368
+ if ($[25] !== collection || $[26] !== dirty || $[27] !== revisions || $[28] !== snackbarController) {
357
369
  let t112;
358
- if ($[29] !== collection || $[30] !== dirty || $[31] !== snackbarController) {
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
- setRevertVersion(revision);
380
+ setRevertVersionDialog(revision);
369
381
  }
370
382
  }, children: /* @__PURE__ */ jsx(HistoryIcon, {}) }) }) }) }, index);
371
383
  };
372
- $[29] = collection;
373
- $[30] = dirty;
374
- $[31] = snackbarController;
375
- $[32] = t112;
384
+ $[30] = collection;
385
+ $[31] = dirty;
386
+ $[32] = snackbarController;
387
+ $[33] = t112;
376
388
  } else {
377
- t112 = $[32];
389
+ t112 = $[33];
378
390
  }
379
391
  t10 = revisions.map(t112);
380
- $[24] = collection;
381
- $[25] = dirty;
382
- $[26] = revisions;
383
- $[27] = snackbarController;
384
- $[28] = t10;
392
+ $[25] = collection;
393
+ $[26] = dirty;
394
+ $[27] = revisions;
395
+ $[28] = snackbarController;
396
+ $[29] = t10;
385
397
  } else {
386
- t10 = $[28];
398
+ t10 = $[29];
387
399
  }
388
400
  let t11;
389
- if ($[33] !== hasMore || $[34] !== isLoading || $[35] !== revisions.length) {
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
- $[33] = hasMore;
395
- $[34] = isLoading;
396
- $[35] = revisions.length;
397
- $[36] = t11;
406
+ $[34] = hasMore;
407
+ $[35] = isLoading;
408
+ $[36] = revisions.length;
409
+ $[37] = t11;
398
410
  } else {
399
- t11 = $[36];
411
+ t11 = $[37];
400
412
  }
401
413
  let t12;
402
- if ($[37] !== t10 || $[38] !== t11 || $[39] !== t9) {
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
- $[37] = t10;
410
- $[38] = t11;
411
- $[39] = t9;
412
- $[40] = t12;
421
+ $[38] = t10;
422
+ $[39] = t11;
423
+ $[40] = t9;
424
+ $[41] = t12;
413
425
  } else {
414
- t12 = $[40];
426
+ t12 = $[41];
415
427
  }
416
- const t13 = Boolean(revertVersion);
428
+ const t13 = Boolean(revertVersionDialog);
417
429
  let t14;
418
- if ($[41] !== doRevert || $[42] !== revertVersion) {
430
+ if ($[42] !== doRevert || $[43] !== revertVersionDialog) {
419
431
  t14 = function() {
420
- if (!revertVersion) {
432
+ if (!revertVersionDialog) {
421
433
  return;
422
434
  }
423
- doRevert(revertVersion);
435
+ doRevert(revertVersionDialog);
424
436
  };
425
- $[41] = doRevert;
426
- $[42] = revertVersion;
427
- $[43] = t14;
437
+ $[42] = doRevert;
438
+ $[43] = revertVersionDialog;
439
+ $[44] = t14;
428
440
  } else {
429
- t14 = $[43];
441
+ t14 = $[44];
430
442
  }
431
443
  let t15;
432
444
  let t16;
433
- if ($[44] === Symbol.for("react.memo_cache_sentinel")) {
445
+ if ($[45] === Symbol.for("react.memo_cache_sentinel")) {
434
446
  t15 = function() {
435
- setRevertVersion(void 0);
447
+ setRevertVersionDialog(void 0);
436
448
  };
437
449
  t16 = /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: "Revert data to this version?" });
438
- $[44] = t15;
439
- $[45] = t16;
450
+ $[45] = t15;
451
+ $[46] = t16;
440
452
  } else {
441
- t15 = $[44];
442
- t16 = $[45];
453
+ t15 = $[45];
454
+ t16 = $[46];
443
455
  }
444
456
  let t17;
445
- if ($[46] !== t13 || $[47] !== t14) {
457
+ if ($[47] !== t13 || $[48] !== t14) {
446
458
  t17 = /* @__PURE__ */ jsx(ConfirmationDialog, { open: t13, onAccept: t14, onCancel: t15, title: t16 });
447
- $[46] = t13;
448
- $[47] = t14;
449
- $[48] = t17;
459
+ $[47] = t13;
460
+ $[48] = t14;
461
+ $[49] = t17;
450
462
  } else {
451
- t17 = $[48];
463
+ t17 = $[49];
452
464
  }
453
465
  let t18;
454
- if ($[49] !== t12 || $[50] !== t17) {
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
- $[49] = t12;
460
- $[50] = t17;
461
- $[51] = t18;
471
+ $[50] = t12;
472
+ $[51] = t17;
473
+ $[52] = t18;
462
474
  } else {
463
- t18 = $[51];
475
+ t18 = $[52];
464
476
  }
465
477
  return t18;
466
478
  }
@@ -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 && 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","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: entity ? /* @__PURE__ */ jsxRuntime.jsx(core.PropertyPreview, { propertyKey: key, value: valueInPath, property: childProperty, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(core.SkeletonPropertyComponent, { property: childProperty, size: "small" }) })
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(52);
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 [revertVersion, setRevertVersion] = React.useState(void 0);
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.user?.uid || $[15] !== collection || $[16] !== dataSource || $[17] !== formContext.formex || $[18] !== snackbarController) {
301
- t6 = function doRevert2(revertVersion_0) {
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
- ...revertVersion_0.values,
306
+ ...revertVersion.values,
304
307
  __metadata: {
305
- ...revertVersion_0.values?.__metadata,
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
- return dataSource.saveEntity({
312
- path: revertVersion_0.path,
313
- entityId: revertVersion_0.id,
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
- }).then(() => {
327
+ });
328
+ return Promise.all([saveReverted, saveRevertedHistory]).then(() => {
318
329
  formContext.formex.resetForm({
319
- values: revertVersion_0.values
330
+ values: revertVersion.values
320
331
  });
321
- setRevertVersion(void 0);
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.user?.uid;
345
+ $[14] = authController;
335
346
  $[15] = collection;
336
347
  $[16] = dataSource;
337
- $[17] = formContext.formex;
338
- $[18] = snackbarController;
339
- $[19] = t6;
348
+ $[17] = entity;
349
+ $[18] = formContext;
350
+ $[19] = snackbarController;
351
+ $[20] = t6;
340
352
  } else {
341
- t6 = $[19];
353
+ t6 = $[20];
342
354
  }
343
355
  const doRevert = t6;
344
356
  let t7;
345
- if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
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
- $[20] = t7;
359
+ $[21] = t7;
348
360
  } else {
349
- t7 = $[20];
361
+ t7 = $[21];
350
362
  }
351
363
  let t8;
352
- if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
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
- $[21] = t8;
366
+ $[22] = t8;
355
367
  } else {
356
- t8 = $[21];
368
+ t8 = $[22];
357
369
  }
358
370
  let t9;
359
- if ($[22] !== revisions.length) {
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
- $[22] = revisions.length;
365
- $[23] = t9;
376
+ $[23] = revisions.length;
377
+ $[24] = t9;
366
378
  } else {
367
- t9 = $[23];
379
+ t9 = $[24];
368
380
  }
369
381
  let t10;
370
- if ($[24] !== collection || $[25] !== dirty || $[26] !== revisions || $[27] !== snackbarController) {
382
+ if ($[25] !== collection || $[26] !== dirty || $[27] !== revisions || $[28] !== snackbarController) {
371
383
  let t112;
372
- if ($[29] !== collection || $[30] !== dirty || $[31] !== snackbarController) {
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
- setRevertVersion(revision);
394
+ setRevertVersionDialog(revision);
383
395
  }
384
396
  }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.HistoryIcon, {}) }) }) }) }, index);
385
397
  };
386
- $[29] = collection;
387
- $[30] = dirty;
388
- $[31] = snackbarController;
389
- $[32] = t112;
398
+ $[30] = collection;
399
+ $[31] = dirty;
400
+ $[32] = snackbarController;
401
+ $[33] = t112;
390
402
  } else {
391
- t112 = $[32];
403
+ t112 = $[33];
392
404
  }
393
405
  t10 = revisions.map(t112);
394
- $[24] = collection;
395
- $[25] = dirty;
396
- $[26] = revisions;
397
- $[27] = snackbarController;
398
- $[28] = t10;
406
+ $[25] = collection;
407
+ $[26] = dirty;
408
+ $[27] = revisions;
409
+ $[28] = snackbarController;
410
+ $[29] = t10;
399
411
  } else {
400
- t10 = $[28];
412
+ t10 = $[29];
401
413
  }
402
414
  let t11;
403
- if ($[33] !== hasMore || $[34] !== isLoading || $[35] !== revisions.length) {
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
- $[33] = hasMore;
409
- $[34] = isLoading;
410
- $[35] = revisions.length;
411
- $[36] = t11;
420
+ $[34] = hasMore;
421
+ $[35] = isLoading;
422
+ $[36] = revisions.length;
423
+ $[37] = t11;
412
424
  } else {
413
- t11 = $[36];
425
+ t11 = $[37];
414
426
  }
415
427
  let t12;
416
- if ($[37] !== t10 || $[38] !== t11 || $[39] !== t9) {
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
- $[37] = t10;
424
- $[38] = t11;
425
- $[39] = t9;
426
- $[40] = t12;
435
+ $[38] = t10;
436
+ $[39] = t11;
437
+ $[40] = t9;
438
+ $[41] = t12;
427
439
  } else {
428
- t12 = $[40];
440
+ t12 = $[41];
429
441
  }
430
- const t13 = Boolean(revertVersion);
442
+ const t13 = Boolean(revertVersionDialog);
431
443
  let t14;
432
- if ($[41] !== doRevert || $[42] !== revertVersion) {
444
+ if ($[42] !== doRevert || $[43] !== revertVersionDialog) {
433
445
  t14 = function() {
434
- if (!revertVersion) {
446
+ if (!revertVersionDialog) {
435
447
  return;
436
448
  }
437
- doRevert(revertVersion);
449
+ doRevert(revertVersionDialog);
438
450
  };
439
- $[41] = doRevert;
440
- $[42] = revertVersion;
441
- $[43] = t14;
451
+ $[42] = doRevert;
452
+ $[43] = revertVersionDialog;
453
+ $[44] = t14;
442
454
  } else {
443
- t14 = $[43];
455
+ t14 = $[44];
444
456
  }
445
457
  let t15;
446
458
  let t16;
447
- if ($[44] === Symbol.for("react.memo_cache_sentinel")) {
459
+ if ($[45] === Symbol.for("react.memo_cache_sentinel")) {
448
460
  t15 = function() {
449
- setRevertVersion(void 0);
461
+ setRevertVersionDialog(void 0);
450
462
  };
451
463
  t16 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "subtitle2", children: "Revert data to this version?" });
452
- $[44] = t15;
453
- $[45] = t16;
464
+ $[45] = t15;
465
+ $[46] = t16;
454
466
  } else {
455
- t15 = $[44];
456
- t16 = $[45];
467
+ t15 = $[45];
468
+ t16 = $[46];
457
469
  }
458
470
  let t17;
459
- if ($[46] !== t13 || $[47] !== t14) {
471
+ if ($[47] !== t13 || $[48] !== t14) {
460
472
  t17 = /* @__PURE__ */ jsxRuntime.jsx(core.ConfirmationDialog, { open: t13, onAccept: t14, onCancel: t15, title: t16 });
461
- $[46] = t13;
462
- $[47] = t14;
463
- $[48] = t17;
473
+ $[47] = t13;
474
+ $[48] = t14;
475
+ $[49] = t17;
464
476
  } else {
465
- t17 = $[48];
477
+ t17 = $[49];
466
478
  }
467
479
  let t18;
468
- if ($[49] !== t12 || $[50] !== t17) {
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
- $[49] = t12;
474
- $[50] = t17;
475
- $[51] = t18;
485
+ $[50] = t12;
486
+ $[51] = t17;
487
+ $[52] = t18;
476
488
  } else {
477
- t18 = $[51];
489
+ t18 = $[52];
478
490
  }
479
491
  return t18;
480
492
  }
@@ -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 && 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","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":"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"}
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.240",
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.240",
12
- "@firecms/formex": "^3.0.0-canary.240",
13
- "@firecms/ui": "^3.0.0-canary.240"
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": "b5b46f7dfb9547324c71d839fff7d52bb3ef54ae"
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
- entity
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 [revertVersion, setRevertVersion] = useState<Entity | undefined>(undefined);
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
- return dataSource.saveEntity({
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
- setRevertVersion(revision);
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(revertVersion)}
224
+ <ConfirmationDialog open={Boolean(revertVersionDialog)}
213
225
  onAccept={function (): void {
214
- if (!revertVersion) return;
215
- doRevert(revertVersion);
226
+ if (!revertVersionDialog) return;
227
+ doRevert(revertVersionDialog);
216
228
  }}
217
229
  onCancel={function (): void {
218
- setRevertVersion(undefined);
230
+ setRevertVersionDialog(undefined);
219
231
  }}
220
232
  title={<Typography variant={"subtitle2"}>Revert data to this version?</Typography>}/>
221
233
  </div>