TSK-1562: Reset filter when changing workbasket and move filter to store

This commit is contained in:
Sofie Hofmann 2021-02-15 16:23:05 +01:00
parent 22999c0bb0
commit 68683b3c06
20 changed files with 226 additions and 99 deletions

View File

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

View File

@ -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: '' })

View File

@ -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;
}

View File

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

View File

@ -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);
});
});

View File

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

View File

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

View File

@ -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 () => {

View File

@ -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());

View File

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

View File

@ -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 ', () => {

View File

@ -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();
}

View File

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

View File

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

View File

@ -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();
}
}

View File

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

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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
];

View File

@ -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);
})
);