@finos/legend-query-builder 4.14.69 → 4.14.71

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.
Files changed (100) 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/QueryBuilderConstantExpressionPanel.d.ts.map +1 -1
  6. package/lib/components/QueryBuilderConstantExpressionPanel.js +2 -1
  7. package/lib/components/QueryBuilderConstantExpressionPanel.js.map +1 -1
  8. package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts +1 -0
  9. package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts.map +1 -1
  10. package/lib/components/explorer/QueryBuilderExplorerPanel.js +87 -52
  11. package/lib/components/explorer/QueryBuilderExplorerPanel.js.map +1 -1
  12. package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts +4 -0
  13. package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts.map +1 -1
  14. package/lib/components/explorer/QueryBuilderPropertySearchPanel.js +172 -108
  15. package/lib/components/explorer/QueryBuilderPropertySearchPanel.js.map +1 -1
  16. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  17. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +2 -1
  18. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  19. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  20. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +29 -18
  21. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  22. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.d.ts.map +1 -1
  23. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js +13 -4
  24. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js.map +1 -1
  25. package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
  26. package/lib/components/filter/QueryBuilderFilterPanel.js +4 -3
  27. package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
  28. package/lib/components/result/QueryBuilderResultPanel.d.ts +12 -0
  29. package/lib/components/result/QueryBuilderResultPanel.d.ts.map +1 -1
  30. package/lib/components/result/QueryBuilderResultPanel.js +60 -8
  31. package/lib/components/result/QueryBuilderResultPanel.js.map +1 -1
  32. package/lib/components/shared/QueryBuilderFilterHelper.d.ts.map +1 -1
  33. package/lib/components/shared/QueryBuilderFilterHelper.js +3 -0
  34. package/lib/components/shared/QueryBuilderFilterHelper.js.map +1 -1
  35. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts +11 -0
  36. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts.map +1 -1
  37. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js +6 -3
  38. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js.map +1 -1
  39. package/lib/graph-manager/QueryBuilderConfig.d.ts +4 -0
  40. package/lib/graph-manager/QueryBuilderConfig.d.ts.map +1 -1
  41. package/lib/graph-manager/QueryBuilderConfig.js +5 -0
  42. package/lib/graph-manager/QueryBuilderConfig.js.map +1 -1
  43. package/lib/index.css +2 -2
  44. package/lib/index.css.map +1 -1
  45. package/lib/package.json +1 -1
  46. package/lib/stores/QueryBuilderConstantsState.d.ts +1 -0
  47. package/lib/stores/QueryBuilderConstantsState.d.ts.map +1 -1
  48. package/lib/stores/QueryBuilderConstantsState.js +6 -1
  49. package/lib/stores/QueryBuilderConstantsState.js.map +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 +3 -1
  57. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts.map +1 -1
  58. package/lib/stores/explorer/QueryBuilderExplorerState.js +63 -8
  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/package.json +8 -8
  79. package/src/__lib__/QueryBuilderTesting.ts +1 -0
  80. package/src/components/QueryBuilderConstantExpressionPanel.tsx +2 -1
  81. package/src/components/explorer/QueryBuilderExplorerPanel.tsx +220 -114
  82. package/src/components/explorer/QueryBuilderPropertySearchPanel.tsx +618 -388
  83. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +5 -2
  84. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +78 -44
  85. package/src/components/fetch-structure/QueryBuilderTDSWindowPanel.tsx +63 -10
  86. package/src/components/filter/QueryBuilderFilterPanel.tsx +4 -2
  87. package/src/components/result/QueryBuilderResultPanel.tsx +207 -20
  88. package/src/components/shared/QueryBuilderFilterHelper.ts +8 -0
  89. package/src/components/shared/QueryBuilderPropertyInfoTooltip.tsx +13 -3
  90. package/src/graph-manager/QueryBuilderConfig.ts +6 -0
  91. package/src/stores/QueryBuilderConstantsState.ts +16 -1
  92. package/src/stores/QueryBuilderResultState.ts +64 -10
  93. package/src/stores/QueryBuilderValueSpecificationBuilderHelper.ts +5 -0
  94. package/src/stores/explorer/QueryBuilderExplorerState.ts +92 -8
  95. package/src/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.ts +46 -0
  96. package/src/stores/explorer/QueryBuilderPropertySearchState.ts +280 -142
  97. package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +8 -1
  98. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.ts +15 -2
  99. package/src/stores/filter/QueryBuilderFilterState.ts +34 -11
  100. package/tsconfig.json +1 -0
@@ -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
  }
package/tsconfig.json CHANGED
@@ -101,6 +101,7 @@
101
101
  "./src/stores/entitlements/QueryBuilderCheckEntitlementsState.ts",
102
102
  "./src/stores/execution-plan/ExecutionPlanState.ts",
103
103
  "./src/stores/explorer/QueryBuilderExplorerState.ts",
104
+ "./src/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.ts",
104
105
  "./src/stores/explorer/QueryBuilderPropertySearchState.ts",
105
106
  "./src/stores/explorer/QueryFunctionsExplorerState.ts",
106
107
  "./src/stores/fetch-structure/QueryBuilderFetchStructureImplementationState.ts",