move filters to classes, add searchKey to entities
This commit is contained in:
parent
d1cc15ec23
commit
5387fef462
@ -64,7 +64,6 @@ export class FileStatusWrapper implements FileStatus, IListable {
|
||||
}
|
||||
}
|
||||
|
||||
readonly excludedPagesCount = this.excludedPages?.length ?? 0;
|
||||
readonly statusSort = StatusSorter[this.status];
|
||||
readonly pages = this._pages;
|
||||
readonly cacheIdentifier = btoa(this.lastUploaded + this.lastOCRTime);
|
||||
@ -88,6 +87,10 @@ export class FileStatusWrapper implements FileStatus, IListable {
|
||||
return this.fileId;
|
||||
}
|
||||
|
||||
get searchKey(): string {
|
||||
return this.filename;
|
||||
}
|
||||
|
||||
private get _pages() {
|
||||
if (this.fileStatus.status === 'ERROR') {
|
||||
return -1;
|
||||
|
||||
@ -100,7 +100,7 @@
|
||||
(click)="toggleFieldActive(field)"
|
||||
(mouseenter)="setHoveredColumn(field.csvColumn)"
|
||||
(mouseleave)="setHoveredColumn()"
|
||||
*ngFor="let field of sortedDisplayedEntities$ | async; trackBy: trackByPrimaryKey"
|
||||
*ngFor="let field of sortedDisplayedEntities$ | async"
|
||||
class="csv-header-pill-wrapper"
|
||||
>
|
||||
<div [class.selected]="isActive(field)" class="csv-header-pill">
|
||||
|
||||
@ -50,7 +50,7 @@
|
||||
|
||||
<div *ngIf="hasFiles" class="mt-24 legend pb-32">
|
||||
<div
|
||||
(click)="filterService.toggleFilter('needsWorkFilters', filter.key)"
|
||||
(click)="filterService.toggleFilter('needsWorkFilters', filter.id)"
|
||||
*ngFor="let filter of needsWorkFilters$ | async"
|
||||
[class.active]="filter.checked"
|
||||
>
|
||||
|
||||
@ -3,7 +3,7 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { AnnotationProcessingService } from '../../services/annotation-processing.service';
|
||||
import { MatDialogRef, MatDialogState } from '@angular/material/dialog';
|
||||
import scrollIntoView from 'scroll-into-view-if-needed';
|
||||
import { CircleButtonTypes, Debounce, FilterService, IconButtonTypes, IqserEventTarget, NestedFilter } from '@iqser/common-ui';
|
||||
import { CircleButtonTypes, Debounce, FilterService, IconButtonTypes, INestedFilter, IqserEventTarget } from '@iqser/common-ui';
|
||||
import { FileDataModel } from '@models/file/file-data.model';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { WebViewerInstance } from '@pdftron/webviewer';
|
||||
@ -122,8 +122,8 @@ export class FileWorkloadComponent {
|
||||
|
||||
private _filterAnnotations(
|
||||
annotations: AnnotationWrapper[],
|
||||
primary: NestedFilter[],
|
||||
secondary: NestedFilter[] = []
|
||||
primary: INestedFilter[],
|
||||
secondary: INestedFilter[] = []
|
||||
): Map<number, AnnotationWrapper[]> {
|
||||
if (!primary) {
|
||||
return;
|
||||
|
||||
@ -1,57 +1,57 @@
|
||||
<ng-container *ngIf="!filter.icon">
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.key === 'redaction'"
|
||||
*ngIf="filter.id === 'redaction'"
|
||||
[color]="dictionaryColor"
|
||||
label="R"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.key === 'recommendation'"
|
||||
*ngIf="filter.id === 'recommendation'"
|
||||
[color]="dictionaryColor"
|
||||
label="R"
|
||||
type="hexagon"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="filter.key === 'hint'" [color]="dictionaryColor" label="H" type="circle"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="filter.id === 'hint'" [color]="dictionaryColor" label="H" type="circle"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.key === 'manual-redaction'"
|
||||
*ngIf="filter.id === 'manual-redaction'"
|
||||
[color]="dictionaryColor"
|
||||
label="M"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.key === 'skipped'"
|
||||
*ngIf="filter.id === 'skipped'"
|
||||
[color]="dictionaryColor"
|
||||
label="S"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="isSuggestion(filter.key)"
|
||||
*ngIf="isSuggestion(filter.id)"
|
||||
[color]="dictionaryColor"
|
||||
label="S"
|
||||
type="rhombus"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="needsAnalysis(filter.key)"
|
||||
*ngIf="needsAnalysis(filter.id)"
|
||||
[color]="dictionaryColor"
|
||||
label="A"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.key === 'declined-suggestion'"
|
||||
*ngIf="filter.id === 'declined-suggestion'"
|
||||
[color]="dictionaryColor"
|
||||
label="S"
|
||||
type="rhombus"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="filter.key === 'none'" color="transparent" label="-" type="none"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="filter.id === 'none'" color="transparent" label="-" type="none"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.key === 'updated'"
|
||||
*ngIf="filter.id === 'updated'"
|
||||
[color]="dictionaryColor"
|
||||
label="U"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="filter.key === 'image'" [color]="dictionaryColor" label="I" type="square"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="filter.id === 'image'" [color]="dictionaryColor" label="I" type="square"></redaction-annotation-icon>
|
||||
|
||||
<div *ngIf="filter.key === 'comment'">
|
||||
<div *ngIf="filter.id === 'comment'">
|
||||
<mat-icon svgIcon="red:comment"></mat-icon>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { NestedFilter } from '@iqser/common-ui';
|
||||
import { INestedFilter } from '@iqser/common-ui';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-type-filter',
|
||||
@ -8,7 +8,7 @@ import { NestedFilter } from '@iqser/common-ui';
|
||||
styleUrls: ['./type-filter.component.scss']
|
||||
})
|
||||
export class TypeFilterComponent implements OnInit {
|
||||
@Input() filter: NestedFilter;
|
||||
@Input() filter: INestedFilter;
|
||||
|
||||
dictionaryColor: string;
|
||||
|
||||
@ -36,6 +36,6 @@ export class TypeFilterComponent implements OnInit {
|
||||
needsAnalysis = (key: string) => this._needsAnalysisKeys.includes(key);
|
||||
|
||||
ngOnInit(): void {
|
||||
this.dictionaryColor = this._appStateService.getDictionaryColor(this.filter.key);
|
||||
this.dictionaryColor = this._appStateService.getDictionaryColor(this.filter.id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, EventEmitter, forwardRef, Injector, Input, OnInit, Output, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { EditDossierSectionInterface } from '../edit-dossier-section.interface';
|
||||
import { Dossier } from '../../../../../state/model/dossier';
|
||||
import { Dossier } from '@state/model/dossier';
|
||||
import {
|
||||
CircleButtonTypes,
|
||||
DefaultListingServices,
|
||||
@ -49,7 +49,6 @@ export class EditDossierDeletedDocumentsComponent extends ListingComponent<FileL
|
||||
@ViewChild('pagesTemplate', { static: true }) pagesTemplate: TemplateRef<never>;
|
||||
@ViewChild('deletedDateTemplate', { static: true }) deletedDateTemplate: TemplateRef<never>;
|
||||
@ViewChild('restoreDateTemplate', { static: true }) restoreDateTemplate: TemplateRef<never>;
|
||||
protected readonly _primaryKey = 'fileId';
|
||||
|
||||
constructor(
|
||||
protected readonly _injector: Injector,
|
||||
@ -167,6 +166,7 @@ export class EditDossierDeletedDocumentsComponent extends ListingComponent<FileL
|
||||
id: file.fileId,
|
||||
...file,
|
||||
restoreDate,
|
||||
searchKey: file.filename,
|
||||
canRestore: this._canRestoreFile(restoreDate)
|
||||
};
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
<div class="small-label stats-subtitle mb-6">
|
||||
<div>
|
||||
<mat-icon svgIcon="red:template"></mat-icon>
|
||||
{{ dossier.dossierTemplateName }}
|
||||
{{ getDossierTemplateNameFor(dossier.dossierTemplateId) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="small-label stats-subtitle">
|
||||
@ -53,7 +53,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<mat-icon svgIcon="red:user"></mat-icon>
|
||||
{{ dossier.memberCount }}
|
||||
{{ dossier.memberIds.length }}
|
||||
</div>
|
||||
<div>
|
||||
<mat-icon svgIcon="red:calendar"></mat-icon>
|
||||
|
||||
@ -16,7 +16,15 @@ 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 { DefaultListingServices, keyChecker, ListingComponent, NestedFilter, TableColumnConfig, TableComponent } from '@iqser/common-ui';
|
||||
import {
|
||||
DefaultListingServices,
|
||||
INestedFilter,
|
||||
keyChecker,
|
||||
ListingComponent,
|
||||
NestedFilter,
|
||||
TableColumnConfig,
|
||||
TableComponent
|
||||
} from '@iqser/common-ui';
|
||||
import { workloadTranslations } from '../../translations/workload-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { fileStatusTranslations } from '../../translations/file-status-translations';
|
||||
@ -46,11 +54,10 @@ export class DossierListingScreenComponent
|
||||
tableColumnConfigs: TableColumnConfig<Dossier>[];
|
||||
dossiersChartData: DoughnutChartConfig[] = [];
|
||||
documentsChartData: DoughnutChartConfig[] = [];
|
||||
@ViewChild('nameTemplate', { static: true }) nameTemplate: TemplateRef<never>;
|
||||
@ViewChild('needsWorkTemplate', { static: true }) needsWorkTemplate: TemplateRef<never>;
|
||||
@ViewChild('ownerTemplate', { static: true }) ownerTemplate: TemplateRef<never>;
|
||||
@ViewChild('statusTemplate', { static: true }) statusTemplate: TemplateRef<never>;
|
||||
protected readonly _primaryKey = 'dossierName';
|
||||
@ViewChild('nameTemplate', { static: true }) nameTemplate: TemplateRef<unknown>;
|
||||
@ViewChild('needsWorkTemplate', { static: true }) needsWorkTemplate: TemplateRef<unknown>;
|
||||
@ViewChild('ownerTemplate', { static: true }) ownerTemplate: TemplateRef<unknown>;
|
||||
@ViewChild('statusTemplate', { static: true }) statusTemplate: TemplateRef<unknown>;
|
||||
private _lastScrolledIndex: number;
|
||||
@ViewChild('needsWorkFilterTemplate', {
|
||||
read: TemplateRef,
|
||||
@ -85,6 +92,10 @@ export class DossierListingScreenComponent
|
||||
|
||||
routerLinkFn = (dossier: Dossier) => ['/main/dossiers/' + dossier.id];
|
||||
|
||||
getDossierTemplateNameFor(dossierTemplateId: string): string {
|
||||
return this._appStateService.getDossierTemplateById(dossierTemplateId).name;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this._configureTableColumns();
|
||||
this.calculateData();
|
||||
@ -156,7 +167,7 @@ export class DossierListingScreenComponent
|
||||
this.tableColumnConfigs = [
|
||||
{
|
||||
label: _('dossier-listing.table-col-names.name'),
|
||||
sortByKey: 'dossierName',
|
||||
sortByKey: 'searchKey',
|
||||
template: this.nameTemplate,
|
||||
width: '2fr'
|
||||
},
|
||||
@ -214,23 +225,29 @@ export class DossierListingScreenComponent
|
||||
allDistinctDossierTemplates.add(entry.dossierTemplateId);
|
||||
});
|
||||
|
||||
const statusFilters = [...allDistinctFileStatus].map<NestedFilter>(status => ({
|
||||
key: status,
|
||||
label: this._translateService.instant(fileStatusTranslations[status])
|
||||
}));
|
||||
const statusFilters = [...allDistinctFileStatus].map<INestedFilter>(
|
||||
status =>
|
||||
new NestedFilter({
|
||||
id: status,
|
||||
label: this._translateService.instant(fileStatusTranslations[status])
|
||||
})
|
||||
);
|
||||
|
||||
this.filterService.addFilterGroup({
|
||||
slug: 'statusFilters',
|
||||
label: this._translateService.instant('filters.status'),
|
||||
icon: 'red:status',
|
||||
filters: statusFilters.sort(StatusSorter.byStatus),
|
||||
filters: statusFilters.sort((a, b) => StatusSorter[a.id] - StatusSorter[b.id]),
|
||||
checker: dossierStatusChecker
|
||||
});
|
||||
|
||||
const peopleFilters = [...allDistinctPeople].map<NestedFilter>(userId => ({
|
||||
key: userId,
|
||||
label: this._userService.getNameForId(userId)
|
||||
}));
|
||||
const peopleFilters = [...allDistinctPeople].map<INestedFilter>(
|
||||
userId =>
|
||||
new NestedFilter({
|
||||
id: userId,
|
||||
label: this._userService.getNameForId(userId)
|
||||
})
|
||||
);
|
||||
|
||||
this.filterService.addFilterGroup({
|
||||
slug: 'peopleFilters',
|
||||
@ -240,25 +257,31 @@ export class DossierListingScreenComponent
|
||||
checker: dossierMemberChecker
|
||||
});
|
||||
|
||||
const needsWorkFilters = [...allDistinctNeedsWork].map<NestedFilter>(type => ({
|
||||
key: type,
|
||||
label: workloadTranslations[type]
|
||||
}));
|
||||
const needsWorkFilters = [...allDistinctNeedsWork].map<INestedFilter>(
|
||||
type =>
|
||||
new NestedFilter({
|
||||
id: type,
|
||||
label: workloadTranslations[type]
|
||||
})
|
||||
);
|
||||
|
||||
this.filterService.addFilterGroup({
|
||||
slug: 'needsWorkFilters',
|
||||
label: this._translateService.instant('filters.needs-work'),
|
||||
icon: 'red:needs-work',
|
||||
filterTemplate: this._needsWorkFilterTemplate,
|
||||
filters: needsWorkFilters.sort(RedactionFilterSorter.byKey),
|
||||
filters: needsWorkFilters.sort((a, b) => RedactionFilterSorter[a.id] - RedactionFilterSorter[b.id]),
|
||||
checker: annotationFilterChecker,
|
||||
matchAll: true
|
||||
});
|
||||
|
||||
const dossierTemplateFilters = [...allDistinctDossierTemplates].map<NestedFilter>(id => ({
|
||||
key: id,
|
||||
label: this._appStateService.getDossierTemplateById(id).name
|
||||
}));
|
||||
const dossierTemplateFilters = [...allDistinctDossierTemplates].map<INestedFilter>(
|
||||
id =>
|
||||
new NestedFilter({
|
||||
id: id,
|
||||
label: this._appStateService.getDossierTemplateById(id).name
|
||||
})
|
||||
);
|
||||
|
||||
this.filterService.addFilterGroup({
|
||||
slug: 'dossierTemplateFilters',
|
||||
@ -276,10 +299,13 @@ export class DossierListingScreenComponent
|
||||
checker: (dw: Dossier) => quickFilters.reduce((acc, f) => acc || (f.checked && f.checker(dw)), false)
|
||||
});
|
||||
|
||||
const dossierFilters = this.entitiesService.all.map<NestedFilter>(dossier => ({
|
||||
key: dossier.dossierName,
|
||||
label: dossier.dossierName
|
||||
}));
|
||||
const dossierFilters = this.entitiesService.all.map<INestedFilter>(
|
||||
dossier =>
|
||||
new NestedFilter({
|
||||
id: dossier.dossierName,
|
||||
label: dossier.dossierName
|
||||
})
|
||||
);
|
||||
this.filterService.addFilterGroup({
|
||||
slug: 'dossierNameFilter',
|
||||
label: this._translateService.instant('dossier-listing.filters.label'),
|
||||
@ -290,30 +316,30 @@ export class DossierListingScreenComponent
|
||||
});
|
||||
}
|
||||
|
||||
private _createQuickFilters() {
|
||||
private _createQuickFilters(): INestedFilter[] {
|
||||
const myDossiersLabel = this._translateService.instant('dossier-listing.quick-filters.my-dossiers');
|
||||
const filters: NestedFilter[] = [
|
||||
const filters: INestedFilter[] = [
|
||||
{
|
||||
key: 'my-dossiers',
|
||||
id: 'my-dossiers',
|
||||
label: myDossiersLabel,
|
||||
checker: (dw: Dossier) => dw.ownerId === this.currentUser.id
|
||||
},
|
||||
{
|
||||
key: 'to-approve',
|
||||
id: 'to-approve',
|
||||
label: this._translateService.instant('dossier-listing.quick-filters.to-approve'),
|
||||
checker: (dw: Dossier) => dw.approverIds.includes(this.currentUser.id)
|
||||
},
|
||||
{
|
||||
key: 'to-review',
|
||||
id: 'to-review',
|
||||
label: this._translateService.instant('dossier-listing.quick-filters.to-review'),
|
||||
checker: (dw: Dossier) => dw.memberIds.includes(this.currentUser.id)
|
||||
},
|
||||
{
|
||||
key: 'other',
|
||||
id: 'other',
|
||||
label: this._translateService.instant('dossier-listing.quick-filters.other'),
|
||||
checker: (dw: Dossier) => !dw.memberIds.includes(this.currentUser.id)
|
||||
}
|
||||
];
|
||||
].map(filter => new NestedFilter(filter));
|
||||
|
||||
return filters.filter(f => f.label === myDossiersLabel || this._userPreferenceService.areDevFeaturesEnabled);
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ import { ActionConfig } from '@shared/components/page-header/models/action-confi
|
||||
import {
|
||||
CircleButtonTypes,
|
||||
DefaultListingServices,
|
||||
INestedFilter,
|
||||
keyChecker,
|
||||
ListingComponent,
|
||||
ListingModes,
|
||||
@ -45,7 +46,6 @@ import {
|
||||
} from '@iqser/common-ui';
|
||||
import { DossierAttributesService } from '@shared/services/controller-wrappers/dossier-attributes.service';
|
||||
import { DossierAttributeWithValue } from '@models/dossier-attributes.model';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { workloadTranslations } from '../../translations/workload-translations';
|
||||
import { fileStatusTranslations } from '../../translations/file-status-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
@ -80,15 +80,14 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
collapsedDetails = false;
|
||||
dossierAttributes: DossierAttributeWithValue[] = [];
|
||||
fileAttributeConfigs: FileAttributeConfig[];
|
||||
@ViewChild('filenameTemplate', { static: true }) filenameTemplate: TemplateRef<never>;
|
||||
@ViewChild('addedOnTemplate', { static: true }) addedOnTemplate: TemplateRef<never>;
|
||||
@ViewChild('attributeTemplate', { static: true }) attributeTemplate: TemplateRef<never>;
|
||||
@ViewChild('needsWorkTemplate', { static: true }) needsWorkTemplate: TemplateRef<never>;
|
||||
@ViewChild('reviewerTemplate', { static: true }) reviewerTemplate: TemplateRef<never>;
|
||||
@ViewChild('pagesTemplate', { static: true }) pagesTemplate: TemplateRef<never>;
|
||||
@ViewChild('statusTemplate', { static: true }) statusTemplate: TemplateRef<never>;
|
||||
@ViewChild('filenameTemplate', { static: true }) filenameTemplate: TemplateRef<unknown>;
|
||||
@ViewChild('addedOnTemplate', { static: true }) addedOnTemplate: TemplateRef<unknown>;
|
||||
@ViewChild('attributeTemplate', { static: true }) attributeTemplate: TemplateRef<unknown>;
|
||||
@ViewChild('needsWorkTemplate', { static: true }) needsWorkTemplate: TemplateRef<unknown>;
|
||||
@ViewChild('reviewerTemplate', { static: true }) reviewerTemplate: TemplateRef<unknown>;
|
||||
@ViewChild('pagesTemplate', { static: true }) pagesTemplate: TemplateRef<unknown>;
|
||||
@ViewChild('statusTemplate', { static: true }) statusTemplate: TemplateRef<unknown>;
|
||||
readonly workflowConfig: WorkflowConfig<FileStatusWrapper, StatusEnum>;
|
||||
protected readonly _primaryKey = 'filename';
|
||||
@ViewChild(DossierDetailsComponent, { static: false })
|
||||
private readonly _dossierDetailsComponent: DossierDetailsComponent;
|
||||
private _lastScrolledIndex: number;
|
||||
@ -112,7 +111,6 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _fileUploadService: FileUploadService,
|
||||
private readonly _statusOverlayService: StatusOverlayService,
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
private readonly _fileDropOverlayService: FileDropOverlayService,
|
||||
private readonly _dossierAttributesService: DossierAttributesService,
|
||||
private readonly _fileActionService: FileActionService
|
||||
@ -243,8 +241,6 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
.pipe(tap(index => (this._lastScrolledIndex = index)))
|
||||
.subscribe();
|
||||
|
||||
this.searchService.setSearchKey('filename');
|
||||
|
||||
this.dossierAttributes = await this._dossierAttributesService.getValues(this.currentDossier);
|
||||
} catch (e) {
|
||||
} finally {
|
||||
@ -296,22 +292,22 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
}
|
||||
|
||||
@HostListener('drop', ['$event'])
|
||||
onDrop(event: DragEvent) {
|
||||
onDrop(event: DragEvent): void {
|
||||
handleFileDrop(event, this.currentDossier, this._uploadFiles.bind(this));
|
||||
}
|
||||
|
||||
@HostListener('dragover', ['$event'])
|
||||
onDragOver(event) {
|
||||
onDragOver(event): void {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
async uploadFiles(files: File[] | FileList) {
|
||||
async uploadFiles(files: File[] | FileList): Promise<void> {
|
||||
await this._uploadFiles(convertFiles(files, this.currentDossier));
|
||||
this._fileInput.nativeElement.value = null;
|
||||
}
|
||||
|
||||
async bulkActionPerformed() {
|
||||
async bulkActionPerformed(): Promise<void> {
|
||||
this.entitiesService.setSelected([]);
|
||||
await this.reloadDossiers();
|
||||
}
|
||||
@ -351,7 +347,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
this.tableColumnConfigs = [
|
||||
{
|
||||
label: _('dossier-overview.table-col-names.name'),
|
||||
sortByKey: 'filename',
|
||||
sortByKey: 'searchKey',
|
||||
template: this.filenameTemplate,
|
||||
width: '3fr'
|
||||
},
|
||||
@ -462,33 +458,40 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
});
|
||||
});
|
||||
|
||||
const statusFilters = [...allDistinctFileStatusWrapper].map<NestedFilter>(item => ({
|
||||
key: item,
|
||||
label: this._translateService.instant(fileStatusTranslations[item])
|
||||
}));
|
||||
const statusFilters = [...allDistinctFileStatusWrapper].map<INestedFilter>(
|
||||
item =>
|
||||
new NestedFilter({
|
||||
id: item,
|
||||
label: this._translateService.instant(fileStatusTranslations[item])
|
||||
})
|
||||
);
|
||||
|
||||
this.filterService.addFilterGroup({
|
||||
slug: 'statusFilters',
|
||||
label: this._translateService.instant('filters.status'),
|
||||
icon: 'red:status',
|
||||
filters: statusFilters.sort(StatusSorter.byStatus),
|
||||
filters: statusFilters.sort((a, b) => StatusSorter[a.id] - StatusSorter[b.id]),
|
||||
checker: keyChecker('status')
|
||||
});
|
||||
|
||||
const peopleFilters = [];
|
||||
const peopleFilters: INestedFilter[] = [];
|
||||
if (allDistinctPeople.has(undefined) || allDistinctPeople.has(null)) {
|
||||
allDistinctPeople.delete(undefined);
|
||||
allDistinctPeople.delete(null);
|
||||
peopleFilters.push({
|
||||
key: null,
|
||||
label: this._translateService.instant('initials-avatar.unassigned')
|
||||
});
|
||||
peopleFilters.push(
|
||||
new NestedFilter({
|
||||
id: null,
|
||||
label: this._translateService.instant('initials-avatar.unassigned')
|
||||
})
|
||||
);
|
||||
}
|
||||
allDistinctPeople.forEach(userId => {
|
||||
peopleFilters.push({
|
||||
key: userId,
|
||||
label: this._userService.getNameForId(userId)
|
||||
});
|
||||
peopleFilters.push(
|
||||
new NestedFilter({
|
||||
id: userId,
|
||||
label: this._userService.getNameForId(userId)
|
||||
})
|
||||
);
|
||||
});
|
||||
this.filterService.addFilterGroup({
|
||||
slug: 'peopleFilters',
|
||||
@ -498,10 +501,13 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
checker: keyChecker('currentReviewer')
|
||||
});
|
||||
|
||||
const needsWorkFilters = [...allDistinctNeedsWork].map<NestedFilter>(item => ({
|
||||
key: item,
|
||||
label: workloadTranslations[item]
|
||||
}));
|
||||
const needsWorkFilters = [...allDistinctNeedsWork].map<INestedFilter>(
|
||||
item =>
|
||||
new NestedFilter({
|
||||
id: item,
|
||||
label: workloadTranslations[item]
|
||||
})
|
||||
);
|
||||
|
||||
this.filterService.addFilterGroup({
|
||||
slug: 'needsWorkFilters',
|
||||
@ -520,11 +526,14 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
slug: key,
|
||||
label: key,
|
||||
icon: 'red:template',
|
||||
filters: [...filterValue].map<NestedFilter>((value: string) => ({
|
||||
key: value,
|
||||
label: value === '-' ? this._translateService.instant('filters.empty') : value
|
||||
})),
|
||||
checker: (input: FileStatusWrapper, filter: NestedFilter) => filter.key === input.fileAttributes.attributeIdToValue[id]
|
||||
filters: [...filterValue].map<INestedFilter>(
|
||||
(value: string) =>
|
||||
new NestedFilter({
|
||||
id: value,
|
||||
label: value === '-' ? this._translateService.instant('filters.empty') : value
|
||||
})
|
||||
),
|
||||
checker: (input: FileStatusWrapper, filter: INestedFilter) => filter.id === input.fileAttributes.attributeIdToValue[id]
|
||||
});
|
||||
});
|
||||
|
||||
@ -537,10 +546,13 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
this.checkedNotRequiredFilters.reduce((acc, f) => acc || f.checker(file), false))
|
||||
});
|
||||
|
||||
const filesNamesFilters = this.entitiesService.all.map<NestedFilter>(file => ({
|
||||
key: file.filename,
|
||||
label: file.filename
|
||||
}));
|
||||
const filesNamesFilters = this.entitiesService.all.map<INestedFilter>(
|
||||
file =>
|
||||
new NestedFilter({
|
||||
id: file.filename,
|
||||
label: file.filename
|
||||
})
|
||||
);
|
||||
|
||||
this.filterService.addFilterGroup({
|
||||
slug: 'filesNamesFilter',
|
||||
@ -552,13 +564,13 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
});
|
||||
}
|
||||
|
||||
private _createQuickFilters() {
|
||||
let quickFilters = [];
|
||||
private _createQuickFilters(): INestedFilter[] {
|
||||
let quickFilters: INestedFilter[] = [];
|
||||
if (this.entitiesService.all.filter(this.recentlyModifiedChecker).length > 0) {
|
||||
const recentPeriod = this._configService.values.RECENT_PERIOD_IN_HOURS;
|
||||
quickFilters = [
|
||||
{
|
||||
key: 'recent',
|
||||
id: 'recent',
|
||||
label: this._translateService.instant('dossier-overview.quick-filters.recent', {
|
||||
hours: recentPeriod
|
||||
}),
|
||||
@ -571,20 +583,20 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
return [
|
||||
...quickFilters,
|
||||
{
|
||||
key: 'assigned-to-me',
|
||||
id: 'assigned-to-me',
|
||||
label: this._translateService.instant('dossier-overview.quick-filters.assigned-to-me'),
|
||||
checker: (file: FileStatusWrapper) => file.currentReviewer === this.currentUser.id
|
||||
},
|
||||
{
|
||||
key: 'unassigned',
|
||||
id: 'unassigned',
|
||||
label: this._translateService.instant('dossier-overview.quick-filters.unassigned'),
|
||||
checker: (file: FileStatusWrapper) => !file.currentReviewer
|
||||
},
|
||||
{
|
||||
key: 'assigned-to-others',
|
||||
id: 'assigned-to-others',
|
||||
label: this._translateService.instant('dossier-overview.quick-filters.assigned-to-others'),
|
||||
checker: (file: FileStatusWrapper) => !!file.currentReviewer && file.currentReviewer !== this.currentUser.id
|
||||
}
|
||||
];
|
||||
].map(filter => new NestedFilter(filter));
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,8 +8,8 @@ import {
|
||||
CircleButtonTypes,
|
||||
Debounce,
|
||||
FilterService,
|
||||
INestedFilter,
|
||||
LoadingService,
|
||||
NestedFilter,
|
||||
processFilters,
|
||||
Toaster
|
||||
} from '@iqser/common-ui';
|
||||
@ -80,7 +80,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
read: TemplateRef,
|
||||
static: true
|
||||
})
|
||||
private readonly _filterTemplate: TemplateRef<NestedFilter>;
|
||||
private readonly _filterTemplate: TemplateRef<INestedFilter>;
|
||||
@ViewChild('fileActions') fileActions: FileActionsComponent;
|
||||
|
||||
constructor(
|
||||
|
||||
@ -1,23 +1,29 @@
|
||||
import { Component, forwardRef, Injector, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { DefaultListingServices, IListable, keyChecker, ListingComponent, LoadingService, TableColumnConfig } from '@iqser/common-ui';
|
||||
import { MatchedDocument, SearchControllerService, SearchResult } from '@redaction/red-ui-http';
|
||||
import {
|
||||
DefaultListingServices,
|
||||
IListable,
|
||||
keyChecker,
|
||||
ListingComponent,
|
||||
LoadingService,
|
||||
NestedFilter,
|
||||
TableColumnConfig
|
||||
} from '@iqser/common-ui';
|
||||
import { List, MatchedDocument, SearchControllerService, SearchResult } from '@redaction/red-ui-http';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { debounceTime, map, skip, switchMap, tap } from 'rxjs/operators';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { fileStatusTranslations } from '../../translations/file-status-translations';
|
||||
import { SearchPositions } from '@shared/components/page-header/models/search-positions.type';
|
||||
import { Dossier } from '../../../../state/model/dossier';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { RouterHistoryService } from '@services/router-history.service';
|
||||
|
||||
interface ListItem extends IListable {
|
||||
readonly dossierId: string;
|
||||
readonly filename: string;
|
||||
readonly unmatched: readonly string[] | null;
|
||||
readonly highlights: Record<string, readonly string[]>;
|
||||
readonly unmatched: List | null;
|
||||
readonly highlights: Record<string, List>;
|
||||
readonly routerLink: string;
|
||||
readonly status: string;
|
||||
readonly dossierName: string;
|
||||
@ -26,7 +32,7 @@ interface ListItem extends IListable {
|
||||
|
||||
interface SearchInput {
|
||||
readonly query: string;
|
||||
readonly dossierIds?: readonly string[];
|
||||
readonly dossierIds?: List;
|
||||
}
|
||||
|
||||
@Component({
|
||||
@ -53,7 +59,6 @@ export class SearchScreenComponent extends ListingComponent<ListItem> implements
|
||||
tap(result => this.entitiesService.setEntities(result)),
|
||||
tap(() => this._loadingService.stop())
|
||||
);
|
||||
protected readonly _primaryKey = 'filename';
|
||||
|
||||
constructor(
|
||||
private readonly _router: Router,
|
||||
@ -72,10 +77,13 @@ export class SearchScreenComponent extends ListingComponent<ListItem> implements
|
||||
label: this._translateService.instant('search-screen.filters.by-dossier'),
|
||||
filterceptionPlaceholder: this._translateService.instant('search-screen.filters.search-placeholder'),
|
||||
icon: 'red:folder',
|
||||
filters: this._appStateService.allDossiers.map(dossier => ({
|
||||
key: dossier.id,
|
||||
label: dossier.dossierName
|
||||
})),
|
||||
filters: this._appStateService.allDossiers.map(
|
||||
dossier =>
|
||||
new NestedFilter({
|
||||
id: dossier.id,
|
||||
label: dossier.dossierName
|
||||
})
|
||||
),
|
||||
checker: keyChecker('id')
|
||||
});
|
||||
|
||||
@ -89,17 +97,13 @@ export class SearchScreenComponent extends ListingComponent<ListItem> implements
|
||||
this.addSubscription = this.searchService.valueChanges$.pipe(debounceTime(300)).subscribe(value => this.updateNavigation(value));
|
||||
|
||||
this.addSubscription = this.filterService.filterGroups$.pipe(skip(1)).subscribe(group => {
|
||||
const dossierIds = group[0].filters.filter(v => v.checked).map(v => v.key);
|
||||
const dossierIds = group[0].filters.filter(v => v.checked).map(v => v.id);
|
||||
this.search$.next({ query: this.searchService.searchValue, dossierIds: dossierIds });
|
||||
});
|
||||
}
|
||||
|
||||
routerLinkFn = (entity: ListItem) => [entity.routerLink];
|
||||
|
||||
setInitialConfig(): void {
|
||||
return;
|
||||
}
|
||||
|
||||
updateNavigation(query: string, mustContain?: string): void {
|
||||
const newQuery = query?.replace(mustContain, `"${mustContain}"`);
|
||||
const queryParams = newQuery && newQuery !== '' ? { query: newQuery } : {};
|
||||
@ -137,14 +141,6 @@ export class SearchScreenComponent extends ListingComponent<ListItem> implements
|
||||
this.search$.next({ query, dossierIds: dossierId ? [dossierId] : [] });
|
||||
}
|
||||
|
||||
private _getFileWrapper(dossierId: string, fileId: string): FileStatusWrapper {
|
||||
return this._appStateService.getFileById(dossierId, fileId);
|
||||
}
|
||||
|
||||
private _getDossierWrapper(dossierId: string): Dossier {
|
||||
return this._appStateService.getDossierById(dossierId);
|
||||
}
|
||||
|
||||
private _toMatchedDocuments({ matchedDocuments }: SearchResult): MatchedDocument[] {
|
||||
return matchedDocuments.filter(doc => doc.score > 0 && doc.matchedTerms.length > 0);
|
||||
}
|
||||
@ -154,7 +150,7 @@ export class SearchScreenComponent extends ListingComponent<ListItem> implements
|
||||
}
|
||||
|
||||
private _toListItem({ dossierId, fileId, unmatchedTerms, highlights }: MatchedDocument): ListItem {
|
||||
const fileWrapper = this._getFileWrapper(dossierId, fileId);
|
||||
const fileWrapper = this._appStateService.getFileById(dossierId, fileId);
|
||||
if (!fileWrapper) {
|
||||
return undefined;
|
||||
}
|
||||
@ -166,8 +162,9 @@ export class SearchScreenComponent extends ListingComponent<ListItem> implements
|
||||
highlights,
|
||||
status: fileWrapper.status,
|
||||
numberOfPages: fileWrapper.numberOfPages,
|
||||
dossierName: this._getDossierWrapper(dossierId).dossierName,
|
||||
dossierName: this._appStateService.getDossierById(dossierId).dossierName,
|
||||
filename: fileWrapper.filename,
|
||||
searchKey: fileWrapper.filename,
|
||||
routerLink: `/main/dossiers/${dossierId}/file/${fileId}`
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,38 +1,36 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { SuperTypeSorter } from '@utils/sorters/super-type-sorter';
|
||||
import { handleCheckedValue, NestedFilter } from '@iqser/common-ui';
|
||||
import { handleCheckedValue, IFilter, INestedFilter, NestedFilter } from '@iqser/common-ui';
|
||||
import { annotationTypesTranslations } from '../../../translations/annotation-types-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
|
||||
@Injectable()
|
||||
export class AnnotationProcessingService {
|
||||
static get secondaryAnnotationFilters(): NestedFilter[] {
|
||||
static get secondaryAnnotationFilters(): INestedFilter[] {
|
||||
return [
|
||||
{
|
||||
key: 'with-comments',
|
||||
id: 'with-comments',
|
||||
icon: 'red:comment',
|
||||
label: _('filter-menu.with-comments'),
|
||||
checked: false,
|
||||
topLevelFilter: true,
|
||||
children: [],
|
||||
checker: (annotation: AnnotationWrapper) => annotation?.comments?.length > 0
|
||||
},
|
||||
{
|
||||
key: 'with-reason-changes',
|
||||
id: 'with-reason-changes',
|
||||
icon: 'red:reason',
|
||||
label: _('filter-menu.with-reason-changes'),
|
||||
checked: false,
|
||||
topLevelFilter: true,
|
||||
children: [],
|
||||
checker: (annotation: AnnotationWrapper) => annotation?.legalBasisChangeValue?.length > 0
|
||||
}
|
||||
];
|
||||
].map(item => new NestedFilter(item));
|
||||
}
|
||||
|
||||
getAnnotationFilter(annotations: AnnotationWrapper[]): NestedFilter[] {
|
||||
const filterMap = new Map<string, NestedFilter>();
|
||||
const filters: NestedFilter[] = [];
|
||||
getAnnotationFilter(annotations: AnnotationWrapper[]): INestedFilter[] {
|
||||
const filterMap = new Map<string, INestedFilter>();
|
||||
const filters: INestedFilter[] = [];
|
||||
|
||||
annotations?.forEach(a => {
|
||||
const topLevelFilter = a.superType !== 'hint' && a.superType !== 'redaction' && a.superType !== 'recommendation';
|
||||
@ -49,11 +47,11 @@ export class AnnotationProcessingService {
|
||||
if (!parentFilter) {
|
||||
parentFilter = this._createParentFilter(a.superType, filterMap, filters);
|
||||
}
|
||||
const childFilter = {
|
||||
key: a.type,
|
||||
const childFilter: IFilter = {
|
||||
id: a.type,
|
||||
label: a.type,
|
||||
searchKey: a.type,
|
||||
checked: false,
|
||||
filters: [],
|
||||
matches: 1
|
||||
};
|
||||
filterMap.set(key, childFilter);
|
||||
@ -63,7 +61,7 @@ export class AnnotationProcessingService {
|
||||
});
|
||||
|
||||
for (const filter of filters) {
|
||||
filter.children.sort((a, b) => a.key.localeCompare(b.key));
|
||||
filter.children.sort((a, b) => a.id.localeCompare(b.id));
|
||||
handleCheckedValue(filter);
|
||||
if (filter.checked || filter.indeterminate) {
|
||||
filter.expanded = true;
|
||||
@ -73,13 +71,13 @@ export class AnnotationProcessingService {
|
||||
}
|
||||
}
|
||||
|
||||
return filters.sort((a, b) => SuperTypeSorter[a.key] - SuperTypeSorter[b.key]);
|
||||
return filters.sort((a, b) => SuperTypeSorter[a.id] - SuperTypeSorter[b.id]);
|
||||
}
|
||||
|
||||
filterAndGroupAnnotations(
|
||||
annotations: AnnotationWrapper[],
|
||||
primaryFilters: NestedFilter[],
|
||||
secondaryFilters?: NestedFilter[]
|
||||
primaryFilters: INestedFilter[],
|
||||
secondaryFilters?: INestedFilter[]
|
||||
): Map<number, AnnotationWrapper[]> {
|
||||
const obj = new Map<number, AnnotationWrapper[]>();
|
||||
|
||||
@ -116,21 +114,20 @@ export class AnnotationProcessingService {
|
||||
return obj;
|
||||
}
|
||||
|
||||
private _createParentFilter(key: string, filterMap: Map<string, NestedFilter>, filters: NestedFilter[]) {
|
||||
const filter: NestedFilter = {
|
||||
key: key,
|
||||
private _createParentFilter(key: string, filterMap: Map<string, INestedFilter>, filters: INestedFilter[]) {
|
||||
const filter: INestedFilter = new NestedFilter({
|
||||
id: key,
|
||||
topLevelFilter: true,
|
||||
matches: 1,
|
||||
label: annotationTypesTranslations[key],
|
||||
children: []
|
||||
};
|
||||
label: annotationTypesTranslations[key]
|
||||
});
|
||||
filterMap.set(key, filter);
|
||||
filters.push(filter);
|
||||
return filter;
|
||||
}
|
||||
|
||||
private _getFlatFilters(filters: NestedFilter[], filterBy?: (f: NestedFilter) => boolean) {
|
||||
const flatFilters: NestedFilter[] = [];
|
||||
private _getFlatFilters(filters: INestedFilter[], filterBy?: (f: INestedFilter) => boolean) {
|
||||
const flatFilters: INestedFilter[] = [];
|
||||
|
||||
filters.forEach(filter => {
|
||||
flatFilters.push(filter);
|
||||
@ -140,7 +137,7 @@ export class AnnotationProcessingService {
|
||||
return filterBy ? flatFilters.filter(f => filterBy(f)) : flatFilters;
|
||||
}
|
||||
|
||||
private _matchesOne = (filters: NestedFilter[], condition: (filter: NestedFilter) => boolean): boolean => {
|
||||
private _matchesOne = (filters: INestedFilter[], condition: (filter: INestedFilter) => boolean): boolean => {
|
||||
if (filters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
@ -154,7 +151,7 @@ export class AnnotationProcessingService {
|
||||
return false;
|
||||
};
|
||||
|
||||
private _matchesAll = (filters: NestedFilter[], condition: (filter: NestedFilter) => boolean): boolean => {
|
||||
private _matchesAll = (filters: INestedFilter[], condition: (filter: INestedFilter) => boolean): boolean => {
|
||||
if (filters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
@ -168,11 +165,11 @@ export class AnnotationProcessingService {
|
||||
return true;
|
||||
};
|
||||
|
||||
private _checkByFilterKey = (filter: NestedFilter, annotation: AnnotationWrapper) => {
|
||||
private _checkByFilterKey = (filter: INestedFilter, annotation: AnnotationWrapper) => {
|
||||
const superType = annotation.superType;
|
||||
const isNotTopLevelFilter = superType === 'hint' || superType === 'redaction' || superType === 'recommendation';
|
||||
|
||||
return filter.key === superType || (filter.key === annotation.type && isNotTopLevelFilter);
|
||||
return filter.id === superType || (filter.id === annotation.type && isNotTopLevelFilter);
|
||||
};
|
||||
|
||||
private _sortAnnotations(annotations: AnnotationWrapper[]): AnnotationWrapper[] {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Component, EventEmitter, Input, Optional, Output, TemplateRef } from '@angular/core';
|
||||
import { ActionConfig } from '@shared/components/page-header/models/action-config.model';
|
||||
import { ButtonConfig } from '@shared/components/page-header/models/button-config.model';
|
||||
import { FilterService, IconButtonTypes, Listable, SearchService } from '@iqser/common-ui';
|
||||
import { FilterService, IListable, SearchService } from '@iqser/common-ui';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { combineLatest, Observable, of } from 'rxjs';
|
||||
import { SearchPosition, SearchPositions } from '@shared/components/page-header/models/search-positions.type';
|
||||
@ -12,7 +12,7 @@ import { FileAttributeConfig } from '@redaction/red-ui-http';
|
||||
templateUrl: './page-header.component.html',
|
||||
styleUrls: ['./page-header.component.scss']
|
||||
})
|
||||
export class PageHeaderComponent<T extends Listable> {
|
||||
export class PageHeaderComponent<T extends IListable> {
|
||||
readonly searchPositions = SearchPositions;
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ export class SimpleDoughnutChartComponent implements OnChanges {
|
||||
}
|
||||
|
||||
filterChecked$(key: string): Observable<boolean> {
|
||||
return this.statusFilters$.pipe(map(all => all?.find(e => e.key === key)?.checked));
|
||||
return this.statusFilters$.pipe(map(all => all?.find(e => e.id === key)?.checked));
|
||||
}
|
||||
|
||||
calculateChartData() {
|
||||
|
||||
@ -1,38 +1,38 @@
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { Dossier } from '../state/model/dossier';
|
||||
import { handleCheckedValue, NestedFilter } from '@iqser/common-ui';
|
||||
import { handleCheckedValue, INestedFilter } from '@iqser/common-ui';
|
||||
|
||||
export function handleFilterDelta(oldFilters: NestedFilter[], newFilters: NestedFilter[], allFilters: NestedFilter[]) {
|
||||
export function handleFilterDelta(oldFilters: INestedFilter[], newFilters: INestedFilter[], allFilters: INestedFilter[]) {
|
||||
const newFiltersDelta = {};
|
||||
for (const newFilter of newFilters) {
|
||||
const oldFilter = oldFilters.find(f => f.key === newFilter.key);
|
||||
const oldFilter = oldFilters.find(f => f.id === newFilter.id);
|
||||
if (!oldFilter || oldFilter.matches !== newFilter.matches) {
|
||||
newFiltersDelta[newFilter.key] = {};
|
||||
newFilter.children.forEach(filter => (newFiltersDelta[newFilter.key][filter.key] = {}));
|
||||
newFiltersDelta[newFilter.id] = {};
|
||||
newFilter.children.forEach(filter => (newFiltersDelta[newFilter.id][filter.id] = {}));
|
||||
}
|
||||
|
||||
if (!oldFilter) {
|
||||
for (const childFilter of newFilter.children) {
|
||||
const oldFilterChild = oldFilter?.children.find(f => f.key === childFilter.key);
|
||||
const oldFilterChild = oldFilter?.children.find(f => f.id === childFilter.id);
|
||||
if (!oldFilterChild || oldFilterChild.matches !== childFilter.matches) {
|
||||
if (!newFiltersDelta[newFilter.key]) {
|
||||
newFiltersDelta[newFilter.key] = {};
|
||||
if (!newFiltersDelta[newFilter.id]) {
|
||||
newFiltersDelta[newFilter.id] = {};
|
||||
}
|
||||
newFiltersDelta[newFilter.key][childFilter.key] = {};
|
||||
newFiltersDelta[newFilter.id][childFilter.id] = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const key of Object.keys(newFiltersDelta)) {
|
||||
const foundFilter = allFilters.find(f => f.key === key);
|
||||
const foundFilter = allFilters.find(f => f.id === key);
|
||||
if (foundFilter) {
|
||||
// if has children
|
||||
if (!foundFilter.children?.length) {
|
||||
foundFilter.checked = true;
|
||||
} else {
|
||||
for (const subKey of Object.keys(newFiltersDelta[key])) {
|
||||
const childFilter = foundFilter.children.find(f => f.key === subKey);
|
||||
const childFilter = foundFilter.children.find(f => f.id === subKey);
|
||||
if (childFilter) {
|
||||
childFilter.checked = true;
|
||||
}
|
||||
@ -45,8 +45,8 @@ export function handleFilterDelta(oldFilters: NestedFilter[], newFilters: Nested
|
||||
});
|
||||
}
|
||||
|
||||
export const annotationFilterChecker = (input: FileStatusWrapper | Dossier, filter: NestedFilter) => {
|
||||
switch (filter.key) {
|
||||
export const annotationFilterChecker = (input: FileStatusWrapper | Dossier, filter: INestedFilter) => {
|
||||
switch (filter.id) {
|
||||
case 'analysis': {
|
||||
if (input instanceof Dossier) {
|
||||
return input.reanalysisRequired;
|
||||
@ -78,10 +78,10 @@ export const annotationFilterChecker = (input: FileStatusWrapper | Dossier, filt
|
||||
}
|
||||
};
|
||||
|
||||
export const dossierStatusChecker = (dw: Dossier, filter: NestedFilter) => dw.hasStatus(filter.key);
|
||||
export const dossierStatusChecker = (dw: Dossier, filter: INestedFilter) => dw.hasStatus(filter.id);
|
||||
|
||||
export const dossierMemberChecker = (dw: Dossier, filter: NestedFilter) => dw.hasMember(filter.key);
|
||||
export const dossierMemberChecker = (dw: Dossier, filter: INestedFilter) => dw.hasMember(filter.id);
|
||||
|
||||
export const dossierTemplateChecker = (dw: Dossier, filter: NestedFilter) => dw.dossierTemplateId === filter.key;
|
||||
export const dossierTemplateChecker = (dw: Dossier, filter: INestedFilter) => dw.dossierTemplateId === filter.id;
|
||||
|
||||
export const dossierApproverChecker = (dw: Dossier, filter: NestedFilter) => dw.approverIds.includes(filter.key);
|
||||
export const dossierApproverChecker = (dw: Dossier, filter: INestedFilter) => dw.approverIds.includes(filter.id);
|
||||
|
||||
@ -6,5 +6,5 @@ export const RedactionFilterSorter = {
|
||||
hint: 4,
|
||||
suggestion: 5,
|
||||
none: 6,
|
||||
byKey: (a: { key: string }, b: { key: string }) => RedactionFilterSorter[a.key] - RedactionFilterSorter[b.key]
|
||||
byKey: (a: { id: string }, b: { id: string }) => RedactionFilterSorter[a.id] - RedactionFilterSorter[b.id]
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user