@finos/legend-query-builder 4.14.19 → 4.14.21

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 (33) hide show
  1. package/lib/components/QueryLoader.d.ts.map +1 -1
  2. package/lib/components/QueryLoader.js +85 -36
  3. package/lib/components/QueryLoader.js.map +1 -1
  4. package/lib/components/result/QueryBuilderResultPanel.d.ts.map +1 -1
  5. package/lib/components/result/QueryBuilderResultPanel.js.map +1 -1
  6. package/lib/components/result/tds/QueryBuilderTDSGridResult.d.ts.map +1 -1
  7. package/lib/components/result/tds/QueryBuilderTDSGridResult.js +3 -2
  8. package/lib/components/result/tds/QueryBuilderTDSGridResult.js.map +1 -1
  9. package/lib/index.css +1 -17
  10. package/lib/index.css.map +1 -1
  11. package/lib/package.json +1 -1
  12. package/lib/stores/QueryBuilderResultState.d.ts +7 -4
  13. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  14. package/lib/stores/QueryBuilderResultState.js +20 -4
  15. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  16. package/lib/stores/QueryBuilderState.d.ts +4 -2
  17. package/lib/stores/QueryBuilderState.d.ts.map +1 -1
  18. package/lib/stores/QueryBuilderState.js +13 -2
  19. package/lib/stores/QueryBuilderState.js.map +1 -1
  20. package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts +19 -1
  21. package/lib/stores/QueryBuilder_LegendApplicationPlugin_Extension.d.ts.map +1 -1
  22. package/lib/stores/QueryLoaderState.d.ts +14 -4
  23. package/lib/stores/QueryLoaderState.d.ts.map +1 -1
  24. package/lib/stores/QueryLoaderState.js +35 -5
  25. package/lib/stores/QueryLoaderState.js.map +1 -1
  26. package/package.json +3 -3
  27. package/src/components/QueryLoader.tsx +279 -127
  28. package/src/components/result/QueryBuilderResultPanel.tsx +0 -1
  29. package/src/components/result/tds/QueryBuilderTDSGridResult.tsx +3 -2
  30. package/src/stores/QueryBuilderResultState.ts +27 -7
  31. package/src/stores/QueryBuilderState.ts +19 -2
  32. package/src/stores/QueryBuilder_LegendApplicationPlugin_Extension.ts +30 -1
  33. package/src/stores/QueryLoaderState.ts +64 -12
@@ -99,7 +99,7 @@ const getLocalColDefs = (
99
99
  enableValue: true,
100
100
  ...getAggregationTDSColumnCustomizations(executionResult, colName),
101
101
  } as DataGridColumnDefinition;
102
- const persistedColumn = resultState.gridConfig.columns.find(
102
+ const persistedColumn = resultState.gridConfig?.columns.find(
103
103
  (c) => c.colId === colName,
104
104
  );
105
105
  if (persistedColumn) {
@@ -240,6 +240,7 @@ export const QueryBuilderTDSGridResult = observer(
240
240
  resultState.setGridConfig({
241
241
  columns: columnAPi.getColumnState(),
242
242
  isPivotModeEnabled: columnAPi.isPivotMode(),
243
+ isLocalModeEnabled: true,
243
244
  });
244
245
  };
245
246
 
@@ -351,7 +352,7 @@ export const QueryBuilderTDSGridResult = observer(
351
352
  onGridReady={(params): void => {
352
353
  setColumnApi(params.columnApi);
353
354
  params.columnApi.setPivotMode(
354
- resultState.gridConfig.isPivotModeEnabled,
355
+ Boolean(resultState.gridConfig?.isPivotModeEnabled),
355
356
  );
356
357
  }}
357
358
  gridOptions={{
@@ -31,6 +31,7 @@ import {
31
31
  type ExecutionResult,
32
32
  type RawLambda,
33
33
  type EXECUTION_SERIALIZATION_FORMAT,
34
+ type QueryGridConfig,
34
35
  GRAPH_MANAGER_EVENT,
35
36
  buildRawLambdaFromLambdaFunction,
36
37
  reportGraphAnalytics,
@@ -79,7 +80,8 @@ export interface QueryBuilderTDSResultCellCoordinate {
79
80
 
80
81
  type QueryBuilderDataGridConfig = {
81
82
  columns: DataGridColumnState[];
82
- isPivotModeEnabled: boolean;
83
+ isPivotModeEnabled: boolean | undefined;
84
+ isLocalModeEnabled: boolean | undefined;
83
85
  };
84
86
 
85
87
  export class QueryBuilderResultState {
@@ -101,7 +103,7 @@ export class QueryBuilderResultState {
101
103
  mousedOverCell: QueryBuilderTDSResultCellData | null = null;
102
104
  isSelectingCells: boolean;
103
105
 
104
- gridConfig!: QueryBuilderDataGridConfig;
106
+ gridConfig: QueryBuilderDataGridConfig | undefined;
105
107
 
106
108
  constructor(queryBuilderState: QueryBuilderState) {
107
109
  makeObservable(this, {
@@ -128,6 +130,7 @@ export class QueryBuilderResultState {
128
130
  setMouseOverCell: action,
129
131
  setQueryRunPromise: action,
130
132
  setIsQueryUsageViewerOpened: action,
133
+ handlePreConfiguredGridConfig: action,
131
134
  exportData: flow,
132
135
  runQuery: flow,
133
136
  cancelQuery: flow,
@@ -136,10 +139,7 @@ export class QueryBuilderResultState {
136
139
  this.isSelectingCells = false;
137
140
 
138
141
  this.selectedCells = [];
139
- this.gridConfig = {
140
- columns: [],
141
- isPivotModeEnabled: false,
142
- };
142
+ this.gridConfig = undefined;
143
143
  this.queryBuilderState = queryBuilderState;
144
144
  this.executionPlanState = new ExecutionPlanState(
145
145
  this.queryBuilderState.applicationStore,
@@ -147,7 +147,7 @@ export class QueryBuilderResultState {
147
147
  );
148
148
  }
149
149
 
150
- setGridConfig(val: QueryBuilderDataGridConfig): void {
150
+ setGridConfig(val: QueryBuilderDataGridConfig | undefined): void {
151
151
  this.gridConfig = val;
152
152
  }
153
153
 
@@ -191,6 +191,26 @@ export class QueryBuilderResultState {
191
191
  this.isQueryUsageViewerOpened = val;
192
192
  }
193
193
 
194
+ handlePreConfiguredGridConfig(config: QueryGridConfig): void {
195
+ const newConfig = {
196
+ columns: config.columns as DataGridColumnState[],
197
+ isPivotModeEnabled: Boolean(config.isPivotModeEnabled),
198
+ isLocalModeEnabled: Boolean(config.isLocalModeEnabled),
199
+ };
200
+ this.setGridConfig(newConfig);
201
+ }
202
+
203
+ getQueryGridConfig(): QueryGridConfig | undefined {
204
+ if (this.gridConfig) {
205
+ return {
206
+ columns: this.gridConfig.columns as object[],
207
+ isPivotModeEnabled: Boolean(this.gridConfig.isPivotModeEnabled),
208
+ isLocalModeEnabled: Boolean(this.gridConfig.isLocalModeEnabled),
209
+ };
210
+ }
211
+ return undefined;
212
+ }
213
+
194
214
  get checkForStaleResults(): boolean {
195
215
  if (this.latestRunHashCode !== this.queryBuilderState.hashCode) {
196
216
  return true;
@@ -53,6 +53,7 @@ import {
53
53
  type GraphManagerState,
54
54
  type ValueSpecification,
55
55
  type Type,
56
+ type QueryGridConfig,
56
57
  GRAPH_MANAGER_EVENT,
57
58
  CompilationError,
58
59
  extractSourceInformationCoordinates,
@@ -393,7 +394,10 @@ export abstract class QueryBuilderState implements CommandRegistrar {
393
394
  );
394
395
  }
395
396
 
396
- resetQueryResult(options?: { preserveResult?: boolean | undefined }): void {
397
+ resetQueryResult(options?: {
398
+ preserveResult?: boolean | undefined;
399
+ gridConfig?: QueryGridConfig | undefined;
400
+ }): void {
397
401
  const resultState = new QueryBuilderResultState(this);
398
402
  resultState.setPreviewLimit(this.resultState.previewLimit);
399
403
  if (options?.preserveResult) {
@@ -401,6 +405,10 @@ export abstract class QueryBuilderState implements CommandRegistrar {
401
405
  resultState.setExecutionDuration(this.resultState.executionDuration);
402
406
  resultState.latestRunHashCode = this.resultState.latestRunHashCode;
403
407
  }
408
+ if (options?.gridConfig) {
409
+ this.isLocalModeEnabled = true;
410
+ resultState.handlePreConfiguredGridConfig(options.gridConfig);
411
+ }
404
412
  this.resultState = resultState;
405
413
  }
406
414
 
@@ -476,6 +484,14 @@ export abstract class QueryBuilderState implements CommandRegistrar {
476
484
  return undefined;
477
485
  }
478
486
 
487
+ getGridConfig(): QueryGridConfig | undefined {
488
+ // for now we will only save in local mode
489
+ if (this.isLocalModeEnabled && this.resultState.gridConfig) {
490
+ return this.resultState.getQueryGridConfig();
491
+ }
492
+ return undefined;
493
+ }
494
+
479
495
  buildQuery(options?: { keepSourceInformation: boolean }): RawLambda {
480
496
  if (!this.isQuerySupported) {
481
497
  const parameters = this.parametersState.parameterStates.map((e) =>
@@ -552,11 +568,12 @@ export abstract class QueryBuilderState implements CommandRegistrar {
552
568
  initializeWithQuery(
553
569
  query: RawLambda,
554
570
  defaultParameterValues?: Map<string, ValueSpecification>,
571
+ gridConfig?: QueryGridConfig,
555
572
  ): void {
556
573
  this.rebuildWithQuery(query, {
557
574
  defaultParameterValues,
558
575
  });
559
- this.resetQueryResult();
576
+ this.resetQueryResult({ gridConfig });
560
577
  this.changeDetectionState.initialize(query);
561
578
  this.changeHistoryState.initialize(query);
562
579
  }
@@ -16,12 +16,29 @@
16
16
 
17
17
  import type { LegendApplicationPlugin } from '@finos/legend-application';
18
18
  import type { QueryBuilderState } from './QueryBuilderState.js';
19
- import type { QuerySearchSpecification } from '@finos/legend-graph';
19
+ import type { QuerySearchSpecification, RawLambda } from '@finos/legend-graph';
20
20
  import type {
21
21
  DataAccessState,
22
22
  DatasetAccessInfo,
23
23
  } from './data-access/DataAccessState.js';
24
24
 
25
+ export type CuratedTemplateQuery = {
26
+ title: string;
27
+ description: string | undefined;
28
+ query: RawLambda;
29
+ executionContextKey: string;
30
+ };
31
+
32
+ export type CuratedTemplateQuerySpecification = {
33
+ getCuratedTemplateQueries(
34
+ queryBuilderState: QueryBuilderState,
35
+ ): CuratedTemplateQuery[];
36
+ loadCuratedTemplateQuery(
37
+ templateQuery: CuratedTemplateQuery,
38
+ queryBuilderState: QueryBuilderState,
39
+ ): void;
40
+ };
41
+
25
42
  export type LoadQueryFilterOption = {
26
43
  key: string;
27
44
  label: (queryBuilderState: QueryBuilderState) => string | undefined;
@@ -59,11 +76,23 @@ export type TemplateQueryPanelContentRenderer = (
59
76
 
60
77
  export interface QueryBuilder_LegendApplicationPlugin_Extension
61
78
  extends LegendApplicationPlugin {
79
+ /**
80
+ * Get the list of template query specifications
81
+ */
82
+ getCuratedTemplateQuerySpecifications?(): CuratedTemplateQuerySpecification[];
83
+
62
84
  /**
63
85
  * Get the list of filter options for query loader.
64
86
  */
65
87
  getExtraLoadQueryFilterOptions?(): LoadQueryFilterOption[];
66
88
 
89
+ /**
90
+ * Get the list of filter options related to template query
91
+ */
92
+ getQueryFilterOptionsRelatedToTemplateQuery?(): (
93
+ queryBuilderState: QueryBuilderState,
94
+ ) => string[];
95
+
67
96
  /**
68
97
  * Get the list of warehouse entitlement configurations
69
98
  */
@@ -19,12 +19,13 @@ import {
19
19
  type GenericLegendApplicationStore,
20
20
  } from '@finos/legend-application';
21
21
  import {
22
- type LightQuery,
23
22
  QuerySearchSpecification,
23
+ GRAPH_MANAGER_EVENT,
24
24
  type QueryInfo,
25
+ type LightQuery,
25
26
  type BasicGraphManagerState,
26
27
  type Query,
27
- GRAPH_MANAGER_EVENT,
28
+ type RawLambda,
28
29
  } from '@finos/legend-graph';
29
30
  import {
30
31
  ActionState,
@@ -36,6 +37,7 @@ import {
36
37
  import { makeObservable, observable, action, flow } from 'mobx';
37
38
  import type { QueryBuilderState } from './QueryBuilderState.js';
38
39
  import type {
40
+ CuratedTemplateQuerySpecification,
39
41
  LoadQueryFilterOption,
40
42
  QueryBuilder_LegendApplicationPlugin_Extension,
41
43
  } from './QueryBuilder_LegendApplicationPlugin_Extension.js';
@@ -72,12 +74,15 @@ export class QueryLoaderState {
72
74
  showCurrentUserQueriesOnly = false; // TODO: if we start having more native filters, we should make them part of `extraFilters`
73
75
  extraFilters = new Map<string, boolean>();
74
76
  extraFilterOptions: LoadQueryFilterOption[] = [];
77
+ extraQueryFilterOptionsRelatedToTemplateQuery: string[] = [];
75
78
  queries: LightQuery[] = [];
79
+ curatedTemplateQuerySepcifications: CuratedTemplateQuerySpecification[] = [];
76
80
 
77
81
  isQueryLoaderDialogOpen = false;
82
+ isCuratedTemplateToggled = false;
78
83
  showingDefaultQueries = true;
79
84
  showPreviewViewer = false;
80
- queryPreviewContent?: QueryInfo;
85
+ queryPreviewContent?: QueryInfo | { name: string; content: string };
81
86
 
82
87
  constructor(
83
88
  applicationStore: GenericLegendApplicationStore,
@@ -107,11 +112,14 @@ export class QueryLoaderState {
107
112
  showCurrentUserQueriesOnly: observable,
108
113
  showPreviewViewer: observable,
109
114
  searchText: observable,
115
+ isCuratedTemplateToggled: observable,
116
+ curatedTemplateQuerySepcifications: observable,
110
117
  setSearchText: action,
111
118
  setQueryLoaderDialogOpen: action,
112
119
  setQueries: action,
113
120
  setShowCurrentUserQueriesOnly: action,
114
121
  setShowPreviewViewer: action,
122
+ setIsCuratedTemplateToggled: action,
115
123
  searchQueries: flow,
116
124
  getPreviewQueryContent: flow,
117
125
  deleteQuery: flow,
@@ -134,6 +142,10 @@ export class QueryLoaderState {
134
142
  options.handleFetchDefaultQueriesFailure;
135
143
  }
136
144
 
145
+ setIsCuratedTemplateToggled(val: boolean): void {
146
+ this.isCuratedTemplateToggled = val;
147
+ }
148
+
137
149
  setSearchText(val: string): void {
138
150
  this.searchText = val;
139
151
  }
@@ -156,6 +168,7 @@ export class QueryLoaderState {
156
168
 
157
169
  reset(): void {
158
170
  this.setShowCurrentUserQueriesOnly(false);
171
+ this.setIsCuratedTemplateToggled(false);
159
172
  }
160
173
 
161
174
  *initialize(queryBuilderState: QueryBuilderState): GeneratorFn<void> {
@@ -168,12 +181,32 @@ export class QueryLoaderState {
168
181
  plugin as QueryBuilder_LegendApplicationPlugin_Extension
169
182
  ).getExtraLoadQueryFilterOptions?.() ?? [],
170
183
  );
184
+ this.extraQueryFilterOptionsRelatedToTemplateQuery =
185
+ this.applicationStore.pluginManager
186
+ .getApplicationPlugins()
187
+ .flatMap(
188
+ (plugin) =>
189
+ (plugin as QueryBuilder_LegendApplicationPlugin_Extension)
190
+ .getQueryFilterOptionsRelatedToTemplateQuery?.()(
191
+ guaranteeNonNullable(this.queryBuilderState),
192
+ )
193
+ .flat() ?? [],
194
+ );
171
195
  const extraFilters = this.extraFilterOptions.map((filterOption) =>
172
196
  filterOption.label(guaranteeNonNullable(this.queryBuilderState)),
173
197
  );
174
198
  extraFilters.forEach(
175
199
  (filter) => filter && this.extraFilters.set(filter, false),
176
200
  );
201
+ this.curatedTemplateQuerySepcifications =
202
+ this.applicationStore.pluginManager
203
+ .getApplicationPlugins()
204
+ .flatMap(
205
+ (plugin) =>
206
+ (
207
+ plugin as QueryBuilder_LegendApplicationPlugin_Extension
208
+ ).getCuratedTemplateQuerySpecifications?.() ?? [],
209
+ );
177
210
  }
178
211
 
179
212
  *searchQueries(searchText: string): GeneratorFn<void> {
@@ -287,17 +320,36 @@ export class QueryLoaderState {
287
320
  }
288
321
  }
289
322
 
290
- *getPreviewQueryContent(queryId: string): GeneratorFn<void> {
323
+ *getPreviewQueryContent(
324
+ queryId: string | undefined,
325
+ template?: {
326
+ queryName: string;
327
+ queryContent: RawLambda;
328
+ },
329
+ ): GeneratorFn<void> {
291
330
  this.previewQueryState.inProgress();
292
331
  try {
293
- const queryInfo = (yield this.graphManagerState.graphManager.getQueryInfo(
294
- queryId,
295
- )) as QueryInfo;
296
- this.queryPreviewContent = queryInfo;
297
- this.queryPreviewContent.content =
298
- (yield this.graphManagerState.graphManager.prettyLambdaContent(
299
- queryInfo.content,
300
- )) as string;
332
+ if (queryId) {
333
+ const queryInfo =
334
+ (yield this.graphManagerState.graphManager.getQueryInfo(
335
+ queryId,
336
+ )) as QueryInfo;
337
+ this.queryPreviewContent = queryInfo;
338
+ this.queryPreviewContent.content =
339
+ (yield this.graphManagerState.graphManager.prettyLambdaContent(
340
+ queryInfo.content,
341
+ )) as string;
342
+ } else if (template) {
343
+ this.queryPreviewContent = {
344
+ name: template.queryName,
345
+ content: '',
346
+ } as QueryInfo;
347
+ this.queryPreviewContent.content =
348
+ (yield this.graphManagerState.graphManager.lambdaToPureCode(
349
+ template.queryContent,
350
+ true,
351
+ )) as string;
352
+ }
301
353
  this.previewQueryState.pass();
302
354
  } catch (error) {
303
355
  assertErrorThrown(error);