RED-3791: use existing convert recommendation to annotation action
This commit is contained in:
parent
f4b9595725
commit
b7d926046d
@ -14,6 +14,7 @@ import { FileDataService } from './services/file-data.service';
|
||||
import { AnnotationsListingService } from './services/annotations-listing.service';
|
||||
import { StampService } from './services/stamp.service';
|
||||
import { PdfProxyService } from './services/pdf-proxy.service';
|
||||
import { PdfAnnotationActionsService } from './services/pdf-annotation-actions.service';
|
||||
|
||||
export const filePreviewScreenProviders = [
|
||||
FilterService,
|
||||
@ -24,6 +25,7 @@ export const filePreviewScreenProviders = [
|
||||
CommentingService,
|
||||
SkippedService,
|
||||
AnnotationActionsService,
|
||||
PdfAnnotationActionsService,
|
||||
FilePreviewStateService,
|
||||
AnnotationReferencesService,
|
||||
AnnotationProcessingService,
|
||||
|
||||
@ -1,19 +1,13 @@
|
||||
import { Inject, Injectable, NgZone } from '@angular/core';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ManualRedactionService } from './manual-redaction.service';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { Observable } from 'rxjs';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { getFirstRelevantTextPart } from '../../../utils';
|
||||
import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
||||
import { BASE_HREF } from '../../../tokens';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { Core } from '@pdftron/webviewer';
|
||||
import {
|
||||
DictionaryEntryTypes,
|
||||
Dossier,
|
||||
IAddRedactionRequest,
|
||||
IHeaderElement,
|
||||
ILegalBasisChangeRequest,
|
||||
IRecategorizationRequest,
|
||||
IRectangle,
|
||||
@ -33,23 +27,16 @@ import { filter } from 'rxjs/operators';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { FilePreviewStateService } from './file-preview-state.service';
|
||||
import { FilePreviewDialogService } from './file-preview-dialog.service';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
import { FileDataService } from './file-data.service';
|
||||
import { PdfViewer } from '../../pdf-viewer/services/pdf-viewer.service';
|
||||
import { REDAnnotationManager } from '../../pdf-viewer/services/annotation-manager.service';
|
||||
import { SkippedService } from './skipped.service';
|
||||
import { REDDocumentViewer } from '../../pdf-viewer/services/document-viewer.service';
|
||||
import { AnnotationsListingService } from './annotations-listing.service';
|
||||
|
||||
@Injectable()
|
||||
export class AnnotationActionsService {
|
||||
constructor(
|
||||
@Inject(BASE_HREF) private readonly _baseHref: string,
|
||||
private readonly _ngZone: NgZone,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _manualRedactionService: ManualRedactionService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _dialogService: FilePreviewDialogService,
|
||||
private readonly _dialog: MatDialog,
|
||||
private readonly _pdf: PdfViewer,
|
||||
@ -57,11 +44,9 @@ export class AnnotationActionsService {
|
||||
private readonly _annotationManager: REDAnnotationManager,
|
||||
private readonly _annotationDrawService: AnnotationDrawService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _dictionariesMapService: DictionariesMapService,
|
||||
private readonly _state: FilePreviewStateService,
|
||||
private readonly _fileDataService: FileDataService,
|
||||
private readonly _skippedService: SkippedService,
|
||||
private readonly _listingService: AnnotationsListingService,
|
||||
) {}
|
||||
|
||||
private get _dossier(): Dossier {
|
||||
@ -71,29 +56,25 @@ export class AnnotationActionsService {
|
||||
acceptSuggestion($event: MouseEvent, annotations: AnnotationWrapper[]) {
|
||||
$event?.stopPropagation();
|
||||
const { dossierId, fileId } = this._state;
|
||||
this._processObsAndEmit(
|
||||
this._manualRedactionService.approve(
|
||||
annotations.map(a => a.id),
|
||||
dossierId,
|
||||
fileId,
|
||||
),
|
||||
);
|
||||
const ids = annotations.map(a => a.id);
|
||||
const request = this._manualRedactionService.approve(ids, dossierId, fileId);
|
||||
this.#processObsAndEmit(request);
|
||||
}
|
||||
|
||||
removeHighlights(highlights: AnnotationWrapper[]): void {
|
||||
const data = this._getHighlightOperationData(TextHighlightOperation.REMOVE, highlights);
|
||||
const data = this.#getHighlightOperationData(TextHighlightOperation.REMOVE, highlights);
|
||||
this._dialogService.openDialog('highlightAction', null, data);
|
||||
}
|
||||
|
||||
convertHighlights(highlights: AnnotationWrapper[]): void {
|
||||
const data = this._getHighlightOperationData(TextHighlightOperation.CONVERT, highlights);
|
||||
const data = this.#getHighlightOperationData(TextHighlightOperation.CONVERT, highlights);
|
||||
this._dialogService.openDialog('highlightAction', null, data);
|
||||
}
|
||||
|
||||
rejectSuggestion($event: MouseEvent, annotations: AnnotationWrapper[]) {
|
||||
$event?.stopPropagation();
|
||||
const { dossierId, fileId } = this._state;
|
||||
this._processObsAndEmit(
|
||||
this.#processObsAndEmit(
|
||||
this._manualRedactionService.declineOrRemove(
|
||||
annotations.map(a => a.id),
|
||||
dossierId,
|
||||
@ -107,7 +88,7 @@ export class AnnotationActionsService {
|
||||
const { dossierId, fileId } = this._state;
|
||||
const data = { dossier: this._dossier, annotations, hint };
|
||||
this._dialogService.openDialog('forceAnnotation', $event, data, (request: ILegalBasisChangeRequest) => {
|
||||
this._processObsAndEmit(
|
||||
this.#processObsAndEmit(
|
||||
this._manualRedactionService.bulkForce(
|
||||
annotations.map(a => ({ ...request, annotationId: a.id })),
|
||||
dossierId,
|
||||
@ -132,7 +113,7 @@ export class AnnotationActionsService {
|
||||
value: data.value,
|
||||
}));
|
||||
|
||||
this._processObsAndEmit(this._manualRedactionService.changeLegalBasis(body, dossierId, fileId));
|
||||
this.#processObsAndEmit(this._manualRedactionService.changeLegalBasis(body, dossierId, fileId));
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -151,7 +132,7 @@ export class AnnotationActionsService {
|
||||
removeFromDictionary,
|
||||
comment: result.comment,
|
||||
}));
|
||||
this._processObsAndEmit(this._manualRedactionService.removeOrSuggestRemove(body, dossierId, fileId, removeFromDictionary));
|
||||
this.#processObsAndEmit(this._manualRedactionService.removeOrSuggestRemove(body, dossierId, fileId, removeFromDictionary));
|
||||
});
|
||||
}
|
||||
|
||||
@ -164,7 +145,7 @@ export class AnnotationActionsService {
|
||||
type,
|
||||
comment,
|
||||
}));
|
||||
this._processObsAndEmit(this._manualRedactionService.recategorizeImage(body, dossierId, fileId));
|
||||
this.#processObsAndEmit(this._manualRedactionService.recategorizeImage(body, dossierId, fileId));
|
||||
});
|
||||
}
|
||||
|
||||
@ -173,7 +154,7 @@ export class AnnotationActionsService {
|
||||
|
||||
const { dossierId, fileId } = this._state;
|
||||
const modifyDictionary = annotations[0].isModifyDictionary;
|
||||
this._processObsAndEmit(
|
||||
this.#processObsAndEmit(
|
||||
this._manualRedactionService.undoRequest(
|
||||
annotations.map(a => a.id),
|
||||
dossierId,
|
||||
@ -194,205 +175,10 @@ export class AnnotationActionsService {
|
||||
const dialogClosed = dialogRef.afterClosed().pipe(filter(value => !!value && !!value.annotations));
|
||||
dialogClosed.subscribe(({ annotations, comment: commentText }) => {
|
||||
const comment = commentText ? { text: commentText } : undefined;
|
||||
this._processObsAndEmit(this._manualRedactionService.addRecommendation(annotations, dossierId, fileId, comment));
|
||||
this.#processObsAndEmit(this._manualRedactionService.addRecommendation(annotations, dossierId, fileId, comment));
|
||||
});
|
||||
}
|
||||
|
||||
getViewerAvailableActions(annotations: AnnotationWrapper[]): IHeaderElement[] {
|
||||
const dossier = this._state.dossier;
|
||||
|
||||
const availableActions: IHeaderElement[] = [];
|
||||
const annotationPermissions = annotations.map(annotation => ({
|
||||
annotation,
|
||||
permissions: AnnotationPermissions.forUser(
|
||||
this._permissionsService.isApprover(dossier),
|
||||
this._userService.currentUser,
|
||||
annotation,
|
||||
this._dictionariesMapService.get(dossier.dossierTemplateId),
|
||||
),
|
||||
}));
|
||||
|
||||
// you can only resize one annotation at a time
|
||||
const canResize = annotationPermissions.length === 1 && annotationPermissions[0].permissions.canResizeAnnotation;
|
||||
if (canResize) {
|
||||
const firstAnnotation = annotations[0];
|
||||
// if we already entered resize-mode previously
|
||||
if (firstAnnotation.resizing) {
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/check.svg'),
|
||||
title: this._translateService.instant('annotation-actions.resize-accept.label'),
|
||||
onClick: () =>
|
||||
this._ngZone.run(async () => {
|
||||
await this.acceptResize(null, firstAnnotation);
|
||||
}),
|
||||
});
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/close.svg'),
|
||||
title: this._translateService.instant('annotation-actions.resize-cancel.label'),
|
||||
onClick: () => this._ngZone.run(() => this.cancelResize(null, firstAnnotation)),
|
||||
});
|
||||
return availableActions;
|
||||
}
|
||||
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/resize.svg'),
|
||||
title: this._translateService.instant('annotation-actions.resize.label'),
|
||||
onClick: () => this._ngZone.run(() => this.resize(null, annotations[0])),
|
||||
});
|
||||
}
|
||||
|
||||
const canChangeLegalBasis = annotationPermissions.reduce((acc, next) => acc && next.permissions.canChangeLegalBasis, true);
|
||||
if (canChangeLegalBasis) {
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/edit.svg'),
|
||||
title: this._translateService.instant('annotation-actions.edit-reason.label'),
|
||||
onClick: () =>
|
||||
this._ngZone.run(() => {
|
||||
this.changeLegalBasis(null, annotations);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
const canRecategorizeImage = annotationPermissions.reduce((acc, next) => acc && next.permissions.canRecategorizeImage, true);
|
||||
if (canRecategorizeImage) {
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/thumb-down.svg'),
|
||||
title: this._translateService.instant('annotation-actions.recategorize-image'),
|
||||
onClick: () =>
|
||||
this._ngZone.run(() => {
|
||||
this.recategorizeImages(null, annotations);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
const canRemoveOrSuggestToRemoveFromDictionary = annotationPermissions.reduce(
|
||||
(acc, next) => acc && next.permissions.canRemoveOrSuggestToRemoveFromDictionary,
|
||||
true,
|
||||
);
|
||||
if (canRemoveOrSuggestToRemoveFromDictionary) {
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/remove-from-dict.svg'),
|
||||
title: this._translateService.instant('annotation-actions.remove-annotation.remove-from-dict'),
|
||||
onClick: () =>
|
||||
this._ngZone.run(() => {
|
||||
this.removeOrSuggestRemoveAnnotation(null, annotations, true);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
const canAcceptRecommendation = annotationPermissions.reduce((acc, next) => acc && next.permissions.canAcceptRecommendation, true);
|
||||
if (canAcceptRecommendation) {
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/check.svg'),
|
||||
title: this._translateService.instant('annotation-actions.accept-recommendation.label'),
|
||||
onClick: () =>
|
||||
this._ngZone.run(() => {
|
||||
this.convertRecommendationToAnnotation(null, annotations);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
const canAcceptSuggestion = annotationPermissions.reduce((acc, next) => acc && next.permissions.canAcceptSuggestion, true);
|
||||
if (canAcceptSuggestion) {
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/check.svg'),
|
||||
title: this._translateService.instant('annotation-actions.accept-suggestion.label'),
|
||||
onClick: () =>
|
||||
this._ngZone.run(() => {
|
||||
this.acceptSuggestion(null, annotations);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
const canUndo = annotationPermissions.reduce((acc, next) => acc && next.permissions.canUndo, true);
|
||||
if (canUndo) {
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/undo.svg'),
|
||||
title: this._translateService.instant('annotation-actions.undo'),
|
||||
onClick: () =>
|
||||
this._ngZone.run(() => {
|
||||
this.undoDirectAction(null, annotations);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
const canMarkAsFalsePositive = annotationPermissions.reduce((acc, next) => acc && next.permissions.canMarkAsFalsePositive, true);
|
||||
if (canMarkAsFalsePositive) {
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/thumb-down.svg'),
|
||||
title: this._translateService.instant('annotation-actions.remove-annotation.false-positive'),
|
||||
onClick: () =>
|
||||
this._ngZone.run(() => {
|
||||
this.markAsFalsePositive(null, annotations);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
const canForceRedaction = annotationPermissions.reduce((acc, next) => acc && next.permissions.canForceRedaction, true);
|
||||
if (canForceRedaction) {
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/thumb-up.svg'),
|
||||
title: this._translateService.instant('annotation-actions.force-redaction.label'),
|
||||
onClick: () =>
|
||||
this._ngZone.run(() => {
|
||||
this.forceAnnotation(null, annotations);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
const canForceHint = annotationPermissions.reduce((acc, next) => acc && next.permissions.canForceHint, true);
|
||||
if (canForceHint) {
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/thumb-up.svg'),
|
||||
title: this._translateService.instant('annotation-actions.force-hint.label'),
|
||||
onClick: () =>
|
||||
this._ngZone.run(() => {
|
||||
this.forceAnnotation(null, annotations, true);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
const canRejectSuggestion = annotationPermissions.reduce((acc, next) => acc && next.permissions.canRejectSuggestion, true);
|
||||
if (canRejectSuggestion) {
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/close.svg'),
|
||||
title: this._translateService.instant('annotation-actions.reject-suggestion'),
|
||||
onClick: () => this._ngZone.run(() => this.rejectSuggestion(null, annotations)),
|
||||
});
|
||||
}
|
||||
|
||||
const canRemoveOrSuggestToRemoveOnlyHere = annotationPermissions.reduce(
|
||||
(acc, next) => acc && next.permissions.canRemoveOrSuggestToRemoveOnlyHere,
|
||||
true,
|
||||
);
|
||||
if (canRemoveOrSuggestToRemoveOnlyHere) {
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/trash.svg'),
|
||||
title: this._translateService.instant('annotation-actions.remove-annotation.only-here'),
|
||||
onClick: () =>
|
||||
this._ngZone.run(() => {
|
||||
this.removeOrSuggestRemoveAnnotation(null, annotations, false);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
return availableActions;
|
||||
}
|
||||
|
||||
async resize($event: MouseEvent, annotationWrapper: AnnotationWrapper) {
|
||||
$event?.stopPropagation();
|
||||
|
||||
@ -415,10 +201,19 @@ export class AnnotationActionsService {
|
||||
}
|
||||
|
||||
async acceptResize($event: MouseEvent, annotation: AnnotationWrapper): Promise<void> {
|
||||
const fileId = this._state.fileId;
|
||||
const textAndPositions = await this._extractTextAndPositions(annotation.id);
|
||||
const textAndPositions = await this.#extractTextAndPositions(annotation.id);
|
||||
if (annotation.isRecommendation) {
|
||||
const recommendation = {
|
||||
...annotation,
|
||||
value: textAndPositions.text,
|
||||
positions: textAndPositions.positions,
|
||||
} as AnnotationWrapper;
|
||||
return this.convertRecommendationToAnnotation($event, [recommendation]);
|
||||
}
|
||||
|
||||
const text = annotation.rectangle ? annotation.value : annotation.isImage ? 'Image' : textAndPositions.text;
|
||||
const data = { annotation, text };
|
||||
|
||||
this._dialogService.openDialog('resizeAnnotation', $event, data, (result: { comment: string; updateDictionary: boolean }) => {
|
||||
const resizeRequest: IResizeRequest = {
|
||||
annotationId: annotation.id,
|
||||
@ -428,14 +223,9 @@ export class AnnotationActionsService {
|
||||
updateDictionary: result.updateDictionary,
|
||||
};
|
||||
|
||||
let obs;
|
||||
if (annotation.isRecommendation) {
|
||||
obs = this.#convertRecommendationToRedaction(resizeRequest, annotation, fileId);
|
||||
} else {
|
||||
obs = this._manualRedactionService.resizeOrSuggestResize([resizeRequest], this._dossier.id, fileId);
|
||||
}
|
||||
|
||||
this._processObsAndEmit(obs);
|
||||
const { fileId, dossierId } = this._state;
|
||||
const request = this._manualRedactionService.resizeOrSuggestResize([resizeRequest], dossierId, fileId);
|
||||
this.#processObsAndEmit(request);
|
||||
});
|
||||
}
|
||||
|
||||
@ -466,17 +256,7 @@ export class AnnotationActionsService {
|
||||
}));
|
||||
const { dossierId, fileId } = this._state;
|
||||
|
||||
this._processObsAndEmit(this._manualRedactionService.addAnnotation(requests, dossierId, fileId));
|
||||
}
|
||||
|
||||
#convertRecommendationToRedaction(resizeRequest: IResizeRequest, annotation: AnnotationWrapper, fileId: string) {
|
||||
const addRequest: IAddRedactionRequest = {
|
||||
...resizeRequest,
|
||||
comment: resizeRequest.comment ? { text: resizeRequest.comment } : null,
|
||||
reason: 'Dictionary Request',
|
||||
type: annotation.type,
|
||||
};
|
||||
return this._manualRedactionService.add([addRequest], this._dossier.id, fileId);
|
||||
this.#processObsAndEmit(this._manualRedactionService.addAnnotation(requests, dossierId, fileId));
|
||||
}
|
||||
|
||||
#generateRectangle(annotationWrapper: AnnotationWrapper) {
|
||||
@ -504,7 +284,7 @@ export class AnnotationActionsService {
|
||||
return annotation;
|
||||
}
|
||||
|
||||
private _getHighlightOperationData(operation: TextHighlightOperation, highlights: AnnotationWrapper[]) {
|
||||
#getHighlightOperationData(operation: TextHighlightOperation, highlights: AnnotationWrapper[]) {
|
||||
return {
|
||||
dossierId: this._state.dossierId,
|
||||
fileId: this._state.fileId,
|
||||
@ -516,7 +296,7 @@ export class AnnotationActionsService {
|
||||
};
|
||||
}
|
||||
|
||||
private _processObsAndEmit(obs: Observable<unknown>) {
|
||||
#processObsAndEmit(obs: Observable<unknown>) {
|
||||
obs.subscribe({
|
||||
next: () => this._fileDataService.annotationsChanged(),
|
||||
error: () => this._fileDataService.annotationsChanged(),
|
||||
@ -546,11 +326,7 @@ export class AnnotationActionsService {
|
||||
return annotation.value;
|
||||
}
|
||||
|
||||
private _convertPath(path: string): string {
|
||||
return this._baseHref + path;
|
||||
}
|
||||
|
||||
private async _extractTextAndPositions(annotationId: string) {
|
||||
async #extractTextAndPositions(annotationId: string) {
|
||||
const viewerAnnotation = this._annotationManager.get(annotationId);
|
||||
|
||||
const document = await this._documentViewer.PDFDoc;
|
||||
|
||||
@ -68,7 +68,7 @@ export class ManualRedactionService extends GenericService<IManualAddResponse> {
|
||||
addToDictionary: true,
|
||||
sourceId: annotation.annotationId,
|
||||
value: annotation.value,
|
||||
reason: annotation.legalBasis,
|
||||
reason: annotation.legalBasis ?? 'Dictionary Request',
|
||||
positions: annotation.positions,
|
||||
type: annotation.recommendationType,
|
||||
comment,
|
||||
|
||||
@ -0,0 +1,168 @@
|
||||
import { inject, Injectable, NgZone } from '@angular/core';
|
||||
import { AnnotationWrapper } from '../../../models/file/annotation.wrapper';
|
||||
import { AnnotationPermissions } from '../../../models/file/annotation.permissions';
|
||||
import { PermissionsService } from '../../../services/permissions.service';
|
||||
import { UserService } from '../../../services/user.service';
|
||||
import { DictionariesMapService } from '../../../services/entity-services/dictionaries-map.service';
|
||||
import { FilePreviewStateService } from './file-preview-state.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { AnnotationActionsService } from './annotation-actions.service';
|
||||
import { BASE_HREF_FN } from '../../../tokens';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { IHeaderElement } from '@red/domain';
|
||||
|
||||
@Injectable()
|
||||
export class PdfAnnotationActionsService {
|
||||
readonly #permissionsService = inject(PermissionsService);
|
||||
readonly #currentUser = inject(UserService).currentUser;
|
||||
readonly #dictionariesMapService = inject(DictionariesMapService);
|
||||
readonly #state = inject(FilePreviewStateService);
|
||||
readonly #translateService = inject(TranslateService);
|
||||
readonly #ngZone = inject(NgZone);
|
||||
readonly #convertPath = inject(BASE_HREF_FN);
|
||||
readonly #annotationActionsService = inject(AnnotationActionsService);
|
||||
|
||||
get(annotations: AnnotationWrapper[]): IHeaderElement[] {
|
||||
const availableActions: IHeaderElement[] = [];
|
||||
const permissions = this.#getAnnotationsPermissions(annotations);
|
||||
|
||||
// you can only resize one annotation at a time
|
||||
if (permissions.canResize) {
|
||||
const firstAnnotation = annotations[0];
|
||||
// if we already entered resize-mode previously
|
||||
if (firstAnnotation.resizing) {
|
||||
const acceptResizeButton = this.#getButton('check', _('annotation-actions.resize-accept.label'), () =>
|
||||
this.#annotationActionsService.acceptResize(null, firstAnnotation),
|
||||
);
|
||||
const cancelResizeButton = this.#getButton('close', _('annotation-actions.resize-cancel.label'), () =>
|
||||
this.#annotationActionsService.cancelResize(null, firstAnnotation),
|
||||
);
|
||||
|
||||
return [acceptResizeButton, cancelResizeButton];
|
||||
}
|
||||
|
||||
const resizeButton = this.#getButton('resize', _('annotation-actions.resize.label'), () =>
|
||||
this.#annotationActionsService.resize(null, firstAnnotation),
|
||||
);
|
||||
|
||||
availableActions.push(resizeButton);
|
||||
}
|
||||
|
||||
if (permissions.canChangeLegalBasis) {
|
||||
const editButton = this.#getButton('edit', _('annotation-actions.edit-reason.label'), () =>
|
||||
this.#annotationActionsService.changeLegalBasis(null, annotations),
|
||||
);
|
||||
availableActions.push(editButton);
|
||||
}
|
||||
|
||||
if (permissions.canRecategorizeImage) {
|
||||
const recategorizeButton = this.#getButton('thumb-down', _('annotation-actions.recategorize-image'), () =>
|
||||
this.#annotationActionsService.recategorizeImages(null, annotations),
|
||||
);
|
||||
availableActions.push(recategorizeButton);
|
||||
}
|
||||
|
||||
if (permissions.canRemoveOrSuggestToRemoveFromDictionary) {
|
||||
const removeFromDictButton = this.#getButton(
|
||||
'remove-from-dict',
|
||||
_('annotation-actions.remove-annotation.remove-from-dict'),
|
||||
() => this.#annotationActionsService.removeOrSuggestRemoveAnnotation(null, annotations, true),
|
||||
);
|
||||
availableActions.push(removeFromDictButton);
|
||||
}
|
||||
|
||||
if (permissions.canAcceptRecommendation) {
|
||||
const acceptRecommendationButton = this.#getButton('check', _('annotation-actions.accept-recommendation.label'), () =>
|
||||
this.#annotationActionsService.convertRecommendationToAnnotation(null, annotations),
|
||||
);
|
||||
availableActions.push(acceptRecommendationButton);
|
||||
}
|
||||
|
||||
if (permissions.canAcceptSuggestion) {
|
||||
const acceptSuggestionButton = this.#getButton('check', _('annotation-actions.accept-suggestion.label'), () =>
|
||||
this.#annotationActionsService.acceptSuggestion(null, annotations),
|
||||
);
|
||||
availableActions.push(acceptSuggestionButton);
|
||||
}
|
||||
|
||||
if (permissions.canUndo) {
|
||||
const undoButton = this.#getButton('undo', _('annotation-actions.undo'), () =>
|
||||
this.#annotationActionsService.undoDirectAction(null, annotations),
|
||||
);
|
||||
availableActions.push(undoButton);
|
||||
}
|
||||
|
||||
if (permissions.canMarkAsFalsePositive) {
|
||||
const markAsFalsePositiveButton = this.#getButton('thumb-down', _('annotation-actions.remove-annotation.false-positive'), () =>
|
||||
this.#annotationActionsService.markAsFalsePositive(null, annotations),
|
||||
);
|
||||
availableActions.push(markAsFalsePositiveButton);
|
||||
}
|
||||
|
||||
if (permissions.canForceRedaction) {
|
||||
const forceRedactionButton = this.#getButton('thumb-up', _('annotation-actions.force-redaction.label'), () =>
|
||||
this.#annotationActionsService.forceAnnotation(null, annotations),
|
||||
);
|
||||
availableActions.push(forceRedactionButton);
|
||||
}
|
||||
|
||||
if (permissions.canForceHint) {
|
||||
const forceHintButton = this.#getButton('thumb-up', _('annotation-actions.force-hint.label'), () =>
|
||||
this.#annotationActionsService.forceAnnotation(null, annotations, true),
|
||||
);
|
||||
availableActions.push(forceHintButton);
|
||||
}
|
||||
|
||||
if (permissions.canRejectSuggestion) {
|
||||
const rejectSuggestionButton = this.#getButton('close', _('annotation-actions.reject-suggestion'), () =>
|
||||
this.#annotationActionsService.rejectSuggestion(null, annotations),
|
||||
);
|
||||
availableActions.push(rejectSuggestionButton);
|
||||
}
|
||||
|
||||
if (permissions.canRemoveOrSuggestToRemoveOnlyHere) {
|
||||
const removeOrSuggestToRemoveOnlyHereButton = this.#getButton(
|
||||
'trash',
|
||||
_('annotation-actions.remove-annotation.only-here'),
|
||||
() => this.#annotationActionsService.removeOrSuggestRemoveAnnotation(null, annotations, false),
|
||||
);
|
||||
availableActions.push(removeOrSuggestToRemoveOnlyHereButton);
|
||||
}
|
||||
|
||||
return availableActions;
|
||||
}
|
||||
|
||||
#getButton(icon: string, title: string, action: () => void | Promise<void>): IHeaderElement {
|
||||
return {
|
||||
type: 'actionButton',
|
||||
img: this.#convertPath(`/assets/icons/general/${icon}.svg`),
|
||||
title: this.#translateService.instant(title),
|
||||
onClick: () => this.#ngZone.run(async () => action()),
|
||||
};
|
||||
}
|
||||
|
||||
#getAnnotationsPermissions(annotations: AnnotationWrapper[]) {
|
||||
const dossier = this.#state.dossier;
|
||||
const isApprover = this.#permissionsService.isApprover(dossier);
|
||||
const dictionaries = this.#dictionariesMapService.get(dossier.dossierTemplateId);
|
||||
|
||||
const permissions = annotations.map(a => AnnotationPermissions.forUser(isApprover, this.#currentUser, a, dictionaries));
|
||||
return {
|
||||
canResize: permissions.length === 1 && permissions[0].canResizeAnnotation,
|
||||
canChangeLegalBasis: permissions.reduce((acc, next) => acc && next.canChangeLegalBasis, true),
|
||||
canRecategorizeImage: permissions.reduce((acc, next) => acc && next.canRecategorizeImage, true),
|
||||
canRemoveOrSuggestToRemoveFromDictionary: permissions.reduce(
|
||||
(acc, next) => acc && next.canRemoveOrSuggestToRemoveFromDictionary,
|
||||
true,
|
||||
),
|
||||
canAcceptRecommendation: permissions.reduce((acc, next) => acc && next.canAcceptRecommendation, true),
|
||||
canAcceptSuggestion: permissions.reduce((acc, next) => acc && next.canAcceptSuggestion, true),
|
||||
canUndo: permissions.reduce((acc, next) => acc && next.canUndo, true),
|
||||
canMarkAsFalsePositive: permissions.reduce((acc, next) => acc && next.canMarkAsFalsePositive, true),
|
||||
canForceRedaction: permissions.reduce((acc, next) => acc && next.canForceRedaction, true),
|
||||
canForceHint: permissions.reduce((acc, next) => acc && next.canForceHint, true),
|
||||
canRejectSuggestion: permissions.reduce((acc, next) => acc && next.canRejectSuggestion, true),
|
||||
canRemoveOrSuggestToRemoveOnlyHere: permissions.reduce((acc, next) => acc && next.canRemoveOrSuggestToRemoveOnlyHere, true),
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -8,7 +8,6 @@ import {
|
||||
ManualRedactionEntryWrapper,
|
||||
} from '../../../models/file/manual-redaction-entry.wrapper';
|
||||
import { AnnotationDrawService } from '../../pdf-viewer/services/annotation-draw.service';
|
||||
import { AnnotationActionsService } from './annotation-actions.service';
|
||||
import { UserPreferenceService } from '../../../services/user-preference.service';
|
||||
import { BASE_HREF_FN, BaseHrefFn } from '../../../tokens';
|
||||
import { shareDistinctLast } from '@iqser/common-ui';
|
||||
@ -28,6 +27,7 @@ import { combineLatest, Observable, Subject } from 'rxjs';
|
||||
import { ViewModeService } from './view-mode.service';
|
||||
import { PermissionsService } from '../../../services/permissions.service';
|
||||
import { AnnotationsListingService } from './annotations-listing.service';
|
||||
import { PdfAnnotationActionsService } from './pdf-annotation-actions.service';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
import Quad = Core.Math.Quad;
|
||||
|
||||
@ -57,7 +57,7 @@ export class PdfProxyService {
|
||||
private readonly _ngZone: NgZone,
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
private readonly _annotationDrawService: AnnotationDrawService,
|
||||
private readonly _annotationActionsService: AnnotationActionsService,
|
||||
private readonly _pdfAnnotationActionsService: PdfAnnotationActionsService,
|
||||
private readonly _fileDataService: FileDataService,
|
||||
private readonly _viewerHeaderService: ViewerHeaderService,
|
||||
private readonly _viewModeService: ViewModeService,
|
||||
@ -191,7 +191,7 @@ export class PdfProxyService {
|
||||
]);
|
||||
}
|
||||
|
||||
const actions = this._annotationActionsService.getViewerAvailableActions(annotationWrappers);
|
||||
const actions = this._pdfAnnotationActionsService.get(annotationWrappers);
|
||||
this.instance.UI.annotationPopup.add(actions);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user