diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.html b/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.html index 4610330d1..77d368eb3 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.html +++ b/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.html @@ -1,7 +1,6 @@
diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.scss b/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.scss index cedc4054d..1c6ea4bc6 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.scss +++ b/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.scss @@ -12,7 +12,7 @@ } &:hover, - &.active-entity, + &:has(iqser-circle-button[aria-expanded='true']), &.help-mode-active { redaction-file-actions { display: initial; diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.ts b/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.ts index c8a1670ce..6f81ffc56 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/components/workflow-item/workflow-item.component.ts @@ -12,7 +12,6 @@ import { FileWorkloadComponent } from '../table-item/file-workload/file-workload import { ProcessingIndicatorComponent } from '@shared/components/processing-indicator/processing-indicator.component'; import { FileActionsComponent } from '../../../shared-dossiers/components/file-actions/file-actions.component'; import { AsyncPipe, NgForOf, NgIf } from '@angular/common'; -import { ActiveListingEntityService } from '@common-ui/listing/services/active-listing-entity.service'; @Component({ selector: 'redaction-workflow-item', @@ -39,14 +38,12 @@ export class WorkflowItemComponent implements OnInit { @ViewChild('actionsWrapper', { static: true }) private _actionsWrapper: ElementRef; width: number; readonly trackBy = trackByFactory(); - readonly activeEntity = computed(() => this._activeListingEntityService.activeEntity() === this.file?.id); @Input({ required: true }) file: File; @Input({ required: true }) dossier: Dossier; @Input({ required: true }) displayedAttributes: IFileAttributeConfig[]; constructor( readonly fileAttributesService: FileAttributesService, - readonly _activeListingEntityService: ActiveListingEntityService, private readonly _changeRef: ChangeDetectorRef, @Optional() readonly helpModeService: HelpModeService, ) {} 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 51bf95b54..90dd06fc8 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 @@ -3,11 +3,11 @@ import { KeyValuePipe, NgClass, NgForOf, NgIf } from '@angular/common'; import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { MatIcon } from '@angular/material/icon'; -import { FilterService } from '@common-ui/filtering'; import { CircleButtonComponent, IconButtonComponent, IconButtonTypes, IqserDialog } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { IComponentLogEntry, IComponentValue } from '@red/domain'; import { RevertValueDialogComponent } from '../../dialogs/docu-mine/revert-value-dialog/revert-value-dialog.component'; +import { FilePreviewStateService } from '../../services/file-preview-state.service'; @Component({ selector: 'redaction-editable-structured-component-value [entry] [canEdit]', @@ -43,8 +43,8 @@ export class EditableStructuredComponentValueComponent implements OnInit { selected = false; constructor( - private readonly _filtersService: FilterService, private readonly _iqserDialog: IqserDialog, + private readonly _state: FilePreviewStateService, ) {} get disabled() { @@ -91,7 +91,7 @@ export class EditableStructuredComponentValueComponent implements OnInit { } this.deselectLast.emit(); this.selected = true; - this.#setWorkloadFilters(); + this._state.componentReferenceIds = this.#getUniqueReferencesIds(this.entry.componentValues); } } @@ -106,7 +106,7 @@ export class EditableStructuredComponentValueComponent implements OnInit { $event?.stopImmediatePropagation(); this.selected = false; this.editing = false; - this._filtersService.deactivateFilters({ primaryFiltersSlug: 'primaryFilters' }); + this._state.componentReferenceIds = null; } removeValue(index: number) { @@ -150,41 +150,14 @@ export class EditableStructuredComponentValueComponent implements OnInit { return value.replace(/\n/g, '
'); } - #setWorkloadFilters() { - this._filtersService.deactivateFilters({ primaryFiltersSlug: 'primaryFilters' }); - const uniqueLabels = this.#getUniqueReferencesLabels(this.entry.componentValues); - let setFilterCount = 0; - for (const label of uniqueLabels) { - const setFilter = this.#setFilter(label); - if (setFilter) { - setFilterCount++; - } - } - if (!setFilterCount) { - this.#setFilter('no-annotations-filter'); - } - } - - #setFilter(label: string) { - const filterGroup = this._filtersService.getGroup('primaryFilters'); - for (const filter of filterGroup.filters) { - const nestedFilter = filter.children.find(f => f.label.toLowerCase() === label); - if (nestedFilter) { - this._filtersService.filterCheckboxClicked({ nestedFilter, filterGroup, primaryFiltersSlug: 'primaryFilters' }); - return true; - } - } - } - - #getUniqueReferencesLabels(values: IComponentValue[]) { - const labels: Set = new Set(); + #getUniqueReferencesIds(values: IComponentValue[]) { + const ids: Set = new Set(); for (const value of values) { for (const reference of value.entityReferences) { - const label = reference.type?.replace(/_/g, ' ')?.toLowerCase(); - labels.add(label); + ids.add(reference.id); } } - return labels; + return Array.from(ids); } #updateTextAreaHeight() { diff --git a/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.html b/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.html index 9e6fac31b..531d15776 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.html @@ -185,26 +185,19 @@ >. - - {{ 'file-preview.tabs.annotations.no-annotations' | translate }} - - - {{ 'file-preview.tabs.annotations.wrong-filters' | translate }} - - {{ 'file-preview.tabs.annotations.the-filters' | translate }} - + @if ((fileDataService.allLength$ | async) > 0 && displayedPages.length === 0) { + @if (this.enabledFilters?.length) { + {{ 'file-preview.tabs.annotations.wrong-filters' | translate }} + + {{ 'file-preview.tabs.annotations.the-filters' | translate }} + } @else if (state.componentReferenceIds?.length === 0) { + {{ 'file-preview.tabs.annotations.no-annotations' | translate }} + } + }
diff --git a/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts b/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts index 4cb63a58d..3bc1ba7b9 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts @@ -20,7 +20,7 @@ import { AutoUnsubscribe, Debounce, IqserEventTarget } from '@iqser/common-ui/li import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { ListItem } from '@models/file/list-item'; import { TranslateModule } from '@ngx-translate/core'; -import { WorkflowFileStatuses } from '@red/domain'; +import { ComponentLogEntry, WorkflowFileStatuses } from '@red/domain'; import { workloadTranslations } from '@translations/workload-translations'; import { UserPreferenceService } from '@users/user-preference.service'; import { getLocalStorageDataByFileId } from '@utils/local-storage'; @@ -90,9 +90,10 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On protected readonly currentPageIsExcluded = computed(() => this.state.file().excludedPages.includes(this.pdf.currentPage())); protected readonly translations = workloadTranslations; protected readonly isDocumine = getConfig().IS_DOCUMINE; - displayedAnnotations = new Map(); - displayedPages: number[] = []; - pagesPanelActive = true; + protected displayedAnnotations = new Map(); + protected displayedPages: number[] = []; + protected pagesPanelActive = true; + protected enabledFilters = []; constructor( readonly filterService: FilterService, @@ -176,11 +177,14 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On this.fileDataService.all$, primary$, secondary$, + this.state.componentReferenceIds$, this.listingService.selected$, this._pageRotationService.rotations$, ]).pipe( delay(0), - map(([annotations, primary, secondary]) => this.#filterAnnotations(annotations, primary, secondary)), + map(([annotations, primary, secondary, componentReferenceIds]) => + this.#filterAnnotations(annotations, primary, secondary, componentReferenceIds), + ), map(annotations => this.#mapListItemsFromAnnotationWrapperArray(annotations)), tap(annotations => this.#scrollToFirstAnnotationPage(annotations)), ); @@ -399,6 +403,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On annotations: AnnotationWrapper[], primary: INestedFilter[], secondary: INestedFilter[] = [], + componentReferenceIds: string[], ): Map { const onlyPageWithAnnotations = this.viewModeService.onlyPagesWithAnnotations(); if (!primary || primary.length === 0) { @@ -410,21 +415,26 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On annotations = annotations.filter(a => !a.isRemoved); } - if (this.isDocumine && !this.#isIqserDevMode) { - annotations = annotations.filter(a => !a.isOCR); + if (this.isDocumine) { + if (!this.#isIqserDevMode) { + annotations = annotations.filter(a => !a.isOCR); + } + if (componentReferenceIds) { + annotations = annotations.filter(a => componentReferenceIds.includes(a.id)); + } } this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(annotations, primary, secondary); const pagesThatDisplayAnnotations = [...this.displayedAnnotations.keys()]; - const enabledFilters = this.filterService.enabledFlatFilters; - if (enabledFilters.some(f => f.id === 'pages-without-annotations')) { - if (enabledFilters.length === 1 && !onlyPageWithAnnotations) { + this.enabledFilters = this.filterService.enabledFlatFilters; + if (this.enabledFilters.some(f => f.id === 'pages-without-annotations')) { + if (this.enabledFilters.length === 1 && !onlyPageWithAnnotations) { this.displayedPages = this.#allPages.filter(page => !pagesThatDisplayAnnotations.includes(page)); } else { this.displayedPages = []; } this.displayedAnnotations.clear(); - } else if (enabledFilters.length || onlyPageWithAnnotations) { + } else if (this.enabledFilters.length || onlyPageWithAnnotations || componentReferenceIds) { this.displayedPages = pagesThatDisplayAnnotations; } else { this.displayedPages = this.#allPages; 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 4cc3bb5bf..0ec8d38ea 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 @@ -3,7 +3,6 @@ import { List } from '@common-ui/utils'; import { IconButtonTypes, LoadingService } from '@iqser/common-ui'; import { ComponentLogEntry, Dictionary, File, IComponentLogEntry, WorkflowFileStatuses } from '@red/domain'; import { ComponentLogService } from '@services/files/component-log.service'; -import { UserPreferenceService } from '@users/user-preference.service'; import { combineLatest, firstValueFrom, Observable } from 'rxjs'; import { EditableStructuredComponentValueComponent } from '../editable-structured-component-value/editable-structured-component-value.component'; import { FilterService, PopupFilterComponent } from '@common-ui/filtering'; @@ -23,7 +22,6 @@ import { TranslateModule } from '@ngx-translate/core'; export class StructuredComponentManagementComponent implements OnInit { protected readonly componentLogData = signal(undefined); protected readonly componentLogData$ = toObservable(this.componentLogData); - protected readonly openScmDialogByDefault = signal(this.userPreferences.getOpenScmDialogByDefault()); protected readonly iconButtonTypes = IconButtonTypes; protected displayedComponents$: Observable; @Input() file: File; @@ -35,7 +33,6 @@ export class StructuredComponentManagementComponent implements OnInit { private readonly _loadingService: LoadingService, private readonly _componentLogFilterService: ComponentLogFilterService, private readonly _filterService: FilterService, - readonly userPreferences: UserPreferenceService, ) {} get canEdit() { @@ -54,12 +51,6 @@ export class StructuredComponentManagementComponent implements OnInit { } } - async toggleOpenScmDialogByDefault() { - await this.userPreferences.toggleOpenScmDialogByDefault(); - await this.userPreferences.reload(); - this.openScmDialogByDefault.set(this.userPreferences.getOpenScmDialogByDefault()); - } - async revertOverride(originalKey: string) { this._loadingService.start(); await firstValueFrom( 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 253b63f4c..e453fb37d 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 @@ -141,10 +141,6 @@ export class AnnotationProcessingService { } } - if (this.#isDocumine) { - this.#createNoAnnotationsFilter(filterMap, filters); - } - return filters.sort((a, b) => SuperTypeSorter[a.id] - SuperTypeSorter[b.id]); } @@ -272,19 +268,4 @@ export class AnnotationProcessingService { return first.pageNumber < second.pageNumber ? -1 : 1; }); } - - #createNoAnnotationsFilter(filterMap: Map, filters: INestedFilter[]) { - const childFilter: IFilter = { - id: 'no-annotations-filter', - label: 'no-annotations-filter', - checked: false, - matches: 1, - skipTranslation: true, - hidden: true, - }; - - const newChildFilter = new Filter(childFilter); - filterMap.set('no-annotations-filter', newChildFilter); - filters[0]?.children.push(newChildFilter); - } } 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 6f584dd5d..50b8f579e 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 @@ -14,7 +14,7 @@ import { FilesMapService } from '@services/files/files-map.service'; import { FilesService } from '@services/files/files.service'; import { PermissionsService } from '@services/permissions.service'; import { NGXLogger } from 'ngx-logger'; -import { firstValueFrom, from, merge, Observable, of, pairwise, Subject, switchMap } from 'rxjs'; +import { BehaviorSubject, firstValueFrom, from, merge, Observable, of, pairwise, Subject, switchMap } from 'rxjs'; import { filter, map, startWith, tap, withLatestFrom } from 'rxjs/operators'; import { ViewModeService } from './view-mode.service'; @@ -41,6 +41,8 @@ export class FilePreviewStateService { readonly isWritable: Signal; readonly dossierDictionary: Signal; readonly blob$: Observable; + readonly componentReferenceIds$: Observable; + readonly #componentReferenceIds$ = new BehaviorSubject(null); readonly dossierId = getParam(DOSSIER_ID); readonly dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); readonly fileId = getParam(FILE_ID); @@ -62,6 +64,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.componentReferenceIds$ = this.#componentReferenceIds$.asObservable(); this.excludedPages = signal(this.file().excludedPages); this.isWritable = computed(() => { const isWritable = this._permissionsService.canPerformAnnotationActions(this.file(), this.dossier()); @@ -91,6 +94,10 @@ export class FilePreviewStateService { ); } + set componentReferenceIds(ids: string[]) { + this.#componentReferenceIds$.next(ids); + } + get dictionaries(): Dictionary[] { const dictionaries = this._dictionariesMapService.get(this.dossierTemplateId); if (this.dossierDictionary()) { @@ -126,6 +133,10 @@ export class FilePreviewStateService { ); } + get componentReferenceIds() { + return this.#componentReferenceIds$.getValue(); + } + reloadBlob(): void { this.#reloadBlob$.next(true); } diff --git a/apps/red-ui/src/app/modules/pdf-viewer/components/paginator/paginator.component.html b/apps/red-ui/src/app/modules/pdf-viewer/components/paginator/paginator.component.html index 221d497fe..006a7bc77 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/components/paginator/paginator.component.html +++ b/apps/red-ui/src/app/modules/pdf-viewer/components/paginator/paginator.component.html @@ -1,4 +1,8 @@ -