diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index 383a62684..c255390da 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -131,7 +131,7 @@ export const appModuleFactory = (config: AppConfig) => { features: { ANNOTATIONS: { color: 'aqua', - enabled: false, + enabled: true, level: NgxLoggerLevel.DEBUG, }, FILTERS: { @@ -147,7 +147,7 @@ export const appModuleFactory = (config: AppConfig) => { enabled: true, }, FILE: { - enabled: true, + enabled: false, }, CHANGES: { enabled: false, diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts index 80b37fe11..7a129a0fa 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts @@ -205,7 +205,6 @@ export class AnnotationActionsService { if (annotationWrapper.rectangle || annotationWrapper.imported || annotationWrapper.isImage) { this._annotationManager.delete(annotationWrapper); const rectangleAnnotation = this.#generateRectangle(annotationWrapper); - console.log(rectangleAnnotation); return this._annotationManager.add(rectangleAnnotation); } @@ -267,11 +266,9 @@ export class AnnotationActionsService { async cancelResize(annotationWrapper: AnnotationWrapper) { this._annotationManager.resizingAnnotationId = undefined; - this._annotationManager.resizingHasStarted = false; this._annotationManager.delete(annotationWrapper); await this._annotationDrawService.draw([annotationWrapper], this._skippedService.hideSkipped(), this._state.dossierTemplateId); this._annotationManager.deselect(); - await this._fileDataService.annotationsChanged(); } #generateRectangle(annotationWrapper: AnnotationWrapper) { diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts index fb5e55f91..7a3c63ca7 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts @@ -31,17 +31,14 @@ export class PdfAnnotationActionsService { const firstAnnotation = annotations[0]; // if we already entered resize-mode previously if (firstAnnotation.id === this.#annotationManager.resizingAnnotationId) { - if (this.#annotationManager.resizingHasStarted) { - const acceptResizeButton = this.#getButton('check', _('annotation-actions.resize-accept.label'), () => - this.#annotationActionsService.acceptResize(firstAnnotation), - ); - const cancelResizeButton = this.#getButton('close', _('annotation-actions.resize-cancel.label'), () => - this.#annotationActionsService.cancelResize(firstAnnotation), - ); + const acceptResizeButton = this.#getButton('check', _('annotation-actions.resize-accept.label'), () => + this.#annotationActionsService.acceptResize(firstAnnotation), + ); + const cancelResizeButton = this.#getButton('close', _('annotation-actions.resize-cancel.label'), () => + this.#annotationActionsService.cancelResize(firstAnnotation), + ); - return [acceptResizeButton, cancelResizeButton]; - } - return []; + return [acceptResizeButton, cancelResizeButton]; } const resizeButton = this.#getButton('resize', _('annotation-actions.resize.label'), () => diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts index 8db518c70..badf12fdf 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts @@ -286,7 +286,7 @@ export class PdfProxyService { this.handleAnnotationSelected([]); } - #processSelectedAnnotations(annotations: Annotation[], action) { + #processSelectedAnnotations(annotations: Annotation[], action: string) { let nextAnnotations: Annotation[]; if (action === 'deselected') { @@ -313,7 +313,10 @@ export class PdfProxyService { nextAnnotations = this._annotationManager.selected; } - this.#configureAnnotationSpecificActions(nextAnnotations); + const annotationWasResized = this._annotationManager.resizingAnnotationId && action === 'modify'; + if (!this._annotationManager.resizingAnnotationId || annotationWasResized) { + this.#configureAnnotationSpecificActions(nextAnnotations); + } if (!(annotations.length === 1 && annotations[0].ReadOnly)) { this._pdf.enable(TextPopups.ADD_RECTANGLE); @@ -344,7 +347,6 @@ export class PdfProxyService { // which is automatically converted to redaction when resized, // so the original annotation(wrapper) is removed this._annotationManager.resizingAnnotationId = undefined; - this._annotationManager.resizingHasStarted = false; return; } @@ -359,20 +361,20 @@ export class PdfProxyService { } #configureAnnotationSpecificActions(viewerAnnotations: Annotation[]) { + this._pdf.resetAnnotationActions(); + if (!this.canPerformActions()) { - return this._pdf.resetAnnotationActions(); + return; } const annotationWrappers = viewerAnnotations.map(va => this._fileDataService.find(va.Id)).filter(va => !!va); - this._pdf.resetAnnotationActions(); - if (annotationWrappers.length === 0) { return this.#configureRectangleAnnotationPopup(viewerAnnotations[0]); } // Add hide action as last item - const allAnnotationsHaveImageAction = annotationWrappers.reduce((acc, next) => acc && next.isImage, true); - if (allAnnotationsHaveImageAction) { + const allAreImage = annotationWrappers.reduce((acc, next) => acc && next.isImage, true); + if (allAreImage && !this._annotationManager.resizingAnnotationId) { const allAreVisible = viewerAnnotations.reduce((acc, next) => next.isVisible() && acc, true); const visibilityButton = { diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts index 5ed80f0db..80eabfe1f 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts @@ -4,8 +4,6 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { Core } from '@pdftron/webviewer'; import { IRectangle, ISectionRectangle, SuperTypes } from '@red/domain'; import { DefaultColorsService } from '@services/entity-services/default-colors.service'; -import { RedactionLogService } from '@services/files/redaction-log.service'; -import { UserPreferenceService } from '@users/user-preference.service'; import { hexToRgb } from '@utils/functions'; import { BoundingBox, Table } from '../../file-preview/services/tables.service'; import { REDAnnotationManager } from './annotation-manager.service'; @@ -31,8 +29,6 @@ export function getSectionRectangle(box: BoundingBox): ISectionRectangle { @Injectable() export class AnnotationDrawService { constructor( - private readonly _redactionLogService: RedactionLogService, - private readonly _userPreferenceService: UserPreferenceService, private readonly _annotationManager: REDAnnotationManager, private readonly _pdf: PdfViewer, private readonly _documentViewer: REDDocumentViewer, @@ -41,7 +37,7 @@ export class AnnotationDrawService { async draw(annotations: List, hideSkipped: boolean, dossierTemplateId: string) { try { - return this._pdf.runWithCleanup(() => this._draw(annotations, hideSkipped, dossierTemplateId)); + return this._pdf.runWithCleanup(() => this.#draw(annotations, hideSkipped, dossierTemplateId)); } catch (e) { console.error(e); } @@ -70,7 +66,7 @@ export class AnnotationDrawService { async drawTables(tables: Table[], page: number, dossierTemplateId: string) { const sections: Core.Annotations.RectangleAnnotation[] = []; tables.forEach(table => { - const section = this._computeSection(page, getSectionRectangle(table.boundingBox), dossierTemplateId); + const section = this.#computeSection(page, getSectionRectangle(table.boundingBox), dossierTemplateId); if (table.experimental) { section.StrokeColor = this.convertColor('#800080'); } else { @@ -80,7 +76,7 @@ export class AnnotationDrawService { table.cellsPerRow .flatMap(row => row) .forEach(row => { - const cellSection = this._computeSection(page, getSectionRectangle(row.boundingBox), dossierTemplateId); + const cellSection = this.#computeSection(page, getSectionRectangle(row.boundingBox), dossierTemplateId); if (table.experimental) { cellSection.StrokeColor = this.convertColor('#800080'); } else { @@ -93,10 +89,10 @@ export class AnnotationDrawService { await this._annotationManager.add(sections); } - private async _draw(annotationWrappers: List, hideSkipped: boolean, dossierTemplateId: string) { + async #draw(annotationWrappers: List, hideSkipped: boolean, dossierTemplateId: string) { const totalPages = this._pdf.totalPages(); const annotations = annotationWrappers - ?.map(annotation => this._computeAnnotation(annotation, hideSkipped, totalPages, dossierTemplateId)) + ?.map(annotation => this.#computeAnnotation(annotation, hideSkipped, totalPages, dossierTemplateId)) .filterTruthy(); if (!this._documentViewer.loaded()) { return; @@ -104,7 +100,7 @@ export class AnnotationDrawService { await this._annotationManager.add(annotations); } - private _computeSection(pageNumber: number, sectionRectangle: ISectionRectangle, dossierTemplateId: string) { + #computeSection(pageNumber: number, sectionRectangle: ISectionRectangle, dossierTemplateId: string) { const rectangleAnnot = this._pdf.rectangle(); const pageHeight = this._documentViewer.getHeight(pageNumber); const rectangle: IRectangle = { @@ -125,7 +121,7 @@ export class AnnotationDrawService { return rectangleAnnot; } - private _computeAnnotation(annotationWrapper: AnnotationWrapper, hideSkipped: boolean, totalPages: number, dossierTemplateId: string) { + #computeAnnotation(annotationWrapper: AnnotationWrapper, hideSkipped: boolean, totalPages: number, dossierTemplateId: string) { const pageNumber = this._pdf.isCompareMode() ? annotationWrapper.pageNumber * 2 - 1 : annotationWrapper.pageNumber; if (pageNumber > totalPages) { // skip imported annotations from files that have more pages than the current one @@ -150,7 +146,7 @@ export class AnnotationDrawService { } const annotation = this._pdf.textHighlight(); - annotation.Quads = this._rectanglesToQuads(annotationWrapper.positions, pageNumber); + annotation.Quads = this.#rectanglesToQuads(annotationWrapper.positions, pageNumber); annotation.Opacity = annotationWrapper.isChangeLogRemoved ? DEFAULT_REMOVED_ANNOTATION_OPACITY : DEFAULT_TEXT_ANNOTATION_OPACITY; annotation.setContents(annotationWrapper.content); annotation.PageNumber = pageNumber; @@ -190,12 +186,12 @@ export class AnnotationDrawService { return annotation; } - private _rectanglesToQuads(positions: IRectangle[], pageNumber: number): Quad[] { + #rectanglesToQuads(positions: IRectangle[], pageNumber: number): Quad[] { const pageHeight = this._documentViewer.getHeight(pageNumber); - return positions.map(p => this._rectangleToQuad(p, pageHeight)); + return positions.map(p => this.#rectangleToQuad(p, pageHeight)); } - private _rectangleToQuad(rectangle: IRectangle, pageHeight: number): Quad { + #rectangleToQuad(rectangle: IRectangle, pageHeight: number): Quad { const x1 = rectangle.topLeft.x; const y1 = pageHeight - (rectangle.topLeft.y + rectangle.height); diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts index 1e0ae111c..79f250bbd 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-manager.service.ts @@ -1,13 +1,13 @@ import { inject, Injectable, signal } from '@angular/core'; -import { Core } from '@pdftron/webviewer'; import type { List } from '@iqser/common-ui/lib/utils'; -import { AnnotationPredicate, DeleteAnnotationsOptions } from '../utils/types'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { Subject } from 'rxjs'; -import { asList, getId, isStringOrWrapper } from '../utils/functions'; +import { Core } from '@pdftron/webviewer'; import { getLast } from '@utils/functions'; -import { AnnotationToolNames } from '../utils/constants'; import { NGXLogger } from 'ngx-logger'; +import { Subject } from 'rxjs'; +import { AnnotationToolNames } from '../utils/constants'; +import { asList, getId, isStringOrWrapper } from '../utils/functions'; +import { AnnotationPredicate, DeleteAnnotationsOptions } from '../utils/types'; import AnnotationManager = Core.AnnotationManager; import Annotation = Core.Annotations.Annotation; @@ -19,7 +19,6 @@ export class REDAnnotationManager { readonly #annotationSelected$ = new Subject<[Annotation[], string]>(); readonly annotationSelected$ = this.#annotationSelected$.asObservable(); resizingAnnotationId?: string = undefined; - resizingHasStarted = false; readonly hidden = this.#hidden.asReadonly(); get selected() { @@ -141,14 +140,12 @@ export class REDAnnotationManager { // when a rectangle is drawn, // it returns one annotation with tool name 'AnnotationCreateRectangle; // this will auto select rectangle after drawing - if (annotations.length === 1 && annotations[0].ToolName === AnnotationToolNames.AnnotationCreateRectangle) { - this.#manager.selectAnnotations(annotations); - annotations[0].disableRotationControl(); - } - if (action === 'modify' && options.source === 'resize' && !this.resizingHasStarted) { - this.resizingHasStarted = true; - this.#annotationSelected$.next([annotations, action]); + const annotation = annotations.length === 1 ? annotations[0] : undefined; + if (annotation && annotation.ToolName === AnnotationToolNames.AnnotationCreateRectangle) { + this.#manager.selectAnnotation(annotation); + annotation.disableRotationControl(); } + this.#annotationSelected$.next([annotations, action]); }); } diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts index d39f33fb4..4e6679ea3 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts @@ -1,18 +1,18 @@ import { effect, inject, Injectable, Signal, signal } from '@angular/core'; +import { toObservable } from '@angular/core/rxjs-interop'; +import { ActivatedRoute } from '@angular/router'; +import { log } from '@iqser/common-ui/lib/utils'; import { Core } from '@pdftron/webviewer'; +import { RotationType, RotationTypes } from '@red/domain'; +import { UserPreferenceService } from '@users/user-preference.service'; import { NGXLogger } from 'ngx-logger'; import { BehaviorSubject, fromEvent, Observable } from 'rxjs'; import { filter, tap } from 'rxjs/operators'; -import { ActivatedRoute } from '@angular/router'; -import { PdfViewer } from './pdf-viewer.service'; -import { UserPreferenceService } from '@users/user-preference.service'; -import { log } from '@iqser/common-ui/lib/utils'; -import { stopAndPrevent, stopAndPreventIfNotAllowed } from '../utils/functions'; -import { RotationType, RotationTypes } from '@red/domain'; import { AnnotationToolNames } from '../utils/constants'; -import { toObservable } from '@angular/core/rxjs-interop'; -import DocumentViewer = Core.DocumentViewer; +import { stopAndPrevent, stopAndPreventIfNotAllowed } from '../utils/functions'; +import { PdfViewer } from './pdf-viewer.service'; import Color = Core.Annotations.Color; +import DocumentViewer = Core.DocumentViewer; import Quad = Core.Math.Quad; @Injectable() diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts index 40944b5ba..0c4cbb236 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts @@ -1,26 +1,26 @@ import { DestroyRef, inject, Injectable, signal, Signal } from '@angular/core'; -import WebViewer, { Core, WebViewerInstance, WebViewerOptions } from '@pdftron/webviewer'; -import { ErrorService, getConfig } from '@iqser/common-ui'; -import { AppConfig, File, IHeaderElement } from '@red/domain'; +import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; -import { map, startWith } from 'rxjs/operators'; -import { combineLatest, fromEvent, Observable } from 'rxjs'; -import { NGXLogger } from 'ngx-logger'; -import { DISABLED_HOTKEYS, DOCUMENT_LOADING_ERROR, SEARCH_OPTIONS, USELESS_ELEMENTS } from '../utils/constants'; -import { Rgb } from '../utils/types'; -import { asList } from '../utils/functions'; +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { environment } from '@environments/environment'; +import { ErrorService, getConfig } from '@iqser/common-ui'; +import { BASE_HREF_FN, shareDistinctLast } from '@iqser/common-ui/lib/utils'; import { TranslateService } from '@ngx-translate/core'; +import WebViewer, { Core, WebViewerInstance, WebViewerOptions } from '@pdftron/webviewer'; +import { AppConfig, File, IHeaderElement } from '@red/domain'; import { LicenseService } from '@services/license.service'; import { UserPreferenceService } from '@users/user-preference.service'; -import { environment } from '@environments/environment'; -import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop'; -import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { BASE_HREF_FN, shareDistinctLast } from '@iqser/common-ui/lib/utils'; -import TextTool = Core.Tools.TextTool; +import { NGXLogger } from 'ngx-logger'; +import { combineLatest, fromEvent, Observable } from 'rxjs'; +import { map, startWith } from 'rxjs/operators'; +import { DISABLED_HOTKEYS, DOCUMENT_LOADING_ERROR, SEARCH_OPTIONS, USELESS_ELEMENTS } from '../utils/constants'; +import { asList } from '../utils/functions'; +import { Rgb } from '../utils/types'; import Annotation = Core.Annotations.Annotation; import TextHighlightAnnotation = Core.Annotations.TextHighlightAnnotation; import DocumentViewer = Core.DocumentViewer; import Quad = Core.Math.Quad; +import TextTool = Core.Tools.TextTool; @Injectable() export class PdfViewer { @@ -40,6 +40,7 @@ export class PdfViewer { }, }; readonly #destroyRef = inject(DestroyRef); + readonly #logger = inject(NGXLogger); readonly #totalPages = signal(0); readonly currentPage$ = inject(ActivatedRoute).queryParamMap.pipe( map(params => Number(params.get('page') ?? '1')), @@ -118,6 +119,7 @@ export class PdfViewer { resetAnnotationActions() { if (this.#instance.UI.annotationPopup.getItems().length) { + this.#logger.info('[PDF] Reset annotation actions'); this.#instance.UI.annotationPopup.update([]); } }