diff --git a/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts b/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts index dfb735ba7..0fa2a9a88 100644 --- a/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts +++ b/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts @@ -8,7 +8,10 @@ export const canForceHint = (annotation: AnnotationWrapper, canAddRedaction: boo canAddRedaction && annotation.isIgnoredHint && !annotation.pending; export const canForceRedaction = (annotation: AnnotationWrapper, canAddRedaction: boolean) => - canAddRedaction && annotation.isSkipped && !annotation.isFalsePositive && !annotation.pending; + canAddRedaction && + (annotation.isSkipped || (annotation.IMAGE_HINT && !annotation.hasBeenForcedRedaction)) && + !annotation.isFalsePositive && + !annotation.pending; export const canAcceptRecommendation = (annotation: AnnotationWrapper) => annotation.isRecommendation && !annotation.pending; diff --git a/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-info.module.ts b/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-info.module.ts index adb906247..b7d6deb4e 100644 --- a/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-info.module.ts +++ b/apps/red-ui/src/app/modules/admin/screens/info/dossier-template-info.module.ts @@ -8,8 +8,15 @@ import { TranslateModule } from '@ngx-translate/core'; import { IqserUsersModule } from '@iqser/common-ui/lib/users'; import { SelectComponent } from '@shared/components/select/select.component'; import { DossierTemplateDetailsComponent } from './dossier-template-details/dossier-template-details.component'; +import { PendingChangesGuard } from '@guards/can-deactivate.guard'; -const routes = [{ path: '', component: DossierTemplateInfoScreenComponent }]; +const routes = [ + { + path: '', + component: DossierTemplateInfoScreenComponent, + canDeactivate: [PendingChangesGuard], + }, +]; @NgModule({ declarations: [DossierTemplateInfoScreenComponent, DossierTemplateDetailsComponent], diff --git a/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-actions/dossier-template-actions.component.html b/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-actions/dossier-template-actions.component.html index c20f6e637..77b4d562d 100644 --- a/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-actions/dossier-template-actions.component.html +++ b/apps/red-ui/src/app/modules/admin/shared/components/dossier-template-actions/dossier-template-actions.component.html @@ -15,6 +15,7 @@ > (); + readonly enableEdit = this._route.routeConfig?.path !== 'info'; dossierTemplate: DossierTemplate; constructor( diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.html b/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.html index 61017a470..ae90408c4 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.html @@ -108,7 +108,7 @@ [tooltip]="'annotation-actions.force-redaction.label' | translate" [type]="buttonType" [buttonId]="annotations.length === 1 ? 'annotation-' + annotations[0].id + '-force_redaction' : 'annotations-force_redaction'" - icon="iqser:thumb-up" + [icon]="isImageHint ? 'red:pdftron-action-add-redaction' : 'iqser:thumb-up'" > annotation.IMAGE_HINT); + } + @Input() set annotations(annotations: AnnotationWrapper[]) { this.#annotations = annotations.filter(a => a !== undefined); diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-details/annotation-details.component.ts b/apps/red-ui/src/app/modules/file-preview/components/annotation-details/annotation-details.component.ts index 1e3c5fd86..d06824982 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-details/annotation-details.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-details/annotation-details.component.ts @@ -6,6 +6,7 @@ import { ListItem } from '@models/file/list-item'; import { TranslateService } from '@ngx-translate/core'; import { annotationChangesTranslations } from '@translations/annotation-changes-translations'; import { MultiSelectService } from '../../services/multi-select.service'; +import { LogEntryEngine, LogEntryEngines } from '@red/domain'; interface Engine { readonly icon: string; @@ -14,17 +15,7 @@ interface Engine { readonly translateParams?: Record; } -export const Engines = { - DICTIONARY: 'DICTIONARY', - NER: 'NER', - RULE: 'RULE', - IMPORTED: 'IMPORTED', - MANUAL: 'MANUAL', -} as const; - -type EngineName = keyof typeof Engines; - -function isBasedOn(annotation: AnnotationWrapper, engineName: EngineName) { +function isBasedOn(annotation: AnnotationWrapper, engineName: LogEntryEngine) { return !!annotation.engines?.includes(engineName); } @@ -43,18 +34,18 @@ const changesProperties: KeysOf[] = [ styleUrls: ['./annotation-details.component.scss'], }) export class AnnotationDetailsComponent implements OnChanges { - private readonly _translateService = inject(TranslateService); - private readonly _multiSelectService = inject(MultiSelectService); @Input() annotation: ListItem; isPopoverOpen = false; engines: Engine[]; changesTooltip: string; noSelection: boolean; + private readonly _translateService = inject(TranslateService); + private readonly _multiSelectService = inject(MultiSelectService); getChangesTooltip(): string | undefined { const changes = changesProperties.filter(key => this.annotation.item[key]); - if (!changes.length || !this.annotation.item.engines?.includes(Engines.MANUAL)) { + if (!changes.length || !this.annotation.item.engines?.includes(LogEntryEngines.MANUAL)) { return; } @@ -74,24 +65,29 @@ export class AnnotationDetailsComponent implements OnChanges { { icon: 'red:dictionary', description: _('annotation-engines.dictionary'), - show: isBasedOn(annotation, Engines.DICTIONARY), + show: isBasedOn(annotation, LogEntryEngines.DICTIONARY), translateParams: { isHint: annotation.HINT }, }, + { + icon: 'red:folder', + description: _('annotation-engines.dossier-dictionary'), + show: isBasedOn(annotation, LogEntryEngines.DOSSIER_DICTIONARY), + }, { icon: 'red:ai', description: _('annotation-engines.ner'), - show: isBasedOn(annotation, Engines.NER), + show: isBasedOn(annotation, LogEntryEngines.NER), }, { icon: 'red:rule', description: _('annotation-engines.rule'), - show: isBasedOn(annotation, Engines.RULE), + show: isBasedOn(annotation, LogEntryEngines.RULE), translateParams: { rule: annotation.legalBasisValue || '' }, }, { icon: 'red:import_redactions', description: _('annotation-engines.imported'), - show: isBasedOn(annotation, Engines.IMPORTED), + show: isBasedOn(annotation, LogEntryEngines.IMPORTED), }, ]; } diff --git a/apps/red-ui/src/app/modules/file-preview/components/page-exclusion/page-exclusion.component.ts b/apps/red-ui/src/app/modules/file-preview/components/page-exclusion/page-exclusion.component.ts index 14dbef330..261994079 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/page-exclusion/page-exclusion.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/page-exclusion/page-exclusion.component.ts @@ -36,6 +36,7 @@ export class PageExclusionComponent { try { const pageRanges = extractPageRanges(inputValue, file); await this._reanalysisService.excludePages({ pageRanges }, file); + this._state.excludedPages.update(value => [...value, ...this.flattenPageRanges(pageRanges)]); this._inputComponent.reset(); } catch (e) { this._toaster.error(_('file-preview.tabs.exclude-pages.error')); @@ -46,6 +47,7 @@ export class PageExclusionComponent { async includePagesRange(range: IPageRange): Promise { this._loadingService.start(); await this._reanalysisService.includePages({ pageRanges: [range] }, this._state.file()); + this._state.excludedPages.update(value => value.filter(page => !this.flattenPageRanges([range]).includes(page))); this._inputComponent.reset(); this._loadingService.stop(); } @@ -64,4 +66,15 @@ export class PageExclusionComponent { return ranges; }, []); } + + flattenPageRanges(ranges: IPageRange[]) { + const flattenedPages = []; + ranges.forEach(range => { + for (let page = range.startPage; page <= range.endPage; page++) { + flattenedPages.push(page); + } + }); + + return flattenedPages; + } } diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/force-redaction-dialog/force-annotation-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/force-redaction-dialog/force-annotation-dialog.component.html index 3c4c15b55..775c89566 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/force-redaction-dialog/force-annotation-dialog.component.html +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/force-redaction-dialog/force-annotation-dialog.component.html @@ -8,6 +8,7 @@ [columns]="tableColumns" [data]="tableData" [staticColumns]="true" + *ngIf="!isImageHint" >
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/force-redaction-dialog/force-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/force-redaction-dialog/force-annotation-dialog.component.ts index 3925d5752..7a151a4f6 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/force-redaction-dialog/force-annotation-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/force-redaction-dialog/force-annotation-dialog.component.ts @@ -53,6 +53,10 @@ export class ForceAnnotationDialogComponent extends BaseDialogComponent implemen this.form = this.#getForm(); } + get isImageHint() { + return this._data.annotations.every(annotation => annotation.IMAGE_HINT); + } + get isHintDialog() { return this._data.hint; } 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 436f34efb..ea41e52b8 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 @@ -173,14 +173,17 @@ export class FilePreviewScreenComponent } }); + effect(() => { + this._viewModeService.viewMode(); + this.updateViewMode().then(); + }); + effect(() => { this.state.updateExcludedPagesStyle(); - if (this._viewModeService.viewMode()) { - this.updateViewMode().then(); - if (_documentViewer.loaded()) { - this._logger.info('[PDF] Stamp pdf'); - this._stampService.stampPDF().then(); - } + this._viewModeService.viewMode(); + if (_documentViewer.loaded()) { + this._logger.info('[PDF] Stamp pdf'); + this._stampService.stampPDF().then(); } }); } diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts index 42d467dd9..3941d297d 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts @@ -3,7 +3,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { getConfig } from '@iqser/common-ui'; import { Filter, handleCheckedValue, IFilter, INestedFilter, NestedFilter } from '@iqser/common-ui/lib/filtering'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { annotationDefaultColorConfig } from '@red/domain'; +import { annotationDefaultColorConfig, LogEntryEngines } from '@red/domain'; import { DefaultColorsService } from '@services/entity-services/default-colors.service'; import { ViewedPagesMapService } from '@services/files/viewed-pages-map.service'; import { annotationTypesTranslations } from '@translations/annotation-types-translations'; @@ -19,7 +19,6 @@ import { } from '../utils/sort-by-page-rotation.utils'; import { FileDataService } from './file-data.service'; import { FilePreviewStateService } from './file-preview-state.service'; -import { Engines } from '../components/annotation-details/annotation-details.component'; @Injectable() export class AnnotationProcessingService { @@ -52,7 +51,7 @@ export class AnnotationProcessingService { checked: false, topLevelFilter: true, checker: (annotation: AnnotationWrapper) => - annotation?.hasRedactionChanges && annotation?.engines?.includes(Engines.MANUAL), + annotation?.hasRedactionChanges && annotation?.engines?.includes(LogEntryEngines.MANUAL), }, { id: 'unseen-pages', diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts index 11d386628..6f584dd5d 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts @@ -1,10 +1,10 @@ import { HttpEvent, HttpEventType, HttpProgressEvent, HttpResponse } from '@angular/common/http'; -import { computed, effect, inject, Injectable, signal, Signal } from '@angular/core'; +import { computed, effect, inject, Injectable, signal, Signal, WritableSignal } from '@angular/core'; import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop'; import { LoadingService, wipeCache } from '@iqser/common-ui'; import { getParam } from '@iqser/common-ui/lib/utils'; import { TranslateService } from '@ngx-translate/core'; -import { Dictionary, Dossier, DOSSIER_ID, DOSSIER_TEMPLATE_ID, File, FILE_ID } from '@red/domain'; +import { Dictionary, Dossier, DOSSIER_ID, DOSSIER_TEMPLATE_ID, File, FILE_ID, ViewModes } from '@red/domain'; import { DossiersService } from '@services/dossiers/dossiers.service'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { DossierDictionariesMapService } from '@services/entity-services/dossier-dictionaries-map.service'; @@ -44,7 +44,8 @@ export class FilePreviewStateService { readonly dossierId = getParam(DOSSIER_ID); readonly dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); readonly fileId = getParam(FILE_ID); - readonly updateExcludedPagesStyle = computed(() => this.file().excludedPages); + readonly excludedPages: WritableSignal; + readonly updateExcludedPagesStyle = computed(() => this.excludedPages()); readonly isEditingReviewer = signal(false); constructor( @@ -61,6 +62,7 @@ export class FilePreviewStateService { this.dossier = toSignal(dossiersServiceResolver().getEntityChanged$(this.dossierId)); this.file$ = inject(FilesMapService).watch$(this.dossierId, this.fileId); this.file = toSignal(this.file$); + this.excludedPages = signal(this.file().excludedPages); this.isWritable = computed(() => { const isWritable = this._permissionsService.canPerformAnnotationActions(this.file(), this.dossier()); this._logger.info('[FILE] Is writeable:', isWritable); @@ -80,7 +82,9 @@ export class FilePreviewStateService { effect( () => { if (this._viewModeService.isEarmarks() && !this.file().hasHighlights) { - this._viewModeService.switchToStandard(); + if (this._viewModeService.viewMode() !== ViewModes.STANDARD) { + this._viewModeService.switchToStandard(); + } } }, { allowSignalWrites: true }, 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 c2086fa7f..deac10928 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 @@ -81,8 +81,11 @@ export class PdfAnnotationActionsService { } if (permissions.canForceRedaction && annotationChangesAllowed) { - const forceRedactionButton = this.#getButton('thumb-up', _('annotation-actions.force-redaction.label'), () => - this.#annotationActionsService.forceAnnotation(annotations), + const isImageHint = annotations.every(annotation => annotation.IMAGE_HINT); + const forceRedactionButton = this.#getButton( + isImageHint ? 'general/pdftron-action-add-redaction' : 'thumb-up', + _('annotation-actions.force-redaction.label'), + () => this.#annotationActionsService.forceAnnotation(annotations), ); availableActions.push(forceRedactionButton); } diff --git a/apps/red-ui/src/app/modules/icons/icons.module.ts b/apps/red-ui/src/app/modules/icons/icons.module.ts index a2b7a8376..dab2ac28d 100644 --- a/apps/red-ui/src/app/modules/icons/icons.module.ts +++ b/apps/red-ui/src/app/modules/icons/icons.module.ts @@ -86,6 +86,7 @@ export class IconsModule { 'visibility', 'visibility-off', 'warning', + 'pdftron-action-add-redaction', ]; for (const icon of icons) { diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/tooltips.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/tooltips.service.ts index e29c09630..0282bbf72 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/tooltips.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/tooltips.service.ts @@ -1,18 +1,13 @@ -import { inject, Injectable } from '@angular/core'; +import { Injectable } from '@angular/core'; import { UserPreferenceService } from '@users/user-preference.service'; -import { HeaderElements } from '../../file-preview/utils/constants'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { TranslateService } from '@ngx-translate/core'; import { PdfViewer } from './pdf-viewer.service'; import { REDDocumentViewer } from './document-viewer.service'; -import { UI_ROOT_PATH_FN } from '@common-ui/utils'; +import { HeaderElements } from '../../file-preview/utils/constants'; @Injectable() export class TooltipsService { - readonly #convertPath = inject(UI_ROOT_PATH_FN); - readonly #enableIcon = this.#convertPath('/assets/icons/general/pdftron-action-enable-tooltips.svg'); - readonly #disableIcon = this.#convertPath('/assets/icons/general/pdftron-action-disable-tooltips.svg'); - constructor( private readonly _pdf: PdfViewer, private readonly _documentViewer: REDDocumentViewer, @@ -26,17 +21,23 @@ export class TooltipsService { }); } - get toggleTooltipsBtnIcon(): string { - const tooltipsDisabled = this._userPreferenceService.getFilePreviewTooltipsPreference(); - return tooltipsDisabled ? this.#enableIcon : this.#disableIcon; - } - async toggleTooltips(): Promise { await this._userPreferenceService.toggleFilePreviewTooltipsPreference(); this._documentViewer.updateTooltipsVisibility(); + + this.updateIconState(); + this._pdf.instance.UI.updateElement(HeaderElements.TOGGLE_TOOLTIPS, { title: this.toggleTooltipsBtnTitle, - img: this.toggleTooltipsBtnIcon, }); } + + updateIconState() { + const element = this._pdf.instance.UI.iframeWindow.document.querySelector(`[data-element=${HeaderElements.TOGGLE_TOOLTIPS}]`); + if (this._userPreferenceService.getFilePreviewTooltipsPreference()) { + element.classList.add('active'); + } else { + element.classList.remove('active'); + } + } } 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 78b7dee74..1a97af173 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 @@ -100,7 +100,7 @@ export class ViewerHeaderService { element: HeaderElements.TOGGLE_TOOLTIPS, dataElement: HeaderElements.TOGGLE_TOOLTIPS, title: this._tooltipsService.toggleTooltipsBtnTitle, - img: this._tooltipsService.toggleTooltipsBtnIcon, + img: this.#convertPath('/assets/icons/general/pdftron-action-enable-tooltips.svg'), onClick: () => this._ngZone.run(() => this._tooltipsService.toggleTooltips()), }; } @@ -137,17 +137,6 @@ export class ViewerHeaderService { }; } - get #closeCompare(): IHeaderElement { - return { - type: 'actionButton', - element: HeaderElements.CLOSE_COMPARE_BUTTON, - dataElement: HeaderElements.CLOSE_COMPARE_BUTTON, - img: this.#convertPath('/assets/icons/general/pdftron-action-close-compare.svg'), - title: 'Leave Compare Mode', - onClick: () => this._ngZone.run(() => this.#closeCompareMode()), - }; - } - get #rotateLeft(): IHeaderElement { return { type: 'actionButton', @@ -238,6 +227,17 @@ export class ViewerHeaderService { }; } + get #closeCompare(): IHeaderElement { + return { + type: 'actionButton', + element: HeaderElements.CLOSE_COMPARE_BUTTON, + dataElement: HeaderElements.CLOSE_COMPARE_BUTTON, + img: this.#convertPath('/assets/icons/general/pdftron-action-compare.svg'), + title: 'Leave Compare Mode', + onClick: () => this._ngZone.run(() => this.#closeCompareMode()), + }; + } + get #toggleLoadAnnotations$() { return merge(this.expandedPanelEvent$, this._helpModeService.isHelpModeActive$).pipe( tap(enable => @@ -281,7 +281,6 @@ export class ViewerHeaderService { [HeaderElements.TOGGLE_TOOLTIPS], [HeaderElements.TOGGLE_LAYERS], [HeaderElements.TOGGLE_READABLE_REDACTIONS], - [HeaderElements.SHAPE_TOOL_GROUP_BUTTON], [ HeaderElements.ROTATE_LEFT_BUTTON, HeaderElements.ROTATE_RIGHT_BUTTON, @@ -290,18 +289,19 @@ export class ViewerHeaderService { ], ]; - const loadAllAnnotationsButton = this.#buttons.get(HeaderElements.LOAD_ALL_ANNOTATIONS); - let startButtons = 10; - let deleteCount = 14; - + header.get('selectToolButton').insertAfter(this.#buttons.get(HeaderElements.SHAPE_TOOL_GROUP_BUTTON)); groups.forEach(group => this.#pushGroup(enabledItems, group)); + const loadAllAnnotationsButton = this.#buttons.get(HeaderElements.LOAD_ALL_ANNOTATIONS); + let startButtons = 11; + let deleteCount = 15; + if (this.#isEnabled(HeaderElements.LOAD_ALL_ANNOTATIONS)) { if (!header.getItems().includes(loadAllAnnotationsButton)) { header.get('leftPanelButton').insertAfter(loadAllAnnotationsButton); } - startButtons = 11; - deleteCount = 15; + startButtons = 12; + deleteCount = 16; } else { header.delete(HeaderElements.LOAD_ALL_ANNOTATIONS); } @@ -311,6 +311,11 @@ export class ViewerHeaderService { this._pdf.instance?.UI.updateElement('selectToolButton', { img: this.#convertPath('/assets/icons/general/pdftron-cursor.svg'), }); + this._tooltipsService.updateIconState(); + const closeCompareButton = this._pdf.instance.UI.iframeWindow.document.querySelector( + `[data-element=${HeaderElements.CLOSE_COMPARE_BUTTON}]`, + ); + closeCompareButton?.classList.add('active'); } disableLoadAllAnnotations(): void { diff --git a/apps/red-ui/src/app/translations/placeholders-descriptions-translations.ts b/apps/red-ui/src/app/translations/placeholders-descriptions-translations.ts index 876acfb02..13f59a0f9 100644 --- a/apps/red-ui/src/app/translations/placeholders-descriptions-translations.ts +++ b/apps/red-ui/src/app/translations/placeholders-descriptions-translations.ts @@ -22,4 +22,6 @@ export const generalPlaceholdersDescriptionsTranslations = { 'redaction.justificationLegalBasis': _('reports-screen.descriptions.general.redaction.justification-legal-basis'), 'redaction.justificationText': _('reports-screen.descriptions.general.redaction.justification-text'), 'redaction.entity.displayName': _('reports-screen.descriptions.general.redaction.entity.display-name'), + 'redaction.isSkipped': _('reports-screen.descriptions.general.redaction.is-skipped'), + 'redaction.paragraphIdx': _('reports-screen.descriptions.general.redaction.paragraph-idx'), } as const; diff --git a/apps/red-ui/src/assets/config/config.json b/apps/red-ui/src/assets/config/config.json index 2ccc6f6d1..441ade243 100644 --- a/apps/red-ui/src/assets/config/config.json +++ b/apps/red-ui/src/assets/config/config.json @@ -1,7 +1,7 @@ { "ADMIN_CONTACT_NAME": null, "ADMIN_CONTACT_URL": null, - "API_URL": "https://frontend2.iqser.cloud", + "API_URL": "https://dan1.iqser.cloud", "APP_NAME": "RedactManager", "IS_DOCUMINE": true, "RULE_EDITOR_DEV_ONLY": false, @@ -13,7 +13,7 @@ "MAX_RETRIES_ON_SERVER_ERROR": 3, "OAUTH_CLIENT_ID": "redaction", "OAUTH_IDP_HINT": null, - "OAUTH_URL": "https://frontend2.iqser.cloud/auth", + "OAUTH_URL": "https://dan1.iqser.cloud/auth", "RECENT_PERIOD_IN_HOURS": 24, "SELECTION_MODE": "structural", "MANUAL_BASE_URL": "https://docs.redactmanager.com/preview", diff --git a/apps/red-ui/src/assets/i18n/redact/de.json b/apps/red-ui/src/assets/i18n/redact/de.json index 519e9fcd7..10e3c8f28 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -133,7 +133,7 @@ "rank": "Rank" }, "save": "Save state", - "success": "Dossier state {type, select, edit{has been updated} creation successful{created} other{}}.", + "success": "Dossier state {type, select, edit{has been updated} create{creation successful} other{}}.", "title": "{type, select, edit{Edit {name}} create{Create} other{}} dossier state" }, "add-edit-entity": { diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index dcd8dafe6..2539b3d11 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -133,7 +133,7 @@ "rank": "Rank" }, "save": "Save state", - "success": "Dossier state {type, select, edit{has been updated} creation successful{created} other{}}.", + "success": "Dossier state {type, select, edit{has been updated} create{creation successful} other{}}.", "title": "{type, select, edit{Edit {name}} create{Create} other{}} dossier state" }, "add-edit-entity": { @@ -372,6 +372,7 @@ }, "annotation-engines": { "dictionary": "Based on dictionary", + "dossier-dictionary": "Based on dossier dictionary", "imported": "Imported", "ner": "Based on AI", "rule": "Based on rule" @@ -2150,11 +2151,11 @@ "description": "Below, you will find a list of placeholders for dossier- and document-specific information. You can include these placeholders in your report templates.", "descriptions": { "dossier-attributes": "This placeholder gets replaced with the value of the dossier attribute {attribute}.", - "file-attributes": "This placeholder gets replaced with the value of the file attribute {attribute}.", + "file-attributes": "This placeholder is replaced with the value of the file attribute {attribute}.", "general": { "date": { "d-m-y": "This placeholder is replaced by the creation date of the report in the common day-month-year notation (dd.MM.yyyy), e.g. 15.10.2021.", - "m-d-y": "This placeholder gets replaced by the creation date of the report in the American all-numeric date format (MM/dd/yyyy), e.g. 10/15/2021.", + "m-d-y": "This placeholder is replaced by the creation date of the report in the American all-numeric date format (MM/dd/yyyy), e.g. 10/15/2021.", "y-m-d": "This placeholder is replaced by the creation date of the report in the international ISO 8601 format (yyyy-MM-dd), e.g. 2021-10-15." }, "dossier": { @@ -2168,13 +2169,15 @@ "display-name": "This placeholder is replaced by the name of the entity the redaction is based on." }, "excerpt": "This placeholder is replaced by a text snippet that contains the redaction.", + "is-skipped": "The skipped redaction placeholder indicates whether a redaction is skipped or not. It can be included in a separate column of a template that also contains the '{{redaction.value'}} placeholder. The placeholder is replaced by “true” if the respective redaction is skipped, and by “false” if it is redacted (i. e., not skipped).", "justification": "This placeholder is replaced by the justification of the redaction. It is a combination of the legal reference (justificationParagraph) and the justification text (justificationReason).", "justification-legal-basis": "This placeholder is replaced by the legal basis for the redaction.", "justification-paragraph": "This placeholder is replaced by the legal reference of the justification of the redaction.", "justification-reason": "This placeholder is replaced by the justification text of the redaction.", "justification-text": "This placeholder is replaced by the justification text.", "page": "This placeholder is replaced by the page number of the redaction.", - "paragraph": "This placeholder is replaced by the paragraph that contains the redaction.", + "paragraph": "This placeholder is replaced by the initial words of the paragraph containing the redaction.", + "paragraph-idx": "The placeholder is replaced by the number of the paragraph containing the redaction. Paragraphs are numbered on a per-page basis.", "value": "This placeholder is replaced by the value that was redacted." }, "time": { diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index 13e936c33..ee85d8505 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -372,6 +372,7 @@ }, "annotation-engines": { "dictionary": "{isHint, select, true{Hint} other{Annotation}} based on dictionary", + "dossier-dictionary": "Annotation based on dossier dictionary", "imported": "Annotation is imported", "ner": "Annotation based on AI", "rule": "Annotation based on rule {rule}" @@ -1759,7 +1760,7 @@ }, "initials-avatar": { "unassigned": "Unassigned", - "you": "" + "you": "You" }, "justifications-listing": { "actions": { @@ -2168,6 +2169,7 @@ "display-name": "This placeholder is replaced by the name of the entity the component is based on." }, "excerpt": "This placeholder is replaced by a text snippet that contains the component.", + "is-skipped": "The skipped redaction placeholder indicates whether a redaction is skipped or not. It can be included in a separate column of a template that also contains the '{{redaction.value'}} placeholder. The placeholder is replaced by “true” if the respective redaction is skipped, and by “false” if it is redacted (i. e., not skipped).", "justification": "This placeholder is replaced by the justification of the component. It is a combination of the legal reference (justificationParagraph) and the justification text (justificationReason).", "justification-legal-basis": "This placeholder is replaced by the legal basis for the component.", "justification-paragraph": "This placeholder is replaced by the legal reference of the justification of the component.", @@ -2175,6 +2177,7 @@ "justification-text": "This placeholder is replaced by the justification text.", "page": "This placeholder is replaced by the page number of the component.", "paragraph": "This placeholder is replaced by the paragraph that contains the component.", + "paragraph-idx": "The placeholder is replaced by the number of the paragraph containing the redaction. Paragraphs are numbered on a per-page basis.", "value": "This placeholder is replaced by the value that was extracted." }, "time": { diff --git a/apps/red-ui/src/assets/icons/general/pdftron-action-close-compare.svg b/apps/red-ui/src/assets/icons/general/pdftron-action-close-compare.svg deleted file mode 100644 index 82ddb11d8..000000000 --- a/apps/red-ui/src/assets/icons/general/pdftron-action-close-compare.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - diff --git a/apps/red-ui/src/assets/icons/general/pdftron-action-compare.svg b/apps/red-ui/src/assets/icons/general/pdftron-action-compare.svg index 6765155b5..eebcf0634 100644 --- a/apps/red-ui/src/assets/icons/general/pdftron-action-compare.svg +++ b/apps/red-ui/src/assets/icons/general/pdftron-action-compare.svg @@ -2,7 +2,7 @@ - + - - - - + + + + + + + + + + + + diff --git a/apps/red-ui/src/assets/icons/general/pdftron-action-disable-tooltips.svg b/apps/red-ui/src/assets/icons/general/pdftron-action-disable-tooltips.svg deleted file mode 100644 index 2bd50bda8..000000000 --- a/apps/red-ui/src/assets/icons/general/pdftron-action-disable-tooltips.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - disable-tooltip - - - - - - - diff --git a/apps/red-ui/src/assets/icons/general/pdftron-action-enable-layers.svg b/apps/red-ui/src/assets/icons/general/pdftron-action-enable-layers.svg index 779e9a93d..7e67cf9f7 100644 --- a/apps/red-ui/src/assets/icons/general/pdftron-action-enable-layers.svg +++ b/apps/red-ui/src/assets/icons/general/pdftron-action-enable-layers.svg @@ -1,15 +1,23 @@ - - - - - - - + + + + + + + + + + + diff --git a/apps/red-ui/src/assets/icons/general/pdftron-action-enable-tooltips.svg b/apps/red-ui/src/assets/icons/general/pdftron-action-enable-tooltips.svg index 468a0936e..b2db10b9c 100644 --- a/apps/red-ui/src/assets/icons/general/pdftron-action-enable-tooltips.svg +++ b/apps/red-ui/src/assets/icons/general/pdftron-action-enable-tooltips.svg @@ -4,7 +4,7 @@ - + diff --git a/apps/red-ui/src/assets/icons/general/pdftron-cursor.svg b/apps/red-ui/src/assets/icons/general/pdftron-cursor.svg index 1d74faca4..8f0b33281 100644 --- a/apps/red-ui/src/assets/icons/general/pdftron-cursor.svg +++ b/apps/red-ui/src/assets/icons/general/pdftron-cursor.svg @@ -5,7 +5,7 @@ - + diff --git a/apps/red-ui/src/assets/icons/general/pdftron-rectangle.svg b/apps/red-ui/src/assets/icons/general/pdftron-rectangle.svg index 274fec468..e93409203 100644 --- a/apps/red-ui/src/assets/icons/general/pdftron-rectangle.svg +++ b/apps/red-ui/src/assets/icons/general/pdftron-rectangle.svg @@ -1,6 +1,6 @@ - + diff --git a/apps/red-ui/src/assets/pdftron/stylesheet.css b/apps/red-ui/src/assets/pdftron/stylesheet.css index f441d75fc..e62137e5a 100644 --- a/apps/red-ui/src/assets/pdftron/stylesheet.css +++ b/apps/red-ui/src/assets/pdftron/stylesheet.css @@ -47,3 +47,11 @@ button.Button[data-element='LOAD_ALL_ANNOTATIONS'] > img[src='/ui/assets/icons/g opacity: 0.5; cursor: default; } + +.HeaderItems .Button:not(.active):not([data-element='TOGGLE_LAYERS']) > img { + filter: brightness(0) saturate(100%) invert(60%) sepia(11%) saturate(294%) hue-rotate(169deg) brightness(91%) contrast(85%); +} + +.HeaderItems .Button.active > img { + filter: invert(19%) sepia(100%) saturate(791%) hue-rotate(175deg) brightness(89%) contrast(85%); +} diff --git a/libs/red-domain/src/lib/files/super-types.ts b/libs/red-domain/src/lib/files/super-types.ts index c673fc945..027b4eecc 100644 --- a/libs/red-domain/src/lib/files/super-types.ts +++ b/libs/red-domain/src/lib/files/super-types.ts @@ -88,7 +88,7 @@ export const SuperTypeMapper: Record resolveRedactionType(entry), }, [EntityTypes.IMAGE_HINT]: { - [EntryStates.APPLIED]: wrongSuperTypeHandler, + [EntryStates.APPLIED]: entry => resolveRedactionType(entry), [EntryStates.SKIPPED]: () => SuperTypes.Hint, [EntryStates.IGNORED]: () => SuperTypes.IgnoredHint, [EntryStates.REMOVED]: wrongSuperTypeHandler, diff --git a/libs/red-domain/src/lib/redaction-log/types.ts b/libs/red-domain/src/lib/redaction-log/types.ts index c35068387..2586dd09c 100644 --- a/libs/red-domain/src/lib/redaction-log/types.ts +++ b/libs/red-domain/src/lib/redaction-log/types.ts @@ -6,6 +6,7 @@ export const LogEntryEngines = { RULE: 'RULE', IMPORTED: 'IMPORTED', MANUAL: 'MANUAL', + DOSSIER_DICTIONARY: 'DOSSIER_DICTIONARY', } as const; export type LogEntryEngine = ValuesOf;