fixed position - RED-2223 and csv backport RED-2496

This commit is contained in:
Timo Bejan 2021-10-06 15:01:50 +03:00
parent 367878e2d0
commit aff65a1166
13 changed files with 187 additions and 14 deletions

View File

@ -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,

View File

@ -297,7 +297,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
}
private _setSelectionMode(): void {
const textTool = (<unknown> this.instance.Core.Tools.TextTool) as TextTool;
const textTool = (<unknown>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));
}
}

View File

@ -11,6 +11,13 @@
tooltipPosition="below"
></redaction-file-download-btn>
<iqser-circle-button
(action)="exportFilesAsCSV()"
[tooltip]="'dossier-overview.header-actions.download-csv' | translate"
icon="red:csv"
tooltipPosition="below"
></iqser-circle-button>
<iqser-circle-button
(action)="reanalyseDossier()"
*ngIf="permissionsService.displayReanalyseBtn(currentDossier) && analysisForced"

View File

@ -23,7 +23,7 @@ import { DossierDetailsComponent } from '../components/dossier-details/dossier-d
import { File } from '@models/file/file';
import { UserService } from '@services/user.service';
import { timer } from 'rxjs';
import { tap } from 'rxjs/operators';
import { take, tap } from 'rxjs/operators';
import { convertFiles, Files, handleFileDrop } from '@utils/index';
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
import {
@ -55,6 +55,7 @@ import { DossiersService } from '@services/entity-services/dossiers.service';
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
import { LongPressEvent } from '@shared/directives/long-press.directive';
import { UserPreferenceService } from '@services/user-preference.service';
import { saveAsCSV } from '../../../../../utils/csv-utils';
@Component({
templateUrl: './dossier-overview-screen.component.html',
@ -154,7 +155,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> 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<File> 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<void> {
await this._uploadFiles(convertFiles(files, this.currentDossier));
this._fileInput.nativeElement.value = null;

View File

@ -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();
});

View File

@ -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);

View File

@ -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)),
};
}

View File

@ -23,6 +23,7 @@ export class IconsModule {
'color-picker',
'comment',
'comment-fill',
'csv',
'dictionary',
'double-chevron-right',
'enter',

View File

@ -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);
}

View File

@ -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": {

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<g>
<path d="M499.677,426.489c4.428,0,8.017-3.589,8.017-8.017V84.977c0-2.1-0.862-4.183-2.347-5.668l-76.96-76.96
C426.899,0.863,424.818,0,422.716,0H106.324C92.473,0,81.205,11.268,81.205,25.119v9.086H12.261
c-6.987,0-10.615,8.738-5.669,13.685l62.741,62.741L6.592,173.371c-4.946,4.947-1.319,13.685,5.669,13.685h68.944v299.825
c0,13.851,11.268,25.119,25.119,25.119h376.251c13.851,0,25.119-11.268,25.119-25.119v-34.205c0-4.427-3.588-8.017-8.017-8.017
c-4.428,0-8.017,3.589-8.017,8.017v34.205c0,5.01-4.076,9.086-9.086,9.086H106.324c-5.01,0-9.086-4.076-9.086-9.086V187.056
h51.841c4.428,0,8.017-3.589,8.017-8.017s-3.588-8.017-8.017-8.017H31.615l54.724-54.724c3.131-3.131,3.131-8.207,0-11.337
L31.615,50.238h348.88v120.785H183.284c-4.428,0-8.017,3.589-8.017,8.017s3.588,8.017,8.017,8.017h205.228
c4.428,0,8.017-3.589,8.017-8.017V42.221c0-4.427-3.588-8.017-8.017-8.017H97.238v-9.086c0-5.01,4.076-9.086,9.086-9.086H414.7
v51.841c0,13.851,11.268,25.119,25.119,25.119h51.841v325.478C491.66,422.9,495.248,426.489,499.677,426.489z M439.819,76.96
c-5.01,0-9.086-4.076-9.086-9.086V27.37l49.589,49.59H439.819z"/>
</g>
</g>
<g>
<g>
<path d="M191.835,128.267h-17.637V92.994h17.637c4.428,0,8.017-3.589,8.017-8.017s-3.588-8.017-8.017-8.017h-25.653
c-4.428,0-8.017,3.589-8.017,8.017v51.307c0,4.427,3.588,8.017,8.017,8.017h25.653c4.428,0,8.017-3.589,8.017-8.017
S196.264,128.267,191.835,128.267z"/>
</g>
</g>
<g>
<g>
<path d="M243.142,102.614h-17.637v-9.62h17.637c4.428,0,8.017-3.589,8.017-8.017s-3.588-8.017-8.017-8.017h-25.653
c-4.428,0-8.017,3.589-8.017,8.017v25.653c0,4.427,3.588,8.017,8.017,8.017h17.637v9.62h-17.637c-4.428,0-8.017,3.589-8.017,8.017
s3.588,8.017,8.017,8.017h25.653c4.428,0,8.017-3.589,8.017-8.017V110.63C251.159,106.203,247.571,102.614,243.142,102.614z"/>
</g>
</g>
<g>
<g>
<path d="M305.536,77.372c-4.145-1.382-8.76,0.925-10.141,5.071l-9.497,28.49l-9.497-28.49c-1.401-4.201-5.939-6.472-10.141-5.071
c-4.201,1.4-6.47,5.94-5.07,10.141l17.102,51.307c1.09,3.273,4.154,5.481,7.605,5.481c3.451,0,6.515-2.208,7.605-5.481
l17.102-51.307C311.986,83.368,309.68,78.754,305.536,77.372z"/>
</g>
</g>
<g>
<g>
<path d="M414.165,213.779H174.733c-9.136,0-16.568,7.432-16.568,16.568v222.33h0c0,9.136,7.432,16.568,16.568,16.568h239.432
c9.136,0,16.568-7.432,16.568-16.568v-222.33C430.733,221.211,423.301,213.779,414.165,213.779z M414.7,452.676
c0,0.295-0.24,0.534-0.534,0.534H174.733c-0.294,0-0.534-0.239-0.534-0.534v-222.33c0-0.295,0.24-0.534,0.534-0.534h239.432
c0.294,0,0.534,0.239,0.534,0.534V452.676z"/>
</g>
</g>
<g>
<g>
<path d="M243.142,256.534h-34.205c-4.428,0-8.017,3.589-8.017,8.017s3.588,8.017,8.017,8.017h34.205
c4.428,0,8.017-3.589,8.017-8.017S247.571,256.534,243.142,256.534z"/>
</g>
</g>
<g>
<g>
<path d="M379.961,256.534H277.347c-4.428,0-8.017,3.589-8.017,8.017s3.588,8.017,8.017,8.017h102.614
c4.428,0,8.017-3.589,8.017-8.017S384.389,256.534,379.961,256.534z"/>
</g>
</g>
<g>
<g>
<path d="M243.142,307.841h-34.205c-4.428,0-8.017,3.589-8.017,8.017s3.588,8.017,8.017,8.017h34.205
c4.428,0,8.017-3.589,8.017-8.017S247.571,307.841,243.142,307.841z"/>
</g>
</g>
<g>
<g>
<path d="M379.961,307.841H277.347c-4.428,0-8.017,3.589-8.017,8.017s3.588,8.017,8.017,8.017h102.614
c4.428,0,8.017-3.589,8.017-8.017S384.389,307.841,379.961,307.841z"/>
</g>
</g>
<g>
<g>
<path d="M243.142,359.148h-34.205c-4.428,0-8.017,3.589-8.017,8.017c0,4.427,3.588,8.017,8.017,8.017h34.205
c4.428,0,8.017-3.589,8.017-8.017C251.159,362.738,247.571,359.148,243.142,359.148z"/>
</g>
</g>
<g>
<g>
<path d="M303,359.148h-25.653c-4.428,0-8.017,3.589-8.017,8.017c0,4.427,3.588,8.017,8.017,8.017H303
c4.428,0,8.017-3.589,8.017-8.017C311.017,362.738,307.429,359.148,303,359.148z"/>
</g>
</g>
<g>
<g>
<path d="M243.142,410.455h-34.205c-4.428,0-8.017,3.589-8.017,8.017c0,4.427,3.588,8.017,8.017,8.017h34.205
c4.428,0,8.017-3.589,8.017-8.017C251.159,414.044,247.571,410.455,243.142,410.455z"/>
</g>
</g>
<g>
<g>
<path d="M303,410.455h-25.653c-4.428,0-8.017,3.589-8.017,8.017c0,4.427,3.588,8.017,8.017,8.017H303
c4.428,0,8.017-3.589,8.017-8.017C311.017,414.044,307.429,410.455,303,410.455z"/>
</g>
</g>
<g>
<g>
<path d="M369.018,392.818l17.101-20.522c2.834-3.401,2.374-8.456-1.026-11.291c-3.4-2.833-8.455-2.374-11.291,1.026
l-15.219,18.263l-15.219-18.263c-2.835-3.402-7.89-3.861-11.291-1.026c-3.401,2.835-3.86,7.89-1.026,11.291l17.101,20.522
l-17.101,20.522c-2.573,3.087-2.422,7.759,0.357,10.667c3.263,3.413,8.937,3.225,11.96-0.402l15.219-18.263l15.219,18.263
c3.023,3.628,8.697,3.815,11.96,0.402c2.78-2.907,2.93-7.578,0.357-10.667L369.018,392.818z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -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) {

0
package-lock.json generated
View File