@firecms/entity_history 3.0.0-beta.14
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/LICENSE +114 -0
- package/README.md +124 -0
- package/dist/HistoryControllerProvider.d.ts +15 -0
- package/dist/components/EntityHistoryEntry.d.ts +17 -0
- package/dist/components/EntityHistoryView.d.ts +2 -0
- package/dist/components/UserChip.d.ts +4 -0
- package/dist/entity_history_callbacks.d.ts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.es.js +578 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +592 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/useEntityHistoryPlugin.d.ts +17 -0
- package/package.json +86 -0
- package/src/HistoryControllerProvider.tsx +40 -0
- package/src/components/EntityHistoryEntry.tsx +164 -0
- package/src/components/EntityHistoryView.tsx +234 -0
- package/src/components/UserChip.tsx +15 -0
- package/src/entity_history_callbacks.ts +99 -0
- package/src/index.ts +2 -0
- package/src/useEntityHistoryPlugin.tsx +61 -0
- package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,592 @@
|
|
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
|
+
const valueInPath = core.getValueInPath(entity.values, key);
|
161
|
+
const element = childProperty ? entity ? /* @__PURE__ */ jsxRuntime.jsx(core.PropertyPreview, { propertyKey: key, value: valueInPath, property: childProperty, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(core.SkeletonPropertyComponent, { property: childProperty, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "body2", children: typeof valueInPath === "string" ? valueInPath : JSON.stringify(valueInPath) });
|
162
|
+
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: element })
|
165
|
+
] }, "ref_prev_" + key);
|
166
|
+
}) })
|
167
|
+
] })
|
168
|
+
] });
|
169
|
+
}
|
170
|
+
function EntityHistoryView(t0) {
|
171
|
+
const $ = reactCompilerRuntime.c(53);
|
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 [revertVersionDialog, setRevertVersionDialog] = 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 || $[15] !== collection || $[16] !== dataSource || $[17] !== entity || $[18] !== formContext || $[19] !== snackbarController) {
|
301
|
+
t6 = function doRevert2(revertVersion) {
|
302
|
+
if (!entity) {
|
303
|
+
throw new Error("No entity to revert");
|
304
|
+
}
|
305
|
+
const revertValues = {
|
306
|
+
...revertVersion.values,
|
307
|
+
__metadata: {
|
308
|
+
...revertVersion.values?.__metadata,
|
309
|
+
reverted: true,
|
310
|
+
updated_on: /* @__PURE__ */ new Date(),
|
311
|
+
updated_by: authController.user?.uid ?? null
|
312
|
+
}
|
313
|
+
};
|
314
|
+
const saveReverted = dataSource.saveEntity({
|
315
|
+
path: entity.path,
|
316
|
+
entityId: entity.id,
|
317
|
+
values: revertValues,
|
318
|
+
collection,
|
319
|
+
status: "existing"
|
320
|
+
});
|
321
|
+
const saveRevertedHistory = dataSource.saveEntity({
|
322
|
+
path: revertVersion.path,
|
323
|
+
entityId: revertVersion.id,
|
324
|
+
values: revertValues,
|
325
|
+
collection,
|
326
|
+
status: "existing"
|
327
|
+
});
|
328
|
+
return Promise.all([saveReverted, saveRevertedHistory]).then(() => {
|
329
|
+
formContext.formex.resetForm({
|
330
|
+
values: revertVersion.values
|
331
|
+
});
|
332
|
+
setRevertVersionDialog(void 0);
|
333
|
+
snackbarController.open({
|
334
|
+
message: "Reverted version",
|
335
|
+
type: "info"
|
336
|
+
});
|
337
|
+
}).catch((error_0) => {
|
338
|
+
console.error("Error reverting entity:", error_0);
|
339
|
+
snackbarController.open({
|
340
|
+
message: "Error reverting entity",
|
341
|
+
type: "error"
|
342
|
+
});
|
343
|
+
});
|
344
|
+
};
|
345
|
+
$[14] = authController;
|
346
|
+
$[15] = collection;
|
347
|
+
$[16] = dataSource;
|
348
|
+
$[17] = entity;
|
349
|
+
$[18] = formContext;
|
350
|
+
$[19] = snackbarController;
|
351
|
+
$[20] = t6;
|
352
|
+
} else {
|
353
|
+
t6 = $[20];
|
354
|
+
}
|
355
|
+
const doRevert = t6;
|
356
|
+
let t7;
|
357
|
+
if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
|
358
|
+
t7 = ui.cls("relative flex-1 h-full overflow-auto w-full flex flex-col gap-4 p-8");
|
359
|
+
$[21] = t7;
|
360
|
+
} else {
|
361
|
+
t7 = $[21];
|
362
|
+
}
|
363
|
+
let t8;
|
364
|
+
if ($[22] === Symbol.for("react.memo_cache_sentinel")) {
|
365
|
+
t8 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "h5", className: "mt-24 ml-4", children: "History" });
|
366
|
+
$[22] = t8;
|
367
|
+
} else {
|
368
|
+
t8 = $[22];
|
369
|
+
}
|
370
|
+
let t9;
|
371
|
+
if ($[23] !== revisions.length) {
|
372
|
+
t9 = revisions.length === 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
373
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { className: "ml-4 mt-8", children: "No history available" }),
|
374
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "caption", className: "ml-4", children: "When you save an entity, a new version is created and stored in the history." })
|
375
|
+
] });
|
376
|
+
$[23] = revisions.length;
|
377
|
+
$[24] = t9;
|
378
|
+
} else {
|
379
|
+
t9 = $[24];
|
380
|
+
}
|
381
|
+
let t10;
|
382
|
+
if ($[25] !== collection || $[26] !== dirty || $[27] !== revisions || $[28] !== snackbarController) {
|
383
|
+
let t112;
|
384
|
+
if ($[30] !== collection || $[31] !== dirty || $[32] !== snackbarController) {
|
385
|
+
t112 = (revision, index) => {
|
386
|
+
const previewKeys = revision.values?.__metadata?.changed_fields;
|
387
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-cols gap-2 w-full", children: /* @__PURE__ */ jsxRuntime.jsx(EntityHistoryEntry, { size: "large", entity: revision, collection, previewKeys, actions: /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { title: "Revert to this version", className: "m-2 grow-0 self-start", children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: () => {
|
388
|
+
if (dirty) {
|
389
|
+
snackbarController.open({
|
390
|
+
message: "Please save or discard your changes before reverting",
|
391
|
+
type: "warning"
|
392
|
+
});
|
393
|
+
} else {
|
394
|
+
setRevertVersionDialog(revision);
|
395
|
+
}
|
396
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsx(ui.HistoryIcon, {}) }) }) }) }, index);
|
397
|
+
};
|
398
|
+
$[30] = collection;
|
399
|
+
$[31] = dirty;
|
400
|
+
$[32] = snackbarController;
|
401
|
+
$[33] = t112;
|
402
|
+
} else {
|
403
|
+
t112 = $[33];
|
404
|
+
}
|
405
|
+
t10 = revisions.map(t112);
|
406
|
+
$[25] = collection;
|
407
|
+
$[26] = dirty;
|
408
|
+
$[27] = revisions;
|
409
|
+
$[28] = snackbarController;
|
410
|
+
$[29] = t10;
|
411
|
+
} else {
|
412
|
+
t10 = $[29];
|
413
|
+
}
|
414
|
+
let t11;
|
415
|
+
if ($[34] !== hasMore || $[35] !== isLoading || $[36] !== revisions.length) {
|
416
|
+
t11 = revisions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: loadMoreRef, className: "py-4 text-center", children: [
|
417
|
+
isLoading && /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "Loading more..." }),
|
418
|
+
!hasMore && revisions.length > 5 && /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: "No more history available" })
|
419
|
+
] });
|
420
|
+
$[34] = hasMore;
|
421
|
+
$[35] = isLoading;
|
422
|
+
$[36] = revisions.length;
|
423
|
+
$[37] = t11;
|
424
|
+
} else {
|
425
|
+
t11 = $[37];
|
426
|
+
}
|
427
|
+
let t12;
|
428
|
+
if ($[38] !== t10 || $[39] !== t11 || $[40] !== t9) {
|
429
|
+
t12 = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 max-w-6xl mx-auto w-full", children: [
|
430
|
+
t8,
|
431
|
+
t9,
|
432
|
+
t10,
|
433
|
+
t11
|
434
|
+
] });
|
435
|
+
$[38] = t10;
|
436
|
+
$[39] = t11;
|
437
|
+
$[40] = t9;
|
438
|
+
$[41] = t12;
|
439
|
+
} else {
|
440
|
+
t12 = $[41];
|
441
|
+
}
|
442
|
+
const t13 = Boolean(revertVersionDialog);
|
443
|
+
let t14;
|
444
|
+
if ($[42] !== doRevert || $[43] !== revertVersionDialog) {
|
445
|
+
t14 = function() {
|
446
|
+
if (!revertVersionDialog) {
|
447
|
+
return;
|
448
|
+
}
|
449
|
+
doRevert(revertVersionDialog);
|
450
|
+
};
|
451
|
+
$[42] = doRevert;
|
452
|
+
$[43] = revertVersionDialog;
|
453
|
+
$[44] = t14;
|
454
|
+
} else {
|
455
|
+
t14 = $[44];
|
456
|
+
}
|
457
|
+
let t15;
|
458
|
+
let t16;
|
459
|
+
if ($[45] === Symbol.for("react.memo_cache_sentinel")) {
|
460
|
+
t15 = function() {
|
461
|
+
setRevertVersionDialog(void 0);
|
462
|
+
};
|
463
|
+
t16 = /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "subtitle2", children: "Revert data to this version?" });
|
464
|
+
$[45] = t15;
|
465
|
+
$[46] = t16;
|
466
|
+
} else {
|
467
|
+
t15 = $[45];
|
468
|
+
t16 = $[46];
|
469
|
+
}
|
470
|
+
let t17;
|
471
|
+
if ($[47] !== t13 || $[48] !== t14) {
|
472
|
+
t17 = /* @__PURE__ */ jsxRuntime.jsx(core.ConfirmationDialog, { open: t13, onAccept: t14, onCancel: t15, title: t16 });
|
473
|
+
$[47] = t13;
|
474
|
+
$[48] = t14;
|
475
|
+
$[49] = t17;
|
476
|
+
} else {
|
477
|
+
t17 = $[49];
|
478
|
+
}
|
479
|
+
let t18;
|
480
|
+
if ($[50] !== t12 || $[51] !== t17) {
|
481
|
+
t18 = /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: t7, children: [
|
482
|
+
t12,
|
483
|
+
t17
|
484
|
+
] });
|
485
|
+
$[50] = t12;
|
486
|
+
$[51] = t17;
|
487
|
+
$[52] = t18;
|
488
|
+
} else {
|
489
|
+
t18 = $[52];
|
490
|
+
}
|
491
|
+
return t18;
|
492
|
+
}
|
493
|
+
const entityHistoryCallbacks = {
|
494
|
+
onSaveSuccess: async (props) => {
|
495
|
+
const changedFields = props.previousValues ? findChangedFields(props.previousValues, props.values) : null;
|
496
|
+
const uid = props.context.authController.user?.uid;
|
497
|
+
props.context.dataSource.saveEntity({
|
498
|
+
path: props.path + "/" + props.entityId + "/__history",
|
499
|
+
values: {
|
500
|
+
...props.values,
|
501
|
+
__metadata: {
|
502
|
+
changed_fields: changedFields,
|
503
|
+
updated_on: /* @__PURE__ */ new Date(),
|
504
|
+
updated_by: uid
|
505
|
+
}
|
506
|
+
},
|
507
|
+
status: "new"
|
508
|
+
}).then(() => {
|
509
|
+
console.debug("History saved for", props.path, props.entityId);
|
510
|
+
});
|
511
|
+
}
|
512
|
+
};
|
513
|
+
function findChangedFields(oldValues, newValues, prefix = "") {
|
514
|
+
const changedFields = [];
|
515
|
+
if (equal(oldValues, newValues)) return changedFields;
|
516
|
+
if (!oldValues || !newValues) return [prefix || "."];
|
517
|
+
const allKeys = /* @__PURE__ */ new Set([...Object.keys(oldValues), ...Object.keys(newValues)]);
|
518
|
+
for (const key of allKeys) {
|
519
|
+
const oldValue = oldValues[key];
|
520
|
+
const newValue = newValues[key];
|
521
|
+
const currentPath = prefix ? `${prefix}.${key}` : key;
|
522
|
+
if (key in oldValues !== key in newValues) {
|
523
|
+
changedFields.push(currentPath);
|
524
|
+
continue;
|
525
|
+
}
|
526
|
+
if (equal(oldValue, newValue)) continue;
|
527
|
+
if (Array.isArray(oldValue) && Array.isArray(newValue)) {
|
528
|
+
if (oldValue.length !== newValue.length) {
|
529
|
+
changedFields.push(currentPath);
|
530
|
+
} else {
|
531
|
+
for (let i = 0; i < oldValue.length; i++) {
|
532
|
+
if (typeof oldValue[i] === "object" && oldValue[i] !== null && typeof newValue[i] === "object" && newValue[i] !== null) {
|
533
|
+
const nestedChanges = findChangedFields(oldValue[i], newValue[i], `${currentPath}[${i}]`);
|
534
|
+
if (nestedChanges.length > 0) {
|
535
|
+
changedFields.push(currentPath);
|
536
|
+
break;
|
537
|
+
}
|
538
|
+
} else if (!equal(oldValue[i], newValue[i])) {
|
539
|
+
changedFields.push(currentPath);
|
540
|
+
break;
|
541
|
+
}
|
542
|
+
}
|
543
|
+
}
|
544
|
+
} else if (typeof oldValue === "object" && oldValue !== null && typeof newValue === "object" && newValue !== null) {
|
545
|
+
const nestedChanges = findChangedFields(oldValue, newValue, currentPath);
|
546
|
+
changedFields.push(...nestedChanges);
|
547
|
+
} else {
|
548
|
+
changedFields.push(currentPath);
|
549
|
+
}
|
550
|
+
}
|
551
|
+
return changedFields;
|
552
|
+
}
|
553
|
+
function useEntityHistoryPlugin(props) {
|
554
|
+
const {
|
555
|
+
defaultEnabled = false
|
556
|
+
} = props ?? {};
|
557
|
+
const modifyCollection = React.useCallback((collection) => {
|
558
|
+
if (collection.history === true || defaultEnabled && collection.history !== false) {
|
559
|
+
return {
|
560
|
+
...collection,
|
561
|
+
entityViews: [...collection.entityViews ?? [], {
|
562
|
+
key: "__history",
|
563
|
+
name: "History",
|
564
|
+
tabComponent: /* @__PURE__ */ jsxRuntime.jsx(ui.HistoryIcon, { size: "small" }),
|
565
|
+
Builder: EntityHistoryView,
|
566
|
+
position: "start"
|
567
|
+
}],
|
568
|
+
callbacks: core.mergeCallbacks(collection.callbacks, entityHistoryCallbacks)
|
569
|
+
};
|
570
|
+
}
|
571
|
+
return collection;
|
572
|
+
}, []);
|
573
|
+
return React.useMemo(() => ({
|
574
|
+
key: "entity_history",
|
575
|
+
provider: {
|
576
|
+
Component: HistoryControllerProvider,
|
577
|
+
props: {
|
578
|
+
getUser: props?.getUser
|
579
|
+
}
|
580
|
+
},
|
581
|
+
collection: {
|
582
|
+
modifyCollection
|
583
|
+
}
|
584
|
+
}), [props]);
|
585
|
+
}
|
586
|
+
exports2.HistoryControllerContext = HistoryControllerContext;
|
587
|
+
exports2.HistoryControllerProvider = HistoryControllerProvider;
|
588
|
+
exports2.useEntityHistoryPlugin = useEntityHistoryPlugin;
|
589
|
+
exports2.useHistoryController = useHistoryController;
|
590
|
+
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
|
591
|
+
});
|
592
|
+
//# sourceMappingURL=index.umd.js.map
|