Let WP back button go back to where the user came from

pull/7112/head
Henriette Dinger 6 years ago
parent 61ca8b3962
commit 0567549ef4
  1. 2
      app/assets/stylesheets/layout/_base.sass
  2. 1
      config/locales/js-en.yml
  3. 5
      frontend/src/app/modules/calendar/openproject-calendar.module.ts
  4. 51
      frontend/src/app/modules/common/back-routing/back-routing.service.ts
  5. 2
      frontend/src/app/modules/common/openproject-common.module.ts
  6. 7
      frontend/src/app/modules/router/openproject.routes.ts
  7. 54
      frontend/src/app/modules/work_packages/routing/work-packages-routes.ts
  8. 10
      frontend/src/app/modules/work_packages/routing/wp-full-view/wp-full-view.component.ts
  9. 6
      frontend/src/app/modules/work_packages/routing/wp-full-view/wp-full-view.html

@ -72,4 +72,4 @@
background-color: $body-background
.-draggable
cursor: move
cursor: grab

@ -52,6 +52,7 @@ en:
copied_successful: "Sucessfully copied to clipboard!"
button_add_watcher: "Add watcher"
button_back: "Back"
button_back_to_list_view: "Back to list view"
button_cancel: "Cancel"
button_close: "Close"

@ -42,7 +42,10 @@ export const CALENDAR_ROUTES:Ng2StateDeclaration[] = [
name: 'work-packages.calendar',
url: '/calendar',
component: WorkPackagesCalendarEntryComponent,
reloadOnSearch: false
reloadOnSearch: false,
data: {
parent: 'work-packages'
}
}
];

@ -0,0 +1,51 @@
// -- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// 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 doc/COPYRIGHT.rdoc for more details.
// ++
import {Injectable, Injector} from '@angular/core';
import {StateService} from "@uirouter/core";
@Injectable()
export class BackRoutingService {
public backRoute:string|undefined;
private $state:StateService = this.injector.get(StateService);
constructor(protected injector:Injector) {
}
public goBack() {
if (this.backRoute){
this.$state.go(this.backRoute, this.$state.params);
} else {
this.$state.go('work-packages.list', this.$state.params);
}
}
public setBackRoute(route:string|undefined) {
this.backRoute = route;
}
}

@ -79,6 +79,7 @@ import {BrowserDetector} from "core-app/modules/common/browser/browser-detector.
import {EditableToolbarTitleComponent} from "core-app/modules/common/editable-toolbar-title/editable-toolbar-title.component";
import {UserAvatarComponent} from "core-components/user/user-avatar/user-avatar.component";
import {GonService} from "core-app/modules/common/gon/gon.service";
import {BackRoutingService} from "core-app/modules/common/back-routing/back-routing.service";
export function bootstrapModule(injector:Injector) {
return () => {
@ -250,6 +251,7 @@ export function bootstrapModule(injector:Injector) {
TimezoneService,
BrowserDetector,
GonService,
BackRoutingService,
]
})
export class OpenprojectCommonModule { }

@ -33,6 +33,7 @@ import {Injector} from "@angular/core";
import {FirstRouteService} from "core-app/modules/router/first-route-service";
import {StatesModule} from "@uirouter/angular";
import {appBaseSelector, ApplicationBaseComponent} from "core-app/modules/router/base/application-base.component";
import {BackRoutingService} from "core-app/modules/common/back-routing/back-routing.service";
export const OPENPROJECT_ROUTES = [
{
@ -98,6 +99,7 @@ export function initializeUiRouterListeners(injector:Injector) {
const notificationsService:NotificationsService = injector.get(NotificationsService);
const currentProject:CurrentProjectService = injector.get(CurrentProjectService);
const firstRoute:FirstRouteService = injector.get(FirstRouteService);
const backRoutingService:BackRoutingService = injector.get(BackRoutingService);
// Check whether we are running within our complete app, or only within some other bootstrapped
// component
@ -133,6 +135,11 @@ export function initializeUiRouterListeners(injector:Injector) {
return $state.target(transition.to(), paramsCopy);
}
// Set backRoute to know where we came from
if (fromState.data && toState.data && fromState.data.parent !== toState.data.parent){
backRoutingService.setBackRoute(fromState.name);
}
// Reset profiler, if we're actually profiling
const profiler:any = (window as any).MiniProfiler;
profiler && profiler.pageTransition();

@ -81,30 +81,39 @@ export const WORK_PACKAGES_ROUTES:Ng2StateDeclaration[] = [
url: '/{workPackageId:[0-9]+}',
// Redirect to 'activity' by default.
redirectTo: 'work-packages.show.activity',
component: WorkPackagesFullViewComponent,
data: {
bodyClasses: 'action-show'
}
component: WorkPackagesFullViewComponent
},
{
name: 'work-packages.show.activity',
url: '/activity',
component: WorkPackageActivityTabComponent
component: WorkPackageActivityTabComponent,
data: {
parent: 'work-packages.show'
}
},
{
name: 'work-packages.show.activity.details',
url: '/activity/details/#{activity_no:\d+}',
component: WorkPackageActivityTabComponent
component: WorkPackageActivityTabComponent,
data: {
parent: 'work-packages.show'
}
},
{
name: 'work-packages.show.relations',
url: '/relations',
component: WorkPackageRelationsTabComponent
component: WorkPackageRelationsTabComponent,
data: {
parent: 'work-packages.show'
}
},
{
name: 'work-packages.show.watchers',
url: '/watchers',
component: WorkPackageWatchersTabComponent
component: WorkPackageWatchersTabComponent,
data: {
parent: 'work-packages.show'
}
},
{
name: 'work-packages.list',
@ -122,7 +131,8 @@ export const WORK_PACKAGES_ROUTES:Ng2StateDeclaration[] = [
reloadOnSearch: false,
data: {
allowMovingInEditMode: true,
bodyClasses: 'action-create'
bodyClasses: 'action-create',
parent: 'work-packages.list'
},
},
{
@ -132,7 +142,8 @@ export const WORK_PACKAGES_ROUTES:Ng2StateDeclaration[] = [
reloadOnSearch: false,
data: {
allowMovingInEditMode: true,
bodyClasses: 'action-details'
bodyClasses: 'action-details',
parent: 'work-packages.list'
},
},
{
@ -154,27 +165,42 @@ export const WORK_PACKAGES_ROUTES:Ng2StateDeclaration[] = [
{
name: 'work-packages.list.details.overview',
url: '/overview',
component: WorkPackageOverviewTabComponent
component: WorkPackageOverviewTabComponent,
data: {
parent: 'work-packages.list.details'
}
},
{
name: 'work-packages.list.details.activity',
url: '/activity',
component: WorkPackageActivityTabComponent,
data: {
parent: 'work-packages.list.details'
}
},
{
name: 'work-packages.list.details.activity.details',
url: '/activity/details/#{activity_no:\d+}',
component: WorkPackageActivityTabComponent
component: WorkPackageActivityTabComponent,
data: {
parent: 'work-packages.list.details'
}
},
{
name: 'work-packages.list.details.relations',
url: '/relations',
component: WorkPackageRelationsTabComponent
component: WorkPackageRelationsTabComponent,
data: {
parent: 'work-packages.list.details'
}
},
{
name: 'work-packages.list.details.watchers',
url: '/watchers',
component: WorkPackageWatchersTabComponent
component: WorkPackageWatchersTabComponent,
data: {
parent: 'work-packages.list.details'
}
},
// Avoid lazy-loading the routes for now
// {

@ -37,6 +37,7 @@ import {States} from 'core-components/states.service';
import {KeepTabService} from 'core-components/wp-single-view-tabs/keep-tab/keep-tab.service';
import {FirstRouteService} from "core-app/modules/router/first-route-service";
import {WorkPackageSingleViewBase} from "core-app/modules/work_packages/routing/wp-view-base/work-package-single-view.base";
import {BackRoutingService} from "core-app/modules/common/back-routing/back-routing.service";
@Component({
templateUrl: './wp-full-view.html',
@ -63,6 +64,8 @@ export class WorkPackagesFullViewComponent extends WorkPackageSingleViewBase {
public actionsAvailable:any;
public triggerMoreMenuAction:Function;
public backRoutingService:BackRoutingService = this.injector.get(BackRoutingService);
constructor(public injector:Injector,
public states:States,
public firstRoute:FirstRouteService,
@ -89,13 +92,12 @@ export class WorkPackagesFullViewComponent extends WorkPackageSingleViewBase {
this.wpTableFocus.updateFocus(this.workPackage.id);
this.setWorkPackageScopeProperties(this.workPackage);
this.text.goToList = this.I18n.t('js.button_back_to_list_view');
this.text.goBack = this.I18n.t('js.button_back');
}
public goToList() {
this.$state.go('work-packages.list', this.$state.params);
public goBack() {
this.backRoutingService.goBack();
}
private setWorkPackageScopeProperties(wp:WorkPackageResource) {
this.isWatched = wp.hasOwnProperty('unwatch');
this.displayWatchButton = wp.hasOwnProperty('unwatch') || wp.hasOwnProperty('watch');

@ -9,10 +9,10 @@
<div id="toolbar">
<div class="wp-show--header-container">
<div class="wp-show--back-button hide-when-print">
<accessible-by-keyboard (execute)="goToList()"
<accessible-by-keyboard (execute)="goBack()"
linkClass="work-packages-list-view-button button"
[linkAriaLabel]="text.goToList"
[linkTitle]="text.goToList">
[linkAriaLabel]="text.goBack"
[linkTitle]="text.goBack">
<op-icon icon-classes="button--icon icon-back-up"></op-icon>
</accessible-by-keyboard>
</div>

Loading…
Cancel
Save