@finos/legend-query-builder 4.14.71 → 4.14.73

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 (84) hide show
  1. package/lib/components/QueryLoader.d.ts.map +1 -1
  2. package/lib/components/QueryLoader.js +12 -34
  3. package/lib/components/QueryLoader.js.map +1 -1
  4. package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts.map +1 -1
  5. package/lib/components/explorer/QueryBuilderPropertySearchPanel.js +108 -36
  6. package/lib/components/explorer/QueryBuilderPropertySearchPanel.js.map +1 -1
  7. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  8. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +10 -3
  9. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  10. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.d.ts.map +1 -1
  11. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js +2 -2
  12. package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js.map +1 -1
  13. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  14. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +6 -2
  15. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  16. package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
  17. package/lib/components/filter/QueryBuilderFilterPanel.js +5 -1
  18. package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
  19. package/lib/components/result/QueryBuilderResultPanel.d.ts.map +1 -1
  20. package/lib/components/result/QueryBuilderResultPanel.js +3 -1
  21. package/lib/components/result/QueryBuilderResultPanel.js.map +1 -1
  22. package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts.map +1 -1
  23. package/lib/components/result/tds/QueryBuilderTDSGridResult.js +5 -2
  24. package/lib/components/result/tds/QueryBuilderTDSGridResult.js.map +1 -1
  25. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.d.ts +3 -0
  26. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.d.ts.map +1 -1
  27. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.js +92 -2
  28. package/lib/components/result/tds/QueryBuilderTDSSimpleGridResult.js.map +1 -1
  29. package/lib/index.css +1 -17
  30. package/lib/index.css.map +1 -1
  31. package/lib/package.json +1 -1
  32. package/lib/stores/QueryBuilderConfig.d.ts +2 -1
  33. package/lib/stores/QueryBuilderConfig.d.ts.map +1 -1
  34. package/lib/stores/QueryBuilderConfig.js +2 -1
  35. package/lib/stores/QueryBuilderConfig.js.map +1 -1
  36. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  37. package/lib/stores/QueryBuilderResultState.js +4 -1
  38. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  39. package/lib/stores/QueryBuilderValueSpecificationHelper.d.ts +1 -1
  40. package/lib/stores/QueryBuilderValueSpecificationHelper.d.ts.map +1 -1
  41. package/lib/stores/QueryBuilderValueSpecificationHelper.js +1 -0
  42. package/lib/stores/QueryBuilderValueSpecificationHelper.js.map +1 -1
  43. package/lib/stores/QueryLoaderState.d.ts +8 -6
  44. package/lib/stores/QueryLoaderState.d.ts.map +1 -1
  45. package/lib/stores/QueryLoaderState.js +30 -7
  46. package/lib/stores/QueryLoaderState.js.map +1 -1
  47. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts +4 -3
  48. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts.map +1 -1
  49. package/lib/stores/explorer/QueryBuilderExplorerState.js +22 -7
  50. package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
  51. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.d.ts.map +1 -1
  52. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js +1 -1
  53. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js.map +1 -1
  54. package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts +7 -1
  55. package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts.map +1 -1
  56. package/lib/stores/explorer/QueryBuilderPropertySearchState.js +160 -74
  57. package/lib/stores/explorer/QueryBuilderPropertySearchState.js.map +1 -1
  58. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts +4 -1
  59. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts.map +1 -1
  60. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js +23 -12
  61. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
  62. package/lib/stores/filter/QueryBuilderFilterState.d.ts +1 -1
  63. package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
  64. package/lib/stores/filter/QueryBuilderFilterState.js +9 -5
  65. package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
  66. package/package.json +3 -3
  67. package/src/components/QueryLoader.tsx +37 -54
  68. package/src/components/explorer/QueryBuilderPropertySearchPanel.tsx +249 -226
  69. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +24 -2
  70. package/src/components/fetch-structure/QueryBuilderResultModifierPanel.tsx +6 -2
  71. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +10 -2
  72. package/src/components/filter/QueryBuilderFilterPanel.tsx +10 -1
  73. package/src/components/result/QueryBuilderResultPanel.tsx +3 -1
  74. package/src/components/result/tds/QueryBuilderTDSGridResult.tsx +8 -2
  75. package/src/components/result/tds/QueryBuilderTDSSimpleGridResult.tsx +106 -1
  76. package/src/stores/QueryBuilderConfig.ts +2 -1
  77. package/src/stores/QueryBuilderResultState.ts +4 -0
  78. package/src/stores/QueryBuilderValueSpecificationHelper.ts +2 -1
  79. package/src/stores/QueryLoaderState.ts +43 -17
  80. package/src/stores/explorer/QueryBuilderExplorerState.ts +58 -5
  81. package/src/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.ts +1 -1
  82. package/src/stores/explorer/QueryBuilderPropertySearchState.ts +194 -92
  83. package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +43 -13
  84. package/src/stores/filter/QueryBuilderFilterState.ts +16 -7
@@ -1020,13 +1020,22 @@ const QueryBuilderFilterConditionEditor = observer(
1020
1020
  rightConditionValue instanceof FilterValueSpecConditionValueState &&
1021
1021
  rightConditionValue.value
1022
1022
  ) {
1023
+ const isInvalidVariable =
1024
+ rightConditionValue.value instanceof VariableExpression &&
1025
+ node.condition.filterState.isInvalidValueSpecFilterValue(node);
1023
1026
  return (
1024
1027
  <div
1025
1028
  ref={dropConnector}
1026
1029
  data-testid={
1027
1030
  QUERY_BUILDER_TEST_ID.QUERY_BUILDER_FILTER_TREE_CONDITION_NODE_VALUE
1028
1031
  }
1029
- className="query-builder-filter-tree__condition-node__value"
1032
+ className={clsx(
1033
+ 'query-builder-filter-tree__condition-node__value',
1034
+ {
1035
+ 'query-builder-filter-tree__condition-node__value--error':
1036
+ isInvalidVariable,
1037
+ },
1038
+ )}
1030
1039
  >
1031
1040
  <PanelEntryDropZonePlaceholder
1032
1041
  isDragOver={isFilterValueDragOver}
@@ -403,7 +403,9 @@ export const QueryBuilderResultPanel = observer(
403
403
  };
404
404
  const resultDescription = executionResult
405
405
  ? getResultSetDescription(executionResult)
406
- : undefined;
406
+ : resultState.executionError
407
+ ? 'fail to execute'
408
+ : undefined;
407
409
 
408
410
  const [previewLimitValue, setPreviewLimitValue] = useState(
409
411
  resultState.previewLimit,
@@ -61,6 +61,10 @@ import {
61
61
  Dialog,
62
62
  CustomSelectorInput,
63
63
  } from '@finos/legend-art';
64
+ import {
65
+ getTDSColumnCustomizations,
66
+ MAXIMUM_FRACTION_DIGITS,
67
+ } from './QueryBuilderTDSSimpleGridResult.js';
64
68
 
65
69
  export const enum QueryBuilderDataGridCustomAggregationFunction {
66
70
  wavg = 'wavg',
@@ -109,7 +113,7 @@ const QueryResultCellRenderer = observer(
109
113
  const formattedCellValue = (): QueryBuilderTDSResultCellDataType => {
110
114
  if (isNumber(cellValue)) {
111
115
  return Intl.NumberFormat(DEFAULT_LOCALE, {
112
- maximumFractionDigits: 4,
116
+ maximumFractionDigits: MAXIMUM_FRACTION_DIGITS,
113
117
  }).format(Number(cellValue));
114
118
  } else if (isBoolean(cellValue)) {
115
119
  return String(cellValue);
@@ -173,6 +177,7 @@ const getLocalColDefs = (
173
177
  tdsExecutionResult: executionResult,
174
178
  },
175
179
  ...getAggregationTDSColumnCustomizations(executionResult, colName),
180
+ ...getTDSColumnCustomizations(executionResult, colName),
176
181
  } as DataGridColumnDefinition;
177
182
  const persistedColumn = resultState.gridConfig?.columns.find(
178
183
  (c) => c.colId === colName,
@@ -207,8 +212,8 @@ const getFilterTDSColumnCustomizations = (
207
212
  };
208
213
  case PRIMITIVE_TYPE.DECIMAL:
209
214
  case PRIMITIVE_TYPE.INTEGER:
210
- case PRIMITIVE_TYPE.FLOAT:
211
215
  case PRIMITIVE_TYPE.NUMBER:
216
+ case PRIMITIVE_TYPE.FLOAT:
212
217
  return {
213
218
  filter: 'agNumberColumnFilter',
214
219
  };
@@ -241,6 +246,7 @@ const getColDefs = (
241
246
  tdsExecutionResult: executionResult,
242
247
  },
243
248
  ...getFilterTDSColumnCustomizations(executionResult, colName),
249
+ ...getTDSColumnCustomizations(executionResult, colName),
244
250
  }) as DataGridColumnDefinition,
245
251
  );
246
252
 
@@ -19,6 +19,7 @@ import { observer } from 'mobx-react-lite';
19
19
  import type { QueryBuilderState } from '../../../stores/QueryBuilderState.js';
20
20
  import {
21
21
  getTDSRowRankByColumnInAsc,
22
+ PRIMITIVE_TYPE,
22
23
  TDSExecutionResult,
23
24
  } from '@finos/legend-graph';
24
25
  import {
@@ -47,6 +48,109 @@ import type {
47
48
  } from '../../../stores/QueryBuilderResultState.js';
48
49
  import { QUERY_BUILDER_TEST_ID } from '../../../__lib__/QueryBuilderTesting.js';
49
50
 
51
+ export const MAXIMUM_FRACTION_DIGITS = 4;
52
+
53
+ export const getFloatGridColumnCustomHeader = (): string =>
54
+ `<div class="ag-cell-label-container" role="presentation">
55
+ <span
56
+ data-ref="eMenu"
57
+ class="ag-header-icon ag-header-cell-menu-button"
58
+ ></span>
59
+ <span
60
+ data-ref="eFilterButton"
61
+ class="ag-header-icon ag-header-cell-filter-button"
62
+ ></span>
63
+ <div data-ref="eLabel" class="ag-header-cell-label" role="presentation">
64
+ <span
65
+ data-ref="eSortOrder"
66
+ class="ag-header-icon ag-sort-order ag-hidden"
67
+ ></span>
68
+ <span
69
+ data-ref="eSortAsc"
70
+ class="ag-header-icon ag-sort-ascending-icon ag-hidden"
71
+ ></span>
72
+ <span
73
+ data-ref="eSortDesc"
74
+ class="ag-header-icon ag-sort-descending-icon ag-hidden"
75
+ ></span>
76
+ <span
77
+ data-ref="eSortMixed"
78
+ class="ag-header-icon ag-sort-mixed-icon ag-hidden"
79
+ ></span>
80
+ <span
81
+ data-ref="eSortNone"
82
+ class="ag-header-icon ag-sort-none-icon ag-hidden"
83
+ ></span>
84
+ <span
85
+ data-ref="eText"
86
+ class="ag-header-cell-text"
87
+ role="columnheader"
88
+ ></span>
89
+ <span data-ref="eFilter" class="ag-header-icon ag-filter-icon"></span>
90
+ </div>
91
+ <div
92
+ data-testid="query__builder__result__grid__custom-header"
93
+ class="query-builder__result__values__table__custom-header"
94
+ >
95
+ <div
96
+ class="query-builder__result__values__table__custom-header__icon"
97
+ title="some values have been rounded using en-us format in this preview grid (defaults to max 4 decimal places)"
98
+ >
99
+ <svg
100
+ stroke="currentColor"
101
+ fill="currentColor"
102
+ stroke-width="0"
103
+ viewBox="0 0 576 512"
104
+ height="1em"
105
+ width="1em"
106
+ xmlns="http://www.w3.org/2000/svg"
107
+ >
108
+ <path d="M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"></path>
109
+ </svg>
110
+ </div>
111
+ </div>
112
+ </div>`;
113
+
114
+ export const getTDSColumnCustomizations = (
115
+ result: TDSExecutionResult,
116
+ columnName: string,
117
+ ): object => {
118
+ const index = result.builder.columns.findIndex(
119
+ (col) => col.name === columnName,
120
+ );
121
+ if (index >= 0) {
122
+ const columnType = result.builder.columns[index]?.type;
123
+ const colValues = result.result.rows.map((r) => r.values[index]);
124
+ const isTruncated = (
125
+ vals: (string | number | boolean | null | undefined)[],
126
+ ): boolean =>
127
+ Boolean(
128
+ vals.some((val) => {
129
+ if (val) {
130
+ const decimalPart = val.toString().split('.')[1];
131
+ return decimalPart && decimalPart.length > MAXIMUM_FRACTION_DIGITS;
132
+ }
133
+ return false;
134
+ }),
135
+ );
136
+ switch (columnType) {
137
+ case PRIMITIVE_TYPE.NUMBER:
138
+ case PRIMITIVE_TYPE.DECIMAL:
139
+ case PRIMITIVE_TYPE.FLOAT:
140
+ return isTruncated(colValues)
141
+ ? {
142
+ headerComponentParams: {
143
+ template: getFloatGridColumnCustomHeader(),
144
+ },
145
+ }
146
+ : {};
147
+ default:
148
+ return {};
149
+ }
150
+ }
151
+ return {};
152
+ };
153
+
50
154
  const QueryResultCellRenderer = observer(
51
155
  (params: IQueryRendererParamsWithGridType) => {
52
156
  const resultState = params.resultState;
@@ -62,7 +166,7 @@ const QueryResultCellRenderer = observer(
62
166
  const formattedCellValue = (): QueryBuilderTDSResultCellDataType => {
63
167
  if (isNumber(cellValue)) {
64
168
  return Intl.NumberFormat(DEFAULT_LOCALE, {
65
- maximumFractionDigits: 4,
169
+ maximumFractionDigits: MAXIMUM_FRACTION_DIGITS,
66
170
  }).format(Number(cellValue));
67
171
  } else if (isBoolean(cellValue)) {
68
172
  return String(cellValue);
@@ -368,6 +472,7 @@ export const QueryBuilderTDSSimpleGridResult = observer(
368
472
  resizable: true,
369
473
  field: colName,
370
474
  flex: 1,
475
+ ...getTDSColumnCustomizations(executionResult, colName),
371
476
  cellRenderer: QueryResultCellRenderer,
372
477
  cellRendererParams: {
373
478
  resultState: resultState,
@@ -25,12 +25,13 @@ export const DEFAULT_VARIABLE_NAME = 'var';
25
25
  export const DEFAULT_CONSTANT_VARIABLE_NAME = 'c_var';
26
26
  export const DEFAULT_POST_FILTER_LAMBDA_VARIABLE_NAME = 'row';
27
27
 
28
- export const QUERY_BUILDER_PROPERTY_SEARCH_MAX_DEPTH = 5;
28
+ export const QUERY_BUILDER_PROPERTY_SEARCH_MAX_DEPTH = 10;
29
29
  export const QUERY_BUILDER_PROPERTY_SEARCH_MAX_NODES = 10000;
30
30
  export const QUERY_BUILDER_PROPERTY_SEARCH_RESULTS_LIMIT = 100;
31
31
 
32
32
  export enum QUERY_BUILDER_PROPERTY_SEARCH_TYPE {
33
33
  CLASS = 'CLASS',
34
+ ENUMERATION = 'ENUMERATION',
34
35
  STRING = 'STRING',
35
36
  BOOLEAN = 'BOOLEAN',
36
37
  NUMBER = 'NUMBER',
@@ -38,6 +38,7 @@ import {
38
38
  reportGraphAnalytics,
39
39
  TDSExecutionResult,
40
40
  V1_ZIPKIN_TRACE_HEADER,
41
+ ExecutionError,
41
42
  } from '@finos/legend-graph';
42
43
  import { buildLambdaFunction } from './QueryBuilderValueSpecificationBuilder.js';
43
44
  import {
@@ -536,6 +537,9 @@ export class QueryBuilderResultState {
536
537
  error,
537
538
  );
538
539
  this.setExecutionError(error);
540
+ if (error instanceof ExecutionError && error.executionTraceId) {
541
+ this.setExecutionTraceId(error.executionTraceId);
542
+ }
539
543
  }
540
544
  } finally {
541
545
  this.setIsRunningQuery(false);
@@ -213,7 +213,7 @@ export const isPropertyExpressionChainOptional = (
213
213
 
214
214
  export const isTypeCompatibleForAssignment = (
215
215
  type: Type | undefined,
216
- assignmentType: Type,
216
+ assignmentType: Type | undefined,
217
217
  ): boolean => {
218
218
  const NUMERIC_PRIMITIVE_TYPES = [
219
219
  PRIMITIVE_TYPE.NUMBER,
@@ -231,6 +231,7 @@ export const isTypeCompatibleForAssignment = (
231
231
  // When changing the return type for LHS, the RHS value should be adjusted accordingly.
232
232
  return (
233
233
  type !== undefined &&
234
+ assignmentType !== undefined &&
234
235
  // Numeric value is handled loosely because of autoboxing
235
236
  // e.g. LHS (integer) = RHS (float) is acceptable
236
237
  ((NUMERIC_PRIMITIVE_TYPES.includes(type.path) &&
@@ -19,17 +19,18 @@ import {
19
19
  type GenericLegendApplicationStore,
20
20
  } from '@finos/legend-application';
21
21
  import {
22
- QuerySearchSpecification,
23
- GRAPH_MANAGER_EVENT,
24
22
  type QueryInfo,
25
23
  type LightQuery,
26
24
  type BasicGraphManagerState,
27
25
  type Query,
28
26
  type RawLambda,
27
+ QuerySearchSpecification,
28
+ GRAPH_MANAGER_EVENT,
29
+ QuerySearchSortBy,
29
30
  } from '@finos/legend-graph';
30
31
  import {
31
- ActionState,
32
32
  type GeneratorFn,
33
+ ActionState,
33
34
  assertErrorThrown,
34
35
  guaranteeNonNullable,
35
36
  LogEvent,
@@ -51,7 +52,7 @@ export enum SORT_BY_OPTIONS {
51
52
  SORT_BY_UPDATE = 'Last Updated',
52
53
  }
53
54
 
54
- export type SortByOption = { label: string; value: string };
55
+ export type SortByOption = { label: SORT_BY_OPTIONS; value: SORT_BY_OPTIONS };
55
56
 
56
57
  export class QueryLoaderState {
57
58
  readonly applicationStore: GenericLegendApplicationStore;
@@ -92,7 +93,7 @@ export class QueryLoaderState {
92
93
  showingDefaultQueries = true;
93
94
  showPreviewViewer = false;
94
95
  queryPreviewContent?: QueryInfo | { name: string; content: string };
95
- sortBy = '';
96
+ sortBy = SORT_BY_OPTIONS.SORT_BY_VIEW;
96
97
 
97
98
  constructor(
98
99
  applicationStore: GenericLegendApplicationStore,
@@ -158,10 +159,23 @@ export class QueryLoaderState {
158
159
  this.isCuratedTemplateToggled = val;
159
160
  }
160
161
 
161
- setSortBy(val: string): void {
162
+ setSortBy(val: SORT_BY_OPTIONS): void {
162
163
  this.sortBy = val;
163
164
  }
164
165
 
166
+ getQuerySearchSortBy(sortByValue: string): QuerySearchSortBy | undefined {
167
+ switch (sortByValue) {
168
+ case SORT_BY_OPTIONS.SORT_BY_CREATE:
169
+ return QuerySearchSortBy.SORT_BY_CREATE;
170
+ case SORT_BY_OPTIONS.SORT_BY_UPDATE:
171
+ return QuerySearchSortBy.SORT_BY_UPDATE;
172
+ case SORT_BY_OPTIONS.SORT_BY_VIEW:
173
+ return QuerySearchSortBy.SORT_BY_VIEW;
174
+ default:
175
+ return undefined;
176
+ }
177
+ }
178
+
165
179
  setSearchText(val: string): void {
166
180
  this.searchText = val;
167
181
  }
@@ -171,7 +185,16 @@ export class QueryLoaderState {
171
185
  }
172
186
 
173
187
  setQueries(val: LightQuery[]): void {
174
- this.queries = val.sort((a, b) => a.name.localeCompare(b.name));
188
+ this.queries = val;
189
+ }
190
+
191
+ // search query using search specification
192
+ canPerformAdvancedSearch(searchText: string): boolean {
193
+ return !(
194
+ searchText.length < DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH &&
195
+ !this.showCurrentUserQueriesOnly &&
196
+ Array.from(this.extraFilters.values()).every((value) => value === false)
197
+ );
175
198
  }
176
199
 
177
200
  setShowPreviewViewer(val: boolean): void {
@@ -226,11 +249,7 @@ export class QueryLoaderState {
226
249
  }
227
250
 
228
251
  *searchQueries(searchText: string): GeneratorFn<void> {
229
- if (
230
- searchText.length < DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH &&
231
- !this.showCurrentUserQueriesOnly &&
232
- Array.from(this.extraFilters.values()).every((value) => value === false)
233
- ) {
252
+ if (!this.canPerformAdvancedSearch(searchText)) {
234
253
  // if no search text is specified, use fetch the default queries
235
254
  if (!searchText) {
236
255
  this.showingDefaultQueries = true;
@@ -268,6 +287,10 @@ export class QueryLoaderState {
268
287
  searchSpecification.limit = QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT + 1;
269
288
  searchSpecification.showCurrentUserQueriesOnly =
270
289
  this.showCurrentUserQueriesOnly;
290
+ const querySearchSortBy = this.getQuerySearchSortBy(this.sortBy);
291
+ if (querySearchSortBy) {
292
+ searchSpecification.sortByOption = querySearchSortBy;
293
+ }
271
294
  if (this.queryBuilderState) {
272
295
  Array.from(this.extraFilters.entries()).forEach(([key, value]) => {
273
296
  if (value) {
@@ -288,11 +311,14 @@ export class QueryLoaderState {
288
311
  searchSpecification =
289
312
  this.decorateSearchSpecification?.(searchSpecification) ??
290
313
  searchSpecification;
291
- this.queries = (
292
- (yield this.graphManagerState.graphManager.searchQueries(
293
- searchSpecification,
294
- )) as LightQuery[]
295
- ).sort((a, b) => a.name.localeCompare(b.name));
314
+ this.queries = (yield this.graphManagerState.graphManager.searchQueries(
315
+ searchSpecification,
316
+ )) as LightQuery[];
317
+ if (!querySearchSortBy) {
318
+ this.queries = this.queries.sort((a, b) =>
319
+ a.name.localeCompare(b.name),
320
+ );
321
+ }
296
322
  this.searchQueriesState.pass();
297
323
  } catch (error) {
298
324
  assertErrorThrown(error);
@@ -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 ExecutionResult;
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 ExecutionResult;
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 = false;
21
+ includeSubTypes = true;
22
22
  includeDocumentation = false;
23
23
 
24
24
  constructor(