diff --git a/app/contracts/queries/base_contract.rb b/app/contracts/queries/base_contract.rb
index 6794647b61..23db2a6560 100644
--- a/app/contracts/queries/base_contract.rb
+++ b/app/contracts/queries/base_contract.rb
@@ -44,6 +44,7 @@ module Queries
attribute :highlighting_mode
attribute :highlighted_attributes
attribute :show_hierarchies
+ attribute :display_representation
attribute :column_names # => columns
attribute :filters
diff --git a/app/services/api/v3/parse_query_params_service.rb b/app/services/api/v3/parse_query_params_service.rb
index a69cbcf520..aba01ea972 100644
--- a/app/services/api/v3/parse_query_params_service.rb
+++ b/app/services/api/v3/parse_query_params_service.rb
@@ -56,6 +56,8 @@ module API
parsed_params[:highlighted_attributes] = highlighted_attributes_from_params(params)
+ parsed_params[:display_representation] = params[:displayRepresentation]
+
parsed_params[:show_hierarchies] = boolearize(params[:showHierarchies])
allow_empty = params.keys + skip_empty
diff --git a/app/services/update_query_from_params_service.rb b/app/services/update_query_from_params_service.rb
index ba6aa9babc..d7d5687935 100644
--- a/app/services/update_query_from_params_service.rb
+++ b/app/services/update_query_from_params_service.rb
@@ -49,6 +49,8 @@ class UpdateQueryFromParamsService
apply_highlighting(params)
+ apply_display_representation(params)
+
disable_hierarchy_when_only_grouped_by(params)
if valid_subset
@@ -106,6 +108,10 @@ class UpdateQueryFromParamsService
query.highlighted_attributes = params[:highlighted_attributes] if params.key?(:highlighted_attributes)
end
+ def apply_display_representation(params)
+ query.display_representation = params[:display_representation] if params.key?(:display_representation)
+ end
+
def disable_hierarchy_when_only_grouped_by(params)
if params.key?(:group_by) && !params.key?(:show_hierarchies)
query.show_hierarchies = false
diff --git a/config/locales/js-en.yml b/config/locales/js-en.yml
index 5858632ff7..96d3a5fc61 100644
--- a/config/locales/js-en.yml
+++ b/config/locales/js-en.yml
@@ -84,6 +84,8 @@ en:
button_open_details: "Open details view"
button_close_details: "Close details view"
button_open_fullscreen: "Open fullscreen view"
+ button_show_cards: "Show card view"
+ button_show_list: "Show list view"
button_quote: "Quote"
button_save: "Save"
button_settings: "Settings"
diff --git a/db/migrate/20190716071941_add_display_representation_to_query.rb b/db/migrate/20190716071941_add_display_representation_to_query.rb
new file mode 100644
index 0000000000..99b494bb2d
--- /dev/null
+++ b/db/migrate/20190716071941_add_display_representation_to_query.rb
@@ -0,0 +1,5 @@
+class AddDisplayRepresentationToQuery < ActiveRecord::Migration[5.2]
+ def change
+ add_column :queries, :display_representation, :text
+ end
+end
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 3cad1195ad..dc1c8352f7 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,15 +30,20 @@ import {KeepTabService} from '../../wp-single-view-tabs/keep-tab/keep-tab.servic
import {States} from '../../states.service';
import {WorkPackageTableFocusService} from 'core-components/wp-fast-table/state/wp-table-focus.service';
import {StateService} from '@uirouter/core';
-import {Component} from '@angular/core';
+import {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 {
+ WorkPackageDisplayRepresentationService,
+ wpDisplayCardRepresentation
+} from "core-components/wp-fast-table/state/work-package-display-representation.service";
@Component({
templateUrl: '../wp-button.template.html',
selector: 'wp-details-view-button',
})
-export class WorkPackageDetailsViewButtonComponent extends AbstractWorkPackageButtonComponent {
+export class WorkPackageDetailsViewButtonComponent extends AbstractWorkPackageButtonComponent implements OnInit, OnDestroy {
public projectIdentifier:string;
public accessKey:number = 8;
public activeState:string = 'work-packages.list.details';
@@ -55,7 +60,9 @@ export class WorkPackageDetailsViewButtonComponent extends AbstractWorkPackageBu
readonly I18n:I18nService,
public states:States,
public wpTableFocus:WorkPackageTableFocusService,
- public keepTab:KeepTabService) {
+ public keepTab:KeepTabService,
+ public wpDisplayRepresentationService:WorkPackageDisplayRepresentationService,
+ public cdRef:ChangeDetectorRef) {
super(I18n);
@@ -63,6 +70,21 @@ export class WorkPackageDetailsViewButtonComponent extends AbstractWorkPackageBu
this.deactivateLabel = I18n.t('js.button_close_details');
}
+ public ngOnInit() {
+ this.wpDisplayRepresentationService.state.values$()
+ .pipe(
+ untilComponentDestroyed(this)
+ )
+ .subscribe(() => {
+ this.disabled = this.wpDisplayRepresentationService.current === wpDisplayCardRepresentation;
+ this.cdRef.detectChanges();
+ });
+ }
+
+ public ngOnDestroy() {
+ // Nothing to do
+ }
+
public get label():string {
if (this.isActive()) {
return this.deactivateLabel;
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 66e92a9733..1c92bda153 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
@@ -32,6 +32,10 @@ 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 {componentDestroyed, untilComponentDestroyed} from "ng2-rx-componentdestroyed";
+import {
+ WorkPackageDisplayRepresentationService,
+ wpDisplayCardRepresentation
+} from "core-components/wp-fast-table/state/work-package-display-representation.service";
export interface TimelineButtonText extends ButtonControllerText {
zoomOut:string;
@@ -64,7 +68,8 @@ export class WorkPackageTimelineButtonComponent extends AbstractWorkPackageButto
constructor(readonly I18n:I18nService,
readonly cdRef:ChangeDetectorRef,
- public wpTableTimeline:WorkPackageTableTimelineService) {
+ public wpTableTimeline:WorkPackageTableTimelineService,
+ public wpDisplayRepresentationService:WorkPackageDisplayRepresentationService) {
super(I18n);
this.activateLabel = I18n.t('js.timelines.button_activate');
@@ -95,6 +100,15 @@ export class WorkPackageTimelineButtonComponent extends AbstractWorkPackageButto
this.isMinLevel = current === this.minZoomLevel;
this.cdRef.detectChanges();
});
+
+ this.wpDisplayRepresentationService.state.values$()
+ .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-view-toggle-button/work-package-view-toggle-button.component.ts b/frontend/src/app/components/wp-buttons/wp-view-toggle-button/work-package-view-toggle-button.component.ts
new file mode 100644
index 0000000000..5901e9c29b
--- /dev/null
+++ b/frontend/src/app/components/wp-buttons/wp-view-toggle-button/work-package-view-toggle-button.component.ts
@@ -0,0 +1,136 @@
+// -- 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 {AbstractWorkPackageButtonComponent} from '../wp-buttons.module';
+import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit} from '@angular/core';
+import {I18nService} from 'core-app/modules/common/i18n/i18n.service';
+import {DynamicBootstrapper} from "core-app/globals/dynamic-bootstrapper";
+import {StateService} from "@uirouter/core";
+import {
+ WorkPackageDisplayRepresentationService, wpDisplayCardRepresentation,
+ wpDisplayListRepresentation
+} from "core-components/wp-fast-table/state/work-package-display-representation.service";
+import {untilComponentDestroyed} from "ng2-rx-componentdestroyed";
+
+
+@Component({
+ template: `
+
+
+
+
+
+
+
+
+`,
+ 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-image2';
+
+ public inListView:boolean = true;
+
+ public cardLabel:string;
+ public listLabel:string;
+
+ constructor(readonly $state:StateService,
+ readonly I18n:I18nService,
+ readonly cdRef:ChangeDetectorRef,
+ readonly wpDisplayRepresentationService:WorkPackageDisplayRepresentationService) {
+ super(I18n);
+
+ this.cardLabel = I18n.t('js.button_card_list');
+ this.listLabel = I18n.t('js.button_show_list');
+ }
+
+ ngOnInit() {
+ this.wpDisplayRepresentationService.state.values$()
+ .pipe(
+ untilComponentDestroyed(this)
+ )
+ .subscribe(() => {
+ this.inListView = this.wpDisplayRepresentationService.current !== wpDisplayCardRepresentation;
+ this.cdRef.detectChanges();
+ });
+ }
+
+ ngOnDestroy() {
+ //
+ }
+
+ public isActive():boolean {
+ return false;
+ }
+
+ public performAction(evt:Event):false {
+ if (this.inListView) {
+ this.activateCardView();
+ } else {
+ this.activateListView();
+ }
+
+ evt.preventDefault();
+ return false;
+ }
+
+ 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 });
diff --git a/frontend/src/app/components/wp-card-view/wp-card-view-horizontal.sass b/frontend/src/app/components/wp-card-view/wp-card-view-horizontal.sass
new file mode 100644
index 0000000000..b9c1ea5df4
--- /dev/null
+++ b/frontend/src/app/components/wp-card-view/wp-card-view-horizontal.sass
@@ -0,0 +1,4 @@
+.wp-cards-container.-horizontal
+ display: grid
+ grid-template-columns: repeat(auto-fit, minmax(100px, 300px))
+ grid-column-gap: 10px
diff --git a/frontend/src/app/components/wp-card-view/wp-card-view-vertical.sass b/frontend/src/app/components/wp-card-view/wp-card-view-vertical.sass
new file mode 100644
index 0000000000..21d2f7725c
--- /dev/null
+++ b/frontend/src/app/components/wp-card-view/wp-card-view-vertical.sass
@@ -0,0 +1,19 @@
+@import 'helpers'
+
+.wp-cards-container.-vertical
+ display: flex
+ flex-direction: column
+ // Ensure 100% height for drag & drop area
+ height: 100%
+ // Some minor left/right padding
+ padding: 0 15px
+ border-radius: 2px
+ // We let the scrollbar be always there, so that we can align the button above with the card view
+ // independently of whether we scroll or not.
+ overflow-y: scroll
+ @include styled-scroll-bar
+
+ .wp-card
+ // Take care that the shadow of the last element is still visible
+ &:last-of-type
+ margin-bottom: 3px
diff --git a/frontend/src/app/components/wp-card-view/wp-card-view.component.html b/frontend/src/app/components/wp-card-view/wp-card-view.component.html
index 213f966f63..bb1fdd3eab 100644
--- a/frontend/src/app/components/wp-card-view/wp-card-view.component.html
+++ b/frontend/src/app/components/wp-card-view/wp-card-view.component.html
@@ -1,5 +1,5 @@
Promise;
@Input() public showStatusButton:boolean = true;
+ @Input() public orientation:CardViewOrientation = 'vertical';
+ /** Whether cards are removable */
+ @Input() public cardsRemovable:boolean = false;
+
+ /** Container reference */
+ @ViewChild('container') public container:ElementRef;
+
+ @Output() onMoved = new EventEmitter();
- public trackByHref = AngularTrackingHelpers.trackByHref;
+ public trackByHref = AngularTrackingHelpers.trackByHrefAndProperty('lockVersion');
public query:QueryResource;
private _workPackages:WorkPackageResource[];
public columns:QueryColumn[];
@@ -71,12 +81,6 @@ export class WorkPackageCardViewComponent implements OnInit {
onReferenced: (wp:WorkPackageResource) => this.addWorkPackageToQuery(wp, 0)
};
- /** Whether cards are removable */
- @Input() public cardsRemovable:boolean = false;
-
- /** Container reference */
- @ViewChild('container') public container:ElementRef;
-
/** Whether the card view has an active inline created wp */
public activeInlineCreateWp?:WorkPackageResource;
@@ -209,6 +213,8 @@ export class WorkPackageCardViewComponent implements OnInit {
const newOrder = this.reorderService.move(this.currentOrder, wpId, toIndex);
this.updateOrder(newOrder);
+
+ this.onMoved.emit();
},
onRemoved: (card:HTMLElement) => {
const wpId:string = card.dataset.workPackageId!;
diff --git a/frontend/src/app/components/wp-fast-table/builders/highlighting/highlighting-mode.const.ts b/frontend/src/app/components/wp-fast-table/builders/highlighting/highlighting-mode.const.ts
index b0734d5bd9..ec08dfd651 100644
--- a/frontend/src/app/components/wp-fast-table/builders/highlighting/highlighting-mode.const.ts
+++ b/frontend/src/app/components/wp-fast-table/builders/highlighting/highlighting-mode.const.ts
@@ -1,3 +1,3 @@
export type HighlightingMode = 'status'|'priority'|'type'|'inline'|'none';
-export type CardHighlightingMode = 'priority'|'type'|'none'|'entire-card';
+export type CardHighlightingMode = 'priority'|'type'|'none'|'inline';
diff --git a/frontend/src/app/components/wp-fast-table/state/work-package-display-representation.service.ts b/frontend/src/app/components/wp-fast-table/state/work-package-display-representation.service.ts
new file mode 100644
index 0000000000..ecd503ff27
--- /dev/null
+++ b/frontend/src/app/components/wp-fast-table/state/work-package-display-representation.service.ts
@@ -0,0 +1,73 @@
+// -- 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 {QueryResource} from 'core-app/modules/hal/resources/query-resource';
+import {WorkPackageQueryStateService} from './wp-table-base.service';
+import {States} from 'core-components/states.service';
+import {IsolatedQuerySpace} from "core-app/modules/work_packages/query-space/isolated-query-space";
+import {Injectable} from '@angular/core';
+import {InputState} from "reactivestates";
+
+
+export const wpDisplayListRepresentation:string = 'list';
+export const wpDisplayCardRepresentation:string = 'card';
+export type wpDisplayRepresentation = 'list'|'card';
+
+@Injectable()
+export class WorkPackageDisplayRepresentationService extends WorkPackageQueryStateService {
+ public constructor(readonly states:States,
+ readonly querySpace:IsolatedQuerySpace) {
+ super(querySpace);
+ }
+
+ public get state():InputState {
+ return this.querySpace.displayRepresentation;
+ }
+
+ public hasChanged(query:QueryResource) {
+ return this.current !== query.displayRepresentation;
+ }
+
+ valueFromQuery(query:QueryResource) {
+ return query.displayRepresentation || null;
+ }
+
+ public applyToQuery(query:QueryResource) {
+ const current = this.current;
+ query.displayRepresentation = current === null ? undefined : current;
+ return true;
+ }
+
+ public get current():string|null {
+ return this.state.getValueOr(null);
+ }
+
+ public setDisplayRepresentation(representation:string) {
+ this.update(representation);
+ }
+}
diff --git a/frontend/src/app/components/wp-grid/wp-grid.component.ts b/frontend/src/app/components/wp-grid/wp-grid.component.ts
new file mode 100644
index 0000000000..84c372cf2e
--- /dev/null
+++ b/frontend/src/app/components/wp-grid/wp-grid.component.ts
@@ -0,0 +1,74 @@
+// -- 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 {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit} from "@angular/core";
+import {WorkPackageTableHighlightingService} from "core-components/wp-fast-table/state/wp-table-highlighting.service";
+import {CardViewOrientation} from "core-components/wp-card-view/wp-card-view.component";
+import {takeUntil} from "rxjs/operators";
+import {IsolatedQuerySpace} from "core-app/modules/work_packages/query-space/isolated-query-space";
+import {HighlightingMode} from "core-components/wp-fast-table/builders/highlighting/highlighting-mode.const";
+import {componentDestroyed, untilComponentDestroyed} from "ng2-rx-componentdestroyed";
+
+@Component({
+ selector: 'wp-grid',
+ template: `
+
+
+ `,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class WorkPackagesGridComponent implements OnInit, OnDestroy {
+ public canDragOutOf = () => { return false; };
+ public gridOrientation:CardViewOrientation = 'horizontal';
+ public highlightingMode:HighlightingMode = 'none';
+
+ constructor(readonly wpTableHighlight:WorkPackageTableHighlightingService,
+ readonly querySpace:IsolatedQuerySpace,
+ readonly cdRef:ChangeDetectorRef) {
+ }
+
+ ngOnInit() {
+ this.querySpace.highlighting.values$()
+ .pipe(
+ takeUntil(this.querySpace.stopAllSubscriptions),
+ untilComponentDestroyed(this)
+ )
+ .subscribe(() => {
+ this.highlightingMode = this.wpTableHighlight.current.mode;
+ this.cdRef.detectChanges();
+ });
+ }
+
+ ngOnDestroy():void {
+ }
+}
diff --git a/frontend/src/app/components/wp-list/wp-states-initialization.service.ts b/frontend/src/app/components/wp-list/wp-states-initialization.service.ts
index 5488b0056f..3877e9d92d 100644
--- a/frontend/src/app/components/wp-list/wp-states-initialization.service.ts
+++ b/frontend/src/app/components/wp-list/wp-states-initialization.service.ts
@@ -20,6 +20,7 @@ import {IsolatedQuerySpace} from "core-app/modules/work_packages/query-space/iso
import {Injectable} from '@angular/core';
import {QuerySchemaResource} from 'core-app/modules/hal/resources/query-schema-resource';
import {WorkPackageTableHighlightingService} from "core-components/wp-fast-table/state/wp-table-highlighting.service";
+import {WorkPackageDisplayRepresentationService} from "core-components/wp-fast-table/state/work-package-display-representation.service";
@Injectable()
export class WorkPackageStatesInitializationService {
@@ -38,7 +39,8 @@ export class WorkPackageStatesInitializationService {
protected wpTableAdditionalElements:WorkPackageTableAdditionalElementsService,
protected wpCacheService:WorkPackageCacheService,
protected wpListChecksumService:WorkPackagesListChecksumService,
- protected authorisationService:AuthorisationService) {
+ protected authorisationService:AuthorisationService,
+ protected wpDisplayRepresentation:WorkPackageDisplayRepresentationService) {
}
/**
@@ -92,6 +94,12 @@ export class WorkPackageStatesInitializationService {
this.states.schemas.get(schema.href as string).putValue(schema);
});
}
+
+ // Ensure we're setting the current results to the query
+ // This is due to 9.X still loading results from /api/v3/work_packages
+ // for a previously loaded query.
+ query.results = results;
+
this.querySpace.query.putValue(query);
this.querySpace.rows.putValue(results.elements);
@@ -126,6 +134,7 @@ export class WorkPackageStatesInitializationService {
this.wpTableTimeline.initialize(query, results);
this.wpTableHierarchies.initialize(query, results);
this.wpTableHighlighting.initialize(query, results);
+ this.wpDisplayRepresentation.initialize(query, results);
this.authorisationService.initModelAuth('query', query.$links);
this.authorisationService.initModelAuth('work_packages', results.$links);
@@ -140,6 +149,7 @@ export class WorkPackageStatesInitializationService {
this.wpTableTimeline.applyToQuery(query);
this.wpTableHighlighting.applyToQuery(query);
this.wpTableHierarchies.applyToQuery(query);
+ this.wpDisplayRepresentation.applyToQuery(query);
}
public clearStates() {
diff --git a/frontend/src/app/components/wp-query/url-params-helper.ts b/frontend/src/app/components/wp-query/url-params-helper.ts
index f5ba6410ad..50637f53a7 100644
--- a/frontend/src/app/components/wp-query/url-params-helper.ts
+++ b/frontend/src/app/components/wp-query/url-params-helper.ts
@@ -77,6 +77,7 @@ export class UrlParamsHelperService {
paramsData = this.encodeFilters(paramsData, query.filters);
paramsData.pa = additional.page;
paramsData.pp = additional.perPage;
+ paramsData.dr = query.displayRepresentation;
return JSON.stringify(paramsData);
}
@@ -187,6 +188,10 @@ export class UrlParamsHelperService {
}
}
+ if (properties.dr) {
+ queryData.displayRepresentation = properties.dr;
+ }
+
if (properties.hl) {
queryData.highlightingMode = properties.hl;
}
@@ -258,6 +263,10 @@ export class UrlParamsHelperService {
queryData.highlightedAttributes = query.highlightedAttributes.map(el => el.href);
}
+ if (query.displayRepresentation) {
+ queryData.displayRepresentation = query.displayRepresentation;
+ }
+
queryData.showHierarchies = !!query.showHierarchies;
queryData.groupBy = _.get(query.groupBy, 'id', '');
diff --git a/frontend/src/app/modules/boards/board/configuration-modal/tabs/highlighting-tab.component.html b/frontend/src/app/modules/boards/board/configuration-modal/tabs/highlighting-tab.component.html
index bfa4c79397..a688a24e5e 100644
--- a/frontend/src/app/modules/boards/board/configuration-modal/tabs/highlighting-tab.component.html
+++ b/frontend/src/app/modules/boards/board/configuration-modal/tabs/highlighting-tab.component.html
@@ -7,7 +7,7 @@