diff --git a/frontend/src/app/components/op-context-menu/wp-context-menu/wp-view-context-menu.directive.ts b/frontend/src/app/components/op-context-menu/wp-context-menu/wp-view-context-menu.directive.ts index 1dbb541f32..e90a043432 100644 --- a/frontend/src/app/components/op-context-menu/wp-context-menu/wp-view-context-menu.directive.ts +++ b/frontend/src/app/components/op-context-menu/wp-context-menu/wp-view-context-menu.directive.ts @@ -16,6 +16,7 @@ import {WpDestroyModal} from "core-components/modals/wp-destroy-modal/wp-destroy import {StateService} from "@uirouter/core"; import {InjectField} from "core-app/helpers/angular/inject-field.decorator"; import {TimeEntryCreateService} from "core-app/modules/time_entries/create/create.service"; +import {splitViewRoute} from "core-app/modules/work_packages/routing/split-view-routes.helper"; export class WorkPackageViewContextMenu extends OpContextMenuHandler { @@ -185,7 +186,9 @@ export class WorkPackageViewContextMenu extends OpContextMenuHandler { disabled: false, icon: 'icon-view-split', class: 'detailsViewMenuItem', - href: this.$state.href(this.baseRoute + '.details.overview', { workPackageId: this.workPackageId }), + href: this.$state.href( + splitViewRoute(this.$state) + '.overview', + { workPackageId: this.workPackageId }), linkText: I18n.t('js.button_open_details'), onClick: ($event:JQuery.TriggeredEvent) => { if (LinkHandling.isClickedWithModifier($event)) { @@ -193,7 +196,7 @@ export class WorkPackageViewContextMenu extends OpContextMenuHandler { } this.$state.go( - this.baseRoute + '.details.overview', + splitViewRoute(this.$state) + '.overview', { workPackageId: this.workPackageId } ); return true; diff --git a/frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.ts b/frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.ts index 1efe05d3eb..ec562cf742 100644 --- a/frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.ts +++ b/frontend/src/app/components/wp-card-view/wp-single-card/wp-single-card.component.ts @@ -18,7 +18,7 @@ import {I18nService} from "core-app/modules/common/i18n/i18n.service"; import {CardHighlightingMode} from "core-components/wp-fast-table/builders/highlighting/highlighting-mode.const"; import {CardViewOrientation} from "core-components/wp-card-view/wp-card-view.component"; import {UntilDestroyedMixin} from "core-app/helpers/angular/until-destroyed.mixin"; - +import {splitViewRoute} from "core-app/modules/work_packages/routing/split-view-routes.helper"; @Component({ selector: 'wp-single-card', @@ -73,7 +73,7 @@ export class WorkPackageSingleCardComponent extends UntilDestroyedMixin implemen let classIdentifier = this.classIdentifier(wp); this.wpTableSelection.setSelection(wp.id!, this.cardView.findRenderedCard(classIdentifier)); this.$state.go( - '.details', + splitViewRoute(this.$state), { workPackageId: wp.id! } ); } diff --git a/frontend/src/app/components/wp-new/wp-create.component.ts b/frontend/src/app/components/wp-new/wp-create.component.ts index 13fbfb3c0f..6755598aea 100644 --- a/frontend/src/app/components/wp-new/wp-create.component.ts +++ b/frontend/src/app/components/wp-new/wp-create.component.ts @@ -45,10 +45,11 @@ import {EditFormComponent} from "core-app/modules/fields/edit/edit-form/edit-for import {WorkPackageNotificationService} from "core-app/modules/work_packages/notifications/work-package-notification.service"; import * as URI from 'urijs'; import {UntilDestroyedMixin} from "core-app/helpers/angular/until-destroyed.mixin"; +import {splitViewRoute} from "core-app/modules/work_packages/routing/split-view-routes.helper"; @Directive() export class WorkPackageCreateComponent extends UntilDestroyedMixin implements OnInit { - public successState:string = this.$state.current.data.baseRoute + '.details'; + public successState:string = splitViewRoute(this.$state); public cancelState:string = this.$state.current.data.baseRoute; public newWorkPackage:WorkPackageResource; public parentWorkPackage:WorkPackageResource; diff --git a/frontend/src/app/modules/work_packages/routing/split-view-routes.helper.ts b/frontend/src/app/modules/work_packages/routing/split-view-routes.helper.ts new file mode 100644 index 0000000000..3e5f4ebfdd --- /dev/null +++ b/frontend/src/app/modules/work_packages/routing/split-view-routes.helper.ts @@ -0,0 +1,39 @@ +// -- 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-2013 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. +// ++ + +import {StateService} from "@uirouter/angular"; + +/** + * Returns the path to the split view based on the current route + * + * @param state State service + */ +export function splitViewRoute(state:StateService):string { + const baseRoute = state.current.data.baseRoute || ''; + return baseRoute + '.details'; +} diff --git a/spec/features/work_packages/navigation_spec.rb b/spec/features/work_packages/navigation_spec.rb index b619693b90..ba809fccd4 100644 --- a/spec/features/work_packages/navigation_spec.rb +++ b/spec/features/work_packages/navigation_spec.rb @@ -260,4 +260,27 @@ RSpec.feature 'Work package navigation', js: true, selenium: true do expect(page).to have_selector('.work-package--attachments--filename', text: 'attachment-first.pdf', wait: 10) end end + + context 'two work packages with card view' do + let!(:work_package) { FactoryBot.create :work_package, project: project } + let!(:work_package2) { FactoryBot.create :work_package, project: project } + let(:display_representation) { ::Components::WorkPackages::DisplayRepresentation.new } + let(:wp_table) { ::Pages::WorkPackagesTable.new(project) } + let(:cards) { ::Pages::WorkPackageCards.new(project) } + + it 'can move between card details using info icon (Regression #33451)' do + wp_table.visit! + wp_table.expect_work_package_listed work_package, work_package2 + display_representation.switch_to_card_layout + cards.expect_work_package_listed work_package, work_package2 + + # move to first details + split = cards.open_full_screen_by_details work_package + split.expect_subject + + # move to second details + split2 = cards.open_full_screen_by_details work_package2 + split2.expect_subject + end + end end diff --git a/spec/support/pages/work_packages/work_package_cards.rb b/spec/support/pages/work_packages/work_package_cards.rb index 2e9124dc7f..e0b95690c7 100644 --- a/spec/support/pages/work_packages/work_package_cards.rb +++ b/spec/support/pages/work_packages/work_package_cards.rb @@ -76,6 +76,8 @@ module Pages scroll_to_element(element) element.hover element.find('.wp-card--details-button').click + + ::Pages::SplitWorkPackage.new(work_package, project) end def select_work_package(work_package)