@finos/legend-application-query 13.4.15 → 13.4.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. package/lib/__lib__/LegendQueryEvent.d.ts +2 -1
  2. package/lib/__lib__/LegendQueryEvent.d.ts.map +1 -1
  3. package/lib/__lib__/LegendQueryEvent.js +1 -0
  4. package/lib/__lib__/LegendQueryEvent.js.map +1 -1
  5. package/lib/__lib__/LegendQueryUserDataHelper.d.ts +23 -3
  6. package/lib/__lib__/LegendQueryUserDataHelper.d.ts.map +1 -1
  7. package/lib/__lib__/LegendQueryUserDataHelper.js +94 -14
  8. package/lib/__lib__/LegendQueryUserDataHelper.js.map +1 -1
  9. package/lib/__lib__/LegendQueryUserDataSpaceHelper.d.ts +31 -0
  10. package/lib/__lib__/LegendQueryUserDataSpaceHelper.d.ts.map +1 -0
  11. package/lib/__lib__/LegendQueryUserDataSpaceHelper.js +54 -0
  12. package/lib/__lib__/LegendQueryUserDataSpaceHelper.js.map +1 -0
  13. package/lib/components/CloneQueryServiceSetup.js +1 -2
  14. package/lib/components/CloneQueryServiceSetup.js.map +1 -1
  15. package/lib/components/Core_LegendQueryApplicationPlugin.d.ts +1 -1
  16. package/lib/components/Core_LegendQueryApplicationPlugin.d.ts.map +1 -1
  17. package/lib/components/Core_LegendQueryApplicationPlugin.js +58 -16
  18. package/lib/components/Core_LegendQueryApplicationPlugin.js.map +1 -1
  19. package/lib/components/CreateMappingQuerySetup.js +1 -2
  20. package/lib/components/CreateMappingQuerySetup.js.map +1 -1
  21. package/lib/components/LegendQueryAppInfo.d.ts +21 -0
  22. package/lib/components/LegendQueryAppInfo.d.ts.map +1 -0
  23. package/lib/components/LegendQueryAppInfo.js +46 -0
  24. package/lib/components/LegendQueryAppInfo.js.map +1 -0
  25. package/lib/components/QueryEditor.d.ts.map +1 -1
  26. package/lib/components/QueryEditor.js +9 -8
  27. package/lib/components/QueryEditor.js.map +1 -1
  28. package/lib/components/QueryEdtiorExistingQueryVersionRevertModal.js +1 -1
  29. package/lib/components/QueryEdtiorExistingQueryVersionRevertModal.js.map +1 -1
  30. package/lib/components/data-space/DataSpaceQuerySetup.js +1 -1
  31. package/lib/components/data-space/DataSpaceQuerySetup.js.map +1 -1
  32. package/lib/index.css +2 -2
  33. package/lib/index.css.map +1 -1
  34. package/lib/package.json +3 -3
  35. package/lib/stores/QueryEditorStore.d.ts +3 -0
  36. package/lib/stores/QueryEditorStore.d.ts.map +1 -1
  37. package/lib/stores/QueryEditorStore.js +13 -1
  38. package/lib/stores/QueryEditorStore.js.map +1 -1
  39. package/lib/stores/data-space/DataSpaceQueryCreatorStore.d.ts +2 -0
  40. package/lib/stores/data-space/DataSpaceQueryCreatorStore.d.ts.map +1 -1
  41. package/lib/stores/data-space/DataSpaceQueryCreatorStore.js +21 -2
  42. package/lib/stores/data-space/DataSpaceQueryCreatorStore.js.map +1 -1
  43. package/lib/stores/data-space/DataSpaceQuerySetupState.d.ts +10 -2
  44. package/lib/stores/data-space/DataSpaceQuerySetupState.d.ts.map +1 -1
  45. package/lib/stores/data-space/DataSpaceQuerySetupState.js +53 -3
  46. package/lib/stores/data-space/DataSpaceQuerySetupState.js.map +1 -1
  47. package/package.json +13 -13
  48. package/src/__lib__/LegendQueryEvent.ts +2 -0
  49. package/src/__lib__/LegendQueryUserDataHelper.ts +192 -18
  50. package/src/__lib__/LegendQueryUserDataSpaceHelper.ts +98 -0
  51. package/src/components/CloneQueryServiceSetup.tsx +1 -1
  52. package/src/components/Core_LegendQueryApplicationPlugin.tsx +89 -41
  53. package/src/components/CreateMappingQuerySetup.tsx +1 -1
  54. package/src/components/LegendQueryAppInfo.tsx +153 -0
  55. package/src/components/QueryEditor.tsx +15 -11
  56. package/src/components/QueryEdtiorExistingQueryVersionRevertModal.tsx +1 -1
  57. package/src/components/data-space/DataSpaceQuerySetup.tsx +1 -1
  58. package/src/stores/QueryEditorStore.ts +19 -0
  59. package/src/stores/data-space/DataSpaceQueryCreatorStore.ts +59 -0
  60. package/src/stores/data-space/DataSpaceQuerySetupState.ts +92 -4
  61. package/tsconfig.json +2 -0
@@ -16,22 +16,38 @@
16
16
 
17
17
  import type { UserDataService } from '@finos/legend-application';
18
18
  import { returnUndefOnError } from '@finos/legend-shared';
19
- import { createSimpleSchema, deserialize, list, primitive } from 'serializr';
19
+ import {
20
+ createSimpleSchema,
21
+ deserialize,
22
+ list,
23
+ primitive,
24
+ raw,
25
+ } from 'serializr';
26
+ import {
27
+ createVisitedDataspaceFromInfo,
28
+ createIdFromDataSpaceInfo,
29
+ createVisitedDataSpaceId,
30
+ type SavedVisitedDataSpaces,
31
+ type VisitedDataspace,
32
+ } from './LegendQueryUserDataSpaceHelper.js';
33
+ import type { DataSpaceInfo } from '@finos/legend-extension-dsl-data-space/application';
20
34
 
21
35
  export enum LEGEND_QUERY_USER_DATA_KEY {
22
36
  RECENTLY_VIEWED_QUERIES = 'query-editor.recent-queries',
37
+ RECENTLY_VIEWED_DATASPACES = 'query-editor.recent-dataSpaces',
23
38
  }
24
39
 
25
- const USER_DATA_RECENTLY_VIEWED_QUERIES_LIMIT = 10;
26
- type RecentlyViewedQueriesData = string[];
40
+ export const USER_DATA_RECENTLY_VIEWED_QUERIES_LIMIT = 10;
41
+ export const USER_DATA_QUERY_DATASPACE_LIMIT = 10;
42
+
43
+ type SavedData = string[];
27
44
 
28
45
  export class LegendQueryUserDataHelper {
29
- static getRecentlyViewedQueries(
46
+ static getPersistedData(
30
47
  service: UserDataService,
31
- ): RecentlyViewedQueriesData {
32
- const data = service.getObjectValue(
33
- LEGEND_QUERY_USER_DATA_KEY.RECENTLY_VIEWED_QUERIES,
34
- );
48
+ key: LEGEND_QUERY_USER_DATA_KEY,
49
+ ): SavedData {
50
+ const data = service.getObjectValue(key);
35
51
  return (
36
52
  // TODO: think of a better way to deserialize this data, maybe like settings, use JSON schema
37
53
  // See https://github.com/finos/legend-studio/issues/407
@@ -45,12 +61,41 @@ export class LegendQueryUserDataHelper {
45
61
  {
46
62
  data,
47
63
  },
48
- ) as { data: RecentlyViewedQueriesData }
64
+ ) as { data: SavedData }
49
65
  ).data,
50
66
  ) ?? []
51
67
  );
52
68
  }
53
69
 
70
+ static persistValue(
71
+ service: UserDataService,
72
+ value: string,
73
+ persistedData: SavedData,
74
+ opts: {
75
+ key: LEGEND_QUERY_USER_DATA_KEY;
76
+ limit: number;
77
+ },
78
+ ): void {
79
+ const idx = persistedData.findIndex((data) => data === value);
80
+ if (idx === -1) {
81
+ if (persistedData.length >= opts.limit) {
82
+ persistedData.pop();
83
+ }
84
+ persistedData.unshift(value);
85
+ } else {
86
+ persistedData.splice(idx, 1);
87
+ persistedData.unshift(value);
88
+ }
89
+ service.persistValue(opts.key, persistedData);
90
+ }
91
+
92
+ static getRecentlyViewedQueries(service: UserDataService): SavedData {
93
+ return LegendQueryUserDataHelper.getPersistedData(
94
+ service,
95
+ LEGEND_QUERY_USER_DATA_KEY.RECENTLY_VIEWED_QUERIES,
96
+ );
97
+ }
98
+
54
99
  static removeRecentlyViewedQueries(service: UserDataService): void {
55
100
  service.persistValue(
56
101
  LEGEND_QUERY_USER_DATA_KEY.RECENTLY_VIEWED_QUERIES,
@@ -79,21 +124,150 @@ export class LegendQueryUserDataHelper {
79
124
  queryId: string,
80
125
  ): void {
81
126
  const queries = LegendQueryUserDataHelper.getRecentlyViewedQueries(service);
82
- const idx = queries.findIndex((query) => query === queryId);
127
+ LegendQueryUserDataHelper.persistValue(service, queryId, queries, {
128
+ limit: USER_DATA_RECENTLY_VIEWED_QUERIES_LIMIT,
129
+ key: LEGEND_QUERY_USER_DATA_KEY.RECENTLY_VIEWED_QUERIES,
130
+ });
131
+ }
132
+ // DataSpaces
133
+ static getRecentlyVisitedDataSpaces(
134
+ service: UserDataService,
135
+ ): SavedVisitedDataSpaces {
136
+ const data = service.getObjectValue(
137
+ LEGEND_QUERY_USER_DATA_KEY.RECENTLY_VIEWED_DATASPACES,
138
+ );
139
+ return (
140
+ // TODO: think of a better way to deserialize this data, maybe like settings, use JSON schema
141
+ // See https://github.com/finos/legend-studio/issues/407
142
+ returnUndefOnError(
143
+ () =>
144
+ (
145
+ deserialize(
146
+ createSimpleSchema({
147
+ data: raw(),
148
+ }),
149
+ {
150
+ data,
151
+ },
152
+ ) as { data: SavedVisitedDataSpaces }
153
+ ).data,
154
+ ) ?? []
155
+ );
156
+ }
157
+
158
+ static findRecentlyVisitedDataSpace(
159
+ service: UserDataService,
160
+ id: string,
161
+ ): VisitedDataspace | undefined {
162
+ return LegendQueryUserDataHelper.getRecentlyVisitedDataSpaces(service).find(
163
+ (v) => v.id === id,
164
+ );
165
+ }
166
+
167
+ static getRecentlyVisitedDataSpace(
168
+ service: UserDataService,
169
+ ): VisitedDataspace | undefined {
170
+ return LegendQueryUserDataHelper.getRecentlyVisitedDataSpaces(service)[0];
171
+ }
172
+
173
+ static persistVisitedDataspace(
174
+ service: UserDataService,
175
+ value: VisitedDataspace,
176
+ persistedData: SavedVisitedDataSpaces,
177
+ limit = USER_DATA_QUERY_DATASPACE_LIMIT,
178
+ ): void {
179
+ const key = LEGEND_QUERY_USER_DATA_KEY.RECENTLY_VIEWED_DATASPACES;
180
+ const idx = persistedData.findIndex((data) => data.id === value.id);
83
181
  if (idx === -1) {
84
- if (queries.length < USER_DATA_RECENTLY_VIEWED_QUERIES_LIMIT) {
85
- queries.unshift(queryId);
86
- } else {
87
- queries.pop();
88
- queries.unshift(queryId);
182
+ if (persistedData.length >= limit) {
183
+ persistedData.pop();
89
184
  }
185
+ persistedData.unshift(value);
90
186
  } else {
91
- queries.splice(idx, 1);
92
- queries.unshift(queryId);
187
+ persistedData.splice(idx, 1);
188
+ persistedData.unshift(value);
93
189
  }
190
+ service.persistValue(key, persistedData);
191
+ }
192
+
193
+ static removeRecentlyViewedDataSpaces(service: UserDataService): void {
194
+ service.persistValue(
195
+ LEGEND_QUERY_USER_DATA_KEY.RECENTLY_VIEWED_DATASPACES,
196
+ [],
197
+ );
198
+ }
199
+
200
+ static removeRecentlyViewedDataSpace(
201
+ service: UserDataService,
202
+ id: string,
203
+ ): void {
204
+ const dataSpaces =
205
+ LegendQueryUserDataHelper.getRecentlyVisitedDataSpaces(service);
206
+ const idx = dataSpaces.findIndex(
207
+ (visitedDataspace) => visitedDataspace.id === id,
208
+ );
209
+ if (idx === -1) {
210
+ return;
211
+ }
212
+ dataSpaces.splice(idx, 1);
94
213
  service.persistValue(
95
214
  LEGEND_QUERY_USER_DATA_KEY.RECENTLY_VIEWED_QUERIES,
96
- queries,
215
+ dataSpaces,
97
216
  );
98
217
  }
218
+
219
+ static removeDataSpace(service: UserDataService, info: DataSpaceInfo): void {
220
+ const id = createIdFromDataSpaceInfo(info);
221
+ if (id) {
222
+ LegendQueryUserDataHelper.removeRecentlyViewedDataSpace(service, id);
223
+ }
224
+ }
225
+
226
+ static addRecentlyVistedDatspace(
227
+ service: UserDataService,
228
+ info: DataSpaceInfo,
229
+ execContext: string | undefined,
230
+ ): void {
231
+ const visited = createVisitedDataspaceFromInfo(info, execContext);
232
+ if (visited) {
233
+ const dataspaces =
234
+ LegendQueryUserDataHelper.getRecentlyVisitedDataSpaces(service);
235
+ LegendQueryUserDataHelper.persistVisitedDataspace(
236
+ service,
237
+ visited,
238
+ dataspaces,
239
+ );
240
+ }
241
+ }
242
+ static addVisitedDatspace(
243
+ service: UserDataService,
244
+ visited: VisitedDataspace,
245
+ ): void {
246
+ const dataspaces =
247
+ LegendQueryUserDataHelper.getRecentlyVisitedDataSpaces(service);
248
+ LegendQueryUserDataHelper.persistVisitedDataspace(
249
+ service,
250
+ visited,
251
+ dataspaces,
252
+ );
253
+ }
254
+
255
+ static updateVisitedDataSpaceExecContext(
256
+ service: UserDataService,
257
+ groupId: string,
258
+ artifactId: string,
259
+ dataspace: string,
260
+ exec: string,
261
+ ): boolean {
262
+ const visited = LegendQueryUserDataHelper.findRecentlyVisitedDataSpace(
263
+ service,
264
+ createVisitedDataSpaceId(groupId, artifactId, dataspace),
265
+ );
266
+ if (visited) {
267
+ visited.execContext = exec;
268
+ LegendQueryUserDataHelper.addVisitedDatspace(service, visited);
269
+ return true;
270
+ }
271
+ return false;
272
+ }
99
273
  }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import type { DataSpaceInfo } from '@finos/legend-extension-dsl-data-space/application';
18
+ import { GAV_DELIMITER, generateGAVCoordinates } from '@finos/legend-storage';
19
+
20
+ export interface VisitedDataspace {
21
+ id: string;
22
+ groupId: string;
23
+ artifactId: string;
24
+ path: string;
25
+ versionId: string | undefined;
26
+ execContext?: string | undefined;
27
+ }
28
+
29
+ export type SavedVisitedDataSpaces = VisitedDataspace[];
30
+
31
+ export const createVisitedDataSpaceId = (
32
+ groupId: string,
33
+ artifactId: string,
34
+ dataSpace: string,
35
+ ): string =>
36
+ // we will consider unique dataSpace if it belongs to the same project. i.e we will not save 2 dataspaces visited for 2 different versionss
37
+ generateGAVCoordinates(groupId, artifactId, undefined) +
38
+ GAV_DELIMITER +
39
+ dataSpace;
40
+
41
+ export const createIdFromDataSpaceInfo = (
42
+ info: DataSpaceInfo,
43
+ ): string | undefined => {
44
+ const groupId = info.groupId;
45
+ const artifactId = info.artifactId;
46
+ if (groupId && artifactId) {
47
+ return createVisitedDataSpaceId(groupId, artifactId, info.path);
48
+ }
49
+ return undefined;
50
+ };
51
+
52
+ export const createSimpleVisitedDataspace = (
53
+ groupId: string,
54
+ artifactId: string,
55
+ versionId: string | undefined,
56
+ path: string,
57
+ exec: string | undefined,
58
+ ): VisitedDataspace => ({
59
+ id: createVisitedDataSpaceId(groupId, artifactId, path),
60
+ groupId,
61
+ artifactId,
62
+ versionId,
63
+ path,
64
+ execContext: exec,
65
+ });
66
+
67
+ export const createVisitedDataspaceFromInfo = (
68
+ info: DataSpaceInfo,
69
+ execContext: string | undefined,
70
+ ): VisitedDataspace | undefined => {
71
+ const groupId = info.groupId;
72
+ const artifactId = info.artifactId;
73
+ const versionId = info.versionId;
74
+ const path = info.path;
75
+ if (groupId && artifactId) {
76
+ return createSimpleVisitedDataspace(
77
+ groupId,
78
+ artifactId,
79
+ versionId,
80
+ path,
81
+ execContext,
82
+ );
83
+ }
84
+ return undefined;
85
+ };
86
+
87
+ export const hasDataSpaceInfoBeenVisited = (
88
+ val: DataSpaceInfo,
89
+ visited: SavedVisitedDataSpaces,
90
+ ): boolean =>
91
+ Boolean(
92
+ visited.find((_visit) => {
93
+ if (_visit.id === createIdFromDataSpaceInfo(val)) {
94
+ return true;
95
+ }
96
+ return false;
97
+ }),
98
+ );
@@ -27,6 +27,7 @@ import {
27
27
  assertErrorThrown,
28
28
  guaranteeNonNullable,
29
29
  guaranteeType,
30
+ compareSemVerVersions,
30
31
  } from '@finos/legend-shared';
31
32
  import { flowResult } from 'mobx';
32
33
  import { observer, useLocalObservable } from 'mobx-react-lite';
@@ -53,7 +54,6 @@ import {
53
54
  type ProjectOption,
54
55
  type VersionOption,
55
56
  } from './QuerySetup.js';
56
- import { compareSemVerVersions } from '@finos/legend-storage';
57
57
 
58
58
  const CloneServiceQuerySetupStoreProvider: React.FC<{
59
59
  children: React.ReactNode;
@@ -50,6 +50,8 @@ import {
50
50
  LEGEND_QUERY_ROUTE_PATTERN,
51
51
  } from '../__lib__/LegendQueryNavigation.js';
52
52
  import {
53
+ ActionAlertActionType,
54
+ ActionAlertType,
53
55
  type ApplicationPageEntry,
54
56
  type LegendApplicationSetup,
55
57
  } from '@finos/legend-application';
@@ -65,14 +67,13 @@ import {
65
67
  generateDataSpaceQueryCreatorRoute,
66
68
  generateDataSpaceQuerySetupRoute,
67
69
  } from '../__lib__/DSL_DataSpace_LegendQueryNavigation.js';
68
- import type {
69
- QueryBuilderHeaderActionConfiguration,
70
- QueryBuilderMenuActionConfiguration,
70
+ import {
71
+ type QueryBuilderHeaderActionConfiguration,
72
+ type QueryBuilderMenuActionConfiguration,
71
73
  } from '@finos/legend-query-builder';
72
74
  import {
73
75
  ExistingQueryEditorStore,
74
76
  QueryBuilderActionConfig_QueryApplication,
75
- createViewProjectHandler,
76
77
  createViewSDLCProjectHandler,
77
78
  } from '../stores/QueryEditorStore.js';
78
79
  import {
@@ -238,6 +239,7 @@ export class Core_LegendQueryApplicationPlugin extends LegendQueryApplicationPlu
238
239
  },
239
240
  ];
240
241
  }
242
+
241
243
  getExtraQueryBuilderExportMenuActionConfigurations?(): QueryBuilderMenuActionConfiguration[] {
242
244
  return [
243
245
  {
@@ -315,6 +317,19 @@ export class Core_LegendQueryApplicationPlugin extends LegendQueryApplicationPlu
315
317
  key: 'about-query-info',
316
318
  title: 'Get Query Info',
317
319
  label: 'About Query Info',
320
+ disableFunc: (queryBuilderState): boolean => {
321
+ if (
322
+ queryBuilderState.workflowState.actionConfig instanceof
323
+ QueryBuilderActionConfig_QueryApplication
324
+ ) {
325
+ const editorStore =
326
+ queryBuilderState.workflowState.actionConfig.editorStore;
327
+ if (editorStore instanceof ExistingQueryEditorStore) {
328
+ return false;
329
+ }
330
+ }
331
+ return true;
332
+ },
318
333
  onClick: (queryBuilderState): void => {
319
334
  if (
320
335
  queryBuilderState.workflowState.actionConfig instanceof
@@ -330,35 +345,22 @@ export class Core_LegendQueryApplicationPlugin extends LegendQueryApplicationPlu
330
345
  icon: <InfoCircleIcon />,
331
346
  },
332
347
  {
333
- key: 'about-query-project',
348
+ key: 'about-query-sdlc-project',
334
349
  title: 'Go to Project',
335
350
  label: 'Go to Project',
336
- onClick: (queryBuilderState): void => {
351
+ disableFunc: (queryBuilderState): boolean => {
337
352
  if (
338
353
  queryBuilderState.workflowState.actionConfig instanceof
339
354
  QueryBuilderActionConfig_QueryApplication
340
355
  ) {
341
356
  const editorStore =
342
357
  queryBuilderState.workflowState.actionConfig.editorStore;
343
- LegendQueryTelemetryHelper.logEvent_QueryViewProjectLaunched(
344
- editorStore.applicationStore.telemetryService,
345
- );
346
- const { groupId, artifactId, versionId } =
347
- editorStore.getProjectInfo();
348
- createViewProjectHandler(editorStore.applicationStore)(
349
- groupId,
350
- artifactId,
351
- versionId,
352
- undefined,
353
- );
358
+ if (editorStore instanceof ExistingQueryEditorStore) {
359
+ return false;
360
+ }
354
361
  }
362
+ return true;
355
363
  },
356
- icon: <InfoCircleIcon />,
357
- },
358
- {
359
- key: 'about-query-sdlc-project',
360
- title: 'Go to SDLC Project',
361
- label: 'Go to SDLC Project',
362
364
  onClick: (queryBuilderState): void => {
363
365
  if (
364
366
  queryBuilderState.workflowState.actionConfig instanceof
@@ -380,6 +382,22 @@ export class Core_LegendQueryApplicationPlugin extends LegendQueryApplicationPlu
380
382
  },
381
383
  icon: <InfoCircleIcon />,
382
384
  },
385
+ {
386
+ key: 'about-legend-query',
387
+ title: 'About Legend Query',
388
+ label: 'About Legend Query',
389
+ onClick: (queryBuilderState): void => {
390
+ if (
391
+ queryBuilderState.workflowState.actionConfig instanceof
392
+ QueryBuilderActionConfig_QueryApplication
393
+ ) {
394
+ const editorStore =
395
+ queryBuilderState.workflowState.actionConfig.editorStore;
396
+ editorStore.setShowAppInfo(true);
397
+ }
398
+ },
399
+ icon: <InfoCircleIcon />,
400
+ },
383
401
  ];
384
402
  }
385
403
 
@@ -425,8 +443,6 @@ export class Core_LegendQueryApplicationPlugin extends LegendQueryApplicationPlu
425
443
  ) {
426
444
  const editorStore =
427
445
  queryBuilderState.workflowState.actionConfig.editorStore;
428
- const isExistingQuery =
429
- editorStore instanceof ExistingQueryEditorStore;
430
446
  const handleNewQuery = (): void => {
431
447
  if (editorStore instanceof ExistingQueryEditorStore) {
432
448
  const query = editorStore.query;
@@ -463,24 +479,50 @@ export class Core_LegendQueryApplicationPlugin extends LegendQueryApplicationPlu
463
479
  }
464
480
  }
465
481
  }
482
+ } else {
483
+ if (
484
+ queryBuilderState.changeHistoryState.canUndo ||
485
+ queryBuilderState.changeHistoryState.canRedo
486
+ ) {
487
+ queryBuilderState.applicationStore.alertService.setActionAlertInfo(
488
+ {
489
+ message:
490
+ 'Current query will be lost when creating a new query. Do you still want to proceed?',
491
+ type: ActionAlertType.CAUTION,
492
+ actions: [
493
+ {
494
+ label: 'Proceed',
495
+ type: ActionAlertActionType.PROCEED_WITH_CAUTION,
496
+ handler:
497
+ queryBuilderState.applicationStore.guardUnhandledError(
498
+ async () => queryBuilderState.resetQueryContent(),
499
+ ),
500
+ },
501
+ {
502
+ label: 'Cancel',
503
+ type: ActionAlertActionType.PROCEED,
504
+ default: true,
505
+ },
506
+ ],
507
+ },
508
+ );
509
+ } else {
510
+ queryBuilderState.resetQueryContent();
511
+ }
466
512
  }
467
513
  };
468
514
  return (
469
- <>
470
- {isExistingQuery && (
471
- <Button
472
- className="query-editor__header__action btn--dark"
473
- disabled={editorStore.isPerformingBlockingAction}
474
- onClick={handleNewQuery}
475
- title="New query"
476
- >
477
- <SaveCurrIcon />
478
- <div className="query-editor__header__action__label">
479
- New Query
480
- </div>
481
- </Button>
482
- )}
483
- </>
515
+ <Button
516
+ className="query-editor__header__action btn--dark"
517
+ disabled={editorStore.isPerformingBlockingAction}
518
+ onClick={handleNewQuery}
519
+ title="New query"
520
+ >
521
+ <SaveCurrIcon />
522
+ <div className="query-editor__header__action__label">
523
+ New Query
524
+ </div>
525
+ </Button>
484
526
  );
485
527
  }
486
528
  return undefined;
@@ -595,7 +637,13 @@ export class Core_LegendQueryApplicationPlugin extends LegendQueryApplicationPlu
595
637
  </div>
596
638
  );
597
639
  }
598
- return undefined;
640
+ return (
641
+ <div className="query-editor__dataspace__header">
642
+ <div className="query-editor__header__content__main query-editor__header__content__title__text query-editor__header__content__title__text--unsaved">
643
+ Unsaved Query
644
+ </div>
645
+ </div>
646
+ );
599
647
  };
600
648
  return (
601
649
  <div className="query-editor__header__content">
@@ -28,6 +28,7 @@ import {
28
28
  getNullableFirstEntry,
29
29
  guaranteeNonNullable,
30
30
  guaranteeType,
31
+ compareSemVerVersions,
31
32
  } from '@finos/legend-shared';
32
33
  import { flowResult } from 'mobx';
33
34
  import { observer, useLocalObservable } from 'mobx-react-lite';
@@ -51,7 +52,6 @@ import {
51
52
  type ProjectOption,
52
53
  type VersionOption,
53
54
  } from './QuerySetup.js';
54
- import { compareSemVerVersions } from '@finos/legend-storage';
55
55
  import type { Mapping, PackageableRuntime } from '@finos/legend-graph';
56
56
  import {
57
57
  buildElementOption,