sortSearch improvements (#4098)
- "no workflows set" removed - motion block filter hides if there is no motion block - inserted the group filter - fixed display of agenda filter menu - show plural if multiple filters are selected, show filtered amount - recommendation, done/not done status filter - active filter count and clearing option - number of current items to the left
This commit is contained in:
parent
57202e74ca
commit
82a1ad8709
@ -22,11 +22,15 @@ export interface OsFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes a list of available options for a drop down menu of a filter
|
||||
* Describes a list of available options for a drop down menu of a filter.
|
||||
* A filter condition of null will be interpreted as a negative filter
|
||||
* ('None of the other filter options').
|
||||
* Filter condition numbers/number arrays will be checked against numerical
|
||||
* values and as id(s) for objects.
|
||||
*/
|
||||
export interface OsFilterOption {
|
||||
label: string;
|
||||
condition: string | boolean | number;
|
||||
condition: string | boolean | number | number[];
|
||||
isActive?: boolean;
|
||||
}
|
||||
|
||||
@ -55,6 +59,47 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
|
||||
|
||||
protected name: string;
|
||||
|
||||
/**
|
||||
* @returns the total count of items before the filter
|
||||
*/
|
||||
public get totalCount(): number {
|
||||
return this.currentRawData ? this.currentRawData.length : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns the amount of items that pass the current filters
|
||||
*/
|
||||
public get filteredCount(): number {
|
||||
return this.filteredData ? this.filteredData.length : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of filters currently in use by this filter Service
|
||||
*
|
||||
* @returns a number of filters
|
||||
*/
|
||||
public get activeFilterCount(): number {
|
||||
if (!this.filterDefinitions || !this.filterDefinitions.length) {
|
||||
return 0;
|
||||
}
|
||||
let filters = 0;
|
||||
for (const filter of this.filterDefinitions) {
|
||||
if (filter.count) {
|
||||
filters += 1;
|
||||
}
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean indicationg if there are any filters described in this service
|
||||
*
|
||||
* @returns true if there are defined filters (regardless of current state)
|
||||
*/
|
||||
public get hasFilterOptions(): boolean {
|
||||
return this.filterDefinitions && this.filterDefinitions.length ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
@ -102,6 +147,12 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a filter option.
|
||||
*
|
||||
* @param filterName: The property name of this filter
|
||||
* @param option: The option to disable
|
||||
*/
|
||||
public removeFilterOption(filterName: string, option: OsFilterOption): void {
|
||||
const filter = this.filterDefinitions.find(f => f.property === filterName);
|
||||
if (filter) {
|
||||
@ -213,23 +264,84 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to see if a model instance passes a filter
|
||||
* Checks if a given ViewBaseModel passes the filter.
|
||||
*
|
||||
* @param item
|
||||
* @param filter
|
||||
* @returns true if the item is to be dispalyed according to the filter
|
||||
*/
|
||||
private checkIncluded(item: V, filter: OsFilter): boolean {
|
||||
const nullFilter = filter.options.find(
|
||||
option => typeof option !== 'string' && option.isActive && option.condition === null
|
||||
);
|
||||
let passesNullFilter = true;
|
||||
for (const option of filter.options) {
|
||||
// ignored options
|
||||
if (typeof option === 'string') {
|
||||
continue;
|
||||
} else if (nullFilter && option === nullFilter) {
|
||||
continue;
|
||||
// active option. The item is included if it passes this test
|
||||
} else if (option.isActive) {
|
||||
if (this.checkFilterIncluded(item, filter, option)) {
|
||||
return true;
|
||||
}
|
||||
if (option.isActive) {
|
||||
if (option.condition === null) {
|
||||
return this.checkIncludedNegative(item, filter);
|
||||
// if a null filter is set, the item needs to not pass all inactive filters
|
||||
} else if (
|
||||
nullFilter &&
|
||||
(item[filter.property] !== null || item[filter.property] !== undefined) &&
|
||||
this.checkFilterIncluded(item, filter, option)
|
||||
) {
|
||||
passesNullFilter = false;
|
||||
}
|
||||
}
|
||||
if (nullFilter && passesNullFilter) {
|
||||
return true;
|
||||
}
|
||||
if (item[filter.property] === undefined) {
|
||||
return false;
|
||||
}
|
||||
if (item[filter.property] instanceof BaseModel) {
|
||||
|
||||
/**
|
||||
* Checks an item against a single filter option.
|
||||
*
|
||||
* @param item A BaseModel to be checked
|
||||
* @param filter The parent filter
|
||||
* @param option The option to be checked
|
||||
* @returns true if the filter condition matches the item
|
||||
*/
|
||||
private checkFilterIncluded(item: V, filter: OsFilter, option: OsFilterOption): boolean {
|
||||
if (item[filter.property] === undefined || item[filter.property] === null) {
|
||||
return false;
|
||||
} else if (Array.isArray(item[filter.property])) {
|
||||
const compareValueCondition = (value, condition): boolean => {
|
||||
if (value === condition) {
|
||||
return true;
|
||||
} else if (value.hasOwnProperty('id') && value.id === condition) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
for (const value of item[filter.property]) {
|
||||
if (Array.isArray(option.condition)) {
|
||||
for (const condition of option.condition) {
|
||||
if (compareValueCondition(value, condition)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (compareValueCondition(value, option.condition)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (Array.isArray(option.condition)) {
|
||||
if (
|
||||
option.condition.indexOf(item[filter.property]) > -1 ||
|
||||
option.condition.indexOf(item[filter.property].id) > -1
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
} else if (typeof item[filter.property] === 'object' && item[filter.property].hasOwnProperty('id')) {
|
||||
if (item[filter.property].id === option.condition) {
|
||||
return true;
|
||||
}
|
||||
@ -238,34 +350,15 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
|
||||
} else if (item[filter.property].toString() === option.condition) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if none of the defined non-null filters apply,
|
||||
* aka 'items that match no filter'
|
||||
* @param item: A viewModel
|
||||
* Retrieves a translatable label or filter property used for displaying the filter
|
||||
*
|
||||
* @param filter
|
||||
* @returns a name, capitalized first character
|
||||
*/
|
||||
private checkIncludedNegative(item: V, filter: OsFilter): boolean {
|
||||
if (item[filter.property] === undefined) {
|
||||
return true;
|
||||
}
|
||||
for (const option of filter.options) {
|
||||
if (typeof option === 'string' || option.condition === null) {
|
||||
continue;
|
||||
}
|
||||
if (item[filter.property] === option.condition) {
|
||||
return false;
|
||||
} else if (item[filter.property].toString() === option.condition) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public getFilterName(filter: OsFilter): string {
|
||||
if (filter.label) {
|
||||
return filter.label;
|
||||
@ -275,20 +368,24 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
|
||||
}
|
||||
}
|
||||
|
||||
public get hasActiveFilters(): number {
|
||||
if (!this.filterDefinitions || !this.filterDefinitions.length) {
|
||||
return 0;
|
||||
/**
|
||||
* Removes all active options of a given filter, clearing it
|
||||
* @param filter
|
||||
*/
|
||||
public clearFilter(filter: OsFilter): void {
|
||||
filter.options.forEach(option => {
|
||||
if (typeof option === 'object' && option.isActive) {
|
||||
this.removeFilterOption(filter.property, option);
|
||||
}
|
||||
let filters = 0;
|
||||
for (const filter of this.filterDefinitions) {
|
||||
if (filter.count) {
|
||||
filters += 1;
|
||||
}
|
||||
}
|
||||
return filters;
|
||||
});
|
||||
}
|
||||
|
||||
public hasFilterOptions(): boolean {
|
||||
return this.filterDefinitions && this.filterDefinitions.length ? true : false;
|
||||
/**
|
||||
* Removes all filters currently in use from this filterService
|
||||
*/
|
||||
public clearAllFilters(): void {
|
||||
this.filterDefinitions.forEach(filter => {
|
||||
this.clearFilter(filter);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,35 @@
|
||||
<div class="custom-table-header on-transition-fade">
|
||||
<div class="custom-table-header flex-spaced on-transition-fade">
|
||||
<div class="filter-count" *ngIf="filterService">
|
||||
<span>{{ filterService.filteredCount }} </span><span translate>of</span>
|
||||
<span> {{ filterService.totalCount }}</span>
|
||||
</div>
|
||||
<div class="current-filters" *ngIf="filterService && filterService.activeFilterCount">
|
||||
<div>
|
||||
<span translate>Active filters</span>:
|
||||
</div>
|
||||
<div>
|
||||
<button mat-button (click)="filterService.clearAllFilters()">
|
||||
<mat-icon inline>cancel</mat-icon>
|
||||
<span translate>Clear all</span>
|
||||
</button>
|
||||
</div>
|
||||
<div *ngFor="let filter of filterService.filterDefinitions">
|
||||
<button mat-button *ngIf="filter.count" (click)="filterService.clearFilter(filter)">
|
||||
<mat-icon inline>close</mat-icon>
|
||||
<span translate>{{ filterService.getFilterName(filter) }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button mat-button *ngIf="hasFilters" (click)="filterMenu.opened ? filterMenu.close() : filterMenu.open()">
|
||||
<span *ngIf="filterService.hasActiveFilters > 0">{{ filterService.hasActiveFilters }} </span>
|
||||
<span class="upper" translate>Filter</span>
|
||||
<span *ngIf="!filterService.activeFilterCount" class="upper" translate>
|
||||
Filter
|
||||
</span>
|
||||
<span *ngIf="filterService.activeFilterCount">
|
||||
{{ filterService.activeFilterCount }}
|
||||
<span *ngIf="filterService.activeFilterCount === 1" class="upper" translate>Filter</span>
|
||||
<span *ngIf="filterService.activeFilterCount > 1" class="upper" translate>Filters</span>
|
||||
</span>
|
||||
</button>
|
||||
<button mat-button *ngIf="vp.isMobile && hasSorting" (click)="openSortDropDown()">
|
||||
<span class="upper" translate>Sort</span>
|
||||
@ -20,6 +48,7 @@
|
||||
<button mat-button (click)="toggleSearchBar()">
|
||||
<mat-icon>{{ isSearchBar ? 'keyboard_arrow_right' : 'search' }}</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Header for the filter side bar -->
|
||||
|
@ -8,3 +8,26 @@
|
||||
span.right-with-margin {
|
||||
margin-right: 25px;
|
||||
}
|
||||
|
||||
.flex-spaced {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.filter-count {
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
min-width: 50px;
|
||||
}
|
||||
|
||||
.current-filters {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin: 5px;
|
||||
button {
|
||||
padding: 3px;
|
||||
font-size: 80%;
|
||||
margin: 5px;
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
|
||||
* be a FilterListService extendingFilterListService.
|
||||
*/
|
||||
@Input()
|
||||
public filterService: any; // TODO a FilterListService extendingFilterListService
|
||||
public filterService: any; // TODO a FilterListService extending FilterListService
|
||||
|
||||
@Output()
|
||||
public searchFieldChange = new EventEmitter<string>();
|
||||
@ -112,7 +112,7 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
|
||||
* Checks if there is an active FilterService present
|
||||
*/
|
||||
public get hasFilters(): boolean {
|
||||
if (this.filterService && this.filterService.hasFilterOptions()) {
|
||||
if (this.filterService && this.filterService.hasFilterOptions) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -13,9 +13,10 @@
|
||||
</div>
|
||||
|
||||
</os-head-bar>
|
||||
<os-sort-filter-bar [filterService] = "filterService" (searchFieldChange)="searchFilter($event)"></os-sort-filter-bar>
|
||||
<mat-drawer-container class="on-transition-fade">
|
||||
<os-sort-filter-bar [filterService] = "filterService" (searchFieldChange)="searchFilter($event)"></os-sort-filter-bar>
|
||||
|
||||
<mat-table class="os-listview-table on-transition-fade" [dataSource]="dataSource" matSort>
|
||||
<mat-table class="os-listview-table on-transition-fade" [dataSource]="dataSource" matSort>
|
||||
<!-- selector column -->
|
||||
<ng-container matColumnDef="selector">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header class="checkbox-cell"></mat-header-cell>
|
||||
@ -83,8 +84,9 @@
|
||||
[ngClass]="selectedRows.indexOf(row) >= 0 ? 'selected' : ''"
|
||||
*matRowDef="let row; columns: getColumnDefinition()"
|
||||
></mat-row>
|
||||
</mat-table>
|
||||
<mat-paginator class="on-transition-fade" [pageSizeOptions]="[25, 50, 75, 100, 125]"></mat-paginator>
|
||||
</mat-table>
|
||||
<mat-paginator class="on-transition-fade" [pageSizeOptions]="[25, 50, 75, 100, 125]"></mat-paginator>
|
||||
</mat-drawer-container>
|
||||
|
||||
<mat-menu #agendaMenu="matMenu">
|
||||
<div *ngIf="!isMultiSelect">
|
||||
|
@ -33,6 +33,7 @@ export class AgendaFilterListService extends FilterListService<Item, ViewItem> {
|
||||
options: [{ label: 'Open', condition: false }, { label: 'Closed', condition: true }]
|
||||
}
|
||||
];
|
||||
this.updateFilterDefinitions(this.filterOptions);
|
||||
}
|
||||
|
||||
private createVisibilityFilterOptions(): OsFilterOption[] {
|
||||
|
@ -10,8 +10,7 @@ export class AssignmentSortListService extends SortListService<ViewAssignment> {
|
||||
sortProperty: 'assignment',
|
||||
sortAscending: true,
|
||||
options: [
|
||||
{ property: 'agendaItem', label: 'agenda Item' },
|
||||
{ property: 'assignment' },
|
||||
{ property: 'assignment', label: 'Name' },
|
||||
{ property: 'phase' },
|
||||
{ property: 'candidateAmount', label: 'Number of candidates' }
|
||||
]
|
||||
|
@ -134,6 +134,15 @@ export class ViewMotion extends BaseViewModel {
|
||||
return this._state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current state of thw workflow is final
|
||||
*
|
||||
* @returns true if it is final
|
||||
*/
|
||||
public get isFinalState(): boolean {
|
||||
return this._state.isFinalState;
|
||||
}
|
||||
|
||||
public get state_id(): number {
|
||||
return this.motion && this.motion.state_id ? this.motion.state_id : null;
|
||||
}
|
||||
@ -209,6 +218,18 @@ export class ViewMotion extends BaseViewModel {
|
||||
return this._attachments ? this._attachments : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the comments' section ids of a motion. Used in filter by motionComment
|
||||
*
|
||||
* @returns an array of ids, or an empty array
|
||||
*/
|
||||
public get commentSectionIds(): number[] {
|
||||
if (!this.motion) {
|
||||
return [];
|
||||
}
|
||||
return this.motion.comments.map(comment => comment.section_id);
|
||||
}
|
||||
|
||||
public constructor(
|
||||
motion?: Motion,
|
||||
category?: Category,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { FilterListService, OsFilter } from '../../../core/services/filter-list.service';
|
||||
import { FilterListService, OsFilter, OsFilterOption } from '../../../core/services/filter-list.service';
|
||||
import { Motion } from '../../../shared/models/motions/motion';
|
||||
import { ViewMotion } from '../models/view-motion';
|
||||
import { CategoryRepositoryService } from './category-repository.service';
|
||||
@ -8,6 +8,7 @@ import { WorkflowRepositoryService } from './workflow-repository.service';
|
||||
import { StorageService } from '../../../core/services/storage.service';
|
||||
import { MotionRepositoryService } from './motion-repository.service';
|
||||
import { MotionBlockRepositoryService } from './motion-block-repository.service';
|
||||
import { MotionCommentSectionRepositoryService } from './motion-comment-section-repository.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -19,19 +20,22 @@ export class MotionFilterListService extends FilterListService<Motion, ViewMotio
|
||||
* generated dynamically, as the options change with the datastore
|
||||
*/
|
||||
public get filterOptions(): OsFilter[] {
|
||||
return [this.flowFilterOptions, this.categoryFilterOptions, this.motionBlockFilterOptions].concat(
|
||||
this.staticFilterOptions
|
||||
);
|
||||
return [
|
||||
this.flowFilterOptions,
|
||||
this.categoryFilterOptions,
|
||||
this.motionBlockFilterOptions,
|
||||
this.recommendationFilterOptions,
|
||||
this.motionCommentFilterOptions
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter definitions for the workflow filter. Options will be generated by
|
||||
* getFilterOptions (as the workflows available may change)
|
||||
*/
|
||||
public flowFilterOptions = {
|
||||
public flowFilterOptions: OsFilter = {
|
||||
property: 'state',
|
||||
label: 'State',
|
||||
isActive: false,
|
||||
options: []
|
||||
};
|
||||
|
||||
@ -39,35 +43,46 @@ export class MotionFilterListService extends FilterListService<Motion, ViewMotio
|
||||
* Filter definitions for the category filter. Options will be generated by
|
||||
* getFilterOptions (as the categories available may change)
|
||||
*/
|
||||
public categoryFilterOptions = {
|
||||
public categoryFilterOptions: OsFilter = {
|
||||
property: 'category',
|
||||
isActive: false,
|
||||
options: []
|
||||
};
|
||||
|
||||
public motionBlockFilterOptions = {
|
||||
public motionBlockFilterOptions: OsFilter = {
|
||||
property: 'motion_block_id',
|
||||
label: 'Motion block',
|
||||
isActive: false,
|
||||
options: []
|
||||
};
|
||||
public commentFilterOptions = {
|
||||
property: 'comment',
|
||||
isActive: false,
|
||||
options: []
|
||||
};
|
||||
|
||||
public staticFilterOptions = [
|
||||
// TODO favorite (attached to user:whoamI!)
|
||||
// TODO personalNote (attached to user:whoamI!)
|
||||
];
|
||||
public motionCommentFilterOptions: OsFilter = {
|
||||
property: 'commentSectionIds',
|
||||
label: 'Comment',
|
||||
options: []
|
||||
};
|
||||
|
||||
public recommendationFilterOptions: OsFilter = {
|
||||
property: 'recommendation',
|
||||
label: 'Recommendation',
|
||||
options: []
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor. Subscribes to a variety of Repository to dynamically update
|
||||
* the available filters
|
||||
*
|
||||
* @param store The browser's storage; required for fetching filters from any previous sessions
|
||||
* @param workflowRepo Subscribing to filters by states/Recommendation
|
||||
* @param categoryRepo Subscribing to filters by Categories
|
||||
* @param motionBlockRepo Subscribing to filters by MotionBlock
|
||||
* @param commentRepo subycribing filter by presense of comment
|
||||
* @param motionRepo the motion's own repository, required by the parent
|
||||
*/
|
||||
public constructor(
|
||||
store: StorageService,
|
||||
private workflowRepo: WorkflowRepositoryService,
|
||||
private categoryRepo: CategoryRepositoryService,
|
||||
private motionBlockRepo: MotionBlockRepositoryService,
|
||||
// private commentRepo: MotionCommentRepositoryService
|
||||
private commentRepo: MotionCommentSectionRepositoryService,
|
||||
motionRepo: MotionRepositoryService
|
||||
) {
|
||||
super(store, motionRepo);
|
||||
@ -77,6 +92,20 @@ export class MotionFilterListService extends FilterListService<Motion, ViewMotio
|
||||
this.subscribeComments();
|
||||
}
|
||||
|
||||
// TODO: Notes/Favorite
|
||||
// does not work, some cloning error. I want to:
|
||||
// 'check all items in filterService against this function, in the
|
||||
// scope of motion-filter.service'
|
||||
// public getNoteFilterFn(): Function {
|
||||
// const notesRepo = this.notesRepo;
|
||||
// return (m: ViewMotion) => {
|
||||
// return notesRepo.hasPersonalNote('Motion', m.id)
|
||||
// }
|
||||
// };
|
||||
|
||||
/**
|
||||
* Subscibes to changing MotionBlocks, and updates the filter accordingly
|
||||
*/
|
||||
private subscribeMotionBlocks(): void {
|
||||
this.motionBlockRepo.getViewModelListObservable().subscribe(motionBlocks => {
|
||||
const motionBlockOptions = [];
|
||||
@ -87,20 +116,25 @@ export class MotionFilterListService extends FilterListService<Motion, ViewMotio
|
||||
isActive: false
|
||||
});
|
||||
});
|
||||
if (motionBlocks.length) {
|
||||
motionBlockOptions.push('-');
|
||||
motionBlockOptions.push({
|
||||
condition: null,
|
||||
label: 'No motion block set',
|
||||
isActive: false
|
||||
});
|
||||
}
|
||||
this.motionBlockFilterOptions.options = motionBlockOptions;
|
||||
this.updateFilterDefinitions(this.filterOptions);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscibes to changing Categories, and updates the filter accordingly
|
||||
*/
|
||||
private subscribeCategories(): void {
|
||||
this.categoryRepo.getViewModelListObservable().subscribe(categories => {
|
||||
const categoryOptions = [];
|
||||
const categoryOptions: (OsFilterOption | string)[] = [];
|
||||
categories.forEach(cat => {
|
||||
categoryOptions.push({
|
||||
condition: cat.id,
|
||||
@ -108,36 +142,96 @@ export class MotionFilterListService extends FilterListService<Motion, ViewMotio
|
||||
isActive: false
|
||||
});
|
||||
});
|
||||
if (categories.length) {
|
||||
categoryOptions.push('-');
|
||||
categoryOptions.push({
|
||||
label: 'No category set',
|
||||
condition: null
|
||||
});
|
||||
}
|
||||
this.categoryFilterOptions.options = categoryOptions;
|
||||
this.updateFilterDefinitions(this.filterOptions);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscibes to changing Workflows, and updates the state and recommendation filters accordingly
|
||||
*/
|
||||
private subscribeWorkflows(): void {
|
||||
this.workflowRepo.getViewModelListObservable().subscribe(workflows => {
|
||||
const workflowOptions = [];
|
||||
const workflowOptions: (OsFilterOption | string)[] = [];
|
||||
const finalStates: number[] = [];
|
||||
const nonFinalStates: number[] = [];
|
||||
const recommendationOptions: (OsFilterOption | string)[] = [];
|
||||
workflows.forEach(workflow => {
|
||||
workflowOptions.push(workflow.name);
|
||||
recommendationOptions.push(workflow.name);
|
||||
workflow.states.forEach(state => {
|
||||
if (state.isFinalState) {
|
||||
finalStates.push(state.id);
|
||||
} else {
|
||||
nonFinalStates.push(state.id);
|
||||
}
|
||||
workflowOptions.push({
|
||||
condition: state.name,
|
||||
condition: state.id,
|
||||
label: state.name,
|
||||
isActive: false
|
||||
});
|
||||
});
|
||||
});
|
||||
workflowOptions.push('-');
|
||||
workflowOptions.push({
|
||||
condition: null,
|
||||
label: 'no workflow set',
|
||||
if (state.recommendation_label) {
|
||||
recommendationOptions.push({
|
||||
condition: state.id,
|
||||
label: state.recommendation_label,
|
||||
isActive: false
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
if (workflowOptions.length) {
|
||||
workflowOptions.push('-');
|
||||
workflowOptions.push({
|
||||
label: 'Done',
|
||||
condition: finalStates
|
||||
});
|
||||
workflowOptions.push({
|
||||
label: 'Undone',
|
||||
condition: nonFinalStates
|
||||
});
|
||||
}
|
||||
if (recommendationOptions.length) {
|
||||
recommendationOptions.push('-');
|
||||
recommendationOptions.push({
|
||||
label: 'No recommendation',
|
||||
condition: null
|
||||
});
|
||||
}
|
||||
this.flowFilterOptions.options = workflowOptions;
|
||||
this.recommendationFilterOptions.options = recommendationOptions;
|
||||
this.updateFilterDefinitions(this.filterOptions);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscibes to changing Comments, and updates the filter accordingly
|
||||
*/
|
||||
private subscribeComments(): void {
|
||||
// TODO
|
||||
this.commentRepo.getViewModelListObservable().subscribe(comments => {
|
||||
const commentOptions: (OsFilterOption | string)[] = [];
|
||||
comments.forEach(comm => {
|
||||
commentOptions.push({
|
||||
condition: comm.id,
|
||||
label: comm.name,
|
||||
isActive: false
|
||||
});
|
||||
});
|
||||
if (comments.length) {
|
||||
commentOptions.push('-');
|
||||
commentOptions.push({
|
||||
label: 'No comment',
|
||||
condition: null
|
||||
});
|
||||
}
|
||||
this.motionCommentFilterOptions.options = commentOptions;
|
||||
this.updateFilterDefinitions(this.filterOptions);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ export class UserFilterListService extends FilterListService<User, ViewUser> {
|
||||
public subscribeGroups(): void {
|
||||
this.groupRepo.getViewModelListObservable().subscribe(groups => {
|
||||
const groupOptions = [];
|
||||
groupOptions.forEach(group => {
|
||||
groups.forEach(group => {
|
||||
groupOptions.push({
|
||||
condition: group.name,
|
||||
label: group.name,
|
||||
|
Loading…
Reference in New Issue
Block a user