RED-6892 deselect text when redaction added
This commit is contained in:
parent
d72d865ad8
commit
a93527e963
@ -141,10 +141,10 @@ export const appModuleFactory = (config: AppConfig) => {
|
||||
enabled: true,
|
||||
},
|
||||
FILE: {
|
||||
enabled: false,
|
||||
enabled: true,
|
||||
},
|
||||
CHANGES: {
|
||||
enabled: false,
|
||||
enabled: true,
|
||||
},
|
||||
STATS: {
|
||||
enabled: false,
|
||||
|
||||
@ -308,7 +308,7 @@ export class FilePreviewScreenComponent
|
||||
|
||||
this._loadingService.start();
|
||||
this.userPreferenceService.saveLastOpenedFileForDossier(this.dossierId, this.fileId).then();
|
||||
this._subscribeToFileUpdates();
|
||||
this.#subscribeToFileUpdates();
|
||||
|
||||
if (file?.analysisRequired && !file.excludedFromAutomaticAnalysis) {
|
||||
await this._reanalysisService.reanalyzeFilesForDossier([file], this.dossierId, { force: true });
|
||||
@ -354,34 +354,33 @@ export class FilePreviewScreenComponent
|
||||
async openRedactTextDialog(manualRedactionEntryWrapper: ManualRedactionEntryWrapper) {
|
||||
const file = this.state.file();
|
||||
const dossierTemplate = this._dossierTemplatesService.find(this.state.dossierTemplateId);
|
||||
const result = await this._iqserDialog
|
||||
.openDefault(RedactTextDialogComponent, {
|
||||
data: {
|
||||
manualRedactionEntryWrapper,
|
||||
dossierId: this.dossierId,
|
||||
file,
|
||||
applyToAllDossiers: dossierTemplate.applyDictionaryUpdatesToAllDossiersByDefault,
|
||||
},
|
||||
})
|
||||
.result();
|
||||
const ref = this._iqserDialog.openDefault(RedactTextDialogComponent, {
|
||||
data: {
|
||||
manualRedactionEntryWrapper,
|
||||
dossierId: this.dossierId,
|
||||
file,
|
||||
applyToAllDossiers: dossierTemplate.applyDictionaryUpdatesToAllDossiersByDefault,
|
||||
},
|
||||
});
|
||||
|
||||
if (result) {
|
||||
const add$ = this._manualRedactionService.addAnnotation(
|
||||
[result.redaction],
|
||||
this.dossierId,
|
||||
this.fileId,
|
||||
result.dictionary?.label,
|
||||
);
|
||||
|
||||
if (result.applyToAllDossiers !== null) {
|
||||
const { ...body } = dossierTemplate;
|
||||
body.applyDictionaryUpdatesToAllDossiersByDefault = result.applyToAllDossiers;
|
||||
await this._dossierTemplatesService.createOrUpdate(body);
|
||||
}
|
||||
|
||||
const addAndReload$ = add$.pipe(switchMap(() => this._filesService.reload(this.dossierId, file)));
|
||||
return firstValueFrom(addAndReload$.pipe(catchError(() => of(undefined))));
|
||||
const result = await ref.result();
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
const add$ = this._manualRedactionService.addAnnotation([result.redaction], this.dossierId, this.fileId, result.dictionary?.label);
|
||||
|
||||
if (result.applyToAllDossiers !== null) {
|
||||
const { ...body } = dossierTemplate;
|
||||
body.applyDictionaryUpdatesToAllDossiersByDefault = result.applyToAllDossiers;
|
||||
await this._dossierTemplatesService.createOrUpdate(body);
|
||||
}
|
||||
|
||||
const addAndReload$ = add$.pipe(
|
||||
tap(() => this._documentViewer.clearSelection()),
|
||||
switchMap(() => this._filesService.reload(this.dossierId, file)),
|
||||
);
|
||||
return firstValueFrom(addAndReload$.pipe(catchError(() => of(undefined))));
|
||||
}
|
||||
|
||||
toggleFullScreen() {
|
||||
@ -610,7 +609,7 @@ export class FilePreviewScreenComponent
|
||||
}, 100);
|
||||
}
|
||||
|
||||
private _subscribeToFileUpdates(): void {
|
||||
#subscribeToFileUpdates(): void {
|
||||
this.addActiveScreenSubscription = this.loadAnnotations().subscribe();
|
||||
|
||||
this.addActiveScreenSubscription = this._dossiersService
|
||||
@ -642,7 +641,7 @@ export class FilePreviewScreenComponent
|
||||
});
|
||||
|
||||
this.addActiveScreenSubscription = this.pdfProxyService.redactTextRequested$.subscribe($event => {
|
||||
this.openRedactTextDialog($event);
|
||||
this.openRedactTextDialog($event).then();
|
||||
});
|
||||
|
||||
this.addActiveScreenSubscription = this.pdfProxyService.pageChanged$.subscribe(page =>
|
||||
|
||||
@ -13,9 +13,10 @@ import { HttpEvent, HttpEventType, HttpProgressEvent, HttpResponse } from '@angu
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
import { DossierDictionariesMapService } from '@services/entity-services/dossier-dictionaries-map.service';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
||||
import { ViewModeService } from './view-mode.service';
|
||||
import { getParam } from '@iqser/common-ui/lib/utils';
|
||||
import { NGXLogger } from 'ngx-logger';
|
||||
|
||||
const ONE_MEGABYTE = 1024 * 1024;
|
||||
|
||||
@ -33,7 +34,6 @@ function isDownload(event: HttpEvent<Blob>): event is HttpProgressEvent {
|
||||
@Injectable()
|
||||
export class FilePreviewStateService {
|
||||
readonly #reloadBlob$ = new Subject();
|
||||
readonly #dossierFileChange: Signal<boolean>;
|
||||
readonly file$: Observable<File>;
|
||||
readonly file: Signal<File>;
|
||||
readonly dossier: Signal<Dossier>;
|
||||
@ -45,12 +45,6 @@ export class FilePreviewStateService {
|
||||
readonly dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID);
|
||||
readonly fileId = getParam(FILE_ID);
|
||||
|
||||
// readonly #routeKey = getReusableRouteKey(inject(ActivatedRoute).snapshot);
|
||||
// readonly isAttached = inject(CustomRouteReuseStrategy).attached$.pipe(
|
||||
// map(route => getReusableRouteKey(route) === this.#routeKey),
|
||||
// startWith(true),
|
||||
// );
|
||||
|
||||
constructor(
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _filesService: FilesService,
|
||||
@ -60,28 +54,27 @@ export class FilePreviewStateService {
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _viewModeService: ViewModeService,
|
||||
private readonly _logger: NGXLogger,
|
||||
) {
|
||||
this.dossier = toSignal(dossiersServiceResolver().getEntityChanged$(this.dossierId));
|
||||
this.file$ = inject(FilesMapService).watch$(this.dossierId, this.fileId);
|
||||
this.file = toSignal(this.file$);
|
||||
// this.file$ = combineLatest([this.isAttached, file$]).pipe(
|
||||
// filter(([isAttached]) => isAttached),
|
||||
// map(([, file]) => file),
|
||||
// log('file$'),
|
||||
// shareDistinctLast(),
|
||||
// );
|
||||
this.isWritable = computed(() => this._permissionsService.canPerformAnnotationActions(this.file(), this.dossier()));
|
||||
this.isWritable = computed(() => {
|
||||
const isWritable = this._permissionsService.canPerformAnnotationActions(this.file(), this.dossier());
|
||||
this._logger.info('[FILE] Is writeable:', isWritable);
|
||||
return isWritable;
|
||||
});
|
||||
this.isReadonly = computed(() => !this.isWritable());
|
||||
|
||||
this.blob$ = this.#blob$;
|
||||
|
||||
this.dossierDictionary = toSignal(inject(DossierDictionariesMapService).watch$(this.dossierId, 'dossier_redaction'));
|
||||
this.#dossierFileChange = toSignal(this.#dossierFilesChange$);
|
||||
effect(() => {
|
||||
if (this.#dossierFileChange()) {
|
||||
this._filesService.loadAll(this.dossierId);
|
||||
}
|
||||
});
|
||||
this.#dossierFilesChange$
|
||||
.pipe(
|
||||
switchMap(() => this._filesService.loadAll(this.dossierId)),
|
||||
takeUntilDestroyed(),
|
||||
)
|
||||
.subscribe();
|
||||
effect(
|
||||
() => {
|
||||
if (this._viewModeService.isEarmarks() && !this.file().hasHighlights) {
|
||||
|
||||
@ -101,8 +101,8 @@ export class PdfProxyService {
|
||||
|
||||
get #annotationSelected$() {
|
||||
return this._annotationManager.annotationSelected$.pipe(
|
||||
map(value => this._ngZone.run(() => this.#processSelectedAnnotations(...value))),
|
||||
tap(annotations => this._ngZone.run(() => this.handleAnnotationSelected(annotations))),
|
||||
map(value => this.#processSelectedAnnotations(...value)),
|
||||
tap(annotations => this.handleAnnotationSelected(annotations)),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { Injectable, signal } from '@angular/core';
|
||||
import { inject, Injectable, signal } from '@angular/core';
|
||||
import { Core } from '@pdftron/webviewer';
|
||||
import type { List } from '@iqser/common-ui/lib/utils';
|
||||
import { AnnotationPredicate, DeleteAnnotationsOptions } from '../utils/types';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { fromEvent, Observable } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
import { asList, getId, isStringOrWrapper } from '../utils/functions';
|
||||
import { getLast } from '@utils/functions';
|
||||
import { AnnotationToolNames } from '../utils/constants';
|
||||
import { NGXLogger } from 'ngx-logger';
|
||||
import AnnotationManager = Core.AnnotationManager;
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
|
||||
@ -15,7 +15,9 @@ import Annotation = Core.Annotations.Annotation;
|
||||
export class REDAnnotationManager {
|
||||
readonly #hidden = signal(new Set<string>());
|
||||
#manager: AnnotationManager;
|
||||
annotationSelected$: Observable<[Annotation[], string]>;
|
||||
readonly #logger = inject(NGXLogger);
|
||||
readonly #annotationSelected$ = new Subject<[Annotation[], string]>();
|
||||
readonly annotationSelected$ = this.#annotationSelected$.asObservable();
|
||||
resizingAnnotationId?: string = undefined;
|
||||
readonly hidden = this.#hidden.asReadonly();
|
||||
|
||||
@ -27,11 +29,6 @@ export class REDAnnotationManager {
|
||||
return this.#get();
|
||||
}
|
||||
|
||||
get #annotationSelected$() {
|
||||
const onSelect$ = fromEvent<[Annotation[], string]>(this.#manager, 'annotationSelected');
|
||||
return onSelect$.pipe(tap(value => console.log('Annotation selected: ', value)));
|
||||
}
|
||||
|
||||
addToHidden(value: string) {
|
||||
this.#hidden.mutate(set => set.add(value));
|
||||
}
|
||||
@ -42,7 +39,7 @@ export class REDAnnotationManager {
|
||||
|
||||
init(annotationManager: AnnotationManager) {
|
||||
this.#manager = annotationManager;
|
||||
this.annotationSelected$ = this.#annotationSelected$;
|
||||
this.#listenForAnnotationSelected();
|
||||
this.#autoSelectRectangleAfterCreation();
|
||||
}
|
||||
|
||||
@ -60,8 +57,11 @@ export class REDAnnotationManager {
|
||||
}
|
||||
|
||||
get(annotation: AnnotationWrapper | string): Annotation;
|
||||
|
||||
get(annotations: List | List<AnnotationWrapper>): Annotation[];
|
||||
|
||||
get(predicate?: (value: Annotation) => boolean): Annotation[];
|
||||
|
||||
get(argument?: AnnotationPredicate | List<AnnotationWrapper> | List | AnnotationWrapper | string): Annotation | Annotation[] {
|
||||
if (isStringOrWrapper(argument)) {
|
||||
return this.#getById(argument);
|
||||
@ -71,8 +71,8 @@ export class REDAnnotationManager {
|
||||
return isList ? this.#getByIds(argument) : this.#get(argument);
|
||||
}
|
||||
|
||||
deselect(annotation: string | AnnotationWrapper);
|
||||
deselect(annotations?: List | List<AnnotationWrapper>);
|
||||
deselect(annotation: string | AnnotationWrapper): void;
|
||||
deselect(annotations?: List | List<AnnotationWrapper>): void;
|
||||
deselect(argument?: string | AnnotationWrapper | List | List<AnnotationWrapper>) {
|
||||
if (!argument) {
|
||||
return this.#manager.deselectAllAnnotations();
|
||||
@ -121,12 +121,20 @@ export class REDAnnotationManager {
|
||||
this.show(hidden);
|
||||
}
|
||||
|
||||
#listenForAnnotationSelected() {
|
||||
this.#manager.addEventListener('annotationSelected', (annotations: Annotation[], action: string) => {
|
||||
this.#logger.info('[PDF] Annotation selected: ', annotations, action);
|
||||
this.#annotationSelected$.next([annotations, action]);
|
||||
});
|
||||
}
|
||||
|
||||
#getById(annotation: AnnotationWrapper | string) {
|
||||
return this.#manager.getAnnotationById(getId(annotation));
|
||||
}
|
||||
|
||||
#autoSelectRectangleAfterCreation() {
|
||||
this.#manager.addEventListener('annotationChanged', (annotations: Annotation[]) => {
|
||||
this.#manager.addEventListener('annotationChanged', (annotations: Annotation[], action: string, options) => {
|
||||
this.#logger.info('[PDF] Annotations changed: ', annotations, action, options);
|
||||
// when a rectangle is drawn,
|
||||
// it returns one annotation with tool name 'AnnotationCreateRectangle;
|
||||
// this will auto select rectangle after drawing
|
||||
|
||||
@ -35,7 +35,7 @@ export class DossiersChangesService extends GenericService<Dossier> implements O
|
||||
changes.map(change => this.#load(change.dossierId).pipe(removeIfNotFound(change.dossierId)));
|
||||
|
||||
return this.hasChangesDetails$().pipe(
|
||||
tap(changes => this.#logger.info('[CHANGES] ', changes)),
|
||||
tap(changes => this.#logger.info('[CHANGES] Dossier changes', changes)),
|
||||
switchMap(dossierChanges =>
|
||||
forkJoin([...load(dossierChanges), this.#dashboardStatsService.loadAll().pipe(take(1))]).pipe(map(() => dossierChanges)),
|
||||
),
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/member-ordering */
|
||||
import { EntitiesService, Toaster } from '@iqser/common-ui';
|
||||
import { Dossier, DossierStats, IDossier, IDossierChanges, IDossierRequest } from '@red/domain';
|
||||
import { Observable, of, Subject } from 'rxjs';
|
||||
|
||||
@ -144,9 +144,13 @@ $dark-accent-10: darken(vars.$accent, 10%);
|
||||
$iqser-app-name-color: vars.$white
|
||||
);
|
||||
|
||||
body {
|
||||
--workload-width: 350px;
|
||||
}
|
||||
|
||||
#viewer {
|
||||
visibility: hidden;
|
||||
width: calc(100% - 350px);
|
||||
width: calc(100% - var(--workload-width));
|
||||
height: calc(100% - calc(var(--iqser-top-bar-height) + 50px));
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user