RED-6829: view modes to signals
This commit is contained in:
parent
e7e6ab3e66
commit
2601822a32
@ -134,14 +134,14 @@ export const appModuleFactory = (config: AppConfig) => {
|
||||
features: {
|
||||
ANNOTATIONS: {
|
||||
color: 'aqua',
|
||||
enabled: false,
|
||||
enabled: true,
|
||||
level: NgxLoggerLevel.DEBUG,
|
||||
},
|
||||
FILTERS: {
|
||||
enabled: false,
|
||||
enabled: true,
|
||||
},
|
||||
PDF: {
|
||||
enabled: false,
|
||||
enabled: true,
|
||||
},
|
||||
FILE: {
|
||||
enabled: false,
|
||||
|
||||
@ -13,6 +13,7 @@ import {
|
||||
IManualChange,
|
||||
IPoint,
|
||||
IRectangle,
|
||||
LogEntryEngine,
|
||||
LogEntryStatuses,
|
||||
LowLevelFilterTypes,
|
||||
ManualRedactionTypes,
|
||||
@ -23,7 +24,7 @@ import {
|
||||
SuperTypes,
|
||||
} from '@red/domain';
|
||||
import { RedactionLogEntry } from '@models/file/redaction-log.entry';
|
||||
import { IListable, List } from '@iqser/common-ui';
|
||||
import { IListable } from '@iqser/common-ui';
|
||||
import { chronologicallyBy, timestampOf } from '../../modules/file-preview/services/file-data.service';
|
||||
|
||||
export class AnnotationWrapper implements IListable, Record<string, unknown> {
|
||||
@ -52,7 +53,7 @@ export class AnnotationWrapper implements IListable, Record<string, unknown> {
|
||||
legalBasisChangeValue?: string;
|
||||
rectangle?: boolean;
|
||||
section?: string;
|
||||
reference: List;
|
||||
reference: string[];
|
||||
imported?: boolean;
|
||||
image?: boolean;
|
||||
manual?: boolean;
|
||||
@ -62,7 +63,7 @@ export class AnnotationWrapper implements IListable, Record<string, unknown> {
|
||||
textBefore?: string;
|
||||
isChangeLogEntry = false;
|
||||
changeLogType?: 'ADDED' | 'REMOVED' | 'CHANGED';
|
||||
engines?: string[];
|
||||
engines?: LogEntryEngine[];
|
||||
hasBeenResized: boolean;
|
||||
hasBeenRecategorized: boolean;
|
||||
hasLegalBasisChanged: boolean;
|
||||
|
||||
@ -38,7 +38,7 @@ export class AnnotationsListComponent extends HasScrollbarDirective implements O
|
||||
}
|
||||
|
||||
ngOnChanges(): void {
|
||||
if (this._viewModeService.isEarmarks) {
|
||||
if (this._viewModeService.isEarmarks()) {
|
||||
this._updateEarmarksGroups();
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@ export class AnnotationsListComponent extends HasScrollbarDirective implements O
|
||||
}
|
||||
|
||||
showHighlightGroup(idx: number): EarmarkGroup {
|
||||
return this._viewModeService.isEarmarks && this.earmarkGroups$.value.find(h => h.startIdx === idx);
|
||||
return this._viewModeService.isEarmarks() && this.earmarkGroups$.value.find(h => h.startIdx === idx);
|
||||
}
|
||||
|
||||
protected readonly _trackBy = (index: number, listItem: ListItem<AnnotationWrapper>) => listItem.item.id;
|
||||
|
||||
@ -133,7 +133,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
|
||||
private get _isEarmarks$(): Observable<boolean> {
|
||||
return this.viewModeService.viewMode$.pipe(
|
||||
tap(() => this._scrollViews()),
|
||||
map(() => this.viewModeService.isEarmarks),
|
||||
map(() => this.viewModeService.isEarmarks()),
|
||||
);
|
||||
}
|
||||
|
||||
@ -373,7 +373,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._viewModeService.isRedacted) {
|
||||
if (this._viewModeService.isRedacted()) {
|
||||
annotations = annotations.filter(a => !bool(a.isChangeLogRemoved));
|
||||
annotations = this._suggestionsService.filterWorkloadSuggestionsInPreview(annotations);
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ export class ViewSwitchComponent {
|
||||
if (viewMode === ViewModes.REDACTED) {
|
||||
return this.#switchToRedactedView();
|
||||
}
|
||||
this.viewModeService.viewMode = viewMode;
|
||||
this.viewModeService.switchTo(viewMode);
|
||||
}
|
||||
|
||||
async #switchToRedactedView() {
|
||||
|
||||
@ -171,7 +171,7 @@ export class FilePreviewScreenComponent
|
||||
}
|
||||
|
||||
get #earmarks$() {
|
||||
const isEarmarksViewMode$ = this._viewModeService.viewMode$.pipe(filter(() => this._viewModeService.isEarmarks));
|
||||
const isEarmarksViewMode$ = this._viewModeService.viewMode$.pipe(filter(() => this._viewModeService.isEarmarks()));
|
||||
|
||||
const earmarks$ = isEarmarksViewMode$.pipe(
|
||||
tap(() => this._loadingService.start()),
|
||||
@ -181,7 +181,7 @@ export class FilePreviewScreenComponent
|
||||
);
|
||||
|
||||
const currentPageIfEarmarksView$ = combineLatest([this.pdf.currentPage$, this._viewModeService.viewMode$]).pipe(
|
||||
filter(() => this._viewModeService.isEarmarks),
|
||||
filter(() => this._viewModeService.isEarmarks()),
|
||||
map(([page]) => page),
|
||||
);
|
||||
|
||||
@ -213,12 +213,12 @@ export class FilePreviewScreenComponent
|
||||
}
|
||||
|
||||
async updateViewMode(): Promise<void> {
|
||||
this._logger.info(`[PDF] Update ${this._viewModeService.viewMode} view mode`);
|
||||
this._logger.info(`[PDF] Update ${this._viewModeService.viewMode()} view mode`);
|
||||
|
||||
const annotations = this._annotationManager.get(a => bool(a.getCustomData('redact-manager')));
|
||||
const redactions = annotations.filter(a => bool(a.getCustomData('redaction')));
|
||||
|
||||
switch (this._viewModeService.viewMode) {
|
||||
switch (this._viewModeService.viewMode()) {
|
||||
case ViewModes.STANDARD: {
|
||||
const wrappers = await this._fileDataService.annotations;
|
||||
const ocrAnnotationIds = wrappers.filter(a => a.isOCR).map(a => a.id);
|
||||
@ -260,8 +260,11 @@ export class FilePreviewScreenComponent
|
||||
}
|
||||
}
|
||||
|
||||
this._logger.info('[PDF] Stamp pdf');
|
||||
await this._stampService.stampPDF();
|
||||
this._logger.info('[PDF] Rebuild filters');
|
||||
this.#rebuildFilters();
|
||||
this._logger.info('[PDF] Update done');
|
||||
}
|
||||
|
||||
ngOnDetach() {
|
||||
|
||||
@ -10,7 +10,7 @@ import {
|
||||
ViewModes,
|
||||
} from '@red/domain';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { BehaviorSubject, firstValueFrom, iif, Observable, Subject, Subscription } from 'rxjs';
|
||||
import { BehaviorSubject, firstValueFrom, Observable, Subject, Subscription } from 'rxjs';
|
||||
import { RedactionLogEntry } from '@models/file/redaction-log.entry';
|
||||
import { Injectable, OnDestroy } from '@angular/core';
|
||||
import { FilePreviewStateService } from './file-preview-state.service';
|
||||
@ -76,11 +76,9 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
||||
this.#subscription = this._viewModeService.viewMode$
|
||||
.pipe(
|
||||
switchMap(viewMode =>
|
||||
iif(
|
||||
() => viewMode === ViewModes.TEXT_HIGHLIGHTS,
|
||||
this.#earmarks$.pipe(map(textHighlights => ([] as AnnotationWrapper[]).concat(...textHighlights.values()))),
|
||||
this.annotations$.pipe(map(annotations => this.#getVisibleAnnotations(annotations, viewMode))),
|
||||
),
|
||||
viewMode === ViewModes.TEXT_HIGHLIGHTS
|
||||
? this.#earmarks$.pipe(map(textHighlights => ([] as AnnotationWrapper[]).concat(...textHighlights.values())))
|
||||
: this.annotations$.pipe(map(annotations => this.#getVisibleAnnotations(annotations, viewMode))),
|
||||
),
|
||||
tap(annotations => this.setEntities(annotations)),
|
||||
)
|
||||
@ -93,6 +91,7 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
||||
|
||||
get #annotations$() {
|
||||
return this.#redactionLog$.pipe(
|
||||
tap(() => console.time('buildAnnotations')),
|
||||
withLatestFrom(this._state.file$),
|
||||
tap(([redactionLog, file]) => this.#buildRemovedRedactions(redactionLog, file)),
|
||||
switchMap(([redactionLog, file]) => this.#buildAnnotations(redactionLog, file)),
|
||||
@ -100,6 +99,7 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
||||
map(annotations =>
|
||||
this._userPreferenceService.areDevFeaturesEnabled ? annotations : annotations.filter(a => !a.isFalsePositive),
|
||||
),
|
||||
tap(() => console.timeEnd('buildAnnotations')),
|
||||
shareLast(),
|
||||
);
|
||||
}
|
||||
@ -129,10 +129,11 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
||||
|
||||
async loadAnnotations(file: File) {
|
||||
if (!file || file.isUnprocessed) {
|
||||
this._logger.info('[ANNOTATIONS] File is null or unprocessed, skipping annotations loading');
|
||||
return;
|
||||
}
|
||||
|
||||
this._logger.info('[ANNOTATIONS] Load annotations');
|
||||
this._logger.info('[ANNOTATIONS] Loading annotations...');
|
||||
|
||||
await this.#loadViewedPages(file);
|
||||
await this.loadRedactionLog();
|
||||
@ -155,9 +156,15 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
||||
return earmarks;
|
||||
}
|
||||
|
||||
loadRedactionLog() {
|
||||
async loadRedactionLog() {
|
||||
this._logger.info('[REDACTION-LOG] Loading redaction log...');
|
||||
console.time('redaction-log');
|
||||
const redactionLog$ = this._redactionLogService.getRedactionLog(this._state.dossierId, this._state.fileId);
|
||||
return firstValueFrom(redactionLog$.pipe(tap(redactionLog => this.#redactionLog$.next(redactionLog))));
|
||||
const redactionLog = await firstValueFrom(redactionLog$);
|
||||
this.#redactionLog$.next(redactionLog);
|
||||
console.timeEnd('redaction-log');
|
||||
this._logger.info('[REDACTION-LOG] Redaction log loaded', redactionLog);
|
||||
return redactionLog;
|
||||
}
|
||||
|
||||
#checkMissingTypes() {
|
||||
@ -173,10 +180,12 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
||||
async #loadViewedPages(file: File) {
|
||||
if (!this._permissionsService.canMarkPagesAsViewed(file)) {
|
||||
this._viewedPagesMapService.set(file.fileId, []);
|
||||
this._logger.info('[VIEWED-PAGES] Cannot mark pages as viewed, skip loading viewed pages');
|
||||
return;
|
||||
}
|
||||
|
||||
this.#originalViewedPages = await this._viewedPagesService.load(file.dossierId, file.fileId);
|
||||
this._logger.info('[VIEWED-PAGES] Loaded viewed pages', this.#originalViewedPages);
|
||||
this._viewedPagesMapService.set(file.fileId, this.#originalViewedPages);
|
||||
}
|
||||
|
||||
@ -196,76 +205,88 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
||||
|
||||
async #buildAnnotations(redactionLog: IRedactionLog, file: File) {
|
||||
const entries = await this.#convertData(redactionLog, file);
|
||||
const annotations = entries.map(entry =>
|
||||
AnnotationWrapper.fromData(entry, this._state.dictionaries, this._defaultColorsService.find(this._state.dossierTemplateId)),
|
||||
);
|
||||
const dictionaries = this._state.dictionaries;
|
||||
const defaultColors = this._defaultColorsService.find(this._state.dossierTemplateId);
|
||||
const annotations: AnnotationWrapper[] = [];
|
||||
|
||||
return annotations.filter(ann => ann.manual || !file.excludedPages.includes(ann.pageNumber));
|
||||
for (const entry of entries) {
|
||||
const pageNumber = entry.positions[0]?.page;
|
||||
const manual = entry.manualChanges?.length > 0;
|
||||
if (!manual && file.excludedPages.includes(pageNumber)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
annotations.push(AnnotationWrapper.fromData(entry, dictionaries, defaultColors));
|
||||
}
|
||||
|
||||
return annotations;
|
||||
}
|
||||
|
||||
async #buildRemovedRedactions(redactionLog: IRedactionLog, file: File): Promise<void> {
|
||||
if (redactionLog.redactionLogEntry) {
|
||||
const redactionLogCopy = JSON.parse(JSON.stringify(redactionLog));
|
||||
redactionLogCopy.redactionLogEntry = redactionLogCopy.redactionLogEntry?.reduce((filtered, entry) => {
|
||||
const lastChange = entry.manualChanges.at(-1);
|
||||
const redactionLogCopy = JSON.parse(JSON.stringify(redactionLog));
|
||||
|
||||
if (
|
||||
lastChange?.annotationStatus === LogEntryStatuses.REQUESTED &&
|
||||
!entry.hint &&
|
||||
!entry.reason.includes('requested to force hint')
|
||||
) {
|
||||
entry.manualChanges.pop();
|
||||
entry.reason = null;
|
||||
filtered.push(entry);
|
||||
}
|
||||
return filtered;
|
||||
}, []);
|
||||
const annotations = await this.#buildAnnotations(redactionLogCopy, file);
|
||||
this._suggestionsService.removedRedactions = annotations.filter(a => !a.isSkipped);
|
||||
}
|
||||
redactionLogCopy.redactionLogEntry = redactionLogCopy.redactionLogEntry?.reduce((filtered, entry) => {
|
||||
const lastChange = entry.manualChanges.at(-1);
|
||||
if (
|
||||
lastChange?.annotationStatus === LogEntryStatuses.REQUESTED &&
|
||||
!entry.hint &&
|
||||
!entry.reason.includes('requested to force hint')
|
||||
) {
|
||||
entry.manualChanges.pop();
|
||||
entry.reason = null;
|
||||
filtered.push(entry);
|
||||
}
|
||||
return filtered;
|
||||
}, []);
|
||||
|
||||
const annotations = await this.#buildAnnotations(redactionLogCopy, file);
|
||||
this._suggestionsService.removedRedactions = annotations.filter(a => !a.isSkipped);
|
||||
}
|
||||
|
||||
async #convertData(redactionLog: IRedactionLog, file: File) {
|
||||
if (!redactionLog.redactionLogEntry) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const result: RedactionLogEntry[] = [];
|
||||
const sourceIdAnnotationIds: { [key: string]: RedactionLogEntry[] } = {};
|
||||
const dictionaries = this._state.dictionaries;
|
||||
let checkDictionary = true;
|
||||
|
||||
if (redactionLog.redactionLogEntry) {
|
||||
for (const redactionLogEntry of redactionLog.redactionLogEntry) {
|
||||
const changeLogValues = this.#getChangeLogValues(redactionLogEntry, file);
|
||||
if (changeLogValues.hidden) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let dictionary = this._state.dictionaries.find(dict => dict.type === redactionLogEntry.type);
|
||||
if (!dictionary && checkDictionary) {
|
||||
const dictionaryRequest = this._dictionaryService.loadDictionaryDataForDossierTemplate(this._state.dossierTemplateId);
|
||||
await firstValueFrom(dictionaryRequest);
|
||||
checkDictionary = false;
|
||||
dictionary = this._state.dictionaries.find(dict => dict.type === redactionLogEntry.type);
|
||||
}
|
||||
|
||||
if (!dictionary) {
|
||||
this.missingTypes.add(redactionLogEntry.type);
|
||||
continue;
|
||||
}
|
||||
|
||||
const redactionLogEntryWrapper: RedactionLogEntry = new RedactionLogEntry(
|
||||
redactionLogEntry,
|
||||
changeLogValues.changeLogType,
|
||||
redactionLog.legalBasis ?? [],
|
||||
!!dictionary?.hint,
|
||||
);
|
||||
|
||||
if (redactionLogEntry.sourceId) {
|
||||
if (!sourceIdAnnotationIds[redactionLogEntry.sourceId]) {
|
||||
sourceIdAnnotationIds[redactionLogEntry.sourceId] = [];
|
||||
}
|
||||
sourceIdAnnotationIds[redactionLogEntry.sourceId].push(redactionLogEntryWrapper);
|
||||
}
|
||||
|
||||
result.push(redactionLogEntryWrapper);
|
||||
for (const redactionLogEntry of redactionLog.redactionLogEntry) {
|
||||
const changeLogValues = this.#getChangeLogValues(redactionLogEntry, file);
|
||||
if (changeLogValues.hidden) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let dictionary = dictionaries.find(dict => dict.type === redactionLogEntry.type);
|
||||
if (!dictionary && checkDictionary) {
|
||||
const dictionaryRequest = this._dictionaryService.loadDictionaryDataForDossierTemplate(this._state.dossierTemplateId);
|
||||
await firstValueFrom(dictionaryRequest);
|
||||
checkDictionary = false;
|
||||
dictionary = dictionaries.find(dict => dict.type === redactionLogEntry.type);
|
||||
}
|
||||
|
||||
if (!dictionary) {
|
||||
this.missingTypes.add(redactionLogEntry.type);
|
||||
continue;
|
||||
}
|
||||
|
||||
const redactionLogEntryWrapper: RedactionLogEntry = new RedactionLogEntry(
|
||||
redactionLogEntry,
|
||||
changeLogValues.changeLogType,
|
||||
redactionLog.legalBasis ?? [],
|
||||
!!dictionary?.hint,
|
||||
);
|
||||
|
||||
if (redactionLogEntry.sourceId) {
|
||||
if (!sourceIdAnnotationIds[redactionLogEntry.sourceId]) {
|
||||
sourceIdAnnotationIds[redactionLogEntry.sourceId] = [];
|
||||
}
|
||||
sourceIdAnnotationIds[redactionLogEntry.sourceId].push(redactionLogEntryWrapper);
|
||||
}
|
||||
|
||||
result.push(redactionLogEntryWrapper);
|
||||
}
|
||||
|
||||
const sourceKeys = Object.keys(sourceIdAnnotationIds);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { ChangeDetectorRef, inject, Injectable, NgZone } from '@angular/core';
|
||||
import { IHeaderElement, IManualRedactionEntry, ViewModes } from '@red/domain';
|
||||
import { IHeaderElement, IManualRedactionEntry } from '@red/domain';
|
||||
import { Core } from '@pdftron/webviewer';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import {
|
||||
@ -196,7 +196,7 @@ export class PdfProxyService {
|
||||
private _handleCustomActions() {
|
||||
const isCurrentPageExcluded = this._state.file.isPageExcluded(this._pdf.currentPage);
|
||||
|
||||
if (this._viewModeService.viewMode === ViewModes.REDACTED) {
|
||||
if (this._viewModeService.isRedacted()) {
|
||||
this._viewerHeaderService.enable([HeaderElements.TOGGLE_READABLE_REDACTIONS]);
|
||||
} else {
|
||||
this._viewerHeaderService.disable([HeaderElements.TOGGLE_READABLE_REDACTIONS]);
|
||||
|
||||
@ -8,8 +8,8 @@ import { PdfViewer } from '../../pdf-viewer/services/pdf-viewer.service';
|
||||
import { REDDocumentViewer } from '../../pdf-viewer/services/document-viewer.service';
|
||||
import { LicenseService } from '@services/license.service';
|
||||
import { WatermarksMapService } from '@services/entity-services/watermarks-map.service';
|
||||
import PDFNet = Core.PDFNet;
|
||||
import { WATERMARK_HORIZONTAL_ALIGNMENTS, WATERMARK_VERTICAL_ALIGNMENTS } from '@red/domain';
|
||||
import PDFNet = Core.PDFNet;
|
||||
|
||||
@Injectable()
|
||||
export class StampService {
|
||||
@ -39,7 +39,7 @@ export class StampService {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._viewModeService.isRedacted) {
|
||||
if (this._viewModeService.isRedacted()) {
|
||||
const { dossierTemplateId, previewWatermarkId } = this._state.dossier;
|
||||
if (previewWatermarkId) {
|
||||
await this._stampPreview(pdfDoc, dossierTemplateId, previewWatermarkId);
|
||||
|
||||
@ -1,77 +1,48 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { computed, Injectable, Signal, signal } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ViewMode, ViewModes } from '@red/domain';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { shareDistinctLast } from '@iqser/common-ui';
|
||||
import { toObservable } from '@angular/core/rxjs-interop';
|
||||
|
||||
@Injectable()
|
||||
export class ViewModeService {
|
||||
readonly viewMode$: Observable<ViewMode>;
|
||||
readonly isRedacted$: Observable<boolean>;
|
||||
readonly isStandard$: Observable<boolean>;
|
||||
readonly isDelta$: Observable<boolean>;
|
||||
|
||||
readonly #viewMode$ = new BehaviorSubject<ViewMode>('STANDARD');
|
||||
readonly viewMode: Signal<ViewMode>;
|
||||
readonly isEarmarks = computed(() => this.viewMode() === ViewModes.TEXT_HIGHLIGHTS);
|
||||
readonly isRedacted = computed(() => this.viewMode() === ViewModes.REDACTED);
|
||||
readonly isStandard = computed(() => this.viewMode() === ViewModes.STANDARD);
|
||||
readonly isDelta = computed(() => this.viewMode() === ViewModes.DELTA);
|
||||
readonly #viewMode = signal<ViewMode>(ViewModes.STANDARD);
|
||||
|
||||
constructor() {
|
||||
this.viewMode$ = this.#viewMode$.asObservable();
|
||||
this.isRedacted$ = this._is('REDACTED');
|
||||
this.isStandard$ = this._is('STANDARD');
|
||||
this.isDelta$ = this._is('DELTA');
|
||||
this.viewMode$ = toObservable(this.#viewMode);
|
||||
this.viewMode = this.#viewMode.asReadonly();
|
||||
}
|
||||
|
||||
get onlyPagesWithAnnotations(): boolean {
|
||||
return ([ViewModes.DELTA, ViewModes.TEXT_HIGHLIGHTS] as ViewMode[]).includes(this.viewMode);
|
||||
get onlyPagesWithAnnotations() {
|
||||
return ([ViewModes.DELTA, ViewModes.TEXT_HIGHLIGHTS] as ViewMode[]).includes(this.#viewMode());
|
||||
}
|
||||
|
||||
get viewMode() {
|
||||
return this.#viewMode$.value;
|
||||
is(viewMode: ViewMode) {
|
||||
return this.viewMode() === viewMode;
|
||||
}
|
||||
|
||||
set viewMode(mode: ViewMode) {
|
||||
this.#viewMode$.next(mode);
|
||||
}
|
||||
|
||||
get isStandard() {
|
||||
return this.#viewMode$.value === 'STANDARD';
|
||||
}
|
||||
|
||||
get isDelta() {
|
||||
return this.#viewMode$.value === 'DELTA';
|
||||
}
|
||||
|
||||
get isRedacted() {
|
||||
return this.#viewMode$.value === 'REDACTED';
|
||||
}
|
||||
|
||||
get isEarmarks() {
|
||||
return this.#viewMode$.value === 'TEXT_HIGHLIGHTS';
|
||||
switchTo(viewMode: ViewMode) {
|
||||
this.#viewMode.set(viewMode);
|
||||
}
|
||||
|
||||
switchToStandard() {
|
||||
this._switchTo('STANDARD');
|
||||
this.switchTo(ViewModes.STANDARD);
|
||||
}
|
||||
|
||||
switchToDelta() {
|
||||
this._switchTo('DELTA');
|
||||
this.switchTo(ViewModes.DELTA);
|
||||
}
|
||||
|
||||
switchToRedacted() {
|
||||
this._switchTo('REDACTED');
|
||||
this.switchTo(ViewModes.REDACTED);
|
||||
}
|
||||
|
||||
switchToHighlights() {
|
||||
this._switchTo('TEXT_HIGHLIGHTS');
|
||||
}
|
||||
|
||||
private _switchTo(mode: ViewMode) {
|
||||
this.#viewMode$.next(mode);
|
||||
}
|
||||
|
||||
private _is(mode: ViewMode) {
|
||||
return this.viewMode$.pipe(
|
||||
map(value => value === mode),
|
||||
shareDistinctLast(),
|
||||
);
|
||||
this.switchTo(ViewModes.TEXT_HIGHLIGHTS);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user