@finos/legend-query-builder 4.14.72 → 4.14.73
Sign up to get free protection for your applications and to get access to all the features.
- 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/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/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/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.map +1 -1
- package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js +1 -1
- 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 +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
- package/package.json +3 -3
- package/src/components/explorer/QueryBuilderPropertySearchPanel.tsx +249 -226
- package/src/components/result/QueryBuilderResultPanel.tsx +3 -1
- package/src/stores/QueryBuilderConfig.ts +2 -1
- package/src/stores/QueryBuilderResultState.ts +4 -0
- 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 +4 -3
- package/src/stores/filter/QueryBuilderFilterState.ts +5 -4
@@ -31,6 +31,7 @@ import {
|
|
31
31
|
type MappingModelCoverageAnalysisResult,
|
32
32
|
type EnumMappedProperty,
|
33
33
|
type MappedEntity,
|
34
|
+
type ExecutionResultWithMetadata,
|
34
35
|
AbstractPropertyExpression,
|
35
36
|
Class,
|
36
37
|
VariableExpression,
|
@@ -55,7 +56,6 @@ import {
|
|
55
56
|
Association,
|
56
57
|
PRIMITIVE_TYPE,
|
57
58
|
TDSExecutionResult,
|
58
|
-
type ExecutionResult,
|
59
59
|
getAllSubclasses,
|
60
60
|
PropertyExplicitReference,
|
61
61
|
reportGraphAnalytics,
|
@@ -115,6 +115,7 @@ export abstract class QueryBuilderExplorerTreeNodeData implements TreeNodeData {
|
|
115
115
|
isPartOfDerivedPropertyBranch: boolean,
|
116
116
|
type: Type,
|
117
117
|
mappingData: QueryBuilderExplorerTreeNodeMappingData,
|
118
|
+
childrenIds?: string[] | undefined,
|
118
119
|
) {
|
119
120
|
makeObservable(this, {
|
120
121
|
isHighlighting: observable,
|
@@ -131,6 +132,9 @@ export abstract class QueryBuilderExplorerTreeNodeData implements TreeNodeData {
|
|
131
132
|
this.isPartOfDerivedPropertyBranch = isPartOfDerivedPropertyBranch;
|
132
133
|
this.type = type;
|
133
134
|
this.mappingData = mappingData;
|
135
|
+
if (childrenIds) {
|
136
|
+
this.childrenIds = childrenIds;
|
137
|
+
}
|
134
138
|
this.elementRef = createRef();
|
135
139
|
}
|
136
140
|
|
@@ -169,6 +173,7 @@ export class QueryBuilderExplorerTreePropertyNodeData extends QueryBuilderExplor
|
|
169
173
|
isPartOfDerivedPropertyBranch: boolean,
|
170
174
|
mappingData: QueryBuilderExplorerTreeNodeMappingData,
|
171
175
|
type?: Type | undefined,
|
176
|
+
childrenIds?: string[],
|
172
177
|
) {
|
173
178
|
super(
|
174
179
|
id,
|
@@ -177,6 +182,7 @@ export class QueryBuilderExplorerTreePropertyNodeData extends QueryBuilderExplor
|
|
177
182
|
isPartOfDerivedPropertyBranch,
|
178
183
|
type ?? property.genericType.value.rawType,
|
179
184
|
mappingData,
|
185
|
+
childrenIds,
|
180
186
|
);
|
181
187
|
this.property = property;
|
182
188
|
this.parentId = parentId;
|
@@ -197,6 +203,7 @@ export class QueryBuilderExplorerTreeSubTypeNodeData extends QueryBuilderExplore
|
|
197
203
|
isPartOfDerivedPropertyBranch: boolean,
|
198
204
|
mappingData: QueryBuilderExplorerTreeNodeMappingData,
|
199
205
|
multiplicity: Multiplicity,
|
206
|
+
childrenIds?: string[],
|
200
207
|
) {
|
201
208
|
super(
|
202
209
|
id,
|
@@ -205,6 +212,7 @@ export class QueryBuilderExplorerTreeSubTypeNodeData extends QueryBuilderExplore
|
|
205
212
|
isPartOfDerivedPropertyBranch,
|
206
213
|
subclass,
|
207
214
|
mappingData,
|
215
|
+
childrenIds,
|
208
216
|
);
|
209
217
|
this.subclass = subclass;
|
210
218
|
this.parentId = parentId;
|
@@ -652,6 +660,49 @@ const getQueryBuilderTreeData = (
|
|
652
660
|
return { rootIds, nodes };
|
653
661
|
};
|
654
662
|
|
663
|
+
export const cloneQueryBuilderExplorerTreeNodeData = (
|
664
|
+
node: QueryBuilderExplorerTreeNodeData,
|
665
|
+
): QueryBuilderExplorerTreeNodeData => {
|
666
|
+
if (node instanceof QueryBuilderExplorerTreeRootNodeData) {
|
667
|
+
return new QueryBuilderExplorerTreeRootNodeData(
|
668
|
+
node.id,
|
669
|
+
node.label,
|
670
|
+
node.dndText,
|
671
|
+
node.isPartOfDerivedPropertyBranch,
|
672
|
+
node.type,
|
673
|
+
node.mappingData,
|
674
|
+
node.childrenIds,
|
675
|
+
);
|
676
|
+
} else if (node instanceof QueryBuilderExplorerTreePropertyNodeData) {
|
677
|
+
return new QueryBuilderExplorerTreePropertyNodeData(
|
678
|
+
node.id,
|
679
|
+
node.label,
|
680
|
+
node.dndText,
|
681
|
+
node.property,
|
682
|
+
node.parentId,
|
683
|
+
node.isPartOfDerivedPropertyBranch,
|
684
|
+
node.mappingData,
|
685
|
+
node.type,
|
686
|
+
node.childrenIds,
|
687
|
+
);
|
688
|
+
} else if (node instanceof QueryBuilderExplorerTreeSubTypeNodeData) {
|
689
|
+
return new QueryBuilderExplorerTreeSubTypeNodeData(
|
690
|
+
node.id,
|
691
|
+
node.label,
|
692
|
+
node.dndText,
|
693
|
+
node.subclass,
|
694
|
+
node.parentId,
|
695
|
+
node.isPartOfDerivedPropertyBranch,
|
696
|
+
node.mappingData,
|
697
|
+
node.multiplicity,
|
698
|
+
node.childrenIds,
|
699
|
+
);
|
700
|
+
}
|
701
|
+
throw new UnsupportedOperationError(
|
702
|
+
`Unable to clone node of type ${node.constructor.name}`,
|
703
|
+
);
|
704
|
+
};
|
705
|
+
|
655
706
|
export class QueryBuilderExplorerPreviewDataState {
|
656
707
|
isGeneratingPreviewData = false;
|
657
708
|
propertyName = '(unknown)';
|
@@ -957,7 +1008,7 @@ export class QueryBuilderExplorerState {
|
|
957
1008
|
case PRIMITIVE_TYPE.INTEGER:
|
958
1009
|
case PRIMITIVE_TYPE.DECIMAL:
|
959
1010
|
case PRIMITIVE_TYPE.FLOAT: {
|
960
|
-
const previewResult =
|
1011
|
+
const previewResult = (
|
961
1012
|
(yield this.queryBuilderState.graphManagerState.graphManager.runQuery(
|
962
1013
|
buildNumericPreviewDataQuery(
|
963
1014
|
this.queryBuilderState,
|
@@ -970,7 +1021,8 @@ export class QueryBuilderExplorerState {
|
|
970
1021
|
abortController:
|
971
1022
|
this.previewDataState.previewDataAbortController,
|
972
1023
|
},
|
973
|
-
)) as
|
1024
|
+
)) as ExecutionResultWithMetadata
|
1025
|
+
).executionResult;
|
974
1026
|
assertType(
|
975
1027
|
previewResult,
|
976
1028
|
TDSExecutionResult,
|
@@ -998,7 +1050,7 @@ export class QueryBuilderExplorerState {
|
|
998
1050
|
case PRIMITIVE_TYPE.DATE:
|
999
1051
|
case PRIMITIVE_TYPE.STRICTDATE:
|
1000
1052
|
case PRIMITIVE_TYPE.DATETIME: {
|
1001
|
-
const previewResult =
|
1053
|
+
const previewResult = (
|
1002
1054
|
(yield this.queryBuilderState.graphManagerState.graphManager.runQuery(
|
1003
1055
|
buildNonNumericPreviewDataQuery(
|
1004
1056
|
this.queryBuilderState,
|
@@ -1011,7 +1063,8 @@ export class QueryBuilderExplorerState {
|
|
1011
1063
|
abortController:
|
1012
1064
|
this.previewDataState.previewDataAbortController,
|
1013
1065
|
},
|
1014
|
-
)) as
|
1066
|
+
)) as ExecutionResultWithMetadata
|
1067
|
+
).executionResult;
|
1015
1068
|
assertType(
|
1016
1069
|
previewResult,
|
1017
1070
|
TDSExecutionResult,
|
@@ -18,7 +18,7 @@ import { FuzzySearchAdvancedConfigState } from '@finos/legend-shared';
|
|
18
18
|
import { action, makeObservable, observable } from 'mobx';
|
19
19
|
|
20
20
|
export class QueryBuilderFuzzySearchAdvancedConfigState extends FuzzySearchAdvancedConfigState {
|
21
|
-
includeSubTypes =
|
21
|
+
includeSubTypes = true;
|
22
22
|
includeDocumentation = false;
|
23
23
|
|
24
24
|
constructor(
|
@@ -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,8 +19,8 @@ import {
|
|
19
19
|
type PureModel,
|
20
20
|
type Type,
|
21
21
|
type ValueSpecification,
|
22
|
-
type ExecutionResult,
|
23
22
|
type SimpleFunctionExpression,
|
23
|
+
type ExecutionResultWithMetadata,
|
24
24
|
observe_ValueSpecification,
|
25
25
|
PrimitiveType,
|
26
26
|
CollectionInstanceValue,
|
@@ -490,7 +490,7 @@ export class PostFilterConditionState implements Hashable {
|
|
490
490
|
);
|
491
491
|
const value = searchValue ?? rightConditionValue.value;
|
492
492
|
if (performTypeahead(value)) {
|
493
|
-
const result =
|
493
|
+
const result = (
|
494
494
|
(yield this.postFilterState.tdsState.queryBuilderState.graphManagerState.graphManager.runQuery(
|
495
495
|
buildProjectionColumnTypeaheadQuery(
|
496
496
|
this.postFilterState.tdsState.queryBuilderState,
|
@@ -507,7 +507,8 @@ export class PostFilterConditionState implements Hashable {
|
|
507
507
|
),
|
508
508
|
this.postFilterState.tdsState.queryBuilderState.graphManagerState
|
509
509
|
.graph,
|
510
|
-
)) as
|
510
|
+
)) as ExecutionResultWithMetadata
|
511
|
+
).executionResult;
|
511
512
|
this.typeaheadSearchResults = buildTypeaheadOptions(result);
|
512
513
|
}
|
513
514
|
this.typeaheadSearchState.pass();
|
@@ -37,10 +37,10 @@ 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
41
|
type Type,
|
42
|
+
type ExecutionResultWithMetadata,
|
43
|
+
AbstractPropertyExpression,
|
44
44
|
observe_ValueSpecification,
|
45
45
|
CollectionInstanceValue,
|
46
46
|
InstanceValue,
|
@@ -300,7 +300,7 @@ export class FilterConditionState implements Hashable {
|
|
300
300
|
);
|
301
301
|
const value = searchValue ?? rightConditionValue.value;
|
302
302
|
if (performTypeahead(value)) {
|
303
|
-
const result =
|
303
|
+
const result = (
|
304
304
|
(yield this.filterState.queryBuilderState.graphManagerState.graphManager.runQuery(
|
305
305
|
buildPropertyTypeaheadQuery(
|
306
306
|
this.filterState.queryBuilderState,
|
@@ -315,7 +315,8 @@ export class FilterConditionState implements Hashable {
|
|
315
315
|
.runtimeValue,
|
316
316
|
),
|
317
317
|
this.filterState.queryBuilderState.graphManagerState.graph,
|
318
|
-
)) as
|
318
|
+
)) as ExecutionResultWithMetadata
|
319
|
+
).executionResult;
|
319
320
|
this.typeaheadSearchResults = buildTypeaheadOptions(result);
|
320
321
|
}
|
321
322
|
this.typeaheadSearchState.pass();
|