UNPKG

@finos/legend-studio

Version:
288 lines (274 loc) 10.1 kB
/** * Copyright (c) 2020-present, Goldman Sachs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import type { EditorStore } from '../EditorStore.js'; import type { EditorSDLCState } from '../EditorSDLCState.js'; import { action, flowResult, makeAutoObservable } from 'mobx'; import { type GeneratorFn, type PlainObject, assertErrorThrown, LogEvent, getNullableFirstElement, } from '@finos/legend-shared'; import { generateSetupRoute } from '../LegendStudioRouter.js'; import { type NewVersionType, CreateVersionCommand, ReviewState, Revision, RevisionAlias, Version, Workspace, Review, areWorkspacesEquivalent, } from '@finos/legend-server-sdlc'; import { LEGEND_STUDIO_APP_EVENT } from '../LegendStudioAppEvent.js'; export enum PROJECT_OVERVIEW_ACTIVITY_MODE { RELEASE = 'RELEASE', OVERVIEW = 'OVERVIEW', VERSIONS = 'VERSIONS', WORKSPACES = 'WORKSPACES', } export class ProjectOverviewState { editorStore: EditorStore; sdlcState: EditorSDLCState; activityMode = PROJECT_OVERVIEW_ACTIVITY_MODE.OVERVIEW; releaseVersion: CreateVersionCommand; committedReviewsBetweenMostRecentVersionAndProjectLatest: Review[] = []; latestProjectVersion?: Version | null; // `undefined` if API is not yet called, `null` if fetched but no version exists currentProjectRevision?: Revision | undefined; projectWorkspaces: Workspace[] = []; isCreatingVersion = false; isFetchingProjectWorkspaces = false; isDeletingWorkspace = false; isUpdatingProject = false; isFetchingLatestVersion = false; isFetchingCurrentProjectRevision = false; constructor(editorStore: EditorStore, sdlcState: EditorSDLCState) { makeAutoObservable(this, { editorStore: false, sdlcState: false, setActivityMode: action, }); this.editorStore = editorStore; this.sdlcState = sdlcState; this.releaseVersion = new CreateVersionCommand(); } setActivityMode(activityMode: PROJECT_OVERVIEW_ACTIVITY_MODE): void { this.activityMode = activityMode; } *fetchProjectWorkspaces(): GeneratorFn<void> { try { this.isFetchingProjectWorkspaces = true; this.projectWorkspaces = ( (yield this.editorStore.sdlcServerClient.getWorkspaces( this.sdlcState.activeProject.projectId, )) as PlainObject<Workspace>[] ).map((v) => Workspace.serialization.fromJson(v)); } catch (error) { assertErrorThrown(error); this.editorStore.applicationStore.log.error( LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE), error, ); } finally { this.isFetchingProjectWorkspaces = false; } } *deleteWorkspace(workspace: Workspace): GeneratorFn<void> { try { this.isDeletingWorkspace = true; yield this.editorStore.sdlcServerClient.deleteWorkspace( this.sdlcState.activeProject.projectId, workspace, ); this.projectWorkspaces = this.projectWorkspaces.filter( (w) => !areWorkspacesEquivalent(workspace, w), ); // redirect to home page if current workspace is deleted if ( areWorkspacesEquivalent( this.editorStore.sdlcState.activeWorkspace, workspace, ) ) { this.editorStore.applicationStore.notifyWarning( 'Current workspace is deleted. Redirecting to home page', ); this.editorStore.setIgnoreNavigationBlocking(true); this.editorStore.applicationStore.navigator.goTo( generateSetupRoute( this.editorStore.sdlcState.activeProject.projectId, ), ); } } catch (error) { assertErrorThrown(error); this.editorStore.applicationStore.log.error( LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE), error, ); } finally { this.isDeletingWorkspace = false; } } *updateProject( name: string, description: string, tags: string[], ): GeneratorFn<void> { try { this.isUpdatingProject = true; yield this.editorStore.sdlcServerClient.updateProject( this.sdlcState.activeProject.projectId, { name, description, tags, }, ); this.editorStore.applicationStore.notifySuccess( `Project '${name}' is succesfully updated`, ); yield flowResult( this.sdlcState.fetchCurrentProject( this.sdlcState.activeProject.projectId, ), ); } catch (error) { assertErrorThrown(error); this.editorStore.applicationStore.notifyError(error); } finally { this.isUpdatingProject = false; } } *fetchLatestProjectVersion(): GeneratorFn<void> { try { this.isFetchingLatestVersion = true; // fetch latest version const version = (yield this.editorStore.sdlcServerClient.getLatestVersion( this.sdlcState.activeProject.projectId, )) as PlainObject<Version> | undefined; this.latestProjectVersion = version ? Version.serialization.fromJson(version) : null; // fetch current project revision and set release revision ID this.currentProjectRevision = Revision.serialization.fromJson( (yield this.editorStore.sdlcServerClient.getRevision( this.sdlcState.activeProject.projectId, undefined, RevisionAlias.CURRENT, )) as PlainObject<Revision>, ); this.releaseVersion.setRevisionId(this.currentProjectRevision.id); // fetch committed reviews between most recent version and project latest if (this.latestProjectVersion) { const latestProjectVersionRevision = Revision.serialization.fromJson( (yield this.editorStore.sdlcServerClient.getRevision( this.sdlcState.activeProject.projectId, undefined, this.latestProjectVersion.revisionId, )) as PlainObject<Revision>, ); // we find the review associated with the latest version revision, this usually exist, except in 2 cases: // 1. the revision is somehow directly added to the branch by the user (in the case of `git`, user directly pushed to unprotected default branch) // 2. the revision is the merged/comitted review revision (this usually happens for projects where fast forwarding merging is not default) // in those case, we will get the time from the revision const latestProjectVersionRevisionReviewObj = getNullableFirstElement( (yield this.editorStore.sdlcServerClient.getReviews( this.sdlcState.activeProject.projectId, ReviewState.COMMITTED, [latestProjectVersionRevision.id], undefined, undefined, 1, )) as PlainObject<Review>[], ); const latestProjectVersionRevisionReview = latestProjectVersionRevisionReviewObj ? Review.serialization.fromJson( latestProjectVersionRevisionReviewObj, ) : undefined; this.committedReviewsBetweenMostRecentVersionAndProjectLatest = ( (yield this.editorStore.sdlcServerClient.getReviews( this.sdlcState.activeProject.projectId, ReviewState.COMMITTED, undefined, latestProjectVersionRevisionReview?.committedAt ?? latestProjectVersionRevision.committedAt, undefined, undefined, )) as PlainObject<Review>[] ) .map((v) => Review.serialization.fromJson(v)) .filter( (review) => !latestProjectVersionRevisionReview || review.id !== latestProjectVersionRevisionReview.id, ); // make sure to exclude the base review } else { this.committedReviewsBetweenMostRecentVersionAndProjectLatest = ( (yield this.editorStore.sdlcServerClient.getReviews( this.sdlcState.activeProject.projectId, ReviewState.COMMITTED, undefined, undefined, undefined, undefined, )) as PlainObject<Review>[] ).map((v) => Review.serialization.fromJson(v)); } } catch (error) { assertErrorThrown(error); this.editorStore.applicationStore.log.error( LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE), error, ); } finally { this.isFetchingLatestVersion = false; } } *createVersion(versionType: NewVersionType): GeneratorFn<void> { if (!this.editorStore.sdlcServerClient.features.canCreateVersion) { this.editorStore.applicationStore.notifyError( `Can't create version: not supported by SDLC server`, ); return; } this.isCreatingVersion = true; try { this.releaseVersion.versionType = versionType; this.releaseVersion.validate(); this.latestProjectVersion = Version.serialization.fromJson( (yield this.editorStore.sdlcServerClient.createVersion( this.sdlcState.activeProject.projectId, CreateVersionCommand.serialization.toJson(this.releaseVersion), )) as PlainObject<Version>, ); yield flowResult(this.fetchLatestProjectVersion()); } catch (error) { assertErrorThrown(error); this.editorStore.applicationStore.log.error( LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE), error, ); this.editorStore.applicationStore.notifyError(error); } finally { this.isCreatingVersion = false; } } }