@firecms/entity_history 3.0.0-canary.237

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.
@@ -0,0 +1,581 @@
1
+ (function(global, factory) {
2
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("react"), require("@firecms/core"), require("react-compiler-runtime"), require("@firecms/ui"), require("react-fast-compare")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "react", "@firecms/core", "react-compiler-runtime", "@firecms/ui", "react-fast-compare"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global["FireCMS data import/export"] = {}, global.jsxRuntime, global.React, global.core, global.reactCompilerRuntime, global.ui, global.equal));
3
+ })(this, function(exports2, jsxRuntime, React, core, reactCompilerRuntime, ui, equal) {
4
+ "use strict";
5
+ function _interopNamespaceDefault(e) {
6
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
7
+ if (e) {
8
+ for (const k in e) {
9
+ if (k !== "default") {
10
+ const d = Object.getOwnPropertyDescriptor(e, k);
11
+ Object.defineProperty(n, k, d.get ? d : {
12
+ enumerable: true,
13
+ get: () => e[k]
14
+ });
15
+ }
16
+ }
17
+ }
18
+ n.default = e;
19
+ return Object.freeze(n);
20
+ }
21
+ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
22
+ const HistoryControllerContext = React.createContext({});
23
+ const useHistoryController = () => {
24
+ return React.useContext(HistoryControllerContext);
25
+ };
26
+ const HistoryControllerProvider = React.memo(function HistoryControllerProvider2(t0) {
27
+ const $ = reactCompilerRuntime.c(5);
28
+ const {
29
+ children,
30
+ getUser
31
+ } = t0;
32
+ let t1;
33
+ if ($[0] !== getUser) {
34
+ t1 = {
35
+ getUser
36
+ };
37
+ $[0] = getUser;
38
+ $[1] = t1;
39
+ } else {
40
+ t1 = $[1];
41
+ }
42
+ let t2;
43
+ if ($[2] !== children || $[3] !== t1) {
44
+ t2 = /* @__PURE__ */ jsxRuntime.jsx(HistoryControllerContext.Provider, { value: t1, children });
45
+ $[2] = children;
46
+ $[3] = t1;
47
+ $[4] = t2;
48
+ } else {
49
+ t2 = $[4];
50
+ }
51
+ return t2;
52
+ }, equal);
53
+ function UserChip(t0) {
54
+ const $ = reactCompilerRuntime.c(11);
55
+ const {
56
+ user
57
+ } = t0;
58
+ const t1 = user.email ?? user.uid;
59
+ let t2;
60
+ if ($[0] !== user.displayName || $[1] !== user.photoURL) {
61
+ t2 = user.photoURL && /* @__PURE__ */ jsxRuntime.jsx("img", { className: "rounded-full w-6 h-6 mr-2", src: user.photoURL, alt: user.displayName ?? "User picture" });
62
+ $[0] = user.displayName;
63
+ $[1] = user.photoURL;
64
+ $[2] = t2;
65
+ } else {
66
+ t2 = $[2];
67
+ }
68
+ const t3 = user.displayName ?? user.email ?? user.uid;
69
+ let t4;
70
+ if ($[3] !== t3) {
71
+ t4 = /* @__PURE__ */ jsxRuntime.jsx("span", { children: t3 });
72
+ $[3] = t3;
73
+ $[4] = t4;
74
+ } else {
75
+ t4 = $[4];
76
+ }
77
+ let t5;
78
+ if ($[5] !== t2 || $[6] !== t4) {
79
+ t5 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Chip, { size: "small", className: "flex items-center", children: [
80
+ t2,
81
+ t4
82
+ ] });
83
+ $[5] = t2;
84
+ $[6] = t4;
85
+ $[7] = t5;
86
+ } else {
87
+ t5 = $[7];
88
+ }
89
+ let t6;
90
+ if ($[8] !== t1 || $[9] !== t5) {
91
+ t6 = /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: t1, children: t5 });
92
+ $[8] = t1;
93
+ $[9] = t5;
94
+ $[10] = t6;
95
+ } else {
96
+ t6 = $[10];
97
+ }
98
+ return t6;
99
+ }
100
+ function EntityHistoryEntry({
101
+ actions,
102
+ disabled,
103
+ hover,
104
+ collection: collectionProp,
105
+ previewKeys,
106
+ onClick,
107
+ size,
108
+ entity
109
+ }) {
110
+ const authController = core.useAuthController();
111
+ const customizationController = core.useCustomizationController();
112
+ const navigationController = core.useNavigationController();
113
+ const sideEntityController = core.useSideEntityController();
114
+ const collection = collectionProp ?? navigationController.getCollection(entity.path);
115
+ const updatedOn = entity.values?.["__metadata"]?.["updated_on"];
116
+ if (!collection) {
117
+ throw Error(`Couldn't find the corresponding collection view for the path: ${entity.path}`);
118
+ }
119
+ const updatedBy = entity.values?.["__metadata"]?.["updated_by"];
120
+ const {
121
+ getUser
122
+ } = useHistoryController();
123
+ const user = getUser?.(updatedBy);
124
+ const resolvedCollection = React__namespace.useMemo(() => core.resolveCollection({
125
+ collection,
126
+ path: entity.path,
127
+ values: entity.values,
128
+ propertyConfigs: customizationController.propertyConfigs,
129
+ authController
130
+ }), [collection]);
131
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full flex flex-col gap-2 mt-4", children: [
132
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-4 flex items-center gap-4", children: [
133
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "body2", color: "secondary", children: updatedOn.toLocaleString() }),
134
+ !user && updatedBy && /* @__PURE__ */ jsxRuntime.jsx(ui.Chip, { size: "small", children: updatedBy }),
135
+ user && /* @__PURE__ */ jsxRuntime.jsx(UserChip, { user })
136
+ ] }),
137
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cls("bg-white dark:bg-surface-900", "min-h-[42px]", "w-full", "items-center", hover ? "hover:bg-surface-accent-50 dark:hover:bg-surface-800 group-hover:bg-surface-accent-50 dark:group-hover:bg-surface-800" : "", size === "small" ? "p-1" : "px-2 py-1", "flex border rounded-lg", onClick ? "cursor-pointer" : "", ui.defaultBorderMixin), children: [
138
+ actions,
139
+ entity && /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "See details for this revision", className: "my-2 grow-0 shrink-0 self-start", children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { color: "inherit", className: "", onClick: (e) => {
140
+ sideEntityController.open({
141
+ entityId: entity.id,
142
+ path: entity.path,
143
+ allowFullScreen: false,
144
+ collection: {
145
+ ...collection,
146
+ subcollections: void 0,
147
+ entityViews: void 0,
148
+ permissions: {
149
+ create: false,
150
+ delete: false,
151
+ edit: false,
152
+ read: true
153
+ }
154
+ },
155
+ updateUrl: true
156
+ });
157
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.KeyboardTabIcon, {}) }) }),
158
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col grow w-full m-1 shrink min-w-0", children: previewKeys && previewKeys.map((key) => {
159
+ const childProperty = core.getPropertyInPath(resolvedCollection.properties, key);
160
+ if (!childProperty) return null;
161
+ const valueInPath = core.getValueInPath(entity.values, key);
162
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full my-1 items-center", children: [
163
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", color: "secondary", className: "min-w-[140px] md:min-w-[200px] w-1/5 pr-8 overflow-hidden text-ellipsis text-right", children: key }),
164
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-4/5", children: entity ? /* @__PURE__ */ jsxRuntime.jsx(core.PropertyPreview, { propertyKey: key, value: valueInPath, property: childProperty, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(core.SkeletonPropertyComponent, { property: childProperty, size: "small" }) })
165
+ ] }, "ref_prev_" + key);
166
+ }) })
167
+ ] })
168
+ ] });
169
+ }
170
+ function EntityHistoryView(t0) {
171
+ const $ = reactCompilerRuntime.c(52);
172
+ const {
173
+ entity,
174
+ collection,
175
+ formContext
176
+ } = t0;
177
+ const authController = core.useAuthController();
178
+ const snackbarController = core.useSnackbarController();
179
+ const dirty = formContext?.formex.dirty;
180
+ const dataSource = core.useDataSource();
181
+ const pathAndId = entity ? entity?.path + "/" + entity?.id : void 0;
182
+ const [revertVersion, setRevertVersion] = React.useState(void 0);
183
+ let t1;
184
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
185
+ t1 = [];
186
+ $[0] = t1;
187
+ } else {
188
+ t1 = $[0];
189
+ }
190
+ const [revisions, setRevisions] = React.useState(t1);
191
+ const [isLoading, setIsLoading] = React.useState(false);
192
+ const [hasMore, setHasMore] = React.useState(true);
193
+ const [limit, setLimit] = React.useState(5);
194
+ const containerRef = React.useRef(null);
195
+ const observerRef = React.useRef(null);
196
+ const loadMoreRef = React.useRef(null);
197
+ let t2;
198
+ let t3;
199
+ if ($[1] !== dataSource || $[2] !== limit || $[3] !== pathAndId) {
200
+ t2 = () => {
201
+ if (!pathAndId) {
202
+ return;
203
+ }
204
+ setIsLoading(true);
205
+ const listener = dataSource.listenCollection?.({
206
+ path: pathAndId + "/__history",
207
+ order: "desc",
208
+ orderBy: "__metadata.updated_on",
209
+ limit,
210
+ startAfter: void 0,
211
+ onUpdate: (entities) => {
212
+ setRevisions(entities);
213
+ setHasMore(entities.length === limit && entities.length >= 5);
214
+ setIsLoading(false);
215
+ },
216
+ onError: (error) => {
217
+ console.error("Error fetching history:", error);
218
+ setIsLoading(false);
219
+ setHasMore(false);
220
+ }
221
+ });
222
+ return () => {
223
+ if (typeof listener === "function") {
224
+ listener();
225
+ }
226
+ };
227
+ };
228
+ t3 = [pathAndId, limit, dataSource];
229
+ $[1] = dataSource;
230
+ $[2] = limit;
231
+ $[3] = pathAndId;
232
+ $[4] = t2;
233
+ $[5] = t3;
234
+ } else {
235
+ t2 = $[4];
236
+ t3 = $[5];
237
+ }
238
+ React.useEffect(t2, t3);
239
+ let t4;
240
+ if ($[6] !== hasMore || $[7] !== isLoading) {
241
+ t4 = () => {
242
+ const currentContainer = containerRef.current;
243
+ const currentLoadMore = loadMoreRef.current;
244
+ if (!currentContainer || !currentLoadMore || !hasMore || isLoading) {
245
+ if (observerRef.current) {
246
+ observerRef.current.disconnect();
247
+ observerRef.current = null;
248
+ }
249
+ return;
250
+ }
251
+ const options = {
252
+ root: currentContainer,
253
+ rootMargin: "0px 0px 200px 0px",
254
+ threshold: 0.01
255
+ };
256
+ const handleObserver = (entries) => {
257
+ const target = entries[0];
258
+ if (target.isIntersecting && hasMore && !isLoading) {
259
+ setLimit((prev) => prev + 5);
260
+ }
261
+ };
262
+ const observer = new IntersectionObserver(handleObserver, options);
263
+ observer.observe(currentLoadMore);
264
+ observerRef.current = observer;
265
+ return () => {
266
+ observer.disconnect();
267
+ if (observerRef.current === observer) {
268
+ observerRef.current = null;
269
+ }
270
+ };
271
+ };
272
+ $[6] = hasMore;
273
+ $[7] = isLoading;
274
+ $[8] = t4;
275
+ } else {
276
+ t4 = $[8];
277
+ }
278
+ let t5;
279
+ if ($[9] !== hasMore || $[10] !== isLoading || $[11] !== revisions.length) {
280
+ t5 = [hasMore, isLoading, revisions.length];
281
+ $[9] = hasMore;
282
+ $[10] = isLoading;
283
+ $[11] = revisions.length;
284
+ $[12] = t5;
285
+ } else {
286
+ t5 = $[12];
287
+ }
288
+ React.useEffect(t4, t5);
289
+ if (!entity) {
290
+ let t62;
291
+ if ($[13] === Symbol.for("react.memo_cache_sentinel")) {
292
+ t62 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "History is only available for existing entities" }) });
293
+ $[13] = t62;
294
+ } else {
295
+ t62 = $[13];
296
+ }
297
+ return t62;
298
+ }
299
+ let t6;
300
+ if ($[14] !== authController.user?.uid || $[15] !== collection || $[16] !== dataSource || $[17] !== formContext.formex || $[18] !== snackbarController) {
301
+ t6 = function doRevert2(revertVersion_0) {
302
+ const revertValues = {
303
+ ...revertVersion_0.values,
304
+ __metadata: {
305
+ ...revertVersion_0.values?.__metadata,
306
+ reverted: true,
307
+ updated_on: /* @__PURE__ */ new Date(),
308
+ updated_by: authController.user?.uid ?? null
309
+ }
310
+ };
311
+ return dataSource.saveEntity({
312
+ path: revertVersion_0.path,
313
+ entityId: revertVersion_0.id,
314
+ values: revertValues,
315
+ collection,
316
+ status: "existing"
317
+ }).then(() => {
318
+ formContext.formex.resetForm({
319
+ values: revertVersion_0.values
320
+ });
321
+ setRevertVersion(void 0);
322
+ snackbarController.open({
323
+ message: "Reverted version",
324
+ type: "info"
325
+ });
326
+ }).catch((error_0) => {
327
+ console.error("Error reverting entity:", error_0);
328
+ snackbarController.open({
329
+ message: "Error reverting entity",
330
+ type: "error"
331
+ });
332
+ });
333
+ };
334
+ $[14] = authController.user?.uid;
335
+ $[15] = collection;
336
+ $[16] = dataSource;
337
+ $[17] = formContext.formex;
338
+ $[18] = snackbarController;
339
+ $[19] = t6;
340
+ } else {
341
+ t6 = $[19];
342
+ }
343
+ const doRevert = t6;
344
+ let t7;
345
+ if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
346
+ t7 = ui.cls("relative flex-1 h-full overflow-auto w-full flex flex-col gap-4 p-8");
347
+ $[20] = t7;
348
+ } else {
349
+ t7 = $[20];
350
+ }
351
+ let t8;
352
+ if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
353
+ t8 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "h5", className: "mt-24 ml-4", children: "History" });
354
+ $[21] = t8;
355
+ } else {
356
+ t8 = $[21];
357
+ }
358
+ let t9;
359
+ if ($[22] !== revisions.length) {
360
+ t9 = revisions.length === 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
361
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { className: "ml-4 mt-8", children: "No history available" }),
362
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "ml-4", children: "When you save an entity, a new version is created and stored in the history." })
363
+ ] });
364
+ $[22] = revisions.length;
365
+ $[23] = t9;
366
+ } else {
367
+ t9 = $[23];
368
+ }
369
+ let t10;
370
+ if ($[24] !== collection || $[25] !== dirty || $[26] !== revisions || $[27] !== snackbarController) {
371
+ let t112;
372
+ if ($[29] !== collection || $[30] !== dirty || $[31] !== snackbarController) {
373
+ t112 = (revision, index) => {
374
+ const previewKeys = revision.values?.__metadata?.changed_fields;
375
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-cols gap-2 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(EntityHistoryEntry, { size: "large", entity: revision, collection, previewKeys, actions: /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "Revert to this version", className: "m-2 grow-0 self-start", children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: () => {
376
+ if (dirty) {
377
+ snackbarController.open({
378
+ message: "Please save or discard your changes before reverting",
379
+ type: "warning"
380
+ });
381
+ } else {
382
+ setRevertVersion(revision);
383
+ }
384
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.HistoryIcon, {}) }) }) }) }, index);
385
+ };
386
+ $[29] = collection;
387
+ $[30] = dirty;
388
+ $[31] = snackbarController;
389
+ $[32] = t112;
390
+ } else {
391
+ t112 = $[32];
392
+ }
393
+ t10 = revisions.map(t112);
394
+ $[24] = collection;
395
+ $[25] = dirty;
396
+ $[26] = revisions;
397
+ $[27] = snackbarController;
398
+ $[28] = t10;
399
+ } else {
400
+ t10 = $[28];
401
+ }
402
+ let t11;
403
+ if ($[33] !== hasMore || $[34] !== isLoading || $[35] !== revisions.length) {
404
+ t11 = revisions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: loadMoreRef, className: "py-4 text-center", children: [
405
+ isLoading && /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Loading more..." }),
406
+ !hasMore && revisions.length > 5 && /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "No more history available" })
407
+ ] });
408
+ $[33] = hasMore;
409
+ $[34] = isLoading;
410
+ $[35] = revisions.length;
411
+ $[36] = t11;
412
+ } else {
413
+ t11 = $[36];
414
+ }
415
+ let t12;
416
+ if ($[37] !== t10 || $[38] !== t11 || $[39] !== t9) {
417
+ t12 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 max-w-6xl mx-auto w-full", children: [
418
+ t8,
419
+ t9,
420
+ t10,
421
+ t11
422
+ ] });
423
+ $[37] = t10;
424
+ $[38] = t11;
425
+ $[39] = t9;
426
+ $[40] = t12;
427
+ } else {
428
+ t12 = $[40];
429
+ }
430
+ const t13 = Boolean(revertVersion);
431
+ let t14;
432
+ if ($[41] !== doRevert || $[42] !== revertVersion) {
433
+ t14 = function() {
434
+ if (!revertVersion) {
435
+ return;
436
+ }
437
+ doRevert(revertVersion);
438
+ };
439
+ $[41] = doRevert;
440
+ $[42] = revertVersion;
441
+ $[43] = t14;
442
+ } else {
443
+ t14 = $[43];
444
+ }
445
+ let t15;
446
+ let t16;
447
+ if ($[44] === Symbol.for("react.memo_cache_sentinel")) {
448
+ t15 = function() {
449
+ setRevertVersion(void 0);
450
+ };
451
+ t16 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "subtitle2", children: "Revert data to this version?" });
452
+ $[44] = t15;
453
+ $[45] = t16;
454
+ } else {
455
+ t15 = $[44];
456
+ t16 = $[45];
457
+ }
458
+ let t17;
459
+ if ($[46] !== t13 || $[47] !== t14) {
460
+ t17 = /* @__PURE__ */ jsxRuntime.jsx(core.ConfirmationDialog, { open: t13, onAccept: t14, onCancel: t15, title: t16 });
461
+ $[46] = t13;
462
+ $[47] = t14;
463
+ $[48] = t17;
464
+ } else {
465
+ t17 = $[48];
466
+ }
467
+ let t18;
468
+ if ($[49] !== t12 || $[50] !== t17) {
469
+ t18 = /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: t7, children: [
470
+ t12,
471
+ t17
472
+ ] });
473
+ $[49] = t12;
474
+ $[50] = t17;
475
+ $[51] = t18;
476
+ } else {
477
+ t18 = $[51];
478
+ }
479
+ return t18;
480
+ }
481
+ const entityHistoryCallbacks = {
482
+ onSaveSuccess: async (props) => {
483
+ const changedFields = props.previousValues ? findChangedFields(props.previousValues, props.values) : null;
484
+ const uid = props.context.authController.user?.uid;
485
+ props.context.dataSource.saveEntity({
486
+ path: props.path + "/" + props.entityId + "/__history",
487
+ values: {
488
+ ...props.values,
489
+ __metadata: {
490
+ changed_fields: changedFields,
491
+ updated_on: /* @__PURE__ */ new Date(),
492
+ updated_by: uid
493
+ }
494
+ },
495
+ status: "new"
496
+ }).then(() => {
497
+ console.debug("History saved for", props.path, props.entityId);
498
+ });
499
+ }
500
+ };
501
+ function findChangedFields(oldValues, newValues, prefix = "") {
502
+ const changedFields = [];
503
+ if (equal(oldValues, newValues)) return changedFields;
504
+ if (!oldValues || !newValues) return [prefix || "."];
505
+ const allKeys = /* @__PURE__ */ new Set([...Object.keys(oldValues), ...Object.keys(newValues)]);
506
+ for (const key of allKeys) {
507
+ const oldValue = oldValues[key];
508
+ const newValue = newValues[key];
509
+ const currentPath = prefix ? `${prefix}.${key}` : key;
510
+ if (key in oldValues !== key in newValues) {
511
+ changedFields.push(currentPath);
512
+ continue;
513
+ }
514
+ if (equal(oldValue, newValue)) continue;
515
+ if (Array.isArray(oldValue) && Array.isArray(newValue)) {
516
+ if (oldValue.length !== newValue.length) {
517
+ changedFields.push(currentPath);
518
+ } else {
519
+ for (let i = 0; i < oldValue.length; i++) {
520
+ if (typeof oldValue[i] === "object" && oldValue[i] !== null && typeof newValue[i] === "object" && newValue[i] !== null) {
521
+ const nestedChanges = findChangedFields(oldValue[i], newValue[i], `${currentPath}[${i}]`);
522
+ if (nestedChanges.length > 0) {
523
+ changedFields.push(currentPath);
524
+ break;
525
+ }
526
+ } else if (!equal(oldValue[i], newValue[i])) {
527
+ changedFields.push(currentPath);
528
+ break;
529
+ }
530
+ }
531
+ }
532
+ } else if (typeof oldValue === "object" && oldValue !== null && typeof newValue === "object" && newValue !== null) {
533
+ const nestedChanges = findChangedFields(oldValue, newValue, currentPath);
534
+ changedFields.push(...nestedChanges);
535
+ } else {
536
+ changedFields.push(currentPath);
537
+ }
538
+ }
539
+ return changedFields;
540
+ }
541
+ function useEntityHistoryPlugin(props) {
542
+ const {
543
+ defaultEnabled = false
544
+ } = props ?? {};
545
+ const modifyCollection = React.useCallback((collection) => {
546
+ if (collection.history === true || defaultEnabled) {
547
+ return {
548
+ ...collection,
549
+ history: true,
550
+ entityViews: [...collection.entityViews ?? [], {
551
+ key: "__history",
552
+ name: "History",
553
+ tabComponent: /* @__PURE__ */ jsxRuntime.jsx(ui.HistoryIcon, { size: "small" }),
554
+ Builder: EntityHistoryView,
555
+ position: "start"
556
+ }],
557
+ callbacks: core.mergeCallbacks(collection.callbacks, entityHistoryCallbacks)
558
+ };
559
+ }
560
+ return collection;
561
+ }, []);
562
+ return React.useMemo(() => ({
563
+ key: "entity_history",
564
+ provider: {
565
+ Component: HistoryControllerProvider,
566
+ props: {
567
+ getUser: props?.getUser
568
+ }
569
+ },
570
+ collection: {
571
+ modifyCollection
572
+ }
573
+ }), [props]);
574
+ }
575
+ exports2.HistoryControllerContext = HistoryControllerContext;
576
+ exports2.HistoryControllerProvider = HistoryControllerProvider;
577
+ exports2.useEntityHistoryPlugin = useEntityHistoryPlugin;
578
+ exports2.useHistoryController = useHistoryController;
579
+ Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
580
+ });
581
+ //# sourceMappingURL=index.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.umd.js","sources":["../src/HistoryControllerProvider.tsx","../src/components/UserChip.tsx","../src/components/EntityHistoryEntry.tsx","../src/components/EntityHistoryView.tsx","../src/entity_history_callbacks.ts","../src/useEntityHistoryPlugin.tsx"],"sourcesContent":["import React, { PropsWithChildren, useContext } from \"react\";\nimport equal from \"react-fast-compare\"\n\nimport { User } from \"@firecms/core\";\n\nexport type HistoryConfigController = {\n /**\n * Function to get a user by uid.\n * @param uid\n */\n getUser?: (uid: string) => User | null;\n}\n\nexport const HistoryControllerContext = React.createContext<HistoryConfigController>({} as any);\nexport const useHistoryController = (): HistoryConfigController => useContext(HistoryControllerContext);\n\n\nexport interface HistoryControllerProviderProps {\n\n getUser?: (uid: string) => User | null;\n\n}\n\nexport const HistoryControllerProvider = React.memo(\n function HistoryControllerProvider({\n children,\n getUser,\n }: PropsWithChildren<HistoryControllerProviderProps>) {\n\n return (\n <HistoryControllerContext.Provider\n value={{\n getUser,\n }}>\n\n {children}\n\n </HistoryControllerContext.Provider>\n );\n }, equal);\n","import { User } from \"@firecms/core\";\nimport { Chip, Tooltip } from \"@firecms/ui\";\n\nexport function UserChip({ user }: { user: User }) {\n return (\n <Tooltip title={user.email ?? user.uid}>\n <Chip size={\"small\"} className={\"flex items-center\"}>\n {user.photoURL && <img\n className={\"rounded-full w-6 h-6 mr-2\"}\n src={user.photoURL} alt={user.displayName ?? \"User picture\"}/>}\n <span>{user.displayName ?? user.email ?? user.uid}</span>\n </Chip>\n </Tooltip>\n );\n}\n","import * as React from \"react\";\n\nimport { Chip, cls, defaultBorderMixin, IconButton, KeyboardTabIcon, Tooltip, Typography } from \"@firecms/ui\";\nimport {\n Entity,\n EntityCollection,\n getPropertyInPath,\n getValueInPath,\n PreviewSize,\n PropertyPreview,\n resolveCollection,\n ResolvedProperty,\n SkeletonPropertyComponent,\n useAuthController,\n useCustomizationController,\n useNavigationController,\n useSideEntityController\n} from \"@firecms/core\";\nimport { useHistoryController } from \"../HistoryControllerProvider\";\nimport { UserChip } from \"./UserChip\";\n\nexport type EntityPreviewProps = {\n size: PreviewSize,\n actions?: React.ReactNode,\n collection?: EntityCollection,\n hover?: boolean;\n previewKeys?: string[],\n disabled?: boolean,\n entity: Entity<any>,\n onClick?: (e: React.SyntheticEvent) => void;\n};\n\n/**\n * This view is used to display a preview of an entity.\n * It is used by default in reference fields and whenever a reference is displayed.\n */\nexport function EntityHistoryEntry({\n actions,\n disabled,\n hover,\n collection: collectionProp,\n previewKeys,\n onClick,\n size,\n entity\n }: EntityPreviewProps) {\n\n const authController = useAuthController();\n const customizationController = useCustomizationController();\n\n const navigationController = useNavigationController();\n const sideEntityController = useSideEntityController();\n\n const collection = collectionProp ?? navigationController.getCollection(entity.path);\n const updatedOn = entity.values?.[\"__metadata\"]?.[\"updated_on\"];\n if (!collection) {\n throw Error(`Couldn't find the corresponding collection view for the path: ${entity.path}`);\n }\n\n const updatedBy = entity.values?.[\"__metadata\"]?.[\"updated_by\"];\n const { getUser } = useHistoryController();\n const user = getUser?.(updatedBy);\n\n const resolvedCollection = React.useMemo(() => resolveCollection({\n collection,\n path: entity.path,\n values: entity.values,\n propertyConfigs: customizationController.propertyConfigs,\n authController\n }), [collection]);\n\n return <div className={\"w-full flex flex-col gap-2 mt-4\"}>\n <div className={\"ml-4 flex items-center gap-4\"}>\n <Typography variant={\"body2\"} color={\"secondary\"}>{updatedOn.toLocaleString()}</Typography>\n {!user && updatedBy && <Chip size={\"small\"}>{updatedBy}</Chip>}\n {user && <UserChip user={user}/>}\n </div>\n <div\n className={cls(\n \"bg-white dark:bg-surface-900\",\n \"min-h-[42px]\",\n \"w-full\",\n \"items-center\",\n hover ? \"hover:bg-surface-accent-50 dark:hover:bg-surface-800 group-hover:bg-surface-accent-50 dark:group-hover:bg-surface-800\" : \"\",\n size === \"small\" ? \"p-1\" : \"px-2 py-1\",\n \"flex border rounded-lg\",\n onClick ? \"cursor-pointer\" : \"\",\n defaultBorderMixin\n )}>\n\n\n {actions}\n\n {entity &&\n <Tooltip title={\"See details for this revision\"}\n className={\"my-2 grow-0 shrink-0 self-start\"}>\n <IconButton\n color={\"inherit\"}\n className={\"\"}\n onClick={(e) => {\n\n sideEntityController.open({\n entityId: entity.id,\n path: entity.path,\n allowFullScreen: false,\n collection: {\n ...collection,\n subcollections: undefined,\n entityViews: undefined,\n permissions: {\n create: false,\n delete: false,\n edit: false,\n read: true\n }\n },\n updateUrl: true\n });\n }}>\n <KeyboardTabIcon/>\n </IconButton>\n </Tooltip>}\n\n <div className={\"flex flex-col grow w-full m-1 shrink min-w-0\"}>\n\n {previewKeys && previewKeys.map((key) => {\n const childProperty = getPropertyInPath(resolvedCollection.properties, key);\n if (!childProperty) return null;\n\n const valueInPath = getValueInPath(entity.values, key);\n return (\n <div key={\"ref_prev_\" + key}\n className=\"flex w-full my-1 items-center\">\n <Typography variant={\"caption\"}\n color={\"secondary\"}\n className=\"min-w-[140px] md:min-w-[200px] w-1/5 pr-8 overflow-hidden text-ellipsis text-right\">\n {key}\n </Typography>\n <div className=\"w-4/5\">\n {\n entity\n ? <PropertyPreview\n propertyKey={key as string}\n value={valueInPath}\n property={childProperty as ResolvedProperty}\n size={\"small\"}/>\n : <SkeletonPropertyComponent\n property={childProperty as ResolvedProperty}\n size={\"small\"}/>\n }\n </div>\n </div>\n );\n })}\n\n </div>\n\n </div>\n </div>\n}\n\n","import { useEffect, useRef, useState } from \"react\";\nimport {\n ConfirmationDialog,\n Entity,\n EntityCustomViewParams,\n useAuthController,\n useDataSource,\n useSnackbarController\n} from \"@firecms/core\";\nimport { cls, HistoryIcon, IconButton, Label, Tooltip, Typography } from \"@firecms/ui\";\nimport { EntityHistoryEntry } from \"./EntityHistoryEntry\";\n\nexport function EntityHistoryView({\n entity,\n collection,\n formContext\n }: EntityCustomViewParams) {\n\n const authController = useAuthController();\n const snackbarController = useSnackbarController();\n const dirty = formContext?.formex.dirty;\n\n const dataSource = useDataSource();\n const pathAndId = entity ? entity?.path + \"/\" + entity?.id : undefined;\n\n const [revertVersion, setRevertVersion] = useState<Entity | undefined>(undefined);\n const [revisions, setRevisions] = useState<Entity[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n\n const PAGE_SIZE = 5;\n const [limit, setLimit] = useState(PAGE_SIZE);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const observerRef = useRef<IntersectionObserver | null>(null);\n const loadMoreRef = useRef<HTMLDivElement>(null);\n\n // Load revisions with the current limit\n useEffect(() => {\n if (!pathAndId) return;\n\n setIsLoading(true); // Set loading true when fetching starts\n const listener = dataSource.listenCollection?.({\n path: pathAndId + \"/__history\",\n order: \"desc\",\n orderBy: \"__metadata.updated_on\",\n limit: limit,\n startAfter: undefined,\n onUpdate: (entities) => {\n setRevisions(entities);\n setHasMore(entities.length === limit && entities.length >= PAGE_SIZE); // Ensure we fetched a full page to consider hasMore\n setIsLoading(false);\n },\n onError: (error) => {\n console.error(\"Error fetching history:\", error);\n setIsLoading(false);\n setHasMore(false); // Stop trying if there's an error\n }\n });\n return () => {\n if (typeof listener === \"function\") {\n listener();\n }\n };\n }, [pathAndId, limit, dataSource]);\n\n // Setup intersection observer for infinite scroll\n useEffect(() => {\n const currentContainer = containerRef.current;\n const currentLoadMore = loadMoreRef.current;\n\n // Conditions for active observation\n if (!currentContainer || !currentLoadMore || !hasMore || isLoading) {\n // If we shouldn't be observing, ensure any existing observer is disconnected\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n return;\n }\n\n // Options for the IntersectionObserver\n const options = {\n root: currentContainer,\n rootMargin: \"0px 0px 200px 0px\", // Trigger 200px before the sentinel is at the bottom edge\n threshold: 0.01 // Trigger if even a small part is visible within the rootMargin\n };\n\n // The callback for when the sentinel's intersection state changes\n const handleObserver = (entries: IntersectionObserverEntry[]) => {\n const target = entries[0];\n if (target.isIntersecting && hasMore && !isLoading) {\n // No need to setIsLoading(true) here, it's done in the data fetching useEffect\n setLimit(prev => prev + PAGE_SIZE);\n }\n };\n\n const observer = new IntersectionObserver(handleObserver, options);\n observer.observe(currentLoadMore);\n observerRef.current = observer; // Store the new observer\n\n // Cleanup function for this effect instance\n return () => {\n observer.disconnect(); // Disconnect the observer created in *this* effect run\n if (observerRef.current === observer) {\n observerRef.current = null;\n }\n };\n // Re-run if hasMore, isLoading changes, or if revisions.length changes (which might make loadMoreRef available/unavailable)\n }, [hasMore, isLoading, revisions.length]);\n\n if (!entity) {\n return <div className=\"flex items-center justify-center h-full\">\n <Label>History is only available for existing entities</Label>\n </div>\n }\n\n function doRevert(revertVersion: Entity) {\n const revertValues = {\n ...revertVersion.values,\n __metadata: {\n ...revertVersion.values?.[\"__metadata\"],\n reverted: true,\n updated_on: new Date(),\n updated_by: authController.user?.uid ?? null,\n }\n };\n return dataSource.saveEntity({\n path: revertVersion.path,\n entityId: revertVersion.id,\n values: revertValues,\n collection,\n status: \"existing\"\n }).then(() => {\n formContext.formex.resetForm({\n values: revertVersion.values\n });\n setRevertVersion(undefined);\n snackbarController.open({\n message: \"Reverted version\",\n type: \"info\"\n });\n }\n ).catch((error) => {\n console.error(\"Error reverting entity:\", error);\n snackbarController.open({\n message: \"Error reverting entity\",\n type: \"error\"\n });\n });\n\n }\n\n return <div\n ref={containerRef}\n className={cls(\"relative flex-1 h-full overflow-auto w-full flex flex-col gap-4 p-8\")}>\n <div className=\"flex flex-col gap-2 max-w-6xl mx-auto w-full\">\n\n <Typography variant={\"h5\"} className={\"mt-24 ml-4\"}>\n History\n </Typography>\n\n {revisions.length === 0 && <>\n <Label className={\"ml-4 mt-8\"}>\n No history available\n </Label>\n <Typography variant={\"caption\"} className={\"ml-4\"}>\n When you save an entity, a new version is created and stored in the history.\n </Typography>\n </>}\n\n {revisions.map((revision, index) => {\n const previewKeys = revision.values?.[\"__metadata\"]?.[\"changed_fields\"];\n return <div key={index} className=\"flex flex-cols gap-2 w-full\">\n <EntityHistoryEntry size={\"large\"}\n entity={revision}\n collection={collection}\n previewKeys={previewKeys}\n actions={\n <Tooltip title={\"Revert to this version\"}\n className={\"m-2 grow-0 self-start\"}>\n <IconButton\n onClick={() => {\n if (dirty) {\n snackbarController.open({\n message: \"Please save or discard your changes before reverting\",\n type: \"warning\"\n });\n } else {\n setRevertVersion(revision);\n }\n }}>\n <HistoryIcon/>\n </IconButton>\n </Tooltip>}\n />\n </div>\n })}\n\n {/* Load more sentinel element */}\n {revisions.length > 0 && (\n <div\n ref={loadMoreRef}\n className=\"py-4 text-center\"\n >\n {isLoading && <Label>Loading more...</Label>}\n {!hasMore && revisions.length > PAGE_SIZE && <Label>No more history available</Label>}\n </div>\n )}\n </div>\n\n <ConfirmationDialog open={Boolean(revertVersion)}\n onAccept={function (): void {\n if (!revertVersion) return;\n doRevert(revertVersion);\n }}\n onCancel={function (): void {\n setRevertVersion(undefined);\n }}\n title={<Typography variant={\"subtitle2\"}>Revert data to this version?</Typography>}/>\n </div>\n}\n","import { EntityCallbacks } from \"@firecms/core\";\nimport equal from \"react-fast-compare\"\n\nexport const entityHistoryCallbacks: EntityCallbacks = {\n onSaveSuccess: async (props) => {\n\n const changedFields = props.previousValues ? findChangedFields(props.previousValues, props.values) : null;\n const uid = props.context.authController.user?.uid;\n props.context.dataSource.saveEntity({\n path: props.path + \"/\" + props.entityId + \"/__history\",\n values: {\n ...props.values,\n __metadata: {\n changed_fields: changedFields,\n updated_on: new Date(),\n updated_by: uid,\n }\n },\n status: \"new\"\n }).then(() => {\n console.debug(\"History saved for\", props.path, props.entityId);\n });\n }\n}\n\nfunction findChangedFields<M extends object>(oldValues: M, newValues: M, prefix: string = \"\"): string[] {\n const changedFields: string[] = [];\n\n // Handle null/undefined cases\n if (equal(oldValues, newValues)) return changedFields;\n if (!oldValues || !newValues) return [prefix || \".\"];\n\n // Get all unique keys from both objects\n const allKeys = new Set([\n ...Object.keys(oldValues),\n ...Object.keys(newValues)\n ]);\n\n for (const key of allKeys) {\n const oldValue = oldValues[key as keyof M];\n const newValue = newValues[key as keyof M];\n const currentPath = prefix ? `${prefix}.${key}` : key;\n\n // If key exists only in one object\n if ((key in oldValues) !== (key in newValues)) {\n changedFields.push(currentPath);\n continue;\n }\n\n // If values are identical (deep equality)\n if (equal(oldValue, newValue)) continue;\n\n // Handle arrays\n if (Array.isArray(oldValue) && Array.isArray(newValue)) {\n if (oldValue.length !== newValue.length) {\n changedFields.push(currentPath);\n } else {\n // Check if any array element changed\n for (let i = 0; i < oldValue.length; i++) {\n if (\n typeof oldValue[i] === \"object\" && oldValue[i] !== null &&\n typeof newValue[i] === \"object\" && newValue[i] !== null\n ) {\n const nestedChanges = findChangedFields(\n oldValue[i] as object,\n newValue[i] as object,\n `${currentPath}[${i}]`\n );\n if (nestedChanges.length > 0) {\n changedFields.push(currentPath);\n break;\n }\n } else if (!equal(oldValue[i], newValue[i])) {\n changedFields.push(currentPath);\n break;\n }\n }\n }\n }\n // Handle nested objects\n else if (\n typeof oldValue === \"object\" && oldValue !== null &&\n typeof newValue === \"object\" && newValue !== null\n ) {\n const nestedChanges = findChangedFields(\n oldValue as object,\n newValue as object,\n currentPath\n );\n changedFields.push(...nestedChanges);\n }\n // Handle primitives\n else {\n changedFields.push(currentPath);\n }\n }\n\n return changedFields;\n}\n","import { useCallback, useMemo } from \"react\";\nimport { EntityCollection, FireCMSPlugin, mergeCallbacks, User } from \"@firecms/core\";\nimport { EntityHistoryView } from \"./components/EntityHistoryView\";\nimport { HistoryIcon } from \"@firecms/ui\";\nimport { entityHistoryCallbacks } from \"./entity_history_callbacks\";\nimport { HistoryControllerProvider } from \"./HistoryControllerProvider\";\n\n/**\n *\n */\nexport function useEntityHistoryPlugin(props?: EntityHistoryPluginProps): FireCMSPlugin<any, any, any, EntityHistoryPluginProps> {\n\n const { defaultEnabled = false } = props ?? {};\n\n const modifyCollection = useCallback((collection: EntityCollection) => {\n if (collection.history === true || defaultEnabled) {\n return {\n ...collection,\n history: true,\n entityViews: [\n ...(collection.entityViews ?? []),\n {\n key: \"__history\",\n name: \"History\",\n tabComponent: <HistoryIcon size={\"small\"}/>,\n Builder: EntityHistoryView,\n position: \"start\"\n }\n ],\n callbacks: mergeCallbacks(collection.callbacks, entityHistoryCallbacks)\n } satisfies EntityCollection;\n }\n return collection;\n }, []);\n\n return useMemo(() => ({\n key: \"entity_history\",\n provider: {\n Component: HistoryControllerProvider,\n props: {\n getUser: props?.getUser\n }\n },\n collection: {\n modifyCollection\n }\n } satisfies FireCMSPlugin), [props]);\n}\n\nexport type EntityHistoryPluginProps = {\n /**\n * If true, the history view will be enabled to all collections by default.\n * Each collection can override this value by setting the `history` property.\n */\n defaultEnabled?: boolean;\n\n /**\n * Function to get the user object from the uid.\n * @param uid\n */\n getUser?: (uid: string) => User | null;\n}\n"],"names":["HistoryControllerContext","React","createContext","useHistoryController","useContext","HistoryControllerProvider","memo","t0","$","_c","children","getUser","t1","t2","equal","UserChip","user","email","uid","displayName","photoURL","jsx","t3","t4","t5","jsxs","Chip","t6","Tooltip","EntityHistoryEntry","actions","disabled","hover","collection","collectionProp","previewKeys","onClick","size","entity","authController","useAuthController","customizationController","useCustomizationController","navigationController","useNavigationController","sideEntityController","useSideEntityController","getCollection","path","updatedOn","values","Error","updatedBy","resolvedCollection","useMemo","resolveCollection","propertyConfigs","Typography","toLocaleString","cls","defaultBorderMixin","IconButton","e","open","entityId","id","allowFullScreen","subcollections","undefined","entityViews","permissions","create","delete","edit","read","updateUrl","KeyboardTabIcon","map","key","childProperty","getPropertyInPath","properties","valueInPath","getValueInPath","PropertyPreview","SkeletonPropertyComponent","EntityHistoryView","formContext","snackbarController","useSnackbarController","dirty","formex","dataSource","useDataSource","pathAndId","revertVersion","setRevertVersion","useState","Symbol","for","revisions","setRevisions","isLoading","setIsLoading","hasMore","setHasMore","limit","setLimit","containerRef","useRef","observerRef","loadMoreRef","listener","listenCollection","order","orderBy","startAfter","onUpdate","entities","length","onError","error","useEffect","currentContainer","current","currentLoadMore","disconnect","options","root","rootMargin","threshold","handleObserver","entries","target","isIntersecting","prev","observer","IntersectionObserver","observe","Label","doRevert","revertVersion_0","revertValues","__metadata","reverted","updated_on","Date","updated_by","saveEntity","status","then","resetForm","message","type","catch","error_0","t7","t8","t9","Fragment","t10","t11","revision","index","changed_fields","HistoryIcon","t12","t13","Boolean","t14","t15","t16","t17","ConfirmationDialog","t18","entityHistoryCallbacks","onSaveSuccess","props","changedFields","previousValues","findChangedFields","context","console","debug","oldValues","newValues","prefix","allKeys","Set","Object","keys","oldValue","newValue","currentPath","push","Array","isArray","i","nestedChanges","useEntityHistoryPlugin","defaultEnabled","modifyCollection","useCallback","history","name","tabComponent","Builder","position","callbacks","mergeCallbacks","provider","Component"],"mappings":"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"}