From 1f768eab65610bc00d57278bcebe3aa2adcb0d3d Mon Sep 17 00:00:00 2001 From: Paula-Kli Date: Thu, 28 Sep 2023 15:47:17 +0200 Subject: [PATCH] feat: Move model from one project to another --- .../capellacollab/projects/toolmodels/crud.py | 11 ++++ .../projects/toolmodels/routes.py | 26 +++++++++ frontend/src/app/app.module.ts | 2 + .../projects/models/service/model.service.ts | 17 ++++++ .../model-overview.component.html | 8 +++ .../model-overview.component.ts | 9 +++ .../move-model/move-model.component.css | 4 ++ .../move-model/move-model.component.html | 42 ++++++++++++++ .../move-model/move-model.component.ts | 58 +++++++++++++++++++ 9 files changed, 177 insertions(+) create mode 100644 frontend/src/app/projects/project-detail/model-overview/move-model/move-model.component.css create mode 100644 frontend/src/app/projects/project-detail/model-overview/move-model/move-model.component.html create mode 100644 frontend/src/app/projects/project-detail/model-overview/move-model/move-model.component.ts diff --git a/backend/capellacollab/projects/toolmodels/crud.py b/backend/capellacollab/projects/toolmodels/crud.py index 8032f945ab..1ea1ba3c77 100644 --- a/backend/capellacollab/projects/toolmodels/crud.py +++ b/backend/capellacollab/projects/toolmodels/crud.py @@ -140,6 +140,17 @@ def update_model( return model +def move_model( + db: orm.Session, + model: models.DatabaseCapellaModel, + project: projects_model.DatabaseProject, +) -> models.DatabaseCapellaModel: + model.project = project + model.project_id = project.id + db.commit() + return model + + def delete_model(db: orm.Session, model: models.DatabaseCapellaModel): db.delete(model) db.commit() diff --git a/backend/capellacollab/projects/toolmodels/routes.py b/backend/capellacollab/projects/toolmodels/routes.py index 069b707ba8..a63d74b15f 100644 --- a/backend/capellacollab/projects/toolmodels/routes.py +++ b/backend/capellacollab/projects/toolmodels/routes.py @@ -147,6 +147,32 @@ def patch_tool_model( return crud.update_model(db, model, body.description, version, nature) +@router.patch( + "/{model_slug}/move", + response_model=models.CapellaModel, + dependencies=[ + fastapi.Depends( + auth_injectables.ProjectRoleVerification( + required_role=projects_users_models.ProjectUserRole.MANAGER + ) + ) + ], + tags=["Projects - Models"], +) +def move_tool_model( + body: dict, + model: models.DatabaseCapellaModel = fastapi.Depends( + injectables.get_existing_capella_model + ), + db: orm.Session = fastapi.Depends(database.get_db), +) -> models.DatabaseCapellaModel: + new_project = projects_injectables.get_existing_project( + body["new_project_slug"], db + ) + + return crud.move_model(db, model, new_project) + + @router.delete( "/{model_slug}", status_code=204, diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 89b4c8187d..aa574447eb 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -90,6 +90,7 @@ import { ModelWrapperComponent } from './projects/models/model-wrapper/model-wra import { EditProjectMetadataComponent } from './projects/project-detail/edit-project-metadata/edit-project-metadata.component'; import { ModelComplexityBadgeComponent } from './projects/project-detail/model-overview/model-complexity-badge/model-complexity-badge.component'; import { ModelOverviewComponent } from './projects/project-detail/model-overview/model-overview.component'; +import { MoveModelComponent } from './projects/project-detail/model-overview/move-model/move-model.component'; import { ProjectDetailsComponent } from './projects/project-detail/project-details.component'; import { ProjectMetadataComponent } from './projects/project-detail/project-metadata/project-metadata.component'; import { AddUserToProjectComponent } from './projects/project-detail/project-users/add-user-to-project/add-user-to-project.component'; @@ -184,6 +185,7 @@ import { SettingsComponent } from './settings/settings.component'; ModelOverviewComponent, ModelRestrictionsComponent, ModelWrapperComponent, + MoveModelComponent, NavBarMenuComponent, NoticeComponent, PipelineRunWrapperComponent, diff --git a/frontend/src/app/projects/models/service/model.service.ts b/frontend/src/app/projects/models/service/model.service.ts index 318c8d859e..0ef2333a6e 100644 --- a/frontend/src/app/projects/models/service/model.service.ts +++ b/frontend/src/app/projects/models/service/model.service.ts @@ -145,6 +145,23 @@ export class ModelService { ); }; } + + moveModelToProject( + projectSlug: string, + modelSlug: string, + new_project_slug: string + ): Observable { + return this.http + .patch(`${this.backendURLFactory(projectSlug, modelSlug)}/move`, { + new_project_slug, + }) + .pipe( + tap(() => { + this.loadModels(projectSlug); + this._model.next(undefined); + }) + ); + } } export type NewModel = { diff --git a/frontend/src/app/projects/project-detail/model-overview/model-overview.component.html b/frontend/src/app/projects/project-detail/model-overview/model-overview.component.html index db1e764bad..2394b61c8a 100644 --- a/frontend/src/app/projects/project-detail/model-overview/model-overview.component.html +++ b/frontend/src/app/projects/project-detail/model-overview/model-overview.component.html @@ -93,6 +93,14 @@

Models

> key + { + this.dialog.open(MoveModelComponent, { + data: { project_slug: project?.slug, model: model }, + }); + }); + } } diff --git a/frontend/src/app/projects/project-detail/model-overview/move-model/move-model.component.css b/frontend/src/app/projects/project-detail/model-overview/move-model/move-model.component.css new file mode 100644 index 0000000000..d49deaffd7 --- /dev/null +++ b/frontend/src/app/projects/project-detail/model-overview/move-model/move-model.component.css @@ -0,0 +1,4 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ diff --git a/frontend/src/app/projects/project-detail/model-overview/move-model/move-model.component.html b/frontend/src/app/projects/project-detail/model-overview/move-model/move-model.component.html new file mode 100644 index 0000000000..7e6a27642c --- /dev/null +++ b/frontend/src/app/projects/project-detail/model-overview/move-model/move-model.component.html @@ -0,0 +1,42 @@ + + + +

Move Model to Different Project

+
Select the project to which you want to move the model to.
+ + Search + + search + + + +
{{ project.name }}
+
+
+
+ +
+
diff --git a/frontend/src/app/projects/project-detail/model-overview/move-model/move-model.component.ts b/frontend/src/app/projects/project-detail/model-overview/move-model/move-model.component.ts new file mode 100644 index 0000000000..b6b09ed4db --- /dev/null +++ b/frontend/src/app/projects/project-detail/model-overview/move-model/move-model.component.ts @@ -0,0 +1,58 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Component, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { Router } from '@angular/router'; +import { ToastService } from 'src/app/helpers/toast/toast.service'; +import { + Model, + ModelService, +} from 'src/app/projects/models/service/model.service'; +import { + Project, + ProjectService, +} from 'src/app/projects/service/project.service'; + +@Component({ + selector: 'app-move-model', + templateUrl: './move-model.component.html', + styleUrls: ['./move-model.component.css'], +}) +export class MoveModelComponent { + selectedProject?: Project; + search = ''; + constructor( + private modelService: ModelService, + private router: Router, + private dialogRef: MatDialogRef, + private toastService: ToastService, + public projectService: ProjectService, + @Inject(MAT_DIALOG_DATA) + public data: { project_slug: string; model: Model } + ) { + this.projectService.loadProjects(); + } + + onProjectSelect(project: Project) { + this.selectedProject = project; + } + + async moveModelToProject(project: Project) { + this.modelService + .moveModelToProject( + this.data.project_slug, + this.data.model.slug, + project.slug + ) + .subscribe(() => { + this.toastService.showSuccess( + 'Model moved', + `The model “${this.data.model.name}” was successfuly moved to project "${this.data.project_slug}".` + ); + this.dialogRef.close(); + }); + } +}