@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.
- package/lib/__lib__/QueryBuilderTesting.d.ts +1 -0
- package/lib/__lib__/QueryBuilderTesting.d.ts.map +1 -1
- package/lib/__lib__/QueryBuilderTesting.js +1 -0
- package/lib/__lib__/QueryBuilderTesting.js.map +1 -1
- package/lib/components/QueryBuilderConstantExpressionPanel.d.ts.map +1 -1
- package/lib/components/QueryBuilderConstantExpressionPanel.js +2 -1
- package/lib/components/QueryBuilderConstantExpressionPanel.js.map +1 -1
- package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts +1 -0
- package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts.map +1 -1
- package/lib/components/explorer/QueryBuilderExplorerPanel.js +87 -52
- package/lib/components/explorer/QueryBuilderExplorerPanel.js.map +1 -1
- package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts +4 -0
- package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts.map +1 -1
- package/lib/components/explorer/QueryBuilderPropertySearchPanel.js +172 -108
- 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 +2 -1
- package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +29 -18
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js +13 -4
- package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js.map +1 -1
- package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
- package/lib/components/filter/QueryBuilderFilterPanel.js +4 -3
- package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
- package/lib/components/result/QueryBuilderResultPanel.d.ts +12 -0
- package/lib/components/result/QueryBuilderResultPanel.d.ts.map +1 -1
- package/lib/components/result/QueryBuilderResultPanel.js +60 -8
- package/lib/components/result/QueryBuilderResultPanel.js.map +1 -1
- package/lib/components/shared/QueryBuilderFilterHelper.d.ts.map +1 -1
- package/lib/components/shared/QueryBuilderFilterHelper.js +3 -0
- package/lib/components/shared/QueryBuilderFilterHelper.js.map +1 -1
- package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts +11 -0
- package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts.map +1 -1
- package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js +6 -3
- package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js.map +1 -1
- package/lib/graph-manager/QueryBuilderConfig.d.ts +4 -0
- package/lib/graph-manager/QueryBuilderConfig.d.ts.map +1 -1
- package/lib/graph-manager/QueryBuilderConfig.js +5 -0
- package/lib/graph-manager/QueryBuilderConfig.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/QueryBuilderConstantsState.d.ts +1 -0
- package/lib/stores/QueryBuilderConstantsState.d.ts.map +1 -1
- package/lib/stores/QueryBuilderConstantsState.js +6 -1
- package/lib/stores/QueryBuilderConstantsState.js.map +1 -1
- package/lib/stores/QueryBuilderResultState.d.ts +11 -3
- package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
- package/lib/stores/QueryBuilderResultState.js +47 -4
- package/lib/stores/QueryBuilderResultState.js.map +1 -1
- package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.d.ts +4 -0
- package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.d.ts.map +1 -1
- package/lib/stores/explorer/QueryBuilderExplorerState.d.ts +3 -1
- package/lib/stores/explorer/QueryBuilderExplorerState.d.ts.map +1 -1
- package/lib/stores/explorer/QueryBuilderExplorerState.js +63 -8
- package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
- package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.d.ts +24 -0
- package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.d.ts.map +1 -0
- package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js +39 -0
- package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js.map +1 -0
- package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts +8 -4
- package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts.map +1 -1
- package/lib/stores/explorer/QueryBuilderPropertySearchState.js +204 -114
- 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 +8 -1
- package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
- package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.d.ts.map +1 -1
- package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js +12 -1
- package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js.map +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.d.ts +8 -1
- package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.js +27 -10
- package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
- package/package.json +8 -8
- package/src/__lib__/QueryBuilderTesting.ts +1 -0
- package/src/components/QueryBuilderConstantExpressionPanel.tsx +2 -1
- package/src/components/explorer/QueryBuilderExplorerPanel.tsx +220 -114
- package/src/components/explorer/QueryBuilderPropertySearchPanel.tsx +618 -388
- package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +5 -2
- package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +78 -44
- package/src/components/fetch-structure/QueryBuilderTDSWindowPanel.tsx +63 -10
- package/src/components/filter/QueryBuilderFilterPanel.tsx +4 -2
- package/src/components/result/QueryBuilderResultPanel.tsx +207 -20
- package/src/components/shared/QueryBuilderFilterHelper.ts +8 -0
- package/src/components/shared/QueryBuilderPropertyInfoTooltip.tsx +13 -3
- package/src/graph-manager/QueryBuilderConfig.ts +6 -0
- package/src/stores/QueryBuilderConstantsState.ts +16 -1
- package/src/stores/QueryBuilderResultState.ts +64 -10
- package/src/stores/QueryBuilderValueSpecificationBuilderHelper.ts +5 -0
- package/src/stores/explorer/QueryBuilderExplorerState.ts +92 -8
- package/src/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.ts +46 -0
- package/src/stores/explorer/QueryBuilderPropertySearchState.ts +280 -142
- package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +8 -1
- package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.ts +15 -2
- package/src/stores/filter/QueryBuilderFilterState.ts +34 -11
- package/tsconfig.json +1 -0
|
@@ -30,7 +30,8 @@ import {
|
|
|
30
30
|
addUniqueEntry,
|
|
31
31
|
deleteEntry,
|
|
32
32
|
guaranteeNonNullable,
|
|
33
|
-
|
|
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:
|
|
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 =
|
|
116
|
-
|
|
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.
|
|
154
|
-
return;
|
|
172
|
+
this.setSearchResults([]);
|
|
173
|
+
return Promise.resolve();
|
|
155
174
|
}
|
|
175
|
+
|
|
156
176
|
this.searchState.inProgress();
|
|
157
177
|
|
|
158
|
-
//
|
|
159
|
-
//
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
-
|
|
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.
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
|
|
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
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
.
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
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
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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) =>
|
|
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
|
|
package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.ts
CHANGED
|
@@ -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
|
|
132
|
-
|
|
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",
|