From a4308c654d987525360ffbdd66810d555379c7a7 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Tue, 20 Apr 2021 22:42:23 +0300 Subject: [PATCH] Add filter option "only with comments" to annotation filters --- .../file-workload.component.html | 1 + .../file-workload/file-workload.component.ts | 5 +- .../file-preview-screen.component.ts | 4 +- .../services/annotation-processing.service.ts | 11 +- .../components/filter/filter.component.html | 105 +++++++++--------- .../components/filter/filter.component.scss | 21 ++++ .../components/filter/filter.component.ts | 23 +++- apps/red-ui/src/assets/i18n/en.json | 4 +- .../src/assets/icons/general/comment.svg | 15 ++- 9 files changed, 125 insertions(+), 64 deletions(-) diff --git a/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.html b/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.html index 59307364c..5c88ae2bd 100644 --- a/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.html +++ b/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.html @@ -12,6 +12,7 @@ [filterTemplate]="annotationFilterTemplate" [actionsTemplate]="annotationFilterActionTemplate" [filters]="annotationFilters" + [enableFilterOptions]="true" > diff --git a/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.ts b/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.ts index d09b08029..2ab4eb6b4 100644 --- a/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.ts +++ b/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.ts @@ -45,6 +45,7 @@ export class FileWorkloadComponent { public quickScrollLastEnabled = false; public displayedPages: number[] = []; public pagesPanelActive = true; + public filterOnlyWithComments = false; @ViewChild('annotationsElement') private _annotationsElement: ElementRef; @ViewChild('quickNavigation') private _quickNavigationElement: ElementRef; @@ -109,8 +110,8 @@ export class FileWorkloadComponent { } @debounce(0) - public filtersChanged(filters: FilterModel[]) { - this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(this._annotations, filters); + public filtersChanged($event: { filters: FilterModel[]; extraFilterBy?: (annotation: AnnotationWrapper) => boolean }) { + this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(this._annotations, $event.filters, $event.extraFilterBy); this.displayedPages = Object.keys(this.displayedAnnotations).map((key) => Number(key)); this.computeQuickNavButtonsState(); this._changeDetectorRef.markForCheck(); diff --git a/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.ts index e09b48f8c..f5cc77839 100644 --- a/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.ts @@ -218,7 +218,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, ); const annotationFilters = this._annotationProcessingService.getAnnotationFilter(this.annotations); this.annotationFilters = processFilters(this.annotationFilters, annotationFilters); - this._workloadComponent.filtersChanged(this.annotationFilters); + this._workloadComponent.filtersChanged({ filters: this.annotationFilters }); console.log('[REDACTION] Process time: ' + (new Date().getTime() - processStartTime) + 'ms'); console.log( '[REDACTION] Annotation Redraw and filter rebuild time: ' + @@ -527,7 +527,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, const oldPageSpecificFilters = this._annotationProcessingService.getAnnotationFilter(currentPageAnnotations); const newPageSpecificFilters = this._annotationProcessingService.getAnnotationFilter(newPageAnnotations); handleFilterDelta(oldPageSpecificFilters, newPageSpecificFilters, this.annotationFilters); - this._workloadComponent.filtersChanged(this.annotationFilters); + this._workloadComponent.filtersChanged({ filters: this.annotationFilters }); } } diff --git a/apps/red-ui/src/app/modules/projects/services/annotation-processing.service.ts b/apps/red-ui/src/app/modules/projects/services/annotation-processing.service.ts index b55219238..5fe3b3592 100644 --- a/apps/red-ui/src/app/modules/projects/services/annotation-processing.service.ts +++ b/apps/red-ui/src/app/modules/projects/services/annotation-processing.service.ts @@ -62,7 +62,11 @@ export class AnnotationProcessingService { return filter; } - filterAndGroupAnnotations(annotations: AnnotationWrapper[], filters: FilterModel[]): { [key: number]: { annotations: AnnotationWrapper[] } } { + filterAndGroupAnnotations( + annotations: AnnotationWrapper[], + filters: FilterModel[], + extraFilterBy?: (annotation: AnnotationWrapper) => boolean + ): { [key: number]: { annotations: AnnotationWrapper[] } } { const obj = {}; const hasActiveFilters = this._hasActiveFilters(filters); @@ -73,6 +77,10 @@ export class AnnotationProcessingService { flatFilters.push(...filter.filters); }); for (const annotation of annotations) { + if (typeof extraFilterBy === 'function' && !extraFilterBy(annotation)) { + continue; + } + const pageNumber = annotation.pageNumber; const type = annotation.superType; @@ -103,6 +111,7 @@ export class AnnotationProcessingService { skipped: 0 }; } + obj[pageNumber].annotations.push(annotation); obj[pageNumber][type]++; } diff --git a/apps/red-ui/src/app/modules/shared/components/filter/filter.component.html b/apps/red-ui/src/app/modules/shared/components/filter/filter.component.html index 032f6e59d..471b7196a 100644 --- a/apps/red-ui/src/app/modules/shared/components/filter/filter.component.html +++ b/apps/red-ui/src/app/modules/shared/components/filter/filter.component.html @@ -1,58 +1,63 @@ -
- - - -
-
-
-
-
-
-
+ + + + + +
+
+
+
+
+
-
-
-
- - -
-
-   -
- - - - +
+
+
+
+ +
-
-
- - - - - -
+
+   +
+ + + + +
+
+
+ + + +
- -
+
+
+
+
+
+ + + {{ 'filter-menu.with-comments' | translate }} + +
+
+
+ {{ filter?.label }} diff --git a/apps/red-ui/src/app/modules/shared/components/filter/filter.component.scss b/apps/red-ui/src/app/modules/shared/components/filter/filter.component.scss index 0b97ef116..cffaf242c 100644 --- a/apps/red-ui/src/app/modules/shared/components/filter/filter.component.scss +++ b/apps/red-ui/src/app/modules/shared/components/filter/filter.component.scss @@ -1,5 +1,6 @@ @import '../../../../../assets/styles/red-variables'; +.filter-menu-options, .filter-menu-header { display: flex; justify-content: space-between; @@ -15,6 +16,26 @@ } } +.filter-menu-options { + margin-top: 8px; + padding: 16px 16px 3px; +} + +.filter-options { + background-color: $grey-2; + padding-bottom: 8px; + + mat-icon { + width: 16px; + height: 16px; + margin-right: 8px; + } +} + +::ng-deep .mat-menu-panel .mat-menu-content:not(:empty) { + padding-bottom: 0; +} + ::ng-deep .filter-menu-checkbox { width: 100%; diff --git a/apps/red-ui/src/app/modules/shared/components/filter/filter.component.ts b/apps/red-ui/src/app/modules/shared/components/filter/filter.component.ts index 64987f97e..345f73c7e 100644 --- a/apps/red-ui/src/app/modules/shared/components/filter/filter.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/filter/filter.component.ts @@ -4,6 +4,7 @@ import { FilterModel } from './model/filter.model'; import { handleCheckedValue } from './utils/filter-utils'; import { MatMenuTrigger } from '@angular/material/menu'; import { MAT_CHECKBOX_DEFAULT_OPTIONS } from '@angular/material/checkbox'; +import { AnnotationWrapper } from '../../../../models/file/annotation.wrapper'; @Component({ selector: 'redaction-filter', @@ -20,11 +21,12 @@ import { MAT_CHECKBOX_DEFAULT_OPTIONS } from '@angular/material/checkbox'; ] }) export class FilterComponent implements OnChanges { - @Output() filtersChanged = new EventEmitter(); + @Output() filtersChanged = new EventEmitter<{ filters: FilterModel[]; extraFilterBy?: (annotation: AnnotationWrapper) => boolean }>(); @Input() filterTemplate: TemplateRef; @Input() actionsTemplate: TemplateRef; @Input() filters: FilterModel[] = []; @Input() filterLabel = 'filter-menu.label'; + @Input() enableFilterOptions = false; @Input() icon: string; @Input() chevron = false; @@ -34,6 +36,7 @@ export class FilterComponent implements OnChanges { mouseOverTimeout: number; atLeastOnFilterIsExpandable = false; + filterOnlyWithComments = false; constructor(public readonly appStateService: AppStateService, private readonly _changeDetectorRef: ChangeDetectorRef) {} @@ -47,6 +50,8 @@ export class FilterComponent implements OnChanges { } filterCheckboxClicked($event: any, filter: FilterModel, parent?: FilterModel) { + $event.stopPropagation(); + filter.checked = !filter.checked; if (parent) { handleCheckedValue(parent); @@ -61,7 +66,13 @@ export class FilterComponent implements OnChanges { this.applyFilters(); } - public activateAllFilters() { + filterOptionsCheckboxClicked($event: Event) { + $event.stopPropagation(); + this.filterOnlyWithComments = !this.filterOnlyWithComments; + this.applyFilters(); + } + + activateAllFilters() { this._setAllFilters(true); } @@ -78,8 +89,12 @@ export class FilterComponent implements OnChanges { return false; } - public applyFilters() { - this.filtersChanged.emit(this.filters); + applyFilters() { + this.filtersChanged.emit({ filters: this.filters, extraFilterBy: this._extraFilterBy }); + } + + private get _extraFilterBy(): (a: AnnotationWrapper) => boolean { + return this.enableFilterOptions && this.filterOnlyWithComments ? (a) => a.comments.length !== 0 : (a) => true; } toggleFilterExpanded($event: MouseEvent, filter: FilterModel) { diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index f798c728c..be4efa650 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -514,7 +514,9 @@ "label": "Filter", "all": "All", "none": "None", - "filter-types": "Filter types" + "filter-types": "Filter types", + "filter-options": "Filter options", + "with-comments": "Show only annotations with comments" }, "sorting": { "recent": "Recent", diff --git a/apps/red-ui/src/assets/icons/general/comment.svg b/apps/red-ui/src/assets/icons/general/comment.svg index 1c1bbc7dd..b345a774c 100644 --- a/apps/red-ui/src/assets/icons/general/comment.svg +++ b/apps/red-ui/src/assets/icons/general/comment.svg @@ -1,6 +1,13 @@ - - - + + status + + + + + + + + - + \ No newline at end of file