@proveanything/smartlinks-utils-ui 0.12.9 → 0.12.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AssetPicker/index.css +42 -9
- package/dist/components/AssetPicker/index.css.map +1 -1
- package/dist/components/ConditionsEditor/index.css +42 -9
- package/dist/components/ConditionsEditor/index.css.map +1 -1
- package/dist/components/FontPicker/index.css +42 -9
- package/dist/components/FontPicker/index.css.map +1 -1
- package/dist/components/IconPicker/index.css +42 -9
- package/dist/components/IconPicker/index.css.map +1 -1
- package/dist/components/LinkPicker/index.css +42 -9
- package/dist/components/LinkPicker/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.css +42 -9
- package/dist/components/RecordsAdmin/index.css.map +1 -1
- package/dist/components/RecordsAdmin/index.d.ts +52 -0
- package/dist/components/RecordsAdmin/index.js +205 -54
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.css +42 -9
- package/dist/index.css.map +1 -1
- package/package.json +1 -1
|
@@ -525,6 +525,10 @@ interface RecordsAdminI18n {
|
|
|
525
525
|
lifecycleStatusActive: string;
|
|
526
526
|
lifecycleStatusArchived: string;
|
|
527
527
|
lifecycleStatusDraft: string;
|
|
528
|
+
/** Product rail subtitle when the only records on a product are archived. */
|
|
529
|
+
subtitleArchivedOnly: string;
|
|
530
|
+
/** Product rail subtitle when the only records on a product are drafts. */
|
|
531
|
+
subtitleDraftOnly: string;
|
|
528
532
|
/** Tooltip on the editor's status control. */
|
|
529
533
|
lifecycleStatusHint: string;
|
|
530
534
|
actionArchive: string;
|
|
@@ -838,6 +842,25 @@ interface RecordSlotContext {
|
|
|
838
842
|
* to populate this directly.
|
|
839
843
|
*/
|
|
840
844
|
actions?: RecordAction[];
|
|
845
|
+
/**
|
|
846
|
+
* Facet keys carried by the row's enclosing group header, when the rail
|
|
847
|
+
* is grouped by facet identity (Rules tab default). The default row
|
|
848
|
+
* renderer uses this to drop the facet prefix from chips whose facet is
|
|
849
|
+
* already named in the group header (so under "BREAD TYPE" you see
|
|
850
|
+
* "Slice" instead of "Bread Type: Slice"). Empty when ungrouped.
|
|
851
|
+
*/
|
|
852
|
+
groupFacetKeys?: readonly string[];
|
|
853
|
+
/**
|
|
854
|
+
* Number of archived (history) records collapsed under this row's
|
|
855
|
+
* lifecycle slot. The default row renderer surfaces this as an inline
|
|
856
|
+
* pill the admin can click to expand/collapse the archived rows
|
|
857
|
+
* underneath. Undefined when there is no history block.
|
|
858
|
+
*/
|
|
859
|
+
historyCount?: number;
|
|
860
|
+
/** Whether the history block for this row is currently expanded. */
|
|
861
|
+
historyExpanded?: boolean;
|
|
862
|
+
/** Toggle the history block. Only present when `historyCount > 0`. */
|
|
863
|
+
onToggleHistory?: () => void;
|
|
841
864
|
}
|
|
842
865
|
/**
|
|
843
866
|
* Declarative column definition for the built-in default item table.
|
|
@@ -1106,6 +1129,12 @@ interface RailConfig<TData = unknown> {
|
|
|
1106
1129
|
key: string;
|
|
1107
1130
|
label: string;
|
|
1108
1131
|
icon?: ReactNode;
|
|
1132
|
+
/**
|
|
1133
|
+
* Optional facet keys this group represents (Rules tab default
|
|
1134
|
+
* grouping populates this). Forwarded to row ctx so the default row
|
|
1135
|
+
* renderer can drop redundant facet prefixes from rule chips.
|
|
1136
|
+
*/
|
|
1137
|
+
facetKeys?: readonly string[];
|
|
1109
1138
|
/**
|
|
1110
1139
|
* Whether this bucket should be expanded by default (records-driven
|
|
1111
1140
|
* accordion mode). Last-write-wins per key. Has no effect in the
|
|
@@ -2381,9 +2410,25 @@ interface UseScopeCountsArgs {
|
|
|
2381
2410
|
maxRecords?: number;
|
|
2382
2411
|
/** Page size used for the underlying SDK list calls. Default 100. */
|
|
2383
2412
|
pageSize?: number;
|
|
2413
|
+
/**
|
|
2414
|
+
* Lifecycle status values treated as "active" when bucketing records
|
|
2415
|
+
* per product. Records with `null`/empty status are ALWAYS active for
|
|
2416
|
+
* back-compat. Defaults to `['active']`.
|
|
2417
|
+
*/
|
|
2418
|
+
activeStatuses?: readonly string[];
|
|
2384
2419
|
}
|
|
2385
2420
|
interface ScopeCounts extends Partial<Record<ScopeKind, number>> {
|
|
2386
2421
|
}
|
|
2422
|
+
/**
|
|
2423
|
+
* Per-product lifecycle bucket counts. `other` covers any non-active
|
|
2424
|
+
* status that isn't draft or archived (e.g. host-defined "scheduled").
|
|
2425
|
+
*/
|
|
2426
|
+
interface ProductLifecycleBuckets {
|
|
2427
|
+
active: number;
|
|
2428
|
+
draft: number;
|
|
2429
|
+
archived: number;
|
|
2430
|
+
other: number;
|
|
2431
|
+
}
|
|
2387
2432
|
interface UseScopeCountsResult {
|
|
2388
2433
|
counts: ScopeCounts;
|
|
2389
2434
|
total: number;
|
|
@@ -2401,6 +2446,13 @@ interface UseScopeCountsResult {
|
|
|
2401
2446
|
* Lower bound when `truncated` is true.
|
|
2402
2447
|
*/
|
|
2403
2448
|
productIds: ReadonlySet<string>;
|
|
2449
|
+
/**
|
|
2450
|
+
* Per-product lifecycle bucket counts, derived from the same scanned
|
|
2451
|
+
* records (no extra network cost). Used by the rail to distinguish a
|
|
2452
|
+
* product that has only-archived or only-draft records from one with
|
|
2453
|
+
* a live record — so the green tick doesn't lie.
|
|
2454
|
+
*/
|
|
2455
|
+
productLifecycle: ReadonlyMap<string, ProductLifecycleBuckets>;
|
|
2404
2456
|
}
|
|
2405
2457
|
declare const useScopeCounts: (args: UseScopeCountsArgs) => UseScopeCountsResult;
|
|
2406
2458
|
/** React Query key factory for cache invalidation from save/delete sites. */
|
|
@@ -15,6 +15,7 @@ import { createPortal } from 'react-dom';
|
|
|
15
15
|
// src/components/RecordsAdmin/data/recordCache.ts
|
|
16
16
|
var RECORD_LIST_QK = ["records-admin", "list"];
|
|
17
17
|
var COLLECTION_ITEMS_QK = ["records-admin", "collection-items"];
|
|
18
|
+
var SCOPE_COUNTS_QK = ["records-admin", "scope-counts"];
|
|
18
19
|
var matchesCtx = (queryKey, prefix, ctx) => {
|
|
19
20
|
if (queryKey.length < prefix.length + 3) return false;
|
|
20
21
|
for (let i = 0; i < prefix.length; i += 1) {
|
|
@@ -87,6 +88,54 @@ function patchRecordIntoCaches(queryClient, ctx, record) {
|
|
|
87
88
|
return replaceOrAppend(prev, record);
|
|
88
89
|
});
|
|
89
90
|
}
|
|
91
|
+
patchRecordIntoScopeCounts(queryClient, ctx, record);
|
|
92
|
+
}
|
|
93
|
+
var matchesScopeCountsCtx = (queryKey, ctx) => {
|
|
94
|
+
if (queryKey.length < 5) return false;
|
|
95
|
+
if (queryKey[0] !== SCOPE_COUNTS_QK[0]) return false;
|
|
96
|
+
if (queryKey[1] !== SCOPE_COUNTS_QK[1]) return false;
|
|
97
|
+
if (queryKey[2] !== ctx.collectionId) return false;
|
|
98
|
+
if (queryKey[3] !== ctx.appId) return false;
|
|
99
|
+
const slot = queryKey[4];
|
|
100
|
+
const expected = ctx.recordType ?? null;
|
|
101
|
+
if (slot !== expected && !(slot == null && expected == null)) return false;
|
|
102
|
+
return true;
|
|
103
|
+
};
|
|
104
|
+
function patchRecordIntoScopeCounts(queryClient, ctx, record) {
|
|
105
|
+
if (!record || !record.id) return;
|
|
106
|
+
const all = queryClient.getQueriesData({
|
|
107
|
+
queryKey: SCOPE_COUNTS_QK
|
|
108
|
+
});
|
|
109
|
+
for (const [key, cache] of all) {
|
|
110
|
+
if (!cache || !Array.isArray(cache.records)) continue;
|
|
111
|
+
if (!matchesScopeCountsCtx(key, ctx)) continue;
|
|
112
|
+
queryClient.setQueryData(key, (prev) => {
|
|
113
|
+
if (!prev || !Array.isArray(prev.records)) return prev;
|
|
114
|
+
const idx = prev.records.findIndex((r) => r.id === record.id);
|
|
115
|
+
if (idx === -1) {
|
|
116
|
+
return { ...prev, records: [...prev.records, record] };
|
|
117
|
+
}
|
|
118
|
+
const next = [...prev.records];
|
|
119
|
+
next[idx] = record;
|
|
120
|
+
return { ...prev, records: next };
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function removeRecordFromScopeCounts(queryClient, ctx, recordId) {
|
|
125
|
+
if (!recordId) return;
|
|
126
|
+
const all = queryClient.getQueriesData({
|
|
127
|
+
queryKey: SCOPE_COUNTS_QK
|
|
128
|
+
});
|
|
129
|
+
for (const [key, cache] of all) {
|
|
130
|
+
if (!cache || !Array.isArray(cache.records)) continue;
|
|
131
|
+
if (!matchesScopeCountsCtx(key, ctx)) continue;
|
|
132
|
+
queryClient.setQueryData(key, (prev) => {
|
|
133
|
+
if (!prev || !Array.isArray(prev.records)) return prev;
|
|
134
|
+
const next = prev.records.filter((r) => r.id !== recordId);
|
|
135
|
+
if (next.length === prev.records.length) return prev;
|
|
136
|
+
return { ...prev, records: next };
|
|
137
|
+
});
|
|
138
|
+
}
|
|
90
139
|
}
|
|
91
140
|
function removeRecordFromCaches(queryClient, ctx, recordId) {
|
|
92
141
|
if (!recordId) return;
|
|
@@ -104,6 +153,7 @@ function removeRecordFromCaches(queryClient, ctx, recordId) {
|
|
|
104
153
|
return next ?? prev;
|
|
105
154
|
});
|
|
106
155
|
}
|
|
156
|
+
removeRecordFromScopeCounts(queryClient, ctx, recordId);
|
|
107
157
|
}
|
|
108
158
|
var DEFAULT_ICONS = {
|
|
109
159
|
scope: {
|
|
@@ -266,6 +316,8 @@ var DEFAULT_I18N = {
|
|
|
266
316
|
lifecycleStatusActive: "Active",
|
|
267
317
|
lifecycleStatusArchived: "Archived",
|
|
268
318
|
lifecycleStatusDraft: "Draft",
|
|
319
|
+
subtitleArchivedOnly: "Archived only",
|
|
320
|
+
subtitleDraftOnly: "Draft only",
|
|
269
321
|
lifecycleStatusHint: "Archived records aren't returned to public consumers.",
|
|
270
322
|
actionArchive: "Archive",
|
|
271
323
|
actionRestore: "Restore",
|
|
@@ -582,7 +634,17 @@ var classify = (rec) => {
|
|
|
582
634
|
return "collection";
|
|
583
635
|
};
|
|
584
636
|
var useScopeCounts = (args) => {
|
|
585
|
-
const {
|
|
637
|
+
const {
|
|
638
|
+
ctx,
|
|
639
|
+
enabled = true,
|
|
640
|
+
maxRecords = 500,
|
|
641
|
+
pageSize = 100,
|
|
642
|
+
activeStatuses
|
|
643
|
+
} = args;
|
|
644
|
+
const activeSet = useMemo(
|
|
645
|
+
() => new Set(activeStatuses ?? ["active"]),
|
|
646
|
+
[activeStatuses]
|
|
647
|
+
);
|
|
586
648
|
const queryKey = useMemo(
|
|
587
649
|
() => [...QK_BASE, ctx.collectionId, ctx.appId, ctx.recordType ?? null],
|
|
588
650
|
[ctx.collectionId, ctx.appId, ctx.recordType]
|
|
@@ -621,10 +683,24 @@ var useScopeCounts = (args) => {
|
|
|
621
683
|
all: 0
|
|
622
684
|
};
|
|
623
685
|
const productIds = /* @__PURE__ */ new Set();
|
|
686
|
+
const productLifecycle = /* @__PURE__ */ new Map();
|
|
624
687
|
for (const rec of records) {
|
|
625
688
|
counts[classify(rec)] += 1;
|
|
626
689
|
const pid = rec.productId ?? void 0;
|
|
627
|
-
if (pid)
|
|
690
|
+
if (pid) {
|
|
691
|
+
productIds.add(pid);
|
|
692
|
+
const raw = rec.status ?? void 0;
|
|
693
|
+
const isActive2 = raw == null || raw === "" || activeSet.has(raw);
|
|
694
|
+
let bucket = productLifecycle.get(pid);
|
|
695
|
+
if (!bucket) {
|
|
696
|
+
bucket = { active: 0, draft: 0, archived: 0, other: 0 };
|
|
697
|
+
productLifecycle.set(pid, bucket);
|
|
698
|
+
}
|
|
699
|
+
if (isActive2) bucket.active += 1;
|
|
700
|
+
else if (raw === "draft") bucket.draft += 1;
|
|
701
|
+
else if (raw === "archived") bucket.archived += 1;
|
|
702
|
+
else bucket.other += 1;
|
|
703
|
+
}
|
|
628
704
|
}
|
|
629
705
|
counts.all = records.length;
|
|
630
706
|
return {
|
|
@@ -633,9 +709,10 @@ var useScopeCounts = (args) => {
|
|
|
633
709
|
isLoading: query.isLoading,
|
|
634
710
|
error: query.error ?? null,
|
|
635
711
|
truncated,
|
|
636
|
-
productIds
|
|
712
|
+
productIds,
|
|
713
|
+
productLifecycle
|
|
637
714
|
};
|
|
638
|
-
}, [query.data, query.isLoading, query.error]);
|
|
715
|
+
}, [query.data, query.isLoading, query.error, activeSet]);
|
|
639
716
|
return result;
|
|
640
717
|
};
|
|
641
718
|
var scopeCountsQueryKey = (collectionId, appId, recordType) => [...QK_BASE, collectionId, appId, recordType ?? null];
|
|
@@ -4070,13 +4147,30 @@ var RuleLabelLookupProvider = ({
|
|
|
4070
4147
|
return /* @__PURE__ */ jsx(RuleLabelLookupContext.Provider, { value: v, children });
|
|
4071
4148
|
};
|
|
4072
4149
|
var DefaultRecordRow = ({ record, ctx, compact = false }) => {
|
|
4073
|
-
const {
|
|
4150
|
+
const {
|
|
4151
|
+
selected,
|
|
4152
|
+
onSelect,
|
|
4153
|
+
isDirty,
|
|
4154
|
+
hasError,
|
|
4155
|
+
onCopy,
|
|
4156
|
+
onDuplicate,
|
|
4157
|
+
onCopyAndNewRule,
|
|
4158
|
+
actions,
|
|
4159
|
+
historyCount,
|
|
4160
|
+
historyExpanded,
|
|
4161
|
+
onToggleHistory
|
|
4162
|
+
} = ctx;
|
|
4074
4163
|
const ruleLabelLookup = useRuleLabelLookup();
|
|
4075
4164
|
const ScopeIcon = record.scope.kind && record.scope.kind !== "collection" ? DEFAULT_ICONS.scope[record.scope.kind] : DEFAULT_ICONS.scope.product;
|
|
4076
4165
|
const tone = resolveTone(void 0, record.status);
|
|
4077
4166
|
const ruleSummary = formatFacetRule(record.facetRule, ruleLabelLookup);
|
|
4078
4167
|
const ruleClauses = summarizeFacetRule(record.facetRule, ruleLabelLookup);
|
|
4079
4168
|
const isRuleRecord = ruleClauses.length > 0;
|
|
4169
|
+
const groupKeys = ctx.groupFacetKeys;
|
|
4170
|
+
const singleGroupFacet = groupKeys && groupKeys.length === 1 ? groupKeys[0] : null;
|
|
4171
|
+
const displayClauses = singleGroupFacet ? ruleClauses.map(
|
|
4172
|
+
(c) => c.facetKey === singleGroupFacet ? { ...c, label: c.values.length <= 3 ? c.values.join(", ") : `${c.values.slice(0, 2).join(", ")} +${c.values.length - 2}` } : c
|
|
4173
|
+
) : ruleClauses;
|
|
4080
4174
|
const i18n = ctx.i18n ?? DEFAULT_I18N;
|
|
4081
4175
|
const subtitle = record.subtitle ?? (isRuleRecord ? null : ruleSummary) ?? (tone === "missing" ? i18n.subtitleEmpty : tone === "own" ? i18n.subtitleConfigured : i18n.subtitleInherited);
|
|
4082
4176
|
return /* @__PURE__ */ jsxs(
|
|
@@ -4084,7 +4178,7 @@ var DefaultRecordRow = ({ record, ctx, compact = false }) => {
|
|
|
4084
4178
|
{
|
|
4085
4179
|
"data-selected": selected ? "true" : "false",
|
|
4086
4180
|
"data-tone": tone,
|
|
4087
|
-
className: cn("ra-row", compact && "ra-row-compact"),
|
|
4181
|
+
className: cn("ra-row", compact && "ra-row-compact", isRuleRecord && !compact && "ra-row-rule"),
|
|
4088
4182
|
style: compact ? { paddingTop: "0.4rem", paddingBottom: "0.4rem" } : void 0,
|
|
4089
4183
|
children: [
|
|
4090
4184
|
/* @__PURE__ */ jsxs("button", { type: "button", onClick: onSelect, className: "ra-row-hit", children: [
|
|
@@ -4098,7 +4192,7 @@ var DefaultRecordRow = ({ record, ctx, compact = false }) => {
|
|
|
4098
4192
|
}
|
|
4099
4193
|
) }),
|
|
4100
4194
|
/* @__PURE__ */ jsxs("div", { className: "ra-row-body", children: [
|
|
4101
|
-
/* @__PURE__ */ jsx("div", { className: "ra-row-title", children: record.label }),
|
|
4195
|
+
!(isRuleRecord && !compact) && /* @__PURE__ */ jsx("div", { className: "ra-row-title", children: record.label }),
|
|
4102
4196
|
!compact && isRuleRecord && /* @__PURE__ */ jsxs(
|
|
4103
4197
|
"div",
|
|
4104
4198
|
{
|
|
@@ -4106,10 +4200,10 @@ var DefaultRecordRow = ({ record, ctx, compact = false }) => {
|
|
|
4106
4200
|
title: ruleSummary ?? void 0,
|
|
4107
4201
|
"aria-label": ruleSummary ?? void 0,
|
|
4108
4202
|
children: [
|
|
4109
|
-
|
|
4110
|
-
|
|
4203
|
+
displayClauses.slice(0, 4).map((clause, i) => /* @__PURE__ */ jsx("span", { className: "ra-rule-chip", children: clause.label }, `${clause.facetKey}-${i}`)),
|
|
4204
|
+
displayClauses.length > 4 && /* @__PURE__ */ jsxs("span", { className: "ra-rule-chip ra-rule-chip-more", children: [
|
|
4111
4205
|
"+",
|
|
4112
|
-
|
|
4206
|
+
displayClauses.length - 4
|
|
4113
4207
|
] })
|
|
4114
4208
|
]
|
|
4115
4209
|
}
|
|
@@ -4144,6 +4238,25 @@ var DefaultRecordRow = ({ record, ctx, compact = false }) => {
|
|
|
4144
4238
|
}
|
|
4145
4239
|
)
|
|
4146
4240
|
] }),
|
|
4241
|
+
historyCount && historyCount > 0 && onToggleHistory ? /* @__PURE__ */ jsxs(
|
|
4242
|
+
"button",
|
|
4243
|
+
{
|
|
4244
|
+
type: "button",
|
|
4245
|
+
className: "ra-row-history-pill",
|
|
4246
|
+
"data-expanded": historyExpanded ? "true" : "false",
|
|
4247
|
+
onClick: (e) => {
|
|
4248
|
+
e.stopPropagation();
|
|
4249
|
+
onToggleHistory();
|
|
4250
|
+
},
|
|
4251
|
+
"aria-expanded": historyExpanded,
|
|
4252
|
+
"aria-label": historyExpanded ? `Hide ${historyCount} archived` : `Show ${historyCount} archived`,
|
|
4253
|
+
title: historyExpanded ? `Hide ${historyCount} archived` : `Show ${historyCount} archived`,
|
|
4254
|
+
children: [
|
|
4255
|
+
/* @__PURE__ */ jsx("span", { className: "ra-row-history-pill-count", children: historyCount }),
|
|
4256
|
+
/* @__PURE__ */ jsx("span", { className: "ra-row-history-pill-label", children: "archived" })
|
|
4257
|
+
]
|
|
4258
|
+
}
|
|
4259
|
+
) : null,
|
|
4147
4260
|
(onCopy || onDuplicate || onCopyAndNewRule || actions && actions.length > 0) && /* @__PURE__ */ jsx(
|
|
4148
4261
|
RowContextMenu,
|
|
4149
4262
|
{
|
|
@@ -4205,7 +4318,7 @@ var RecordList = ({
|
|
|
4205
4318
|
buttons[nextIdx].scrollIntoView({ block: "nearest" });
|
|
4206
4319
|
}
|
|
4207
4320
|
}, []);
|
|
4208
|
-
const buildCtx = (item) => {
|
|
4321
|
+
const buildCtx = (item, groupFacetKeys) => {
|
|
4209
4322
|
const cb = rowClipboard ? rowClipboard(item) : null;
|
|
4210
4323
|
const extraActions = rowActions ? rowActions(item) ?? void 0 : void 0;
|
|
4211
4324
|
const itemAnchorKey = anchorKey(item.scope);
|
|
@@ -4222,6 +4335,7 @@ var RecordList = ({
|
|
|
4222
4335
|
isDirty: dirtyIdMatch || dirtyAnchorMatch || idInStore || anchorInStore,
|
|
4223
4336
|
hasError: errorInStore,
|
|
4224
4337
|
i18n,
|
|
4338
|
+
groupFacetKeys,
|
|
4225
4339
|
...cb ?? {},
|
|
4226
4340
|
actions: extraActions && extraActions.length > 0 ? extraActions : void 0
|
|
4227
4341
|
};
|
|
@@ -4249,43 +4363,30 @@ var RecordList = ({
|
|
|
4249
4363
|
return next;
|
|
4250
4364
|
});
|
|
4251
4365
|
}, []);
|
|
4252
|
-
const renderItems = (rows) => {
|
|
4366
|
+
const renderItems = (rows, groupFacetKeys) => {
|
|
4253
4367
|
const compact = presentation === "compact";
|
|
4254
4368
|
return /* @__PURE__ */ jsx("ul", { children: rows.map((item, idx) => {
|
|
4255
|
-
const ctx = buildCtx(item);
|
|
4369
|
+
const ctx = buildCtx(item, groupFacetKeys);
|
|
4256
4370
|
const key = item.id ?? (anchorKey(item.scope) || `pos:${idx}`);
|
|
4257
4371
|
const sKey = historyBySlot ? slotKey(item) : null;
|
|
4258
4372
|
const history = sKey ? historyBySlot.get(sKey) : void 0;
|
|
4259
4373
|
const expanded = sKey ? expandedSlots.has(sKey) : false;
|
|
4260
|
-
const
|
|
4261
|
-
const
|
|
4262
|
-
const label = (expanded ? hideLabel : showLabel).replace("{n}", String(history?.length ?? 0));
|
|
4374
|
+
const historyCount = history?.length ?? 0;
|
|
4375
|
+
const ctxWithHistory = historyCount > 0 && sKey ? { ...ctx, historyCount, historyExpanded: expanded, onToggleHistory: () => toggleSlot(sKey) } : ctx;
|
|
4263
4376
|
return /* @__PURE__ */ jsxs("li", { children: [
|
|
4264
|
-
renderListRow ? renderListRow(item,
|
|
4265
|
-
history && history.length > 0 ? /* @__PURE__ */
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
badges
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
}) }) : null,
|
|
4278
|
-
/* @__PURE__ */ jsx(
|
|
4279
|
-
"button",
|
|
4280
|
-
{
|
|
4281
|
-
type: "button",
|
|
4282
|
-
className: "ra-history-disclosure",
|
|
4283
|
-
onClick: () => sKey && toggleSlot(sKey),
|
|
4284
|
-
"aria-expanded": expanded,
|
|
4285
|
-
children: label
|
|
4286
|
-
}
|
|
4287
|
-
)
|
|
4288
|
-
] }) : null
|
|
4377
|
+
renderListRow ? renderListRow(item, ctxWithHistory) : /* @__PURE__ */ jsx(DefaultRecordRow, { record: item, ctx: ctxWithHistory, compact }),
|
|
4378
|
+
history && history.length > 0 ? /* @__PURE__ */ jsx("div", { className: "ra-history-block", children: expanded ? /* @__PURE__ */ jsx("ul", { className: "ra-history-rows", "aria-label": "Archived records", children: history.map((h, hIdx) => {
|
|
4379
|
+
const hCtx = buildCtx(h, groupFacetKeys);
|
|
4380
|
+
const hKey = h.id ?? `hist:${idx}:${hIdx}`;
|
|
4381
|
+
const badged = {
|
|
4382
|
+
...h,
|
|
4383
|
+
badges: [
|
|
4384
|
+
...h.badges ?? [],
|
|
4385
|
+
{ label: h.lifecycleStatus ?? "archived", tone: "warning" }
|
|
4386
|
+
]
|
|
4387
|
+
};
|
|
4388
|
+
return /* @__PURE__ */ jsx("li", { className: "ra-history-row", "data-history": "true", children: renderListRow ? renderListRow(badged, hCtx) : /* @__PURE__ */ jsx(DefaultRecordRow, { record: badged, ctx: hCtx, compact }) }, hKey);
|
|
4389
|
+
}) }) : null }) : null
|
|
4289
4390
|
] }, key);
|
|
4290
4391
|
}) });
|
|
4291
4392
|
};
|
|
@@ -4358,7 +4459,7 @@ var GroupedList = ({
|
|
|
4358
4459
|
}
|
|
4359
4460
|
) : null
|
|
4360
4461
|
] }),
|
|
4361
|
-
/* @__PURE__ */ jsx("div", { className: "ra-group-body", children: renderItems(g.items) })
|
|
4462
|
+
/* @__PURE__ */ jsx("div", { className: "ra-group-body", children: renderItems(g.items, g.facetKeys) })
|
|
4362
4463
|
] }, g.key);
|
|
4363
4464
|
}) });
|
|
4364
4465
|
};
|
|
@@ -8937,8 +9038,12 @@ var EditorPoolBody = ({
|
|
|
8937
9038
|
}) => {
|
|
8938
9039
|
const ctx = useEditorSlotContext(editorId);
|
|
8939
9040
|
if (!ctx) return null;
|
|
8940
|
-
return renderEditor
|
|
9041
|
+
return /* @__PURE__ */ jsx(CallbackRenderer, { render: renderEditor, args: ctx });
|
|
8941
9042
|
};
|
|
9043
|
+
var CallbackRenderer = ({
|
|
9044
|
+
render,
|
|
9045
|
+
args
|
|
9046
|
+
}) => /* @__PURE__ */ jsx(Fragment, { children: render(args) });
|
|
8942
9047
|
var TOP_LEVEL_SCOPES = ["collection", "rule", "product"];
|
|
8943
9048
|
var OPT_IN_TOP_LEVEL_SCOPES = ["all"];
|
|
8944
9049
|
var DRAFT_ID3 = "__draft__";
|
|
@@ -8951,16 +9056,39 @@ var coerceDraftItemId2 = (generateItemId) => {
|
|
|
8951
9056
|
const candidate = generateItemId ? generateItemId() : mintDraftItemId2();
|
|
8952
9057
|
return isDraftId3(candidate) ? candidate : `draft:${candidate}`;
|
|
8953
9058
|
};
|
|
8954
|
-
var productItemToSummary = (p,
|
|
9059
|
+
var productItemToSummary = (p, buckets, i18n) => {
|
|
8955
9060
|
const ref = buildRef({ productId: p.id });
|
|
9061
|
+
const total = buckets ? buckets.active + buckets.draft + buckets.archived + buckets.other : 0;
|
|
9062
|
+
const hasAnyActive = (buckets?.active ?? 0) > 0;
|
|
9063
|
+
let status;
|
|
9064
|
+
let toneHint;
|
|
9065
|
+
let subtitle = p.sku ?? void 0;
|
|
9066
|
+
if (hasAnyActive) {
|
|
9067
|
+
status = "configured";
|
|
9068
|
+
} else if (total === 0) {
|
|
9069
|
+
status = "empty";
|
|
9070
|
+
} else {
|
|
9071
|
+
status = "partial";
|
|
9072
|
+
if ((buckets.archived ?? 0) > 0 && (buckets.draft ?? 0) === 0) {
|
|
9073
|
+
toneHint = "muted";
|
|
9074
|
+
subtitle = i18n.subtitleArchivedOnly;
|
|
9075
|
+
} else if ((buckets.draft ?? 0) > 0 && (buckets.archived ?? 0) === 0) {
|
|
9076
|
+
toneHint = "warning";
|
|
9077
|
+
subtitle = i18n.subtitleDraftOnly;
|
|
9078
|
+
} else {
|
|
9079
|
+
toneHint = "warning";
|
|
9080
|
+
subtitle = (buckets.draft ?? 0) > 0 ? i18n.subtitleDraftOnly : i18n.subtitleArchivedOnly;
|
|
9081
|
+
}
|
|
9082
|
+
}
|
|
8956
9083
|
return {
|
|
8957
9084
|
id: null,
|
|
8958
9085
|
ref,
|
|
8959
9086
|
scope: parseRef(ref),
|
|
8960
9087
|
data: null,
|
|
8961
|
-
status
|
|
9088
|
+
status,
|
|
8962
9089
|
label: p.name,
|
|
8963
|
-
subtitle
|
|
9090
|
+
subtitle,
|
|
9091
|
+
toneHint
|
|
8964
9092
|
};
|
|
8965
9093
|
};
|
|
8966
9094
|
function RecordsAdminShell(props) {
|
|
@@ -9121,7 +9249,10 @@ function RecordsAdminShellInner(props) {
|
|
|
9121
9249
|
labels: actionLabels,
|
|
9122
9250
|
icons: actionIcons
|
|
9123
9251
|
} = actions ?? {};
|
|
9124
|
-
const i18n =
|
|
9252
|
+
const i18n = useMemo(
|
|
9253
|
+
() => ({ ...DEFAULT_I18N, ...i18nOverride ?? {} }),
|
|
9254
|
+
[i18nOverride]
|
|
9255
|
+
);
|
|
9125
9256
|
const icons = useMemo(() => mergeIcons(iconsOverride), [iconsOverride]);
|
|
9126
9257
|
const deepLinkState = useDeepLinkState(deepLink);
|
|
9127
9258
|
const multiOpenWarnedRef = useRef(false);
|
|
@@ -9181,7 +9312,7 @@ function RecordsAdminShellInner(props) {
|
|
|
9181
9312
|
};
|
|
9182
9313
|
}, [queryClient, recordChangeRef]);
|
|
9183
9314
|
const probe = useScopeProbe({ SL, collectionId });
|
|
9184
|
-
const scopeCounts = useScopeCounts({ ctx });
|
|
9315
|
+
const scopeCounts = useScopeCounts({ ctx, activeStatuses: resolvedActiveStatuses });
|
|
9185
9316
|
const topLevelScopes = useMemo(() => {
|
|
9186
9317
|
const requested = requestedScopes ?? [];
|
|
9187
9318
|
const allowed = /* @__PURE__ */ new Set([...TOP_LEVEL_SCOPES, ...OPT_IN_TOP_LEVEL_SCOPES]);
|
|
@@ -9931,7 +10062,13 @@ function RecordsAdminShellInner(props) {
|
|
|
9931
10062
|
] });
|
|
9932
10063
|
}
|
|
9933
10064
|
const previewAnchorRef = previewReopenAnchorRef;
|
|
9934
|
-
const previewBody = renderPreview && effectivePreviewScope ?
|
|
10065
|
+
const previewBody = renderPreview && effectivePreviewScope ? /* @__PURE__ */ jsx(
|
|
10066
|
+
CallbackRenderer,
|
|
10067
|
+
{
|
|
10068
|
+
render: renderPreview,
|
|
10069
|
+
args: { resolved: editorCtx.value, previewScope: effectivePreviewScope }
|
|
10070
|
+
}
|
|
10071
|
+
) : null;
|
|
9935
10072
|
const scopePicker = previewScopePicker && effectivePreviewScope ? /* @__PURE__ */ jsx(
|
|
9936
10073
|
PreviewScopePicker,
|
|
9937
10074
|
{
|
|
@@ -10089,7 +10226,13 @@ function RecordsAdminShellInner(props) {
|
|
|
10089
10226
|
renderEditor
|
|
10090
10227
|
}
|
|
10091
10228
|
),
|
|
10092
|
-
fallback:
|
|
10229
|
+
fallback: /* @__PURE__ */ jsx(
|
|
10230
|
+
CallbackRenderer,
|
|
10231
|
+
{
|
|
10232
|
+
render: renderEditor,
|
|
10233
|
+
args: editorCtx
|
|
10234
|
+
}
|
|
10235
|
+
)
|
|
10093
10236
|
}
|
|
10094
10237
|
)
|
|
10095
10238
|
}
|
|
@@ -10214,7 +10357,12 @@ function RecordsAdminShellInner(props) {
|
|
|
10214
10357
|
}];
|
|
10215
10358
|
}
|
|
10216
10359
|
const configured = scopeCounts.productIds;
|
|
10217
|
-
const
|
|
10360
|
+
const lifecycle = scopeCounts.productLifecycle;
|
|
10361
|
+
const lifecycleI18n = {
|
|
10362
|
+
subtitleArchivedOnly: i18n.subtitleArchivedOnly,
|
|
10363
|
+
subtitleDraftOnly: i18n.subtitleDraftOnly
|
|
10364
|
+
};
|
|
10365
|
+
const all = productBrowse.items.map((p) => productItemToSummary(p, lifecycle.get(p.id), lifecycleI18n));
|
|
10218
10366
|
const isConfigured = (s) => {
|
|
10219
10367
|
const pid = s.scope.productId;
|
|
10220
10368
|
return !!pid && configured.has(pid);
|
|
@@ -10231,7 +10379,10 @@ function RecordsAdminShellInner(props) {
|
|
|
10231
10379
|
productBrowse.items,
|
|
10232
10380
|
pinnedProduct.item,
|
|
10233
10381
|
scopeCounts.productIds,
|
|
10234
|
-
|
|
10382
|
+
scopeCounts.productLifecycle,
|
|
10383
|
+
filter,
|
|
10384
|
+
i18n.subtitleArchivedOnly,
|
|
10385
|
+
i18n.subtitleDraftOnly
|
|
10235
10386
|
]);
|
|
10236
10387
|
const isRuleTab = activeScope === "rule";
|
|
10237
10388
|
const isGlobalTab = activeScope === "collection";
|
|
@@ -10269,7 +10420,7 @@ function RecordsAdminShellInner(props) {
|
|
|
10269
10420
|
if (keys.length === 0) return null;
|
|
10270
10421
|
const key = `facets:${keys.join("|")}`;
|
|
10271
10422
|
const label2 = keys.map((k) => ruleLabelLookup?.facetLabel?.(k) ?? k).join(" \xB7 ");
|
|
10272
|
-
return { key, label: label2 };
|
|
10423
|
+
return { key, label: label2, facetKeys: keys };
|
|
10273
10424
|
};
|
|
10274
10425
|
}, [groupBy, isRuleTab, isAllTab, isCollection, ruleLabelLookup]);
|
|
10275
10426
|
const [bulkRuleEditTarget, setBulkRuleEditTarget] = useState(null);
|
|
@@ -11117,7 +11268,7 @@ function RecordsAdminShellInner(props) {
|
|
|
11117
11268
|
isGlobalTab && !isCollection && !hasSingletonConflicts ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
11118
11269
|
leftLoading && /* @__PURE__ */ jsx(LoadingState, {}),
|
|
11119
11270
|
!leftLoading && leftError && /* @__PURE__ */ jsx(ErrorState, { error: leftError }),
|
|
11120
|
-
!leftLoading && !leftError && decoratedLeftItems.length === 0 && (renderEmptyState ?
|
|
11271
|
+
!leftLoading && !leftError && decoratedLeftItems.length === 0 && (renderEmptyState ? /* @__PURE__ */ jsx(CallbackRenderer, { render: renderEmptyState, args: { scope: activeScope } }) : /* @__PURE__ */ jsx(
|
|
11121
11272
|
EmptyState,
|
|
11122
11273
|
{
|
|
11123
11274
|
icon: search ? icons.empty.search : icons.empty.default,
|