use custom share operators, update data streams
This commit is contained in:
parent
1e14469941
commit
e15884f037
@ -8,8 +8,9 @@ import { FileDownloadService } from '@upload-download/services/file-download.ser
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { SpotlightSearchAction } from '@components/spotlight-search/spotlight-search-action';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { distinctUntilChanged, filter, map, startWith } from 'rxjs/operators';
|
||||
import { filter, map, startWith } from 'rxjs/operators';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { shareDistinctLast } from '@iqser/common-ui';
|
||||
|
||||
interface MenuItem {
|
||||
readonly name: string;
|
||||
@ -73,7 +74,7 @@ export class BaseScreenComponent {
|
||||
filter(isNavigationStart),
|
||||
map((event: NavigationStart) => event.url),
|
||||
startWith(this._router.url),
|
||||
distinctUntilChanged(),
|
||||
shareDistinctLast(),
|
||||
);
|
||||
readonly isDossiersView$ = this._navigationStart$.pipe(map(isDossiersView));
|
||||
readonly isSearchScreen$ = this._navigationStart$.pipe(map(isSearchScreen));
|
||||
|
||||
@ -105,11 +105,11 @@
|
||||
|
||||
<div style="overflow: hidden; width: 100%">
|
||||
<ng-container *ngIf="!excludePages">
|
||||
<div [attr.anotation-page-header]="activeViewerPage" [class.padding-left-0]="isExcluded" class="page-separator">
|
||||
<div [attr.anotation-page-header]="activeViewerPage" [class.padding-left-0]="currentPageIsExcluded" class="page-separator">
|
||||
<span *ngIf="!!activeViewerPage" class="flex-align-items-center">
|
||||
<iqser-circle-button
|
||||
(action)="viewExcludePages()"
|
||||
*ngIf="isExcluded"
|
||||
*ngIf="currentPageIsExcluded"
|
||||
[tooltip]="'file-preview.excluded-from-redaction' | translate | capitalize"
|
||||
icon="red:exclude-pages"
|
||||
tooltipPosition="above"
|
||||
@ -152,7 +152,7 @@
|
||||
[verticalPadding]="40"
|
||||
icon="iqser:document"
|
||||
>
|
||||
<ng-container *ngIf="isExcluded">
|
||||
<ng-container *ngIf="currentPageIsExcluded">
|
||||
{{ 'file-preview.tabs.annotations.page-is' | translate }}
|
||||
<a (click)="viewExcludePages()" class="with-underline" translate="file-preview.excluded-from-redaction"></a
|
||||
>.
|
||||
|
||||
@ -90,7 +90,7 @@ export class FileWorkloadComponent {
|
||||
return !this._permissionsService.canPerformAnnotationActions();
|
||||
}
|
||||
|
||||
get isExcluded(): boolean {
|
||||
get currentPageIsExcluded(): boolean {
|
||||
return this.fileData?.file?.excludedPages?.includes(this.activeViewerPage);
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,14 @@
|
||||
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
EventEmitter,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output,
|
||||
SimpleChanges,
|
||||
} from '@angular/core';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { ConfigService } from '@services/config.service';
|
||||
@ -11,6 +21,7 @@ import { AutoUnsubscribe } from '@iqser/common-ui';
|
||||
selector: 'redaction-page-indicator',
|
||||
templateUrl: './page-indicator.component.html',
|
||||
styleUrls: ['./page-indicator.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class PageIndicatorComponent extends AutoUnsubscribe implements OnChanges, OnInit, OnDestroy {
|
||||
@Input() active: boolean;
|
||||
@ -62,12 +73,12 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnChanges
|
||||
}
|
||||
}
|
||||
|
||||
toggleReadState() {
|
||||
async toggleReadState() {
|
||||
if (this.canMarkPagesAsViewed) {
|
||||
if (this.read) {
|
||||
this._markPageUnread();
|
||||
await this._markPageUnread();
|
||||
} else {
|
||||
this._markPageRead();
|
||||
await this._markPageRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -82,9 +93,9 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnChanges
|
||||
}
|
||||
|
||||
if (this.active && !this.read) {
|
||||
this.pageReadTimeout = window.setTimeout(() => {
|
||||
this.pageReadTimeout = window.setTimeout(async () => {
|
||||
if (this.active && !this.read) {
|
||||
this._markPageRead();
|
||||
await this._markPageRead();
|
||||
}
|
||||
}, this._configService.values.AUTO_READ_TIME * 1000);
|
||||
}
|
||||
@ -107,26 +118,24 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnChanges
|
||||
// }
|
||||
// }
|
||||
|
||||
private _markPageRead() {
|
||||
this.addSubscription = this._viewedPagesService
|
||||
private async _markPageRead() {
|
||||
await this._viewedPagesService
|
||||
.addPage({ page: this.number }, this._dossiersService.activeDossierId, this._appStateService.activeFileId)
|
||||
.subscribe(() => {
|
||||
if (this.activePage) {
|
||||
this.activePage.hasChanges = false;
|
||||
} else {
|
||||
this.viewedPages?.push({ page: this.number, fileId: this._appStateService.activeFileId });
|
||||
}
|
||||
});
|
||||
.toPromise();
|
||||
if (this.activePage) {
|
||||
this.activePage.hasChanges = false;
|
||||
} else {
|
||||
this.viewedPages?.push({ page: this.number, fileId: this._appStateService.activeFileId });
|
||||
}
|
||||
}
|
||||
|
||||
private _markPageUnread() {
|
||||
this.addSubscription = this._viewedPagesService
|
||||
private async _markPageUnread() {
|
||||
await this._viewedPagesService
|
||||
.removePage(this._dossiersService.activeDossierId, this._appStateService.activeFileId, this.number)
|
||||
.subscribe(() => {
|
||||
this.viewedPages?.splice(
|
||||
this.viewedPages?.findIndex(p => p.page === this.number),
|
||||
1,
|
||||
);
|
||||
});
|
||||
.toPromise();
|
||||
this.viewedPages?.splice(
|
||||
this.viewedPages?.findIndex(p => p.page === this.number),
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<section *ngIf="appStateService.activeFile" [class.fullscreen]="fullScreen">
|
||||
<section *ngIf="appStateService.activeFile as file" [class.fullscreen]="fullScreen">
|
||||
<div class="page-header">
|
||||
<div class="flex flex-1">
|
||||
<div
|
||||
@ -30,8 +30,8 @@
|
||||
</div>
|
||||
|
||||
<div *ngIf="dossiersService.activeDossier$ | async as dossier" class="flex-1 actions-container">
|
||||
<ng-container *ngIf="!appStateService.activeFile.excluded">
|
||||
<ng-container *ngIf="!appStateService.activeFile.isProcessing">
|
||||
<ng-container *ngIf="!file.excluded">
|
||||
<ng-container *ngIf="!file.isProcessing">
|
||||
<iqser-status-bar [configs]="statusBarConfig" [small]="true"></iqser-status-bar>
|
||||
|
||||
<div class="all-caps-label mr-16 ml-8">
|
||||
@ -142,7 +142,7 @@
|
||||
[annotations]="annotations"
|
||||
[canPerformActions]="canPerformAnnotationActions"
|
||||
[fileData]="displayData"
|
||||
[file]="appStateService.activeFile"
|
||||
[file]="file"
|
||||
[multiSelectActive]="multiSelectActive"
|
||||
[shouldDeselectAnnotationsOnPageChange]="shouldDeselectAnnotationsOnPageChange"
|
||||
></redaction-pdf-viewer>
|
||||
@ -150,7 +150,7 @@
|
||||
|
||||
<div class="right-container">
|
||||
<iqser-empty-state
|
||||
*ngIf="appStateService.activeFile.excluded && !viewDocumentInfo && !excludePages"
|
||||
*ngIf="file.excluded && !viewDocumentInfo && !excludePages"
|
||||
[horizontalPadding]="40"
|
||||
[text]="'file-preview.tabs.is-excluded' | translate"
|
||||
icon="red:needs-work"
|
||||
@ -170,7 +170,7 @@
|
||||
(selectAnnotations)="selectAnnotations($event)"
|
||||
(selectPage)="selectPage($event)"
|
||||
(toggleSkipped)="toggleSkipped($event)"
|
||||
*ngIf="!appStateService.activeFile.excluded"
|
||||
*ngIf="!file.excluded"
|
||||
[(shouldDeselectAnnotationsOnPageChange)]="shouldDeselectAnnotationsOnPageChange"
|
||||
[activeViewerPage]="activeViewerPage"
|
||||
[annotationActionsTemplate]="annotationActionsTemplate"
|
||||
|
||||
@ -8,7 +8,6 @@ import {
|
||||
CircleButtonTypes,
|
||||
Debounce,
|
||||
FilterService,
|
||||
INestedFilter,
|
||||
List,
|
||||
LoadingService,
|
||||
OnAttach,
|
||||
@ -24,7 +23,7 @@ import { AnnotationData, FileDataModel } from '@models/file/file-data.model';
|
||||
import { FileActionService } from '../../shared/services/file-action.service';
|
||||
import { AnnotationDrawService } from '../../services/annotation-draw.service';
|
||||
import { AnnotationProcessingService } from '../../services/annotation-processing.service';
|
||||
import { Dossier, File, FileStatus, User, ViewMode } from '@red/domain';
|
||||
import { Dossier, FileStatus, User, ViewMode } from '@red/domain';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { timer } from 'rxjs';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
@ -42,6 +41,7 @@ import { FileActionsComponent } from '../../shared/components/file-actions/file-
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { FileManagementService } from '../../shared/services/file-management.service';
|
||||
import { filter, switchMapTo, tap } from 'rxjs/operators';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
|
||||
const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
|
||||
@ -78,7 +78,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
read: TemplateRef,
|
||||
static: true,
|
||||
})
|
||||
private readonly _filterTemplate: TemplateRef<INestedFilter>;
|
||||
private readonly _filterTemplate: TemplateRef<unknown>;
|
||||
|
||||
constructor(
|
||||
readonly appStateService: AppStateService,
|
||||
@ -311,6 +311,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
handleAnnotationSelected(annotationIds: string[]) {
|
||||
// TODO: use includes() here
|
||||
this.selectedAnnotations = annotationIds
|
||||
.map(id => this.annotations.find(annotationWrapper => annotationWrapper.id === id))
|
||||
.filter(ann => ann !== undefined);
|
||||
@ -318,7 +319,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this._workloadComponent.multiSelectActive = true;
|
||||
}
|
||||
this._workloadComponent.scrollToSelectedAnnotation();
|
||||
this._changeDetectorRef.detectChanges();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
selectAnnotations(annotations?: AnnotationWrapper[] | { annotations: AnnotationWrapper[]; multiSelect: boolean }) {
|
||||
@ -396,7 +397,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
return;
|
||||
}
|
||||
|
||||
this._changeDetectorRef.detectChanges();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
viewerPageChanged($event: any) {
|
||||
@ -416,13 +417,13 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
};
|
||||
this._router.navigate([], extras).then();
|
||||
|
||||
this._changeDetectorRef.detectChanges();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
async viewerReady($event: WebViewerInstance) {
|
||||
this._instance = $event;
|
||||
await this._stampExcludedPages();
|
||||
this._cleanupAndRedrawManualAnnotations();
|
||||
this._cleanupAndRedrawManualAnnotations$();
|
||||
this._updateCanPerformActions();
|
||||
|
||||
// Go to initial page from query params
|
||||
@ -464,7 +465,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
case 'exclude-pages':
|
||||
await this.appStateService.reloadActiveDossierFiles();
|
||||
await this._loadFileData(true);
|
||||
this._cleanupAndRedrawManualAnnotations();
|
||||
this._cleanupAndRedrawManualAnnotations$();
|
||||
await this._stampExcludedPages();
|
||||
this._loadingService.stop();
|
||||
return;
|
||||
@ -521,12 +522,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this._scrollViews();
|
||||
}
|
||||
|
||||
downloadOriginalFile() {
|
||||
this.addSubscription = this._fileManagementService
|
||||
async downloadOriginalFile() {
|
||||
const data = await this._fileManagementService
|
||||
.downloadOriginalFile(this.fileData.file.dossierId, this.fileId, 'response', true, this.fileData.file.cacheIdentifier)
|
||||
.subscribe(data => {
|
||||
download(data, this.fileData.file.filename);
|
||||
});
|
||||
.toPromise();
|
||||
download(data, this.fileData.file.filename);
|
||||
}
|
||||
|
||||
toggleSkipped($event) {
|
||||
@ -540,8 +540,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
private _setHiddenPropertyToNewAnnotations(newAnnotations: AnnotationWrapper[], oldAnnotations: AnnotationWrapper[]) {
|
||||
newAnnotations.map((newAnnotation: AnnotationWrapper) => {
|
||||
const oldAnnotation = oldAnnotations.find((a: AnnotationWrapper) => a.annotationId === newAnnotation.annotationId);
|
||||
newAnnotations.map(newAnnotation => {
|
||||
const oldAnnotation = oldAnnotations.find(a => a.annotationId === newAnnotation.annotationId);
|
||||
if (oldAnnotation) {
|
||||
newAnnotation.hidden = oldAnnotation.hidden;
|
||||
}
|
||||
@ -574,20 +574,20 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
await this._doStampExcludedPages(this.fileData.file.excludedPages);
|
||||
this._instance.Core.documentViewer.refreshAll();
|
||||
this._instance.Core.documentViewer.updateView([this.activeViewerPage], this.activeViewerPage);
|
||||
this._changeDetectorRef.detectChanges();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
private _subscribeToFileUpdates(): void {
|
||||
this.addSubscription = timer(0, 10000).subscribe(async () => this.appStateService.reloadActiveFile());
|
||||
this.addSubscription = this.appStateService.fileReanalysed$.subscribe(async (file: File) => {
|
||||
if (file.fileId === this.fileId) {
|
||||
this.addSubscription = timer(0, 10000).pipe(switchMapTo(this.appStateService.reloadActiveFile())).subscribe();
|
||||
this.addSubscription = this.appStateService.fileReanalysed$
|
||||
.pipe(filter(file => file.fileId === this.fileId))
|
||||
.subscribe(async () => {
|
||||
await this._loadFileData(!this._reloadFileOnReanalysis);
|
||||
this._reloadFileOnReanalysis = false;
|
||||
this._loadingService.stop();
|
||||
this._updateCanPerformActions();
|
||||
this._cleanupAndRedrawManualAnnotations();
|
||||
}
|
||||
});
|
||||
this._cleanupAndRedrawManualAnnotations$();
|
||||
});
|
||||
}
|
||||
|
||||
private _updateCanPerformActions() {
|
||||
@ -627,16 +627,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
/* Get the documentElement (<html>) to display the page in fullscreen */
|
||||
|
||||
private _cleanupAndRedrawManualAnnotations() {
|
||||
this._fileDownloadService.loadActiveFileRedactionLog().subscribe(async redactionLogPreview => {
|
||||
this.fileData.redactionLog = redactionLogPreview;
|
||||
await this._annotationDrawService.drawAnnotations(
|
||||
this._instance,
|
||||
this.annotationData.allAnnotations,
|
||||
this.hideSkipped,
|
||||
this.viewerComponent.utils.isCompareMode,
|
||||
);
|
||||
});
|
||||
private _cleanupAndRedrawManualAnnotations$() {
|
||||
return this._fileDownloadService.loadActiveFileRedactionLog().pipe(
|
||||
tap(redactionLog => (this.fileData.redactionLog = redactionLog)),
|
||||
switchMapTo(this._redrawAnnotations()),
|
||||
);
|
||||
}
|
||||
|
||||
private async _cleanupAndRedrawManualAnnotationsForEntirePage(page: number) {
|
||||
@ -654,15 +649,19 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
});
|
||||
const newPageAnnotations = this.annotations.filter(item => item.pageNumber === page);
|
||||
this._handleDeltaAnnotationFilters(currentPageAnnotations, newPageAnnotations);
|
||||
await this._annotationDrawService.drawAnnotations(
|
||||
this._instance,
|
||||
newPageAnnotations,
|
||||
this.hideSkipped,
|
||||
this.viewerComponent.utils.isCompareMode,
|
||||
);
|
||||
await this._redrawAnnotations(newPageAnnotations);
|
||||
}
|
||||
}
|
||||
|
||||
private _redrawAnnotations(annotations = this.annotationData.allAnnotations) {
|
||||
return this._annotationDrawService.drawAnnotations(
|
||||
this._instance,
|
||||
annotations,
|
||||
this.hideSkipped,
|
||||
this.viewerComponent.utils.isCompareMode,
|
||||
);
|
||||
}
|
||||
|
||||
private _handleDeltaAnnotationFilters(currentPageAnnotations: AnnotationWrapper[], newPageAnnotations: AnnotationWrapper[]) {
|
||||
const primaryFilterGroup = this._filterService.getGroup('primaryFilters');
|
||||
const primaryFilters = primaryFilterGroup.filters;
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
import { Injector } from '@angular/core';
|
||||
import { FilterService, SearchService } from '@iqser/common-ui';
|
||||
|
||||
/**
|
||||
* This should be removed when refactoring is done
|
||||
* @param injector
|
||||
* @constructor
|
||||
*/
|
||||
export const TEMPORARY_INJECTOR = injector =>
|
||||
Injector.create({
|
||||
providers: [
|
||||
{ provide: FilterService, useClass: FilterService },
|
||||
{ provide: SearchService, useClass: SearchService },
|
||||
],
|
||||
parent: injector,
|
||||
});
|
||||
@ -9,10 +9,10 @@ import {
|
||||
} from '@red/domain';
|
||||
import { interval, Observable } from 'rxjs';
|
||||
import { ConfigService } from '@services/config.service';
|
||||
import { map, mergeMap, tap } from 'rxjs/operators';
|
||||
import { filter, map, switchMapTo, tap, withLatestFrom } from 'rxjs/operators';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { EntitiesService, List, RequiredParam, Validate } from '@iqser/common-ui';
|
||||
import { EntitiesService, List, mapEach, RequiredParam, Validate } from '@iqser/common-ui';
|
||||
|
||||
@Injectable()
|
||||
export class FileDownloadService extends EntitiesService<DownloadStatus, IDownloadStatus> {
|
||||
@ -25,23 +25,25 @@ export class FileDownloadService extends EntitiesService<DownloadStatus, IDownlo
|
||||
protected readonly _injector: Injector,
|
||||
) {
|
||||
super(_injector, DownloadStatus, 'async/download');
|
||||
interval(5000).subscribe(() => {
|
||||
if (_userService.currentUser.isUser) {
|
||||
this.loadAll().subscribe(() => {});
|
||||
}
|
||||
});
|
||||
interval(5000)
|
||||
.pipe(
|
||||
withLatestFrom(_userService.currentUser$),
|
||||
filter(([, user]) => user.isUser),
|
||||
switchMapTo(this.loadAll()),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
downloadFiles(fileIds: List, dossierId: string): Observable<any> {
|
||||
downloadFiles(fileIds: List, dossierId: string): Observable<DownloadStatus[]> {
|
||||
return this.prepareDownload({
|
||||
fileIds,
|
||||
dossierId,
|
||||
}).pipe(mergeMap(() => this.loadAll()));
|
||||
}).pipe(switchMapTo(this.loadAll()));
|
||||
}
|
||||
|
||||
loadAll(): Observable<DownloadStatus[]> {
|
||||
return this.getStatuses().pipe(
|
||||
map(entities => entities.map(entity => new DownloadStatus(entity))),
|
||||
mapEach(entity => new DownloadStatus(entity)),
|
||||
tap(entities => this.setEntities(entities)),
|
||||
tap(() => (this.hasPendingDownloads = !!this.all.find(f => !f.lastDownload && f.isReady))),
|
||||
);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { catchError, filter, mergeMap, take, tap } from 'rxjs/operators';
|
||||
import { catchError, filter, mergeMapTo, take, tap } from 'rxjs/operators';
|
||||
import { ConfigService } from '@services/config.service';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { of } from 'rxjs';
|
||||
@ -15,7 +15,7 @@ export function configurationInitializer(
|
||||
keycloakService.keycloakEvents$
|
||||
.pipe(
|
||||
filter(event => event.type === KeycloakEventType.OnReady),
|
||||
mergeMap(() => generalSettingsService.getGeneralConfigurations()),
|
||||
mergeMapTo(generalSettingsService.getGeneralConfigurations()),
|
||||
tap(configuration => configService.updateDisplayName(configuration.displayName)),
|
||||
catchError(() => {
|
||||
title.setTitle('RedactManager');
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit e1ce89e38d3520ad11960074f74c381429c0251a
|
||||
Subproject commit 712178ea34c998098cd2c079a0be1dd863dd266e
|
||||
Loading…
x
Reference in New Issue
Block a user