@platforma-sdk/model 1.80.17 → 1.81.1
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/columns/column.cjs +9 -6
- package/dist/columns/column.cjs.map +1 -1
- package/dist/columns/column.d.ts +5 -5
- package/dist/columns/column.d.ts.map +1 -1
- package/dist/columns/column.js +10 -7
- package/dist/columns/column.js.map +1 -1
- package/dist/columns/column_providers/index.cjs.map +1 -1
- package/dist/columns/column_providers/index.d.ts.map +1 -1
- package/dist/columns/column_providers/index.js.map +1 -1
- package/dist/columns/column_providers/providers.cjs +5 -5
- package/dist/columns/column_providers/providers.cjs.map +1 -1
- package/dist/columns/column_providers/providers.d.ts +8 -8
- package/dist/columns/column_providers/providers.d.ts.map +1 -1
- package/dist/columns/column_providers/providers.js +5 -5
- package/dist/columns/column_providers/providers.js.map +1 -1
- package/dist/columns/column_providers/types.d.ts +3 -3
- package/dist/columns/column_providers/types.d.ts.map +1 -1
- package/dist/columns/column_recipes/column_discovered_recipe.cjs +1 -1
- package/dist/columns/column_recipes/column_discovered_recipe.cjs.map +1 -1
- package/dist/columns/column_recipes/column_discovered_recipe.d.ts +1 -1
- package/dist/columns/column_recipes/column_discovered_recipe.js +1 -1
- package/dist/columns/column_recipes/column_discovered_recipe.js.map +1 -1
- package/dist/columns/column_recipes/column_overrided_recipe.cjs +47 -2
- package/dist/columns/column_recipes/column_overrided_recipe.cjs.map +1 -1
- package/dist/columns/column_recipes/column_overrided_recipe.d.ts +30 -3
- package/dist/columns/column_recipes/column_overrided_recipe.d.ts.map +1 -1
- package/dist/columns/column_recipes/column_overrided_recipe.js +47 -3
- package/dist/columns/column_recipes/column_overrided_recipe.js.map +1 -1
- package/dist/columns/column_recipes/index.cjs +4 -14
- package/dist/columns/column_recipes/index.cjs.map +1 -1
- package/dist/columns/column_recipes/index.d.ts +3 -10
- package/dist/columns/column_recipes/index.d.ts.map +1 -1
- package/dist/columns/column_recipes/index.js +5 -14
- package/dist/columns/column_recipes/index.js.map +1 -1
- package/dist/columns/{column_lazy.cjs → data_column.cjs} +57 -54
- package/dist/columns/data_column.cjs.map +1 -0
- package/dist/columns/data_column.d.ts +152 -0
- package/dist/columns/data_column.d.ts.map +1 -0
- package/dist/columns/{column_lazy.js → data_column.js} +55 -52
- package/dist/columns/data_column.js.map +1 -0
- package/dist/columns/derive_axis_values_labels.cjs +4 -4
- package/dist/columns/derive_axis_values_labels.cjs.map +1 -1
- package/dist/columns/derive_axis_values_labels.d.ts +2 -2
- package/dist/columns/derive_axis_values_labels.js +4 -4
- package/dist/columns/derive_axis_values_labels.js.map +1 -1
- package/dist/columns/index.cjs +9 -9
- package/dist/columns/index.d.ts +5 -5
- package/dist/columns/index.js +5 -5
- package/dist/columns/{expand_by_partition.cjs → split_by_axes.cjs} +13 -8
- package/dist/columns/split_by_axes.cjs.map +1 -0
- package/dist/columns/{expand_by_partition.d.ts → split_by_axes.d.ts} +18 -8
- package/dist/columns/split_by_axes.d.ts.map +1 -0
- package/dist/columns/{expand_by_partition.js → split_by_axes.js} +14 -9
- package/dist/columns/split_by_axes.js.map +1 -0
- package/dist/columns/utils.cjs +50 -43
- package/dist/columns/utils.cjs.map +1 -1
- package/dist/columns/utils.d.ts +44 -19
- package/dist/columns/utils.d.ts.map +1 -1
- package/dist/columns/utils.js +50 -44
- package/dist/columns/utils.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs +3 -3
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js +3 -3
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs +2 -2
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js +2 -2
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +2 -2
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs +1 -1
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js +2 -2
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/utils.cjs +1 -1
- package/dist/components/PlDataTable/createPlDataTable/utils.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/utils.js +1 -1
- package/dist/components/PlDataTable/createPlDataTable/utils.js.map +1 -1
- package/dist/components/PlDatasetSelector/enrichment_discovery.cjs +1 -1
- package/dist/components/PlDatasetSelector/enrichment_discovery.cjs.map +1 -1
- package/dist/components/PlDatasetSelector/enrichment_discovery.js +2 -2
- package/dist/components/PlDatasetSelector/enrichment_discovery.js.map +1 -1
- package/dist/index.cjs +9 -9
- package/dist/index.d.ts +5 -5
- package/dist/index.js +5 -5
- package/dist/package.cjs +1 -1
- package/dist/package.js +1 -1
- package/package.json +8 -8
- package/src/columns/__test_helpers__/collection_driver.ts +6 -6
- package/src/columns/__test_helpers__/stub_registry.ts +4 -6
- package/src/columns/column.ts +20 -9
- package/src/columns/column_providers/index.ts +9 -3
- package/src/columns/column_providers/providers.ts +16 -15
- package/src/columns/column_providers/types.ts +3 -3
- package/src/columns/column_recipes/column_discovered_recipe.ts +1 -1
- package/src/columns/column_recipes/column_overrided_recipe.ts +58 -4
- package/src/columns/column_recipes/column_recipes.test.ts +2 -2
- package/src/columns/column_recipes/index.ts +5 -20
- package/src/columns/{column_lazy.test.ts → data_column.test.ts} +19 -19
- package/src/columns/{column_lazy.ts → data_column.ts} +105 -67
- package/src/columns/derive_axis_values_labels.ts +4 -4
- package/src/columns/index.ts +2 -2
- package/src/columns/predicates.test.ts +124 -0
- package/src/columns/{expand_by_partition.test.ts → split_by_axes.test.ts} +29 -21
- package/src/columns/{expand_by_partition.ts → split_by_axes.ts} +22 -9
- package/src/columns/utils.ts +53 -48
- package/src/components/PlDataTable/columnResolver.test.ts +3 -3
- package/src/components/PlDataTable/createPlDataTable/createPTableDefV2.ts +3 -3
- package/src/components/PlDataTable/createPlDataTable/createPlDataTableV2.ts +2 -2
- package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +2 -2
- package/src/components/PlDataTable/createPlDataTable/discoverColumns.ts +2 -2
- package/src/components/PlDataTable/createPlDataTable/utils.test.ts +34 -3
- package/src/components/PlDataTable/createPlDataTable/utils.ts +4 -1
- package/src/components/PlDatasetSelector/enrichment_discovery.ts +2 -2
- package/dist/columns/column_lazy.cjs.map +0 -1
- package/dist/columns/column_lazy.d.ts +0 -137
- package/dist/columns/column_lazy.d.ts.map +0 -1
- package/dist/columns/column_lazy.js.map +0 -1
- package/dist/columns/expand_by_partition.cjs.map +0 -1
- package/dist/columns/expand_by_partition.d.ts.map +0 -1
- package/dist/columns/expand_by_partition.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createPlDataTableV2.js","names":[],"sources":["../../../../src/components/PlDataTable/createPlDataTable/createPlDataTableV2.ts"],"sourcesContent":["import type {\n ColumnUniversalId,\n FilterSpecNode,\n PColumn,\n PTableColumnIdColumn,\n PTableSorting,\n} from \"@milaboratories/pl-model-common\";\nimport {\n Annotation,\n getColumnIdAndSpec,\n isLinkerColumn,\n PColumnName,\n} from \"@milaboratories/pl-model-common\";\nimport type {\n AxisLabelProvider,\n ColumnProvider,\n PColumnDataUniversal,\n RenderCtxBase,\n} from \"../../../render\";\nimport { allPColumnsReady, deriveLabels, PColumnCollection } from \"../../../render\";\nimport { identity } from \"es-toolkit\";\nimport type {\n CreatePlDataTableOps,\n PlDataTableFilters,\n PlDataTableFilterSpecLeaf,\n PlDataTableModel,\n} from \"../typesV8\";\nimport { upgradePlDataTableStateV2 } from \"../state-migration\";\nimport type { PlDataTableStateV2 } from \"../state-migration\";\nimport { getMatchingLabelColumns } from \"../labels\";\nimport { collectFilterSpecColumns, traverseFilterSpec } from \"../../../filters/traverse\";\nimport { createPTableDefV2 } from \"./createPTableDefV2\";\nimport { isColumnOptional } from \"./utils\";\nimport { ColumnLazyImpl } from \"../../../columns\";\nimport { createColumnResolver, type ColumnResolver } from \"../columnResolver\";\nimport { isNil, type Nil } from \"@milaboratories/helpers\";\n\n/**\n * @deprecated This function is deprecated and will be removed in future. Please migrate to createPlDataTable with v3 options for improved column discovery and display configuration. See createPlDataTableOptionsV3 for details on the new options format and migration guidance.\n */\nexport type createPlDataTableOptionsV2 = {\n columns: PColumn<PColumnDataUniversal>[];\n tableState?: PlDataTableStateV2;\n options?: CreatePlDataTableOps;\n};\n\n/**\n * Create p-table spec and handle given ui table state\n *\n * @deprecated This version of createPlDataTable is deprecated and will be removed in future. Please migrate to v3 by switching to the new options format and providing necessary information for column discovery and display configuration. See createPlDataTableOptionsV3 for details.\n * @param ctx context\n * @param columns column list\n * @param tableState table ui state\n * @returns PlAgDataTableV2 table source\n */\nexport function createPlDataTableV2<A, U>(\n ctx: RenderCtxBase<A, U>,\n columns: createPlDataTableOptionsV2[\"columns\"],\n tableState?: createPlDataTableOptionsV2[\"tableState\"],\n options?: createPlDataTableOptionsV2[\"options\"],\n): PlDataTableModel | undefined {\n if (columns.length === 0) return undefined;\n\n const tableStateNormalized = upgradePlDataTableStateV2(tableState);\n const allLabelColumns = getAllLabelColumns(ctx.resultPool) ?? [];\n\n let fullLabelColumns = getMatchingLabelColumns(columns, allLabelColumns);\n fullLabelColumns = deriveLabels(fullLabelColumns, identity, { includeNativeLabel: true }).map(\n (v) => {\n return {\n ...v.value,\n spec: {\n ...v.value.spec,\n annotations: {\n ...v.value.spec.annotations,\n [Annotation.Label]: v.label,\n },\n },\n };\n },\n );\n\n const fullColumns = [...columns, ...fullLabelColumns];\n\n const resolver = createColumnResolver(\n fullColumns.map((c) => ColumnLazyImpl.fromColumn(c)),\n { warn: ctx.logWarn.bind(ctx) },\n );\n\n // -- Filtering: rewrite via resolver, throw if any reference is unresolved --\n const rawFilters = tableStateNormalized.pTableParams.filters;\n const rawDefaultFilters = options?.filters ?? undefined;\n const filters = remapFiltersThrowing(rawFilters, resolver, \"filter\");\n const defaultFilters = remapFiltersThrowing(\n rawDefaultFilters ?? null,\n resolver,\n \"default filter\",\n );\n\n // -- Sorting: rewrite via resolver, throw if any reference is unresolved --\n const userSorting = tableStateNormalized.pTableParams.sorting;\n const rawSorting = (isNil(userSorting) ? options?.sorting : userSorting) ?? [];\n const sorting = remapSortingThrowing(rawSorting, resolver);\n\n const coreJoinType = options?.coreJoinType ?? \"full\";\n const fullDef = createPTableDefV2({\n columns,\n labelColumns: fullLabelColumns,\n coreJoinType,\n filters: filters ?? null,\n sorting,\n coreColumnPredicate: options?.coreColumnPredicate,\n });\n\n const fullHandle = ctx.createPTableV2(fullDef);\n const pframeHandle = ctx.createPFrame(fullColumns);\n if (!fullHandle || !pframeHandle) return undefined;\n\n const hiddenColumns = new Set<ColumnUniversalId>(\n ((): ColumnUniversalId[] => {\n // Inner join works as a filter - all columns must be present\n if (coreJoinType === \"inner\") return [];\n\n const hiddenColIds = tableStateNormalized.pTableParams.hiddenColIds;\n if (hiddenColIds !== null) {\n return hiddenColIds\n .filter((s): s is PTableColumnIdColumn => s.type === \"column\")\n .map((s) => s.id);\n }\n\n return columns.filter((c) => isColumnOptional(c.spec)).map((c) => c.id);\n })(),\n );\n\n // Preserve linker columns\n columns.filter((c) => isLinkerColumn(c.spec)).forEach((c) => hiddenColumns.delete(c.id));\n\n // Preserve core columns as they change the shape of join.\n const coreColumnPredicate = options?.coreColumnPredicate;\n if (coreColumnPredicate) {\n const coreColumns = columns.flatMap((c) =>\n coreColumnPredicate(getColumnIdAndSpec(c)) ? [c.id] : [],\n );\n coreColumns.forEach((c) => hiddenColumns.delete(c));\n }\n\n // Preserve sorted columns from being hidden\n sorting\n .map((s) => s.column)\n .filter((c): c is PTableColumnIdColumn => c.type === \"column\")\n .forEach((c) => hiddenColumns.delete(c.id));\n\n // Preserve filter columns from being hidden\n if (filters) {\n collectFilterSpecColumns(filters)\n .flatMap((c) => (c.type === \"column\" ? [c.id] : []))\n .forEach((c) => hiddenColumns.delete(c));\n }\n\n const visibleColumns = columns.filter((c) => !hiddenColumns.has(c.id));\n const visibleLabelColumns = getMatchingLabelColumns(\n visibleColumns.map(getColumnIdAndSpec),\n allLabelColumns,\n );\n\n // if at least one column is not yet computed, we can't show the table\n if (!allPColumnsReady([...visibleColumns, ...visibleLabelColumns])) return undefined;\n\n const visibleDef = createPTableDefV2({\n columns: visibleColumns,\n labelColumns: visibleLabelColumns,\n coreJoinType,\n filters: filters ?? null,\n sorting,\n coreColumnPredicate,\n });\n const visibleHandle = ctx.createPTableV2(visibleDef);\n\n if (!visibleHandle) return undefined;\n\n return {\n sourceId: tableStateNormalized.pTableParams.sourceId,\n fullTableHandle: fullHandle,\n fullPframeHandle: pframeHandle,\n visibleTableHandle: visibleHandle,\n defaultFilters: defaultFilters ?? undefined,\n } satisfies PlDataTableModel;\n}\n\n/** Rewrite filter column refs through the resolver; throw on any unresolved ref. */\nfunction remapFiltersThrowing(\n filters: Nil | PlDataTableFilters,\n resolver: ColumnResolver,\n label: string,\n): Nil | PlDataTableFilters {\n if (isNil(filters)) return filters;\n\n type Node = FilterSpecNode<PlDataTableFilterSpecLeaf>;\n return traverseFilterSpec(filters, {\n leaf: (leaf): Node => {\n if (leaf.type === undefined) return leaf;\n const result = { ...leaf };\n if (\"column\" in result) {\n const c = resolver(result.column);\n if (isNil(c))\n throw new Error(\n `Invalid ${label} column ${JSON.stringify(result.column)}: column reference does not match the table columns`,\n );\n result.column = c;\n }\n if (\"rhs\" in result) {\n const c = resolver(result.rhs);\n if (isNil(c))\n throw new Error(\n `Invalid ${label} column ${JSON.stringify(result.rhs)}: column reference does not match the table columns`,\n );\n result.rhs = c;\n }\n return result;\n },\n and: (results): Node => ({ type: \"and\", filters: results }),\n or: (results): Node => ({ type: \"or\", filters: results }),\n not: (result): Node => ({ type: \"not\", filter: result }),\n }) as PlDataTableFilters;\n}\n\n/** Rewrite sorting column refs through the resolver; throw on any unresolved ref. */\nfunction remapSortingThrowing(sorting: PTableSorting[], resolver: ColumnResolver): PTableSorting[] {\n return sorting.map((s) => {\n const c = resolver(s.column);\n if (isNil(c))\n throw new Error(\n `Invalid sorting column ${JSON.stringify(s.column)}: column reference does not match the table columns`,\n );\n return { ...s, column: c };\n });\n}\n\nfunction getAllLabelColumns(\n resultPool: AxisLabelProvider & ColumnProvider,\n): undefined | PColumn<undefined | PColumnDataUniversal>[] {\n return new PColumnCollection()\n .addAxisLabelProvider(resultPool)\n .addColumnProvider(resultPool)\n .getColumns(\n {\n name: PColumnName.Label,\n axes: [{}], // exactly one axis\n },\n { dontWaitAllData: true, overrideLabelAnnotation: false },\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createPlDataTableV2.js","names":[],"sources":["../../../../src/components/PlDataTable/createPlDataTable/createPlDataTableV2.ts"],"sourcesContent":["import type {\n ColumnUniversalId,\n FilterSpecNode,\n PColumn,\n PTableColumnIdColumn,\n PTableSorting,\n} from \"@milaboratories/pl-model-common\";\nimport {\n Annotation,\n getColumnIdAndSpec,\n isLinkerColumn,\n PColumnName,\n} from \"@milaboratories/pl-model-common\";\nimport type {\n AxisLabelProvider,\n ColumnProvider,\n PColumnDataUniversal,\n RenderCtxBase,\n} from \"../../../render\";\nimport { allPColumnsReady, deriveLabels, PColumnCollection } from \"../../../render\";\nimport { identity } from \"es-toolkit\";\nimport type {\n CreatePlDataTableOps,\n PlDataTableFilters,\n PlDataTableFilterSpecLeaf,\n PlDataTableModel,\n} from \"../typesV8\";\nimport { upgradePlDataTableStateV2 } from \"../state-migration\";\nimport type { PlDataTableStateV2 } from \"../state-migration\";\nimport { getMatchingLabelColumns } from \"../labels\";\nimport { collectFilterSpecColumns, traverseFilterSpec } from \"../../../filters/traverse\";\nimport { createPTableDefV2 } from \"./createPTableDefV2\";\nimport { isColumnOptional } from \"./utils\";\nimport { DataColumn } from \"../../../columns\";\nimport { createColumnResolver, type ColumnResolver } from \"../columnResolver\";\nimport { isNil, type Nil } from \"@milaboratories/helpers\";\n\n/**\n * @deprecated This function is deprecated and will be removed in future. Please migrate to createPlDataTable with v3 options for improved column discovery and display configuration. See createPlDataTableOptionsV3 for details on the new options format and migration guidance.\n */\nexport type createPlDataTableOptionsV2 = {\n columns: PColumn<PColumnDataUniversal>[];\n tableState?: PlDataTableStateV2;\n options?: CreatePlDataTableOps;\n};\n\n/**\n * Create p-table spec and handle given ui table state\n *\n * @deprecated This version of createPlDataTable is deprecated and will be removed in future. Please migrate to v3 by switching to the new options format and providing necessary information for column discovery and display configuration. See createPlDataTableOptionsV3 for details.\n * @param ctx context\n * @param columns column list\n * @param tableState table ui state\n * @returns PlAgDataTableV2 table source\n */\nexport function createPlDataTableV2<A, U>(\n ctx: RenderCtxBase<A, U>,\n columns: createPlDataTableOptionsV2[\"columns\"],\n tableState?: createPlDataTableOptionsV2[\"tableState\"],\n options?: createPlDataTableOptionsV2[\"options\"],\n): PlDataTableModel | undefined {\n if (columns.length === 0) return undefined;\n\n const tableStateNormalized = upgradePlDataTableStateV2(tableState);\n const allLabelColumns = getAllLabelColumns(ctx.resultPool) ?? [];\n\n let fullLabelColumns = getMatchingLabelColumns(columns, allLabelColumns);\n fullLabelColumns = deriveLabels(fullLabelColumns, identity, { includeNativeLabel: true }).map(\n (v) => {\n return {\n ...v.value,\n spec: {\n ...v.value.spec,\n annotations: {\n ...v.value.spec.annotations,\n [Annotation.Label]: v.label,\n },\n },\n };\n },\n );\n\n const fullColumns = [...columns, ...fullLabelColumns];\n\n const resolver = createColumnResolver(\n fullColumns.map((c) => DataColumn.fromColumn(c)),\n { warn: ctx.logWarn.bind(ctx) },\n );\n\n // -- Filtering: rewrite via resolver, throw if any reference is unresolved --\n const rawFilters = tableStateNormalized.pTableParams.filters;\n const rawDefaultFilters = options?.filters ?? undefined;\n const filters = remapFiltersThrowing(rawFilters, resolver, \"filter\");\n const defaultFilters = remapFiltersThrowing(\n rawDefaultFilters ?? null,\n resolver,\n \"default filter\",\n );\n\n // -- Sorting: rewrite via resolver, throw if any reference is unresolved --\n const userSorting = tableStateNormalized.pTableParams.sorting;\n const rawSorting = (isNil(userSorting) ? options?.sorting : userSorting) ?? [];\n const sorting = remapSortingThrowing(rawSorting, resolver);\n\n const coreJoinType = options?.coreJoinType ?? \"full\";\n const fullDef = createPTableDefV2({\n columns,\n labelColumns: fullLabelColumns,\n coreJoinType,\n filters: filters ?? null,\n sorting,\n coreColumnPredicate: options?.coreColumnPredicate,\n });\n\n const fullHandle = ctx.createPTableV2(fullDef);\n const pframeHandle = ctx.createPFrame(fullColumns);\n if (!fullHandle || !pframeHandle) return undefined;\n\n const hiddenColumns = new Set<ColumnUniversalId>(\n ((): ColumnUniversalId[] => {\n // Inner join works as a filter - all columns must be present\n if (coreJoinType === \"inner\") return [];\n\n const hiddenColIds = tableStateNormalized.pTableParams.hiddenColIds;\n if (hiddenColIds !== null) {\n return hiddenColIds\n .filter((s): s is PTableColumnIdColumn => s.type === \"column\")\n .map((s) => s.id);\n }\n\n return columns.filter((c) => isColumnOptional(c.spec)).map((c) => c.id);\n })(),\n );\n\n // Preserve linker columns\n columns.filter((c) => isLinkerColumn(c.spec)).forEach((c) => hiddenColumns.delete(c.id));\n\n // Preserve core columns as they change the shape of join.\n const coreColumnPredicate = options?.coreColumnPredicate;\n if (coreColumnPredicate) {\n const coreColumns = columns.flatMap((c) =>\n coreColumnPredicate(getColumnIdAndSpec(c)) ? [c.id] : [],\n );\n coreColumns.forEach((c) => hiddenColumns.delete(c));\n }\n\n // Preserve sorted columns from being hidden\n sorting\n .map((s) => s.column)\n .filter((c): c is PTableColumnIdColumn => c.type === \"column\")\n .forEach((c) => hiddenColumns.delete(c.id));\n\n // Preserve filter columns from being hidden\n if (filters) {\n collectFilterSpecColumns(filters)\n .flatMap((c) => (c.type === \"column\" ? [c.id] : []))\n .forEach((c) => hiddenColumns.delete(c));\n }\n\n const visibleColumns = columns.filter((c) => !hiddenColumns.has(c.id));\n const visibleLabelColumns = getMatchingLabelColumns(\n visibleColumns.map(getColumnIdAndSpec),\n allLabelColumns,\n );\n\n // if at least one column is not yet computed, we can't show the table\n if (!allPColumnsReady([...visibleColumns, ...visibleLabelColumns])) return undefined;\n\n const visibleDef = createPTableDefV2({\n columns: visibleColumns,\n labelColumns: visibleLabelColumns,\n coreJoinType,\n filters: filters ?? null,\n sorting,\n coreColumnPredicate,\n });\n const visibleHandle = ctx.createPTableV2(visibleDef);\n\n if (!visibleHandle) return undefined;\n\n return {\n sourceId: tableStateNormalized.pTableParams.sourceId,\n fullTableHandle: fullHandle,\n fullPframeHandle: pframeHandle,\n visibleTableHandle: visibleHandle,\n defaultFilters: defaultFilters ?? undefined,\n } satisfies PlDataTableModel;\n}\n\n/** Rewrite filter column refs through the resolver; throw on any unresolved ref. */\nfunction remapFiltersThrowing(\n filters: Nil | PlDataTableFilters,\n resolver: ColumnResolver,\n label: string,\n): Nil | PlDataTableFilters {\n if (isNil(filters)) return filters;\n\n type Node = FilterSpecNode<PlDataTableFilterSpecLeaf>;\n return traverseFilterSpec(filters, {\n leaf: (leaf): Node => {\n if (leaf.type === undefined) return leaf;\n const result = { ...leaf };\n if (\"column\" in result) {\n const c = resolver(result.column);\n if (isNil(c))\n throw new Error(\n `Invalid ${label} column ${JSON.stringify(result.column)}: column reference does not match the table columns`,\n );\n result.column = c;\n }\n if (\"rhs\" in result) {\n const c = resolver(result.rhs);\n if (isNil(c))\n throw new Error(\n `Invalid ${label} column ${JSON.stringify(result.rhs)}: column reference does not match the table columns`,\n );\n result.rhs = c;\n }\n return result;\n },\n and: (results): Node => ({ type: \"and\", filters: results }),\n or: (results): Node => ({ type: \"or\", filters: results }),\n not: (result): Node => ({ type: \"not\", filter: result }),\n }) as PlDataTableFilters;\n}\n\n/** Rewrite sorting column refs through the resolver; throw on any unresolved ref. */\nfunction remapSortingThrowing(sorting: PTableSorting[], resolver: ColumnResolver): PTableSorting[] {\n return sorting.map((s) => {\n const c = resolver(s.column);\n if (isNil(c))\n throw new Error(\n `Invalid sorting column ${JSON.stringify(s.column)}: column reference does not match the table columns`,\n );\n return { ...s, column: c };\n });\n}\n\nfunction getAllLabelColumns(\n resultPool: AxisLabelProvider & ColumnProvider,\n): undefined | PColumn<undefined | PColumnDataUniversal>[] {\n return new PColumnCollection()\n .addAxisLabelProvider(resultPool)\n .addColumnProvider(resultPool)\n .getColumns(\n {\n name: PColumnName.Label,\n axes: [{}], // exactly one axis\n },\n { dontWaitAllData: true, overrideLabelAnnotation: false },\n );\n}\n"],"mappings":"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"}
|
|
@@ -122,7 +122,7 @@ function resolveInputColumns(ctx, options) {
|
|
|
122
122
|
function splitByTopology(columns) {
|
|
123
123
|
const direct = [];
|
|
124
124
|
const linked = [];
|
|
125
|
-
for (const c of columns) if (require_utils.
|
|
125
|
+
for (const c of columns) if (require_utils.hasSingleDataColumn(c)) direct.push(c);
|
|
126
126
|
else linked.push(c);
|
|
127
127
|
return {
|
|
128
128
|
direct,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createPlDataTableV3.cjs","names":["upgradePlDataTableStateV2","deriveAllLabels","isColumnHidden","evaluateRules","createColumnResolver","collectLinkerColumns","createPTableDefV3","discoverLabelColumns","discoverTableColumns","isLeafColumn","hitQualifications","queriesQualifications","buildDataStatusMap","toRuleColumn","getEffectiveVisibility","getOrderPriority","collectFilterSpecColumns"],"sources":["../../../../src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts"],"sourcesContent":["import type {\n ColumnUniversalId,\n FilterSpecNode,\n PObjectId,\n PTableColumnId,\n PTableColumnIdColumn,\n PTableSorting,\n MultiColumnSelector,\n ColumnSelector,\n} from \"@milaboratories/pl-model-common\";\nimport {\n canonicalizeAxisId,\n dedupColumns,\n extractPObjectId,\n uniqueBy,\n} from \"@milaboratories/pl-model-common\";\nimport { collectFilterSpecColumns } from \"../../../filters/traverse\";\nimport { createColumnResolver, type ColumnResolver } from \"../columnResolver\";\nimport type { RenderCtxBase } from \"../../../render\";\nimport type {\n PlDataTableColumnsMeta,\n PlDataTableFilters,\n PlDataTableFilterSpecLeaf,\n PlDataTableModel,\n} from \"../typesV8\";\nimport { upgradePlDataTableStateV2 } from \"../state-migration\";\nimport type { PlDataTableStateV2 } from \"../state-migration\";\nimport type { MatchingMode } from \"@milaboratories/pl-model-common\";\nimport {\n isLeafColumn,\n hitQualifications,\n collectLinkerColumns,\n queriesQualifications,\n type ColumnRecipe,\n} from \"../../../columns\";\nimport type { DeriveLabelsOptions } from \"../../../labels/derive_distinct_labels\";\nimport {\n deriveAllLabels,\n evaluateRules,\n getEffectiveVisibility,\n getOrderPriority,\n isColumnHidden,\n buildDataStatusMap,\n toRuleColumn,\n} from \"./utils\";\nimport { createPTableDefV3 } from \"./createPTableDefV3\";\nimport {\n discoverLabelColumns,\n discoverTableColumns,\n type DiscoverTableColumnOptions,\n} from \"./discoverColumns\";\nimport { isNil, isPlainObject, type Nil } from \"@milaboratories/helpers\";\nimport { uniq } from \"es-toolkit\";\n\nexport type createPlDataTableOptionsV3 = (\n | {\n columns: Nil | DiscoverTableColumnOptions;\n }\n | {\n primaryColumns: ColumnRecipe[];\n columns: Nil | ColumnRecipe[];\n }\n) & {\n tableState?: PlDataTableStateV2;\n\n filters?: PlDataTableFilters;\n sorting?: PTableSorting[];\n primaryJoinType?: \"inner\" | \"full\";\n\n labelsOptions?: DeriveLabelsOptions;\n displayOptions?: ColumnsDisplayOptions;\n};\n\n/** Structured source config — selectors/anchors instead of raw ColumnsSource. */\nexport type ColumnsSelectorConfig = {\n include?: MultiColumnSelector | MultiColumnSelector[];\n exclude?: MultiColumnSelector | MultiColumnSelector[];\n mode?: MatchingMode;\n maxHops?: number;\n};\n\nexport type ColumnsDisplayOptions = {\n /** Column ordering rules. Higher priority = further left. First matching rule wins. */\n ordering?: ColumnOrderRule[];\n /** Column visibility rules. First matching rule wins. Unmatched columns use default visibility. */\n visibility?: ColumnVisibilityRule[];\n};\n\nexport type ColumnOrderRule = {\n match: ColumnSelector;\n /** Higher number = further left in table */\n priority: number;\n};\n\nexport type ColumnVisibilityRule = {\n match: ColumnSelector;\n visibility: \"default\" | \"optional\" | \"hidden\";\n};\n\nexport function createPlDataTableV3<A, U>(\n ctx: RenderCtxBase<A, U>,\n options: createPlDataTableOptionsV3,\n): PlDataTableModel | undefined {\n const state = upgradePlDataTableStateV2(options.tableState);\n const primaryJoinType = options.primaryJoinType ?? \"full\";\n\n const resolved = resolveInputColumns(ctx, options);\n if (resolved === undefined) return undefined;\n const { primary, secondary } = resolved;\n if (primary.length === 0) return undefined;\n\n const { direct, linked } = splitByTopology(secondary);\n\n const allColumns = [...primary, ...secondary];\n const derivedLabels = deriveAllLabels({\n // Skip hidden columns when deriving labels — they don't appear in the\n // table, so they shouldn't influence label disambiguation (#1623).\n columns: allColumns.filter((c) => !isColumnHidden(c.getSpec())).map(toLabelableColumn),\n deriveLabelsOptions: {\n includeNativeLabel: true,\n ...options.labelsOptions,\n },\n });\n\n // Rule-based visibility/order maps (keyed by bare PObjectId). Computed once\n // here: `computeHiddenColumns` needs visibility to decide the visible set,\n // and `buildColumnsMeta` (below, once the visible set is known) reuses both.\n const allColumnsForRules = [...primary, ...direct, ...linked, ...collectLinkerSnapshots(linked)];\n const visibilityByColId = evaluateRules(\n options.displayOptions?.visibility ?? [],\n allColumnsForRules,\n );\n const orderByColId = evaluateRules(options.displayOptions?.ordering ?? [], allColumnsForRules);\n\n const resolver = createColumnResolver(\n [...primary, ...direct, ...linked.flatMap((lc) => [...collectLinkerColumns(lc), lc])],\n { warn: ctx.logWarn.bind(ctx) },\n );\n\n const remapedDefaultFilters = remapFilterColumnIds(options.filters, resolver);\n const filters = filterFilters(\n concatFilters(\n state.pTableParams.filters,\n state.pTableParams.defaultFilters ?? remapedDefaultFilters,\n ),\n resolver,\n );\n\n const sorting = filterSorting(\n resolveSorting(state.pTableParams.sorting, remapSortingColumnIds(options.sorting, resolver)),\n resolver,\n );\n\n const fullDef = createPTableDefV3({\n primaryJoinType,\n primary,\n secondary: [...direct, ...linked],\n filters,\n sorting,\n });\n\n const fullHandle = ctx.createPTableV2(fullDef);\n // TODO: is workaround for dropdown suggestions.\n // Pframe have not equivalent data for columns relativly to Ptable.\n // PFrame is the physical column registry — one entry per bare PObjectId,\n // so strip the rich recipe ids down to their physical leaf id and dedupe:\n // multiple discovered variants of the same hit collapse to the same bare id.\n const pframeHandle = ctx.createPFrame(\n uniq([\n ...primary.map((v) => extractPObjectId(v.id)),\n ...direct.map((v) => extractPObjectId(v.id)),\n ...linked.map((v) => extractPObjectId(v.id)),\n ]),\n );\n\n const hiddenSpecs = state.pTableParams.hiddenColIds;\n const hiddenColumnIds = computeHiddenColumns({\n columns: [...primary, ...direct, ...linked],\n visibilityByColId,\n sorting,\n filters,\n hiddenSpecs,\n });\n\n const visible = {\n primary,\n direct: direct.filter((c) => !hiddenColumnIds.has(c.id)),\n linked: linked.filter((c) => !hiddenColumnIds.has(c.id)),\n };\n const visibleDef = createPTableDefV3({\n primaryJoinType,\n primary,\n secondary: [...visible.direct, ...visible.linked],\n filters,\n sorting,\n });\n const visibleHandle = ctx.createPTableV2(visibleDef);\n\n // Built here, where the visible set is known: per-column data status is\n // computed for visible columns only (the probe is meaningful only for what\n // the user sees), while label/visibility/order/axes cover all columns.\n const columnsMeta = buildColumnsMeta({\n fullColumns: [...primary, ...direct, ...linked],\n visibleColumns: [...visible.primary, ...visible.direct, ...visible.linked],\n primaryColumns: primary,\n derivedLabels,\n visibilityByColId,\n orderByColId,\n });\n\n return {\n sourceId: state.pTableParams.sourceId,\n fullTableHandle: fullHandle,\n fullPframeHandle: pframeHandle,\n visibleTableHandle: visibleHandle,\n defaultFilters: remapedDefaultFilters,\n columnsMeta,\n } satisfies PlDataTableModel;\n}\n\ntype ResolvedColumns = {\n readonly primary: ColumnRecipe[];\n readonly secondary: ColumnRecipe[];\n};\n\n/** Normalize either option branch into a {primary, secondary} pair of recipes. */\nfunction resolveInputColumns<A, U>(\n ctx: RenderCtxBase<A, U>,\n options: createPlDataTableOptionsV3,\n): undefined | ResolvedColumns {\n if (\"primaryColumns\" in options) {\n const primary = options.primaryColumns;\n const secondary = options.columns ?? [];\n const labels = discoverLabelColumns(ctx, primary);\n // Exclude from secondary anything already present in primary: a label\n // column the block hands in as primary can be re-discovered here as a\n // label for that same axis, landing in the table twice with the same id.\n const primaryIds = new Set(primary.map((c) => c.id));\n return {\n primary,\n secondary: dedupColumns(\n [...secondary, ...labels].filter((c) => !primaryIds.has(c.id)),\n (c) => c.id,\n (c) => c.getSpec(),\n ),\n };\n }\n\n if (isPlainObject(options.columns)) {\n return discoverTableColumns(ctx, options.columns);\n }\n\n return undefined;\n}\n\n/** Split secondary recipes by query topology: leaves (no linker chain) vs joined. */\nfunction splitByTopology(columns: ColumnRecipe[]): {\n direct: ColumnRecipe[];\n linked: ColumnRecipe[];\n} {\n const direct: ColumnRecipe[] = [];\n const linked: ColumnRecipe[] = [];\n for (const c of columns) {\n if (isLeafColumn(c)) direct.push(c);\n else linked.push(c);\n }\n return { direct, linked };\n}\n\n/** All linker recipes across the given linked columns, deduped by id. */\nfunction collectLinkerSnapshots(linked: ColumnRecipe[]): ColumnRecipe[] {\n return uniqueBy(\n linked.flatMap((c) => collectLinkerColumns(c)),\n (c) => c.id,\n );\n}\n\nfunction toLabelableColumn(col: ColumnRecipe) {\n return {\n id: col.id,\n spec: col.getSpec(),\n linkerPath: collectLinkerColumns(col).map((linker) => ({\n linker: { spec: linker.getSpec() },\n })),\n qualifications: {\n forHit: [...hitQualifications(col)],\n forQueries: queriesQualifications(col),\n },\n };\n}\n\n/**\n * Compute display metadata as a sidecar keyed by each emitted column's\n * `ColumnUniversalId` (and axis `AxisId`), instead of baking it into the specs\n * via `withSpecs`. Spec overrides change a recipe's id, so the same physical\n * column reached two ways would diverge into two ids and render twice; keeping\n * meta out of the spec preserves identity and lets dedup collapse such cases.\n * The UI overlays this onto the engine-emitted specs at render time.\n */\nfunction buildColumnsMeta(params: {\n /** Every column in the table (primary + secondary) — drives `columns` and `axes`. */\n fullColumns: ColumnRecipe[];\n /** The visible subset — `status` is probed for these only. */\n visibleColumns: ColumnRecipe[];\n /** The primary join columns — their axes are the visible index; all other axes are hidden. */\n primaryColumns: ColumnRecipe[];\n derivedLabels: Record<string, string>;\n visibilityByColId: Map<PObjectId, ColumnVisibilityRule>;\n orderByColId: Map<PObjectId, ColumnOrderRule>;\n}): PlDataTableColumnsMeta {\n const { fullColumns, visibleColumns, primaryColumns, derivedLabels } = params;\n const { visibilityByColId, orderByColId } = params;\n // Status only for visible columns — the probe is meaningful only for what the\n // user actually sees; non-visible columns get no `status`.\n const visibleStatus = buildDataStatusMap(visibleColumns);\n\n const columns = fullColumns.reduce<PlDataTableColumnsMeta[\"columns\"]>((acc, c) => {\n const rc = toRuleColumn(c);\n acc[c.id] = {\n label: derivedLabels[c.id],\n visibility: getEffectiveVisibility(rc, visibilityByColId),\n order: getOrderPriority(rc, orderByColId),\n status: visibleStatus[c.id],\n };\n return acc;\n }, {});\n\n // Only primary columns declare the table's visible axes. Any axis introduced\n // solely by a secondary column (a linker-bridge axis, or a distinct-domain\n // copy) is flagged hidden — otherwise it renders as a second index axis.\n const primaryAxisKeys = new Set(\n primaryColumns.flatMap((c) => c.getSpec().axesSpec.map((a) => canonicalizeAxisId(a))),\n );\n const axes = fullColumns.reduce<PlDataTableColumnsMeta[\"axes\"]>(\n (acc, c) =>\n c.getSpec().axesSpec.reduce((inner, ax) => {\n const key = canonicalizeAxisId(ax);\n if (inner[key] === undefined) inner[key] = { hidden: !primaryAxisKeys.has(key) };\n return inner;\n }, acc),\n {},\n );\n\n return { columns, axes };\n}\n\n/** Drop filter leaves whose column references cannot be resolved; rewrite the\n * resolvable ones through the resolver. Prune empty and/or/not groups. */\nfunction filterFilters(\n filters: Nil | PlDataTableFilters,\n resolver: ColumnResolver,\n): Nil | PlDataTableFilters {\n if (isNil(filters)) return filters;\n\n const rewriteLeaf = (leaf: PlDataTableFilterSpecLeaf): Nil | PlDataTableFilterSpecLeaf => {\n if (leaf.type === undefined) return leaf;\n const result = { ...leaf };\n if (\"column\" in result) {\n const c = resolver(result.column);\n if (isNil(c)) return undefined;\n result.column = c;\n }\n if (\"rhs\" in result) {\n const c = resolver(result.rhs);\n if (isNil(c)) return undefined;\n result.rhs = c;\n }\n return result;\n };\n\n const prune = (node: PlDataTableFilterNode): Nil | PlDataTableFilterNode => {\n if (node.type === \"and\" || node.type === \"or\") {\n const kept = node.filters\n .map((f) => prune(f))\n .filter((f): f is PlDataTableFilterNode => !isNil(f));\n if (kept.length === 0) return undefined;\n return { type: node.type, filters: kept };\n }\n if (node.type === \"not\") {\n const inner = prune(node.filter);\n return isNil(inner) ? undefined : { type: \"not\", filter: inner };\n }\n return rewriteLeaf(node);\n };\n\n return prune(filters) as Nil | PlDataTableFilters;\n}\n\n/** Merge two filter trees into one AND-combined tree. Returns the non-nil one if the other is nil.\n * Exported for unit testing. */\nexport function concatFilters(\n a: Nil | PlDataTableFilters,\n b: Nil | PlDataTableFilters,\n): Nil | PlDataTableFilters {\n if (isNil(a)) return b;\n if (isNil(b)) return a;\n const operands = (f: PlDataTableFilters): PlDataTableFilterNode[] =>\n f.type === \"and\" ? f.filters : [f as PlDataTableFilterNode];\n return { type: \"and\", filters: [...operands(a), ...operands(b)] };\n}\n\n/** Pick user sorting from state if set, otherwise fall back to options default.\n * null = user has not touched sorting → use default;\n * [] = user has explicitly cleared sorting → no sorting (default ignored). */\nfunction resolveSorting(\n userSorting: Nil | PTableSorting[],\n defaultSorting: Nil | PTableSorting[],\n): PTableSorting[] {\n return (isNil(userSorting) ? defaultSorting : userSorting) ?? [];\n}\n\n/** Rewrite sorting entries through the resolver; drop those that fail to resolve. */\nfunction filterSorting(sorting: PTableSorting[], resolver: ColumnResolver): PTableSorting[] {\n return sorting.flatMap((s) => {\n const col = resolver(s.column);\n return isNil(col) ? [] : [{ ...s, column: col }];\n });\n}\n\n/** Determine which columns should be hidden based on state or optional-column defaults.\n * Keyed by the recipe's logical {@link ColumnUniversalId} (rich) — variants of\n * the same physical column are independently visible/hidden. */\nfunction computeHiddenColumns(params: {\n columns: ColumnRecipe[];\n visibilityByColId: Map<PObjectId, ColumnVisibilityRule>;\n sorting: Nil | PTableSorting[];\n filters: Nil | PlDataTableFilters;\n hiddenSpecs: Nil | PTableColumnId[];\n}): Set<ColumnUniversalId> {\n const { columns, visibilityByColId, sorting, filters, hiddenSpecs } = params;\n const visibilityOf = (c: ColumnRecipe) =>\n getEffectiveVisibility(toRuleColumn(c), visibilityByColId);\n const alwaysHidden = columns.filter((c) => visibilityOf(c) === \"hidden\").map((c) => c.id);\n const optionalHidden = !isNil(hiddenSpecs)\n ? hiddenSpecs.filter((s): s is PTableColumnIdColumn => s.type === \"column\").map((s) => s.id)\n : columns.filter((c) => visibilityOf(c) === \"optional\").map((c) => c.id);\n const initial = [...alwaysHidden, ...optionalHidden];\n const preserved = collectPreservedColumnIds(sorting, filters);\n\n return new Set(initial.filter((id) => !preserved.has(id)));\n}\n\n/** Collect IDs of columns that must remain visible (sorted, filtered). */\nfunction collectPreservedColumnIds(\n sorting: Nil | PTableSorting[],\n filters: Nil | PlDataTableFilters,\n): Set<ColumnUniversalId> {\n const sortedIds = (sorting ?? [])\n .map((s) => s.column)\n .filter((c): c is PTableColumnIdColumn => c.type === \"column\")\n .map((c) => c.id);\n\n const filterIds = !isNil(filters)\n ? collectFilterSpecColumns(filters).flatMap((c) => (c.type === \"column\" ? [c.id] : []))\n : [];\n\n return new Set<ColumnUniversalId>([...sortedIds, ...filterIds]);\n}\n\n/** Remap column references in sorting entries through the resolver.\n * Unresolved entries are dropped with a warning (best-effort contract). */\nfunction remapSortingColumnIds(\n sorting: Nil | PTableSorting[],\n resolver: ColumnResolver,\n): Nil | PTableSorting[] {\n return sorting?.flatMap((s) => {\n const col = resolver(s.column);\n if (isNil(col)) {\n console.warn(\n `Sorting column ${JSON.stringify(s.column)} does not match any discovered column — dropped.`,\n );\n return [];\n }\n return [{ ...s, column: col }];\n });\n}\n\ntype PlDataTableFilterNode = FilterSpecNode<PlDataTableFilterSpecLeaf>;\n\n/** Remap column references in a filter tree through the resolver.\n * Unresolved leaves are dropped with a warning; empty groups are pruned. */\nfunction remapFilterColumnIds(\n filters: Nil | PlDataTableFilters,\n resolver: ColumnResolver,\n): Nil | PlDataTableFilters {\n if (isNil(filters)) return filters;\n\n const mapLeaf = (leaf: PlDataTableFilterSpecLeaf): Nil | PlDataTableFilterSpecLeaf => {\n if (leaf.type === undefined) return leaf;\n const result = { ...leaf };\n if (\"column\" in result) {\n const c = resolver(result.column);\n if (isNil(c)) {\n console.warn(\n `Filter column ${JSON.stringify(result.column)} does not match any discovered column — dropped.`,\n );\n return undefined;\n }\n result.column = c;\n }\n if (\"rhs\" in result) {\n const c = resolver(result.rhs);\n if (isNil(c)) {\n console.warn(\n `Filter rhs ${JSON.stringify(result.rhs)} does not match any discovered column — dropped.`,\n );\n return undefined;\n }\n result.rhs = c;\n }\n return result;\n };\n\n const prune = (node: PlDataTableFilterNode): Nil | PlDataTableFilterNode => {\n if (node.type === \"and\" || node.type === \"or\") {\n const kept = node.filters\n .map((f) => prune(f))\n .filter((f): f is PlDataTableFilterNode => !isNil(f));\n if (kept.length === 0) return undefined;\n return { type: node.type, filters: kept };\n }\n if (node.type === \"not\") {\n const inner = prune(node.filter);\n return isNil(inner) ? undefined : { type: \"not\", filter: inner };\n }\n return mapLeaf(node);\n };\n\n return prune(filters) as Nil | PlDataTableFilters;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createPlDataTableV3.cjs","names":["upgradePlDataTableStateV2","deriveAllLabels","isColumnHidden","evaluateRules","createColumnResolver","collectLinkerColumns","createPTableDefV3","discoverLabelColumns","discoverTableColumns","hasSingleDataColumn","hitQualifications","queriesQualifications","buildDataStatusMap","toRuleColumn","getEffectiveVisibility","getOrderPriority","collectFilterSpecColumns"],"sources":["../../../../src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts"],"sourcesContent":["import type {\n ColumnUniversalId,\n FilterSpecNode,\n PObjectId,\n PTableColumnId,\n PTableColumnIdColumn,\n PTableSorting,\n MultiColumnSelector,\n ColumnSelector,\n} from \"@milaboratories/pl-model-common\";\nimport {\n canonicalizeAxisId,\n dedupColumns,\n extractPObjectId,\n uniqueBy,\n} from \"@milaboratories/pl-model-common\";\nimport { collectFilterSpecColumns } from \"../../../filters/traverse\";\nimport { createColumnResolver, type ColumnResolver } from \"../columnResolver\";\nimport type { RenderCtxBase } from \"../../../render\";\nimport type {\n PlDataTableColumnsMeta,\n PlDataTableFilters,\n PlDataTableFilterSpecLeaf,\n PlDataTableModel,\n} from \"../typesV8\";\nimport { upgradePlDataTableStateV2 } from \"../state-migration\";\nimport type { PlDataTableStateV2 } from \"../state-migration\";\nimport type { MatchingMode } from \"@milaboratories/pl-model-common\";\nimport {\n hasSingleDataColumn,\n hitQualifications,\n collectLinkerColumns,\n queriesQualifications,\n type ColumnRecipe,\n} from \"../../../columns\";\nimport type { DeriveLabelsOptions } from \"../../../labels/derive_distinct_labels\";\nimport {\n deriveAllLabels,\n evaluateRules,\n getEffectiveVisibility,\n getOrderPriority,\n isColumnHidden,\n buildDataStatusMap,\n toRuleColumn,\n} from \"./utils\";\nimport { createPTableDefV3 } from \"./createPTableDefV3\";\nimport {\n discoverLabelColumns,\n discoverTableColumns,\n type DiscoverTableColumnOptions,\n} from \"./discoverColumns\";\nimport { isNil, isPlainObject, type Nil } from \"@milaboratories/helpers\";\nimport { uniq } from \"es-toolkit\";\n\nexport type createPlDataTableOptionsV3 = (\n | {\n columns: Nil | DiscoverTableColumnOptions;\n }\n | {\n primaryColumns: ColumnRecipe[];\n columns: Nil | ColumnRecipe[];\n }\n) & {\n tableState?: PlDataTableStateV2;\n\n filters?: PlDataTableFilters;\n sorting?: PTableSorting[];\n primaryJoinType?: \"inner\" | \"full\";\n\n labelsOptions?: DeriveLabelsOptions;\n displayOptions?: ColumnsDisplayOptions;\n};\n\n/** Structured source config — selectors/anchors instead of raw ColumnsSource. */\nexport type ColumnsSelectorConfig = {\n include?: MultiColumnSelector | MultiColumnSelector[];\n exclude?: MultiColumnSelector | MultiColumnSelector[];\n mode?: MatchingMode;\n maxHops?: number;\n};\n\nexport type ColumnsDisplayOptions = {\n /** Column ordering rules. Higher priority = further left. First matching rule wins. */\n ordering?: ColumnOrderRule[];\n /** Column visibility rules. First matching rule wins. Unmatched columns use default visibility. */\n visibility?: ColumnVisibilityRule[];\n};\n\nexport type ColumnOrderRule = {\n match: ColumnSelector;\n /** Higher number = further left in table */\n priority: number;\n};\n\nexport type ColumnVisibilityRule = {\n match: ColumnSelector;\n visibility: \"default\" | \"optional\" | \"hidden\";\n};\n\nexport function createPlDataTableV3<A, U>(\n ctx: RenderCtxBase<A, U>,\n options: createPlDataTableOptionsV3,\n): PlDataTableModel | undefined {\n const state = upgradePlDataTableStateV2(options.tableState);\n const primaryJoinType = options.primaryJoinType ?? \"full\";\n\n const resolved = resolveInputColumns(ctx, options);\n if (resolved === undefined) return undefined;\n const { primary, secondary } = resolved;\n if (primary.length === 0) return undefined;\n\n const { direct, linked } = splitByTopology(secondary);\n\n const allColumns = [...primary, ...secondary];\n const derivedLabels = deriveAllLabels({\n // Skip hidden columns when deriving labels — they don't appear in the\n // table, so they shouldn't influence label disambiguation (#1623).\n columns: allColumns.filter((c) => !isColumnHidden(c.getSpec())).map(toLabelableColumn),\n deriveLabelsOptions: {\n includeNativeLabel: true,\n ...options.labelsOptions,\n },\n });\n\n // Rule-based visibility/order maps (keyed by bare PObjectId). Computed once\n // here: `computeHiddenColumns` needs visibility to decide the visible set,\n // and `buildColumnsMeta` (below, once the visible set is known) reuses both.\n const allColumnsForRules = [...primary, ...direct, ...linked, ...collectLinkerSnapshots(linked)];\n const visibilityByColId = evaluateRules(\n options.displayOptions?.visibility ?? [],\n allColumnsForRules,\n );\n const orderByColId = evaluateRules(options.displayOptions?.ordering ?? [], allColumnsForRules);\n\n const resolver = createColumnResolver(\n [...primary, ...direct, ...linked.flatMap((lc) => [...collectLinkerColumns(lc), lc])],\n { warn: ctx.logWarn.bind(ctx) },\n );\n\n const remapedDefaultFilters = remapFilterColumnIds(options.filters, resolver);\n const filters = filterFilters(\n concatFilters(\n state.pTableParams.filters,\n state.pTableParams.defaultFilters ?? remapedDefaultFilters,\n ),\n resolver,\n );\n\n const sorting = filterSorting(\n resolveSorting(state.pTableParams.sorting, remapSortingColumnIds(options.sorting, resolver)),\n resolver,\n );\n\n const fullDef = createPTableDefV3({\n primaryJoinType,\n primary,\n secondary: [...direct, ...linked],\n filters,\n sorting,\n });\n\n const fullHandle = ctx.createPTableV2(fullDef);\n // TODO: is workaround for dropdown suggestions.\n // Pframe have not equivalent data for columns relativly to Ptable.\n // PFrame is the physical column registry — one entry per bare PObjectId,\n // so strip the rich recipe ids down to their physical leaf id and dedupe:\n // multiple discovered variants of the same hit collapse to the same bare id.\n const pframeHandle = ctx.createPFrame(\n uniq([\n ...primary.map((v) => extractPObjectId(v.id)),\n ...direct.map((v) => extractPObjectId(v.id)),\n ...linked.map((v) => extractPObjectId(v.id)),\n ]),\n );\n\n const hiddenSpecs = state.pTableParams.hiddenColIds;\n const hiddenColumnIds = computeHiddenColumns({\n columns: [...primary, ...direct, ...linked],\n visibilityByColId,\n sorting,\n filters,\n hiddenSpecs,\n });\n\n const visible = {\n primary,\n direct: direct.filter((c) => !hiddenColumnIds.has(c.id)),\n linked: linked.filter((c) => !hiddenColumnIds.has(c.id)),\n };\n const visibleDef = createPTableDefV3({\n primaryJoinType,\n primary,\n secondary: [...visible.direct, ...visible.linked],\n filters,\n sorting,\n });\n const visibleHandle = ctx.createPTableV2(visibleDef);\n\n // Built here, where the visible set is known: per-column data status is\n // computed for visible columns only (the probe is meaningful only for what\n // the user sees), while label/visibility/order/axes cover all columns.\n const columnsMeta = buildColumnsMeta({\n fullColumns: [...primary, ...direct, ...linked],\n visibleColumns: [...visible.primary, ...visible.direct, ...visible.linked],\n primaryColumns: primary,\n derivedLabels,\n visibilityByColId,\n orderByColId,\n });\n\n return {\n sourceId: state.pTableParams.sourceId,\n fullTableHandle: fullHandle,\n fullPframeHandle: pframeHandle,\n visibleTableHandle: visibleHandle,\n defaultFilters: remapedDefaultFilters,\n columnsMeta,\n } satisfies PlDataTableModel;\n}\n\ntype ResolvedColumns = {\n readonly primary: ColumnRecipe[];\n readonly secondary: ColumnRecipe[];\n};\n\n/** Normalize either option branch into a {primary, secondary} pair of recipes. */\nfunction resolveInputColumns<A, U>(\n ctx: RenderCtxBase<A, U>,\n options: createPlDataTableOptionsV3,\n): undefined | ResolvedColumns {\n if (\"primaryColumns\" in options) {\n const primary = options.primaryColumns;\n const secondary = options.columns ?? [];\n const labels = discoverLabelColumns(ctx, primary);\n // Exclude from secondary anything already present in primary: a label\n // column the block hands in as primary can be re-discovered here as a\n // label for that same axis, landing in the table twice with the same id.\n const primaryIds = new Set(primary.map((c) => c.id));\n return {\n primary,\n secondary: dedupColumns(\n [...secondary, ...labels].filter((c) => !primaryIds.has(c.id)),\n (c) => c.id,\n (c) => c.getSpec(),\n ),\n };\n }\n\n if (isPlainObject(options.columns)) {\n return discoverTableColumns(ctx, options.columns);\n }\n\n return undefined;\n}\n\n/** Split secondary recipes by query topology: leaves (no linker chain) vs joined. */\nfunction splitByTopology(columns: ColumnRecipe[]): {\n direct: ColumnRecipe[];\n linked: ColumnRecipe[];\n} {\n const direct: ColumnRecipe[] = [];\n const linked: ColumnRecipe[] = [];\n for (const c of columns) {\n if (hasSingleDataColumn(c)) direct.push(c);\n else linked.push(c);\n }\n return { direct, linked };\n}\n\n/** All linker recipes across the given linked columns, deduped by id. */\nfunction collectLinkerSnapshots(linked: ColumnRecipe[]): ColumnRecipe[] {\n return uniqueBy(\n linked.flatMap((c) => collectLinkerColumns(c)),\n (c) => c.id,\n );\n}\n\nfunction toLabelableColumn(col: ColumnRecipe) {\n return {\n id: col.id,\n spec: col.getSpec(),\n linkerPath: collectLinkerColumns(col).map((linker) => ({\n linker: { spec: linker.getSpec() },\n })),\n qualifications: {\n forHit: [...hitQualifications(col)],\n forQueries: queriesQualifications(col),\n },\n };\n}\n\n/**\n * Compute display metadata as a sidecar keyed by each emitted column's\n * `ColumnUniversalId` (and axis `AxisId`), instead of baking it into the specs\n * via `withSpecs`. Spec overrides change a recipe's id, so the same physical\n * column reached two ways would diverge into two ids and render twice; keeping\n * meta out of the spec preserves identity and lets dedup collapse such cases.\n * The UI overlays this onto the engine-emitted specs at render time.\n */\nfunction buildColumnsMeta(params: {\n /** Every column in the table (primary + secondary) — drives `columns` and `axes`. */\n fullColumns: ColumnRecipe[];\n /** The visible subset — `status` is probed for these only. */\n visibleColumns: ColumnRecipe[];\n /** The primary join columns — their axes are the visible index; all other axes are hidden. */\n primaryColumns: ColumnRecipe[];\n derivedLabels: Record<string, string>;\n visibilityByColId: Map<PObjectId, ColumnVisibilityRule>;\n orderByColId: Map<PObjectId, ColumnOrderRule>;\n}): PlDataTableColumnsMeta {\n const { fullColumns, visibleColumns, primaryColumns, derivedLabels } = params;\n const { visibilityByColId, orderByColId } = params;\n // Status only for visible columns — the probe is meaningful only for what the\n // user actually sees; non-visible columns get no `status`.\n const visibleStatus = buildDataStatusMap(visibleColumns);\n\n const columns = fullColumns.reduce<PlDataTableColumnsMeta[\"columns\"]>((acc, c) => {\n const rc = toRuleColumn(c);\n acc[c.id] = {\n label: derivedLabels[c.id],\n visibility: getEffectiveVisibility(rc, visibilityByColId),\n order: getOrderPriority(rc, orderByColId),\n status: visibleStatus[c.id],\n };\n return acc;\n }, {});\n\n // Only primary columns declare the table's visible axes. Any axis introduced\n // solely by a secondary column (a linker-bridge axis, or a distinct-domain\n // copy) is flagged hidden — otherwise it renders as a second index axis.\n const primaryAxisKeys = new Set(\n primaryColumns.flatMap((c) => c.getSpec().axesSpec.map((a) => canonicalizeAxisId(a))),\n );\n const axes = fullColumns.reduce<PlDataTableColumnsMeta[\"axes\"]>(\n (acc, c) =>\n c.getSpec().axesSpec.reduce((inner, ax) => {\n const key = canonicalizeAxisId(ax);\n if (inner[key] === undefined) inner[key] = { hidden: !primaryAxisKeys.has(key) };\n return inner;\n }, acc),\n {},\n );\n\n return { columns, axes };\n}\n\n/** Drop filter leaves whose column references cannot be resolved; rewrite the\n * resolvable ones through the resolver. Prune empty and/or/not groups. */\nfunction filterFilters(\n filters: Nil | PlDataTableFilters,\n resolver: ColumnResolver,\n): Nil | PlDataTableFilters {\n if (isNil(filters)) return filters;\n\n const rewriteLeaf = (leaf: PlDataTableFilterSpecLeaf): Nil | PlDataTableFilterSpecLeaf => {\n if (leaf.type === undefined) return leaf;\n const result = { ...leaf };\n if (\"column\" in result) {\n const c = resolver(result.column);\n if (isNil(c)) return undefined;\n result.column = c;\n }\n if (\"rhs\" in result) {\n const c = resolver(result.rhs);\n if (isNil(c)) return undefined;\n result.rhs = c;\n }\n return result;\n };\n\n const prune = (node: PlDataTableFilterNode): Nil | PlDataTableFilterNode => {\n if (node.type === \"and\" || node.type === \"or\") {\n const kept = node.filters\n .map((f) => prune(f))\n .filter((f): f is PlDataTableFilterNode => !isNil(f));\n if (kept.length === 0) return undefined;\n return { type: node.type, filters: kept };\n }\n if (node.type === \"not\") {\n const inner = prune(node.filter);\n return isNil(inner) ? undefined : { type: \"not\", filter: inner };\n }\n return rewriteLeaf(node);\n };\n\n return prune(filters) as Nil | PlDataTableFilters;\n}\n\n/** Merge two filter trees into one AND-combined tree. Returns the non-nil one if the other is nil.\n * Exported for unit testing. */\nexport function concatFilters(\n a: Nil | PlDataTableFilters,\n b: Nil | PlDataTableFilters,\n): Nil | PlDataTableFilters {\n if (isNil(a)) return b;\n if (isNil(b)) return a;\n const operands = (f: PlDataTableFilters): PlDataTableFilterNode[] =>\n f.type === \"and\" ? f.filters : [f as PlDataTableFilterNode];\n return { type: \"and\", filters: [...operands(a), ...operands(b)] };\n}\n\n/** Pick user sorting from state if set, otherwise fall back to options default.\n * null = user has not touched sorting → use default;\n * [] = user has explicitly cleared sorting → no sorting (default ignored). */\nfunction resolveSorting(\n userSorting: Nil | PTableSorting[],\n defaultSorting: Nil | PTableSorting[],\n): PTableSorting[] {\n return (isNil(userSorting) ? defaultSorting : userSorting) ?? [];\n}\n\n/** Rewrite sorting entries through the resolver; drop those that fail to resolve. */\nfunction filterSorting(sorting: PTableSorting[], resolver: ColumnResolver): PTableSorting[] {\n return sorting.flatMap((s) => {\n const col = resolver(s.column);\n return isNil(col) ? [] : [{ ...s, column: col }];\n });\n}\n\n/** Determine which columns should be hidden based on state or optional-column defaults.\n * Keyed by the recipe's logical {@link ColumnUniversalId} (rich) — variants of\n * the same physical column are independently visible/hidden. */\nfunction computeHiddenColumns(params: {\n columns: ColumnRecipe[];\n visibilityByColId: Map<PObjectId, ColumnVisibilityRule>;\n sorting: Nil | PTableSorting[];\n filters: Nil | PlDataTableFilters;\n hiddenSpecs: Nil | PTableColumnId[];\n}): Set<ColumnUniversalId> {\n const { columns, visibilityByColId, sorting, filters, hiddenSpecs } = params;\n const visibilityOf = (c: ColumnRecipe) =>\n getEffectiveVisibility(toRuleColumn(c), visibilityByColId);\n const alwaysHidden = columns.filter((c) => visibilityOf(c) === \"hidden\").map((c) => c.id);\n const optionalHidden = !isNil(hiddenSpecs)\n ? hiddenSpecs.filter((s): s is PTableColumnIdColumn => s.type === \"column\").map((s) => s.id)\n : columns.filter((c) => visibilityOf(c) === \"optional\").map((c) => c.id);\n const initial = [...alwaysHidden, ...optionalHidden];\n const preserved = collectPreservedColumnIds(sorting, filters);\n\n return new Set(initial.filter((id) => !preserved.has(id)));\n}\n\n/** Collect IDs of columns that must remain visible (sorted, filtered). */\nfunction collectPreservedColumnIds(\n sorting: Nil | PTableSorting[],\n filters: Nil | PlDataTableFilters,\n): Set<ColumnUniversalId> {\n const sortedIds = (sorting ?? [])\n .map((s) => s.column)\n .filter((c): c is PTableColumnIdColumn => c.type === \"column\")\n .map((c) => c.id);\n\n const filterIds = !isNil(filters)\n ? collectFilterSpecColumns(filters).flatMap((c) => (c.type === \"column\" ? [c.id] : []))\n : [];\n\n return new Set<ColumnUniversalId>([...sortedIds, ...filterIds]);\n}\n\n/** Remap column references in sorting entries through the resolver.\n * Unresolved entries are dropped with a warning (best-effort contract). */\nfunction remapSortingColumnIds(\n sorting: Nil | PTableSorting[],\n resolver: ColumnResolver,\n): Nil | PTableSorting[] {\n return sorting?.flatMap((s) => {\n const col = resolver(s.column);\n if (isNil(col)) {\n console.warn(\n `Sorting column ${JSON.stringify(s.column)} does not match any discovered column — dropped.`,\n );\n return [];\n }\n return [{ ...s, column: col }];\n });\n}\n\ntype PlDataTableFilterNode = FilterSpecNode<PlDataTableFilterSpecLeaf>;\n\n/** Remap column references in a filter tree through the resolver.\n * Unresolved leaves are dropped with a warning; empty groups are pruned. */\nfunction remapFilterColumnIds(\n filters: Nil | PlDataTableFilters,\n resolver: ColumnResolver,\n): Nil | PlDataTableFilters {\n if (isNil(filters)) return filters;\n\n const mapLeaf = (leaf: PlDataTableFilterSpecLeaf): Nil | PlDataTableFilterSpecLeaf => {\n if (leaf.type === undefined) return leaf;\n const result = { ...leaf };\n if (\"column\" in result) {\n const c = resolver(result.column);\n if (isNil(c)) {\n console.warn(\n `Filter column ${JSON.stringify(result.column)} does not match any discovered column — dropped.`,\n );\n return undefined;\n }\n result.column = c;\n }\n if (\"rhs\" in result) {\n const c = resolver(result.rhs);\n if (isNil(c)) {\n console.warn(\n `Filter rhs ${JSON.stringify(result.rhs)} does not match any discovered column — dropped.`,\n );\n return undefined;\n }\n result.rhs = c;\n }\n return result;\n };\n\n const prune = (node: PlDataTableFilterNode): Nil | PlDataTableFilterNode => {\n if (node.type === \"and\" || node.type === \"or\") {\n const kept = node.filters\n .map((f) => prune(f))\n .filter((f): f is PlDataTableFilterNode => !isNil(f));\n if (kept.length === 0) return undefined;\n return { type: node.type, filters: kept };\n }\n if (node.type === \"not\") {\n const inner = prune(node.filter);\n return isNil(inner) ? undefined : { type: \"not\", filter: inner };\n }\n return mapLeaf(node);\n };\n\n return prune(filters) as Nil | PlDataTableFilters;\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { collectLinkerColumns,
|
|
1
|
+
import { collectLinkerColumns, hasSingleDataColumn, hitQualifications, queriesQualifications } from "../../../columns/utils.js";
|
|
2
2
|
import "../../../columns/index.js";
|
|
3
3
|
import { collectFilterSpecColumns } from "../../../filters/traverse.js";
|
|
4
4
|
import { upgradePlDataTableStateV2 } from "../state-migration.js";
|
|
@@ -122,7 +122,7 @@ function resolveInputColumns(ctx, options) {
|
|
|
122
122
|
function splitByTopology(columns) {
|
|
123
123
|
const direct = [];
|
|
124
124
|
const linked = [];
|
|
125
|
-
for (const c of columns) if (
|
|
125
|
+
for (const c of columns) if (hasSingleDataColumn(c)) direct.push(c);
|
|
126
126
|
else linked.push(c);
|
|
127
127
|
return {
|
|
128
128
|
direct,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createPlDataTableV3.js","names":[],"sources":["../../../../src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts"],"sourcesContent":["import type {\n ColumnUniversalId,\n FilterSpecNode,\n PObjectId,\n PTableColumnId,\n PTableColumnIdColumn,\n PTableSorting,\n MultiColumnSelector,\n ColumnSelector,\n} from \"@milaboratories/pl-model-common\";\nimport {\n canonicalizeAxisId,\n dedupColumns,\n extractPObjectId,\n uniqueBy,\n} from \"@milaboratories/pl-model-common\";\nimport { collectFilterSpecColumns } from \"../../../filters/traverse\";\nimport { createColumnResolver, type ColumnResolver } from \"../columnResolver\";\nimport type { RenderCtxBase } from \"../../../render\";\nimport type {\n PlDataTableColumnsMeta,\n PlDataTableFilters,\n PlDataTableFilterSpecLeaf,\n PlDataTableModel,\n} from \"../typesV8\";\nimport { upgradePlDataTableStateV2 } from \"../state-migration\";\nimport type { PlDataTableStateV2 } from \"../state-migration\";\nimport type { MatchingMode } from \"@milaboratories/pl-model-common\";\nimport {\n isLeafColumn,\n hitQualifications,\n collectLinkerColumns,\n queriesQualifications,\n type ColumnRecipe,\n} from \"../../../columns\";\nimport type { DeriveLabelsOptions } from \"../../../labels/derive_distinct_labels\";\nimport {\n deriveAllLabels,\n evaluateRules,\n getEffectiveVisibility,\n getOrderPriority,\n isColumnHidden,\n buildDataStatusMap,\n toRuleColumn,\n} from \"./utils\";\nimport { createPTableDefV3 } from \"./createPTableDefV3\";\nimport {\n discoverLabelColumns,\n discoverTableColumns,\n type DiscoverTableColumnOptions,\n} from \"./discoverColumns\";\nimport { isNil, isPlainObject, type Nil } from \"@milaboratories/helpers\";\nimport { uniq } from \"es-toolkit\";\n\nexport type createPlDataTableOptionsV3 = (\n | {\n columns: Nil | DiscoverTableColumnOptions;\n }\n | {\n primaryColumns: ColumnRecipe[];\n columns: Nil | ColumnRecipe[];\n }\n) & {\n tableState?: PlDataTableStateV2;\n\n filters?: PlDataTableFilters;\n sorting?: PTableSorting[];\n primaryJoinType?: \"inner\" | \"full\";\n\n labelsOptions?: DeriveLabelsOptions;\n displayOptions?: ColumnsDisplayOptions;\n};\n\n/** Structured source config — selectors/anchors instead of raw ColumnsSource. */\nexport type ColumnsSelectorConfig = {\n include?: MultiColumnSelector | MultiColumnSelector[];\n exclude?: MultiColumnSelector | MultiColumnSelector[];\n mode?: MatchingMode;\n maxHops?: number;\n};\n\nexport type ColumnsDisplayOptions = {\n /** Column ordering rules. Higher priority = further left. First matching rule wins. */\n ordering?: ColumnOrderRule[];\n /** Column visibility rules. First matching rule wins. Unmatched columns use default visibility. */\n visibility?: ColumnVisibilityRule[];\n};\n\nexport type ColumnOrderRule = {\n match: ColumnSelector;\n /** Higher number = further left in table */\n priority: number;\n};\n\nexport type ColumnVisibilityRule = {\n match: ColumnSelector;\n visibility: \"default\" | \"optional\" | \"hidden\";\n};\n\nexport function createPlDataTableV3<A, U>(\n ctx: RenderCtxBase<A, U>,\n options: createPlDataTableOptionsV3,\n): PlDataTableModel | undefined {\n const state = upgradePlDataTableStateV2(options.tableState);\n const primaryJoinType = options.primaryJoinType ?? \"full\";\n\n const resolved = resolveInputColumns(ctx, options);\n if (resolved === undefined) return undefined;\n const { primary, secondary } = resolved;\n if (primary.length === 0) return undefined;\n\n const { direct, linked } = splitByTopology(secondary);\n\n const allColumns = [...primary, ...secondary];\n const derivedLabels = deriveAllLabels({\n // Skip hidden columns when deriving labels — they don't appear in the\n // table, so they shouldn't influence label disambiguation (#1623).\n columns: allColumns.filter((c) => !isColumnHidden(c.getSpec())).map(toLabelableColumn),\n deriveLabelsOptions: {\n includeNativeLabel: true,\n ...options.labelsOptions,\n },\n });\n\n // Rule-based visibility/order maps (keyed by bare PObjectId). Computed once\n // here: `computeHiddenColumns` needs visibility to decide the visible set,\n // and `buildColumnsMeta` (below, once the visible set is known) reuses both.\n const allColumnsForRules = [...primary, ...direct, ...linked, ...collectLinkerSnapshots(linked)];\n const visibilityByColId = evaluateRules(\n options.displayOptions?.visibility ?? [],\n allColumnsForRules,\n );\n const orderByColId = evaluateRules(options.displayOptions?.ordering ?? [], allColumnsForRules);\n\n const resolver = createColumnResolver(\n [...primary, ...direct, ...linked.flatMap((lc) => [...collectLinkerColumns(lc), lc])],\n { warn: ctx.logWarn.bind(ctx) },\n );\n\n const remapedDefaultFilters = remapFilterColumnIds(options.filters, resolver);\n const filters = filterFilters(\n concatFilters(\n state.pTableParams.filters,\n state.pTableParams.defaultFilters ?? remapedDefaultFilters,\n ),\n resolver,\n );\n\n const sorting = filterSorting(\n resolveSorting(state.pTableParams.sorting, remapSortingColumnIds(options.sorting, resolver)),\n resolver,\n );\n\n const fullDef = createPTableDefV3({\n primaryJoinType,\n primary,\n secondary: [...direct, ...linked],\n filters,\n sorting,\n });\n\n const fullHandle = ctx.createPTableV2(fullDef);\n // TODO: is workaround for dropdown suggestions.\n // Pframe have not equivalent data for columns relativly to Ptable.\n // PFrame is the physical column registry — one entry per bare PObjectId,\n // so strip the rich recipe ids down to their physical leaf id and dedupe:\n // multiple discovered variants of the same hit collapse to the same bare id.\n const pframeHandle = ctx.createPFrame(\n uniq([\n ...primary.map((v) => extractPObjectId(v.id)),\n ...direct.map((v) => extractPObjectId(v.id)),\n ...linked.map((v) => extractPObjectId(v.id)),\n ]),\n );\n\n const hiddenSpecs = state.pTableParams.hiddenColIds;\n const hiddenColumnIds = computeHiddenColumns({\n columns: [...primary, ...direct, ...linked],\n visibilityByColId,\n sorting,\n filters,\n hiddenSpecs,\n });\n\n const visible = {\n primary,\n direct: direct.filter((c) => !hiddenColumnIds.has(c.id)),\n linked: linked.filter((c) => !hiddenColumnIds.has(c.id)),\n };\n const visibleDef = createPTableDefV3({\n primaryJoinType,\n primary,\n secondary: [...visible.direct, ...visible.linked],\n filters,\n sorting,\n });\n const visibleHandle = ctx.createPTableV2(visibleDef);\n\n // Built here, where the visible set is known: per-column data status is\n // computed for visible columns only (the probe is meaningful only for what\n // the user sees), while label/visibility/order/axes cover all columns.\n const columnsMeta = buildColumnsMeta({\n fullColumns: [...primary, ...direct, ...linked],\n visibleColumns: [...visible.primary, ...visible.direct, ...visible.linked],\n primaryColumns: primary,\n derivedLabels,\n visibilityByColId,\n orderByColId,\n });\n\n return {\n sourceId: state.pTableParams.sourceId,\n fullTableHandle: fullHandle,\n fullPframeHandle: pframeHandle,\n visibleTableHandle: visibleHandle,\n defaultFilters: remapedDefaultFilters,\n columnsMeta,\n } satisfies PlDataTableModel;\n}\n\ntype ResolvedColumns = {\n readonly primary: ColumnRecipe[];\n readonly secondary: ColumnRecipe[];\n};\n\n/** Normalize either option branch into a {primary, secondary} pair of recipes. */\nfunction resolveInputColumns<A, U>(\n ctx: RenderCtxBase<A, U>,\n options: createPlDataTableOptionsV3,\n): undefined | ResolvedColumns {\n if (\"primaryColumns\" in options) {\n const primary = options.primaryColumns;\n const secondary = options.columns ?? [];\n const labels = discoverLabelColumns(ctx, primary);\n // Exclude from secondary anything already present in primary: a label\n // column the block hands in as primary can be re-discovered here as a\n // label for that same axis, landing in the table twice with the same id.\n const primaryIds = new Set(primary.map((c) => c.id));\n return {\n primary,\n secondary: dedupColumns(\n [...secondary, ...labels].filter((c) => !primaryIds.has(c.id)),\n (c) => c.id,\n (c) => c.getSpec(),\n ),\n };\n }\n\n if (isPlainObject(options.columns)) {\n return discoverTableColumns(ctx, options.columns);\n }\n\n return undefined;\n}\n\n/** Split secondary recipes by query topology: leaves (no linker chain) vs joined. */\nfunction splitByTopology(columns: ColumnRecipe[]): {\n direct: ColumnRecipe[];\n linked: ColumnRecipe[];\n} {\n const direct: ColumnRecipe[] = [];\n const linked: ColumnRecipe[] = [];\n for (const c of columns) {\n if (isLeafColumn(c)) direct.push(c);\n else linked.push(c);\n }\n return { direct, linked };\n}\n\n/** All linker recipes across the given linked columns, deduped by id. */\nfunction collectLinkerSnapshots(linked: ColumnRecipe[]): ColumnRecipe[] {\n return uniqueBy(\n linked.flatMap((c) => collectLinkerColumns(c)),\n (c) => c.id,\n );\n}\n\nfunction toLabelableColumn(col: ColumnRecipe) {\n return {\n id: col.id,\n spec: col.getSpec(),\n linkerPath: collectLinkerColumns(col).map((linker) => ({\n linker: { spec: linker.getSpec() },\n })),\n qualifications: {\n forHit: [...hitQualifications(col)],\n forQueries: queriesQualifications(col),\n },\n };\n}\n\n/**\n * Compute display metadata as a sidecar keyed by each emitted column's\n * `ColumnUniversalId` (and axis `AxisId`), instead of baking it into the specs\n * via `withSpecs`. Spec overrides change a recipe's id, so the same physical\n * column reached two ways would diverge into two ids and render twice; keeping\n * meta out of the spec preserves identity and lets dedup collapse such cases.\n * The UI overlays this onto the engine-emitted specs at render time.\n */\nfunction buildColumnsMeta(params: {\n /** Every column in the table (primary + secondary) — drives `columns` and `axes`. */\n fullColumns: ColumnRecipe[];\n /** The visible subset — `status` is probed for these only. */\n visibleColumns: ColumnRecipe[];\n /** The primary join columns — their axes are the visible index; all other axes are hidden. */\n primaryColumns: ColumnRecipe[];\n derivedLabels: Record<string, string>;\n visibilityByColId: Map<PObjectId, ColumnVisibilityRule>;\n orderByColId: Map<PObjectId, ColumnOrderRule>;\n}): PlDataTableColumnsMeta {\n const { fullColumns, visibleColumns, primaryColumns, derivedLabels } = params;\n const { visibilityByColId, orderByColId } = params;\n // Status only for visible columns — the probe is meaningful only for what the\n // user actually sees; non-visible columns get no `status`.\n const visibleStatus = buildDataStatusMap(visibleColumns);\n\n const columns = fullColumns.reduce<PlDataTableColumnsMeta[\"columns\"]>((acc, c) => {\n const rc = toRuleColumn(c);\n acc[c.id] = {\n label: derivedLabels[c.id],\n visibility: getEffectiveVisibility(rc, visibilityByColId),\n order: getOrderPriority(rc, orderByColId),\n status: visibleStatus[c.id],\n };\n return acc;\n }, {});\n\n // Only primary columns declare the table's visible axes. Any axis introduced\n // solely by a secondary column (a linker-bridge axis, or a distinct-domain\n // copy) is flagged hidden — otherwise it renders as a second index axis.\n const primaryAxisKeys = new Set(\n primaryColumns.flatMap((c) => c.getSpec().axesSpec.map((a) => canonicalizeAxisId(a))),\n );\n const axes = fullColumns.reduce<PlDataTableColumnsMeta[\"axes\"]>(\n (acc, c) =>\n c.getSpec().axesSpec.reduce((inner, ax) => {\n const key = canonicalizeAxisId(ax);\n if (inner[key] === undefined) inner[key] = { hidden: !primaryAxisKeys.has(key) };\n return inner;\n }, acc),\n {},\n );\n\n return { columns, axes };\n}\n\n/** Drop filter leaves whose column references cannot be resolved; rewrite the\n * resolvable ones through the resolver. Prune empty and/or/not groups. */\nfunction filterFilters(\n filters: Nil | PlDataTableFilters,\n resolver: ColumnResolver,\n): Nil | PlDataTableFilters {\n if (isNil(filters)) return filters;\n\n const rewriteLeaf = (leaf: PlDataTableFilterSpecLeaf): Nil | PlDataTableFilterSpecLeaf => {\n if (leaf.type === undefined) return leaf;\n const result = { ...leaf };\n if (\"column\" in result) {\n const c = resolver(result.column);\n if (isNil(c)) return undefined;\n result.column = c;\n }\n if (\"rhs\" in result) {\n const c = resolver(result.rhs);\n if (isNil(c)) return undefined;\n result.rhs = c;\n }\n return result;\n };\n\n const prune = (node: PlDataTableFilterNode): Nil | PlDataTableFilterNode => {\n if (node.type === \"and\" || node.type === \"or\") {\n const kept = node.filters\n .map((f) => prune(f))\n .filter((f): f is PlDataTableFilterNode => !isNil(f));\n if (kept.length === 0) return undefined;\n return { type: node.type, filters: kept };\n }\n if (node.type === \"not\") {\n const inner = prune(node.filter);\n return isNil(inner) ? undefined : { type: \"not\", filter: inner };\n }\n return rewriteLeaf(node);\n };\n\n return prune(filters) as Nil | PlDataTableFilters;\n}\n\n/** Merge two filter trees into one AND-combined tree. Returns the non-nil one if the other is nil.\n * Exported for unit testing. */\nexport function concatFilters(\n a: Nil | PlDataTableFilters,\n b: Nil | PlDataTableFilters,\n): Nil | PlDataTableFilters {\n if (isNil(a)) return b;\n if (isNil(b)) return a;\n const operands = (f: PlDataTableFilters): PlDataTableFilterNode[] =>\n f.type === \"and\" ? f.filters : [f as PlDataTableFilterNode];\n return { type: \"and\", filters: [...operands(a), ...operands(b)] };\n}\n\n/** Pick user sorting from state if set, otherwise fall back to options default.\n * null = user has not touched sorting → use default;\n * [] = user has explicitly cleared sorting → no sorting (default ignored). */\nfunction resolveSorting(\n userSorting: Nil | PTableSorting[],\n defaultSorting: Nil | PTableSorting[],\n): PTableSorting[] {\n return (isNil(userSorting) ? defaultSorting : userSorting) ?? [];\n}\n\n/** Rewrite sorting entries through the resolver; drop those that fail to resolve. */\nfunction filterSorting(sorting: PTableSorting[], resolver: ColumnResolver): PTableSorting[] {\n return sorting.flatMap((s) => {\n const col = resolver(s.column);\n return isNil(col) ? [] : [{ ...s, column: col }];\n });\n}\n\n/** Determine which columns should be hidden based on state or optional-column defaults.\n * Keyed by the recipe's logical {@link ColumnUniversalId} (rich) — variants of\n * the same physical column are independently visible/hidden. */\nfunction computeHiddenColumns(params: {\n columns: ColumnRecipe[];\n visibilityByColId: Map<PObjectId, ColumnVisibilityRule>;\n sorting: Nil | PTableSorting[];\n filters: Nil | PlDataTableFilters;\n hiddenSpecs: Nil | PTableColumnId[];\n}): Set<ColumnUniversalId> {\n const { columns, visibilityByColId, sorting, filters, hiddenSpecs } = params;\n const visibilityOf = (c: ColumnRecipe) =>\n getEffectiveVisibility(toRuleColumn(c), visibilityByColId);\n const alwaysHidden = columns.filter((c) => visibilityOf(c) === \"hidden\").map((c) => c.id);\n const optionalHidden = !isNil(hiddenSpecs)\n ? hiddenSpecs.filter((s): s is PTableColumnIdColumn => s.type === \"column\").map((s) => s.id)\n : columns.filter((c) => visibilityOf(c) === \"optional\").map((c) => c.id);\n const initial = [...alwaysHidden, ...optionalHidden];\n const preserved = collectPreservedColumnIds(sorting, filters);\n\n return new Set(initial.filter((id) => !preserved.has(id)));\n}\n\n/** Collect IDs of columns that must remain visible (sorted, filtered). */\nfunction collectPreservedColumnIds(\n sorting: Nil | PTableSorting[],\n filters: Nil | PlDataTableFilters,\n): Set<ColumnUniversalId> {\n const sortedIds = (sorting ?? [])\n .map((s) => s.column)\n .filter((c): c is PTableColumnIdColumn => c.type === \"column\")\n .map((c) => c.id);\n\n const filterIds = !isNil(filters)\n ? collectFilterSpecColumns(filters).flatMap((c) => (c.type === \"column\" ? [c.id] : []))\n : [];\n\n return new Set<ColumnUniversalId>([...sortedIds, ...filterIds]);\n}\n\n/** Remap column references in sorting entries through the resolver.\n * Unresolved entries are dropped with a warning (best-effort contract). */\nfunction remapSortingColumnIds(\n sorting: Nil | PTableSorting[],\n resolver: ColumnResolver,\n): Nil | PTableSorting[] {\n return sorting?.flatMap((s) => {\n const col = resolver(s.column);\n if (isNil(col)) {\n console.warn(\n `Sorting column ${JSON.stringify(s.column)} does not match any discovered column — dropped.`,\n );\n return [];\n }\n return [{ ...s, column: col }];\n });\n}\n\ntype PlDataTableFilterNode = FilterSpecNode<PlDataTableFilterSpecLeaf>;\n\n/** Remap column references in a filter tree through the resolver.\n * Unresolved leaves are dropped with a warning; empty groups are pruned. */\nfunction remapFilterColumnIds(\n filters: Nil | PlDataTableFilters,\n resolver: ColumnResolver,\n): Nil | PlDataTableFilters {\n if (isNil(filters)) return filters;\n\n const mapLeaf = (leaf: PlDataTableFilterSpecLeaf): Nil | PlDataTableFilterSpecLeaf => {\n if (leaf.type === undefined) return leaf;\n const result = { ...leaf };\n if (\"column\" in result) {\n const c = resolver(result.column);\n if (isNil(c)) {\n console.warn(\n `Filter column ${JSON.stringify(result.column)} does not match any discovered column — dropped.`,\n );\n return undefined;\n }\n result.column = c;\n }\n if (\"rhs\" in result) {\n const c = resolver(result.rhs);\n if (isNil(c)) {\n console.warn(\n `Filter rhs ${JSON.stringify(result.rhs)} does not match any discovered column — dropped.`,\n );\n return undefined;\n }\n result.rhs = c;\n }\n return result;\n };\n\n const prune = (node: PlDataTableFilterNode): Nil | PlDataTableFilterNode => {\n if (node.type === \"and\" || node.type === \"or\") {\n const kept = node.filters\n .map((f) => prune(f))\n .filter((f): f is PlDataTableFilterNode => !isNil(f));\n if (kept.length === 0) return undefined;\n return { type: node.type, filters: kept };\n }\n if (node.type === \"not\") {\n const inner = prune(node.filter);\n return isNil(inner) ? undefined : { type: \"not\", filter: inner };\n }\n return mapLeaf(node);\n };\n\n return prune(filters) as Nil | PlDataTableFilters;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createPlDataTableV3.js","names":[],"sources":["../../../../src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts"],"sourcesContent":["import type {\n ColumnUniversalId,\n FilterSpecNode,\n PObjectId,\n PTableColumnId,\n PTableColumnIdColumn,\n PTableSorting,\n MultiColumnSelector,\n ColumnSelector,\n} from \"@milaboratories/pl-model-common\";\nimport {\n canonicalizeAxisId,\n dedupColumns,\n extractPObjectId,\n uniqueBy,\n} from \"@milaboratories/pl-model-common\";\nimport { collectFilterSpecColumns } from \"../../../filters/traverse\";\nimport { createColumnResolver, type ColumnResolver } from \"../columnResolver\";\nimport type { RenderCtxBase } from \"../../../render\";\nimport type {\n PlDataTableColumnsMeta,\n PlDataTableFilters,\n PlDataTableFilterSpecLeaf,\n PlDataTableModel,\n} from \"../typesV8\";\nimport { upgradePlDataTableStateV2 } from \"../state-migration\";\nimport type { PlDataTableStateV2 } from \"../state-migration\";\nimport type { MatchingMode } from \"@milaboratories/pl-model-common\";\nimport {\n hasSingleDataColumn,\n hitQualifications,\n collectLinkerColumns,\n queriesQualifications,\n type ColumnRecipe,\n} from \"../../../columns\";\nimport type { DeriveLabelsOptions } from \"../../../labels/derive_distinct_labels\";\nimport {\n deriveAllLabels,\n evaluateRules,\n getEffectiveVisibility,\n getOrderPriority,\n isColumnHidden,\n buildDataStatusMap,\n toRuleColumn,\n} from \"./utils\";\nimport { createPTableDefV3 } from \"./createPTableDefV3\";\nimport {\n discoverLabelColumns,\n discoverTableColumns,\n type DiscoverTableColumnOptions,\n} from \"./discoverColumns\";\nimport { isNil, isPlainObject, type Nil } from \"@milaboratories/helpers\";\nimport { uniq } from \"es-toolkit\";\n\nexport type createPlDataTableOptionsV3 = (\n | {\n columns: Nil | DiscoverTableColumnOptions;\n }\n | {\n primaryColumns: ColumnRecipe[];\n columns: Nil | ColumnRecipe[];\n }\n) & {\n tableState?: PlDataTableStateV2;\n\n filters?: PlDataTableFilters;\n sorting?: PTableSorting[];\n primaryJoinType?: \"inner\" | \"full\";\n\n labelsOptions?: DeriveLabelsOptions;\n displayOptions?: ColumnsDisplayOptions;\n};\n\n/** Structured source config — selectors/anchors instead of raw ColumnsSource. */\nexport type ColumnsSelectorConfig = {\n include?: MultiColumnSelector | MultiColumnSelector[];\n exclude?: MultiColumnSelector | MultiColumnSelector[];\n mode?: MatchingMode;\n maxHops?: number;\n};\n\nexport type ColumnsDisplayOptions = {\n /** Column ordering rules. Higher priority = further left. First matching rule wins. */\n ordering?: ColumnOrderRule[];\n /** Column visibility rules. First matching rule wins. Unmatched columns use default visibility. */\n visibility?: ColumnVisibilityRule[];\n};\n\nexport type ColumnOrderRule = {\n match: ColumnSelector;\n /** Higher number = further left in table */\n priority: number;\n};\n\nexport type ColumnVisibilityRule = {\n match: ColumnSelector;\n visibility: \"default\" | \"optional\" | \"hidden\";\n};\n\nexport function createPlDataTableV3<A, U>(\n ctx: RenderCtxBase<A, U>,\n options: createPlDataTableOptionsV3,\n): PlDataTableModel | undefined {\n const state = upgradePlDataTableStateV2(options.tableState);\n const primaryJoinType = options.primaryJoinType ?? \"full\";\n\n const resolved = resolveInputColumns(ctx, options);\n if (resolved === undefined) return undefined;\n const { primary, secondary } = resolved;\n if (primary.length === 0) return undefined;\n\n const { direct, linked } = splitByTopology(secondary);\n\n const allColumns = [...primary, ...secondary];\n const derivedLabels = deriveAllLabels({\n // Skip hidden columns when deriving labels — they don't appear in the\n // table, so they shouldn't influence label disambiguation (#1623).\n columns: allColumns.filter((c) => !isColumnHidden(c.getSpec())).map(toLabelableColumn),\n deriveLabelsOptions: {\n includeNativeLabel: true,\n ...options.labelsOptions,\n },\n });\n\n // Rule-based visibility/order maps (keyed by bare PObjectId). Computed once\n // here: `computeHiddenColumns` needs visibility to decide the visible set,\n // and `buildColumnsMeta` (below, once the visible set is known) reuses both.\n const allColumnsForRules = [...primary, ...direct, ...linked, ...collectLinkerSnapshots(linked)];\n const visibilityByColId = evaluateRules(\n options.displayOptions?.visibility ?? [],\n allColumnsForRules,\n );\n const orderByColId = evaluateRules(options.displayOptions?.ordering ?? [], allColumnsForRules);\n\n const resolver = createColumnResolver(\n [...primary, ...direct, ...linked.flatMap((lc) => [...collectLinkerColumns(lc), lc])],\n { warn: ctx.logWarn.bind(ctx) },\n );\n\n const remapedDefaultFilters = remapFilterColumnIds(options.filters, resolver);\n const filters = filterFilters(\n concatFilters(\n state.pTableParams.filters,\n state.pTableParams.defaultFilters ?? remapedDefaultFilters,\n ),\n resolver,\n );\n\n const sorting = filterSorting(\n resolveSorting(state.pTableParams.sorting, remapSortingColumnIds(options.sorting, resolver)),\n resolver,\n );\n\n const fullDef = createPTableDefV3({\n primaryJoinType,\n primary,\n secondary: [...direct, ...linked],\n filters,\n sorting,\n });\n\n const fullHandle = ctx.createPTableV2(fullDef);\n // TODO: is workaround for dropdown suggestions.\n // Pframe have not equivalent data for columns relativly to Ptable.\n // PFrame is the physical column registry — one entry per bare PObjectId,\n // so strip the rich recipe ids down to their physical leaf id and dedupe:\n // multiple discovered variants of the same hit collapse to the same bare id.\n const pframeHandle = ctx.createPFrame(\n uniq([\n ...primary.map((v) => extractPObjectId(v.id)),\n ...direct.map((v) => extractPObjectId(v.id)),\n ...linked.map((v) => extractPObjectId(v.id)),\n ]),\n );\n\n const hiddenSpecs = state.pTableParams.hiddenColIds;\n const hiddenColumnIds = computeHiddenColumns({\n columns: [...primary, ...direct, ...linked],\n visibilityByColId,\n sorting,\n filters,\n hiddenSpecs,\n });\n\n const visible = {\n primary,\n direct: direct.filter((c) => !hiddenColumnIds.has(c.id)),\n linked: linked.filter((c) => !hiddenColumnIds.has(c.id)),\n };\n const visibleDef = createPTableDefV3({\n primaryJoinType,\n primary,\n secondary: [...visible.direct, ...visible.linked],\n filters,\n sorting,\n });\n const visibleHandle = ctx.createPTableV2(visibleDef);\n\n // Built here, where the visible set is known: per-column data status is\n // computed for visible columns only (the probe is meaningful only for what\n // the user sees), while label/visibility/order/axes cover all columns.\n const columnsMeta = buildColumnsMeta({\n fullColumns: [...primary, ...direct, ...linked],\n visibleColumns: [...visible.primary, ...visible.direct, ...visible.linked],\n primaryColumns: primary,\n derivedLabels,\n visibilityByColId,\n orderByColId,\n });\n\n return {\n sourceId: state.pTableParams.sourceId,\n fullTableHandle: fullHandle,\n fullPframeHandle: pframeHandle,\n visibleTableHandle: visibleHandle,\n defaultFilters: remapedDefaultFilters,\n columnsMeta,\n } satisfies PlDataTableModel;\n}\n\ntype ResolvedColumns = {\n readonly primary: ColumnRecipe[];\n readonly secondary: ColumnRecipe[];\n};\n\n/** Normalize either option branch into a {primary, secondary} pair of recipes. */\nfunction resolveInputColumns<A, U>(\n ctx: RenderCtxBase<A, U>,\n options: createPlDataTableOptionsV3,\n): undefined | ResolvedColumns {\n if (\"primaryColumns\" in options) {\n const primary = options.primaryColumns;\n const secondary = options.columns ?? [];\n const labels = discoverLabelColumns(ctx, primary);\n // Exclude from secondary anything already present in primary: a label\n // column the block hands in as primary can be re-discovered here as a\n // label for that same axis, landing in the table twice with the same id.\n const primaryIds = new Set(primary.map((c) => c.id));\n return {\n primary,\n secondary: dedupColumns(\n [...secondary, ...labels].filter((c) => !primaryIds.has(c.id)),\n (c) => c.id,\n (c) => c.getSpec(),\n ),\n };\n }\n\n if (isPlainObject(options.columns)) {\n return discoverTableColumns(ctx, options.columns);\n }\n\n return undefined;\n}\n\n/** Split secondary recipes by query topology: leaves (no linker chain) vs joined. */\nfunction splitByTopology(columns: ColumnRecipe[]): {\n direct: ColumnRecipe[];\n linked: ColumnRecipe[];\n} {\n const direct: ColumnRecipe[] = [];\n const linked: ColumnRecipe[] = [];\n for (const c of columns) {\n if (hasSingleDataColumn(c)) direct.push(c);\n else linked.push(c);\n }\n return { direct, linked };\n}\n\n/** All linker recipes across the given linked columns, deduped by id. */\nfunction collectLinkerSnapshots(linked: ColumnRecipe[]): ColumnRecipe[] {\n return uniqueBy(\n linked.flatMap((c) => collectLinkerColumns(c)),\n (c) => c.id,\n );\n}\n\nfunction toLabelableColumn(col: ColumnRecipe) {\n return {\n id: col.id,\n spec: col.getSpec(),\n linkerPath: collectLinkerColumns(col).map((linker) => ({\n linker: { spec: linker.getSpec() },\n })),\n qualifications: {\n forHit: [...hitQualifications(col)],\n forQueries: queriesQualifications(col),\n },\n };\n}\n\n/**\n * Compute display metadata as a sidecar keyed by each emitted column's\n * `ColumnUniversalId` (and axis `AxisId`), instead of baking it into the specs\n * via `withSpecs`. Spec overrides change a recipe's id, so the same physical\n * column reached two ways would diverge into two ids and render twice; keeping\n * meta out of the spec preserves identity and lets dedup collapse such cases.\n * The UI overlays this onto the engine-emitted specs at render time.\n */\nfunction buildColumnsMeta(params: {\n /** Every column in the table (primary + secondary) — drives `columns` and `axes`. */\n fullColumns: ColumnRecipe[];\n /** The visible subset — `status` is probed for these only. */\n visibleColumns: ColumnRecipe[];\n /** The primary join columns — their axes are the visible index; all other axes are hidden. */\n primaryColumns: ColumnRecipe[];\n derivedLabels: Record<string, string>;\n visibilityByColId: Map<PObjectId, ColumnVisibilityRule>;\n orderByColId: Map<PObjectId, ColumnOrderRule>;\n}): PlDataTableColumnsMeta {\n const { fullColumns, visibleColumns, primaryColumns, derivedLabels } = params;\n const { visibilityByColId, orderByColId } = params;\n // Status only for visible columns — the probe is meaningful only for what the\n // user actually sees; non-visible columns get no `status`.\n const visibleStatus = buildDataStatusMap(visibleColumns);\n\n const columns = fullColumns.reduce<PlDataTableColumnsMeta[\"columns\"]>((acc, c) => {\n const rc = toRuleColumn(c);\n acc[c.id] = {\n label: derivedLabels[c.id],\n visibility: getEffectiveVisibility(rc, visibilityByColId),\n order: getOrderPriority(rc, orderByColId),\n status: visibleStatus[c.id],\n };\n return acc;\n }, {});\n\n // Only primary columns declare the table's visible axes. Any axis introduced\n // solely by a secondary column (a linker-bridge axis, or a distinct-domain\n // copy) is flagged hidden — otherwise it renders as a second index axis.\n const primaryAxisKeys = new Set(\n primaryColumns.flatMap((c) => c.getSpec().axesSpec.map((a) => canonicalizeAxisId(a))),\n );\n const axes = fullColumns.reduce<PlDataTableColumnsMeta[\"axes\"]>(\n (acc, c) =>\n c.getSpec().axesSpec.reduce((inner, ax) => {\n const key = canonicalizeAxisId(ax);\n if (inner[key] === undefined) inner[key] = { hidden: !primaryAxisKeys.has(key) };\n return inner;\n }, acc),\n {},\n );\n\n return { columns, axes };\n}\n\n/** Drop filter leaves whose column references cannot be resolved; rewrite the\n * resolvable ones through the resolver. Prune empty and/or/not groups. */\nfunction filterFilters(\n filters: Nil | PlDataTableFilters,\n resolver: ColumnResolver,\n): Nil | PlDataTableFilters {\n if (isNil(filters)) return filters;\n\n const rewriteLeaf = (leaf: PlDataTableFilterSpecLeaf): Nil | PlDataTableFilterSpecLeaf => {\n if (leaf.type === undefined) return leaf;\n const result = { ...leaf };\n if (\"column\" in result) {\n const c = resolver(result.column);\n if (isNil(c)) return undefined;\n result.column = c;\n }\n if (\"rhs\" in result) {\n const c = resolver(result.rhs);\n if (isNil(c)) return undefined;\n result.rhs = c;\n }\n return result;\n };\n\n const prune = (node: PlDataTableFilterNode): Nil | PlDataTableFilterNode => {\n if (node.type === \"and\" || node.type === \"or\") {\n const kept = node.filters\n .map((f) => prune(f))\n .filter((f): f is PlDataTableFilterNode => !isNil(f));\n if (kept.length === 0) return undefined;\n return { type: node.type, filters: kept };\n }\n if (node.type === \"not\") {\n const inner = prune(node.filter);\n return isNil(inner) ? undefined : { type: \"not\", filter: inner };\n }\n return rewriteLeaf(node);\n };\n\n return prune(filters) as Nil | PlDataTableFilters;\n}\n\n/** Merge two filter trees into one AND-combined tree. Returns the non-nil one if the other is nil.\n * Exported for unit testing. */\nexport function concatFilters(\n a: Nil | PlDataTableFilters,\n b: Nil | PlDataTableFilters,\n): Nil | PlDataTableFilters {\n if (isNil(a)) return b;\n if (isNil(b)) return a;\n const operands = (f: PlDataTableFilters): PlDataTableFilterNode[] =>\n f.type === \"and\" ? f.filters : [f as PlDataTableFilterNode];\n return { type: \"and\", filters: [...operands(a), ...operands(b)] };\n}\n\n/** Pick user sorting from state if set, otherwise fall back to options default.\n * null = user has not touched sorting → use default;\n * [] = user has explicitly cleared sorting → no sorting (default ignored). */\nfunction resolveSorting(\n userSorting: Nil | PTableSorting[],\n defaultSorting: Nil | PTableSorting[],\n): PTableSorting[] {\n return (isNil(userSorting) ? defaultSorting : userSorting) ?? [];\n}\n\n/** Rewrite sorting entries through the resolver; drop those that fail to resolve. */\nfunction filterSorting(sorting: PTableSorting[], resolver: ColumnResolver): PTableSorting[] {\n return sorting.flatMap((s) => {\n const col = resolver(s.column);\n return isNil(col) ? [] : [{ ...s, column: col }];\n });\n}\n\n/** Determine which columns should be hidden based on state or optional-column defaults.\n * Keyed by the recipe's logical {@link ColumnUniversalId} (rich) — variants of\n * the same physical column are independently visible/hidden. */\nfunction computeHiddenColumns(params: {\n columns: ColumnRecipe[];\n visibilityByColId: Map<PObjectId, ColumnVisibilityRule>;\n sorting: Nil | PTableSorting[];\n filters: Nil | PlDataTableFilters;\n hiddenSpecs: Nil | PTableColumnId[];\n}): Set<ColumnUniversalId> {\n const { columns, visibilityByColId, sorting, filters, hiddenSpecs } = params;\n const visibilityOf = (c: ColumnRecipe) =>\n getEffectiveVisibility(toRuleColumn(c), visibilityByColId);\n const alwaysHidden = columns.filter((c) => visibilityOf(c) === \"hidden\").map((c) => c.id);\n const optionalHidden = !isNil(hiddenSpecs)\n ? hiddenSpecs.filter((s): s is PTableColumnIdColumn => s.type === \"column\").map((s) => s.id)\n : columns.filter((c) => visibilityOf(c) === \"optional\").map((c) => c.id);\n const initial = [...alwaysHidden, ...optionalHidden];\n const preserved = collectPreservedColumnIds(sorting, filters);\n\n return new Set(initial.filter((id) => !preserved.has(id)));\n}\n\n/** Collect IDs of columns that must remain visible (sorted, filtered). */\nfunction collectPreservedColumnIds(\n sorting: Nil | PTableSorting[],\n filters: Nil | PlDataTableFilters,\n): Set<ColumnUniversalId> {\n const sortedIds = (sorting ?? [])\n .map((s) => s.column)\n .filter((c): c is PTableColumnIdColumn => c.type === \"column\")\n .map((c) => c.id);\n\n const filterIds = !isNil(filters)\n ? collectFilterSpecColumns(filters).flatMap((c) => (c.type === \"column\" ? [c.id] : []))\n : [];\n\n return new Set<ColumnUniversalId>([...sortedIds, ...filterIds]);\n}\n\n/** Remap column references in sorting entries through the resolver.\n * Unresolved entries are dropped with a warning (best-effort contract). */\nfunction remapSortingColumnIds(\n sorting: Nil | PTableSorting[],\n resolver: ColumnResolver,\n): Nil | PTableSorting[] {\n return sorting?.flatMap((s) => {\n const col = resolver(s.column);\n if (isNil(col)) {\n console.warn(\n `Sorting column ${JSON.stringify(s.column)} does not match any discovered column — dropped.`,\n );\n return [];\n }\n return [{ ...s, column: col }];\n });\n}\n\ntype PlDataTableFilterNode = FilterSpecNode<PlDataTableFilterSpecLeaf>;\n\n/** Remap column references in a filter tree through the resolver.\n * Unresolved leaves are dropped with a warning; empty groups are pruned. */\nfunction remapFilterColumnIds(\n filters: Nil | PlDataTableFilters,\n resolver: ColumnResolver,\n): Nil | PlDataTableFilters {\n if (isNil(filters)) return filters;\n\n const mapLeaf = (leaf: PlDataTableFilterSpecLeaf): Nil | PlDataTableFilterSpecLeaf => {\n if (leaf.type === undefined) return leaf;\n const result = { ...leaf };\n if (\"column\" in result) {\n const c = resolver(result.column);\n if (isNil(c)) {\n console.warn(\n `Filter column ${JSON.stringify(result.column)} does not match any discovered column — dropped.`,\n );\n return undefined;\n }\n result.column = c;\n }\n if (\"rhs\" in result) {\n const c = resolver(result.rhs);\n if (isNil(c)) {\n console.warn(\n `Filter rhs ${JSON.stringify(result.rhs)} does not match any discovered column — dropped.`,\n );\n return undefined;\n }\n result.rhs = c;\n }\n return result;\n };\n\n const prune = (node: PlDataTableFilterNode): Nil | PlDataTableFilterNode => {\n if (node.type === \"and\" || node.type === \"or\") {\n const kept = node.filters\n .map((f) => prune(f))\n .filter((f): f is PlDataTableFilterNode => !isNil(f));\n if (kept.length === 0) return undefined;\n return { type: node.type, filters: kept };\n }\n if (node.type === \"not\") {\n const inner = prune(node.filter);\n return isNil(inner) ? undefined : { type: \"not\", filter: inner };\n }\n return mapLeaf(node);\n };\n\n return prune(filters) as Nil | PlDataTableFilters;\n}\n"],"mappings":"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"}
|
|
@@ -15,7 +15,7 @@ function discoverTableColumns(ctx, options) {
|
|
|
15
15
|
}).getColumns();
|
|
16
16
|
const primary = [];
|
|
17
17
|
const secondary = [];
|
|
18
|
-
for (const col of discoveredColumns) if (require_utils.
|
|
18
|
+
for (const col of discoveredColumns) if (require_utils.hasSingleDataColumn(col)) primary.push(col);
|
|
19
19
|
else secondary.push(col);
|
|
20
20
|
return {
|
|
21
21
|
primary,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discoverColumns.cjs","names":["ColumnsCollection","
|
|
1
|
+
{"version":3,"file":"discoverColumns.cjs","names":["ColumnsCollection","hasSingleDataColumn","PColumnName"],"sources":["../../../../src/components/PlDataTable/createPlDataTable/discoverColumns.ts"],"sourcesContent":["import type {\n PColumnSpec,\n PlRef,\n PObjectId,\n RelaxedColumnSelector,\n} from \"@milaboratories/pl-model-common\";\nimport { PColumnName } from \"@milaboratories/pl-model-common\";\nimport type { RenderCtxBase } from \"../../../render\";\nimport type { ColumnRecipe, ColumnsSource } from \"../../../columns\";\nimport { ColumnsCollection, hasSingleDataColumn } from \"../../../columns\";\nimport type { ColumnsSelectorConfig } from \"./createPlDataTableV3\";\n\nexport type DiscoverTableColumnOptions = {\n sources?: ColumnsSource[];\n anchors: Record<string, PlRef | PObjectId | PColumnSpec | RelaxedColumnSelector>;\n selector: ColumnsSelectorConfig;\n};\n\n/** Split of discovered columns into anchor-matching (primary) and the rest. */\nexport type DiscoveredTableColumns = {\n readonly primary: ColumnRecipe[];\n readonly secondary: ColumnRecipe[];\n};\n\n/**\n * Discover columns from sources/anchors and split them into primary\n * (direct anchor hits — zero-hop, query is a bare column) and secondary\n * (reached via a linker chain, query carries a join).\n */\nexport function discoverTableColumns(\n ctx: RenderCtxBase,\n options: DiscoverTableColumnOptions,\n): DiscoveredTableColumns {\n const discoveredColumns = ColumnsCollection(options.sources, { ctx: ctx.ctx })\n .discover({ ...options.selector, anchors: options.anchors })\n .getColumns();\n\n const primary: ColumnRecipe[] = [];\n const secondary: ColumnRecipe[] = [];\n for (const col of discoveredColumns) {\n if (hasSingleDataColumn(col)) primary.push(col);\n else secondary.push(col);\n }\n return { primary, secondary };\n}\n\n/**\n * Discover label columns matching the axes of the given value columns from\n * ctx providers. Returns a list of label {@link ColumnRecipe}s.\n *\n * Primary columns are used as anchors for axis-aware label discovery.\n * `maxHops` is taken from the longest linker chain present in `columns`.\n */\nexport function discoverLabelColumns<A, U>(\n ctx: RenderCtxBase<A, U>,\n primary: ColumnRecipe[],\n): ColumnRecipe[] {\n if (primary.length === 0) return [];\n\n const axes = primary.flatMap((col) => col.getSpec().axesSpec);\n return ColumnsCollection(undefined, { ctx: ctx.ctx })\n .discover({\n include: axes.map((a) => ({\n name: { type: \"exact\", value: PColumnName.Label },\n axes: [{ name: { type: \"exact\", value: a.name } }],\n })),\n anchors: Object.fromEntries(primary.map((col, i) => [`anchor_${i}`, col.getSpec()])),\n maxHops: 0,\n })\n .getColumns();\n}\n"],"mappings":";;;;;;;;;;AA6BA,SAAgB,qBACd,KACA,SACwB;CACxB,MAAM,oBAAoBA,2BAAAA,kBAAkB,QAAQ,SAAS,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,CAC3E,SAAS;EAAE,GAAG,QAAQ;EAAU,SAAS,QAAQ;CAAQ,CAAC,CAAC,CAC3D,WAAW;CAEd,MAAM,UAA0B,CAAC;CACjC,MAAM,YAA4B,CAAC;CACnC,KAAK,MAAM,OAAO,mBAChB,IAAIC,cAAAA,oBAAoB,GAAG,GAAG,QAAQ,KAAK,GAAG;MACzC,UAAU,KAAK,GAAG;CAEzB,OAAO;EAAE;EAAS;CAAU;AAC9B;;;;;;;;AASA,SAAgB,qBACd,KACA,SACgB;CAChB,IAAI,QAAQ,WAAW,GAAG,OAAO,CAAC;CAElC,MAAM,OAAO,QAAQ,SAAS,QAAQ,IAAI,QAAQ,CAAC,CAAC,QAAQ;CAC5D,OAAOD,2BAAAA,kBAAkB,KAAA,GAAW,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,CAClD,SAAS;EACR,SAAS,KAAK,KAAK,OAAO;GACxB,MAAM;IAAE,MAAM;IAAS,OAAOE,gCAAAA,YAAY;GAAM;GAChD,MAAM,CAAC,EAAE,MAAM;IAAE,MAAM;IAAS,OAAO,EAAE;GAAK,EAAE,CAAC;EACnD,EAAE;EACF,SAAS,OAAO,YAAY,QAAQ,KAAK,KAAK,MAAM,CAAC,UAAU,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC;EACnF,SAAS;CACX,CAAC,CAAC,CACD,WAAW;AAChB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ColumnsCollection } from "../../../columns/columns_collection.js";
|
|
2
|
-
import {
|
|
2
|
+
import { hasSingleDataColumn } from "../../../columns/utils.js";
|
|
3
3
|
import "../../../columns/index.js";
|
|
4
4
|
import { PColumnName } from "@milaboratories/pl-model-common";
|
|
5
5
|
//#region src/components/PlDataTable/createPlDataTable/discoverColumns.ts
|
|
@@ -15,7 +15,7 @@ function discoverTableColumns(ctx, options) {
|
|
|
15
15
|
}).getColumns();
|
|
16
16
|
const primary = [];
|
|
17
17
|
const secondary = [];
|
|
18
|
-
for (const col of discoveredColumns) if (
|
|
18
|
+
for (const col of discoveredColumns) if (hasSingleDataColumn(col)) primary.push(col);
|
|
19
19
|
else secondary.push(col);
|
|
20
20
|
return {
|
|
21
21
|
primary,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discoverColumns.js","names":[],"sources":["../../../../src/components/PlDataTable/createPlDataTable/discoverColumns.ts"],"sourcesContent":["import type {\n PColumnSpec,\n PlRef,\n PObjectId,\n RelaxedColumnSelector,\n} from \"@milaboratories/pl-model-common\";\nimport { PColumnName } from \"@milaboratories/pl-model-common\";\nimport type { RenderCtxBase } from \"../../../render\";\nimport type { ColumnRecipe, ColumnsSource } from \"../../../columns\";\nimport { ColumnsCollection,
|
|
1
|
+
{"version":3,"file":"discoverColumns.js","names":[],"sources":["../../../../src/components/PlDataTable/createPlDataTable/discoverColumns.ts"],"sourcesContent":["import type {\n PColumnSpec,\n PlRef,\n PObjectId,\n RelaxedColumnSelector,\n} from \"@milaboratories/pl-model-common\";\nimport { PColumnName } from \"@milaboratories/pl-model-common\";\nimport type { RenderCtxBase } from \"../../../render\";\nimport type { ColumnRecipe, ColumnsSource } from \"../../../columns\";\nimport { ColumnsCollection, hasSingleDataColumn } from \"../../../columns\";\nimport type { ColumnsSelectorConfig } from \"./createPlDataTableV3\";\n\nexport type DiscoverTableColumnOptions = {\n sources?: ColumnsSource[];\n anchors: Record<string, PlRef | PObjectId | PColumnSpec | RelaxedColumnSelector>;\n selector: ColumnsSelectorConfig;\n};\n\n/** Split of discovered columns into anchor-matching (primary) and the rest. */\nexport type DiscoveredTableColumns = {\n readonly primary: ColumnRecipe[];\n readonly secondary: ColumnRecipe[];\n};\n\n/**\n * Discover columns from sources/anchors and split them into primary\n * (direct anchor hits — zero-hop, query is a bare column) and secondary\n * (reached via a linker chain, query carries a join).\n */\nexport function discoverTableColumns(\n ctx: RenderCtxBase,\n options: DiscoverTableColumnOptions,\n): DiscoveredTableColumns {\n const discoveredColumns = ColumnsCollection(options.sources, { ctx: ctx.ctx })\n .discover({ ...options.selector, anchors: options.anchors })\n .getColumns();\n\n const primary: ColumnRecipe[] = [];\n const secondary: ColumnRecipe[] = [];\n for (const col of discoveredColumns) {\n if (hasSingleDataColumn(col)) primary.push(col);\n else secondary.push(col);\n }\n return { primary, secondary };\n}\n\n/**\n * Discover label columns matching the axes of the given value columns from\n * ctx providers. Returns a list of label {@link ColumnRecipe}s.\n *\n * Primary columns are used as anchors for axis-aware label discovery.\n * `maxHops` is taken from the longest linker chain present in `columns`.\n */\nexport function discoverLabelColumns<A, U>(\n ctx: RenderCtxBase<A, U>,\n primary: ColumnRecipe[],\n): ColumnRecipe[] {\n if (primary.length === 0) return [];\n\n const axes = primary.flatMap((col) => col.getSpec().axesSpec);\n return ColumnsCollection(undefined, { ctx: ctx.ctx })\n .discover({\n include: axes.map((a) => ({\n name: { type: \"exact\", value: PColumnName.Label },\n axes: [{ name: { type: \"exact\", value: a.name } }],\n })),\n anchors: Object.fromEntries(primary.map((col, i) => [`anchor_${i}`, col.getSpec()])),\n maxHops: 0,\n })\n .getColumns();\n}\n"],"mappings":";;;;;;;;;;AA6BA,SAAgB,qBACd,KACA,SACwB;CACxB,MAAM,oBAAoB,kBAAkB,QAAQ,SAAS,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,CAC3E,SAAS;EAAE,GAAG,QAAQ;EAAU,SAAS,QAAQ;CAAQ,CAAC,CAAC,CAC3D,WAAW;CAEd,MAAM,UAA0B,CAAC;CACjC,MAAM,YAA4B,CAAC;CACnC,KAAK,MAAM,OAAO,mBAChB,IAAI,oBAAoB,GAAG,GAAG,QAAQ,KAAK,GAAG;MACzC,UAAU,KAAK,GAAG;CAEzB,OAAO;EAAE;EAAS;CAAU;AAC9B;;;;;;;;AASA,SAAgB,qBACd,KACA,SACgB;CAChB,IAAI,QAAQ,WAAW,GAAG,OAAO,CAAC;CAElC,MAAM,OAAO,QAAQ,SAAS,QAAQ,IAAI,QAAQ,CAAC,CAAC,QAAQ;CAC5D,OAAO,kBAAkB,KAAA,GAAW,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,CAClD,SAAS;EACR,SAAS,KAAK,KAAK,OAAO;GACxB,MAAM;IAAE,MAAM;IAAS,OAAO,YAAY;GAAM;GAChD,MAAM,CAAC,EAAE,MAAM;IAAE,MAAM;IAAS,OAAO,EAAE;GAAK,EAAE,CAAC;EACnD,EAAE;EACF,SAAS,OAAO,YAAY,QAAQ,KAAK,KAAK,MAAM,CAAC,UAAU,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC;EACnF,SAAS;CACX,CAAC,CAAC,CACD,WAAW;AAChB"}
|
|
@@ -57,7 +57,7 @@ function evaluateRules(rules, columns) {
|
|
|
57
57
|
}]);
|
|
58
58
|
for (const rule of selectorRules) {
|
|
59
59
|
const hitIds = baseCollection.filter({ include: rule.match }).getColumnIds();
|
|
60
|
-
if (hitIds.length === 0)
|
|
60
|
+
if (hitIds.length === 0) continue;
|
|
61
61
|
selectorHitsByRule.set(rule, new Set(hitIds.map((id) => (0, _milaboratories_pl_model_common.extractPObjectId)(id))));
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs","names":["Annotation","ColumnsCollection","hasColumnData","deriveDistinctLabels"],"sources":["../../../../src/components/PlDataTable/createPlDataTable/utils.ts"],"sourcesContent":["import {\n type AnnotationDataStatus,\n type ColumnUniversalId,\n type PColumn,\n type PColumnSpec,\n type PObjectId,\n Annotation,\n extractPObjectId,\n readAnnotation,\n} from \"@milaboratories/pl-model-common\";\nimport {\n deriveDistinctLabels,\n type DeriveLabelsOptions,\n} from \"../../../labels/derive_distinct_labels\";\nimport {\n deriveDistinctTooltips,\n type TooltipEntry,\n} from \"../../../labels/derive_distinct_tooltips\";\nimport type { ColumnOrderRule, ColumnVisibilityRule } from \"./createPlDataTableV3\";\nimport type { ColumnSelector, MatchQualifications } from \"@milaboratories/pl-model-common\";\nimport { ColumnsCollection, hasColumnData, type ColumnRecipe } from \"../../../columns\";\nimport type { GlobalCfgRenderCtx } from \"../../../render/internal\";\nimport { isNil, uniqBy } from \"es-toolkit\";\nimport { getField } from \"@milaboratories/helpers\";\n\n/** Adapt a {@link ColumnRecipe} to the plain {@link RuleColumn} shape. */\nexport function toRuleColumn(col: ColumnRecipe): RuleColumn {\n return { id: extractPObjectId(col.id), spec: col.getSpec() };\n}\n\n/** Check if column should be omitted from the table */\nexport function isColumnHidden(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"hidden\";\n}\n\n/** Check if column is hidden by default */\nexport function isColumnOptional(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"optional\";\n}\n\n/** Column shape consumed by rule evaluation. */\nexport type RuleColumn = Pick<PColumn<PObjectId>, \"id\" | \"spec\">;\n\n/** Get effective visibility for a column. Rule map lookup first, then annotation fallback. */\nexport function getEffectiveVisibility(\n col: RuleColumn,\n visibilityByColId?: Map<PObjectId, ColumnVisibilityRule>,\n): undefined | \"default\" | \"optional\" | \"hidden\" {\n const rule = visibilityByColId?.get(col.id);\n if (rule !== undefined) return rule.visibility;\n if (isColumnHidden(col.spec)) return \"hidden\";\n if (isColumnOptional(col.spec)) return \"optional\";\n return undefined;\n}\n\n/** Get ordering priority for a column. Rule map lookup first, then annotation fallback. */\nexport function getOrderPriority(\n col: RuleColumn,\n orderByColId?: Map<PObjectId, ColumnOrderRule>,\n): undefined | number {\n const rule = orderByColId?.get(col.id);\n if (rule !== undefined) return rule.priority;\n const annotation = Number(readAnnotation(col.spec, Annotation.Table.OrderPriority));\n return isNaN(annotation) ? undefined : annotation;\n}\n\n/**\n * Evaluate display rules against a set of columns and return a map of `colId → winning rule`\n * (first-match-wins, preserving original rule order).\n *\n * Predicate-based rules (`ColumnMatcher`) are evaluated directly on the spec.\n * Selector-based rules (`ColumnSelector`) are matched via the\n * `columnsCollection` service — the inline column ids must be resolvable in\n * the active render ctx for the host to read their specs.\n */\nexport function evaluateRules<R extends { match: ColumnSelector }>(\n rules: R[],\n columns: ColumnRecipe[],\n): Map<PObjectId, R> {\n const result = new Map<PObjectId, R>();\n if (rules.length === 0 || columns.length === 0) return result;\n\n const selectorRules = rules.filter((rule) => typeof rule.match !== \"function\");\n const selectorHitsByRule = new Map<R, Set<PObjectId>>();\n\n if (selectorRules.length > 0) {\n const baseColumns = uniqBy(columns, (col) => col.id);\n const baseCollection = ColumnsCollection([{ columns: baseColumns, isFinal: true }]);\n for (const rule of selectorRules) {\n const hitIds = baseCollection.filter({ include: rule.match }).getColumnIds();\n if (hitIds.length === 0) return result;\n selectorHitsByRule.set(rule, new Set(hitIds.map((id) => extractPObjectId(id))));\n }\n }\n\n for (const col of columns) {\n const colKey = extractPObjectId(col.id);\n for (const rule of rules) {\n const matches = selectorHitsByRule.get(rule)?.has(colKey) ?? false;\n if (matches) {\n result.set(colKey, rule);\n break;\n }\n }\n }\n return result;\n}\n\n/**\n * Build a sidecar map `columnId → AnnotationDataStatus` derived from each\n * recipe's own status. This is *rendering* metadata — kept out of the spec\n * so it cannot perturb column identity (id-bearing spec overrides would\n * diverge the visible PTable's column ids from the full table / pframe).\n *\n * Mapping `ColumnFieldStatus` × actual byte-presence → `AnnotationDataStatus`:\n * - `absent` → `\"absent\"`\n * - `resolving` → `\"computing\"`\n * - `present` + `hasColumnData()` → `\"ready\"`\n * - `present` + no bytes yet → `\"computing\"`\n *\n * Intentionally scoped to visible columns — the probe is meaningful only for\n * what the user will actually see.\n */\nexport function buildDataStatusMap(\n columns: ColumnRecipe[],\n opts: { ctx?: GlobalCfgRenderCtx } = {},\n): Record<ColumnUniversalId, AnnotationDataStatus> {\n return columns.reduce(\n (acc, c) => ((acc[c.id] = deriveDataStatus(c, opts)), acc),\n {} as Record<ColumnUniversalId, AnnotationDataStatus>,\n );\n}\n\nfunction deriveDataStatus(\n column: ColumnRecipe,\n opts: { ctx?: GlobalCfgRenderCtx },\n): AnnotationDataStatus {\n const field = column.getDataStatus();\n if (field === \"absent\") return \"absent\";\n if (field === \"resolving\") return \"computing\";\n return hasColumnData(column, opts) ? \"ready\" : \"computing\";\n}\n\n/** Column shape required by label derivation. */\nexport type LabelableColumn = {\n readonly id: ColumnUniversalId;\n readonly spec: PColumnSpec;\n readonly linkerPath?: ReadonlyArray<{ readonly linker: { readonly spec: PColumnSpec } }>;\n readonly qualifications?: MatchQualifications;\n};\n\n/** Derive labels for all table elements: columns via deriveDistinctLabels, axes from label columns. */\nexport function deriveAllLabels(options: {\n columns: LabelableColumn[];\n deriveLabelsOptions?: DeriveLabelsOptions;\n}): Record<string, string> {\n const { columns, deriveLabelsOptions } = options;\n const entries = columns.map((c) => ({\n spec: c.spec,\n linkerPath: c.linkerPath?.map((step) => ({ spec: step.linker.spec })),\n qualifications: c.qualifications,\n }));\n const columnLabels = deriveDistinctLabels(entries, deriveLabelsOptions).reduce(\n (acc, label, index) => ((acc[columns[index].id] = label), acc),\n {} as Record<string, string>,\n );\n return columnLabels;\n}\n\n/** Column shape required by tooltip derivation. */\nexport type TooltipableColumn = {\n readonly id: ColumnUniversalId;\n readonly spec: PColumnSpec;\n readonly originalId?: PObjectId;\n readonly linkerPath?: ReadonlyArray<{ readonly linker: { readonly spec: PColumnSpec } }>;\n readonly qualifications?: MatchQualifications;\n};\n\n/** Derive origin tooltips for columns whose qualifications or linker path carry info. */\nexport function deriveAllTooltips(options: {\n columns: TooltipableColumn[];\n}): Record<ColumnUniversalId, string> {\n const { columns } = options;\n\n const variantCountByOriginal = columns.reduce<Map<ColumnUniversalId, number>>((acc, c) => {\n return acc.set(getField(c, \"originalId\") ?? c.id, (acc.get(c.originalId ?? c.id) ?? 0) + 1);\n }, new Map());\n\n const { entries } = columns.reduce(\n ({ entries, variantSeen }, c) => {\n const id = getField(c, \"originalId\") ?? c.id;\n const variantCount = variantCountByOriginal.get(id);\n const variantIndex =\n (variantSeen.set(id, (variantSeen.get(id) ?? 0) + 1), variantSeen.get(id));\n\n entries.push({\n spec: c.spec,\n linkerPath: c.linkerPath,\n qualifications: c.qualifications,\n variantIndex,\n variantCount,\n });\n\n return { entries, variantSeen };\n },\n { entries: [] as TooltipEntry[], variantSeen: new Map<ColumnUniversalId, number>() },\n );\n\n const tooltips = deriveDistinctTooltips(entries);\n\n return Object.fromEntries(\n tooltips.flatMap((t, i) => (isNil(t) ? [] : [[columns[i].id, t] as const])),\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.cjs","names":["Annotation","ColumnsCollection","hasColumnData","deriveDistinctLabels"],"sources":["../../../../src/components/PlDataTable/createPlDataTable/utils.ts"],"sourcesContent":["import {\n type AnnotationDataStatus,\n type ColumnUniversalId,\n type PColumn,\n type PColumnSpec,\n type PObjectId,\n Annotation,\n extractPObjectId,\n readAnnotation,\n} from \"@milaboratories/pl-model-common\";\nimport {\n deriveDistinctLabels,\n type DeriveLabelsOptions,\n} from \"../../../labels/derive_distinct_labels\";\nimport {\n deriveDistinctTooltips,\n type TooltipEntry,\n} from \"../../../labels/derive_distinct_tooltips\";\nimport type { ColumnOrderRule, ColumnVisibilityRule } from \"./createPlDataTableV3\";\nimport type { ColumnSelector, MatchQualifications } from \"@milaboratories/pl-model-common\";\nimport { ColumnsCollection, hasColumnData, type ColumnRecipe } from \"../../../columns\";\nimport type { GlobalCfgRenderCtx } from \"../../../render/internal\";\nimport { isNil, uniqBy } from \"es-toolkit\";\nimport { getField } from \"@milaboratories/helpers\";\n\n/** Adapt a {@link ColumnRecipe} to the plain {@link RuleColumn} shape. */\nexport function toRuleColumn(col: ColumnRecipe): RuleColumn {\n return { id: extractPObjectId(col.id), spec: col.getSpec() };\n}\n\n/** Check if column should be omitted from the table */\nexport function isColumnHidden(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"hidden\";\n}\n\n/** Check if column is hidden by default */\nexport function isColumnOptional(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"optional\";\n}\n\n/** Column shape consumed by rule evaluation. */\nexport type RuleColumn = Pick<PColumn<PObjectId>, \"id\" | \"spec\">;\n\n/** Get effective visibility for a column. Rule map lookup first, then annotation fallback. */\nexport function getEffectiveVisibility(\n col: RuleColumn,\n visibilityByColId?: Map<PObjectId, ColumnVisibilityRule>,\n): undefined | \"default\" | \"optional\" | \"hidden\" {\n const rule = visibilityByColId?.get(col.id);\n if (rule !== undefined) return rule.visibility;\n if (isColumnHidden(col.spec)) return \"hidden\";\n if (isColumnOptional(col.spec)) return \"optional\";\n return undefined;\n}\n\n/** Get ordering priority for a column. Rule map lookup first, then annotation fallback. */\nexport function getOrderPriority(\n col: RuleColumn,\n orderByColId?: Map<PObjectId, ColumnOrderRule>,\n): undefined | number {\n const rule = orderByColId?.get(col.id);\n if (rule !== undefined) return rule.priority;\n const annotation = Number(readAnnotation(col.spec, Annotation.Table.OrderPriority));\n return isNaN(annotation) ? undefined : annotation;\n}\n\n/**\n * Evaluate display rules against a set of columns and return a map of `colId → winning rule`\n * (first-match-wins, preserving original rule order).\n *\n * Predicate-based rules (`ColumnMatcher`) are evaluated directly on the spec.\n * Selector-based rules (`ColumnSelector`) are matched via the\n * `columnsCollection` service — the inline column ids must be resolvable in\n * the active render ctx for the host to read their specs.\n */\nexport function evaluateRules<R extends { match: ColumnSelector }>(\n rules: R[],\n columns: ColumnRecipe[],\n): Map<PObjectId, R> {\n const result = new Map<PObjectId, R>();\n if (rules.length === 0 || columns.length === 0) return result;\n\n const selectorRules = rules.filter((rule) => typeof rule.match !== \"function\");\n const selectorHitsByRule = new Map<R, Set<PObjectId>>();\n\n if (selectorRules.length > 0) {\n const baseColumns = uniqBy(columns, (col) => col.id);\n const baseCollection = ColumnsCollection([{ columns: baseColumns, isFinal: true }]);\n for (const rule of selectorRules) {\n const hitIds = baseCollection.filter({ include: rule.match }).getColumnIds();\n // A rule matching nothing simply contributes no entries — it must not\n // discard the rules evaluated alongside it. The lookup below is\n // null-safe, so leaving this rule out of the map is enough.\n if (hitIds.length === 0) continue;\n selectorHitsByRule.set(rule, new Set(hitIds.map((id) => extractPObjectId(id))));\n }\n }\n\n for (const col of columns) {\n const colKey = extractPObjectId(col.id);\n for (const rule of rules) {\n const matches = selectorHitsByRule.get(rule)?.has(colKey) ?? false;\n if (matches) {\n result.set(colKey, rule);\n break;\n }\n }\n }\n return result;\n}\n\n/**\n * Build a sidecar map `columnId → AnnotationDataStatus` derived from each\n * recipe's own status. This is *rendering* metadata — kept out of the spec\n * so it cannot perturb column identity (id-bearing spec overrides would\n * diverge the visible PTable's column ids from the full table / pframe).\n *\n * Mapping `ColumnFieldStatus` × actual byte-presence → `AnnotationDataStatus`:\n * - `absent` → `\"absent\"`\n * - `resolving` → `\"computing\"`\n * - `present` + `hasColumnData()` → `\"ready\"`\n * - `present` + no bytes yet → `\"computing\"`\n *\n * Intentionally scoped to visible columns — the probe is meaningful only for\n * what the user will actually see.\n */\nexport function buildDataStatusMap(\n columns: ColumnRecipe[],\n opts: { ctx?: GlobalCfgRenderCtx } = {},\n): Record<ColumnUniversalId, AnnotationDataStatus> {\n return columns.reduce(\n (acc, c) => ((acc[c.id] = deriveDataStatus(c, opts)), acc),\n {} as Record<ColumnUniversalId, AnnotationDataStatus>,\n );\n}\n\nfunction deriveDataStatus(\n column: ColumnRecipe,\n opts: { ctx?: GlobalCfgRenderCtx },\n): AnnotationDataStatus {\n const field = column.getDataStatus();\n if (field === \"absent\") return \"absent\";\n if (field === \"resolving\") return \"computing\";\n return hasColumnData(column, opts) ? \"ready\" : \"computing\";\n}\n\n/** Column shape required by label derivation. */\nexport type LabelableColumn = {\n readonly id: ColumnUniversalId;\n readonly spec: PColumnSpec;\n readonly linkerPath?: ReadonlyArray<{ readonly linker: { readonly spec: PColumnSpec } }>;\n readonly qualifications?: MatchQualifications;\n};\n\n/** Derive labels for all table elements: columns via deriveDistinctLabels, axes from label columns. */\nexport function deriveAllLabels(options: {\n columns: LabelableColumn[];\n deriveLabelsOptions?: DeriveLabelsOptions;\n}): Record<string, string> {\n const { columns, deriveLabelsOptions } = options;\n const entries = columns.map((c) => ({\n spec: c.spec,\n linkerPath: c.linkerPath?.map((step) => ({ spec: step.linker.spec })),\n qualifications: c.qualifications,\n }));\n const columnLabels = deriveDistinctLabels(entries, deriveLabelsOptions).reduce(\n (acc, label, index) => ((acc[columns[index].id] = label), acc),\n {} as Record<string, string>,\n );\n return columnLabels;\n}\n\n/** Column shape required by tooltip derivation. */\nexport type TooltipableColumn = {\n readonly id: ColumnUniversalId;\n readonly spec: PColumnSpec;\n readonly originalId?: PObjectId;\n readonly linkerPath?: ReadonlyArray<{ readonly linker: { readonly spec: PColumnSpec } }>;\n readonly qualifications?: MatchQualifications;\n};\n\n/** Derive origin tooltips for columns whose qualifications or linker path carry info. */\nexport function deriveAllTooltips(options: {\n columns: TooltipableColumn[];\n}): Record<ColumnUniversalId, string> {\n const { columns } = options;\n\n const variantCountByOriginal = columns.reduce<Map<ColumnUniversalId, number>>((acc, c) => {\n return acc.set(getField(c, \"originalId\") ?? c.id, (acc.get(c.originalId ?? c.id) ?? 0) + 1);\n }, new Map());\n\n const { entries } = columns.reduce(\n ({ entries, variantSeen }, c) => {\n const id = getField(c, \"originalId\") ?? c.id;\n const variantCount = variantCountByOriginal.get(id);\n const variantIndex =\n (variantSeen.set(id, (variantSeen.get(id) ?? 0) + 1), variantSeen.get(id));\n\n entries.push({\n spec: c.spec,\n linkerPath: c.linkerPath,\n qualifications: c.qualifications,\n variantIndex,\n variantCount,\n });\n\n return { entries, variantSeen };\n },\n { entries: [] as TooltipEntry[], variantSeen: new Map<ColumnUniversalId, number>() },\n );\n\n const tooltips = deriveDistinctTooltips(entries);\n\n return Object.fromEntries(\n tooltips.flatMap((t, i) => (isNil(t) ? [] : [[columns[i].id, t] as const])),\n );\n}\n"],"mappings":"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"}
|
|
@@ -57,7 +57,7 @@ function evaluateRules(rules, columns) {
|
|
|
57
57
|
}]);
|
|
58
58
|
for (const rule of selectorRules) {
|
|
59
59
|
const hitIds = baseCollection.filter({ include: rule.match }).getColumnIds();
|
|
60
|
-
if (hitIds.length === 0)
|
|
60
|
+
if (hitIds.length === 0) continue;
|
|
61
61
|
selectorHitsByRule.set(rule, new Set(hitIds.map((id) => extractPObjectId(id))));
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":[],"sources":["../../../../src/components/PlDataTable/createPlDataTable/utils.ts"],"sourcesContent":["import {\n type AnnotationDataStatus,\n type ColumnUniversalId,\n type PColumn,\n type PColumnSpec,\n type PObjectId,\n Annotation,\n extractPObjectId,\n readAnnotation,\n} from \"@milaboratories/pl-model-common\";\nimport {\n deriveDistinctLabels,\n type DeriveLabelsOptions,\n} from \"../../../labels/derive_distinct_labels\";\nimport {\n deriveDistinctTooltips,\n type TooltipEntry,\n} from \"../../../labels/derive_distinct_tooltips\";\nimport type { ColumnOrderRule, ColumnVisibilityRule } from \"./createPlDataTableV3\";\nimport type { ColumnSelector, MatchQualifications } from \"@milaboratories/pl-model-common\";\nimport { ColumnsCollection, hasColumnData, type ColumnRecipe } from \"../../../columns\";\nimport type { GlobalCfgRenderCtx } from \"../../../render/internal\";\nimport { isNil, uniqBy } from \"es-toolkit\";\nimport { getField } from \"@milaboratories/helpers\";\n\n/** Adapt a {@link ColumnRecipe} to the plain {@link RuleColumn} shape. */\nexport function toRuleColumn(col: ColumnRecipe): RuleColumn {\n return { id: extractPObjectId(col.id), spec: col.getSpec() };\n}\n\n/** Check if column should be omitted from the table */\nexport function isColumnHidden(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"hidden\";\n}\n\n/** Check if column is hidden by default */\nexport function isColumnOptional(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"optional\";\n}\n\n/** Column shape consumed by rule evaluation. */\nexport type RuleColumn = Pick<PColumn<PObjectId>, \"id\" | \"spec\">;\n\n/** Get effective visibility for a column. Rule map lookup first, then annotation fallback. */\nexport function getEffectiveVisibility(\n col: RuleColumn,\n visibilityByColId?: Map<PObjectId, ColumnVisibilityRule>,\n): undefined | \"default\" | \"optional\" | \"hidden\" {\n const rule = visibilityByColId?.get(col.id);\n if (rule !== undefined) return rule.visibility;\n if (isColumnHidden(col.spec)) return \"hidden\";\n if (isColumnOptional(col.spec)) return \"optional\";\n return undefined;\n}\n\n/** Get ordering priority for a column. Rule map lookup first, then annotation fallback. */\nexport function getOrderPriority(\n col: RuleColumn,\n orderByColId?: Map<PObjectId, ColumnOrderRule>,\n): undefined | number {\n const rule = orderByColId?.get(col.id);\n if (rule !== undefined) return rule.priority;\n const annotation = Number(readAnnotation(col.spec, Annotation.Table.OrderPriority));\n return isNaN(annotation) ? undefined : annotation;\n}\n\n/**\n * Evaluate display rules against a set of columns and return a map of `colId → winning rule`\n * (first-match-wins, preserving original rule order).\n *\n * Predicate-based rules (`ColumnMatcher`) are evaluated directly on the spec.\n * Selector-based rules (`ColumnSelector`) are matched via the\n * `columnsCollection` service — the inline column ids must be resolvable in\n * the active render ctx for the host to read their specs.\n */\nexport function evaluateRules<R extends { match: ColumnSelector }>(\n rules: R[],\n columns: ColumnRecipe[],\n): Map<PObjectId, R> {\n const result = new Map<PObjectId, R>();\n if (rules.length === 0 || columns.length === 0) return result;\n\n const selectorRules = rules.filter((rule) => typeof rule.match !== \"function\");\n const selectorHitsByRule = new Map<R, Set<PObjectId>>();\n\n if (selectorRules.length > 0) {\n const baseColumns = uniqBy(columns, (col) => col.id);\n const baseCollection = ColumnsCollection([{ columns: baseColumns, isFinal: true }]);\n for (const rule of selectorRules) {\n const hitIds = baseCollection.filter({ include: rule.match }).getColumnIds();\n if (hitIds.length === 0) return result;\n selectorHitsByRule.set(rule, new Set(hitIds.map((id) => extractPObjectId(id))));\n }\n }\n\n for (const col of columns) {\n const colKey = extractPObjectId(col.id);\n for (const rule of rules) {\n const matches = selectorHitsByRule.get(rule)?.has(colKey) ?? false;\n if (matches) {\n result.set(colKey, rule);\n break;\n }\n }\n }\n return result;\n}\n\n/**\n * Build a sidecar map `columnId → AnnotationDataStatus` derived from each\n * recipe's own status. This is *rendering* metadata — kept out of the spec\n * so it cannot perturb column identity (id-bearing spec overrides would\n * diverge the visible PTable's column ids from the full table / pframe).\n *\n * Mapping `ColumnFieldStatus` × actual byte-presence → `AnnotationDataStatus`:\n * - `absent` → `\"absent\"`\n * - `resolving` → `\"computing\"`\n * - `present` + `hasColumnData()` → `\"ready\"`\n * - `present` + no bytes yet → `\"computing\"`\n *\n * Intentionally scoped to visible columns — the probe is meaningful only for\n * what the user will actually see.\n */\nexport function buildDataStatusMap(\n columns: ColumnRecipe[],\n opts: { ctx?: GlobalCfgRenderCtx } = {},\n): Record<ColumnUniversalId, AnnotationDataStatus> {\n return columns.reduce(\n (acc, c) => ((acc[c.id] = deriveDataStatus(c, opts)), acc),\n {} as Record<ColumnUniversalId, AnnotationDataStatus>,\n );\n}\n\nfunction deriveDataStatus(\n column: ColumnRecipe,\n opts: { ctx?: GlobalCfgRenderCtx },\n): AnnotationDataStatus {\n const field = column.getDataStatus();\n if (field === \"absent\") return \"absent\";\n if (field === \"resolving\") return \"computing\";\n return hasColumnData(column, opts) ? \"ready\" : \"computing\";\n}\n\n/** Column shape required by label derivation. */\nexport type LabelableColumn = {\n readonly id: ColumnUniversalId;\n readonly spec: PColumnSpec;\n readonly linkerPath?: ReadonlyArray<{ readonly linker: { readonly spec: PColumnSpec } }>;\n readonly qualifications?: MatchQualifications;\n};\n\n/** Derive labels for all table elements: columns via deriveDistinctLabels, axes from label columns. */\nexport function deriveAllLabels(options: {\n columns: LabelableColumn[];\n deriveLabelsOptions?: DeriveLabelsOptions;\n}): Record<string, string> {\n const { columns, deriveLabelsOptions } = options;\n const entries = columns.map((c) => ({\n spec: c.spec,\n linkerPath: c.linkerPath?.map((step) => ({ spec: step.linker.spec })),\n qualifications: c.qualifications,\n }));\n const columnLabels = deriveDistinctLabels(entries, deriveLabelsOptions).reduce(\n (acc, label, index) => ((acc[columns[index].id] = label), acc),\n {} as Record<string, string>,\n );\n return columnLabels;\n}\n\n/** Column shape required by tooltip derivation. */\nexport type TooltipableColumn = {\n readonly id: ColumnUniversalId;\n readonly spec: PColumnSpec;\n readonly originalId?: PObjectId;\n readonly linkerPath?: ReadonlyArray<{ readonly linker: { readonly spec: PColumnSpec } }>;\n readonly qualifications?: MatchQualifications;\n};\n\n/** Derive origin tooltips for columns whose qualifications or linker path carry info. */\nexport function deriveAllTooltips(options: {\n columns: TooltipableColumn[];\n}): Record<ColumnUniversalId, string> {\n const { columns } = options;\n\n const variantCountByOriginal = columns.reduce<Map<ColumnUniversalId, number>>((acc, c) => {\n return acc.set(getField(c, \"originalId\") ?? c.id, (acc.get(c.originalId ?? c.id) ?? 0) + 1);\n }, new Map());\n\n const { entries } = columns.reduce(\n ({ entries, variantSeen }, c) => {\n const id = getField(c, \"originalId\") ?? c.id;\n const variantCount = variantCountByOriginal.get(id);\n const variantIndex =\n (variantSeen.set(id, (variantSeen.get(id) ?? 0) + 1), variantSeen.get(id));\n\n entries.push({\n spec: c.spec,\n linkerPath: c.linkerPath,\n qualifications: c.qualifications,\n variantIndex,\n variantCount,\n });\n\n return { entries, variantSeen };\n },\n { entries: [] as TooltipEntry[], variantSeen: new Map<ColumnUniversalId, number>() },\n );\n\n const tooltips = deriveDistinctTooltips(entries);\n\n return Object.fromEntries(\n tooltips.flatMap((t, i) => (isNil(t) ? [] : [[columns[i].id, t] as const])),\n );\n}\n"],"mappings":";;;;;;;;;;AA0BA,SAAgB,aAAa,KAA+B;CAC1D,OAAO;EAAE,IAAI,iBAAiB,IAAI,EAAE;EAAG,MAAM,IAAI,QAAQ;CAAE;AAC7D;;AAGA,SAAgB,eAAe,MAA6C;CAC1E,OAAO,eAAe,MAAM,WAAW,MAAM,UAAU,MAAM;AAC/D;;AAGA,SAAgB,iBAAiB,MAA6C;CAC5E,OAAO,eAAe,MAAM,WAAW,MAAM,UAAU,MAAM;AAC/D;;AAMA,SAAgB,uBACd,KACA,mBAC+C;CAC/C,MAAM,OAAO,mBAAmB,IAAI,IAAI,EAAE;CAC1C,IAAI,SAAS,KAAA,GAAW,OAAO,KAAK;CACpC,IAAI,eAAe,IAAI,IAAI,GAAG,OAAO;CACrC,IAAI,iBAAiB,IAAI,IAAI,GAAG,OAAO;AAEzC;;AAGA,SAAgB,iBACd,KACA,cACoB;CACpB,MAAM,OAAO,cAAc,IAAI,IAAI,EAAE;CACrC,IAAI,SAAS,KAAA,GAAW,OAAO,KAAK;CACpC,MAAM,aAAa,OAAO,eAAe,IAAI,MAAM,WAAW,MAAM,aAAa,CAAC;CAClF,OAAO,MAAM,UAAU,IAAI,KAAA,IAAY;AACzC;;;;;;;;;;AAWA,SAAgB,cACd,OACA,SACmB;CACnB,MAAM,yBAAS,IAAI,IAAkB;CACrC,IAAI,MAAM,WAAW,KAAK,QAAQ,WAAW,GAAG,OAAO;CAEvD,MAAM,gBAAgB,MAAM,QAAQ,SAAS,OAAO,KAAK,UAAU,UAAU;CAC7E,MAAM,qCAAqB,IAAI,IAAuB;CAEtD,IAAI,cAAc,SAAS,GAAG;EAE5B,MAAM,iBAAiB,kBAAkB,CAAC;GAAE,SADxB,OAAO,UAAU,QAAQ,IAAI,EACc;GAAG,SAAS;EAAK,CAAC,CAAC;EAClF,KAAK,MAAM,QAAQ,eAAe;GAChC,MAAM,SAAS,eAAe,OAAO,EAAE,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,aAAa;GAC3E,IAAI,OAAO,WAAW,GAAG,OAAO;GAChC,mBAAmB,IAAI,MAAM,IAAI,IAAI,OAAO,KAAK,OAAO,iBAAiB,EAAE,CAAC,CAAC,CAAC;EAChF;CACF;CAEA,KAAK,MAAM,OAAO,SAAS;EACzB,MAAM,SAAS,iBAAiB,IAAI,EAAE;EACtC,KAAK,MAAM,QAAQ,OAEjB,IADgB,mBAAmB,IAAI,IAAI,CAAC,EAAE,IAAI,MAAM,KAAK,OAChD;GACX,OAAO,IAAI,QAAQ,IAAI;GACvB;EACF;CAEJ;CACA,OAAO;AACT;;;;;;;;;;;;;;;;AAiBA,SAAgB,mBACd,SACA,OAAqC,CAAC,GACW;CACjD,OAAO,QAAQ,QACZ,KAAK,OAAQ,IAAI,EAAE,MAAM,iBAAiB,GAAG,IAAI,GAAI,MACtD,CAAC,CACH;AACF;AAEA,SAAS,iBACP,QACA,MACsB;CACtB,MAAM,QAAQ,OAAO,cAAc;CACnC,IAAI,UAAU,UAAU,OAAO;CAC/B,IAAI,UAAU,aAAa,OAAO;CAClC,OAAO,cAAc,QAAQ,IAAI,IAAI,UAAU;AACjD;;AAWA,SAAgB,gBAAgB,SAGL;CACzB,MAAM,EAAE,SAAS,wBAAwB;CAUzC,OAJqB,qBALL,QAAQ,KAAK,OAAO;EAClC,MAAM,EAAE;EACR,YAAY,EAAE,YAAY,KAAK,UAAU,EAAE,MAAM,KAAK,OAAO,KAAK,EAAE;EACpE,gBAAgB,EAAE;CACpB,EACgD,GAAG,mBAAmB,CAAC,CAAC,QACrE,KAAK,OAAO,WAAY,IAAI,QAAQ,MAAM,CAAC,MAAM,OAAQ,MAC1D,CAAC,CAEe;AACpB"}
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../../../src/components/PlDataTable/createPlDataTable/utils.ts"],"sourcesContent":["import {\n type AnnotationDataStatus,\n type ColumnUniversalId,\n type PColumn,\n type PColumnSpec,\n type PObjectId,\n Annotation,\n extractPObjectId,\n readAnnotation,\n} from \"@milaboratories/pl-model-common\";\nimport {\n deriveDistinctLabels,\n type DeriveLabelsOptions,\n} from \"../../../labels/derive_distinct_labels\";\nimport {\n deriveDistinctTooltips,\n type TooltipEntry,\n} from \"../../../labels/derive_distinct_tooltips\";\nimport type { ColumnOrderRule, ColumnVisibilityRule } from \"./createPlDataTableV3\";\nimport type { ColumnSelector, MatchQualifications } from \"@milaboratories/pl-model-common\";\nimport { ColumnsCollection, hasColumnData, type ColumnRecipe } from \"../../../columns\";\nimport type { GlobalCfgRenderCtx } from \"../../../render/internal\";\nimport { isNil, uniqBy } from \"es-toolkit\";\nimport { getField } from \"@milaboratories/helpers\";\n\n/** Adapt a {@link ColumnRecipe} to the plain {@link RuleColumn} shape. */\nexport function toRuleColumn(col: ColumnRecipe): RuleColumn {\n return { id: extractPObjectId(col.id), spec: col.getSpec() };\n}\n\n/** Check if column should be omitted from the table */\nexport function isColumnHidden(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"hidden\";\n}\n\n/** Check if column is hidden by default */\nexport function isColumnOptional(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"optional\";\n}\n\n/** Column shape consumed by rule evaluation. */\nexport type RuleColumn = Pick<PColumn<PObjectId>, \"id\" | \"spec\">;\n\n/** Get effective visibility for a column. Rule map lookup first, then annotation fallback. */\nexport function getEffectiveVisibility(\n col: RuleColumn,\n visibilityByColId?: Map<PObjectId, ColumnVisibilityRule>,\n): undefined | \"default\" | \"optional\" | \"hidden\" {\n const rule = visibilityByColId?.get(col.id);\n if (rule !== undefined) return rule.visibility;\n if (isColumnHidden(col.spec)) return \"hidden\";\n if (isColumnOptional(col.spec)) return \"optional\";\n return undefined;\n}\n\n/** Get ordering priority for a column. Rule map lookup first, then annotation fallback. */\nexport function getOrderPriority(\n col: RuleColumn,\n orderByColId?: Map<PObjectId, ColumnOrderRule>,\n): undefined | number {\n const rule = orderByColId?.get(col.id);\n if (rule !== undefined) return rule.priority;\n const annotation = Number(readAnnotation(col.spec, Annotation.Table.OrderPriority));\n return isNaN(annotation) ? undefined : annotation;\n}\n\n/**\n * Evaluate display rules against a set of columns and return a map of `colId → winning rule`\n * (first-match-wins, preserving original rule order).\n *\n * Predicate-based rules (`ColumnMatcher`) are evaluated directly on the spec.\n * Selector-based rules (`ColumnSelector`) are matched via the\n * `columnsCollection` service — the inline column ids must be resolvable in\n * the active render ctx for the host to read their specs.\n */\nexport function evaluateRules<R extends { match: ColumnSelector }>(\n rules: R[],\n columns: ColumnRecipe[],\n): Map<PObjectId, R> {\n const result = new Map<PObjectId, R>();\n if (rules.length === 0 || columns.length === 0) return result;\n\n const selectorRules = rules.filter((rule) => typeof rule.match !== \"function\");\n const selectorHitsByRule = new Map<R, Set<PObjectId>>();\n\n if (selectorRules.length > 0) {\n const baseColumns = uniqBy(columns, (col) => col.id);\n const baseCollection = ColumnsCollection([{ columns: baseColumns, isFinal: true }]);\n for (const rule of selectorRules) {\n const hitIds = baseCollection.filter({ include: rule.match }).getColumnIds();\n // A rule matching nothing simply contributes no entries — it must not\n // discard the rules evaluated alongside it. The lookup below is\n // null-safe, so leaving this rule out of the map is enough.\n if (hitIds.length === 0) continue;\n selectorHitsByRule.set(rule, new Set(hitIds.map((id) => extractPObjectId(id))));\n }\n }\n\n for (const col of columns) {\n const colKey = extractPObjectId(col.id);\n for (const rule of rules) {\n const matches = selectorHitsByRule.get(rule)?.has(colKey) ?? false;\n if (matches) {\n result.set(colKey, rule);\n break;\n }\n }\n }\n return result;\n}\n\n/**\n * Build a sidecar map `columnId → AnnotationDataStatus` derived from each\n * recipe's own status. This is *rendering* metadata — kept out of the spec\n * so it cannot perturb column identity (id-bearing spec overrides would\n * diverge the visible PTable's column ids from the full table / pframe).\n *\n * Mapping `ColumnFieldStatus` × actual byte-presence → `AnnotationDataStatus`:\n * - `absent` → `\"absent\"`\n * - `resolving` → `\"computing\"`\n * - `present` + `hasColumnData()` → `\"ready\"`\n * - `present` + no bytes yet → `\"computing\"`\n *\n * Intentionally scoped to visible columns — the probe is meaningful only for\n * what the user will actually see.\n */\nexport function buildDataStatusMap(\n columns: ColumnRecipe[],\n opts: { ctx?: GlobalCfgRenderCtx } = {},\n): Record<ColumnUniversalId, AnnotationDataStatus> {\n return columns.reduce(\n (acc, c) => ((acc[c.id] = deriveDataStatus(c, opts)), acc),\n {} as Record<ColumnUniversalId, AnnotationDataStatus>,\n );\n}\n\nfunction deriveDataStatus(\n column: ColumnRecipe,\n opts: { ctx?: GlobalCfgRenderCtx },\n): AnnotationDataStatus {\n const field = column.getDataStatus();\n if (field === \"absent\") return \"absent\";\n if (field === \"resolving\") return \"computing\";\n return hasColumnData(column, opts) ? \"ready\" : \"computing\";\n}\n\n/** Column shape required by label derivation. */\nexport type LabelableColumn = {\n readonly id: ColumnUniversalId;\n readonly spec: PColumnSpec;\n readonly linkerPath?: ReadonlyArray<{ readonly linker: { readonly spec: PColumnSpec } }>;\n readonly qualifications?: MatchQualifications;\n};\n\n/** Derive labels for all table elements: columns via deriveDistinctLabels, axes from label columns. */\nexport function deriveAllLabels(options: {\n columns: LabelableColumn[];\n deriveLabelsOptions?: DeriveLabelsOptions;\n}): Record<string, string> {\n const { columns, deriveLabelsOptions } = options;\n const entries = columns.map((c) => ({\n spec: c.spec,\n linkerPath: c.linkerPath?.map((step) => ({ spec: step.linker.spec })),\n qualifications: c.qualifications,\n }));\n const columnLabels = deriveDistinctLabels(entries, deriveLabelsOptions).reduce(\n (acc, label, index) => ((acc[columns[index].id] = label), acc),\n {} as Record<string, string>,\n );\n return columnLabels;\n}\n\n/** Column shape required by tooltip derivation. */\nexport type TooltipableColumn = {\n readonly id: ColumnUniversalId;\n readonly spec: PColumnSpec;\n readonly originalId?: PObjectId;\n readonly linkerPath?: ReadonlyArray<{ readonly linker: { readonly spec: PColumnSpec } }>;\n readonly qualifications?: MatchQualifications;\n};\n\n/** Derive origin tooltips for columns whose qualifications or linker path carry info. */\nexport function deriveAllTooltips(options: {\n columns: TooltipableColumn[];\n}): Record<ColumnUniversalId, string> {\n const { columns } = options;\n\n const variantCountByOriginal = columns.reduce<Map<ColumnUniversalId, number>>((acc, c) => {\n return acc.set(getField(c, \"originalId\") ?? c.id, (acc.get(c.originalId ?? c.id) ?? 0) + 1);\n }, new Map());\n\n const { entries } = columns.reduce(\n ({ entries, variantSeen }, c) => {\n const id = getField(c, \"originalId\") ?? c.id;\n const variantCount = variantCountByOriginal.get(id);\n const variantIndex =\n (variantSeen.set(id, (variantSeen.get(id) ?? 0) + 1), variantSeen.get(id));\n\n entries.push({\n spec: c.spec,\n linkerPath: c.linkerPath,\n qualifications: c.qualifications,\n variantIndex,\n variantCount,\n });\n\n return { entries, variantSeen };\n },\n { entries: [] as TooltipEntry[], variantSeen: new Map<ColumnUniversalId, number>() },\n );\n\n const tooltips = deriveDistinctTooltips(entries);\n\n return Object.fromEntries(\n tooltips.flatMap((t, i) => (isNil(t) ? [] : [[columns[i].id, t] as const])),\n );\n}\n"],"mappings":";;;;;;;;;;AA0BA,SAAgB,aAAa,KAA+B;CAC1D,OAAO;EAAE,IAAI,iBAAiB,IAAI,EAAE;EAAG,MAAM,IAAI,QAAQ;CAAE;AAC7D;;AAGA,SAAgB,eAAe,MAA6C;CAC1E,OAAO,eAAe,MAAM,WAAW,MAAM,UAAU,MAAM;AAC/D;;AAGA,SAAgB,iBAAiB,MAA6C;CAC5E,OAAO,eAAe,MAAM,WAAW,MAAM,UAAU,MAAM;AAC/D;;AAMA,SAAgB,uBACd,KACA,mBAC+C;CAC/C,MAAM,OAAO,mBAAmB,IAAI,IAAI,EAAE;CAC1C,IAAI,SAAS,KAAA,GAAW,OAAO,KAAK;CACpC,IAAI,eAAe,IAAI,IAAI,GAAG,OAAO;CACrC,IAAI,iBAAiB,IAAI,IAAI,GAAG,OAAO;AAEzC;;AAGA,SAAgB,iBACd,KACA,cACoB;CACpB,MAAM,OAAO,cAAc,IAAI,IAAI,EAAE;CACrC,IAAI,SAAS,KAAA,GAAW,OAAO,KAAK;CACpC,MAAM,aAAa,OAAO,eAAe,IAAI,MAAM,WAAW,MAAM,aAAa,CAAC;CAClF,OAAO,MAAM,UAAU,IAAI,KAAA,IAAY;AACzC;;;;;;;;;;AAWA,SAAgB,cACd,OACA,SACmB;CACnB,MAAM,yBAAS,IAAI,IAAkB;CACrC,IAAI,MAAM,WAAW,KAAK,QAAQ,WAAW,GAAG,OAAO;CAEvD,MAAM,gBAAgB,MAAM,QAAQ,SAAS,OAAO,KAAK,UAAU,UAAU;CAC7E,MAAM,qCAAqB,IAAI,IAAuB;CAEtD,IAAI,cAAc,SAAS,GAAG;EAE5B,MAAM,iBAAiB,kBAAkB,CAAC;GAAE,SADxB,OAAO,UAAU,QAAQ,IAAI,EACc;GAAG,SAAS;EAAK,CAAC,CAAC;EAClF,KAAK,MAAM,QAAQ,eAAe;GAChC,MAAM,SAAS,eAAe,OAAO,EAAE,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,aAAa;GAI3E,IAAI,OAAO,WAAW,GAAG;GACzB,mBAAmB,IAAI,MAAM,IAAI,IAAI,OAAO,KAAK,OAAO,iBAAiB,EAAE,CAAC,CAAC,CAAC;EAChF;CACF;CAEA,KAAK,MAAM,OAAO,SAAS;EACzB,MAAM,SAAS,iBAAiB,IAAI,EAAE;EACtC,KAAK,MAAM,QAAQ,OAEjB,IADgB,mBAAmB,IAAI,IAAI,CAAC,EAAE,IAAI,MAAM,KAAK,OAChD;GACX,OAAO,IAAI,QAAQ,IAAI;GACvB;EACF;CAEJ;CACA,OAAO;AACT;;;;;;;;;;;;;;;;AAiBA,SAAgB,mBACd,SACA,OAAqC,CAAC,GACW;CACjD,OAAO,QAAQ,QACZ,KAAK,OAAQ,IAAI,EAAE,MAAM,iBAAiB,GAAG,IAAI,GAAI,MACtD,CAAC,CACH;AACF;AAEA,SAAS,iBACP,QACA,MACsB;CACtB,MAAM,QAAQ,OAAO,cAAc;CACnC,IAAI,UAAU,UAAU,OAAO;CAC/B,IAAI,UAAU,aAAa,OAAO;CAClC,OAAO,cAAc,QAAQ,IAAI,IAAI,UAAU;AACjD;;AAWA,SAAgB,gBAAgB,SAGL;CACzB,MAAM,EAAE,SAAS,wBAAwB;CAUzC,OAJqB,qBALL,QAAQ,KAAK,OAAO;EAClC,MAAM,EAAE;EACR,YAAY,EAAE,YAAY,KAAK,UAAU,EAAE,MAAM,KAAK,OAAO,KAAK,EAAE;EACpE,gBAAgB,EAAE;CACpB,EACgD,GAAG,mBAAmB,CAAC,CAAC,QACrE,KAAK,OAAO,WAAY,IAAI,QAAQ,MAAM,CAAC,MAAM,OAAQ,MAC1D,CAAC,CAEe;AACpB"}
|
|
@@ -24,7 +24,7 @@ function findEnrichmentColumns(options) {
|
|
|
24
24
|
}).getColumns();
|
|
25
25
|
const predicate = options.predicate;
|
|
26
26
|
return columns.filter((v) => {
|
|
27
|
-
if (require_utils.
|
|
27
|
+
if (require_utils.hasSingleDataColumn(v)) return false;
|
|
28
28
|
if (predicate !== void 0 && !predicate(v.getSpec())) return false;
|
|
29
29
|
if (!(0, _milaboratories_pl_model_common.isGlobalPObjectId)((0, _milaboratories_pl_model_common.extractPObjectId)(v.id))) return false;
|
|
30
30
|
if (require_utils.collectLinkerIds(v).some((id) => !(0, _milaboratories_pl_model_common.isGlobalPObjectId)(id))) return false;
|