@firecms/entity_history 3.0.0-canary.251 → 3.0.0-canary.253
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/EntityHistoryEntry.d.ts +3 -3
- package/dist/index.es.js +109 -21
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +107 -19
- package/dist/index.umd.js.map +1 -1
- package/package.json +5 -5
- package/src/components/EntityHistoryEntry.tsx +58 -6
- package/src/components/EntityHistoryView.tsx +19 -9
- package/src/entity_history_callbacks.ts +1 -0
@@ -1,17 +1,17 @@
|
|
1
1
|
import * as React from "react";
|
2
|
-
import { Entity, EntityCollection, PreviewSize } from "@firecms/core";
|
2
|
+
import { Entity, EntityCollection, EntityValues, PreviewSize } from "@firecms/core";
|
3
3
|
export type EntityPreviewProps = {
|
4
4
|
size: PreviewSize;
|
5
5
|
actions?: React.ReactNode;
|
6
6
|
collection?: EntityCollection;
|
7
7
|
hover?: boolean;
|
8
8
|
previewKeys?: string[];
|
9
|
-
disabled?: boolean;
|
10
9
|
entity: Entity<any>;
|
10
|
+
previousValues?: EntityValues<any>;
|
11
11
|
onClick?: (e: React.SyntheticEvent) => void;
|
12
12
|
};
|
13
13
|
/**
|
14
14
|
* This view is used to display a preview of an entity.
|
15
15
|
* It is used by default in reference fields and whenever a reference is displayed.
|
16
16
|
*/
|
17
|
-
export declare function EntityHistoryEntry({ actions,
|
17
|
+
export declare function EntityHistoryEntry({ actions, hover, collection: collectionProp, previewKeys, onClick, size, entity, previousValues }: EntityPreviewProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/index.es.js
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
2
2
|
import * as React from "react";
|
3
3
|
import React__default, { useContext, useState, useRef, useEffect, useCallback, useMemo } from "react";
|
4
|
-
import { useAuthController, useCustomizationController, useNavigationController, useSideEntityController, resolveCollection, getPropertyInPath, getValueInPath, PropertyPreview, SkeletonPropertyComponent, useSnackbarController, useDataSource, ConfirmationDialog, mergeCallbacks } from "@firecms/core";
|
4
|
+
import { useAuthController, useCustomizationController, useNavigationController, useSideEntityController, resolveCollection, getPropertyInPath, getValueInPath, PropertyPreview, SkeletonPropertyComponent, useSnackbarController, useDataSource, EntityView, ErrorBoundary, ConfirmationDialog, mergeCallbacks } from "@firecms/core";
|
5
5
|
import { c } from "react-compiler-runtime";
|
6
|
-
import { Chip, Tooltip, Typography, cls, defaultBorderMixin, IconButton, KeyboardTabIcon, Label, HistoryIcon } from "@firecms/ui";
|
6
|
+
import { Chip, Tooltip, Typography, cls, defaultBorderMixin, IconButton, KeyboardTabIcon, KeyboardBackspaceIcon, Label, HistoryIcon } from "@firecms/ui";
|
7
7
|
import equal from "react-fast-compare";
|
8
8
|
const HistoryControllerContext = React__default.createContext({});
|
9
9
|
const useHistoryController = () => {
|
@@ -83,15 +83,86 @@ function UserChip(t0) {
|
|
83
83
|
}
|
84
84
|
return t6;
|
85
85
|
}
|
86
|
+
function PreviousValueView(t0) {
|
87
|
+
const $ = c(12);
|
88
|
+
const {
|
89
|
+
previousValueInPath,
|
90
|
+
childProperty,
|
91
|
+
key
|
92
|
+
} = t0;
|
93
|
+
if (typeof previousValueInPath === "string" || typeof previousValueInPath === "number") {
|
94
|
+
let t1;
|
95
|
+
if ($[0] !== previousValueInPath) {
|
96
|
+
t1 = /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", className: "line-through", children: previousValueInPath });
|
97
|
+
$[0] = previousValueInPath;
|
98
|
+
$[1] = t1;
|
99
|
+
} else {
|
100
|
+
t1 = $[1];
|
101
|
+
}
|
102
|
+
return t1;
|
103
|
+
} else {
|
104
|
+
if (typeof previousValueInPath === "boolean") {
|
105
|
+
const t1 = previousValueInPath ? "true" : "false";
|
106
|
+
let t2;
|
107
|
+
if ($[2] !== t1) {
|
108
|
+
t2 = /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", className: "line-through", children: t1 });
|
109
|
+
$[2] = t1;
|
110
|
+
$[3] = t2;
|
111
|
+
} else {
|
112
|
+
t2 = $[3];
|
113
|
+
}
|
114
|
+
return t2;
|
115
|
+
} else {
|
116
|
+
let t1;
|
117
|
+
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
|
118
|
+
t1 = /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: "Previous value" });
|
119
|
+
$[4] = t1;
|
120
|
+
} else {
|
121
|
+
t1 = $[4];
|
122
|
+
}
|
123
|
+
const t2 = key;
|
124
|
+
const t3 = childProperty;
|
125
|
+
let t4;
|
126
|
+
if ($[5] !== previousValueInPath || $[6] !== t2 || $[7] !== t3) {
|
127
|
+
t4 = /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
128
|
+
t1,
|
129
|
+
/* @__PURE__ */ jsx(PropertyPreview, { propertyKey: t2, value: previousValueInPath, property: t3, size: "small" })
|
130
|
+
] });
|
131
|
+
$[5] = previousValueInPath;
|
132
|
+
$[6] = t2;
|
133
|
+
$[7] = t3;
|
134
|
+
$[8] = t4;
|
135
|
+
} else {
|
136
|
+
t4 = $[8];
|
137
|
+
}
|
138
|
+
let t5;
|
139
|
+
if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
|
140
|
+
t5 = /* @__PURE__ */ jsx(KeyboardBackspaceIcon, { size: "smallest", color: "disabled", className: "mb-1" });
|
141
|
+
$[9] = t5;
|
142
|
+
} else {
|
143
|
+
t5 = $[9];
|
144
|
+
}
|
145
|
+
let t6;
|
146
|
+
if ($[10] !== t4) {
|
147
|
+
t6 = /* @__PURE__ */ jsx(Tooltip, { side: "left", title: t4, children: t5 });
|
148
|
+
$[10] = t4;
|
149
|
+
$[11] = t6;
|
150
|
+
} else {
|
151
|
+
t6 = $[11];
|
152
|
+
}
|
153
|
+
return t6;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
}
|
86
157
|
function EntityHistoryEntry({
|
87
158
|
actions,
|
88
|
-
disabled,
|
89
159
|
hover,
|
90
160
|
collection: collectionProp,
|
91
161
|
previewKeys,
|
92
162
|
onClick,
|
93
163
|
size,
|
94
|
-
entity
|
164
|
+
entity,
|
165
|
+
previousValues
|
95
166
|
}) {
|
96
167
|
const authController = useAuthController();
|
97
168
|
const customizationController = useCustomizationController();
|
@@ -144,17 +215,21 @@ function EntityHistoryEntry({
|
|
144
215
|
/* @__PURE__ */ jsx("div", { className: "flex flex-col grow w-full m-1 shrink min-w-0", children: previewKeys && previewKeys.map((key) => {
|
145
216
|
const childProperty = getPropertyInPath(resolvedCollection.properties, key);
|
146
217
|
const valueInPath = getValueInPath(entity.values, key);
|
218
|
+
const previousValueInPath = previousValues ? getValueInPath(previousValues, key) : void 0;
|
147
219
|
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
220
|
return /* @__PURE__ */ jsxs("div", { className: "flex w-full my-1 items-center", children: [
|
149
221
|
/* @__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__ */
|
222
|
+
/* @__PURE__ */ jsxs("div", { className: "w-4/5", children: [
|
223
|
+
previousValueInPath !== void 0 && previousValueInPath !== valueInPath && /* @__PURE__ */ jsx(PreviousValueView, { previousValueInPath, childProperty }, key),
|
224
|
+
element
|
225
|
+
] })
|
151
226
|
] }, "ref_prev_" + key);
|
152
227
|
}) })
|
153
228
|
] })
|
154
229
|
] });
|
155
230
|
}
|
156
231
|
function EntityHistoryView(t0) {
|
157
|
-
const $ = c(
|
232
|
+
const $ = c(58);
|
158
233
|
const {
|
159
234
|
entity,
|
160
235
|
collection,
|
@@ -370,7 +445,8 @@ function EntityHistoryView(t0) {
|
|
370
445
|
if ($[30] !== collection || $[31] !== dirty || $[32] !== snackbarController) {
|
371
446
|
t112 = (revision, index) => {
|
372
447
|
const previewKeys = revision.values?.__metadata?.changed_fields;
|
373
|
-
|
448
|
+
const previousValues = revision.values?.__metadata?.previous_values;
|
449
|
+
return /* @__PURE__ */ jsx("div", { className: "flex flex-cols gap-2 w-full", children: /* @__PURE__ */ jsx(EntityHistoryEntry, { size: "large", entity: revision, collection, previewKeys, previousValues, actions: /* @__PURE__ */ jsx(Tooltip, { title: "Revert to this version", className: "m-2 grow-0 self-start", children: /* @__PURE__ */ jsx(IconButton, { onClick: () => {
|
374
450
|
if (dirty) {
|
375
451
|
snackbarController.open({
|
376
452
|
message: "Please save or discard your changes before reverting",
|
@@ -454,27 +530,38 @@ function EntityHistoryView(t0) {
|
|
454
530
|
t16 = $[46];
|
455
531
|
}
|
456
532
|
let t17;
|
457
|
-
if ($[47] !==
|
458
|
-
t17 = /* @__PURE__ */ jsx(
|
459
|
-
$[47] =
|
460
|
-
$[48] =
|
461
|
-
$[49] =
|
533
|
+
if ($[47] !== collection || $[48] !== entity?.path || $[49] !== revertVersionDialog) {
|
534
|
+
t17 = revertVersionDialog ? /* @__PURE__ */ jsx(EntityView, { entity: revertVersionDialog, collection, path: entity?.path }) : null;
|
535
|
+
$[47] = collection;
|
536
|
+
$[48] = entity?.path;
|
537
|
+
$[49] = revertVersionDialog;
|
538
|
+
$[50] = t17;
|
462
539
|
} else {
|
463
|
-
t17 = $[
|
540
|
+
t17 = $[50];
|
464
541
|
}
|
465
542
|
let t18;
|
466
|
-
if ($[
|
467
|
-
t18 = /* @__PURE__ */
|
543
|
+
if ($[51] !== t13 || $[52] !== t14 || $[53] !== t17) {
|
544
|
+
t18 = /* @__PURE__ */ jsx(ErrorBoundary, { children: /* @__PURE__ */ jsx(ConfirmationDialog, { open: t13, onAccept: t14, onCancel: t15, title: t16, body: t17 }) });
|
545
|
+
$[51] = t13;
|
546
|
+
$[52] = t14;
|
547
|
+
$[53] = t17;
|
548
|
+
$[54] = t18;
|
549
|
+
} else {
|
550
|
+
t18 = $[54];
|
551
|
+
}
|
552
|
+
let t19;
|
553
|
+
if ($[55] !== t12 || $[56] !== t18) {
|
554
|
+
t19 = /* @__PURE__ */ jsxs("div", { ref: containerRef, className: t7, children: [
|
468
555
|
t12,
|
469
|
-
|
556
|
+
t18
|
470
557
|
] });
|
471
|
-
$[
|
472
|
-
$[
|
473
|
-
$[
|
558
|
+
$[55] = t12;
|
559
|
+
$[56] = t18;
|
560
|
+
$[57] = t19;
|
474
561
|
} else {
|
475
|
-
|
562
|
+
t19 = $[57];
|
476
563
|
}
|
477
|
-
return
|
564
|
+
return t19;
|
478
565
|
}
|
479
566
|
const entityHistoryCallbacks = {
|
480
567
|
onSaveSuccess: async (props) => {
|
@@ -485,6 +572,7 @@ const entityHistoryCallbacks = {
|
|
485
572
|
values: {
|
486
573
|
...props.values,
|
487
574
|
__metadata: {
|
575
|
+
previous_values: props.previousValues,
|
488
576
|
changed_fields: changedFields,
|
489
577
|
updated_on: /* @__PURE__ */ new Date(),
|
490
578
|
updated_by: uid
|
package/dist/index.es.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.es.js","sources":["../src/HistoryControllerProvider.tsx","../src/components/UserChip.tsx","../src/components/EntityHistoryEntry.tsx","../src/components/EntityHistoryView.tsx","../src/entity_history_callbacks.ts","../src/useEntityHistoryPlugin.tsx"],"sourcesContent":["import React, { PropsWithChildren, useContext } from \"react\";\nimport equal from \"react-fast-compare\"\n\nimport { User } from \"@firecms/core\";\n\nexport type HistoryConfigController = {\n /**\n * Function to get a user by uid.\n * @param uid\n */\n getUser?: (uid: string) => User | null;\n}\n\nexport const HistoryControllerContext = React.createContext<HistoryConfigController>({} as any);\nexport const useHistoryController = (): HistoryConfigController => useContext(HistoryControllerContext);\n\n\nexport interface HistoryControllerProviderProps {\n\n getUser?: (uid: string) => User | null;\n\n}\n\nexport const HistoryControllerProvider = React.memo(\n function HistoryControllerProvider({\n children,\n getUser,\n }: PropsWithChildren<HistoryControllerProviderProps>) {\n\n return (\n <HistoryControllerContext.Provider\n value={{\n getUser,\n }}>\n\n {children}\n\n </HistoryControllerContext.Provider>\n );\n }, equal);\n","import { User } from \"@firecms/core\";\nimport { Chip, Tooltip } from \"@firecms/ui\";\n\nexport function UserChip({ user }: { user: User }) {\n return (\n <Tooltip title={user.email ?? user.uid}>\n <Chip size={\"small\"} className={\"flex items-center\"}>\n {user.photoURL && <img\n className={\"rounded-full w-6 h-6 mr-2\"}\n src={user.photoURL} alt={user.displayName ?? \"User picture\"}/>}\n <span>{user.displayName ?? user.email ?? user.uid}</span>\n </Chip>\n </Tooltip>\n );\n}\n","import * as React from \"react\";\n\nimport { Chip, cls, defaultBorderMixin, IconButton, KeyboardTabIcon, Tooltip, Typography } from \"@firecms/ui\";\nimport {\n Entity,\n EntityCollection,\n getPropertyInPath,\n getValueInPath,\n PreviewSize,\n PropertyPreview,\n resolveCollection,\n ResolvedProperty,\n SkeletonPropertyComponent,\n useAuthController,\n useCustomizationController,\n useNavigationController,\n useSideEntityController\n} from \"@firecms/core\";\nimport { useHistoryController } from \"../HistoryControllerProvider\";\nimport { UserChip } from \"./UserChip\";\n\nexport type EntityPreviewProps = {\n size: PreviewSize,\n actions?: React.ReactNode,\n collection?: EntityCollection,\n hover?: boolean;\n previewKeys?: string[],\n disabled?: boolean,\n entity: Entity<any>,\n onClick?: (e: React.SyntheticEvent) => void;\n};\n\n/**\n * This view is used to display a preview of an entity.\n * It is used by default in reference fields and whenever a reference is displayed.\n */\nexport function EntityHistoryEntry({\n actions,\n disabled,\n hover,\n collection: collectionProp,\n previewKeys,\n onClick,\n size,\n entity\n }: EntityPreviewProps) {\n\n const authController = useAuthController();\n const customizationController = useCustomizationController();\n\n const navigationController = useNavigationController();\n const sideEntityController = useSideEntityController();\n\n const collection = collectionProp ?? navigationController.getCollection(entity.path);\n const updatedOn = entity.values?.[\"__metadata\"]?.[\"updated_on\"];\n if (!collection) {\n throw Error(`Couldn't find the corresponding collection view for the path: ${entity.path}`);\n }\n\n const updatedBy = entity.values?.[\"__metadata\"]?.[\"updated_by\"];\n const { getUser } = useHistoryController();\n const user = getUser?.(updatedBy);\n\n const resolvedCollection = React.useMemo(() => resolveCollection({\n collection,\n path: entity.path,\n values: entity.values,\n propertyConfigs: customizationController.propertyConfigs,\n authController\n }), [collection]);\n\n return <div className={\"w-full flex flex-col gap-2 mt-4\"}>\n <div className={\"ml-4 flex items-center gap-4\"}>\n <Typography variant={\"body2\"} color={\"secondary\"}>{updatedOn.toLocaleString()}</Typography>\n {!user && updatedBy && <Chip size={\"small\"}>{updatedBy}</Chip>}\n {user && <UserChip user={user}/>}\n </div>\n <div\n className={cls(\n \"bg-white dark:bg-surface-900\",\n \"min-h-[42px]\",\n \"w-full\",\n \"items-center\",\n hover ? \"hover:bg-surface-accent-50 dark:hover:bg-surface-800 group-hover:bg-surface-accent-50 dark:group-hover:bg-surface-800\" : \"\",\n size === \"small\" ? \"p-1\" : \"px-2 py-1\",\n \"flex border rounded-lg\",\n onClick ? \"cursor-pointer\" : \"\",\n defaultBorderMixin\n )}>\n\n\n {actions}\n\n {entity &&\n <Tooltip title={\"See details for this revision\"}\n className={\"my-2 grow-0 shrink-0 self-start\"}>\n <IconButton\n color={\"inherit\"}\n className={\"\"}\n onClick={(e) => {\n\n sideEntityController.open({\n entityId: entity.id,\n path: entity.path,\n allowFullScreen: false,\n collection: {\n ...collection,\n subcollections: undefined,\n entityViews: undefined,\n permissions: {\n create: false,\n delete: false,\n edit: false,\n read: true\n }\n },\n updateUrl: true\n });\n }}>\n <KeyboardTabIcon/>\n </IconButton>\n </Tooltip>}\n\n <div className={\"flex flex-col grow w-full m-1 shrink min-w-0\"}>\n\n {previewKeys && previewKeys.map((key) => {\n const childProperty = getPropertyInPath(resolvedCollection.properties, key);\n\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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"}
|
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 {\n Chip,\n cls,\n defaultBorderMixin,\n DescriptionIcon,\n IconButton, KeyboardBackspaceIcon,\n KeyboardTabIcon,\n Tooltip,\n Typography\n} from \"@firecms/ui\";\nimport {\n Entity,\n EntityCollection,\n EntityValues,\n getPropertyInPath,\n getValueInPath,\n PreviewSize,\n Property,\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 entity: Entity<any>,\n previousValues?: EntityValues<any>;\n onClick?: (e: React.SyntheticEvent) => void;\n};\n\nfunction PreviousValueView({\n previousValueInPath,\n childProperty,\n key\n }: {\n previousValueInPath: any,\n childProperty: Property,\n key: string\n}) {\n if (typeof previousValueInPath === \"string\" || typeof previousValueInPath === \"number\") {\n return <Typography variant={\"caption\"} color={\"secondary\"} className=\"line-through\">\n {previousValueInPath}\n </Typography>;\n } else if (typeof previousValueInPath === \"boolean\") {\n return <Typography variant={\"caption\"} color={\"secondary\"} className=\"line-through\">\n {previousValueInPath ? \"true\" : \"false\"}\n </Typography>;\n\n } else {\n return <Tooltip\n side={\"left\"}\n title={<div className={\"flex flex-col gap-2\"}>\n <Typography variant={\"caption\"} color={\"secondary\"}>\n Previous value\n </Typography>\n <PropertyPreview\n propertyKey={key as string}\n value={previousValueInPath}\n property={childProperty as ResolvedProperty}\n size={\"small\"}/>\n </div>}>\n <KeyboardBackspaceIcon size={\"smallest\"} color={\"disabled\"} className={\"mb-1\"}/>\n </Tooltip>\n }\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 hover,\n collection: collectionProp,\n previewKeys,\n onClick,\n size,\n entity,\n previousValues\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 previousValueInPath = previousValues ? getValueInPath(previousValues, key) : undefined;\n\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 {previousValueInPath !== undefined && previousValueInPath !== valueInPath &&\n <PreviousValueView previousValueInPath={previousValueInPath}\n childProperty={childProperty as ResolvedProperty}\n key={key}/>\n }\n {element}\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 EntityView,\n ErrorBoundary,\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 const previousValues: object | undefined = revision.values?.[\"__metadata\"]?.[\"previous_values\"];\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 previousValues={previousValues}\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 <ErrorBoundary>\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 body={revertVersionDialog ?\n <EntityView entity={revertVersionDialog}\n collection={collection}\n path={entity?.path}/> : null}/>\n </ErrorBoundary>\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 previous_values: props.previousValues,\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","PreviousValueView","previousValueInPath","childProperty","key","Symbol","for","EntityHistoryEntry","actions","hover","collection","collectionProp","previewKeys","onClick","size","entity","previousValues","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","getPropertyInPath","properties","valueInPath","getValueInPath","element","JSON","stringify","EntityHistoryView","formContext","snackbarController","useSnackbarController","dirty","formex","dataSource","useDataSource","pathAndId","revertVersionDialog","setRevertVersionDialog","useState","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","previous_values","t12","t13","Boolean","t14","t15","t16","t17","t18","t19","entityHistoryCallbacks","onSaveSuccess","props","changedFields","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
@@ -97,15 +97,86 @@
|
|
97
97
|
}
|
98
98
|
return t6;
|
99
99
|
}
|
100
|
+
function PreviousValueView(t0) {
|
101
|
+
const $ = reactCompilerRuntime.c(12);
|
102
|
+
const {
|
103
|
+
previousValueInPath,
|
104
|
+
childProperty,
|
105
|
+
key
|
106
|
+
} = t0;
|
107
|
+
if (typeof previousValueInPath === "string" || typeof previousValueInPath === "number") {
|
108
|
+
let t1;
|
109
|
+
if ($[0] !== previousValueInPath) {
|
110
|
+
t1 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", className: "line-through", children: previousValueInPath });
|
111
|
+
$[0] = previousValueInPath;
|
112
|
+
$[1] = t1;
|
113
|
+
} else {
|
114
|
+
t1 = $[1];
|
115
|
+
}
|
116
|
+
return t1;
|
117
|
+
} else {
|
118
|
+
if (typeof previousValueInPath === "boolean") {
|
119
|
+
const t1 = previousValueInPath ? "true" : "false";
|
120
|
+
let t2;
|
121
|
+
if ($[2] !== t1) {
|
122
|
+
t2 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", className: "line-through", children: t1 });
|
123
|
+
$[2] = t1;
|
124
|
+
$[3] = t2;
|
125
|
+
} else {
|
126
|
+
t2 = $[3];
|
127
|
+
}
|
128
|
+
return t2;
|
129
|
+
} else {
|
130
|
+
let t1;
|
131
|
+
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
|
132
|
+
t1 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", children: "Previous value" });
|
133
|
+
$[4] = t1;
|
134
|
+
} else {
|
135
|
+
t1 = $[4];
|
136
|
+
}
|
137
|
+
const t2 = key;
|
138
|
+
const t3 = childProperty;
|
139
|
+
let t4;
|
140
|
+
if ($[5] !== previousValueInPath || $[6] !== t2 || $[7] !== t3) {
|
141
|
+
t4 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
142
|
+
t1,
|
143
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.PropertyPreview, { propertyKey: t2, value: previousValueInPath, property: t3, size: "small" })
|
144
|
+
] });
|
145
|
+
$[5] = previousValueInPath;
|
146
|
+
$[6] = t2;
|
147
|
+
$[7] = t3;
|
148
|
+
$[8] = t4;
|
149
|
+
} else {
|
150
|
+
t4 = $[8];
|
151
|
+
}
|
152
|
+
let t5;
|
153
|
+
if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
|
154
|
+
t5 = /* @__PURE__ */ jsxRuntime.jsx(ui.KeyboardBackspaceIcon, { size: "smallest", color: "disabled", className: "mb-1" });
|
155
|
+
$[9] = t5;
|
156
|
+
} else {
|
157
|
+
t5 = $[9];
|
158
|
+
}
|
159
|
+
let t6;
|
160
|
+
if ($[10] !== t4) {
|
161
|
+
t6 = /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { side: "left", title: t4, children: t5 });
|
162
|
+
$[10] = t4;
|
163
|
+
$[11] = t6;
|
164
|
+
} else {
|
165
|
+
t6 = $[11];
|
166
|
+
}
|
167
|
+
return t6;
|
168
|
+
}
|
169
|
+
}
|
170
|
+
}
|
100
171
|
function EntityHistoryEntry({
|
101
172
|
actions,
|
102
|
-
disabled,
|
103
173
|
hover,
|
104
174
|
collection: collectionProp,
|
105
175
|
previewKeys,
|
106
176
|
onClick,
|
107
177
|
size,
|
108
|
-
entity
|
178
|
+
entity,
|
179
|
+
previousValues
|
109
180
|
}) {
|
110
181
|
const authController = core.useAuthController();
|
111
182
|
const customizationController = core.useCustomizationController();
|
@@ -158,17 +229,21 @@
|
|
158
229
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col grow w-full m-1 shrink min-w-0", children: previewKeys && previewKeys.map((key) => {
|
159
230
|
const childProperty = core.getPropertyInPath(resolvedCollection.properties, key);
|
160
231
|
const valueInPath = core.getValueInPath(entity.values, key);
|
232
|
+
const previousValueInPath = previousValues ? core.getValueInPath(previousValues, key) : void 0;
|
161
233
|
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
234
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full my-1 items-center", children: [
|
163
235
|
/* @__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.
|
236
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-4/5", children: [
|
237
|
+
previousValueInPath !== void 0 && previousValueInPath !== valueInPath && /* @__PURE__ */ jsxRuntime.jsx(PreviousValueView, { previousValueInPath, childProperty }, key),
|
238
|
+
element
|
239
|
+
] })
|
165
240
|
] }, "ref_prev_" + key);
|
166
241
|
}) })
|
167
242
|
] })
|
168
243
|
] });
|
169
244
|
}
|
170
245
|
function EntityHistoryView(t0) {
|
171
|
-
const $ = reactCompilerRuntime.c(
|
246
|
+
const $ = reactCompilerRuntime.c(58);
|
172
247
|
const {
|
173
248
|
entity,
|
174
249
|
collection,
|
@@ -384,7 +459,8 @@
|
|
384
459
|
if ($[30] !== collection || $[31] !== dirty || $[32] !== snackbarController) {
|
385
460
|
t112 = (revision, index) => {
|
386
461
|
const previewKeys = revision.values?.__metadata?.changed_fields;
|
387
|
-
|
462
|
+
const previousValues = revision.values?.__metadata?.previous_values;
|
463
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-cols gap-2 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(EntityHistoryEntry, { size: "large", entity: revision, collection, previewKeys, previousValues, 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: () => {
|
388
464
|
if (dirty) {
|
389
465
|
snackbarController.open({
|
390
466
|
message: "Please save or discard your changes before reverting",
|
@@ -468,27 +544,38 @@
|
|
468
544
|
t16 = $[46];
|
469
545
|
}
|
470
546
|
let t17;
|
471
|
-
if ($[47] !==
|
472
|
-
t17 = /* @__PURE__ */ jsxRuntime.jsx(core.
|
473
|
-
$[47] =
|
474
|
-
$[48] =
|
475
|
-
$[49] =
|
547
|
+
if ($[47] !== collection || $[48] !== entity?.path || $[49] !== revertVersionDialog) {
|
548
|
+
t17 = revertVersionDialog ? /* @__PURE__ */ jsxRuntime.jsx(core.EntityView, { entity: revertVersionDialog, collection, path: entity?.path }) : null;
|
549
|
+
$[47] = collection;
|
550
|
+
$[48] = entity?.path;
|
551
|
+
$[49] = revertVersionDialog;
|
552
|
+
$[50] = t17;
|
476
553
|
} else {
|
477
|
-
t17 = $[
|
554
|
+
t17 = $[50];
|
478
555
|
}
|
479
556
|
let t18;
|
480
|
-
if ($[
|
481
|
-
t18 = /* @__PURE__ */ jsxRuntime.
|
557
|
+
if ($[51] !== t13 || $[52] !== t14 || $[53] !== t17) {
|
558
|
+
t18 = /* @__PURE__ */ jsxRuntime.jsx(core.ErrorBoundary, { children: /* @__PURE__ */ jsxRuntime.jsx(core.ConfirmationDialog, { open: t13, onAccept: t14, onCancel: t15, title: t16, body: t17 }) });
|
559
|
+
$[51] = t13;
|
560
|
+
$[52] = t14;
|
561
|
+
$[53] = t17;
|
562
|
+
$[54] = t18;
|
563
|
+
} else {
|
564
|
+
t18 = $[54];
|
565
|
+
}
|
566
|
+
let t19;
|
567
|
+
if ($[55] !== t12 || $[56] !== t18) {
|
568
|
+
t19 = /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: t7, children: [
|
482
569
|
t12,
|
483
|
-
|
570
|
+
t18
|
484
571
|
] });
|
485
|
-
$[
|
486
|
-
$[
|
487
|
-
$[
|
572
|
+
$[55] = t12;
|
573
|
+
$[56] = t18;
|
574
|
+
$[57] = t19;
|
488
575
|
} else {
|
489
|
-
|
576
|
+
t19 = $[57];
|
490
577
|
}
|
491
|
-
return
|
578
|
+
return t19;
|
492
579
|
}
|
493
580
|
const entityHistoryCallbacks = {
|
494
581
|
onSaveSuccess: async (props) => {
|
@@ -499,6 +586,7 @@
|
|
499
586
|
values: {
|
500
587
|
...props.values,
|
501
588
|
__metadata: {
|
589
|
+
previous_values: props.previousValues,
|
502
590
|
changed_fields: changedFields,
|
503
591
|
updated_on: /* @__PURE__ */ new Date(),
|
504
592
|
updated_by: uid
|
package/dist/index.umd.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.umd.js","sources":["../src/HistoryControllerProvider.tsx","../src/components/UserChip.tsx","../src/components/EntityHistoryEntry.tsx","../src/components/EntityHistoryView.tsx","../src/entity_history_callbacks.ts","../src/useEntityHistoryPlugin.tsx"],"sourcesContent":["import React, { PropsWithChildren, useContext } from \"react\";\nimport equal from \"react-fast-compare\"\n\nimport { User } from \"@firecms/core\";\n\nexport type HistoryConfigController = {\n /**\n * Function to get a user by uid.\n * @param uid\n */\n getUser?: (uid: string) => User | null;\n}\n\nexport const HistoryControllerContext = React.createContext<HistoryConfigController>({} as any);\nexport const useHistoryController = (): HistoryConfigController => useContext(HistoryControllerContext);\n\n\nexport interface HistoryControllerProviderProps {\n\n getUser?: (uid: string) => User | null;\n\n}\n\nexport const HistoryControllerProvider = React.memo(\n function HistoryControllerProvider({\n children,\n getUser,\n }: PropsWithChildren<HistoryControllerProviderProps>) {\n\n return (\n <HistoryControllerContext.Provider\n value={{\n getUser,\n }}>\n\n {children}\n\n </HistoryControllerContext.Provider>\n );\n }, equal);\n","import { User } from \"@firecms/core\";\nimport { Chip, Tooltip } from \"@firecms/ui\";\n\nexport function UserChip({ user }: { user: User }) {\n return (\n <Tooltip title={user.email ?? user.uid}>\n <Chip size={\"small\"} className={\"flex items-center\"}>\n {user.photoURL && <img\n className={\"rounded-full w-6 h-6 mr-2\"}\n src={user.photoURL} alt={user.displayName ?? \"User picture\"}/>}\n <span>{user.displayName ?? user.email ?? user.uid}</span>\n </Chip>\n </Tooltip>\n );\n}\n","import * as React from \"react\";\n\nimport { Chip, cls, defaultBorderMixin, IconButton, KeyboardTabIcon, Tooltip, Typography } from \"@firecms/ui\";\nimport {\n Entity,\n EntityCollection,\n getPropertyInPath,\n getValueInPath,\n PreviewSize,\n PropertyPreview,\n resolveCollection,\n ResolvedProperty,\n SkeletonPropertyComponent,\n useAuthController,\n useCustomizationController,\n useNavigationController,\n useSideEntityController\n} from \"@firecms/core\";\nimport { useHistoryController } from \"../HistoryControllerProvider\";\nimport { UserChip } from \"./UserChip\";\n\nexport type EntityPreviewProps = {\n size: PreviewSize,\n actions?: React.ReactNode,\n collection?: EntityCollection,\n hover?: boolean;\n previewKeys?: string[],\n disabled?: boolean,\n entity: Entity<any>,\n onClick?: (e: React.SyntheticEvent) => void;\n};\n\n/**\n * This view is used to display a preview of an entity.\n * It is used by default in reference fields and whenever a reference is displayed.\n */\nexport function EntityHistoryEntry({\n actions,\n disabled,\n hover,\n collection: collectionProp,\n previewKeys,\n onClick,\n size,\n entity\n }: EntityPreviewProps) {\n\n const authController = useAuthController();\n const customizationController = useCustomizationController();\n\n const navigationController = useNavigationController();\n const sideEntityController = useSideEntityController();\n\n const collection = collectionProp ?? navigationController.getCollection(entity.path);\n const updatedOn = entity.values?.[\"__metadata\"]?.[\"updated_on\"];\n if (!collection) {\n throw Error(`Couldn't find the corresponding collection view for the path: ${entity.path}`);\n }\n\n const updatedBy = entity.values?.[\"__metadata\"]?.[\"updated_by\"];\n const { getUser } = useHistoryController();\n const user = getUser?.(updatedBy);\n\n const resolvedCollection = React.useMemo(() => resolveCollection({\n collection,\n path: entity.path,\n values: entity.values,\n propertyConfigs: customizationController.propertyConfigs,\n authController\n }), [collection]);\n\n return <div className={\"w-full flex flex-col gap-2 mt-4\"}>\n <div className={\"ml-4 flex items-center gap-4\"}>\n <Typography variant={\"body2\"} color={\"secondary\"}>{updatedOn.toLocaleString()}</Typography>\n {!user && updatedBy && <Chip size={\"small\"}>{updatedBy}</Chip>}\n {user && <UserChip user={user}/>}\n </div>\n <div\n className={cls(\n \"bg-white dark:bg-surface-900\",\n \"min-h-[42px]\",\n \"w-full\",\n \"items-center\",\n hover ? \"hover:bg-surface-accent-50 dark:hover:bg-surface-800 group-hover:bg-surface-accent-50 dark:group-hover:bg-surface-800\" : \"\",\n size === \"small\" ? \"p-1\" : \"px-2 py-1\",\n \"flex border rounded-lg\",\n onClick ? \"cursor-pointer\" : \"\",\n defaultBorderMixin\n )}>\n\n\n {actions}\n\n {entity &&\n <Tooltip title={\"See details for this revision\"}\n className={\"my-2 grow-0 shrink-0 self-start\"}>\n <IconButton\n color={\"inherit\"}\n className={\"\"}\n onClick={(e) => {\n\n sideEntityController.open({\n entityId: entity.id,\n path: entity.path,\n allowFullScreen: false,\n collection: {\n ...collection,\n subcollections: undefined,\n entityViews: undefined,\n permissions: {\n create: false,\n delete: false,\n edit: false,\n read: true\n }\n },\n updateUrl: true\n });\n }}>\n <KeyboardTabIcon/>\n </IconButton>\n </Tooltip>}\n\n <div className={\"flex flex-col grow w-full m-1 shrink min-w-0\"}>\n\n {previewKeys && previewKeys.map((key) => {\n const childProperty = getPropertyInPath(resolvedCollection.properties, key);\n\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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"}
|
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 {\n Chip,\n cls,\n defaultBorderMixin,\n DescriptionIcon,\n IconButton, KeyboardBackspaceIcon,\n KeyboardTabIcon,\n Tooltip,\n Typography\n} from \"@firecms/ui\";\nimport {\n Entity,\n EntityCollection,\n EntityValues,\n getPropertyInPath,\n getValueInPath,\n PreviewSize,\n Property,\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 entity: Entity<any>,\n previousValues?: EntityValues<any>;\n onClick?: (e: React.SyntheticEvent) => void;\n};\n\nfunction PreviousValueView({\n previousValueInPath,\n childProperty,\n key\n }: {\n previousValueInPath: any,\n childProperty: Property,\n key: string\n}) {\n if (typeof previousValueInPath === \"string\" || typeof previousValueInPath === \"number\") {\n return <Typography variant={\"caption\"} color={\"secondary\"} className=\"line-through\">\n {previousValueInPath}\n </Typography>;\n } else if (typeof previousValueInPath === \"boolean\") {\n return <Typography variant={\"caption\"} color={\"secondary\"} className=\"line-through\">\n {previousValueInPath ? \"true\" : \"false\"}\n </Typography>;\n\n } else {\n return <Tooltip\n side={\"left\"}\n title={<div className={\"flex flex-col gap-2\"}>\n <Typography variant={\"caption\"} color={\"secondary\"}>\n Previous value\n </Typography>\n <PropertyPreview\n propertyKey={key as string}\n value={previousValueInPath}\n property={childProperty as ResolvedProperty}\n size={\"small\"}/>\n </div>}>\n <KeyboardBackspaceIcon size={\"smallest\"} color={\"disabled\"} className={\"mb-1\"}/>\n </Tooltip>\n }\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 hover,\n collection: collectionProp,\n previewKeys,\n onClick,\n size,\n entity,\n previousValues\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 previousValueInPath = previousValues ? getValueInPath(previousValues, key) : undefined;\n\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 {previousValueInPath !== undefined && previousValueInPath !== valueInPath &&\n <PreviousValueView previousValueInPath={previousValueInPath}\n childProperty={childProperty as ResolvedProperty}\n key={key}/>\n }\n {element}\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 EntityView,\n ErrorBoundary,\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 const previousValues: object | undefined = revision.values?.[\"__metadata\"]?.[\"previous_values\"];\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 previousValues={previousValues}\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 <ErrorBoundary>\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 body={revertVersionDialog ?\n <EntityView entity={revertVersionDialog}\n collection={collection}\n path={entity?.path}/> : null}/>\n </ErrorBoundary>\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 previous_values: props.previousValues,\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","PreviousValueView","previousValueInPath","childProperty","key","Typography","Symbol","for","PropertyPreview","KeyboardBackspaceIcon","EntityHistoryEntry","actions","hover","collection","collectionProp","previewKeys","onClick","size","entity","previousValues","authController","useAuthController","customizationController","useCustomizationController","navigationController","useNavigationController","sideEntityController","useSideEntityController","getCollection","path","updatedOn","values","Error","updatedBy","resolvedCollection","useMemo","resolveCollection","propertyConfigs","toLocaleString","cls","defaultBorderMixin","IconButton","e","open","entityId","id","allowFullScreen","subcollections","undefined","entityViews","permissions","create","delete","edit","read","updateUrl","KeyboardTabIcon","map","getPropertyInPath","properties","valueInPath","getValueInPath","element","SkeletonPropertyComponent","JSON","stringify","EntityHistoryView","formContext","snackbarController","useSnackbarController","dirty","formex","dataSource","useDataSource","pathAndId","revertVersionDialog","setRevertVersionDialog","useState","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","previous_values","HistoryIcon","t12","t13","Boolean","t14","t15","t16","t17","EntityView","t18","ErrorBoundary","ConfirmationDialog","t19","entityHistoryCallbacks","onSaveSuccess","props","changedFields","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.
|
4
|
+
"version": "3.0.0-canary.253",
|
5
5
|
"access": "public",
|
6
6
|
"main": "./dist/index.umd.js",
|
7
7
|
"module": "./dist/index.es.js",
|
8
8
|
"types": "./dist/index.d.ts",
|
9
9
|
"source": "src/index.ts",
|
10
10
|
"dependencies": {
|
11
|
-
"@firecms/core": "^3.0.0-canary.
|
12
|
-
"@firecms/formex": "^3.0.0-canary.
|
13
|
-
"@firecms/ui": "^3.0.0-canary.
|
11
|
+
"@firecms/core": "^3.0.0-canary.253",
|
12
|
+
"@firecms/formex": "^3.0.0-canary.253",
|
13
|
+
"@firecms/ui": "^3.0.0-canary.253"
|
14
14
|
},
|
15
15
|
"peerDependencies": {
|
16
16
|
"react": ">=18.0.0",
|
@@ -82,5 +82,5 @@
|
|
82
82
|
"publishConfig": {
|
83
83
|
"access": "public"
|
84
84
|
},
|
85
|
-
"gitHead": "
|
85
|
+
"gitHead": "c4dff639fcd32ba5d706f5b8cf92692af6e94893"
|
86
86
|
}
|
@@ -1,12 +1,23 @@
|
|
1
1
|
import * as React from "react";
|
2
2
|
|
3
|
-
import {
|
3
|
+
import {
|
4
|
+
Chip,
|
5
|
+
cls,
|
6
|
+
defaultBorderMixin,
|
7
|
+
DescriptionIcon,
|
8
|
+
IconButton, KeyboardBackspaceIcon,
|
9
|
+
KeyboardTabIcon,
|
10
|
+
Tooltip,
|
11
|
+
Typography
|
12
|
+
} from "@firecms/ui";
|
4
13
|
import {
|
5
14
|
Entity,
|
6
15
|
EntityCollection,
|
16
|
+
EntityValues,
|
7
17
|
getPropertyInPath,
|
8
18
|
getValueInPath,
|
9
19
|
PreviewSize,
|
20
|
+
Property,
|
10
21
|
PropertyPreview,
|
11
22
|
resolveCollection,
|
12
23
|
ResolvedProperty,
|
@@ -25,24 +36,60 @@ export type EntityPreviewProps = {
|
|
25
36
|
collection?: EntityCollection,
|
26
37
|
hover?: boolean;
|
27
38
|
previewKeys?: string[],
|
28
|
-
disabled?: boolean,
|
29
39
|
entity: Entity<any>,
|
40
|
+
previousValues?: EntityValues<any>;
|
30
41
|
onClick?: (e: React.SyntheticEvent) => void;
|
31
42
|
};
|
32
43
|
|
44
|
+
function PreviousValueView({
|
45
|
+
previousValueInPath,
|
46
|
+
childProperty,
|
47
|
+
key
|
48
|
+
}: {
|
49
|
+
previousValueInPath: any,
|
50
|
+
childProperty: Property,
|
51
|
+
key: string
|
52
|
+
}) {
|
53
|
+
if (typeof previousValueInPath === "string" || typeof previousValueInPath === "number") {
|
54
|
+
return <Typography variant={"caption"} color={"secondary"} className="line-through">
|
55
|
+
{previousValueInPath}
|
56
|
+
</Typography>;
|
57
|
+
} else if (typeof previousValueInPath === "boolean") {
|
58
|
+
return <Typography variant={"caption"} color={"secondary"} className="line-through">
|
59
|
+
{previousValueInPath ? "true" : "false"}
|
60
|
+
</Typography>;
|
61
|
+
|
62
|
+
} else {
|
63
|
+
return <Tooltip
|
64
|
+
side={"left"}
|
65
|
+
title={<div className={"flex flex-col gap-2"}>
|
66
|
+
<Typography variant={"caption"} color={"secondary"}>
|
67
|
+
Previous value
|
68
|
+
</Typography>
|
69
|
+
<PropertyPreview
|
70
|
+
propertyKey={key as string}
|
71
|
+
value={previousValueInPath}
|
72
|
+
property={childProperty as ResolvedProperty}
|
73
|
+
size={"small"}/>
|
74
|
+
</div>}>
|
75
|
+
<KeyboardBackspaceIcon size={"smallest"} color={"disabled"} className={"mb-1"}/>
|
76
|
+
</Tooltip>
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
33
80
|
/**
|
34
81
|
* This view is used to display a preview of an entity.
|
35
82
|
* It is used by default in reference fields and whenever a reference is displayed.
|
36
83
|
*/
|
37
84
|
export function EntityHistoryEntry({
|
38
85
|
actions,
|
39
|
-
disabled,
|
40
86
|
hover,
|
41
87
|
collection: collectionProp,
|
42
88
|
previewKeys,
|
43
89
|
onClick,
|
44
90
|
size,
|
45
|
-
entity
|
91
|
+
entity,
|
92
|
+
previousValues
|
46
93
|
}: EntityPreviewProps) {
|
47
94
|
|
48
95
|
const authController = useAuthController();
|
@@ -127,6 +174,8 @@ export function EntityHistoryEntry({
|
|
127
174
|
const childProperty = getPropertyInPath(resolvedCollection.properties, key);
|
128
175
|
|
129
176
|
const valueInPath = getValueInPath(entity.values, key);
|
177
|
+
const previousValueInPath = previousValues ? getValueInPath(previousValues, key) : undefined;
|
178
|
+
|
130
179
|
const element = childProperty ? (entity
|
131
180
|
? <PropertyPreview
|
132
181
|
propertyKey={key as string}
|
@@ -148,9 +197,12 @@ export function EntityHistoryEntry({
|
|
148
197
|
{key}
|
149
198
|
</Typography>
|
150
199
|
<div className="w-4/5">
|
151
|
-
{
|
152
|
-
|
200
|
+
{previousValueInPath !== undefined && previousValueInPath !== valueInPath &&
|
201
|
+
<PreviousValueView previousValueInPath={previousValueInPath}
|
202
|
+
childProperty={childProperty as ResolvedProperty}
|
203
|
+
key={key}/>
|
153
204
|
}
|
205
|
+
{element}
|
154
206
|
</div>
|
155
207
|
</div>
|
156
208
|
);
|
@@ -3,6 +3,8 @@ import {
|
|
3
3
|
ConfirmationDialog,
|
4
4
|
Entity,
|
5
5
|
EntityCustomViewParams,
|
6
|
+
EntityView,
|
7
|
+
ErrorBoundary,
|
6
8
|
useAuthController,
|
7
9
|
useDataSource,
|
8
10
|
useSnackbarController
|
@@ -183,11 +185,13 @@ export function EntityHistoryView({
|
|
183
185
|
|
184
186
|
{revisions.map((revision, index) => {
|
185
187
|
const previewKeys = revision.values?.["__metadata"]?.["changed_fields"];
|
188
|
+
const previousValues: object | undefined = revision.values?.["__metadata"]?.["previous_values"];
|
186
189
|
return <div key={index} className="flex flex-cols gap-2 w-full">
|
187
190
|
<EntityHistoryEntry size={"large"}
|
188
191
|
entity={revision}
|
189
192
|
collection={collection}
|
190
193
|
previewKeys={previewKeys}
|
194
|
+
previousValues={previousValues}
|
191
195
|
actions={
|
192
196
|
<Tooltip title={"Revert to this version"}
|
193
197
|
className={"m-2 grow-0 self-start"}>
|
@@ -221,14 +225,20 @@ export function EntityHistoryView({
|
|
221
225
|
)}
|
222
226
|
</div>
|
223
227
|
|
224
|
-
<
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
228
|
+
<ErrorBoundary>
|
229
|
+
<ConfirmationDialog open={Boolean(revertVersionDialog)}
|
230
|
+
onAccept={function (): void {
|
231
|
+
if (!revertVersionDialog) return;
|
232
|
+
doRevert(revertVersionDialog);
|
233
|
+
}}
|
234
|
+
onCancel={function (): void {
|
235
|
+
setRevertVersionDialog(undefined);
|
236
|
+
}}
|
237
|
+
title={<Typography variant={"subtitle2"}>Revert data to this version?</Typography>}
|
238
|
+
body={revertVersionDialog ?
|
239
|
+
<EntityView entity={revertVersionDialog}
|
240
|
+
collection={collection}
|
241
|
+
path={entity?.path}/> : null}/>
|
242
|
+
</ErrorBoundary>
|
233
243
|
</div>
|
234
244
|
}
|