@finos/legend-application-studio 28.21.5 → 28.21.6

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 (74) hide show
  1. package/lib/__lib__/LegendStudioEvent.d.ts +4 -1
  2. package/lib/__lib__/LegendStudioEvent.d.ts.map +1 -1
  3. package/lib/__lib__/LegendStudioEvent.js +3 -0
  4. package/lib/__lib__/LegendStudioEvent.js.map +1 -1
  5. package/lib/__lib__/LegendStudioTelemetryHelper.d.ts +2 -1
  6. package/lib/__lib__/LegendStudioTelemetryHelper.d.ts.map +1 -1
  7. package/lib/__lib__/LegendStudioTelemetryHelper.js +11 -3
  8. package/lib/__lib__/LegendStudioTelemetryHelper.js.map +1 -1
  9. package/lib/__lib__/LegendStudioUserDataHelper.d.ts +41 -1
  10. package/lib/__lib__/LegendStudioUserDataHelper.d.ts.map +1 -1
  11. package/lib/__lib__/LegendStudioUserDataHelper.js +120 -1
  12. package/lib/__lib__/LegendStudioUserDataHelper.js.map +1 -1
  13. package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.d.ts.map +1 -1
  14. package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.js +1 -1
  15. package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.js.map +1 -1
  16. package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.d.ts.map +1 -1
  17. package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.js +2 -1
  18. package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.js.map +1 -1
  19. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.d.ts.map +1 -1
  20. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js +1 -1
  21. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js.map +1 -1
  22. package/lib/components/editor/editor-group/testable/TestableSharedComponents.d.ts.map +1 -1
  23. package/lib/components/editor/editor-group/testable/TestableSharedComponents.js +1 -1
  24. package/lib/components/editor/editor-group/testable/TestableSharedComponents.js.map +1 -1
  25. package/lib/components/workspace-setup/RecentWorkspacesPanel.d.ts +22 -0
  26. package/lib/components/workspace-setup/RecentWorkspacesPanel.d.ts.map +1 -0
  27. package/lib/components/workspace-setup/RecentWorkspacesPanel.js +80 -0
  28. package/lib/components/workspace-setup/RecentWorkspacesPanel.js.map +1 -0
  29. package/lib/components/workspace-setup/WorkspaceSetup.d.ts.map +1 -1
  30. package/lib/components/workspace-setup/WorkspaceSetup.js +61 -6
  31. package/lib/components/workspace-setup/WorkspaceSetup.js.map +1 -1
  32. package/lib/index.css +2 -2
  33. package/lib/index.css.map +1 -1
  34. package/lib/package.json +1 -1
  35. package/lib/stores/editor/EditorStore.d.ts.map +1 -1
  36. package/lib/stores/editor/EditorStore.js +31 -0
  37. package/lib/stores/editor/EditorStore.js.map +1 -1
  38. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts.map +1 -1
  39. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js +4 -2
  40. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js.map +1 -1
  41. package/lib/stores/editor/sidebar-state/ProjectOverviewState.d.ts.map +1 -1
  42. package/lib/stores/editor/sidebar-state/ProjectOverviewState.js +11 -0
  43. package/lib/stores/editor/sidebar-state/ProjectOverviewState.js.map +1 -1
  44. package/lib/stores/editor/sidebar-state/WorkspaceReviewState.d.ts.map +1 -1
  45. package/lib/stores/editor/sidebar-state/WorkspaceReviewState.js +11 -0
  46. package/lib/stores/editor/sidebar-state/WorkspaceReviewState.js.map +1 -1
  47. package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.d.ts.map +1 -1
  48. package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.js +2 -1
  49. package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.js.map +1 -1
  50. package/lib/stores/project-reviewer/ProjectReviewerStore.d.ts.map +1 -1
  51. package/lib/stores/project-reviewer/ProjectReviewerStore.js +12 -0
  52. package/lib/stores/project-reviewer/ProjectReviewerStore.js.map +1 -1
  53. package/lib/stores/workspace-setup/WorkspaceSetupStore.d.ts +17 -0
  54. package/lib/stores/workspace-setup/WorkspaceSetupStore.d.ts.map +1 -1
  55. package/lib/stores/workspace-setup/WorkspaceSetupStore.js +61 -0
  56. package/lib/stores/workspace-setup/WorkspaceSetupStore.js.map +1 -1
  57. package/package.json +10 -10
  58. package/src/__lib__/LegendStudioEvent.ts +3 -0
  59. package/src/__lib__/LegendStudioTelemetryHelper.ts +35 -11
  60. package/src/__lib__/LegendStudioUserDataHelper.ts +204 -1
  61. package/src/components/editor/editor-group/data-editor/EmbeddedDataEditor.tsx +1 -0
  62. package/src/components/editor/editor-group/data-editor/RelationElementsDataEditor.tsx +13 -5
  63. package/src/components/editor/editor-group/dataProduct/DataProductEditor.tsx +1 -0
  64. package/src/components/editor/editor-group/testable/TestableSharedComponents.tsx +1 -0
  65. package/src/components/workspace-setup/RecentWorkspacesPanel.tsx +161 -0
  66. package/src/components/workspace-setup/WorkspaceSetup.tsx +97 -8
  67. package/src/stores/editor/EditorStore.ts +44 -0
  68. package/src/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.ts +5 -1
  69. package/src/stores/editor/sidebar-state/ProjectOverviewState.ts +14 -0
  70. package/src/stores/editor/sidebar-state/WorkspaceReviewState.ts +14 -0
  71. package/src/stores/editor/sidebar-state/dev-metadata/DevMetadataState.ts +8 -1
  72. package/src/stores/project-reviewer/ProjectReviewerStore.ts +15 -0
  73. package/src/stores/workspace-setup/WorkspaceSetupStore.ts +93 -0
  74. package/tsconfig.json +1 -0
@@ -63,7 +63,9 @@ import {
63
63
  EqualTo,
64
64
  EqualToRelation,
65
65
  RelationElement,
66
+ RelationRowTestData,
66
67
  observe_RelationElement,
68
+ observe_RelationRowTestData,
67
69
  ModelStore,
68
70
  RelationElementsData,
69
71
  CORE_PURE_PATH,
@@ -723,7 +725,6 @@ export const createFunctionTest = async (
723
725
  assertion.id = DEFAULT_TEST_ASSERTION_ID;
724
726
  const expectedRelElement = new RelationElement();
725
727
  expectedRelElement.paths = [];
726
- expectedRelElement.rows = [];
727
728
  let inferredColumns: string[] = [];
728
729
  if (type.path === CORE_PURE_PATH.RELATION) {
729
730
  try {
@@ -746,6 +747,9 @@ export const createFunctionTest = async (
746
747
  }
747
748
  }
748
749
  expectedRelElement.columns = inferredColumns;
750
+ const emptyRow = observe_RelationRowTestData(new RelationRowTestData());
751
+ emptyRow.values = inferredColumns.map(() => '');
752
+ expectedRelElement.rows = [emptyRow];
749
753
  observe_RelationElement(expectedRelElement);
750
754
  assertion.expected = expectedRelElement;
751
755
  _assertion = assertion;
@@ -42,6 +42,7 @@ import {
42
42
  type WorkspaceType,
43
43
  } from '@finos/legend-server-sdlc';
44
44
  import { LEGEND_STUDIO_APP_EVENT } from '../../../__lib__/LegendStudioEvent.js';
45
+ import { LegendStudioUserDataHelper } from '../../../__lib__/LegendStudioUserDataHelper.js';
45
46
 
46
47
  export enum PROJECT_OVERVIEW_ACTIVITY_MODE {
47
48
  RELEASE = 'RELEASE',
@@ -155,6 +156,19 @@ export class ProjectOverviewState {
155
156
  this.projectWorkspaces = this.projectWorkspaces.filter(
156
157
  (w) => !areWorkspacesEquivalent(workspace, w),
157
158
  );
159
+ // Drop the deleted workspace from the recents cache so the workspace
160
+ // setup screen doesn't keep offering a dead link. Patch workspaces are
161
+ // never cached, so this is a no-op for them.
162
+ if (workspace.source === undefined) {
163
+ LegendStudioUserDataHelper.workspaceSetup_removeRecentWorkspace(
164
+ this.editorStore.applicationStore.userDataService,
165
+ {
166
+ projectId: this.sdlcState.activeProject.projectId,
167
+ workspaceId: workspace.workspaceId,
168
+ workspaceType: workspace.workspaceType,
169
+ },
170
+ );
171
+ }
158
172
  // redirect to home page if current workspace is deleted
159
173
  if (
160
174
  areWorkspacesEquivalent(
@@ -25,6 +25,7 @@ import {
25
25
  import type { EditorStore } from '../EditorStore.js';
26
26
  import type { EditorSDLCState } from '../EditorSDLCState.js';
27
27
  import { LEGEND_STUDIO_APP_EVENT } from '../../../__lib__/LegendStudioEvent.js';
28
+ import { LegendStudioUserDataHelper } from '../../../__lib__/LegendStudioUserDataHelper.js';
28
29
  import {
29
30
  type GeneratorFn,
30
31
  type PlainObject,
@@ -402,6 +403,19 @@ export class WorkspaceReviewState {
402
403
  review.id,
403
404
  { message: `${review.title} [review]` },
404
405
  );
406
+ // Committing a review deletes the workspace on SDLC. Drop it from
407
+ // the recents cache so the workspace setup screen doesn't keep
408
+ // offering a dead link. Patch workspaces are never cached.
409
+ if (this.sdlcState.activePatch === undefined) {
410
+ LegendStudioUserDataHelper.workspaceSetup_removeRecentWorkspace(
411
+ this.editorStore.applicationStore.userDataService,
412
+ {
413
+ projectId: this.sdlcState.activeProject.projectId,
414
+ workspaceId: this.sdlcState.activeWorkspace.workspaceId,
415
+ workspaceType: this.sdlcState.activeWorkspace.workspaceType,
416
+ },
417
+ );
418
+ }
405
419
  this.editorStore.applicationStore.alertService.setActionAlertInfo({
406
420
  message: 'Committed review successfully',
407
421
  prompt:
@@ -156,6 +156,13 @@ export class DevMetadataState {
156
156
  'Project Name required to push to dev mode',
157
157
  );
158
158
  this.pushState.inProgress();
159
+ LegendStudioTelemetryHelper.logEvent_DevMetadataPushLaunched(
160
+ this.editorStore.applicationStore.telemetryService,
161
+ this.editorStore.editorMode.getSourceInfo(),
162
+ currentProjectConfiguration.groupId,
163
+ currentProjectConfiguration.artifactId,
164
+ undefined,
165
+ );
159
166
  const result =
160
167
  (yield this.editorStore.graphManagerState.graphManager.pushToDevMetadata(
161
168
  currentProjectConfiguration.groupId,
@@ -165,7 +172,7 @@ export class DevMetadataState {
165
172
  this.editorStore.graphManagerState.graph,
166
173
  )) as DeployProjectResponse;
167
174
  this.result = result;
168
- LegendStudioTelemetryHelper.logEvent_DevMetadataPushLaunched(
175
+ LegendStudioTelemetryHelper.logEvent_DevMetadataPushSucceeded(
169
176
  this.editorStore.applicationStore.telemetryService,
170
177
  this.editorStore.editorMode.getSourceInfo(),
171
178
  currentProjectConfiguration.groupId,
@@ -45,6 +45,7 @@ import {
45
45
  ReviewApproval,
46
46
  } from '@finos/legend-server-sdlc';
47
47
  import { LEGEND_STUDIO_APP_EVENT } from '../../__lib__/LegendStudioEvent.js';
48
+ import { LegendStudioUserDataHelper } from '../../__lib__/LegendStudioUserDataHelper.js';
48
49
  import { DEFAULT_TAB_SIZE } from '@finos/legend-application';
49
50
  import type { Entity } from '@finos/legend-storage';
50
51
  import { EntityDiffViewState } from '../editor/editor-state/entity-diff-editor-state/EntityDiffViewState.js';
@@ -457,6 +458,20 @@ export class ProjectReviewerStore {
457
458
  { message: `${this.review.title} [review]` },
458
459
  )) as PlainObject<Review>,
459
460
  );
461
+ // Committing a review deletes its workspace on SDLC. Drop the
462
+ // matching entry from the local recents cache (no-op if it wasn't
463
+ // there, e.g., the reviewer isn't the workspace author). Patch
464
+ // workspaces are never cached.
465
+ if (this.patchReleaseVersionId === undefined) {
466
+ LegendStudioUserDataHelper.workspaceSetup_removeRecentWorkspace(
467
+ this.editorStore.applicationStore.userDataService,
468
+ {
469
+ projectId: this.projectId,
470
+ workspaceId: this.review.workspaceId,
471
+ workspaceType: this.review.workspaceType,
472
+ },
473
+ );
474
+ }
460
475
  } catch (error) {
461
476
  assertErrorThrown(error);
462
477
  this.editorStore.applicationStore.logService.error(
@@ -51,6 +51,11 @@ import {
51
51
  ProjectConfigurationStatus,
52
52
  } from './ProjectConfigurationStatus.js';
53
53
  import { GraphManagerState } from '@finos/legend-graph';
54
+ import {
55
+ LegendStudioUserDataHelper,
56
+ type RecentProjectEntry,
57
+ type RecentWorkspaceEntry,
58
+ } from '../../__lib__/LegendStudioUserDataHelper.js';
54
59
 
55
60
  interface ImportProjectSuccessReport {
56
61
  projectId: string;
@@ -92,6 +97,12 @@ export class WorkspaceSetupStore {
92
97
 
93
98
  graphManagerState: GraphManagerState;
94
99
 
100
+ // Cached recents to make re-opening a project/workspace instantaneous.
101
+ // NOTE: patch-based workspaces are intentionally excluded from this cache.
102
+ recentProjects: RecentProjectEntry[] = [];
103
+ recentWorkspaces: RecentWorkspaceEntry[] = [];
104
+ selectRecentProjectState = ActionState.create();
105
+
95
106
  constructor(
96
107
  applicationStore: LegendStudioApplicationStore,
97
108
  sdlcServerClient: SDLCServerClient,
@@ -113,6 +124,8 @@ export class WorkspaceSetupStore {
113
124
  enginePromise: observable,
114
125
  sandboxModal: observable,
115
126
  hasSandboxAccess: observable,
127
+ recentProjects: observable,
128
+ recentWorkspaces: observable,
116
129
  setShowCreateProjectModal: action,
117
130
  setShowCreateWorkspaceModal: action,
118
131
  setShowAdvancedWorkspaceFilterOptions: action,
@@ -121,6 +134,9 @@ export class WorkspaceSetupStore {
121
134
  changeWorkspace: action,
122
135
  resetProject: action,
123
136
  resetWorkspace: action,
137
+ removeRecentProject: action,
138
+ removeRecentWorkspace: action,
139
+ clearRecents: action,
124
140
  initialize: flow,
125
141
  loadProjects: flow,
126
142
  loadSandboxProject: flow,
@@ -130,6 +146,7 @@ export class WorkspaceSetupStore {
130
146
  createSandboxProject: flow,
131
147
  createWorkspace: flow,
132
148
  initializeEngine: flow,
149
+ selectRecentProject: flow,
133
150
  });
134
151
 
135
152
  this.applicationStore = applicationStore;
@@ -138,6 +155,14 @@ export class WorkspaceSetupStore {
138
155
  applicationStore.pluginManager,
139
156
  applicationStore.logService,
140
157
  );
158
+ this.recentProjects =
159
+ LegendStudioUserDataHelper.workspaceSetup_getRecentProjects(
160
+ applicationStore.userDataService,
161
+ );
162
+ this.recentWorkspaces =
163
+ LegendStudioUserDataHelper.workspaceSetup_getRecentWorkspaces(
164
+ applicationStore.userDataService,
165
+ );
141
166
  if (this.supportsCreatingSandboxProject) {
142
167
  flowResult(this.initializeEngine()).catch(
143
168
  applicationStore.alertUnhandledError,
@@ -197,6 +222,67 @@ export class WorkspaceSetupStore {
197
222
  this.sandboxModal = val;
198
223
  }
199
224
 
225
+ // --- Recents -------------------------------------------------------------
226
+ // NOTE: writes to the recents cache happen from the editor (see
227
+ // `EditorStore.initialize`) at the moment a workspace is actually opened.
228
+ // This store only reads the cache (to seed dropdowns) and prunes entries
229
+ // that are discovered to be stale.
230
+
231
+ removeRecentProject(projectId: string): void {
232
+ const updated =
233
+ LegendStudioUserDataHelper.workspaceSetup_removeRecentProject(
234
+ this.applicationStore.userDataService,
235
+ projectId,
236
+ );
237
+ this.recentProjects = updated.projects;
238
+ this.recentWorkspaces = updated.workspaces;
239
+ }
240
+
241
+ removeRecentWorkspace(entry: {
242
+ projectId: string;
243
+ workspaceId: string;
244
+ workspaceType: WorkspaceType;
245
+ }): void {
246
+ this.recentWorkspaces =
247
+ LegendStudioUserDataHelper.workspaceSetup_removeRecentWorkspace(
248
+ this.applicationStore.userDataService,
249
+ entry,
250
+ );
251
+ }
252
+
253
+ clearRecents(): void {
254
+ LegendStudioUserDataHelper.workspaceSetup_clearRecents(
255
+ this.applicationStore.userDataService,
256
+ );
257
+ this.recentProjects = [];
258
+ this.recentWorkspaces = [];
259
+ }
260
+
261
+ /**
262
+ * Fetches a project by id (used when the user picks a cached "recent"
263
+ * project that may not be in the current search results) and switches to
264
+ * it. If the project no longer exists, the entry is pruned from recents.
265
+ */
266
+ *selectRecentProject(projectId: string): GeneratorFn<void> {
267
+ this.selectRecentProjectState.inProgress();
268
+ try {
269
+ const project = Project.serialization.fromJson(
270
+ (yield this.sdlcServerClient.getProject(
271
+ projectId,
272
+ )) as PlainObject<Project>,
273
+ );
274
+ yield flowResult(this.changeProject(project));
275
+ this.selectRecentProjectState.pass();
276
+ } catch (error) {
277
+ assertErrorThrown(error);
278
+ this.removeRecentProject(projectId);
279
+ this.applicationStore.notificationService.notifyWarning(
280
+ `Recent project could not be opened and was removed from recents`,
281
+ );
282
+ this.selectRecentProjectState.fail();
283
+ }
284
+ }
285
+
200
286
  *createSandboxProject(): GeneratorFn<void> {
201
287
  try {
202
288
  if (!this.hasSandboxAccess) {
@@ -277,6 +363,7 @@ export class WorkspaceSetupStore {
277
363
  )) as PlainObject<Project>,
278
364
  );
279
365
  } catch {
366
+ this.removeRecentProject(projectId);
280
367
  this.applicationStore.navigationService.navigator.updateCurrentLocation(
281
368
  generateSetupRoute(undefined, undefined),
282
369
  );
@@ -513,6 +600,12 @@ export class WorkspaceSetupStore {
513
600
  if (matchingWorkspace) {
514
601
  this.changeWorkspace(matchingWorkspace);
515
602
  } else {
603
+ // Workspace no longer exists — prune from recents.
604
+ this.removeRecentWorkspace({
605
+ projectId: project.projectId,
606
+ workspaceId: workspaceInfo.workspaceId,
607
+ workspaceType: workspaceInfo.workspaceType,
608
+ });
516
609
  this.applicationStore.navigationService.navigator.updateCurrentLocation(
517
610
  generateSetupRoute(project.projectId, undefined),
518
611
  );
package/tsconfig.json CHANGED
@@ -374,6 +374,7 @@
374
374
  "./src/components/workspace-setup/CreateProjectModal.tsx",
375
375
  "./src/components/workspace-setup/CreateWorkspaceModal.tsx",
376
376
  "./src/components/workspace-setup/ProjectSelectorUtils.tsx",
377
+ "./src/components/workspace-setup/RecentWorkspacesPanel.tsx",
377
378
  "./src/components/workspace-setup/WorkspaceSelectorUtils.tsx",
378
379
  "./src/components/workspace-setup/WorkspaceSetup.tsx"
379
380
  ],