@finos/legend-application-studio 28.4.3 → 28.5.0

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 (123) hide show
  1. package/lib/__lib__/LegendStudioDocumentation.d.ts +1 -0
  2. package/lib/__lib__/LegendStudioDocumentation.d.ts.map +1 -1
  3. package/lib/__lib__/LegendStudioDocumentation.js +1 -0
  4. package/lib/__lib__/LegendStudioDocumentation.js.map +1 -1
  5. package/lib/__lib__/LegendStudioNavigation.d.ts +12 -2
  6. package/lib/__lib__/LegendStudioNavigation.d.ts.map +1 -1
  7. package/lib/__lib__/LegendStudioNavigation.js +92 -37
  8. package/lib/__lib__/LegendStudioNavigation.js.map +1 -1
  9. package/lib/components/LegendStudioWebApplication.d.ts.map +1 -1
  10. package/lib/components/LegendStudioWebApplication.js +6 -0
  11. package/lib/components/LegendStudioWebApplication.js.map +1 -1
  12. package/lib/components/editor/ActivityBar.js +1 -1
  13. package/lib/components/editor/ActivityBar.js.map +1 -1
  14. package/lib/components/editor/Editor.d.ts.map +1 -1
  15. package/lib/components/editor/Editor.js +10 -2
  16. package/lib/components/editor/Editor.js.map +1 -1
  17. package/lib/components/editor/StatusBar.d.ts.map +1 -1
  18. package/lib/components/editor/StatusBar.js +4 -1
  19. package/lib/components/editor/StatusBar.js.map +1 -1
  20. package/lib/components/editor/__test-utils__/EditorComponentTestUtils.d.ts.map +1 -1
  21. package/lib/components/editor/__test-utils__/EditorComponentTestUtils.js +1 -1
  22. package/lib/components/editor/__test-utils__/EditorComponentTestUtils.js.map +1 -1
  23. package/lib/components/editor/editor-group/GrammarTextEditor.d.ts.map +1 -1
  24. package/lib/components/editor/editor-group/GrammarTextEditor.js +6 -3
  25. package/lib/components/editor/editor-group/GrammarTextEditor.js.map +1 -1
  26. package/lib/components/editor/editor-group/project-configuration-editor/ProjectDependencyEditor.d.ts +4 -0
  27. package/lib/components/editor/editor-group/project-configuration-editor/ProjectDependencyEditor.d.ts.map +1 -1
  28. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.d.ts +2 -3
  29. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.d.ts.map +1 -1
  30. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.js +9 -9
  31. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.js.map +1 -1
  32. package/lib/components/editor/side-bar/ProjectOverview.d.ts.map +1 -1
  33. package/lib/components/editor/side-bar/ProjectOverview.js +109 -7
  34. package/lib/components/editor/side-bar/ProjectOverview.js.map +1 -1
  35. package/lib/components/project-view/ProjectViewer.js +1 -1
  36. package/lib/components/project-view/ProjectViewer.js.map +1 -1
  37. package/lib/components/workspace-review/WorkspaceReview.js +1 -1
  38. package/lib/components/workspace-review/WorkspaceReview.js.map +1 -1
  39. package/lib/components/workspace-setup/CreateWorkspaceModal.d.ts +5 -1
  40. package/lib/components/workspace-setup/CreateWorkspaceModal.d.ts.map +1 -1
  41. package/lib/components/workspace-setup/CreateWorkspaceModal.js +34 -6
  42. package/lib/components/workspace-setup/CreateWorkspaceModal.js.map +1 -1
  43. package/lib/components/workspace-setup/WorkspaceSelectorUtils.d.ts.map +1 -1
  44. package/lib/components/workspace-setup/WorkspaceSelectorUtils.js +1 -1
  45. package/lib/components/workspace-setup/WorkspaceSelectorUtils.js.map +1 -1
  46. package/lib/components/workspace-setup/WorkspaceSetup.d.ts +1 -0
  47. package/lib/components/workspace-setup/WorkspaceSetup.d.ts.map +1 -1
  48. package/lib/components/workspace-setup/WorkspaceSetup.js +2 -1
  49. package/lib/components/workspace-setup/WorkspaceSetup.js.map +1 -1
  50. package/lib/index.css +2 -2
  51. package/lib/index.css.map +1 -1
  52. package/lib/package.json +1 -1
  53. package/lib/stores/LegendStudioApplicationPlugin.d.ts +1 -1
  54. package/lib/stores/LegendStudioApplicationPlugin.d.ts.map +1 -1
  55. package/lib/stores/editor/EditorSDLCState.d.ts +8 -2
  56. package/lib/stores/editor/EditorSDLCState.d.ts.map +1 -1
  57. package/lib/stores/editor/EditorSDLCState.js +29 -3
  58. package/lib/stores/editor/EditorSDLCState.js.map +1 -1
  59. package/lib/stores/editor/EditorStore.d.ts +1 -1
  60. package/lib/stores/editor/EditorStore.d.ts.map +1 -1
  61. package/lib/stores/editor/EditorStore.js +8 -5
  62. package/lib/stores/editor/EditorStore.js.map +1 -1
  63. package/lib/stores/editor/StandardEditorMode.d.ts.map +1 -1
  64. package/lib/stores/editor/StandardEditorMode.js +1 -1
  65. package/lib/stores/editor/StandardEditorMode.js.map +1 -1
  66. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.d.ts +5 -5
  67. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.d.ts.map +1 -1
  68. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.js +19 -8
  69. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.js.map +1 -1
  70. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.d.ts.map +1 -1
  71. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.js +1 -1
  72. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.js.map +1 -1
  73. package/lib/stores/editor/sidebar-state/ProjectOverviewState.d.ts +9 -3
  74. package/lib/stores/editor/sidebar-state/ProjectOverviewState.d.ts.map +1 -1
  75. package/lib/stores/editor/sidebar-state/ProjectOverviewState.js +71 -7
  76. package/lib/stores/editor/sidebar-state/ProjectOverviewState.js.map +1 -1
  77. package/lib/stores/editor/sidebar-state/WorkspaceReviewState.d.ts.map +1 -1
  78. package/lib/stores/editor/sidebar-state/WorkspaceReviewState.js +6 -6
  79. package/lib/stores/editor/sidebar-state/WorkspaceReviewState.js.map +1 -1
  80. package/lib/stores/editor/sidebar-state/WorkspaceUpdaterState.d.ts.map +1 -1
  81. package/lib/stores/editor/sidebar-state/WorkspaceUpdaterState.js +2 -2
  82. package/lib/stores/editor/sidebar-state/WorkspaceUpdaterState.js.map +1 -1
  83. package/lib/stores/workspace-review/WorkspaceReviewStore.d.ts +3 -1
  84. package/lib/stores/workspace-review/WorkspaceReviewStore.d.ts.map +1 -1
  85. package/lib/stores/workspace-review/WorkspaceReviewStore.js +13 -7
  86. package/lib/stores/workspace-review/WorkspaceReviewStore.js.map +1 -1
  87. package/lib/stores/workspace-setup/ProjectConfigurationStatus.d.ts +1 -1
  88. package/lib/stores/workspace-setup/ProjectConfigurationStatus.d.ts.map +1 -1
  89. package/lib/stores/workspace-setup/ProjectConfigurationStatus.js +2 -2
  90. package/lib/stores/workspace-setup/ProjectConfigurationStatus.js.map +1 -1
  91. package/lib/stores/workspace-setup/WorkspaceSetupStore.d.ts +6 -2
  92. package/lib/stores/workspace-setup/WorkspaceSetupStore.d.ts.map +1 -1
  93. package/lib/stores/workspace-setup/WorkspaceSetupStore.js +45 -12
  94. package/lib/stores/workspace-setup/WorkspaceSetupStore.js.map +1 -1
  95. package/package.json +7 -7
  96. package/src/__lib__/LegendStudioDocumentation.ts +1 -0
  97. package/src/__lib__/LegendStudioNavigation.ts +106 -25
  98. package/src/components/LegendStudioWebApplication.tsx +6 -0
  99. package/src/components/editor/ActivityBar.tsx +1 -1
  100. package/src/components/editor/Editor.tsx +15 -2
  101. package/src/components/editor/StatusBar.tsx +5 -1
  102. package/src/components/editor/__test-utils__/EditorComponentTestUtils.tsx +1 -0
  103. package/src/components/editor/editor-group/GrammarTextEditor.tsx +6 -3
  104. package/src/components/editor/editor-group/project-configuration-editor/ProjectDependencyEditor.tsx +1 -1
  105. package/src/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.tsx +13 -14
  106. package/src/components/editor/side-bar/ProjectOverview.tsx +340 -8
  107. package/src/components/project-view/ProjectViewer.tsx +1 -1
  108. package/src/components/workspace-review/WorkspaceReview.tsx +1 -1
  109. package/src/components/workspace-setup/CreateWorkspaceModal.tsx +63 -4
  110. package/src/components/workspace-setup/WorkspaceSelectorUtils.tsx +13 -6
  111. package/src/components/workspace-setup/WorkspaceSetup.tsx +3 -0
  112. package/src/stores/LegendStudioApplicationPlugin.ts +1 -1
  113. package/src/stores/editor/EditorSDLCState.ts +45 -0
  114. package/src/stores/editor/EditorStore.ts +15 -2
  115. package/src/stores/editor/StandardEditorMode.ts +1 -0
  116. package/src/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.ts +31 -10
  117. package/src/stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.ts +1 -0
  118. package/src/stores/editor/sidebar-state/ProjectOverviewState.ts +135 -1
  119. package/src/stores/editor/sidebar-state/WorkspaceReviewState.ts +6 -1
  120. package/src/stores/editor/sidebar-state/WorkspaceUpdaterState.ts +2 -0
  121. package/src/stores/workspace-review/WorkspaceReviewStore.ts +15 -1
  122. package/src/stores/workspace-setup/ProjectConfigurationStatus.ts +2 -0
  123. package/src/stores/workspace-setup/WorkspaceSetupStore.ts +71 -7
@@ -33,13 +33,20 @@ export const formatWorkspaceOptionLabel = (
33
33
  option: WorkspaceOption,
34
34
  ): React.ReactNode => (
35
35
  <div className="workspace-selector__option">
36
- <div className="workspace-selector__option__icon">
37
- {option.value.workspaceType === WorkspaceType.GROUP ? (
38
- <UsersIcon />
39
- ) : (
40
- <UserIcon />
36
+ <div className="workspace-selector__option__label">
37
+ <div className="workspace-selector__option__icon">
38
+ {option.value.workspaceType === WorkspaceType.GROUP ? (
39
+ <UsersIcon />
40
+ ) : (
41
+ <UserIcon />
42
+ )}
43
+ </div>
44
+ <div className="workspace-selector__option__name">{option.label}</div>
45
+ </div>
46
+ <div className="workspace-selector__option__source">
47
+ {option.value.source && (
48
+ <div className="workspace-selector__option__source__patch">{`patch/${option.value.source}`}</div>
41
49
  )}
42
50
  </div>
43
- <div className="workspace-selector__option__name">{option.label}</div>
44
51
  </div>
45
52
  );
@@ -62,6 +62,8 @@ const WorkspaceSetupStoreContext = createContext<
62
62
  WorkspaceSetupStore | undefined
63
63
  >(undefined);
64
64
 
65
+ export const DEFAULT_WORKSPACE_SOURCE = 'HEAD';
66
+
65
67
  const WorkspaceSetupStoreProvider: React.FC<{
66
68
  children: React.ReactNode;
67
69
  }> = ({ children }) => {
@@ -175,6 +177,7 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
175
177
  applicationStore.navigationService.navigator.goToLocation(
176
178
  generateEditorRoute(
177
179
  setupStore.currentProject.projectId,
180
+ setupStore.currentWorkspace.source,
178
181
  setupStore.currentWorkspace.workspaceId,
179
182
  setupStore.currentWorkspace.workspaceType,
180
183
  ),
@@ -331,5 +331,5 @@ export interface DSL_LegendStudioApplicationPlugin_Extension
331
331
  * Get a string of the Pure grammar element name for auto-folding the element
332
332
  * (e.g. Diagram, or Text)
333
333
  */
334
- getAutoFoldingCandidateToken?(): string[];
334
+ getExtraGrammarTextEditorAutoFoldingElementCreatorKeywords?(): string[];
335
335
  }
@@ -46,6 +46,7 @@ import {
46
46
  Version,
47
47
  Workspace,
48
48
  WorkspaceAccessType,
49
+ Patch,
49
50
  } from '@finos/legend-server-sdlc';
50
51
  import { LEGEND_STUDIO_APP_EVENT } from '../../__lib__/LegendStudioEvent.js';
51
52
 
@@ -65,6 +66,7 @@ export class EditorSDLCState {
65
66
  isFetchingProject = false;
66
67
 
67
68
  currentProject?: Project | undefined;
69
+ currentPatch?: Patch | undefined;
68
70
  currentWorkspace?: Workspace | undefined;
69
71
  remoteWorkspaceRevision?: Revision | undefined;
70
72
  currentRevision?: Revision | undefined;
@@ -75,6 +77,7 @@ export class EditorSDLCState {
75
77
  constructor(editorStore: EditorStore) {
76
78
  makeObservable(this, {
77
79
  currentProject: observable,
80
+ currentPatch: observable,
78
81
  currentWorkspace: observable,
79
82
  remoteWorkspaceRevision: observable,
80
83
  currentRevision: observable,
@@ -88,9 +91,11 @@ export class EditorSDLCState {
88
91
  activeProject: computed,
89
92
  activeWorkspace: computed,
90
93
  activeRevision: computed,
94
+ activePatch: computed,
91
95
  activeRemoteWorkspaceRevision: computed,
92
96
  isWorkspaceOutOfSync: computed,
93
97
  setCurrentProject: action,
98
+ setCurrentPatch: action,
94
99
  setCurrentWorkspace: action,
95
100
  setCurrentRevision: action,
96
101
  setWorkspaceLatestRevision: action,
@@ -100,6 +105,7 @@ export class EditorSDLCState {
100
105
  checkIfCurrentWorkspaceIsInConflictResolutionMode: flow,
101
106
  fetchRemoteWorkspaceRevision: flow,
102
107
  fetchCurrentRevision: flow,
108
+ fetchCurrentPatch: flow,
103
109
  checkIfWorkspaceIsOutdated: flow,
104
110
  buildWorkspaceLatestRevisionEntityHashesIndex: flow,
105
111
  buildWorkspaceBaseRevisionEntityHashesIndex: flow,
@@ -125,6 +131,10 @@ export class EditorSDLCState {
125
131
  );
126
132
  }
127
133
 
134
+ get activePatch(): Patch | undefined {
135
+ return this.currentPatch;
136
+ }
137
+
128
138
  get activeRevision(): Revision {
129
139
  return guaranteeNonNullable(
130
140
  this.currentRevision,
@@ -147,6 +157,10 @@ export class EditorSDLCState {
147
157
  this.currentProject = val;
148
158
  }
149
159
 
160
+ setCurrentPatch(val: Patch): void {
161
+ this.currentPatch = val;
162
+ }
163
+
150
164
  setCurrentWorkspace(val: Workspace): void {
151
165
  this.currentWorkspace = val;
152
166
  }
@@ -204,8 +218,37 @@ export class EditorSDLCState {
204
218
  }
205
219
  }
206
220
 
221
+ *fetchCurrentPatch(
222
+ projectId: string,
223
+ patchReleaseVersionId: string | undefined,
224
+ options?: { suppressNotification?: boolean },
225
+ ): GeneratorFn<void> {
226
+ if (patchReleaseVersionId) {
227
+ try {
228
+ this.currentPatch = Patch.serialization.fromJson(
229
+ (yield this.editorStore.sdlcServerClient.getPatch(
230
+ projectId,
231
+ patchReleaseVersionId,
232
+ )) as PlainObject<Patch>,
233
+ );
234
+ } catch (error) {
235
+ assertErrorThrown(error);
236
+ this.editorStore.applicationStore.logService.error(
237
+ LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE),
238
+ error,
239
+ );
240
+ if (!options?.suppressNotification) {
241
+ this.editorStore.applicationStore.notificationService.notifyError(
242
+ error,
243
+ );
244
+ }
245
+ }
246
+ }
247
+ }
248
+
207
249
  *fetchCurrentWorkspace(
208
250
  projectId: string,
251
+ patchReleaseVersionId: string | undefined,
209
252
  workspaceId: string,
210
253
  workspaceType: WorkspaceType,
211
254
  options?: { suppressNotification?: boolean },
@@ -214,10 +257,12 @@ export class EditorSDLCState {
214
257
  this.currentWorkspace = Workspace.serialization.fromJson(
215
258
  (yield this.editorStore.sdlcServerClient.getWorkspace(
216
259
  projectId,
260
+ patchReleaseVersionId,
217
261
  workspaceId,
218
262
  workspaceType,
219
263
  )) as PlainObject<Workspace>,
220
264
  );
265
+ this.currentWorkspace.source = patchReleaseVersionId;
221
266
  const isInConflictResolutionMode = (yield flowResult(
222
267
  this.checkIfCurrentWorkspaceIsInConflictResolutionMode(),
223
268
  )) as boolean;
@@ -501,7 +501,12 @@ export class EditorStore implements CommandRegistrar {
501
501
  if (entityPath) {
502
502
  this.initialEntityPath = entityPath;
503
503
  this.applicationStore.navigationService.navigator.updateCurrentLocation(
504
- generateEditorRoute(projectId, workspaceId, workspaceType),
504
+ generateEditorRoute(
505
+ projectId,
506
+ params.patchReleaseVersionId,
507
+ workspaceId,
508
+ workspaceType,
509
+ ),
505
510
  );
506
511
  }
507
512
  }
@@ -513,6 +518,7 @@ export class EditorStore implements CommandRegistrar {
513
518
  */
514
519
  *initialize(
515
520
  projectId: string,
521
+ patchReleaseVersionId: string | undefined,
516
522
  workspaceId: string,
517
523
  workspaceType: WorkspaceType,
518
524
  ): GeneratorFn<void> {
@@ -577,7 +583,7 @@ export class EditorStore implements CommandRegistrar {
577
583
  type: ActionAlertActionType.STANDARD,
578
584
  handler: (): void => {
579
585
  this.applicationStore.navigationService.navigator.goToLocation(
580
- generateSetupRoute(undefined),
586
+ generateSetupRoute(undefined, undefined),
581
587
  );
582
588
  },
583
589
  },
@@ -586,9 +592,15 @@ export class EditorStore implements CommandRegistrar {
586
592
  onLeave(false);
587
593
  return;
588
594
  }
595
+ yield flowResult(
596
+ this.sdlcState.fetchCurrentPatch(projectId, patchReleaseVersionId, {
597
+ suppressNotification: true,
598
+ }),
599
+ );
589
600
  yield flowResult(
590
601
  this.sdlcState.fetchCurrentWorkspace(
591
602
  projectId,
603
+ patchReleaseVersionId,
592
604
  workspaceId,
593
605
  workspaceType,
594
606
  {
@@ -611,6 +623,7 @@ export class EditorStore implements CommandRegistrar {
611
623
  });
612
624
  const workspace = await this.sdlcServerClient.createWorkspace(
613
625
  projectId,
626
+ patchReleaseVersionId,
614
627
  workspaceId,
615
628
  workspaceType,
616
629
  );
@@ -38,6 +38,7 @@ export class StandardEditorMode extends EditorMode {
38
38
  generateElementLink(elementPath: string): string {
39
39
  return generateEditorRoute(
40
40
  this.editorStore.sdlcState.activeProject.projectId,
41
+ this.editorStore.sdlcState.activePatch?.patchReleaseVersionId.id,
41
42
  this.editorStore.sdlcState.activeWorkspace.workspaceId,
42
43
  this.editorStore.sdlcState.activeWorkspace.workspaceType,
43
44
  elementPath,
@@ -32,6 +32,8 @@ import {
32
32
  SimpleFunctionExpression,
33
33
  CollectionInstanceValue,
34
34
  resolveServiceQueryRawLambda,
35
+ PrimitiveInstanceValue,
36
+ PrimitiveType,
35
37
  } from '@finos/legend-graph';
36
38
  import { action, flow, makeObservable, observable } from 'mobx';
37
39
  import {
@@ -198,7 +200,7 @@ export class ServiceTestSetupState {
198
200
  addServiceTestAssertKeys: action,
199
201
  syncWithQuery: action,
200
202
  removeParamValueState: action,
201
- getBindingWithParamFromQuery: action,
203
+ getContentTypeWithParamFromQuery: action,
202
204
  });
203
205
  this.parameterValueStates = this.buildParameterStates();
204
206
  }
@@ -239,8 +241,8 @@ export class ServiceTestSetupState {
239
241
  }));
240
242
  }
241
243
 
242
- getBindingWithParamFromQuery(): {
243
- binding: Binding;
244
+ getContentTypeWithParamFromQuery(): {
245
+ contentType: string;
244
246
  param: string;
245
247
  }[] {
246
248
  const query = resolveServiceQueryRawLambda(this.testState.service);
@@ -255,7 +257,7 @@ export class ServiceTestSetupState {
255
257
  this.editorStore.graphManagerState.graph,
256
258
  );
257
259
  if (valueSpec instanceof LambdaFunctionInstanceValue) {
258
- return this.getBindingWithParamRecursively(
260
+ return this.getContentTypeWithParamRecursively(
259
261
  valueSpec.values[0]?.expressionSequence.find(
260
262
  (exp) =>
261
263
  exp instanceof SimpleFunctionExpression &&
@@ -280,13 +282,15 @@ export class ServiceTestSetupState {
280
282
  return [];
281
283
  }
282
284
 
283
- getBindingWithParamRecursively(expression: ValueSpecification | undefined): {
284
- binding: Binding;
285
+ getContentTypeWithParamRecursively(
286
+ expression: ValueSpecification | undefined,
287
+ ): {
288
+ contentType: string;
285
289
  param: string;
286
290
  }[] {
287
291
  let currentExpression = expression;
288
292
  const res: {
289
- binding: Binding;
293
+ contentType: string;
290
294
  param: string;
291
295
  }[] = [];
292
296
  // use if statement to safely scan service query without breaking the app
@@ -308,8 +312,25 @@ export class ServiceTestSetupState {
308
312
  currentExpression.parametersValues[2] instanceof VariableExpression
309
313
  ) {
310
314
  res.push({
311
- binding: currentExpression.parametersValues[1].values[0]
312
- .value as Binding,
315
+ contentType: (
316
+ currentExpression.parametersValues[1].values[0].value as Binding
317
+ ).contentType,
318
+ param: currentExpression.parametersValues[2].name,
319
+ });
320
+ } else if (
321
+ matchFunctionName(
322
+ currentExpression.functionName,
323
+ QUERY_BUILDER_SUPPORTED_FUNCTIONS.GET_RUNTIME_WITH_MODEL_QUERY_CONNECTION,
324
+ ) &&
325
+ currentExpression.parametersValues[1] instanceof
326
+ PrimitiveInstanceValue &&
327
+ currentExpression.parametersValues[1].genericType.value.rawType ===
328
+ PrimitiveType.STRING &&
329
+ currentExpression.parametersValues[2] instanceof VariableExpression
330
+ ) {
331
+ res.push({
332
+ contentType: currentExpression.parametersValues[1]
333
+ .values[0] as string,
313
334
  param: currentExpression.parametersValues[2].name,
314
335
  });
315
336
  }
@@ -331,7 +352,7 @@ export class ServiceTestSetupState {
331
352
  const collection = currentExpression.parametersValues[0];
332
353
  if (collection instanceof CollectionInstanceValue) {
333
354
  collection.values
334
- .map((v) => this.getBindingWithParamRecursively(v))
355
+ .map((v) => this.getContentTypeWithParamRecursively(v))
335
356
  .flat()
336
357
  .map((p) => res.push(p));
337
358
  }
@@ -246,6 +246,7 @@ export class ProjectConfigurationEditorState extends EditorState {
246
246
  yield flowResult(
247
247
  this.editorStore.sdlcState.fetchCurrentWorkspace(
248
248
  this.editorStore.sdlcState.activeProject.projectId,
249
+ this.editorStore.sdlcState.activePatch?.patchReleaseVersionId.id,
249
250
  this.editorStore.sdlcState.activeWorkspace.workspaceId,
250
251
  this.editorStore.sdlcState.activeWorkspace.workspaceType,
251
252
  ),
@@ -23,8 +23,12 @@ import {
23
23
  assertErrorThrown,
24
24
  LogEvent,
25
25
  getNullableFirstEntry,
26
+ ActionState,
26
27
  } from '@finos/legend-shared';
27
- import { generateSetupRoute } from '../../../__lib__/LegendStudioNavigation.js';
28
+ import {
29
+ generateEditorRoute,
30
+ generateSetupRoute,
31
+ } from '../../../__lib__/LegendStudioNavigation.js';
28
32
  import {
29
33
  type NewVersionType,
30
34
  CreateVersionCommand,
@@ -35,6 +39,8 @@ import {
35
39
  Workspace,
36
40
  Review,
37
41
  areWorkspacesEquivalent,
42
+ Patch,
43
+ type WorkspaceType,
38
44
  } from '@finos/legend-server-sdlc';
39
45
  import { LEGEND_STUDIO_APP_EVENT } from '../../../__lib__/LegendStudioEvent.js';
40
46
 
@@ -43,6 +49,7 @@ export enum PROJECT_OVERVIEW_ACTIVITY_MODE {
43
49
  OVERVIEW = 'OVERVIEW',
44
50
  VERSIONS = 'VERSIONS',
45
51
  WORKSPACES = 'WORKSPACES',
52
+ PATCH = 'PATCH',
46
53
  }
47
54
 
48
55
  export class ProjectOverviewState {
@@ -55,6 +62,8 @@ export class ProjectOverviewState {
55
62
  currentProjectRevision?: Revision | undefined;
56
63
  projectWorkspaces: Workspace[] = [];
57
64
 
65
+ patches: Patch[] = [];
66
+
58
67
  isCreatingVersion = false;
59
68
  isFetchingProjectWorkspaces = false;
60
69
  isDeletingWorkspace = false;
@@ -62,8 +71,11 @@ export class ProjectOverviewState {
62
71
  isFetchingLatestVersion = false;
63
72
  isFetchingCurrentProjectRevision = false;
64
73
 
74
+ createPatchState = ActionState.create();
75
+
65
76
  constructor(editorStore: EditorStore, sdlcState: EditorSDLCState) {
66
77
  makeObservable(this, {
78
+ patches: observable,
67
79
  activityMode: observable,
68
80
  releaseVersion: observable,
69
81
  committedReviewsBetweenMostRecentVersionAndProjectLatest: observable,
@@ -82,6 +94,9 @@ export class ProjectOverviewState {
82
94
  updateProject: flow,
83
95
  fetchLatestProjectVersion: flow,
84
96
  createVersion: flow,
97
+ createPatchVersion: flow,
98
+ createPatch: flow,
99
+ fetchPatches: flow,
85
100
  });
86
101
 
87
102
  this.editorStore = editorStore;
@@ -96,11 +111,30 @@ export class ProjectOverviewState {
96
111
  *fetchProjectWorkspaces(): GeneratorFn<void> {
97
112
  try {
98
113
  this.isFetchingProjectWorkspaces = true;
114
+ this.patches = (
115
+ (yield this.editorStore.sdlcServerClient.getPatches(
116
+ this.sdlcState.activeProject.projectId,
117
+ )) as PlainObject<Patch>[]
118
+ ).map((v) => Patch.serialization.fromJson(v));
99
119
  this.projectWorkspaces = (
100
120
  (yield this.editorStore.sdlcServerClient.getWorkspaces(
101
121
  this.sdlcState.activeProject.projectId,
102
122
  )) as PlainObject<Workspace>[]
103
123
  ).map((v) => Workspace.serialization.fromJson(v));
124
+ for (const patch of this.patches) {
125
+ this.projectWorkspaces = this.projectWorkspaces.concat(
126
+ (
127
+ (yield this.editorStore.sdlcServerClient.getWorkspaces(
128
+ this.sdlcState.activeProject.projectId,
129
+ patch.patchReleaseVersionId.id,
130
+ )) as PlainObject<Workspace>[]
131
+ ).map((v) => {
132
+ const w = Workspace.serialization.fromJson(v);
133
+ w.source = patch.patchReleaseVersionId.id;
134
+ return w;
135
+ }),
136
+ );
137
+ }
104
138
  } catch (error) {
105
139
  assertErrorThrown(error);
106
140
  this.editorStore.applicationStore.logService.error(
@@ -135,6 +169,7 @@ export class ProjectOverviewState {
135
169
  this.editorStore.applicationStore.navigationService.navigator.goToLocation(
136
170
  generateSetupRoute(
137
171
  this.editorStore.sdlcState.activeProject.projectId,
172
+ undefined,
138
173
  ),
139
174
  {
140
175
  ignoreBlocking: true,
@@ -183,6 +218,23 @@ export class ProjectOverviewState {
183
218
  }
184
219
  }
185
220
 
221
+ *fetchPatches(): GeneratorFn<void> {
222
+ try {
223
+ this.patches = (
224
+ (yield this.editorStore.sdlcServerClient.getPatches(
225
+ this.sdlcState.activeProject.projectId,
226
+ )) as PlainObject<Patch>[]
227
+ ).map((v: PlainObject<Patch>) => Patch.serialization.fromJson(v));
228
+ } catch (error) {
229
+ assertErrorThrown(error);
230
+ this.editorStore.applicationStore.logService.error(
231
+ LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE),
232
+ error,
233
+ );
234
+ this.editorStore.applicationStore.notificationService.notifyError(error);
235
+ }
236
+ }
237
+
186
238
  *fetchLatestProjectVersion(): GeneratorFn<void> {
187
239
  try {
188
240
  this.isFetchingLatestVersion = true;
@@ -219,6 +271,7 @@ export class ProjectOverviewState {
219
271
  const latestProjectVersionRevisionReviewObj = getNullableFirstEntry(
220
272
  (yield this.editorStore.sdlcServerClient.getReviews(
221
273
  this.sdlcState.activeProject.projectId,
274
+ undefined,
222
275
  {
223
276
  state: ReviewState.COMMITTED,
224
277
  revisionIds: [latestProjectVersionRevision.id],
@@ -235,6 +288,7 @@ export class ProjectOverviewState {
235
288
  this.committedReviewsBetweenMostRecentVersionAndProjectLatest = (
236
289
  (yield this.editorStore.sdlcServerClient.getReviews(
237
290
  this.sdlcState.activeProject.projectId,
291
+ undefined,
238
292
  {
239
293
  state: ReviewState.COMMITTED,
240
294
  since:
@@ -253,6 +307,7 @@ export class ProjectOverviewState {
253
307
  this.committedReviewsBetweenMostRecentVersionAndProjectLatest = (
254
308
  (yield this.editorStore.sdlcServerClient.getReviews(
255
309
  this.sdlcState.activeProject.projectId,
310
+ undefined,
256
311
  {
257
312
  state: ReviewState.COMMITTED,
258
313
  },
@@ -299,4 +354,83 @@ export class ProjectOverviewState {
299
354
  this.isCreatingVersion = false;
300
355
  }
301
356
  }
357
+
358
+ *createPatchVersion(id: string): GeneratorFn<void> {
359
+ this.isCreatingVersion = true;
360
+ try {
361
+ const version = Version.serialization.fromJson(
362
+ (yield this.editorStore.sdlcServerClient.releasePatch(
363
+ this.sdlcState.activeProject.projectId,
364
+ id,
365
+ )) as PlainObject<Version>,
366
+ );
367
+ this.editorStore.applicationStore.notificationService.notifySuccess(
368
+ `${version.id.id} is released successfully`,
369
+ );
370
+ } catch (error) {
371
+ assertErrorThrown(error);
372
+ this.editorStore.applicationStore.logService.error(
373
+ LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE),
374
+ error,
375
+ );
376
+ this.editorStore.applicationStore.notificationService.notifyError(error);
377
+ } finally {
378
+ this.isCreatingVersion = false;
379
+ }
380
+ }
381
+
382
+ *createPatch(
383
+ sourceVersion: string,
384
+ workspaceName: string,
385
+ workspaceType: WorkspaceType,
386
+ ): GeneratorFn<void> {
387
+ if (!workspaceName) {
388
+ this.editorStore.applicationStore.notificationService.notify(
389
+ `Please provide workspace name`,
390
+ );
391
+ }
392
+ this.createPatchState.inProgress();
393
+ this.createPatchState.setMessage(`Creating patch...`);
394
+ try {
395
+ const newPatch = Patch.serialization.fromJson(
396
+ (yield this.editorStore.sdlcServerClient.createPatch(
397
+ this.sdlcState.activeProject.projectId,
398
+ sourceVersion,
399
+ )) as PlainObject<Patch>,
400
+ );
401
+ this.editorStore.applicationStore.notificationService.notifySuccess(
402
+ `Patch '${newPatch.patchReleaseVersionId.id}' is succesfully created`,
403
+ );
404
+ this.createPatchState.setMessage(`Creating workspace...`);
405
+ const newWorkspace = Workspace.serialization.fromJson(
406
+ (yield this.editorStore.sdlcServerClient.createWorkspace(
407
+ this.sdlcState.activeProject.projectId,
408
+ newPatch.patchReleaseVersionId.id,
409
+ workspaceName,
410
+ workspaceType,
411
+ )) as PlainObject<Workspace>,
412
+ );
413
+ newWorkspace.source = newPatch.patchReleaseVersionId.id;
414
+ this.editorStore.applicationStore.notificationService.notifySuccess(
415
+ `Workspace '${newWorkspace.workspaceId}' is succesfully created`,
416
+ );
417
+ this.editorStore.applicationStore.navigationService.navigator.goToLocation(
418
+ generateEditorRoute(
419
+ this.sdlcState.activeProject.projectId,
420
+ newPatch.patchReleaseVersionId.id,
421
+ workspaceName,
422
+ workspaceType,
423
+ ),
424
+ );
425
+ } catch (error) {
426
+ assertErrorThrown(error);
427
+ this.editorStore.applicationStore.logService.error(
428
+ LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE),
429
+ error,
430
+ );
431
+ this.editorStore.applicationStore.notificationService.notifyError(error);
432
+ } finally {
433
+ this.createPatchState.reset();
434
+ }
435
+ }
302
436
  }
@@ -182,7 +182,7 @@ export class WorkspaceReviewState {
182
182
  )) as Revision;
183
183
  const reviews = (yield this.editorStore.sdlcServerClient.getReviews(
184
184
  this.sdlcState.activeProject.projectId,
185
-
185
+ this.sdlcState.activePatch?.patchReleaseVersionId.id,
186
186
  {
187
187
  state: ReviewState.OPEN,
188
188
  revisionIds: [
@@ -236,6 +236,7 @@ export class WorkspaceReviewState {
236
236
  });
237
237
  yield this.editorStore.sdlcServerClient.createWorkspace(
238
238
  this.sdlcState.activeProject.projectId,
239
+ this.sdlcState.activePatch?.patchReleaseVersionId.id,
239
240
  this.sdlcState.activeWorkspace.workspaceId,
240
241
  this.sdlcState.activeWorkspace.workspaceType,
241
242
  );
@@ -265,6 +266,7 @@ export class WorkspaceReviewState {
265
266
  try {
266
267
  yield this.editorStore.sdlcServerClient.rejectReview(
267
268
  this.sdlcState.activeProject.projectId,
269
+ this.sdlcState.activePatch?.patchReleaseVersionId.id,
268
270
  this.workspaceReview.id,
269
271
  );
270
272
  this.workspaceReview = undefined;
@@ -308,6 +310,7 @@ export class WorkspaceReviewState {
308
310
  this.workspaceReview = Review.serialization.fromJson(
309
311
  (yield this.editorStore.sdlcServerClient.createReview(
310
312
  this.sdlcState.activeProject.projectId,
313
+ this.sdlcState.activePatch?.patchReleaseVersionId.id,
311
314
  {
312
315
  workspaceId: this.sdlcState.activeWorkspace.workspaceId,
313
316
  title,
@@ -367,6 +370,7 @@ export class WorkspaceReviewState {
367
370
  try {
368
371
  yield this.editorStore.sdlcServerClient.commitReview(
369
372
  this.sdlcState.activeProject.projectId,
373
+ this.sdlcState.activePatch?.patchReleaseVersionId.id,
370
374
  review.id,
371
375
  { message: `${review.title} [review]` },
372
376
  );
@@ -389,6 +393,7 @@ export class WorkspaceReviewState {
389
393
  this.editorStore.applicationStore.navigationService.navigator.goToLocation(
390
394
  generateSetupRoute(
391
395
  this.editorStore.sdlcState.activeProject.projectId,
396
+ this.sdlcState.activePatch?.patchReleaseVersionId.id,
392
397
  ),
393
398
  {
394
399
  ignoreBlocking: true,
@@ -331,6 +331,7 @@ export class WorkspaceUpdaterState {
331
331
  const baseReviewObj = getNullableFirstEntry(
332
332
  (yield this.editorStore.sdlcServerClient.getReviews(
333
333
  this.sdlcState.activeProject.projectId,
334
+ this.sdlcState.activePatch?.patchReleaseVersionId.id,
334
335
  {
335
336
  state: ReviewState.COMMITTED,
336
337
  revisionIds: [workspaceBaseRevision.id],
@@ -344,6 +345,7 @@ export class WorkspaceUpdaterState {
344
345
  this.committedReviewsBetweenWorkspaceBaseAndProjectLatest = (
345
346
  (yield this.editorStore.sdlcServerClient.getReviews(
346
347
  this.sdlcState.activeProject.projectId,
348
+ this.sdlcState.activePatch?.patchReleaseVersionId.id,
347
349
  {
348
350
  state: ReviewState.COMMITTED,
349
351
  since: baseReview