excluded pages fix and legal basis / image reacat fix

This commit is contained in:
Timo Bejan 2021-08-17 21:21:42 +03:00
parent 8eba40d5f5
commit 929aa355d7
16 changed files with 106 additions and 85 deletions

View File

@ -26,7 +26,8 @@ export type AnnotationSuperType =
export class AnnotationWrapper {
superType: AnnotationSuperType;
dictionary: string;
typeValue: string;
recategorizationType: string;
color: string;
comments: Comment[] = [];
firstTopLeftPoint: Point;
@ -42,7 +43,7 @@ export class AnnotationWrapper {
dictionaryOperation: boolean;
positions: Rectangle[];
recommendationType: string;
legalBasis: string;
legalBasisValue: string;
legalBasisChangeValue?: string;
manual?: boolean;
@ -89,11 +90,15 @@ export class AnnotationWrapper {
}
get isImage() {
return this.dictionary?.toLowerCase() === 'image' || this.image;
return this.type?.toLowerCase() === 'image' || this.image;
}
get isOCR() {
return this.dictionary?.toLowerCase() === 'ocr';
return this.type?.toLowerCase() === 'ocr';
}
get type() {
return this.recategorizationType || this.typeValue;
}
get isManuallySkipped() {
@ -102,7 +107,7 @@ export class AnnotationWrapper {
get isFalsePositive() {
return (
this.dictionary?.toLowerCase() === 'false_positive' &&
this.type?.toLowerCase() === 'false_positive' &&
(this.superType === 'skipped' || this.superType === 'hint' || this.superType === 'redaction')
);
}
@ -185,6 +190,10 @@ export class AnnotationWrapper {
return this.firstTopLeftPoint.y;
}
get legalBasis() {
return this.legalBasisChangeValue || this.legalBasisValue;
}
static fromData(redactionLogEntry?: RedactionLogEntryWrapper) {
const annotationWrapper = new AnnotationWrapper();
@ -195,7 +204,8 @@ export class AnnotationWrapper {
annotationWrapper.changeLogType = redactionLogEntry.changeLogType;
annotationWrapper.redaction = redactionLogEntry.redacted;
annotationWrapper.hint = redactionLogEntry.hint;
annotationWrapper.dictionary = redactionLogEntry.type;
annotationWrapper.typeValue = redactionLogEntry.type;
annotationWrapper.recategorizationType = redactionLogEntry.recategorizationType;
annotationWrapper.value = redactionLogEntry.value;
annotationWrapper.firstTopLeftPoint = redactionLogEntry.positions[0]?.topLeft;
annotationWrapper.pageNumber = redactionLogEntry.positions[0]?.page;
@ -206,8 +216,8 @@ export class AnnotationWrapper {
annotationWrapper.dictionaryOperation = redactionLogEntry.dictionaryEntry;
annotationWrapper.image = redactionLogEntry.image;
annotationWrapper.legalBasisChangeValue = redactionLogEntry.legalBasisChangeValue;
annotationWrapper.legalBasisValue = redactionLogEntry.legalBasis;
annotationWrapper.comments = redactionLogEntry.comments || [];
annotationWrapper.legalBasis = redactionLogEntry.legalBasis;
annotationWrapper.manual = redactionLogEntry.manual;
this._createContent(annotationWrapper, redactionLogEntry);
@ -247,7 +257,7 @@ export class AnnotationWrapper {
return;
}
if (annotationWrapper.dictionary?.toLowerCase() === 'false_positive') {
if (annotationWrapper.type?.toLowerCase() === 'false_positive') {
if (redactionLogEntryWrapper.status === 'REQUESTED') {
annotationWrapper.superType = 'suggestion-add-dictionary';
return;
@ -372,24 +382,24 @@ export class AnnotationWrapper {
content += entry.reason + '\n\n';
}
if (entry.legalBasisChangeValue || entry.legalBasis) {
content += 'Legal basis: ' + entry.legalBasis + '\n\n';
if (annotationWrapper.legalBasis) {
content += 'Legal basis: ' + annotationWrapper.legalBasis + '\n\n';
}
if (entry.section) {
content += 'In section: "' + entry.section + '"';
}
annotationWrapper.shortContent = this._getShortContent(entry) || content;
annotationWrapper.shortContent = this._getShortContent(annotationWrapper, entry) || content;
annotationWrapper.content = content;
}
private static _getShortContent(entry: RedactionLogEntryWrapper) {
if (entry.legalBasis) {
const lb = entry.legalBasisMapping?.find(lbm => lbm.reason.toLowerCase().includes(entry.legalBasis.toLowerCase()));
private static _getShortContent(annotationWrapper: AnnotationWrapper, entry: RedactionLogEntryWrapper) {
if (annotationWrapper.legalBasis) {
const lb = entry.legalBasisMapping?.find(lbm => lbm.reason.toLowerCase().includes(annotationWrapper.legalBasis.toLowerCase()));
if (lb) return lb.name;
}
return entry.legalBasis;
return annotationWrapper.legalBasis;
}
}

View File

@ -171,7 +171,7 @@ export class WatermarkScreenComponent implements OnInit {
const opacity = this.configForm.get('opacity').value;
const color = this.configForm.get('hexColor').value;
await stampPDFPage(document, pdfNet, text, fontSize, fontType, orientation, opacity, color, 1);
await stampPDFPage(document, pdfNet, text, fontSize, fontType, orientation, opacity, color, [1]);
this._instance.docViewer.refreshAll();
this._instance.docViewer.updateView([0], 0);
this._changeDetectorRef.detectChanges();

View File

@ -180,11 +180,11 @@
<div>
<strong>{{ annotation.typeLabel | translate }}</strong>
</div>
<div *ngIf="annotation?.dictionary !== 'manual'">
<div *ngIf="annotation?.type !== 'manual'">
<strong>
<span>{{ annotation.descriptor | translate }}</span
>: </strong
>{{ annotation.dictionary | humanize: false }}
>{{ annotation.type | humanize: false }}
</div>
<div *ngIf="annotation.shortContent && !annotation.isHint">
<strong><span translate="content"></span>: </strong>{{ annotation.shortContent }}
@ -225,7 +225,7 @@
<redaction-page-exclusion
(actionPerformed)="actionPerformed.emit($event)"
*ngIf="excludePages"
[fileData]="fileData"
[fileStatus]="fileData.fileStatus"
></redaction-page-exclusion>
</div>
</div>

View File

@ -6,6 +6,7 @@ import { FileDataModel } from '../../../../models/file/file-data.model';
import { Toaster } from '@services/toaster.service';
import { LoadingService } from '@services/loading.service';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { FileStatusWrapper } from '../../../../models/file/file-status.wrapper';
@Component({
selector: 'redaction-page-exclusion',
@ -13,7 +14,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
styleUrls: ['./page-exclusion.component.scss']
})
export class PageExclusionComponent implements OnChanges {
@Input() fileData: FileDataModel;
@Input() fileStatus: FileStatusWrapper;
@Output() actionPerformed = new EventEmitter<string>();
excludePagesForm: FormGroup;
@ -31,22 +32,20 @@ export class PageExclusionComponent implements OnChanges {
});
}
ngOnChanges(changes: SimpleChanges) {
if (changes.fileData) {
const excludedPages = (this.fileData?.fileStatus?.excludedPages || []).sort((p1, p2) => p1 - p2);
this.excludedPagesRanges = excludedPages.reduce((ranges, page) => {
if (!ranges.length) {
return [{ startPage: page, endPage: page }];
}
ngOnChanges() {
const excludedPages = (this.fileStatus?.excludedPages || []).sort((p1, p2) => p1 - p2);
this.excludedPagesRanges = excludedPages.reduce((ranges, page) => {
if (!ranges.length) {
return [{ startPage: page, endPage: page }];
}
if (page === ranges[ranges.length - 1].endPage + 1) {
ranges[ranges.length - 1].endPage = page;
} else {
ranges.push({ startPage: page, endPage: page });
}
return ranges;
}, []);
}
if (page === ranges[ranges.length - 1].endPage + 1) {
ranges[ranges.length - 1].endPage = page;
} else {
ranges.push({ startPage: page, endPage: page });
}
return ranges;
}, []);
}
async excludePagesRange() {
@ -72,8 +71,8 @@ export class PageExclusionComponent implements OnChanges {
{
pageRanges: pageRanges
},
this.fileData.fileStatus.dossierId,
this.fileData.fileStatus.fileId
this.fileStatus.dossierId,
this.fileStatus.fileId
)
.toPromise();
this.excludePagesForm.reset();
@ -91,8 +90,8 @@ export class PageExclusionComponent implements OnChanges {
{
pageRanges: [range]
},
this.fileData.fileStatus.dossierId,
this.fileData.fileStatus.fileId
this.fileStatus.dossierId,
this.fileStatus.fileId
)
.toPromise();
this.excludePagesForm.reset();

View File

@ -21,7 +21,7 @@ export class TypeAnnotationIconComponent implements OnChanges {
if (this.annotation.isSuperTypeBasedColor) {
this.color = this._appStateService.getDictionaryColor(this.annotation.superType);
} else {
this.color = this._appStateService.getDictionaryColor(this.annotation.dictionary);
this.color = this._appStateService.getDictionaryColor(this.annotation.type);
}
this.type =
this.annotation.isSuggestion || this.annotation.isDeclinedSuggestion
@ -38,7 +38,7 @@ export class TypeAnnotationIconComponent implements OnChanges {
? 'S'
: this.annotation.isReadyForAnalysis
? 'A'
: this.annotation.dictionary[0].toUpperCase();
: this.annotation.type[0].toUpperCase();
}
}
}

View File

@ -25,14 +25,14 @@ export class RecategorizeImageDialogComponent implements OnInit {
) {}
get changed(): boolean {
return this.recategorizeImageForm.get('type').value !== this.annotations[0].dictionary;
return this.recategorizeImageForm.get('type').value !== this.annotations[0].type;
}
async ngOnInit() {
this.isDocumentAdmin = this._permissionsService.isApprover();
this.recategorizeImageForm = this._formBuilder.group({
type: [this.annotations[0].dictionary, Validators.required],
type: [this.annotations[0].type, Validators.required],
comment: this.isDocumentAdmin ? [null] : [null, Validators.required]
});
}

View File

@ -26,7 +26,7 @@
</thead>
<tbody>
<tr *ngFor="let annotation of data.annotationsToRemove">
<td>{{ annotation.dictionary }}</td>
<td>{{ annotation.type }}</td>
<td>{{ annotation.value }}</td>
</tr>
</tbody>

View File

@ -42,7 +42,7 @@ export class RemoveAnnotationsDialogComponent {
printable(annotation: AnnotationWrapper) {
if (annotation.isImage) {
return this._translateService.instant('remove-annotations-dialog.image-type', {
typeLabel: humanize(annotation.dictionary)
typeLabel: humanize(annotation.type)
});
} else {
return annotation.value;

View File

@ -5,7 +5,6 @@
[showCloseButton]="true"
>
<redaction-file-download-btn
[disabled]="entitiesService.areSomeSelected$ | async"
[dossier]="currentDossier"
[file]="entitiesService.all$ | async"
tooltipPosition="below"
@ -14,7 +13,6 @@
<iqser-circle-button
(action)="reanalyseDossier()"
*ngIf="permissionsService.displayReanalyseBtn()"
[disabled]="entitiesService.areSomeSelected$ | async"
[tooltipClass]="'small ' + ((entitiesService.areSomeSelected$ | async) ? '' : 'warn')"
[tooltip]="'dossier-overview.new-rule.toast.actions.reanalyse-all' | translate"
icon="red:refresh"

View File

@ -93,8 +93,8 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
constructor(
private readonly _toaster: Toaster,
protected readonly _injector: Injector,
private readonly _userService: UserService,
readonly permissionsService: PermissionsService,
private readonly _userService: UserService,
private readonly _loadingService: LoadingService,
private readonly _appStateService: AppStateService,
private readonly _appConfigService: AppConfigService,

View File

@ -31,7 +31,7 @@ import { FileWorkloadComponent } from '../../components/file-workload/file-workl
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy';
import { LoadingService } from '@services/loading.service';
import { stampPDFPage } from '@utils/page-stamper';
import { clearStamps, stampPDFPage } from '@utils/page-stamper';
import { TranslateService } from '@ngx-translate/core';
import { fileStatusTranslations } from '../../translations/file-status-translations';
import { handleFilterDelta } from '@shared/components/filters/popup-filter/utils/filter-utils';
@ -443,6 +443,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
case 'exclude-pages':
await this.appStateService.reloadActiveDossierFiles();
await this._loadFileData(true);
await this._stampExcludedPages();
this._loadingService.stop();
return;
@ -525,25 +526,26 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
window.open(`/html-debug/${this.dossierId}/${this.fileId}`, '_blank');
}
private async _stampPage(page: number) {
const document = await this._instance.docViewer.getDocument().getPDFDoc();
await stampPDFPage(
document,
this._instance.PDFNet,
this._translateService.instant('file-preview.excluded-from-redaction'),
25,
'courier',
'DIAGONAL',
33,
'#283241',
page
);
private async _doStampExcludedPages(excludedPages: number[]) {
if (excludedPages && excludedPages.length > 0) {
const document = await this._instance.docViewer.getDocument().getPDFDoc();
await clearStamps(document, this._instance.PDFNet, [...Array(this.fileData.fileStatus.numberOfPages).keys()]);
await stampPDFPage(
document,
this._instance.PDFNet,
this._translateService.instant('file-preview.excluded-from-redaction'),
25,
'courier',
'DIAGONAL',
33,
'#283241',
excludedPages
);
}
}
private async _stampExcludedPages() {
for (const page of this.fileData.fileStatus.excludedPages) {
await this._stampPage(page);
}
await this._doStampExcludedPages(this.fileData.fileStatus.excludedPages);
this._instance.docViewer.refreshAll();
this._instance.docViewer.updateView([this.activeViewerPage], this.activeViewerPage);
this._changeDetectorRef.detectChanges();

View File

@ -84,7 +84,7 @@ export class AnnotationDrawService {
const pageNumber = compareMode ? annotationWrapper.pageNumber * 2 - 1 : annotationWrapper.pageNumber;
const highlight = new activeViewer.Annotations.TextHighlightAnnotation();
highlight.PageNumber = pageNumber;
highlight.StrokeColor = this.getColor(activeViewer, annotationWrapper.superType, annotationWrapper.dictionary);
highlight.StrokeColor = this.getColor(activeViewer, annotationWrapper.superType, annotationWrapper.type);
highlight.setContents(annotationWrapper.content);
highlight.Quads = this._rectanglesToQuads(annotationWrapper.positions, activeViewer, pageNumber);
highlight.Id = annotationWrapper.id;
@ -99,7 +99,7 @@ export class AnnotationDrawService {
highlight.setCustomData('changeLog', annotationWrapper.isChangeLogEntry);
highlight.setCustomData('changeLogRemoved', annotationWrapper.isChangeLogRemoved);
highlight.setCustomData('redactionColor', this.getColor(activeViewer, 'redaction', 'redaction'));
highlight.setCustomData('annotationColor', this.getColor(activeViewer, annotationWrapper.superType, annotationWrapper.dictionary));
highlight.setCustomData('annotationColor', this.getColor(activeViewer, annotationWrapper.superType, annotationWrapper.type));
return highlight;
}

View File

@ -37,7 +37,7 @@ export class AnnotationProcessingService {
annotations?.forEach(a => {
const topLevelFilter = a.superType !== 'hint' && a.superType !== 'redaction' && a.superType !== 'recommendation';
const key = topLevelFilter ? a.superType : a.superType + a.dictionary;
const key = topLevelFilter ? a.superType : a.superType + a.type;
const filter = filterMap.get(key);
if (filter) {
filter.matches += 1;
@ -51,8 +51,8 @@ export class AnnotationProcessingService {
parentFilter = this._createParentFilter(a.superType, filterMap, filters);
}
const childFilter = {
key: a.dictionary,
label: a.dictionary,
key: a.type,
label: a.type,
checked: false,
filters: [],
matches: 1
@ -172,7 +172,7 @@ export class AnnotationProcessingService {
const superType = annotation.superType;
const isNotTopLevelFilter = superType === 'hint' || superType === 'redaction' || superType === 'recommendation';
return filter.key === superType || (filter.key === annotation.dictionary && isNotTopLevelFilter);
return filter.key === superType || (filter.key === annotation.type && isNotTopLevelFilter);
};
private _sortAnnotations(annotations: AnnotationWrapper[]): AnnotationWrapper[] {

View File

@ -168,7 +168,7 @@ export class ManualAnnotationService {
if (this._permissionsService.isApprover()) {
// if it was something manual simply decline the existing request
if (annotationWrapper.dictionary === 'manual') {
if (annotationWrapper.type === 'manual') {
mode = 'undo';
body = annotationWrapper.id;
} else {

View File

@ -9,17 +9,9 @@ const processPage = async (pageNumber, document1, document2, mergedDocument, PDF
const blankPage = await mergedDocument.pageCreate(await pageToCopy.getCropBox());
await blankPage.setRotation(await pageToCopy.getRotation());
await mergedDocument.pagePushBack(blankPage);
await stampPDFPage(
mergedDocument,
PDFNet,
'<< Compare Placeholder Page >>',
20,
'courier',
'DIAGONAL',
33,
'#ffb83b',
await stampPDFPage(mergedDocument, PDFNet, '<< Compare Placeholder Page >>', 20, 'courier', 'DIAGONAL', 33, '#ffb83b', [
await mergedDocument.getPageCount()
);
]);
}
};

View File

@ -3,6 +3,17 @@ import { environment } from '@environments/environment';
import { PDFNet } from '@pdftron/webviewer';
import PDFDoc = PDFNet.PDFDoc;
export async function clearStamps(document: PDFDoc, PdfNet: any, pages: number[]) {
await PdfNet.runWithCleanup(
async () => {
await document.lock();
const pageSet = await createPageSet(PdfNet, pages);
await PdfNet.Stamper.deleteStamps(document, pageSet);
},
environment.licenseKey ? atob(environment.licenseKey) : null
);
}
export async function stampPDFPage(
document: PDFDoc,
PdfNet: any,
@ -12,14 +23,13 @@ export async function stampPDFPage(
orientation: 'DIAGONAL' | 'HORIZONTAL' | 'VERTICAL',
opacity: number,
color: string,
page: number
pages: number[]
) {
await PdfNet.runWithCleanup(
async () => {
await document.lock();
const pageSet = await PdfNet.PageSet.createSinglePage(page);
const pageSet = await createPageSet(PdfNet, pages);
await PdfNet.Stamper.deleteStamps(document, pageSet);
const rgbColor = hexToRgb(color);
@ -50,6 +60,16 @@ export async function stampPDFPage(
);
}
async function createPageSet(PdfNet: any, pages: number[]) {
const pageSet = await PdfNet.PageSet.create();
for (const page of pages) {
if (page > 0) {
await pageSet.addPage(page);
}
}
return pageSet;
}
function convertFont(type: string): number {
switch (type) {
case 'times-new-roman':