diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/file-workload/file-workload.component.html b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/file-workload/file-workload.component.html index 36978ca6f..4f1b7424d 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/file-workload/file-workload.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/file-workload/file-workload.component.html @@ -207,7 +207,7 @@ > - + diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-exclusion/page-exclusion.component.html b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-exclusion/page-exclusion.component.html index acafdb9c1..4e7f39197 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-exclusion/page-exclusion.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-exclusion/page-exclusion.component.html @@ -1,4 +1,4 @@ -
+
-
+
-
-
+
+
{{ range.startPage }} + {{ range.startPage }} - {{ range.endPage }} +
-
+
diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-exclusion/page-exclusion.component.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-exclusion/page-exclusion.component.ts index b4689a5e2..ef40421ca 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-exclusion/page-exclusion.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-exclusion/page-exclusion.component.ts @@ -1,21 +1,23 @@ -import { Component, Input, OnChanges, ViewChild } from '@angular/core'; +import { Component, ViewChild } from '@angular/core'; import { PermissionsService } from '@services/permissions.service'; -import { InputWithActionComponent, LoadingService, Toaster } from '@iqser/common-ui'; +import { InputWithActionComponent, LoadingService, shareLast, Toaster } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { File, IPageRange } from '@red/domain'; +import { IPageRange } from '@red/domain'; import { ReanalysisService } from '@services/reanalysis.service'; import { ExcludedPagesService } from '../../services/excluded-pages.service'; -import { firstValueFrom } from 'rxjs'; +import { combineLatest, firstValueFrom, Observable } from 'rxjs'; +import { FilePreviewStateService } from '../../services/file-preview-state.service'; +import { map, pluck } from 'rxjs/operators'; @Component({ selector: 'redaction-page-exclusion', templateUrl: './page-exclusion.component.html', styleUrls: ['./page-exclusion.component.scss'], }) -export class PageExclusionComponent implements OnChanges { - @Input() file: File; - - excludedPagesRanges: IPageRange[] = []; +export class PageExclusionComponent { + readonly excludedRanges$: Observable; + readonly canExcludePages$: Observable; + readonly noExcludedAndCantExclude$: Observable; @ViewChild(InputWithActionComponent) private readonly _inputComponent: InputWithActionComponent; constructor( @@ -24,11 +26,72 @@ export class PageExclusionComponent implements OnChanges { private readonly _reanalysisService: ReanalysisService, private readonly _toaster: Toaster, private readonly _loadingService: LoadingService, - ) {} + private readonly _state: FilePreviewStateService, + ) { + this.canExcludePages$ = this._state.file$.pipe( + map(file => permissionsService.canExcludePages(file)), + shareLast(), + ); + this.excludedRanges$ = this._excludedRanges$; + this.noExcludedAndCantExclude$ = this._noExcludedAndCantExclude$; + } - ngOnChanges(): void { - const excludedPages = (this.file?.excludedPages || []).sort((p1, p2) => p1 - p2); - this.excludedPagesRanges = excludedPages.reduce((ranges: IPageRange[], page) => { + private get _excludedRanges$() { + return this._state.file$.pipe( + pluck('excludedPages'), + map(pages => pages.sort((p1, p2) => p1 - p2)), + map(pages => this._toPageRange(pages)), + shareLast(), + ); + } + + private get _noExcludedAndCantExclude$() { + const combination = combineLatest([this.canExcludePages$, this.excludedRanges$]); + return combination.pipe(map(([canExclude, excluded]) => !canExclude && !excluded.length)); + } + + async excludePagesRange(inputValue: string): Promise { + this._loadingService.start(); + const value = inputValue.replace(/[^0-9-,]/g, ''); + const file = await this._state.file; + try { + const pageRanges = value.split(',').map(range => { + const splitted = range.split('-'); + const startPage = parseInt(splitted[0], 10); + const endPage = splitted.length > 1 ? parseInt(splitted[1], 10) : startPage; + if (!startPage || !endPage || startPage > file.numberOfPages || endPage > file.numberOfPages) { + throw new Error(); + } + return { + startPage, + endPage, + }; + }); + const excludePages$ = this._reanalysisService.excludePages({ pageRanges }, this._state.dossierId, this._state.fileId); + await firstValueFrom(excludePages$); + this._inputComponent.reset(); + } catch (e) { + this._toaster.error(_('file-preview.tabs.exclude-pages.error')); + } + this._loadingService.stop(); + } + + async includePagesRange(range: IPageRange): Promise { + this._loadingService.start(); + const includePages$ = this._reanalysisService.includePages( + { + pageRanges: [range], + }, + this._state.dossierId, + this._state.fileId, + ); + await firstValueFrom(includePages$); + this._inputComponent.reset(); + this._loadingService.stop(); + } + + private _toPageRange(pages: number[]) { + return pages.reduce((ranges: IPageRange[], page) => { if (!ranges.length) { return [{ startPage: page, endPage: page }]; } @@ -41,51 +104,4 @@ export class PageExclusionComponent implements OnChanges { return ranges; }, []); } - - async excludePagesRange(inputValue: string): Promise { - this._loadingService.start(); - const value = inputValue.replace(/[^0-9-,]/g, ''); - try { - const pageRanges = value.split(',').map(range => { - const splitted = range.split('-'); - const startPage = parseInt(splitted[0], 10); - const endPage = splitted.length > 1 ? parseInt(splitted[1], 10) : startPage; - if (!startPage || !endPage || startPage > this.file.numberOfPages || endPage > this.file.numberOfPages) { - throw new Error(); - } - return { - startPage, - endPage, - }; - }); - await firstValueFrom( - this._reanalysisService.excludePages( - { - pageRanges: pageRanges, - }, - this.file.dossierId, - this.file.fileId, - ), - ); - this._inputComponent.reset(); - } catch (e) { - this._toaster.error(_('file-preview.tabs.exclude-pages.error')); - } - this._loadingService.stop(); - } - - async includePagesRange(range: IPageRange): Promise { - this._loadingService.start(); - await firstValueFrom( - this._reanalysisService.includePages( - { - pageRanges: [range], - }, - this.file.dossierId, - this.file.fileId, - ), - ); - this._inputComponent.reset(); - this._loadingService.stop(); - } } diff --git a/libs/red-domain/src/lib/files/file.model.ts b/libs/red-domain/src/lib/files/file.model.ts index ad1c1e501..f333045c8 100644 --- a/libs/red-domain/src/lib/files/file.model.ts +++ b/libs/red-domain/src/lib/files/file.model.ts @@ -35,7 +35,7 @@ export class File extends Entity implements IFile { readonly numberOfPages?: number; readonly rulesVersion?: number; readonly uploader?: string; - readonly excludedPages?: number[]; + readonly excludedPages: number[]; readonly hasSuggestions: boolean; readonly processingStatus: ProcessingFileStatus; readonly workflowStatus: WorkflowFileStatus; @@ -90,7 +90,7 @@ export class File extends Entity implements IFile { this.numberOfPages = this.isError ? 0 : file.numberOfPages ?? 0; this.rulesVersion = file.rulesVersion; this.uploader = file.uploader; - this.excludedPages = file.excludedPages; + this.excludedPages = file.excludedPages || []; this.hasSuggestions = !!file.hasSuggestions; this.statusSort = StatusSorter[this.workflowStatus];