From f709edb2ee68750262df1810fd63c35cbacc4108 Mon Sep 17 00:00:00 2001 From: Valentin Mihai Date: Wed, 24 Apr 2024 21:48:35 +0300 Subject: [PATCH] RED-8748 - WIP on filtering components --- .../annotation-card.component.html | 4 +- .../annotation-card.component.scss | 7 ++++ .../annotation-card.component.ts | 6 ++- .../annotations-list.component.html | 1 + .../annotations-list.component.scss | 3 +- .../annotations-list.component.ts | 3 +- ...-structured-component-value.component.html | 23 +++++----- ...-structured-component-value.component.scss | 35 ++++++++++++++-- ...le-structured-component-value.component.ts | 42 +++++++++---------- ...ctured-component-management.component.html | 2 +- ...ructured-component-management.component.ts | 12 +++++- .../file-preview/file-preview-providers.ts | 2 + .../services/component-log-filter.service.ts | 29 +++++++++++++ apps/red-ui/src/app/utils/filter-utils.ts | 4 +- 14 files changed, 125 insertions(+), 48 deletions(-) create mode 100644 apps/red-ui/src/app/modules/file-preview/services/component-log-filter.service.ts diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html index 50a482417..e017c7e41 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html @@ -6,7 +6,7 @@ class="mt-6 mr-10" > -
+
{{ annotation.superTypeLabel | translate }}   @@ -15,7 +15,7 @@
-
+
{{ annotation.descriptor | translate }}: diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.scss b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.scss index 79b889eaf..6be337063 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.scss +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.scss @@ -3,6 +3,13 @@ position: relative; font-size: 11px; line-height: 14px; + + .type-label { + width: 130px; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } } .active-icon-marker-container { diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.ts b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.ts index 8fb71348f..20c573ffd 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.ts @@ -3,6 +3,7 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { MultiSelectService } from '../../services/multi-select.service'; import { annotationTypesTranslations } from '@translations/annotation-types-translations'; import { Roles } from '@users/roles'; +import { getConfig } from '@iqser/common-ui'; @Component({ selector: 'redaction-annotation-card', @@ -10,8 +11,9 @@ import { Roles } from '@users/roles'; styleUrls: ['./annotation-card.component.scss'], }) export class AnnotationCardComponent { - readonly roles = Roles; - readonly annotationTypesTranslations = annotationTypesTranslations; + protected readonly roles = Roles; + protected readonly annotationTypesTranslations = annotationTypesTranslations; + protected readonly isDocumine = getConfig().IS_DOCUMINE; @Input() annotation: AnnotationWrapper; @Input() isSelected = false; diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.html b/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.html index 1d960a7ab..c62243644 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.html @@ -8,6 +8,7 @@ (click)="annotationClicked(annotation.item, $event)" [annotation]="annotation" [id]="'annotation-' + annotation.item.id" + [class.documine-wrapper]="isDocumine" > diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.scss b/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.scss index 5f41248b8..1623da0aa 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.scss +++ b/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.scss @@ -10,7 +10,8 @@ @include common-mixins.scroll-bar; } - &.has-scrollbar:hover redaction-annotation-wrapper::ng-deep { + &.has-scrollbar:hover redaction-annotation-wrapper::ng-deep, + &::ng-deep.documine-wrapper { .annotation { padding-right: 5px; } diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.ts b/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.ts index e1a7a033b..0ef4a6d48 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectorRef, Component, computed, ElementRef, EventEmitter, Input, Output } from '@angular/core'; -import { HasScrollbarDirective } from '@iqser/common-ui'; +import { getConfig, HasScrollbarDirective } from '@iqser/common-ui'; import { FilterService } from '@iqser/common-ui/lib/filtering'; import { IqserEventTarget } from '@iqser/common-ui/lib/utils'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; @@ -26,6 +26,7 @@ export class AnnotationsListComponent extends HasScrollbarDirective { } return [] as EarmarkGroup[]; }); + protected readonly isDocumine = getConfig().IS_DOCUMINE; constructor( protected readonly _elementRef: ElementRef, diff --git a/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.html b/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.html index ca19f3835..25abd1b20 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.html @@ -11,10 +11,9 @@ (action)="edit()" *ngIf="canEdit" [tooltip]="'component-management.actions.edit' | translate" - class="ml-2" icon="iqser:edit" > -
+
@@ -22,41 +21,41 @@
- -
+ +
-
- +
+
- -
diff --git a/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.scss b/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.scss index 901d6b438..5f619e3a6 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.scss +++ b/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.scss @@ -90,18 +90,26 @@ .editing-value { display: flex; - align-items: center; margin: 10px 0 10px 22px; .iqser-input-group { margin-top: 0; - textarea { - resize: none; + textarea::-webkit-resizer { + display: none; + } + + textarea::-moz-resizer { + display: none; } } + iqser-circle-button { + margin-top: 3px; + } + .draggable { + margin-top: 7px; cursor: grab; } } @@ -111,11 +119,30 @@ flex-direction: row; align-items: center; gap: 12px; - margin: 20px 10px 10px 22px; + margin: 30px 10px 10px 22px; .right { margin-left: auto; + gap: 10px; } } } } + +::ng-deep .add-value { + mat-icon { + transform: scale(2); + } +} + +::ng-deep .undo-value { + mat-icon { + transform: scale(1.3); + } +} + +::ng-deep .remove-value { + mat-icon { + transform: scale(1.2); + } +} diff --git a/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.ts b/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.ts index 24545fcb0..e4bb4783e 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.ts @@ -1,36 +1,29 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { ComponentLogEntry } from '@red/domain'; import { FormBuilder, FormControl, UntypedFormGroup } from '@angular/forms'; -import { IconButtonTypes } from '@iqser/common-ui'; +import { BaseFormComponent } from '@iqser/common-ui'; @Component({ selector: 'redaction-editable-structured-component-value [entry] [canEdit]', templateUrl: './editable-structured-component-value.component.html', styleUrls: ['/editable-structured-component-value.component.scss'], }) -export class EditableStructuredComponentValueComponent implements OnInit { +export class EditableStructuredComponentValueComponent extends BaseFormComponent implements OnInit { @Input() entry: ComponentLogEntry; @Input() canEdit: boolean; @Output() readonly deselectLast = new EventEmitter(); - protected readonly iconButtonTypes = IconButtonTypes; - form: UntypedFormGroup; selected = false; editing = false; - constructor(private readonly _formBuilder: FormBuilder) {} + constructor(private readonly _formBuilder: FormBuilder) { + super(); + } ngOnInit() { this.form = this.#getForm(); - } - - #getForm() { - const form = this._formBuilder.group({}); - this.entry.componentValues.forEach((value, index) => { - form.addControl(index.toString(), this._formBuilder.control(value.value ?? value.originalValue)); - }); - return form; + this.initialFormValue = this.form.getRawValue(); } select() { @@ -56,23 +49,26 @@ export class EditableStructuredComponentValueComponent implements OnInit { this.editing = false; } - removeValue(key: number) { - this.form.removeControl(key.toString()); + removeValue(key: string) { + this.form.removeControl(key); } - save() {} + async save() { + const value = this.form.getRawValue(); + } undo(originalKey: string) {} add() { - const key = (Object.keys(this.form.controls).length + 1).toString(); + const key = Object.keys(this.form.controls).length.toString(); this.form.addControl(key, new FormControl('')); - this.entry.componentValues.push({ - value: '', - originalValue: '', - valueDescription: '', - componentRuleId: '', - entityReferences: [], + } + + #getForm() { + const form = this._formBuilder.group({}); + this.entry.componentValues.forEach((value, index) => { + form.addControl(index.toString(), this._formBuilder.control(value.value ?? value.originalValue)); }); + return form; } } diff --git a/apps/red-ui/src/app/modules/file-preview/components/structured-component-management/structured-component-management.component.html b/apps/red-ui/src/app/modules/file-preview/components/structured-component-management/structured-component-management.component.html index bde5b1bf2..ce7af1ab5 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/structured-component-management/structured-component-management.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/structured-component-management/structured-component-management.component.html @@ -1,6 +1,6 @@
- +
diff --git a/apps/red-ui/src/app/modules/file-preview/components/structured-component-management/structured-component-management.component.ts b/apps/red-ui/src/app/modules/file-preview/components/structured-component-management/structured-component-management.component.ts index 1191df27a..664e8c63d 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/structured-component-management/structured-component-management.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/structured-component-management/structured-component-management.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, QueryList, signal, ViewChildren } from '@angular/core'; +import { Component, Input, signal, ViewChildren } from '@angular/core'; import { ComponentLogEntry, Dictionary, File, WorkflowFileStatuses } from '@red/domain'; import { IconButtonTypes, LoadingService } from '@iqser/common-ui'; import { ComponentLogService } from '@services/files/component-log.service'; @@ -7,6 +7,8 @@ import { UserPreferenceService } from '@users/user-preference.service'; import { firstValueFrom } from 'rxjs'; import { List } from '@common-ui/utils'; import { EditableStructuredComponentValueComponent } from '../editable-structured-component-value/editable-structured-component-value.component'; +import { FilterService } from '@common-ui/filtering'; +import { ComponentLogFilterService } from '../../services/component-log-filter.service'; interface DeselectEvent { name: string; @@ -31,6 +33,8 @@ export class StructuredComponentManagementComponent { private readonly _componentLogService: ComponentLogService, private readonly _filesMapService: FilesMapService, private readonly _loadingService: LoadingService, + private readonly _componentLogFilterService: ComponentLogFilterService, + private readonly _filterService: FilterService, readonly userPreferences: UserPreferenceService, ) {} @@ -100,6 +104,7 @@ export class StructuredComponentManagementComponent { const componentLogData = await firstValueFrom( this._componentLogService.getComponentLogData(this.file.dossierTemplateId, this.file.dossierId, this.file.fileId), ); + this.#computeFilters(componentLogData); this.#updateDisplayValue(componentLogData); this.componentLogData.set(componentLogData); this._loadingService.stop(); @@ -120,4 +125,9 @@ export class StructuredComponentManagementComponent { } } } + + #computeFilters(componentLogs: ComponentLogEntry[]) { + const filterGroups = this._componentLogFilterService.filterGroups(componentLogs); + this._filterService.addFilterGroups(filterGroups); + } } 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 e809b6ab5..e4abcaae4 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 @@ -16,6 +16,7 @@ import { PdfProxyService } from './services/pdf-proxy.service'; import { SkippedService } from './services/skipped.service'; import { StampService } from './services/stamp.service'; import { ViewModeService } from './services/view-mode.service'; +import { ComponentLogFilterService } from './services/component-log-filter.service'; export const filePreviewScreenProviders = [ FilterService, @@ -38,4 +39,5 @@ export const filePreviewScreenProviders = [ SearchService, StampService, PdfProxyService, + ComponentLogFilterService, ]; diff --git a/apps/red-ui/src/app/modules/file-preview/services/component-log-filter.service.ts b/apps/red-ui/src/app/modules/file-preview/services/component-log-filter.service.ts new file mode 100644 index 000000000..77360f0a6 --- /dev/null +++ b/apps/red-ui/src/app/modules/file-preview/services/component-log-filter.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@angular/core'; +import { ComponentLogEntry } from '@red/domain'; +import { NestedFilter } from '@common-ui/filtering'; +import { componentLogChecker } from '@utils/filter-utils'; + +@Injectable() +export class ComponentLogFilterService { + filterGroups(entities: ComponentLogEntry[]) { + const allDistinctComponentLogs = new Set(); + + entities?.forEach(entry => allDistinctComponentLogs.add(entry.name)); + + const componentLogFilters = [...allDistinctComponentLogs].map( + id => + new NestedFilter({ + id: id, + label: id, + }), + ); + + return [ + { + slug: 'componentLogFilters', + filters: componentLogFilters, + checker: componentLogChecker, + }, + ]; + } +} diff --git a/apps/red-ui/src/app/utils/filter-utils.ts b/apps/red-ui/src/app/utils/filter-utils.ts index 68bf58595..8793b9e0e 100644 --- a/apps/red-ui/src/app/utils/filter-utils.ts +++ b/apps/red-ui/src/app/utils/filter-utils.ts @@ -1,5 +1,5 @@ import { handleCheckedValue, INestedFilter } from '@iqser/common-ui/lib/filtering'; -import { Dossier, File, User, UserType } from '@red/domain'; +import { ComponentLogEntry, Dossier, File, User, UserType } from '@red/domain'; export function handleFilterDelta(oldFilters: INestedFilter[], newFilters: INestedFilter[], allFilters: INestedFilter[]) { const newFiltersDelta = {}; @@ -84,6 +84,8 @@ export const dossierTemplateChecker = (dw: Dossier, filter: INestedFilter) => dw export const dossierStateChecker = (dw: Dossier, filter: INestedFilter) => dw.dossierStatusId === (filter.id === 'undefined' ? null : filter.id); +export const componentLogChecker = (componentLogEntry: ComponentLogEntry, filter: INestedFilter) => componentLogEntry.name === filter.id; + export const userTypeFilters: { [key in UserType]: (user: User) => boolean } = { INACTIVE: (user: User) => !user.hasAnyRole, REGULAR: (user: User) => user.roles.length === 1 && user.roles[0] === 'RED_USER',