@finos/legend-query-builder 4.14.71 → 4.14.73
Sign up to get free protection for your applications and to get access to all the features.
- package/lib/components/QueryLoader.d.ts.map +1 -1
- package/lib/components/QueryLoader.js +12 -34
- package/lib/components/QueryLoader.js.map +1 -1
- package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts.map +1 -1
- package/lib/components/explorer/QueryBuilderPropertySearchPanel.js +108 -36
- package/lib/components/explorer/QueryBuilderPropertySearchPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +10 -3
- package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js +2 -2
- package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +6 -2
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
- package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
- package/lib/components/filter/QueryBuilderFilterPanel.js +5 -1
- package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
- package/lib/components/result/QueryBuilderResultPanel.d.ts.map +1 -1
- package/lib/components/result/QueryBuilderResultPanel.js +3 -1
- package/lib/components/result/QueryBuilderResultPanel.js.map +1 -1
- package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts.map +1 -1
- package/lib/components/result/tds/QueryBuilderTDSGridResult.js +5 -2
- package/lib/components/result/tds/QueryBuilderTDSGridResult.js.map +1 -1
- package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.d.ts +3 -0
- package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.d.ts.map +1 -1
- package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.js +92 -2
- package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.js.map +1 -1
- package/lib/index.css +1 -17
- package/lib/index.css.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/QueryBuilderConfig.d.ts +2 -1
- package/lib/stores/QueryBuilderConfig.d.ts.map +1 -1
- package/lib/stores/QueryBuilderConfig.js +2 -1
- package/lib/stores/QueryBuilderConfig.js.map +1 -1
- package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
- package/lib/stores/QueryBuilderResultState.js +4 -1
- package/lib/stores/QueryBuilderResultState.js.map +1 -1
- package/lib/stores/QueryBuilderValueSpecificationHelper.d.ts +1 -1
- package/lib/stores/QueryBuilderValueSpecificationHelper.d.ts.map +1 -1
- package/lib/stores/QueryBuilderValueSpecificationHelper.js +1 -0
- package/lib/stores/QueryBuilderValueSpecificationHelper.js.map +1 -1
- package/lib/stores/QueryLoaderState.d.ts +8 -6
- package/lib/stores/QueryLoaderState.d.ts.map +1 -1
- package/lib/stores/QueryLoaderState.js +30 -7
- package/lib/stores/QueryLoaderState.js.map +1 -1
- package/lib/stores/explorer/QueryBuilderExplorerState.d.ts +4 -3
- package/lib/stores/explorer/QueryBuilderExplorerState.d.ts.map +1 -1
- package/lib/stores/explorer/QueryBuilderExplorerState.js +22 -7
- package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
- package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.d.ts.map +1 -1
- package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js +1 -1
- package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js.map +1 -1
- package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts +7 -1
- package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts.map +1 -1
- package/lib/stores/explorer/QueryBuilderPropertySearchState.js +160 -74
- package/lib/stores/explorer/QueryBuilderPropertySearchState.js.map +1 -1
- package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts +4 -1
- package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts.map +1 -1
- package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js +23 -12
- package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.d.ts +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.js +9 -5
- package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
- package/package.json +3 -3
- package/src/components/QueryLoader.tsx +37 -54
- package/src/components/explorer/QueryBuilderPropertySearchPanel.tsx +249 -226
- package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +24 -2
- package/src/components/fetch-structure/QueryBuilderResultModifierPanel.tsx +6 -2
- package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +10 -2
- package/src/components/filter/QueryBuilderFilterPanel.tsx +10 -1
- package/src/components/result/QueryBuilderResultPanel.tsx +3 -1
- package/src/components/result/tds/QueryBuilderTDSGridResult.tsx +8 -2
- package/src/components/result/tds/QueryBuilderTDSSimpleGridResult.tsx +106 -1
- package/src/stores/QueryBuilderConfig.ts +2 -1
- package/src/stores/QueryBuilderResultState.ts +4 -0
- package/src/stores/QueryBuilderValueSpecificationHelper.ts +2 -1
- package/src/stores/QueryLoaderState.ts +43 -17
- package/src/stores/explorer/QueryBuilderExplorerState.ts +58 -5
- package/src/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.ts +1 -1
- package/src/stores/explorer/QueryBuilderPropertySearchState.ts +194 -92
- package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +43 -13
- package/src/stores/filter/QueryBuilderFilterState.ts +16 -7
@@ -23,15 +23,16 @@ import {
|
|
23
23
|
PRIMITIVE_TYPE,
|
24
24
|
CORE_PURE_PATH,
|
25
25
|
PURE_DOC_TAG,
|
26
|
+
Enumeration,
|
26
27
|
} from '@finos/legend-graph';
|
27
28
|
import {
|
29
|
+
type FuzzySearchEngineSortFunctionArg,
|
28
30
|
ActionState,
|
29
31
|
FuzzySearchEngine,
|
30
32
|
addUniqueEntry,
|
31
33
|
deleteEntry,
|
32
34
|
guaranteeNonNullable,
|
33
35
|
isNonNullable,
|
34
|
-
type FuzzySearchEngineSortFunctionArg,
|
35
36
|
} from '@finos/legend-shared';
|
36
37
|
import {
|
37
38
|
observable,
|
@@ -47,11 +48,13 @@ import {
|
|
47
48
|
QUERY_BUILDER_PROPERTY_SEARCH_MAX_NODES,
|
48
49
|
} from '../QueryBuilderConfig.js';
|
49
50
|
import {
|
51
|
+
type QueryBuilderExplorerTreeNodeData,
|
50
52
|
getQueryBuilderPropertyNodeData,
|
51
53
|
getQueryBuilderSubTypeNodeData,
|
52
|
-
type QueryBuilderExplorerTreeNodeData,
|
53
54
|
QueryBuilderExplorerTreePropertyNodeData,
|
54
55
|
QueryBuilderExplorerTreeSubTypeNodeData,
|
56
|
+
cloneQueryBuilderExplorerTreeNodeData,
|
57
|
+
QueryBuilderExplorerTreeRootNodeData,
|
55
58
|
} from './QueryBuilderExplorerState.js';
|
56
59
|
import type { QueryBuilderState } from '../QueryBuilderState.js';
|
57
60
|
import { QueryBuilderFuzzySearchAdvancedConfigState } from './QueryBuilderFuzzySearchAdvancedConfigState.js';
|
@@ -74,7 +77,8 @@ export class QueryBuilderPropertySearchState {
|
|
74
77
|
* is that we could interact with the searched nodes, i.e. drag them to
|
75
78
|
* various panels to create filter, fetch-structure, etc.
|
76
79
|
*/
|
77
|
-
|
80
|
+
indexedExplorerTreeNodeMap: Map<string, QueryBuilderExplorerTreeNodeData> =
|
81
|
+
new Map();
|
78
82
|
|
79
83
|
// search
|
80
84
|
searchEngine: FuzzySearchEngine<QueryBuilderExplorerTreeNodeData>;
|
@@ -89,8 +93,10 @@ export class QueryBuilderPropertySearchState {
|
|
89
93
|
showSearchConfigurationMenu = false;
|
90
94
|
|
91
95
|
// filter
|
96
|
+
includeOneMany = false;
|
92
97
|
typeFilters = [
|
93
98
|
QUERY_BUILDER_PROPERTY_SEARCH_TYPE.CLASS,
|
99
|
+
QUERY_BUILDER_PROPERTY_SEARCH_TYPE.ENUMERATION,
|
94
100
|
QUERY_BUILDER_PROPERTY_SEARCH_TYPE.STRING,
|
95
101
|
QUERY_BUILDER_PROPERTY_SEARCH_TYPE.BOOLEAN,
|
96
102
|
QUERY_BUILDER_PROPERTY_SEARCH_TYPE.NUMBER,
|
@@ -99,14 +105,16 @@ export class QueryBuilderPropertySearchState {
|
|
99
105
|
|
100
106
|
constructor(queryBuilderState: QueryBuilderState) {
|
101
107
|
makeObservable(this, {
|
102
|
-
|
108
|
+
indexedExplorerTreeNodeMap: observable,
|
103
109
|
searchText: observable,
|
104
110
|
searchResults: observable,
|
105
111
|
isOverSearchLimit: observable,
|
106
112
|
isSearchPanelOpen: observable,
|
107
113
|
isSearchPanelHidden: observable,
|
108
114
|
showSearchConfigurationMenu: observable,
|
115
|
+
includeOneMany: observable,
|
109
116
|
typeFilters: observable,
|
117
|
+
indexedExplorerTreeNodes: computed,
|
110
118
|
filteredSearchResults: computed,
|
111
119
|
search: action,
|
112
120
|
resetSearch: action,
|
@@ -116,6 +124,8 @@ export class QueryBuilderPropertySearchState {
|
|
116
124
|
setShowSearchConfigurationMenu: action,
|
117
125
|
setIsSearchPanelOpen: action,
|
118
126
|
setIsSearchPanelHidden: action,
|
127
|
+
setIncludeOneMany: action,
|
128
|
+
setFilterOnlyType: action,
|
119
129
|
toggleFilterForType: action,
|
120
130
|
initialize: action,
|
121
131
|
});
|
@@ -156,9 +166,22 @@ export class QueryBuilderPropertySearchState {
|
|
156
166
|
resetSearch(): void {
|
157
167
|
this.searchText = '';
|
158
168
|
this.searchResults = [];
|
169
|
+
this.indexedExplorerTreeNodes.forEach((node) => {
|
170
|
+
if (!(node instanceof QueryBuilderExplorerTreeRootNodeData)) {
|
171
|
+
node.setIsOpen(false);
|
172
|
+
}
|
173
|
+
});
|
159
174
|
this.searchState.complete();
|
160
175
|
}
|
161
176
|
|
177
|
+
setIncludeOneMany(val: boolean): void {
|
178
|
+
this.includeOneMany = val;
|
179
|
+
}
|
180
|
+
|
181
|
+
setFilterOnlyType(val: QUERY_BUILDER_PROPERTY_SEARCH_TYPE): void {
|
182
|
+
this.typeFilters = [val];
|
183
|
+
}
|
184
|
+
|
162
185
|
toggleFilterForType(val: QUERY_BUILDER_PROPERTY_SEARCH_TYPE): void {
|
163
186
|
if (this.typeFilters.includes(val)) {
|
164
187
|
deleteEntry(this.typeFilters, val);
|
@@ -167,6 +190,29 @@ export class QueryBuilderPropertySearchState {
|
|
167
190
|
}
|
168
191
|
}
|
169
192
|
|
193
|
+
isNodeMultiple(node: QueryBuilderExplorerTreeNodeData): boolean {
|
194
|
+
// Check if node or any ancestors are one-many nodes.
|
195
|
+
let currNode: QueryBuilderExplorerTreeNodeData | undefined = node;
|
196
|
+
while (currNode) {
|
197
|
+
if (
|
198
|
+
(currNode instanceof QueryBuilderExplorerTreeSubTypeNodeData &&
|
199
|
+
(currNode.multiplicity.upperBound === undefined ||
|
200
|
+
currNode.multiplicity.upperBound > 1)) ||
|
201
|
+
(currNode instanceof QueryBuilderExplorerTreePropertyNodeData &&
|
202
|
+
(currNode.property.multiplicity.upperBound === undefined ||
|
203
|
+
currNode.property.multiplicity.upperBound > 1))
|
204
|
+
) {
|
205
|
+
return true;
|
206
|
+
}
|
207
|
+
currNode =
|
208
|
+
currNode instanceof QueryBuilderExplorerTreePropertyNodeData ||
|
209
|
+
currNode instanceof QueryBuilderExplorerTreeSubTypeNodeData
|
210
|
+
? this.indexedExplorerTreeNodeMap.get(currNode.parentId)
|
211
|
+
: undefined;
|
212
|
+
}
|
213
|
+
return false;
|
214
|
+
}
|
215
|
+
|
170
216
|
async search(): Promise<void> {
|
171
217
|
if (!this.searchText) {
|
172
218
|
this.setSearchResults([]);
|
@@ -175,6 +221,12 @@ export class QueryBuilderPropertySearchState {
|
|
175
221
|
|
176
222
|
this.searchState.inProgress();
|
177
223
|
|
224
|
+
this.indexedExplorerTreeNodes.forEach((node) => {
|
225
|
+
if (!(node instanceof QueryBuilderExplorerTreeRootNodeData)) {
|
226
|
+
node.setIsOpen(false);
|
227
|
+
}
|
228
|
+
});
|
229
|
+
|
178
230
|
// Perform the search in a setTimeout so we can execute it asynchronously and
|
179
231
|
// show the loading indicator while search is in progress.
|
180
232
|
return new Promise((resolve) =>
|
@@ -210,18 +262,13 @@ export class QueryBuilderPropertySearchState {
|
|
210
262
|
return node;
|
211
263
|
})
|
212
264
|
.filter((node) => {
|
213
|
-
// Filter out
|
214
|
-
if (
|
215
|
-
|
216
|
-
|
217
|
-
node
|
265
|
+
// Filter out nodes if their parent class node is already in the results.
|
266
|
+
if (
|
267
|
+
(node instanceof QueryBuilderExplorerTreePropertyNodeData ||
|
268
|
+
node instanceof QueryBuilderExplorerTreeSubTypeNodeData) &&
|
269
|
+
classNodes.has(node.parentId)
|
218
270
|
) {
|
219
|
-
|
220
|
-
return true;
|
221
|
-
} else if (classNodes.has(node.parentId)) {
|
222
|
-
classNodes.get(node.parentId)?.setIsOpen(true);
|
223
|
-
return false;
|
224
|
-
}
|
271
|
+
return false;
|
225
272
|
}
|
226
273
|
return true;
|
227
274
|
});
|
@@ -260,22 +307,26 @@ export class QueryBuilderPropertySearchState {
|
|
260
307
|
// show the loading indicator while initialization is in progress.
|
261
308
|
return new Promise((resolve) =>
|
262
309
|
setTimeout(() => {
|
263
|
-
|
310
|
+
const treeData =
|
311
|
+
this.queryBuilderState.explorerState.nonNullableTreeData;
|
312
|
+
const rootNodeMap = new Map(
|
313
|
+
treeData.rootIds
|
314
|
+
.map((rootId) => treeData.nodes.get(rootId))
|
315
|
+
.filter(isNonNullable)
|
316
|
+
.map((rootNode) => [rootNode.id, rootNode]),
|
317
|
+
);
|
318
|
+
this.indexedExplorerTreeNodeMap = new Map();
|
264
319
|
|
265
320
|
let currentLevelPropertyNodes: QueryBuilderExplorerTreeNodeData[] = [];
|
266
321
|
let nextLevelPropertyNodes: QueryBuilderExplorerTreeNodeData[] = [];
|
267
322
|
|
268
323
|
// Get all the children of the root node(s)
|
269
324
|
Array.from(
|
270
|
-
|
325
|
+
treeData.rootIds
|
271
326
|
.map((rootId) =>
|
272
|
-
|
327
|
+
treeData.nodes
|
273
328
|
.get(rootId)
|
274
|
-
?.childrenIds.map((childId) =>
|
275
|
-
this.queryBuilderState.explorerState.nonNullableTreeData.nodes.get(
|
276
|
-
childId,
|
277
|
-
),
|
278
|
-
),
|
329
|
+
?.childrenIds.map((childId) => treeData.nodes.get(childId)),
|
279
330
|
)
|
280
331
|
.flat()
|
281
332
|
.filter(isNonNullable)
|
@@ -287,24 +338,54 @@ export class QueryBuilderPropertySearchState {
|
|
287
338
|
),
|
288
339
|
).forEach((node) => {
|
289
340
|
if (node.mappingData.mapped && !node.isPartOfDerivedPropertyBranch) {
|
290
|
-
|
291
|
-
|
341
|
+
const clonedNode = cloneQueryBuilderExplorerTreeNodeData(node);
|
342
|
+
currentLevelPropertyNodes.push(clonedNode);
|
343
|
+
this.indexedExplorerTreeNodeMap.set(clonedNode.id, clonedNode);
|
292
344
|
}
|
293
345
|
});
|
294
346
|
|
295
347
|
// ensure we don't navigate more nodes than the limit so we could
|
296
348
|
// keep the initialization/indexing time within acceptable range
|
297
349
|
const NODE_LIMIT =
|
298
|
-
this.
|
350
|
+
this.indexedExplorerTreeNodeMap.size +
|
299
351
|
QUERY_BUILDER_PROPERTY_SEARCH_MAX_NODES;
|
300
352
|
const addNode = (node: QueryBuilderExplorerTreeNodeData): void =>
|
301
353
|
runInAction(() => {
|
302
|
-
if (this.
|
354
|
+
if (this.indexedExplorerTreeNodeMap.size > NODE_LIMIT) {
|
303
355
|
return;
|
304
356
|
}
|
305
|
-
|
357
|
+
const clonedNode = cloneQueryBuilderExplorerTreeNodeData(node);
|
358
|
+
this.indexedExplorerTreeNodeMap.set(clonedNode.id, clonedNode);
|
306
359
|
});
|
307
360
|
|
361
|
+
// helper function to check if a node has the same type as one of its
|
362
|
+
// ancestor nodes. This allows us to avoid including circular dependencies
|
363
|
+
// in the indexed nodes list.
|
364
|
+
const nodeHasSameTypeAsAncestor = (
|
365
|
+
node: QueryBuilderExplorerTreeNodeData,
|
366
|
+
): boolean => {
|
367
|
+
if (
|
368
|
+
node instanceof QueryBuilderExplorerTreePropertyNodeData ||
|
369
|
+
node instanceof QueryBuilderExplorerTreeSubTypeNodeData
|
370
|
+
) {
|
371
|
+
let ancestor =
|
372
|
+
this.indexedExplorerTreeNodeMap.get(node.parentId) ??
|
373
|
+
rootNodeMap.get(node.parentId);
|
374
|
+
while (ancestor) {
|
375
|
+
if (node.type === ancestor.type) {
|
376
|
+
return true;
|
377
|
+
}
|
378
|
+
ancestor =
|
379
|
+
ancestor instanceof QueryBuilderExplorerTreePropertyNodeData ||
|
380
|
+
ancestor instanceof QueryBuilderExplorerTreeSubTypeNodeData
|
381
|
+
? (this.indexedExplorerTreeNodeMap.get(ancestor.parentId) ??
|
382
|
+
rootNodeMap.get(ancestor.parentId))
|
383
|
+
: undefined;
|
384
|
+
}
|
385
|
+
}
|
386
|
+
return false;
|
387
|
+
};
|
388
|
+
|
308
389
|
// limit the depth of navigation to keep the initialization/indexing
|
309
390
|
// time within acceptable range
|
310
391
|
let currentDepth = 1;
|
@@ -336,8 +417,10 @@ export class QueryBuilderPropertySearchState {
|
|
336
417
|
),
|
337
418
|
);
|
338
419
|
if (
|
339
|
-
propertyTreeNodeData
|
340
|
-
|
420
|
+
propertyTreeNodeData &&
|
421
|
+
propertyTreeNodeData.mappingData.mapped &&
|
422
|
+
!propertyTreeNodeData.isPartOfDerivedPropertyBranch &&
|
423
|
+
!nodeHasSameTypeAsAncestor(propertyTreeNodeData)
|
341
424
|
) {
|
342
425
|
nextLevelPropertyNodes.push(propertyTreeNodeData);
|
343
426
|
addNode(propertyTreeNodeData);
|
@@ -353,7 +436,10 @@ export class QueryBuilderPropertySearchState {
|
|
353
436
|
.mappingModelCoverageAnalysisResult,
|
354
437
|
),
|
355
438
|
);
|
356
|
-
if (
|
439
|
+
if (
|
440
|
+
subTypeTreeNodeData.mappingData.mapped &&
|
441
|
+
!nodeHasSameTypeAsAncestor(subTypeTreeNodeData)
|
442
|
+
) {
|
357
443
|
nextLevelPropertyNodes.push(subTypeTreeNodeData);
|
358
444
|
addNode(subTypeTreeNodeData);
|
359
445
|
}
|
@@ -365,7 +451,7 @@ export class QueryBuilderPropertySearchState {
|
|
365
451
|
// number of indexed nodes to figure out if we should proceed further
|
366
452
|
if (
|
367
453
|
!currentLevelPropertyNodes.length &&
|
368
|
-
this.
|
454
|
+
this.indexedExplorerTreeNodeMap.size < NODE_LIMIT
|
369
455
|
) {
|
370
456
|
currentLevelPropertyNodes = nextLevelPropertyNodes;
|
371
457
|
nextLevelPropertyNodes = [];
|
@@ -388,21 +474,25 @@ export class QueryBuilderPropertySearchState {
|
|
388
474
|
threshold: 0.2,
|
389
475
|
keys: [
|
390
476
|
{
|
391
|
-
name: '
|
477
|
+
name: 'label',
|
392
478
|
weight: 4,
|
479
|
+
},
|
480
|
+
{
|
481
|
+
name: 'path',
|
482
|
+
weight: 2,
|
393
483
|
getFn: (node) => {
|
394
|
-
const parentNode =
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
QueryBuilderExplorerTreeSubTypeNodeData
|
484
|
+
const parentNode =
|
485
|
+
node instanceof QueryBuilderExplorerTreePropertyNodeData ||
|
486
|
+
node instanceof QueryBuilderExplorerTreeSubTypeNodeData
|
487
|
+
? this.indexedExplorerTreeNodeMap.get(node.parentId)
|
488
|
+
: undefined;
|
489
|
+
|
490
|
+
const fullPath = parentNode
|
491
|
+
? parentNode instanceof
|
492
|
+
QueryBuilderExplorerTreeSubTypeNodeData
|
404
493
|
? prettyPropertyNameForSubType(node.id)
|
405
|
-
: prettyPropertyNameFromNodeId(node.id)
|
494
|
+
: prettyPropertyNameFromNodeId(node.id)
|
495
|
+
: '';
|
406
496
|
|
407
497
|
return fullPath;
|
408
498
|
},
|
@@ -471,61 +561,73 @@ export class QueryBuilderPropertySearchState {
|
|
471
561
|
);
|
472
562
|
}
|
473
563
|
|
474
|
-
get
|
475
|
-
return this.
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
564
|
+
get indexedExplorerTreeNodes(): QueryBuilderExplorerTreeNodeData[] {
|
565
|
+
return Array.from(this.indexedExplorerTreeNodeMap.values());
|
566
|
+
}
|
567
|
+
|
568
|
+
isNodeIncludedInFilter(node: QueryBuilderExplorerTreeNodeData): boolean {
|
569
|
+
if (!this.includeOneMany && this.isNodeMultiple(node)) {
|
570
|
+
return false;
|
571
|
+
}
|
572
|
+
if (this.typeFilters.includes(QUERY_BUILDER_PROPERTY_SEARCH_TYPE.CLASS)) {
|
573
|
+
if (node.type instanceof Class) {
|
574
|
+
return true;
|
480
575
|
}
|
481
|
-
|
482
|
-
|
483
|
-
)
|
484
|
-
|
485
|
-
|
486
|
-
|
576
|
+
}
|
577
|
+
if (
|
578
|
+
this.typeFilters.includes(QUERY_BUILDER_PROPERTY_SEARCH_TYPE.ENUMERATION)
|
579
|
+
) {
|
580
|
+
if (node.type instanceof Enumeration) {
|
581
|
+
return true;
|
487
582
|
}
|
583
|
+
}
|
584
|
+
if (this.typeFilters.includes(QUERY_BUILDER_PROPERTY_SEARCH_TYPE.STRING)) {
|
585
|
+
if (node.type === PrimitiveType.STRING) {
|
586
|
+
return true;
|
587
|
+
}
|
588
|
+
}
|
589
|
+
if (this.typeFilters.includes(QUERY_BUILDER_PROPERTY_SEARCH_TYPE.NUMBER)) {
|
488
590
|
if (
|
489
|
-
|
591
|
+
node.type instanceof PrimitiveType &&
|
592
|
+
(
|
593
|
+
[
|
594
|
+
PRIMITIVE_TYPE.NUMBER,
|
595
|
+
PRIMITIVE_TYPE.DECIMAL,
|
596
|
+
PRIMITIVE_TYPE.INTEGER,
|
597
|
+
PRIMITIVE_TYPE.FLOAT,
|
598
|
+
] as string[]
|
599
|
+
).includes(node.type.name)
|
490
600
|
) {
|
491
|
-
|
492
|
-
node.type instanceof PrimitiveType &&
|
493
|
-
(
|
494
|
-
[
|
495
|
-
PRIMITIVE_TYPE.NUMBER,
|
496
|
-
PRIMITIVE_TYPE.DECIMAL,
|
497
|
-
PRIMITIVE_TYPE.INTEGER,
|
498
|
-
PRIMITIVE_TYPE.FLOAT,
|
499
|
-
] as string[]
|
500
|
-
).includes(node.type.name)
|
501
|
-
) {
|
502
|
-
return true;
|
503
|
-
}
|
601
|
+
return true;
|
504
602
|
}
|
603
|
+
}
|
604
|
+
if (this.typeFilters.includes(QUERY_BUILDER_PROPERTY_SEARCH_TYPE.BOOLEAN)) {
|
605
|
+
if (node.type === PrimitiveType.BOOLEAN) {
|
606
|
+
return true;
|
607
|
+
}
|
608
|
+
}
|
609
|
+
if (this.typeFilters.includes(QUERY_BUILDER_PROPERTY_SEARCH_TYPE.DATE)) {
|
505
610
|
if (
|
506
|
-
|
611
|
+
node.type instanceof PrimitiveType &&
|
612
|
+
(
|
613
|
+
[
|
614
|
+
PRIMITIVE_TYPE.DATE,
|
615
|
+
PRIMITIVE_TYPE.DATETIME,
|
616
|
+
PRIMITIVE_TYPE.STRICTDATE,
|
617
|
+
PRIMITIVE_TYPE.STRICTTIME,
|
618
|
+
PRIMITIVE_TYPE.LATESTDATE,
|
619
|
+
] as string[]
|
620
|
+
).includes(node.type.name)
|
507
621
|
) {
|
508
|
-
|
509
|
-
return true;
|
510
|
-
}
|
622
|
+
return true;
|
511
623
|
}
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
PRIMITIVE_TYPE.STRICTTIME,
|
521
|
-
PRIMITIVE_TYPE.LATESTDATE,
|
522
|
-
] as string[]
|
523
|
-
).includes(node.type.name)
|
524
|
-
) {
|
525
|
-
return true;
|
526
|
-
}
|
527
|
-
}
|
528
|
-
return false;
|
529
|
-
});
|
624
|
+
}
|
625
|
+
return false;
|
626
|
+
}
|
627
|
+
|
628
|
+
get filteredSearchResults(): QueryBuilderExplorerTreeNodeData[] {
|
629
|
+
return this.searchResults.filter((node) =>
|
630
|
+
this.isNodeIncludedInFilter(node),
|
631
|
+
);
|
530
632
|
}
|
531
633
|
}
|
@@ -19,13 +19,13 @@ import {
|
|
19
19
|
type PureModel,
|
20
20
|
type Type,
|
21
21
|
type ValueSpecification,
|
22
|
-
type ExecutionResult,
|
23
|
-
type VariableExpression,
|
24
22
|
type SimpleFunctionExpression,
|
23
|
+
type ExecutionResultWithMetadata,
|
25
24
|
observe_ValueSpecification,
|
26
25
|
PrimitiveType,
|
27
26
|
CollectionInstanceValue,
|
28
27
|
InstanceValue,
|
28
|
+
VariableExpression,
|
29
29
|
} from '@finos/legend-graph';
|
30
30
|
import {
|
31
31
|
type GeneratorFn,
|
@@ -74,11 +74,13 @@ import type { QueryBuilderTDSColumnState } from '../QueryBuilderTDSColumnState.j
|
|
74
74
|
import {
|
75
75
|
getCollectionValueSpecificationType,
|
76
76
|
getNonCollectionValueSpecificationType,
|
77
|
+
isTypeCompatibleForAssignment,
|
77
78
|
isValidInstanceValue,
|
78
79
|
isValueExpressionReferencedInValue,
|
79
80
|
} from '../../../QueryBuilderValueSpecificationHelper.js';
|
80
81
|
import { buildtdsPropertyExpressionFromColState } from './operators/QueryBuilderPostFilterOperatorValueSpecificationBuilder.js';
|
81
82
|
import { TDS_COLUMN_GETTER } from '../../../../graph/QueryBuilderMetaModelConst.js';
|
83
|
+
import type { QueryBuilderFilterTreeNodeData } from '../../../filter/QueryBuilderFilterState.js';
|
82
84
|
|
83
85
|
export enum QUERY_BUILDER_POST_FILTER_DND_TYPE {
|
84
86
|
GROUP_CONDITION = 'QUERY_BUILDER_POST_FILTER_DND_TYPE.GROUP_CONDITION',
|
@@ -488,7 +490,7 @@ export class PostFilterConditionState implements Hashable {
|
|
488
490
|
);
|
489
491
|
const value = searchValue ?? rightConditionValue.value;
|
490
492
|
if (performTypeahead(value)) {
|
491
|
-
const result =
|
493
|
+
const result = (
|
492
494
|
(yield this.postFilterState.tdsState.queryBuilderState.graphManagerState.graphManager.runQuery(
|
493
495
|
buildProjectionColumnTypeaheadQuery(
|
494
496
|
this.postFilterState.tdsState.queryBuilderState,
|
@@ -505,7 +507,8 @@ export class PostFilterConditionState implements Hashable {
|
|
505
507
|
),
|
506
508
|
this.postFilterState.tdsState.queryBuilderState.graphManagerState
|
507
509
|
.graph,
|
508
|
-
)) as
|
510
|
+
)) as ExecutionResultWithMetadata
|
511
|
+
).executionResult;
|
509
512
|
this.typeaheadSearchResults = buildTypeaheadOptions(result);
|
510
513
|
}
|
511
514
|
this.typeaheadSearchState.pass();
|
@@ -1011,15 +1014,45 @@ export class QueryBuilderPostFilterState
|
|
1011
1014
|
);
|
1012
1015
|
}
|
1013
1016
|
|
1017
|
+
isInvalidValueSpecPostFilterValue(
|
1018
|
+
node: QueryBuilderPostFilterTreeNodeData,
|
1019
|
+
): boolean {
|
1020
|
+
return (
|
1021
|
+
node instanceof QueryBuilderPostFilterTreeConditionNodeData &&
|
1022
|
+
node.condition.rightConditionValue instanceof
|
1023
|
+
PostFilterValueSpecConditionValueState &&
|
1024
|
+
((node.condition.rightConditionValue.value instanceof InstanceValue &&
|
1025
|
+
!isValidInstanceValue(node.condition.rightConditionValue.value)) ||
|
1026
|
+
(node.condition.rightConditionValue.value instanceof
|
1027
|
+
VariableExpression &&
|
1028
|
+
!isTypeCompatibleForAssignment(
|
1029
|
+
node.condition.leftConditionValue.getColumnType(),
|
1030
|
+
node.condition.rightConditionValue.type,
|
1031
|
+
)))
|
1032
|
+
);
|
1033
|
+
}
|
1034
|
+
|
1035
|
+
isInvalidTDSColumnPostFilterValue(
|
1036
|
+
node: QueryBuilderFilterTreeNodeData,
|
1037
|
+
): boolean {
|
1038
|
+
return (
|
1039
|
+
node instanceof QueryBuilderPostFilterTreeConditionNodeData &&
|
1040
|
+
node.condition.rightConditionValue instanceof
|
1041
|
+
PostFilterTDSColumnValueConditionValueState &&
|
1042
|
+
!isTypeCompatibleForAssignment(
|
1043
|
+
node.condition.leftConditionValue.getColumnType(),
|
1044
|
+
node.condition.rightConditionValue.type,
|
1045
|
+
)
|
1046
|
+
);
|
1047
|
+
}
|
1048
|
+
|
1014
1049
|
get allValidationIssues(): string[] {
|
1015
1050
|
const validationIssues: string[] = [];
|
1016
1051
|
Array.from(this.nodes.values()).forEach((node) => {
|
1017
1052
|
if (node instanceof QueryBuilderPostFilterTreeConditionNodeData) {
|
1018
1053
|
if (
|
1019
|
-
node
|
1020
|
-
|
1021
|
-
node.condition.rightConditionValue.value instanceof InstanceValue &&
|
1022
|
-
!isValidInstanceValue(node.condition.rightConditionValue.value)
|
1054
|
+
this.isInvalidValueSpecPostFilterValue(node) ||
|
1055
|
+
this.isInvalidTDSColumnPostFilterValue(node)
|
1023
1056
|
) {
|
1024
1057
|
validationIssues.push(
|
1025
1058
|
`Filter value for ${node.condition.leftConditionValue.columnName} is missing or invalid`,
|
@@ -1042,11 +1075,8 @@ export class QueryBuilderPostFilterState
|
|
1042
1075
|
get hasInvalidFilterValues(): boolean {
|
1043
1076
|
return Array.from(this.nodes.values()).some(
|
1044
1077
|
(node) =>
|
1045
|
-
node
|
1046
|
-
node
|
1047
|
-
PostFilterValueSpecConditionValueState &&
|
1048
|
-
node.condition.rightConditionValue.value instanceof InstanceValue &&
|
1049
|
-
!isValidInstanceValue(node.condition.rightConditionValue.value),
|
1078
|
+
this.isInvalidValueSpecPostFilterValue(node) ||
|
1079
|
+
this.isInvalidTDSColumnPostFilterValue(node),
|
1050
1080
|
);
|
1051
1081
|
}
|
1052
1082
|
|
@@ -37,15 +37,15 @@ import type { QueryBuilderExplorerTreeDragSource } from '../explorer/QueryBuilde
|
|
37
37
|
import { QueryBuilderPropertyExpressionState } from '../QueryBuilderPropertyEditorState.js';
|
38
38
|
import type { QueryBuilderState } from '../QueryBuilderState.js';
|
39
39
|
import {
|
40
|
-
type ExecutionResult,
|
41
|
-
AbstractPropertyExpression,
|
42
40
|
type ValueSpecification,
|
43
|
-
type VariableExpression,
|
44
41
|
type Type,
|
42
|
+
type ExecutionResultWithMetadata,
|
43
|
+
AbstractPropertyExpression,
|
45
44
|
observe_ValueSpecification,
|
46
45
|
CollectionInstanceValue,
|
47
46
|
InstanceValue,
|
48
47
|
SimpleFunctionExpression,
|
48
|
+
VariableExpression,
|
49
49
|
matchFunctionName,
|
50
50
|
} from '@finos/legend-graph';
|
51
51
|
import { DEFAULT_LAMBDA_VARIABLE_NAME } from '../QueryBuilderConfig.js';
|
@@ -61,6 +61,7 @@ import { QUERY_BUILDER_STATE_HASH_STRUCTURE } from '../QueryBuilderStateHashUtil
|
|
61
61
|
import {
|
62
62
|
getCollectionValueSpecificationType,
|
63
63
|
getNonCollectionValueSpecificationType,
|
64
|
+
isTypeCompatibleForAssignment,
|
64
65
|
isValidInstanceValue,
|
65
66
|
isValueExpressionReferencedInValue,
|
66
67
|
} from '../QueryBuilderValueSpecificationHelper.js';
|
@@ -299,7 +300,7 @@ export class FilterConditionState implements Hashable {
|
|
299
300
|
);
|
300
301
|
const value = searchValue ?? rightConditionValue.value;
|
301
302
|
if (performTypeahead(value)) {
|
302
|
-
const result =
|
303
|
+
const result = (
|
303
304
|
(yield this.filterState.queryBuilderState.graphManagerState.graphManager.runQuery(
|
304
305
|
buildPropertyTypeaheadQuery(
|
305
306
|
this.filterState.queryBuilderState,
|
@@ -314,7 +315,8 @@ export class FilterConditionState implements Hashable {
|
|
314
315
|
.runtimeValue,
|
315
316
|
),
|
316
317
|
this.filterState.queryBuilderState.graphManagerState.graph,
|
317
|
-
)) as
|
318
|
+
)) as ExecutionResultWithMetadata
|
319
|
+
).executionResult;
|
318
320
|
this.typeaheadSearchResults = buildTypeaheadOptions(result);
|
319
321
|
}
|
320
322
|
this.typeaheadSearchState.pass();
|
@@ -1185,8 +1187,15 @@ export class QueryBuilderFilterState
|
|
1185
1187
|
node instanceof QueryBuilderFilterTreeConditionNodeData &&
|
1186
1188
|
node.condition.rightConditionValue instanceof
|
1187
1189
|
FilterValueSpecConditionValueState &&
|
1188
|
-
node.condition.rightConditionValue.value instanceof InstanceValue &&
|
1189
|
-
|
1190
|
+
((node.condition.rightConditionValue.value instanceof InstanceValue &&
|
1191
|
+
!isValidInstanceValue(node.condition.rightConditionValue.value)) ||
|
1192
|
+
(node.condition.rightConditionValue.value instanceof
|
1193
|
+
VariableExpression &&
|
1194
|
+
!isTypeCompatibleForAssignment(
|
1195
|
+
node.condition.propertyExpressionState.propertyExpression.func.value
|
1196
|
+
.genericType.value.rawType,
|
1197
|
+
node.condition.rightConditionValue.value.genericType?.value.rawType,
|
1198
|
+
)))
|
1190
1199
|
);
|
1191
1200
|
}
|
1192
1201
|
|