refactor filter models
This commit is contained in:
parent
1df154926a
commit
6654bd9e8a
@ -20,7 +20,7 @@ import { FileDataModel } from '@models/file/file-data.model';
|
||||
import { CommentsComponent } from '../comments/comments.component';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { CircleButtonTypes, FilterModel, IconButtonTypes } from '@iqser/common-ui';
|
||||
import { CircleButtonTypes, NestedFilter, IconButtonTypes } from '@iqser/common-ui';
|
||||
|
||||
const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape'];
|
||||
const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
|
||||
@ -39,8 +39,8 @@ export class FileWorkloadComponent {
|
||||
@Input() activeViewerPage: number;
|
||||
@Input() shouldDeselectAnnotationsOnPageChange: boolean;
|
||||
@Input() dialogRef: MatDialogRef<any>;
|
||||
@Input() primaryFilters: FilterModel[];
|
||||
@Input() secondaryFilters: FilterModel[];
|
||||
@Input() primaryFilters: NestedFilter[];
|
||||
@Input() secondaryFilters: NestedFilter[];
|
||||
@Input() fileData: FileDataModel;
|
||||
@Input() hideSkipped: boolean;
|
||||
@Input() excludePages: boolean;
|
||||
@ -143,7 +143,7 @@ export class FileWorkloadComponent {
|
||||
}
|
||||
|
||||
@debounce(0)
|
||||
filtersChanged(filters: { primary: FilterModel[]; secondary?: FilterModel[] }) {
|
||||
filtersChanged(filters: { primary: NestedFilter[]; secondary?: NestedFilter[] }) {
|
||||
this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(
|
||||
this._annotations,
|
||||
filters.primary,
|
||||
@ -268,8 +268,8 @@ export class FileWorkloadComponent {
|
||||
this.selectPage.emit(this._nextPageWithAnnotations());
|
||||
}
|
||||
|
||||
_(filter): FilterModel {
|
||||
return filter as FilterModel;
|
||||
_(filter): NestedFilter {
|
||||
return filter as NestedFilter;
|
||||
}
|
||||
|
||||
private _selectFirstAnnotationOnCurrentPageIfNecessary() {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { FilterModel } from '@iqser/common-ui';
|
||||
import { NestedFilter } from '@iqser/common-ui';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-type-filter',
|
||||
@ -8,7 +8,7 @@ import { FilterModel } from '@iqser/common-ui';
|
||||
styleUrls: ['./type-filter.component.scss']
|
||||
})
|
||||
export class TypeFilterComponent implements OnInit {
|
||||
@Input() filter: FilterModel;
|
||||
@Input() filter: NestedFilter;
|
||||
|
||||
dictionaryColor: string;
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import { DossiersDialogService } from '../../services/dossiers-dialog.service';
|
||||
import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { ButtonConfig } from '@shared/components/page-header/models/button-config.model';
|
||||
import { FilterModel, FilterService } from '@iqser/common-ui';
|
||||
import { FilterService, NestedFilter } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
@ -204,7 +204,7 @@ export class DossierListingScreenComponent
|
||||
allDistinctDossierTemplates.add(entry.dossierTemplateId);
|
||||
});
|
||||
|
||||
const statusFilters = [...allDistinctFileStatus].map<FilterModel>(status => ({
|
||||
const statusFilters = [...allDistinctFileStatus].map<NestedFilter>(status => ({
|
||||
key: status,
|
||||
label: this._translateService.instant(fileStatusTranslations[status])
|
||||
}));
|
||||
@ -217,7 +217,7 @@ export class DossierListingScreenComponent
|
||||
checker: dossierStatusChecker
|
||||
});
|
||||
|
||||
const peopleFilters = [...allDistinctPeople].map<FilterModel>(userId => ({
|
||||
const peopleFilters = [...allDistinctPeople].map<NestedFilter>(userId => ({
|
||||
key: userId,
|
||||
label: this._userService.getNameForId(userId)
|
||||
}));
|
||||
@ -230,7 +230,7 @@ export class DossierListingScreenComponent
|
||||
checker: dossierMemberChecker
|
||||
});
|
||||
|
||||
const needsWorkFilters = [...allDistinctNeedsWork].map<FilterModel>(type => ({
|
||||
const needsWorkFilters = [...allDistinctNeedsWork].map<NestedFilter>(type => ({
|
||||
key: type,
|
||||
label: workloadTranslations[type]
|
||||
}));
|
||||
@ -246,7 +246,7 @@ export class DossierListingScreenComponent
|
||||
checkerArgs: this.permissionsService
|
||||
});
|
||||
|
||||
const dossierTemplateFilters = [...allDistinctDossierTemplates].map<FilterModel>(id => ({
|
||||
const dossierTemplateFilters = [...allDistinctDossierTemplates].map<NestedFilter>(id => ({
|
||||
key: id,
|
||||
label: this._appStateService.getDossierTemplateById(id).name
|
||||
}));
|
||||
@ -270,7 +270,7 @@ export class DossierListingScreenComponent
|
||||
|
||||
private _createQuickFilters() {
|
||||
const myDossiersLabel = this._translateService.instant('dossier-listing.quick-filters.my-dossiers');
|
||||
const filters: FilterModel[] = [
|
||||
const filters: NestedFilter[] = [
|
||||
{
|
||||
key: 'my-dossiers',
|
||||
label: myDossiersLabel,
|
||||
|
||||
@ -21,7 +21,7 @@ import { DossierWrapper } from '@state/model/dossier.wrapper';
|
||||
import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy';
|
||||
import { AppConfigKey, AppConfigService } from '@app-config/app-config.service';
|
||||
import { ActionConfig } from '@shared/components/page-header/models/action-config.model';
|
||||
import { FilterModel, FilterService, keyChecker } from '@iqser/common-ui';
|
||||
import { NestedFilter, FilterService, keyChecker } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { ScreenStateService } from '@shared/services/screen-state.service';
|
||||
import { SortingService } from '@services/sorting.service';
|
||||
@ -305,7 +305,7 @@ export class DossierOverviewScreenComponent
|
||||
if (file.hasNone) allDistinctNeedsWork.add('none');
|
||||
});
|
||||
|
||||
const statusFilters = [...allDistinctFileStatusWrapper].map<FilterModel>(item => ({
|
||||
const statusFilters = [...allDistinctFileStatusWrapper].map<NestedFilter>(item => ({
|
||||
key: item,
|
||||
label: this._translateService.instant(fileStatusTranslations[item])
|
||||
}));
|
||||
@ -341,7 +341,7 @@ export class DossierOverviewScreenComponent
|
||||
checker: keyChecker('currentReviewer')
|
||||
});
|
||||
|
||||
const needsWorkFilters = [...allDistinctNeedsWork].map<FilterModel>(item => ({
|
||||
const needsWorkFilters = [...allDistinctNeedsWork].map<NestedFilter>(item => ({
|
||||
key: item,
|
||||
label: workloadTranslations[item]
|
||||
}));
|
||||
|
||||
@ -36,7 +36,7 @@ import { stampPDFPage } from '@utils/page-stamper';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { AutoUnsubscribeComponent, CircleButtonTypes } from '@iqser/common-ui';
|
||||
import { fileStatusTranslations } from '../../translations/file-status-translations';
|
||||
import { FilterModel } from '@iqser/common-ui';
|
||||
import { NestedFilter } from '@iqser/common-ui';
|
||||
import { processFilters } from '@iqser/common-ui';
|
||||
import { handleFilterDelta } from '@shared/components/filters/popup-filter/utils/filter-utils';
|
||||
|
||||
@ -59,8 +59,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribeComponent impleme
|
||||
fileData: FileDataModel;
|
||||
annotationData: AnnotationData;
|
||||
selectedAnnotations: AnnotationWrapper[];
|
||||
primaryFilters: FilterModel[];
|
||||
secondaryFilters: FilterModel[];
|
||||
primaryFilters: NestedFilter[];
|
||||
secondaryFilters: NestedFilter[];
|
||||
canPerformAnnotationActions: boolean;
|
||||
hideSkipped = false;
|
||||
displayPDFViewer = false;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, Injector, OnDestroy } from '@angular/core';
|
||||
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { MatchedDocument, SearchControllerService, SearchResult } from '@redaction/red-ui-http';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { debounceTime, map, skip, switchMap, tap } from 'rxjs/operators';
|
||||
@ -104,8 +104,8 @@ export class SearchScreenComponent extends BaseListingComponent<ListItem> implem
|
||||
.valueChanges.pipe(debounceTime(300))
|
||||
.subscribe(value => this.updateNavigation(value));
|
||||
|
||||
this.addSubscription = this.filterService.filterGroups$.pipe(skip(1)).subscribe(filters => {
|
||||
const dossierIds = filters[0].values.filter(v => v.checked).map(v => v.key);
|
||||
this.addSubscription = this.filterService.filterGroups$.pipe(skip(1)).subscribe(group => {
|
||||
const dossierIds = group[0].filters.filter(v => v.checked).map(v => v.key);
|
||||
this.search$.next({ query: this.searchService.searchValue, dossierIds: dossierIds });
|
||||
});
|
||||
}
|
||||
|
||||
@ -4,11 +4,11 @@ import { SuperTypeSorter } from '@utils/sorters/super-type-sorter';
|
||||
import { handleCheckedValue } from '@iqser/common-ui';
|
||||
import { annotationTypesTranslations } from '../../../translations/annotation-types-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { FilterModel } from '@iqser/common-ui';
|
||||
import { NestedFilter } from '@iqser/common-ui';
|
||||
|
||||
@Injectable()
|
||||
export class AnnotationProcessingService {
|
||||
static get secondaryAnnotationFilters(): FilterModel[] {
|
||||
static get secondaryAnnotationFilters(): NestedFilter[] {
|
||||
return [
|
||||
{
|
||||
key: 'with-comments',
|
||||
@ -16,7 +16,7 @@ export class AnnotationProcessingService {
|
||||
label: _('filter-menu.with-comments'),
|
||||
checked: false,
|
||||
topLevelFilter: true,
|
||||
filters: [],
|
||||
children: [],
|
||||
checker: (annotation: AnnotationWrapper) => annotation?.comments?.length > 0
|
||||
},
|
||||
{
|
||||
@ -25,15 +25,15 @@ export class AnnotationProcessingService {
|
||||
label: _('filter-menu.with-reason-changes'),
|
||||
checked: false,
|
||||
topLevelFilter: true,
|
||||
filters: [],
|
||||
children: [],
|
||||
checker: (annotation: AnnotationWrapper) => annotation?.legalBasisChangeValue?.length > 0
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
getAnnotationFilter(annotations: AnnotationWrapper[]): FilterModel[] {
|
||||
const filterMap = new Map<string, FilterModel>();
|
||||
const filters: FilterModel[] = [];
|
||||
getAnnotationFilter(annotations: AnnotationWrapper[]): NestedFilter[] {
|
||||
const filterMap = new Map<string, NestedFilter>();
|
||||
const filters: NestedFilter[] = [];
|
||||
|
||||
annotations?.forEach(a => {
|
||||
const topLevelFilter = a.superType !== 'hint' && a.superType !== 'redaction' && a.superType !== 'recommendation';
|
||||
@ -52,24 +52,25 @@ export class AnnotationProcessingService {
|
||||
}
|
||||
const childFilter = {
|
||||
key: a.dictionary,
|
||||
label: a.dictionary,
|
||||
checked: false,
|
||||
filters: [],
|
||||
matches: 1
|
||||
};
|
||||
filterMap.set(key, childFilter);
|
||||
parentFilter.filters.push(childFilter);
|
||||
parentFilter.children.push(childFilter);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for (const filter of filters) {
|
||||
filter.filters.sort((a, b) => a.key.localeCompare(b.key));
|
||||
filter.children.sort((a, b) => a.key.localeCompare(b.key));
|
||||
handleCheckedValue(filter);
|
||||
if (filter.checked || filter.indeterminate) {
|
||||
filter.expanded = true;
|
||||
}
|
||||
if (filter.filters.length > 0) {
|
||||
filter.matches = filter.filters.reduce((a, b) => a + b.matches, 0);
|
||||
if (filter.children.length > 0) {
|
||||
filter.matches = filter.children.reduce((a, b) => a + b.matches, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,8 +79,8 @@ export class AnnotationProcessingService {
|
||||
|
||||
filterAndGroupAnnotations(
|
||||
annotations: AnnotationWrapper[],
|
||||
primaryFilters: FilterModel[],
|
||||
secondaryFilters?: FilterModel[]
|
||||
primaryFilters: NestedFilter[],
|
||||
secondaryFilters?: NestedFilter[]
|
||||
): { [key: number]: { annotations: AnnotationWrapper[] } } {
|
||||
const obj = {};
|
||||
|
||||
@ -123,31 +124,31 @@ export class AnnotationProcessingService {
|
||||
return obj;
|
||||
}
|
||||
|
||||
private _createParentFilter(key: string, filterMap: Map<string, FilterModel>, filters: FilterModel[]) {
|
||||
const filter: FilterModel = {
|
||||
private _createParentFilter(key: string, filterMap: Map<string, NestedFilter>, filters: NestedFilter[]) {
|
||||
const filter: NestedFilter = {
|
||||
key: key,
|
||||
topLevelFilter: true,
|
||||
matches: 1,
|
||||
label: annotationTypesTranslations[key],
|
||||
filters: []
|
||||
children: []
|
||||
};
|
||||
filterMap.set(key, filter);
|
||||
filters.push(filter);
|
||||
return filter;
|
||||
}
|
||||
|
||||
private _getFlatFilters(filters: FilterModel[], filterBy?: (f: FilterModel) => boolean) {
|
||||
const flatFilters: FilterModel[] = [];
|
||||
private _getFlatFilters(filters: NestedFilter[], filterBy?: (f: NestedFilter) => boolean) {
|
||||
const flatFilters: NestedFilter[] = [];
|
||||
|
||||
filters.forEach(filter => {
|
||||
flatFilters.push(filter);
|
||||
flatFilters.push(...filter.filters);
|
||||
flatFilters.push(...filter.children);
|
||||
});
|
||||
|
||||
return filterBy ? flatFilters.filter(f => filterBy(f)) : flatFilters;
|
||||
}
|
||||
|
||||
private _matchesOne = (filters: FilterModel[], condition: (filter: FilterModel) => boolean): boolean => {
|
||||
private _matchesOne = (filters: NestedFilter[], condition: (filter: NestedFilter) => boolean): boolean => {
|
||||
if (filters.length === 0) return true;
|
||||
|
||||
for (const filter of filters) {
|
||||
@ -157,7 +158,7 @@ export class AnnotationProcessingService {
|
||||
return false;
|
||||
};
|
||||
|
||||
private _matchesAll = (filters: FilterModel[], condition: (filter: FilterModel) => boolean): boolean => {
|
||||
private _matchesAll = (filters: NestedFilter[], condition: (filter: NestedFilter) => boolean): boolean => {
|
||||
if (filters.length === 0) return true;
|
||||
|
||||
for (const filter of filters) {
|
||||
@ -167,7 +168,7 @@ export class AnnotationProcessingService {
|
||||
return true;
|
||||
};
|
||||
|
||||
private _checkByFilterKey = (filter: FilterModel, annotation: AnnotationWrapper) => {
|
||||
private _checkByFilterKey = (filter: NestedFilter, annotation: AnnotationWrapper) => {
|
||||
const superType = annotation.superType;
|
||||
const isNotTopLevelFilter = superType === 'hint' || superType === 'redaction' || superType === 'recommendation';
|
||||
|
||||
|
||||
@ -86,8 +86,8 @@
|
||||
<ng-container [ngTemplateOutletContext]="{ filter: filter }" [ngTemplateOutlet]="actionsTemplate ?? null"></ng-container>
|
||||
</div>
|
||||
|
||||
<div *ngIf="_(filter).filters?.length && _(filter).expanded">
|
||||
<div (click)="$event.stopPropagation()" *ngFor="let subFilter of _(filter).filters" class="padding-left mat-menu-item">
|
||||
<div *ngIf="_(filter).children?.length && _(filter).expanded">
|
||||
<div (click)="$event.stopPropagation()" *ngFor="let subFilter of _(filter).children" class="padding-left mat-menu-item">
|
||||
<mat-checkbox (click)="filterCheckboxClicked($event, subFilter, filter)" [checked]="subFilter.checked">
|
||||
<ng-container
|
||||
[ngTemplateOutletContext]="{ filter: subFilter }"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, TemplateRef } from '@angular/core';
|
||||
import { FilterModel } from '@iqser/common-ui';
|
||||
import { NestedFilter } from '@iqser/common-ui';
|
||||
import { handleCheckedValue } from '@iqser/common-ui';
|
||||
import { MAT_CHECKBOX_DEFAULT_OPTIONS } from '@angular/material/checkbox';
|
||||
|
||||
@ -19,13 +19,13 @@ import { MAT_CHECKBOX_DEFAULT_OPTIONS } from '@angular/material/checkbox';
|
||||
})
|
||||
export class PopupFilterComponent implements OnChanges {
|
||||
@Output() filtersChanged = new EventEmitter<{
|
||||
primary: FilterModel[];
|
||||
secondary?: FilterModel[];
|
||||
primary: NestedFilter[];
|
||||
secondary?: NestedFilter[];
|
||||
}>();
|
||||
@Input() filterTemplate: TemplateRef<any>;
|
||||
@Input() actionsTemplate: TemplateRef<any>;
|
||||
@Input() primaryFilters: FilterModel[] = [];
|
||||
@Input() secondaryFilters: FilterModel[] = [];
|
||||
@Input() primaryFilters: NestedFilter[] = [];
|
||||
@Input() secondaryFilters: NestedFilter[] = [];
|
||||
@Input() filterLabel;
|
||||
@Input() icon: string;
|
||||
|
||||
@ -38,7 +38,7 @@ export class PopupFilterComponent implements OnChanges {
|
||||
return !!this._allFilters.find(f => f.checked || f.indeterminate);
|
||||
}
|
||||
|
||||
private get _allFilters(): FilterModel[] {
|
||||
private get _allFilters(): NestedFilter[] {
|
||||
return [...(this.primaryFilters ?? []), ...(this.secondaryFilters ?? [])];
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ export class PopupFilterComponent implements OnChanges {
|
||||
this.atLeastOneSecondaryFilterIsExpandable = !!this.secondaryFilters?.find(f => this.isExpandable(f));
|
||||
}
|
||||
|
||||
filterCheckboxClicked($event: any, filter: FilterModel, parent?: FilterModel) {
|
||||
filterCheckboxClicked($event: any, filter: NestedFilter, parent?: NestedFilter) {
|
||||
$event.stopPropagation();
|
||||
|
||||
filter.checked = !filter.checked;
|
||||
@ -57,7 +57,7 @@ export class PopupFilterComponent implements OnChanges {
|
||||
} else {
|
||||
if (filter.indeterminate) filter.checked = false;
|
||||
filter.indeterminate = false;
|
||||
filter.filters?.forEach(f => (f.checked = filter.checked));
|
||||
filter.children?.forEach(f => (f.checked = filter.checked));
|
||||
}
|
||||
|
||||
this.applyFilters();
|
||||
@ -79,17 +79,17 @@ export class PopupFilterComponent implements OnChanges {
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
toggleFilterExpanded($event: MouseEvent, filter: FilterModel) {
|
||||
toggleFilterExpanded($event: MouseEvent, filter: NestedFilter) {
|
||||
$event.stopPropagation();
|
||||
filter.expanded = !filter.expanded;
|
||||
}
|
||||
|
||||
isExpandable(filter: FilterModel) {
|
||||
return filter?.filters?.length > 0;
|
||||
isExpandable(filter: NestedFilter) {
|
||||
return filter?.children?.length > 0;
|
||||
}
|
||||
|
||||
_(obj): FilterModel {
|
||||
return obj as FilterModel;
|
||||
_(obj): NestedFilter {
|
||||
return obj as NestedFilter;
|
||||
}
|
||||
|
||||
private _setFilters(onlyPrimaryFilters = false) {
|
||||
@ -97,7 +97,7 @@ export class PopupFilterComponent implements OnChanges {
|
||||
filters.forEach(f => {
|
||||
f.checked = onlyPrimaryFilters;
|
||||
f.indeterminate = false;
|
||||
f.filters?.forEach(ff => (ff.checked = onlyPrimaryFilters));
|
||||
f.children?.forEach(ff => (ff.checked = onlyPrimaryFilters));
|
||||
});
|
||||
this.applyFilters();
|
||||
}
|
||||
|
||||
@ -2,20 +2,20 @@ import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { DossierWrapper } from '@state/model/dossier.wrapper';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { handleCheckedValue } from '@iqser/common-ui';
|
||||
import { FilterModel } from '@iqser/common-ui';
|
||||
import { NestedFilter } from '@iqser/common-ui';
|
||||
|
||||
export function handleFilterDelta(oldFilters: FilterModel[], newFilters: FilterModel[], allFilters: FilterModel[]) {
|
||||
export function handleFilterDelta(oldFilters: NestedFilter[], newFilters: NestedFilter[], allFilters: NestedFilter[]) {
|
||||
const newFiltersDelta = {};
|
||||
for (const newFilter of newFilters) {
|
||||
const oldFilter = oldFilters.find(f => f.key === newFilter.key);
|
||||
if (!oldFilter || oldFilter.matches !== newFilter.matches) {
|
||||
newFiltersDelta[newFilter.key] = {};
|
||||
newFilter.filters.forEach(filter => (newFiltersDelta[newFilter.key][filter.key] = {}));
|
||||
newFilter.children.forEach(filter => (newFiltersDelta[newFilter.key][filter.key] = {}));
|
||||
}
|
||||
|
||||
if (!oldFilter) {
|
||||
for (const childFilter of newFilter.filters) {
|
||||
const oldFilterChild = oldFilter?.filters.find(f => f.key === childFilter.key);
|
||||
for (const childFilter of newFilter.children) {
|
||||
const oldFilterChild = oldFilter?.children.find(f => f.key === childFilter.key);
|
||||
if (!oldFilterChild || oldFilterChild.matches !== childFilter.matches) {
|
||||
if (!newFiltersDelta[newFilter.key]) {
|
||||
newFiltersDelta[newFilter.key] = {};
|
||||
@ -30,11 +30,11 @@ export function handleFilterDelta(oldFilters: FilterModel[], newFilters: FilterM
|
||||
const foundFilter = allFilters.find(f => f.key === key);
|
||||
if (foundFilter) {
|
||||
// if has children
|
||||
if (!foundFilter.filters?.length) {
|
||||
if (!foundFilter.children?.length) {
|
||||
foundFilter.checked = true;
|
||||
} else {
|
||||
for (const subKey of Object.keys(newFiltersDelta[key])) {
|
||||
const childFilter = foundFilter.filters.find(f => f.key === subKey);
|
||||
const childFilter = foundFilter.children.find(f => f.key === subKey);
|
||||
if (childFilter) {
|
||||
childFilter.checked = true;
|
||||
}
|
||||
@ -49,7 +49,7 @@ export function handleFilterDelta(oldFilters: FilterModel[], newFilters: FilterM
|
||||
|
||||
export const annotationFilterChecker = (
|
||||
input: FileStatusWrapper | DossierWrapper,
|
||||
filter: FilterModel,
|
||||
filter: NestedFilter,
|
||||
permissionsService: PermissionsService
|
||||
) => {
|
||||
switch (filter.key) {
|
||||
@ -81,10 +81,13 @@ export const annotationFilterChecker = (
|
||||
}
|
||||
};
|
||||
|
||||
export const dossierStatusChecker = (dw: DossierWrapper, filter: FilterModel) => dw.hasStatus(filter.key);
|
||||
export const dossierStatusChecker = (dw: DossierWrapper, filter: NestedFilter) => {
|
||||
console.log(dw, filter);
|
||||
return dw.hasStatus(filter.key);
|
||||
};
|
||||
|
||||
export const dossierMemberChecker = (dw: DossierWrapper, filter: FilterModel) => dw.hasMember(filter.key);
|
||||
export const dossierMemberChecker = (dw: DossierWrapper, filter: NestedFilter) => dw.hasMember(filter.key);
|
||||
|
||||
export const dossierTemplateChecker = (dw: DossierWrapper, filter: FilterModel) => dw.dossierTemplateId === filter.key;
|
||||
export const dossierTemplateChecker = (dw: DossierWrapper, filter: NestedFilter) => dw.dossierTemplateId === filter.key;
|
||||
|
||||
export const dossierApproverChecker = (dw: DossierWrapper, filter: FilterModel) => dw.approverIds.includes(filter.key);
|
||||
export const dossierApproverChecker = (dw: DossierWrapper, filter: NestedFilter) => dw.approverIds.includes(filter.key);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { BaseHeaderConfig } from './base-config.model';
|
||||
|
||||
export interface ActionConfig extends BaseHeaderConfig {
|
||||
readonly action: ($event) => void;
|
||||
readonly action: ($event: MouseEvent) => void;
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { IconButtonType } from '@iqser/common-ui';
|
||||
import { BaseHeaderConfig } from './base-config.model';
|
||||
import { ActionConfig } from '@shared/components/page-header/models/action-config.model';
|
||||
|
||||
export interface ButtonConfig extends BaseHeaderConfig {
|
||||
readonly action: ($event) => void;
|
||||
export interface ButtonConfig extends ActionConfig {
|
||||
readonly type?: IconButtonType;
|
||||
}
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
import { FilterModel } from '@iqser/common-ui';
|
||||
import { TemplateRef } from '@angular/core';
|
||||
import { BaseHeaderConfig } from './base-config.model';
|
||||
|
||||
export interface FilterConfig extends BaseHeaderConfig {
|
||||
readonly primaryFilters?: FilterModel[];
|
||||
readonly primaryFiltersLabel?: string;
|
||||
readonly filterTemplate?: TemplateRef<any>;
|
||||
}
|
||||
@ -31,12 +31,8 @@ export class PageHeaderComponent {
|
||||
get _showResetFilters$(): Observable<boolean> {
|
||||
if (!this.filterService) return of(false);
|
||||
|
||||
const filtersLength$ = this.filters$.pipe(
|
||||
map(f => f.length),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
return combineLatest([filtersLength$, this.filterService.showResetFilters$, this.searchService.valueChanges$]).pipe(
|
||||
map(([hasFilters, showResetFilters, searchValue]) => hasFilters && (showResetFilters || !!searchValue)),
|
||||
return combineLatest([this.filterService.showResetFilters$, this.searchService.valueChanges$]).pipe(
|
||||
map(([showResetFilters, searchValue]) => showResetFilters || !!searchValue),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,25 +1,26 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
|
||||
import { BehaviorSubject, combineLatest, Observable, pipe } from 'rxjs';
|
||||
import { distinctUntilChanged, map, tap } from 'rxjs/operators';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { SearchService } from '@shared/services/search.service';
|
||||
import { getFilteredEntities } from '@iqser/common-ui';
|
||||
|
||||
const toLengthValue = entities => entities?.length ?? 0;
|
||||
const toLengthValue = (entities: unknown[]) => entities?.length ?? 0;
|
||||
const getLength = pipe(map(toLengthValue), distinctUntilChanged());
|
||||
|
||||
@Injectable()
|
||||
export class ScreenStateService<T> {
|
||||
private readonly _allEntities$ = new BehaviorSubject<T[]>([]);
|
||||
readonly allEntities$ = this._allEntities$.asObservable();
|
||||
readonly allEntitiesLength$ = this._allEntitiesLength$;
|
||||
readonly allEntitiesLength$ = this._allEntities$.pipe(getLength);
|
||||
|
||||
private readonly _displayedEntities$ = new BehaviorSubject<T[]>([]);
|
||||
readonly displayedEntities$ = this._getDisplayedEntities$;
|
||||
readonly displayedLength$ = this._displayedLength$;
|
||||
readonly displayedLength$ = this._displayedEntities$.pipe(getLength);
|
||||
|
||||
private readonly _selectedEntities$ = new BehaviorSubject<T[]>([]);
|
||||
readonly selectedEntities$ = this._selectedEntities$.asObservable();
|
||||
readonly selectedLength$ = this._selectedLength$;
|
||||
readonly selectedLength$ = this._selectedEntities$.pipe(getLength);
|
||||
|
||||
readonly noData$ = this._noData$;
|
||||
readonly areAllEntitiesSelected$ = this._areAllEntitiesSelected$;
|
||||
@ -57,18 +58,6 @@ export class ScreenStateService<T> {
|
||||
);
|
||||
}
|
||||
|
||||
private get _allEntitiesLength$(): Observable<number> {
|
||||
return this.allEntities$.pipe(map(toLengthValue), distinctUntilChanged());
|
||||
}
|
||||
|
||||
private get _displayedLength$(): Observable<number> {
|
||||
return this.displayedEntities$.pipe(map(toLengthValue), distinctUntilChanged());
|
||||
}
|
||||
|
||||
private get _selectedLength$(): Observable<number> {
|
||||
return this.selectedEntities$.pipe(map(toLengthValue), distinctUntilChanged());
|
||||
}
|
||||
|
||||
private get _areAllEntitiesSelected$(): Observable<boolean> {
|
||||
return combineLatest([this.displayedLength$, this.selectedLength$]).pipe(
|
||||
map(([displayedLength, selectedLength]) => displayedLength && displayedLength === selectedLength),
|
||||
@ -76,9 +65,6 @@ export class ScreenStateService<T> {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that some entities are selected. If all are selected this returns true
|
||||
*/
|
||||
private get _areSomeEntitiesSelected$(): Observable<boolean> {
|
||||
return this.selectedLength$.pipe(
|
||||
map(value => !!value),
|
||||
@ -86,9 +72,6 @@ export class ScreenStateService<T> {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that some entities are selected, but not all
|
||||
*/
|
||||
private get _notAllEntitiesSelected$(): Observable<boolean> {
|
||||
return combineLatest([this.areAllEntitiesSelected$, this.areSomeEntitiesSelected$]).pipe(
|
||||
map(([allEntitiesAreSelected, someEntitiesAreSelected]) => !allEntitiesAreSelected && someEntitiesAreSelected),
|
||||
@ -107,11 +90,11 @@ export class ScreenStateService<T> {
|
||||
return this.displayedEntities.length !== 0 && this.displayedEntities.length === this.selectedEntities.length;
|
||||
}
|
||||
|
||||
setEntities(newEntities: Partial<T[]>): void {
|
||||
setEntities(newEntities: T[]): void {
|
||||
this._allEntities$.next(newEntities);
|
||||
}
|
||||
|
||||
setSelectedEntities(newEntities: Partial<T[]>): void {
|
||||
setSelectedEntities(newEntities: T[]): void {
|
||||
this._selectedEntities$.next(newEntities);
|
||||
}
|
||||
|
||||
@ -120,7 +103,7 @@ export class ScreenStateService<T> {
|
||||
}
|
||||
|
||||
selectEntities(entities?: T[]): void {
|
||||
if (entities !== undefined && entities !== null && entities.length > 0) {
|
||||
if (entities?.length > 0) {
|
||||
return entities.forEach(entity => this._selectOne(entity));
|
||||
}
|
||||
return this._selectAll();
|
||||
|
||||
@ -94,8 +94,8 @@ export class DossierWrapper {
|
||||
return this.dossier.watermarkEnabled;
|
||||
}
|
||||
|
||||
hasStatus(status: string) {
|
||||
return this._files.find(f => f.status === status);
|
||||
hasStatus(status: string): boolean {
|
||||
return !!this._files.find(f => f.status === status);
|
||||
}
|
||||
|
||||
hasMember(key: string) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user