Merge pull request #7152 from opf/feature/29519/board-wide-filters
[29519] Implement board-wide filters [ci skip]pull/7157/head
commit
821108156b
@ -1,61 +0,0 @@ |
||||
//-- 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 {FilterOperator} from "core-components/api/api-v3/api-v3-filter-builder"; |
||||
import {ApiV3Paths} from "core-app/modules/common/path-helper/apiv3/apiv3-paths"; |
||||
|
||||
export class QueryFilterBuilder { |
||||
|
||||
constructor(readonly v3:ApiV3Paths) { |
||||
} |
||||
|
||||
/** |
||||
* Build a query filter object by hand. |
||||
* |
||||
* @param id |
||||
* @param operator |
||||
* @param values |
||||
*/ |
||||
public build(id:string, operator:FilterOperator, values:any[]):Object { |
||||
return { |
||||
"_type": "QueryFilter", |
||||
"_links": { |
||||
"filter": { |
||||
"href": this.v3.resource("/queries/filters/" + id) |
||||
}, |
||||
"schema": { |
||||
"href": this.v3.resource("/queries/filter_instance_schemas/" + id) |
||||
}, |
||||
"operator": { |
||||
"href": this.v3.resource("/queries/operators/" + operator) |
||||
}, |
||||
"values": values |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1 @@ |
||||
<filter-container></filter-container> |
@ -0,0 +1,92 @@ |
||||
import {Component, Input, OnDestroy, OnInit, Output} from "@angular/core"; |
||||
import {Board} from "core-app/modules/boards/board/board"; |
||||
import {CurrentProjectService} from "core-components/projects/current-project.service"; |
||||
import {QueryFormDmService} from "core-app/modules/hal/dm-services/query-form-dm.service"; |
||||
import {WorkPackageStatesInitializationService} from "core-components/wp-list/wp-states-initialization.service"; |
||||
import {QueryFormResource} from "core-app/modules/hal/resources/query-form-resource"; |
||||
import {IsolatedQuerySpace} from "core-app/modules/work_packages/query-space/isolated-query-space"; |
||||
import {QueryResource} from "core-app/modules/hal/resources/query-resource"; |
||||
import {HalResourceService} from "core-app/modules/hal/services/hal-resource.service"; |
||||
import {WorkPackageTableFiltersService} from "core-components/wp-fast-table/state/wp-table-filters.service"; |
||||
import {componentDestroyed} from "ng2-rx-componentdestroyed"; |
||||
import {QueryFilterInstanceResource} from "core-app/modules/hal/resources/query-filter-instance-resource"; |
||||
import {UrlParamsHelperService} from "core-components/wp-query/url-params-helper"; |
||||
import {StateService} from "@uirouter/core"; |
||||
import {DebouncedEventEmitter} from "core-components/angular/debounced-event-emitter"; |
||||
import {skip} from "rxjs/internal/operators"; |
||||
import {ApiV3Filter} from "core-components/api/api-v3/api-v3-filter-builder"; |
||||
|
||||
@Component({ |
||||
selector: 'board-filter', |
||||
templateUrl: './board-filter.component.html' |
||||
}) |
||||
export class BoardFilterComponent implements OnInit, OnDestroy { |
||||
@Input() public board:Board; |
||||
|
||||
@Output() public filters = new DebouncedEventEmitter<ApiV3Filter[]>(componentDestroyed(this)); |
||||
|
||||
constructor(private readonly currentProjectService:CurrentProjectService, |
||||
private readonly querySpace:IsolatedQuerySpace, |
||||
private readonly halResourceService:HalResourceService, |
||||
private readonly wpStatesInitialization:WorkPackageStatesInitializationService, |
||||
private readonly wpTableFilters:WorkPackageTableFiltersService, |
||||
private readonly urlParamsHelper:UrlParamsHelperService, |
||||
private readonly $state:StateService, |
||||
private readonly queryFormDm:QueryFormDmService) { |
||||
} |
||||
|
||||
ngOnInit():void { |
||||
// Initially load the form once to be able to render filters
|
||||
this.loadQueryForm(); |
||||
|
||||
// Update checksum service whenever filters change
|
||||
this.updateChecksumOnFilterChanges(); |
||||
|
||||
// Remove action attribute from filter service
|
||||
if (this.board.isAction) { |
||||
this.wpTableFilters.hidden.push(this.board.actionAttribute!); |
||||
} |
||||
} |
||||
|
||||
ngOnDestroy():void { |
||||
// Compliance
|
||||
} |
||||
|
||||
private updateChecksumOnFilterChanges() { |
||||
this.wpTableFilters |
||||
.observeUntil(componentDestroyed(this)) |
||||
.pipe(skip(1)) |
||||
.subscribe(() => { |
||||
|
||||
let query_props:string|null = null; |
||||
const filters:QueryFilterInstanceResource[] = this.wpTableFilters.current; |
||||
let filterHash = this.urlParamsHelper.buildV3GetFilters(filters); |
||||
|
||||
if (filters.length > 0) { |
||||
query_props = JSON.stringify(filterHash); |
||||
} |
||||
|
||||
this.filters.emit(filterHash); |
||||
|
||||
this.$state.go('.', { query_props: query_props }, {custom: {notify: false}}); |
||||
}); |
||||
} |
||||
|
||||
private loadQueryForm() { |
||||
this.queryFormDm |
||||
.loadWithParams( |
||||
{ filters: JSON.stringify(this.board.filters) }, |
||||
undefined, |
||||
this.currentProjectService.id |
||||
) |
||||
.then((form:QueryFormResource) => { |
||||
const query:QueryResource = this.halResourceService.createHalResourceOfClass( |
||||
QueryResource, |
||||
form.payload.$source |
||||
); |
||||
|
||||
this.querySpace.query.putValue(query); |
||||
this.wpStatesInitialization.updateStatesFromForm(query, form); |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,2 @@ |
||||
.boards--listing-group |
||||
position: relative |
Loading…
Reference in new issue