From aff65a11665846c0134d46ad46b5ba4df84b1bea Mon Sep 17 00:00:00 2001 From: Timo Bejan Date: Wed, 6 Oct 2021 15:01:50 +0300 Subject: [PATCH] fixed position - RED-2223 and csv backport RED-2496 --- .../src/app/modules/auth/auth.module.ts | 2 +- .../pdf-viewer/pdf-viewer.component.ts | 4 +- .../dossier-overview-screen.component.html | 7 ++ .../dossier-overview-screen.component.ts | 33 +++++- .../dossiers-listing-screen.component.ts | 2 +- .../file-preview-screen.component.ts | 2 +- .../modules/dossier/utils/pdf-viewer.utils.ts | 6 +- .../src/app/modules/icons/icons.module.ts | 1 + apps/red-ui/src/app/utils/csv-utils.ts | 30 +++++ apps/red-ui/src/assets/i18n/en.json | 3 +- apps/red-ui/src/assets/icons/general/csv.svg | 104 ++++++++++++++++++ libs/red-cache/src/lib/caches/cache-utils.ts | 7 +- package-lock.json | 0 13 files changed, 187 insertions(+), 14 deletions(-) create mode 100644 apps/red-ui/src/app/utils/csv-utils.ts create mode 100644 apps/red-ui/src/assets/icons/general/csv.svg delete mode 100644 package-lock.json diff --git a/apps/red-ui/src/app/modules/auth/auth.module.ts b/apps/red-ui/src/app/modules/auth/auth.module.ts index a4c4cd032..b4bbe3a24 100644 --- a/apps/red-ui/src/app/modules/auth/auth.module.ts +++ b/apps/red-ui/src/app/modules/auth/auth.module.ts @@ -20,7 +20,7 @@ function getKeycloakOptions(configService: ConfigService, baseUrl: string) { }, initOptions: { checkLoginIframe: false, - onLoad: 'login-required', + onLoad: 'check-sso', silentCheckSsoRedirectUri: environment.production ? window.location.origin + baseUrl + '/assets/oauth/silent-refresh.html' : null, diff --git a/apps/red-ui/src/app/modules/dossier/components/pdf-viewer/pdf-viewer.component.ts b/apps/red-ui/src/app/modules/dossier/components/pdf-viewer/pdf-viewer.component.ts index 8546b9aa4..7378b805a 100644 --- a/apps/red-ui/src/app/modules/dossier/components/pdf-viewer/pdf-viewer.component.ts +++ b/apps/red-ui/src/app/modules/dossier/components/pdf-viewer/pdf-viewer.component.ts @@ -297,7 +297,7 @@ export class PdfViewerComponent implements OnInit, OnChanges { } private _setSelectionMode(): void { - const textTool = ( this.instance.Core.Tools.TextTool) as TextTool; + const textTool = (this.instance.Core.Tools.TextTool) as TextTool; textTool.SELECTION_MODE = this._configService.values.SELECTION_MODE; } @@ -518,6 +518,7 @@ export class PdfViewerComponent implements OnInit, OnChanges { onClick: () => { const selectedQuads = this.instance.Core.documentViewer.getSelectedTextQuads(); const text = this.instance.Core.documentViewer.getSelectedText(); + console.log(selectedQuads); const mre = this._getManualRedactionEntry(selectedQuads, text, true); this.manualAnnotationRequested.emit( new ManualRedactionEntryWrapper(this.instance.Core.documentViewer.getSelectedTextQuads(), mre, 'REDACTION'), @@ -561,6 +562,7 @@ export class PdfViewerComponent implements OnInit, OnChanges { for (const key of Object.keys(quads)) { for (const quad of quads[key]) { const page = parseInt(key, 10); + console.log(quad); entry.positions.push(this.utils.toPosition(page, convertQuads ? this.utils.translateQuads(page, quad) : quad)); } } diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html index b1e2b5283..1f173e733 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html @@ -11,6 +11,13 @@ tooltipPosition="below" > + + imple this.calculateData(); - this.addSubscription = timer(0, 10 * 1000).subscribe(async () => { + this.addSubscription = timer(0, 20 * 1000).subscribe(async () => { await this._appStateService.reloadActiveDossierFilesIfNecessary(); this.calculateData(); }); @@ -239,6 +240,34 @@ export class DossierOverviewScreenComponent extends ListingComponent imple event.preventDefault(); } + exportFilesAsCSV() { + this.sortedDisplayedEntities$.pipe(take(1)).subscribe(entities => { + const fileName = this._dossiersService.activeDossier.dossierName + '.export.csv'; + saveAsCSV( + fileName, + entities, + [ + 'dossierId', + 'fileId', + 'filename', + 'primaryAttribute', + 'numberOfPages', + 'assignee', + 'status', + 'lastUpdated', + 'lastUploaded', + 'lastProcessed', + 'hasHints', + 'hasImages', + 'hasRedactions', + 'hasUpdates', + 'excluded', + ], + fsv => ({ ...fsv, assignee: this._userService.getNameForId(fsv.currentReviewer) }), + ); + }); + } + async uploadFiles(files: Files): Promise { await this._uploadFiles(convertFiles(files, this.currentDossier)); this._fileInput.nativeElement.value = null; diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/screen/dossiers-listing-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/screen/dossiers-listing-screen.component.ts index ae1cea4a8..24a17f1c4 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/screen/dossiers-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/screen/dossiers-listing-screen.component.ts @@ -81,7 +81,7 @@ export class DossiersListingScreenComponent ngOnInit(): void { this.calculateData(); - this.addSubscription = timer(0, 10000).subscribe(async () => { + this.addSubscription = timer(0, 20000).subscribe(async () => { await this._appStateService.loadAllDossiers(); this.calculateData(); }); diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts index 253349b2a..e4faf60bc 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts @@ -572,7 +572,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni } private _subscribeToFileUpdates(): void { - this.addSubscription = timer(0, 5000).subscribe(async () => this.appStateService.reloadActiveFile()); + this.addSubscription = timer(0, 10000).subscribe(async () => this.appStateService.reloadActiveFile()); this.addSubscription = this.appStateService.fileReanalysed$.subscribe(async (file: File) => { if (file.fileId === this.fileId) { await this._loadFileData(!this._reloadFileOnReanalysis); diff --git a/apps/red-ui/src/app/modules/dossier/utils/pdf-viewer.utils.ts b/apps/red-ui/src/app/modules/dossier/utils/pdf-viewer.utils.ts index 514c72398..e18e7b8d5 100644 --- a/apps/red-ui/src/app/modules/dossier/utils/pdf-viewer.utils.ts +++ b/apps/red-ui/src/app/modules/dossier/utils/pdf-viewer.utils.ts @@ -121,17 +121,17 @@ export class PdfViewerUtils { return translateQuads(page, rotation, quads); } - toPosition(page: number, selectedQuad: { x3: number; x4: number; y4: number; y2: number }): Rectangle { + toPosition(page: number, selectedQuad: { x1: number; x2: number; x3: number; x4: number; y4: number; y2: number }): Rectangle { const pageHeight = this._documentViewer.getPageHeight(page); const height = selectedQuad.y2 - selectedQuad.y4; return { page: page, topLeft: { - x: selectedQuad.x4, + x: Math.min(selectedQuad.x3, selectedQuad.x4, selectedQuad.x2, selectedQuad.x1), y: pageHeight - (selectedQuad.y4 + height), }, height: height, - width: selectedQuad.x3 - selectedQuad.x4, + width: Math.max(4, Math.abs(selectedQuad.x3 - selectedQuad.x4), Math.abs(selectedQuad.x3 - selectedQuad.x1)), }; } diff --git a/apps/red-ui/src/app/modules/icons/icons.module.ts b/apps/red-ui/src/app/modules/icons/icons.module.ts index 899cd4615..73a9cfcff 100644 --- a/apps/red-ui/src/app/modules/icons/icons.module.ts +++ b/apps/red-ui/src/app/modules/icons/icons.module.ts @@ -23,6 +23,7 @@ export class IconsModule { 'color-picker', 'comment', 'comment-fill', + 'csv', 'dictionary', 'double-chevron-right', 'enter', diff --git a/apps/red-ui/src/app/utils/csv-utils.ts b/apps/red-ui/src/app/utils/csv-utils.ts new file mode 100644 index 000000000..672960308 --- /dev/null +++ b/apps/red-ui/src/app/utils/csv-utils.ts @@ -0,0 +1,30 @@ +import { humanize } from '@iqser/common-ui'; +import { saveAs } from 'file-saver'; + +function toCSVContent(lines: any[], keys: string[]) { + return lines + .map(line => { + const escapedValues: any[] = []; + for (const key of keys) { + escapedValues.push('"' + (line[key] !== null && line[key] !== undefined ? `${line[key]}`.replace('"', '""') : '') + '"'); + } + + return escapedValues.join(','); + }) + .join('\n'); +} + +function camelCaseToSnakeCase(item: string) { + return item.replace(/[\w]([A-Z])/g, m => m[0] + '_' + m[1]).toLowerCase(); +} + +export function saveAsCSV(fileName: string, objects: readonly any[], fields: string[], mapper: (any) => any = (input: any) => input) { + const headerLine = fields.map(f => '"' + humanize(camelCaseToSnakeCase(f)) + '"').join(',') + '\n'; + const csvContent = toCSVContent(objects.map(mapper), fields); + + const blob = new Blob([headerLine + csvContent], { + type: 'text/csv;charset=utf-8', + }); + + saveAs(blob, fileName); +} diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 09f1c887e..20d466686 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -701,7 +701,8 @@ }, "header-actions": { "edit": "Edit Dossier", - "upload-document": "Upload Document" + "upload-document": "Upload Document", + "download-csv": "Download CSV File Report" }, "new-rule": { "toast": { diff --git a/apps/red-ui/src/assets/icons/general/csv.svg b/apps/red-ui/src/assets/icons/general/csv.svg new file mode 100644 index 000000000..7ad687795 --- /dev/null +++ b/apps/red-ui/src/assets/icons/general/csv.svg @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/red-cache/src/lib/caches/cache-utils.ts b/libs/red-cache/src/lib/caches/cache-utils.ts index 3f97633f2..9539093c2 100644 --- a/libs/red-cache/src/lib/caches/cache-utils.ts +++ b/libs/red-cache/src/lib/caches/cache-utils.ts @@ -7,17 +7,16 @@ export const DYNAMIC_CACHES = [ clearOnLogout: false, maxAge: 24 * 3600, maxSize: 1000, - methods: ['GET'] + methods: ['GET'], }, - { urls: ['/download/original'], name: 'files', maxAge: 3600 * 24 * 7, maxSize: 1000, clearOnLogout: true, - methods: ['GET'] - } + methods: ['GET'], + }, ]; export async function wipeCaches(logoutDependant: boolean = false) { diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index e69de29bb..000000000