@proveanything/smartlinks-utils-ui 0.10.9 → 0.11.0
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/{chunk-2MW54ZVG.js → chunk-BNC6Z6WB.js} +97 -4
- package/dist/chunk-BNC6Z6WB.js.map +1 -0
- package/dist/components/AssetPicker/index.css +3 -0
- package/dist/components/AssetPicker/index.css.map +1 -1
- package/dist/components/ConditionsEditor/index.css +3 -0
- package/dist/components/ConditionsEditor/index.css.map +1 -1
- package/dist/components/FontPicker/index.css +3 -0
- package/dist/components/FontPicker/index.css.map +1 -1
- package/dist/components/IconPicker/index.css +3 -0
- package/dist/components/IconPicker/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.css +3 -0
- package/dist/components/RecordsAdmin/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.d.ts +93 -5
- package/dist/components/RecordsAdmin/index.js +518 -89
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.css +3 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +51 -1
- package/dist/index.js +32 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-2MW54ZVG.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AdminPageHeader } from '../../chunk-
|
|
1
|
+
import { useIntroState, AdminPageHeader } from '../../chunk-BNC6Z6WB.js';
|
|
2
2
|
import { assertComponentStylesLoaded } from '../../chunk-OLYC54YT.js';
|
|
3
3
|
import '../../chunk-5UQQYXCX.js';
|
|
4
4
|
import { FacetRuleEditor } from '../../chunk-JMCV6FOW.js';
|
|
@@ -6,12 +6,105 @@ import { useFacets } from '../../chunk-4LHF5JB7.js';
|
|
|
6
6
|
import { cn } from '../../chunk-L7FQ52F5.js';
|
|
7
7
|
import { parsedRefToTarget, parsedRefToScope, matchRecords, scopesEqual, getRecordById, listRecords, upsertRecord, updateRecord, createRecord, removeRecord } from '../../chunk-KA4MKRHL.js';
|
|
8
8
|
export { bulkDelete, bulkUpsert, createRecord, getRecordById, listRecords, matchRecords, parsedRefToScope, parsedRefToTarget, removeRecord, restoreRecord, scopesEqual, upsertRecord } from '../../chunk-KA4MKRHL.js';
|
|
9
|
-
import { createContext, useState, useEffect, useCallback,
|
|
10
|
-
import { ChevronDown, Database, Lightbulb, SearchX, Inbox, LayoutGrid, Eye, MoreHorizontal, Download, Upload, Trash2, Copy, Pencil, Plus, CircleDashed, ArrowDownLeft, CheckCircle2, List, SlidersHorizontal, Globe, Tag, Boxes, Layers, Package, Target, Rows3, ChevronRight, Eraser, ClipboardPaste, Box, X, Search, Image, Table, ArrowLeft, ChevronLeft, AlertTriangle, Info, HelpCircle, CornerDownLeft, Circle, MinusCircle, XCircle, CopyPlus, AlertCircle, Undo2, Save, Loader2, ArrowRight, Globe2, Check, Settings2 } from 'lucide-react';
|
|
9
|
+
import { createContext, useMemo, useState, useEffect, useCallback, useRef, isValidElement, useContext, useSyncExternalStore, useLayoutEffect, createElement } from 'react';
|
|
10
|
+
import { ChevronDown, Database, Lightbulb, SearchX, Inbox, LayoutGrid, Eye, MoreHorizontal, Download, Upload, Trash2, Copy, Pencil, Plus, CircleDashed, ArrowDownLeft, CheckCircle2, List, SlidersHorizontal, Globe, Tag, Boxes, Layers, Package, Target, Rows3, ChevronRight, Eraser, ClipboardPaste, Box, X, Search, Image, Table, ArrowLeft, ChevronLeft, AlertTriangle, Info, HelpCircle, CornerDownLeft, Circle, ArrowUpDown, ArrowUp, ArrowDown, MinusCircle, XCircle, CopyPlus, AlertCircle, Undo2, Save, Loader2, ArrowRight, Globe2, Check, Settings2 } from 'lucide-react';
|
|
11
11
|
import { useQuery, useQueryClient, useInfiniteQuery } from '@tanstack/react-query';
|
|
12
12
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
13
13
|
import { createPortal } from 'react-dom';
|
|
14
14
|
|
|
15
|
+
// src/components/RecordsAdmin/data/recordCache.ts
|
|
16
|
+
var RECORD_LIST_QK = ["records-admin", "list"];
|
|
17
|
+
var COLLECTION_ITEMS_QK = ["records-admin", "collection-items"];
|
|
18
|
+
var matchesCtx = (queryKey, prefix, ctx) => {
|
|
19
|
+
if (queryKey.length < prefix.length + 3) return false;
|
|
20
|
+
for (let i = 0; i < prefix.length; i += 1) {
|
|
21
|
+
if (queryKey[i] !== prefix[i]) return false;
|
|
22
|
+
}
|
|
23
|
+
if (queryKey[prefix.length] !== ctx.collectionId) return false;
|
|
24
|
+
if (queryKey[prefix.length + 1] !== ctx.appId) return false;
|
|
25
|
+
if (queryKey[prefix.length + 2] !== (ctx.recordType ?? void 0) && queryKey[prefix.length + 2] !== ctx.recordType) {
|
|
26
|
+
const slot = queryKey[prefix.length + 2];
|
|
27
|
+
if (slot !== void 0 && slot !== ctx.recordType) return false;
|
|
28
|
+
if (slot === void 0 && ctx.recordType) return false;
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
};
|
|
32
|
+
var replaceOrAppend = (cache, record) => {
|
|
33
|
+
let replaced = false;
|
|
34
|
+
const nextPages = cache.pages.map((page) => {
|
|
35
|
+
const idx = page.data.findIndex((r) => r.id === record.id);
|
|
36
|
+
if (idx === -1) return page;
|
|
37
|
+
replaced = true;
|
|
38
|
+
const nextData = [...page.data];
|
|
39
|
+
nextData[idx] = record;
|
|
40
|
+
return { ...page, data: nextData };
|
|
41
|
+
});
|
|
42
|
+
if (replaced) return { ...cache, pages: nextPages };
|
|
43
|
+
if (nextPages.length === 0) {
|
|
44
|
+
return {
|
|
45
|
+
pageParams: [0],
|
|
46
|
+
pages: [{ data: [record], total: 1, hasMore: false, nextOffset: 1 }]
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const last = nextPages[nextPages.length - 1];
|
|
50
|
+
const updatedLast = {
|
|
51
|
+
...last,
|
|
52
|
+
data: [...last.data, record],
|
|
53
|
+
total: (last.total ?? 0) + 1,
|
|
54
|
+
nextOffset: (last.nextOffset ?? last.data.length) + 1
|
|
55
|
+
};
|
|
56
|
+
const bumped = nextPages.map((p, i) => i === nextPages.length - 1 ? updatedLast : { ...p, total: (p.total ?? 0) + 1 });
|
|
57
|
+
return { ...cache, pages: bumped };
|
|
58
|
+
};
|
|
59
|
+
var removeFromPages = (cache, recordId) => {
|
|
60
|
+
let found = false;
|
|
61
|
+
const nextPages = cache.pages.map((page) => {
|
|
62
|
+
const idx = page.data.findIndex((r) => r.id === recordId);
|
|
63
|
+
if (idx === -1) return page;
|
|
64
|
+
found = true;
|
|
65
|
+
return {
|
|
66
|
+
...page,
|
|
67
|
+
data: page.data.filter((r) => r.id !== recordId),
|
|
68
|
+
total: Math.max(0, (page.total ?? 0) - 1)
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
if (!found) return null;
|
|
72
|
+
const bumped = nextPages.map((p) => p.data.some((r) => r.id === recordId) ? p : { ...p, total: Math.max(0, p.total ?? 0) });
|
|
73
|
+
return { ...cache, pages: bumped };
|
|
74
|
+
};
|
|
75
|
+
function patchRecordIntoCaches(queryClient, ctx, record) {
|
|
76
|
+
if (!record || !record.id) return;
|
|
77
|
+
const all = [
|
|
78
|
+
...queryClient.getQueriesData({ queryKey: RECORD_LIST_QK }),
|
|
79
|
+
...queryClient.getQueriesData({ queryKey: COLLECTION_ITEMS_QK })
|
|
80
|
+
];
|
|
81
|
+
for (const [key, cache] of all) {
|
|
82
|
+
if (!cache || !Array.isArray(cache.pages)) continue;
|
|
83
|
+
const prefix = key[0] === RECORD_LIST_QK[0] && key[1] === RECORD_LIST_QK[1] ? RECORD_LIST_QK : COLLECTION_ITEMS_QK;
|
|
84
|
+
if (!matchesCtx(key, prefix, ctx)) continue;
|
|
85
|
+
queryClient.setQueryData(key, (prev) => {
|
|
86
|
+
if (!prev || !Array.isArray(prev.pages)) return prev;
|
|
87
|
+
return replaceOrAppend(prev, record);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function removeRecordFromCaches(queryClient, ctx, recordId) {
|
|
92
|
+
if (!recordId) return;
|
|
93
|
+
const all = [
|
|
94
|
+
...queryClient.getQueriesData({ queryKey: RECORD_LIST_QK }),
|
|
95
|
+
...queryClient.getQueriesData({ queryKey: COLLECTION_ITEMS_QK })
|
|
96
|
+
];
|
|
97
|
+
for (const [key, cache] of all) {
|
|
98
|
+
if (!cache || !Array.isArray(cache.pages)) continue;
|
|
99
|
+
const prefix = key[0] === RECORD_LIST_QK[0] && key[1] === RECORD_LIST_QK[1] ? RECORD_LIST_QK : COLLECTION_ITEMS_QK;
|
|
100
|
+
if (!matchesCtx(key, prefix, ctx)) continue;
|
|
101
|
+
queryClient.setQueryData(key, (prev) => {
|
|
102
|
+
if (!prev || !Array.isArray(prev.pages)) return prev;
|
|
103
|
+
const next = removeFromPages(prev, recordId);
|
|
104
|
+
return next ?? prev;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
15
108
|
var DEFAULT_ICONS = {
|
|
16
109
|
scope: {
|
|
17
110
|
collection: Globe,
|
|
@@ -412,58 +505,12 @@ function useResolvedRecord(args) {
|
|
|
412
505
|
error: query.error ?? null
|
|
413
506
|
};
|
|
414
507
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
var useIntroDismissed = (SL,
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
} catch {
|
|
422
|
-
return false;
|
|
423
|
-
}
|
|
424
|
-
});
|
|
425
|
-
useEffect(() => {
|
|
426
|
-
let cancelled = false;
|
|
427
|
-
(async () => {
|
|
428
|
-
try {
|
|
429
|
-
const cfg = await SL?.appConfiguration?.getConfig?.({ collectionId, appId, admin: true });
|
|
430
|
-
if (cancelled) return;
|
|
431
|
-
const flag = cfg?._meta?.introDismissed?.[RT_KEY(recordType)];
|
|
432
|
-
if (flag) setDismissed(true);
|
|
433
|
-
} catch {
|
|
434
|
-
}
|
|
435
|
-
})();
|
|
436
|
-
return () => {
|
|
437
|
-
cancelled = true;
|
|
438
|
-
};
|
|
439
|
-
}, [SL, collectionId, appId, recordType]);
|
|
440
|
-
const dismiss = useCallback(async () => {
|
|
441
|
-
setDismissed(true);
|
|
442
|
-
try {
|
|
443
|
-
localStorage.setItem(lsKey(appId, recordType), "1");
|
|
444
|
-
} catch {
|
|
445
|
-
}
|
|
446
|
-
try {
|
|
447
|
-
const cfg = await SL?.appConfiguration?.getConfig?.({ collectionId, appId, admin: true }).catch(() => ({}));
|
|
448
|
-
const next = {
|
|
449
|
-
...cfg ?? {},
|
|
450
|
-
_meta: {
|
|
451
|
-
...cfg?._meta ?? {},
|
|
452
|
-
introDismissed: { ...cfg?._meta?.introDismissed ?? {}, [RT_KEY(recordType)]: true }
|
|
453
|
-
}
|
|
454
|
-
};
|
|
455
|
-
await SL?.appConfiguration?.setConfig?.({ collectionId, appId, admin: true, config: next });
|
|
456
|
-
} catch {
|
|
457
|
-
}
|
|
458
|
-
}, [SL, collectionId, appId, recordType]);
|
|
459
|
-
const undismiss = useCallback(() => {
|
|
460
|
-
setDismissed(false);
|
|
461
|
-
try {
|
|
462
|
-
localStorage.removeItem(lsKey(appId, recordType));
|
|
463
|
-
} catch {
|
|
464
|
-
}
|
|
465
|
-
}, [appId, recordType]);
|
|
466
|
-
return { dismissed, dismiss, undismiss };
|
|
508
|
+
|
|
509
|
+
// src/components/RecordsAdmin/hooks/useIntroDismissed.ts
|
|
510
|
+
var useIntroDismissed = (SL, _collectionId, appId, recordType) => {
|
|
511
|
+
const persistKey = recordType ? `${appId}:${recordType}` : appId;
|
|
512
|
+
const { dismissed, onDismiss, onReopen } = useIntroState({ SL, persistKey });
|
|
513
|
+
return { dismissed, dismiss: onDismiss, undismiss: onReopen };
|
|
467
514
|
};
|
|
468
515
|
var useScopeProbe = ({ SL, collectionId, admin = true, enabled = true }) => {
|
|
469
516
|
const query = useQuery({
|
|
@@ -1055,7 +1102,8 @@ function useShellBrowser(opts) {
|
|
|
1055
1102
|
probeIsLoading,
|
|
1056
1103
|
selectedProductId,
|
|
1057
1104
|
drillTab,
|
|
1058
|
-
classify: classify3
|
|
1105
|
+
classify: classify3,
|
|
1106
|
+
pageSize
|
|
1059
1107
|
} = opts;
|
|
1060
1108
|
const [search, setSearch] = useState("");
|
|
1061
1109
|
const [filter, setFilter] = useState("all");
|
|
@@ -1081,7 +1129,8 @@ function useShellBrowser(opts) {
|
|
|
1081
1129
|
filter,
|
|
1082
1130
|
classify: classify3,
|
|
1083
1131
|
contextScope,
|
|
1084
|
-
enabled: recordListEnabled
|
|
1132
|
+
enabled: recordListEnabled,
|
|
1133
|
+
pageSize
|
|
1085
1134
|
});
|
|
1086
1135
|
const facetBrowse = useFacetBrowse({
|
|
1087
1136
|
SL,
|
|
@@ -2352,6 +2401,7 @@ var createEditorStore = () => {
|
|
|
2352
2401
|
let nextOrder = 0;
|
|
2353
2402
|
let hooksBundle = null;
|
|
2354
2403
|
let notifier = null;
|
|
2404
|
+
let recordChangeNotifier = null;
|
|
2355
2405
|
const buildRecordSummary = (entry, value) => ({
|
|
2356
2406
|
id: entry.recordId ?? null,
|
|
2357
2407
|
ref: entry.spec.scope.raw,
|
|
@@ -2557,8 +2607,9 @@ var createEditorStore = () => {
|
|
|
2557
2607
|
});
|
|
2558
2608
|
try {
|
|
2559
2609
|
let nextRecordId = entry.recordId;
|
|
2610
|
+
let savedRecord = null;
|
|
2560
2611
|
if (entry.recordId && entry.source === "self") {
|
|
2561
|
-
await updateRecord(ctx, entry.recordId, {
|
|
2612
|
+
savedRecord = await updateRecord(ctx, entry.recordId, {
|
|
2562
2613
|
data: persistedValue,
|
|
2563
2614
|
facetRule: persistedFacetRule
|
|
2564
2615
|
});
|
|
@@ -2577,6 +2628,7 @@ var createEditorStore = () => {
|
|
|
2577
2628
|
facetRule: persistedFacetRule
|
|
2578
2629
|
});
|
|
2579
2630
|
nextRecordId = created?.id ?? nextRecordId;
|
|
2631
|
+
savedRecord = created;
|
|
2580
2632
|
} else {
|
|
2581
2633
|
const upserted = await upsertRecord(ctx, {
|
|
2582
2634
|
ref: spec.ref,
|
|
@@ -2585,6 +2637,7 @@ var createEditorStore = () => {
|
|
|
2585
2637
|
facetRule: persistedFacetRule
|
|
2586
2638
|
});
|
|
2587
2639
|
nextRecordId = upserted.record?.id ?? nextRecordId;
|
|
2640
|
+
savedRecord = upserted.record;
|
|
2588
2641
|
}
|
|
2589
2642
|
update(editorId, (e) => {
|
|
2590
2643
|
if (persistedValue !== entry.value) {
|
|
@@ -2597,6 +2650,12 @@ var createEditorStore = () => {
|
|
|
2597
2650
|
e.status = "saved";
|
|
2598
2651
|
e.error = void 0;
|
|
2599
2652
|
});
|
|
2653
|
+
if (savedRecord && savedRecord.id) {
|
|
2654
|
+
try {
|
|
2655
|
+
recordChangeNotifier?.({ kind: "saved", record: savedRecord, isCreate, ctx });
|
|
2656
|
+
} catch {
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2600
2659
|
if (hooksBundle?.afterSave) {
|
|
2601
2660
|
const refreshed = map.get(editorId);
|
|
2602
2661
|
const hookCtx = {
|
|
@@ -2654,6 +2713,10 @@ var createEditorStore = () => {
|
|
|
2654
2713
|
await removeRecord(entry.saveSpec.ctx, entry.recordId);
|
|
2655
2714
|
map.delete(editorId);
|
|
2656
2715
|
emit();
|
|
2716
|
+
try {
|
|
2717
|
+
recordChangeNotifier?.({ kind: "deleted", recordId: entry.recordId, ctx: entry.saveSpec.ctx });
|
|
2718
|
+
} catch {
|
|
2719
|
+
}
|
|
2657
2720
|
if (hooksBundle?.afterDelete && deletedSnapshot) {
|
|
2658
2721
|
try {
|
|
2659
2722
|
await hooksBundle.afterDelete(deletedSnapshot);
|
|
@@ -2688,6 +2751,9 @@ var createEditorStore = () => {
|
|
|
2688
2751
|
},
|
|
2689
2752
|
setNotifier(notify2) {
|
|
2690
2753
|
notifier = notify2 ?? null;
|
|
2754
|
+
},
|
|
2755
|
+
setRecordChangeNotifier(notify2) {
|
|
2756
|
+
recordChangeNotifier = notify2 ?? null;
|
|
2691
2757
|
}
|
|
2692
2758
|
};
|
|
2693
2759
|
};
|
|
@@ -2711,12 +2777,14 @@ var EditorSessionProvider = ({
|
|
|
2711
2777
|
maxOpenEditors = 8,
|
|
2712
2778
|
defaultValueFactory,
|
|
2713
2779
|
hooks,
|
|
2714
|
-
onHookNotice
|
|
2780
|
+
onHookNotice,
|
|
2781
|
+
onRecordChange
|
|
2715
2782
|
}) => {
|
|
2716
2783
|
const storeRef = useRef(null);
|
|
2717
2784
|
if (!storeRef.current) storeRef.current = createEditorStore();
|
|
2718
2785
|
storeRef.current.setHooks(hooks ?? null);
|
|
2719
2786
|
storeRef.current.setNotifier(onHookNotice ?? null);
|
|
2787
|
+
storeRef.current.setRecordChangeNotifier(onRecordChange ?? null);
|
|
2720
2788
|
const currentRef = useRef(void 0);
|
|
2721
2789
|
const listenersRef = useRef(/* @__PURE__ */ new Set());
|
|
2722
2790
|
const subscribeCurrent = useCallback((cb) => {
|
|
@@ -3749,6 +3817,56 @@ var ProductList = RecordList;
|
|
|
3749
3817
|
var FacetList = RecordList;
|
|
3750
3818
|
var VariantList = RecordList;
|
|
3751
3819
|
var BatchList = RecordList;
|
|
3820
|
+
function LoadMoreFooter({
|
|
3821
|
+
shown,
|
|
3822
|
+
total,
|
|
3823
|
+
hasNextPage,
|
|
3824
|
+
isFetchingNextPage,
|
|
3825
|
+
onLoadMore,
|
|
3826
|
+
label
|
|
3827
|
+
}) {
|
|
3828
|
+
if (!hasNextPage && (total === void 0 || total <= shown)) return null;
|
|
3829
|
+
const knownTotal = typeof total === "number" && total >= shown;
|
|
3830
|
+
const summary = knownTotal ? `Showing ${shown} of ${total}` : `${shown} shown`;
|
|
3831
|
+
return /* @__PURE__ */ jsxs(
|
|
3832
|
+
"div",
|
|
3833
|
+
{
|
|
3834
|
+
className: "ra-loadmore",
|
|
3835
|
+
style: {
|
|
3836
|
+
display: "flex",
|
|
3837
|
+
alignItems: "center",
|
|
3838
|
+
gap: "8px",
|
|
3839
|
+
padding: "8px 12px",
|
|
3840
|
+
borderTop: "1px solid hsl(var(--ra-border))",
|
|
3841
|
+
background: "hsl(var(--ra-surface))"
|
|
3842
|
+
},
|
|
3843
|
+
children: [
|
|
3844
|
+
/* @__PURE__ */ jsx(
|
|
3845
|
+
"span",
|
|
3846
|
+
{
|
|
3847
|
+
style: {
|
|
3848
|
+
fontSize: "11px",
|
|
3849
|
+
color: "hsl(var(--ra-muted-text))",
|
|
3850
|
+
flex: 1
|
|
3851
|
+
},
|
|
3852
|
+
children: summary
|
|
3853
|
+
}
|
|
3854
|
+
),
|
|
3855
|
+
hasNextPage && /* @__PURE__ */ jsx(
|
|
3856
|
+
"button",
|
|
3857
|
+
{
|
|
3858
|
+
type: "button",
|
|
3859
|
+
onClick: onLoadMore,
|
|
3860
|
+
disabled: isFetchingNextPage,
|
|
3861
|
+
className: "ra-btn",
|
|
3862
|
+
style: { fontSize: "11px", padding: "4px 10px" },
|
|
3863
|
+
children: isFetchingNextPage ? "Loading\u2026" : label ?? "Load more"
|
|
3864
|
+
}
|
|
3865
|
+
)
|
|
3866
|
+
]
|
|
3867
|
+
}
|
|
3868
|
+
);
|
|
3869
|
+
}
|
|
3752
3870
|
var COLLAPSED_FACET_CAP = 6;
|
|
3753
3871
|
var COLLAPSED_VALUE_CAP = 12;
|
|
3754
3872
|
var VALUE_SEARCH_THRESHOLD = 12;
|
|
@@ -5659,18 +5777,52 @@ function DefaultItemTable({
|
|
|
5659
5777
|
selectedId,
|
|
5660
5778
|
onOpen,
|
|
5661
5779
|
onDelete,
|
|
5780
|
+
sort,
|
|
5781
|
+
onToggleSort,
|
|
5662
5782
|
rowActions,
|
|
5663
5783
|
rowClipboard,
|
|
5664
5784
|
i18n
|
|
5665
5785
|
}) {
|
|
5666
5786
|
const cols = columns ?? [];
|
|
5667
5787
|
const useFallback = cols.length === 0;
|
|
5788
|
+
const renderSortIcon = (key, sortable) => {
|
|
5789
|
+
if (!sortable) return null;
|
|
5790
|
+
if (sort?.key !== key || !sort?.dir) {
|
|
5791
|
+
return /* @__PURE__ */ jsx(ArrowUpDown, { className: "w-3 h-3 opacity-40", "aria-hidden": "true" });
|
|
5792
|
+
}
|
|
5793
|
+
return sort.dir === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "w-3 h-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ArrowDown, { className: "w-3 h-3", "aria-hidden": "true" });
|
|
5794
|
+
};
|
|
5668
5795
|
return /* @__PURE__ */ jsx("div", { className: "ra-item-table-wrap", children: /* @__PURE__ */ jsxs("table", { className: "ra-item-table", children: [
|
|
5669
5796
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
5670
5797
|
useFallback ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5671
|
-
/* @__PURE__ */ jsx("th", { children:
|
|
5672
|
-
|
|
5673
|
-
|
|
5798
|
+
/* @__PURE__ */ jsx("th", { children: /* @__PURE__ */ jsx(
|
|
5799
|
+
SortableHeader,
|
|
5800
|
+
{
|
|
5801
|
+
label: i18n.itemColumnLabel,
|
|
5802
|
+
sortable: !!onToggleSort,
|
|
5803
|
+
icon: renderSortIcon("__label", !!onToggleSort),
|
|
5804
|
+
onClick: () => onToggleSort?.("__label")
|
|
5805
|
+
}
|
|
5806
|
+
) }),
|
|
5807
|
+
/* @__PURE__ */ jsx("th", { style: { width: "12rem" }, children: /* @__PURE__ */ jsx(
|
|
5808
|
+
SortableHeader,
|
|
5809
|
+
{
|
|
5810
|
+
label: i18n.itemColumnUpdated,
|
|
5811
|
+
sortable: !!onToggleSort,
|
|
5812
|
+
icon: renderSortIcon("__updated", !!onToggleSort),
|
|
5813
|
+
onClick: () => onToggleSort?.("__updated")
|
|
5814
|
+
}
|
|
5815
|
+
) })
|
|
5816
|
+
] }) : cols.map((c) => /* @__PURE__ */ jsx("th", { style: { width: c.width, textAlign: c.align ?? "left" }, children: /* @__PURE__ */ jsx(
|
|
5817
|
+
SortableHeader,
|
|
5818
|
+
{
|
|
5819
|
+
label: c.header,
|
|
5820
|
+
sortable: !!c.sortBy && !!onToggleSort,
|
|
5821
|
+
icon: renderSortIcon(c.key, !!c.sortBy && !!onToggleSort),
|
|
5822
|
+
onClick: () => onToggleSort?.(c.key),
|
|
5823
|
+
align: c.align ?? "left"
|
|
5824
|
+
}
|
|
5825
|
+
) }, c.key)),
|
|
5674
5826
|
/* @__PURE__ */ jsx(
|
|
5675
5827
|
"th",
|
|
5676
5828
|
{
|
|
@@ -5758,6 +5910,39 @@ function DefaultItemTable({
|
|
|
5758
5910
|
}) })
|
|
5759
5911
|
] }) });
|
|
5760
5912
|
}
|
|
5913
|
+
function SortableHeader({
|
|
5914
|
+
label,
|
|
5915
|
+
sortable,
|
|
5916
|
+
icon,
|
|
5917
|
+
onClick,
|
|
5918
|
+
align = "left"
|
|
5919
|
+
}) {
|
|
5920
|
+
if (!sortable) return /* @__PURE__ */ jsx(Fragment, { children: label });
|
|
5921
|
+
return /* @__PURE__ */ jsxs(
|
|
5922
|
+
"button",
|
|
5923
|
+
{
|
|
5924
|
+
type: "button",
|
|
5925
|
+
onClick,
|
|
5926
|
+
className: "ra-item-th-sort",
|
|
5927
|
+
style: {
|
|
5928
|
+
display: "inline-flex",
|
|
5929
|
+
alignItems: "center",
|
|
5930
|
+
gap: "4px",
|
|
5931
|
+
background: "transparent",
|
|
5932
|
+
border: 0,
|
|
5933
|
+
padding: 0,
|
|
5934
|
+
font: "inherit",
|
|
5935
|
+
color: "inherit",
|
|
5936
|
+
cursor: "pointer",
|
|
5937
|
+
textAlign: align
|
|
5938
|
+
},
|
|
5939
|
+
children: [
|
|
5940
|
+
/* @__PURE__ */ jsx("span", { children: label }),
|
|
5941
|
+
icon
|
|
5942
|
+
]
|
|
5943
|
+
}
|
|
5944
|
+
);
|
|
5945
|
+
}
|
|
5761
5946
|
var initials = (label) => label.split(/\s+/).slice(0, 2).map((s) => s[0]?.toUpperCase() ?? "").join("") || "?";
|
|
5762
5947
|
function DefaultItemCards({
|
|
5763
5948
|
items,
|
|
@@ -5872,9 +6057,75 @@ function ItemListView({
|
|
|
5872
6057
|
cardSize = "md",
|
|
5873
6058
|
rowActions,
|
|
5874
6059
|
rowClipboard,
|
|
6060
|
+
searchableFields,
|
|
6061
|
+
searchable = true,
|
|
6062
|
+
total,
|
|
6063
|
+
hasNextPage,
|
|
6064
|
+
isFetchingNextPage,
|
|
6065
|
+
onLoadMore,
|
|
5875
6066
|
i18n
|
|
5876
6067
|
}) {
|
|
5877
6068
|
const newLabel = i18n.newItem.includes("{noun}") ? i18n.newItem.replace("{noun}", itemNoun) : i18n.newItem;
|
|
6069
|
+
const [search, setSearch] = useState("");
|
|
6070
|
+
const [sort, setSort] = useState({ key: null, dir: null });
|
|
6071
|
+
const onToggleSort = (key) => {
|
|
6072
|
+
setSort((cur) => {
|
|
6073
|
+
if (cur.key !== key) return { key, dir: "asc" };
|
|
6074
|
+
const next = cur.dir === "asc" ? "desc" : cur.dir === "desc" ? null : "asc";
|
|
6075
|
+
return { key: next ? key : null, dir: next };
|
|
6076
|
+
});
|
|
6077
|
+
};
|
|
6078
|
+
const wantsFullSet = search.trim().length > 0 || sort.dir !== null;
|
|
6079
|
+
const loadingNextRef = useRef(false);
|
|
6080
|
+
useEffect(() => {
|
|
6081
|
+
if (!wantsFullSet || !hasNextPage || !onLoadMore) return;
|
|
6082
|
+
if (isFetchingNextPage || loadingNextRef.current) return;
|
|
6083
|
+
loadingNextRef.current = true;
|
|
6084
|
+
onLoadMore();
|
|
6085
|
+
}, [wantsFullSet, hasNextPage, onLoadMore, isFetchingNextPage]);
|
|
6086
|
+
useEffect(() => {
|
|
6087
|
+
if (!isFetchingNextPage) loadingNextRef.current = false;
|
|
6088
|
+
}, [isFetchingNextPage]);
|
|
6089
|
+
const lookupColumn = useMemo(() => {
|
|
6090
|
+
const m = /* @__PURE__ */ new Map();
|
|
6091
|
+
(itemColumns ?? []).forEach((c) => m.set(c.key, c));
|
|
6092
|
+
return m;
|
|
6093
|
+
}, [itemColumns]);
|
|
6094
|
+
const visibleItems = useMemo(() => {
|
|
6095
|
+
let out = items;
|
|
6096
|
+
const q = search.trim().toLowerCase();
|
|
6097
|
+
if (q) {
|
|
6098
|
+
out = out.filter((it) => {
|
|
6099
|
+
const fields = [it.label, it.subtitle];
|
|
6100
|
+
if (searchableFields) fields.push(...searchableFields(it));
|
|
6101
|
+
return fields.some((f) => typeof f === "string" && f.toLowerCase().includes(q));
|
|
6102
|
+
});
|
|
6103
|
+
}
|
|
6104
|
+
if (sort.key && sort.dir) {
|
|
6105
|
+
const dir = sort.dir === "asc" ? 1 : -1;
|
|
6106
|
+
const getter = (it) => {
|
|
6107
|
+
if (sort.key === "__label") return it.label;
|
|
6108
|
+
if (sort.key === "__updated") return it.updatedAt;
|
|
6109
|
+
const col = lookupColumn.get(sort.key);
|
|
6110
|
+
return col?.sortBy ? col.sortBy(it) : void 0;
|
|
6111
|
+
};
|
|
6112
|
+
const norm = (v) => {
|
|
6113
|
+
if (v == null) return Number.POSITIVE_INFINITY;
|
|
6114
|
+
if (v instanceof Date) return v.getTime();
|
|
6115
|
+
if (typeof v === "boolean") return v ? 1 : 0;
|
|
6116
|
+
if (typeof v === "number") return v;
|
|
6117
|
+
return String(v).toLowerCase();
|
|
6118
|
+
};
|
|
6119
|
+
out = [...out].sort((a, b) => {
|
|
6120
|
+
const av = norm(getter(a));
|
|
6121
|
+
const bv = norm(getter(b));
|
|
6122
|
+
if (av < bv) return -1 * dir;
|
|
6123
|
+
if (av > bv) return 1 * dir;
|
|
6124
|
+
return 0;
|
|
6125
|
+
});
|
|
6126
|
+
}
|
|
6127
|
+
return out;
|
|
6128
|
+
}, [items, search, sort, lookupColumn, searchableFields]);
|
|
5878
6129
|
const [pendingDeleteId, setPendingDeleteId] = useState(null);
|
|
5879
6130
|
const pendingRecord = useMemo(
|
|
5880
6131
|
() => pendingDeleteId ? items.find((it) => (it.itemId ?? "") === pendingDeleteId) ?? null : null,
|
|
@@ -5889,9 +6140,62 @@ function ItemListView({
|
|
|
5889
6140
|
const toolbar = /* @__PURE__ */ jsxs("div", { className: "ra-item-toolbar", children: [
|
|
5890
6141
|
/* @__PURE__ */ jsxs("div", { className: "ra-item-toolbar-title", children: [
|
|
5891
6142
|
/* @__PURE__ */ jsx("h2", { className: "ra-display", style: { fontSize: "0.95rem", margin: 0 }, children: i18n.itemListTitle }),
|
|
5892
|
-
/* @__PURE__ */ jsx("span", { className: "ra-item-toolbar-count", children: items.length })
|
|
6143
|
+
/* @__PURE__ */ jsx("span", { className: "ra-item-toolbar-count", children: visibleItems.length === items.length ? items.length : `${visibleItems.length} / ${items.length}` })
|
|
5893
6144
|
] }),
|
|
5894
6145
|
/* @__PURE__ */ jsxs("div", { className: "ra-item-toolbar-actions", children: [
|
|
6146
|
+
searchable && items.length > 0 && /* @__PURE__ */ jsxs(
|
|
6147
|
+
"div",
|
|
6148
|
+
{
|
|
6149
|
+
className: "ra-item-search",
|
|
6150
|
+
style: {
|
|
6151
|
+
display: "inline-flex",
|
|
6152
|
+
alignItems: "center",
|
|
6153
|
+
gap: "6px",
|
|
6154
|
+
padding: "4px 8px",
|
|
6155
|
+
border: "1px solid hsl(var(--ra-border))",
|
|
6156
|
+
borderRadius: "6px",
|
|
6157
|
+
background: "hsl(var(--ra-surface))"
|
|
6158
|
+
},
|
|
6159
|
+
children: [
|
|
6160
|
+
/* @__PURE__ */ jsx(Search, { className: "w-3.5 h-3.5", "aria-hidden": "true", style: { opacity: 0.6 } }),
|
|
6161
|
+
/* @__PURE__ */ jsx(
|
|
6162
|
+
"input",
|
|
6163
|
+
{
|
|
6164
|
+
type: "text",
|
|
6165
|
+
value: search,
|
|
6166
|
+
onChange: (e) => setSearch(e.target.value),
|
|
6167
|
+
placeholder: `Search ${itemNoun}s`,
|
|
6168
|
+
"aria-label": `Search ${itemNoun}s`,
|
|
6169
|
+
style: {
|
|
6170
|
+
background: "transparent",
|
|
6171
|
+
border: 0,
|
|
6172
|
+
outline: "none",
|
|
6173
|
+
font: "inherit",
|
|
6174
|
+
fontSize: "12px",
|
|
6175
|
+
color: "inherit",
|
|
6176
|
+
width: "160px"
|
|
6177
|
+
}
|
|
6178
|
+
}
|
|
6179
|
+
),
|
|
6180
|
+
search && /* @__PURE__ */ jsx(
|
|
6181
|
+
"button",
|
|
6182
|
+
{
|
|
6183
|
+
type: "button",
|
|
6184
|
+
onClick: () => setSearch(""),
|
|
6185
|
+
"aria-label": "Clear search",
|
|
6186
|
+
style: {
|
|
6187
|
+
background: "transparent",
|
|
6188
|
+
border: 0,
|
|
6189
|
+
padding: 0,
|
|
6190
|
+
cursor: "pointer",
|
|
6191
|
+
color: "hsl(var(--ra-muted-text))"
|
|
6192
|
+
},
|
|
6193
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5", "aria-hidden": "true" })
|
|
6194
|
+
}
|
|
6195
|
+
)
|
|
6196
|
+
]
|
|
6197
|
+
}
|
|
6198
|
+
),
|
|
5895
6199
|
!renderItemList && /* @__PURE__ */ jsx(
|
|
5896
6200
|
ItemViewSwitcher,
|
|
5897
6201
|
{
|
|
@@ -5942,17 +6246,27 @@ function ItemListView({
|
|
|
5942
6246
|
)
|
|
5943
6247
|
}
|
|
5944
6248
|
);
|
|
6249
|
+
} else if (visibleItems.length === 0) {
|
|
6250
|
+
body = /* @__PURE__ */ jsx(
|
|
6251
|
+
EmptyState,
|
|
6252
|
+
{
|
|
6253
|
+
title: "No matches",
|
|
6254
|
+
body: `No ${itemNoun}s match "${search}".`
|
|
6255
|
+
}
|
|
6256
|
+
);
|
|
5945
6257
|
} else if (renderItemList) {
|
|
5946
|
-
body = renderItemList(
|
|
6258
|
+
body = renderItemList(visibleItems, guardedCtx);
|
|
5947
6259
|
} else if (view === "table") {
|
|
5948
6260
|
body = /* @__PURE__ */ jsx(
|
|
5949
6261
|
DefaultItemTable,
|
|
5950
6262
|
{
|
|
5951
|
-
items,
|
|
6263
|
+
items: visibleItems,
|
|
5952
6264
|
columns: itemColumns,
|
|
5953
6265
|
selectedId: guardedCtx.selectedId,
|
|
5954
6266
|
onOpen: guardedCtx.onOpen,
|
|
5955
6267
|
onDelete: guardedCtx.onDelete,
|
|
6268
|
+
sort,
|
|
6269
|
+
onToggleSort,
|
|
5956
6270
|
rowActions,
|
|
5957
6271
|
rowClipboard,
|
|
5958
6272
|
i18n
|
|
@@ -5962,7 +6276,7 @@ function ItemListView({
|
|
|
5962
6276
|
body = /* @__PURE__ */ jsx(
|
|
5963
6277
|
DefaultItemCards,
|
|
5964
6278
|
{
|
|
5965
|
-
items,
|
|
6279
|
+
items: visibleItems,
|
|
5966
6280
|
variant: view,
|
|
5967
6281
|
selectedId: guardedCtx.selectedId,
|
|
5968
6282
|
ctx: guardedCtx,
|
|
@@ -5998,6 +6312,29 @@ function ItemListView({
|
|
|
5998
6312
|
}
|
|
5999
6313
|
) : null,
|
|
6000
6314
|
/* @__PURE__ */ jsx("div", { className: "ra-item-list-body", children: body }),
|
|
6315
|
+
wantsFullSet && hasNextPage && /* @__PURE__ */ jsx(
|
|
6316
|
+
"div",
|
|
6317
|
+
{
|
|
6318
|
+
style: {
|
|
6319
|
+
padding: "6px 12px",
|
|
6320
|
+
fontSize: "11px",
|
|
6321
|
+
color: "hsl(var(--ra-muted-text))",
|
|
6322
|
+
borderTop: "1px solid hsl(var(--ra-border))",
|
|
6323
|
+
background: "hsl(var(--ra-muted) / 0.4)"
|
|
6324
|
+
},
|
|
6325
|
+
children: isFetchingNextPage ? `Loading more ${itemNoun}s to ${search ? "search" : "sort"}\u2026` : `${search ? "Searching" : "Sorting"} the ${items.length} ${itemNoun}s loaded so far. More available \u2014 keep loading for the full set.`
|
|
6326
|
+
}
|
|
6327
|
+
),
|
|
6328
|
+
onLoadMore && /* @__PURE__ */ jsx(
|
|
6329
|
+
LoadMoreFooter,
|
|
6330
|
+
{
|
|
6331
|
+
shown: items.length,
|
|
6332
|
+
total,
|
|
6333
|
+
hasNextPage: !!hasNextPage,
|
|
6334
|
+
isFetchingNextPage: !!isFetchingNextPage,
|
|
6335
|
+
onLoadMore
|
|
6336
|
+
}
|
|
6337
|
+
),
|
|
6001
6338
|
/* @__PURE__ */ jsx(
|
|
6002
6339
|
ConfirmDialog,
|
|
6003
6340
|
{
|
|
@@ -6086,7 +6423,11 @@ function SiblingRail({
|
|
|
6086
6423
|
itemNoun,
|
|
6087
6424
|
dirtyKeys,
|
|
6088
6425
|
errorKeys,
|
|
6089
|
-
i18n
|
|
6426
|
+
i18n,
|
|
6427
|
+
total,
|
|
6428
|
+
hasNextPage,
|
|
6429
|
+
isFetchingNextPage,
|
|
6430
|
+
onLoadMore
|
|
6090
6431
|
}) {
|
|
6091
6432
|
const ruleLabelLookup = useRuleLabelLookup();
|
|
6092
6433
|
const newLabel = i18n.newItem.includes("{noun}") ? i18n.newItem.replace("{noun}", itemNoun ?? "item") : i18n.newItem;
|
|
@@ -6166,6 +6507,16 @@ function SiblingRail({
|
|
|
6166
6507
|
) }, key);
|
|
6167
6508
|
}) })
|
|
6168
6509
|
] }),
|
|
6510
|
+
onLoadMore && /* @__PURE__ */ jsx(
|
|
6511
|
+
LoadMoreFooter,
|
|
6512
|
+
{
|
|
6513
|
+
shown: items.length,
|
|
6514
|
+
total,
|
|
6515
|
+
hasNextPage: !!hasNextPage,
|
|
6516
|
+
isFetchingNextPage: !!isFetchingNextPage,
|
|
6517
|
+
onLoadMore
|
|
6518
|
+
}
|
|
6519
|
+
),
|
|
6169
6520
|
onCreate && /* @__PURE__ */ jsx("div", { className: "ra-sibling-footer", children: /* @__PURE__ */ jsxs(
|
|
6170
6521
|
"button",
|
|
6171
6522
|
{
|
|
@@ -7334,12 +7685,17 @@ function RecordsAdminShell(props) {
|
|
|
7334
7685
|
}),
|
|
7335
7686
|
[props.SL, props.collectionId, props.appId, props.recordType]
|
|
7336
7687
|
);
|
|
7688
|
+
const recordChangeRef = useRef(null);
|
|
7689
|
+
const onRecordChange = useCallback((notice) => {
|
|
7690
|
+
recordChangeRef.current?.(notice);
|
|
7691
|
+
}, []);
|
|
7337
7692
|
return /* @__PURE__ */ jsx(
|
|
7338
7693
|
EditorSessionProvider,
|
|
7339
7694
|
{
|
|
7340
7695
|
ctx,
|
|
7341
7696
|
defaultValueFactory: props.defaultData,
|
|
7342
7697
|
hooks: props.hooks,
|
|
7698
|
+
onRecordChange,
|
|
7343
7699
|
onHookNotice: (notice) => {
|
|
7344
7700
|
console.warn(`[RecordsAdmin] ${notice.kind} hook failed`, notice.error);
|
|
7345
7701
|
try {
|
|
@@ -7352,7 +7708,7 @@ function RecordsAdminShell(props) {
|
|
|
7352
7708
|
} catch {
|
|
7353
7709
|
}
|
|
7354
7710
|
},
|
|
7355
|
-
children: /* @__PURE__ */ jsx(RecordsAdminShellInner, { ...props })
|
|
7711
|
+
children: /* @__PURE__ */ jsx(RecordsAdminShellInner, { ...props, recordChangeRef })
|
|
7356
7712
|
}
|
|
7357
7713
|
);
|
|
7358
7714
|
}
|
|
@@ -7385,7 +7741,8 @@ function RecordsAdminShellInner(props) {
|
|
|
7385
7741
|
recordActions,
|
|
7386
7742
|
icons: iconsOverride,
|
|
7387
7743
|
// Deep linking
|
|
7388
|
-
deepLink
|
|
7744
|
+
deepLink,
|
|
7745
|
+
recordChangeRef
|
|
7389
7746
|
} = props;
|
|
7390
7747
|
const {
|
|
7391
7748
|
show: showHeader,
|
|
@@ -7412,7 +7769,8 @@ function RecordsAdminShellInner(props) {
|
|
|
7412
7769
|
groupBy,
|
|
7413
7770
|
defaultGroupKey,
|
|
7414
7771
|
onGroupExpanded,
|
|
7415
|
-
density = "comfortable"
|
|
7772
|
+
density = "comfortable",
|
|
7773
|
+
pageSize: railPageSize
|
|
7416
7774
|
} = rail ?? {};
|
|
7417
7775
|
const {
|
|
7418
7776
|
tabs: editorTabs = "off",
|
|
@@ -7435,7 +7793,10 @@ function RecordsAdminShellInner(props) {
|
|
|
7435
7793
|
renderEmpty: renderItemEmpty,
|
|
7436
7794
|
cardSize: itemCardSize = "md",
|
|
7437
7795
|
railMode: collectionRailMode = "siblings",
|
|
7438
|
-
toSummary: itemToSummary
|
|
7796
|
+
toSummary: itemToSummary,
|
|
7797
|
+
pageSize: itemsPageSize,
|
|
7798
|
+
searchableFields: itemsSearchableFields,
|
|
7799
|
+
searchable: itemsSearchable
|
|
7439
7800
|
} = items ?? {};
|
|
7440
7801
|
const {
|
|
7441
7802
|
strategy: dirtyStrategy = "keep",
|
|
@@ -7495,6 +7856,21 @@ function RecordsAdminShellInner(props) {
|
|
|
7495
7856
|
[SL, collectionId, appId, recordType]
|
|
7496
7857
|
);
|
|
7497
7858
|
const queryClient = useQueryClient();
|
|
7859
|
+
useEffect(() => {
|
|
7860
|
+
recordChangeRef.current = (notice) => {
|
|
7861
|
+
if (notice.kind === "saved") {
|
|
7862
|
+
patchRecordIntoCaches(queryClient, notice.ctx, notice.record);
|
|
7863
|
+
} else {
|
|
7864
|
+
removeRecordFromCaches(queryClient, notice.ctx, notice.recordId);
|
|
7865
|
+
}
|
|
7866
|
+
queryClient.invalidateQueries({
|
|
7867
|
+
queryKey: scopeCountsQueryKey(notice.ctx.collectionId, notice.ctx.appId, notice.ctx.recordType)
|
|
7868
|
+
});
|
|
7869
|
+
};
|
|
7870
|
+
return () => {
|
|
7871
|
+
recordChangeRef.current = null;
|
|
7872
|
+
};
|
|
7873
|
+
}, [queryClient, recordChangeRef]);
|
|
7498
7874
|
const probe = useScopeProbe({ SL, collectionId });
|
|
7499
7875
|
const scopeCounts = useScopeCounts({ ctx });
|
|
7500
7876
|
const topLevelScopes = useMemo(() => {
|
|
@@ -7577,7 +7953,8 @@ function RecordsAdminShellInner(props) {
|
|
|
7577
7953
|
probeIsLoading: probe.isLoading,
|
|
7578
7954
|
selectedProductId,
|
|
7579
7955
|
drillTab,
|
|
7580
|
-
classify: classify3
|
|
7956
|
+
classify: classify3,
|
|
7957
|
+
pageSize: railPageSize
|
|
7581
7958
|
});
|
|
7582
7959
|
const {
|
|
7583
7960
|
search,
|
|
@@ -7658,7 +8035,8 @@ function RecordsAdminShellInner(props) {
|
|
|
7658
8035
|
// host-supplied lifecycle grouping has the full picture.
|
|
7659
8036
|
includeAll: isCollection && activeScope === "all",
|
|
7660
8037
|
enabled: isCollection,
|
|
7661
|
-
toSummary: itemToSummary
|
|
8038
|
+
toSummary: itemToSummary,
|
|
8039
|
+
pageSize: itemsPageSize
|
|
7662
8040
|
});
|
|
7663
8041
|
useEffect(() => {
|
|
7664
8042
|
if (skipNextItemResetRef.current) {
|
|
@@ -7667,6 +8045,36 @@ function RecordsAdminShellInner(props) {
|
|
|
7667
8045
|
}
|
|
7668
8046
|
setSelectedItemId(null);
|
|
7669
8047
|
}, [editingScope?.raw]);
|
|
8048
|
+
const isLifecycleRailEarly = (activeScope === "all" || activeScope === "collection") && isCollection && !!groupBy;
|
|
8049
|
+
const lifecycleBucketLabel = useMemo(() => {
|
|
8050
|
+
if (!isLifecycleRailEarly || !selectedLifecycleKey || !groupBy) return null;
|
|
8051
|
+
for (const it of collectionItems.items) {
|
|
8052
|
+
const g = groupBy(it);
|
|
8053
|
+
if (g && g.key === selectedLifecycleKey) return g.label ?? null;
|
|
8054
|
+
}
|
|
8055
|
+
return null;
|
|
8056
|
+
}, [isLifecycleRailEarly, selectedLifecycleKey, groupBy, collectionItems.items]);
|
|
8057
|
+
const scopedCollectionItemsList = useMemo(() => {
|
|
8058
|
+
if (!isLifecycleRailEarly || !selectedLifecycleKey || !groupBy) return collectionItems.items;
|
|
8059
|
+
return collectionItems.items.filter((it) => {
|
|
8060
|
+
const g = groupBy(it);
|
|
8061
|
+
return g?.key === selectedLifecycleKey;
|
|
8062
|
+
});
|
|
8063
|
+
}, [isLifecycleRailEarly, selectedLifecycleKey, groupBy, collectionItems.items]);
|
|
8064
|
+
useEffect(() => {
|
|
8065
|
+
if (!isLifecycleRailEarly || !groupBy) return;
|
|
8066
|
+
if (selectedLifecycleKey || !selectedItemId) return;
|
|
8067
|
+
const row = collectionItems.items.find(
|
|
8068
|
+
(it) => it.itemId === selectedItemId || it.id === selectedItemId
|
|
8069
|
+
);
|
|
8070
|
+
if (!row) return;
|
|
8071
|
+
const g = groupBy(row);
|
|
8072
|
+
if (g?.key) setSelectedLifecycleKey(g.key);
|
|
8073
|
+
}, [isLifecycleRailEarly, groupBy, selectedItemId, selectedLifecycleKey, collectionItems.items, setSelectedLifecycleKey]);
|
|
8074
|
+
const scopedCollectionItems = useMemo(() => ({
|
|
8075
|
+
...collectionItems,
|
|
8076
|
+
items: scopedCollectionItemsList
|
|
8077
|
+
}), [collectionItems, scopedCollectionItemsList]);
|
|
7670
8078
|
const { lastAppliedDLRef } = useShellDeepLink({
|
|
7671
8079
|
deepLinkState,
|
|
7672
8080
|
editingScope,
|
|
@@ -7769,7 +8177,6 @@ function RecordsAdminShellInner(props) {
|
|
|
7769
8177
|
if (isCreate && isCollection && savedRecordId && isDraftId3(selectedItemId)) {
|
|
7770
8178
|
setSelectedItemId(savedRecordId);
|
|
7771
8179
|
}
|
|
7772
|
-
await refetchAll();
|
|
7773
8180
|
if (!isCollection && isCreate && activeScope === "collection") {
|
|
7774
8181
|
setSelectedRecordId(savedRecordId ?? null);
|
|
7775
8182
|
}
|
|
@@ -7788,7 +8195,6 @@ function RecordsAdminShellInner(props) {
|
|
|
7788
8195
|
setSelectedRecordId(null);
|
|
7789
8196
|
setDraftKind(null);
|
|
7790
8197
|
}
|
|
7791
|
-
await refetchAll();
|
|
7792
8198
|
setIsReconcilingRecordSelection(false);
|
|
7793
8199
|
}
|
|
7794
8200
|
});
|
|
@@ -7954,7 +8360,7 @@ function RecordsAdminShellInner(props) {
|
|
|
7954
8360
|
setSelectedItemId,
|
|
7955
8361
|
editingScope,
|
|
7956
8362
|
baseScopeRef,
|
|
7957
|
-
collectionItems,
|
|
8363
|
+
collectionItems: scopedCollectionItems,
|
|
7958
8364
|
queryClient,
|
|
7959
8365
|
ctx,
|
|
7960
8366
|
collectionId,
|
|
@@ -8670,7 +9076,7 @@ function RecordsAdminShellInner(props) {
|
|
|
8670
9076
|
!railHidden && /* @__PURE__ */ jsx("aside", { className: "border-r overflow-hidden flex flex-col", style: { borderColor: "hsl(var(--ra-border))", background: "hsl(var(--ra-surface))" }, children: isCollection && selectedItemId && collectionRailMode === "siblings" && ruleWizardStep === null ? /* @__PURE__ */ jsx(
|
|
8671
9077
|
SiblingRail,
|
|
8672
9078
|
{
|
|
8673
|
-
items:
|
|
9079
|
+
items: scopedCollectionItemsList,
|
|
8674
9080
|
selectedItemId,
|
|
8675
9081
|
isLoading: collectionItems.isLoading,
|
|
8676
9082
|
error: collectionItems.error,
|
|
@@ -8680,8 +9086,13 @@ function RecordsAdminShellInner(props) {
|
|
|
8680
9086
|
itemNoun: itemNounLabel,
|
|
8681
9087
|
dirtyKeys,
|
|
8682
9088
|
errorKeys,
|
|
8683
|
-
|
|
8684
|
-
|
|
9089
|
+
hasNextPage: !!collectionItems.hasNextPage,
|
|
9090
|
+
isFetchingNextPage: !!collectionItems.isFetchingNextPage,
|
|
9091
|
+
onLoadMore: () => {
|
|
9092
|
+
void collectionItems.fetchNextPage();
|
|
9093
|
+
},
|
|
9094
|
+
contextKind: isLifecycleRailEarly && lifecycleBucketLabel ? lifecycleBucketLabel : activeScope === "rule" ? "Rule" : activeScope === "product" ? "Product" : activeScope === "collection" ? "Global" : activeScope === "all" ? "All records" : activeScope === "variant" ? "Variant" : activeScope === "batch" ? "Batch" : activeScope === "facet" ? "Facet" : void 0,
|
|
9095
|
+
contextSummary: isLifecycleRailEarly && lifecycleBucketLabel ? `${scopedCollectionItemsList.length} ${itemNounLabel}${scopedCollectionItemsList.length === 1 ? "" : "s"}` : activeScope === "rule" ? activeRuleSummary : activeScope === "product" ? editorHeaderLabel ?? null : null,
|
|
8685
9096
|
i18n
|
|
8686
9097
|
}
|
|
8687
9098
|
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -8859,19 +9270,29 @@ function RecordsAdminShellInner(props) {
|
|
|
8859
9270
|
i18n
|
|
8860
9271
|
}
|
|
8861
9272
|
),
|
|
8862
|
-
isProductTab && !productPinned &&
|
|
8863
|
-
|
|
9273
|
+
isProductTab && !productPinned && /* @__PURE__ */ jsx(
|
|
9274
|
+
LoadMoreFooter,
|
|
8864
9275
|
{
|
|
8865
|
-
|
|
8866
|
-
|
|
9276
|
+
shown: leftItems.length,
|
|
9277
|
+
hasNextPage: !!productBrowse.hasNextPage,
|
|
9278
|
+
isFetchingNextPage: !!productBrowse.isFetchingNextPage,
|
|
9279
|
+
onLoadMore: () => {
|
|
8867
9280
|
void productBrowse.fetchNextPage();
|
|
8868
|
-
}
|
|
8869
|
-
disabled: productBrowse.isFetchingNextPage,
|
|
8870
|
-
className: "w-full text-xs py-2 rounded-md border transition-opacity disabled:opacity-50 hover:bg-[hsl(var(--ra-muted))]",
|
|
8871
|
-
style: { borderColor: "hsl(var(--ra-border))", color: "hsl(var(--ra-text))" },
|
|
8872
|
-
children: productBrowse.isFetchingNextPage ? "Loading\u2026" : `Load more (${leftItems.length} shown)`
|
|
9281
|
+
}
|
|
8873
9282
|
}
|
|
8874
|
-
)
|
|
9283
|
+
),
|
|
9284
|
+
isRecordsTab && (!isCollection || !(isAllTab || isGlobalTab)) && /* @__PURE__ */ jsx(
|
|
9285
|
+
LoadMoreFooter,
|
|
9286
|
+
{
|
|
9287
|
+
shown: recordList.items.length,
|
|
9288
|
+
total: recordList.total,
|
|
9289
|
+
hasNextPage: !!recordList.hasNextPage,
|
|
9290
|
+
isFetchingNextPage: !!recordList.isFetchingNextPage,
|
|
9291
|
+
onLoadMore: () => {
|
|
9292
|
+
void recordList.fetchNextPage();
|
|
9293
|
+
}
|
|
9294
|
+
}
|
|
9295
|
+
)
|
|
8875
9296
|
] })
|
|
8876
9297
|
] }) })
|
|
8877
9298
|
] }) }),
|
|
@@ -8956,6 +9377,14 @@ function RecordsAdminShellInner(props) {
|
|
|
8956
9377
|
ruleSummary: activeRuleSummary,
|
|
8957
9378
|
rowActions: wrappedRecordActions,
|
|
8958
9379
|
rowClipboard,
|
|
9380
|
+
searchableFields: itemsSearchableFields,
|
|
9381
|
+
searchable: itemsSearchable,
|
|
9382
|
+
total: collectionItems.total,
|
|
9383
|
+
hasNextPage: !!collectionItems.hasNextPage,
|
|
9384
|
+
isFetchingNextPage: !!collectionItems.isFetchingNextPage,
|
|
9385
|
+
onLoadMore: () => {
|
|
9386
|
+
void collectionItems.fetchNextPage();
|
|
9387
|
+
},
|
|
8959
9388
|
i18n
|
|
8960
9389
|
}
|
|
8961
9390
|
),
|