TSK-1562: Reset filter when changing workbasket and move filter to store
This commit is contained in:
parent
22999c0bb0
commit
68683b3c06
|
@ -25,8 +25,7 @@
|
|||
</mat-toolbar>
|
||||
|
||||
<!-- FILTER COMPONENT -->
|
||||
<taskana-shared-workbasket-filter *ngIf="toolbarState" (performFilter)="performAvailableFilter($event)"
|
||||
isExpanded="true" component="distribution-target"></taskana-shared-workbasket-filter>
|
||||
<taskana-shared-workbasket-filter *ngIf="toolbarState" isExpanded="true" [component]="component"></taskana-shared-workbasket-filter>
|
||||
|
||||
<!-- WORKBASKET LIST -->
|
||||
<div class="{{toolbarState? 'distribution-targets-list__list--with-filter' : 'distribution-targets-list__list--no-filter'}}"
|
||||
|
|
|
@ -9,13 +9,11 @@ import { Side } from '../workbasket-distribution-targets/workbasket-distribution
|
|||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { MatListModule } from '@angular/material/list';
|
||||
import { WorkbasketQueryFilterParameter } from '../../../shared/models/workbasket-query-filter-parameter';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { OrderBy } from '../../../shared/pipes/order-by.pipe';
|
||||
|
||||
@Component({ selector: 'taskana-shared-workbasket-filter', template: '' })
|
||||
class FilterStub {
|
||||
@Output() performFilter = new EventEmitter<WorkbasketQueryFilterParameter>();
|
||||
@Input() component = 'availableDistributionTargetList';
|
||||
}
|
||||
|
||||
@Component({ selector: 'taskana-shared-spinner', template: '' })
|
||||
|
|
|
@ -1,19 +1,8 @@
|
|||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter,
|
||||
AfterContentChecked,
|
||||
ChangeDetectorRef,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import { Component, OnInit, Input, AfterContentChecked, ChangeDetectorRef, ViewChild } from '@angular/core';
|
||||
import { WorkbasketSummary } from 'app/shared/models/workbasket-summary';
|
||||
import { expandDown } from 'app/shared/animations/expand.animation';
|
||||
import { Side } from '../workbasket-distribution-targets/workbasket-distribution-targets.component';
|
||||
import { MatSelectionList } from '@angular/material/list';
|
||||
import { Pair } from '../../../shared/models/pair';
|
||||
import { WorkbasketQueryFilterParameter } from '../../../shared/models/workbasket-query-filter-parameter';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-administration-workbasket-distribution-targets-list',
|
||||
|
@ -26,7 +15,7 @@ export class WorkbasketDistributionTargetsListComponent implements OnInit, After
|
|||
@Input() side: Side;
|
||||
@Input() header: string;
|
||||
@Input() allSelected;
|
||||
@Output() performDualListFilter = new EventEmitter<Pair<Side, WorkbasketQueryFilterParameter>>();
|
||||
@Input() component;
|
||||
|
||||
toolbarState = false;
|
||||
@ViewChild('workbasket') distributionTargetsList: MatSelectionList;
|
||||
|
@ -49,12 +38,6 @@ export class WorkbasketDistributionTargetsListComponent implements OnInit, After
|
|||
this.distributionTargets.map((item) => (item['selected'] = selected));
|
||||
}
|
||||
|
||||
performAvailableFilter(pair: Pair<string, WorkbasketQueryFilterParameter>) {
|
||||
if (pair.left === 'distribution-target') {
|
||||
this.performDualListFilter.emit({ left: this.side, right: pair.right });
|
||||
}
|
||||
}
|
||||
|
||||
changeToolbarState(state: boolean) {
|
||||
this.toolbarState = state;
|
||||
}
|
||||
|
|
|
@ -83,10 +83,10 @@
|
|||
[ngClass]="sideBySide ? 'distribution-targets-list__lists--left-side' : ''"
|
||||
header="Selected distribution targets"
|
||||
[distributionTargets]="selectedDistributionTargets"
|
||||
(performDualListFilter)="performFilter($event)"
|
||||
[side]="side.SELECTED"
|
||||
[allSelected]="selectAllLeft"
|
||||
[hidden]="displayingDistributionTargetsPicker && !sideBySide"
|
||||
[component]="'selectedDistributionTargets'"
|
||||
>
|
||||
|
||||
</taskana-administration-workbasket-distribution-targets-list>
|
||||
|
@ -95,9 +95,9 @@
|
|||
header="Available distribution targets"
|
||||
[distributionTargets]="availableDistributionTargets"
|
||||
[side]="side.AVAILABLE"
|
||||
(performDualListFilter)="performFilter($event)"
|
||||
[allSelected]="selectAllRight"
|
||||
*ngIf="displayingDistributionTargetsPicker"
|
||||
[component]="'availableDistributionTargets'"
|
||||
>
|
||||
|
||||
</taskana-administration-workbasket-distribution-targets-list>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { Component, DebugElement, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { Component, DebugElement, Input } from '@angular/core';
|
||||
import { Side, WorkbasketDistributionTargetsComponent } from './workbasket-distribution-targets.component';
|
||||
import { WorkbasketSummary } from '../../../shared/models/workbasket-summary';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
|
@ -18,8 +18,6 @@ import {
|
|||
selectedWorkbasketMock,
|
||||
workbasketReadStateMock
|
||||
} from '../../../shared/store/mock-data/mock-store';
|
||||
import { WorkbasketQueryFilterParameter } from '../../../shared/models/workbasket-query-filter-parameter';
|
||||
import { Pair } from '../../../shared/models/pair';
|
||||
import { DomainService } from '../../../shared/services/domain/domain.service';
|
||||
|
||||
const routeParamsMock = { id: 'workbasket' };
|
||||
|
@ -31,15 +29,10 @@ const activatedRouteMock = {
|
|||
@Component({ selector: 'taskana-administration-workbasket-distribution-targets-list', template: '' })
|
||||
class WorkbasketDistributionTargetsListStub {
|
||||
@Input() distributionTargets: WorkbasketSummary[];
|
||||
@Input() distributionTargetsSelected: WorkbasketSummary[];
|
||||
@Output() performDualListFilter = new EventEmitter<Pair<Side, WorkbasketQueryFilterParameter>>();
|
||||
@Input() requestInProgress = false;
|
||||
@Input() loadingItems? = false;
|
||||
@Input() side: Side;
|
||||
@Input() header: string;
|
||||
@Output() scrolling = new EventEmitter<Side>();
|
||||
@Input() component: 'availableDistributionTargets';
|
||||
@Input() allSelected;
|
||||
@Output() allSelectedChange = new EventEmitter<boolean>();
|
||||
}
|
||||
|
||||
const domainServiceSpy = jest.fn().mockImplementation(
|
||||
|
@ -185,4 +178,10 @@ describe('WorkbasketDistributionTargetsComponent', () => {
|
|||
expect(component.selectedDistributionTargets).toHaveLength(3);
|
||||
expect(component.selectedDistributionTargetsFilterClone).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('should call performFilter when filter value from store is obtained', () => {
|
||||
const performFilter = jest.spyOn(component, 'performFilter');
|
||||
component.ngOnInit();
|
||||
expect(performFilter).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -21,6 +21,8 @@ import { WorkbasketSelectors } from '../../../shared/store/workbasket-store/work
|
|||
import { ButtonAction } from '../../models/button-action';
|
||||
import { Pair } from '../../../shared/models/pair';
|
||||
import { WorkbasketQueryFilterParameter } from '../../../shared/models/workbasket-query-filter-parameter';
|
||||
import { FilterSelectors } from '../../../shared/store/filter-store/filter.selectors';
|
||||
import { SetFilter } from '../../../shared/store/filter-store/filter.actions';
|
||||
|
||||
export enum Side {
|
||||
AVAILABLE,
|
||||
|
@ -45,12 +47,14 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
|
||||
availableDistributionTargets: WorkbasketSummary[] = [];
|
||||
availableDistributionTargetsUndoClone: WorkbasketSummary[];
|
||||
availableDistributionTargetsFilterClone: WorkbasketSummary[];
|
||||
availableDistributionTargetsFilterClone: WorkbasketSummary[] = [];
|
||||
availableDistributionTargetsFilter: WorkbasketQueryFilterParameter;
|
||||
|
||||
selectedDistributionTargets: WorkbasketSummary[];
|
||||
selectedDistributionTargetsUndoClone: WorkbasketSummary[];
|
||||
selectedDistributionTargetsFilterClone: WorkbasketSummary[];
|
||||
selectedDistributionTargetsFilterClone: WorkbasketSummary[] = [];
|
||||
selectedDistributionTargetsResource: WorkbasketDistributionTargets;
|
||||
selectedDistributionTargetsFilter: WorkbasketQueryFilterParameter;
|
||||
|
||||
@Select(WorkbasketSelectors.workbasketDistributionTargets)
|
||||
workbasketDistributionTargets$: Observable<WorkbasketDistributionTargets>;
|
||||
|
@ -64,6 +68,12 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
@Select(WorkbasketSelectors.selectedWorkbasket)
|
||||
selectedWorkbasket$: Observable<Workbasket>;
|
||||
|
||||
@Select(FilterSelectors.getAvailableDistributionTargetsFilter)
|
||||
availableDistributionTargetsFilter$: Observable<WorkbasketQueryFilterParameter>;
|
||||
|
||||
@Select(FilterSelectors.getSelectedDistributionTargetsFilter)
|
||||
selectedDistributionTargetsFilter$: Observable<WorkbasketQueryFilterParameter>;
|
||||
|
||||
destroy$ = new Subject<void>();
|
||||
|
||||
constructor(
|
||||
|
@ -112,6 +122,16 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
}
|
||||
});
|
||||
|
||||
this.availableDistributionTargetsFilter$.pipe(takeUntil(this.destroy$)).subscribe((filter) => {
|
||||
this.availableDistributionTargetsFilter = filter;
|
||||
this.performFilter({ left: 0, right: filter });
|
||||
});
|
||||
|
||||
this.selectedDistributionTargetsFilter$.pipe(takeUntil(this.destroy$)).subscribe((filter) => {
|
||||
this.selectedDistributionTargetsFilter = filter;
|
||||
this.performFilter({ left: 1, right: filter });
|
||||
});
|
||||
|
||||
// saving workbasket distributions targets when existing workbasket was modified
|
||||
this.ngxsActions$.pipe(ofActionCompleted(UpdateWorkbasket), takeUntil(this.destroy$)).subscribe(() => {
|
||||
this.onSave();
|
||||
|
@ -263,6 +283,8 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
this.availableDistributionTargetsFilterClone = this.availableDistributionTargets;
|
||||
this.selectAllRight = true;
|
||||
this.selectAllLeft = true;
|
||||
this.store.dispatch(new SetFilter(this.selectedDistributionTargetsFilter, 'selectedDistributionTargets'));
|
||||
this.store.dispatch(new SetFilter(this.availableDistributionTargetsFilter, 'availableDistributionTargets'));
|
||||
}
|
||||
|
||||
onClear() {
|
||||
|
|
|
@ -29,9 +29,7 @@
|
|||
</button>
|
||||
|
||||
<div class="filter__filter-component-wrapper">
|
||||
<taskana-shared-workbasket-filter [isExpanded]="isExpanded"
|
||||
(performFilter)="filtering($event)"
|
||||
component="workbasket-list"></taskana-shared-workbasket-filter>
|
||||
<taskana-shared-workbasket-filter [isExpanded]="isExpanded" component="workbasketList"></taskana-shared-workbasket-filter>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -17,8 +17,6 @@ import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
|
||||
import { Pair } from '../../../shared/models/pair';
|
||||
import { WorkbasketQueryFilterParameter } from '../../../shared/models/workbasket-query-filter-parameter';
|
||||
|
||||
const getDomainFn = jest.fn().mockReturnValue(true);
|
||||
const domainServiceMock = jest.fn().mockImplementation(
|
||||
|
@ -44,7 +42,6 @@ class SortStub {
|
|||
@Component({ selector: 'taskana-shared-workbasket-filter', template: '' })
|
||||
class FilterStub {
|
||||
@Input() isExpanded = false;
|
||||
@Output() performFilter = new EventEmitter<WorkbasketQueryFilterParameter>();
|
||||
}
|
||||
|
||||
const requestInProgressServiceSpy = jest.fn().mockImplementation(
|
||||
|
@ -124,24 +121,6 @@ describe('WorkbasketListToolbarComponent', () => {
|
|||
expect(sort).toMatchObject(mockSort);
|
||||
});
|
||||
|
||||
it('should NOT emit value when filtering is called with wrong component', () => {
|
||||
const mockFilter: Pair<string, WorkbasketQueryFilterParameter> = { left: 'foo', right: { domain: ['DOMAIN_A'] } };
|
||||
const performFilterSpy = jest.spyOn(component.performFilter, 'emit');
|
||||
component.filtering(mockFilter);
|
||||
expect(performFilterSpy).toBeCalledTimes(0);
|
||||
});
|
||||
|
||||
it('should emit value when filtering is called with correct component', () => {
|
||||
const mockFilter: Pair<string, WorkbasketQueryFilterParameter> = {
|
||||
left: 'workbasket-list',
|
||||
right: { domain: ['DOMAIN_A'] }
|
||||
};
|
||||
const performFilterSpy = jest.spyOn(component.performFilter, 'emit');
|
||||
component.filtering(mockFilter);
|
||||
expect(performFilterSpy).toBeCalledTimes(1);
|
||||
expect(performFilterSpy).toBeCalledWith(mockFilter.right);
|
||||
});
|
||||
|
||||
/* HTML */
|
||||
|
||||
it('should call AddWorkbasket() when add-workbasket button is clicked', async () => {
|
||||
|
|
|
@ -10,8 +10,6 @@ import { ACTION } from '../../../shared/models/action';
|
|||
import { CreateWorkbasket } from '../../../shared/store/workbasket-store/workbasket.actions';
|
||||
import { WorkbasketSelectors } from '../../../shared/store/workbasket-store/workbasket.selectors';
|
||||
import { WorkbasketService } from '../../../shared/services/workbasket/workbasket.service';
|
||||
import { WorkbasketQueryFilterParameter } from '../../../shared/models/workbasket-query-filter-parameter';
|
||||
import { Pair } from '../../../shared/models/pair';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-administration-workbasket-list-toolbar',
|
||||
|
@ -21,10 +19,9 @@ import { Pair } from '../../../shared/models/pair';
|
|||
})
|
||||
export class WorkbasketListToolbarComponent implements OnInit {
|
||||
@Input() workbasketListExpanded: boolean = true;
|
||||
@Input() workbaskets: Array<WorkbasketSummary>;
|
||||
@Input() workbaskets: WorkbasketSummary[];
|
||||
@Input() workbasketDefaultSortBy: WorkbasketQuerySortParameter;
|
||||
@Output() performSorting = new EventEmitter<Sorting<WorkbasketQuerySortParameter>>();
|
||||
@Output() performFilter = new EventEmitter<WorkbasketQueryFilterParameter>();
|
||||
|
||||
selectionToImport = TaskanaType.WORKBASKETS;
|
||||
sortingFields: Map<WorkbasketQuerySortParameter, string> = WORKBASKET_SORT_PARAMETER_NAMING;
|
||||
|
@ -50,12 +47,6 @@ export class WorkbasketListToolbarComponent implements OnInit {
|
|||
this.performSorting.emit(sort);
|
||||
}
|
||||
|
||||
filtering({ left: component, right: filter }: Pair<string, WorkbasketQueryFilterParameter>) {
|
||||
if (component === 'workbasket-list') {
|
||||
this.performFilter.emit(filter);
|
||||
}
|
||||
}
|
||||
|
||||
addWorkbasket() {
|
||||
if (this.action !== ACTION.CREATE) {
|
||||
this.store.dispatch(new CreateWorkbasket());
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="workbasket-list">
|
||||
<!-- TOOLBAR -->
|
||||
<section #wbToolbar class="workbasket-list__toolbar">
|
||||
<taskana-administration-workbasket-list-toolbar [workbaskets]="workbasketsSummary$ | async" (performFilter)="performFilter($event)"
|
||||
<taskana-administration-workbasket-list-toolbar [workbaskets]="workbasketsSummary$ | async"
|
||||
(performSorting)="performSorting($event)" [workbasketDefaultSortBy]="workbasketDefaultSortBy" [workbasketListExpanded]="expanded">
|
||||
</taskana-administration-workbasket-list-toolbar>
|
||||
</section>
|
||||
|
|
|
@ -74,7 +74,6 @@ class WorkbasketListToolbarStub {
|
|||
@Input() workbasketDefaultSortBy: string;
|
||||
@Input() workbasketListExpanded: boolean;
|
||||
@Output() performSorting = new EventEmitter<Sorting<WorkbasketQuerySortParameter>>();
|
||||
@Output() performFilter = new EventEmitter<WorkbasketQueryFilterParameter>();
|
||||
}
|
||||
|
||||
@Component({ selector: 'taskana-administration-icon-type', template: '' })
|
||||
|
@ -165,10 +164,17 @@ describe('WorkbasketListComponent', () => {
|
|||
expect(component.sort).toMatchObject(sort);
|
||||
});
|
||||
|
||||
it('should set filter value when performFilter is called', () => {
|
||||
const filter: WorkbasketQueryFilterParameter = { domain: ['123'] };
|
||||
it('should set filter value without updating domain when performFilter is called', () => {
|
||||
component.filterBy = { domain: ['123'] };
|
||||
const filter: WorkbasketQueryFilterParameter = { 'name-like': ['workbasket'], domain: [''] };
|
||||
component.performFilter(filter);
|
||||
expect(component.filterBy).toMatchObject(filter);
|
||||
expect(component.filterBy).toMatchObject({ 'name-like': ['workbasket'], domain: ['123'] });
|
||||
});
|
||||
|
||||
it('should call performFilter when filter value from store is obtained', () => {
|
||||
const performFilter = jest.spyOn(component, 'performFilter');
|
||||
component.ngOnInit();
|
||||
expect(performFilter).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should change page value when change page function is called ', () => {
|
||||
|
|
|
@ -10,7 +10,7 @@ import { WorkbasketService } from 'app/shared/services/workbasket/workbasket.ser
|
|||
import { OrientationService } from 'app/shared/services/orientation/orientation.service';
|
||||
import { ImportExportService } from 'app/administration/services/import-export.service';
|
||||
import { Actions, ofActionCompleted, ofActionDispatched, Select, Store } from '@ngxs/store';
|
||||
import { takeUntil, take } from 'rxjs/operators';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import {
|
||||
DeselectWorkbasket,
|
||||
GetWorkbasketsSummary,
|
||||
|
@ -23,6 +23,7 @@ import { DomainService } from '../../../shared/services/domain/domain.service';
|
|||
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
|
||||
import { WorkbasketQueryFilterParameter } from '../../../shared/models/workbasket-query-filter-parameter';
|
||||
import { QueryPagingParameter } from '../../../shared/models/query-paging-parameter';
|
||||
import { FilterSelectors } from '../../../shared/store/filter-store/filter.selectors';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-administration-workbasket-list',
|
||||
|
@ -59,6 +60,9 @@ export class WorkbasketListComponent implements OnInit, OnDestroy {
|
|||
@Select(WorkbasketSelectors.selectedWorkbasket)
|
||||
selectedWorkbasket$: Observable<Workbasket>;
|
||||
|
||||
@Select(FilterSelectors.getWorkbasketListFilter)
|
||||
getWorkbasketListFilter$: Observable<WorkbasketQueryFilterParameter>;
|
||||
|
||||
destroy$ = new Subject<void>();
|
||||
|
||||
@ViewChild('workbasket') workbasketList: MatSelectionList;
|
||||
|
@ -137,6 +141,10 @@ export class WorkbasketListComponent implements OnInit, OnDestroy {
|
|||
.subscribe((value) => {
|
||||
this.requestInProgress = value;
|
||||
});
|
||||
|
||||
this.getWorkbasketListFilter$.pipe(takeUntil(this.destroy$)).subscribe((filter) => {
|
||||
this.performFilter(filter);
|
||||
});
|
||||
}
|
||||
|
||||
selectWorkbasket(id: string) {
|
||||
|
@ -159,7 +167,7 @@ export class WorkbasketListComponent implements OnInit, OnDestroy {
|
|||
|
||||
performFilter(filterBy: WorkbasketQueryFilterParameter) {
|
||||
const domain = this.filterBy.domain;
|
||||
this.filterBy = filterBy;
|
||||
this.filterBy = { ...filterBy };
|
||||
this.filterBy.domain = domain;
|
||||
this.performRequest();
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ export class WorkbasketOverviewComponent implements OnInit {
|
|||
|
||||
ngOnInit() {
|
||||
if (this.route.url) {
|
||||
this.route.url.subscribe((params) => {
|
||||
this.route.url.pipe(takeUntil(this.destroy$)).subscribe((params) => {
|
||||
if (params[0].path === 'workbaskets') {
|
||||
this.selectedWorkbasket$.pipe(take(1)).subscribe((workbasket) => {
|
||||
if (typeof workbasket.workbasketId !== 'undefined') {
|
||||
|
@ -39,7 +39,7 @@ export class WorkbasketOverviewComponent implements OnInit {
|
|||
});
|
||||
}
|
||||
if (this.route.firstChild) {
|
||||
this.route.firstChild.params.subscribe((params) => {
|
||||
this.route.firstChild.params.pipe(takeUntil(this.destroy$)).subscribe((params) => {
|
||||
this.routerParams = params;
|
||||
if (this.routerParams.id) {
|
||||
this.showDetail = true;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</mat-form-field>
|
||||
|
||||
<!-- CLEAR BUTTON -->
|
||||
<button mat-stroked-button (click)="clear(); search()" matTooltip="Clear workbasket filter"
|
||||
<button mat-stroked-button (click)="clear()" matTooltip="Clear Workbasket filter"
|
||||
class="filter__undo-button">
|
||||
<mat-icon style="color: #555">undo</mat-icon>
|
||||
</button>
|
||||
|
@ -43,7 +43,7 @@
|
|||
<div class="filter__name-and-key-input">
|
||||
<mat-form-field appearance="legacy" floatLabel="auto" class="filter__input-field">
|
||||
<mat-label>Filter by description</mat-label>
|
||||
<input matInput [(ngModel)]="filter['description-like']" matTooltip="Type to filter by description"
|
||||
<input matInput [(ngModel)]="filter['description-like'][0]" matTooltip="Type to filter by description"
|
||||
(keyup.enter)="search()">
|
||||
</mat-form-field>
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
|||
<div class="filter__action-buttons">
|
||||
|
||||
<!-- TYPE FILTER -->
|
||||
<button mat-stroked-button [matMenuTriggerFor]="menu" matTooltip="Filter workbaskets by type">
|
||||
<button mat-stroked-button [matMenuTriggerFor]="menu" matTooltip="Filter Workbaskets by type">
|
||||
Filter by type
|
||||
<mat-icon *ngIf="filter.type.length == 0" style="color: #555">filter_list</mat-icon>
|
||||
<taskana-administration-icon-type *ngIf="filter.type[0]"
|
||||
|
@ -68,14 +68,14 @@
|
|||
</button>
|
||||
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item *ngFor="let type of allTypes | mapValues" (click)="selectType(type.key); search()">
|
||||
<button mat-menu-item *ngFor="let type of allTypes | mapValues" (click)="selectType(type.key)">
|
||||
<span *ngIf="type.value === 'All'"> <mat-icon style="color: #555" class="filter__all-icon">filter_list</mat-icon> All </span>
|
||||
<taskana-administration-icon-type *ngIf="type.value !== 'All'" [type]='type.key' [text]="type.value"></taskana-administration-icon-type>
|
||||
</button>
|
||||
</mat-menu>
|
||||
|
||||
<!-- CLEAR BUTTON -->
|
||||
<button mat-stroked-button (click)="clear(); search()" matTooltip="Clear workbasket filter">
|
||||
<button mat-stroked-button (click)="clear()" matTooltip="Clear Workbasket filter">
|
||||
Reset
|
||||
<mat-icon style="color: #555">undo</mat-icon>
|
||||
</button>
|
||||
|
|
|
@ -1,35 +1,66 @@
|
|||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { ALL_TYPES, WorkbasketType } from '../../models/workbasket-type';
|
||||
import { WorkbasketQueryFilterParameter } from '../../models/workbasket-query-filter-parameter';
|
||||
import { Pair } from '../../models/pair';
|
||||
import { Select, Store } from '@ngxs/store';
|
||||
import { ClearFilter, SetFilter } from '../../store/filter-store/filter.actions';
|
||||
import { FilterSelectors } from '../../store/filter-store/filter.selectors';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-shared-workbasket-filter',
|
||||
templateUrl: './workbasket-filter.component.html',
|
||||
styleUrls: ['./workbasket-filter.component.scss']
|
||||
})
|
||||
export class WorkbasketFilterComponent implements OnInit {
|
||||
export class WorkbasketFilterComponent implements OnInit, OnDestroy {
|
||||
allTypes: Map<WorkbasketType, string> = ALL_TYPES;
|
||||
|
||||
@Input() component: string;
|
||||
@Input() isExpanded: boolean;
|
||||
|
||||
@Output() performFilter = new EventEmitter<Pair<string, WorkbasketQueryFilterParameter>>();
|
||||
@Select(FilterSelectors.getAvailableDistributionTargetsFilter)
|
||||
availableDistributionTargetsFilter$: Observable<WorkbasketQueryFilterParameter>;
|
||||
|
||||
@Select(FilterSelectors.getSelectedDistributionTargetsFilter)
|
||||
selectedDistributionTargetsFilter$: Observable<WorkbasketQueryFilterParameter>;
|
||||
|
||||
@Select(FilterSelectors.getWorkbasketListFilter)
|
||||
workbasketListFilter$: Observable<WorkbasketQueryFilterParameter>;
|
||||
|
||||
destroy$ = new Subject<void>();
|
||||
|
||||
filter: WorkbasketQueryFilterParameter;
|
||||
|
||||
constructor(private store: Store) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.clear();
|
||||
if (this.component === 'availableDistributionTargets') {
|
||||
this.availableDistributionTargetsFilter$.pipe(takeUntil(this.destroy$)).subscribe((filter) => {
|
||||
this.setFilter(filter);
|
||||
});
|
||||
} else if (this.component === 'selectedDistributionTargets') {
|
||||
this.selectedDistributionTargetsFilter$.pipe(takeUntil(this.destroy$)).subscribe((filter) => {
|
||||
this.setFilter(filter);
|
||||
});
|
||||
} else if (this.component === 'workbasketList') {
|
||||
this.workbasketListFilter$.pipe(takeUntil(this.destroy$)).subscribe((filter) => {
|
||||
this.setFilter(filter);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
setFilter(filter: WorkbasketQueryFilterParameter) {
|
||||
this.filter = {
|
||||
'description-like': [...filter['description-like']],
|
||||
'key-like': [...filter['key-like']],
|
||||
'name-like': [...filter['name-like']],
|
||||
'owner-like': [...filter['owner-like']],
|
||||
type: [...filter['type']]
|
||||
};
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.filter = {
|
||||
'name-like': [],
|
||||
'key-like': [],
|
||||
'description-like': [],
|
||||
'owner-like': [],
|
||||
type: []
|
||||
};
|
||||
this.store.dispatch(new ClearFilter(this.component));
|
||||
}
|
||||
|
||||
selectType(type: WorkbasketType) {
|
||||
|
@ -37,6 +68,11 @@ export class WorkbasketFilterComponent implements OnInit {
|
|||
}
|
||||
|
||||
search() {
|
||||
this.performFilter.emit({ left: this.component, right: this.filter });
|
||||
this.store.dispatch(new SetFilter(this.filter, this.component));
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { WorkbasketQueryFilterParameter } from '../../models/workbasket-query-filter-parameter';
|
||||
|
||||
export class SetFilter {
|
||||
static readonly type = '[Workbasket filter] Set filter parameter';
|
||||
constructor(public parameters: WorkbasketQueryFilterParameter, public component: string) {}
|
||||
}
|
||||
|
||||
export class ClearFilter {
|
||||
static readonly type = '[Workbasket filter] Clear filter parameter';
|
||||
constructor(public component: string) {}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import { FilterState, FilterStateModel } from './filter.state';
|
||||
import { Selector } from '@ngxs/store';
|
||||
import { WorkbasketQueryFilterParameter } from '../../models/workbasket-query-filter-parameter';
|
||||
|
||||
export class FilterSelectors {
|
||||
@Selector([FilterState])
|
||||
static getAvailableDistributionTargetsFilter(state: FilterStateModel): WorkbasketQueryFilterParameter {
|
||||
return state.availableDistributionTargets;
|
||||
}
|
||||
|
||||
@Selector([FilterState])
|
||||
static getSelectedDistributionTargetsFilter(state: FilterStateModel): WorkbasketQueryFilterParameter {
|
||||
return state.selectedDistributionTargets;
|
||||
}
|
||||
|
||||
@Selector([FilterState])
|
||||
static getWorkbasketListFilter(state: FilterStateModel): WorkbasketQueryFilterParameter {
|
||||
return state.workbasketList;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
import { Action, NgxsOnInit, State, StateContext } from '@ngxs/store';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { WorkbasketQueryFilterParameter } from '../../models/workbasket-query-filter-parameter';
|
||||
import { ClearFilter, SetFilter } from './filter.actions';
|
||||
|
||||
const emptyFilter: WorkbasketQueryFilterParameter = {
|
||||
'description-like': [],
|
||||
'key-like': [],
|
||||
'name-like': [],
|
||||
'owner-like': [],
|
||||
type: []
|
||||
};
|
||||
|
||||
@State<FilterStateModel>({ name: 'FilterState' })
|
||||
export class FilterState implements NgxsOnInit {
|
||||
@Action(SetFilter)
|
||||
setAvailableDistributionTargetsFilter(ctx: StateContext<FilterStateModel>, action: SetFilter): Observable<null> {
|
||||
const currentState = ctx.getState()[action.component];
|
||||
const param = action.parameters;
|
||||
const filter: WorkbasketQueryFilterParameter = {
|
||||
'description-like': param['description-like'] ? [...param['description-like']] : currentState['description-like'],
|
||||
'key-like': param['key-like'] ? [...param['key-like']] : currentState['key-like'],
|
||||
'name-like': param['name-like'] ? [...param['name-like']] : currentState['name-like'],
|
||||
'owner-like': param['owner-like'] ? [...param['owner-like']] : currentState['owner-like'],
|
||||
type: param['type'] ? [...param['type']] : currentState['type']
|
||||
};
|
||||
|
||||
ctx.setState({
|
||||
...ctx.getState(),
|
||||
[action.component]: filter
|
||||
});
|
||||
|
||||
return of(null);
|
||||
}
|
||||
|
||||
@Action(ClearFilter)
|
||||
clearFilter(ctx: StateContext<FilterStateModel>, action: ClearFilter): Observable<null> {
|
||||
ctx.setState({
|
||||
...ctx.getState(),
|
||||
[action.component]: { ...emptyFilter }
|
||||
});
|
||||
|
||||
return of(null);
|
||||
}
|
||||
|
||||
ngxsOnInit(ctx: StateContext<FilterStateModel>): void {
|
||||
ctx.setState({
|
||||
...ctx.getState(),
|
||||
availableDistributionTargets: emptyFilter,
|
||||
selectedDistributionTargets: emptyFilter,
|
||||
workbasketList: emptyFilter
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export interface FilterStateModel {
|
||||
availableDistributionTargets: WorkbasketQueryFilterParameter;
|
||||
selectedDistributionTargets: WorkbasketQueryFilterParameter;
|
||||
workbasketList: WorkbasketQueryFilterParameter;
|
||||
}
|
|
@ -2,5 +2,12 @@ import { EngineConfigurationState } from './engine-configuration-store/engine-co
|
|||
import { ClassificationState } from './classification-store/classification.state';
|
||||
import { WorkbasketState } from './workbasket-store/workbasket.state';
|
||||
import { AccessItemsManagementState } from './access-items-management-store/access-items-management.state';
|
||||
import { FilterState } from './filter-store/filter.state';
|
||||
|
||||
export const STATES = [EngineConfigurationState, ClassificationState, WorkbasketState, AccessItemsManagementState];
|
||||
export const STATES = [
|
||||
EngineConfigurationState,
|
||||
ClassificationState,
|
||||
WorkbasketState,
|
||||
AccessItemsManagementState,
|
||||
FilterState
|
||||
];
|
||||
|
|
|
@ -37,6 +37,7 @@ import { RequestInProgressService } from '../../services/request-in-progress/req
|
|||
import { WorkbasketType } from '../../models/workbasket-type';
|
||||
import { TaskanaDate } from '../../util/taskana.date';
|
||||
import { DomainService } from '../../services/domain/domain.service';
|
||||
import { ClearFilter } from '../filter-store/filter.actions';
|
||||
|
||||
class InitializeStore {
|
||||
static readonly type = '[Workbasket] Initializing state';
|
||||
|
@ -134,6 +135,9 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
|||
.path()
|
||||
.replace(/(workbaskets).*/g, `workbaskets/(detail:${action.workbasketId})?tab=${selectedComponent}`)
|
||||
);
|
||||
|
||||
ctx.dispatch(new ClearFilter('selectedDistributionTargets'));
|
||||
ctx.dispatch(new ClearFilter('availableDistributionTargets'));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -220,6 +224,9 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
|||
badgeMessage: `Copying workbasket: ${workbasket.key}`
|
||||
});
|
||||
|
||||
ctx.dispatch(new ClearFilter('selectedDistributionTargets'));
|
||||
ctx.dispatch(new ClearFilter('availableDistributionTargets'));
|
||||
|
||||
return of(null);
|
||||
}
|
||||
|
||||
|
@ -254,6 +261,9 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
|||
workbasketDistributionTargets: distributionTargets
|
||||
});
|
||||
|
||||
ctx.dispatch(new ClearFilter('selectedDistributionTargets'));
|
||||
ctx.dispatch(new ClearFilter('availableDistributionTargets'));
|
||||
|
||||
return of(null);
|
||||
})
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue