-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/web/src/app/shared/components/task-filter/task-filter.component.scss b/web/src/app/shared/components/task-filter/task-filter.component.scss
index 73f6630ad..f64f086a3 100644
--- a/web/src/app/shared/components/task-filter/task-filter.component.scss
+++ b/web/src/app/shared/components/task-filter/task-filter.component.scss
@@ -1,15 +1,34 @@
-.dropdown-menu-users {
- & > li {
- margin-bottom: 5px;
+@import 'src/theme/_colors.scss';
+
+.task-filter {
+ display: flex;
+ flex-direction: column;
+
+ &__button--primary {
+ background: $aquamarine;
+ color: white;
+
+ position: relative;
+ top: 30px;
}
- margin-left: 15px;
-}
+ &__button--secondary {
+ position: relative;
+ top: 24px;
+ }
-button.btn.btn-default.pull-right.margin-right {
- margin-top: 1px;
-}
+ .task-filter__row {
+ display: flex;
+ flex-direction: row;
+ }
+
+ &__input-field--large {
+ width: 320px;
+ }
+
+ &__input-field--small {
+ flex-grow: 1;
+ min-width: 140px;
+ }
-.blue {
- color: #2e9eca;
}
diff --git a/web/src/app/shared/components/task-filter/task-filter.component.ts b/web/src/app/shared/components/task-filter/task-filter.component.ts
index dda3ec010..b8f94fe64 100644
--- a/web/src/app/shared/components/task-filter/task-filter.component.ts
+++ b/web/src/app/shared/components/task-filter/task-filter.component.ts
@@ -1,29 +1,39 @@
-import { Component, EventEmitter, OnInit, Output } from '@angular/core';
+import { Component, OnDestroy, OnInit } from '@angular/core';
import { ALL_STATES, TaskState } from '../../models/task-state';
import { TaskQueryFilterParameter } from '../../models/task-query-filter-parameter';
+import { Actions, ofActionCompleted, Store } from '@ngxs/store';
+import { ClearTaskFilter, SetTaskFilter } from '../../store/filter-store/filter.actions';
+import { takeUntil } from 'rxjs/operators';
+import { Subject } from 'rxjs';
@Component({
selector: 'taskana-shared-task-filter',
templateUrl: './task-filter.component.html',
styleUrls: ['./task-filter.component.scss']
})
-export class TaskFilterComponent implements OnInit {
+export class TaskFilterComponent implements OnInit, OnDestroy {
filter: TaskQueryFilterParameter;
-
- @Output() performFilter = new EventEmitter
();
+ destroy$ = new Subject();
allStates: Map = ALL_STATES;
- ngOnInit(): void {
+ constructor(private store: Store, private ngxsActions$: Actions) {}
+
+ ngOnInit() {
this.clear();
+ this.ngxsActions$.pipe(ofActionCompleted(ClearTaskFilter), takeUntil(this.destroy$)).subscribe(() => this.clear());
}
- selectState(state: TaskState) {
+ setStatus(state: TaskState) {
this.filter.state = state ? [state] : [];
+ this.updateState();
}
- search() {
- this.performFilter.emit(this.filter);
+ // TODO: filter tasks when pressing 'enter'
+ search() {}
+
+ updateState() {
+ this.store.dispatch(new SetTaskFilter(this.filter));
}
clear() {
@@ -33,4 +43,9 @@ export class TaskFilterComponent implements OnInit {
'owner-like': []
};
}
+
+ ngOnDestroy() {
+ this.destroy$.next();
+ this.destroy$.complete();
+ }
}
diff --git a/web/src/app/shared/components/workbasket-filter/workbasket-filter.component.ts b/web/src/app/shared/components/workbasket-filter/workbasket-filter.component.ts
index b5f28462d..9c2a19052 100644
--- a/web/src/app/shared/components/workbasket-filter/workbasket-filter.component.ts
+++ b/web/src/app/shared/components/workbasket-filter/workbasket-filter.component.ts
@@ -2,7 +2,7 @@ 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 { Select, Store } from '@ngxs/store';
-import { ClearFilter, SetFilter } from '../../store/filter-store/filter.actions';
+import { ClearWorkbasketFilter, SetWorkbasketFilter } from '../../store/filter-store/filter.actions';
import { FilterSelectors } from '../../store/filter-store/filter.selectors';
import { Observable, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@@ -60,7 +60,7 @@ export class WorkbasketFilterComponent implements OnInit, OnDestroy {
}
clear() {
- this.store.dispatch(new ClearFilter(this.component));
+ this.store.dispatch(new ClearWorkbasketFilter(this.component));
}
selectType(type: WorkbasketType) {
@@ -68,7 +68,7 @@ export class WorkbasketFilterComponent implements OnInit, OnDestroy {
}
search() {
- this.store.dispatch(new SetFilter(this.filter, this.component));
+ this.store.dispatch(new SetWorkbasketFilter(this.filter, this.component));
}
ngOnDestroy() {
diff --git a/web/src/app/shared/store/filter-store/filter.actions.ts b/web/src/app/shared/store/filter-store/filter.actions.ts
index a746cb681..f1bb75e42 100644
--- a/web/src/app/shared/store/filter-store/filter.actions.ts
+++ b/web/src/app/shared/store/filter-store/filter.actions.ts
@@ -1,11 +1,23 @@
import { WorkbasketQueryFilterParameter } from '../../models/workbasket-query-filter-parameter';
+import { TaskQueryFilterParameter } from '../../models/task-query-filter-parameter';
-export class SetFilter {
- static readonly type = '[Workbasket filter] Set filter parameter';
+// Workbasket Filter
+export class SetWorkbasketFilter {
+ static readonly type = '[Workbasket filter] Set workbasket filter parameter';
constructor(public parameters: WorkbasketQueryFilterParameter, public component: string) {}
}
-export class ClearFilter {
- static readonly type = '[Workbasket filter] Clear filter parameter';
+export class ClearWorkbasketFilter {
+ static readonly type = '[Workbasket filter] Clear workbasket filter parameter';
constructor(public component: string) {}
}
+
+// Task Filter
+export class SetTaskFilter {
+ static readonly type = '[Task filter] Set task filter parameter';
+ constructor(public parameters: TaskQueryFilterParameter) {}
+}
+
+export class ClearTaskFilter {
+ static readonly type = '[Task filter] Clear task filter parameter';
+}
diff --git a/web/src/app/shared/store/filter-store/filter.selectors.ts b/web/src/app/shared/store/filter-store/filter.selectors.ts
index 06a0aff32..18f7a9eef 100644
--- a/web/src/app/shared/store/filter-store/filter.selectors.ts
+++ b/web/src/app/shared/store/filter-store/filter.selectors.ts
@@ -1,6 +1,7 @@
import { FilterState, FilterStateModel } from './filter.state';
import { Selector } from '@ngxs/store';
import { WorkbasketQueryFilterParameter } from '../../models/workbasket-query-filter-parameter';
+import { TaskQueryFilterParameter } from '../../models/task-query-filter-parameter';
export class FilterSelectors {
@Selector([FilterState])
@@ -17,4 +18,9 @@ export class FilterSelectors {
static getWorkbasketListFilter(state: FilterStateModel): WorkbasketQueryFilterParameter {
return state.workbasketList;
}
+
+ @Selector([FilterState])
+ static getTaskFilter(state: FilterStateModel): TaskQueryFilterParameter {
+ return state.tasks;
+ }
}
diff --git a/web/src/app/shared/store/filter-store/filter.state.ts b/web/src/app/shared/store/filter-store/filter.state.ts
index b8a3a8b0f..bc50e7d2b 100644
--- a/web/src/app/shared/store/filter-store/filter.state.ts
+++ b/web/src/app/shared/store/filter-store/filter.state.ts
@@ -1,9 +1,10 @@
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';
+import { ClearTaskFilter, ClearWorkbasketFilter, SetTaskFilter, SetWorkbasketFilter } from './filter.actions';
+import { TaskQueryFilterParameter } from '../../models/task-query-filter-parameter';
-const emptyFilter: WorkbasketQueryFilterParameter = {
+const emptyWorkbasketFilter: WorkbasketQueryFilterParameter = {
'description-like': [],
'key-like': [],
'name-like': [],
@@ -11,10 +12,20 @@ const emptyFilter: WorkbasketQueryFilterParameter = {
type: []
};
+const emptyTaskFilter: TaskQueryFilterParameter = {
+ 'name-like': [],
+ 'owner-like': [],
+ state: [],
+ priority: [],
+ 'por.value': [],
+ 'wildcard-search-fields': [],
+ 'wildcard-search-value': []
+};
+
@State({ name: 'FilterState' })
export class FilterState implements NgxsOnInit {
- @Action(SetFilter)
- setAvailableDistributionTargetsFilter(ctx: StateContext, action: SetFilter): Observable {
+ @Action(SetWorkbasketFilter)
+ setWorkbasketFilter(ctx: StateContext, action: SetWorkbasketFilter): Observable {
const currentState = ctx.getState()[action.component];
const param = action.parameters;
const filter: WorkbasketQueryFilterParameter = {
@@ -33,22 +44,66 @@ export class FilterState implements NgxsOnInit {
return of(null);
}
- @Action(ClearFilter)
- clearFilter(ctx: StateContext, action: ClearFilter): Observable {
+ @Action(ClearWorkbasketFilter)
+ clearWorkbasketFilter(ctx: StateContext, action: ClearWorkbasketFilter): Observable {
ctx.setState({
...ctx.getState(),
- [action.component]: { ...emptyFilter }
+ [action.component]: { ...emptyWorkbasketFilter }
});
return of(null);
}
+ @Action(SetTaskFilter)
+ setTaskFilter(ctx: StateContext, action: SetTaskFilter): Observable {
+ const param = action.parameters;
+ let filter = { ...ctx.getState().tasks };
+
+ Object.keys(param).forEach((key) => {
+ filter[key] = [...param[key]];
+ });
+
+ const isWildcardSearch = filter['wildcard-search-value'].length !== 0 && filter['wildcard-search-value'] !== [''];
+ filter['wildcard-search-fields'] = isWildcardSearch ? this.initWildcardFields() : [];
+
+ // Delete wildcard search field 'NAME' if 'name-like' exists
+ if (filter['name-like'].length > 0 && filter['name-like'][0] !== '') {
+ filter['wildcard-search-fields'].shift();
+ }
+
+ ctx.setState({
+ ...ctx.getState(),
+ tasks: filter
+ });
+
+ return of(null);
+ }
+
+ @Action(ClearTaskFilter)
+ clearTaskFilter(ctx: StateContext): Observable {
+ ctx.setState({
+ ...ctx.getState(),
+ tasks: { ...emptyTaskFilter }
+ });
+
+ return of(null);
+ }
+
+ initWildcardFields() {
+ let wildcardSearchFields = ['NAME', 'DESCRIPTION'];
+ [...Array(16).keys()].map((number) => {
+ wildcardSearchFields.push(`CUSTOM_${number + 1}`);
+ });
+ return wildcardSearchFields;
+ }
+
ngxsOnInit(ctx: StateContext): void {
ctx.setState({
...ctx.getState(),
- availableDistributionTargets: emptyFilter,
- selectedDistributionTargets: emptyFilter,
- workbasketList: emptyFilter
+ availableDistributionTargets: emptyWorkbasketFilter,
+ selectedDistributionTargets: emptyWorkbasketFilter,
+ workbasketList: emptyWorkbasketFilter,
+ tasks: emptyTaskFilter
});
}
}
@@ -57,4 +112,5 @@ export interface FilterStateModel {
availableDistributionTargets: WorkbasketQueryFilterParameter;
selectedDistributionTargets: WorkbasketQueryFilterParameter;
workbasketList: WorkbasketQueryFilterParameter;
+ tasks: TaskQueryFilterParameter;
}
diff --git a/web/src/app/shared/store/workbasket-store/workbasket.state.ts b/web/src/app/shared/store/workbasket-store/workbasket.state.ts
index 1124afc08..790840e9c 100644
--- a/web/src/app/shared/store/workbasket-store/workbasket.state.ts
+++ b/web/src/app/shared/store/workbasket-store/workbasket.state.ts
@@ -37,7 +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';
+import { ClearWorkbasketFilter } from '../filter-store/filter.actions';
class InitializeStore {
static readonly type = '[Workbasket] Initializing state';
@@ -136,8 +136,8 @@ export class WorkbasketState implements NgxsAfterBootstrap {
.replace(/(workbaskets).*/g, `workbaskets/(detail:${action.workbasketId})?tab=${selectedComponent}`)
);
- ctx.dispatch(new ClearFilter('selectedDistributionTargets'));
- ctx.dispatch(new ClearFilter('availableDistributionTargets'));
+ ctx.dispatch(new ClearWorkbasketFilter('selectedDistributionTargets'));
+ ctx.dispatch(new ClearWorkbasketFilter('availableDistributionTargets'));
})
);
}
@@ -224,8 +224,8 @@ export class WorkbasketState implements NgxsAfterBootstrap {
badgeMessage: `Copying workbasket: ${workbasket.key}`
});
- ctx.dispatch(new ClearFilter('selectedDistributionTargets'));
- ctx.dispatch(new ClearFilter('availableDistributionTargets'));
+ ctx.dispatch(new ClearWorkbasketFilter('selectedDistributionTargets'));
+ ctx.dispatch(new ClearWorkbasketFilter('availableDistributionTargets'));
return of(null);
}
@@ -261,8 +261,8 @@ export class WorkbasketState implements NgxsAfterBootstrap {
workbasketDistributionTargets: distributionTargets
});
- ctx.dispatch(new ClearFilter('selectedDistributionTargets'));
- ctx.dispatch(new ClearFilter('availableDistributionTargets'));
+ ctx.dispatch(new ClearWorkbasketFilter('selectedDistributionTargets'));
+ ctx.dispatch(new ClearWorkbasketFilter('availableDistributionTargets'));
return of(null);
})
@@ -433,8 +433,8 @@ export class WorkbasketState implements NgxsAfterBootstrap {
selectedWorkbasket,
action: ACTION.READ
});
- ctx.dispatch(new ClearFilter('selectedDistributionTargets'));
- ctx.dispatch(new ClearFilter('availableDistributionTargets'));
+ ctx.dispatch(new ClearWorkbasketFilter('selectedDistributionTargets'));
+ ctx.dispatch(new ClearWorkbasketFilter('availableDistributionTargets'));
});
}
this.requestInProgressService.setRequestInProgress(false);
diff --git a/web/src/app/workplace/components/task-list-toolbar/task-list-toolbar.component.html b/web/src/app/workplace/components/task-list-toolbar/task-list-toolbar.component.html
index 252b14bb1..a67722b59 100644
--- a/web/src/app/workplace/components/task-list-toolbar/task-list-toolbar.component.html
+++ b/web/src/app/workplace/components/task-list-toolbar/task-list-toolbar.component.html
@@ -35,13 +35,13 @@
- Type
+ Filter by type
- Value
+ Filter by value
diff --git a/web/src/app/workplace/components/task-list/task-list.component.html b/web/src/app/workplace/components/task-list/task-list.component.html
index ce8fc91bd..efe51155c 100644
--- a/web/src/app/workplace/components/task-list/task-list.component.html
+++ b/web/src/app/workplace/components/task-list/task-list.component.html
@@ -33,7 +33,7 @@
-
Select a workbasket
+ Select a Workbasket