diff --git a/app/assets/javascripts/onboarding/work_package_tour.js b/app/assets/javascripts/onboarding/work_package_tour.js
index 38329ef4a2..9b3d56ff1d 100644
--- a/app/assets/javascripts/onboarding/work_package_tour.js
+++ b/app/assets/javascripts/onboarding/work_package_tour.js
@@ -37,16 +37,18 @@
resolve();
});
});
-
+ },
+ onNext: function () {
+ $('#wp-view-toggle-button').click();
}
},
{
- 'next .timeline-toolbar--button': I18n.t('js.onboarding.steps.wp.timeline_button'),
+ 'next #wp-view-toggle-button': I18n.t('js.onboarding.steps.wp.timeline_button'),
'showSkip': false,
'nextButton': {text: I18n.t('js.onboarding.buttons.next')},
- 'shape': 'circle',
+ 'bottom': '-100',
onNext: function () {
- $('.timeline-toolbar--button')[0].click();
+ $('#wp-view-context-menu .icon-view-timeline')[0].click();
}
},
{
diff --git a/config/locales/js-en.yml b/config/locales/js-en.yml
index ccea0324fc..1771fff6b5 100644
--- a/config/locales/js-en.yml
+++ b/config/locales/js-en.yml
@@ -917,3 +917,8 @@ en:
all_projects: "all projects"
project_and_subprojects: "and all subprojects"
search_for: "Search for"
+
+ views:
+ card: 'Cards'
+ list: 'Table'
+ timeline: 'Gantt'
diff --git a/frontend/src/app/components/op-context-menu/handlers/wp-view-dropdown-menu.directive.ts b/frontend/src/app/components/op-context-menu/handlers/wp-view-dropdown-menu.directive.ts
new file mode 100644
index 0000000000..df353a84b6
--- /dev/null
+++ b/frontend/src/app/components/op-context-menu/handlers/wp-view-dropdown-menu.directive.ts
@@ -0,0 +1,107 @@
+//-- 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 {OPContextMenuService} from "core-components/op-context-menu/op-context-menu.service";
+import {Directive, ElementRef} from "@angular/core";
+import {OpContextMenuTrigger} from "core-components/op-context-menu/handlers/op-context-menu-trigger.directive";
+import {I18nService} from "core-app/modules/common/i18n/i18n.service";
+import {
+ WorkPackageViewDisplayRepresentationService,
+ wpDisplayCardRepresentation,
+ wpDisplayListRepresentation
+} from "core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service";
+import {WorkPackageViewTimelineService} from "core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service";
+
+@Directive({
+ selector: '[wpViewDropdown]'
+})
+export class WorkPackageViewDropdownMenuDirective extends OpContextMenuTrigger {
+ constructor(readonly elementRef:ElementRef,
+ readonly opContextMenu:OPContextMenuService,
+ readonly I18n:I18nService,
+ readonly wpDisplayRepresentationService:WorkPackageViewDisplayRepresentationService,
+ readonly wpTableTimeline:WorkPackageViewTimelineService) {
+
+ super(elementRef, opContextMenu);
+ }
+
+ protected open(evt:JQueryEventObject) {
+ this.buildItems();
+ this.opContextMenu.show(this, evt);
+ }
+
+ public get locals() {
+ return {
+ items: this.items,
+ contextMenuId: 'wp-view-context-menu'
+ };
+ }
+
+ private buildItems() {
+ this.items = [
+ {
+ // Card View
+ linkText: this.I18n.t('js.views.card'),
+ icon: 'icon-view-card',
+ onClick: (evt:any) => {
+ this.wpDisplayRepresentationService.setDisplayRepresentation(wpDisplayCardRepresentation);
+ if (this.wpTableTimeline.isVisible) {
+ // Necessary for the timeline buttons to disappear
+ this.wpTableTimeline.toggle();
+ }
+ return true;
+ }
+ },
+ {
+ // List View
+ linkText: this.I18n.t('js.views.list'),
+ icon: 'icon-view-list',
+ onClick: (evt:any) => {
+ this.wpDisplayRepresentationService.setDisplayRepresentation(wpDisplayListRepresentation);
+ if (this.wpTableTimeline.isVisible) {
+ this.wpTableTimeline.toggle();
+ }
+ return true;
+ }
+ },
+ {
+ // List View with enabled Gantt
+ linkText: this.I18n.t('js.views.timeline'),
+ icon: 'icon-view-timeline',
+ onClick: (evt:any) => {
+ this.wpDisplayRepresentationService.setDisplayRepresentation(wpDisplayListRepresentation);
+ if (!this.wpTableTimeline.isVisible) {
+ this.wpTableTimeline.toggle();
+ }
+ return true;
+ }
+ }
+ ];
+ }
+}
+
diff --git a/frontend/src/app/components/wp-buttons/wp-details-view-button/wp-details-view-button.component.ts b/frontend/src/app/components/wp-buttons/wp-details-view-button/wp-details-view-button.component.ts
index 7580989f3d..edc273c828 100644
--- a/frontend/src/app/components/wp-buttons/wp-details-view-button/wp-details-view-button.component.ts
+++ b/frontend/src/app/components/wp-buttons/wp-details-view-button/wp-details-view-button.component.ts
@@ -30,18 +30,16 @@ import {KeepTabService} from '../../wp-single-view-tabs/keep-tab/keep-tab.servic
import {States} from '../../states.service';
import {WorkPackageViewFocusService} from 'core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-focus.service';
import {StateService, TransitionService} from '@uirouter/core';
-import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit} from '@angular/core';
+import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy} from '@angular/core';
import {AbstractWorkPackageButtonComponent} from 'core-components/wp-buttons/wp-buttons.module';
import {I18nService} from "core-app/modules/common/i18n/i18n.service";
-import {untilComponentDestroyed} from "ng2-rx-componentdestroyed";
-import {WorkPackageViewDisplayRepresentationService} from "core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service";
@Component({
templateUrl: '../wp-button.template.html',
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'wp-details-view-button',
})
-export class WorkPackageDetailsViewButtonComponent extends AbstractWorkPackageButtonComponent implements OnInit, OnDestroy {
+export class WorkPackageDetailsViewButtonComponent extends AbstractWorkPackageButtonComponent implements OnDestroy {
public projectIdentifier:string;
public accessKey:number = 8;
public activeState:string = 'work-packages.list.details';
@@ -62,9 +60,7 @@ export class WorkPackageDetailsViewButtonComponent extends AbstractWorkPackageBu
readonly cdRef:ChangeDetectorRef,
public states:States,
public wpTableFocus:WorkPackageViewFocusService,
- public keepTab:KeepTabService,
- public wpDisplayRepresentationService:WorkPackageViewDisplayRepresentationService) {
-
+ public keepTab:KeepTabService) {
super(I18n);
this.activateLabel = I18n.t('js.button_open_details');
@@ -76,16 +72,6 @@ export class WorkPackageDetailsViewButtonComponent extends AbstractWorkPackageBu
});
}
- public ngOnInit() {
- this.wpDisplayRepresentationService.live$()
- .pipe(
- untilComponentDestroyed(this)
- )
- .subscribe(() => {
- this.cdRef.detectChanges();
- });
- }
-
public ngOnDestroy() {
this.transitionListener();
}
diff --git a/frontend/src/app/components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.component.ts b/frontend/src/app/components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.component.ts
index 5ed82bbda9..ea01998808 100644
--- a/frontend/src/app/components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.component.ts
+++ b/frontend/src/app/components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.component.ts
@@ -31,10 +31,6 @@ import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit
import {I18nService} from 'core-app/modules/common/i18n/i18n.service';
import {TimelineZoomLevel} from 'core-app/modules/hal/resources/query-resource';
import {untilComponentDestroyed} from "ng2-rx-componentdestroyed";
-import {
- WorkPackageViewDisplayRepresentationService,
- wpDisplayCardRepresentation
-} from "core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-display-representation.service";
import {WorkPackageViewTimelineService} from "core-app/modules/work_packages/routing/wp-view-base/view-services/wp-view-timeline.service";
export interface TimelineButtonText extends ButtonControllerText {
@@ -67,8 +63,7 @@ export class WorkPackageTimelineButtonComponent extends AbstractWorkPackageButto
constructor(readonly I18n:I18nService,
readonly cdRef:ChangeDetectorRef,
- public wpTableTimeline:WorkPackageViewTimelineService,
- public wpDisplayRepresentationService:WorkPackageViewDisplayRepresentationService) {
+ public wpTableTimeline:WorkPackageViewTimelineService) {
super(I18n);
this.activateLabel = I18n.t('js.timelines.button_activate');
@@ -102,15 +97,6 @@ export class WorkPackageTimelineButtonComponent extends AbstractWorkPackageButto
this.isMinLevel = current === this.minZoomLevel;
this.cdRef.detectChanges();
});
-
- this.wpDisplayRepresentationService.live$()
- .pipe(
- untilComponentDestroyed(this)
- )
- .subscribe(() => {
- this.disabled = this.wpDisplayRepresentationService.current === wpDisplayCardRepresentation;
- this.cdRef.detectChanges();
- });
}
ngOnDestroy():void {
diff --git a/frontend/src/app/components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.html b/frontend/src/app/components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.html
index 21b751cc61..6a4ad8e322 100644
--- a/frontend/src/app/components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.html
+++ b/frontend/src/app/components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.html
@@ -30,16 +30,4 @@