Pull request #165: reuse file preview routes

Merge in RED/ui from file-preview-reuse to master

* commit 'dcc96dc4bd144c13e4355439d45e7dadf0b87043':
  reuse file preview routes
This commit is contained in:
Timo Bejan 2021-04-22 09:05:34 +02:00
commit 1efdcb3ac0
4 changed files with 79 additions and 48 deletions

View File

@ -108,7 +108,7 @@ export class FileActionsComponent implements OnInit {
$event.stopPropagation();
await this._fileActionService.toggleAnalysis(this.fileStatus).toPromise();
await this.appStateService.getFiles();
this.actionPerformed.emit(this.fileStatus.isExcluded ? 'enable-analysis' : 'disable-analysis');
this.actionPerformed.emit(this.fileStatus?.isExcluded ? 'enable-analysis' : 'disable-analysis');
}
get toggleTooltip(): string {
@ -116,6 +116,6 @@ export class FileActionsComponent implements OnInit {
return 'file-preview.toggle-analysis.only-managers';
}
return this.fileStatus.isExcluded ? 'file-preview.toggle-analysis.enable' : 'file-preview.toggle-analysis.disable';
return this.fileStatus?.isExcluded ? 'file-preview.toggle-analysis.enable' : 'file-preview.toggle-analysis.disable';
}
}

View File

@ -33,7 +33,7 @@ const routes = [
canActivate: [CompositeRouteGuard],
data: {
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard],
reuse: false // TODO ROUTE REUSE FOR file
reuse: true
}
}
];

View File

@ -1,5 +1,5 @@
import { ChangeDetectorRef, Component, HostListener, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ActivatedRoute, ActivatedRouteSnapshot, Router } from '@angular/router';
import { AppStateService } from '../../../../state/app-state.service';
import { WebViewerInstance } from '@pdftron/webviewer';
import { PdfViewerComponent } from '../../components/pdf-viewer/pdf-viewer.component';
@ -28,7 +28,7 @@ import { download } from '../../../../utils/file-download-utils';
import { ViewMode } from '../../../../models/file/view-mode';
import { FileWorkloadComponent } from '../../components/file-workload/file-workload.component';
import { ProjectsDialogService } from '../../services/projects-dialog.service';
import { ReuseAwareRoute } from '../../../../utils/custom-route-reuse.strategy';
import { OnAttach, OnDetach } from '../../../../utils/custom-route-reuse.strategy';
const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
@ -37,7 +37,7 @@ const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
templateUrl: './file-preview-screen.component.html',
styleUrls: ['./file-preview-screen.component.scss']
})
export class FilePreviewScreenComponent implements OnInit, OnDestroy, ReuseAwareRoute {
export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, OnDetach {
public dialogRef: MatDialogRef<any>;
public viewMode: ViewMode = 'STANDARD';
public fullScreen = false;
@ -60,6 +60,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, ReuseAware
displayPDFViewer = false;
public viewDocumentInfo = false;
private _instance: WebViewerInstance;
private _lastPage: string;
@ViewChild('fileWorkloadComponent') private _workloadComponent: FileWorkloadComponent;
@ViewChild(PdfViewerComponent) private _viewerComponent: PdfViewerComponent;
@ -167,16 +168,16 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, ReuseAware
this._updateCanPerformActions();
}
// TODO POC
onRouteReuse() {
// primitive route reuse mechanic to trigger code on reuse, in this case reload PDF Viewer,
// we would still need to first store some state-related data and the restore it to the new instance
// for example page
console.log('testing route reuse ... ');
ngOnDetach() {
this.displayPDFViewer = false;
setTimeout(() => {
this.displayPDFViewer = true;
});
this.viewReady = false;
this._unsubscribeFromFileUpdates();
}
ngOnAttach(previousRoute: ActivatedRouteSnapshot) {
this.displayPDFViewer = true;
this._lastPage = previousRoute.queryParams.page;
this._subscribeToFileUpdates();
}
ngOnInit(): void {
@ -188,32 +189,15 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, ReuseAware
}
});
this.filesAutoUpdateTimer = timer(0, 5000)
.pipe(
tap(async () => {
await this.appStateService.reloadActiveFile();
})
)
.subscribe();
this._loadFileData().subscribe(() => {
this._updateCanPerformActions();
});
this.fileReanalysedSubscription = this.appStateService.fileReanalysed.subscribe((fileStatus: FileStatusWrapper) => {
if (fileStatus.fileId === this.fileId) {
this._loadFileData(true).subscribe(() => {
this.viewReady = true;
this.loadingMessage = null;
this._stopAnalysisTimer();
this._updateCanPerformActions();
this._cleanupAndRedrawManualAnnotations();
});
}
});
this._subscribeToFileUpdates();
}
ngOnDestroy(): void {
this.filesAutoUpdateTimer.unsubscribe();
this.fileReanalysedSubscription.unsubscribe();
this._unsubscribeFromFileUpdates();
}
public rebuildFilters(deletePreviousAnnotations: boolean = false) {
@ -344,7 +328,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, ReuseAware
this._cleanupAndRedrawManualAnnotations();
this.viewReady = true;
// Go to initial page from query params
const pageNumber = this._activatedRoute.snapshot.queryParams.page;
const pageNumber = this._lastPage || this._activatedRoute.snapshot.queryParams.page;
if (pageNumber) {
setTimeout(() => {
this.selectPage(parseInt(pageNumber, 10));
@ -447,6 +431,32 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, ReuseAware
window.open(`/html-debug/${this.projectId}/${this.fileId}`, '_blank');
}
private _subscribeToFileUpdates(): void {
this.filesAutoUpdateTimer = timer(0, 5000)
.pipe(
tap(async () => {
await this.appStateService.reloadActiveFile();
})
)
.subscribe();
this.fileReanalysedSubscription = this.appStateService.fileReanalysed.subscribe((fileStatus: FileStatusWrapper) => {
if (fileStatus.fileId === this.fileId) {
this._loadFileData(true).subscribe(() => {
this.viewReady = true;
this.loadingMessage = null;
this._stopAnalysisTimer();
this._updateCanPerformActions();
this._cleanupAndRedrawManualAnnotations();
});
}
});
}
private _unsubscribeFromFileUpdates(): void {
this.filesAutoUpdateTimer.unsubscribe();
this.fileReanalysedSubscription.unsubscribe();
}
private _updateCanPerformActions() {
this.canPerformAnnotationActions = this.permissionsService.canPerformAnnotationActions() && this.viewMode === 'STANDARD';
}

View File

@ -1,8 +1,21 @@
import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router';
import { debounce } from './debounce';
export interface OnAttach {
ngOnAttach(previousRoute: ActivatedRouteSnapshot);
}
export interface OnDetach {
ngOnDetach();
}
interface RouteStorageObject {
handle: DetachedRouteHandle;
previousRoute: ActivatedRouteSnapshot;
}
export class CustomRouteReuseStrategy implements RouteReuseStrategy {
private _handlers: { [key: string]: DetachedRouteHandle } = {};
private _storedRoutes: { [key: string]: RouteStorageObject } = {};
shouldDetach(route: ActivatedRouteSnapshot): boolean {
return !!route.routeConfig.data?.reuse && !!this._getKey(route);
@ -10,19 +23,26 @@ export class CustomRouteReuseStrategy implements RouteReuseStrategy {
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
if (handle === null) return;
this._handlers[this._getKey(route)] = handle;
const element: any = handle;
if (element?.componentRef?.instance?.ngOnDetach) {
this._onDetach(element.componentRef?.instance);
}
this._storedRoutes[this._getKey(route)] = { handle: element as DetachedRouteHandle, previousRoute: route };
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
return !!this._handlers[this._getKey(route)];
return !!this._storedRoutes[this._getKey(route)];
}
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
const key = this._getKey(route);
const element: any = this._handlers[key];
const element: any = this._storedRoutes[key]?.handle;
if (element?.componentRef?.instance?.onRouteReuse) {
this._reuseRoute(element.componentRef?.instance);
if (element?.componentRef?.instance?.ngOnAttach) {
this._onAttach(element.componentRef?.instance, this._storedRoutes[key].previousRoute);
}
return element as DetachedRouteHandle;
@ -40,11 +60,12 @@ export class CustomRouteReuseStrategy implements RouteReuseStrategy {
}
@debounce()
private _reuseRoute(instance: any) {
instance.onRouteReuse();
private _onAttach(instance: OnAttach, previousRoute?: ActivatedRouteSnapshot) {
instance.ngOnAttach(previousRoute);
}
@debounce()
private _onDetach(instance: OnDetach) {
instance.ngOnDetach();
}
}
export interface ReuseAwareRoute {
onRouteReuse();
}