+
+
{{ 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];