Annotations filter menu

This commit is contained in:
Adina Țeudan 2020-10-15 06:02:46 +03:00
parent bfca1865dd
commit 84c6612ccb
15 changed files with 220 additions and 20 deletions

View File

@ -5,10 +5,9 @@
translate="file-preview.view-toggle.label"></mat-slide-toggle>
<div>
<button color="primary" mat-flat-button
[matMenuTriggerFor]="downloadMenu"
class="add-project-btn">
[matMenuTriggerFor]="downloadMenu">
<span translate="file-preview.download.label"></span>
<mat-icon>arrow_drop_down</mat-icon>
<mat-icon class="dropdown-icon">arrow_drop_down</mat-icon>
</button>
<mat-menu #downloadMenu="matMenu" xPosition="before">
<div mat-menu-item
@ -49,6 +48,33 @@
#navigationTabElement>
<div class="tab-title" [ngClass]="navigationTab ? 'heading' : 'subheading'"
translate="file-preview.tabs.quick-navigation.label">
<div>
<button color="accent" mat-button
[matMenuTriggerFor]="filterMenu" [ngClass]="{ overlay: hasActiveFilters }">
<span translate="file-preview.filter-menu.label"></span>
<mat-icon class="dropdown-icon">arrow_drop_down</mat-icon>
</button>
<div class="dot" *ngIf="hasActiveFilters"></div>
<mat-menu class="filter-menu" #filterMenu="matMenu" xPosition="before">
<div class="filter-menu-header">
<div class="subheading" translate="file-preview.filter-menu.filter-types.label"></div>
<div class="actions">
<div class="subheading primary pointer" translate="file-preview.filter-menu.all.label"
(click)="setAllFilters(true); $event.stopPropagation();"></div>
<div class="subheading primary pointer" translate="file-preview.filter-menu.none.label"
(click)="setAllFilters(false); $event.stopPropagation();"></div>
</div>
</div>
<div class="mat-menu-item" *ngFor="let key of filterKeys" (click)="$event.stopPropagation()">
<mat-checkbox [(ngModel)]="filters[key].value" color="primary">
<div [class]="filters[key].class + ' x-small'">
{{ filters[key].symbol }}
</div>
{{filters[key].label | translate }}
</mat-checkbox>
</div>
</mat-menu>
</div>
</div>
<div class="tab-content" [class.not-visible]="!navigationTab">
@ -88,7 +114,10 @@
#annotationsContainer>
<div class="tab-title" [ngClass]="annotationsTab ? 'heading' : 'subheading'"
translate="file-preview.tabs.annotations.label">
<mat-icon *ngIf="annotationsTab" (click)="selectTab('NAVIGATION', $event)" svgIcon="red:close"></mat-icon>
<mat-icon class="close-icon"
*ngIf="annotationsTab"
(click)="selectTab('NAVIGATION', $event)"
svgIcon="red:close"></mat-icon>
</div>
<div class="tab-content" [class.not-visible]="!annotationsTab">
@ -115,7 +144,10 @@
<div class="vertical" (click)="selectTab('INFO')" [ngClass]="{ active: infoTab}">
<div class="tab-title" [ngClass]="infoTab ? 'heading' : 'subheading'"
translate="file-preview.tabs.info.label">
<mat-icon *ngIf="infoTab" (click)="selectTab('NAVIGATION', $event)" svgIcon="red:close"></mat-icon>
<mat-icon class="close-icon"
*ngIf="infoTab"
(click)="selectTab('NAVIGATION', $event)"
svgIcon="red:close"></mat-icon>
</div>
<div *ngIf="infoTab" class="tab-content info-container">

View File

@ -32,7 +32,21 @@ redaction-pdf-viewer {
justify-content: space-between;
padding: 0 25px;
mat-icon {
> div {
position: relative;
.dot {
background: $primary;
height: 10px;
width: 10px;
border-radius: 50%;
position: absolute;
top: 0;
left: 0;
}
}
.close-icon {
height: 14px;
width: 14px;
cursor: pointer;
@ -91,7 +105,7 @@ redaction-pdf-viewer {
}
&.active {
border-left: 2px solid $red-1;
border-left: 2px solid $primary;
}
.annotation-actions {
@ -114,7 +128,7 @@ redaction-pdf-viewer {
border-left: 4px solid transparent;
&:hover {
background-color: #F4F5F7;
background-color: $grey-2;
}
.page-number {
@ -134,7 +148,19 @@ redaction-pdf-viewer {
}
&.active {
border-left: 4px solid $red-1;
border-left: 4px solid $primary;
}
}
}
.filter-menu-header {
display: flex;
justify-content: space-between;
width: 250px;
padding: 7px 15px 15px;
.actions {
display: flex;
gap: 8px;
}
}

View File

@ -21,6 +21,8 @@ import { UserService } from '../../../user/user.service';
import { debounce } from '../../../utils/debounce';
import scrollIntoView from 'scroll-into-view-if-needed';
import { ConfirmationDialogComponent } from '../../../common/confirmation-dialog/confirmation-dialog.component';
import { AnnotationFilters } from '../../../utils/types';
import { FiltersService } from '../service/filters.service';
@Component({
selector: 'redaction-file-preview-screen',
@ -54,6 +56,12 @@ export class FilePreviewScreenComponent implements OnInit {
ignore: number;
}[] = [];
public filters: AnnotationFilters;
public get filterKeys() {
return Object.keys(this.filters);
}
private _manualRedactionEntry: ManualRedactionEntry;
activeViewerPage: number;
@ -71,12 +79,14 @@ export class FilePreviewScreenComponent implements OnInit {
private readonly _manualRedactionControllerService: ManualRedactionControllerService,
private readonly _userService: UserService,
private readonly _fileUploadControllerService: FileUploadControllerService,
private readonly _projectControllerService: ProjectControllerService) {
private readonly _projectControllerService: ProjectControllerService,
private readonly _filtersService: FiltersService) {
this._activatedRoute.params.subscribe(params => {
this.projectId = params.projectId;
this.fileId = params.fileId;
this.appStateService.activateFile(this.projectId, this.fileId);
});
this.filters = _filtersService.filters;
}
get user() {
@ -310,4 +320,20 @@ export class FilePreviewScreenComponent implements OnInit {
public downloadFile(type: 'original' | 'annotated' | 'redacted') {
console.log(`Downloading ${type}...`);
}
public setAllFilters(value: boolean) {
Object.keys(this.filters).map((key) => {
this.filters[key].value = value;
});
}
public get hasActiveFilters(): boolean {
let activeFilters = false;
Object.keys(this.filters).map((key) => {
if (this.filters[key].value) {
activeFilters = true;
}
});
return activeFilters;
}
}

View File

@ -0,0 +1,22 @@
import { Injectable } from '@angular/core';
import { AnnotationFilters } from '../../../utils/types';
@Injectable({
providedIn: 'root'
})
export class FiltersService {
constructor() {
}
private _filters: AnnotationFilters = {
hint: { label: 'file-preview.filter-menu.hint.label', value: false, class: 'oval darkgray-white', symbol: 'H' },
redaction: { label: 'file-preview.filter-menu.redaction.label', value: false, class: 'square darkgray-white', symbol: 'R' },
comment: { label: 'file-preview.filter-menu.comment.label', value: false, class: 'oval darkgray-white', symbol: 'C' },
suggestion: { label: 'file-preview.filter-menu.suggestion.label', value: false, class: 'oval red-white', symbol: 'S' },
ignored: { label: 'file-preview.filter-menu.ignored.label', value: false, class: 'oval lightgray-white', symbol: 'I' },
}
public get filters(): AnnotationFilters {
return JSON.parse(JSON.stringify(this._filters));
}
}

View File

@ -15,3 +15,11 @@ export class SortingOption {
column: string;
}
export class AnnotationFilters {
[key: string]: {
label: string,
value: boolean,
class: string,
symbol: string
}
}

View File

@ -342,6 +342,33 @@
"view-toggle": {
"label": "Redacted View"
},
"filter-menu": {
"label": "Filter",
"all": {
"label": "All"
},
"none": {
"label": "None"
},
"filter-types": {
"label": "Filter types"
},
"hint": {
"label": "Hint annotation"
},
"redaction": {
"label": "Redaction"
},
"comment": {
"label": "Comment"
},
"suggestion": {
"label": "Suggested redaction"
},
"ignored": {
"label": "Ignored redaction"
}
},
"tabs": {
"quick-navigation": {
"label": "Quick Navigation"

View File

@ -1,5 +1,15 @@
button.mat-flat-button {
@import "red-variables";
.mat-button, .mat-flat-button {
font-family: Inter, sans-serif !important;
font-weight: 400 !important;
border-radius: 25px !important;
.dropdown-icon {
width: 16px;
}
}
.mat-button[aria-expanded="true"], .mat-button.overlay {
background: rgba($primary, 0.1);
}

View File

@ -0,0 +1,12 @@
@import "red-variables";
.mat-checkbox .mat-checkbox-frame {
border: 1px solid $grey-5;
}
.mat-checkbox-indeterminate.mat-accent .mat-checkbox-background, .mat-checkbox-checked.mat-accent .mat-checkbox-background {
margin-top: 1px;
margin-left: 1px;
width: 18px;
height: 18px;
}

View File

@ -12,13 +12,13 @@
height: 6px;
width: 16px;
border-radius: 3px;
background-color: $red-1;
background-color: $primary;
}
.line-2 {
height: 6px;
width: 22px;
border-radius: 6px;
background-color: $red-1;
background-color: $primary;
}
}

View File

@ -0,0 +1,30 @@
@import "red-variables";
.mat-menu-panel {
border-radius: 8px !important;
box-shadow: 0 2px 6px 0 rgba(40, 50, 65, 0.3);
.mat-menu-item {
font-family: 'Inter', sans-serif;
font-size: 13px;
color: $accent;
.mat-checkbox-layout {
width: 100%;
.mat-checkbox-inner-container {
margin-left: 0;
}
.mat-checkbox-label {
font-family: 'Inter', sans-serif;
font-size: 13px;
color: $accent;
display: flex;
align-items: center;
gap: 4px;
}
}
}
}

View File

@ -167,7 +167,7 @@ html, body {
}
&:last-child {
color: $red-1;
color: $primary;
}
}

View File

@ -42,11 +42,11 @@
line-height: 14px;
&.mat-selected.mat-active {
color: $red-1;
color: $primary;
}
&:hover {
background: #F4F5F7 !important;
background: $grey-2 !important;
}
}
}

View File

@ -2,10 +2,10 @@
@import "red-mixins";
a {
color: $red-1;
color: $primary;
&:hover {
color: lighten($red-1, 10%)
color: lighten($primary, 10%)
}
cursor: pointer;
@ -51,3 +51,8 @@ a {
.clamp-2 {
@include line-clamp(2);
}
.primary {
color: $primary;
opacity: 1;
}

View File

@ -9,7 +9,9 @@
@import "red-input";
@import "red-button";
@import "red-select";
@import "red-checkbox";
@import "red-toggle";
@import "red-menu";
@import "red-media-queries";
@import "red-tables";
@import "red-components";

View File

@ -7,7 +7,7 @@ $light: #FFF;
$dark: #000;
$grey-1: #283241;
$grey-2: #ECECEE;
$grey-2: #F4F5F7;
$grey-3: #AAACB3;
$grey-4: #E2E4E9;
$grey-5: #D3D5DA;
@ -16,7 +16,7 @@ $blue-1: #4875F7;
$blue-2: #48C9F7;
$blue-3: #5B97DB;
$blue-4: #374C81;
$red-1: #F65757;
$red-1: #DD4D50;
$yellow-1: #FFB83B;
$green-1: #46CE7D;
$green-2: #5CE594;