From 3bb3e93906b576ac586fd114f0ccdc5e909e45eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Thu, 7 Apr 2022 14:41:52 +0300 Subject: [PATCH] RED-3721: New highlights endpoints --- .../src/app/models/file/annotation.wrapper.ts | 14 ++++---- .../services/text-highlight.service.ts | 35 ++++++++++--------- .../highlights-separator.component.ts | 9 ++++- .../highlight-action-dialog.component.ts | 7 ++-- .../services/file-data.service.ts | 19 +++------- apps/red-ui/src/assets/i18n/en.json | 2 +- .../src/lib/text-highlight/highlight.ts | 7 ++++ .../lib/text-highlight/imported-redaction.ts | 6 ---- .../src/lib/text-highlight/index.ts | 2 +- .../text-highlight-operation.ts | 5 ++- .../text-highlight/text-highlight.response.ts | 4 +-- 11 files changed, 55 insertions(+), 55 deletions(-) create mode 100644 libs/red-domain/src/lib/text-highlight/highlight.ts delete mode 100644 libs/red-domain/src/lib/text-highlight/imported-redaction.ts diff --git a/apps/red-ui/src/app/models/file/annotation.wrapper.ts b/apps/red-ui/src/app/models/file/annotation.wrapper.ts index d826475d5..355c31935 100644 --- a/apps/red-ui/src/app/models/file/annotation.wrapper.ts +++ b/apps/red-ui/src/app/models/file/annotation.wrapper.ts @@ -1,6 +1,6 @@ import { annotationTypesTranslations } from '../../translations/annotation-types-translations'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { IComment, IManualChange, ImportedRedaction, IPoint, IRectangle, LogEntryStatus, ManualRedactionType } from '@red/domain'; +import { Highlight, IComment, IManualChange, IPoint, IRectangle, LogEntryStatus, ManualRedactionType } from '@red/domain'; import { RedactionLogEntry } from '@models/file/redaction-log.entry'; import { FalsePositiveSuperTypes, @@ -228,17 +228,17 @@ export class AnnotationWrapper implements IListable, Record { ); } - static fromHighlight(color: string, entry: ImportedRedaction) { + static fromHighlight(highlight: Highlight) { const annotationWrapper = new AnnotationWrapper(); - annotationWrapper.annotationId = entry.id; - annotationWrapper.pageNumber = entry.positions[0].page; + annotationWrapper.annotationId = highlight.id; + annotationWrapper.pageNumber = highlight.positions[0].page; annotationWrapper.superType = SuperTypes.TextHighlight; annotationWrapper.typeValue = SuperTypes.TextHighlight; annotationWrapper.value = 'Imported'; - annotationWrapper.color = color; - annotationWrapper.positions = entry.positions; - annotationWrapper.firstTopLeftPoint = entry.positions[0]?.topLeft; + annotationWrapper.color = highlight.hexColor; + annotationWrapper.positions = highlight.positions; + annotationWrapper.firstTopLeftPoint = highlight.positions[0]?.topLeft; annotationWrapper.typeLabel = annotationTypesTranslations[annotationWrapper.superType]; return annotationWrapper; diff --git a/apps/red-ui/src/app/modules/dossier/services/text-highlight.service.ts b/apps/red-ui/src/app/modules/dossier/services/text-highlight.service.ts index af3b0c4a9..97f43209b 100644 --- a/apps/red-ui/src/app/modules/dossier/services/text-highlight.service.ts +++ b/apps/red-ui/src/app/modules/dossier/services/text-highlight.service.ts @@ -1,40 +1,41 @@ import { Injectable, Injector } from '@angular/core'; import { GenericService, RequiredParam, Toaster, Validate } from '@iqser/common-ui'; -import { ImportedRedaction, TextHighlightOperation, TextHighlightRequest, TextHighlightResponse } from '@red/domain'; -import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { Highlight, TextHighlightOperation, TextHighlightResponse } from '@red/domain'; import { catchError, map, tap } from 'rxjs/operators'; -import { of } from 'rxjs'; +import { Observable, of } from 'rxjs'; +import { AnnotationWrapper } from '@models/file/annotation.wrapper'; +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; @Injectable({ providedIn: 'root', }) export class TextHighlightService extends GenericService { constructor(protected readonly _injector: Injector, private readonly _toaster: Toaster) { - super(_injector, 'texthighlights-conversion'); + super(_injector, ''); } @Validate() - getTextHighlights(@RequiredParam() dossierId: string, @RequiredParam() fileId: string) { - const request: TextHighlightRequest = { - dossierId, - fileId, - operation: TextHighlightOperation.INFO, - }; - - return this._post(request).pipe( - map(response => response.redactionPerColor), - catchError(() => of({} as Record)), + getTextHighlights(@RequiredParam() dossierId: string, @RequiredParam() fileId: string): Observable { + return this._http.get<{ highlights: Highlight[] }>(`/${this.#getPath(dossierId, fileId)}`).pipe( + map(response => response.highlights), + map(highlights => highlights.map(highlight => AnnotationWrapper.fromHighlight(highlight))), + catchError(() => of([])), ); } @Validate() performHighlightsAction( + @RequiredParam() ids: string[], @RequiredParam() dossierId: string, @RequiredParam() fileId: string, - @RequiredParam() colors: string[], @RequiredParam() operation: TextHighlightOperation, ) { - const request: TextHighlightRequest = { dossierId, fileId, colors, operation }; - return this._post(request).pipe(tap(() => this._toaster.success(_('highlight-action-dialog.success'), { params: { operation } }))); + return this._post({ ids }, `${this.#getPath(dossierId, fileId)}/${operation}`).pipe( + tap(() => this._toaster.success(_('highlight-action-dialog.success'), { params: { operation } })), + ); + } + + #getPath(dossierId: string, fileId: string): string { + return `dossiers/${dossierId}/files/${fileId}/highlights`; } } diff --git a/apps/red-ui/src/app/modules/file-preview/components/highlights-separator/highlights-separator.component.ts b/apps/red-ui/src/app/modules/file-preview/components/highlights-separator/highlights-separator.component.ts index c591709b3..3af0fc034 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/highlights-separator/highlights-separator.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/highlights-separator/highlights-separator.component.ts @@ -4,6 +4,7 @@ import { TextHighlightOperation, TextHighlightsGroup } from '@red/domain'; import { FilePreviewStateService } from '../../services/file-preview-state.service'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { FilePreviewDialogService } from '../../services/file-preview-dialog.service'; +import { FileDataService } from '../../services/file-data.service'; @Component({ selector: 'redaction-highlights-separator [highlightGroup] [annotation]', @@ -18,7 +19,11 @@ export class HighlightsSeparatorComponent { readonly circleButtonTypes = CircleButtonTypes; readonly isWritable$ = this._state.isWritable$; - constructor(private readonly _dialogService: FilePreviewDialogService, private readonly _state: FilePreviewStateService) {} + constructor( + private readonly _dialogService: FilePreviewDialogService, + private readonly _state: FilePreviewStateService, + private readonly _fileDataService: FileDataService, + ) {} convertHighlights(highlightGroup: TextHighlightsGroup): void { const data = this._getActionData(highlightGroup, TextHighlightOperation.CONVERT); @@ -31,11 +36,13 @@ export class HighlightsSeparatorComponent { } private _getActionData(highlightGroup: TextHighlightsGroup, operation: TextHighlightOperation) { + const highlights = this._fileDataService.all.filter(a => a.color === highlightGroup.color); return { dossierId: this._state.dossierId, fileId: this._state.fileId, color: highlightGroup.color, operation, + highlights, }; } } diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/highlight-action-dialog/highlight-action-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/highlight-action-dialog/highlight-action-dialog.component.ts index f3234ad4d..67c221800 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/highlight-action-dialog/highlight-action-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/highlight-action-dialog/highlight-action-dialog.component.ts @@ -6,12 +6,14 @@ import { BaseDialogComponent, LoadingService } from '@iqser/common-ui'; import { TextHighlightService } from '../../../dossier/services/text-highlight.service'; import { firstValueFrom } from 'rxjs'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { AnnotationWrapper } from '@models/file/annotation.wrapper'; export interface HighlightActionData { readonly operation: TextHighlightOperation; readonly color: string; readonly dossierId: string; readonly fileId: string; + readonly highlights: AnnotationWrapper[]; } @Component({ @@ -55,8 +57,9 @@ export class HighlightActionDialogComponent extends BaseDialogComponent { async save(): Promise { this._loadingService.start(); - const { dossierId, fileId, color, operation } = this.data; - await firstValueFrom(this._textHighlightService.performHighlightsAction(dossierId, fileId, [color], operation)); + const { dossierId, fileId, operation, highlights } = this.data; + const ids = highlights.map(h => h.id); + await firstValueFrom(this._textHighlightService.performHighlightsAction(ids, dossierId, fileId, operation)); this._loadingService.stop(); this._dialogRef.close(true); } 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 1517a8f66..97a3b1f43 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 @@ -1,7 +1,6 @@ import { ChangeType, File, - ImportedRedaction, IRedactionLog, IRedactionLogEntry, IViewedPage, @@ -100,12 +99,11 @@ export class FileDataService extends EntitiesService { await this.loadRedactionLog(); } - async loadTextHighlights() { - const redactionPerColor = this._textHighlightsService.getTextHighlights(this._state.dossierId, this._state.fileId); - const textHighlights = this.#buildTextHighlights(await firstValueFrom(redactionPerColor)); - this.#textHighlights$.next(textHighlights); + async loadTextHighlights(): Promise { + const highlights = await firstValueFrom(this._textHighlightsService.getTextHighlights(this._state.dossierId, this._state.fileId)); + this.#textHighlights$.next(highlights); - return textHighlights; + return highlights; } loadRedactionLog() { @@ -159,15 +157,6 @@ export class FileDataService extends EntitiesService { }); } - #buildTextHighlights(redactionPerColor: Record): AnnotationWrapper[] { - if (!redactionPerColor) { - return []; - } - - const highlights = Object.entries(redactionPerColor); - return highlights.flatMap(([color, entries]) => entries.map(entry => AnnotationWrapper.fromHighlight(color, entry))); - } - #buildAnnotations(redactionLog: IRedactionLog, file: File) { const entries: RedactionLogEntry[] = this.#convertData(redactionLog, file); const annotations = entries.map(entry => AnnotationWrapper.fromData(entry)); diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index fb91e022b..384c3a29a 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -1436,7 +1436,7 @@ "save": "Remove Highlights", "title": "Remove highlights" }, - "success": "{operation, select, CONVERT{Converting} REMOVE{Removing} other{}} highlights in progress..." + "success": "{operation, select, convert{Converting} delete{Removing} other{}} highlights in progress..." }, "highlights": "{color} - {length} {length, plural, one{highlight} other{highlights}}", "image-category": { diff --git a/libs/red-domain/src/lib/text-highlight/highlight.ts b/libs/red-domain/src/lib/text-highlight/highlight.ts new file mode 100644 index 000000000..b5604c1bf --- /dev/null +++ b/libs/red-domain/src/lib/text-highlight/highlight.ts @@ -0,0 +1,7 @@ +import { IRectangle } from '../geometry'; + +export interface Highlight { + readonly id: string; + readonly positions: IRectangle[]; + readonly hexColor: string; +} diff --git a/libs/red-domain/src/lib/text-highlight/imported-redaction.ts b/libs/red-domain/src/lib/text-highlight/imported-redaction.ts deleted file mode 100644 index 7a08fee0d..000000000 --- a/libs/red-domain/src/lib/text-highlight/imported-redaction.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IRectangle } from '../geometry'; - -export interface ImportedRedaction { - id: string; - positions: IRectangle[]; -} diff --git a/libs/red-domain/src/lib/text-highlight/index.ts b/libs/red-domain/src/lib/text-highlight/index.ts index f49b5580a..5af0eb93f 100644 --- a/libs/red-domain/src/lib/text-highlight/index.ts +++ b/libs/red-domain/src/lib/text-highlight/index.ts @@ -1,4 +1,4 @@ -export * from './imported-redaction'; +export * from './highlight'; export * from './text-highlight-operation'; export * from './text-highlight.response'; export * from './text-highlight.request'; diff --git a/libs/red-domain/src/lib/text-highlight/text-highlight-operation.ts b/libs/red-domain/src/lib/text-highlight/text-highlight-operation.ts index c198d7dda..607108826 100644 --- a/libs/red-domain/src/lib/text-highlight/text-highlight-operation.ts +++ b/libs/red-domain/src/lib/text-highlight/text-highlight-operation.ts @@ -1,5 +1,4 @@ export enum TextHighlightOperation { - REMOVE = 'REMOVE', - CONVERT = 'CONVERT', - INFO = 'INFO', + REMOVE = 'delete', + CONVERT = 'convert', } diff --git a/libs/red-domain/src/lib/text-highlight/text-highlight.response.ts b/libs/red-domain/src/lib/text-highlight/text-highlight.response.ts index 6a79ec21c..960db7d5c 100644 --- a/libs/red-domain/src/lib/text-highlight/text-highlight.response.ts +++ b/libs/red-domain/src/lib/text-highlight/text-highlight.response.ts @@ -1,9 +1,9 @@ -import { ImportedRedaction } from './imported-redaction'; +import { Highlight } from './highlight'; import { TextHighlightOperation } from './text-highlight-operation'; export interface TextHighlightResponse { dossierId?: string; fileId?: string; operation?: TextHighlightOperation; - redactionPerColor?: Record; + redactionPerColor?: Record; }