@platforma-sdk/model 1.70.0 → 1.72.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/block_model.cjs +3 -0
- package/dist/block_model.cjs.map +1 -1
- package/dist/block_model.d.ts +2 -0
- package/dist/block_model.d.ts.map +1 -1
- package/dist/block_model.js +2 -0
- package/dist/block_model.js.map +1 -1
- package/dist/block_model_legacy.cjs +4 -1
- package/dist/block_model_legacy.cjs.map +1 -1
- package/dist/block_model_legacy.d.ts.map +1 -1
- package/dist/block_model_legacy.js +3 -1
- package/dist/block_model_legacy.js.map +1 -1
- package/dist/columns/column_snapshot_provider.cjs +26 -2
- package/dist/columns/column_snapshot_provider.cjs.map +1 -1
- package/dist/columns/column_snapshot_provider.d.ts +2 -1
- package/dist/columns/column_snapshot_provider.d.ts.map +1 -1
- package/dist/columns/column_snapshot_provider.js +25 -2
- package/dist/columns/column_snapshot_provider.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +40 -20
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +41 -21
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/utils.cjs +15 -0
- package/dist/components/PlDataTable/createPlDataTable/utils.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/utils.js +15 -1
- package/dist/components/PlDataTable/createPlDataTable/utils.js.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.js +1 -1
- package/dist/render/api.cjs +3 -14
- package/dist/render/api.cjs.map +1 -1
- package/dist/render/api.d.ts.map +1 -1
- package/dist/render/api.js +4 -15
- package/dist/render/api.js.map +1 -1
- package/dist/render/index.cjs +1 -1
- package/dist/render/index.js +1 -1
- package/package.json +8 -8
- package/src/block_model.ts +2 -0
- package/src/block_model_legacy.ts +2 -0
- package/src/columns/column_snapshot_provider.ts +30 -14
- package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +58 -43
- package/src/components/PlDataTable/createPlDataTable/utils.ts +25 -2
- package/src/render/api.ts +5 -17
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import type { PObjectId } from "@milaboratories/pl-model-common";
|
|
2
|
-
import { PColumn } from "@milaboratories/pl-model-common";
|
|
2
|
+
import { isDataInfo, PColumn, visitDataInfo } from "@milaboratories/pl-model-common";
|
|
3
3
|
import { TreeNodeAccessor } from "../render/accessor";
|
|
4
4
|
import type { PColumnDataUniversal } from "../render/internal";
|
|
5
5
|
import type { ColumnDataStatus, ColumnSnapshot } from "./column_snapshot";
|
|
6
6
|
|
|
7
|
-
// --- ColumnProvider ---
|
|
8
|
-
|
|
9
7
|
/**
|
|
10
8
|
* Data source interface for column enumeration.
|
|
11
9
|
*
|
|
@@ -22,8 +20,6 @@ export interface ColumnSnapshotProvider {
|
|
|
22
20
|
isColumnListComplete(): boolean;
|
|
23
21
|
}
|
|
24
22
|
|
|
25
|
-
// --- ColumnSource ---
|
|
26
|
-
|
|
27
23
|
/**
|
|
28
24
|
* Union of types that can serve as column sources for helpers and builders.
|
|
29
25
|
* Does NOT include TreeNodeAccessor — call `.toColumnSource()` on it first.
|
|
@@ -33,8 +29,6 @@ export type ColumnSource =
|
|
|
33
29
|
| ColumnSnapshot<PObjectId>[]
|
|
34
30
|
| PColumn<PColumnDataUniversal | undefined>[];
|
|
35
31
|
|
|
36
|
-
// --- ArrayColumnProvider ---
|
|
37
|
-
|
|
38
32
|
/**
|
|
39
33
|
* Simple provider wrapping an array of PColumns.
|
|
40
34
|
* Always complete, data status always 'ready'.
|
|
@@ -46,8 +40,8 @@ export class ArrayColumnProvider implements ColumnSnapshotProvider {
|
|
|
46
40
|
this.columns = columns.map((col) => ({
|
|
47
41
|
id: col.id,
|
|
48
42
|
spec: col.spec,
|
|
49
|
-
dataStatus: "ready" as const,
|
|
50
43
|
data: { get: () => col.data },
|
|
44
|
+
dataStatus: this.getStatus(col.data),
|
|
51
45
|
}));
|
|
52
46
|
}
|
|
53
47
|
|
|
@@ -58,9 +52,35 @@ export class ArrayColumnProvider implements ColumnSnapshotProvider {
|
|
|
58
52
|
isColumnListComplete(): boolean {
|
|
59
53
|
return true;
|
|
60
54
|
}
|
|
61
|
-
}
|
|
62
55
|
|
|
63
|
-
|
|
56
|
+
protected getStatus(
|
|
57
|
+
d: undefined | PColumnDataUniversal | (() => undefined | PColumnDataUniversal),
|
|
58
|
+
): ColumnDataStatus {
|
|
59
|
+
if (d == null) {
|
|
60
|
+
return "absent";
|
|
61
|
+
}
|
|
62
|
+
if (typeof d === "function") {
|
|
63
|
+
return this.getStatus(d());
|
|
64
|
+
}
|
|
65
|
+
if (d instanceof TreeNodeAccessor) {
|
|
66
|
+
if (d.getIsReadyOrError()) return "ready";
|
|
67
|
+
if (d.getIsFinal()) return "absent";
|
|
68
|
+
return "computing";
|
|
69
|
+
}
|
|
70
|
+
if (isDataInfo(d)) {
|
|
71
|
+
let ready = true;
|
|
72
|
+
let final = true;
|
|
73
|
+
visitDataInfo(d, (v) => {
|
|
74
|
+
ready &&= v.getIsReadyOrError();
|
|
75
|
+
final &&= v.getIsFinal();
|
|
76
|
+
});
|
|
77
|
+
if (ready) return "ready";
|
|
78
|
+
if (final) return "absent";
|
|
79
|
+
return "computing";
|
|
80
|
+
}
|
|
81
|
+
return "ready";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
64
84
|
|
|
65
85
|
/**
|
|
66
86
|
* Provider wrapping an array of ColumnSnapshots.
|
|
@@ -78,8 +98,6 @@ export class SnapshotColumnProvider implements ColumnSnapshotProvider {
|
|
|
78
98
|
}
|
|
79
99
|
}
|
|
80
100
|
|
|
81
|
-
// --- OutputColumnProvider ---
|
|
82
|
-
|
|
83
101
|
export interface OutputColumnProviderOpts {
|
|
84
102
|
/** When true and the accessor is final, columns with no ready data get status 'absent'. */
|
|
85
103
|
allowPermanentAbsence?: boolean;
|
|
@@ -133,8 +151,6 @@ export class OutputColumnProvider implements ColumnSnapshotProvider {
|
|
|
133
151
|
}
|
|
134
152
|
}
|
|
135
153
|
|
|
136
|
-
// --- Source normalization ---
|
|
137
|
-
|
|
138
154
|
/** Checks if a value is a ColumnSnapshotProvider (duck-typing). */
|
|
139
155
|
export function isColumnSnapshotProvider(source: unknown): source is ColumnSnapshotProvider {
|
|
140
156
|
return (
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
withLabelAnnotations,
|
|
33
33
|
withTableVisualAnnotations,
|
|
34
34
|
withInfoAnnotations,
|
|
35
|
+
withDataStatusAnnotations,
|
|
35
36
|
} from "./utils";
|
|
36
37
|
import type { PrimaryEntry, SecondaryGroup } from "./createPTableDefV3";
|
|
37
38
|
import { createPTableDefV3 } from "./createPTableDefV3";
|
|
@@ -79,8 +80,6 @@ export type ColumnVisibilityRule = {
|
|
|
79
80
|
|
|
80
81
|
export type ColumnMatcher = (spec: PColumnSpec) => boolean;
|
|
81
82
|
|
|
82
|
-
// Main Function
|
|
83
|
-
|
|
84
83
|
export function createPlDataTableV3<A, U>(
|
|
85
84
|
ctx: RenderCtxBase<A, U>,
|
|
86
85
|
options: createPlDataTableOptionsV3,
|
|
@@ -138,17 +137,18 @@ export function createPlDataTableV3<A, U>(
|
|
|
138
137
|
]);
|
|
139
138
|
|
|
140
139
|
const remapedDefaultFilters = remapFilterColumnIds(options.filters, discovered);
|
|
141
|
-
const filters =
|
|
142
|
-
|
|
143
|
-
|
|
140
|
+
const filters = filterFilters(
|
|
141
|
+
concatFilters(
|
|
142
|
+
state.pTableParams.filters,
|
|
143
|
+
state.pTableParams.defaultFilters ?? remapedDefaultFilters,
|
|
144
|
+
),
|
|
145
|
+
columnIsAvailable,
|
|
144
146
|
);
|
|
145
|
-
validateFilters(filters, columnIsAvailable);
|
|
146
147
|
|
|
147
|
-
const sorting =
|
|
148
|
-
state.pTableParams.sorting,
|
|
149
|
-
|
|
148
|
+
const sorting = filterSorting(
|
|
149
|
+
resolveSorting(state.pTableParams.sorting, remapSortingColumnIds(options.sorting, discovered)),
|
|
150
|
+
columnIsAvailable,
|
|
150
151
|
);
|
|
151
|
-
validateSorting(sorting, columnIsAvailable);
|
|
152
152
|
|
|
153
153
|
const primaryEntries: PrimaryEntry<undefined | PColumnDataUniversal>[] = primarySnapshots.map(
|
|
154
154
|
(v) => ({ column: resolveSnapshot(v.column) }),
|
|
@@ -274,6 +274,7 @@ function annotateColumnGroups(params: {
|
|
|
274
274
|
const directAnnotated = liftToVariantColumns(
|
|
275
275
|
direct,
|
|
276
276
|
flow(
|
|
277
|
+
(cols) => withDataStatusAnnotations(cols),
|
|
277
278
|
(cols) => withLabelAnnotations(derivedLabels, cols),
|
|
278
279
|
(cols) => withInfoAnnotations(derivedTooltips, cols),
|
|
279
280
|
(cols) => withTableVisualAnnotations(visibilityByColId, orderByColId, cols),
|
|
@@ -283,6 +284,7 @@ function annotateColumnGroups(params: {
|
|
|
283
284
|
const linkedAnnotated = liftToVariantColumns(
|
|
284
285
|
linked,
|
|
285
286
|
flow(
|
|
287
|
+
(cols) => withDataStatusAnnotations(cols),
|
|
286
288
|
(cols) => withHidenAxesAnnotations(cols),
|
|
287
289
|
(cols) => withLabelAnnotations(derivedLabels, cols),
|
|
288
290
|
(cols) => withInfoAnnotations(derivedTooltips, cols),
|
|
@@ -344,19 +346,35 @@ function createColumnValidationById(
|
|
|
344
346
|
};
|
|
345
347
|
}
|
|
346
348
|
|
|
347
|
-
/**
|
|
348
|
-
function
|
|
349
|
+
/** Drop filter leaves whose column references are not available in the table. */
|
|
350
|
+
function filterFilters(
|
|
349
351
|
filters: Nil | PlDataTableFilters,
|
|
350
352
|
isValidColumnId: (id: string) => boolean,
|
|
351
|
-
):
|
|
352
|
-
if (filters
|
|
353
|
-
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}
|
|
353
|
+
): Nil | PlDataTableFilters {
|
|
354
|
+
if (isNil(filters)) return filters;
|
|
355
|
+
|
|
356
|
+
const isLeafValid = (leaf: PlDataTableFilterSpecLeaf): boolean => {
|
|
357
|
+
if (leaf.type === undefined) return true;
|
|
358
|
+
if ("column" in leaf && !isValidColumnId(leaf.column)) return false;
|
|
359
|
+
if ("rhs" in leaf && !isValidColumnId(leaf.rhs)) return false;
|
|
360
|
+
return true;
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const prune = (node: PlDataTableFilterNode): Nil | PlDataTableFilterNode => {
|
|
364
|
+
if (node.type === "and" || node.type === "or") {
|
|
365
|
+
const kept = node.filters
|
|
366
|
+
.map((f) => prune(f))
|
|
367
|
+
.filter((f): f is PlDataTableFilterNode => !isNil(f));
|
|
368
|
+
return { type: node.type, filters: kept };
|
|
369
|
+
}
|
|
370
|
+
if (node.type === "not") {
|
|
371
|
+
const inner = prune(node.filter);
|
|
372
|
+
return isNil(inner) ? undefined : { type: "not", filter: inner };
|
|
373
|
+
}
|
|
374
|
+
return isLeafValid(node) ? node : undefined;
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
return prune(filters) as Nil | PlDataTableFilters;
|
|
360
378
|
}
|
|
361
379
|
|
|
362
380
|
/** Merge two filter trees into one AND-combined tree. Returns the non-nil one if the other is nil. */
|
|
@@ -377,16 +395,12 @@ function resolveSorting(
|
|
|
377
395
|
return (isEmpty(userSorting) ? defaultSorting : userSorting) ?? [];
|
|
378
396
|
}
|
|
379
397
|
|
|
380
|
-
/**
|
|
381
|
-
function
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
throw new Error(
|
|
387
|
-
`Invalid sorting column ${JSON.stringify(firstInvalid.column)}: column reference does not match the table columns`,
|
|
388
|
-
);
|
|
389
|
-
}
|
|
398
|
+
/** Drop sorting entries whose column is not available in the table. */
|
|
399
|
+
function filterSorting(
|
|
400
|
+
sorting: PTableSorting[],
|
|
401
|
+
isValidColumnId: (id: string) => boolean,
|
|
402
|
+
): PTableSorting[] {
|
|
403
|
+
return sorting.filter((s) => isValidColumnId(canonicalizeJson<PTableColumnId>(s.column)));
|
|
390
404
|
}
|
|
391
405
|
|
|
392
406
|
function buildSecondaryGroups(
|
|
@@ -473,21 +487,22 @@ function remapSortingColumnIds(
|
|
|
473
487
|
sorting: Nil | PTableSorting[],
|
|
474
488
|
columns: TableColumnVariant[],
|
|
475
489
|
): Nil | PTableSorting[] {
|
|
476
|
-
return sorting?.
|
|
477
|
-
if (s.column.type === "axis") return s; // Axis references are unaffected by column ID remapping
|
|
490
|
+
return sorting?.flatMap((s) => {
|
|
491
|
+
if (s.column.type === "axis") return [s]; // Axis references are unaffected by column ID remapping
|
|
478
492
|
|
|
479
493
|
const id = s.column.id;
|
|
480
|
-
const column =
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
494
|
+
const column = columns.find((c) => (c.originalId ?? c.column.id) === id);
|
|
495
|
+
if (column === undefined) return [];
|
|
496
|
+
|
|
497
|
+
return [
|
|
498
|
+
{
|
|
499
|
+
...s,
|
|
500
|
+
column: {
|
|
501
|
+
type: "column" as const,
|
|
502
|
+
id: column.column.id,
|
|
503
|
+
},
|
|
489
504
|
},
|
|
490
|
-
|
|
505
|
+
];
|
|
491
506
|
});
|
|
492
507
|
}
|
|
493
508
|
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
deriveDistinctTooltips,
|
|
18
18
|
type TooltipEntry,
|
|
19
19
|
} from "../../../labels/derive_distinct_tooltips";
|
|
20
|
-
import type { MatchQualifications, MatchVariant } from "../../../columns";
|
|
20
|
+
import type { ColumnDataStatus, MatchQualifications, MatchVariant } from "../../../columns";
|
|
21
21
|
import type { ColumnMatcher, ColumnOrderRule, ColumnVisibilityRule } from "./createPlDataTableV3";
|
|
22
22
|
import type { ColumnSelector } from "../../../columns";
|
|
23
23
|
import { ArrayColumnProvider, ColumnCollectionBuilder } from "../../../columns";
|
|
@@ -130,7 +130,10 @@ function dedupeById(columns: RuleColumn[]): RuleColumn[] {
|
|
|
130
130
|
* For each axis in column specs: writes derived axis label into AxisSpec annotations.
|
|
131
131
|
*/
|
|
132
132
|
export function withLabelAnnotations<
|
|
133
|
-
T extends {
|
|
133
|
+
T extends {
|
|
134
|
+
readonly id: PObjectId;
|
|
135
|
+
readonly spec: PColumnSpec;
|
|
136
|
+
},
|
|
134
137
|
>(derivedLabels: undefined | Record<string, string>, columns: T[]): T[] {
|
|
135
138
|
if (derivedLabels === undefined) return columns;
|
|
136
139
|
return columns.map((col) => {
|
|
@@ -153,6 +156,26 @@ export function withLabelAnnotations<
|
|
|
153
156
|
});
|
|
154
157
|
}
|
|
155
158
|
|
|
159
|
+
export function withDataStatusAnnotations<
|
|
160
|
+
T extends {
|
|
161
|
+
readonly spec: PColumnSpec;
|
|
162
|
+
readonly dataStatus: ColumnDataStatus;
|
|
163
|
+
},
|
|
164
|
+
>(columns: T[]): T[] {
|
|
165
|
+
return columns.map((col) => {
|
|
166
|
+
return {
|
|
167
|
+
...col,
|
|
168
|
+
spec: {
|
|
169
|
+
...col.spec,
|
|
170
|
+
annotations: {
|
|
171
|
+
...col.spec.annotations,
|
|
172
|
+
[Annotation.DataStatus]: col.dataStatus,
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
} as T;
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
156
179
|
/**
|
|
157
180
|
* Writes effective display properties (OrderPriority, Visibility) from precomputed rule maps
|
|
158
181
|
* into column annotations. Returns new column objects — originals are not mutated.
|
package/src/render/api.ts
CHANGED
|
@@ -29,10 +29,8 @@ import type {
|
|
|
29
29
|
} from "@milaboratories/pl-model-common";
|
|
30
30
|
import {
|
|
31
31
|
AnchoredIdDeriver,
|
|
32
|
-
collectSpecQueryColumns,
|
|
33
32
|
ensurePColumn,
|
|
34
33
|
parseJson,
|
|
35
|
-
extractAllColumns,
|
|
36
34
|
isDataInfo,
|
|
37
35
|
isPColumn,
|
|
38
36
|
isPColumnSpec,
|
|
@@ -46,6 +44,7 @@ import {
|
|
|
46
44
|
readAnnotation,
|
|
47
45
|
withEnrichments,
|
|
48
46
|
legacyColumnSelectorsToPredicate,
|
|
47
|
+
extractAllColumns,
|
|
49
48
|
} from "@milaboratories/pl-model-common";
|
|
50
49
|
import canonicalize from "canonicalize";
|
|
51
50
|
import type { Optional } from "utility-types";
|
|
@@ -70,9 +69,9 @@ import type { LabelDerivationOps } from "./util/label";
|
|
|
70
69
|
import { deriveLabels } from "./util/label";
|
|
71
70
|
import type { APColumnSelectorWithSplit } from "./util/split_selectors";
|
|
72
71
|
import { patchInSetFilters } from "./util/pframe_upgraders";
|
|
73
|
-
import { allPColumnsReady } from "./util/pcolumn_data";
|
|
74
72
|
import type { PColumnDataUniversal } from "./internal";
|
|
75
73
|
import { getService } from "../services";
|
|
74
|
+
import { allPColumnsReady } from "./util";
|
|
76
75
|
|
|
77
76
|
/**
|
|
78
77
|
* Helper function to match domain objects
|
|
@@ -97,7 +96,7 @@ export type UniversalColumnOption = { label: string; value: SUniversalPColumnId
|
|
|
97
96
|
* @returns Transformed data compatible with platform API
|
|
98
97
|
*/
|
|
99
98
|
function transformPColumnData(
|
|
100
|
-
data: PColumn<PColumnDataUniversal> | PColumnLazy<PColumnDataUniversal>,
|
|
99
|
+
data: PColumn<undefined | PColumnDataUniversal> | PColumnLazy<undefined | PColumnDataUniversal>,
|
|
101
100
|
): PColumn<PColumnValues | AccessorHandle | DataInfo<AccessorHandle>> {
|
|
102
101
|
return mapPObjectData(data, (d) => {
|
|
103
102
|
if (d instanceof TreeNodeAccessor) {
|
|
@@ -105,7 +104,7 @@ function transformPColumnData(
|
|
|
105
104
|
} else if (isDataInfo(d)) {
|
|
106
105
|
return mapDataInfo(d, (accessor) => accessor.handle);
|
|
107
106
|
} else {
|
|
108
|
-
return d;
|
|
107
|
+
return d ?? [];
|
|
109
108
|
}
|
|
110
109
|
});
|
|
111
110
|
}
|
|
@@ -663,8 +662,6 @@ export abstract class RenderCtxBase<Args = unknown, Data = unknown> {
|
|
|
663
662
|
PColumn<undefined | PColumnDataUniversal> | PColumnLazy<undefined | PColumnDataUniversal>
|
|
664
663
|
>,
|
|
665
664
|
): PFrameHandle | undefined {
|
|
666
|
-
if (!allPColumnsReady(def)) return undefined;
|
|
667
|
-
this.verifyInlineAndExplicitColumnsSupport(def);
|
|
668
665
|
return this.ctx.createPFrame(def.map((c) => transformPColumnData(c)));
|
|
669
666
|
}
|
|
670
667
|
|
|
@@ -709,16 +706,7 @@ export abstract class RenderCtxBase<Args = unknown, Data = unknown> {
|
|
|
709
706
|
public createPTableV2(
|
|
710
707
|
def: PTableDefV2<PColumn<undefined | PColumnDataUniversal>>,
|
|
711
708
|
): PTableHandle | undefined {
|
|
712
|
-
|
|
713
|
-
if (!allPColumnsReady(columns)) return undefined;
|
|
714
|
-
this.verifyInlineAndExplicitColumnsSupport(columns);
|
|
715
|
-
return this.ctx.createPTableV2(
|
|
716
|
-
mapPTableDefV2(def, (po) => {
|
|
717
|
-
if (po.data === undefined)
|
|
718
|
-
throw new Error("unreachable: column data undefined after readiness check");
|
|
719
|
-
return transformPColumnData({ id: po.id, spec: po.spec, data: po.data });
|
|
720
|
-
}),
|
|
721
|
-
);
|
|
709
|
+
return this.ctx.createPTableV2(mapPTableDefV2(def, (po) => transformPColumnData(po)));
|
|
722
710
|
}
|
|
723
711
|
|
|
724
712
|
/** @deprecated scheduled for removal from SDK */
|