Add context menu for "toggle-view" button to switch between the work package views

pull/7548/head
Henriette Dinger 5 years ago
parent f2a9e53a35
commit ecef1041c2
  1. 5
      config/locales/js-en.yml
  2. 107
      frontend/src/app/components/op-context-menu/handlers/wp-view-dropdown-menu.directive.ts
  3. 13
      frontend/src/app/components/wp-buttons/wp-details-view-button/wp-details-view-button.component.ts
  4. 16
      frontend/src/app/components/wp-buttons/wp-timeline-toggle-button/wp-timeline-toggle-button.component.ts
  5. 79
      frontend/src/app/components/wp-buttons/wp-view-toggle-button/work-package-view-toggle-button.component.ts
  6. 2
      frontend/src/app/modules/work_packages/openproject-work-packages.module.ts

@ -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'

@ -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 {
WorkPackageDisplayRepresentationService,
wpDisplayCardRepresentation,
wpDisplayListRepresentation
} from "core-components/wp-fast-table/state/work-package-display-representation.service";
import {I18nService} from "core-app/modules/common/i18n/i18n.service";
import {WorkPackageTableTimelineService} from "core-components/wp-fast-table/state/wp-table-timeline.service";
@Directive({
selector: '[wpViewDropdown]'
})
export class WorkPackageViewDropdownMenuDirective extends OpContextMenuTrigger {
constructor(readonly elementRef:ElementRef,
readonly opContextMenu:OPContextMenuService,
readonly I18n:I18nService,
readonly wpDisplayRepresentationService:WorkPackageDisplayRepresentationService,
readonly wpTableTimeline:WorkPackageTableTimelineService) {
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;
}
}
];
}
}

@ -33,8 +33,6 @@ import {StateService, TransitionService} from '@uirouter/core';
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit} 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',
@ -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');
@ -77,13 +73,6 @@ export class WorkPackageDetailsViewButtonComponent extends AbstractWorkPackageBu
}
public ngOnInit() {
this.wpDisplayRepresentationService.live$()
.pipe(
untilComponentDestroyed(this)
)
.subscribe(() => {
this.cdRef.detectChanges();
});
}
public ngOnDestroy() {

@ -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 {

@ -39,52 +39,22 @@ import {untilComponentDestroyed} from "ng2-rx-componentdestroyed";
@Component({
template: `
<ul class="toolbar-button-group">
<li>
<button class="button"
type="button"
[ngClass]="{ '-active': inListView }"
[disabled]="inListView"
id="wp-view-toggle-button--list"
[attr.title]="listLabel"
[attr.accesskey]="accessKey"
(accessibleClick)="performAction($event)">
<op-icon icon-classes="{{ iconListView }} button--icon"></op-icon>
</button>
</li>
<li>
<button class="button"
[ngClass]="{ '-active': !inListView }"
id="wp-view-toggle-button--card"
[attr.title]="cardLabel"
[disabled]="!inListView"
(click)="performAction($event)">
<op-icon icon-classes="{{ iconCardView }} button--icon"></op-icon>
</button>
</li>
</ul>
template: `
<button class="button"
wpViewDropdown>
<op-icon icon-classes="button--icon"></op-icon>
<span class="button--text"
aria-hidden="true"></span>
<op-icon icon-classes="button--icon icon-small icon-pulldown"></op-icon>
</button>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'wp-view-toggle-button',
})
export class WorkPackageViewToggleButton extends AbstractWorkPackageButtonComponent implements OnInit, OnDestroy {
public iconListView:string = 'icon-view-list';
public iconCardView:string = 'icon-view-card';
public inListView:boolean = true;
public cardLabel:string;
public listLabel:string;
constructor(readonly $state:StateService,
readonly I18n:I18nService,
export class WorkPackageViewToggleButton implements OnInit, OnDestroy {
constructor(readonly I18n:I18nService,
readonly cdRef:ChangeDetectorRef,
readonly wpDisplayRepresentationService:WorkPackageViewDisplayRepresentationService) {
super(I18n);
this.cardLabel = I18n.t('js.button_card_list');
this.listLabel = I18n.t('js.button_show_list');
}
ngOnInit() {
@ -93,40 +63,13 @@ export class WorkPackageViewToggleButton extends AbstractWorkPackageButtonCompon
untilComponentDestroyed(this)
)
.subscribe(() => {
this.inListView = this.wpDisplayRepresentationService.current !== wpDisplayCardRepresentation;
this.cdRef.detectChanges();
});
}
ngOnDestroy() {
//
}
public performAction(evt:Event):false {
if (this.inListView) {
this.activateCardView();
} else {
this.activateListView();
}
evt.preventDefault();
return false;
// Nothing to do
}
private activateCardView() {
this.inListView = false;
this.wpDisplayRepresentationService.setDisplayRepresentation(wpDisplayCardRepresentation);
this.cdRef.detectChanges();
}
private activateListView() {
this.inListView = true;
this.wpDisplayRepresentationService.setDisplayRepresentation(wpDisplayListRepresentation);
this.cdRef.detectChanges();
}
}
DynamicBootstrapper.register({ selector: 'wp-view-toggle-button', cls: WorkPackageViewToggleButton });

@ -158,6 +158,7 @@ import {WorkPackagesTableConfigMenu} from "core-components/wp-table/config-menu/
import {WorkPackageIsolatedGraphQuerySpaceDirective} from "core-app/modules/work_packages/query-space/wp-isolated-graph-query-space.directive";
import {WorkPackageViewToggleButton} from "core-components/wp-buttons/wp-view-toggle-button/work-package-view-toggle-button.component";
import {WorkPackagesGridComponent} from "core-components/wp-grid/wp-grid.component";
import {WorkPackageViewDropdownMenuDirective} from "core-components/op-context-menu/handlers/wp-view-dropdown-menu.directive";
@NgModule({
@ -275,6 +276,7 @@ import {WorkPackagesGridComponent} from "core-components/wp-grid/wp-grid.compone
WorkPackageCreateSettingsMenuDirective,
WorkPackageSingleContextMenuDirective,
WorkPackageQuerySelectDropdownComponent,
WorkPackageViewDropdownMenuDirective,
// Timeline
WorkPackageTimelineButtonComponent,

Loading…
Cancel
Save