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 5b113dd43..357f280d6 100644 --- a/apps/red-ui/src/app/models/file/annotation.wrapper.ts +++ b/apps/red-ui/src/app/models/file/annotation.wrapper.ts @@ -57,11 +57,10 @@ export class AnnotationWrapper { isChangeLogEntry?: boolean; changeLogType?: 'ADDED' | 'REMOVED'; + engines?: string[]; private _origin: RedactionLogEntryWrapper; - constructor() {} - get isChangeLogRemoved() { return this.changeLogType === 'REMOVED'; } @@ -220,6 +219,7 @@ export class AnnotationWrapper { annotationWrapper.legalBasisValue = redactionLogEntry.legalBasis; annotationWrapper.comments = redactionLogEntry.comments || []; annotationWrapper.manual = redactionLogEntry.manual; + annotationWrapper.engines = redactionLogEntry.engines; this._createContent(annotationWrapper, redactionLogEntry); this._setSuperType(annotationWrapper, redactionLogEntry); diff --git a/apps/red-ui/src/app/models/file/redaction-log-entry.wrapper.ts b/apps/red-ui/src/app/models/file/redaction-log-entry.wrapper.ts index 2ddc9d003..728a87532 100644 --- a/apps/red-ui/src/app/models/file/redaction-log-entry.wrapper.ts +++ b/apps/red-ui/src/app/models/file/redaction-log-entry.wrapper.ts @@ -35,4 +35,5 @@ export interface RedactionLogEntryWrapper { recategorizationType?: string; legalBasisChangeValue?: string; + engines?: string[]; } diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/reset-password/reset-password.component.html b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/reset-password/reset-password.component.html index 1cfcc107f..f16527517 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/reset-password/reset-password.component.html +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/reset-password/reset-password.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/reset-password/reset-password.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/reset-password/reset-password.component.ts index 34881d642..7dfb3d7b3 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/reset-password/reset-password.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/reset-password/reset-password.component.ts @@ -23,10 +23,6 @@ export class ResetPasswordComponent { private readonly _loadingService: LoadingService ) {} - get userName() { - return this._userService.getNameForId(this.user.id); - } - async save() { this._loadingService.start(); await this._userControllerService diff --git a/apps/red-ui/src/app/modules/dossier/components/comments/comments.component.html b/apps/red-ui/src/app/modules/dossier/components/comments/comments.component.html index f41430b73..e284ee1c3 100644 --- a/apps/red-ui/src/app/modules/dossier/components/comments/comments.component.html +++ b/apps/red-ui/src/app/modules/dossier/components/comments/comments.component.html @@ -1,9 +1,10 @@
- {{ getOwnerName(comment) }} + {{ comment.user | name }} {{ comment.date | date: 'sophisticatedDate' }}
+
+
{{ comment.text }}
diff --git a/apps/red-ui/src/app/modules/dossier/components/comments/comments.component.ts b/apps/red-ui/src/app/modules/dossier/components/comments/comments.component.ts index e5fbd8e13..40537f464 100644 --- a/apps/red-ui/src/app/modules/dossier/components/comments/comments.component.ts +++ b/apps/red-ui/src/app/modules/dossier/components/comments/comments.component.ts @@ -52,8 +52,4 @@ export class CommentsComponent { } }); } - - getOwnerName(comment: Comment): string { - return this._userService.getNameForId(comment.user); - } } diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotation-source/annotation-source.component.html b/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotation-source/annotation-source.component.html new file mode 100644 index 000000000..766e23aa6 --- /dev/null +++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotation-source/annotation-source.component.html @@ -0,0 +1,23 @@ + +
+ + + +
+ + +
+ +
+ + {{ engine.description }} +
+
+
+
+
diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotation-source/annotation-source.component.scss b/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotation-source/annotation-source.component.scss new file mode 100644 index 000000000..1d0cf5aa6 --- /dev/null +++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotation-source/annotation-source.component.scss @@ -0,0 +1,51 @@ +@use 'variables'; + +.popover { + width: 260px; + padding: 10px; + border-radius: 3px; + background-color: variables.$grey-1; + color: variables.$white; + + mat-icon { + color: variables.$white; + flex-shrink: 0; + } + + span { + padding-left: 8px; + font-size: 11px; + line-height: 14px; + } +} + +.chip { + height: 24px; + + &:hover { + background-color: variables.$grey-6; + border-radius: 12px; + + mat-icon { + opacity: 1; + } + } + + mat-icon { + opacity: 50%; + margin-left: 3px; + margin-right: 3px; + + &:first-of-type { + margin-left: 8px; + } + + &:last-of-type { + margin-right: 8px; + } + } +} + +mat-icon { + width: 10px; +} diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotation-source/annotation-source.component.ts b/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotation-source/annotation-source.component.ts new file mode 100644 index 000000000..f22c9eaa9 --- /dev/null +++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotation-source/annotation-source.component.ts @@ -0,0 +1,65 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { AnnotationWrapper } from '@models/file/annotation.wrapper'; +import { OnChange } from '@iqser/common-ui'; +import { TranslateService } from '@ngx-translate/core'; + +interface Engine { + readonly icon: string; + readonly description: string; + readonly show: boolean; +} + +type Engines = readonly Engine[]; + +const Engines = { + DICTIONARY: 'DICTIONARY', + NER: 'NER', + RULE: 'RULE' +} as const; + +type EngineName = keyof typeof Engines; + +@Component({ + selector: 'redaction-annotation-source', + templateUrl: './annotation-source.component.html', + styleUrls: ['./annotation-source.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AnnotationSourceComponent { + @Input() + @OnChange('updateEngines') + annotation: AnnotationWrapper; + + isPopoverOpen = false; + engines: Engines; + + constructor(private readonly _translateService: TranslateService) {} + + get hasEnginesToShow(): boolean { + return this.engines.length && this.engines.some(source => source.show); + } + + updateEngines(): void { + this.engines = [ + { + icon: 'red:dictionary', + description: this._translateService.instant('annotation-engines.dictionary'), + show: this._isBasedOn(Engines.DICTIONARY) + }, + { + icon: 'red:ai', + description: this._translateService.instant('annotation-engines.ner'), + show: this._isBasedOn(Engines.NER) + }, + { + icon: 'red:rule', + description: this._translateService.instant('annotation-engines.rule', { rule: this.annotation.legalBasisValue }), + show: this._isBasedOn(Engines.RULE) + } + ]; + } + + private _isBasedOn(engineName: EngineName) { + return !!this.annotation.engines?.includes(engineName); + } +} diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotations-list/annotations-list.component.html b/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotations-list/annotations-list.component.html new file mode 100644 index 000000000..c4545aa39 --- /dev/null +++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotations-list/annotations-list.component.html @@ -0,0 +1,62 @@ +
+
+ +
+
+ + +
+
+ {{ annotation.typeLabel | translate }} +
+
+ + {{ annotation.descriptor | translate }}: {{ annotation.type | humanize: false }} +
+
+ : {{ annotation.shortContent }} +
+
+ +
+ +
+
+ +
+
+ + {{ annotation.comments.length }} +
+ +
+ +
+
+ + +
+ + +
diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotations-list/annotations-list.component.scss b/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotations-list/annotations-list.component.scss new file mode 100644 index 000000000..60afc5027 --- /dev/null +++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotations-list/annotations-list.component.scss @@ -0,0 +1,96 @@ +@use 'variables'; + +:host { + width: 100%; + position: relative; +} + +.annotation-wrapper { + display: flex; + width: 100%; + border-bottom: 1px solid variables.$separator; + + .active-bar-marker { + min-width: 4px; + min-height: 100%; + } + + .active-icon-marker-container { + min-width: 20px; + } + + &.active { + &:not(.lower-height) .active-bar-marker { + background-color: variables.$primary; + } + } + + .annotation { + padding: 10px 16px 8px 10px; + font-size: 11px; + line-height: 14px; + cursor: pointer; + display: flex; + flex-direction: column; + width: 100%; + + &.removed { + text-decoration: line-through; + color: variables.$grey-7; + } + + .details { + display: flex; + position: relative; + } + + .actions-wrapper { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 8px; + min-height: 34px; + padding-left: 18px; + + .comments-counter { + cursor: pointer; + display: flex; + align-items: center; + padding: 0 8px; + transition: background-color 0.2s; + line-height: 13px; + height: 24px; + border-radius: 12px; + + mat-icon { + width: 10px; + height: 10px; + margin-right: 4px; + } + + &:hover { + background-color: variables.$grey-4; + } + } + } + + redaction-type-annotation-icon { + margin-top: 6px; + margin-right: 10px; + } + } + + &:hover { + background-color: variables.$grey-8; + + ::ng-deep .annotation-actions { + display: flex; + } + } +} + +redaction-annotation-source { + position: absolute; + top: 6px; + right: 8px; +} diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotations-list/annotations-list.component.ts b/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotations-list/annotations-list.component.ts new file mode 100644 index 000000000..391e02415 --- /dev/null +++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/components/annotations-list/annotations-list.component.ts @@ -0,0 +1,48 @@ +import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, TemplateRef } from '@angular/core'; +import { AnnotationWrapper } from '@models/file/annotation.wrapper'; +import { IqserEventTarget } from '@iqser/common-ui'; + +@Component({ + selector: 'redaction-annotations-list', + templateUrl: './annotations-list.component.html', + styleUrls: ['./annotations-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AnnotationsListComponent { + @Input() annotations: AnnotationWrapper[]; + @Input() selectedAnnotations: AnnotationWrapper[]; + @Input() annotationActionsTemplate: TemplateRef; + @Input() multiSelectActive = false; + @Input() activeViewerPage: number; + @Input() canMultiSelect = true; + + @Output() readonly multiSelectActiveChange = new EventEmitter(); + @Output() readonly pagesPanelActive = new EventEmitter(); + @Output() readonly selectAnnotations = new EventEmitter< + AnnotationWrapper[] | { annotations: AnnotationWrapper[]; multiSelect: boolean } + >(); + @Output() readonly deselectAnnotations = new EventEmitter(); + + annotationClicked(annotation: AnnotationWrapper, $event: MouseEvent): void { + if (($event.target as IqserEventTarget).localName === 'input') { + return; + } + this.pagesPanelActive.emit(false); + if (this.isSelected(annotation.annotationId)) { + this.deselectAnnotations.emit([annotation]); + } else { + if (this.canMultiSelect && ($event.ctrlKey || $event.metaKey) && this.selectedAnnotations.length > 0) { + this.multiSelectActive = true; + this.multiSelectActiveChange.emit(true); + } + this.selectAnnotations.emit({ + annotations: [annotation], + multiSelect: this.multiSelectActive + }); + } + } + + isSelected(annotationId: string): boolean { + return !!this.selectedAnnotations?.find(a => a?.annotationId === annotationId); + } +} diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html index 27a895164..05ec345ea 100644 --- a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html +++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html @@ -1,6 +1,3 @@ - - -
- . @@ -174,62 +170,17 @@
-
-
-
-
- -
-
- {{ annotation.typeLabel | translate }} -
-
- - {{ annotation.descriptor | translate }}: {{ annotation.type | humanize: false }} -
-
- : {{ annotation.shortContent }} -
-
- -
- -
-
- -
-
- - {{ annotation.comments.length }} -
-
- -
-
- -
-
+
diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.scss b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.scss index e15439435..f96c2b1fd 100644 --- a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.scss +++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.scss @@ -157,96 +157,12 @@ align-items: center; flex-direction: column; - .annotation-wrapper { - display: flex; - width: 100%; - border-bottom: 1px solid variables.$separator; - - .active-bar-marker { - min-width: 4px; - min-height: 100%; - } - - .active-icon-marker-container { - min-width: 20px; - } - - &.active { - &:not(.lower-height) .active-bar-marker { - background-color: variables.$primary; - } - } - - .annotation { - padding: 10px 16px 8px 10px; - font-size: 11px; - line-height: 14px; - cursor: pointer; - display: flex; - flex-direction: column; - width: 100%; - - &.removed { - text-decoration: line-through; - color: variables.$grey-7; - } - - .details { - display: flex; - position: relative; - } - - .actions-wrapper { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 8px; - min-height: 34px; - padding-left: 18px; - - .comments-counter { - cursor: pointer; - display: flex; - align-items: center; - padding: 0 8px; - transition: background-color 0.2s; - line-height: 13px; - height: 24px; - border-radius: 12px; - - mat-icon { - width: 10px; - height: 10px; - margin-right: 4px; - } - - &:hover { - background-color: variables.$grey-4; - } - } - } - - redaction-type-annotation-icon { - margin-top: 6px; - margin-right: 10px; - } - } - - &:hover { - background-color: variables.$grey-8; - - ::ng-deep .annotation-actions { - display: flex; - } - } - } - &:hover { overflow-y: auto; @include common-mixins.scroll-bar; } - &.has-scrollbar:hover .annotation-wrapper .annotation { + &.has-scrollbar:hover::ng-deep .annotation-wrapper .annotation { padding-right: 5px; } } diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts index 112a2cf00..e58b9455b 100644 --- a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts +++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts @@ -1,23 +1,10 @@ -import { - ChangeDetectorRef, - Component, - ElementRef, - EventEmitter, - HostListener, - Input, - Output, - QueryList, - TemplateRef, - ViewChild, - ViewChildren -} from '@angular/core'; +import { ChangeDetectorRef, Component, ElementRef, EventEmitter, HostListener, Input, Output, TemplateRef, ViewChild } from '@angular/core'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { AnnotationProcessingService } from '../../services/annotation-processing.service'; import { MatDialogRef, MatDialogState } from '@angular/material/dialog'; import scrollIntoView from 'scroll-into-view-if-needed'; import { CircleButtonTypes, Debounce, FilterService, IconButtonTypes, IqserEventTarget, NestedFilter } from '@iqser/common-ui'; import { FileDataModel } from '@models/file/file-data.model'; -import { CommentsComponent } from '../comments/comments.component'; import { PermissionsService } from '@services/permissions.service'; import { WebViewerInstance } from '@pdftron/webviewer'; import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; @@ -56,7 +43,6 @@ export class FileWorkloadComponent { @Output() readonly actionPerformed = new EventEmitter(); displayedPages: number[] = []; pagesPanelActive = true; - @ViewChildren(CommentsComponent) readonly annotationCommentsComponents: QueryList; @ViewChild('annotationsElement') private readonly _annotationsElement: ElementRef; @ViewChild('quickNavigation') private readonly _quickNavigationElement: ElementRef; @@ -118,15 +104,6 @@ export class FileWorkloadComponent { } } - isSelected(annotation: AnnotationWrapper) { - return this.selectedAnnotations?.find(a => a?.id === annotation.id); - } - - toggleExpandComments(annotation: AnnotationWrapper, $event: MouseEvent) { - $event.stopPropagation(); - this.annotationCommentsComponents.find(c => c.annotation === annotation).toggleExpandComments(); - } - logAnnotation(annotation: AnnotationWrapper) { console.log(annotation); } @@ -156,25 +133,6 @@ export class FileWorkloadComponent { return this.displayedAnnotations; } - annotationClicked(annotation: AnnotationWrapper, $event: MouseEvent): void { - if (($event.target as IqserEventTarget).localName === 'input') { - return; - } - this.pagesPanelActive = false; - this.logAnnotation(annotation); - if (this.isSelected(annotation)) { - this.deselectAnnotations.emit([annotation]); - } else { - if (($event.ctrlKey || $event.metaKey) && this.selectedAnnotations.length > 0) { - this.multiSelectActive = true; - } - this.selectAnnotations.emit({ - annotations: [annotation], - multiSelect: this.multiSelectActive - }); - } - } - @HostListener('window:keyup', ['$event']) handleKeyEvent($event: KeyboardEvent): void { if ( diff --git a/apps/red-ui/src/app/modules/dossier/components/team-members-manager/team-members-manager.component.html b/apps/red-ui/src/app/modules/dossier/components/team-members-manager/team-members-manager.component.html index 6885e0382..6802347a2 100644 --- a/apps/red-ui/src/app/modules/dossier/components/team-members-manager/team-members-manager.component.html +++ b/apps/red-ui/src/app/modules/dossier/components/team-members-manager/team-members-manager.component.html @@ -4,7 +4,7 @@ {{ 'assign-dossier-owner.dialog.single-user' | translate }} - {{ userService.getNameForId(userId) }} + {{ userId | name }} diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.html b/apps/red-ui/src/app/modules/dossier/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.html index ad948d812..1dd48e2e6 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.html +++ b/apps/red-ui/src/app/modules/dossier/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.html @@ -14,7 +14,7 @@ {{ 'assign-owner.dialog.label' | translate: { type: data.mode } }} - {{ userService.getNameForId(userId) }} + {{ userId | name }} diff --git a/apps/red-ui/src/app/modules/dossier/dossiers.module.ts b/apps/red-ui/src/app/modules/dossier/dossiers.module.ts index 4bcf20638..4daae1ee8 100644 --- a/apps/red-ui/src/app/modules/dossier/dossiers.module.ts +++ b/apps/red-ui/src/app/modules/dossier/dossiers.module.ts @@ -49,6 +49,9 @@ import { DossiersService } from './services/dossiers.service'; import { DossierDetailsStatsComponent } from './components/dossier-details-stats/dossier-details-stats.component'; import { SearchScreenComponent } from './screens/search-screen/search-screen.component'; import { EditDossierDeletedDocumentsComponent } from './dialogs/edit-dossier-dialog/deleted-documents/edit-dossier-deleted-documents.component'; +import { AnnotationsListComponent } from './components/file-workload/components/annotations-list/annotations-list.component'; +import { AnnotationSourceComponent } from './components/file-workload/components/annotation-source/annotation-source.component'; +import { OverlayModule } from '@angular/cdk/overlay'; const screens = [DossierListingScreenComponent, DossierOverviewScreenComponent, FilePreviewScreenComponent, SearchScreenComponent]; @@ -89,6 +92,8 @@ const components = [ PageExclusionComponent, DossierDetailsStatsComponent, EditDossierDeletedDocumentsComponent, + AnnotationsListComponent, + AnnotationSourceComponent, ...screens, ...dialogs @@ -109,6 +114,6 @@ const services = [ @NgModule({ declarations: [...components], providers: [...services], - imports: [CommonModule, SharedModule, FileUploadDownloadModule, DossiersRoutingModule] + imports: [CommonModule, SharedModule, FileUploadDownloadModule, DossiersRoutingModule, OverlayModule] }) export class DossiersModule {} diff --git a/apps/red-ui/src/app/modules/dossier/services/annotation-draw.service.ts b/apps/red-ui/src/app/modules/dossier/services/annotation-draw.service.ts index 42894f3da..471f2f1cb 100644 --- a/apps/red-ui/src/app/modules/dossier/services/annotation-draw.service.ts +++ b/apps/red-ui/src/app/modules/dossier/services/annotation-draw.service.ts @@ -16,11 +16,12 @@ export class AnnotationDrawService { ) {} drawAnnotations(activeViewer: WebViewerInstance, annotationWrappers: AnnotationWrapper[], hideSkipped = false, compareMode = false) { - const annotations = []; - annotationWrappers.forEach(annotation => { - annotations.push(this.computeAnnotation(activeViewer, annotation, hideSkipped, compareMode)); - }); - + if (!activeViewer) { + return; + } + const annotations = annotationWrappers.map(annotation => + this.computeAnnotation(activeViewer, annotation, hideSkipped, compareMode) + ); const annotationManager = activeViewer.Core.annotationManager; annotationManager.addAnnotations(annotations, { imported: true }); annotationManager.drawAnnotationsFromList(annotations); 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 8473e453a..3c63fcc4e 100644 --- a/apps/red-ui/src/app/modules/icons/icons.module.ts +++ b/apps/red-ui/src/app/modules/icons/icons.module.ts @@ -12,6 +12,7 @@ export class IconsModule { constructor(private readonly _iconRegistry: MatIconRegistry, private readonly _sanitizer: DomSanitizer) { const icons = [ 'add', + 'ai', 'analyse', 'approved', 'arrow-right', @@ -62,6 +63,7 @@ export class IconsModule { 'reason', 'remove-from-dict', 'report', + 'rule', 'secret', 'status', 'status-collapse', diff --git a/apps/red-ui/src/app/modules/shared/pipes/name.pipe.ts b/apps/red-ui/src/app/modules/shared/pipes/name.pipe.ts new file mode 100644 index 000000000..b95d4e83c --- /dev/null +++ b/apps/red-ui/src/app/modules/shared/pipes/name.pipe.ts @@ -0,0 +1,17 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { UserService, UserWrapper } from '@services/user.service'; +import { TranslateService } from '@ngx-translate/core'; + +@Pipe({ + name: 'name' +}) +export class NamePipe implements PipeTransform { + constructor(private readonly _userService: UserService, private readonly _translateService: TranslateService) {} + + transform(value: UserWrapper | string): string { + if (typeof value === 'string') { + return this._userService.getNameForId(value) || this._translateService.instant('unknown'); + } + return value.name; + } +} diff --git a/apps/red-ui/src/app/modules/shared/shared.module.ts b/apps/red-ui/src/app/modules/shared/shared.module.ts index 381b6d0bb..06178f8be 100644 --- a/apps/red-ui/src/app/modules/shared/shared.module.ts +++ b/apps/red-ui/src/app/modules/shared/shared.module.ts @@ -25,6 +25,7 @@ import { AssignUserDropdownComponent } from './components/assign-user-dropdown/a import { PageHeaderComponent } from './components/page-header/page-header.component'; import { DatePipe } from '@shared/pipes/date.pipe'; import { LongPressDirective } from '@shared/directives/long-press.directive'; +import { NamePipe } from '@shared/pipes/name.pipe'; const buttons = [FileDownloadBtnComponent, UserButtonComponent]; @@ -45,7 +46,7 @@ const components = [ ...buttons ]; -const utils = [DatePipe, NavigateLastDossiersScreenDirective, LongPressDirective]; +const utils = [DatePipe, NamePipe, NavigateLastDossiersScreenDirective, LongPressDirective]; const modules = [MatConfigModule, ScrollingModule, IconsModule, FormsModule, ReactiveFormsModule, CommonUiModule]; @@ -68,4 +69,5 @@ const modules = [MatConfigModule, ScrollingModule, IconsModule, FormsModule, Rea } ] }) -export class SharedModule {} +export class SharedModule { +} diff --git a/apps/red-ui/src/app/services/user.service.ts b/apps/red-ui/src/app/services/user.service.ts index f0eeaf28f..a7b86c994 100644 --- a/apps/red-ui/src/app/services/user.service.ts +++ b/apps/red-ui/src/app/services/user.service.ts @@ -106,8 +106,7 @@ export class UserService { } getNameForId(userId: string): string | undefined { - const user = this.getUserById(userId); - return user ? user.name : undefined; + return this.getUserById(userId)?.name; } isManager(user: UserWrapper = this._currentUser): boolean { diff --git a/apps/red-ui/src/assets/i18n/de.json b/apps/red-ui/src/assets/i18n/de.json index e2610469f..16ad8a22d 100644 --- a/apps/red-ui/src/assets/i18n/de.json +++ b/apps/red-ui/src/assets/i18n/de.json @@ -1379,5 +1379,10 @@ "text-placeholder": "Text eingeben" }, "title": "Wasserzeichen" + }, + "annotation-engines": { + "dictionary": "", + "ner": "", + "rule": "" } } diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 1eb06a6d1..c5122764f 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -1521,5 +1521,10 @@ }, "title": "Watermark" }, - "yesterday": "Yesterday" + "yesterday": "Yesterday", + "annotation-engines": { + "dictionary": "Redaction based on dictionary", + "ner": "Redaction based on AI", + "rule": "Redaction based on rule {rule}" + } } diff --git a/apps/red-ui/src/assets/icons/general/ai.svg b/apps/red-ui/src/assets/icons/general/ai.svg new file mode 100644 index 000000000..34a989ee0 --- /dev/null +++ b/apps/red-ui/src/assets/icons/general/ai.svg @@ -0,0 +1,12 @@ + + + ai + + + + + + diff --git a/apps/red-ui/src/assets/icons/general/rule.svg b/apps/red-ui/src/assets/icons/general/rule.svg new file mode 100644 index 000000000..6543b4767 --- /dev/null +++ b/apps/red-ui/src/assets/icons/general/rule.svg @@ -0,0 +1,12 @@ + + + rule + + + + + + diff --git a/libs/common-ui b/libs/common-ui index a16d1db3a..b55e3bf0d 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit a16d1db3ab938dccc2c9d82c5e3d283bb857f46c +Subproject commit b55e3bf0ddbda8e8459cb0ae23c8abd5fff46a18 diff --git a/libs/red-ui-http/src/lib/model/redactionLogEntry.ts b/libs/red-ui-http/src/lib/model/redactionLogEntry.ts index f84bd6689..c4b9745f1 100644 --- a/libs/red-ui-http/src/lib/model/redactionLogEntry.ts +++ b/libs/red-ui-http/src/lib/model/redactionLogEntry.ts @@ -40,6 +40,7 @@ export interface RedactionLogEntry { type?: string; value?: string; legalBasisChangeValue?: string; + engines?: string[]; } export namespace RedactionLogEntry {