@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
@@ -0,0 +1,153 @@
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 {
18
+ CopyIcon,
19
+ Dialog,
20
+ InfoCircleIcon,
21
+ Modal,
22
+ ModalBody,
23
+ ModalHeader,
24
+ ModalHeaderActions,
25
+ ModalTitle,
26
+ TimesIcon,
27
+ } from '@finos/legend-art';
28
+ import { isNonNullable } from '@finos/legend-shared';
29
+ import { useQueryEditorStore } from './QueryEditorStoreProvider.js';
30
+
31
+ export const LegendQueryInfo: React.FC<{
32
+ open: boolean;
33
+ closeModal: () => void;
34
+ }> = (props) => {
35
+ const { open, closeModal } = props;
36
+ const editorStore = useQueryEditorStore();
37
+ const applicationStore = editorStore.applicationStore;
38
+ const config = applicationStore.config;
39
+ const copyInfo = (): void => {
40
+ applicationStore.clipboardService
41
+ .copyTextToClipboard(
42
+ [
43
+ `Environment: ${config.env}`,
44
+ `Version: ${config.appVersion}`,
45
+ `Revision: ${config.appVersionCommitId}`,
46
+ `Build Time: ${config.appVersionBuildTime}`,
47
+ `Engine Server: ${config.engineServerUrl}`,
48
+ `Depot Server: ${config.depotServerUrl}`,
49
+ ]
50
+ .filter(isNonNullable)
51
+ .join('\n'),
52
+ )
53
+ .then(() =>
54
+ applicationStore.notificationService.notifySuccess(
55
+ 'Copied application info to clipboard',
56
+ ),
57
+ )
58
+ .catch(applicationStore.alertUnhandledError);
59
+ };
60
+
61
+ const goToReleaseLog = (): void => {
62
+ closeModal();
63
+ applicationStore.releaseNotesService.setReleaseLog(true);
64
+ };
65
+
66
+ return (
67
+ <Dialog onClose={closeModal} open={open}>
68
+ <Modal
69
+ darkMode={
70
+ !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled
71
+ }
72
+ className="modal--scrollable app__info"
73
+ >
74
+ <ModalHeader>
75
+ <ModalTitle icon={<InfoCircleIcon />} title="About Legend Query" />
76
+ <ModalHeaderActions>
77
+ <button
78
+ className="modal__header__action"
79
+ tabIndex={-1}
80
+ onClick={copyInfo}
81
+ title="Copy application info"
82
+ >
83
+ <CopyIcon />
84
+ </button>
85
+ <button
86
+ className="modal__header__action"
87
+ tabIndex={-1}
88
+ onClick={closeModal}
89
+ >
90
+ <TimesIcon />
91
+ </button>
92
+ </ModalHeaderActions>
93
+ </ModalHeader>
94
+ <ModalBody>
95
+ <div className="app__info__entry">
96
+ <div className="app__info__entry__title">Environment:</div>
97
+ <div className="app__info__entry__value">{config.env}</div>
98
+ </div>
99
+ <div className="app__info__entry">
100
+ <div className="app__info__entry__title">Version:</div>
101
+ <div className="app__info__entry__value">{config.appVersion}</div>
102
+ </div>
103
+ <div className="app__info__entry">
104
+ <div className="app__info__entry__title">Revision:</div>
105
+ <div className="app__info__entry__value">
106
+ {config.appVersionCommitId}
107
+ </div>
108
+ </div>
109
+ <div className="app__info__entry">
110
+ <div className="app__info__entry__title">Build Time:</div>
111
+ <div className="app__info__entry__value">
112
+ {config.appVersionBuildTime}
113
+ </div>
114
+ </div>
115
+ <div className="app__info__entry">
116
+ <div
117
+ onClick={goToReleaseLog}
118
+ className="app__info__entry__value app__info__entry__value__action"
119
+ >
120
+ Details of Released Versions
121
+ </div>
122
+ </div>
123
+ <div className="app__info__group">
124
+ <div className="app__info__entry">
125
+ <div className="app__info__entry__title">Engine Server:</div>
126
+ <div className="app__info__entry__value">
127
+ <a
128
+ href={config.engineServerUrl}
129
+ target="_blank"
130
+ rel="noopener noreferrer"
131
+ >
132
+ {config.engineServerUrl}
133
+ </a>
134
+ </div>
135
+ </div>
136
+ <div className="app__info__entry">
137
+ <div className="app__info__entry__title">Depot Server:</div>
138
+ <div className="app__info__entry__value">
139
+ <a
140
+ href={config.depotServerUrl}
141
+ target="_blank"
142
+ rel="noopener noreferrer"
143
+ >
144
+ {config.depotServerUrl}
145
+ </a>
146
+ </div>
147
+ </div>
148
+ </div>
149
+ </ModalBody>
150
+ </Modal>
151
+ </Dialog>
152
+ );
153
+ };
@@ -45,7 +45,7 @@ import {
45
45
  SunIcon,
46
46
  } from '@finos/legend-art';
47
47
  import { observer } from 'mobx-react-lite';
48
- import { Fragment, useEffect, useMemo, useRef, useState } from 'react';
48
+ import { useEffect, useMemo, useRef, useState } from 'react';
49
49
  import {
50
50
  type MappingQueryCreatorPathParams,
51
51
  type ExistingQueryEditorPathParams,
@@ -58,6 +58,8 @@ import {
58
58
  import { ExistingQueryEditorStore } from '../stores/QueryEditorStore.js';
59
59
  import {
60
60
  LEGEND_APPLICATION_COLOR_THEME,
61
+ ReleaseLogManager,
62
+ ReleaseNotesManager,
61
63
  useApplicationStore,
62
64
  } from '@finos/legend-application';
63
65
  import { useParams } from '@finos/legend-application/browser';
@@ -76,10 +78,7 @@ import {
76
78
  type QueryBuilderState,
77
79
  } from '@finos/legend-query-builder';
78
80
 
79
- import {
80
- compareSemVerVersions,
81
- generateGAVCoordinates,
82
- } from '@finos/legend-storage';
81
+ import { generateGAVCoordinates } from '@finos/legend-storage';
83
82
  import {
84
83
  type Query,
85
84
  QueryDataSpaceExecutionContext,
@@ -88,7 +87,8 @@ import {
88
87
  import { LATEST_VERSION_ALIAS } from '@finos/legend-server-depot';
89
88
  import { buildVersionOption, type VersionOption } from './QuerySetup.js';
90
89
  import { QueryEditorExistingQueryVersionRevertModal } from './QueryEdtiorExistingQueryVersionRevertModal.js';
91
- import { debounce } from '@finos/legend-shared';
90
+ import { debounce, compareSemVerVersions } from '@finos/legend-shared';
91
+ import { LegendQueryInfo } from './LegendQueryAppInfo.js';
92
92
 
93
93
  const CreateQueryDialog = observer(() => {
94
94
  const editorStore = useQueryEditorStore();
@@ -588,8 +588,6 @@ export const QueryEditor = observer(() => {
588
588
  generateQuerySetupRoute(),
589
589
  ),
590
590
  );
591
- const goToReleaseLog = (): void =>
592
- applicationStore.releaseNotesService.setReleaseLog(true);
593
591
  // settings
594
592
  // NOTE: this is temporary until we find a better home for these settings in query builder
595
593
  const engineConfig =
@@ -612,6 +610,7 @@ export const QueryEditor = observer(() => {
612
610
  flowResult(editorStore.initialize()).catch(
613
611
  applicationStore.alertUnhandledError,
614
612
  );
613
+ applicationStore.releaseNotesService.updateViewedVersion();
615
614
  }, [editorStore, applicationStore]);
616
615
 
617
616
  return (
@@ -631,9 +630,6 @@ export const QueryEditor = observer(() => {
631
630
  <MenuContentItem onClick={goToQuerySetup}>
632
631
  Back to query setup
633
632
  </MenuContentItem>
634
- <MenuContentItem onClick={goToReleaseLog}>
635
- Legend Query Release Log
636
- </MenuContentItem>
637
633
  <MenuContentItem
638
634
  disabled={!appDocUrl}
639
635
  onClick={goToDocumentation}
@@ -724,6 +720,12 @@ export const QueryEditor = observer(() => {
724
720
  />
725
721
  )}
726
722
  {editorStore.queryCreatorState.showCreateModal && <CreateQueryDialog />}
723
+ {editorStore.showAppInfo && (
724
+ <LegendQueryInfo
725
+ open={editorStore.showAppInfo}
726
+ closeModal={() => editorStore.setShowAppInfo(false)}
727
+ />
728
+ )}
727
729
  {isExistingQuery &&
728
730
  editorStore.updateState.showQueryInfo &&
729
731
  editorStore.query && (
@@ -732,6 +734,8 @@ export const QueryEditor = observer(() => {
732
734
  query={editorStore.query}
733
735
  />
734
736
  )}
737
+ <ReleaseLogManager />
738
+ <ReleaseNotesManager />
735
739
  </div>
736
740
  );
737
741
  });
@@ -23,7 +23,7 @@ import {
23
23
  ModalFooterButton,
24
24
  } from '@finos/legend-art';
25
25
  import { LATEST_VERSION_ALIAS } from '@finos/legend-server-depot';
26
- import { compareSemVerVersions } from '@finos/legend-storage';
26
+ import { compareSemVerVersions } from '@finos/legend-shared';
27
27
  import { flowResult } from 'mobx';
28
28
  import { observer } from 'mobx-react-lite';
29
29
  import { useState, useEffect } from 'react';
@@ -95,7 +95,7 @@ const DataSpaceQuerySetupSetupPanelContent = observer(
95
95
  queryBuilderState.showAdvancedSearchPanel();
96
96
 
97
97
  useEffect(() => {
98
- flowResult(queryBuilderState.loadDataSpaces()).catch(
98
+ flowResult(queryBuilderState.initializeDataSpaceSetup()).catch(
99
99
  applicationStore.alertUnhandledError,
100
100
  );
101
101
  }, [queryBuilderState, applicationStore]);
@@ -123,6 +123,7 @@ import {
123
123
  retrieveAnalyticsResultCache,
124
124
  } from '@finos/legend-extension-dsl-data-space/graph';
125
125
  import { generateDataSpaceQueryCreatorRoute } from '../__lib__/DSL_DataSpace_LegendQueryNavigation.js';
126
+ import { hasDataSpaceInfoBeenVisited } from '../__lib__/LegendQueryUserDataSpaceHelper.js';
126
127
 
127
128
  export const createViewProjectHandler =
128
129
  (applicationStore: LegendQueryApplicationStore) =>
@@ -314,6 +315,7 @@ export abstract class QueryEditorStore {
314
315
  queryCreatorState: QueryCreatorState;
315
316
  existingQueryName: string | undefined;
316
317
  showRegisterServiceModal = false;
318
+ showAppInfo = false;
317
319
 
318
320
  constructor(
319
321
  applicationStore: LegendQueryApplicationStore,
@@ -324,10 +326,12 @@ export abstract class QueryEditorStore {
324
326
  queryLoaderState: observable,
325
327
  existingQueryName: observable,
326
328
  showRegisterServiceModal: observable,
329
+ showAppInfo: observable,
327
330
  queryBuilderState: observable,
328
331
  isPerformingBlockingAction: computed,
329
332
  setExistingQueryName: action,
330
333
  setShowRegisterServiceModal: action,
334
+ setShowAppInfo: action,
331
335
  initialize: flow,
332
336
  buildGraph: flow,
333
337
  searchExistingQueryName: flow,
@@ -405,6 +409,10 @@ export abstract class QueryEditorStore {
405
409
  this.existingQueryName = val;
406
410
  }
407
411
 
412
+ setShowAppInfo(val: boolean): void {
413
+ this.showAppInfo = val;
414
+ }
415
+
408
416
  setShowRegisterServiceModal(val: boolean): void {
409
417
  this.showRegisterServiceModal = val;
410
418
  }
@@ -534,10 +542,15 @@ export abstract class QueryEditorStore {
534
542
  error,
535
543
  );
536
544
  this.applicationStore.notificationService.notifyError(error);
545
+ this.onInitializeFailure();
537
546
  this.initState.fail();
538
547
  }
539
548
  }
540
549
 
550
+ onInitializeFailure(): void {
551
+ // Do Nothing
552
+ }
553
+
541
554
  *searchExistingQueryName(searchText: string): GeneratorFn<void> {
542
555
  const isValidSearchString =
543
556
  searchText.length >= DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH;
@@ -1234,6 +1247,10 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
1234
1247
  versionId: projectInfo.versionId,
1235
1248
  dataSpace: dataSpace.path,
1236
1249
  };
1250
+ const visitedDataSpaces =
1251
+ LegendQueryUserDataHelper.getRecentlyVisitedDataSpaces(
1252
+ this.applicationStore.userDataService,
1253
+ );
1237
1254
  const dataSpaceQueryBuilderState = new DataSpaceQueryBuilderState(
1238
1255
  this.applicationStore,
1239
1256
  this.graphManagerState,
@@ -1313,6 +1330,8 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
1313
1330
  projectInfo,
1314
1331
  this.applicationStore.config.options.queryBuilderConfig,
1315
1332
  sourceInfo,
1333
+ (dataSpaceInfo: DataSpaceInfo) =>
1334
+ hasDataSpaceInfoBeenVisited(dataSpaceInfo, visitedDataSpaces),
1316
1335
  );
1317
1336
  const mappingModelCoverageAnalysisResult =
1318
1337
  dataSpaceAnalysisResult?.executionContextsIndex.get(
@@ -29,8 +29,11 @@ import {
29
29
  LATEST_VERSION_ALIAS,
30
30
  } from '@finos/legend-server-depot';
31
31
  import {
32
+ LogEvent,
33
+ assertErrorThrown,
32
34
  guaranteeNonNullable,
33
35
  guaranteeType,
36
+ returnUndefOnError,
34
37
  uuid,
35
38
  } from '@finos/legend-shared';
36
39
  import {
@@ -59,6 +62,13 @@ import {
59
62
  type DataSpaceInfo,
60
63
  } from '@finos/legend-extension-dsl-data-space/application';
61
64
  import { generateDataSpaceQueryCreatorRoute } from '../../__lib__/DSL_DataSpace_LegendQueryNavigation.js';
65
+ import { LegendQueryUserDataHelper } from '../../__lib__/LegendQueryUserDataHelper.js';
66
+ import {
67
+ createVisitedDataSpaceId,
68
+ hasDataSpaceInfoBeenVisited,
69
+ createSimpleVisitedDataspace,
70
+ } from '../../__lib__/LegendQueryUserDataSpaceHelper.js';
71
+ import { LEGEND_QUERY_APP_EVENT } from '../../__lib__/LegendQueryEvent.js';
62
72
 
63
73
  export class DataSpaceQueryCreatorStore extends QueryEditorStore {
64
74
  readonly groupId: string;
@@ -144,6 +154,10 @@ export class DataSpaceQueryCreatorStore extends QueryEditorStore {
144
154
  versionId: projectInfo.versionId,
145
155
  dataSpace: dataSpace.path,
146
156
  };
157
+ const visitedDataSpaces =
158
+ LegendQueryUserDataHelper.getRecentlyVisitedDataSpaces(
159
+ this.applicationStore.userDataService,
160
+ );
147
161
  const queryBuilderState = new DataSpaceQueryBuilderState(
148
162
  this.applicationStore,
149
163
  this.graphManagerState,
@@ -193,6 +207,15 @@ export class DataSpaceQueryCreatorStore extends QueryEditorStore {
193
207
  queryBuilderState.class?.path,
194
208
  ),
195
209
  );
210
+ returnUndefOnError(() =>
211
+ LegendQueryUserDataHelper.updateVisitedDataSpaceExecContext(
212
+ this.applicationStore.userDataService,
213
+ this.groupId,
214
+ this.artifactId,
215
+ dataSpace.path,
216
+ ec.name,
217
+ ),
218
+ );
196
219
  },
197
220
  (runtimeValue: Runtime) => {
198
221
  const runtimePointer = guaranteeType(runtimeValue, RuntimePointer);
@@ -235,6 +258,8 @@ export class DataSpaceQueryCreatorStore extends QueryEditorStore {
235
258
  projectInfo,
236
259
  this.applicationStore.config.options.queryBuilderConfig,
237
260
  sourceInfo,
261
+ (dataSpaceInfo: DataSpaceInfo) =>
262
+ hasDataSpaceInfoBeenVisited(dataSpaceInfo, visitedDataSpaces),
238
263
  );
239
264
  queryBuilderState.setExecutionContext(executionContext);
240
265
  queryBuilderState.propagateExecutionContextChange(executionContext);
@@ -257,9 +282,32 @@ export class DataSpaceQueryCreatorStore extends QueryEditorStore {
257
282
  );
258
283
  }
259
284
 
285
+ // add to visited dataspaces
286
+ this.addVisitedDataSpace(executionContext.name);
260
287
  return queryBuilderState;
261
288
  }
262
289
 
290
+ addVisitedDataSpace(execName: string | undefined): void {
291
+ try {
292
+ LegendQueryUserDataHelper.addVisitedDatspace(
293
+ this.applicationStore.userDataService,
294
+ createSimpleVisitedDataspace(
295
+ this.groupId,
296
+ this.artifactId,
297
+ this.versionId,
298
+ this.dataSpacePath,
299
+ execName,
300
+ ),
301
+ );
302
+ } catch (error) {
303
+ assertErrorThrown(error);
304
+ this.applicationStore.logService.warn(
305
+ LogEvent.create(LEGEND_QUERY_APP_EVENT.LOCAL_STORAGE_PERSIST_ERROR),
306
+ error.message,
307
+ );
308
+ }
309
+ }
310
+
263
311
  getPersistConfiguration(
264
312
  lambda: RawLambda,
265
313
  options?: { update?: boolean | undefined },
@@ -283,4 +331,15 @@ export class DataSpaceQueryCreatorStore extends QueryEditorStore {
283
331
  },
284
332
  };
285
333
  }
334
+
335
+ override onInitializeFailure(): void {
336
+ LegendQueryUserDataHelper.removeRecentlyViewedDataSpace(
337
+ this.applicationStore.userDataService,
338
+ createVisitedDataSpaceId(
339
+ this.groupId,
340
+ this.artifactId,
341
+ this.dataSpacePath,
342
+ ),
343
+ );
344
+ }
286
345
  }
@@ -22,13 +22,13 @@ import {
22
22
  } from '@finos/legend-server-depot';
23
23
  import type { GraphManagerState, RawLambda } from '@finos/legend-graph';
24
24
  import { type GenericLegendApplicationStore } from '@finos/legend-application';
25
- import { action, flow, makeObservable, observable } from 'mobx';
25
+ import { action, flow, flowResult, makeObservable, observable } from 'mobx';
26
26
  import {
27
27
  type QueryBuilderConfig,
28
28
  QueryBuilderState,
29
29
  QueryBuilderDataBrowserWorkflow,
30
30
  } from '@finos/legend-query-builder';
31
- import type { ProjectGAVCoordinates } from '@finos/legend-storage';
31
+ import type { Entity, ProjectGAVCoordinates } from '@finos/legend-storage';
32
32
  import {
33
33
  ActionState,
34
34
  assertErrorThrown,
@@ -51,7 +51,13 @@ import {
51
51
  import { generateDataSpaceQueryCreatorRoute } from '../../__lib__/DSL_DataSpace_LegendQueryNavigation.js';
52
52
  import { renderDataSpaceQuerySetupSetupPanelContent } from '../../components/data-space/DataSpaceQuerySetup.js';
53
53
  import { DataSpaceAdvancedSearchState } from '@finos/legend-extension-dsl-data-space/application-query';
54
+ import type { VisitedDataspace } from '../../__lib__/LegendQueryUserDataSpaceHelper.js';
55
+ import { LegendQueryUserDataHelper } from '../../__lib__/LegendQueryUserDataHelper.js';
54
56
 
57
+ type DataSpaceVisitedEntity = {
58
+ visited: VisitedDataspace;
59
+ entity: Entity;
60
+ };
55
61
  export class DataSpaceQuerySetupState extends QueryBuilderState {
56
62
  editorStore: QueryEditorStore;
57
63
  readonly depotServerClient: DepotServerClient;
@@ -107,7 +113,9 @@ export class DataSpaceQuerySetupState extends QueryBuilderState {
107
113
  advancedSearchState: observable,
108
114
  showAdvancedSearchPanel: action,
109
115
  hideAdvancedSearchPanel: action,
110
- loadDataSpaces: flow,
116
+ initializeDataSpaceSetup: flow,
117
+ redirectIfPossible: flow,
118
+ hyrdateVisitedDataSpace: flow,
111
119
  });
112
120
 
113
121
  this.editorStore = editorStore;
@@ -144,9 +152,29 @@ export class DataSpaceQuerySetupState extends QueryBuilderState {
144
152
  this.advancedSearchState = undefined;
145
153
  }
146
154
 
147
- *loadDataSpaces(): GeneratorFn<void> {
155
+ *initializeDataSpaceSetup(): GeneratorFn<void> {
148
156
  this.loadDataSpacesState.inProgress();
149
157
  try {
158
+ const hydrated = (yield flowResult(this.redirectIfPossible())) as
159
+ | DataSpaceVisitedEntity
160
+ | undefined;
161
+ if (hydrated) {
162
+ this.applicationStore.navigationService.navigator.goToLocation(
163
+ generateDataSpaceQueryCreatorRoute(
164
+ guaranteeNonNullable(hydrated.visited.groupId),
165
+ guaranteeNonNullable(hydrated.visited.artifactId),
166
+ hydrated.visited.versionId ?? LATEST_VERSION_ALIAS,
167
+ hydrated.visited.path,
168
+ hydrated.visited.execContext ??
169
+ (hydrated.entity.content.defaultExecutionContext as string),
170
+ undefined,
171
+ undefined,
172
+ ),
173
+ );
174
+ this.loadDataSpacesState.complete();
175
+ return;
176
+ }
177
+
150
178
  this.dataSpaces = (
151
179
  (yield this.depotServerClient.getEntitiesByClassifier(
152
180
  DATA_SPACE_ELEMENT_CLASSIFIER_PATH,
@@ -162,6 +190,66 @@ export class DataSpaceQuerySetupState extends QueryBuilderState {
162
190
  this.applicationStore.notificationService.notifyError(error);
163
191
  }
164
192
  }
193
+
194
+ *redirectIfPossible(): GeneratorFn<DataSpaceVisitedEntity | undefined> {
195
+ const visitedQueries =
196
+ LegendQueryUserDataHelper.getRecentlyVisitedDataSpaces(
197
+ this.applicationStore.userDataService,
198
+ );
199
+ let redirect: DataSpaceVisitedEntity | undefined = undefined;
200
+ for (let i = 0; i < visitedQueries.length; i++) {
201
+ const visited = visitedQueries[i];
202
+ if (visited) {
203
+ const hydrated = (yield flowResult(
204
+ this.hyrdateVisitedDataSpace(visited),
205
+ )) as DataSpaceVisitedEntity | undefined;
206
+ if (hydrated) {
207
+ redirect = hydrated;
208
+ break;
209
+ }
210
+ }
211
+ }
212
+ return redirect;
213
+ }
214
+
215
+ *hyrdateVisitedDataSpace(
216
+ visited: VisitedDataspace,
217
+ ): GeneratorFn<DataSpaceVisitedEntity | undefined> {
218
+ try {
219
+ const entity = (yield this.depotServerClient.getVersionEntity(
220
+ visited.groupId,
221
+ visited.artifactId,
222
+ visited.versionId ?? LATEST_VERSION_ALIAS,
223
+ visited.path,
224
+ )) as Entity;
225
+ const content = entity.content as {
226
+ executionContexts: { name: string }[];
227
+ };
228
+ if (visited.execContext) {
229
+ const found = content.executionContexts.find(
230
+ (e) => e.name === visited.execContext,
231
+ );
232
+ if (!found) {
233
+ visited.execContext = undefined;
234
+ return {
235
+ visited,
236
+ entity,
237
+ };
238
+ }
239
+ }
240
+ return {
241
+ visited,
242
+ entity,
243
+ };
244
+ } catch (error) {
245
+ assertErrorThrown(error);
246
+ LegendQueryUserDataHelper.removeRecentlyViewedDataSpace(
247
+ this.applicationStore.userDataService,
248
+ visited.id,
249
+ );
250
+ }
251
+ return undefined;
252
+ }
165
253
  }
166
254
 
167
255
  export class DataSpaceQuerySetupStore extends QueryEditorStore {
package/tsconfig.json CHANGED
@@ -57,6 +57,7 @@
57
57
  "./src/__lib__/LegendQueryNavigation.ts",
58
58
  "./src/__lib__/LegendQueryTelemetryHelper.ts",
59
59
  "./src/__lib__/LegendQueryUserDataHelper.ts",
60
+ "./src/__lib__/LegendQueryUserDataSpaceHelper.ts",
60
61
  "./src/application/Core_LegendQuery_LegendApplicationPlugin.ts",
61
62
  "./src/application/LegendQueryApplicationConfig.ts",
62
63
  "./src/application/LegendQueryPluginManager.ts",
@@ -79,6 +80,7 @@
79
80
  "./src/components/Core_LegendQueryApplicationPlugin.tsx",
80
81
  "./src/components/CreateMappingQuerySetup.tsx",
81
82
  "./src/components/EditExistingQuerySetup.tsx",
83
+ "./src/components/LegendQueryAppInfo.tsx",
82
84
  "./src/components/LegendQueryFrameworkProvider.tsx",
83
85
  "./src/components/LegendQueryWebApplication.tsx",
84
86
  "./src/components/LoadProjectServiceQuerySetup.tsx",