diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts b/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts index 282e6f611..89ebb9d0b 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts @@ -8,7 +8,6 @@ import { AnnotationReferencesService } from '../../services/annotation-reference import { MultiSelectService } from '../../services/multi-select.service'; import { FilePreviewStateService } from '../../services/file-preview-state.service'; import { HelpModeService } from '@iqser/common-ui'; -import { FileDataService } from '../../services/file-data.service'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { ViewModeService } from '../../services/view-mode.service'; import { REDAnnotationManager } from '../../../pdf-viewer/services/annotation-manager.service'; @@ -43,7 +42,6 @@ export class AnnotationActionsComponent implements OnChanges { private readonly _annotationManager: REDAnnotationManager, private readonly _state: FilePreviewStateService, private readonly _permissionsService: PermissionsService, - private readonly _fileDataService: FileDataService, private readonly _dictionariesMapService: DictionariesMapService, ) {} @@ -96,14 +94,14 @@ export class AnnotationActionsComponent implements OnChanges { $event.stopPropagation(); this._annotationManager.hide(this.viewerAnnotations); this._annotationManager.deselect(); - this._fileDataService.updateHiddenAnnotations(this.viewerAnnotations, true); + this._annotationManager.hidden.add(this.viewerAnnotations[0].Id); } showAnnotation($event: MouseEvent) { $event.stopPropagation(); this._annotationManager.show(this.viewerAnnotations); this._annotationManager.deselect(); - this._fileDataService.updateHiddenAnnotations(this.viewerAnnotations, false); + this._annotationManager.hidden.delete(this.viewerAnnotations[0].Id); } resize($event: MouseEvent) { diff --git a/apps/red-ui/src/app/modules/file-preview/components/pdf-paginator/pdf-paginator.component.ts b/apps/red-ui/src/app/modules/file-preview/components/pdf-paginator/pdf-paginator.component.ts index 6cb1f2126..08d98fc95 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/pdf-paginator/pdf-paginator.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/pdf-paginator/pdf-paginator.component.ts @@ -8,7 +8,7 @@ import { ManualRedactionEntryWrapper, } from '@models/file/manual-redaction-entry.wrapper'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { AnnotationDrawService } from '../../services/annotation-draw.service'; +import { AnnotationDrawService } from '../../../pdf-viewer/services/annotation-draw.service'; import { AnnotationActionsService } from '../../services/annotation-actions.service'; import { UserPreferenceService } from '@services/user-preference.service'; import { BASE_HREF_FN, BaseHrefFn } from '../../../../tokens'; @@ -26,7 +26,12 @@ import { ManualRedactionService } from '../../services/manual-redaction.service' import { PdfViewer } from '../../../pdf-viewer/services/pdf-viewer.service'; import { REDAnnotationManager } from '../../../pdf-viewer/services/annotation-manager.service'; import { translateQuads } from '../../../../utils'; -import { ROTATION_ACTION_BUTTONS } from '../../../pdf-viewer/utils/constants'; +import { + ALLOWED_ACTIONS_WHEN_PAGE_EXCLUDED, + HEADER_ITEMS_TO_TOGGLE, + ROTATION_ACTION_BUTTONS, + TEXT_POPUPS_TO_TOGGLE, +} from '../../../pdf-viewer/utils/constants'; import Annotation = Core.Annotations.Annotation; @Component({ @@ -163,7 +168,7 @@ export class PdfPaginatorComponent extends AutoUnsubscribe implements OnInit, On private _configureElements() { const dossierTemplateId = this.dossier.dossierTemplateId; - const color = this._annotationDrawService.getAndConvertColor(dossierTemplateId, 'manual'); + const color = this._annotationDrawService.getAndConvertColor(dossierTemplateId, dossierTemplateId, 'manual'); this.pdf.setRectangleToolStyles(color); } @@ -197,11 +202,12 @@ export class PdfPaginatorComponent extends AutoUnsubscribe implements OnInit, On this._ngZone.run(() => { if (allAreVisible) { this._annotationManager.hide(viewerAnnotations); + this._annotationManager.hidden.add(viewerAnnotations[0].Id); } else { this._annotationManager.show(viewerAnnotations); + this._annotationManager.hidden.delete(viewerAnnotations[0].Id); } this._annotationManager.deselect(); - this._fileDataService.updateHiddenAnnotations(viewerAnnotations, allAreVisible); }); }, }, @@ -305,13 +311,6 @@ export class PdfPaginatorComponent extends AutoUnsubscribe implements OnInit, On } private _handleCustomActions() { - const textPopupsToToggle = [TextPopups.ADD_REDACTION, TextPopups.ADD_RECTANGLE, TextPopups.ADD_FALSE_POSITIVE]; - const headerItemsToToggle = [ - HeaderElements.SHAPE_TOOL_GROUP_BUTTON, - HeaderElements.ROTATE_LEFT_BUTTON, - HeaderElements.ROTATE_RIGHT_BUTTON, - ]; - const isCurrentPageExcluded = this._state.file.isPageExcluded(this.pdf.currentPage); if (this.canPerformActions && !isCurrentPageExcluded) { @@ -320,8 +319,8 @@ export class PdfPaginatorComponent extends AutoUnsubscribe implements OnInit, On } catch (e) { // happens } - this.pdf.enable(textPopupsToToggle); - this._viewerHeaderService.enable(headerItemsToToggle); + this.pdf.enable(TEXT_POPUPS_TO_TOGGLE); + this._viewerHeaderService.enable(HEADER_ITEMS_TO_TOGGLE); if (this._selectedText.length > 2) { this.pdf.enable([TextPopups.ADD_DICTIONARY, TextPopups.ADD_FALSE_POSITIVE]); @@ -330,17 +329,14 @@ export class PdfPaginatorComponent extends AutoUnsubscribe implements OnInit, On return; } - let textPopupElementsToDisable = [...textPopupsToToggle]; - let headerElementsToDisable = [...headerItemsToToggle]; + let textPopupElementsToDisable = [...TEXT_POPUPS_TO_TOGGLE]; + let headerElementsToDisable = [...HEADER_ITEMS_TO_TOGGLE]; if (isCurrentPageExcluded) { - const allowedActionsWhenPageExcluded: string[] = [ - TextPopups.ADD_RECTANGLE, - TextPopups.ADD_REDACTION, - HeaderElements.SHAPE_TOOL_GROUP_BUTTON, - ]; - textPopupElementsToDisable = textPopupElementsToDisable.filter(element => !allowedActionsWhenPageExcluded.includes(element)); - headerElementsToDisable = headerElementsToDisable.filter(element => !allowedActionsWhenPageExcluded.includes(element)); + textPopupElementsToDisable = textPopupElementsToDisable.filter( + element => !ALLOWED_ACTIONS_WHEN_PAGE_EXCLUDED.includes(element), + ); + headerElementsToDisable = headerElementsToDisable.filter(element => !ALLOWED_ACTIONS_WHEN_PAGE_EXCLUDED.includes(element)); } else { this.instance.UI.disableTools(['AnnotationCreateRectangle']); } diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts index 5bbd9831f..2cd235d1a 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts @@ -4,7 +4,6 @@ import { MultiSelectService } from './services/multi-select.service'; import { DocumentInfoService } from './services/document-info.service'; import { CommentingService } from './services/commenting.service'; import { SkippedService } from './services/skipped.service'; -import { AnnotationDrawService } from './services/annotation-draw.service'; import { AnnotationActionsService } from './services/annotation-actions.service'; import { FilePreviewStateService } from './services/file-preview-state.service'; import { AnnotationReferencesService } from './services/annotation-references.service'; @@ -23,7 +22,6 @@ export const filePreviewScreenProviders = [ DocumentInfoService, CommentingService, SkippedService, - AnnotationDrawService, AnnotationActionsService, FilePreviewStateService, AnnotationReferencesService, diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts index a455e9a55..0dd1e0f11 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts @@ -21,7 +21,7 @@ import { import { MatDialogRef, MatDialogState } from '@angular/material/dialog'; import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { AnnotationDrawService } from './services/annotation-draw.service'; +import { AnnotationDrawService } from '../pdf-viewer/services/annotation-draw.service'; import { AnnotationProcessingService } from './services/annotation-processing.service'; import { File, ViewMode, ViewModes } from '@red/domain'; import { PermissionsService } from '@services/permissions.service'; @@ -54,6 +54,7 @@ import { PdfViewer } from '../pdf-viewer/services/pdf-viewer.service'; import { REDAnnotationManager } from '../pdf-viewer/services/annotation-manager.service'; import { ViewerHeaderService } from '../pdf-viewer/services/viewer-header.service'; import { ROTATION_ACTION_BUTTONS } from '../pdf-viewer/utils/constants'; +import { SkippedService } from './services/skipped.service'; import Annotation = Core.Annotations.Annotation; @Component({ @@ -98,6 +99,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni private readonly _loadingService: LoadingService, private readonly _filesMapService: FilesMapService, private readonly _dossiersService: DossiersService, + private readonly _skippedService: SkippedService, private readonly _fileDataService: FileDataService, private readonly _viewModeService: ViewModeService, private readonly _changeDetectorRef: ChangeDetectorRef, @@ -185,7 +187,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni this._loadingService.start(); this._annotationManager.hide(annotations); const highlights = await this._fileDataService.loadTextHighlights(); - await this._annotationDrawService.draw(highlights); + await this._annotationDrawService.draw(highlights, this.state.dossierTemplateId, this._skippedService.hideSkipped); this._loadingService.stop(); } } @@ -211,6 +213,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni await this.ngOnInit(); await this._fileDataService.loadRedactionLog(); + this._viewerHeaderService.updateElements(); this._lastPage = previousRoute.queryParams.page; this._changeDetectorRef.markForCheck(); } @@ -557,7 +560,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni this._handleDeltaAnnotationFilters(currentFilters, this._fileDataService.all); } - await this._annotationDrawService.draw(newAnnotations); + await this._annotationDrawService.draw(newAnnotations, this.state.dossierTemplateId, this._skippedService.hideSkipped); this._logger.info(`[ANNOTATIONS] Redraw time: ${new Date().getTime() - startTime} ms for ${newAnnotations.length} annotations`); } 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 5c04fb851..262e32060 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 @@ -20,7 +20,7 @@ import { TextHighlightOperation, } from '@red/domain'; import { toPosition } from '../utils/pdf-calculation.utils'; -import { AnnotationDrawService } from './annotation-draw.service'; +import { AnnotationDrawService } from '../../pdf-viewer/services/annotation-draw.service'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { AcceptRecommendationData, @@ -36,6 +36,7 @@ import { DictionariesMapService } from '@services/entity-services/dictionaries-m 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 Quad = Core.Math.Quad; @Injectable() @@ -56,6 +57,7 @@ export class AnnotationActionsService { private readonly _dictionariesMapService: DictionariesMapService, private readonly _state: FilePreviewStateService, private readonly _fileDataService: FileDataService, + private readonly _skippedService: SkippedService, private readonly _listingService: ListingService, ) {} @@ -438,7 +440,7 @@ export class AnnotationActionsService { annotationWrapper.resizing = false; this._annotationManager.delete(annotationWrapper); - await this._annotationDrawService.draw([annotationWrapper]); + await this._annotationDrawService.draw([annotationWrapper], this._state.dossierTemplateId, this._skippedService.hideSkipped); this._annotationManager.deselect(); await this._fileDataService.annotationsChanged(); } @@ -474,7 +476,12 @@ export class AnnotationActionsService { annotation.ReadOnly = false; annotation.Hidden = false; annotation.disableRotationControl(); - annotation.FillColor = this._annotationDrawService.getAndConvertColor(annotationWrapper.superType, annotationWrapper.type); + const dossierTemplateId = this._state.dossierTemplateId; + annotation.FillColor = this._annotationDrawService.getAndConvertColor( + annotationWrapper.superType, + dossierTemplateId, + annotationWrapper.type, + ); annotation.StrokeColor = annotation.FillColor; annotation.Opacity = 0.6; annotation.StrokeThickness = 1; diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts index 6bbedecda..637a0d150 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts @@ -19,7 +19,6 @@ import dayjs from 'dayjs'; import { NGXLogger } from 'ngx-logger'; import { MultiSelectService } from './multi-select.service'; import { FilesService } from '@services/files/files.service'; -import Annotation = Core.Annotations.Annotation; const DELTA_VIEW_TIME = 10 * 60 * 1000; // 10 minutes; @@ -113,19 +112,6 @@ export class FileDataService extends EntitiesService { return firstValueFrom(redactionLog$.pipe(tap(redactionLog => this.#redactionLog$.next(redactionLog)))); } - updateHiddenAnnotations(viewerAnnotations: Annotation[], hidden: boolean) { - const annotationId = viewerAnnotations[0].Id; - if (hidden) { - this.hiddenAnnotations.add(annotationId); - } else { - this.hiddenAnnotations.delete(annotationId); - } - } - - isHidden(annotationId: string) { - return this.hiddenAnnotations.has(annotationId); - } - #checkMissingTypes() { if (this.missingTypes.size > 0) { this._toaster.error(_('error.missing-types'), { diff --git a/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.module.ts b/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.module.ts index a6a6b4ff0..676e22ce6 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.module.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.module.ts @@ -9,11 +9,12 @@ import { TooltipsService } from './services/tooltips.service'; import { ViewerHeaderService } from './services/viewer-header.service'; import { PaginatorComponent } from './components/paginator/paginator.component'; import { MatIconModule } from '@angular/material/icon'; +import { AnnotationDrawService } from './services/annotation-draw.service'; @NgModule({ declarations: [PdfViewerComponent, CompareFileInputComponent, PaginatorComponent], exports: [PdfViewerComponent], imports: [CommonModule, MatIconModule], - providers: [PdfViewer, REDAnnotationManager, PageRotationService, TooltipsService, ViewerHeaderService], + providers: [PdfViewer, REDAnnotationManager, PageRotationService, TooltipsService, ViewerHeaderService, AnnotationDrawService], }) export class PdfViewerModule {} diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-draw.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts similarity index 71% rename from apps/red-ui/src/app/modules/file-preview/services/annotation-draw.service.ts rename to apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts index 8916a0624..28737f976 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-draw.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts @@ -1,19 +1,19 @@ import { Injectable } from '@angular/core'; import { Core } from '@pdftron/webviewer'; import { hexToRgb } from '../../../utils'; -import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { UserPreferenceService } from '@services/user-preference.service'; -import { RedactionLogService } from '@services/files/redaction-log.service'; -import { environment } from '@environments/environment'; +import { AnnotationWrapper } from '../../../models/file/annotation.wrapper'; +import { UserPreferenceService } from '../../../services/user-preference.service'; +import { RedactionLogService } from '../../../services/files/redaction-log.service'; +import { environment } from '../../../../environments/environment'; -import { IRectangle, ISectionGrid, ISectionRectangle } from '@red/domain'; -import { SkippedService } from './skipped.service'; +import { DOSSIER_ID, FILE_ID, IRectangle, ISectionGrid, ISectionRectangle } from '@red/domain'; import { firstValueFrom } from 'rxjs'; -import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; -import { FilePreviewStateService } from './file-preview-state.service'; -import { FileDataService } from './file-data.service'; -import { SuperTypes } from '@models/file/super-types'; -import { PdfViewer } from '../../pdf-viewer/services/pdf-viewer.service'; +import { DictionariesMapService } from '../../../services/entity-services/dictionaries-map.service'; +import { SuperTypes } from '../../../models/file/super-types'; +import { PdfViewer } from './pdf-viewer.service'; +import { ActivatedRoute } from '@angular/router'; +import { REDAnnotationManager } from './annotation-manager.service'; +import { List } from '@iqser/common-ui'; import Annotation = Core.Annotations.Annotation; import Quad = Core.Math.Quad; @@ -26,39 +26,18 @@ export class AnnotationDrawService { private readonly _dictionariesMapService: DictionariesMapService, private readonly _redactionLogService: RedactionLogService, private readonly _userPreferenceService: UserPreferenceService, - private readonly _skippedService: SkippedService, + private readonly _activatedRoute: ActivatedRoute, + private readonly _annotationManager: REDAnnotationManager, private readonly _pdf: PdfViewer, - private readonly _state: FilePreviewStateService, - private readonly _fileDataService: FileDataService, ) {} - draw(annotations: readonly AnnotationWrapper[]) { + draw(annotations: List, dossierTemplateId: string, hideSkipped: boolean) { const licenseKey = environment.licenseKey ? atob(environment.licenseKey) : null; - return this._pdf.PDFNet.runWithCleanup(() => this._draw(annotations), licenseKey); + return this._pdf.PDFNet.runWithCleanup(() => this._draw(annotations, dossierTemplateId, hideSkipped), licenseKey); } - getColor(superType: string, dictionary?: string) { - let color: string; - switch (superType) { - case SuperTypes.Hint: - case SuperTypes.Redaction: - color = this._dictionariesMapService.getDictionaryColor(dictionary, this._state.dossierTemplateId); - break; - case SuperTypes.Recommendation: - color = this._dictionariesMapService.getDictionaryColor(dictionary, this._state.dossierTemplateId, true); - break; - case SuperTypes.Skipped: - color = this._dictionariesMapService.getDictionaryColor(superType, this._state.dossierTemplateId); - break; - default: - color = this._dictionariesMapService.getDictionaryColor(superType, this._state.dossierTemplateId); - break; - } - return color; - } - - getAndConvertColor(superType: string, dictionary?: string) { - return this.convertColor(this.getColor(superType, dictionary)); + getAndConvertColor(superType: string, dossierTemplateId: string, dictionary?: string) { + return this.convertColor(this.#getColor(superType, dossierTemplateId, dictionary)); } convertColor(hexColor: string) { @@ -81,25 +60,48 @@ export class AnnotationDrawService { return this._pdf.quad(x1, y1, x2, y2, x3, y3, x4, y4); } - private async _draw(annotationWrappers: readonly AnnotationWrapper[]) { - const annotations = annotationWrappers.map(annotation => this._computeAnnotation(annotation)).filter(a => !!a); + #getColor(superType: string, dossierTemplateId: string, dictionary?: string) { + let color: string; + switch (superType) { + case SuperTypes.Hint: + case SuperTypes.Redaction: + color = this._dictionariesMapService.getDictionaryColor(dictionary, dossierTemplateId); + break; + case SuperTypes.Recommendation: + color = this._dictionariesMapService.getDictionaryColor(dictionary, dossierTemplateId, true); + break; + case SuperTypes.Skipped: + color = this._dictionariesMapService.getDictionaryColor(superType, dossierTemplateId); + break; + default: + color = this._dictionariesMapService.getDictionaryColor(superType, dossierTemplateId); + break; + } + return color; + } + + private async _draw(annotationWrappers: List, dossierTemplateId: string, hideSkipped: boolean) { + const annotations = annotationWrappers + .map(annotation => this._computeAnnotation(annotation, dossierTemplateId, hideSkipped)) + .filter(a => !!a); this._pdf.annotationManager.addAnnotations(annotations, { imported: true }); await this._pdf.annotationManager.drawAnnotationsFromList(annotations); if (this._userPreferenceService.areDevFeaturesEnabled) { - const { dossierId, fileId } = this._state; + const dossierId = this._activatedRoute.snapshot.paramMap.get(DOSSIER_ID); + const fileId = this._activatedRoute.snapshot.paramMap.get(FILE_ID); const sectionsGrid$ = this._redactionLogService.getSectionGrid(dossierId, fileId); const sectionsGrid = await firstValueFrom(sectionsGrid$).catch(() => ({ rectanglesPerPage: {} })); - await this._drawSections(sectionsGrid); + await this._drawSections(sectionsGrid, dossierTemplateId); } } - private async _drawSections(sectionGrid: ISectionGrid) { + private async _drawSections(sectionGrid: ISectionGrid, dossierTemplateId: string) { const sections: Core.Annotations.RectangleAnnotation[] = []; for (const page of Object.keys(sectionGrid.rectanglesPerPage)) { const sectionRectangles = sectionGrid.rectanglesPerPage[page]; sectionRectangles.forEach(sectionRectangle => { - sections.push(this._computeSection(parseInt(page, 10), sectionRectangle)); + sections.push(this._computeSection(dossierTemplateId, parseInt(page, 10), sectionRectangle)); // sectionRectangle.tableCells?.forEach(cell =>{ // sections.push(this.computeSection(activeViewer, parseInt(page, 10), cell)); // }) @@ -109,7 +111,7 @@ export class AnnotationDrawService { await this._pdf.annotationManager.drawAnnotationsFromList(sections); } - private _computeSection(pageNumber: number, sectionRectangle: ISectionRectangle) { + private _computeSection(dossierTemplateId: string, pageNumber: number, sectionRectangle: ISectionRectangle) { const rectangleAnnot = this._pdf.rectangle(); const pageHeight = this._pdf.getPageHeight(pageNumber); const rectangle: IRectangle = { @@ -124,13 +126,13 @@ export class AnnotationDrawService { rectangleAnnot.Width = rectangle.width + 2; rectangleAnnot.Height = rectangle.height + 2; rectangleAnnot.ReadOnly = true; - rectangleAnnot.StrokeColor = this.getAndConvertColor('analysis', 'analysis'); + rectangleAnnot.StrokeColor = this.getAndConvertColor('analysis', dossierTemplateId, 'analysis'); rectangleAnnot.StrokeThickness = 1; return rectangleAnnot; } - private _computeAnnotation(annotationWrapper: AnnotationWrapper) { + private _computeAnnotation(annotationWrapper: AnnotationWrapper, dossierTemplateId: string, hideSkipped: boolean) { const pageNumber = this._pdf.isCompare ? annotationWrapper.pageNumber * 2 - 1 : annotationWrapper.pageNumber; if (pageNumber > this._pdf.pageCount) { // skip imported annotations from files that have more pages than the current one @@ -159,23 +161,26 @@ export class AnnotationDrawService { annotation.Opacity = annotationWrapper.isChangeLogRemoved ? DEFAULT_REMOVED_ANNOTATION_OPACITY : DEFAULT_TEXT_ANNOTATION_OPACITY; annotation.setContents(annotationWrapper.content); annotation.PageNumber = pageNumber; - annotation.StrokeColor = this.getAndConvertColor(annotationWrapper.superType, annotationWrapper.type); + annotation.StrokeColor = this.getAndConvertColor(annotationWrapper.superType, dossierTemplateId, annotationWrapper.type); annotation.Id = annotationWrapper.id; annotation.ReadOnly = true; annotation.Hidden = annotationWrapper.isChangeLogRemoved || - (this._skippedService.hideSkipped && annotationWrapper.isSkipped) || + (hideSkipped && annotationWrapper.isSkipped) || annotationWrapper.isOCR || - this._fileDataService.isHidden(annotationWrapper.annotationId); + this._annotationManager.isHidden(annotationWrapper.annotationId); annotation.setCustomData('redact-manager', 'true'); annotation.setCustomData('redaction', String(annotationWrapper.previewAnnotation)); annotation.setCustomData('skipped', String(annotationWrapper.isSkipped)); annotation.setCustomData('changeLog', String(annotationWrapper.isChangeLogEntry)); annotation.setCustomData('changeLogRemoved', String(annotationWrapper.isChangeLogRemoved)); annotation.setCustomData('opacity', String(annotation.Opacity)); - annotation.setCustomData('redactionColor', String(this.getColor('redaction', 'preview'))); - annotation.setCustomData('annotationColor', String(this.getColor(annotationWrapper.superType, annotationWrapper.type))); + annotation.setCustomData('redactionColor', String(this.#getColor('redaction', dossierTemplateId, 'preview'))); + annotation.setCustomData( + 'annotationColor', + String(this.#getColor(annotationWrapper.superType, dossierTemplateId, annotationWrapper.type)), + ); return annotation; } 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 c3d4d00be..8b2cf370e 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 @@ -12,6 +12,8 @@ import Annotation = Core.Annotations.Annotation; @Injectable() export class REDAnnotationManager { annotationSelected$: Observable<[Annotation[], string]>; + readonly hidden = new Set(); + #manager: AnnotationManager; get selected() { @@ -33,6 +35,10 @@ export class REDAnnotationManager { this.#autoSelectRectangleAfterCreation(); } + isHidden(annotationId: string) { + return this.hidden.has(annotationId); + } + delete(annotations?: List | List | string | AnnotationWrapper) { const items = isStringOrWrapper(annotations) ? [this.get(annotations)] : this.get(annotations); const options: DeleteAnnotationsOptions = { force: true }; diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts index 35415cdf6..de09e2b58 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts @@ -156,7 +156,7 @@ export class ViewerHeaderService { [HeaderElements.CLOSE_COMPARE_BUTTON, this._closeCompare], ]); - this._updateElements(); + this.updateElements(); } enable(elements: HeaderElementType[]): void { @@ -167,6 +167,25 @@ export class ViewerHeaderService { this._updateState(elements, false); } + updateElements(): void { + this._pdf.instance.UI.setHeaderItems(header => { + const enabledItems: IHeaderElement[] = []; + const groups: HeaderElementType[][] = [ + [HeaderElements.COMPARE_BUTTON, HeaderElements.CLOSE_COMPARE_BUTTON], + [HeaderElements.TOGGLE_TOOLTIPS], + [HeaderElements.SHAPE_TOOL_GROUP_BUTTON], + [ + HeaderElements.ROTATE_LEFT_BUTTON, + HeaderElements.ROTATE_RIGHT_BUTTON, + HeaderElements.APPLY_ROTATION, + HeaderElements.DISCARD_ROTATION, + ], + ]; + groups.forEach(group => this._pushGroup(enabledItems, group)); + header.getItems().splice(8, header.getItems().length - 13, ...enabledItems); + }); + } + #toggleRotationActionButtons() { if (this._rotationService.hasRotations) { this.enable(ROTATION_ACTION_BUTTONS); @@ -213,28 +232,9 @@ export class ViewerHeaderService { } } - private _updateElements(): void { - this._pdf.instance.UI.setHeaderItems(header => { - const enabledItems: IHeaderElement[] = []; - const groups: HeaderElementType[][] = [ - [HeaderElements.COMPARE_BUTTON, HeaderElements.CLOSE_COMPARE_BUTTON], - [HeaderElements.TOGGLE_TOOLTIPS], - [HeaderElements.SHAPE_TOOL_GROUP_BUTTON], - [ - HeaderElements.ROTATE_LEFT_BUTTON, - HeaderElements.ROTATE_RIGHT_BUTTON, - HeaderElements.APPLY_ROTATION, - HeaderElements.DISCARD_ROTATION, - ], - ]; - groups.forEach(group => this._pushGroup(enabledItems, group)); - header.getItems().splice(8, header.getItems().length - 13, ...enabledItems); - }); - } - private _updateState(elements: HeaderElementType[], value: boolean): void { elements.forEach(element => this.#config.set(element, value)); - this._updateElements(); + this.updateElements(); } private _isEnabled(key: HeaderElementType): boolean { diff --git a/apps/red-ui/src/app/modules/pdf-viewer/utils/constants.ts b/apps/red-ui/src/app/modules/pdf-viewer/utils/constants.ts index 518a7f6e5..02f3dcef9 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/utils/constants.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/utils/constants.ts @@ -1,9 +1,23 @@ import { CustomError, List } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { HeaderElements } from '../../file-preview/utils/constants'; +import { HeaderElements, TextPopups } from '../../file-preview/utils/constants'; export const ROTATION_ACTION_BUTTONS = [HeaderElements.APPLY_ROTATION, HeaderElements.DISCARD_ROTATION]; +export const TEXT_POPUPS_TO_TOGGLE = [TextPopups.ADD_REDACTION, TextPopups.ADD_RECTANGLE, TextPopups.ADD_FALSE_POSITIVE]; + +export const HEADER_ITEMS_TO_TOGGLE = [ + HeaderElements.SHAPE_TOOL_GROUP_BUTTON, + HeaderElements.ROTATE_LEFT_BUTTON, + HeaderElements.ROTATE_RIGHT_BUTTON, +]; + +export const ALLOWED_ACTIONS_WHEN_PAGE_EXCLUDED: string[] = [ + TextPopups.ADD_RECTANGLE, + TextPopups.ADD_REDACTION, + HeaderElements.SHAPE_TOOL_GROUP_BUTTON, +]; + export const ALLOWED_KEYBOARD_SHORTCUTS: List = ['+', '-', 'p', 'r', 'Escape'] as const; export const DOCUMENT_LOADING_ERROR = new CustomError(_('error.file-preview.label'), _('error.file-preview.action'), 'iqser:refresh');