@okf/ootils 1.40.0 → 1.41.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.
@@ -285,9 +285,10 @@ declare const collectMarkIdsInOrder: (editorState: any) => string[];
285
285
  * }
286
286
  * ]
287
287
  */
288
- declare function getRollupPossibilities({ tagType, allTpls }: {
288
+ declare function getRollupPossibilities({ tagType, allTpls, includeSelfHead, }: {
289
289
  tagType: string;
290
290
  allTpls: any[];
291
+ includeSelfHead?: boolean;
291
292
  }): any[];
292
293
 
293
294
  declare namespace BASE_BULLMQ_CONFIG {
@@ -1241,6 +1242,27 @@ declare const processAuthorAndCommonFilters: (allTpls: any[], filterScopes: stri
1241
1242
 
1242
1243
  declare const _self_managed_getFixedAnnoTagBlock: (selectedTpls: any[], annotationTagsCount: any) => any[];
1243
1244
 
1245
+ /**
1246
+ * FOLLOWUP (consolidate the count->rollupPath rule into one source of truth):
1247
+ *
1248
+ * The rule "given annotationTagsCount, which self-managed anno rollupPaths exist"
1249
+ * (subThemes>0 -> ['tags','subThemes']; subThemes>0 && themes>0 -> ['tags','subThemes','themes'])
1250
+ * is currently duplicated in THREE places and will drift:
1251
+ * 1. here (_self_managed_getFixedAnnoRollupBlocks) -> filter blocks
1252
+ * 2. _self_managed_buildAnnoHierarchyConfig -> anno hierarchy filter UI
1253
+ * 3. okf-fe _extractAllAnnoBasedDimensionsAsOptions.js -> reports dimension dropdown
1254
+ *
1255
+ * (#3 was added to fix a crash: the reports widget previously discovered these rollups
1256
+ * from publishing-segment tpls via getRollupPossibilities, but self-managed taxonomy lives
1257
+ * on `collections`-segment tpls which isTplAnnotationEnabled excludes -> empty list ->
1258
+ * unguarded .find('subThemes') returned undefined -> crash. The FE now builds them from the
1259
+ * count, mirroring this function.)
1260
+ *
1261
+ * Extract a pure helper here in ootils:
1262
+ * export const getSelfManagedAnnoRollupPaths = (annotationTagsCount): string[][] => [...]
1263
+ * then have all three call sites consume it (each maps paths -> its own shape:
1264
+ * filter-blocks / hierarchy levels / dropdown options). One rule, three presentations.
1265
+ */
1244
1266
  declare const _self_managed_getFixedAnnoRollupBlocks: ({ selectedTpls, allTpls, annotationTagsCount }: {
1245
1267
  selectedTpls: any[];
1246
1268
  allTpls: any[];
@@ -1342,6 +1364,7 @@ declare const _self_managed_buildDocHierarchyConfig: ({ combinedDocumentBlocks,
1342
1364
  display: any;
1343
1365
  filters: any[];
1344
1366
  rollups: any[];
1367
+ rollupDisplayMap: Record<string, string>;
1345
1368
  }[];
1346
1369
  };
1347
1370
  target: {
@@ -1501,6 +1524,7 @@ declare const autoGenFilterConfigsFromTpl: ({ selectedTpls, allTpls, filterScope
1501
1524
  display: any;
1502
1525
  filters: any[];
1503
1526
  rollups: any[];
1527
+ rollupDisplayMap: Record<string, string>;
1504
1528
  }[];
1505
1529
  };
1506
1530
  target: {
package/dist/browser.d.ts CHANGED
@@ -285,9 +285,10 @@ declare const collectMarkIdsInOrder: (editorState: any) => string[];
285
285
  * }
286
286
  * ]
287
287
  */
288
- declare function getRollupPossibilities({ tagType, allTpls }: {
288
+ declare function getRollupPossibilities({ tagType, allTpls, includeSelfHead, }: {
289
289
  tagType: string;
290
290
  allTpls: any[];
291
+ includeSelfHead?: boolean;
291
292
  }): any[];
292
293
 
293
294
  declare namespace BASE_BULLMQ_CONFIG {
@@ -1241,6 +1242,27 @@ declare const processAuthorAndCommonFilters: (allTpls: any[], filterScopes: stri
1241
1242
 
1242
1243
  declare const _self_managed_getFixedAnnoTagBlock: (selectedTpls: any[], annotationTagsCount: any) => any[];
1243
1244
 
1245
+ /**
1246
+ * FOLLOWUP (consolidate the count->rollupPath rule into one source of truth):
1247
+ *
1248
+ * The rule "given annotationTagsCount, which self-managed anno rollupPaths exist"
1249
+ * (subThemes>0 -> ['tags','subThemes']; subThemes>0 && themes>0 -> ['tags','subThemes','themes'])
1250
+ * is currently duplicated in THREE places and will drift:
1251
+ * 1. here (_self_managed_getFixedAnnoRollupBlocks) -> filter blocks
1252
+ * 2. _self_managed_buildAnnoHierarchyConfig -> anno hierarchy filter UI
1253
+ * 3. okf-fe _extractAllAnnoBasedDimensionsAsOptions.js -> reports dimension dropdown
1254
+ *
1255
+ * (#3 was added to fix a crash: the reports widget previously discovered these rollups
1256
+ * from publishing-segment tpls via getRollupPossibilities, but self-managed taxonomy lives
1257
+ * on `collections`-segment tpls which isTplAnnotationEnabled excludes -> empty list ->
1258
+ * unguarded .find('subThemes') returned undefined -> crash. The FE now builds them from the
1259
+ * count, mirroring this function.)
1260
+ *
1261
+ * Extract a pure helper here in ootils:
1262
+ * export const getSelfManagedAnnoRollupPaths = (annotationTagsCount): string[][] => [...]
1263
+ * then have all three call sites consume it (each maps paths -> its own shape:
1264
+ * filter-blocks / hierarchy levels / dropdown options). One rule, three presentations.
1265
+ */
1244
1266
  declare const _self_managed_getFixedAnnoRollupBlocks: ({ selectedTpls, allTpls, annotationTagsCount }: {
1245
1267
  selectedTpls: any[];
1246
1268
  allTpls: any[];
@@ -1342,6 +1364,7 @@ declare const _self_managed_buildDocHierarchyConfig: ({ combinedDocumentBlocks,
1342
1364
  display: any;
1343
1365
  filters: any[];
1344
1366
  rollups: any[];
1367
+ rollupDisplayMap: Record<string, string>;
1345
1368
  }[];
1346
1369
  };
1347
1370
  target: {
@@ -1501,6 +1524,7 @@ declare const autoGenFilterConfigsFromTpl: ({ selectedTpls, allTpls, filterScope
1501
1524
  display: any;
1502
1525
  filters: any[];
1503
1526
  rollups: any[];
1527
+ rollupDisplayMap: Record<string, string>;
1504
1528
  }[];
1505
1529
  };
1506
1530
  target: {
package/dist/browser.js CHANGED
@@ -722,7 +722,8 @@ var collectMarkIdsInOrder = (editorState) => {
722
722
  var MAX_DEPTH_ROLLUP_POSSIBILITIES = 10;
723
723
  function getRollupPossibilities({
724
724
  tagType,
725
- allTpls
725
+ allTpls,
726
+ includeSelfHead = false
726
727
  }) {
727
728
  const thisTagTpl = allTpls.find((d) => d.kp_content_type === tagType);
728
729
  if (!thisTagTpl) return [];
@@ -754,7 +755,8 @@ function getRollupPossibilities({
754
755
  chains.push({
755
756
  rollupType: "tagType",
756
757
  tagTypeCollectionToRollup: tagType,
757
- rollupPath: [...visited, startTagType, nextTagType]
758
+ rollupPath: [...visited, startTagType, nextTagType],
759
+ filterDisplay: block.props?.shortLabel || block.props?.label
758
760
  });
759
761
  if (visited.length < maxDepth - 1) {
760
762
  const nextChains = findTagChains(
@@ -800,7 +802,8 @@ function getRollupPossibilities({
800
802
  const directChain = {
801
803
  rollupType: "tagType",
802
804
  tagTypeCollectionToRollup: tagType,
803
- rollupPath: [tagType, block.props.tagType]
805
+ rollupPath: [tagType, block.props.tagType],
806
+ filterDisplay: block.props?.shortLabel || block.props?.label
804
807
  };
805
808
  const deeperChains = findTagChains(
806
809
  block.props?.tagType,
@@ -809,7 +812,14 @@ function getRollupPossibilities({
809
812
  );
810
813
  return [directChain, ...deeperChains];
811
814
  });
812
- return [...singleLevelValuePathRollups, ...nestedTagRollups];
815
+ const selfHeadRollup = includeSelfHead && nestedTagRollups.length > 0 && singleLevelValuePathRollups.length === 0 ? [
816
+ {
817
+ rollupType: "tagType",
818
+ tagTypeCollectionToRollup: tagType,
819
+ rollupPath: [tagType]
820
+ }
821
+ ] : [];
822
+ return [...singleLevelValuePathRollups, ...selfHeadRollup, ...nestedTagRollups];
813
823
  }
814
824
 
815
825
  // src/bullmq/GLOBAL_BULLMQ_CONFIG.js
@@ -1714,6 +1724,7 @@ var buildFilterConfigurations = ({ groups, type, selectedTpls, allTpls, isRollup
1714
1724
  if (isTerminalValuePath) {
1715
1725
  return element.filterDisplay || lastItemInPath;
1716
1726
  }
1727
+ if (element.filterDisplay) return element.filterDisplay;
1717
1728
  const lastTag = rollupPath[rollupPath.length - 1];
1718
1729
  const lastTagTpl = allTpls.find(
1719
1730
  (tpl) => tpl.kp_content_type === lastTag
@@ -1980,7 +1991,7 @@ var extractAndOrganizeBlocks = (selectedTpls, allTpls, { smTagTypesConfig } = {}
1980
1991
  return {
1981
1992
  contentType: tpl.kp_content_type,
1982
1993
  blocks: allBlocks.filter((block) => block.valuePath.startsWith("tags.") && ["TagsInputSingle", "TagsInputMulti"].includes(block.comp)).flatMap((block) => {
1983
- const possibilities = getRollupPossibilities({ tagType: block.props.tagType, allTpls });
1994
+ const possibilities = getRollupPossibilities({ tagType: block.props.tagType, allTpls, includeSelfHead: true });
1984
1995
  return possibilities.map((p) => ({
1985
1996
  ...p,
1986
1997
  filterType: p.rollupPath ? "nestedRollupTagType" : "rollupValuePathType"
@@ -2313,13 +2324,16 @@ var buildTagTypeParentMap = (tagTypesInGroup, allTpls) => {
2313
2324
  const tagBlocks = blocks.filter(
2314
2325
  (block) => block.valuePath?.startsWith("tags.") && block.props?.tagType
2315
2326
  );
2327
+ const referencedTagTypes = /* @__PURE__ */ new Set();
2316
2328
  for (const block of tagBlocks) {
2317
2329
  const referencedTagType = block.props.tagType;
2318
2330
  if (tagTypeSet.has(referencedTagType) && referencedTagType !== tagType) {
2319
- parentMap.set(tagType, referencedTagType);
2320
- break;
2331
+ referencedTagTypes.add(referencedTagType);
2321
2332
  }
2322
2333
  }
2334
+ if (referencedTagTypes.size === 1) {
2335
+ parentMap.set(tagType, [...referencedTagTypes][0]);
2336
+ }
2323
2337
  }
2324
2338
  for (const child of parentMap.keys()) {
2325
2339
  const visited = /* @__PURE__ */ new Set();
@@ -2393,6 +2407,34 @@ var sortFiltersHierarchically = (filters) => {
2393
2407
  return sorted;
2394
2408
  };
2395
2409
 
2410
+ // src/utils/autoGenFilterConfigsFromTpl/utils/deduplicateRollupTagFilters.ts
2411
+ var deduplicateRollupTagFilters = (rollups) => {
2412
+ const tagTerminals = [];
2413
+ const nonTag = [];
2414
+ for (const r of rollups) {
2415
+ const rp = r.target?.rollupPath;
2416
+ if (rp?.length && !rp[rp.length - 1].startsWith("main.")) {
2417
+ tagTerminals.push(r);
2418
+ } else {
2419
+ nonTag.push({ ...r, isTagRollup: false });
2420
+ }
2421
+ }
2422
+ if (tagTerminals.length === 0) return nonTag;
2423
+ const byTerminal = /* @__PURE__ */ new Map();
2424
+ for (const r of tagTerminals) {
2425
+ const terminal = r.target.rollupPath[r.target.rollupPath.length - 1];
2426
+ const existing = byTerminal.get(terminal);
2427
+ if (!existing || r.target.rollupPath.length < existing.target.rollupPath.length) {
2428
+ byTerminal.set(terminal, r);
2429
+ }
2430
+ }
2431
+ const dedupedTags = [...byTerminal.values()].map((r) => ({
2432
+ ...r,
2433
+ isTagRollup: true
2434
+ }));
2435
+ return [...nonTag, ...dedupedTags];
2436
+ };
2437
+
2396
2438
  // src/utils/autoGenFilterConfigsFromTpl/utils/_self_managed_buildDocHierarchyConfig.ts
2397
2439
  var injectFilterOptionsBy = (filters) => filters.map(
2398
2440
  (f) => f.parentFilterId ? { ...f, source: { ...f.source, filterOptionsBy: { filterId: f.parentFilterId } } } : f
@@ -2499,24 +2541,34 @@ var _self_managed_buildDocHierarchyConfig = ({
2499
2541
  const dedupedFilters = filtersWithCommonFlag.filter(
2500
2542
  (f) => !rollupSourceKeys.has(JSON.stringify(f.source))
2501
2543
  );
2502
- const combined = [...dedupedFilters, ...rollupConfigs];
2544
+ const dedupedRollupConfigs = deduplicateRollupTagFilters(rollupConfigs);
2545
+ const combined = [...dedupedFilters, ...dedupedRollupConfigs];
2503
2546
  const combinedWithParents = injectFilterOptionsBy(
2504
2547
  sortFiltersHierarchically(
2505
2548
  attachParentFields(combined, allTpls)
2506
2549
  )
2507
2550
  );
2508
- const rollupFilterIds = new Set(rollupConfigs.map((r) => r.filterId));
2551
+ const rollupFilterIds = new Set(dedupedRollupConfigs.map((r) => r.filterId));
2509
2552
  const filtersWithParents = combinedWithParents.filter(
2510
2553
  (f) => !rollupFilterIds.has(f.filterId)
2511
2554
  );
2512
2555
  const rollupsWithParents = combinedWithParents.filter(
2513
2556
  (f) => rollupFilterIds.has(f.filterId)
2514
2557
  );
2558
+ const rollupContentTypes = new Set(
2559
+ rollupsWithParents.filter((r) => r.target?.rollupPath).flatMap((r) => r.target.rollupPath)
2560
+ );
2561
+ const rollupDisplayMap = {};
2562
+ for (const ct of rollupContentTypes) {
2563
+ const t = allTpls.find((tp) => tp.kp_content_type === ct);
2564
+ if (t?.general?.content?.title) rollupDisplayMap[ct] = t.general.content.title;
2565
+ }
2515
2566
  return {
2516
2567
  contentType: tpl.kp_content_type,
2517
2568
  display: tplData?.general?.content?.title || tpl.kp_content_type,
2518
2569
  filters: filtersWithParents,
2519
- rollups: rollupsWithParents
2570
+ rollups: rollupsWithParents,
2571
+ rollupDisplayMap
2520
2572
  };
2521
2573
  });
2522
2574
  const filteredPerDataset = perDataset.filter(
package/dist/browser.mjs CHANGED
@@ -652,7 +652,8 @@ var collectMarkIdsInOrder = (editorState) => {
652
652
  var MAX_DEPTH_ROLLUP_POSSIBILITIES = 10;
653
653
  function getRollupPossibilities({
654
654
  tagType,
655
- allTpls
655
+ allTpls,
656
+ includeSelfHead = false
656
657
  }) {
657
658
  const thisTagTpl = allTpls.find((d) => d.kp_content_type === tagType);
658
659
  if (!thisTagTpl) return [];
@@ -684,7 +685,8 @@ function getRollupPossibilities({
684
685
  chains.push({
685
686
  rollupType: "tagType",
686
687
  tagTypeCollectionToRollup: tagType,
687
- rollupPath: [...visited, startTagType, nextTagType]
688
+ rollupPath: [...visited, startTagType, nextTagType],
689
+ filterDisplay: block.props?.shortLabel || block.props?.label
688
690
  });
689
691
  if (visited.length < maxDepth - 1) {
690
692
  const nextChains = findTagChains(
@@ -730,7 +732,8 @@ function getRollupPossibilities({
730
732
  const directChain = {
731
733
  rollupType: "tagType",
732
734
  tagTypeCollectionToRollup: tagType,
733
- rollupPath: [tagType, block.props.tagType]
735
+ rollupPath: [tagType, block.props.tagType],
736
+ filterDisplay: block.props?.shortLabel || block.props?.label
734
737
  };
735
738
  const deeperChains = findTagChains(
736
739
  block.props?.tagType,
@@ -739,7 +742,14 @@ function getRollupPossibilities({
739
742
  );
740
743
  return [directChain, ...deeperChains];
741
744
  });
742
- return [...singleLevelValuePathRollups, ...nestedTagRollups];
745
+ const selfHeadRollup = includeSelfHead && nestedTagRollups.length > 0 && singleLevelValuePathRollups.length === 0 ? [
746
+ {
747
+ rollupType: "tagType",
748
+ tagTypeCollectionToRollup: tagType,
749
+ rollupPath: [tagType]
750
+ }
751
+ ] : [];
752
+ return [...singleLevelValuePathRollups, ...selfHeadRollup, ...nestedTagRollups];
743
753
  }
744
754
 
745
755
  // src/bullmq/GLOBAL_BULLMQ_CONFIG.js
@@ -1644,6 +1654,7 @@ var buildFilterConfigurations = ({ groups, type, selectedTpls, allTpls, isRollup
1644
1654
  if (isTerminalValuePath) {
1645
1655
  return element.filterDisplay || lastItemInPath;
1646
1656
  }
1657
+ if (element.filterDisplay) return element.filterDisplay;
1647
1658
  const lastTag = rollupPath[rollupPath.length - 1];
1648
1659
  const lastTagTpl = allTpls.find(
1649
1660
  (tpl) => tpl.kp_content_type === lastTag
@@ -1910,7 +1921,7 @@ var extractAndOrganizeBlocks = (selectedTpls, allTpls, { smTagTypesConfig } = {}
1910
1921
  return {
1911
1922
  contentType: tpl.kp_content_type,
1912
1923
  blocks: allBlocks.filter((block) => block.valuePath.startsWith("tags.") && ["TagsInputSingle", "TagsInputMulti"].includes(block.comp)).flatMap((block) => {
1913
- const possibilities = getRollupPossibilities({ tagType: block.props.tagType, allTpls });
1924
+ const possibilities = getRollupPossibilities({ tagType: block.props.tagType, allTpls, includeSelfHead: true });
1914
1925
  return possibilities.map((p) => ({
1915
1926
  ...p,
1916
1927
  filterType: p.rollupPath ? "nestedRollupTagType" : "rollupValuePathType"
@@ -2243,13 +2254,16 @@ var buildTagTypeParentMap = (tagTypesInGroup, allTpls) => {
2243
2254
  const tagBlocks = blocks.filter(
2244
2255
  (block) => block.valuePath?.startsWith("tags.") && block.props?.tagType
2245
2256
  );
2257
+ const referencedTagTypes = /* @__PURE__ */ new Set();
2246
2258
  for (const block of tagBlocks) {
2247
2259
  const referencedTagType = block.props.tagType;
2248
2260
  if (tagTypeSet.has(referencedTagType) && referencedTagType !== tagType) {
2249
- parentMap.set(tagType, referencedTagType);
2250
- break;
2261
+ referencedTagTypes.add(referencedTagType);
2251
2262
  }
2252
2263
  }
2264
+ if (referencedTagTypes.size === 1) {
2265
+ parentMap.set(tagType, [...referencedTagTypes][0]);
2266
+ }
2253
2267
  }
2254
2268
  for (const child of parentMap.keys()) {
2255
2269
  const visited = /* @__PURE__ */ new Set();
@@ -2323,6 +2337,34 @@ var sortFiltersHierarchically = (filters) => {
2323
2337
  return sorted;
2324
2338
  };
2325
2339
 
2340
+ // src/utils/autoGenFilterConfigsFromTpl/utils/deduplicateRollupTagFilters.ts
2341
+ var deduplicateRollupTagFilters = (rollups) => {
2342
+ const tagTerminals = [];
2343
+ const nonTag = [];
2344
+ for (const r of rollups) {
2345
+ const rp = r.target?.rollupPath;
2346
+ if (rp?.length && !rp[rp.length - 1].startsWith("main.")) {
2347
+ tagTerminals.push(r);
2348
+ } else {
2349
+ nonTag.push({ ...r, isTagRollup: false });
2350
+ }
2351
+ }
2352
+ if (tagTerminals.length === 0) return nonTag;
2353
+ const byTerminal = /* @__PURE__ */ new Map();
2354
+ for (const r of tagTerminals) {
2355
+ const terminal = r.target.rollupPath[r.target.rollupPath.length - 1];
2356
+ const existing = byTerminal.get(terminal);
2357
+ if (!existing || r.target.rollupPath.length < existing.target.rollupPath.length) {
2358
+ byTerminal.set(terminal, r);
2359
+ }
2360
+ }
2361
+ const dedupedTags = [...byTerminal.values()].map((r) => ({
2362
+ ...r,
2363
+ isTagRollup: true
2364
+ }));
2365
+ return [...nonTag, ...dedupedTags];
2366
+ };
2367
+
2326
2368
  // src/utils/autoGenFilterConfigsFromTpl/utils/_self_managed_buildDocHierarchyConfig.ts
2327
2369
  var injectFilterOptionsBy = (filters) => filters.map(
2328
2370
  (f) => f.parentFilterId ? { ...f, source: { ...f.source, filterOptionsBy: { filterId: f.parentFilterId } } } : f
@@ -2429,24 +2471,34 @@ var _self_managed_buildDocHierarchyConfig = ({
2429
2471
  const dedupedFilters = filtersWithCommonFlag.filter(
2430
2472
  (f) => !rollupSourceKeys.has(JSON.stringify(f.source))
2431
2473
  );
2432
- const combined = [...dedupedFilters, ...rollupConfigs];
2474
+ const dedupedRollupConfigs = deduplicateRollupTagFilters(rollupConfigs);
2475
+ const combined = [...dedupedFilters, ...dedupedRollupConfigs];
2433
2476
  const combinedWithParents = injectFilterOptionsBy(
2434
2477
  sortFiltersHierarchically(
2435
2478
  attachParentFields(combined, allTpls)
2436
2479
  )
2437
2480
  );
2438
- const rollupFilterIds = new Set(rollupConfigs.map((r) => r.filterId));
2481
+ const rollupFilterIds = new Set(dedupedRollupConfigs.map((r) => r.filterId));
2439
2482
  const filtersWithParents = combinedWithParents.filter(
2440
2483
  (f) => !rollupFilterIds.has(f.filterId)
2441
2484
  );
2442
2485
  const rollupsWithParents = combinedWithParents.filter(
2443
2486
  (f) => rollupFilterIds.has(f.filterId)
2444
2487
  );
2488
+ const rollupContentTypes = new Set(
2489
+ rollupsWithParents.filter((r) => r.target?.rollupPath).flatMap((r) => r.target.rollupPath)
2490
+ );
2491
+ const rollupDisplayMap = {};
2492
+ for (const ct of rollupContentTypes) {
2493
+ const t = allTpls.find((tp) => tp.kp_content_type === ct);
2494
+ if (t?.general?.content?.title) rollupDisplayMap[ct] = t.general.content.title;
2495
+ }
2445
2496
  return {
2446
2497
  contentType: tpl.kp_content_type,
2447
2498
  display: tplData?.general?.content?.title || tpl.kp_content_type,
2448
2499
  filters: filtersWithParents,
2449
- rollups: rollupsWithParents
2500
+ rollups: rollupsWithParents,
2501
+ rollupDisplayMap
2450
2502
  };
2451
2503
  });
2452
2504
  const filteredPerDataset = perDataset.filter(
package/dist/node.d.mts CHANGED
@@ -293,9 +293,10 @@ declare const collectMarkIdsInOrder: (editorState: any) => string[];
293
293
  * }
294
294
  * ]
295
295
  */
296
- declare function getRollupPossibilities({ tagType, allTpls }: {
296
+ declare function getRollupPossibilities({ tagType, allTpls, includeSelfHead, }: {
297
297
  tagType: string;
298
298
  allTpls: any[];
299
+ includeSelfHead?: boolean;
299
300
  }): any[];
300
301
 
301
302
  declare namespace BASE_BULLMQ_CONFIG {
@@ -1249,6 +1250,27 @@ declare const processAuthorAndCommonFilters: (allTpls: any[], filterScopes: stri
1249
1250
 
1250
1251
  declare const _self_managed_getFixedAnnoTagBlock: (selectedTpls: any[], annotationTagsCount: any) => any[];
1251
1252
 
1253
+ /**
1254
+ * FOLLOWUP (consolidate the count->rollupPath rule into one source of truth):
1255
+ *
1256
+ * The rule "given annotationTagsCount, which self-managed anno rollupPaths exist"
1257
+ * (subThemes>0 -> ['tags','subThemes']; subThemes>0 && themes>0 -> ['tags','subThemes','themes'])
1258
+ * is currently duplicated in THREE places and will drift:
1259
+ * 1. here (_self_managed_getFixedAnnoRollupBlocks) -> filter blocks
1260
+ * 2. _self_managed_buildAnnoHierarchyConfig -> anno hierarchy filter UI
1261
+ * 3. okf-fe _extractAllAnnoBasedDimensionsAsOptions.js -> reports dimension dropdown
1262
+ *
1263
+ * (#3 was added to fix a crash: the reports widget previously discovered these rollups
1264
+ * from publishing-segment tpls via getRollupPossibilities, but self-managed taxonomy lives
1265
+ * on `collections`-segment tpls which isTplAnnotationEnabled excludes -> empty list ->
1266
+ * unguarded .find('subThemes') returned undefined -> crash. The FE now builds them from the
1267
+ * count, mirroring this function.)
1268
+ *
1269
+ * Extract a pure helper here in ootils:
1270
+ * export const getSelfManagedAnnoRollupPaths = (annotationTagsCount): string[][] => [...]
1271
+ * then have all three call sites consume it (each maps paths -> its own shape:
1272
+ * filter-blocks / hierarchy levels / dropdown options). One rule, three presentations.
1273
+ */
1252
1274
  declare const _self_managed_getFixedAnnoRollupBlocks: ({ selectedTpls, allTpls, annotationTagsCount }: {
1253
1275
  selectedTpls: any[];
1254
1276
  allTpls: any[];
@@ -1350,6 +1372,7 @@ declare const _self_managed_buildDocHierarchyConfig: ({ combinedDocumentBlocks,
1350
1372
  display: any;
1351
1373
  filters: any[];
1352
1374
  rollups: any[];
1375
+ rollupDisplayMap: Record<string, string>;
1353
1376
  }[];
1354
1377
  };
1355
1378
  target: {
@@ -1509,6 +1532,7 @@ declare const autoGenFilterConfigsFromTpl: ({ selectedTpls, allTpls, filterScope
1509
1532
  display: any;
1510
1533
  filters: any[];
1511
1534
  rollups: any[];
1535
+ rollupDisplayMap: Record<string, string>;
1512
1536
  }[];
1513
1537
  };
1514
1538
  target: {
package/dist/node.d.ts CHANGED
@@ -293,9 +293,10 @@ declare const collectMarkIdsInOrder: (editorState: any) => string[];
293
293
  * }
294
294
  * ]
295
295
  */
296
- declare function getRollupPossibilities({ tagType, allTpls }: {
296
+ declare function getRollupPossibilities({ tagType, allTpls, includeSelfHead, }: {
297
297
  tagType: string;
298
298
  allTpls: any[];
299
+ includeSelfHead?: boolean;
299
300
  }): any[];
300
301
 
301
302
  declare namespace BASE_BULLMQ_CONFIG {
@@ -1249,6 +1250,27 @@ declare const processAuthorAndCommonFilters: (allTpls: any[], filterScopes: stri
1249
1250
 
1250
1251
  declare const _self_managed_getFixedAnnoTagBlock: (selectedTpls: any[], annotationTagsCount: any) => any[];
1251
1252
 
1253
+ /**
1254
+ * FOLLOWUP (consolidate the count->rollupPath rule into one source of truth):
1255
+ *
1256
+ * The rule "given annotationTagsCount, which self-managed anno rollupPaths exist"
1257
+ * (subThemes>0 -> ['tags','subThemes']; subThemes>0 && themes>0 -> ['tags','subThemes','themes'])
1258
+ * is currently duplicated in THREE places and will drift:
1259
+ * 1. here (_self_managed_getFixedAnnoRollupBlocks) -> filter blocks
1260
+ * 2. _self_managed_buildAnnoHierarchyConfig -> anno hierarchy filter UI
1261
+ * 3. okf-fe _extractAllAnnoBasedDimensionsAsOptions.js -> reports dimension dropdown
1262
+ *
1263
+ * (#3 was added to fix a crash: the reports widget previously discovered these rollups
1264
+ * from publishing-segment tpls via getRollupPossibilities, but self-managed taxonomy lives
1265
+ * on `collections`-segment tpls which isTplAnnotationEnabled excludes -> empty list ->
1266
+ * unguarded .find('subThemes') returned undefined -> crash. The FE now builds them from the
1267
+ * count, mirroring this function.)
1268
+ *
1269
+ * Extract a pure helper here in ootils:
1270
+ * export const getSelfManagedAnnoRollupPaths = (annotationTagsCount): string[][] => [...]
1271
+ * then have all three call sites consume it (each maps paths -> its own shape:
1272
+ * filter-blocks / hierarchy levels / dropdown options). One rule, three presentations.
1273
+ */
1252
1274
  declare const _self_managed_getFixedAnnoRollupBlocks: ({ selectedTpls, allTpls, annotationTagsCount }: {
1253
1275
  selectedTpls: any[];
1254
1276
  allTpls: any[];
@@ -1350,6 +1372,7 @@ declare const _self_managed_buildDocHierarchyConfig: ({ combinedDocumentBlocks,
1350
1372
  display: any;
1351
1373
  filters: any[];
1352
1374
  rollups: any[];
1375
+ rollupDisplayMap: Record<string, string>;
1353
1376
  }[];
1354
1377
  };
1355
1378
  target: {
@@ -1509,6 +1532,7 @@ declare const autoGenFilterConfigsFromTpl: ({ selectedTpls, allTpls, filterScope
1509
1532
  display: any;
1510
1533
  filters: any[];
1511
1534
  rollups: any[];
1535
+ rollupDisplayMap: Record<string, string>;
1512
1536
  }[];
1513
1537
  };
1514
1538
  target: {
package/dist/node.js CHANGED
@@ -2959,7 +2959,8 @@ var collectMarkIdsInOrder = (editorState) => {
2959
2959
  var MAX_DEPTH_ROLLUP_POSSIBILITIES = 10;
2960
2960
  function getRollupPossibilities({
2961
2961
  tagType,
2962
- allTpls
2962
+ allTpls,
2963
+ includeSelfHead = false
2963
2964
  }) {
2964
2965
  const thisTagTpl = allTpls.find((d) => d.kp_content_type === tagType);
2965
2966
  if (!thisTagTpl) return [];
@@ -2991,7 +2992,8 @@ function getRollupPossibilities({
2991
2992
  chains.push({
2992
2993
  rollupType: "tagType",
2993
2994
  tagTypeCollectionToRollup: tagType,
2994
- rollupPath: [...visited, startTagType, nextTagType]
2995
+ rollupPath: [...visited, startTagType, nextTagType],
2996
+ filterDisplay: block.props?.shortLabel || block.props?.label
2995
2997
  });
2996
2998
  if (visited.length < maxDepth - 1) {
2997
2999
  const nextChains = findTagChains(
@@ -3037,7 +3039,8 @@ function getRollupPossibilities({
3037
3039
  const directChain = {
3038
3040
  rollupType: "tagType",
3039
3041
  tagTypeCollectionToRollup: tagType,
3040
- rollupPath: [tagType, block.props.tagType]
3042
+ rollupPath: [tagType, block.props.tagType],
3043
+ filterDisplay: block.props?.shortLabel || block.props?.label
3041
3044
  };
3042
3045
  const deeperChains = findTagChains(
3043
3046
  block.props?.tagType,
@@ -3046,7 +3049,14 @@ function getRollupPossibilities({
3046
3049
  );
3047
3050
  return [directChain, ...deeperChains];
3048
3051
  });
3049
- return [...singleLevelValuePathRollups, ...nestedTagRollups];
3052
+ const selfHeadRollup = includeSelfHead && nestedTagRollups.length > 0 && singleLevelValuePathRollups.length === 0 ? [
3053
+ {
3054
+ rollupType: "tagType",
3055
+ tagTypeCollectionToRollup: tagType,
3056
+ rollupPath: [tagType]
3057
+ }
3058
+ ] : [];
3059
+ return [...singleLevelValuePathRollups, ...selfHeadRollup, ...nestedTagRollups];
3050
3060
  }
3051
3061
 
3052
3062
  // src/universal.ts
@@ -3454,6 +3464,7 @@ var buildFilterConfigurations = ({ groups, type, selectedTpls, allTpls, isRollup
3454
3464
  if (isTerminalValuePath) {
3455
3465
  return element.filterDisplay || lastItemInPath;
3456
3466
  }
3467
+ if (element.filterDisplay) return element.filterDisplay;
3457
3468
  const lastTag = rollupPath[rollupPath.length - 1];
3458
3469
  const lastTagTpl = allTpls.find(
3459
3470
  (tpl) => tpl.kp_content_type === lastTag
@@ -3720,7 +3731,7 @@ var extractAndOrganizeBlocks = (selectedTpls, allTpls, { smTagTypesConfig } = {}
3720
3731
  return {
3721
3732
  contentType: tpl.kp_content_type,
3722
3733
  blocks: allBlocks.filter((block) => block.valuePath.startsWith("tags.") && ["TagsInputSingle", "TagsInputMulti"].includes(block.comp)).flatMap((block) => {
3723
- const possibilities = getRollupPossibilities({ tagType: block.props.tagType, allTpls });
3734
+ const possibilities = getRollupPossibilities({ tagType: block.props.tagType, allTpls, includeSelfHead: true });
3724
3735
  return possibilities.map((p) => ({
3725
3736
  ...p,
3726
3737
  filterType: p.rollupPath ? "nestedRollupTagType" : "rollupValuePathType"
@@ -4053,13 +4064,16 @@ var buildTagTypeParentMap = (tagTypesInGroup, allTpls) => {
4053
4064
  const tagBlocks = blocks.filter(
4054
4065
  (block) => block.valuePath?.startsWith("tags.") && block.props?.tagType
4055
4066
  );
4067
+ const referencedTagTypes = /* @__PURE__ */ new Set();
4056
4068
  for (const block of tagBlocks) {
4057
4069
  const referencedTagType = block.props.tagType;
4058
4070
  if (tagTypeSet.has(referencedTagType) && referencedTagType !== tagType) {
4059
- parentMap.set(tagType, referencedTagType);
4060
- break;
4071
+ referencedTagTypes.add(referencedTagType);
4061
4072
  }
4062
4073
  }
4074
+ if (referencedTagTypes.size === 1) {
4075
+ parentMap.set(tagType, [...referencedTagTypes][0]);
4076
+ }
4063
4077
  }
4064
4078
  for (const child of parentMap.keys()) {
4065
4079
  const visited = /* @__PURE__ */ new Set();
@@ -4133,6 +4147,34 @@ var sortFiltersHierarchically = (filters) => {
4133
4147
  return sorted;
4134
4148
  };
4135
4149
 
4150
+ // src/utils/autoGenFilterConfigsFromTpl/utils/deduplicateRollupTagFilters.ts
4151
+ var deduplicateRollupTagFilters = (rollups) => {
4152
+ const tagTerminals = [];
4153
+ const nonTag = [];
4154
+ for (const r of rollups) {
4155
+ const rp = r.target?.rollupPath;
4156
+ if (rp?.length && !rp[rp.length - 1].startsWith("main.")) {
4157
+ tagTerminals.push(r);
4158
+ } else {
4159
+ nonTag.push({ ...r, isTagRollup: false });
4160
+ }
4161
+ }
4162
+ if (tagTerminals.length === 0) return nonTag;
4163
+ const byTerminal = /* @__PURE__ */ new Map();
4164
+ for (const r of tagTerminals) {
4165
+ const terminal = r.target.rollupPath[r.target.rollupPath.length - 1];
4166
+ const existing = byTerminal.get(terminal);
4167
+ if (!existing || r.target.rollupPath.length < existing.target.rollupPath.length) {
4168
+ byTerminal.set(terminal, r);
4169
+ }
4170
+ }
4171
+ const dedupedTags = [...byTerminal.values()].map((r) => ({
4172
+ ...r,
4173
+ isTagRollup: true
4174
+ }));
4175
+ return [...nonTag, ...dedupedTags];
4176
+ };
4177
+
4136
4178
  // src/utils/autoGenFilterConfigsFromTpl/utils/_self_managed_buildDocHierarchyConfig.ts
4137
4179
  var injectFilterOptionsBy = (filters) => filters.map(
4138
4180
  (f) => f.parentFilterId ? { ...f, source: { ...f.source, filterOptionsBy: { filterId: f.parentFilterId } } } : f
@@ -4239,24 +4281,34 @@ var _self_managed_buildDocHierarchyConfig = ({
4239
4281
  const dedupedFilters = filtersWithCommonFlag.filter(
4240
4282
  (f) => !rollupSourceKeys.has(JSON.stringify(f.source))
4241
4283
  );
4242
- const combined = [...dedupedFilters, ...rollupConfigs];
4284
+ const dedupedRollupConfigs = deduplicateRollupTagFilters(rollupConfigs);
4285
+ const combined = [...dedupedFilters, ...dedupedRollupConfigs];
4243
4286
  const combinedWithParents = injectFilterOptionsBy(
4244
4287
  sortFiltersHierarchically(
4245
4288
  attachParentFields(combined, allTpls)
4246
4289
  )
4247
4290
  );
4248
- const rollupFilterIds = new Set(rollupConfigs.map((r) => r.filterId));
4291
+ const rollupFilterIds = new Set(dedupedRollupConfigs.map((r) => r.filterId));
4249
4292
  const filtersWithParents = combinedWithParents.filter(
4250
4293
  (f) => !rollupFilterIds.has(f.filterId)
4251
4294
  );
4252
4295
  const rollupsWithParents = combinedWithParents.filter(
4253
4296
  (f) => rollupFilterIds.has(f.filterId)
4254
4297
  );
4298
+ const rollupContentTypes = new Set(
4299
+ rollupsWithParents.filter((r) => r.target?.rollupPath).flatMap((r) => r.target.rollupPath)
4300
+ );
4301
+ const rollupDisplayMap = {};
4302
+ for (const ct of rollupContentTypes) {
4303
+ const t = allTpls.find((tp) => tp.kp_content_type === ct);
4304
+ if (t?.general?.content?.title) rollupDisplayMap[ct] = t.general.content.title;
4305
+ }
4255
4306
  return {
4256
4307
  contentType: tpl.kp_content_type,
4257
4308
  display: tplData?.general?.content?.title || tpl.kp_content_type,
4258
4309
  filters: filtersWithParents,
4259
- rollups: rollupsWithParents
4310
+ rollups: rollupsWithParents,
4311
+ rollupDisplayMap
4260
4312
  };
4261
4313
  });
4262
4314
  const filteredPerDataset = perDataset.filter(
package/dist/node.mjs CHANGED
@@ -2887,7 +2887,8 @@ var collectMarkIdsInOrder = (editorState) => {
2887
2887
  var MAX_DEPTH_ROLLUP_POSSIBILITIES = 10;
2888
2888
  function getRollupPossibilities({
2889
2889
  tagType,
2890
- allTpls
2890
+ allTpls,
2891
+ includeSelfHead = false
2891
2892
  }) {
2892
2893
  const thisTagTpl = allTpls.find((d) => d.kp_content_type === tagType);
2893
2894
  if (!thisTagTpl) return [];
@@ -2919,7 +2920,8 @@ function getRollupPossibilities({
2919
2920
  chains.push({
2920
2921
  rollupType: "tagType",
2921
2922
  tagTypeCollectionToRollup: tagType,
2922
- rollupPath: [...visited, startTagType, nextTagType]
2923
+ rollupPath: [...visited, startTagType, nextTagType],
2924
+ filterDisplay: block.props?.shortLabel || block.props?.label
2923
2925
  });
2924
2926
  if (visited.length < maxDepth - 1) {
2925
2927
  const nextChains = findTagChains(
@@ -2965,7 +2967,8 @@ function getRollupPossibilities({
2965
2967
  const directChain = {
2966
2968
  rollupType: "tagType",
2967
2969
  tagTypeCollectionToRollup: tagType,
2968
- rollupPath: [tagType, block.props.tagType]
2970
+ rollupPath: [tagType, block.props.tagType],
2971
+ filterDisplay: block.props?.shortLabel || block.props?.label
2969
2972
  };
2970
2973
  const deeperChains = findTagChains(
2971
2974
  block.props?.tagType,
@@ -2974,7 +2977,14 @@ function getRollupPossibilities({
2974
2977
  );
2975
2978
  return [directChain, ...deeperChains];
2976
2979
  });
2977
- return [...singleLevelValuePathRollups, ...nestedTagRollups];
2980
+ const selfHeadRollup = includeSelfHead && nestedTagRollups.length > 0 && singleLevelValuePathRollups.length === 0 ? [
2981
+ {
2982
+ rollupType: "tagType",
2983
+ tagTypeCollectionToRollup: tagType,
2984
+ rollupPath: [tagType]
2985
+ }
2986
+ ] : [];
2987
+ return [...singleLevelValuePathRollups, ...selfHeadRollup, ...nestedTagRollups];
2978
2988
  }
2979
2989
 
2980
2990
  // src/universal.ts
@@ -3382,6 +3392,7 @@ var buildFilterConfigurations = ({ groups, type, selectedTpls, allTpls, isRollup
3382
3392
  if (isTerminalValuePath) {
3383
3393
  return element.filterDisplay || lastItemInPath;
3384
3394
  }
3395
+ if (element.filterDisplay) return element.filterDisplay;
3385
3396
  const lastTag = rollupPath[rollupPath.length - 1];
3386
3397
  const lastTagTpl = allTpls.find(
3387
3398
  (tpl) => tpl.kp_content_type === lastTag
@@ -3648,7 +3659,7 @@ var extractAndOrganizeBlocks = (selectedTpls, allTpls, { smTagTypesConfig } = {}
3648
3659
  return {
3649
3660
  contentType: tpl.kp_content_type,
3650
3661
  blocks: allBlocks.filter((block) => block.valuePath.startsWith("tags.") && ["TagsInputSingle", "TagsInputMulti"].includes(block.comp)).flatMap((block) => {
3651
- const possibilities = getRollupPossibilities({ tagType: block.props.tagType, allTpls });
3662
+ const possibilities = getRollupPossibilities({ tagType: block.props.tagType, allTpls, includeSelfHead: true });
3652
3663
  return possibilities.map((p) => ({
3653
3664
  ...p,
3654
3665
  filterType: p.rollupPath ? "nestedRollupTagType" : "rollupValuePathType"
@@ -3981,13 +3992,16 @@ var buildTagTypeParentMap = (tagTypesInGroup, allTpls) => {
3981
3992
  const tagBlocks = blocks.filter(
3982
3993
  (block) => block.valuePath?.startsWith("tags.") && block.props?.tagType
3983
3994
  );
3995
+ const referencedTagTypes = /* @__PURE__ */ new Set();
3984
3996
  for (const block of tagBlocks) {
3985
3997
  const referencedTagType = block.props.tagType;
3986
3998
  if (tagTypeSet.has(referencedTagType) && referencedTagType !== tagType) {
3987
- parentMap.set(tagType, referencedTagType);
3988
- break;
3999
+ referencedTagTypes.add(referencedTagType);
3989
4000
  }
3990
4001
  }
4002
+ if (referencedTagTypes.size === 1) {
4003
+ parentMap.set(tagType, [...referencedTagTypes][0]);
4004
+ }
3991
4005
  }
3992
4006
  for (const child of parentMap.keys()) {
3993
4007
  const visited = /* @__PURE__ */ new Set();
@@ -4061,6 +4075,34 @@ var sortFiltersHierarchically = (filters) => {
4061
4075
  return sorted;
4062
4076
  };
4063
4077
 
4078
+ // src/utils/autoGenFilterConfigsFromTpl/utils/deduplicateRollupTagFilters.ts
4079
+ var deduplicateRollupTagFilters = (rollups) => {
4080
+ const tagTerminals = [];
4081
+ const nonTag = [];
4082
+ for (const r of rollups) {
4083
+ const rp = r.target?.rollupPath;
4084
+ if (rp?.length && !rp[rp.length - 1].startsWith("main.")) {
4085
+ tagTerminals.push(r);
4086
+ } else {
4087
+ nonTag.push({ ...r, isTagRollup: false });
4088
+ }
4089
+ }
4090
+ if (tagTerminals.length === 0) return nonTag;
4091
+ const byTerminal = /* @__PURE__ */ new Map();
4092
+ for (const r of tagTerminals) {
4093
+ const terminal = r.target.rollupPath[r.target.rollupPath.length - 1];
4094
+ const existing = byTerminal.get(terminal);
4095
+ if (!existing || r.target.rollupPath.length < existing.target.rollupPath.length) {
4096
+ byTerminal.set(terminal, r);
4097
+ }
4098
+ }
4099
+ const dedupedTags = [...byTerminal.values()].map((r) => ({
4100
+ ...r,
4101
+ isTagRollup: true
4102
+ }));
4103
+ return [...nonTag, ...dedupedTags];
4104
+ };
4105
+
4064
4106
  // src/utils/autoGenFilterConfigsFromTpl/utils/_self_managed_buildDocHierarchyConfig.ts
4065
4107
  var injectFilterOptionsBy = (filters) => filters.map(
4066
4108
  (f) => f.parentFilterId ? { ...f, source: { ...f.source, filterOptionsBy: { filterId: f.parentFilterId } } } : f
@@ -4167,24 +4209,34 @@ var _self_managed_buildDocHierarchyConfig = ({
4167
4209
  const dedupedFilters = filtersWithCommonFlag.filter(
4168
4210
  (f) => !rollupSourceKeys.has(JSON.stringify(f.source))
4169
4211
  );
4170
- const combined = [...dedupedFilters, ...rollupConfigs];
4212
+ const dedupedRollupConfigs = deduplicateRollupTagFilters(rollupConfigs);
4213
+ const combined = [...dedupedFilters, ...dedupedRollupConfigs];
4171
4214
  const combinedWithParents = injectFilterOptionsBy(
4172
4215
  sortFiltersHierarchically(
4173
4216
  attachParentFields(combined, allTpls)
4174
4217
  )
4175
4218
  );
4176
- const rollupFilterIds = new Set(rollupConfigs.map((r) => r.filterId));
4219
+ const rollupFilterIds = new Set(dedupedRollupConfigs.map((r) => r.filterId));
4177
4220
  const filtersWithParents = combinedWithParents.filter(
4178
4221
  (f) => !rollupFilterIds.has(f.filterId)
4179
4222
  );
4180
4223
  const rollupsWithParents = combinedWithParents.filter(
4181
4224
  (f) => rollupFilterIds.has(f.filterId)
4182
4225
  );
4226
+ const rollupContentTypes = new Set(
4227
+ rollupsWithParents.filter((r) => r.target?.rollupPath).flatMap((r) => r.target.rollupPath)
4228
+ );
4229
+ const rollupDisplayMap = {};
4230
+ for (const ct of rollupContentTypes) {
4231
+ const t = allTpls.find((tp) => tp.kp_content_type === ct);
4232
+ if (t?.general?.content?.title) rollupDisplayMap[ct] = t.general.content.title;
4233
+ }
4183
4234
  return {
4184
4235
  contentType: tpl.kp_content_type,
4185
4236
  display: tplData?.general?.content?.title || tpl.kp_content_type,
4186
4237
  filters: filtersWithParents,
4187
- rollups: rollupsWithParents
4238
+ rollups: rollupsWithParents,
4239
+ rollupDisplayMap
4188
4240
  };
4189
4241
  });
4190
4242
  const filteredPerDataset = perDataset.filter(
@@ -285,9 +285,10 @@ declare const collectMarkIdsInOrder: (editorState: any) => string[];
285
285
  * }
286
286
  * ]
287
287
  */
288
- declare function getRollupPossibilities({ tagType, allTpls }: {
288
+ declare function getRollupPossibilities({ tagType, allTpls, includeSelfHead, }: {
289
289
  tagType: string;
290
290
  allTpls: any[];
291
+ includeSelfHead?: boolean;
291
292
  }): any[];
292
293
 
293
294
  declare namespace BASE_BULLMQ_CONFIG {
@@ -1241,6 +1242,27 @@ declare const processAuthorAndCommonFilters: (allTpls: any[], filterScopes: stri
1241
1242
 
1242
1243
  declare const _self_managed_getFixedAnnoTagBlock: (selectedTpls: any[], annotationTagsCount: any) => any[];
1243
1244
 
1245
+ /**
1246
+ * FOLLOWUP (consolidate the count->rollupPath rule into one source of truth):
1247
+ *
1248
+ * The rule "given annotationTagsCount, which self-managed anno rollupPaths exist"
1249
+ * (subThemes>0 -> ['tags','subThemes']; subThemes>0 && themes>0 -> ['tags','subThemes','themes'])
1250
+ * is currently duplicated in THREE places and will drift:
1251
+ * 1. here (_self_managed_getFixedAnnoRollupBlocks) -> filter blocks
1252
+ * 2. _self_managed_buildAnnoHierarchyConfig -> anno hierarchy filter UI
1253
+ * 3. okf-fe _extractAllAnnoBasedDimensionsAsOptions.js -> reports dimension dropdown
1254
+ *
1255
+ * (#3 was added to fix a crash: the reports widget previously discovered these rollups
1256
+ * from publishing-segment tpls via getRollupPossibilities, but self-managed taxonomy lives
1257
+ * on `collections`-segment tpls which isTplAnnotationEnabled excludes -> empty list ->
1258
+ * unguarded .find('subThemes') returned undefined -> crash. The FE now builds them from the
1259
+ * count, mirroring this function.)
1260
+ *
1261
+ * Extract a pure helper here in ootils:
1262
+ * export const getSelfManagedAnnoRollupPaths = (annotationTagsCount): string[][] => [...]
1263
+ * then have all three call sites consume it (each maps paths -> its own shape:
1264
+ * filter-blocks / hierarchy levels / dropdown options). One rule, three presentations.
1265
+ */
1244
1266
  declare const _self_managed_getFixedAnnoRollupBlocks: ({ selectedTpls, allTpls, annotationTagsCount }: {
1245
1267
  selectedTpls: any[];
1246
1268
  allTpls: any[];
@@ -1342,6 +1364,7 @@ declare const _self_managed_buildDocHierarchyConfig: ({ combinedDocumentBlocks,
1342
1364
  display: any;
1343
1365
  filters: any[];
1344
1366
  rollups: any[];
1367
+ rollupDisplayMap: Record<string, string>;
1345
1368
  }[];
1346
1369
  };
1347
1370
  target: {
@@ -1501,6 +1524,7 @@ declare const autoGenFilterConfigsFromTpl: ({ selectedTpls, allTpls, filterScope
1501
1524
  display: any;
1502
1525
  filters: any[];
1503
1526
  rollups: any[];
1527
+ rollupDisplayMap: Record<string, string>;
1504
1528
  }[];
1505
1529
  };
1506
1530
  target: {
@@ -285,9 +285,10 @@ declare const collectMarkIdsInOrder: (editorState: any) => string[];
285
285
  * }
286
286
  * ]
287
287
  */
288
- declare function getRollupPossibilities({ tagType, allTpls }: {
288
+ declare function getRollupPossibilities({ tagType, allTpls, includeSelfHead, }: {
289
289
  tagType: string;
290
290
  allTpls: any[];
291
+ includeSelfHead?: boolean;
291
292
  }): any[];
292
293
 
293
294
  declare namespace BASE_BULLMQ_CONFIG {
@@ -1241,6 +1242,27 @@ declare const processAuthorAndCommonFilters: (allTpls: any[], filterScopes: stri
1241
1242
 
1242
1243
  declare const _self_managed_getFixedAnnoTagBlock: (selectedTpls: any[], annotationTagsCount: any) => any[];
1243
1244
 
1245
+ /**
1246
+ * FOLLOWUP (consolidate the count->rollupPath rule into one source of truth):
1247
+ *
1248
+ * The rule "given annotationTagsCount, which self-managed anno rollupPaths exist"
1249
+ * (subThemes>0 -> ['tags','subThemes']; subThemes>0 && themes>0 -> ['tags','subThemes','themes'])
1250
+ * is currently duplicated in THREE places and will drift:
1251
+ * 1. here (_self_managed_getFixedAnnoRollupBlocks) -> filter blocks
1252
+ * 2. _self_managed_buildAnnoHierarchyConfig -> anno hierarchy filter UI
1253
+ * 3. okf-fe _extractAllAnnoBasedDimensionsAsOptions.js -> reports dimension dropdown
1254
+ *
1255
+ * (#3 was added to fix a crash: the reports widget previously discovered these rollups
1256
+ * from publishing-segment tpls via getRollupPossibilities, but self-managed taxonomy lives
1257
+ * on `collections`-segment tpls which isTplAnnotationEnabled excludes -> empty list ->
1258
+ * unguarded .find('subThemes') returned undefined -> crash. The FE now builds them from the
1259
+ * count, mirroring this function.)
1260
+ *
1261
+ * Extract a pure helper here in ootils:
1262
+ * export const getSelfManagedAnnoRollupPaths = (annotationTagsCount): string[][] => [...]
1263
+ * then have all three call sites consume it (each maps paths -> its own shape:
1264
+ * filter-blocks / hierarchy levels / dropdown options). One rule, three presentations.
1265
+ */
1244
1266
  declare const _self_managed_getFixedAnnoRollupBlocks: ({ selectedTpls, allTpls, annotationTagsCount }: {
1245
1267
  selectedTpls: any[];
1246
1268
  allTpls: any[];
@@ -1342,6 +1364,7 @@ declare const _self_managed_buildDocHierarchyConfig: ({ combinedDocumentBlocks,
1342
1364
  display: any;
1343
1365
  filters: any[];
1344
1366
  rollups: any[];
1367
+ rollupDisplayMap: Record<string, string>;
1345
1368
  }[];
1346
1369
  };
1347
1370
  target: {
@@ -1501,6 +1524,7 @@ declare const autoGenFilterConfigsFromTpl: ({ selectedTpls, allTpls, filterScope
1501
1524
  display: any;
1502
1525
  filters: any[];
1503
1526
  rollups: any[];
1527
+ rollupDisplayMap: Record<string, string>;
1504
1528
  }[];
1505
1529
  };
1506
1530
  target: {
package/dist/universal.js CHANGED
@@ -722,7 +722,8 @@ var collectMarkIdsInOrder = (editorState) => {
722
722
  var MAX_DEPTH_ROLLUP_POSSIBILITIES = 10;
723
723
  function getRollupPossibilities({
724
724
  tagType,
725
- allTpls
725
+ allTpls,
726
+ includeSelfHead = false
726
727
  }) {
727
728
  const thisTagTpl = allTpls.find((d) => d.kp_content_type === tagType);
728
729
  if (!thisTagTpl) return [];
@@ -754,7 +755,8 @@ function getRollupPossibilities({
754
755
  chains.push({
755
756
  rollupType: "tagType",
756
757
  tagTypeCollectionToRollup: tagType,
757
- rollupPath: [...visited, startTagType, nextTagType]
758
+ rollupPath: [...visited, startTagType, nextTagType],
759
+ filterDisplay: block.props?.shortLabel || block.props?.label
758
760
  });
759
761
  if (visited.length < maxDepth - 1) {
760
762
  const nextChains = findTagChains(
@@ -800,7 +802,8 @@ function getRollupPossibilities({
800
802
  const directChain = {
801
803
  rollupType: "tagType",
802
804
  tagTypeCollectionToRollup: tagType,
803
- rollupPath: [tagType, block.props.tagType]
805
+ rollupPath: [tagType, block.props.tagType],
806
+ filterDisplay: block.props?.shortLabel || block.props?.label
804
807
  };
805
808
  const deeperChains = findTagChains(
806
809
  block.props?.tagType,
@@ -809,7 +812,14 @@ function getRollupPossibilities({
809
812
  );
810
813
  return [directChain, ...deeperChains];
811
814
  });
812
- return [...singleLevelValuePathRollups, ...nestedTagRollups];
815
+ const selfHeadRollup = includeSelfHead && nestedTagRollups.length > 0 && singleLevelValuePathRollups.length === 0 ? [
816
+ {
817
+ rollupType: "tagType",
818
+ tagTypeCollectionToRollup: tagType,
819
+ rollupPath: [tagType]
820
+ }
821
+ ] : [];
822
+ return [...singleLevelValuePathRollups, ...selfHeadRollup, ...nestedTagRollups];
813
823
  }
814
824
 
815
825
  // src/bullmq/GLOBAL_BULLMQ_CONFIG.js
@@ -1714,6 +1724,7 @@ var buildFilterConfigurations = ({ groups, type, selectedTpls, allTpls, isRollup
1714
1724
  if (isTerminalValuePath) {
1715
1725
  return element.filterDisplay || lastItemInPath;
1716
1726
  }
1727
+ if (element.filterDisplay) return element.filterDisplay;
1717
1728
  const lastTag = rollupPath[rollupPath.length - 1];
1718
1729
  const lastTagTpl = allTpls.find(
1719
1730
  (tpl) => tpl.kp_content_type === lastTag
@@ -1980,7 +1991,7 @@ var extractAndOrganizeBlocks = (selectedTpls, allTpls, { smTagTypesConfig } = {}
1980
1991
  return {
1981
1992
  contentType: tpl.kp_content_type,
1982
1993
  blocks: allBlocks.filter((block) => block.valuePath.startsWith("tags.") && ["TagsInputSingle", "TagsInputMulti"].includes(block.comp)).flatMap((block) => {
1983
- const possibilities = getRollupPossibilities({ tagType: block.props.tagType, allTpls });
1994
+ const possibilities = getRollupPossibilities({ tagType: block.props.tagType, allTpls, includeSelfHead: true });
1984
1995
  return possibilities.map((p) => ({
1985
1996
  ...p,
1986
1997
  filterType: p.rollupPath ? "nestedRollupTagType" : "rollupValuePathType"
@@ -2313,13 +2324,16 @@ var buildTagTypeParentMap = (tagTypesInGroup, allTpls) => {
2313
2324
  const tagBlocks = blocks.filter(
2314
2325
  (block) => block.valuePath?.startsWith("tags.") && block.props?.tagType
2315
2326
  );
2327
+ const referencedTagTypes = /* @__PURE__ */ new Set();
2316
2328
  for (const block of tagBlocks) {
2317
2329
  const referencedTagType = block.props.tagType;
2318
2330
  if (tagTypeSet.has(referencedTagType) && referencedTagType !== tagType) {
2319
- parentMap.set(tagType, referencedTagType);
2320
- break;
2331
+ referencedTagTypes.add(referencedTagType);
2321
2332
  }
2322
2333
  }
2334
+ if (referencedTagTypes.size === 1) {
2335
+ parentMap.set(tagType, [...referencedTagTypes][0]);
2336
+ }
2323
2337
  }
2324
2338
  for (const child of parentMap.keys()) {
2325
2339
  const visited = /* @__PURE__ */ new Set();
@@ -2393,6 +2407,34 @@ var sortFiltersHierarchically = (filters) => {
2393
2407
  return sorted;
2394
2408
  };
2395
2409
 
2410
+ // src/utils/autoGenFilterConfigsFromTpl/utils/deduplicateRollupTagFilters.ts
2411
+ var deduplicateRollupTagFilters = (rollups) => {
2412
+ const tagTerminals = [];
2413
+ const nonTag = [];
2414
+ for (const r of rollups) {
2415
+ const rp = r.target?.rollupPath;
2416
+ if (rp?.length && !rp[rp.length - 1].startsWith("main.")) {
2417
+ tagTerminals.push(r);
2418
+ } else {
2419
+ nonTag.push({ ...r, isTagRollup: false });
2420
+ }
2421
+ }
2422
+ if (tagTerminals.length === 0) return nonTag;
2423
+ const byTerminal = /* @__PURE__ */ new Map();
2424
+ for (const r of tagTerminals) {
2425
+ const terminal = r.target.rollupPath[r.target.rollupPath.length - 1];
2426
+ const existing = byTerminal.get(terminal);
2427
+ if (!existing || r.target.rollupPath.length < existing.target.rollupPath.length) {
2428
+ byTerminal.set(terminal, r);
2429
+ }
2430
+ }
2431
+ const dedupedTags = [...byTerminal.values()].map((r) => ({
2432
+ ...r,
2433
+ isTagRollup: true
2434
+ }));
2435
+ return [...nonTag, ...dedupedTags];
2436
+ };
2437
+
2396
2438
  // src/utils/autoGenFilterConfigsFromTpl/utils/_self_managed_buildDocHierarchyConfig.ts
2397
2439
  var injectFilterOptionsBy = (filters) => filters.map(
2398
2440
  (f) => f.parentFilterId ? { ...f, source: { ...f.source, filterOptionsBy: { filterId: f.parentFilterId } } } : f
@@ -2499,24 +2541,34 @@ var _self_managed_buildDocHierarchyConfig = ({
2499
2541
  const dedupedFilters = filtersWithCommonFlag.filter(
2500
2542
  (f) => !rollupSourceKeys.has(JSON.stringify(f.source))
2501
2543
  );
2502
- const combined = [...dedupedFilters, ...rollupConfigs];
2544
+ const dedupedRollupConfigs = deduplicateRollupTagFilters(rollupConfigs);
2545
+ const combined = [...dedupedFilters, ...dedupedRollupConfigs];
2503
2546
  const combinedWithParents = injectFilterOptionsBy(
2504
2547
  sortFiltersHierarchically(
2505
2548
  attachParentFields(combined, allTpls)
2506
2549
  )
2507
2550
  );
2508
- const rollupFilterIds = new Set(rollupConfigs.map((r) => r.filterId));
2551
+ const rollupFilterIds = new Set(dedupedRollupConfigs.map((r) => r.filterId));
2509
2552
  const filtersWithParents = combinedWithParents.filter(
2510
2553
  (f) => !rollupFilterIds.has(f.filterId)
2511
2554
  );
2512
2555
  const rollupsWithParents = combinedWithParents.filter(
2513
2556
  (f) => rollupFilterIds.has(f.filterId)
2514
2557
  );
2558
+ const rollupContentTypes = new Set(
2559
+ rollupsWithParents.filter((r) => r.target?.rollupPath).flatMap((r) => r.target.rollupPath)
2560
+ );
2561
+ const rollupDisplayMap = {};
2562
+ for (const ct of rollupContentTypes) {
2563
+ const t = allTpls.find((tp) => tp.kp_content_type === ct);
2564
+ if (t?.general?.content?.title) rollupDisplayMap[ct] = t.general.content.title;
2565
+ }
2515
2566
  return {
2516
2567
  contentType: tpl.kp_content_type,
2517
2568
  display: tplData?.general?.content?.title || tpl.kp_content_type,
2518
2569
  filters: filtersWithParents,
2519
- rollups: rollupsWithParents
2570
+ rollups: rollupsWithParents,
2571
+ rollupDisplayMap
2520
2572
  };
2521
2573
  });
2522
2574
  const filteredPerDataset = perDataset.filter(
@@ -652,7 +652,8 @@ var collectMarkIdsInOrder = (editorState) => {
652
652
  var MAX_DEPTH_ROLLUP_POSSIBILITIES = 10;
653
653
  function getRollupPossibilities({
654
654
  tagType,
655
- allTpls
655
+ allTpls,
656
+ includeSelfHead = false
656
657
  }) {
657
658
  const thisTagTpl = allTpls.find((d) => d.kp_content_type === tagType);
658
659
  if (!thisTagTpl) return [];
@@ -684,7 +685,8 @@ function getRollupPossibilities({
684
685
  chains.push({
685
686
  rollupType: "tagType",
686
687
  tagTypeCollectionToRollup: tagType,
687
- rollupPath: [...visited, startTagType, nextTagType]
688
+ rollupPath: [...visited, startTagType, nextTagType],
689
+ filterDisplay: block.props?.shortLabel || block.props?.label
688
690
  });
689
691
  if (visited.length < maxDepth - 1) {
690
692
  const nextChains = findTagChains(
@@ -730,7 +732,8 @@ function getRollupPossibilities({
730
732
  const directChain = {
731
733
  rollupType: "tagType",
732
734
  tagTypeCollectionToRollup: tagType,
733
- rollupPath: [tagType, block.props.tagType]
735
+ rollupPath: [tagType, block.props.tagType],
736
+ filterDisplay: block.props?.shortLabel || block.props?.label
734
737
  };
735
738
  const deeperChains = findTagChains(
736
739
  block.props?.tagType,
@@ -739,7 +742,14 @@ function getRollupPossibilities({
739
742
  );
740
743
  return [directChain, ...deeperChains];
741
744
  });
742
- return [...singleLevelValuePathRollups, ...nestedTagRollups];
745
+ const selfHeadRollup = includeSelfHead && nestedTagRollups.length > 0 && singleLevelValuePathRollups.length === 0 ? [
746
+ {
747
+ rollupType: "tagType",
748
+ tagTypeCollectionToRollup: tagType,
749
+ rollupPath: [tagType]
750
+ }
751
+ ] : [];
752
+ return [...singleLevelValuePathRollups, ...selfHeadRollup, ...nestedTagRollups];
743
753
  }
744
754
 
745
755
  // src/bullmq/GLOBAL_BULLMQ_CONFIG.js
@@ -1644,6 +1654,7 @@ var buildFilterConfigurations = ({ groups, type, selectedTpls, allTpls, isRollup
1644
1654
  if (isTerminalValuePath) {
1645
1655
  return element.filterDisplay || lastItemInPath;
1646
1656
  }
1657
+ if (element.filterDisplay) return element.filterDisplay;
1647
1658
  const lastTag = rollupPath[rollupPath.length - 1];
1648
1659
  const lastTagTpl = allTpls.find(
1649
1660
  (tpl) => tpl.kp_content_type === lastTag
@@ -1910,7 +1921,7 @@ var extractAndOrganizeBlocks = (selectedTpls, allTpls, { smTagTypesConfig } = {}
1910
1921
  return {
1911
1922
  contentType: tpl.kp_content_type,
1912
1923
  blocks: allBlocks.filter((block) => block.valuePath.startsWith("tags.") && ["TagsInputSingle", "TagsInputMulti"].includes(block.comp)).flatMap((block) => {
1913
- const possibilities = getRollupPossibilities({ tagType: block.props.tagType, allTpls });
1924
+ const possibilities = getRollupPossibilities({ tagType: block.props.tagType, allTpls, includeSelfHead: true });
1914
1925
  return possibilities.map((p) => ({
1915
1926
  ...p,
1916
1927
  filterType: p.rollupPath ? "nestedRollupTagType" : "rollupValuePathType"
@@ -2243,13 +2254,16 @@ var buildTagTypeParentMap = (tagTypesInGroup, allTpls) => {
2243
2254
  const tagBlocks = blocks.filter(
2244
2255
  (block) => block.valuePath?.startsWith("tags.") && block.props?.tagType
2245
2256
  );
2257
+ const referencedTagTypes = /* @__PURE__ */ new Set();
2246
2258
  for (const block of tagBlocks) {
2247
2259
  const referencedTagType = block.props.tagType;
2248
2260
  if (tagTypeSet.has(referencedTagType) && referencedTagType !== tagType) {
2249
- parentMap.set(tagType, referencedTagType);
2250
- break;
2261
+ referencedTagTypes.add(referencedTagType);
2251
2262
  }
2252
2263
  }
2264
+ if (referencedTagTypes.size === 1) {
2265
+ parentMap.set(tagType, [...referencedTagTypes][0]);
2266
+ }
2253
2267
  }
2254
2268
  for (const child of parentMap.keys()) {
2255
2269
  const visited = /* @__PURE__ */ new Set();
@@ -2323,6 +2337,34 @@ var sortFiltersHierarchically = (filters) => {
2323
2337
  return sorted;
2324
2338
  };
2325
2339
 
2340
+ // src/utils/autoGenFilterConfigsFromTpl/utils/deduplicateRollupTagFilters.ts
2341
+ var deduplicateRollupTagFilters = (rollups) => {
2342
+ const tagTerminals = [];
2343
+ const nonTag = [];
2344
+ for (const r of rollups) {
2345
+ const rp = r.target?.rollupPath;
2346
+ if (rp?.length && !rp[rp.length - 1].startsWith("main.")) {
2347
+ tagTerminals.push(r);
2348
+ } else {
2349
+ nonTag.push({ ...r, isTagRollup: false });
2350
+ }
2351
+ }
2352
+ if (tagTerminals.length === 0) return nonTag;
2353
+ const byTerminal = /* @__PURE__ */ new Map();
2354
+ for (const r of tagTerminals) {
2355
+ const terminal = r.target.rollupPath[r.target.rollupPath.length - 1];
2356
+ const existing = byTerminal.get(terminal);
2357
+ if (!existing || r.target.rollupPath.length < existing.target.rollupPath.length) {
2358
+ byTerminal.set(terminal, r);
2359
+ }
2360
+ }
2361
+ const dedupedTags = [...byTerminal.values()].map((r) => ({
2362
+ ...r,
2363
+ isTagRollup: true
2364
+ }));
2365
+ return [...nonTag, ...dedupedTags];
2366
+ };
2367
+
2326
2368
  // src/utils/autoGenFilterConfigsFromTpl/utils/_self_managed_buildDocHierarchyConfig.ts
2327
2369
  var injectFilterOptionsBy = (filters) => filters.map(
2328
2370
  (f) => f.parentFilterId ? { ...f, source: { ...f.source, filterOptionsBy: { filterId: f.parentFilterId } } } : f
@@ -2429,24 +2471,34 @@ var _self_managed_buildDocHierarchyConfig = ({
2429
2471
  const dedupedFilters = filtersWithCommonFlag.filter(
2430
2472
  (f) => !rollupSourceKeys.has(JSON.stringify(f.source))
2431
2473
  );
2432
- const combined = [...dedupedFilters, ...rollupConfigs];
2474
+ const dedupedRollupConfigs = deduplicateRollupTagFilters(rollupConfigs);
2475
+ const combined = [...dedupedFilters, ...dedupedRollupConfigs];
2433
2476
  const combinedWithParents = injectFilterOptionsBy(
2434
2477
  sortFiltersHierarchically(
2435
2478
  attachParentFields(combined, allTpls)
2436
2479
  )
2437
2480
  );
2438
- const rollupFilterIds = new Set(rollupConfigs.map((r) => r.filterId));
2481
+ const rollupFilterIds = new Set(dedupedRollupConfigs.map((r) => r.filterId));
2439
2482
  const filtersWithParents = combinedWithParents.filter(
2440
2483
  (f) => !rollupFilterIds.has(f.filterId)
2441
2484
  );
2442
2485
  const rollupsWithParents = combinedWithParents.filter(
2443
2486
  (f) => rollupFilterIds.has(f.filterId)
2444
2487
  );
2488
+ const rollupContentTypes = new Set(
2489
+ rollupsWithParents.filter((r) => r.target?.rollupPath).flatMap((r) => r.target.rollupPath)
2490
+ );
2491
+ const rollupDisplayMap = {};
2492
+ for (const ct of rollupContentTypes) {
2493
+ const t = allTpls.find((tp) => tp.kp_content_type === ct);
2494
+ if (t?.general?.content?.title) rollupDisplayMap[ct] = t.general.content.title;
2495
+ }
2445
2496
  return {
2446
2497
  contentType: tpl.kp_content_type,
2447
2498
  display: tplData?.general?.content?.title || tpl.kp_content_type,
2448
2499
  filters: filtersWithParents,
2449
- rollups: rollupsWithParents
2500
+ rollups: rollupsWithParents,
2501
+ rollupDisplayMap
2450
2502
  };
2451
2503
  });
2452
2504
  const filteredPerDataset = perDataset.filter(
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.40.0",
6
+ "version": "1.41.0",
7
7
  "description": "Utility functions for both browser and Node.js",
8
8
  "main": "dist/index.js",
9
9
  "module": "dist/index.mjs",