@finos/legend-application-query 12.0.7 → 12.0.9

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 (52) hide show
  1. package/lib/__lib__/LegendQueryEvent.d.ts +3 -1
  2. package/lib/__lib__/LegendQueryEvent.d.ts.map +1 -1
  3. package/lib/__lib__/LegendQueryEvent.js +2 -0
  4. package/lib/__lib__/LegendQueryEvent.js.map +1 -1
  5. package/lib/__lib__/LegendQueryTelemetryHelper.d.ts +2 -0
  6. package/lib/__lib__/LegendQueryTelemetryHelper.d.ts.map +1 -1
  7. package/lib/__lib__/LegendQueryTelemetryHelper.js +6 -0
  8. package/lib/__lib__/LegendQueryTelemetryHelper.js.map +1 -1
  9. package/lib/application/LegendQueryDocumentation.d.ts +19 -0
  10. package/lib/application/LegendQueryDocumentation.d.ts.map +1 -0
  11. package/lib/application/LegendQueryDocumentation.js +20 -0
  12. package/lib/application/LegendQueryDocumentation.js.map +1 -0
  13. package/lib/components/CloneQueryServiceSetup.d.ts.map +1 -1
  14. package/lib/components/CloneQueryServiceSetup.js +1 -2
  15. package/lib/components/CloneQueryServiceSetup.js.map +1 -1
  16. package/lib/components/CreateMappingQuerySetup.d.ts.map +1 -1
  17. package/lib/components/CreateMappingQuerySetup.js +1 -2
  18. package/lib/components/CreateMappingQuerySetup.js.map +1 -1
  19. package/lib/components/LegendQueryWebApplication.d.ts +0 -1
  20. package/lib/components/LegendQueryWebApplication.d.ts.map +1 -1
  21. package/lib/components/QueryEditor.d.ts +0 -1
  22. package/lib/components/QueryEditor.d.ts.map +1 -1
  23. package/lib/components/QueryEditor.js +113 -28
  24. package/lib/components/QueryEditor.js.map +1 -1
  25. package/lib/components/QuerySetup.d.ts +1 -1
  26. package/lib/components/QuerySetup.d.ts.map +1 -1
  27. package/lib/components/QuerySetup.js +13 -4
  28. package/lib/components/QuerySetup.js.map +1 -1
  29. package/lib/index.css +2 -2
  30. package/lib/index.css.map +1 -1
  31. package/lib/index.d.ts +1 -1
  32. package/lib/index.d.ts.map +1 -1
  33. package/lib/package.json +4 -4
  34. package/lib/stores/LegendQueryApplicationPlugin.d.ts +15 -5
  35. package/lib/stores/LegendQueryApplicationPlugin.d.ts.map +1 -1
  36. package/lib/stores/LegendQueryApplicationPlugin.js.map +1 -1
  37. package/lib/stores/QueryEditorStore.d.ts +52 -11
  38. package/lib/stores/QueryEditorStore.d.ts.map +1 -1
  39. package/lib/stores/QueryEditorStore.js +228 -21
  40. package/lib/stores/QueryEditorStore.js.map +1 -1
  41. package/package.json +11 -11
  42. package/src/__lib__/LegendQueryEvent.ts +3 -0
  43. package/src/__lib__/LegendQueryTelemetryHelper.ts +15 -0
  44. package/src/application/LegendQueryDocumentation.ts +19 -0
  45. package/src/components/CloneQueryServiceSetup.tsx +1 -5
  46. package/src/components/CreateMappingQuerySetup.tsx +1 -5
  47. package/src/components/QueryEditor.tsx +332 -73
  48. package/src/components/QuerySetup.tsx +17 -5
  49. package/src/index.ts +1 -1
  50. package/src/stores/LegendQueryApplicationPlugin.ts +22 -5
  51. package/src/stores/QueryEditorStore.ts +315 -31
  52. package/tsconfig.json +1 -0
@@ -140,14 +140,14 @@ export const createViewSDLCProjectHandler =
140
140
  }
141
141
  };
142
142
 
143
- export interface QueryExportConfiguration {
143
+ export interface QueryPersistConfiguration {
144
144
  defaultName?: string | undefined;
145
145
  allowUpdate?: boolean | undefined;
146
146
  onQueryUpdate?: ((query: Query) => void) | undefined;
147
147
  decorator: ((query: Query) => void) | undefined;
148
148
  }
149
149
 
150
- export class QueryExportState {
150
+ export class QuerySaveAsState {
151
151
  editorStore: QueryEditorStore;
152
152
  lambda: RawLambda;
153
153
  queryName: string;
@@ -155,18 +155,19 @@ export class QueryExportState {
155
155
  onQueryUpdate?: ((query: Query) => void) | undefined;
156
156
  decorator?: ((query: Query) => void) | undefined;
157
157
  queryBuilderState: QueryBuilderState;
158
- persistQueryState = ActionState.create();
158
+ createQueryState = ActionState.create();
159
159
 
160
160
  constructor(
161
161
  editorStore: QueryEditorStore,
162
162
  queryBuilderState: QueryBuilderState,
163
163
  lambda: RawLambda,
164
- config: QueryExportConfiguration,
164
+ config: QueryPersistConfiguration,
165
165
  ) {
166
166
  makeObservable(this, {
167
167
  queryName: observable,
168
168
  allowPersist: computed,
169
169
  setQueryName: action,
170
+ createQuery: flow,
170
171
  });
171
172
 
172
173
  this.editorStore = editorStore;
@@ -184,13 +185,13 @@ export class QueryExportState {
184
185
 
185
186
  get allowPersist(): boolean {
186
187
  return (
187
- !this.persistQueryState.isInProgress &&
188
+ !this.createQueryState.isInProgress &&
188
189
  Boolean(this.queryBuilderState.mapping) &&
189
190
  this.queryBuilderState.runtimeValue instanceof RuntimePointer
190
191
  );
191
192
  }
192
193
 
193
- async persistQuery(createNew: boolean): Promise<void> {
194
+ *createQuery(createNew: boolean): GeneratorFn<void> {
194
195
  if (
195
196
  this.editorStore.isSaveActionDisabled ||
196
197
  !this.queryBuilderState.mapping ||
@@ -198,7 +199,7 @@ export class QueryExportState {
198
199
  ) {
199
200
  return;
200
201
  }
201
- this.persistQueryState.inProgress();
202
+ this.createQueryState.inProgress();
202
203
  const query = new Query();
203
204
  query.name = this.queryName;
204
205
  query.mapping = PackageableElementExplicitReference.create(
@@ -208,9 +209,9 @@ export class QueryExportState {
208
209
  this.decorator?.(query);
209
210
  try {
210
211
  query.content =
211
- await this.editorStore.graphManagerState.graphManager.lambdaToPureCode(
212
+ (yield this.editorStore.graphManagerState.graphManager.lambdaToPureCode(
212
213
  this.lambda,
213
- );
214
+ )) as string;
214
215
  } catch (error) {
215
216
  assertErrorThrown(error);
216
217
  this.editorStore.applicationStore.logService.error(
@@ -218,7 +219,7 @@ export class QueryExportState {
218
219
  error,
219
220
  );
220
221
  this.editorStore.applicationStore.notificationService.notifyError(error);
221
- this.persistQueryState.reset();
222
+ this.createQueryState.reset();
222
223
  return;
223
224
  }
224
225
 
@@ -226,10 +227,10 @@ export class QueryExportState {
226
227
  if (createNew) {
227
228
  query.id = uuid();
228
229
  const newQuery =
229
- await this.editorStore.graphManagerState.graphManager.createQuery(
230
+ (yield this.editorStore.graphManagerState.graphManager.createQuery(
230
231
  query,
231
232
  this.editorStore.graphManagerState.graph,
232
- );
233
+ )) as Query;
233
234
  this.editorStore.applicationStore.notificationService.notifySuccess(
234
235
  `Successfully created query!`,
235
236
  );
@@ -255,15 +256,17 @@ export class QueryExportState {
255
256
  this.queryBuilderState.changeDetectionState.initialize(this.lambda);
256
257
  // turn off change detection at this point
257
258
  // TODO: to make performance better, refrain from refreshing like this
259
+ this.editorStore.setTitle(query.name);
258
260
  this.editorStore.applicationStore.navigationService.navigator.goToLocation(
259
261
  generateExistingQueryEditorRoute(newQuery.id),
260
262
  );
261
263
  } else {
262
264
  const updatedQuery =
263
- await this.editorStore.graphManagerState.graphManager.updateQuery(
265
+ (yield this.editorStore.graphManagerState.graphManager.updateQuery(
264
266
  query,
265
267
  this.editorStore.graphManagerState.graph,
266
- );
268
+ )) as Query;
269
+ this.editorStore.setTitle(updatedQuery.name);
267
270
  this.editorStore.applicationStore.notificationService.notifySuccess(
268
271
  `Successfully updated query!`,
269
272
  );
@@ -291,8 +294,220 @@ export class QueryExportState {
291
294
  );
292
295
  this.editorStore.applicationStore.notificationService.notifyError(error);
293
296
  } finally {
294
- this.persistQueryState.reset();
295
- this.editorStore.setExportState(undefined);
297
+ this.createQueryState.reset();
298
+ this.editorStore.setSaveAsState(undefined);
299
+ }
300
+ }
301
+ }
302
+
303
+ export class QuerySaveState {
304
+ editorStore: QueryEditorStore;
305
+ lambda: RawLambda;
306
+ queryName: string;
307
+ allowUpdate = false;
308
+ onQueryUpdate?: ((query: Query) => void) | undefined;
309
+ decorator?: ((query: Query) => void) | undefined;
310
+ queryBuilderState: QueryBuilderState;
311
+ saveQueryState = ActionState.create();
312
+
313
+ constructor(
314
+ editorStore: QueryEditorStore,
315
+ queryBuilderState: QueryBuilderState,
316
+ lambda: RawLambda,
317
+ config: QueryPersistConfiguration,
318
+ ) {
319
+ makeObservable(this, {
320
+ queryName: observable,
321
+ allowPersist: computed,
322
+ saveQuery: flow,
323
+ });
324
+
325
+ this.editorStore = editorStore;
326
+ this.queryBuilderState = queryBuilderState;
327
+ this.lambda = lambda;
328
+ this.allowUpdate = config.allowUpdate ?? false;
329
+ this.queryName = config.defaultName ?? 'New Query';
330
+ this.decorator = config.decorator;
331
+ this.onQueryUpdate = config.onQueryUpdate;
332
+ }
333
+
334
+ get allowPersist(): boolean {
335
+ return (
336
+ !this.saveQueryState.isInProgress &&
337
+ Boolean(this.queryBuilderState.mapping) &&
338
+ this.queryBuilderState.runtimeValue instanceof RuntimePointer
339
+ );
340
+ }
341
+
342
+ *saveQuery(): GeneratorFn<void> {
343
+ if (
344
+ this.editorStore.isSaveActionDisabled ||
345
+ !this.queryBuilderState.mapping ||
346
+ !(this.queryBuilderState.runtimeValue instanceof RuntimePointer)
347
+ ) {
348
+ return;
349
+ }
350
+ this.saveQueryState.inProgress();
351
+ const query = new Query();
352
+ query.name = this.queryName;
353
+ query.mapping = PackageableElementExplicitReference.create(
354
+ this.queryBuilderState.mapping,
355
+ );
356
+ query.runtime = this.queryBuilderState.runtimeValue.packageableRuntime;
357
+ this.decorator?.(query);
358
+ try {
359
+ query.content =
360
+ (yield this.editorStore.graphManagerState.graphManager.lambdaToPureCode(
361
+ this.lambda,
362
+ )) as string;
363
+ } catch (error) {
364
+ assertErrorThrown(error);
365
+ this.editorStore.applicationStore.logService.error(
366
+ LogEvent.create(LEGEND_QUERY_APP_EVENT.GENERIC_FAILURE),
367
+ error,
368
+ );
369
+ this.editorStore.applicationStore.notificationService.notifyError(error);
370
+ this.saveQueryState.reset();
371
+ return;
372
+ }
373
+
374
+ try {
375
+ const updatedQuery =
376
+ (yield this.editorStore.graphManagerState.graphManager.updateQuery(
377
+ query,
378
+ this.editorStore.graphManagerState.graph,
379
+ )) as Query;
380
+ this.editorStore.applicationStore.notificationService.notifySuccess(
381
+ `Successfully updated query!`,
382
+ );
383
+
384
+ LegendQueryTelemetryHelper.logEvent_UpdateQuerySucceeded(
385
+ this.editorStore.applicationStore.telemetryService,
386
+ {
387
+ query: {
388
+ id: query.id,
389
+ name: query.name,
390
+ groupId: query.groupId,
391
+ artifactId: query.artifactId,
392
+ versionId: query.versionId,
393
+ },
394
+ },
395
+ );
396
+ this.onQueryUpdate?.(updatedQuery);
397
+ } catch (error) {
398
+ assertErrorThrown(error);
399
+ this.editorStore.applicationStore.logService.error(
400
+ LogEvent.create(LEGEND_QUERY_APP_EVENT.GENERIC_FAILURE),
401
+ error,
402
+ );
403
+ this.editorStore.applicationStore.notificationService.notifyError(error);
404
+ } finally {
405
+ this.saveQueryState.reset();
406
+ this.editorStore.setSaveState(undefined);
407
+ }
408
+ }
409
+ }
410
+
411
+ export class QueryRenameState {
412
+ editorStore: QueryEditorStore;
413
+ lambda: RawLambda;
414
+ queryName: string;
415
+ allowUpdate = false;
416
+ onQueryUpdate?: ((query: Query) => void) | undefined;
417
+ decorator?: ((query: Query) => void) | undefined;
418
+ queryBuilderState: QueryBuilderState;
419
+ saveQueryState = ActionState.create();
420
+
421
+ constructor(
422
+ editorStore: QueryEditorStore,
423
+ queryBuilderState: QueryBuilderState,
424
+ lambda: RawLambda,
425
+ config: QueryPersistConfiguration,
426
+ ) {
427
+ makeObservable(this, {
428
+ queryName: observable,
429
+ setQueryName: action,
430
+ renameQuery: flow,
431
+ });
432
+
433
+ this.editorStore = editorStore;
434
+ this.queryBuilderState = queryBuilderState;
435
+ this.lambda = lambda;
436
+ this.allowUpdate = config.allowUpdate ?? false;
437
+ this.queryName = config.defaultName ?? 'New Query';
438
+ this.decorator = config.decorator;
439
+ this.onQueryUpdate = config.onQueryUpdate;
440
+ }
441
+
442
+ setQueryName(val: string): void {
443
+ this.queryName = val;
444
+ }
445
+
446
+ *renameQuery(): GeneratorFn<void> {
447
+ if (
448
+ this.editorStore.isSaveActionDisabled ||
449
+ !this.queryBuilderState.mapping ||
450
+ !(this.queryBuilderState.runtimeValue instanceof RuntimePointer)
451
+ ) {
452
+ return;
453
+ }
454
+ this.saveQueryState.inProgress();
455
+ const query = new Query();
456
+ query.name = this.queryName;
457
+ query.mapping = PackageableElementExplicitReference.create(
458
+ this.queryBuilderState.mapping,
459
+ );
460
+ query.runtime = this.queryBuilderState.runtimeValue.packageableRuntime;
461
+ this.decorator?.(query);
462
+ try {
463
+ query.content =
464
+ (yield this.editorStore.graphManagerState.graphManager.lambdaToPureCode(
465
+ this.lambda,
466
+ )) as string;
467
+ } catch (error) {
468
+ assertErrorThrown(error);
469
+ this.editorStore.applicationStore.logService.error(
470
+ LogEvent.create(LEGEND_QUERY_APP_EVENT.GENERIC_FAILURE),
471
+ error,
472
+ );
473
+ this.editorStore.applicationStore.notificationService.notifyError(error);
474
+ this.saveQueryState.reset();
475
+ return;
476
+ }
477
+
478
+ try {
479
+ const updatedQuery =
480
+ (yield this.editorStore.graphManagerState.graphManager.updateQuery(
481
+ query,
482
+ this.editorStore.graphManagerState.graph,
483
+ )) as Query;
484
+ this.editorStore.setTitle(updatedQuery.name);
485
+ this.editorStore.applicationStore.notificationService.notifySuccess(
486
+ `Successfully renamed query!`,
487
+ );
488
+ LegendQueryTelemetryHelper.logEvent_UpdateQuerySucceeded(
489
+ this.editorStore.applicationStore.telemetryService,
490
+ {
491
+ query: {
492
+ id: query.id,
493
+ name: query.name,
494
+ groupId: query.groupId,
495
+ artifactId: query.artifactId,
496
+ versionId: query.versionId,
497
+ },
498
+ },
499
+ );
500
+ this.onQueryUpdate?.(updatedQuery);
501
+ } catch (error) {
502
+ assertErrorThrown(error);
503
+ this.editorStore.applicationStore.logService.error(
504
+ LogEvent.create(LEGEND_QUERY_APP_EVENT.GENERIC_FAILURE),
505
+ error,
506
+ );
507
+ this.editorStore.applicationStore.notificationService.notifyError(error);
508
+ } finally {
509
+ this.saveQueryState.reset();
510
+ this.editorStore.setRenameState(undefined);
296
511
  }
297
512
  }
298
513
  }
@@ -367,19 +582,36 @@ export abstract class QueryEditorStore {
367
582
 
368
583
  readonly initState = ActionState.create();
369
584
  queryBuilderState?: QueryBuilderState | undefined;
370
- exportState?: QueryExportState | undefined;
585
+ saveAsState?: QuerySaveAsState | undefined;
586
+ saveState?: QuerySaveState | undefined;
587
+ renameState?: QueryRenameState | undefined;
588
+
589
+ // if the implementation of QueryEditorStore does not support save
590
+ // saveState = undefined
591
+
371
592
  queryLoaderState: QueryLoaderState;
593
+ title: string | undefined;
594
+ existingQueryName: string | undefined;
372
595
 
373
596
  constructor(
374
597
  applicationStore: LegendQueryApplicationStore,
375
598
  depotServerClient: DepotServerClient,
376
599
  ) {
377
600
  makeObservable(this, {
378
- exportState: observable,
601
+ saveAsState: observable,
379
602
  queryLoaderState: observable,
380
- setExportState: action,
603
+ renameState: observable,
604
+ saveState: observable,
605
+ existingQueryName: observable,
606
+ title: observable,
607
+ setRenameState: action,
608
+ setExistingQueryName: action,
609
+ setSaveAsState: action,
610
+ setSaveState: action,
611
+ setTitle: action,
381
612
  initialize: flow,
382
613
  buildGraph: flow,
614
+ searchExistingQueryName: flow,
383
615
  });
384
616
 
385
617
  this.applicationStore = applicationStore;
@@ -400,8 +632,25 @@ export abstract class QueryEditorStore {
400
632
  return false;
401
633
  }
402
634
 
403
- setExportState(val: QueryExportState | undefined): void {
404
- this.exportState = val;
635
+ setTitle(val: string | undefined): void {
636
+ document.title = `${val} - Legend Query`;
637
+ this.title = val;
638
+ }
639
+
640
+ setSaveAsState(val: QuerySaveAsState | undefined): void {
641
+ this.saveAsState = val;
642
+ }
643
+
644
+ setSaveState(val: QuerySaveState | undefined): void {
645
+ this.saveState = val;
646
+ }
647
+
648
+ setRenameState(val: QueryRenameState | undefined): void {
649
+ this.renameState = val;
650
+ }
651
+
652
+ setExistingQueryName(val: string | undefined): void {
653
+ this.existingQueryName = val;
405
654
  }
406
655
 
407
656
  abstract getProjectInfo(): ProjectGAVCoordinates;
@@ -417,9 +666,11 @@ export abstract class QueryEditorStore {
417
666
  * Set up the query builder state after building the graph
418
667
  */
419
668
  protected abstract initializeQueryBuilderState(): Promise<QueryBuilderState>;
669
+
420
670
  abstract getExportConfiguration(
421
671
  lambda: RawLambda,
422
- ): Promise<QueryExportConfiguration>;
672
+ options?: { update?: boolean | undefined },
673
+ ): Promise<QueryPersistConfiguration>;
423
674
 
424
675
  *initialize(): GeneratorFn<void> {
425
676
  if (!this.initState.isInInitialState) {
@@ -465,6 +716,30 @@ export abstract class QueryEditorStore {
465
716
  }
466
717
  }
467
718
 
719
+ *searchExistingQueryName(searchText: string): GeneratorFn<void> {
720
+ const isValidSearchString =
721
+ searchText.length >= DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH;
722
+ try {
723
+ const searchSpecification = new QuerySearchSpecification();
724
+ searchSpecification.searchTerm = isValidSearchString
725
+ ? searchText
726
+ : undefined;
727
+ searchSpecification.limit = 1;
728
+ const queries = (yield this.graphManagerState.graphManager.searchQueries(
729
+ searchSpecification,
730
+ )) as LightQuery[];
731
+
732
+ if (queries.length > 0 && queries[0]?.name === searchText) {
733
+ this.setExistingQueryName(queries[0]?.name);
734
+ } else {
735
+ this.setExistingQueryName(undefined);
736
+ }
737
+ } catch (error) {
738
+ assertErrorThrown(error);
739
+ this.applicationStore.notificationService.notifyError(error);
740
+ }
741
+ }
742
+
468
743
  *buildGraph(): GeneratorFn<void> {
469
744
  const stopWatch = new StopWatch();
470
745
 
@@ -634,7 +909,7 @@ export class MappingQueryCreatorStore extends QueryEditorStore {
634
909
  return queryBuilderState;
635
910
  }
636
911
 
637
- async getExportConfiguration(): Promise<QueryExportConfiguration> {
912
+ async getExportConfiguration(): Promise<QueryPersistConfiguration> {
638
913
  return {
639
914
  decorator: (query: Query): void => {
640
915
  query.id = uuid();
@@ -722,11 +997,16 @@ export class ServiceQueryCreatorStore extends QueryEditorStore {
722
997
  return queryBuilderState;
723
998
  }
724
999
 
725
- async getExportConfiguration(): Promise<QueryExportConfiguration> {
1000
+ async getExportConfiguration(
1001
+ lambda: RawLambda,
1002
+ options?: { update?: boolean | undefined },
1003
+ ): Promise<QueryPersistConfiguration> {
726
1004
  return {
727
- defaultName: `New Query for ${extractElementNameFromPath(
728
- this.servicePath,
729
- )}${this.executionKey ? `[${this.executionKey}]` : ''}`,
1005
+ defaultName: options?.update
1006
+ ? `${extractElementNameFromPath(this.servicePath)}`
1007
+ : `New Query for ${extractElementNameFromPath(this.servicePath)}${
1008
+ this.executionKey ? `[${this.executionKey}]` : ''
1009
+ }`,
730
1010
  decorator: (query: Query): void => {
731
1011
  query.id = uuid();
732
1012
  query.groupId = this.groupId;
@@ -827,14 +1107,18 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
827
1107
  },
828
1108
  },
829
1109
  );
830
-
831
- queryBuilderState.setTitleOfQuery(this.query.name);
1110
+ this.setTitle(this.query.name);
832
1111
  return queryBuilderState;
833
1112
  }
834
1113
 
835
- async getExportConfiguration(): Promise<QueryExportConfiguration> {
1114
+ async getExportConfiguration(
1115
+ lambda: RawLambda,
1116
+ options?: { update?: boolean | undefined },
1117
+ ): Promise<QueryPersistConfiguration> {
836
1118
  return {
837
- defaultName: `New query created from '${this.query.name}'`,
1119
+ defaultName: options?.update
1120
+ ? `${this.query.name}`
1121
+ : `Copy of ${this.query.name}`,
838
1122
  allowUpdate: this.query.isCurrentUserQuery,
839
1123
  decorator: (query: Query): void => {
840
1124
  query.id = this.query.id;
package/tsconfig.json CHANGED
@@ -39,6 +39,7 @@
39
39
  "./src/__lib__/LegendQueryNavigation.ts",
40
40
  "./src/__lib__/LegendQueryTelemetryHelper.ts",
41
41
  "./src/application/LegendQueryApplicationConfig.ts",
42
+ "./src/application/LegendQueryDocumentation.ts",
42
43
  "./src/application/LegendQueryPluginManager.ts",
43
44
  "./src/stores/CloneServiceQuerySetupStore.ts",
44
45
  "./src/stores/CreateMappingQuerySetupStore.ts",