Subfilters

This commit is contained in:
Adina Țeudan 2020-10-18 23:18:23 +03:00 committed by Timo Bejan
parent 0979287274
commit 89ba7efc36
8 changed files with 125 additions and 21 deletions

View File

@ -50,3 +50,15 @@
.ignore { .ignore {
background-color: $grey-5; background-color: $grey-5;
} }
.hint_only {
background-color: $orange-1;
}
.vertebrate {
background-color: $green-1;
}
.names {
background-color: $yellow-2;
}

View File

@ -56,17 +56,34 @@
<div class="all-caps-label" translate="file-preview.filter-menu.filter-types.label"></div> <div class="all-caps-label" translate="file-preview.filter-menu.filter-types.label"></div>
<div class="actions"> <div class="actions">
<div class="all-caps-label primary pointer" translate="file-preview.filter-menu.all.label" <div class="all-caps-label primary pointer" translate="file-preview.filter-menu.all.label"
(click)="setAllFilters(true); $event.stopPropagation();"></div> (click)="setAllFilters(filters, true); applyFilters(); $event.stopPropagation();"></div>
<div class="all-caps-label primary pointer" translate="file-preview.filter-menu.none.label" <div class="all-caps-label primary pointer" translate="file-preview.filter-menu.none.label"
(click)="setAllFilters(false); $event.stopPropagation();"></div> (click)="setAllFilters(filters, false); applyFilters(); $event.stopPropagation();"></div>
</div> </div>
</div> </div>
<div class="mat-menu-item" *ngFor="let key of filterKeys" (click)="$event.stopPropagation()"> <div *ngFor="let key of filterKeys()">
<mat-checkbox [(ngModel)]="filters[key]" (change)="applyFilters()" color="primary"> <div class="mat-menu-item" (click)="$event.stopPropagation()">
<redaction-annotation-icon [type]="key"></redaction-annotation-icon> <mat-checkbox [checked]="isChecked(key)"
{{"file-preview.filter-menu."+ key + ".label" | translate }} [indeterminate]="isIndeterminate(key)"
</mat-checkbox> (change)="setAllFilters(filters[key], $event.checked, hasSubsections(filters[key]) ? null : key)"
color="primary">
<redaction-annotation-icon [type]="key"></redaction-annotation-icon>
{{"file-preview.filter-menu." + key + ".label" | translate }}
</mat-checkbox>
</div>
<div *ngIf="hasSubsections(filters[key])">
<div *ngFor="let subkey of filterKeys(key)"
class="padding-left mat-menu-item"
(click)="$event.stopPropagation()"
>
<mat-checkbox [(ngModel)]="filters[key][subkey]" (change)="applyFilters()" color="primary">
<redaction-annotation-icon [type]="key + ' ' + subkey"></redaction-annotation-icon>
{{"file-preview.filter-menu." + key + "." + subkey + ".label" | translate }}
</mat-checkbox>
</div>
</div>
</div> </div>
</mat-menu> </mat-menu>
</div> </div>
</div> </div>
@ -94,7 +111,7 @@
(click)="selectAnnotation(annotation)" (click)="selectAnnotation(annotation)"
> >
<redaction-annotation-icon [type]="getType(annotation)"></redaction-annotation-icon> <redaction-annotation-icon [type]="getType(annotation) + ' ' + getDictionary(annotation)"></redaction-annotation-icon>
<div class="flex-1"> <div class="flex-1">
<div><strong>{{getType(annotation) | translate}}</strong></div> <div><strong>{{getType(annotation) | translate}}</strong></div>
<div><strong><span translate="dictionary"></span>: </strong>{{getDictionary(annotation)}}</div> <div><strong><span translate="dictionary"></span>: </strong>{{getDictionary(annotation)}}</div>

View File

@ -82,7 +82,11 @@ export class FilePreviewScreenComponent implements OnInit {
return this._userService.user; return this._userService.user;
} }
public get filterKeys() { public filterKeys(key?: string) {
if (key) {
return Object.keys(this.filters[key]);
}
return Object.keys(this.filters); return Object.keys(this.filters);
} }
@ -272,13 +276,36 @@ export class FilePreviewScreenComponent implements OnInit {
}); });
} }
public setAllFilters(value: boolean) { public setAllFilters(filter: AnnotationFilters, value: boolean, rootKey?: string) {
Object.keys(this.filters).map((key) => { if (rootKey) {
this.filters[key] = value; this.filters[rootKey] = value;
}); } else {
for (const key of Object.keys(filter)) {
if (AnnotationUtils.hasSubsections(filter[key])) {
this.setAllFilters(filter[key], value);
} else {
filter[key] = value;
}
}
}
this.applyFilters();
}
public isChecked(key: string): boolean {
return AnnotationUtils.isChecked(this.filters[key]);
}
public isIndeterminate(key: string): boolean {
return AnnotationUtils.isIndeterminate(this.filters[key]);
} }
public get hasActiveFilters(): boolean { public get hasActiveFilters(): boolean {
return AnnotationUtils.hasActiveFilters(this.filters); return AnnotationUtils.hasActiveFilters(this.filters);
} }
public hasSubsections(filter: AnnotationFilters | boolean) {
return AnnotationUtils.hasSubsections(filter);
}
} }

View File

@ -9,7 +9,11 @@ export class FiltersService {
} }
private _filters: AnnotationFilters = { private _filters: AnnotationFilters = {
hint: false, hint: {
hint_only: false,
vertebrate: false,
names: false,
},
redaction: false, redaction: false,
comment: false, comment: false,
suggestion: false, suggestion: false,

View File

@ -17,8 +17,31 @@ export class AnnotationUtils {
}); });
} }
public static hasActiveFilters(filters: AnnotationFilters): boolean { public static hasSubsections(filter: AnnotationFilters | boolean) {
return Object.keys(filters).filter(type => filters[type]).length > 0; return filter instanceof Object;
}
public static checkedSubkeys(filter: AnnotationFilters | boolean) {
return Object.keys(filter).filter(subkey => this.isChecked(filter[subkey])).length;
}
// Only some of the sub-items are selected
public static isIndeterminate(filter: AnnotationFilters | boolean): boolean {
return this.hasSubsections(filter) ? AnnotationUtils.checkedSubkeys(filter) > 0 && !this.isChecked(filter) : false;
}
// All sub-items are selected
public static isChecked(filter: AnnotationFilters | boolean): boolean {
return this.hasSubsections(filter) ?
AnnotationUtils.checkedSubkeys(filter) === Object.keys(filter).length :
filter as boolean;
}
public static hasActiveFilters(filter: AnnotationFilters): boolean {
const activeFilters = Object.keys(filter).filter(key => {
return this.isChecked(filter[key]) || this.isIndeterminate(filter[key]);
});
return activeFilters.length > 0;
} }
public static parseAnnotations(annotations: Annotations.Annotation[], filters: AnnotationFilters): public static parseAnnotations(annotations: Annotations.Annotation[], filters: AnnotationFilters):
@ -28,9 +51,16 @@ export class AnnotationUtils {
for (const ann of annotations) { for (const ann of annotations) {
const pageNumber = ann.getPageNumber(); const pageNumber = ann.getPageNumber();
const type = this.getType(ann); const type = this.getType(ann);
const dictionary = this.getDictionary(ann);
if (this.hasActiveFilters(filters) && !filters[type]) { if (this.hasActiveFilters(filters)) {
continue; if (!this.hasSubsections(filters[type]) && !filters[type]) {
continue;
}
if (this.hasSubsections(filters[type]) && !filters[type][dictionary]) {
continue;
}
} }
if (!obj[pageNumber]) { if (!obj[pageNumber]) {
@ -54,7 +84,6 @@ export class AnnotationUtils {
return obj; return obj;
} }
public static addAnnotations(initialAnnotations: Annotations.Annotation[], addedAnnotations: Annotations.Annotation[]) { public static addAnnotations(initialAnnotations: Annotations.Annotation[], addedAnnotations: Annotations.Annotation[]) {
for (const annotation of addedAnnotations) { for (const annotation of addedAnnotations) {
if (annotation.Id.indexOf(':') > 0) { if (annotation.Id.indexOf(':') > 0) {

View File

@ -362,7 +362,16 @@
"label": "Filter types" "label": "Filter types"
}, },
"hint": { "hint": {
"label": "Hint annotation" "label": "Hint annotation",
"hint_only": {
"label": "Hint only"
},
"vertebrate": {
"label": "Vertebrate"
},
"names": {
"label": "Names"
}
}, },
"redaction": { "redaction": {
"label": "Redaction" "label": "Redaction"

View File

@ -9,6 +9,10 @@
font-size: 13px; font-size: 13px;
color: $accent; color: $accent;
&.padding-left {
padding-left: 40px;
}
.mat-checkbox-layout { .mat-checkbox-layout {
width: 100%; width: 100%;

View File

@ -14,8 +14,10 @@ $blue-3: #5B97DB;
$blue-4: #374C81; $blue-4: #374C81;
$red-1: #DD4D50; $red-1: #DD4D50;
$yellow-1: #FFB83B; $yellow-1: #FFB83B;
$green-1: #46CE7D; $yellow-2: #FFFF02;
$green-1: #00FF00;
$green-2: #5CE594; $green-2: #5CE594;
$orange-1: #FF801A;
$primary: $red-1; $primary: $red-1;
$accent: $grey-1; $accent: $grey-1;