@finos/legend-query-builder 4.14.68 → 4.14.70

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. package/lib/__lib__/QueryBuilderTesting.d.ts +1 -0
  2. package/lib/__lib__/QueryBuilderTesting.d.ts.map +1 -1
  3. package/lib/__lib__/QueryBuilderTesting.js +1 -0
  4. package/lib/__lib__/QueryBuilderTesting.js.map +1 -1
  5. package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts +1 -0
  6. package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts.map +1 -1
  7. package/lib/components/explorer/QueryBuilderExplorerPanel.js +95 -53
  8. package/lib/components/explorer/QueryBuilderExplorerPanel.js.map +1 -1
  9. package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts +4 -0
  10. package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts.map +1 -1
  11. package/lib/components/explorer/QueryBuilderPropertySearchPanel.js +172 -108
  12. package/lib/components/explorer/QueryBuilderPropertySearchPanel.js.map +1 -1
  13. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  14. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +2 -1
  15. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  16. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  17. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +29 -18
  18. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  19. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.d.ts.map +1 -1
  20. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js +13 -4
  21. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js.map +1 -1
  22. package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
  23. package/lib/components/filter/QueryBuilderFilterPanel.js +4 -3
  24. package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
  25. package/lib/components/result/QueryBuilderResultPanel.d.ts +12 -0
  26. package/lib/components/result/QueryBuilderResultPanel.d.ts.map +1 -1
  27. package/lib/components/result/QueryBuilderResultPanel.js +60 -8
  28. package/lib/components/result/QueryBuilderResultPanel.js.map +1 -1
  29. package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts.map +1 -1
  30. package/lib/components/result/tds/QueryBuilderTDSGridResult.js +47 -28
  31. package/lib/components/result/tds/QueryBuilderTDSGridResult.js.map +1 -1
  32. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.d.ts +1 -0
  33. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.d.ts.map +1 -1
  34. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.js +34 -1
  35. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.js.map +1 -1
  36. package/lib/components/shared/QueryBuilderFilterHelper.d.ts.map +1 -1
  37. package/lib/components/shared/QueryBuilderFilterHelper.js +3 -0
  38. package/lib/components/shared/QueryBuilderFilterHelper.js.map +1 -1
  39. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts +11 -0
  40. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts.map +1 -1
  41. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js +6 -3
  42. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js.map +1 -1
  43. package/lib/graph-manager/QueryBuilderConfig.d.ts +4 -0
  44. package/lib/graph-manager/QueryBuilderConfig.d.ts.map +1 -1
  45. package/lib/graph-manager/QueryBuilderConfig.js +5 -0
  46. package/lib/graph-manager/QueryBuilderConfig.js.map +1 -1
  47. package/lib/index.css +2 -2
  48. package/lib/index.css.map +1 -1
  49. package/lib/package.json +1 -1
  50. package/lib/stores/QueryBuilderResultState.d.ts +11 -3
  51. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  52. package/lib/stores/QueryBuilderResultState.js +47 -4
  53. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  54. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.d.ts +4 -0
  55. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.d.ts.map +1 -1
  56. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts +5 -1
  57. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts.map +1 -1
  58. package/lib/stores/explorer/QueryBuilderExplorerState.js +80 -10
  59. package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
  60. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.d.ts +24 -0
  61. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.d.ts.map +1 -0
  62. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js +39 -0
  63. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js.map +1 -0
  64. package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts +8 -4
  65. package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts.map +1 -1
  66. package/lib/stores/explorer/QueryBuilderPropertySearchState.js +204 -114
  67. package/lib/stores/explorer/QueryBuilderPropertySearchState.js.map +1 -1
  68. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts.map +1 -1
  69. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js +8 -1
  70. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
  71. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.d.ts.map +1 -1
  72. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js +12 -1
  73. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js.map +1 -1
  74. package/lib/stores/filter/QueryBuilderFilterState.d.ts +8 -1
  75. package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
  76. package/lib/stores/filter/QueryBuilderFilterState.js +27 -10
  77. package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
  78. package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts +1 -0
  79. package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts.map +1 -1
  80. package/lib/stores/shared/ValueSpecificationEditorHelper.js +6 -2
  81. package/lib/stores/shared/ValueSpecificationEditorHelper.js.map +1 -1
  82. package/package.json +9 -9
  83. package/src/__lib__/QueryBuilderTesting.ts +1 -0
  84. package/src/components/explorer/QueryBuilderExplorerPanel.tsx +228 -115
  85. package/src/components/explorer/QueryBuilderPropertySearchPanel.tsx +618 -388
  86. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +5 -2
  87. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +78 -44
  88. package/src/components/fetch-structure/QueryBuilderTDSWindowPanel.tsx +63 -10
  89. package/src/components/filter/QueryBuilderFilterPanel.tsx +4 -2
  90. package/src/components/result/QueryBuilderResultPanel.tsx +207 -20
  91. package/src/components/result/tds/QueryBuilderTDSGridResult.tsx +57 -38
  92. package/src/components/result/tds/QueryBuilderTDSSimpleGridResult.tsx +43 -0
  93. package/src/components/shared/QueryBuilderFilterHelper.ts +8 -0
  94. package/src/components/shared/QueryBuilderPropertyInfoTooltip.tsx +13 -3
  95. package/src/graph-manager/QueryBuilderConfig.ts +6 -0
  96. package/src/stores/QueryBuilderResultState.ts +64 -10
  97. package/src/stores/QueryBuilderValueSpecificationBuilderHelper.ts +5 -0
  98. package/src/stores/explorer/QueryBuilderExplorerState.ts +112 -8
  99. package/src/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.ts +46 -0
  100. package/src/stores/explorer/QueryBuilderPropertySearchState.ts +280 -142
  101. package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +8 -1
  102. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.ts +15 -2
  103. package/src/stores/filter/QueryBuilderFilterState.ts +34 -11
  104. package/src/stores/shared/ValueSpecificationEditorHelper.ts +9 -1
  105. package/tsconfig.json +1 -0
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { FuzzySearchAdvancedConfigState } from '@finos/legend-shared';
18
+ import { action, makeObservable, observable } from 'mobx';
19
+
20
+ export class QueryBuilderFuzzySearchAdvancedConfigState extends FuzzySearchAdvancedConfigState {
21
+ includeSubTypes = false;
22
+ includeDocumentation = false;
23
+
24
+ constructor(
25
+ onSearchModeChange: () => Promise<void>,
26
+ onSearchModeChangeError: (error: Error) => void,
27
+ ) {
28
+ super(() => {
29
+ onSearchModeChange().catch(onSearchModeChangeError);
30
+ });
31
+ makeObservable(this, {
32
+ includeSubTypes: observable,
33
+ includeDocumentation: observable,
34
+ setIncludeSubTypes: action,
35
+ setIncludeDocumentation: action,
36
+ });
37
+ }
38
+
39
+ setIncludeSubTypes(val: boolean): void {
40
+ this.includeSubTypes = val;
41
+ }
42
+
43
+ setIncludeDocumentation(val: boolean): void {
44
+ this.includeDocumentation = val;
45
+ }
46
+ }
@@ -30,7 +30,8 @@ import {
30
30
  addUniqueEntry,
31
31
  deleteEntry,
32
32
  guaranteeNonNullable,
33
- FuzzySearchAdvancedConfigState,
33
+ isNonNullable,
34
+ type FuzzySearchEngineSortFunctionArg,
34
35
  } from '@finos/legend-shared';
35
36
  import {
36
37
  observable,
@@ -53,6 +54,11 @@ import {
53
54
  QueryBuilderExplorerTreeSubTypeNodeData,
54
55
  } from './QueryBuilderExplorerState.js';
55
56
  import type { QueryBuilderState } from '../QueryBuilderState.js';
57
+ import { QueryBuilderFuzzySearchAdvancedConfigState } from './QueryBuilderFuzzySearchAdvancedConfigState.js';
58
+ import {
59
+ prettyPropertyNameForSubType,
60
+ prettyPropertyNameFromNodeId,
61
+ } from '../../components/explorer/QueryBuilderPropertySearchPanel.js';
56
62
 
57
63
  export class QueryBuilderPropertySearchState {
58
64
  queryBuilderState: QueryBuilderState;
@@ -72,7 +78,8 @@ export class QueryBuilderPropertySearchState {
72
78
 
73
79
  // search
74
80
  searchEngine: FuzzySearchEngine<QueryBuilderExplorerTreeNodeData>;
75
- searchConfigurationState: FuzzySearchAdvancedConfigState;
81
+ searchConfigurationState: QueryBuilderFuzzySearchAdvancedConfigState;
82
+ initializationState = ActionState.create();
76
83
  searchState = ActionState.create();
77
84
  searchText = '';
78
85
  searchResults: QueryBuilderExplorerTreeNodeData[] = [];
@@ -103,6 +110,8 @@ export class QueryBuilderPropertySearchState {
103
110
  filteredSearchResults: computed,
104
111
  search: action,
105
112
  resetSearch: action,
113
+ setSearchResults: action,
114
+ setIsOverSearchLimit: action,
106
115
  setSearchText: action,
107
116
  setShowSearchConfigurationMenu: action,
108
117
  setIsSearchPanelOpen: action,
@@ -112,9 +121,11 @@ export class QueryBuilderPropertySearchState {
112
121
  });
113
122
 
114
123
  this.queryBuilderState = queryBuilderState;
115
- this.searchConfigurationState = new FuzzySearchAdvancedConfigState(
116
- (): void => this.search(),
117
- );
124
+ this.searchConfigurationState =
125
+ new QueryBuilderFuzzySearchAdvancedConfigState(
126
+ async (): Promise<void> => this.search(),
127
+ this.queryBuilderState.applicationStore.alertUnhandledError,
128
+ );
118
129
  this.searchEngine = new FuzzySearchEngine(this.indexedExplorerTreeNodes);
119
130
  }
120
131
 
@@ -130,6 +141,14 @@ export class QueryBuilderPropertySearchState {
130
141
  this.showSearchConfigurationMenu = val;
131
142
  }
132
143
 
144
+ setSearchResults(val: QueryBuilderExplorerTreeNodeData[]): void {
145
+ this.searchResults = val;
146
+ }
147
+
148
+ setIsOverSearchLimit(val: boolean): void {
149
+ this.isOverSearchLimit = val;
150
+ }
151
+
133
152
  setSearchText(val: string): void {
134
153
  this.searchText = val;
135
154
  }
@@ -148,46 +167,82 @@ export class QueryBuilderPropertySearchState {
148
167
  }
149
168
  }
150
169
 
151
- search(): void {
170
+ async search(): Promise<void> {
152
171
  if (!this.searchText) {
153
- this.searchResults = [];
154
- return;
172
+ this.setSearchResults([]);
173
+ return Promise.resolve();
155
174
  }
175
+
156
176
  this.searchState.inProgress();
157
177
 
158
- // NOTE: performanced of fuzzy search is impacted by the number of indexed entries and the length
159
- // of the search pattern, so to a certain extent this could become laggy. If this becomes too inconvenient
160
- // for the users, we might need to use another fuzzy-search implementation, or have appropriate search
161
- // policy, e.g. limit length of search text, etc.
162
- //
163
- // See https://github.com/farzher/fuzzysort
164
- const searchResults = Array.from(
165
- this.searchEngine
166
- .search(
167
- this.searchConfigurationState.generateSearchText(
168
- this.searchText.toLowerCase(),
169
- ),
170
- {
171
- // NOTE: search for limit + 1 item so we can know if there are more search results
172
- limit: QUERY_BUILDER_PROPERTY_SEARCH_RESULTS_LIMIT + 1,
173
- },
178
+ // Perform the search in a setTimeout so we can execute it asynchronously and
179
+ // show the loading indicator while search is in progress.
180
+ return new Promise((resolve) =>
181
+ setTimeout(() => {
182
+ // NOTE: performanced of fuzzy search is impacted by the number of indexed entries and the length
183
+ // of the search pattern, so to a certain extent this could become laggy. If this becomes too inconvenient
184
+ // for the users, we might need to use another fuzzy-search implementation, or have appropriate search
185
+ // policy, e.g. limit length of search text, etc.
186
+ //
187
+ // See https://github.com/farzher/fuzzysort
188
+
189
+ const classNodes: Map<string, QueryBuilderExplorerTreeNodeData> =
190
+ new Map();
191
+
192
+ const searchResults = Array.from(
193
+ this.searchEngine
194
+ .search(
195
+ this.searchConfigurationState.generateSearchText(
196
+ this.searchText.toLowerCase(),
197
+ ),
198
+ {
199
+ // NOTE: search for limit + 1 item so we can know if there are more search results
200
+ limit: QUERY_BUILDER_PROPERTY_SEARCH_RESULTS_LIMIT + 1,
201
+ },
202
+ )
203
+ .values(),
174
204
  )
175
- .values(),
176
- ).map((result) => result.item);
177
-
178
- // check if the search results exceed the limit
179
- if (searchResults.length > QUERY_BUILDER_PROPERTY_SEARCH_RESULTS_LIMIT) {
180
- this.isOverSearchLimit = true;
181
- this.searchResults = searchResults.slice(
182
- 0,
183
- QUERY_BUILDER_PROPERTY_SEARCH_RESULTS_LIMIT,
184
- );
185
- } else {
186
- this.isOverSearchLimit = false;
187
- this.searchResults = searchResults;
188
- }
205
+ .map((result) => result.item)
206
+ .map((node) => {
207
+ if (node.type instanceof Class) {
208
+ classNodes.set(node.id, node);
209
+ }
210
+ return node;
211
+ })
212
+ .filter((node) => {
213
+ // Filter out property nodes if their parent class node is already in the results.
214
+ if (node.type instanceof Class) {
215
+ return true;
216
+ } else if (
217
+ node instanceof QueryBuilderExplorerTreePropertyNodeData
218
+ ) {
219
+ if (this.searchText.toLowerCase() === node.label.toLowerCase()) {
220
+ return true;
221
+ } else if (classNodes.has(node.parentId)) {
222
+ classNodes.get(node.parentId)?.setIsOpen(true);
223
+ return false;
224
+ }
225
+ }
226
+ return true;
227
+ });
189
228
 
190
- this.searchState.complete();
229
+ // check if the search results exceed the limit
230
+ if (
231
+ searchResults.length > QUERY_BUILDER_PROPERTY_SEARCH_RESULTS_LIMIT
232
+ ) {
233
+ this.setIsOverSearchLimit(true);
234
+ this.setSearchResults(
235
+ searchResults.slice(0, QUERY_BUILDER_PROPERTY_SEARCH_RESULTS_LIMIT),
236
+ );
237
+ } else {
238
+ this.setIsOverSearchLimit(false);
239
+ this.setSearchResults(searchResults);
240
+ }
241
+
242
+ this.searchState.complete();
243
+ resolve();
244
+ }, 0),
245
+ );
191
246
  }
192
247
 
193
248
  /**
@@ -198,49 +253,72 @@ export class QueryBuilderPropertySearchState {
198
253
  * this process is often not the performance bottleneck, else, we would need to make this
199
254
  * asynchronous and block the UI while waiting.
200
255
  */
201
- initialize(): void {
202
- this.indexedExplorerTreeNodes = [];
203
-
204
- let currentLevelPropertyNodes: QueryBuilderExplorerTreeNodeData[] = [];
205
- let nextLevelPropertyNodes: QueryBuilderExplorerTreeNodeData[] = [];
206
-
207
- Array.from(
208
- this.queryBuilderState.explorerState.nonNullableTreeData.nodes.values(),
209
- )
210
- .slice(1)
211
- .forEach((node) => {
212
- if (node.mappingData.mapped && !node.isPartOfDerivedPropertyBranch) {
213
- currentLevelPropertyNodes.push(node);
214
- this.indexedExplorerTreeNodes.push(node);
215
- }
216
- });
217
-
218
- // ensure we don't navigate more nodes than the limit so we could
219
- // keep the initialization/indexing time within acceptable range
220
- const NODE_LIMIT =
221
- this.indexedExplorerTreeNodes.length +
222
- QUERY_BUILDER_PROPERTY_SEARCH_MAX_NODES;
223
- const addNode = (node: QueryBuilderExplorerTreeNodeData): void =>
224
- runInAction(() => {
225
- if (this.indexedExplorerTreeNodes.length > NODE_LIMIT) {
226
- return;
227
- }
228
- this.indexedExplorerTreeNodes.push(node);
229
- });
230
-
231
- // limit the depth of navigation to keep the initialization/indexing
232
- // time within acceptable range
233
- let currentDepth = 1;
234
- while (
235
- currentLevelPropertyNodes.length &&
236
- currentDepth <= QUERY_BUILDER_PROPERTY_SEARCH_MAX_DEPTH
237
- ) {
238
- const node = currentLevelPropertyNodes.shift();
239
- if (node) {
240
- if (node.childrenIds.length) {
256
+ async initialize(): Promise<void> {
257
+ this.initializationState.inProgress();
258
+
259
+ // Perform the initialization in a setTimeout so we can execute it asynchronously and
260
+ // show the loading indicator while initialization is in progress.
261
+ return new Promise((resolve) =>
262
+ setTimeout(() => {
263
+ this.indexedExplorerTreeNodes = [];
264
+
265
+ let currentLevelPropertyNodes: QueryBuilderExplorerTreeNodeData[] = [];
266
+ let nextLevelPropertyNodes: QueryBuilderExplorerTreeNodeData[] = [];
267
+
268
+ // Get all the children of the root node(s)
269
+ Array.from(
270
+ this.queryBuilderState.explorerState.nonNullableTreeData.rootIds
271
+ .map((rootId) =>
272
+ this.queryBuilderState.explorerState.nonNullableTreeData.nodes
273
+ .get(rootId)
274
+ ?.childrenIds.map((childId) =>
275
+ this.queryBuilderState.explorerState.nonNullableTreeData.nodes.get(
276
+ childId,
277
+ ),
278
+ ),
279
+ )
280
+ .flat()
281
+ .filter(isNonNullable)
282
+ .filter((node) =>
283
+ node.mappingData.mapped &&
284
+ this.searchConfigurationState.includeSubTypes
285
+ ? true
286
+ : node instanceof QueryBuilderExplorerTreePropertyNodeData,
287
+ ),
288
+ ).forEach((node) => {
289
+ if (node.mappingData.mapped && !node.isPartOfDerivedPropertyBranch) {
290
+ currentLevelPropertyNodes.push(node);
291
+ this.indexedExplorerTreeNodes.push(node);
292
+ }
293
+ });
294
+
295
+ // ensure we don't navigate more nodes than the limit so we could
296
+ // keep the initialization/indexing time within acceptable range
297
+ const NODE_LIMIT =
298
+ this.indexedExplorerTreeNodes.length +
299
+ QUERY_BUILDER_PROPERTY_SEARCH_MAX_NODES;
300
+ const addNode = (node: QueryBuilderExplorerTreeNodeData): void =>
301
+ runInAction(() => {
302
+ if (this.indexedExplorerTreeNodes.length > NODE_LIMIT) {
303
+ return;
304
+ }
305
+ this.indexedExplorerTreeNodes.push(node);
306
+ });
307
+
308
+ // limit the depth of navigation to keep the initialization/indexing
309
+ // time within acceptable range
310
+ let currentDepth = 1;
311
+ while (
312
+ currentLevelPropertyNodes.length &&
313
+ currentDepth <= QUERY_BUILDER_PROPERTY_SEARCH_MAX_DEPTH
314
+ ) {
315
+ const node = currentLevelPropertyNodes.shift();
241
316
  if (
317
+ node?.mappingData.mapped &&
318
+ node.childrenIds.length &&
242
319
  (node instanceof QueryBuilderExplorerTreePropertyNodeData ||
243
- node instanceof QueryBuilderExplorerTreeSubTypeNodeData) &&
320
+ (this.searchConfigurationState.includeSubTypes &&
321
+ node instanceof QueryBuilderExplorerTreeSubTypeNodeData)) &&
244
322
  node.type instanceof Class
245
323
  ) {
246
324
  (node instanceof QueryBuilderExplorerTreeSubTypeNodeData
@@ -265,72 +343,132 @@ export class QueryBuilderPropertySearchState {
265
343
  addNode(propertyTreeNodeData);
266
344
  }
267
345
  });
268
- node.type._subclasses.forEach((subclass) => {
269
- const subTypeTreeNodeData = getQueryBuilderSubTypeNodeData(
270
- subclass,
271
- node,
272
- guaranteeNonNullable(
273
- this.queryBuilderState.explorerState
274
- .mappingModelCoverageAnalysisResult,
275
- ),
276
- );
277
- nextLevelPropertyNodes.push(subTypeTreeNodeData);
278
- addNode(subTypeTreeNodeData);
279
- });
346
+ if (this.searchConfigurationState.includeSubTypes) {
347
+ node.type._subclasses.forEach((subclass) => {
348
+ const subTypeTreeNodeData = getQueryBuilderSubTypeNodeData(
349
+ subclass,
350
+ node,
351
+ guaranteeNonNullable(
352
+ this.queryBuilderState.explorerState
353
+ .mappingModelCoverageAnalysisResult,
354
+ ),
355
+ );
356
+ if (subTypeTreeNodeData.mappingData.mapped) {
357
+ nextLevelPropertyNodes.push(subTypeTreeNodeData);
358
+ addNode(subTypeTreeNodeData);
359
+ }
360
+ });
361
+ }
362
+ }
363
+
364
+ // when we done processing one depth, we will do check on the depth and the total
365
+ // number of indexed nodes to figure out if we should proceed further
366
+ if (
367
+ !currentLevelPropertyNodes.length &&
368
+ this.indexedExplorerTreeNodes.length < NODE_LIMIT
369
+ ) {
370
+ currentLevelPropertyNodes = nextLevelPropertyNodes;
371
+ nextLevelPropertyNodes = [];
372
+ currentDepth++;
280
373
  }
281
374
  }
282
- }
283
375
 
284
- // when we done processing one depth, we will do check on the depth and the total
285
- // number of indexed nodes to figureo ut if we should proceed further
286
- if (
287
- !currentLevelPropertyNodes.length &&
288
- this.indexedExplorerTreeNodes.length < NODE_LIMIT
289
- ) {
290
- currentLevelPropertyNodes = nextLevelPropertyNodes;
291
- nextLevelPropertyNodes = [];
292
- currentDepth++;
293
- }
294
- }
376
+ // indexing
377
+ this.searchEngine = new FuzzySearchEngine(
378
+ this.indexedExplorerTreeNodes,
379
+ {
380
+ includeScore: true,
381
+ shouldSort: true,
382
+ // Ignore location when computing the search score
383
+ // See https://fusejs.io/concepts/scoring-theory.html
384
+ ignoreLocation: true,
385
+ // This specifies the point the search gives up
386
+ // `0.0` means exact match where `1.0` would match anything
387
+ // We set a relatively low threshold to filter out irrelevant results
388
+ threshold: 0.2,
389
+ keys: [
390
+ {
391
+ name: 'path',
392
+ weight: 4,
393
+ getFn: (node) => {
394
+ const parentNode = this.indexedExplorerTreeNodes.find(
395
+ (pn) =>
396
+ node instanceof
397
+ QueryBuilderExplorerTreePropertyNodeData &&
398
+ node.parentId === pn.id,
399
+ );
295
400
 
296
- // indexing
297
- this.searchEngine = new FuzzySearchEngine(this.indexedExplorerTreeNodes, {
298
- includeScore: true,
299
- shouldSort: true,
300
- // Ignore location when computing the search score
301
- // See https://fusejs.io/concepts/scoring-theory.html
302
- ignoreLocation: true,
303
- // This specifies the point the search gives up
304
- // `0.0` means exact match where `1.0` would match anything
305
- // We set a relatively low threshold to filter out irrelevant results
306
- threshold: 0.2,
307
- keys: [
308
- {
309
- name: 'label',
310
- weight: 4,
311
- },
312
- {
313
- name: 'taggedValues',
314
- weight: 2,
315
- // aggregate the property documentation, do not account for class documentation
316
- getFn: (node: QueryBuilderExplorerTreeNodeData) =>
317
- node instanceof QueryBuilderExplorerTreePropertyNodeData
318
- ? node.property.taggedValues
319
- .filter(
320
- (taggedValue) =>
321
- taggedValue.tag.ownerReference.value.path ===
322
- CORE_PURE_PATH.PROFILE_DOC &&
323
- taggedValue.tag.value.value === PURE_DOC_TAG,
324
- )
325
- .map((taggedValue) => taggedValue.value)
326
- .join('\n')
327
- : '',
328
- },
329
- ],
330
- // extended search allows for exact word match through single quote
331
- // See https://fusejs.io/examples.html#extended-search
332
- useExtendedSearch: true,
333
- });
401
+ const fullPath =
402
+ parentNode instanceof
403
+ QueryBuilderExplorerTreeSubTypeNodeData
404
+ ? prettyPropertyNameForSubType(node.id)
405
+ : prettyPropertyNameFromNodeId(node.id);
406
+
407
+ return fullPath;
408
+ },
409
+ },
410
+ ...(this.searchConfigurationState.includeDocumentation
411
+ ? [
412
+ {
413
+ name: 'taggedValues',
414
+ weight: 2,
415
+ // aggregate the property documentation, do not account for class documentation
416
+ getFn: (node: QueryBuilderExplorerTreeNodeData) =>
417
+ node instanceof QueryBuilderExplorerTreePropertyNodeData
418
+ ? node.property.taggedValues
419
+ .filter(
420
+ (taggedValue) =>
421
+ taggedValue.tag.ownerReference.value.path ===
422
+ CORE_PURE_PATH.PROFILE_DOC &&
423
+ taggedValue.tag.value.value === PURE_DOC_TAG,
424
+ )
425
+ .map((taggedValue) => taggedValue.value)
426
+ .join('\n')
427
+ : '',
428
+ },
429
+ ]
430
+ : []),
431
+ ],
432
+ sortFn: (
433
+ a: FuzzySearchEngineSortFunctionArg,
434
+ b: FuzzySearchEngineSortFunctionArg,
435
+ ) => {
436
+ // If 2 items have similar scores, we should prefer the one that is
437
+ // less deeply nested.
438
+ const similarScores = Math.abs(a.score - b.score) <= 0.1;
439
+ if (similarScores) {
440
+ const aPathLength: number | undefined =
441
+ a.item[0] && Object.hasOwn(a.item[0], 'v')
442
+ ? (
443
+ a.item[0] as {
444
+ v: string;
445
+ }
446
+ ).v.split('/').length
447
+ : undefined;
448
+ const bPathLength: number | undefined =
449
+ b.item[0] && Object.hasOwn(b.item[0], 'v')
450
+ ? (
451
+ b.item[0] as {
452
+ v: string;
453
+ }
454
+ ).v.split('/').length
455
+ : undefined;
456
+ if (aPathLength !== undefined && bPathLength !== undefined) {
457
+ return aPathLength - bPathLength;
458
+ }
459
+ }
460
+ return a.score - b.score;
461
+ },
462
+ // extended search allows for exact word match through single quote
463
+ // See https://fusejs.io/examples.html#extended-search
464
+ useExtendedSearch: true,
465
+ },
466
+ );
467
+
468
+ this.initializationState.complete();
469
+ resolve();
470
+ }, 0),
471
+ );
334
472
  }
335
473
 
336
474
  get filteredSearchResults(): QueryBuilderExplorerTreeNodeData[] {
@@ -668,7 +668,14 @@ export class QueryBuilderPostFilterState
668
668
  return uniq(
669
669
  Array.from(this.nodes.values())
670
670
  .filter(filterByType(QueryBuilderPostFilterTreeConditionNodeData))
671
- .map((n) => n.condition.leftConditionValue),
671
+ .map((n) => [
672
+ n.condition.leftConditionValue,
673
+ ...(n.condition.rightConditionValue instanceof
674
+ PostFilterTDSColumnValueConditionValueState
675
+ ? [n.condition.rightConditionValue.tdsColumn]
676
+ : []),
677
+ ])
678
+ .flat(),
672
679
  );
673
680
  }
674
681
 
@@ -69,6 +69,7 @@ const appendResultSetModifier = (
69
69
  options?:
70
70
  | {
71
71
  overridingLimit?: number | undefined;
72
+ withDataOverflowCheck?: boolean | undefined;
72
73
  }
73
74
  | undefined,
74
75
  ): LambdaFunction => {
@@ -128,8 +129,16 @@ const appendResultSetModifier = (
128
129
  );
129
130
  limit.values = [
130
131
  Math.min(
131
- resultModifierState.limit ?? Number.MAX_SAFE_INTEGER,
132
- options?.overridingLimit ?? Number.MAX_SAFE_INTEGER,
132
+ resultModifierState.limit
133
+ ? options?.withDataOverflowCheck
134
+ ? resultModifierState.limit + 1
135
+ : resultModifierState.limit
136
+ : Number.MAX_SAFE_INTEGER,
137
+ options?.overridingLimit
138
+ ? options.withDataOverflowCheck
139
+ ? options.overridingLimit + 1
140
+ : options.overridingLimit
141
+ : Number.MAX_SAFE_INTEGER,
133
142
  ),
134
143
  ];
135
144
  const takeFunction = new SimpleFunctionExpression(
@@ -502,5 +511,9 @@ export const appendProjection = (
502
511
  options?.isBuildingExecutionQuery && !options.isExportingResult
503
512
  ? queryBuilderState.resultState.previewLimit
504
513
  : undefined,
514
+ withDataOverflowCheck:
515
+ options?.isBuildingExecutionQuery && !options.isExportingResult
516
+ ? options.withDataOverflowCheck
517
+ : undefined,
505
518
  });
506
519
  };
@@ -571,6 +571,40 @@ export class QueryBuilderFilterTreeExistsNodeData
571
571
  }
572
572
  }
573
573
 
574
+ export const isExistsNodeChild = (
575
+ node: QueryBuilderFilterTreeConditionNodeData,
576
+ ): boolean => {
577
+ let parentNode = node.condition.filterState.getParentNode(node);
578
+ while (parentNode !== undefined) {
579
+ if (parentNode instanceof QueryBuilderFilterTreeExistsNodeData) {
580
+ return true;
581
+ }
582
+ parentNode = node.condition.filterState.getParentNode(parentNode);
583
+ }
584
+ return false;
585
+ };
586
+
587
+ /**
588
+ *
589
+ * @param node the node from which to start searching
590
+ * @returns the furthest away parent node that is an exists node, or
591
+ * undefined if none exists.
592
+ */
593
+ export const getFurthestExistsNodeParent = (
594
+ node: QueryBuilderFilterTreeConditionNodeData,
595
+ ): QueryBuilderFilterTreeExistsNodeData | undefined => {
596
+ let furthestExistsNode: QueryBuilderFilterTreeExistsNodeData | undefined =
597
+ undefined;
598
+ let parentNode = node.condition.filterState.getParentNode(node);
599
+ while (parentNode) {
600
+ if (parentNode instanceof QueryBuilderFilterTreeExistsNodeData) {
601
+ furthestExistsNode = parentNode;
602
+ }
603
+ parentNode = node.condition.filterState.getParentNode(parentNode);
604
+ }
605
+ return furthestExistsNode;
606
+ };
607
+
574
608
  export class QueryBuilderFilterTreeConditionNodeData
575
609
  extends QueryBuilderFilterTreeNodeData
576
610
  implements Hashable
@@ -596,17 +630,6 @@ export class QueryBuilderFilterTreeConditionNodeData
596
630
  this.isNewlyAdded = val;
597
631
  }
598
632
 
599
- get isExistsNodeChild(): boolean {
600
- let parentNode = this.condition.filterState.getParentNode(this);
601
- while (parentNode !== undefined) {
602
- if (parentNode instanceof QueryBuilderFilterTreeExistsNodeData) {
603
- return true;
604
- }
605
- parentNode = this.condition.filterState.getParentNode(parentNode);
606
- }
607
- return false;
608
- }
609
-
610
633
  get dragPreviewLabel(): string {
611
634
  return this.condition.propertyExpressionState.title;
612
635
  }