diff --git a/apps/red-ui/src/app/app-routing.module.ts b/apps/red-ui/src/app/app-routing.module.ts
index 71b80cfc7..4ccfaae0d 100644
--- a/apps/red-ui/src/app/app-routing.module.ts
+++ b/apps/red-ui/src/app/app-routing.module.ts
@@ -1,9 +1,7 @@
import { AuthErrorComponent } from './components/auth-error/auth-error.component';
import { AuthGuard } from './modules/auth/auth.guard';
-import { PdfViewerScreenComponent } from './components/pdf-viewer-screen/pdf-viewer-screen.component';
import { CompositeRouteGuard } from './guards/composite-route.guard';
import { RedRoleGuard } from './modules/auth/red-role.guard';
-import { HtmlDebugScreenComponent } from './components/html-debug-screen/html-debug-screen.component';
import { BaseScreenComponent } from './components/base-screen/base-screen.component';
import { RouteReuseStrategy, RouterModule } from '@angular/router';
import { NgModule } from '@angular/core';
@@ -23,22 +21,6 @@ const routes = [
component: AuthErrorComponent,
canActivate: [AuthGuard]
},
- {
- path: 'pdf-preview/:projectId/:fileId',
- component: PdfViewerScreenComponent,
- canActivate: [CompositeRouteGuard],
- data: {
- routeGuards: [AuthGuard, RedRoleGuard]
- }
- },
- {
- path: 'html-debug/:projectId/:fileId',
- component: HtmlDebugScreenComponent,
- canActivate: [CompositeRouteGuard],
- data: {
- routeGuards: [AuthGuard, RedRoleGuard]
- }
- },
{
path: 'main/my-profile',
component: BaseScreenComponent,
diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts
index 639cdd333..daf5d79f8 100644
--- a/apps/red-ui/src/app/app.module.ts
+++ b/apps/red-ui/src/app/app.module.ts
@@ -22,8 +22,6 @@ import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/materia
import { ToastComponent } from './components/toast/toast.component';
import { HttpCacheInterceptor } from '@redaction/red-cache';
import { NotificationsComponent } from './components/notifications/notifications.component';
-import { PdfViewerScreenComponent } from './components/pdf-viewer-screen/pdf-viewer-screen.component';
-import { HtmlDebugScreenComponent } from './components/html-debug-screen/html-debug-screen.component';
import { KeycloakService } from 'keycloak-angular';
import { DownloadsListScreenComponent } from './components/downloads-list-screen/downloads-list-screen.component';
import { AppRoutingModule } from './app-routing.module';
@@ -49,7 +47,7 @@ function cleanupBaseUrl(baseUrl: string) {
}
}
-const screens = [BaseScreenComponent, PdfViewerScreenComponent, HtmlDebugScreenComponent, DownloadsListScreenComponent, UserProfileScreenComponent];
+const screens = [BaseScreenComponent, DownloadsListScreenComponent, UserProfileScreenComponent];
const components = [AppComponent, LogoComponent, AuthErrorComponent, ToastComponent, NotificationsComponent, ...screens];
diff --git a/apps/red-ui/src/app/components/html-debug-screen/html-debug-screen.component.html b/apps/red-ui/src/app/components/html-debug-screen/html-debug-screen.component.html
deleted file mode 100644
index 64c7852a3..000000000
--- a/apps/red-ui/src/app/components/html-debug-screen/html-debug-screen.component.html
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/apps/red-ui/src/app/components/html-debug-screen/html-debug-screen.component.scss b/apps/red-ui/src/app/components/html-debug-screen/html-debug-screen.component.scss
deleted file mode 100644
index ec70e8d52..000000000
--- a/apps/red-ui/src/app/components/html-debug-screen/html-debug-screen.component.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-section {
- height: calc(100vh - 40px);
- display: flex;
- flex-direction: column;
- align-items: center;
- padding: 20px;
-}
diff --git a/apps/red-ui/src/app/components/html-debug-screen/html-debug-screen.component.ts b/apps/red-ui/src/app/components/html-debug-screen/html-debug-screen.component.ts
deleted file mode 100644
index fbecf52a1..000000000
--- a/apps/red-ui/src/app/components/html-debug-screen/html-debug-screen.component.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import { ChangeDetectorRef, Component } from '@angular/core';
-import { ActivatedRoute } from '@angular/router';
-import { DebugControllerService, FileManagementControllerService } from '@redaction/red-ui-http';
-import { FileStatusWrapper } from '../../models/file/file-status.wrapper';
-import { mergeMap } from 'rxjs/operators';
-
-@Component({
- selector: 'redaction-html-debug-screen',
- templateUrl: './html-debug-screen.component.html',
- styleUrls: ['./html-debug-screen.component.scss']
-})
-export class HtmlDebugScreenComponent {
- private _fileId: string;
- private _projectId: string;
-
- htmlData: any;
- loading: boolean;
-
- constructor(
- private readonly _activatedRoute: ActivatedRoute,
- private readonly _changeDetectorRef: ChangeDetectorRef,
- private readonly _debugControllerService: DebugControllerService,
- private readonly _fileManagementControllerService: FileManagementControllerService
- ) {
- this._activatedRoute.params.subscribe((params) => {
- this._fileId = params.fileId;
- this._projectId = params.projectId;
- this._loadDebugHTML();
- });
- }
-
- private _loadDebugHTML() {
- this.loading = true;
- const fileStatus = new FileStatusWrapper(
- {
- projectId: this._projectId,
- fileId: this._fileId,
- lastProcessed: new Date().toISOString()
- },
- null
- );
-
- this._fileManagementControllerService
- .downloadAnnotatedFile(fileStatus.projectId, fileStatus.fileId, true, fileStatus.lastUploaded, 'body')
- .pipe(
- mergeMap((fileData) => {
- return this._debugControllerService.debugHtmlTablesForm(fileData, true);
- })
- )
- .subscribe((data) => {
- const reader = new FileReader();
- reader.onload = () => {
- this.htmlData = reader.result;
- this.loading = false;
- };
- reader.readAsText(data);
- });
- }
-}
diff --git a/apps/red-ui/src/app/components/pdf-viewer-screen/pdf-viewer-screen.component.html b/apps/red-ui/src/app/components/pdf-viewer-screen/pdf-viewer-screen.component.html
deleted file mode 100644
index 534e12c77..000000000
--- a/apps/red-ui/src/app/components/pdf-viewer-screen/pdf-viewer-screen.component.html
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/apps/red-ui/src/app/components/pdf-viewer-screen/pdf-viewer-screen.component.scss b/apps/red-ui/src/app/components/pdf-viewer-screen/pdf-viewer-screen.component.scss
deleted file mode 100644
index c5aa1aa0f..000000000
--- a/apps/red-ui/src/app/components/pdf-viewer-screen/pdf-viewer-screen.component.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-.viewer {
- width: 100vw;
- height: 100vh;
-}
diff --git a/apps/red-ui/src/app/components/pdf-viewer-screen/pdf-viewer-screen.component.ts b/apps/red-ui/src/app/components/pdf-viewer-screen/pdf-viewer-screen.component.ts
deleted file mode 100644
index 30b0521ad..000000000
--- a/apps/red-ui/src/app/components/pdf-viewer-screen/pdf-viewer-screen.component.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-import { ChangeDetectorRef, Component, ElementRef, Inject, OnInit, ViewChild } from '@angular/core';
-import WebViewer, { WebViewerInstance } from '@pdftron/webviewer';
-import { environment } from '../../../environments/environment';
-import { ActivatedRoute } from '@angular/router';
-import { FileStatusWrapper } from '../../models/file/file-status.wrapper';
-import { FileManagementControllerService } from '@redaction/red-ui-http';
-import { BASE_HREF } from '../../tokens';
-
-@Component({
- selector: 'redaction-pdf-viewer-screen',
- templateUrl: './pdf-viewer-screen.component.html',
- styleUrls: ['./pdf-viewer-screen.component.scss']
-})
-export class PdfViewerScreenComponent implements OnInit {
- private _instance: WebViewerInstance;
- @ViewChild('viewer', { static: true })
- private _viewer: ElementRef;
-
- private _fileId: string;
- private _projectId: string;
- private _fileData: any;
-
- constructor(
- @Inject(BASE_HREF) private readonly _baseHref: string,
- private readonly _activatedRoute: ActivatedRoute,
- private readonly _changeDetectorRef: ChangeDetectorRef,
- private readonly _fileManagementControllerService: FileManagementControllerService
- ) {
- this._activatedRoute.params.subscribe((params) => {
- this._fileId = params.fileId;
- this._projectId = params.projectId;
- this._loadFile();
- });
- }
-
- ngOnInit(): void {
- this._loadViewer();
- }
-
- private _loadViewer() {
- WebViewer(
- {
- licenseKey: environment.licenseKey ? atob(environment.licenseKey) : null,
- isReadOnly: true,
- path: this._baseHref + '/assets/wv-resources',
- css: this._baseHref + '/assets/pdftron/stylesheet.css'
- },
- this._viewer.nativeElement
- ).then((instance) => {
- this._instance = instance;
-
- instance.docViewer.on('documentLoaded', () => {
- this._changeDetectorRef.detectChanges();
- });
-
- if (this._fileData) {
- this._loadDocumentIntoViewer();
- }
- });
- }
-
- private _loadFile() {
- const fileStatus = new FileStatusWrapper(
- {
- projectId: this._projectId,
- fileId: this._fileId,
- lastProcessed: new Date().toISOString()
- },
- null
- );
-
- this._fileManagementControllerService
- .downloadAnnotatedFile(fileStatus.projectId, fileStatus.fileId, true, fileStatus.lastUploaded, 'body')
- .subscribe((data) => {
- this._fileData = data;
- this._loadDocumentIntoViewer();
- });
- }
-
- private _loadDocumentIntoViewer() {
- if (this._instance) {
- this._instance.loadDocument(this._fileData, {
- filename: 'document.pdf'
- });
- }
- }
-}
diff --git a/apps/red-ui/src/app/models/file/file-status.wrapper.ts b/apps/red-ui/src/app/models/file/file-status.wrapper.ts
index 74aea75e4..0fa149b9e 100644
--- a/apps/red-ui/src/app/models/file/file-status.wrapper.ts
+++ b/apps/red-ui/src/app/models/file/file-status.wrapper.ts
@@ -1,8 +1,27 @@
-import { FileStatus } from '@redaction/red-ui-http';
+import { FileAttributeConfig, FileStatus } from '@redaction/red-ui-http';
import { StatusSorter } from '../../utils/sorters/status-sorter';
export class FileStatusWrapper {
- constructor(public fileStatus: FileStatus, public reviewerName: string) {}
+ primaryAttribute: string;
+
+ searchField: string;
+
+ constructor(public fileStatus: FileStatus, public reviewerName: string, fileAttributesConfig?: FileAttributeConfig[]) {
+ this.searchField = fileStatus.filename;
+
+ if (fileAttributesConfig) {
+ const primary = fileAttributesConfig.find((c) => c.primaryAttribute);
+ if (primary && fileStatus.fileAttributes?.attributeIdToValue) {
+ this.primaryAttribute = fileStatus.fileAttributes?.attributeIdToValue[primary.id];
+ this.searchField += ' ' + this.primaryAttribute;
+ }
+
+ if (!this.primaryAttribute) {
+ // Fallback here
+ this.primaryAttribute = '-';
+ }
+ }
+ }
get analysisDuration() {
return this.fileStatus.analysisDuration;
@@ -52,6 +71,14 @@ export class FileStatusWrapper {
return this.fileStatus.filename;
}
+ get hasAnnotationComments() {
+ return this.fileStatus.hasAnnotationComments;
+ }
+
+ get ocrTime() {
+ return this.fileStatus.lastOCRTime;
+ }
+
get hasHints() {
return this.fileStatus.hasHints;
}
diff --git a/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.html
index 1aef2499d..e2418b5c2 100644
--- a/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.html
+++ b/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.html
@@ -158,24 +158,6 @@
tooltip="file-preview.download-original-file"
tooltipPosition="below"
>
-
-
+
+
+ {{ fileStatus.primaryAttribute }}
+
+
+
+
+
+ {{ fileStatus.ocrTime ? (fileStatus.ocrTime | date: 'mediumDate') : ('project-overview.no-ocr' | translate) }}
+
+
diff --git a/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.scss b/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.scss
index dd6c59430..a1719e9b1 100644
--- a/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.scss
+++ b/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.scss
@@ -121,3 +121,7 @@ cdk-virtual-scroll-viewport {
color: initial;
}
}
+
+.primary-attribute {
+ padding-top: 6px;
+}
diff --git a/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.ts b/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.ts
index 165fb0164..aa59ddc6f 100644
--- a/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.ts
+++ b/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.ts
@@ -34,7 +34,7 @@ import { OnAttach, OnDetach } from '../../../../utils/custom-route-reuse.strateg
styleUrls: ['./project-overview-screen.component.scss']
})
export class ProjectOverviewScreenComponent extends BaseListingComponent implements OnInit, OnDestroy, OnDetach, OnAttach {
- protected readonly _searchKey = 'filename';
+ protected readonly _searchKey = 'searchField';
protected readonly _selectionKey = 'fileId';
protected readonly _sortKey = 'project-overview';
@@ -42,7 +42,6 @@ export class ProjectOverviewScreenComponent extends BaseListingComponent p.projectId)).toPromise();
+
for (const projectId of Object.keys(fileData)) {
- this._processFiles(
- mappedProjects.find((p) => p.projectId === projectId),
- fileData[projectId],
- emitEvents
- );
+ const project = mappedProjects.find((p) => p.projectId === projectId);
+ const fileAttributesConfig = await this._fileAttributesService
+ .getFileAttributesConfiguration(project.ruleSetId)
+ .pipe(catchError(() => of({})))
+ .toPromise();
+
+ console.log(fileAttributesConfig);
+
+ this._processFiles(project, fileData[projectId], emitEvents, fileAttributesConfig);
}
this._appState.projects = mappedProjects;
@@ -266,7 +272,11 @@ export class AppStateService {
const oldProcessedDate = this.activeFile.lastProcessed;
const activeFile = await this._statusControllerService.getFileStatus(this.activeProjectId, this.activeFileId).toPromise();
- const activeFileWrapper = new FileStatusWrapper(activeFile, this._userService.getNameForId(activeFile.currentReviewer));
+ const activeFileWrapper = new FileStatusWrapper(
+ activeFile,
+ this._userService.getNameForId(activeFile.currentReviewer),
+ this._appState.activeFileAttributesConfig
+ );
this.activeProject.files = this.activeProject.files.map((file) => (file.fileId === activeFileWrapper.fileId ? activeFileWrapper : file));
await this.updateDictionaryVersion();
@@ -282,12 +292,17 @@ export class AppStateService {
if (!project) {
project = this.activeProject;
}
- const files = await this._statusControllerService.getProjectStatus(project.project.projectId).toPromise();
+ const files = await this._statusControllerService.getProjectStatus(project.projectId).toPromise();
- return this._processFiles(project, files, emitEvents);
+ const fileAttributesConfig = await this._fileAttributesService
+ .getFileAttributesConfiguration(project.ruleSetId)
+ .pipe(catchError(() => of({})))
+ .toPromise();
+
+ return this._processFiles(project, files, emitEvents, fileAttributesConfig);
}
- private _processFiles(project: ProjectWrapper, files: FileStatus[], emitEvents: boolean = true) {
+ private _processFiles(project: ProjectWrapper, files: FileStatus[], emitEvents: boolean = true, fileAttributesConfig: FileAttributesConfig) {
const oldFiles = [...project.files];
const fileStatusChangedEvent = [];
@@ -298,7 +313,11 @@ export class AppStateService {
for (const oldFile of oldFiles) {
if (oldFile.fileId === file.fileId) {
// emit when analysis count changed
- const fileStatusWrapper = new FileStatusWrapper(file, this._userService.getNameForId(file.currentReviewer));
+ const fileStatusWrapper = new FileStatusWrapper(
+ file,
+ this._userService.getNameForId(file.currentReviewer),
+ fileAttributesConfig?.fileAttributeConfigs
+ );
if (JSON.stringify(oldFile) !== JSON.stringify(fileStatusWrapper)) {
fileStatusChangedEvent.push(fileStatusWrapper);
}
@@ -311,12 +330,14 @@ export class AppStateService {
}
// emit for new file
if (!found) {
- const fsw = new FileStatusWrapper(file, this._userService.getNameForId(file.currentReviewer));
+ const fsw = new FileStatusWrapper(file, this._userService.getNameForId(file.currentReviewer), fileAttributesConfig?.fileAttributeConfigs);
fileStatusChangedEvent.push(fsw);
}
}
- project.files = files.map((f) => new FileStatusWrapper(f, this._userService.getNameForId(f.currentReviewer)));
+ project.files = files.map(
+ (f) => new FileStatusWrapper(f, this._userService.getNameForId(f.currentReviewer), fileAttributesConfig?.fileAttributeConfigs)
+ );
this._computeStats();
if (emitEvents) {
@@ -343,12 +364,6 @@ export class AppStateService {
this._router.navigate(['/main/projects']);
return;
}
- this._fileAttributesService
- .getFileAttributesConfiguration(this.getProjectById(projectId).ruleSetId)
- .toPromise()
- .then((data) => {
- this._appState.activeFileAttributesConfig = data.fileAttributeConfigs;
- });
}
activateFile(projectId: string, fileId: string) {
diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json
index be4efa650..78d5e9526 100644
--- a/apps/red-ui/src/assets/i18n/en.json
+++ b/apps/red-ui/src/assets/i18n/en.json
@@ -192,6 +192,7 @@
"collapse": "Hide Details"
},
"project-overview": {
+ "no-ocr": "No OCR",
"no-data": {
"title": "There are no documents yet.",
"action": "Upload Document"
diff --git a/libs/red-ui-http/src/lib/model/fileStatus.ts b/libs/red-ui-http/src/lib/model/fileStatus.ts
index 6b8569577..9e9b88431 100644
--- a/libs/red-ui-http/src/lib/model/fileStatus.ts
+++ b/libs/red-ui-http/src/lib/model/fileStatus.ts
@@ -48,6 +48,10 @@ export interface FileStatus {
* The file's name.
*/
filename?: string;
+ /**
+ * Shows if this file has comments on annotations.
+ */
+ hasAnnotationComments?: boolean;
/**
* Shows if any hints were found during the analysis.
*/
@@ -68,6 +72,10 @@ export interface FileStatus {
* Shows if there is any change between the previous and current analysis.
*/
hasUpdates?: boolean;
+ /**
+ * Shows if this file has been OCRed by us. Last Time of OCR.
+ */
+ lastOCRTime?: string;
/**
* Shows the last date of a successful analysis.
*/
@@ -109,31 +117,30 @@ export interface FileStatus {
*/
uploader?: string;
}
-
export namespace FileStatus {
export type StatusEnum =
| 'UNPROCESSED'
| 'REPROCESS'
- | 'FULLREPROCESS'
| 'PROCESSING'
- | 'OCR_PROCESSING'
| 'ERROR'
| 'UNASSIGNED'
| 'UNDER_REVIEW'
- | 'EXCLUDED'
| 'UNDER_APPROVAL'
- | 'APPROVED';
+ | 'APPROVED'
+ | 'FULLREPROCESS'
+ | 'OCR_PROCESSING'
+ | 'EXCLUDED';
export const StatusEnum = {
UNPROCESSED: 'UNPROCESSED' as StatusEnum,
- FULLREPROCESS: 'FULLREPROCESS' as StatusEnum,
REPROCESS: 'REPROCESS' as StatusEnum,
PROCESSING: 'PROCESSING' as StatusEnum,
- OCR_PROCESSING: 'OCR_PROCESSING' as StatusEnum,
ERROR: 'ERROR' as StatusEnum,
UNASSIGNED: 'UNASSIGNED' as StatusEnum,
UNDERREVIEW: 'UNDER_REVIEW' as StatusEnum,
UNDERAPPROVAL: 'UNDER_APPROVAL' as StatusEnum,
APPROVED: 'APPROVED' as StatusEnum,
+ FULLREPROCESS: 'FULLREPROCESS' as StatusEnum,
+ OCR_PROCESSING: 'OCR_PROCESSING' as StatusEnum,
EXCLUDED: 'EXCLUDED' as StatusEnum
};
}