Files
dspace-angular/src/app/app.component.ts
2024-03-26 20:52:26 +01:00

182 lines
5.0 KiB
TypeScript

import {
AsyncPipe,
DOCUMENT,
isPlatformBrowser,
} from '@angular/common';
import {
AfterViewInit,
ChangeDetectionStrategy,
Component,
HostListener,
Inject,
OnInit,
PLATFORM_ID,
} from '@angular/core';
import {
NavigationCancel,
NavigationEnd,
NavigationStart,
Router,
} from '@angular/router';
import {
NgbModal,
NgbModalConfig,
} from '@ng-bootstrap/ng-bootstrap';
import {
select,
Store,
} from '@ngrx/store';
import { TranslateService } from '@ngx-translate/core';
import {
BehaviorSubject,
Observable,
} from 'rxjs';
import {
distinctUntilChanged,
take,
withLatestFrom,
} from 'rxjs/operators';
import { environment } from '../environments/environment';
import { AuthService } from './core/auth/auth.service';
import { isAuthenticationBlocking } from './core/auth/selectors';
import {
NativeWindowRef,
NativeWindowService,
} from './core/services/window.service';
import { distinctNext } from './core/shared/distinct-next';
import { ThemedRootComponent } from './root/themed-root.component';
import { HostWindowResizeAction } from './shared/host-window.actions';
import { IdleModalComponent } from './shared/idle-modal/idle-modal.component';
import { CSSVariableService } from './shared/sass-helper/css-variable.service';
import { HostWindowState } from './shared/search/host-window.reducer';
import { ThemeService } from './shared/theme-support/theme.service';
@Component({
selector: 'ds-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
ThemedRootComponent,
AsyncPipe,
],
})
export class AppComponent implements OnInit, AfterViewInit {
notificationOptions;
models;
/**
* Whether or not the authentication is currently blocking the UI
*/
isAuthBlocking$: Observable<boolean>;
/**
* Whether or not the app is in the process of rerouting
*/
isRouteLoading$: BehaviorSubject<boolean> = new BehaviorSubject(false);
/**
* Whether or not the theme is in the process of being swapped
*/
isThemeLoading$: Observable<boolean>;
/**
* Whether or not the idle modal is is currently open
*/
idleModalOpen: boolean;
constructor(
@Inject(NativeWindowService) private _window: NativeWindowRef,
@Inject(DOCUMENT) private document: any,
@Inject(PLATFORM_ID) private platformId: any,
private themeService: ThemeService,
private translate: TranslateService,
private store: Store<HostWindowState>,
private authService: AuthService,
private router: Router,
private cssService: CSSVariableService,
private modalService: NgbModal,
private modalConfig: NgbModalConfig,
) {
this.notificationOptions = environment.notifications;
if (isPlatformBrowser(this.platformId)) {
this.trackIdleModal();
}
this.isThemeLoading$ = this.themeService.isThemeLoading$;
this.storeCSSVariables();
}
ngOnInit() {
/** Implement behavior for interface {@link ModalBeforeDismiss} */
this.modalConfig.beforeDismiss = async function () {
if (typeof this?.componentInstance?.beforeDismiss === 'function') {
return this.componentInstance.beforeDismiss();
}
// fall back to default behavior
return true;
};
this.isAuthBlocking$ = this.store.pipe(
select(isAuthenticationBlocking),
distinctUntilChanged(),
);
this.dispatchWindowSize(this._window.nativeWindow.innerWidth, this._window.nativeWindow.innerHeight);
}
private storeCSSVariables() {
this.cssService.clearCSSVariables();
this.cssService.addCSSVariables(this.cssService.getCSSVariablesFromStylesheets(this.document));
}
ngAfterViewInit() {
this.router.events.subscribe((event) => {
if (event instanceof NavigationStart) {
distinctNext(this.isRouteLoading$, true);
} else if (
event instanceof NavigationEnd ||
event instanceof NavigationCancel
) {
distinctNext(this.isRouteLoading$, false);
}
});
}
@HostListener('window:resize', ['$event'])
public onResize(event): void {
this.dispatchWindowSize(event.target.innerWidth, event.target.innerHeight);
}
private dispatchWindowSize(width, height): void {
this.store.dispatch(
new HostWindowResizeAction(width, height),
);
}
private trackIdleModal() {
const isIdle$ = this.authService.isUserIdle();
const isAuthenticated$ = this.authService.isAuthenticated();
isIdle$.pipe(withLatestFrom(isAuthenticated$))
.subscribe(([userIdle, authenticated]) => {
if (userIdle && authenticated) {
if (!this.idleModalOpen) {
const modalRef = this.modalService.open(IdleModalComponent, { ariaLabelledBy: 'idle-modal.header' });
this.idleModalOpen = true;
modalRef.componentInstance.response.pipe(take(1)).subscribe((closed: boolean) => {
if (closed) {
this.idleModalOpen = false;
}
});
}
}
});
}
}