diff --git a/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.scss b/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.scss index 5563fd6d6..c3269744d 100644 --- a/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.scss +++ b/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.scss @@ -50,3 +50,15 @@ .ignore { background-color: $grey-5; } + +.hint_only { + background-color: $orange-1; +} + +.vertebrate { + background-color: $green-1; +} + +.names { + background-color: $yellow-2; +} diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html index 6094254c0..29af6b76f 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html @@ -56,17 +56,34 @@
+ (click)="setAllFilters(filters, true); applyFilters(); $event.stopPropagation();">
+ (click)="setAllFilters(filters, false); applyFilters(); $event.stopPropagation();"> -
- - - {{"file-preview.filter-menu."+ key + ".label" | translate }} - +
+
+ + + {{"file-preview.filter-menu." + key + ".label" | translate }} + +
+
+
+ + + {{"file-preview.filter-menu." + key + "." + subkey + ".label" | translate }} + +
+
+
@@ -94,7 +111,7 @@ (click)="selectAnnotation(annotation)" > - +
{{getType(annotation) | translate}}
: {{getDictionary(annotation)}}
diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts index 324ec58c0..d0b873eff 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts @@ -82,7 +82,11 @@ export class FilePreviewScreenComponent implements OnInit { return this._userService.user; } - public get filterKeys() { + public filterKeys(key?: string) { + if (key) { + return Object.keys(this.filters[key]); + } + return Object.keys(this.filters); } @@ -272,13 +276,36 @@ export class FilePreviewScreenComponent implements OnInit { }); } - public setAllFilters(value: boolean) { - Object.keys(this.filters).map((key) => { - this.filters[key] = value; - }); + public setAllFilters(filter: AnnotationFilters, value: boolean, rootKey?: string) { + if (rootKey) { + 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 { return AnnotationUtils.hasActiveFilters(this.filters); } + + public hasSubsections(filter: AnnotationFilters | boolean) { + return AnnotationUtils.hasSubsections(filter); + } } diff --git a/apps/red-ui/src/app/screens/file/service/filters.service.ts b/apps/red-ui/src/app/screens/file/service/filters.service.ts index 986fe5d94..cb8cb7807 100644 --- a/apps/red-ui/src/app/screens/file/service/filters.service.ts +++ b/apps/red-ui/src/app/screens/file/service/filters.service.ts @@ -9,7 +9,11 @@ export class FiltersService { } private _filters: AnnotationFilters = { - hint: false, + hint: { + hint_only: false, + vertebrate: false, + names: false, + }, redaction: false, comment: false, suggestion: false, diff --git a/apps/red-ui/src/app/utils/annotation-utils.ts b/apps/red-ui/src/app/utils/annotation-utils.ts index 9d6fdfa92..cdfc3fa2e 100644 --- a/apps/red-ui/src/app/utils/annotation-utils.ts +++ b/apps/red-ui/src/app/utils/annotation-utils.ts @@ -17,8 +17,31 @@ export class AnnotationUtils { }); } - public static hasActiveFilters(filters: AnnotationFilters): boolean { - return Object.keys(filters).filter(type => filters[type]).length > 0; + public static hasSubsections(filter: AnnotationFilters | boolean) { + 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): @@ -28,9 +51,16 @@ export class AnnotationUtils { for (const ann of annotations) { const pageNumber = ann.getPageNumber(); const type = this.getType(ann); + const dictionary = this.getDictionary(ann); - if (this.hasActiveFilters(filters) && !filters[type]) { - continue; + if (this.hasActiveFilters(filters)) { + if (!this.hasSubsections(filters[type]) && !filters[type]) { + continue; + } + + if (this.hasSubsections(filters[type]) && !filters[type][dictionary]) { + continue; + } } if (!obj[pageNumber]) { @@ -54,7 +84,6 @@ export class AnnotationUtils { return obj; } - public static addAnnotations(initialAnnotations: Annotations.Annotation[], addedAnnotations: Annotations.Annotation[]) { for (const annotation of addedAnnotations) { if (annotation.Id.indexOf(':') > 0) { diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 134f76839..bc41964a8 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -362,7 +362,16 @@ "label": "Filter types" }, "hint": { - "label": "Hint annotation" + "label": "Hint annotation", + "hint_only": { + "label": "Hint only" + }, + "vertebrate": { + "label": "Vertebrate" + }, + "names": { + "label": "Names" + } }, "redaction": { "label": "Redaction" diff --git a/apps/red-ui/src/assets/styles/red-menu.scss b/apps/red-ui/src/assets/styles/red-menu.scss index 755380deb..e030e4d30 100644 --- a/apps/red-ui/src/assets/styles/red-menu.scss +++ b/apps/red-ui/src/assets/styles/red-menu.scss @@ -9,6 +9,10 @@ font-size: 13px; color: $accent; + &.padding-left { + padding-left: 40px; + } + .mat-checkbox-layout { width: 100%; diff --git a/apps/red-ui/src/assets/styles/red-variables.scss b/apps/red-ui/src/assets/styles/red-variables.scss index 6815af85e..c2aedf111 100644 --- a/apps/red-ui/src/assets/styles/red-variables.scss +++ b/apps/red-ui/src/assets/styles/red-variables.scss @@ -14,8 +14,10 @@ $blue-3: #5B97DB; $blue-4: #374C81; $red-1: #DD4D50; $yellow-1: #FFB83B; -$green-1: #46CE7D; +$yellow-2: #FFFF02; +$green-1: #00FF00; $green-2: #5CE594; +$orange-1: #FF801A; $primary: $red-1; $accent: $grey-1;