@proveanything/smartlinks-utils-ui 0.12.8 → 0.12.10
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.
|
@@ -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;
|
|
@@ -2381,9 +2385,25 @@ interface UseScopeCountsArgs {
|
|
|
2381
2385
|
maxRecords?: number;
|
|
2382
2386
|
/** Page size used for the underlying SDK list calls. Default 100. */
|
|
2383
2387
|
pageSize?: number;
|
|
2388
|
+
/**
|
|
2389
|
+
* Lifecycle status values treated as "active" when bucketing records
|
|
2390
|
+
* per product. Records with `null`/empty status are ALWAYS active for
|
|
2391
|
+
* back-compat. Defaults to `['active']`.
|
|
2392
|
+
*/
|
|
2393
|
+
activeStatuses?: readonly string[];
|
|
2384
2394
|
}
|
|
2385
2395
|
interface ScopeCounts extends Partial<Record<ScopeKind, number>> {
|
|
2386
2396
|
}
|
|
2397
|
+
/**
|
|
2398
|
+
* Per-product lifecycle bucket counts. `other` covers any non-active
|
|
2399
|
+
* status that isn't draft or archived (e.g. host-defined "scheduled").
|
|
2400
|
+
*/
|
|
2401
|
+
interface ProductLifecycleBuckets {
|
|
2402
|
+
active: number;
|
|
2403
|
+
draft: number;
|
|
2404
|
+
archived: number;
|
|
2405
|
+
other: number;
|
|
2406
|
+
}
|
|
2387
2407
|
interface UseScopeCountsResult {
|
|
2388
2408
|
counts: ScopeCounts;
|
|
2389
2409
|
total: number;
|
|
@@ -2401,6 +2421,13 @@ interface UseScopeCountsResult {
|
|
|
2401
2421
|
* Lower bound when `truncated` is true.
|
|
2402
2422
|
*/
|
|
2403
2423
|
productIds: ReadonlySet<string>;
|
|
2424
|
+
/**
|
|
2425
|
+
* Per-product lifecycle bucket counts, derived from the same scanned
|
|
2426
|
+
* records (no extra network cost). Used by the rail to distinguish a
|
|
2427
|
+
* product that has only-archived or only-draft records from one with
|
|
2428
|
+
* a live record — so the green tick doesn't lie.
|
|
2429
|
+
*/
|
|
2430
|
+
productLifecycle: ReadonlyMap<string, ProductLifecycleBuckets>;
|
|
2404
2431
|
}
|
|
2405
2432
|
declare const useScopeCounts: (args: UseScopeCountsArgs) => UseScopeCountsResult;
|
|
2406
2433
|
/** React Query key factory for cache invalidation from save/delete sites. */
|
|
@@ -266,6 +266,8 @@ var DEFAULT_I18N = {
|
|
|
266
266
|
lifecycleStatusActive: "Active",
|
|
267
267
|
lifecycleStatusArchived: "Archived",
|
|
268
268
|
lifecycleStatusDraft: "Draft",
|
|
269
|
+
subtitleArchivedOnly: "Archived only",
|
|
270
|
+
subtitleDraftOnly: "Draft only",
|
|
269
271
|
lifecycleStatusHint: "Archived records aren't returned to public consumers.",
|
|
270
272
|
actionArchive: "Archive",
|
|
271
273
|
actionRestore: "Restore",
|
|
@@ -582,7 +584,17 @@ var classify = (rec) => {
|
|
|
582
584
|
return "collection";
|
|
583
585
|
};
|
|
584
586
|
var useScopeCounts = (args) => {
|
|
585
|
-
const {
|
|
587
|
+
const {
|
|
588
|
+
ctx,
|
|
589
|
+
enabled = true,
|
|
590
|
+
maxRecords = 500,
|
|
591
|
+
pageSize = 100,
|
|
592
|
+
activeStatuses
|
|
593
|
+
} = args;
|
|
594
|
+
const activeSet = useMemo(
|
|
595
|
+
() => new Set(activeStatuses ?? ["active"]),
|
|
596
|
+
[activeStatuses]
|
|
597
|
+
);
|
|
586
598
|
const queryKey = useMemo(
|
|
587
599
|
() => [...QK_BASE, ctx.collectionId, ctx.appId, ctx.recordType ?? null],
|
|
588
600
|
[ctx.collectionId, ctx.appId, ctx.recordType]
|
|
@@ -621,10 +633,24 @@ var useScopeCounts = (args) => {
|
|
|
621
633
|
all: 0
|
|
622
634
|
};
|
|
623
635
|
const productIds = /* @__PURE__ */ new Set();
|
|
636
|
+
const productLifecycle = /* @__PURE__ */ new Map();
|
|
624
637
|
for (const rec of records) {
|
|
625
638
|
counts[classify(rec)] += 1;
|
|
626
639
|
const pid = rec.productId ?? void 0;
|
|
627
|
-
if (pid)
|
|
640
|
+
if (pid) {
|
|
641
|
+
productIds.add(pid);
|
|
642
|
+
const raw = rec.status ?? void 0;
|
|
643
|
+
const isActive2 = raw == null || raw === "" || activeSet.has(raw);
|
|
644
|
+
let bucket = productLifecycle.get(pid);
|
|
645
|
+
if (!bucket) {
|
|
646
|
+
bucket = { active: 0, draft: 0, archived: 0, other: 0 };
|
|
647
|
+
productLifecycle.set(pid, bucket);
|
|
648
|
+
}
|
|
649
|
+
if (isActive2) bucket.active += 1;
|
|
650
|
+
else if (raw === "draft") bucket.draft += 1;
|
|
651
|
+
else if (raw === "archived") bucket.archived += 1;
|
|
652
|
+
else bucket.other += 1;
|
|
653
|
+
}
|
|
628
654
|
}
|
|
629
655
|
counts.all = records.length;
|
|
630
656
|
return {
|
|
@@ -633,9 +659,10 @@ var useScopeCounts = (args) => {
|
|
|
633
659
|
isLoading: query.isLoading,
|
|
634
660
|
error: query.error ?? null,
|
|
635
661
|
truncated,
|
|
636
|
-
productIds
|
|
662
|
+
productIds,
|
|
663
|
+
productLifecycle
|
|
637
664
|
};
|
|
638
|
-
}, [query.data, query.isLoading, query.error]);
|
|
665
|
+
}, [query.data, query.isLoading, query.error, activeSet]);
|
|
639
666
|
return result;
|
|
640
667
|
};
|
|
641
668
|
var scopeCountsQueryKey = (collectionId, appId, recordType) => [...QK_BASE, collectionId, appId, recordType ?? null];
|
|
@@ -8951,16 +8978,39 @@ var coerceDraftItemId2 = (generateItemId) => {
|
|
|
8951
8978
|
const candidate = generateItemId ? generateItemId() : mintDraftItemId2();
|
|
8952
8979
|
return isDraftId3(candidate) ? candidate : `draft:${candidate}`;
|
|
8953
8980
|
};
|
|
8954
|
-
var productItemToSummary = (p,
|
|
8981
|
+
var productItemToSummary = (p, buckets, i18n) => {
|
|
8955
8982
|
const ref = buildRef({ productId: p.id });
|
|
8983
|
+
const total = buckets ? buckets.active + buckets.draft + buckets.archived + buckets.other : 0;
|
|
8984
|
+
const hasAnyActive = (buckets?.active ?? 0) > 0;
|
|
8985
|
+
let status;
|
|
8986
|
+
let toneHint;
|
|
8987
|
+
let subtitle = p.sku ?? void 0;
|
|
8988
|
+
if (hasAnyActive) {
|
|
8989
|
+
status = "configured";
|
|
8990
|
+
} else if (total === 0) {
|
|
8991
|
+
status = "empty";
|
|
8992
|
+
} else {
|
|
8993
|
+
status = "partial";
|
|
8994
|
+
if ((buckets.archived ?? 0) > 0 && (buckets.draft ?? 0) === 0) {
|
|
8995
|
+
toneHint = "muted";
|
|
8996
|
+
subtitle = i18n.subtitleArchivedOnly;
|
|
8997
|
+
} else if ((buckets.draft ?? 0) > 0 && (buckets.archived ?? 0) === 0) {
|
|
8998
|
+
toneHint = "warning";
|
|
8999
|
+
subtitle = i18n.subtitleDraftOnly;
|
|
9000
|
+
} else {
|
|
9001
|
+
toneHint = "warning";
|
|
9002
|
+
subtitle = (buckets.draft ?? 0) > 0 ? i18n.subtitleDraftOnly : i18n.subtitleArchivedOnly;
|
|
9003
|
+
}
|
|
9004
|
+
}
|
|
8956
9005
|
return {
|
|
8957
9006
|
id: null,
|
|
8958
9007
|
ref,
|
|
8959
9008
|
scope: parseRef(ref),
|
|
8960
9009
|
data: null,
|
|
8961
|
-
status
|
|
9010
|
+
status,
|
|
8962
9011
|
label: p.name,
|
|
8963
|
-
subtitle
|
|
9012
|
+
subtitle,
|
|
9013
|
+
toneHint
|
|
8964
9014
|
};
|
|
8965
9015
|
};
|
|
8966
9016
|
function RecordsAdminShell(props) {
|
|
@@ -9181,7 +9231,7 @@ function RecordsAdminShellInner(props) {
|
|
|
9181
9231
|
};
|
|
9182
9232
|
}, [queryClient, recordChangeRef]);
|
|
9183
9233
|
const probe = useScopeProbe({ SL, collectionId });
|
|
9184
|
-
const scopeCounts = useScopeCounts({ ctx });
|
|
9234
|
+
const scopeCounts = useScopeCounts({ ctx, activeStatuses: resolvedActiveStatuses });
|
|
9185
9235
|
const topLevelScopes = useMemo(() => {
|
|
9186
9236
|
const requested = requestedScopes ?? [];
|
|
9187
9237
|
const allowed = /* @__PURE__ */ new Set([...TOP_LEVEL_SCOPES, ...OPT_IN_TOP_LEVEL_SCOPES]);
|
|
@@ -9981,7 +10031,7 @@ function RecordsAdminShellInner(props) {
|
|
|
9981
10031
|
]
|
|
9982
10032
|
}
|
|
9983
10033
|
) : null;
|
|
9984
|
-
const selectedSummary =
|
|
10034
|
+
const selectedSummary = isCollection && selectedItemId && !isDraftId3(selectedItemId) ? collectionItems.items.find((r) => r.id === selectedItemId || r.itemId === selectedItemId) : selectedRecordId && selectedRecordId !== DRAFT_ID3 ? recordList.items.find((r) => r.id === selectedRecordId) ?? globalScopedList.items.find((r) => r.id === selectedRecordId) ?? ruleScopedList.items.find((r) => r.id === selectedRecordId) ?? collectionItems.items.find((r) => r.id === selectedRecordId) : void 0;
|
|
9985
10035
|
const editorLifecycleControl = selectedSummary?.id ? /* @__PURE__ */ jsx(
|
|
9986
10036
|
LifecycleStatusControl,
|
|
9987
10037
|
{
|
|
@@ -10214,7 +10264,12 @@ function RecordsAdminShellInner(props) {
|
|
|
10214
10264
|
}];
|
|
10215
10265
|
}
|
|
10216
10266
|
const configured = scopeCounts.productIds;
|
|
10217
|
-
const
|
|
10267
|
+
const lifecycle = scopeCounts.productLifecycle;
|
|
10268
|
+
const lifecycleI18n = {
|
|
10269
|
+
subtitleArchivedOnly: i18n.subtitleArchivedOnly,
|
|
10270
|
+
subtitleDraftOnly: i18n.subtitleDraftOnly
|
|
10271
|
+
};
|
|
10272
|
+
const all = productBrowse.items.map((p) => productItemToSummary(p, lifecycle.get(p.id), lifecycleI18n));
|
|
10218
10273
|
const isConfigured = (s) => {
|
|
10219
10274
|
const pid = s.scope.productId;
|
|
10220
10275
|
return !!pid && configured.has(pid);
|
|
@@ -10231,7 +10286,10 @@ function RecordsAdminShellInner(props) {
|
|
|
10231
10286
|
productBrowse.items,
|
|
10232
10287
|
pinnedProduct.item,
|
|
10233
10288
|
scopeCounts.productIds,
|
|
10234
|
-
|
|
10289
|
+
scopeCounts.productLifecycle,
|
|
10290
|
+
filter,
|
|
10291
|
+
i18n.subtitleArchivedOnly,
|
|
10292
|
+
i18n.subtitleDraftOnly
|
|
10235
10293
|
]);
|
|
10236
10294
|
const isRuleTab = activeScope === "rule";
|
|
10237
10295
|
const isGlobalTab = activeScope === "collection";
|