Pull request #236: RED-1771
Merge in RED/ui from RED-1771 to master * commit '483bd71c2f4998961bc9b96f2c79ee2d6eb65bdd': Stamp excluded pages Display page excluded from redaction in workload
This commit is contained in:
commit
3616988cf3
@ -70,8 +70,8 @@ export class WatermarkScreenComponent implements OnInit {
|
||||
}
|
||||
|
||||
@debounce()
|
||||
configChanged() {
|
||||
this._drawWatermark();
|
||||
async configChanged() {
|
||||
await this._drawWatermark();
|
||||
}
|
||||
|
||||
save() {
|
||||
@ -111,17 +111,17 @@ export class WatermarkScreenComponent implements OnInit {
|
||||
);
|
||||
}
|
||||
|
||||
revert() {
|
||||
async revert() {
|
||||
this.configForm.setValue({ ...this._watermark });
|
||||
this.configChanged();
|
||||
await this.configChanged();
|
||||
}
|
||||
|
||||
triggerChanges() {}
|
||||
|
||||
setValue(type: 'fontType' | 'orientation' | 'hexColor', value: any) {
|
||||
async setValue(type: 'fontType' | 'orientation' | 'hexColor', value: any) {
|
||||
if (!this.configForm.get(type).disabled) {
|
||||
this.configForm.get(type).setValue(value);
|
||||
this.configChanged();
|
||||
await this.configChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,9 +157,9 @@ export class WatermarkScreenComponent implements OnInit {
|
||||
).then(instance => {
|
||||
this._instance = instance;
|
||||
|
||||
instance.docViewer.on('documentLoaded', () => {
|
||||
instance.docViewer.on('documentLoaded', async () => {
|
||||
this.viewReady = true;
|
||||
this._drawWatermark();
|
||||
await this._drawWatermark();
|
||||
});
|
||||
|
||||
this._disableElements();
|
||||
|
||||
@ -30,6 +30,6 @@ export class DocumentInfoComponent {
|
||||
}
|
||||
|
||||
edit() {
|
||||
this._dialogService.openDialog('document-info', null, this.file);
|
||||
this._dialogService.openDialog('documentInfo', null, this.file);
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ export class DossierListingActionsComponent {
|
||||
) {}
|
||||
|
||||
openEditDossierDialog($event: MouseEvent, dossierWrapper: DossierWrapper) {
|
||||
this._dialogService.openDialog('edit-dossier', $event, {
|
||||
this._dialogService.openDialog('editDossier', $event, {
|
||||
dossierWrapper,
|
||||
afterSave: () => {
|
||||
this.actionPerformed.emit();
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
>
|
||||
<div>
|
||||
<redaction-circle-button
|
||||
(action)="closeExcludePagesView.emit()"
|
||||
(action)="actionPerformed.emit('view-exclude-pages')"
|
||||
icon="red:close"
|
||||
tooltip="file-preview.tabs.exclude-pages.close"
|
||||
tooltipPosition="before"
|
||||
@ -142,13 +142,29 @@
|
||||
redactionHasScrollbar
|
||||
tabindex="1"
|
||||
>
|
||||
<ng-container *ngIf="!displayedAnnotations[activeViewerPage]">
|
||||
<ng-container
|
||||
*ngIf="activeViewerPage && !displayedAnnotations[activeViewerPage]"
|
||||
>
|
||||
<redaction-empty-state
|
||||
[horizontalPadding]="24"
|
||||
[verticalPadding]="40"
|
||||
icon="red:document"
|
||||
screen="file-preview"
|
||||
></redaction-empty-state>
|
||||
>
|
||||
<ng-container
|
||||
*ngIf="
|
||||
fileData?.fileStatus?.excludedPages?.includes(activeViewerPage)
|
||||
"
|
||||
>
|
||||
{{ 'file-preview.tabs.annotations.page-is' | translate }}
|
||||
<a
|
||||
(click)="actionPerformed.emit('view-exclude-pages')"
|
||||
translate="file-preview.excluded-from-redaction"
|
||||
>
|
||||
</a
|
||||
>.
|
||||
</ng-container>
|
||||
</redaction-empty-state>
|
||||
<div class="no-annotations-buttons-container mt-32">
|
||||
<redaction-icon-button
|
||||
(action)="jumpToPreviousWithAnnotations()"
|
||||
@ -267,8 +283,8 @@
|
||||
|
||||
<ng-template #annotationFilterActionTemplate let-filter="filter">
|
||||
<redaction-circle-button
|
||||
*ngIf="filter.key === 'skipped'"
|
||||
(action)="toggleSkipped.emit($event)"
|
||||
*ngIf="filter.key === 'skipped'"
|
||||
[icon]="hideSkipped ? 'red:visibility-off' : 'red:visibility'"
|
||||
type="dark-bg"
|
||||
></redaction-circle-button>
|
||||
|
||||
@ -50,7 +50,6 @@ export class FileWorkloadComponent {
|
||||
@Output() selectPage = new EventEmitter<number>();
|
||||
@Output() toggleSkipped = new EventEmitter<any>();
|
||||
@Output() annotationsChanged = new EventEmitter<AnnotationWrapper>();
|
||||
@Output() closeExcludePagesView = new EventEmitter();
|
||||
@Output() actionPerformed = new EventEmitter<string>();
|
||||
displayedPages: number[] = [];
|
||||
pagesPanelActive = true;
|
||||
|
||||
@ -9,14 +9,14 @@
|
||||
type="file"
|
||||
/>
|
||||
|
||||
<div *ngIf="utils.totalPages && utils.currentPage" class="pagination noselect">
|
||||
<div *ngIf="utils?.totalPages && utils?.currentPage" class="pagination noselect">
|
||||
<div (click)="utils.previousPage()">
|
||||
<mat-icon class="chevron-icon" svgIcon="red:nav-prev"></mat-icon>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
#pageInput
|
||||
(change)="utils.navigateToPageByInput(pageInput.value)"
|
||||
(change)="utils.navigateToPage(pageInput.value)"
|
||||
[max]="utils.totalPages"
|
||||
[value]="utils.currentPage"
|
||||
class="page-number-input"
|
||||
|
||||
@ -150,8 +150,8 @@ export class PdfViewerComponent implements OnInit, OnChanges {
|
||||
() => {
|
||||
this.viewMode = 'COMPARE';
|
||||
},
|
||||
(page: number) => {
|
||||
this.utils.navigateToPage(page);
|
||||
() => {
|
||||
this.utils.navigateToPage(1);
|
||||
},
|
||||
PDFNet
|
||||
);
|
||||
|
||||
@ -196,7 +196,7 @@ export class DossierListingScreenComponent
|
||||
this._calculateData();
|
||||
await this._router.navigate([`/main/dossiers/${addResponse.dossier.dossierId}`]);
|
||||
if (addResponse.addMembers) {
|
||||
this._dialogService.openDialog('edit-dossier', null, {
|
||||
this._dialogService.openDialog('editDossier', null, {
|
||||
dossierWrapper: addResponse.dossier,
|
||||
section: 'members'
|
||||
});
|
||||
|
||||
@ -293,14 +293,14 @@ export class DossierOverviewScreenComponent
|
||||
}
|
||||
|
||||
openEditDossierDialog($event: MouseEvent) {
|
||||
this._dialogService.openDialog('edit-dossier', $event, {
|
||||
this._dialogService.openDialog('editDossier', $event, {
|
||||
dossierWrapper: this.activeDossier
|
||||
});
|
||||
}
|
||||
|
||||
openAssignDossierMembersDialog(): void {
|
||||
this._dialogService.openDialog(
|
||||
'edit-dossier',
|
||||
'editDossier',
|
||||
null,
|
||||
{
|
||||
dossierWrapper: this.activeDossier,
|
||||
|
||||
@ -174,7 +174,6 @@
|
||||
#fileWorkloadComponent
|
||||
(actionPerformed)="fileActionPerformed($event)"
|
||||
(annotationsChanged)="annotationsChangedByReviewAction($event)"
|
||||
(closeExcludePagesView)="excludePages = false"
|
||||
(deselectAnnotations)="deselectAnnotations($event)"
|
||||
(selectAnnotations)="selectAnnotations($event)"
|
||||
(selectPage)="selectPage($event)"
|
||||
|
||||
@ -46,6 +46,8 @@ import {
|
||||
processFilters
|
||||
} from '@shared/components/filters/popup-filter/utils/filter-utils';
|
||||
import { LoadingService } from '../../../../services/loading.service';
|
||||
import { stampPDFPage } from '../../../../utils/page-stamper';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
|
||||
|
||||
@ -96,7 +98,8 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
private readonly _statusControllerService: StatusControllerService,
|
||||
private readonly _ngZone: NgZone,
|
||||
private readonly _fileManagementControllerService: FileManagementControllerService,
|
||||
private readonly _loadingService: LoadingService
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _translateService: TranslateService
|
||||
) {
|
||||
document.documentElement.addEventListener('fullscreenchange', () => {
|
||||
if (!document.fullscreenElement) {
|
||||
@ -361,7 +364,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
}
|
||||
|
||||
selectPage(pageNumber: number) {
|
||||
this.viewerComponent.utils.navigateToPageByInput(pageNumber);
|
||||
this.viewerComponent.utils.navigateToPage(pageNumber);
|
||||
this._workloadComponent?.scrollAnnotationsToPage(pageNumber, 'always');
|
||||
}
|
||||
|
||||
@ -447,8 +450,9 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
viewerReady($event: WebViewerInstance) {
|
||||
async viewerReady($event: WebViewerInstance) {
|
||||
this._instance = $event;
|
||||
await this._stampExcludedPages();
|
||||
this._cleanupAndRedrawManualAnnotations();
|
||||
this._updateCanPerformActions();
|
||||
this.viewReady = true;
|
||||
@ -570,6 +574,30 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
||||
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 _stampExcludedPages() {
|
||||
for (const page of this.fileData.fileStatus.excludedPages) {
|
||||
await this._stampPage(page);
|
||||
}
|
||||
this._instance.docViewer.refreshAll();
|
||||
this._instance.docViewer.updateView([this.activeViewerPage], this.activeViewerPage);
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
private _subscribeToFileUpdates(): void {
|
||||
this.filesAutoUpdateTimer = timer(0, 5000)
|
||||
.pipe(tap(async () => await this.appStateService.reloadActiveFile()))
|
||||
|
||||
@ -33,7 +33,7 @@ const dialogConfig = {
|
||||
|
||||
// TODO: Continue refactor
|
||||
|
||||
type DialogType = 'confirm' | 'document-info' | 'edit-dossier';
|
||||
type DialogType = 'confirm' | 'documentInfo' | 'editDossier';
|
||||
|
||||
type DossiersDialogConfig = {
|
||||
[key in DialogType]: {
|
||||
@ -48,11 +48,11 @@ export class DossiersDialogService extends DialogService<DialogType> {
|
||||
confirm: {
|
||||
component: ConfirmationDialogComponent
|
||||
},
|
||||
'document-info': {
|
||||
documentInfo: {
|
||||
component: DocumentInfoDialogComponent,
|
||||
dialogConfig: { autoFocus: true }
|
||||
},
|
||||
'edit-dossier': {
|
||||
editDossier: {
|
||||
component: EditDossierDialogComponent,
|
||||
dialogConfig: { ...this._largeConfig, autoFocus: true }
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ export const loadCompareDocumentWrapper = async (
|
||||
instance,
|
||||
fileStatus,
|
||||
setCompareViewMode: () => void,
|
||||
navigateToPage: (number) => void,
|
||||
navigateToPage: () => void,
|
||||
PDFNet
|
||||
) => {
|
||||
try {
|
||||
@ -65,7 +65,7 @@ export const loadCompareDocumentWrapper = async (
|
||||
instance.disableElements(['compareButton']);
|
||||
instance.enableElements(['closeCompareButton']);
|
||||
|
||||
navigateToPage(1);
|
||||
navigateToPage();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
@ -91,28 +91,22 @@ export class PdfViewerUtils {
|
||||
return this.instance?.docViewer?.getPageCount();
|
||||
}
|
||||
|
||||
navigateToPage(pageNumber) {
|
||||
const activePage = this.instance.docViewer.getCurrentPage();
|
||||
if (activePage !== pageNumber) {
|
||||
this.instance.docViewer.displayPageLocation(pageNumber, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
navigateToPageByInput(pageNumber) {
|
||||
this.navigateToPage(
|
||||
this.paginationOffset === 2 ? pageNumber * this.paginationOffset - 1 : pageNumber
|
||||
navigateToPage(pageNumber: string | number) {
|
||||
const parsedNumber = typeof pageNumber === 'string' ? parseInt(pageNumber, 10) : pageNumber;
|
||||
this._navigateToPage(
|
||||
this.paginationOffset === 2 ? parsedNumber * this.paginationOffset - 1 : parsedNumber
|
||||
);
|
||||
}
|
||||
|
||||
previousPage() {
|
||||
if (this._currentInternalPage > 1) {
|
||||
this.navigateToPage(Math.max(this._currentInternalPage - this.paginationOffset, 1));
|
||||
this._navigateToPage(Math.max(this._currentInternalPage - this.paginationOffset, 1));
|
||||
}
|
||||
}
|
||||
|
||||
nextPage() {
|
||||
if (this._currentInternalPage < this._totalInternalPages) {
|
||||
this.navigateToPage(
|
||||
this._navigateToPage(
|
||||
Math.min(
|
||||
this._currentInternalPage + this.paginationOffset,
|
||||
this._totalInternalPages
|
||||
@ -178,6 +172,13 @@ export class PdfViewerUtils {
|
||||
this.instance.annotManager.deselectAnnotations(ann);
|
||||
}
|
||||
|
||||
private _navigateToPage(pageNumber) {
|
||||
const activePage = this.instance.docViewer.getCurrentPage();
|
||||
if (activePage !== pageNumber) {
|
||||
this.instance.docViewer.displayPageLocation(pageNumber, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private _getAnnotationById(id: string): Annotations.Annotation {
|
||||
return this.instance.annotManager.getAnnotationById(id);
|
||||
}
|
||||
|
||||
@ -7,6 +7,9 @@
|
||||
class="empty-state"
|
||||
>
|
||||
<mat-icon [svgIcon]="icon"></mat-icon>
|
||||
<div class="ng-content-wrapper heading-l">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
<div [translate]="text || screen + '.' + type + '.title'" class="heading-l"></div>
|
||||
<redaction-icon-button
|
||||
(action)="action.emit()"
|
||||
|
||||
@ -20,4 +20,8 @@
|
||||
redaction-icon-button {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.ng-content-wrapper:not(:empty) + .heading-l {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,30 +1,32 @@
|
||||
import { hexToRgb } from './functions';
|
||||
import { environment } from '../../environments/environment';
|
||||
import { PDFNet } from '@pdftron/webviewer';
|
||||
import PDFDoc = PDFNet.PDFDoc;
|
||||
|
||||
export async function stampPDFPage(
|
||||
document: any,
|
||||
PDFNet: any,
|
||||
document: PDFDoc,
|
||||
PdfNet: any,
|
||||
text: string,
|
||||
fontSize: number,
|
||||
fontType: string,
|
||||
orientation: string,
|
||||
orientation: 'DIAGONAL' | 'HORIZONTAL' | 'VERTICAL',
|
||||
opacity: number,
|
||||
color: string,
|
||||
page: number
|
||||
) {
|
||||
await PDFNet.runWithCleanup(
|
||||
await PdfNet.runWithCleanup(
|
||||
async () => {
|
||||
await document.lock();
|
||||
|
||||
const pageSet = await PDFNet.PageSet.createSinglePage(page);
|
||||
const pageSet = await PdfNet.PageSet.createSinglePage(page);
|
||||
|
||||
await PDFNet.Stamper.deleteStamps(document, pageSet);
|
||||
await PdfNet.Stamper.deleteStamps(document, pageSet);
|
||||
|
||||
const rgbColor = hexToRgb(color);
|
||||
|
||||
const stamper = await PDFNet.Stamper.create(3, fontSize, 0);
|
||||
const stamper = await PdfNet.Stamper.create(3, fontSize, 0);
|
||||
await stamper.setFontColor(
|
||||
await PDFNet.ColorPt.init(rgbColor.r / 255, rgbColor.g / 255, rgbColor.b / 255)
|
||||
await PdfNet.ColorPt.init(rgbColor.r / 255, rgbColor.g / 255, rgbColor.b / 255)
|
||||
);
|
||||
await stamper.setOpacity(opacity / 100);
|
||||
|
||||
@ -41,7 +43,7 @@ export async function stampPDFPage(
|
||||
await stamper.setRotation(-45);
|
||||
}
|
||||
|
||||
const font = await PDFNet.Font.createAndEmbed(document, convertFont(fontType));
|
||||
const font = await PdfNet.Font.createAndEmbed(document, convertFont(fontType));
|
||||
await stamper.setFont(font);
|
||||
await stamper.setTextAlignment(0);
|
||||
await stamper.stampText(document, text, pageSet);
|
||||
|
||||
@ -923,6 +923,7 @@
|
||||
"document-info": "Your Document Info lives here. This includes metadata required on each document.",
|
||||
"download-original-file": "Download Original File",
|
||||
"exclude-pages": "Exclude pages from redaction",
|
||||
"excluded-from-redaction": "excluded from redaction",
|
||||
"fullscreen": "Full Screen (F)",
|
||||
"html-debug": "Open Document HTML Debug",
|
||||
"last-reviewer": "Last Reviewed by:",
|
||||
@ -948,7 +949,8 @@
|
||||
"label": "Workload",
|
||||
"select": "Select",
|
||||
"select-all": "All",
|
||||
"select-none": "None"
|
||||
"select-none": "None",
|
||||
"page-is": "This page is"
|
||||
},
|
||||
"document-info": {
|
||||
"close": "Close Document Info",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user