@finos/legend-application-studio 28.5.9 → 28.7.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.
- package/lib/__lib__/LegendStudioDocumentation.d.ts +1 -0
- package/lib/__lib__/LegendStudioDocumentation.d.ts.map +1 -1
- package/lib/__lib__/LegendStudioDocumentation.js +2 -0
- package/lib/__lib__/LegendStudioDocumentation.js.map +1 -1
- package/lib/components/editor/editor-group/service-editor/ServiceEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/service-editor/ServiceEditor.js +52 -5
- package/lib/components/editor/editor-group/service-editor/ServiceEditor.js.map +1 -1
- package/lib/components/editor/side-bar/ProjectOverview.d.ts.map +1 -1
- package/lib/components/editor/side-bar/ProjectOverview.js +17 -6
- package/lib/components/editor/side-bar/ProjectOverview.js.map +1 -1
- package/lib/components/editor/side-bar/WorkspaceReview.d.ts.map +1 -1
- package/lib/components/editor/side-bar/WorkspaceReview.js +23 -10
- package/lib/components/editor/side-bar/WorkspaceReview.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/editor/EditorSDLCState.d.ts +8 -1
- package/lib/stores/editor/EditorSDLCState.d.ts.map +1 -1
- package/lib/stores/editor/EditorSDLCState.js +43 -2
- package/lib/stores/editor/EditorSDLCState.js.map +1 -1
- package/lib/stores/editor/EditorStore.d.ts.map +1 -1
- package/lib/stores/editor/EditorStore.js +2 -0
- package/lib/stores/editor/EditorStore.js.map +1 -1
- package/lib/stores/editor/NewElementState.d.ts.map +1 -1
- package/lib/stores/editor/NewElementState.js +0 -5
- package/lib/stores/editor/NewElementState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceEditorState.d.ts +17 -0
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceEditorState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceEditorState.js +54 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceEditorState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceRegistrationState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceRegistrationState.js +2 -1
- package/lib/stores/editor/editor-state/element-editor-state/service/ServiceRegistrationState.js.map +1 -1
- package/lib/stores/editor/sidebar-state/ProjectOverviewState.d.ts +1 -1
- package/lib/stores/editor/sidebar-state/ProjectOverviewState.d.ts.map +1 -1
- package/lib/stores/editor/sidebar-state/ProjectOverviewState.js +4 -4
- package/lib/stores/editor/sidebar-state/ProjectOverviewState.js.map +1 -1
- package/lib/stores/editor/sidebar-state/WorkspaceReviewState.d.ts +2 -0
- package/lib/stores/editor/sidebar-state/WorkspaceReviewState.d.ts.map +1 -1
- package/lib/stores/editor/sidebar-state/WorkspaceReviewState.js +10 -2
- package/lib/stores/editor/sidebar-state/WorkspaceReviewState.js.map +1 -1
- package/lib/stores/editor/utils/MockDataUtils.d.ts.map +1 -1
- package/lib/stores/editor/utils/MockDataUtils.js +8 -4
- package/lib/stores/editor/utils/MockDataUtils.js.map +1 -1
- package/lib/stores/graph-modifier/DSL_Service_GraphModifierHelper.d.ts +6 -1
- package/lib/stores/graph-modifier/DSL_Service_GraphModifierHelper.d.ts.map +1 -1
- package/lib/stores/graph-modifier/DSL_Service_GraphModifierHelper.js +21 -3
- package/lib/stores/graph-modifier/DSL_Service_GraphModifierHelper.js.map +1 -1
- package/package.json +6 -6
- package/src/__lib__/LegendStudioDocumentation.ts +3 -0
- package/src/components/editor/editor-group/service-editor/ServiceEditor.tsx +400 -135
- package/src/components/editor/side-bar/ProjectOverview.tsx +50 -13
- package/src/components/editor/side-bar/WorkspaceReview.tsx +35 -22
- package/src/stores/editor/EditorSDLCState.ts +61 -0
- package/src/stores/editor/EditorStore.ts +2 -0
- package/src/stores/editor/NewElementState.ts +0 -6
- package/src/stores/editor/editor-state/element-editor-state/service/ServiceEditorState.ts +74 -0
- package/src/stores/editor/editor-state/element-editor-state/service/ServiceRegistrationState.ts +4 -1
- package/src/stores/editor/sidebar-state/ProjectOverviewState.ts +4 -4
- package/src/stores/editor/sidebar-state/WorkspaceReviewState.ts +23 -1
- package/src/stores/editor/utils/MockDataUtils.ts +17 -3
- package/src/stores/graph-modifier/DSL_Service_GraphModifierHelper.ts +39 -2
@@ -23,7 +23,6 @@ import {
|
|
23
23
|
ShareIcon,
|
24
24
|
PanelLoadingIndicator,
|
25
25
|
ContextMenu,
|
26
|
-
SyncIcon,
|
27
26
|
PencilIcon,
|
28
27
|
InfoCircleIcon,
|
29
28
|
TimesIcon,
|
@@ -338,7 +337,15 @@ const ReleaseEditor = observer(() => {
|
|
338
337
|
const canCreateVersion =
|
339
338
|
!isCurrentProjectVersionLatest &&
|
340
339
|
!isDispatchingAction &&
|
341
|
-
editorStore.sdlcServerClient.features.canCreateVersion
|
340
|
+
editorStore.sdlcServerClient.features.canCreateVersion &&
|
341
|
+
editorStore.sdlcState.canCreateVersion;
|
342
|
+
const disabledCreateVersionTitle = isCurrentProjectVersionLatest
|
343
|
+
? `Can't create version: project version not the latest`
|
344
|
+
: !editorStore.sdlcServerClient.features.canCreateVersion
|
345
|
+
? `Can't create version: current svn system does not support creating versions`
|
346
|
+
: !editorStore.sdlcState.canCreateVersion
|
347
|
+
? `Can't create version: You do not have the rights to create a version`
|
348
|
+
: undefined;
|
342
349
|
|
343
350
|
// since this can be affected by other users, we refresh it more proactively
|
344
351
|
useEffect(() => {
|
@@ -381,6 +388,7 @@ const ReleaseEditor = observer(() => {
|
|
381
388
|
onClick={createMajorRelease}
|
382
389
|
disabled={!canCreateVersion}
|
383
390
|
title={
|
391
|
+
disabledCreateVersionTitle ??
|
384
392
|
'Create a major release which comes with backward-incompatible features'
|
385
393
|
}
|
386
394
|
>
|
@@ -391,6 +399,7 @@ const ReleaseEditor = observer(() => {
|
|
391
399
|
onClick={createMinorRelease}
|
392
400
|
disabled={!canCreateVersion}
|
393
401
|
title={
|
402
|
+
disabledCreateVersionTitle ??
|
394
403
|
'Create a minor release which comes with backward-compatible features'
|
395
404
|
}
|
396
405
|
>
|
@@ -401,6 +410,7 @@ const ReleaseEditor = observer(() => {
|
|
401
410
|
onClick={createPatchRelease}
|
402
411
|
disabled={!canCreateVersion}
|
403
412
|
title={
|
413
|
+
disabledCreateVersionTitle ??
|
404
414
|
'Create a patch release which comes with backward-compatible bug fixes'
|
405
415
|
}
|
406
416
|
>
|
@@ -637,7 +647,9 @@ const PatchEditor = observer(() => {
|
|
637
647
|
Create Patch
|
638
648
|
<DocumentationLink
|
639
649
|
className="project-overview__patch__documentation"
|
640
|
-
documentationKey={
|
650
|
+
documentationKey={
|
651
|
+
LEGEND_STUDIO_DOCUMENTATION_KEY.QUESTION_WHAT_ARE_PROJECT_ROLES
|
652
|
+
}
|
641
653
|
/>
|
642
654
|
</div>
|
643
655
|
</div>
|
@@ -883,7 +895,8 @@ const OverviewViewer = observer(() => {
|
|
883
895
|
const initialName = sdlcState.currentProject?.name ?? '';
|
884
896
|
const initialDescription = sdlcState.currentProject?.description ?? '';
|
885
897
|
const initialTags = sdlcState.currentProject?.tags ?? [];
|
886
|
-
const isDispatchingAction =
|
898
|
+
const isDispatchingAction =
|
899
|
+
projectOverviewState.updatingProjectState.isInProgress;
|
887
900
|
const [projectIdentifier, setProjectIdentifier] = useState(initialName);
|
888
901
|
const [description, setDescription] = useState(initialDescription);
|
889
902
|
const [itemValue, setItemValue] = useState<string>('');
|
@@ -948,7 +961,6 @@ const OverviewViewer = observer(() => {
|
|
948
961
|
),
|
949
962
|
).catch(applicationStore.alertUnhandledError);
|
950
963
|
};
|
951
|
-
|
952
964
|
return (
|
953
965
|
<div className="panel side-bar__panel project-overview__panel project-overview__overview">
|
954
966
|
<div className="panel__header">
|
@@ -957,14 +969,20 @@ const OverviewViewer = observer(() => {
|
|
957
969
|
{PROJECT_OVERVIEW_ACTIVITY_MODE.OVERVIEW}
|
958
970
|
</div>
|
959
971
|
</div>
|
960
|
-
<
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
972
|
+
<div className="panel__header__actions">
|
973
|
+
<button
|
974
|
+
className="panel__header__action project-overview__update-btn"
|
975
|
+
onClick={handleUpdate}
|
976
|
+
title="Update Project"
|
977
|
+
tabIndex={-1}
|
978
|
+
>
|
979
|
+
<div className="project-overview__update-btn__label">
|
980
|
+
<div className="project-overview__update-btn__label__title">
|
981
|
+
Update
|
982
|
+
</div>
|
983
|
+
</div>
|
984
|
+
</button>
|
985
|
+
</div>
|
968
986
|
</div>
|
969
987
|
<div className="panel__content project-overview__panel__content">
|
970
988
|
<PanelLoadingIndicator isLoading={isDispatchingAction} />
|
@@ -981,6 +999,25 @@ const OverviewViewer = observer(() => {
|
|
981
999
|
onChange={changeProjectIdentifier}
|
982
1000
|
/>
|
983
1001
|
</div>
|
1002
|
+
{
|
1003
|
+
<div className="panel__content__form__section">
|
1004
|
+
<div className="panel__content__form__section__header__label">
|
1005
|
+
Project User Role
|
1006
|
+
<DocumentationLink
|
1007
|
+
documentationKey={
|
1008
|
+
LEGEND_STUDIO_DOCUMENTATION_KEY.QUESTION_WHAT_ARE_PROJECT_ROLES
|
1009
|
+
}
|
1010
|
+
/>
|
1011
|
+
</div>
|
1012
|
+
<input
|
1013
|
+
className="panel__content__form__section__input"
|
1014
|
+
title="Project User Role"
|
1015
|
+
disabled={true}
|
1016
|
+
spellCheck={false}
|
1017
|
+
value={sdlcState.accessRole?.accessRole ?? '(unknown)'}
|
1018
|
+
/>
|
1019
|
+
</div>
|
1020
|
+
}
|
984
1021
|
</div>
|
985
1022
|
<div className="panel__content__form">
|
986
1023
|
<div className="panel__content__form__section">
|
@@ -33,7 +33,10 @@ import { ACTIVITY_MODE } from '../../../stores/editor/EditorConfig.js';
|
|
33
33
|
import { generateReviewRoute } from '../../../__lib__/LegendStudioNavigation.js';
|
34
34
|
import { LEGEND_STUDIO_TEST_ID } from '../../../__lib__/LegendStudioTesting.js';
|
35
35
|
import { flowResult } from 'mobx';
|
36
|
-
import
|
36
|
+
import {
|
37
|
+
AuthorizableProjectAction,
|
38
|
+
type EntityDiff,
|
39
|
+
} from '@finos/legend-server-sdlc';
|
37
40
|
import { entityDiffSorter } from '../../../stores/editor/EditorSDLCState.js';
|
38
41
|
import { useEditorStore } from '../EditorStoreProvider.js';
|
39
42
|
import { useLegendStudioApplicationStore } from '../../LegendStudioFrameworkProvider.js';
|
@@ -128,6 +131,19 @@ export const WorkspaceReview = observer(() => {
|
|
128
131
|
applicationStore.alertUnhandledError,
|
129
132
|
);
|
130
133
|
};
|
134
|
+
// commit Review
|
135
|
+
const isCommitReviewDisabled =
|
136
|
+
isDispatchingAction ||
|
137
|
+
Boolean(!workspaceReview) ||
|
138
|
+
workspaceContainsSnapshotDependencies ||
|
139
|
+
!workspaceReviewState.canMergeReview;
|
140
|
+
const commitReviewTitle = workspaceContainsSnapshotDependencies
|
141
|
+
? `Can't commit review: workspace has snapshot dependencies`
|
142
|
+
: !workspaceReviewState.canMergeReview
|
143
|
+
? workspaceReviewState.sdlcState.unAuthorizedActionMessage(
|
144
|
+
AuthorizableProjectAction.COMMIT_REVIEW,
|
145
|
+
)
|
146
|
+
: 'Commit review';
|
131
147
|
const commitReview = (): void => {
|
132
148
|
if (workspaceReview && !isDispatchingAction) {
|
133
149
|
editorStore.localChangesState.alertUnsavedChanges((): void => {
|
@@ -138,6 +154,20 @@ export const WorkspaceReview = observer(() => {
|
|
138
154
|
});
|
139
155
|
}
|
140
156
|
};
|
157
|
+
// create Review
|
158
|
+
const isCreateReviewDisabled =
|
159
|
+
isDispatchingAction ||
|
160
|
+
Boolean(workspaceReview) ||
|
161
|
+
!workspaceReviewState.reviewTitle ||
|
162
|
+
workspaceContainsSnapshotDependencies ||
|
163
|
+
!workspaceReviewState.canCreateReview;
|
164
|
+
const createReviewTitle = workspaceContainsSnapshotDependencies
|
165
|
+
? `Can't create review: workspace has snapshot dependencies`
|
166
|
+
: !workspaceReviewState.canCreateReview
|
167
|
+
? workspaceReviewState.sdlcState.unAuthorizedActionMessage(
|
168
|
+
AuthorizableProjectAction.SUBMIT_REVIEW,
|
169
|
+
)
|
170
|
+
: 'Create review';
|
141
171
|
const createReview = (): void => {
|
142
172
|
if (
|
143
173
|
workspaceReviewState.reviewTitle &&
|
@@ -229,17 +259,8 @@ export const WorkspaceReview = observer(() => {
|
|
229
259
|
'btn--error': workspaceContainsSnapshotDependencies,
|
230
260
|
})}
|
231
261
|
onClick={createReview}
|
232
|
-
disabled={
|
233
|
-
|
234
|
-
Boolean(workspaceReview) ||
|
235
|
-
!workspaceReviewState.reviewTitle ||
|
236
|
-
workspaceContainsSnapshotDependencies
|
237
|
-
}
|
238
|
-
title={
|
239
|
-
!workspaceContainsSnapshotDependencies
|
240
|
-
? 'Create review'
|
241
|
-
: `Can't create review: workspace has snapshot dependencies`
|
242
|
-
}
|
262
|
+
disabled={isCreateReviewDisabled}
|
263
|
+
title={createReviewTitle}
|
243
264
|
>
|
244
265
|
<PlusIcon />
|
245
266
|
</button>
|
@@ -283,17 +304,9 @@ export const WorkspaceReview = observer(() => {
|
|
283
304
|
{ 'btn--error': workspaceContainsSnapshotDependencies },
|
284
305
|
)}
|
285
306
|
onClick={commitReview}
|
286
|
-
disabled={
|
287
|
-
isDispatchingAction ||
|
288
|
-
Boolean(!workspaceReview) ||
|
289
|
-
workspaceContainsSnapshotDependencies
|
290
|
-
}
|
307
|
+
disabled={isCommitReviewDisabled}
|
291
308
|
tabIndex={-1}
|
292
|
-
title={
|
293
|
-
!workspaceContainsSnapshotDependencies
|
294
|
-
? 'Commit review'
|
295
|
-
: `Can't commit review: workspace has snapshot dependencies`
|
296
|
-
}
|
309
|
+
title={commitReviewTitle}
|
297
310
|
>
|
298
311
|
<TruncatedGitMergeIcon />
|
299
312
|
</button>
|
@@ -33,6 +33,7 @@ import {
|
|
33
33
|
guaranteeNonNullable,
|
34
34
|
assertTrue,
|
35
35
|
ActionState,
|
36
|
+
prettyCONSTName,
|
36
37
|
} from '@finos/legend-shared';
|
37
38
|
import { EDITOR_MODE, ACTIVITY_MODE } from './EditorConfig.js';
|
38
39
|
import { type Entity, extractEntityNameFromPath } from '@finos/legend-storage';
|
@@ -47,6 +48,8 @@ import {
|
|
47
48
|
Workspace,
|
48
49
|
WorkspaceAccessType,
|
49
50
|
Patch,
|
51
|
+
ProjectAccessRole,
|
52
|
+
AuthorizableProjectAction,
|
50
53
|
} from '@finos/legend-server-sdlc';
|
51
54
|
import { LEGEND_STUDIO_APP_EVENT } from '../../__lib__/LegendStudioEvent.js';
|
52
55
|
|
@@ -73,6 +76,8 @@ export class EditorSDLCState {
|
|
73
76
|
workspaceWorkflows: Workflow[] = [];
|
74
77
|
projectVersions: Version[] = [];
|
75
78
|
projectPublishedVersions: string[] = [];
|
79
|
+
authorizedActions: AuthorizableProjectAction[] | undefined;
|
80
|
+
accessRole: ProjectAccessRole | undefined;
|
76
81
|
|
77
82
|
constructor(editorStore: EditorStore) {
|
78
83
|
makeObservable(this, {
|
@@ -88,11 +93,15 @@ export class EditorSDLCState {
|
|
88
93
|
isFetchingProjectVersions: observable,
|
89
94
|
isFetchingProject: observable,
|
90
95
|
projectPublishedVersions: observable,
|
96
|
+
authorizedActions: observable,
|
97
|
+
accessRole: observable,
|
91
98
|
activeProject: computed,
|
92
99
|
activeWorkspace: computed,
|
93
100
|
activeRevision: computed,
|
94
101
|
activePatch: computed,
|
95
102
|
activeRemoteWorkspaceRevision: computed,
|
103
|
+
canCreateWorkspace: computed,
|
104
|
+
canCreateVersion: computed,
|
96
105
|
isWorkspaceOutOfSync: computed,
|
97
106
|
setCurrentProject: action,
|
98
107
|
setCurrentPatch: action,
|
@@ -112,6 +121,7 @@ export class EditorSDLCState {
|
|
112
121
|
buildProjectLatestRevisionEntityHashesIndex: flow,
|
113
122
|
fetchWorkspaceWorkflows: flow,
|
114
123
|
fetchPublishedProjectVersions: flow,
|
124
|
+
fetchAuthorizedActions: flow,
|
115
125
|
});
|
116
126
|
|
117
127
|
this.editorStore = editorStore;
|
@@ -153,6 +163,32 @@ export class EditorSDLCState {
|
|
153
163
|
return this.activeRemoteWorkspaceRevision.id !== this.activeRevision.id;
|
154
164
|
}
|
155
165
|
|
166
|
+
get canCreateWorkspace(): boolean {
|
167
|
+
return this.userCanPerformAction(
|
168
|
+
AuthorizableProjectAction.CREATE_WORKSPACE,
|
169
|
+
);
|
170
|
+
}
|
171
|
+
|
172
|
+
get canCreateVersion(): boolean {
|
173
|
+
return this.userCanPerformAction(AuthorizableProjectAction.CREATE_VERSION);
|
174
|
+
}
|
175
|
+
|
176
|
+
unAuthorizedActionMessage(_action: AuthorizableProjectAction): string {
|
177
|
+
if (this.accessRole) {
|
178
|
+
return `Your role ${
|
179
|
+
this.accessRole.accessRole
|
180
|
+
} does not allow you to perform the action '${prettyCONSTName(_action)}'`;
|
181
|
+
}
|
182
|
+
return `Your are not entitled to perform the action: ${_action}`;
|
183
|
+
}
|
184
|
+
|
185
|
+
userCanPerformAction(authorizedAction: AuthorizableProjectAction): boolean {
|
186
|
+
return Boolean(
|
187
|
+
this.authorizedActions === undefined ||
|
188
|
+
this.authorizedActions.includes(authorizedAction),
|
189
|
+
);
|
190
|
+
}
|
191
|
+
|
156
192
|
setCurrentProject(val: Project): void {
|
157
193
|
this.currentProject = val;
|
158
194
|
}
|
@@ -530,6 +566,31 @@ export class EditorSDLCState {
|
|
530
566
|
}
|
531
567
|
}
|
532
568
|
|
569
|
+
*fetchAuthorizedActions(): GeneratorFn<void> {
|
570
|
+
try {
|
571
|
+
const [authorizedActions, accessRoleRaw] = (yield Promise.all([
|
572
|
+
this.editorStore.sdlcServerClient.getAutorizedActions(
|
573
|
+
this.activeProject.projectId,
|
574
|
+
),
|
575
|
+
this.editorStore.sdlcServerClient.getAccessRole(
|
576
|
+
this.activeProject.projectId,
|
577
|
+
),
|
578
|
+
])) as [AuthorizableProjectAction[], PlainObject<ProjectAccessRole>];
|
579
|
+
this.authorizedActions = authorizedActions;
|
580
|
+
this.accessRole = ProjectAccessRole.serialization.fromJson(accessRoleRaw);
|
581
|
+
} catch (error) {
|
582
|
+
assertErrorThrown(error);
|
583
|
+
// if there is an error fetching authorized actions we should set undefined
|
584
|
+
this.authorizedActions = undefined;
|
585
|
+
this.accessRole = undefined;
|
586
|
+
this.editorStore.applicationStore.logService.error(
|
587
|
+
LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE),
|
588
|
+
error,
|
589
|
+
);
|
590
|
+
this.editorStore.applicationStore.notificationService.notifyError(error);
|
591
|
+
}
|
592
|
+
}
|
593
|
+
|
533
594
|
*fetchPublishedProjectVersions(): GeneratorFn<void> {
|
534
595
|
try {
|
535
596
|
this.fetchPublishedProjectVersionsState.inProgress();
|
@@ -748,6 +748,7 @@ export class EditorStore implements CommandRegistrar {
|
|
748
748
|
this.graphState.fetchAvailableRelationalDatabseTypeConfigurations(),
|
749
749
|
this.sdlcState.fetchProjectVersions(),
|
750
750
|
this.sdlcState.fetchPublishedProjectVersions(),
|
751
|
+
this.sdlcState.fetchAuthorizedActions(),
|
751
752
|
]);
|
752
753
|
}
|
753
754
|
|
@@ -790,6 +791,7 @@ export class EditorStore implements CommandRegistrar {
|
|
790
791
|
this.graphState.fetchAvailableRelationalDatabseTypeConfigurations(),
|
791
792
|
this.sdlcState.fetchProjectVersions(),
|
792
793
|
this.sdlcState.fetchPublishedProjectVersions(),
|
794
|
+
this.sdlcState.fetchAuthorizedActions(),
|
793
795
|
]);
|
794
796
|
}
|
795
797
|
|
@@ -558,12 +558,6 @@ export class NewServiceDriver extends NewElementDriver<Service> {
|
|
558
558
|
this.editorStore.changeDetectionState.observerContext,
|
559
559
|
);
|
560
560
|
service_initNewService(service);
|
561
|
-
const currentUserId =
|
562
|
-
this.editorStore.graphManagerState.graphManager.TEMPORARY__getEngineConfig()
|
563
|
-
.currentUserId;
|
564
|
-
if (currentUserId) {
|
565
|
-
service.owners = [currentUserId];
|
566
|
-
}
|
567
561
|
return service;
|
568
562
|
}
|
569
563
|
}
|
@@ -38,6 +38,8 @@ import {
|
|
38
38
|
Service,
|
39
39
|
PureSingleExecution,
|
40
40
|
PureMultiExecution,
|
41
|
+
DeploymentOwnership,
|
42
|
+
UserListOwnership,
|
41
43
|
isStubbed_RawLambda,
|
42
44
|
getValueSpecificationReturnType,
|
43
45
|
type Type,
|
@@ -48,6 +50,7 @@ import { ServiceTestableState } from './testable/ServiceTestableState.js';
|
|
48
50
|
import { User } from '@finos/legend-server-sdlc';
|
49
51
|
import { ServicePostValidationsState } from './ServicePostValidationState.js';
|
50
52
|
import { valueSpecReturnTDS } from '@finos/legend-query-builder';
|
53
|
+
import { service_setOwnership } from '../../../../graph-modifier/DSL_Service_GraphModifierHelper.js';
|
51
54
|
|
52
55
|
export enum SERVICE_TAB {
|
53
56
|
GENERAL = 'GENERAL',
|
@@ -57,6 +60,11 @@ export enum SERVICE_TAB {
|
|
57
60
|
POST_VALIDATION = 'POST_VALIDATION',
|
58
61
|
}
|
59
62
|
|
63
|
+
enum ServiceOwnershipType {
|
64
|
+
DEPLOYMENT_OWNERSHIP = 'deploymentOwnership',
|
65
|
+
USERLIST_OWNERSHIP = 'userListOwnership',
|
66
|
+
}
|
67
|
+
|
60
68
|
export const resolveServiceQueryValueSpec = (
|
61
69
|
service: Service,
|
62
70
|
editorStore: EditorStore,
|
@@ -101,6 +109,24 @@ export const isServiceQueryTDS = (
|
|
101
109
|
};
|
102
110
|
|
103
111
|
export const MINIMUM_SERVICE_OWNERS = 2;
|
112
|
+
export const DeploymentOwnershipLabel = 'Deployment';
|
113
|
+
export const UserlistOwnershipLabel = 'User List';
|
114
|
+
export const OWNERSHIP_OPTIONS = [
|
115
|
+
{
|
116
|
+
label: DeploymentOwnershipLabel,
|
117
|
+
value: ServiceOwnershipType.DEPLOYMENT_OWNERSHIP,
|
118
|
+
},
|
119
|
+
{
|
120
|
+
label: UserlistOwnershipLabel,
|
121
|
+
value: ServiceOwnershipType.USERLIST_OWNERSHIP,
|
122
|
+
},
|
123
|
+
];
|
124
|
+
|
125
|
+
export type ServiceOwnerOption = {
|
126
|
+
label: string;
|
127
|
+
value: string;
|
128
|
+
};
|
129
|
+
|
104
130
|
export class ServiceEditorState extends ElementEditorState {
|
105
131
|
executionState: ServiceExecutionState;
|
106
132
|
registrationState: ServiceRegistrationState;
|
@@ -113,10 +139,12 @@ export class ServiceEditorState extends ElementEditorState {
|
|
113
139
|
|
114
140
|
makeObservable(this, {
|
115
141
|
executionState: observable,
|
142
|
+
selectedOwnership: computed,
|
116
143
|
registrationState: observable,
|
117
144
|
selectedTab: observable,
|
118
145
|
postValidationState: observable,
|
119
146
|
setSelectedTab: action,
|
147
|
+
setSelectedOwnership: action,
|
120
148
|
resetExecutionState: action,
|
121
149
|
openToTestTab: action,
|
122
150
|
service: computed,
|
@@ -153,6 +181,52 @@ export class ServiceEditorState extends ElementEditorState {
|
|
153
181
|
this.selectedTab = SERVICE_TAB.TEST;
|
154
182
|
}
|
155
183
|
|
184
|
+
get selectedOwnership(): ServiceOwnerOption | undefined {
|
185
|
+
const ownership = this.service.ownership;
|
186
|
+
if (ownership instanceof DeploymentOwnership) {
|
187
|
+
return {
|
188
|
+
label: DeploymentOwnershipLabel,
|
189
|
+
value: ServiceOwnershipType.DEPLOYMENT_OWNERSHIP,
|
190
|
+
};
|
191
|
+
} else if (ownership instanceof UserListOwnership) {
|
192
|
+
return {
|
193
|
+
label: UserlistOwnershipLabel,
|
194
|
+
value: ServiceOwnershipType.USERLIST_OWNERSHIP,
|
195
|
+
};
|
196
|
+
}
|
197
|
+
return undefined;
|
198
|
+
}
|
199
|
+
|
200
|
+
setSelectedOwnership(o: ServiceOwnerOption): void {
|
201
|
+
switch (o.value) {
|
202
|
+
case ServiceOwnershipType.DEPLOYMENT_OWNERSHIP: {
|
203
|
+
service_setOwnership(
|
204
|
+
this.service,
|
205
|
+
new DeploymentOwnership('', this.service),
|
206
|
+
);
|
207
|
+
break;
|
208
|
+
}
|
209
|
+
case ServiceOwnershipType.USERLIST_OWNERSHIP: {
|
210
|
+
const currentUserId =
|
211
|
+
this.editorStore.graphManagerState.graphManager.TEMPORARY__getEngineConfig()
|
212
|
+
.currentUserId;
|
213
|
+
service_setOwnership(
|
214
|
+
this.service,
|
215
|
+
new UserListOwnership(
|
216
|
+
currentUserId ? [currentUserId] : [],
|
217
|
+
this.service,
|
218
|
+
),
|
219
|
+
);
|
220
|
+
break;
|
221
|
+
}
|
222
|
+
default: {
|
223
|
+
this.editorStore.applicationStore.notificationService.notifyError(
|
224
|
+
'Unsupported ownership type',
|
225
|
+
);
|
226
|
+
}
|
227
|
+
}
|
228
|
+
}
|
229
|
+
|
156
230
|
resetExecutionState(): void {
|
157
231
|
this.executionState = this.buildExecutionState();
|
158
232
|
}
|
package/src/stores/editor/editor-state/element-editor-state/service/ServiceRegistrationState.ts
CHANGED
@@ -354,7 +354,10 @@ export class ServiceRegistrationState extends ServiceConfigState {
|
|
354
354
|
assertNonEmptyString(owner, `Service can't have an empty owner name`),
|
355
355
|
);
|
356
356
|
assertTrue(
|
357
|
-
|
357
|
+
Boolean(
|
358
|
+
this.service.ownership ??
|
359
|
+
this.service.owners.length >= MINIMUM_SERVICE_OWNERS,
|
360
|
+
),
|
358
361
|
`Service needs to have at least 2 owners in order to be registered`,
|
359
362
|
);
|
360
363
|
guaranteeNonNullable(
|
@@ -67,7 +67,7 @@ export class ProjectOverviewState {
|
|
67
67
|
isCreatingVersion = false;
|
68
68
|
isFetchingProjectWorkspaces = false;
|
69
69
|
isDeletingWorkspace = false;
|
70
|
-
|
70
|
+
updatingProjectState = ActionState.create();
|
71
71
|
isFetchingLatestVersion = false;
|
72
72
|
isFetchingCurrentProjectRevision = false;
|
73
73
|
|
@@ -85,7 +85,7 @@ export class ProjectOverviewState {
|
|
85
85
|
isCreatingVersion: observable,
|
86
86
|
isFetchingProjectWorkspaces: observable,
|
87
87
|
isDeletingWorkspace: observable,
|
88
|
-
|
88
|
+
updatingProjectState: observable,
|
89
89
|
isFetchingLatestVersion: observable,
|
90
90
|
isFetchingCurrentProjectRevision: observable,
|
91
91
|
setActivityMode: action,
|
@@ -193,7 +193,7 @@ export class ProjectOverviewState {
|
|
193
193
|
tags: string[],
|
194
194
|
): GeneratorFn<void> {
|
195
195
|
try {
|
196
|
-
this.
|
196
|
+
this.updatingProjectState.inProgress();
|
197
197
|
yield this.editorStore.sdlcServerClient.updateProject(
|
198
198
|
this.sdlcState.activeProject.projectId,
|
199
199
|
{
|
@@ -214,7 +214,7 @@ export class ProjectOverviewState {
|
|
214
214
|
assertErrorThrown(error);
|
215
215
|
this.editorStore.applicationStore.notificationService.notifyError(error);
|
216
216
|
} finally {
|
217
|
-
this.
|
217
|
+
this.updatingProjectState.complete();
|
218
218
|
}
|
219
219
|
}
|
220
220
|
|
@@ -14,7 +14,14 @@
|
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
16
|
|
17
|
-
import {
|
17
|
+
import {
|
18
|
+
action,
|
19
|
+
makeObservable,
|
20
|
+
flowResult,
|
21
|
+
observable,
|
22
|
+
flow,
|
23
|
+
computed,
|
24
|
+
} from 'mobx';
|
18
25
|
import type { EditorStore } from '../EditorStore.js';
|
19
26
|
import type { EditorSDLCState } from '../EditorSDLCState.js';
|
20
27
|
import { LEGEND_STUDIO_APP_EVENT } from '../../../__lib__/LegendStudioEvent.js';
|
@@ -36,6 +43,7 @@ import {
|
|
36
43
|
Review,
|
37
44
|
ReviewState,
|
38
45
|
RevisionAlias,
|
46
|
+
AuthorizableProjectAction,
|
39
47
|
} from '@finos/legend-server-sdlc';
|
40
48
|
import { ActionAlertActionType } from '@finos/legend-application';
|
41
49
|
|
@@ -69,6 +77,8 @@ export class WorkspaceReviewState {
|
|
69
77
|
isCreatingWorkspaceReview: observable,
|
70
78
|
isCommittingWorkspaceReview: observable,
|
71
79
|
isRecreatingWorkspaceAfterCommittingReview: observable,
|
80
|
+
canCreateReview: computed,
|
81
|
+
canMergeReview: computed,
|
72
82
|
setReviewTitle: action,
|
73
83
|
openReviewChange: action,
|
74
84
|
refreshWorkspaceChanges: flow,
|
@@ -83,6 +93,18 @@ export class WorkspaceReviewState {
|
|
83
93
|
this.sdlcState = sdlcState;
|
84
94
|
}
|
85
95
|
|
96
|
+
get canCreateReview(): boolean {
|
97
|
+
return this.sdlcState.userCanPerformAction(
|
98
|
+
AuthorizableProjectAction.SUBMIT_REVIEW,
|
99
|
+
);
|
100
|
+
}
|
101
|
+
|
102
|
+
get canMergeReview(): boolean {
|
103
|
+
return this.sdlcState.userCanPerformAction(
|
104
|
+
AuthorizableProjectAction.COMMIT_REVIEW,
|
105
|
+
);
|
106
|
+
}
|
107
|
+
|
86
108
|
setReviewTitle(val: string): void {
|
87
109
|
this.reviewTitle = val;
|
88
110
|
}
|
@@ -56,6 +56,7 @@ import {
|
|
56
56
|
Date as ColumnDate,
|
57
57
|
SemiStructured,
|
58
58
|
Json,
|
59
|
+
MILESTONING_VERSION_PROPERTY_SUFFIX,
|
59
60
|
} from '@finos/legend-graph';
|
60
61
|
import {
|
61
62
|
CLASS_PROPERTY_TYPE,
|
@@ -116,10 +117,23 @@ export const createMockClassInstance = (
|
|
116
117
|
depth = 0,
|
117
118
|
): PlainObject => {
|
118
119
|
const properties = traverseNonRequiredProperties
|
119
|
-
? getAllClassProperties(_class)
|
120
|
-
: getAllClassProperties(_class).filter(
|
120
|
+
? getAllClassProperties(_class, true)
|
121
|
+
: getAllClassProperties(_class, true).filter(
|
122
|
+
(p) => p.multiplicity.lowerBound,
|
123
|
+
);
|
124
|
+
const propertyNames = properties.map((property) => property.name);
|
125
|
+
const filteredProperties = properties.filter(
|
126
|
+
(prop) =>
|
127
|
+
prop.name.endsWith(MILESTONING_VERSION_PROPERTY_SUFFIX.ALL_VERSIONS) ||
|
128
|
+
(!propertyNames.includes(
|
129
|
+
prop.name + MILESTONING_VERSION_PROPERTY_SUFFIX.ALL_VERSIONS,
|
130
|
+
) &&
|
131
|
+
!prop.name.endsWith(
|
132
|
+
MILESTONING_VERSION_PROPERTY_SUFFIX.ALL_VERSIONS_IN_RANGE,
|
133
|
+
)),
|
134
|
+
);
|
121
135
|
const mockData: Record<string, object | string | number | boolean> = {};
|
122
|
-
|
136
|
+
filteredProperties.forEach((property) => {
|
123
137
|
const propertyType = property.genericType.value.rawType;
|
124
138
|
let propertyMockData: PlainObject | string | number | boolean | undefined;
|
125
139
|
switch (getClassPropertyType(propertyType)) {
|
@@ -23,6 +23,9 @@ import {
|
|
23
23
|
type RawLambda,
|
24
24
|
type Runtime,
|
25
25
|
type Service,
|
26
|
+
DeploymentOwnership,
|
27
|
+
type UserListOwnership,
|
28
|
+
type ServiceOwnership,
|
26
29
|
type ServiceExecution,
|
27
30
|
type ObserverContext,
|
28
31
|
type ServiceTestSuite,
|
@@ -47,6 +50,7 @@ import {
|
|
47
50
|
observe_PostValidationAssertion,
|
48
51
|
TestData,
|
49
52
|
observe_TestData,
|
53
|
+
observe_Ownership,
|
50
54
|
} from '@finos/legend-graph';
|
51
55
|
import { addUniqueEntry, deleteEntry, uuid } from '@finos/legend-shared';
|
52
56
|
import { action } from 'mobx';
|
@@ -158,12 +162,20 @@ export const service_deleteTestSuite = action(
|
|
158
162
|
},
|
159
163
|
);
|
160
164
|
|
165
|
+
export const service_setOwnership = action(
|
166
|
+
(service: Service, value: ServiceOwnership | undefined): void => {
|
167
|
+
service.ownership = value ? observe_Ownership(value) : undefined;
|
168
|
+
},
|
169
|
+
);
|
170
|
+
|
161
171
|
export const service_initNewService = action(
|
162
172
|
(service: Service, userId?: string): void => {
|
163
173
|
service.pattern = `/${uuid()}`; // initialize the service pattern with an UUID to avoid people leaving the pattern as /
|
164
174
|
if (userId) {
|
165
|
-
service.owners
|
166
|
-
}
|
175
|
+
service.owners = [userId];
|
176
|
+
} else {
|
177
|
+
service_setOwnership(service, new DeploymentOwnership('', service));
|
178
|
+
}
|
167
179
|
},
|
168
180
|
);
|
169
181
|
export const service_setExecution = action(
|
@@ -180,6 +192,31 @@ export const service_setPattern = action(
|
|
180
192
|
service.pattern = value;
|
181
193
|
},
|
182
194
|
);
|
195
|
+
|
196
|
+
export const service_deploymentOwnership = action(
|
197
|
+
(deployment: DeploymentOwnership, value: string): void => {
|
198
|
+
deployment.identifier = value;
|
199
|
+
},
|
200
|
+
);
|
201
|
+
|
202
|
+
export const service_addUserOwnership = action(
|
203
|
+
(userList: UserListOwnership, value: string): void => {
|
204
|
+
userList.users.push(value);
|
205
|
+
},
|
206
|
+
);
|
207
|
+
|
208
|
+
export const service_updateUserOwnership = action(
|
209
|
+
(userList: UserListOwnership, value: string, index: number): void => {
|
210
|
+
userList.users[index] = value;
|
211
|
+
},
|
212
|
+
);
|
213
|
+
|
214
|
+
export const service_deleteValueFromUserOwnership = action(
|
215
|
+
(userList: UserListOwnership, index: number): void => {
|
216
|
+
userList.users.splice(index, 1);
|
217
|
+
},
|
218
|
+
);
|
219
|
+
|
183
220
|
export const service_setDocumentation = action(
|
184
221
|
(service: Service, value: string): void => {
|
185
222
|
service.documentation = value;
|