From 6137d1c0d8643fdcdc1447f4f1099751dcfa9a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Fri, 23 Oct 2020 16:55:12 +0300 Subject: [PATCH 1/9] Removed duplicate flash/lightning icon --- apps/red-ui/src/app/icons/icons.module.ts | 2 +- .../project-listing-screen.component.html | 2 +- .../project-overview-screen.component.html | 2 +- .../project-overview-screen.component.ts | 43 ++++++++++--------- .../red-ui/src/assets/icons/general/flash.svg | 4 -- 5 files changed, 25 insertions(+), 28 deletions(-) delete mode 100644 apps/red-ui/src/assets/icons/general/flash.svg diff --git a/apps/red-ui/src/app/icons/icons.module.ts b/apps/red-ui/src/app/icons/icons.module.ts index cc91cb1a2..b492ecc2a 100644 --- a/apps/red-ui/src/app/icons/icons.module.ts +++ b/apps/red-ui/src/app/icons/icons.module.ts @@ -18,7 +18,7 @@ export class IconsModule { 'check', 'close', 'document', 'double-chevron-right', 'download', 'edit', 'error', 'folder', 'info', 'lightning', 'logout', 'menu', 'pages', 'plus', 'preview', 'refresh', 'report', 'secret', 'sort-asc', 'sort-desc', - 'status', 'trash', 'user', 'check-alt',"flash" + 'status', 'trash', 'user', 'check-alt', ]; for (const icon of icons) { diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html index b5c6bc238..71e3a2df3 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html +++ b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html @@ -74,7 +74,7 @@ {{pw.project.date | date:'mediumDate'}}
- + {{pw.project.dueDate | date:'mediumDate'}}
diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html index bd97db018..0f6b49a6c 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html @@ -151,7 +151,7 @@ {{ appStateService.activeProject.project.date | date:'d MMM. yyyy' }}
- + {{appStateService.activeProject.project.dueDate | date:'mediumDate'}}
diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts index 7c792c1f2..59efd5162 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts @@ -1,17 +1,17 @@ -import {Component, OnDestroy, OnInit} from '@angular/core'; -import {ActivatedRoute, Router} from '@angular/router'; -import {FileStatus, ReanalysisControllerService, StatusControllerService} from '@redaction/red-ui-http'; -import {NotificationService} from '../../notification/notification.service'; -import {AppStateService} from '../../state/app-state.service'; -import {FileDropOverlayService} from '../../upload/file-drop/service/file-drop-overlay.service'; -import {FileUploadModel} from '../../upload/model/file-upload.model'; -import {FileUploadService} from '../../upload/file-upload.service'; -import {UploadStatusOverlayService} from '../../upload/upload-status-dialog/service/upload-status-overlay.service'; -import {UserService} from '../../user/user.service'; -import {SortingOption} from '../../utils/types'; -import {DoughnutChartConfig} from '../../components/simple-doughnut-chart/simple-doughnut-chart.component'; -import {groupBy} from '../../utils/functions'; -import {DialogService} from '../../dialogs/dialog.service'; +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { FileStatus, ReanalysisControllerService, StatusControllerService } from '@redaction/red-ui-http'; +import { NotificationService } from '../../notification/notification.service'; +import { AppStateService } from '../../state/app-state.service'; +import { FileDropOverlayService } from '../../upload/file-drop/service/file-drop-overlay.service'; +import { FileUploadModel } from '../../upload/model/file-upload.model'; +import { FileUploadService } from '../../upload/file-upload.service'; +import { UploadStatusOverlayService } from '../../upload/upload-status-dialog/service/upload-status-overlay.service'; +import { UserService } from '../../user/user.service'; +import { SortingOption } from '../../utils/types'; +import { DoughnutChartConfig } from '../../components/simple-doughnut-chart/simple-doughnut-chart.component'; +import { groupBy } from '../../utils/functions'; +import { DialogService } from '../../dialogs/dialog.service'; @Component({ @@ -23,11 +23,11 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { private _selectedFileIds: string[] = []; public sortingOptions: SortingOption[] = [ - {label: 'project-overview.sorting.recent.label', order: 'desc', column: 'lastUpdated'}, - {label: 'project-overview.sorting.oldest.label', order: 'asc', column: 'lastUpdated'}, - {label: 'project-overview.sorting.alphabetically.label', order: 'asc', column: 'filename'}, - {label: 'project-overview.sorting.number-of-pages.label', order: 'asc', column: 'numberOfPages'}, - {label: 'project-overview.sorting.number-of-analyses.label', order: 'desc', column: 'numberOfAnalyses'} + { label: 'project-overview.sorting.recent.label', order: 'desc', column: 'lastUpdated' }, + { label: 'project-overview.sorting.oldest.label', order: 'asc', column: 'lastUpdated' }, + { label: 'project-overview.sorting.alphabetically.label', order: 'asc', column: 'filename' }, + { label: 'project-overview.sorting.number-of-pages.label', order: 'asc', column: 'numberOfPages' }, + { label: 'project-overview.sorting.number-of-analyses.label', order: 'desc', column: 'numberOfAnalyses' } ]; public sortingOption: SortingOption = this.sortingOptions[0]; public documentsChartData: DoughnutChartConfig[] = []; @@ -95,7 +95,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { const groups = groupBy(this.appStateService.activeProject.files, 'status'); this.documentsChartData = []; for (const key of Object.keys(groups)) { - this.documentsChartData.push({value: groups[key].length, color: key, label: key}); + this.documentsChartData.push({ value: groups[key].length, color: key, label: key }); } } @@ -118,7 +118,8 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { } public areAllFilesSelected() { - return this._selectedFileIds.length === this.appStateService.activeProject.files.length; + return this.appStateService.activeProject.files.length !== 0 && + this._selectedFileIds.length === this.appStateService.activeProject.files.length; } public isFileSelected(file: FileStatus) { diff --git a/apps/red-ui/src/assets/icons/general/flash.svg b/apps/red-ui/src/assets/icons/general/flash.svg deleted file mode 100644 index eb030e0ed..000000000 --- a/apps/red-ui/src/assets/icons/general/flash.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - From c0edce517a873985a3c73431feb483906666241d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Fri, 23 Oct 2020 20:59:40 +0300 Subject: [PATCH 2/9] Working arrow navigation --- .../base-screen/base-screen.component.scss | 25 ++++ .../file-preview-screen.component.html | 4 +- .../file-preview-screen.component.scss | 4 + .../file-preview-screen.component.ts | 119 ++++++++++++++---- .../src/assets/styles/red-page-layout.scss | 22 ---- 5 files changed, 129 insertions(+), 45 deletions(-) diff --git a/apps/red-ui/src/app/screens/base-screen/base-screen.component.scss b/apps/red-ui/src/app/screens/base-screen/base-screen.component.scss index e69de29bb..647662bef 100644 --- a/apps/red-ui/src/app/screens/base-screen/base-screen.component.scss +++ b/apps/red-ui/src/app/screens/base-screen/base-screen.component.scss @@ -0,0 +1,25 @@ +@import "../../../assets/styles/red-variables"; +@import "../../../assets/styles/red-mixins"; + +.breadcrumbs-container { + display: flex; + gap: 8px; + + .breadcrumb { + text-decoration: none; + color: $accent; + font-weight: 600; + width: fit-content; + white-space: nowrap; + + &:last-child { + color: $primary; + @include line-clamp(1); + } + + .mat-icon { + vertical-align: middle; + width: 6px; + } + } +} 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 432656490..1c391c203 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 @@ -126,7 +126,7 @@
-
+
-
+
{{page}} diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss index 5c054bb30..f2701b6c9 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss @@ -69,6 +69,10 @@ redaction-pdf-viewer { width: 0; background: transparent; /* Chrome/Safari/Webkit */ } + + &.activePanel { + background-color: #FAFAFA; + } } .pages { 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 6bd5c696c..5e23a6307 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 @@ -1,19 +1,19 @@ -import {ChangeDetectorRef, Component, ElementRef, HostListener, NgZone, OnInit, ViewChild} from '@angular/core'; -import {ActivatedRoute, Router} from '@angular/router'; -import {ManualRedactionEntry, ReanalysisControllerService} from '@redaction/red-ui-http'; -import {AppStateService} from '../../../state/app-state.service'; -import {Annotations, WebViewerInstance} from '@pdftron/webviewer'; -import {PdfViewerComponent} from '../pdf-viewer/pdf-viewer.component'; -import {AnnotationUtils} from '../../../utils/annotation-utils'; -import {UserService} from '../../../user/user.service'; -import {debounce} from '../../../utils/debounce'; +import { ChangeDetectorRef, Component, ElementRef, HostListener, NgZone, OnInit, ViewChild } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { ManualRedactionEntry, ReanalysisControllerService } from '@redaction/red-ui-http'; +import { AppStateService } from '../../../state/app-state.service'; +import { Annotations, WebViewerInstance } from '@pdftron/webviewer'; +import { PdfViewerComponent } from '../pdf-viewer/pdf-viewer.component'; +import { AnnotationUtils } from '../../../utils/annotation-utils'; +import { UserService } from '../../../user/user.service'; +import { debounce } from '../../../utils/debounce'; import scrollIntoView from 'scroll-into-view-if-needed'; -import {AnnotationFilters} from '../../../utils/types'; -import {FiltersService} from '../service/filters.service'; -import {FileDownloadService} from '../service/file-download.service'; -import {saveAs} from 'file-saver'; -import {FileType} from '../model/file-type'; -import {DialogService} from '../../../dialogs/dialog.service'; +import { AnnotationFilters } from '../../../utils/types'; +import { FiltersService } from '../service/filters.service'; +import { FileDownloadService } from '../service/file-download.service'; +import { saveAs } from 'file-saver'; +import { FileType } from '../model/file-type'; +import { DialogService } from '../../../dialogs/dialog.service'; @Component({ selector: 'redaction-file-preview-screen', @@ -37,6 +37,7 @@ export class FilePreviewScreenComponent implements OnInit { public selectedAnnotation: Annotations.Annotation; public filters: AnnotationFilters; public expandedFilters: AnnotationFilters = {hint: false}; + public pagesPanelActive = false; private instance: WebViewerInstance; constructor( @@ -167,7 +168,6 @@ export class FilePreviewScreenComponent implements OnInit { } - get activeViewerPage() { return this.instance.docViewer.getCurrentPage(); } @@ -274,8 +274,35 @@ export class FilePreviewScreenComponent implements OnInit { handleKeyEvent($event: KeyboardEvent) { $event.preventDefault(); - if (!this.selectedAnnotation) { - this.selectAnnotation(this.displayedAnnotations[this.displayedPages[0]].annotations[0]); + if ($event.key === 'ArrowLeft' || $event.key === 'ArrowRight') { + this.pagesPanelActive = !this.pagesPanelActive; + this._changeDetectorRef.detectChanges(); + return; + } + + if (!this.pagesPanelActive) { + this._navigateAnnotations($event); + } else { + this._navigatePages($event); + } + } + + private _navigateAnnotations($event: KeyboardEvent) { + if (!this.selectedAnnotation || this.activeViewerPage !== this.selectedAnnotation.getPageNumber()) { + const pageIdx = this.displayedPages.indexOf(this.activeViewerPage); + if (pageIdx !== -1) { // Displayed page has annotations + this.selectAnnotation(this.displayedAnnotations[this.activeViewerPage].annotations[0]); + } else { // Displayed page doesn't have annotations + if ($event.key === 'ArrowDown') { + const nextPage = this._nextPageWithAnnotations(); + this.selectAnnotation(this.displayedAnnotations[nextPage].annotations[0]); + } else { + const prevPage = this._prevPageWithAnnotations(); + const prevPageAnnotations = this.displayedAnnotations[prevPage].annotations; + this.selectAnnotation(prevPageAnnotations[prevPageAnnotations.length - 1]); + } + } + } else { const page = this.selectedAnnotation.getPageNumber(); const pageIdx = this.displayedPages.indexOf(page); @@ -289,9 +316,7 @@ export class FilePreviewScreenComponent implements OnInit { const nextPageAnnotations = this.displayedAnnotations[this.displayedPages[pageIdx + 1]].annotations; this.selectAnnotation(nextPageAnnotations[0]); } - } - - if ($event.key === 'ArrowUp') { + } else { if (idx !== 0) { // If not first item in page this.selectAnnotation(annotationsOnPage[idx - 1]); } else if (pageIdx) { // If not first page @@ -302,6 +327,58 @@ export class FilePreviewScreenComponent implements OnInit { } } + private _navigatePages($event: KeyboardEvent) { + const pageIdx = this.displayedPages.indexOf(this.activeViewerPage); + + if ($event.key === 'ArrowDown') { + if (pageIdx !== -1) { // If active page has annotations + if (pageIdx !== this.displayedPages.length - 1) { + this.selectPage(this.displayedPages[pageIdx + 1]); + } + } else { // If active page doesn't have annotations + const nextPage = this._nextPageWithAnnotations(); + if (nextPage) { + this.selectPage(nextPage); + } + } + } else { + if (pageIdx !== -1) { // If active page has annotations + if (pageIdx !== 0) { + this.selectPage(this.displayedPages[pageIdx - 1]); + } + } else { // If active page doesn't have annotations + const prevPage = this._prevPageWithAnnotations(); + if (prevPage) { + this.selectPage(prevPage); + } + } + } + } + + private _nextPageWithAnnotations() { + let idx = 0; + for (const page of this.displayedPages) { + if (page > this.activeViewerPage) { + break; + } + ++idx; + } + return idx < this.displayedPages.length ? this.displayedPages[idx] : null; + } + + private _prevPageWithAnnotations() { + let idx = this.displayedPages.length - 1; + for (const page of this.displayedPages.reverse()) { + if (page < this.activeViewerPage) { + this.selectPage(this.displayedPages[idx]); + this._scrollAnnotations(); + break; + } + --idx; + } + return idx >= 0 ? this.displayedPages[idx] : null; + } + viewerPageChanged($event: number) { this._scrollViews(); this._changeDetectorRef.detectChanges(); diff --git a/apps/red-ui/src/assets/styles/red-page-layout.scss b/apps/red-ui/src/assets/styles/red-page-layout.scss index e003252a3..93dd96f44 100644 --- a/apps/red-ui/src/assets/styles/red-page-layout.scss +++ b/apps/red-ui/src/assets/styles/red-page-layout.scss @@ -1,5 +1,4 @@ @import "red-variables"; -@import "red-mixins"; html, body { margin: 0; @@ -172,27 +171,6 @@ html, body { } } - .breadcrumbs-container { - display: flex; - gap: 8px; - - .breadcrumb { - text-decoration: none; - color: $accent; - font-weight: 600; - - &:last-child { - color: $primary; - @include line-clamp(1); - } - - .mat-icon { - vertical-align: middle; - width: 6px; - } - } - } - .divider { height: 1px; opacity: 0.15; From 40067ff6e6cf3b7414bbffdc32aa5de70c5a3d90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Sat, 24 Oct 2020 00:13:26 +0300 Subject: [PATCH 3/9] Fixes --- .../file-preview-screen.component.html | 8 ++++++-- .../file-preview-screen.component.ts | 6 ++---- .../screens/file/pdf-viewer/pdf-viewer.component.ts | 10 +++++----- 3 files changed, 13 insertions(+), 11 deletions(-) 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 1c391c203..92fe4d1f8 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 @@ -126,7 +126,9 @@
-
+
-
+
{{page}} 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 5e23a6307..58371212b 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 @@ -24,6 +24,7 @@ export class FilePreviewScreenComponent implements OnInit { private projectId: string; private _activeViewer: 'ANNOTATED' | 'REDACTED' = 'ANNOTATED'; + private instance: WebViewerInstance; @ViewChild(PdfViewerComponent) private _viewerComponent: PdfViewerComponent; @ViewChild('annotations') private _annotationsElement: ElementRef; @@ -37,8 +38,7 @@ export class FilePreviewScreenComponent implements OnInit { public selectedAnnotation: Annotations.Annotation; public filters: AnnotationFilters; public expandedFilters: AnnotationFilters = {hint: false}; - public pagesPanelActive = false; - private instance: WebViewerInstance; + public pagesPanelActive = true; constructor( public readonly appStateService: AppStateService, @@ -272,8 +272,6 @@ export class FilePreviewScreenComponent implements OnInit { @HostListener('window:keyup', ['$event']) handleKeyEvent($event: KeyboardEvent) { - $event.preventDefault(); - if ($event.key === 'ArrowLeft' || $event.key === 'ArrowRight') { this.pagesPanelActive = !this.pagesPanelActive; this._changeDetectorRef.detectChanges(); diff --git a/apps/red-ui/src/app/screens/file/pdf-viewer/pdf-viewer.component.ts b/apps/red-ui/src/app/screens/file/pdf-viewer/pdf-viewer.component.ts index 4d948502f..981d94634 100644 --- a/apps/red-ui/src/app/screens/file/pdf-viewer/pdf-viewer.component.ts +++ b/apps/red-ui/src/app/screens/file/pdf-viewer/pdf-viewer.component.ts @@ -184,14 +184,14 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { public selectAnnotation(annotation: Annotations.Annotation) { this.instance.annotManager.deselectAllAnnotations(); this.instance.annotManager.selectAnnotation(annotation); - this.instance.docViewer.displayPageLocation( - annotation.getPageNumber(), - 0, - annotation.getY() - 100); + this.navigateToPage(annotation.getPageNumber()); } public navigateToPage(pageNumber: number) { - this.instance.docViewer.displayPageLocation(pageNumber, 0, 0); + const activePage = this.instance.docViewer.getCurrentPage(); + if (activePage !== pageNumber) { + this.instance.docViewer.displayPageLocation(pageNumber, 0, 0); + } } From b78f8493d95d507979e1c87a64e7cdc198ee3bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Sat, 24 Oct 2020 01:12:37 +0300 Subject: [PATCH 4/9] Some input styling --- .../add-edit-project-dialog.component.html | 2 +- .../manual-redaction-dialog.component.html | 16 ++-- .../file-preview-screen.component.scss | 8 +- apps/red-ui/src/assets/i18n/en.json | 2 +- .../src/assets/styles/red-checkbox.scss | 16 ++++ apps/red-ui/src/assets/styles/red-dialog.scss | 4 + apps/red-ui/src/assets/styles/red-input.scss | 80 +++++++++++-------- apps/red-ui/src/assets/styles/red-menu.scss | 21 +---- apps/red-ui/src/assets/styles/red-mixins.scss | 9 +++ 9 files changed, 87 insertions(+), 71 deletions(-) diff --git a/apps/red-ui/src/app/dialogs/add-edit-project-dialog/add-edit-project-dialog.component.html b/apps/red-ui/src/app/dialogs/add-edit-project-dialog/add-edit-project-dialog.component.html index a197c3a66..bf66f92d2 100644 --- a/apps/red-ui/src/app/dialogs/add-edit-project-dialog/add-edit-project-dialog.component.html +++ b/apps/red-ui/src/app/dialogs/add-edit-project-dialog/add-edit-project-dialog.component.html @@ -17,7 +17,7 @@
- + {{'project-listing.add-edit-dialog.form.due-date.label' | translate}} diff --git a/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-redaction-dialog.component.html b/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-redaction-dialog.component.html index 0be3a13ba..6bee578f6 100644 --- a/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-redaction-dialog.component.html +++ b/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-redaction-dialog.component.html @@ -7,11 +7,11 @@
-
-
-
+ +
+
+ {{ addRedactionRequest.value }}
@@ -23,17 +23,17 @@
- - {{'manual-redaction.dialog.content.dictionary.label' | translate}} +
+ {{dictionary.type}} - +
- {{'manual-redaction.dialog.content.dictionary.add.label' | translate}}
diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss index f2701b6c9..491fa77d4 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss @@ -62,13 +62,7 @@ redaction-pdf-viewer { .pages, .annotations { overflow-y: scroll; - - scrollbar-width: none; /* Firefox */ - -ms-overflow-style: none; /* IE 10+ */ - &::-webkit-scrollbar { - width: 0; - background: transparent; /* Chrome/Safari/Webkit */ - } + @include no-scroll-bar(); &.activePanel { background-color: #FAFAFA; diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 9b3ea77ee..39b152da1 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -52,7 +52,7 @@ }, "content": { "text": { - "label": "Selected Text: {{value}}" + "label": "Selected text:" }, "dictionary": { "add": { diff --git a/apps/red-ui/src/assets/styles/red-checkbox.scss b/apps/red-ui/src/assets/styles/red-checkbox.scss index 919495916..febf4d51a 100644 --- a/apps/red-ui/src/assets/styles/red-checkbox.scss +++ b/apps/red-ui/src/assets/styles/red-checkbox.scss @@ -10,3 +10,19 @@ width: 18px; height: 18px; } + +.mat-checkbox-layout { + .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; + } +} diff --git a/apps/red-ui/src/assets/styles/red-dialog.scss b/apps/red-ui/src/assets/styles/red-dialog.scss index 16ca57741..51388cc44 100644 --- a/apps/red-ui/src/assets/styles/red-dialog.scss +++ b/apps/red-ui/src/assets/styles/red-dialog.scss @@ -1,3 +1,7 @@ +.mat-dialog-container { + border-radius: 8px; +} + .dialog { position: relative; min-height: 80px; diff --git a/apps/red-ui/src/assets/styles/red-input.scss b/apps/red-ui/src/assets/styles/red-input.scss index bb5b4ec4b..e60713169 100644 --- a/apps/red-ui/src/assets/styles/red-input.scss +++ b/apps/red-ui/src/assets/styles/red-input.scss @@ -1,53 +1,63 @@ @import "red-variables"; +@import "red-mixins"; .red-input-group { - display: flex; flex-direction: column; - margin-top: 5px; - margin-bottom: 8px; + margin-top: 13px; - label { - height: 14px; - opacity: 0.6; + &:first-child { + margin-top: 0; + } + + input, textarea, mat-select { + box-sizing: border-box; + width: 322px; + padding-left: 11px; + padding-right: 11px; + border: 1px solid $grey-5; + font-family: Inter, sans-serif; font-size: 11px; - font-weight: 500; - letter-spacing: 0; line-height: 14px; - margin-bottom: 5px; + background-color: #FFFFFF; + border-radius: 8px; + outline: none; + margin-top: 3px; + min-height: 34px; + + &:focus { + border-color: $grey-1; + } + } + + mat-select { + width: 220px; + + .mat-select-trigger { + height: 32px; + } + + .mat-select-value { + vertical-align: middle; + } } textarea { resize: none; - box-sizing: border-box; - padding-left: 11px; - padding-right: 11px; - width: 300px; - border: 1px solid $grey-3; - opacity: 0.4; - border-radius: 2px; - background-color: #FFFFFF; - outline: none; - - &:focus { - border-color: $grey-1; - } + padding-top: 7px; + padding-bottom: 7px; + @include no-scroll-bar(); } - input { - box-sizing: border-box; - padding-left: 11px; - padding-right: 11px; - height: 34px; - width: 300px; - border: 1px solid $grey-3; - opacity: 0.4; - border-radius: 2px; - background-color: #FFFFFF; - outline: none; + label { + opacity: 0.7; + font-size: 11px; + letter-spacing: 0; + line-height: 14px; + margin-bottom: 2px; - &:focus { - border-color: $grey-1; + &.mat-checkbox-layout { + opacity: 1; } } } diff --git a/apps/red-ui/src/assets/styles/red-menu.scss b/apps/red-ui/src/assets/styles/red-menu.scss index 5b10ac247..14d760557 100644 --- a/apps/red-ui/src/assets/styles/red-menu.scss +++ b/apps/red-ui/src/assets/styles/red-menu.scss @@ -11,7 +11,8 @@ color: $accent; .arrow-wrapper { - width: 24px; + width: 16px; + margin-right: 8px; text-align: center; mat-icon { @@ -24,23 +25,5 @@ &.padding-left { padding-left: 64px; } - - .mat-checkbox-layout { - margin-left: 4px; - - .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; - } - } } } diff --git a/apps/red-ui/src/assets/styles/red-mixins.scss b/apps/red-ui/src/assets/styles/red-mixins.scss index 317437d89..fb3975951 100644 --- a/apps/red-ui/src/assets/styles/red-mixins.scss +++ b/apps/red-ui/src/assets/styles/red-mixins.scss @@ -8,3 +8,12 @@ text-overflow: ellipsis; white-space: nowrap; } + +@mixin no-scroll-bar { + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE 10+ */ + &::-webkit-scrollbar { + width: 0; + background: transparent; /* Chrome/Safari/Webkit */ + } +} From f80639def10dab3bbd0cf887334fabe26c4d0aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Tue, 27 Oct 2020 02:23:53 +0200 Subject: [PATCH 5/9] Redo tables layout with grid --- .../project-listing-screen.component.html | 119 ++++++++-------- .../project-listing-screen.component.scss | 18 +-- .../project-overview-screen.component.html | 127 ++++++++++-------- .../project-overview-screen.component.scss | 37 +++-- apps/red-ui/src/assets/styles/red-tables.scss | 92 ++++++++----- 5 files changed, 214 insertions(+), 179 deletions(-) diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html index 71e3a2df3..1f6a98d34 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html +++ b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html @@ -31,7 +31,7 @@
- {{'project-listing.table-header.title.label'| translate:{length: appStateService.allProjects?.length || 0} }} + {{'project-listing.table-header.title.label'| translate:{ length: appStateService.allProjects?.length || 0 } }}
@@ -45,70 +45,75 @@
-
-
-
-
-
+
+
+ +
+
+ +
+
+ +
-
+
-
-
-
- {{pw.project.projectName}} -
-
-
- - {{documentCount(pw)}}
-
- - {{userCount(pw)}}
-
- - {{pw.project.date | date:'mediumDate'}} +
+
+
+ {{pw.project.projectName}}
-
- - {{pw.project.dueDate | date:'mediumDate'}} +
+
+ + {{documentCount(pw)}}
+
+ + {{userCount(pw)}}
+
+ + {{pw.project.date | date:'mediumDate'}} +
+
+ + {{pw.project.dueDate | date:'mediumDate'}} +
+
+
+
+ +
+
+ + +
+ + +
-
- -
-
- -
-
- - - - - - -
+
diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.scss b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.scss index a15eff02b..e5fb4b227 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.scss +++ b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.scss @@ -11,19 +11,15 @@ .left-container { width: calc(100vw - #{$right-container-width} - 130px); - .table-item { - &:hover { - .status { - display: none; - } - } - - .stats-subtitle { - margin-top: 6px; - } + .grid-container { + grid-template-columns: 2fr 1fr auto; } - .status, .action-buttons { + .stats-subtitle { + margin-top: 6px; + } + + .status-container { width: 160px; } } diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html index 0f6b49a6c..1ad9a2d5f 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html @@ -51,75 +51,92 @@
+
+ +
-
-
-
-
+
+ +
+ +
- - + +
-
-
-
-
-
- -
- -
- {{ fileStatus.filename }} +
+
-
- {{ fileStatus.added | date:'d MMM. yyyy, hh:mm a' }} +
+
-
- - +
+
-
- -
+
-
- -
+
+
+
+ +
+ {{ fileStatus.filename }} +
+ +
+ {{ fileStatus.added | date:'d MMM. yyyy, hh:mm a' }} +
+ +
+ + +
+ +
+ +
+ +
+ + +
+ + + + +
+
-
- - - -
diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.scss b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.scss index 8d4b215bf..c0b41e96d 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.scss +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.scss @@ -4,10 +4,6 @@ display: none; } -.min-width { - min-width: 60px; -} - .select-all-container { display: flex; gap: 16px; @@ -18,14 +14,16 @@ } } +.pr-0 { + padding-right: 0 !important; +} + .select-oval { width: 20px; height: 20px; border-radius: 50%; border: 1px solid $grey-5; background-color: $white; - padding: 0; - margin-left: 16px; cursor: pointer; &.active { @@ -37,25 +35,20 @@ } } -.table-item { - .needs-work { - display: flex; - flex-direction: row; - gap: 4px; - } +.grid-container { + grid-template-columns: auto 3fr 2fr 1fr 2fr auto; - .status-container { - display: flex; - justify-content: flex-end; - } - - &:hover { - .assigned-to, .status-container { - display: none; + .table-item { + .table-item-title { + line-height: 80px; } - .action-buttons { - margin-left: 32px; + .needs-work { + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + gap: 4px; } } } diff --git a/apps/red-ui/src/assets/styles/red-tables.scss b/apps/red-ui/src/assets/styles/red-tables.scss index f331982d7..908a86093 100644 --- a/apps/red-ui/src/assets/styles/red-tables.scss +++ b/apps/red-ui/src/assets/styles/red-tables.scss @@ -16,59 +16,83 @@ } } -.table-col-names { - display: flex; - text-transform: uppercase; - border-bottom: 1px solid rgba(226, 228, 233, 0.9); - align-items: center; +.grid-container { + display: grid; + position: relative; - > div { - padding: 8px 16px; + .no-data { + grid-column: 1/-1; + } + + .table-col-name { font-weight: 600; display: flex; + gap: 8px; + padding: 8px 16px; + border-bottom: 1px solid rgba(226, 228, 233, 0.9); align-items: center; - gap: 6px; - } + text-transform: uppercase; - .sort-arrows-container { - mat-icon { - display: block; - width: 6px; - height: 11px; + .sort-arrows-container { + mat-icon { + display: block; + width: 6px; + height: 11px; + } } } -} -.table-item { - display: flex; - align-items: center; - height: 80px; - border-bottom: 1px solid rgba(226, 228, 233, 0.9); + .table-item { + display: contents; - > div { - padding: 0 16px; - } + > div { + display: flex; + flex-direction: column; + justify-content: center; + height: 100%; + width: 100%; + position: relative; + box-sizing: border-box; + } - .table-item-title { - font-weight: 600; - @include line-clamp(1); - } + .table-item-title { + font-weight: 600; + @include line-clamp(1); + } - .action-buttons { - display: none; - } + > div { + height: 80px; + border-bottom: 1px solid rgba(226, 228, 233, 0.9); + padding: 0 16px; + } - &:hover { - background-color: #F9FAFB; .action-buttons { - display: flex; + position: absolute; + display: none; + right: 0; + top: 0; + height: 100%; + width: fit-content; + flex-direction: row; align-items: center; - justify-content: flex-end; + padding-left: 100px; + padding-right: 8px; + background: linear-gradient(to right, rgba(244, 245, 247, 0) 0%, #F4F5F7 35%); mat-icon { width: 14px; } } + + &:hover { + > div { + background-color: #F9FAFB; + } + + .action-buttons { + display: flex; + } + } } } From 205fe574223106537fc0e2e41b9f359552d18e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Tue, 27 Oct 2020 02:49:41 +0200 Subject: [PATCH 6/9] Project status bar using real data --- .../status-bar/status-bar.component.html | 2 +- .../status-bar/status-bar.component.scss | 18 ++++++------- .../project-listing-screen.component.html | 2 +- .../project-listing-screen.component.ts | 26 +++++++++++++------ .../src/assets/styles/red-page-layout.scss | 16 ------------ 5 files changed, 29 insertions(+), 35 deletions(-) diff --git a/apps/red-ui/src/app/components/status-bar/status-bar.component.html b/apps/red-ui/src/app/components/status-bar/status-bar.component.html index c9a84a7b7..37013bbd0 100644 --- a/apps/red-ui/src/app/components/status-bar/status-bar.component.html +++ b/apps/red-ui/src/app/components/status-bar/status-bar.component.html @@ -1,5 +1,5 @@
-
+
{{ rect.label }}
diff --git a/apps/red-ui/src/app/components/status-bar/status-bar.component.scss b/apps/red-ui/src/app/components/status-bar/status-bar.component.scss index 8acab4c5a..66ec22018 100644 --- a/apps/red-ui/src/app/components/status-bar/status-bar.component.scss +++ b/apps/red-ui/src/app/components/status-bar/status-bar.component.scss @@ -39,39 +39,39 @@ .rectangle { height: 4px; - &.unassigned { + &.UNASSIGNED { background-color: $grey-5; } - &.under-review { + &.UNDER_REVIEW { background-color: $yellow-1; } - &.under-approval { + &.UNDER_APPROVAL { background-color: $red-1; } - &.approved { + &.APPROVED { background-color: $blue-2; } - &.submitted { + &.SUBMITTED { background-color: $blue-3; } - &.efsa { + &.EFSA { background-color: $blue-4; } - &.finished { + &.FINISHED { background-color: $green-2; } - &.active { + &.ACTIVE { background-color: $primary; } - &.archived { + &.ARCHIVED { background-color: rgba($red-1, 0.1); } } diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html index 1f6a98d34..006c960e3 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html +++ b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.html @@ -92,7 +92,7 @@
diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts index 9d2351002..df592011b 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts +++ b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts @@ -1,11 +1,11 @@ -import {Component, OnInit} from '@angular/core'; -import {Project} from '@redaction/red-ui-http'; -import {AppStateService, ProjectWrapper} from '../../state/app-state.service'; -import {UserService} from '../../user/user.service'; -import {DoughnutChartConfig} from '../../components/simple-doughnut-chart/simple-doughnut-chart.component'; -import {SortingOption} from '../../utils/types'; -import {groupBy} from '../../utils/functions'; -import {DialogService} from '../../dialogs/dialog.service'; +import { Component, OnInit } from '@angular/core'; +import { Project } from '@redaction/red-ui-http'; +import { AppStateService, ProjectWrapper } from '../../state/app-state.service'; +import { UserService } from '../../user/user.service'; +import { DoughnutChartConfig } from '../../components/simple-doughnut-chart/simple-doughnut-chart.component'; +import { SortingOption } from '../../utils/types'; +import { groupBy } from '../../utils/functions'; +import { DialogService } from '../../dialogs/dialog.service'; @Component({ selector: 'redaction-project-listing-screen', @@ -99,4 +99,14 @@ export class ProjectListingScreenComponent implements OnInit { public openAssignProjectOwnerDialog($event: MouseEvent, project: Project) { this._dialogService.openAssignProjectMembersAndOwnerDialog($event, project); } + + public getProjectStatusConfig(pw: ProjectWrapper) { + const obj = pw.files.reduce((acc, file) => { + const status = file.status; + acc[status]++ || (acc[status] = 1); + return acc; + }, {}) + + return Object.keys(obj).map(status => ({ length: obj[status], color: status })); + } } diff --git a/apps/red-ui/src/assets/styles/red-page-layout.scss b/apps/red-ui/src/assets/styles/red-page-layout.scss index 93dd96f44..5137d1761 100644 --- a/apps/red-ui/src/assets/styles/red-page-layout.scss +++ b/apps/red-ui/src/assets/styles/red-page-layout.scss @@ -88,22 +88,6 @@ html, body { flex: 2; } -.flex-3 { - flex: 3; -} - -.flex-4 { - flex: 4; -} - -.flex-5 { - flex: 5; -} - -.flex-6 { - flex: 6; -} - .mt-5 { margin-top: 5px; } From 56c1147d5fa3f6d441e9fa07abaf609083d974b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Tue, 27 Oct 2020 03:23:35 +0200 Subject: [PATCH 7/9] Avatar initials color depending on role --- .../initials-avatar.component.html | 2 +- .../initials-avatar.component.ts | 35 +++++++++++++++---- .../base-screen/base-screen.component.html | 2 +- .../project-listing-screen.component.html | 3 +- .../project-listing-screen.component.ts | 6 +--- .../project-overview-screen.component.html | 9 +++-- .../project-overview-screen.component.ts | 16 ++------- 7 files changed, 38 insertions(+), 35 deletions(-) diff --git a/apps/red-ui/src/app/common/initials-avatar/initials-avatar.component.html b/apps/red-ui/src/app/common/initials-avatar/initials-avatar.component.html index 98decd5c8..0e4717459 100644 --- a/apps/red-ui/src/app/common/initials-avatar/initials-avatar.component.html +++ b/apps/red-ui/src/app/common/initials-avatar/initials-avatar.component.html @@ -1,4 +1,4 @@
-
{{initials}}
+
{{initials}}
{{username || ('initials-avatar.unassigned.label' | translate)}}
diff --git a/apps/red-ui/src/app/common/initials-avatar/initials-avatar.component.ts b/apps/red-ui/src/app/common/initials-avatar/initials-avatar.component.ts index 6c65d0a68..e748b81c3 100644 --- a/apps/red-ui/src/app/common/initials-avatar/initials-avatar.component.ts +++ b/apps/red-ui/src/app/common/initials-avatar/initials-avatar.component.ts @@ -1,16 +1,18 @@ -import {Component, Input, OnInit} from '@angular/core'; +import { Component, Input, OnChanges, OnInit } from '@angular/core'; +import { UserService } from '../../user/user.service'; +import { User } from '@redaction/red-ui-http'; @Component({ selector: 'redaction-initials-avatar', templateUrl: './initials-avatar.component.html', styleUrls: ['./initials-avatar.component.scss'] }) -export class InitialsAvatarComponent implements OnInit { +export class InitialsAvatarComponent implements OnInit, OnChanges { @Input() - public username: string; + public userId: string; @Input() - public color = 'lightgray-dark'; + public color = 'lightgray'; @Input() public size: 'small' | 'large' = 'small'; @@ -18,21 +20,40 @@ export class InitialsAvatarComponent implements OnInit { @Input() public withName = false; - constructor() { + public _user: User; + + constructor(private readonly _userService: UserService) { } ngOnInit(): void { } + ngOnChanges(): void { + this._user = this._userService.getUserById(this.userId); + } + + public get username(): string { + return this._userService.getName(this._user); + } + public get initials(): string { - if (!this.username) { + if (!this._user) { return '?' } - return this.username + return this._userService.getName(this._user) .split(' ') + .filter(value => value !== ' ') .filter((value, idx) => idx < 2) .map((str) => str[0]) .join(''); } + + public get colorClass() { + if (this.color.includes('-')) { + return this.color; + } + const textColor = !this._user || !this._userService.isManager(this._user) ? 'dark' : 'red'; + return `${this.color}-${textColor}` + } } diff --git a/apps/red-ui/src/app/screens/base-screen/base-screen.component.html b/apps/red-ui/src/app/screens/base-screen/base-screen.component.html index da5a7c2f3..3070fa98e 100644 --- a/apps/red-ui/src/app/screens/base-screen/base-screen.component.html +++ b/apps/red-ui/src/app/screens/base-screen/base-screen.component.html @@ -40,7 +40,7 @@
-
diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts index df592011b..cdcb496e8 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts +++ b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts @@ -68,10 +68,6 @@ export class ProjectListingScreenComponent implements OnInit { return this.appStateService.allProjects.length - this.activeProjects; } - public getOwnerName(pw: ProjectWrapper) { - return this._userService.getNameForId(pw.project.ownerId); - } - public documentCount(project: ProjectWrapper) { return project.files.length; } @@ -107,6 +103,6 @@ export class ProjectListingScreenComponent implements OnInit { return acc; }, {}) - return Object.keys(obj).map(status => ({ length: obj[status], color: status })); + return Object.keys(obj).sort().map(status => ({ length: obj[status], color: status })); } } diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html index 1ad9a2d5f..0a9356f9b 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html @@ -108,7 +108,7 @@
@@ -178,9 +178,8 @@
-
@@ -192,8 +191,8 @@
-
- +
+
+{{overflowCount}}
diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts index 59efd5162..5cfd2cdbe 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts @@ -69,20 +69,12 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { return this._userService.user; } - public get members() { - return this.activeProject.memberIds.map(m => this._userService.getName(this._userService.getUserById(m))); - } - public get displayMembers() { - return this.members.slice(0, 6); + return this.activeProject.memberIds.slice(0, 6); } public get overflowCount() { - return this.members.length > 6 ? this.members.length - 6 : 0; - } - - public get ownerName() { - return this._userService.getNameForId(this.activeProject.ownerId); + return this.activeProject.memberIds.length > 6 ? this.activeProject.memberIds.length - 6 : 0; } private _getFileStatus() { @@ -190,10 +182,6 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy { return fileStatus === 'PROCESSING' || fileStatus === 'REVIEWED' || true; } - public getFileOwnerUsername(fileStatus: FileStatus) { - return this._userService.getNameForId(fileStatus.currentReviewer); - } - public toggleSortByAddedOn() { const sortedByRecent: boolean = (this.sortingOption === this.sortingOptions[0]); this.sortingOption = sortedByRecent ? this.sortingOptions[1] : this.sortingOptions[0]; From 2a6859b5847fa1fed5d09a80512291f28263beed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Tue, 27 Oct 2020 04:02:15 +0200 Subject: [PATCH 8/9] Some arrow navigation fixes --- apps/red-ui/src/app/dialogs/dialog.service.ts | 111 +++++++++++------- .../file-preview-screen.component.html | 8 +- .../file-preview-screen.component.scss | 1 + .../file-preview-screen.component.ts | 31 +++-- 4 files changed, 93 insertions(+), 58 deletions(-) diff --git a/apps/red-ui/src/app/dialogs/dialog.service.ts b/apps/red-ui/src/app/dialogs/dialog.service.ts index 14629083d..be912d86c 100644 --- a/apps/red-ui/src/app/dialogs/dialog.service.ts +++ b/apps/red-ui/src/app/dialogs/dialog.service.ts @@ -1,6 +1,6 @@ -import {Injectable} from '@angular/core'; -import {FileDetailsDialogComponent} from './file-details-dialog/file-details-dialog.component'; -import {MatDialog} from '@angular/material/dialog'; +import { Injectable } from '@angular/core'; +import { FileDetailsDialogComponent } from './file-details-dialog/file-details-dialog.component'; +import { MatDialog, MatDialogRef } from '@angular/material/dialog'; import { FileStatus, FileUploadControllerService, @@ -8,15 +8,15 @@ import { ManualRedactionEntry, Project } from '@redaction/red-ui-http'; -import {ConfirmationDialogComponent} from '../common/confirmation-dialog/confirmation-dialog.component'; -import {NotificationService, NotificationType} from '../notification/notification.service'; -import {TranslateService} from '@ngx-translate/core'; -import {AppStateService, ProjectWrapper} from '../state/app-state.service'; -import {AddEditProjectDialogComponent} from './add-edit-project-dialog/add-edit-project-dialog.component'; -import {AssignOwnerDialogComponent} from './assign-owner-dialog/assign-owner-dialog.component'; -import {ProjectDetailsDialogComponent} from './project-details-dialog/project-details-dialog.component'; -import {ManualRedactionDialogComponent} from './manual-redaction-dialog/manual-redaction-dialog.component'; -import {Annotations} from '@pdftron/webviewer'; +import { ConfirmationDialogComponent } from '../common/confirmation-dialog/confirmation-dialog.component'; +import { NotificationService, NotificationType } from '../notification/notification.service'; +import { TranslateService } from '@ngx-translate/core'; +import { AppStateService, ProjectWrapper } from '../state/app-state.service'; +import { AddEditProjectDialogComponent } from './add-edit-project-dialog/add-edit-project-dialog.component'; +import { AssignOwnerDialogComponent } from './assign-owner-dialog/assign-owner-dialog.component'; +import { ProjectDetailsDialogComponent } from './project-details-dialog/project-details-dialog.component'; +import { ManualRedactionDialogComponent } from './manual-redaction-dialog/manual-redaction-dialog.component'; +import { Annotations } from '@pdftron/webviewer'; const dialogConfig = { width: '600px', @@ -38,17 +38,19 @@ export class DialogService { } - public openFileDetailsDialog($event: MouseEvent, file: FileStatus) { + public openFileDetailsDialog($event: MouseEvent, file: FileStatus): MatDialogRef { $event.stopPropagation(); - this._dialog.open(FileDetailsDialogComponent, { + return this._dialog.open(FileDetailsDialogComponent, { ...dialogConfig, data: file }); } - public openDeleteFileDialog($event: MouseEvent, projectId: string, fileId: string, cb?: Function) { + public openDeleteFileDialog($event: MouseEvent, projectId: string, fileId: string, cb?: Function): MatDialogRef { $event.stopPropagation(); - this._dialog.open(ConfirmationDialogComponent, dialogConfig).afterClosed().subscribe(result => { + const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig); + + ref.afterClosed().subscribe(result => { if (result) { const file = this._appStateService.getFileById(projectId, fileId); this._fileUploadControllerService.deleteFile(file.projectId, file.fileId).subscribe(async () => { @@ -62,28 +64,34 @@ export class DialogService { }); } }); + + return ref; } - public openManualRedactionDialog($event: ManualRedactionEntry, cb?: Function) { - this._dialog.open(ManualRedactionDialogComponent, { + public openManualRedactionDialog($event: ManualRedactionEntry, cb?: Function): MatDialogRef { + const ref = this._dialog.open(ManualRedactionDialogComponent, { ...dialogConfig, autoFocus: true, data: $event - }).afterClosed().subscribe(result => { + }); + + ref.afterClosed().subscribe(result => { if (cb) { cb(result); } }); + + return ref; } - public acceptSuggestionAnnotation($event: MouseEvent, annotation: Annotations.Annotation, projectId: string, fileId: string) { + public acceptSuggestionAnnotation($event: MouseEvent, annotation: Annotations.Annotation, projectId: string, fileId: string): MatDialogRef { $event.stopPropagation(); const parts = annotation.Id.split(':'); const annotationId = parts[parts.length - 1]; - this._dialog.open(ConfirmationDialogComponent, dialogConfig) - .afterClosed().subscribe(result => { + const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig); + ref.afterClosed().subscribe(result => { if (result) { this._manualRedactionControllerService.approveRequest(projectId, fileId, annotationId).subscribe(() => { this._notificationService.showToastNotification(this._translateService.instant('manual-redaction.confirm-annotation.success.label'), null, NotificationType.SUCCESS); @@ -92,18 +100,22 @@ export class DialogService { }); } }); + + return ref; } - public suggestRemoveAnnotation($event: MouseEvent, annotation: Annotations.Annotation, projectId: string, fileId: string) { + public suggestRemoveAnnotation($event: MouseEvent, annotation: Annotations.Annotation, projectId: string, fileId: string): MatDialogRef { $event.stopPropagation(); const parts = annotation.Id.split(':'); const annotationId = parts[parts.length - 1]; - this._dialog.open(ConfirmationDialogComponent, { + const ref = this._dialog.open(ConfirmationDialogComponent, { width: '400px', maxWidth: '90vw' - }).afterClosed().subscribe(result => { + }); + + ref.afterClosed().subscribe(result => { if (result) { this._manualRedactionControllerService.undo(projectId, fileId, annotationId).subscribe(ok => { this._notificationService.showToastNotification(this._translateService.instant('manual-redaction.remove-annotation.success.label'), null, NotificationType.SUCCESS); @@ -113,63 +125,74 @@ export class DialogService { } }); + return ref; } - public openEditProjectDialog($event: MouseEvent, project: Project) { + public openEditProjectDialog($event: MouseEvent, project: Project): MatDialogRef { $event.stopPropagation(); - this._dialog.open(AddEditProjectDialogComponent, { + return this._dialog.open(AddEditProjectDialogComponent, { ...dialogConfig, autoFocus: true, data: project }); } - public openDeleteProjectDialog($event: MouseEvent, project: Project, cb?: Function) { + public openDeleteProjectDialog($event: MouseEvent, project: Project, cb?: Function): MatDialogRef { $event.stopPropagation(); - this._dialog.open(ConfirmationDialogComponent, dialogConfig) - .afterClosed().subscribe(async result => { + const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig); + ref.afterClosed().subscribe(async result => { if (result) { await this._appStateService.deleteProject(project); if (cb) cb(); } }); + return ref; } - public openAssignProjectMembersAndOwnerDialog($event: MouseEvent, project: Project, cb?: Function) { + public openAssignProjectMembersAndOwnerDialog($event: MouseEvent, project: Project, cb?: Function): MatDialogRef { $event?.stopPropagation(); - this._dialog.open(AssignOwnerDialogComponent, { + const ref = this._dialog.open(AssignOwnerDialogComponent, { ...dialogConfig, - data: {type: 'project', project: project} - }).afterClosed().subscribe(result => { + data: { type: 'project', project: project } + }); + ref.afterClosed().subscribe(result => { if (result && cb) cb(); }); + return ref; } - public openAssignFileOwnerDialog($event: MouseEvent, file: FileStatus, cb?: Function) { + public openAssignFileOwnerDialog($event: MouseEvent, file: FileStatus, cb?: Function): MatDialogRef { $event.stopPropagation(); - this._dialog.open(AssignOwnerDialogComponent, { + const ref = this._dialog.open(AssignOwnerDialogComponent, { ...dialogConfig, - data: {type: 'file', file: file} - }).afterClosed().subscribe(() => { + data: { type: 'file', file: file } + }); + + ref.afterClosed().subscribe(() => { if (cb) cb(); }); + + return ref; } - public openProjectDetailsDialog($event: MouseEvent, project: ProjectWrapper) { + public openProjectDetailsDialog($event: MouseEvent, project: ProjectWrapper): MatDialogRef { $event.stopPropagation(); - this._dialog.open(ProjectDetailsDialogComponent, { + return this._dialog.open(ProjectDetailsDialogComponent, { ...dialogConfig, data: project }); } - public openAddProjectDialog(cb?: Function): void { - this._dialog.open(AddEditProjectDialogComponent, { + public openAddProjectDialog(cb?: Function): MatDialogRef { + const ref = this._dialog.open(AddEditProjectDialogComponent, { ...dialogConfig, autoFocus: true - }).afterClosed().subscribe(result => { + }); + + ref.afterClosed().subscribe(result => { if (result && cb) cb(); }); - } + return ref; + } } 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 92fe4d1f8..e792e566b 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 @@ -127,7 +127,9 @@
diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss index 491fa77d4..07cda4c1f 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss @@ -63,6 +63,7 @@ redaction-pdf-viewer { .pages, .annotations { overflow-y: scroll; @include no-scroll-bar(); + outline: none; &.activePanel { background-color: #FAFAFA; 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 58371212b..651ef114e 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 @@ -14,6 +14,7 @@ import { FileDownloadService } from '../service/file-download.service'; import { saveAs } from 'file-saver'; import { FileType } from '../model/file-type'; import { DialogService } from '../../../dialogs/dialog.service'; +import { MatDialogRef, MatDialogState } from '@angular/material/dialog'; @Component({ selector: 'redaction-file-preview-screen', @@ -25,6 +26,7 @@ export class FilePreviewScreenComponent implements OnInit { private projectId: string; private _activeViewer: 'ANNOTATED' | 'REDACTED' = 'ANNOTATED'; private instance: WebViewerInstance; + private _dialogRef: MatDialogRef; @ViewChild(PdfViewerComponent) private _viewerComponent: PdfViewerComponent; @ViewChild('annotations') private _annotationsElement: ElementRef; @@ -37,7 +39,7 @@ export class FilePreviewScreenComponent implements OnInit { public displayedAnnotations: { [key: number]: { annotations: Annotations.Annotation[] } } = {}; public selectedAnnotation: Annotations.Annotation; public filters: AnnotationFilters; - public expandedFilters: AnnotationFilters = {hint: false}; + public expandedFilters: AnnotationFilters = { hint: false }; public pagesPanelActive = true; constructor( @@ -84,11 +86,11 @@ export class FilePreviewScreenComponent implements OnInit { localStorage.clear(); this._reloadFiles(); this.appStateService.fileStatusChanged.subscribe((fileStatus) => { - if(fileStatus.fileId === this.fileId) { + if (fileStatus.fileId === this.fileId) { console.log(fileStatus); this._reloadFiles(); } - }) + }); } private _reloadFiles() { @@ -103,7 +105,7 @@ export class FilePreviewScreenComponent implements OnInit { } public openFileDetailsDialog($event: MouseEvent) { - this._dialogService.openFileDetailsDialog($event, this.appStateService.activeFile); + this._dialogRef = this._dialogService.openFileDetailsDialog($event, this.appStateService.activeFile); } public reanalyseFile($event: MouseEvent) { @@ -114,17 +116,16 @@ export class FilePreviewScreenComponent implements OnInit { } public openDeleteFileDialog($event: MouseEvent) { - this._dialogService.openDeleteFileDialog($event, this.projectId, this.fileId, () => { + this._dialogRef = this._dialogService.openDeleteFileDialog($event, this.projectId, this.fileId, () => { this._router.navigate([`/ui/projects/${this.projectId}`]); }); } public openAssignFileOwnerDialog($event: MouseEvent) { const file = this.appStateService.getFileById(this.projectId, this.fileId); - this._dialogService.openAssignFileOwnerDialog($event, file); + this._dialogRef = this._dialogService.openAssignFileOwnerDialog($event, file); } - public get activeViewer() { return this.instance; } @@ -162,7 +163,7 @@ export class FilePreviewScreenComponent implements OnInit { public openManualRedactionDialog($event: ManualRedactionEntry) { this.ngZone.run(() => { - this._dialogService.openManualRedactionDialog($event, () => { + this._dialogRef = this._dialogService.openManualRedactionDialog($event, () => { }); }); @@ -212,13 +213,13 @@ export class FilePreviewScreenComponent implements OnInit { public acceptSuggestionAnnotation($event: MouseEvent, annotation: Annotations.Annotation) { this.ngZone.run(() => { - this._dialogService.acceptSuggestionAnnotation($event, annotation, this.projectId, this.fileId); + this._dialogRef = this._dialogService.acceptSuggestionAnnotation($event, annotation, this.projectId, this.fileId); }); } public suggestRemoveAnnotation($event: MouseEvent, annotation: Annotations.Annotation) { this.ngZone.run(() => { - this._dialogService.suggestRemoveAnnotation($event, annotation, this.projectId, this.fileId); + this._dialogRef = this._dialogService.suggestRemoveAnnotation($event, annotation, this.projectId, this.fileId); }); } @@ -272,6 +273,12 @@ export class FilePreviewScreenComponent implements OnInit { @HostListener('window:keyup', ['$event']) handleKeyEvent($event: KeyboardEvent) { + const keyArray = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']; + + if (!keyArray.includes($event.key) || this._dialogRef?.getState() === MatDialogState.OPEN) { + return; + } + if ($event.key === 'ArrowLeft' || $event.key === 'ArrowRight') { this.pagesPanelActive = !this.pagesPanelActive; this._changeDetectorRef.detectChanges(); @@ -391,9 +398,9 @@ export class FilePreviewScreenComponent implements OnInit { // handle comments annotations.forEach(a => { a['comments'] = a['Mi'] ? a['Mi'].map(m => { - return {value: m.eC} + return { value: m.eC }; }) : []; - }) + }); AnnotationUtils.addAnnotations(this.annotations, annotations); this.applyFilters(); From e8993da266e9d0fe4eb98b3546b00887aab2f602 Mon Sep 17 00:00:00 2001 From: Timo Bejan Date: Tue, 27 Oct 2020 15:40:18 +0200 Subject: [PATCH 9/9] fixed lint errors --- .../project-listing-screen.component.ts | 24 +++++++++++-------- .../red-ui/src/app/state/app-state.service.ts | 6 ++--- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts index cdcb496e8..29d82bae9 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts +++ b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts @@ -1,11 +1,11 @@ -import { Component, OnInit } from '@angular/core'; -import { Project } from '@redaction/red-ui-http'; -import { AppStateService, ProjectWrapper } from '../../state/app-state.service'; -import { UserService } from '../../user/user.service'; -import { DoughnutChartConfig } from '../../components/simple-doughnut-chart/simple-doughnut-chart.component'; -import { SortingOption } from '../../utils/types'; -import { groupBy } from '../../utils/functions'; -import { DialogService } from '../../dialogs/dialog.service'; +import {Component, OnInit} from '@angular/core'; +import {Project} from '@redaction/red-ui-http'; +import {AppStateService, ProjectWrapper} from '../../state/app-state.service'; +import {UserService} from '../../user/user.service'; +import {DoughnutChartConfig} from '../../components/simple-doughnut-chart/simple-doughnut-chart.component'; +import {SortingOption} from '../../utils/types'; +import {groupBy} from '../../utils/functions'; +import {DialogService} from '../../dialogs/dialog.service'; @Component({ selector: 'redaction-project-listing-screen', @@ -99,10 +99,14 @@ export class ProjectListingScreenComponent implements OnInit { public getProjectStatusConfig(pw: ProjectWrapper) { const obj = pw.files.reduce((acc, file) => { const status = file.status; - acc[status]++ || (acc[status] = 1); + if (!acc[status]) { + acc[status] = 1; + } else { + acc[status]++; + } return acc; }, {}) - return Object.keys(obj).sort().map(status => ({ length: obj[status], color: status })); + return Object.keys(obj).sort().map(status => ({length: obj[status], color: status})); } } diff --git a/apps/red-ui/src/app/state/app-state.service.ts b/apps/red-ui/src/app/state/app-state.service.ts index 92a90e2b8..5a7c7b17b 100644 --- a/apps/red-ui/src/app/state/app-state.service.ts +++ b/apps/red-ui/src/app/state/app-state.service.ts @@ -128,7 +128,7 @@ export class AppStateService { const projects = await this._projectControllerService.getProjects().toPromise(); if (projects) { - let mappedProjects = projects.map(p => { + const mappedProjects = projects.map(p => { return new ProjectWrapper(p, this._getExistingFiles(p)); }); @@ -150,9 +150,9 @@ export class AppStateService { const files = await this._statusControllerService.getProjectStatus(project.project.projectId).toPromise(); const oldFiles = [...project.files]; - for (let file of files) { + for (const file of files) { let found = false; - for (let oldFile of oldFiles) { + for (const oldFile of oldFiles) { if (oldFile.fileId === file.fileId) { // emit when analysis count changed if (oldFile.numberOfAnalyses !== file.numberOfAnalyses) {