From 2d6968d48b81116bb15216a89d58e4f669e0d3ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 11 Mar 2020 08:16:29 +0100 Subject: [PATCH] Allow to delete viewpoint in gallery --- .../modules/bim/bcf/api/bcf-api.service.ts | 6 +- .../bcf/api/viewpoints/bcf-viewpoint.paths.ts | 4 + .../bcf-wp-single-view.component.ts | 39 +++++++--- modules/bim/config/locales/js-en.yml | 1 + .../features/viewer/delete_viewpoint_spec.rb | 73 +++++++++++++++++++ .../pages/ifc_models/bcf_details_page.rb | 10 +++ 6 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 modules/bim/spec/features/viewer/delete_viewpoint_spec.rb diff --git a/frontend/src/app/modules/bim/bcf/api/bcf-api.service.ts b/frontend/src/app/modules/bim/bcf/api/bcf-api.service.ts index bc3246af3c..8a4ccb0c03 100644 --- a/frontend/src/app/modules/bim/bcf/api/bcf-api.service.ts +++ b/frontend/src/app/modules/bim/bcf/api/bcf-api.service.ts @@ -27,7 +27,7 @@ // ++ import {Injectable, Injector} from "@angular/core"; -import {BcfResourceCollectionPath, BcfResourcePath} from "core-app/modules/bim/bcf/api/bcf-path-resources"; +import {BcfResourceCollectionPath} from "core-app/modules/bim/bcf/api/bcf-path-resources"; import {BcfProjectPaths} from "core-app/modules/bim/bcf/api/projects/bcf-project.paths"; @@ -49,9 +49,9 @@ export class BcfApiService { * * @param href */ - parse(href:string):BcfResourcePath|BcfResourceCollectionPath|undefined { + parse(href:string):T { if (!href.startsWith(this.bcfApiBase)) { - return; + throw new Error(`Cannot parse ${href} into BCF resource.`); } const parts = href diff --git a/frontend/src/app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.paths.ts b/frontend/src/app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.paths.ts index 9fb9a5ae77..e07d006fcc 100644 --- a/frontend/src/app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.paths.ts +++ b/frontend/src/app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.paths.ts @@ -9,4 +9,8 @@ export class BcfViewpointPaths extends BcfResourcePath { get(params:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}) { return this.bcfTopicService.get(this.toPath(), params, headers); } + + delete(headers:HTTPClientHeaders = {}) { + return this.bcfTopicService.request('delete', this.toPath(), {}, headers); + } } \ No newline at end of file diff --git a/frontend/src/app/modules/bim/bcf/bcf-wp-single-view/bcf-wp-single-view.component.ts b/frontend/src/app/modules/bim/bcf/bcf-wp-single-view/bcf-wp-single-view.component.ts index 47f1b86eba..5719225de3 100644 --- a/frontend/src/app/modules/bim/bcf/bcf-wp-single-view/bcf-wp-single-view.component.ts +++ b/frontend/src/app/modules/bim/bcf/bcf-wp-single-view/bcf-wp-single-view.component.ts @@ -28,6 +28,8 @@ export class BcfWpSingleViewComponent implements OnInit, OnDestroy { viewpoint: this.I18n.t('js.bcf.viewpoint'), add_viewpoint: this.I18n.t('js.bcf.add_viewpoint'), show_viewpoint: this.I18n.t('js.bcf.show_viewpoint'), + delete_viewpoint: this.I18n.t('js.bcf.delete_viewpoint'), + text_are_you_sure: this.I18n.t('js.text_are_you_sure') }; actions = [ @@ -35,6 +37,11 @@ export class BcfWpSingleViewComponent implements OnInit, OnDestroy { icon: 'icon-watched', onClick: this.showViewpoint.bind(this), titleText: this.text.show_viewpoint + }, + { + icon: 'icon-delete', + onClick: this.deleteViewpoint.bind(this), + titleText: this.text.delete_viewpoint } ]; @@ -118,21 +125,28 @@ export class BcfWpSingleViewComponent implements OnInit, OnDestroy { } showViewpoint(event:Event, index:number) { - let viewpointHref = this.workPackage.bcfViewpoints[index].href; - let viewpoint = this.bcfApi.parse(viewpointHref)!; - let viewpointUuid = viewpoint.id as string; - this - .bcfApi - .projects.id(this.workPackage.project.idFromLink) - .topics.id(this.topicUUID!) - .viewpoints.id(viewpointUuid) + .viewpointFromIndex(index) .get() .subscribe(data => { this.viewerBridge.showViewpoint(data); }); } + deleteViewpoint(event:Event, index:number) { + if (!window.confirm(this.text.text_are_you_sure)) { + return; + } + + this + .viewpointFromIndex(index) + .delete() + .subscribe(data => { + // Update the work package to reload the viewpoint + this.wpCache.require(this.workPackage.id!, true); + }); + } + async saveCurrentAsViewpoint() { const viewpoint = await this.viewerBridge.getViewpoint(); const uuid = this.topicUUID || await this.createBcfTopic(); @@ -160,7 +174,7 @@ export class BcfWpSingleViewComponent implements OnInit, OnDestroy { const topicHref:string|undefined = this.workPackage.bcfTopic?.href; if (topicHref) { - return this.bcfApi.parse(topicHref)!.id as string; + return this.bcfApi.parse(topicHref)!.id as string; } return null; @@ -177,7 +191,7 @@ export class BcfWpSingleViewComponent implements OnInit, OnDestroy { private setViewpoints() { this.viewpoints = this.workPackage.bcfViewpoints.map((vp:HalLink) => { - const viewpointResource = this.bcfApi.parse(vp.href!) as BcfViewpointPaths; + const viewpointResource = this.bcfApi.parse(vp.href!); return { snapshotId: viewpointResource.id, @@ -193,4 +207,9 @@ export class BcfWpSingleViewComponent implements OnInit, OnDestroy { }; }); } + + private viewpointFromIndex(index:number):BcfViewpointPaths { + let viewpointHref = this.workPackage.bcfViewpoints[index].href; + return this.bcfApi.parse(viewpointHref); + } } diff --git a/modules/bim/config/locales/js-en.yml b/modules/bim/config/locales/js-en.yml index 6dfab340c1..3ce063107d 100644 --- a/modules/bim/config/locales/js-en.yml +++ b/modules/bim/config/locales/js-en.yml @@ -8,6 +8,7 @@ en: viewpoint: 'Viewpoint' add_viewpoint: 'Add viewpoint' show_viewpoint: 'Show viewpoint' + delete_viewpoint: 'Delete viewpoint' ifc_models: models: default: 'Default IFC models' diff --git a/modules/bim/spec/features/viewer/delete_viewpoint_spec.rb b/modules/bim/spec/features/viewer/delete_viewpoint_spec.rb new file mode 100644 index 0000000000..c52457bc91 --- /dev/null +++ b/modules/bim/spec/features/viewer/delete_viewpoint_spec.rb @@ -0,0 +1,73 @@ +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 2012-2020 the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2017 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ + +require_relative '../../spec_helper' + +describe 'Delete viewpoint in model viewer', type: :feature, js: true do + let(:project) { FactoryBot.create :project, enabled_module_names: [:bim, :work_package_tracking] } + let(:user) { FactoryBot.create :admin } + + let!(:work_package) { FactoryBot.create(:work_package, project: project) } + let!(:bcf) { FactoryBot.create :bcf_issue, work_package: work_package } + let!(:viewpoint) { FactoryBot.create :bcf_viewpoint, issue: bcf, viewpoint_name: 'minimal_hidden_except_one' } + + let!(:model) do + FactoryBot.create(:ifc_model_minimal_converted, + title: 'minimal', + project: project, + uploader: user) + end + + let(:model_tree) { ::Components::XeokitModelTree.new } + let(:bcf_details) { ::Pages::BcfDetailsPage.new(work_package, project) } + + before do + login_as(user) + bcf_details.visit! + end + + it 'can delete the viewpoint through the gallery' do + bcf_details.ensure_page_loaded + bcf_details.expect_viewpoint_count 1 + bcf_details.show_current_viewpoint + + # Delete but don't confirm alert + bcf_details.delete_current_viewpoint confirm: false + + sleep 1 + bcf_details.expect_viewpoint_count 1 + + # Delete for real now + bcf_details.delete_current_viewpoint confirm: true + sleep 1 + bcf_details.expect_viewpoint_count 0 + + bcf.reload + expect(bcf.viewpoints).to be_empty + end +end diff --git a/modules/bim/spec/support/pages/ifc_models/bcf_details_page.rb b/modules/bim/spec/support/pages/ifc_models/bcf_details_page.rb index ec3f59a49f..e72c5979bc 100644 --- a/modules/bim/spec/support/pages/ifc_models/bcf_details_page.rb +++ b/modules/bim/spec/support/pages/ifc_models/bcf_details_page.rb @@ -46,6 +46,16 @@ module Pages page.find('.icon-watched.ngx-gallery-icon-content').click end + def delete_current_viewpoint(confirm: true) + page.find('.icon-delete.ngx-gallery-icon-content').click + + if confirm + page.driver.browser.switch_to.alert.accept + else + page.driver.browser.switch_to.alert.dismiss + end + end + def add_viewpoint page.find('a.button', text: 'Viewpoint').click end