Pull request #11: Ui updates

Merge in RED/ui from ui-updates to master

* commit 'f97f9bac62d797f15471d917294eb71f9fa44163':
  Filter annotations logic
  Annotations filter menu
  Quick navigation list items
  File preview close tabs
  Added translations
  Download file button
  View toggle
This commit is contained in:
Timo Bejan 2020-10-15 14:23:49 +02:00
commit 661b9cf4f2
22 changed files with 488 additions and 128 deletions

View File

@ -52,6 +52,7 @@ import { AppStateGuard } from './state/app-state.guard';
import { SimpleDoughnutChartComponent } from './components/simple-doughnut-chart/simple-doughnut-chart.component';
import { ManualRedactionDialogComponent } from './screens/file/manual-redaction-dialog/manual-redaction-dialog.component';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
export function HttpLoaderFactory(httpClient: HttpClient) {
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
@ -134,6 +135,7 @@ export function HttpLoaderFactory(httpClient: HttpClient) {
NgpSortModule,
MatToolbarModule,
MatButtonModule,
MatSlideToggleModule,
MatMenuModule,
MatIconModule,
MatTooltipModule,

View File

@ -10,7 +10,7 @@ export class InitialsAvatarComponent implements OnInit {
public username: string;
@Input()
public color: 'red-white' | 'gray-red' | 'gray-dark' = 'gray-dark';
public color = 'lightgray-dark';
@Input()
public size: 'small' | 'large' = 'small';

View File

@ -1,19 +1,29 @@
<section class="" [class.hidden]="!viewReady">
<div class="page-header">
<div class="flex-row">
<div class="btn-group">
<button class="btn-group-btn" [class.active]="activeViewer === 'ANNOTATED'"
(click)="activateViewer('ANNOTATED')"
translate="file-preview.annotated.label">
</button>
<button class="btn-group-btn" [class.active]="activeViewer === 'REDACTED'"
(click)="activateViewer('REDACTED')"
translate="file-preview.redacted.label">
</button>
</div>
<mat-slide-toggle color="primary"
[(ngModel)]="redactedView"
translate="file-preview.view-toggle.label"></mat-slide-toggle>
<div>
<button color="primary" mat-flat-button
[matMenuTriggerFor]="downloadMenu">
<span translate="file-preview.download.label"></span>
<mat-icon class="dropdown-icon">arrow_drop_down</mat-icon>
</button>
<mat-menu #downloadMenu="matMenu" xPosition="before">
<div mat-menu-item
translate="file-preview.download.dropdown.original.label"
(click)="downloadFile('original')"
></div>
<div mat-menu-item
translate="file-preview.download.dropdown.annotated.label"
(click)="downloadFile('annotated')"
></div>
<div mat-menu-item
translate="file-preview.download.dropdown.redacted.label"
(click)="downloadFile('redacted')"
></div>
</mat-menu>
</div>
<button color="warn" mat-flat-button
translate="file-preview.download-redacted.label"></button>
</div>
<div class="flex red-content-inner">
@ -36,31 +46,49 @@
<!-- Quick navigation tab-->
<div class="vertical" (click)="selectTab('NAVIGATION')" [ngClass]="{ active: navigationTab}"
#navigationTabElement>
<div class="tab-title" [ngClass]="navigationTab ? 'heading' : 'subheading'">
Quick Navigation
<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">
<div *ngFor="let item of quickNavigation | sortBy:'asc':'number'"
class="page-navigation"
[id]="'quick-nav-page-'+item.pageNumber"
[ngClass]="{ active: item.pageNumber === activeViewerPage }"
[ngClass]="{ active: item.pageNumber === activeViewerPage, hidden: !showQuickNavigationItem(item) }"
(click)="selectPage(item.pageNumber)"
>
<div class="page-number">Page {{ item.pageNumber }}</div>
<div class="stats-subtitle subtitle mt-5">
<div *ngIf="item.redactions" class="center">
<mat-icon svgIcon="red:secret"></mat-icon>
{{item.redactions}} Redactions
</div>
<div *ngIf="item.hints" class="center">
<mat-icon svgIcon="red:idea"></mat-icon>
{{item.hints}} Hints
</div>
<div *ngIf="item.hints" class="center">
<mat-icon svgIcon="red:info"></mat-icon>
{{item.ignore}} Ignore
</div>
<div class="page-number subtitle">{{ item.pageNumber }}</div>
<div *ngFor="let key of filterKeys"
[ngClass]="{ hidden: !showAnnotations(item, key)}" class="page-stats subtitle">
<div [class]="filters[key].class + ' x-small'">{{ filters[key].symbol }}</div>
{{item[key]}}
</div>
</div>
</div>
@ -69,8 +97,12 @@
<!-- Annotations tab-->
<div (click)="selectTab('ANNOTATIONS')" class="vertical" [ngClass]="{ active: annotationsTab }"
#annotationsContainer>
<div class="tab-title" [ngClass]="annotationsTab ? 'heading' : 'subheading'">
Annotations
<div class="tab-title" [ngClass]="annotationsTab ? 'heading' : 'subheading'"
translate="file-preview.tabs.annotations.label">
<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">
@ -86,7 +118,7 @@
<div class="annotation-actions">
<button mat-icon-button (click)="suggestRemoveAnnotation($event, annotation)">
<mat-icon svgIcon="red:delete" ></mat-icon>
<mat-icon svgIcon="red:delete"></mat-icon>
</button>
</div>
</div>
@ -95,8 +127,12 @@
<!-- Info tab-->
<div class="vertical" (click)="selectTab('INFO')" [ngClass]="{ active: infoTab}">
<div class="tab-title" [ngClass]="infoTab ? 'heading' : 'subheading'">
Info
<div class="tab-title" [ngClass]="infoTab ? 'heading' : 'subheading'"
translate="file-preview.tabs.info.label">
<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">
@ -115,25 +151,22 @@
<div class="flex-row mt-20">
<redaction-initials-avatar size="large" color="red-white"></redaction-initials-avatar>
<a class="assign-reviewer">Assign Reviewer</a>
<a class="assign-reviewer" translate="file-preview.tabs.info.assign-reviewer.label"></a>
</div>
<div class="subheading mt-20">
Added on
<div class="subheading mt-20" translate="file-preview.tabs.info.added-on.label">
</div>
<div class="subtitle mt-5">
{{appStateService.activeFile.added | date:'medium'}}
</div>
<div class="subheading mt-20">
Added by
<div class="subheading mt-20" translate="file-preview.tabs.info.added-by.label">
</div>
<div class="subtitle mt-5">
{{user.name}}
</div>
<div class="subheading mt-20">
Last modified on
<div class="subheading mt-20" translate="file-preview.tabs.info.last-modified-on.label">
</div>
<div class="subtitle mt-5">
{{appStateService.activeFile.lastUpdated | date:'medium'}}

View File

@ -29,7 +29,28 @@ redaction-pdf-viewer {
display: flex;
border-bottom: 1px solid $separator;
align-items: center;
justify-content: space-between;
padding: 0 25px;
> 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;
}
}
.tab-content {
@ -84,7 +105,7 @@ redaction-pdf-viewer {
}
&.active {
border-left: 2px solid $red-1;
border-left: 2px solid $primary;
}
.annotation-actions {
@ -98,21 +119,48 @@ redaction-pdf-viewer {
}
.page-navigation {
display: flex;
align-items: center;
gap: 12px;
cursor: pointer;
border-bottom: 1px solid $separator;
padding: 14px;
border-left: 4px solid transparent;
&:hover {
background-color: #F4F5F7;
background-color: $grey-2;
}
.page-number {
font-weight: 600;
border: 1px solid $separator;
padding: 7px;
margin-right: 3px;
width: 14px;
text-align: center;
}
.page-stats {
display: flex;
justify-content: center;
align-items: center;
gap: 6px;
opacity: 1;
}
&.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

@ -1,5 +1,5 @@
import {ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import { ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import {
FileUploadControllerService,
ManualRedactionControllerService,
@ -7,20 +7,31 @@ import {
ProjectControllerService,
StatusControllerService
} from '@redaction/red-ui-http';
import {TranslateService} from '@ngx-translate/core';
import {NotificationService, NotificationType} from '../../../notification/notification.service';
import {MatDialog} from '@angular/material/dialog';
import {AppStateService} from '../../../state/app-state.service';
import {FileDetailsDialogComponent} from './file-details-dialog/file-details-dialog.component';
import {ViewerSyncService} from '../service/viewer-sync.service';
import {Annotations} from '@pdftron/webviewer';
import {PdfViewerComponent} from '../pdf-viewer/pdf-viewer.component';
import {AnnotationUtils} from '../../../utils/annotation-utils';
import {ManualRedactionDialogComponent} from "../manual-redaction-dialog/manual-redaction-dialog.component";
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 { TranslateService } from '@ngx-translate/core';
import { NotificationService, NotificationType } from '../../../notification/notification.service';
import { MatDialog } from '@angular/material/dialog';
import { AppStateService } from '../../../state/app-state.service';
import { FileDetailsDialogComponent } from './file-details-dialog/file-details-dialog.component';
import { ViewerSyncService } from '../service/viewer-sync.service';
import { Annotations } from '@pdftron/webviewer';
import { PdfViewerComponent } from '../pdf-viewer/pdf-viewer.component';
import { AnnotationUtils } from '../../../utils/annotation-utils';
import { ManualRedactionDialogComponent } from '../manual-redaction-dialog/manual-redaction-dialog.component';
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';
class QuickNavigationItem {
pageNumber: number;
hints: number;
redactions: number;
comments: number;
suggestions: number;
ignored: number;
}
@Component({
selector: 'redaction-file-preview-screen',
@ -31,6 +42,7 @@ export class FilePreviewScreenComponent implements OnInit {
private _readyViewers: string[] = [];
private projectId: string;
private _selectedTab: 'NAVIGATION' | 'ANNOTATIONS' | 'INFO' = 'NAVIGATION';
private _activeViewer: 'ANNOTATED' | 'REDACTED' = 'ANNOTATED';
@ViewChild(PdfViewerComponent)
private _viewerComponent: PdfViewerComponent;
@ -44,7 +56,13 @@ export class FilePreviewScreenComponent implements OnInit {
public fileId: string;
public annotations: Annotations.Annotation[] = [];
public selectedAnnotation: Annotations.Annotation;
public quickNavigation: { pageNumber: number, redactions: number, hints: number, ignore: number; }[] = [];
public quickNavigation: QuickNavigationItem[] = [];
public filters: AnnotationFilters;
public get filterKeys() {
return Object.keys(this.filters);
}
private _manualRedactionEntry: ManualRedactionEntry;
@ -63,18 +81,29 @@ 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.appStateService.activateFile(this.projectId, this.fileId);
});
this.filters = _filtersService.filters;
}
get user() {
return this._userService.user;
}
public get redactedView() {
return this._activeViewer === 'REDACTED';
}
public set redactedView(value: boolean) {
this._activeViewer = value ? 'REDACTED' : 'ANNOTATED';
this._activateViewer(this._activeViewer);
}
public ngOnInit(): void {
// PDFTRON cache fix
localStorage.clear();
@ -103,11 +132,14 @@ export class FilePreviewScreenComponent implements OnInit {
return this._viewerSyncService.activeViewer;
}
public activateViewer(value: string) {
private _activateViewer(value: string) {
this._viewerSyncService.activateViewer(value);
}
public selectTab(value: 'ANNOTATIONS' | 'INFO' | 'NAVIGATION') {
public selectTab(value: 'ANNOTATIONS' | 'INFO' | 'NAVIGATION', $event?: MouseEvent) {
if ($event) {
$event.stopPropagation();
}
if (value !== this._selectedTab) {
this._selectedTab = value;
setTimeout(() => {
@ -124,14 +156,14 @@ export class FilePreviewScreenComponent implements OnInit {
const pageNumber = annotation.getPageNumber();
let el = this.quickNavigation.find((page) => page.pageNumber === pageNumber);
if (!el) {
el = {pageNumber, redactions: 0, hints: 0, ignore: 0}
el = { pageNumber, redactions: 0, hints: 0, ignored: 0, comments: 0, suggestions: 0 };
this.quickNavigation.push(el);
}
if (annotation.Id.startsWith('hint:')) {
el.hints++;
}
if (annotation.Id.startsWith('ignore:')) {
el.ignore++;
el.ignored++;
}
if (annotation.Id.startsWith('redaction:')) {
el.redactions++;
@ -141,6 +173,16 @@ export class FilePreviewScreenComponent implements OnInit {
this.annotations = AnnotationUtils.sortAnnotations(this.annotations);
}
public showQuickNavigationItem(item: QuickNavigationItem): boolean {
let showItem = false;
Object.keys(this.filters).map((key) => {
if (this.showAnnotations(item, key)) {
showItem = true;
}
})
return showItem;
}
public handleAnnotationSelected(annotation: Annotations.Annotation) {
this.selectedAnnotation = annotation;
this.selectTab('ANNOTATIONS');
@ -191,7 +233,7 @@ export class FilePreviewScreenComponent implements OnInit {
ref.afterClosed().subscribe(() => {
this._manualRedactionEntry = null;
})
});
}
viewerPageChanged(pageNumber: number) {
@ -228,8 +270,8 @@ export class FilePreviewScreenComponent implements OnInit {
behavior: 'smooth',
scrollMode: 'if-needed',
block: 'center',
inline: 'center',
})
inline: 'center'
});
}
}
@ -278,12 +320,36 @@ export class FilePreviewScreenComponent implements OnInit {
id: annotation.Id,
removeFromDictionary: false
}]
}, this.appStateService.activeProjectId, this.appStateService.activeFile.fileId).subscribe(ok=>{
this._notificationService.showToastNotification(this._translateService.instant('manual-redaction.remove-annotation.success.label'), null, NotificationType.SUCCESS);
},(err)=>{
this._notificationService.showToastNotification(this._translateService.instant('manual-redaction.remove-annotation.failed.label',err), null, NotificationType.ERROR);
});
}, this.appStateService.activeProjectId, this.appStateService.activeFile.fileId).subscribe(ok => {
this._notificationService.showToastNotification(this._translateService.instant('manual-redaction.remove-annotation.success.label'), null, NotificationType.SUCCESS);
}, (err) => {
this._notificationService.showToastNotification(this._translateService.instant('manual-redaction.remove-annotation.failed.label', err), null, NotificationType.ERROR);
});
}
});
}
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;
}
public showAnnotations(item: QuickNavigationItem, type: string): boolean {
return item[type] && (!this.hasActiveFilters || (this.hasActiveFilters && this.filters[type]?.value));
}
}

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 = {
hints: { label: 'file-preview.filter-menu.hint.label', value: false, class: 'oval darkgray-white', symbol: 'H' },
redactions: { label: 'file-preview.filter-menu.redaction.label', value: false, class: 'square darkgray-white', symbol: 'R' },
comments: { label: 'file-preview.filter-menu.comment.label', value: false, class: 'oval darkgray-white', symbol: 'C' },
suggestions: { 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

@ -7,23 +7,23 @@
<div translate="filters.project.label"></div>
<div translate="filters.document.label"></div>
</div>
<button (click)="openAddProjectDialog()" color="warn" mat-flat-button class="add-project-btn">
<button (click)="openAddProjectDialog()" color="primary" mat-flat-button class="add-project-btn">
<mat-icon svgIcon="red:plus">
</mat-icon>
<span translate="projects.add-new.label"></span>
<span translate="project-listing.add-new.label"></span>
</button>
</div>
<div *ngIf="appStateService.allProjects?.length === 0 " translate="projects.no-projects.label"></div>
<div *ngIf="appStateService.allProjects?.length === 0 " translate="project-listing.no-projects.label"></div>
<div class="flex red-content-inner">
<div class="left-container">
<div class="table-header">
<span class="subheading">
{{'projects.table-header.title.label'| translate:{ length: appStateService.allProjects?.length || 0 } }}
{{'project-listing.table-header.title.label'| translate:{ length: appStateService.allProjects?.length || 0 } }}
</span>
<div class="actions">
<div translate="projects.table-header.bulk-select.label"></div>
<div translate="project-listing.table-header.bulk-select.label"></div>
<mat-form-field appearance="none" class="red-select">
<mat-select [(ngModel)]="sortingOption" panelClass="red-select-panel">
<mat-option *ngFor="let option of sortingOptions" [value]="option">
@ -57,7 +57,7 @@
</div>
<div class="flex-1">
<redaction-initials-avatar [username]="user.name"
color="gray-red"
color="lightgray-red"
withName="true"
></redaction-initials-avatar>
</div>
@ -88,7 +88,7 @@
<div>
<redaction-simple-doughnut-chart [config]="projectsChartData"
[strokeWidth]="15"
[subtitle]="'Projects'"
[subtitle]="'project-listing.stats.charts.projects.label' | translate"
></redaction-simple-doughnut-chart>
<div class="project-stats-container">
@ -96,7 +96,7 @@
<mat-icon svgIcon="red:files"></mat-icon>
<div>
<div class="heading">{{totalPages}}</div>
<div>Analyzed pages</div>
<div translate="project-listing.stats.analyzed-pages.label"></div>
</div>
</div>
@ -104,7 +104,7 @@
<mat-icon svgIcon="red:user"></mat-icon>
<div>
<div class="heading">240</div>
<div>Total people</div>
<div translate="project-listing.stats.total-people.label"></div>
</div>
</div>
</div>
@ -112,7 +112,7 @@
<div>
<redaction-simple-doughnut-chart [config]="documentsChartData"
[strokeWidth]="15"
[subtitle]="'Total Documents'"
[subtitle]="'project-listing.stats.charts.total-documents.label' | translate"
></redaction-simple-doughnut-chart>
</div>
</div>

View File

@ -20,8 +20,8 @@ export class ProjectListingScreenComponent implements OnInit {
public projectsChartData: DoughnutChartConfig [] = [];
public documentsChartData: DoughnutChartConfig [] = [];
public sortingOptions: SortingOption[] = [
{ label: 'projects.sorting.recent.label', order: 'desc', column: 'projectDate' },
{ label: 'projects.sorting.alphabetically.label', order: 'asc', column: 'project.projectName' }
{ label: 'project-listing.sorting.recent.label', order: 'desc', column: 'projectDate' },
{ label: 'project-listing.sorting.alphabetically.label', order: 'asc', column: 'project.projectName' }
];
public sortingOption: SortingOption = this.sortingOptions[0];

View File

@ -11,7 +11,7 @@
<div translate="filters.due-date.label"></div>
<div translate="filters.document.label"></div>
</div>
<button (click)="fileInput.click()" color="warn" mat-flat-button
<button (click)="fileInput.click()" color="primary" mat-flat-button
translate="project-overview.upload-document.label"></button>
<input #fileInput (change)="uploadFiles($event.target.files)" class="file-upload-input" multiple="true"
type="file">
@ -120,7 +120,7 @@
<div class="owner flex-row mt-20">
<redaction-initials-avatar [username]="user.name"
size="large"
color="gray-red"
color="lightgray-red"
withName="true"
></redaction-initials-avatar>
</div>
@ -136,10 +136,10 @@
<redaction-initials-avatar [username]="username" size="large"></redaction-initials-avatar>
</div>
<div class="member">
<div class="oval large">+2</div>
<div class="oval large white-dark">+2</div>
</div>
<div class="member">
<div class="oval red large">+</div>
<div class="oval red-white large">+</div>
</div>
</div>
</div>

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

@ -133,7 +133,7 @@
"label": "Document"
}
},
"projects": {
"project-listing": {
"table-header": {
"title": {
"label": "{{length}} active projects"
@ -145,6 +145,22 @@
"label": "Recent"
}
},
"stats": {
"analyzed-pages": {
"label": "Analyzed pages"
},
"total-people": {
"label": "Total people"
},
"charts": {
"projects": {
"label": "Projects"
},
"total-documents": {
"label": "Total Documents"
}
}
},
"add-edit-dialog": {
"header-new": {
"label": "New Project"
@ -323,14 +339,72 @@
}
},
"file-preview": {
"annotated": {
"label": "Review Annotations"
"view-toggle": {
"label": "Redacted View"
},
"redacted": {
"label": "Preview Redaction"
"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"
}
},
"download-redacted": {
"label": "Download Redacted"
"tabs": {
"quick-navigation": {
"label": "Quick Navigation"
},
"annotations": {
"label": "Annotations"
},
"info": {
"label": "Info",
"assign-reviewer": {
"label": "Assign reviewer"
},
"added-on": {
"label": "Added on"
},
"added-by": {
"label": "Added by"
},
"last-modified-on": {
"label": "Last modified on"
}
}
},
"download": {
"label": "Download",
"dropdown": {
"original": {
"label": "Original"
},
"annotated": {
"label": "Annotated"
},
"redacted": {
"label": "Redacted"
}
}
}
},
"initials-avatar": {

View File

@ -0,0 +1,20 @@
@import "red-variables";
.mat-button, .mat-flat-button {
font-family: Inter, sans-serif !important;
font-weight: 400 !important;
border-radius: 25px !important;
.mat-button-wrapper {
display: flex;
align-items: center;
}
.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

@ -1,44 +1,62 @@
@import "red-variables";
.oval {
.oval, .square {
font-weight: 600;
display: flex;
justify-content: center;
align-items: center;
height: 24px;
width: 24px;
border-radius: 12px;
font-size: 10px;
border: 1px solid #E2E4E9;
letter-spacing: 0;
line-height: 12px;
text-align: center;
text-transform: uppercase;
font-family: Inter, sans-serif;
border: none;
&.large {
height: 32px;
width: 32px;
border-radius: 16px;
font-size: 13px;
}
&.gray-dark {
background-color: $grey-4;
border: none;
&.x-small {
height: 16px;
width: 16px;
font-size: 11px;
line-height: 14px;
}
&.gray-red {
&.lightgray-dark {
background-color: $grey-4;
}
&.lightgray-red {
background-color: $grey-4;
color: $red-1;
border: none;
}
&.darkgray-white {
background-color: $grey-1;
color: $white;
}
&.lightgray-white {
background-color: $grey-5;
color: $white;
}
&.red-white {
background-color: $red-1;
color: $white;
border: none;
}
&.white-dark {
border: 1px solid #E2E4E9;
}
}
.oval {
border-radius: 50%;
}
.stats-subtitle {

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

@ -1,17 +1,11 @@
@import "red-variables";
@import "red-mixins";
button {
font-family: Inter, sans-serif !important;
font-weight: 400 !important;
border-radius: 17px !important;
}
a {
color: $red-1;
color: $primary;
&:hover {
color: lighten($red-1, 10%)
color: lighten($primary, 10%)
}
cursor: pointer;
@ -57,3 +51,8 @@ a {
.clamp-2 {
@include line-clamp(2);
}
.primary {
color: $primary;
opacity: 1;
}

View File

@ -1,12 +1,17 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Inconsolata:wght@300;400;500;600;700&display=swap');
@import url("https://fonts.googleapis.com/icon?family=Material+Icons");
@import '~ngx-toastr/toastr';
@import "red-material-theme";
@import "red-page-layout";
@import "red-text-styles";
@import "red-dialog";
@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

@ -0,0 +1,23 @@
mat-slide-toggle {
display: flex !important;
flex-direction: row-reverse;
gap: 8px;
.mat-slide-toggle-bar {
height: 16px !important;
width: 30px !important;
border-radius: 16px !important;
}
.mat-slide-toggle-thumb-container {
top: 2px !important;
left: 2px !important;
height: 12px !important;
width: 12px !important;
}
.mat-slide-toggle-thumb {
height: 12px !important;
width: 12px !important;
}
}

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;