diff --git a/apps/red-ui/src/app/models/file/file-data.model.ts b/apps/red-ui/src/app/models/file/file-data.model.ts index 6407c15fd..1c0d3b920 100644 --- a/apps/red-ui/src/app/models/file/file-data.model.ts +++ b/apps/red-ui/src/app/models/file/file-data.model.ts @@ -117,9 +117,10 @@ export class FileDataModel { const relevantChanges = redactionLogEntry.changes.filter(change => moment(change.dateTime).valueOf() > viewTime); // at least one unseen change if (relevantChanges.length > 0) { + // at least 1 relevant change wrapper.changeLogType = relevantChanges[relevantChanges.length - 1].type; wrapper.isChangeLogEntry = true; - viewedPage.hasChanges = true; + viewedPage.showAsUnseen = moment(viewedPage.viewedTime).valueOf() < moment(lastChange.dateTime).valueOf(); this.hasChangeLog = true; } else { // no relevant changes - hide removed anyway diff --git a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts index 86390b6e1..f2e07904d 100644 --- a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts @@ -127,7 +127,6 @@ export class FileAttributesListingScreenComponent extends ListingComponent { - console.log('error'); if (error.status === HttpStatusCode.Conflict) { this._toaster.error(_('file-attributes-listing.error.conflict')); } else { diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component.html b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component.html index 6657b935e..1cc4516d4 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component.html +++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component.html @@ -16,12 +16,16 @@ class="iqser-input-group" > - + > + + diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component.ts index d9fd47b83..e22722727 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component.ts +++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component.ts @@ -53,7 +53,7 @@ export class EditDossierAttributesComponent implements EditDossierSectionInterfa } get valid(): boolean { - return this.form?.valid; + return !!this.form?.valid; } async ngOnInit() { @@ -66,7 +66,9 @@ export class EditDossierAttributesComponent implements EditDossierSectionInterfa async save(): EditDossierSaveResult { const dossierAttributeList = this.attributes.map(attr => ({ dossierAttributeConfigId: attr.id, - value: this.currentAttrValue(attr), + value: this.isSpecificType(attr, DossierAttributeConfigTypes.DATE) + ? moment(this.currentAttrValue(attr)).format('YYYY-MM-DD') + : this.currentAttrValue(attr), })); try { await this._dossierAttributesService.setAttributes(this.dossier, dossierAttributeList).toPromise(); diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-details/dossiers-listing-details.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-details/dossiers-listing-details.component.html index ffcf42195..1371e0061 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-details/dossiers-listing-details.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-details/dossiers-listing-details.component.html @@ -4,7 +4,7 @@ [config]="config" [radius]="80" [strokeWidth]="15" - [subtitle]="'dossier-listing.stats.charts.dossiers' | translate" + [subtitle]="'dossier-listing.stats.charts.dossiers' | translate: { count: config[0].value }" >
@@ -12,7 +12,7 @@
{{ stats.totalAnalyzedPages | number }}
-
+
diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/file-workload/file-workload.component.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/file-workload/file-workload.component.ts index 0607b4055..8f7c86e16 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/file-workload/file-workload.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/file-workload/file-workload.component.ts @@ -161,7 +161,7 @@ export class FileWorkloadComponent { } hasOnlyManualRedactionsAndIsExcluded(pageNumber: number): boolean { - const hasOnlyManualRedactions = this.displayedAnnotations.get(pageNumber).every(annotation => annotation.manual); + const hasOnlyManualRedactions = this.displayedAnnotations.get(pageNumber)?.every(annotation => annotation.manual); return hasOnlyManualRedactions && this.file.excludedPages.includes(pageNumber); } @@ -207,7 +207,7 @@ export class FileWorkloadComponent { // Disable annotation navigation in multi select mode // => TODO: maybe implement selection on enter? if (!this.multiSelectService.isActive) { - this._navigateAnnotations($event); + this.navigateAnnotations($event); } } else { this._navigatePages($event); @@ -276,38 +276,11 @@ export class FileWorkloadComponent { this.selectPage.emit(this._nextPageWithAnnotations()); } - private _disableMultiSelectAndDocumentInfo(): void { - this.multiSelectService.deactivate(); - this.documentInfoService.hide(); - } - - private _filterAnnotations( - annotations: AnnotationWrapper[], - primary: INestedFilter[], - secondary: INestedFilter[] = [], - ): Map { - if (!primary) { - return; - } - this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(annotations, primary, secondary); - this.displayedPages = [...this.displayedAnnotations.keys()]; - return this.displayedAnnotations; - } - - private _selectFirstAnnotationOnCurrentPageIfNecessary() { - if ( - (!this._firstSelectedAnnotation || this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber) && - this.displayedPages.indexOf(this.activeViewerPage) >= 0 - ) { - this.selectAnnotations.emit([this.activeAnnotations[0]]); - } - } - - private _navigateAnnotations($event: KeyboardEvent) { + navigateAnnotations($event: KeyboardEvent) { if (!this._firstSelectedAnnotation || this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber) { if (this.displayedPages.indexOf(this.activeViewerPage) !== -1) { // Displayed page has annotations - return this.selectAnnotations.emit([this.activeAnnotations[0]]); + return this.selectAnnotations.emit(this.activeAnnotations ? [this.activeAnnotations[0]] : null); } // Displayed page doesn't have annotations if ($event.key === 'ArrowDown') { @@ -354,6 +327,34 @@ export class FileWorkloadComponent { } } + private _disableMultiSelectAndDocumentInfo(): void { + this.multiSelectService.deactivate(); + this.documentInfoService.hide(); + } + + private _filterAnnotations( + annotations: AnnotationWrapper[], + primary: INestedFilter[], + secondary: INestedFilter[] = [], + ): Map { + if (!primary || primary.length === 0) { + this.displayedPages = Array.from({ length: this.file?.numberOfPages }, (x, i) => i + 1); + return; + } + this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(annotations, primary, secondary); + this.displayedPages = [...this.displayedAnnotations.keys()]; + return this.displayedAnnotations; + } + + private _selectFirstAnnotationOnCurrentPageIfNecessary() { + if ( + (!this._firstSelectedAnnotation || this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber) && + this.displayedPages.indexOf(this.activeViewerPage) >= 0 + ) { + this.selectAnnotations.emit([this.activeAnnotations[0]]); + } + } + private _navigatePages($event: KeyboardEvent) { const pageIdx = this.displayedPages.indexOf(this.activeViewerPage); diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-indicator/page-indicator.component.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-indicator/page-indicator.component.ts index dc417f73d..2b217e9d4 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-indicator/page-indicator.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-indicator/page-indicator.component.ts @@ -24,6 +24,7 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy @Output() readonly pageSelected = new EventEmitter(); pageReadTimeout: number = null; + read = false; constructor( private readonly _viewedPagesService: ViewedPagesService, @@ -39,16 +40,17 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy return this.viewedPages?.find(p => p.page === this.number); } - get read() { + private _setReadState() { const activePage = this.activePage; if (!activePage) { - return false; + this.read = false; } else { - return !activePage.hasChanges; + this.read = !activePage.showAsUnseen; } } ngOnChanges() { + this._setReadState(); this.handlePageRead(); } @@ -83,10 +85,11 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy private async _markPageRead() { await this._viewedPagesService.addPage({ page: this.number }, this.file.dossierId, this.file.fileId).toPromise(); if (this.activePage) { - this.activePage.hasChanges = false; + this.activePage.showAsUnseen = false; } else { this.viewedPages?.push({ page: this.number, fileId: this.file.fileId }); } + this._setReadState(); } private async _markPageUnread() { @@ -95,5 +98,6 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy this.viewedPages?.findIndex(p => p.page === this.number), 1, ); + this._setReadState(); } } diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/pdf-viewer/pdf-viewer.component.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/pdf-viewer/pdf-viewer.component.ts index 059d44dc7..f2f467526 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/pdf-viewer/pdf-viewer.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/pdf-viewer/pdf-viewer.component.ts @@ -82,7 +82,6 @@ export class PdfViewerComponent implements OnInit, OnChanges { annotationManager: Core.AnnotationManager; utils: PdfViewerUtils; private _selectedText = ''; - private _firstPageChange = true; constructor( @Inject(BASE_HREF) private readonly _baseHref: string, @@ -248,15 +247,7 @@ export class PdfViewerComponent implements OnInit, OnChanges { if (this.shouldDeselectAnnotationsOnPageChange) { this.utils.deselectAllAnnotations(); } - if (this._firstPageChange && pageNumber === 1) { - this._firstPageChange = false; - const routePageNumber = this._activatedRoute.snapshot.queryParams.page; - if (pageNumber) { - this.utils.navigateToPage(parseInt(routePageNumber, 10)); - } - } else { - this._ngZone.run(() => this.pageChanged.emit(pageNumber)); - } + this._ngZone.run(() => this.pageChanged.emit(pageNumber)); this._handleCustomActions(); }); @@ -309,7 +300,7 @@ export class PdfViewerComponent implements OnInit, OnChanges { private _setInitialDisplayMode() { this.instance.UI.setFitMode('FitPage'); const instanceDisplayMode = this.documentViewer.getDisplayModeManager().getDisplayMode(); - instanceDisplayMode.mode = this.viewModeService.isStandard ? 'Single' : 'Facing'; + instanceDisplayMode.mode = this.viewModeService.isCompare ? 'Facing' : 'Single'; this.documentViewer.getDisplayModeManager().setDisplayMode(instanceDisplayMode); } @@ -648,8 +639,9 @@ export class PdfViewerComponent implements OnInit, OnChanges { private _setReadyAndInitialState(): void { this._ngZone.run(() => { this.utils.ready = true; - this._firstPageChange = true; this.viewerReady.emit(this.instance); + const routePageNumber = this._activatedRoute.snapshot.queryParams.page; + this.pageChanged.emit(routePageNumber || 1); this._setInitialDisplayMode(); this._updateTooltipsVisibility(); }); diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html index 3b8387637..b18e1c5fe 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html @@ -95,7 +95,11 @@ icon="red:needs-work" > - + (first: readonly T[], second: readonly T[]): T[] { + // symmetrical difference between two arrays + const a = new Set(first); + const b = new Set(second); + + return [...first.filter(x => !b.has(x)), ...second.filter(x => !a.has(x))]; +} @Component({ templateUrl: './file-preview-screen.component.html', @@ -63,14 +71,14 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni shouldDeselectAnnotationsOnPageChange = true; fileData: FileDataModel; annotationData: AnnotationData; - selectedAnnotations: AnnotationWrapper[]; + selectedAnnotations: AnnotationWrapper[] = []; hideSkipped = false; displayPdfViewer = false; + activeViewerPage: number = null; @ViewChild(PdfViewerComponent) readonly viewerComponent: PdfViewerComponent; readonly dossierId: string; readonly canPerformAnnotationActions$: Observable; readonly dossier$: Observable; - readonly viewDocumentInfo$: Observable; readonly file$: Observable; readonly fileId: string; ready = false; @@ -121,7 +129,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni }), shareLast(), ); - this.viewDocumentInfo$ = this._viewDocumentInfo$; this.canPerformAnnotationActions$ = this._canPerformAnnotationActions$; document.documentElement.addEventListener('fullscreenchange', () => { @@ -139,24 +146,17 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni return this._instance; } - get activeViewerPage(): number { + private _setActiveViewerPage() { const currentPage = this._instance?.Core.documentViewer?.getCurrentPage(); if (!currentPage) { - return 0; + this.activeViewerPage = 1; + } else { + this.activeViewerPage = this.viewModeService.isCompare + ? currentPage % 2 === 0 + ? currentPage / 2 + : (currentPage + 1) / 2 + : currentPage; } - return this.viewModeService.isStandard ? currentPage : currentPage % 2 === 0 ? currentPage / 2 : (currentPage + 1) / 2; - } - - private get _viewDocumentInfo$() { - return this.documentInfoService.shown$.pipe( - tap(value => { - if (value) { - this.multiSelectService.deactivate(); - this.excludedPagesService.hide(); - } - }), - shareDistinctLast(), - ); } private get _canPerformAnnotationActions$() { @@ -246,8 +246,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni } catch (error) { console.error(error); } + console.log(`[REDACTION] Delete previous annotations time: ${new Date().getTime() - startTime} ms`); } - console.log(`[REDACTION] Delete previous annotations time: ${new Date().getTime() - startTime} ms`); const processStartTime = new Date().getTime(); const dossier = this._dossiersService.find(this.dossierId); const newAnnotationsData = this.fileData.getAnnotations( @@ -275,11 +275,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni filters: processFilters(secondaryFilters, AnnotationProcessingService.secondaryAnnotationFilters(this.fileData?.viewedPages)), }); console.log(`[REDACTION] Process time: ${new Date().getTime() - processStartTime} ms`); - console.log( - `[REDACTION] Annotation Redraw and filter rebuild time: ${new Date().getTime() - startTime} ms for: ${ - this.annotations.length - } annotations`, - ); + console.log(`[REDACTION] Filter rebuild time: ${new Date().getTime() - startTime}`); + console.log(); } handleAnnotationSelected(annotationIds: string[]) { @@ -294,12 +291,12 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni this._changeDetectorRef.markForCheck(); } - @Debounce(0) + @Debounce(10) selectAnnotations(annotations?: AnnotationWrapper[]) { if (annotations) { - this.viewerComponent?.utils.selectAnnotations(annotations, this.multiSelectService.isActive); + this.viewerComponent?.utils?.selectAnnotations(annotations, this.multiSelectService.isActive); } else { - this.viewerComponent?.utils.deselectAllAnnotations(); + this.viewerComponent?.utils?.deselectAllAnnotations(); } } @@ -325,7 +322,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni response.manualRedactionEntryWrapper.rectId, ); this._instance.Core.annotationManager.deleteAnnotation(annotation); - await this._filesService.reload(this.dossierId, this.fileId).toPromise(); + // await this._filesService.reload(this.dossierId, this.fileId).toPromise(); const distinctPages = manualRedactionEntryWrapper.manualRedactionEntry.positions .map(p => p.page) .filter((item, pos, self) => self.indexOf(item) === pos); @@ -357,9 +354,17 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni return; } + if (['ArrowUp', 'ArrowDown'].includes($event.key)) { + if (this.selectedAnnotations.length === 1) { + this._workloadComponent.navigateAnnotations($event); + } + return; + } + if (['Escape'].includes($event.key)) { this.fullScreen = false; this.closeFullScreen(); + this._changeDetectorRef.markForCheck(); } if (['f', 'F'].includes($event.key)) { @@ -370,8 +375,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni this.toggleFullScreen(); return; } - - this._changeDetectorRef.markForCheck(); } viewerPageChanged($event: any) { @@ -388,9 +391,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni const extras: NavigationExtras = { queryParams: { page: $event }, queryParamsHandling: 'merge', + replaceUrl: true, }; this._router.navigate([], extras).then(); + this._setActiveViewerPage(); this._changeDetectorRef.markForCheck(); } @@ -410,7 +415,9 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni if (pageNumber) { setTimeout(() => { this.selectPage(parseInt(pageNumber, 10)); + this._setActiveViewerPage(); this._scrollViews(); + this._changeDetectorRef.markForCheck(); this._loadingService.stop(); }); } else { @@ -476,7 +483,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni } private _setHiddenPropertyToNewAnnotations(newAnnotations: AnnotationWrapper[], oldAnnotations: AnnotationWrapper[]) { - newAnnotations.map(newAnnotation => { + newAnnotations.forEach(newAnnotation => { const oldAnnotation = oldAnnotations.find(a => a.annotationId === newAnnotation.annotationId); if (oldAnnotation) { newAnnotation.hidden = oldAnnotation.hidden; @@ -504,7 +511,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni } this._instance.Core.documentViewer.refreshAll(); this._instance.Core.documentViewer.updateView([this.activeViewerPage], this.activeViewerPage); - this._changeDetectorRef.detectChanges(); + this._changeDetectorRef.markForCheck(); } private async _stampPreview(document: PDFNet.PDFDoc, dossierTemplateId: string) { @@ -547,8 +554,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni .subscribe(async file => { await this._loadFileData(file, !this._reloadFileOnReanalysis); this._reloadFileOnReanalysis = false; - this._loadingService.stop(); await this._reloadAnnotations(); + this._loadingService.stop(); }); } @@ -559,21 +566,21 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni const fileData = await this._fileDownloadService.loadDataFor(file).toPromise(); - if (!file.isPending) { - let excludedOrIncludedPages = new Set(); - let currentPageAnnotations: AnnotationWrapper[] = []; + if (file.isPending) { + return; + } - if (performUpdate && !!this.fileData) { - this.fileData.redactionLog = fileData.redactionLog; - this.fileData.viewedPages = fileData.viewedPages; - excludedOrIncludedPages = new Set([...this.fileData.file.excludedPages, ...file.excludedPages]); - currentPageAnnotations = this.annotations.filter(a => excludedOrIncludedPages.has(a.pageNumber)); - this.fileData.file = file; - } else { - this.fileData = fileData; + if (performUpdate && !!this.fileData) { + this.fileData.redactionLog = fileData.redactionLog; + this.fileData.viewedPages = fileData.viewedPages; + const excludedOrIncludedPages = new Set(diff(this.fileData.file.excludedPages, file.excludedPages)); + const currentPageAnnotations = this.annotations.filter(a => excludedOrIncludedPages.has(a.pageNumber)); + this.fileData.file = file; + if (excludedOrIncludedPages?.size) { + await this._cleanupAndRedrawAnnotations(currentPageAnnotations, a => excludedOrIncludedPages.has(a.pageNumber)); } - - return this._cleanupAndRedrawAnnotations(currentPageAnnotations, a => excludedOrIncludedPages.has(a.pageNumber)); + } else { + this.fileData = fileData; } } @@ -591,7 +598,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni private async _reloadAnnotationsForPage(page: number) { const currentPageAnnotations = this.annotations.filter(a => a.pageNumber === page); - await this._filesService.reload(this.dossierId, this.fileId).toPromise(); this.fileData.redactionLog = await this._fileDownloadService.loadRedactionLogFor(this.dossierId, this.fileId).toPromise(); await this._cleanupAndRedrawAnnotations(currentPageAnnotations, annotation => annotation.pageNumber === page); @@ -604,12 +610,16 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni this.rebuildFilters(); if (this.viewModeService.viewMode === 'STANDARD') { + const startTime = new Date().getTime(); annotationsToDelete?.forEach(annotation => { this._findAndDeleteAnnotation(annotation.id); }); - const newPageAnnotations = newAnnotationsFilter ? this.annotations.filter(newAnnotationsFilter) : this.annotations; - this._handleDeltaAnnotationFilters(annotationsToDelete ?? [], newPageAnnotations); - await this._redrawAnnotations(newPageAnnotations); + const newAnnotations = newAnnotationsFilter ? this.annotations.filter(newAnnotationsFilter) : this.annotations; + this._handleDeltaAnnotationFilters(annotationsToDelete ?? [], newAnnotations); + await this._redrawAnnotations(newAnnotations); + console.log( + `[REDACTION] Annotations redraw time: ${new Date().getTime() - startTime} ms for ${newAnnotations.length} annotations`, + ); } } diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/document-info.service.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/document-info.service.ts index 156fcd7c6..60023ef3a 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/document-info.service.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/document-info.service.ts @@ -1,11 +1,13 @@ import { Injectable } from '@angular/core'; import { BehaviorSubject, merge, Observable } from 'rxjs'; import { shareLast } from '@iqser/common-ui'; -import { filter, map, startWith, withLatestFrom } from 'rxjs/operators'; +import { filter, map, startWith, tap, withLatestFrom } from 'rxjs/operators'; import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service'; import { FileAttributesService } from '@services/entity-services/file-attributes.service'; import { FilesMapService } from '@services/entity-services/files-map.service'; import { File, IFileAttributeConfig } from '@red/domain'; +import { MultiSelectService } from './multi-select.service'; +import { ExcludedPagesService } from './excluded-pages.service'; @Injectable() export class DocumentInfoService { @@ -17,8 +19,18 @@ export class DocumentInfoService { private readonly _dossierTemplatesService: DossierTemplatesService, private readonly _fileAttributesService: FileAttributesService, private readonly _filesMapService: FilesMapService, + private readonly _multiSelectService: MultiSelectService, + private readonly _excludedPagesService: ExcludedPagesService, ) { - this.shown$ = this._show$.asObservable().pipe(shareLast()); + this.shown$ = this._show$.asObservable().pipe( + tap(show => { + if (show) { + this._multiSelectService.deactivate(); + this._excludedPagesService.hide(); + } + }), + shareLast(), + ); this.hidden$ = this.shown$.pipe( map(value => !value), shareLast(), diff --git a/apps/red-ui/src/app/modules/dossier/utils/pdf-viewer.utils.ts b/apps/red-ui/src/app/modules/dossier/utils/pdf-viewer.utils.ts index 5b29b9c07..90fc310e4 100644 --- a/apps/red-ui/src/app/modules/dossier/utils/pdf-viewer.utils.ts +++ b/apps/red-ui/src/app/modules/dossier/utils/pdf-viewer.utils.ts @@ -120,15 +120,17 @@ export class PdfViewerUtils { this._annotationManager.deselectAllAnnotations(); } - selectAnnotations(annotations: AnnotationWrapper[], multiSelectActive: boolean) { + selectAnnotations(annotations?: AnnotationWrapper[], multiSelectActive: boolean = false) { + if (!annotations) { + return; + } if (!multiSelectActive) { this.deselectAllAnnotations(); } const annotationsFromViewer = annotations.map(ann => this._getAnnotationById(ann.id)); - this._annotationManager.selectAnnotations(annotationsFromViewer); - // this.navigateToPage(annotations[0].pageNumber*this.paginationOffset); this._annotationManager.jumpToAnnotation(annotationsFromViewer[0]); + this._annotationManager.selectAnnotations(annotationsFromViewer); } deselectAnnotations(annotations: AnnotationWrapper[]) { diff --git a/apps/red-ui/src/app/services/user-preference.service.ts b/apps/red-ui/src/app/services/user-preference.service.ts index ac318c13d..cc89c6b6e 100644 --- a/apps/red-ui/src/app/services/user-preference.service.ts +++ b/apps/red-ui/src/app/services/user-preference.service.ts @@ -68,12 +68,9 @@ export class UserPreferenceService extends GenericService { window.location.reload(); } - reload(): Promise { - return this.getAll() - .toPromise() - .then(attributes => { - this._userAttributes = attributes ?? {}; - }); + async reload(): Promise { + const attributes = await this.getAll().toPromise(); + this._userAttributes = attributes ?? {}; } @Validate() diff --git a/apps/red-ui/src/app/utils/configuration.initializer.ts b/apps/red-ui/src/app/utils/configuration.initializer.ts index 2f31bef07..2f4bc4faf 100644 --- a/apps/red-ui/src/app/utils/configuration.initializer.ts +++ b/apps/red-ui/src/app/utils/configuration.initializer.ts @@ -1,4 +1,4 @@ -import { catchError, filter, mergeMapTo, switchMap, take, tap } from 'rxjs/operators'; +import { catchError, filter, mergeMap, switchMap, take, tap } from 'rxjs/operators'; import { ConfigService } from '@services/config.service'; import { Title } from '@angular/platform-browser'; import { from, of, throwError } from 'rxjs'; @@ -21,9 +21,10 @@ export function configurationInitializer( filter(event => event.type === KeycloakEventType.OnReady), switchMap(() => from(keycloakService.isLoggedIn())), switchMap(loggedIn => (!loggedIn ? throwError('Not Logged In') : of({}))), - mergeMapTo(generalSettingsService.getGeneralConfigurations()), + mergeMap(() => generalSettingsService.getGeneralConfigurations()), tap(configuration => configService.updateDisplayName(configuration.displayName)), - tap(() => userPreferenceService.reload().then(() => languageService.chooseAndSetInitialLanguage())), + switchMap(() => userPreferenceService.reload()), + tap(() => languageService.chooseAndSetInitialLanguage()), catchError(() => { title.setTitle('RedactManager'); return of({}); diff --git a/apps/red-ui/src/assets/config/config.json b/apps/red-ui/src/assets/config/config.json index c5a78443c..6befaaf58 100644 --- a/apps/red-ui/src/assets/config/config.json +++ b/apps/red-ui/src/assets/config/config.json @@ -1,7 +1,7 @@ { "ADMIN_CONTACT_NAME": null, "ADMIN_CONTACT_URL": null, - "API_URL": "https://dev-08.iqser.cloud/redaction-gateway-v1", + "API_URL": "https://dev-03.iqser.cloud/redaction-gateway-v1", "APP_NAME": "RedactManager", "AUTO_READ_TIME": 1.5, "BACKEND_APP_VERSION": "4.4.40", @@ -17,7 +17,7 @@ "MAX_RETRIES_ON_SERVER_ERROR": 3, "OAUTH_CLIENT_ID": "redaction", "OAUTH_IDP_HINT": null, - "OAUTH_URL": "https://dev-08.iqser.cloud/auth/realms/redaction", + "OAUTH_URL": "https://dev-03.iqser.cloud/auth/realms/redaction", "RECENT_PERIOD_IN_HOURS": 24, "SELECTION_MODE": "structural" } diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 2c97ec621..726d368c1 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -663,12 +663,12 @@ "action": "Analyze entire dossier" }, "stats": { - "analyzed-pages": "Pages", + "analyzed-pages": "{count, plural, one{Page} other{Pages}}", "charts": { - "dossiers": "Dossiers", - "total-documents": "Total Document(s)" + "dossiers": "{count, plural, one{Dossier} other{Dossiers}}", + "total-documents": "Total Documents" }, - "total-people": "Total user(s)" + "total-people": "Total users" }, "table-col-names": { "name": "Name", diff --git a/libs/red-domain/src/lib/pages/viewed-page.ts b/libs/red-domain/src/lib/pages/viewed-page.ts index 7dc11fc42..4de1e3c17 100644 --- a/libs/red-domain/src/lib/pages/viewed-page.ts +++ b/libs/red-domain/src/lib/pages/viewed-page.ts @@ -3,5 +3,5 @@ export interface IViewedPage { page?: number; userId?: string; viewedTime?: string; - hasChanges?: boolean; + showAsUnseen?: boolean; } diff --git a/package.json b/package.json index 91a9f08b4..63e4bbe64 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "redaction", - "version": "3.111.0", + "version": "3.115.0", "private": true, "license": "MIT", "scripts": { diff --git a/paligo-theme.tar.gz b/paligo-theme.tar.gz index 840317a80..99fc58a10 100644 Binary files a/paligo-theme.tar.gz and b/paligo-theme.tar.gz differ