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