Annotations filter menu
This commit is contained in:
parent
bfca1865dd
commit
84c6612ccb
@ -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">
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
22
apps/red-ui/src/app/screens/file/service/filters.service.ts
Normal file
22
apps/red-ui/src/app/screens/file/service/filters.service.ts
Normal 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));
|
||||
}
|
||||
}
|
||||
8
apps/red-ui/src/app/utils/types.d.ts
vendored
8
apps/red-ui/src/app/utils/types.d.ts
vendored
@ -15,3 +15,11 @@ export class SortingOption {
|
||||
column: string;
|
||||
}
|
||||
|
||||
export class AnnotationFilters {
|
||||
[key: string]: {
|
||||
label: string,
|
||||
value: boolean,
|
||||
class: string,
|
||||
symbol: string
|
||||
}
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
12
apps/red-ui/src/assets/styles/red-checkbox.scss
Normal file
12
apps/red-ui/src/assets/styles/red-checkbox.scss
Normal 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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
30
apps/red-ui/src/assets/styles/red-menu.scss
Normal file
30
apps/red-ui/src/assets/styles/red-menu.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -167,7 +167,7 @@ html, body {
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
color: $red-1;
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -42,11 +42,11 @@
|
||||
line-height: 14px;
|
||||
|
||||
&.mat-selected.mat-active {
|
||||
color: $red-1;
|
||||
color: $primary;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #F4F5F7 !important;
|
||||
background: $grey-2 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user