@platforma-sdk/model 1.22.59 → 1.23.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.
@@ -1,4 +1,4 @@
1
- import { AxisId, Option, PColumn, PColumnSpec, PColumnValues, PFrameDef, PFrameHandle, PObject, PObjectSpec, PSpecPredicate, PTableDef, PTableHandle, PTableRecordFilter, PTableSorting, PlRef, ResultCollection, ValueOrError } from '@milaboratories/pl-model-common';
1
+ import { APColumnSelector, AxisId, Option, PColumn, PColumnSelector, PColumnSpec, PColumnValues, PFrameDef, PFrameHandle, PObject, PObjectSpec, PSpecPredicate, PTableDef, PTableHandle, PTableRecordFilter, PTableSorting, PlRef, ResultCollection, ValueOrError, AnchorIdDeriver } from '@milaboratories/pl-model-common';
2
2
  import { Optional } from 'utility-types';
3
3
  import { TreeNodeAccessor } from './accessor';
4
4
  import { FutureRef } from './future';
@@ -10,7 +10,44 @@ export declare class ResultPool {
10
10
  */
11
11
  calculateOptions(predicate: PSpecPredicate): Option[];
12
12
  private defaultLabelFn;
13
- getOptions(predicate: (spec: PObjectSpec) => boolean, label?: ((spec: PObjectSpec, ref: PlRef) => string) | LabelDerivationOps): Option[];
13
+ getOptions(predicateOrSelector: ((spec: PObjectSpec) => boolean) | PColumnSelector | PColumnSelector[], label?: ((spec: PObjectSpec, ref: PlRef) => string) | LabelDerivationOps): Option[];
14
+ /**
15
+ * Calculates anchored identifier options for columns matching a given predicate.
16
+ *
17
+ * This function filters column specifications from the result pool that match the provided predicate,
18
+ * creates a standardized AnchorCtx from the provided anchors, and generates a list of label-value
19
+ * pairs for UI components (like dropdowns).
20
+ *
21
+ * @param anchorsOrCtx - Either:
22
+ * - An existing AnchorCtx instance
23
+ * - A record mapping anchor IDs to PColumnSpec objects
24
+ * - A record mapping anchor IDs to PlRef objects (which will be resolved to PColumnSpec)
25
+ * @param predicateOrSelector - Either:
26
+ * - A predicate function that takes a PColumnSpec and returns a boolean.
27
+ * Only specs that return true will be included.
28
+ * - An APColumnSelector object for declarative filtering, which will be
29
+ * resolved against the provided anchors and matched using matchPColumn.
30
+ * - An array of APColumnSelector objects - columns matching ANY selector
31
+ * in the array will be included (OR operation).
32
+ * @param labelOps - Optional configuration for label generation:
33
+ * - includeNativeLabel: Whether to include native column labels
34
+ * - separator: String to use between label parts (defaults to " / ")
35
+ * - addLabelAsSuffix: Whether to add labels as suffix instead of prefix
36
+ * @returns An array of objects with `label` (display text) and `value` (anchored ID string) properties,
37
+ * or undefined if any PlRef resolution fails.
38
+ */
39
+ getAnchoredOptions(anchorsOrCtx: AnchorIdDeriver, predicateOrSelectors: ((spec: PColumnSpec) => boolean) | APColumnSelector | APColumnSelector[], labelOps?: LabelDerivationOps): {
40
+ label: string;
41
+ value: string;
42
+ }[];
43
+ getAnchoredOptions(anchorsOrCtx: Record<string, PColumnSpec>, predicateOrSelectors: ((spec: PColumnSpec) => boolean) | APColumnSelector | APColumnSelector[], labelOps?: LabelDerivationOps): {
44
+ label: string;
45
+ value: string;
46
+ }[];
47
+ getAnchoredOptions(anchorsOrCtx: Record<string, PColumnSpec | PlRef>, predicateOrSelectors: ((spec: PColumnSpec) => boolean) | APColumnSelector | APColumnSelector[], labelOps?: LabelDerivationOps): {
48
+ label: string;
49
+ value: string;
50
+ }[] | undefined;
14
51
  /**
15
52
  * @deprecated use getData()
16
53
  */
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/render/api.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,MAAM,EACN,OAAO,EACP,WAAW,EACX,aAAa,EACb,SAAS,EACT,YAAY,EACZ,OAAO,EACP,WAAW,EACX,cAAc,EACd,SAAS,EACT,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,KAAK,EACL,gBAAgB,EAChB,YAAY,EAQb,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,gBAAgB,EAAS,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,EAAE,kBAAkB,EAAgB,MAAM,cAAc,CAAC;AAEhE,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAyC;IAE7D;;OAEG;IACI,gBAAgB,CAAC,SAAS,EAAE,cAAc,GAAG,MAAM,EAAE;IAI5D,OAAO,CAAC,cAAc,CACgC;IAE/C,UAAU,CACf,SAAS,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,EACzC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,KAAK,KAAK,MAAM,CAAC,GAAG,kBAAkB,GACvE,MAAM,EAAE;IAcX;;OAEG;IACI,qBAAqB,IAAI,gBAAgB,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAIpE,OAAO,IAAI,gBAAgB,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAc7D;;OAEG;IACI,+BAA+B,IAAI,gBAAgB,CACxD,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAChE;IAIM,iBAAiB,IAAI,gBAAgB,CAC1C,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAChE;IAiBD;;OAEG;IACI,sBAAsB,IAAI,gBAAgB,CAAC,WAAW,CAAC;IAIvD,QAAQ,IAAI,gBAAgB,CAAC,WAAW,CAAC;IAIhD;;;OAGG;IACI,YAAY,CAAC,GAAG,EAAE,KAAK,GAAG,OAAO,CAAC,gBAAgB,CAAC,GAAG,SAAS;IAYtE;;;;OAIG;IACI,eAAe,CAAC,GAAG,EAAE,KAAK,GAAG,OAAO,CAAC,gBAAgB,CAAC,GAAG,SAAS;IAMzE;;;;OAIG;IACI,mBAAmB,CAAC,GAAG,EAAE,KAAK,GAAG,WAAW,GAAG,SAAS;IAO/D;;;OAGG;IACI,YAAY,CAAC,GAAG,EAAE,KAAK,GAAG,WAAW,GAAG,SAAS;IASxD;;;;OAIG;IACI,0BAA0B,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,EAAE;CA4ClF;AAWD,iGAAiG;AACjG,qBAAa,SAAS,CAAC,IAAI,EAAE,OAAO;IAClC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqB;IAEzC,SAAgB,IAAI,EAAE,IAAI,CAAC;IAC3B,SAAgB,OAAO,EAAE,OAAO,CAAC;;IASjC,OAAO,CAAC,gBAAgB,CAAC,CAAe;IAExC;;;SAGK;IACL,IAAW,UAAU,IAAI,IAAI,GAAG,SAAS,CAMxC;IAOD,OAAO,CAAC,gBAAgB;IAOxB,IAAW,MAAM,IAAI,gBAAgB,GAAG,SAAS,CAEhD;IAED,IAAW,OAAO,IAAI,gBAAgB,GAAG,SAAS,CAEjD;IAED,SAAgB,UAAU,aAAoB;IAE9C;;;OAGG;IACI,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS;IA8B5E,OAAO,CAAC,0BAA0B;IAM3B,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,gBAAgB,GAAG,aAAa,CAAC,GAAG,YAAY;IAO5E,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,OAAO,CAAC,gBAAgB,GAAG,aAAa,CAAC,CAAC,GAAG,YAAY;IACrF,YAAY,CAAC,GAAG,EAAE;QACvB,OAAO,EAAE,OAAO,CAAC,gBAAgB,GAAG,aAAa,CAAC,EAAE,CAAC;QACrD,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAC;QAC/B,oBAAoB;QACpB,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;KAC3B,GAAG,YAAY;IAgChB,iDAAiD;IAC1C,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAItC,wBAAwB,IAAI,MAAM,GAAG,SAAS;CAKtD;AAED,MAAM,MAAM,cAAc,CAAC,IAAI,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO,IAAI,CAC7E,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,KAC3B,GAAG,CAAC;AAET,MAAM,MAAM,eAAe,CAAC,CAAC,IAC3B,CAAC,SAAS,SAAS,CAAC,MAAM,CAAC,CAAC,GACxB,CAAC,GACD,CAAC,SAAS,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GACtE,CAAC,GACD;KAAG,GAAG,IAAI,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;CAAE,CAAC;AAEtD,MAAM,MAAM,yBAAyB,CAAC,EAAE,SAAS,QAAQ,IAAI,EAAE,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,MAAM,CAAC,GAC7F,eAAe,CAAC,CAAC,CAAC,GAClB,KAAK,CAAC"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/render/api.ts"],"names":[],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const PlatformaSDKVersion = "1.22.59";
1
+ export declare const PlatformaSDKVersion = "1.23.0";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,YAAY,CAAC"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,WAAW,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platforma-sdk/model",
3
- "version": "1.22.59",
3
+ "version": "1.23.0",
4
4
  "description": "Platforma.bio SDK / Block Model",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.js",
@@ -20,7 +20,7 @@
20
20
  "dependencies": {
21
21
  "utility-types": "^3.11.0",
22
22
  "zod": "~3.23.8",
23
- "@milaboratories/pl-model-common": "^1.10.6"
23
+ "@milaboratories/pl-model-common": "^1.11.0"
24
24
  },
25
25
  "devDependencies": {
26
26
  "typescript": "~5.5.4",
@@ -28,7 +28,8 @@
28
28
  "@types/jest": "^29.5.14",
29
29
  "jest": "^29.7.0",
30
30
  "@jest/globals": "^29.7.0",
31
- "ts-jest": "^29.2.5",
31
+ "ts-jest": "^29.2.6",
32
+ "@platforma-sdk/eslint-config": "1.0.1",
32
33
  "@milaboratories/platforma-build-configs": "1.0.2"
33
34
  },
34
35
  "scripts": {
@@ -1,12 +1,11 @@
1
1
  import {test, expect, describe} from '@jest/globals';
2
- import {getAdditionalColumns} from './PFrameForGraphs';
2
+ import {enrichColumnsWithCompatible, getAdditionalColumns, IS_VIRTUAL_COLUMN} from './PFrameForGraphs';
3
3
  import {PColumn, PColumnSpec, PColumnValues, PObjectId} from "@milaboratories/pl-model-common";
4
4
  import {TreeNodeAccessor} from "../render";
5
5
 
6
-
7
6
  describe('PFrameForGraph', () => {
8
7
  test('columns are compatible, no additional columns', () => {
9
- const columnSpec1:PColumnSpec = {
8
+ const columnSpec1: PColumnSpec = {
10
9
  kind: 'PColumn',
11
10
  name: 'column1',
12
11
  valueType: 'Int',
@@ -15,13 +14,13 @@ describe('PFrameForGraph', () => {
15
14
  {type: 'Int', name: 'axis2', domain: {}}
16
15
  ]
17
16
  }
18
- const columnSpec2:PColumnSpec = {
17
+ const columnSpec2: PColumnSpec = {
19
18
  kind: 'PColumn',
20
19
  name: 'column2',
21
20
  valueType: 'Int',
22
21
  axesSpec: [{type: 'String', name: 'axis1', domain: {}}]
23
22
  }
24
- const columns:PColumn<TreeNodeAccessor | PColumnValues>[] = [{
23
+ const columns: PColumn<TreeNodeAccessor | PColumnValues>[] = [{
25
24
  id: 'id1' as PObjectId,
26
25
  spec: columnSpec1,
27
26
  data: []
@@ -36,19 +35,19 @@ describe('PFrameForGraph', () => {
36
35
  });
37
36
 
38
37
  test('columns are not compatible, 1 additional column', () => {
39
- const columnSpec1:PColumnSpec = {
38
+ const columnSpec1: PColumnSpec = {
40
39
  kind: 'PColumn',
41
40
  name: 'column1',
42
41
  valueType: 'Int',
43
42
  axesSpec: [{type: 'String', name: 'axis1', domain: {key1: 'a'}}]
44
43
  }
45
- const columnSpec2:PColumnSpec = {
44
+ const columnSpec2: PColumnSpec = {
46
45
  kind: 'PColumn',
47
46
  name: 'column2',
48
47
  valueType: 'Int',
49
48
  axesSpec: [{type: 'String', name: 'axis1', domain: {}}]
50
49
  }
51
- const columns:PColumn<TreeNodeAccessor | PColumnValues>[] = [
50
+ const columns: PColumn<TreeNodeAccessor | PColumnValues>[] = [
52
51
  {id: 'id1' as PObjectId, spec: columnSpec1, data: []},
53
52
  {id: 'id2' as PObjectId, spec: columnSpec2, data: []}
54
53
  ] as PColumn<PColumnValues>[]
@@ -61,23 +60,24 @@ describe('PFrameForGraph', () => {
61
60
  kind: 'PColumn',
62
61
  name: 'column2',
63
62
  valueType: 'Int',
64
- axesSpec: [{type: 'String', name: 'axis1', domain: {key1: 'a'}}]
63
+ axesSpec: [{type: 'String', name: 'axis1', domain: {key1: 'a'}}],
64
+ annotations: {[IS_VIRTUAL_COLUMN]: 'true'}
65
65
  });
66
66
  });
67
67
  test('columns are not compatible, additional columns are impossible', () => {
68
- const columnSpec1:PColumnSpec = {
68
+ const columnSpec1: PColumnSpec = {
69
69
  kind: 'PColumn',
70
70
  name: 'column1',
71
71
  valueType: 'Int',
72
72
  axesSpec: [{type: 'String', name: 'axis1', domain: {key1: 'a'}}]
73
73
  }
74
- const columnSpec2:PColumnSpec = {
74
+ const columnSpec2: PColumnSpec = {
75
75
  kind: 'PColumn',
76
76
  name: 'column2',
77
77
  valueType: 'Int',
78
78
  axesSpec: [{type: 'String', name: 'axis1', domain: {key2: 'b'}}]
79
79
  }
80
- const columns:PColumn<TreeNodeAccessor | PColumnValues>[] = [
80
+ const columns: PColumn<TreeNodeAccessor | PColumnValues>[] = [
81
81
  {id: 'id1' as PObjectId, spec: columnSpec1, data: []},
82
82
  {id: 'id2' as PObjectId, spec: columnSpec2, data: []}
83
83
  ] as PColumn<PColumnValues>[]
@@ -86,7 +86,7 @@ describe('PFrameForGraph', () => {
86
86
  expect(additionalColumns.length).toEqual(0);
87
87
  });
88
88
  test('columns are not compatible, 2 additional columns', () => {
89
- const columnSpec1:PColumnSpec = {
89
+ const columnSpec1: PColumnSpec = {
90
90
  kind: 'PColumn',
91
91
  name: 'column1',
92
92
  valueType: 'Int',
@@ -95,13 +95,13 @@ describe('PFrameForGraph', () => {
95
95
  {type: 'String', name: 'axis1', domain: {key1: 'b'}},
96
96
  ]
97
97
  }
98
- const columnSpec2:PColumnSpec = {
98
+ const columnSpec2: PColumnSpec = {
99
99
  kind: 'PColumn',
100
100
  name: 'column2',
101
101
  valueType: 'Int',
102
102
  axesSpec: [{type: 'String', name: 'axis1', domain: {}}]
103
103
  }
104
- const columns:PColumn<TreeNodeAccessor | PColumnValues>[] = [
104
+ const columns: PColumn<TreeNodeAccessor | PColumnValues>[] = [
105
105
  {id: 'id1' as PObjectId, spec: columnSpec1, data: []},
106
106
  {id: 'id2' as PObjectId, spec: columnSpec2, data: []}
107
107
  ] as PColumn<PColumnValues>[]
@@ -110,7 +110,7 @@ describe('PFrameForGraph', () => {
110
110
  expect(additionalColumns.length).toEqual(2);
111
111
  });
112
112
  test('columns are not compatible, 4 additional columns - by 2 axes', () => {
113
- const columnSpec1:PColumnSpec = {
113
+ const columnSpec1: PColumnSpec = {
114
114
  kind: 'PColumn',
115
115
  name: 'column1',
116
116
  valueType: 'Int',
@@ -121,7 +121,7 @@ describe('PFrameForGraph', () => {
121
121
  {type: 'String', name: 'axis2', domain: {key1: 'b'}},
122
122
  ]
123
123
  }
124
- const columnSpec2:PColumnSpec = {
124
+ const columnSpec2: PColumnSpec = {
125
125
  kind: 'PColumn',
126
126
  name: 'column2',
127
127
  valueType: 'Int',
@@ -130,7 +130,7 @@ describe('PFrameForGraph', () => {
130
130
  {type: 'String', name: 'axis2', domain: {}}
131
131
  ]
132
132
  }
133
- const columns:PColumn<TreeNodeAccessor | PColumnValues>[] = [
133
+ const columns: PColumn<TreeNodeAccessor | PColumnValues>[] = [
134
134
  {id: 'id1' as PObjectId, spec: columnSpec1, data: []},
135
135
  {id: 'id2' as PObjectId, spec: columnSpec2, data: []}
136
136
  ] as PColumn<PColumnValues>[]
@@ -138,4 +138,47 @@ describe('PFrameForGraph', () => {
138
138
  const additionalColumns = getAdditionalColumns(columns);
139
139
  expect(additionalColumns.length).toEqual(4);
140
140
  });
141
+
142
+ test('enrichColumnsWithCompatibleMetadata', () => {
143
+ const columnSpec1: PColumnSpec = {
144
+ kind: 'PColumn',
145
+ name: 'column1',
146
+ valueType: 'Int',
147
+ axesSpec: [
148
+ {type: 'String', name: 'axis1', domain: {key1: 'a'}},
149
+ {type: 'String', name: 'axis2', domain: {key1: 'b'}},
150
+ ]
151
+ };
152
+ const metaColumnSpec1: PColumnSpec = {
153
+ kind: 'PColumn',
154
+ name: 'metadata1',
155
+ valueType: 'Int',
156
+ axesSpec: [{type: 'String', name: 'axis1'}]
157
+ };
158
+ const metaColumnSpec2: PColumnSpec = {
159
+ kind: 'PColumn',
160
+ name: 'metadata2',
161
+ valueType: 'String',
162
+ axesSpec: [{type: 'String', name: 'axis1', domain: {key1: 'a'}}]
163
+ };
164
+ const metaColumnSpec3: PColumnSpec = {
165
+ kind: 'PColumn',
166
+ name: 'metadata2',
167
+ valueType: 'String',
168
+ axesSpec: [{type: 'String', name: 'axis3'}]
169
+ };
170
+
171
+ const columns: PColumn<TreeNodeAccessor | PColumnValues>[] = [
172
+ {id: 'id1' as PObjectId, spec: columnSpec1, data: []},
173
+ ] as PColumn<PColumnValues>[];
174
+ const upstream: PColumn<TreeNodeAccessor | PColumnValues>[] = [
175
+ {id: 'id1' as PObjectId, spec: columnSpec1, data: []},
176
+ {id: 'id2' as PObjectId, spec: metaColumnSpec1, data: []},
177
+ {id: 'id3' as PObjectId, spec: metaColumnSpec2, data: []},
178
+ {id: 'id4' as PObjectId, spec: metaColumnSpec3, data: []},
179
+ ] as PColumn<PColumnValues>[];
180
+
181
+ const enrichedColumns = enrichColumnsWithCompatible(columns, upstream);
182
+ expect(enrichedColumns.map((c) => c.id)).toEqual(['id1', 'id2', 'id3'])
183
+ })
141
184
  })
@@ -1,12 +1,15 @@
1
1
  import {
2
2
  AxisId,
3
3
  getAxisId,
4
+ isPColumn,
4
5
  matchAxisId,
5
6
  PColumn,
6
- PColumnValues, PFrameHandle,
7
+ PColumnValues,
8
+ PFrameHandle,
7
9
  PObjectId,
10
+ ValueType,
8
11
  } from '@milaboratories/pl-model-common';
9
- import { RenderCtx, TreeNodeAccessor } from '../render';
12
+ import {RenderCtx, TreeNodeAccessor} from '../render';
10
13
 
11
14
  /** Create id for column copy with added keys in axes domains */
12
15
  const colId = (id: PObjectId, domains: (Record<string, string> | undefined)[]) => {
@@ -38,8 +41,30 @@ function getKeysCombinations(idsLists: AxisId[][]) {
38
41
  return result;
39
42
  }
40
43
 
44
+ /** Check if axes of secondary column are exactly in axes of main column */
45
+ function checkFullCompatibility(
46
+ mainColumn: PColumn<TreeNodeAccessor | PColumnValues>,
47
+ secondaryColumn: PColumn<TreeNodeAccessor | PColumnValues>
48
+ ): boolean {
49
+ const mainAxesIds = mainColumn.spec.axesSpec.map(getAxisId);
50
+ const secondaryAxesIds = secondaryColumn.spec.axesSpec.map(getAxisId);
51
+ return secondaryAxesIds.every(id => mainAxesIds.some(mainId => matchAxisId(mainId, id) && matchAxisId(id, mainId)));
52
+ }
53
+
54
+ /** Check if axes of secondary column are in axes of main column, but they can have compatible difference in domains */
55
+ function checkCompatibility(
56
+ mainColumn: PColumn<TreeNodeAccessor | PColumnValues>,
57
+ secondaryColumn: PColumn<TreeNodeAccessor | PColumnValues>
58
+ ): boolean {
59
+ const mainAxesIds = mainColumn.spec.axesSpec.map(getAxisId);
60
+ const secondaryAxesIds = secondaryColumn.spec.axesSpec.map(getAxisId);
61
+ return secondaryAxesIds.every(id => mainAxesIds.some(mainId => matchAxisId(mainId, id)));
62
+ }
63
+
64
+ export const IS_VIRTUAL_COLUMN = 'pl7.app/graph/isVirtual'; // annotation for column duplicates with extended domains
65
+
41
66
  /** Main column can have additional domains, if secondary column (meta-column) has all axes match main column axes
42
- we can add its copy with missed domain fields for compatibility */
67
+ we can add its copy with missed domain fields for compatibility */
43
68
  function getAdditionalColumnsForPair(
44
69
  mainColumn: PColumn<TreeNodeAccessor | PColumnValues>,
45
70
  secondaryColumn: PColumn<TreeNodeAccessor | PColumnValues>
@@ -47,11 +72,11 @@ function getAdditionalColumnsForPair(
47
72
  const mainAxesIds = mainColumn.spec.axesSpec.map(getAxisId);
48
73
  const secondaryAxesIds = secondaryColumn.spec.axesSpec.map(getAxisId);
49
74
 
50
- const isFullCompatible = secondaryAxesIds.every(id => mainAxesIds.some(mainId => matchAxisId(mainId, id) && matchAxisId(id, mainId)));
75
+ const isFullCompatible = checkFullCompatibility(mainColumn, secondaryColumn);
51
76
  if (isFullCompatible) { // in this case it isn't necessary to add more columns
52
77
  return [];
53
78
  }
54
- const isCompatible = secondaryAxesIds.every(id => mainAxesIds.some(mainId => matchAxisId(mainId, id)));
79
+ const isCompatible = checkCompatibility(mainColumn, secondaryColumn);
55
80
  if (!isCompatible) { // in this case it is impossible to add some compatible column
56
81
  return [];
57
82
  }
@@ -71,14 +96,18 @@ function getAdditionalColumnsForPair(
71
96
  axesSpec: idsList.map((axisId, idx) => ({
72
97
  ...axisId,
73
98
  annotations: secondaryColumn.spec.axesSpec[idx].annotations
74
- }))
99
+ })),
100
+ annotations: {
101
+ ...secondaryColumn.spec.annotations,
102
+ [IS_VIRTUAL_COLUMN]: 'true'
103
+ }
75
104
  },
76
105
  data: secondaryColumn.data
77
106
  };
78
107
  });
79
108
  }
80
109
 
81
- export function getAdditionalColumns(columns: PColumn<TreeNodeAccessor | PColumnValues>[]):PColumn<TreeNodeAccessor | PColumnValues>[] {
110
+ export function getAdditionalColumns(columns: PColumn<TreeNodeAccessor | PColumnValues>[]): PColumn<TreeNodeAccessor | PColumnValues>[] {
82
111
  const additionalColumns: PColumn<TreeNodeAccessor | PColumnValues>[] = [];
83
112
  for (let i = 0; i < columns.length; i++) {
84
113
  for (let j = i + 1; j < columns.length; j++) {
@@ -95,11 +124,51 @@ export function getAdditionalColumns(columns: PColumn<TreeNodeAccessor | PColumn
95
124
  return additionalColumns;
96
125
  }
97
126
 
127
+ export function enrichColumnsWithCompatible(
128
+ mainColumns: PColumn<TreeNodeAccessor | PColumnValues>[],
129
+ secondaryColumns: PColumn<TreeNodeAccessor | PColumnValues>[]
130
+ ): PColumn<TreeNodeAccessor | PColumnValues>[] {
131
+ const result = [...mainColumns];
132
+ for (const secondaryColumn of secondaryColumns) {
133
+ for (const mainColumn of mainColumns) {
134
+ if (mainColumn.id === secondaryColumn.id) {
135
+ break;
136
+ }
137
+ if (checkCompatibility(mainColumn, secondaryColumn)) {
138
+ result.push(secondaryColumn);
139
+ break;
140
+ }
141
+ }
142
+ }
143
+ return result;
144
+ }
145
+
146
+ const VALUE_TYPES: ValueType[] = [
147
+ 'Int',
148
+ 'Long',
149
+ 'Float',
150
+ 'Double',
151
+ 'String',
152
+ 'Bytes'
153
+ ];
154
+
98
155
  export function createPFrameForGraphs<A, U>(
99
156
  ctx: RenderCtx<A, U>,
100
- columns: PColumn<TreeNodeAccessor | PColumnValues>[]
157
+ blockColumns?: PColumn<TreeNodeAccessor | PColumnValues>[]
101
158
  ): PFrameHandle | undefined {
102
- const extendedColumns = [...columns, ...getAdditionalColumns(columns)];
159
+ if (blockColumns === undefined) return undefined;
160
+
161
+ const upstreamColumns = ctx.resultPool
162
+ .getData()
163
+ .entries.map((v) => v.obj)
164
+ .filter(isPColumn)
165
+ .filter((column) => VALUE_TYPES.includes(column.spec.valueType));
166
+
167
+ const columnsWithCompatibleFromUpstream = enrichColumnsWithCompatible(blockColumns, upstreamColumns);
168
+
169
+ // additional columns are duplicates with extra fields in domains for compatibility in all possible pairs of columns set
170
+ const extendedColumns = [...columnsWithCompatibleFromUpstream, ...getAdditionalColumns(columnsWithCompatibleFromUpstream)];
171
+
103
172
  // if at least one column is not yet ready, we can't show the table
104
173
  if (
105
174
  extendedColumns.some(
@@ -109,4 +178,4 @@ export function createPFrameForGraphs<A, U>(
109
178
  return undefined;
110
179
 
111
180
  return ctx.createPFrame(extendedColumns);
112
- }
181
+ }