@proveanything/smartlinks-utils-ui 0.12.6 → 0.12.7
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-WCUKTVWC.js +382 -0
- package/dist/chunk-WCUKTVWC.js.map +1 -0
- package/dist/components/AssetPicker/index.css +7 -0
- package/dist/components/AssetPicker/index.css.map +1 -1
- package/dist/components/ConditionsEditor/index.css +7 -0
- package/dist/components/ConditionsEditor/index.css.map +1 -1
- package/dist/components/ConditionsEditor/index.js +1 -1
- package/dist/components/FontPicker/index.css +7 -0
- package/dist/components/FontPicker/index.css.map +1 -1
- package/dist/components/IconPicker/index.css +7 -0
- package/dist/components/IconPicker/index.css.map +1 -1
- package/dist/components/LinkPicker/index.css +3989 -0
- package/dist/components/LinkPicker/index.css.map +1 -0
- package/dist/components/LinkPicker/index.d.ts +131 -0
- package/dist/components/LinkPicker/index.js +6 -0
- package/dist/components/LinkPicker/index.js.map +1 -0
- package/dist/components/RecordsAdmin/index.css +7 -0
- package/dist/components/RecordsAdmin/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.d.ts +37 -2
- package/dist/components/RecordsAdmin/index.js +382 -123
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.css +7 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { parsedRefToTarget, parsedRefToScope, matchRecords, scopesEqual, getRecordById, listRecords, upsertRecord, updateRecord, createRecord, removeRecord } from '../../chunk-KA4MKRHL.js';
|
|
2
|
+
export { bulkDelete, bulkUpsert, createRecord, getRecordById, listRecords, matchRecords, parsedRefToScope, parsedRefToTarget, removeRecord, restoreRecord, scopesEqual, upsertRecord } from '../../chunk-KA4MKRHL.js';
|
|
1
3
|
import { useIntroState, AdminPageHeader } from '../../chunk-3RRHM4LP.js';
|
|
2
|
-
import { assertComponentStylesLoaded } from '../../chunk-OLYC54YT.js';
|
|
3
|
-
import '../../chunk-5UQQYXCX.js';
|
|
4
4
|
import { FacetRuleEditor } from '../../chunk-JMCV6FOW.js';
|
|
5
5
|
import { useFacets } from '../../chunk-4LHF5JB7.js';
|
|
6
|
+
import { assertComponentStylesLoaded } from '../../chunk-OLYC54YT.js';
|
|
7
|
+
import '../../chunk-5UQQYXCX.js';
|
|
6
8
|
import { cn } from '../../chunk-L7FQ52F5.js';
|
|
7
|
-
import { parsedRefToTarget, parsedRefToScope, matchRecords, scopesEqual, getRecordById, listRecords, upsertRecord, updateRecord, createRecord, removeRecord } from '../../chunk-KA4MKRHL.js';
|
|
8
|
-
export { bulkDelete, bulkUpsert, createRecord, getRecordById, listRecords, matchRecords, parsedRefToScope, parsedRefToTarget, removeRecord, restoreRecord, scopesEqual, upsertRecord } from '../../chunk-KA4MKRHL.js';
|
|
9
9
|
import { createContext, useMemo, useState, useEffect, useCallback, useRef, isValidElement, useLayoutEffect, useContext, useSyncExternalStore, createElement } from 'react';
|
|
10
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, Check, Rows3, ChevronRight, Eraser, FilePlus2, CopyPlus, ClipboardPaste, Box, X, Search, Image, Table, ArrowLeft, ChevronLeft, AlertTriangle, Info, HelpCircle, CornerDownLeft, Circle, ArrowUpDown, ArrowUp, ArrowDown, MinusCircle, XCircle, AlertCircle, Undo2, Save, Loader2, Archive, ArrowRight, Globe2, Sparkles, Settings2 } from 'lucide-react';
|
|
11
11
|
import { useQuery, useQueryClient, useInfiniteQuery } from '@tanstack/react-query';
|
|
@@ -276,7 +276,15 @@ var DEFAULT_I18N = {
|
|
|
276
276
|
conflictArchiveDuplicates: "Archive duplicates",
|
|
277
277
|
conflictDeleteDuplicates: "Delete duplicates",
|
|
278
278
|
conflictDeleteConfirm: "Permanently delete {n} duplicate record(s)? This cannot be undone.",
|
|
279
|
-
conflictResolveLabel: "Resolve"
|
|
279
|
+
conflictResolveLabel: "Resolve",
|
|
280
|
+
ruleSortLabel: "Sort",
|
|
281
|
+
ruleSortRecent: "Recently updated",
|
|
282
|
+
ruleSortName: "Name",
|
|
283
|
+
ruleSortActiveCount: "Active count",
|
|
284
|
+
ruleSortHasArchived: "Has archived",
|
|
285
|
+
lifecycleBadgeActive: "{n} active",
|
|
286
|
+
lifecycleBadgeArchived: "{n} archived",
|
|
287
|
+
lifecycleBadgeDraft: "{n} draft"
|
|
280
288
|
};
|
|
281
289
|
|
|
282
290
|
// src/components/RecordsAdmin/types/presentation.ts
|
|
@@ -851,6 +859,24 @@ var useRecordList = (args) => {
|
|
|
851
859
|
}
|
|
852
860
|
return map;
|
|
853
861
|
}, [historyItems]);
|
|
862
|
+
const ruleLifecycleCounts = useMemo(() => {
|
|
863
|
+
const map = /* @__PURE__ */ new Map();
|
|
864
|
+
for (const r of items) {
|
|
865
|
+
const h = ruleHash(r.facetRule ?? null);
|
|
866
|
+
if (!h) continue;
|
|
867
|
+
let bucket = map.get(h);
|
|
868
|
+
if (!bucket) {
|
|
869
|
+
bucket = { active: 0, archived: 0, draft: 0, other: 0 };
|
|
870
|
+
map.set(h, bucket);
|
|
871
|
+
}
|
|
872
|
+
const ls = r.lifecycleStatus;
|
|
873
|
+
if (ls == null || ls === "" || activeStatuses.includes(ls)) bucket.active += 1;
|
|
874
|
+
else if (ls === "archived") bucket.archived += 1;
|
|
875
|
+
else if (ls === "draft") bucket.draft += 1;
|
|
876
|
+
else bucket.other += 1;
|
|
877
|
+
}
|
|
878
|
+
return map;
|
|
879
|
+
}, [items, activeStatuses]);
|
|
854
880
|
const refetch = useCallback(() => queryClient.refetchQueries({
|
|
855
881
|
queryKey: [...QK_BASE2, ctx.collectionId, ctx.appId, ctx.recordType]
|
|
856
882
|
}), [queryClient, ctx.collectionId, ctx.appId, ctx.recordType]);
|
|
@@ -861,6 +887,7 @@ var useRecordList = (args) => {
|
|
|
861
887
|
activeItems,
|
|
862
888
|
historyItems,
|
|
863
889
|
historyBySlot,
|
|
890
|
+
ruleLifecycleCounts,
|
|
864
891
|
total,
|
|
865
892
|
counts,
|
|
866
893
|
isLoading: query.isLoading,
|
|
@@ -6881,6 +6908,8 @@ function ItemListView({
|
|
|
6881
6908
|
hasNextPage,
|
|
6882
6909
|
isFetchingNextPage,
|
|
6883
6910
|
onLoadMore,
|
|
6911
|
+
groupByLifecycle = false,
|
|
6912
|
+
lifecycle,
|
|
6884
6913
|
i18n
|
|
6885
6914
|
}) {
|
|
6886
6915
|
const newLabel = i18n.newItem.includes("{noun}") ? i18n.newItem.replace("{noun}", itemNoun) : i18n.newItem;
|
|
@@ -6955,6 +6984,69 @@ function ItemListView({
|
|
|
6955
6984
|
}), [ctx]);
|
|
6956
6985
|
const confirmName = pendingRecord?.label ?? itemNoun;
|
|
6957
6986
|
const confirmBody = i18n.deleteConfirmBody.includes("{name}") ? i18n.deleteConfirmBody.replace("{name}", confirmName) : i18n.deleteConfirmBody;
|
|
6987
|
+
const activeValues = useMemo(
|
|
6988
|
+
() => getActiveStatusValues(lifecycle),
|
|
6989
|
+
[lifecycle]
|
|
6990
|
+
);
|
|
6991
|
+
const buckets = useMemo(() => {
|
|
6992
|
+
if (!groupByLifecycle) return null;
|
|
6993
|
+
const map = /* @__PURE__ */ new Map();
|
|
6994
|
+
for (const item of visibleItems) {
|
|
6995
|
+
const def = resolveLifecycleStatus(item, lifecycle);
|
|
6996
|
+
const existing = map.get(def.value);
|
|
6997
|
+
if (existing) existing.items.push(item);
|
|
6998
|
+
else map.set(def.value, { label: def.label, items: [item] });
|
|
6999
|
+
}
|
|
7000
|
+
return Array.from(map.entries()).map(([key, v]) => ({
|
|
7001
|
+
key,
|
|
7002
|
+
label: v.label,
|
|
7003
|
+
items: v.items,
|
|
7004
|
+
isActive: activeValues.includes(key)
|
|
7005
|
+
})).sort((a, b) => compareLifecycleBuckets(a.key, b.key)).filter((b) => b.items.length > 0);
|
|
7006
|
+
}, [groupByLifecycle, visibleItems, lifecycle, activeValues]);
|
|
7007
|
+
const [collapsedBuckets, setCollapsedBuckets] = useState(() => /* @__PURE__ */ new Set());
|
|
7008
|
+
const toggleBucket = (key) => {
|
|
7009
|
+
setCollapsedBuckets((prev) => {
|
|
7010
|
+
const next = new Set(prev);
|
|
7011
|
+
if (next.has(key)) next.delete(key);
|
|
7012
|
+
else next.add(key);
|
|
7013
|
+
return next;
|
|
7014
|
+
});
|
|
7015
|
+
};
|
|
7016
|
+
const renderBody = (rows) => {
|
|
7017
|
+
if (renderItemList) return renderItemList(rows, guardedCtx);
|
|
7018
|
+
if (view === "table") {
|
|
7019
|
+
return /* @__PURE__ */ jsx(
|
|
7020
|
+
DefaultItemTable,
|
|
7021
|
+
{
|
|
7022
|
+
items: rows,
|
|
7023
|
+
columns: itemColumns,
|
|
7024
|
+
selectedId: guardedCtx.selectedId,
|
|
7025
|
+
onOpen: guardedCtx.onOpen,
|
|
7026
|
+
onDelete: guardedCtx.onDelete,
|
|
7027
|
+
sort,
|
|
7028
|
+
onToggleSort,
|
|
7029
|
+
rowActions,
|
|
7030
|
+
rowClipboard,
|
|
7031
|
+
i18n
|
|
7032
|
+
}
|
|
7033
|
+
);
|
|
7034
|
+
}
|
|
7035
|
+
return /* @__PURE__ */ jsx(
|
|
7036
|
+
DefaultItemCards,
|
|
7037
|
+
{
|
|
7038
|
+
items: rows,
|
|
7039
|
+
variant: view,
|
|
7040
|
+
selectedId: guardedCtx.selectedId,
|
|
7041
|
+
ctx: guardedCtx,
|
|
7042
|
+
renderCard: renderItemCard,
|
|
7043
|
+
cardSize,
|
|
7044
|
+
rowActions,
|
|
7045
|
+
rowClipboard,
|
|
7046
|
+
i18n
|
|
7047
|
+
}
|
|
7048
|
+
);
|
|
7049
|
+
};
|
|
6958
7050
|
const toolbar = /* @__PURE__ */ jsxs("div", { className: "ra-item-toolbar", children: [
|
|
6959
7051
|
/* @__PURE__ */ jsxs("div", { className: "ra-item-toolbar-title", children: [
|
|
6960
7052
|
/* @__PURE__ */ jsx("h2", { className: "ra-display", style: { fontSize: "0.95rem", margin: 0 }, children: i18n.itemListTitle }),
|
|
@@ -7072,39 +7164,62 @@ function ItemListView({
|
|
|
7072
7164
|
body: `No ${itemNoun}s match "${search}".`
|
|
7073
7165
|
}
|
|
7074
7166
|
);
|
|
7075
|
-
} else if (
|
|
7076
|
-
body =
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
|
|
7087
|
-
|
|
7088
|
-
|
|
7089
|
-
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
|
|
7167
|
+
} else if (buckets && buckets.length > 0) {
|
|
7168
|
+
body = /* @__PURE__ */ jsx("div", { className: "ra-item-buckets", children: buckets.map((bucket) => {
|
|
7169
|
+
const open = bucket.isActive || !collapsedBuckets.has(bucket.key);
|
|
7170
|
+
return /* @__PURE__ */ jsxs(
|
|
7171
|
+
"section",
|
|
7172
|
+
{
|
|
7173
|
+
className: "ra-item-bucket",
|
|
7174
|
+
"data-bucket": bucket.key,
|
|
7175
|
+
children: [
|
|
7176
|
+
/* @__PURE__ */ jsxs(
|
|
7177
|
+
"button",
|
|
7178
|
+
{
|
|
7179
|
+
type: "button",
|
|
7180
|
+
className: "ra-item-bucket-header",
|
|
7181
|
+
onClick: () => !bucket.isActive && toggleBucket(bucket.key),
|
|
7182
|
+
"aria-expanded": open,
|
|
7183
|
+
disabled: bucket.isActive,
|
|
7184
|
+
style: {
|
|
7185
|
+
display: "flex",
|
|
7186
|
+
alignItems: "center",
|
|
7187
|
+
gap: "6px",
|
|
7188
|
+
width: "100%",
|
|
7189
|
+
padding: "6px 12px",
|
|
7190
|
+
background: "transparent",
|
|
7191
|
+
border: 0,
|
|
7192
|
+
borderTop: "1px solid hsl(var(--ra-border))",
|
|
7193
|
+
font: "inherit",
|
|
7194
|
+
fontSize: "11px",
|
|
7195
|
+
fontWeight: 600,
|
|
7196
|
+
textTransform: "uppercase",
|
|
7197
|
+
letterSpacing: "0.04em",
|
|
7198
|
+
color: "hsl(var(--ra-muted-text))",
|
|
7199
|
+
cursor: bucket.isActive ? "default" : "pointer"
|
|
7200
|
+
},
|
|
7201
|
+
children: [
|
|
7202
|
+
!bucket.isActive ? open ? /* @__PURE__ */ jsx(ChevronDown, { className: "w-3 h-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "w-3 h-3", "aria-hidden": "true" }) : null,
|
|
7203
|
+
/* @__PURE__ */ jsx("span", { children: bucket.label }),
|
|
7204
|
+
/* @__PURE__ */ jsx("span", { style: { marginLeft: "auto", fontWeight: 500 }, children: bucket.items.length })
|
|
7205
|
+
]
|
|
7206
|
+
}
|
|
7207
|
+
),
|
|
7208
|
+
open && /* @__PURE__ */ jsx(
|
|
7209
|
+
"div",
|
|
7210
|
+
{
|
|
7211
|
+
className: "ra-item-bucket-body",
|
|
7212
|
+
style: bucket.isActive ? void 0 : { opacity: 0.75 },
|
|
7213
|
+
children: renderBody(bucket.items)
|
|
7214
|
+
}
|
|
7215
|
+
)
|
|
7216
|
+
]
|
|
7217
|
+
},
|
|
7218
|
+
bucket.key
|
|
7219
|
+
);
|
|
7220
|
+
}) });
|
|
7093
7221
|
} else {
|
|
7094
|
-
body =
|
|
7095
|
-
DefaultItemCards,
|
|
7096
|
-
{
|
|
7097
|
-
items: visibleItems,
|
|
7098
|
-
variant: view,
|
|
7099
|
-
selectedId: guardedCtx.selectedId,
|
|
7100
|
-
ctx: guardedCtx,
|
|
7101
|
-
renderCard: renderItemCard,
|
|
7102
|
-
cardSize,
|
|
7103
|
-
rowActions,
|
|
7104
|
-
rowClipboard,
|
|
7105
|
-
i18n
|
|
7106
|
-
}
|
|
7107
|
-
);
|
|
7222
|
+
body = renderBody(visibleItems);
|
|
7108
7223
|
}
|
|
7109
7224
|
return /* @__PURE__ */ jsxs("div", { className: "ra-item-list", children: [
|
|
7110
7225
|
toolbar,
|
|
@@ -7247,10 +7362,42 @@ function SiblingRail({
|
|
|
7247
7362
|
isFetchingNextPage,
|
|
7248
7363
|
onLoadMore,
|
|
7249
7364
|
rowClipboard,
|
|
7250
|
-
rowActions
|
|
7365
|
+
rowActions,
|
|
7366
|
+
groupByLifecycle = false,
|
|
7367
|
+
lifecycle
|
|
7251
7368
|
}) {
|
|
7252
7369
|
const ruleLabelLookup = useRuleLabelLookup();
|
|
7253
7370
|
const newLabel = i18n.newItem.includes("{noun}") ? i18n.newItem.replace("{noun}", itemNoun ?? "item") : i18n.newItem;
|
|
7371
|
+
const activeValues = useMemo(
|
|
7372
|
+
() => getActiveStatusValues(lifecycle),
|
|
7373
|
+
[lifecycle]
|
|
7374
|
+
);
|
|
7375
|
+
const buckets = useMemo(() => {
|
|
7376
|
+
if (!groupByLifecycle) return null;
|
|
7377
|
+
const map = /* @__PURE__ */ new Map();
|
|
7378
|
+
for (const item of items) {
|
|
7379
|
+
const def = resolveLifecycleStatus(item, lifecycle);
|
|
7380
|
+
const key = def.value;
|
|
7381
|
+
const existing = map.get(key);
|
|
7382
|
+
if (existing) existing.items.push(item);
|
|
7383
|
+
else map.set(key, { label: def.label, items: [item] });
|
|
7384
|
+
}
|
|
7385
|
+
return Array.from(map.entries()).map(([key, v]) => ({
|
|
7386
|
+
key,
|
|
7387
|
+
label: v.label,
|
|
7388
|
+
items: v.items,
|
|
7389
|
+
isActive: activeValues.includes(key)
|
|
7390
|
+
})).sort((a, b) => compareLifecycleBuckets(a.key, b.key)).filter((b) => b.items.length > 0);
|
|
7391
|
+
}, [groupByLifecycle, items, lifecycle, activeValues]);
|
|
7392
|
+
const [collapsed, setCollapsed] = useState(() => /* @__PURE__ */ new Set());
|
|
7393
|
+
const toggleBucket = (key) => {
|
|
7394
|
+
setCollapsed((prev) => {
|
|
7395
|
+
const next = new Set(prev);
|
|
7396
|
+
if (next.has(key)) next.delete(key);
|
|
7397
|
+
else next.add(key);
|
|
7398
|
+
return next;
|
|
7399
|
+
});
|
|
7400
|
+
};
|
|
7254
7401
|
return /* @__PURE__ */ jsxs("div", { className: "ra-sibling-rail", children: [
|
|
7255
7402
|
(onBack || contextKind) && /* @__PURE__ */ jsxs("div", { className: "ra-sibling-context", children: [
|
|
7256
7403
|
onBack && /* @__PURE__ */ jsx(
|
|
@@ -7276,79 +7423,125 @@ function SiblingRail({
|
|
|
7276
7423
|
isLoading && /* @__PURE__ */ jsx(LoadingState, {}),
|
|
7277
7424
|
!isLoading && error && /* @__PURE__ */ jsx(ErrorState, { error }),
|
|
7278
7425
|
!isLoading && !error && items.length === 0 && /* @__PURE__ */ jsx(EmptyState, { title: i18n.noItemsTitle, body: i18n.noItemsBody }),
|
|
7279
|
-
!isLoading && !error && items.length > 0 &&
|
|
7280
|
-
const
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7284
|
-
|
|
7285
|
-
|
|
7286
|
-
|
|
7287
|
-
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
/* @__PURE__ */ jsxs(
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
type: "button",
|
|
7294
|
-
onClick: () => onSelect(id),
|
|
7295
|
-
className: "ra-row",
|
|
7296
|
-
"data-selected": selected,
|
|
7297
|
-
children: [
|
|
7298
|
-
/* @__PURE__ */ jsxs("div", { className: "ra-row-body", children: [
|
|
7299
|
-
/* @__PURE__ */ jsx("div", { className: "ra-row-title", children: item.label }),
|
|
7300
|
-
item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: item.subtitle })
|
|
7301
|
-
] }),
|
|
7302
|
-
isTargeted && /* @__PURE__ */ jsx(
|
|
7303
|
-
"span",
|
|
7304
|
-
{
|
|
7305
|
-
className: "ra-row-rule-pip",
|
|
7306
|
-
title: ruleSummary ? `Targeted: ${ruleSummary}` : "This item has targeting rules",
|
|
7307
|
-
"aria-label": ruleSummary ? `Targeted: ${ruleSummary}` : "This item has targeting rules",
|
|
7308
|
-
children: /* @__PURE__ */ jsx(Target, { className: "w-3 h-3", "aria-hidden": "true" })
|
|
7309
|
-
}
|
|
7310
|
-
),
|
|
7311
|
-
hasError ? /* @__PURE__ */ jsx(
|
|
7312
|
-
"span",
|
|
7313
|
-
{
|
|
7314
|
-
className: "ra-error-pip",
|
|
7315
|
-
title: "Save failed",
|
|
7316
|
-
"aria-label": "Save failed"
|
|
7317
|
-
}
|
|
7318
|
-
) : isDirty ? /* @__PURE__ */ jsx(
|
|
7319
|
-
"span",
|
|
7320
|
-
{
|
|
7321
|
-
className: "ra-dirty-pip",
|
|
7322
|
-
title: "Unsaved changes",
|
|
7323
|
-
"aria-label": "Unsaved changes"
|
|
7324
|
-
}
|
|
7325
|
-
) : null
|
|
7326
|
-
]
|
|
7327
|
-
}
|
|
7328
|
-
),
|
|
7329
|
-
(() => {
|
|
7330
|
-
const cb = rowClipboard ? rowClipboard(item) : null;
|
|
7331
|
-
const extra = rowActions ? rowActions(item) ?? void 0 : void 0;
|
|
7332
|
-
if (!cb?.onCopy && !cb?.onDuplicate && !cb?.onCopyAndNewRule && !(extra && extra.length)) {
|
|
7333
|
-
return null;
|
|
7334
|
-
}
|
|
7335
|
-
return /* @__PURE__ */ jsx(
|
|
7336
|
-
RowContextMenu,
|
|
7426
|
+
!isLoading && !error && items.length > 0 && (() => {
|
|
7427
|
+
const renderRow = (item, idx, dimmed) => {
|
|
7428
|
+
const id = item.itemId ?? "";
|
|
7429
|
+
const key = item.id ?? (id || anchorKey(item.scope) || `pos:${idx}`);
|
|
7430
|
+
const akey = anchorKey(item.scope);
|
|
7431
|
+
const selected = selectedItemId === id;
|
|
7432
|
+
const isDirty = !!(id && dirtyKeys?.has(id) || akey && dirtyKeys?.has(akey));
|
|
7433
|
+
const hasError = !!(id && errorKeys?.has(id) || akey && errorKeys?.has(akey));
|
|
7434
|
+
const ruleClauses = item.facetRule ? summarizeFacetRule(item.facetRule, ruleLabelLookup) : [];
|
|
7435
|
+
const isTargeted = ruleClauses.length > 0;
|
|
7436
|
+
const ruleSummary = isTargeted ? ruleClauses.map((c) => c.label).join(" \xB7 ") : null;
|
|
7437
|
+
return /* @__PURE__ */ jsx("li", { "data-dimmed": dimmed || void 0, children: /* @__PURE__ */ jsxs("div", { className: "ra-row-shell", "data-selected": selected, children: [
|
|
7438
|
+
/* @__PURE__ */ jsxs(
|
|
7439
|
+
"button",
|
|
7337
7440
|
{
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7441
|
+
type: "button",
|
|
7442
|
+
onClick: () => onSelect(id),
|
|
7443
|
+
className: "ra-row",
|
|
7444
|
+
"data-selected": selected,
|
|
7445
|
+
style: dimmed ? { opacity: 0.7 } : void 0,
|
|
7446
|
+
children: [
|
|
7447
|
+
/* @__PURE__ */ jsxs("div", { className: "ra-row-body", children: [
|
|
7448
|
+
/* @__PURE__ */ jsx("div", { className: "ra-row-title", children: item.label }),
|
|
7449
|
+
item.subtitle && /* @__PURE__ */ jsx("div", { className: "ra-row-sub", children: item.subtitle })
|
|
7450
|
+
] }),
|
|
7451
|
+
isTargeted && /* @__PURE__ */ jsx(
|
|
7452
|
+
"span",
|
|
7453
|
+
{
|
|
7454
|
+
className: "ra-row-rule-pip",
|
|
7455
|
+
title: ruleSummary ? `Targeted: ${ruleSummary}` : "This item has targeting rules",
|
|
7456
|
+
"aria-label": ruleSummary ? `Targeted: ${ruleSummary}` : "This item has targeting rules",
|
|
7457
|
+
children: /* @__PURE__ */ jsx(Target, { className: "w-3 h-3", "aria-hidden": "true" })
|
|
7458
|
+
}
|
|
7459
|
+
),
|
|
7460
|
+
hasError ? /* @__PURE__ */ jsx(
|
|
7461
|
+
"span",
|
|
7462
|
+
{
|
|
7463
|
+
className: "ra-error-pip",
|
|
7464
|
+
title: "Save failed",
|
|
7465
|
+
"aria-label": "Save failed"
|
|
7466
|
+
}
|
|
7467
|
+
) : isDirty ? /* @__PURE__ */ jsx(
|
|
7468
|
+
"span",
|
|
7469
|
+
{
|
|
7470
|
+
className: "ra-dirty-pip",
|
|
7471
|
+
title: "Unsaved changes",
|
|
7472
|
+
"aria-label": "Unsaved changes"
|
|
7473
|
+
}
|
|
7474
|
+
) : null
|
|
7475
|
+
]
|
|
7476
|
+
}
|
|
7477
|
+
),
|
|
7478
|
+
(() => {
|
|
7479
|
+
const cb = rowClipboard ? rowClipboard(item) : null;
|
|
7480
|
+
const extra = rowActions ? rowActions(item) ?? void 0 : void 0;
|
|
7481
|
+
if (!cb?.onCopy && !cb?.onDuplicate && !cb?.onCopyAndNewRule && !(extra && extra.length)) {
|
|
7482
|
+
return null;
|
|
7483
|
+
}
|
|
7484
|
+
return /* @__PURE__ */ jsx(
|
|
7485
|
+
RowContextMenu,
|
|
7486
|
+
{
|
|
7487
|
+
onCopy: cb?.onCopy,
|
|
7488
|
+
onDuplicate: cb?.onDuplicate,
|
|
7489
|
+
onCopyAndNewRule: cb?.onCopyAndNewRule,
|
|
7490
|
+
actions: extra,
|
|
7491
|
+
i18n: {
|
|
7492
|
+
copy: i18n.copy,
|
|
7493
|
+
duplicateAction: i18n.duplicateAction,
|
|
7494
|
+
copyAndNewRuleAction: i18n.copyAndNewRuleAction
|
|
7495
|
+
}
|
|
7346
7496
|
}
|
|
7497
|
+
);
|
|
7498
|
+
})()
|
|
7499
|
+
] }) }, key);
|
|
7500
|
+
};
|
|
7501
|
+
if (!buckets) {
|
|
7502
|
+
return /* @__PURE__ */ jsx("ul", { className: "ra-sibling-list", children: items.map((item, idx) => renderRow(item, idx, false)) });
|
|
7503
|
+
}
|
|
7504
|
+
return /* @__PURE__ */ jsx("div", { className: "ra-sibling-buckets", children: buckets.map((bucket) => {
|
|
7505
|
+
const open = bucket.isActive || !collapsed.has(bucket.key);
|
|
7506
|
+
return /* @__PURE__ */ jsxs("section", { className: "ra-sibling-bucket", "data-bucket": bucket.key, children: [
|
|
7507
|
+
/* @__PURE__ */ jsxs(
|
|
7508
|
+
"button",
|
|
7509
|
+
{
|
|
7510
|
+
type: "button",
|
|
7511
|
+
className: "ra-sibling-bucket-header",
|
|
7512
|
+
onClick: () => !bucket.isActive && toggleBucket(bucket.key),
|
|
7513
|
+
"aria-expanded": open,
|
|
7514
|
+
disabled: bucket.isActive,
|
|
7515
|
+
style: {
|
|
7516
|
+
display: "flex",
|
|
7517
|
+
alignItems: "center",
|
|
7518
|
+
gap: "6px",
|
|
7519
|
+
width: "100%",
|
|
7520
|
+
padding: "6px 10px",
|
|
7521
|
+
background: "transparent",
|
|
7522
|
+
border: 0,
|
|
7523
|
+
borderTop: "1px solid hsl(var(--ra-border))",
|
|
7524
|
+
font: "inherit",
|
|
7525
|
+
fontSize: "11px",
|
|
7526
|
+
fontWeight: 600,
|
|
7527
|
+
textTransform: "uppercase",
|
|
7528
|
+
letterSpacing: "0.04em",
|
|
7529
|
+
color: "hsl(var(--ra-muted-text))",
|
|
7530
|
+
cursor: bucket.isActive ? "default" : "pointer"
|
|
7531
|
+
},
|
|
7532
|
+
children: [
|
|
7533
|
+
!bucket.isActive ? open ? /* @__PURE__ */ jsx(ChevronDown, { className: "w-3 h-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "w-3 h-3", "aria-hidden": "true" }) : null,
|
|
7534
|
+
/* @__PURE__ */ jsx("span", { children: bucket.label }),
|
|
7535
|
+
/* @__PURE__ */ jsx("span", { style: { marginLeft: "auto", fontWeight: 500 }, children: bucket.items.length })
|
|
7536
|
+
]
|
|
7347
7537
|
}
|
|
7348
|
-
)
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7538
|
+
),
|
|
7539
|
+
open && /* @__PURE__ */ jsx("ul", { className: "ra-sibling-list", children: bucket.items.map(
|
|
7540
|
+
(item, idx) => renderRow(item, idx, !bucket.isActive)
|
|
7541
|
+
) })
|
|
7542
|
+
] }, bucket.key);
|
|
7543
|
+
}) });
|
|
7544
|
+
})()
|
|
7352
7545
|
] }),
|
|
7353
7546
|
onLoadMore && /* @__PURE__ */ jsx(
|
|
7354
7547
|
LoadMoreFooter,
|
|
@@ -8892,6 +9085,7 @@ function RecordsAdminShellInner(props) {
|
|
|
8892
9085
|
onTelemetry?.({ type: "presentation.change", recordType, from: presentation, to: next });
|
|
8893
9086
|
setPresentation(next);
|
|
8894
9087
|
}, [onTelemetry, recordType, presentation, setPresentation]);
|
|
9088
|
+
const [ruleSort, setRuleSort] = useState("recent");
|
|
8895
9089
|
const [itemView, setItemView] = useItemViewPref({
|
|
8896
9090
|
appId,
|
|
8897
9091
|
recordType,
|
|
@@ -10070,6 +10264,7 @@ function RecordsAdminShellInner(props) {
|
|
|
10070
10264
|
if (cardinality === "collection") {
|
|
10071
10265
|
setRuleWizardStep(2);
|
|
10072
10266
|
if (ruleWizardSeedMode) {
|
|
10267
|
+
skipNextItemResetRef.current = true;
|
|
10073
10268
|
const id = coerceDraftItemId2(generateItemId);
|
|
10074
10269
|
setSelectedItemId(id);
|
|
10075
10270
|
}
|
|
@@ -10080,7 +10275,7 @@ function RecordsAdminShellInner(props) {
|
|
|
10080
10275
|
setSelectedRecordId(DRAFT_ID3);
|
|
10081
10276
|
}
|
|
10082
10277
|
}
|
|
10083
|
-
}, [cardinality, ruleWizardSeedMode, mintRuleWizardDraftKey, generateItemId]);
|
|
10278
|
+
}, [cardinality, ruleWizardSeedMode, mintRuleWizardDraftKey, generateItemId, skipNextItemResetRef]);
|
|
10084
10279
|
const startRuleWizardDraft = useCallback((seed) => {
|
|
10085
10280
|
setRuleWizardSeedMode(seed);
|
|
10086
10281
|
setRuleWizardDraftKey(mintRuleWizardDraftKey());
|
|
@@ -10134,17 +10329,51 @@ function RecordsAdminShellInner(props) {
|
|
|
10134
10329
|
buckets.set(hash, { rep: item, count: 1 });
|
|
10135
10330
|
}
|
|
10136
10331
|
}
|
|
10137
|
-
|
|
10138
|
-
|
|
10139
|
-
|
|
10140
|
-
|
|
10141
|
-
|
|
10142
|
-
|
|
10143
|
-
|
|
10144
|
-
|
|
10145
|
-
|
|
10146
|
-
|
|
10147
|
-
|
|
10332
|
+
const counts = recordList.ruleLifecycleCounts;
|
|
10333
|
+
return Array.from(buckets.entries()).map(([hash, { rep, count }]) => {
|
|
10334
|
+
const lc = counts.get(hash) ?? { active: 0, archived: 0, draft: 0, other: 0 };
|
|
10335
|
+
const lifecycleBadges = [];
|
|
10336
|
+
if (lc.active > 0) lifecycleBadges.push({
|
|
10337
|
+
label: i18n.lifecycleBadgeActive.replace("{n}", String(lc.active)),
|
|
10338
|
+
tone: "success"
|
|
10339
|
+
});
|
|
10340
|
+
if (lc.draft > 0) lifecycleBadges.push({
|
|
10341
|
+
label: i18n.lifecycleBadgeDraft.replace("{n}", String(lc.draft)),
|
|
10342
|
+
tone: "warning"
|
|
10343
|
+
});
|
|
10344
|
+
if (lc.archived > 0) lifecycleBadges.push({
|
|
10345
|
+
label: i18n.lifecycleBadgeArchived.replace("{n}", String(lc.archived)),
|
|
10346
|
+
tone: "neutral"
|
|
10347
|
+
});
|
|
10348
|
+
return {
|
|
10349
|
+
...rep,
|
|
10350
|
+
// Title carries the count + identity; the rule chips below render
|
|
10351
|
+
// the friendly facet/value labels (via the lookup) so we don't
|
|
10352
|
+
// repeat the same information in two places.
|
|
10353
|
+
label: `${count} ${itemNoun}${count === 1 ? "" : "s"}`,
|
|
10354
|
+
subtitle: void 0,
|
|
10355
|
+
badges: [...rep.badges ?? [], ...lifecycleBadges],
|
|
10356
|
+
// Stash counts on the row for the sort comparator below.
|
|
10357
|
+
__lifecycleCounts: lc
|
|
10358
|
+
};
|
|
10359
|
+
});
|
|
10360
|
+
}, [isRuleTab, isCollection, filteredRuleItems, itemNoun, recordList.ruleLifecycleCounts, i18n]);
|
|
10361
|
+
const sortedCollectionRuleRailItems = useMemo(() => {
|
|
10362
|
+
if (!isRuleTab || !isCollection || ruleSort === "recent") return collectionRuleRailItems;
|
|
10363
|
+
const arr = [...collectionRuleRailItems];
|
|
10364
|
+
const counts = (r) => r.__lifecycleCounts ?? { active: 0, archived: 0 };
|
|
10365
|
+
if (ruleSort === "name") arr.sort((a, b) => a.label.localeCompare(b.label));
|
|
10366
|
+
else if (ruleSort === "activeCount") arr.sort((a, b) => counts(b).active - counts(a).active);
|
|
10367
|
+
else if (ruleSort === "hasArchived") {
|
|
10368
|
+
arr.sort((a, b) => {
|
|
10369
|
+
const ah = counts(a).archived > 0 ? 1 : 0;
|
|
10370
|
+
const bh = counts(b).archived > 0 ? 1 : 0;
|
|
10371
|
+
if (ah !== bh) return bh - ah;
|
|
10372
|
+
return counts(b).archived - counts(a).archived;
|
|
10373
|
+
});
|
|
10374
|
+
}
|
|
10375
|
+
return arr;
|
|
10376
|
+
}, [collectionRuleRailItems, isRuleTab, isCollection, ruleSort]);
|
|
10148
10377
|
const activeRuleSummary = useMemo(() => {
|
|
10149
10378
|
if (!isRuleTab || !isCollection) return null;
|
|
10150
10379
|
if (!selectedRecordId || isDraftId3(selectedRecordId)) return null;
|
|
@@ -10283,9 +10512,9 @@ function RecordsAdminShellInner(props) {
|
|
|
10283
10512
|
});
|
|
10284
10513
|
}, [isLifecycleRail, selectedLifecycleKey, lcGroupBy, collectionItems.items]);
|
|
10285
10514
|
const leftItems = isProductTab ? productListItems : isRuleTab ? applyFacetBrowseFilter(
|
|
10286
|
-
isCollection ?
|
|
10515
|
+
isCollection ? sortedCollectionRuleRailItems : filteredRuleItems
|
|
10287
10516
|
) : isLifecycleRail ? lifecycleRows : (isGlobalTab || isAllTab) && isCollection ? [collectionGlobalAllRow] : isRecordsTab ? applyFacetBrowseFilter(recordList.items) : [];
|
|
10288
|
-
const railShowsHistoryDisclosure = isRecordsTab && !isLifecycleRail && !
|
|
10517
|
+
const railShowsHistoryDisclosure = isRecordsTab && !isLifecycleRail && !isCollection;
|
|
10289
10518
|
const filteredLeftItems = useMemo(() => {
|
|
10290
10519
|
if (!railShowsHistoryDisclosure) return leftItems;
|
|
10291
10520
|
return leftItems.filter((r) => {
|
|
@@ -10553,6 +10782,8 @@ function RecordsAdminShellInner(props) {
|
|
|
10553
10782
|
},
|
|
10554
10783
|
rowClipboard,
|
|
10555
10784
|
rowActions: wrappedRecordActions,
|
|
10785
|
+
groupByLifecycle: true,
|
|
10786
|
+
lifecycle: lifecycleConfig,
|
|
10556
10787
|
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,
|
|
10557
10788
|
contextSummary: isLifecycleRailEarly && lifecycleBucketLabel ? `${scopedCollectionItemsList.length} ${itemNounLabel}${scopedCollectionItemsList.length === 1 ? "" : "s"}` : activeScope === "rule" ? activeRuleSummary : activeScope === "product" ? editorHeaderLabel ?? null : null,
|
|
10558
10789
|
i18n
|
|
@@ -10683,7 +10914,33 @@ function RecordsAdminShellInner(props) {
|
|
|
10683
10914
|
onChange: setFacetBrowseFilter,
|
|
10684
10915
|
isLoading: facetBrowse.isLoading
|
|
10685
10916
|
}
|
|
10686
|
-
)
|
|
10917
|
+
),
|
|
10918
|
+
isRuleTab && isCollection && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
10919
|
+
/* @__PURE__ */ jsx(
|
|
10920
|
+
"label",
|
|
10921
|
+
{
|
|
10922
|
+
htmlFor: "ra-rule-sort",
|
|
10923
|
+
style: { color: "hsl(var(--ra-text-muted))" },
|
|
10924
|
+
children: i18n.ruleSortLabel
|
|
10925
|
+
}
|
|
10926
|
+
),
|
|
10927
|
+
/* @__PURE__ */ jsxs(
|
|
10928
|
+
"select",
|
|
10929
|
+
{
|
|
10930
|
+
id: "ra-rule-sort",
|
|
10931
|
+
value: ruleSort,
|
|
10932
|
+
onChange: (e) => setRuleSort(e.target.value),
|
|
10933
|
+
className: "text-xs px-2 py-1 rounded-md border bg-transparent focus:outline-none focus:ring-1",
|
|
10934
|
+
style: { borderColor: "hsl(var(--ra-border))", color: "hsl(var(--ra-text))" },
|
|
10935
|
+
children: [
|
|
10936
|
+
/* @__PURE__ */ jsx("option", { value: "recent", children: i18n.ruleSortRecent }),
|
|
10937
|
+
/* @__PURE__ */ jsx("option", { value: "name", children: i18n.ruleSortName }),
|
|
10938
|
+
/* @__PURE__ */ jsx("option", { value: "activeCount", children: i18n.ruleSortActiveCount }),
|
|
10939
|
+
/* @__PURE__ */ jsx("option", { value: "hasArchived", children: i18n.ruleSortHasArchived })
|
|
10940
|
+
]
|
|
10941
|
+
}
|
|
10942
|
+
)
|
|
10943
|
+
] })
|
|
10687
10944
|
] })
|
|
10688
10945
|
] }),
|
|
10689
10946
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto", children: [
|
|
@@ -10920,6 +11177,8 @@ function RecordsAdminShellInner(props) {
|
|
|
10920
11177
|
onLoadMore: () => {
|
|
10921
11178
|
void collectionItems.fetchNextPage();
|
|
10922
11179
|
},
|
|
11180
|
+
groupByLifecycle: true,
|
|
11181
|
+
lifecycle: lifecycleConfig,
|
|
10923
11182
|
i18n
|
|
10924
11183
|
}
|
|
10925
11184
|
),
|