mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
233 lines
8.6 KiB
TypeScript
233 lines
8.6 KiB
TypeScript
import { delay, distinctUntilChanged, filter, take } from 'rxjs/operators';
|
|
import {
|
|
AfterViewInit,
|
|
ChangeDetectionStrategy,
|
|
Component,
|
|
HostListener,
|
|
Inject,
|
|
OnInit,
|
|
Optional,
|
|
PLATFORM_ID,
|
|
} from '@angular/core';
|
|
import { NavigationCancel, NavigationEnd, NavigationStart, Router } from '@angular/router';
|
|
|
|
import { BehaviorSubject, Observable, of } from 'rxjs';
|
|
import { select, Store } from '@ngrx/store';
|
|
import { TranslateService } from '@ngx-translate/core';
|
|
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
|
|
|
|
import { MetadataService } from './core/metadata/metadata.service';
|
|
import { HostWindowResizeAction } from './shared/host-window.actions';
|
|
import { HostWindowState } from './shared/search/host-window.reducer';
|
|
import { NativeWindowRef, NativeWindowService } from './core/services/window.service';
|
|
import { isAuthenticationBlocking } from './core/auth/selectors';
|
|
import { AuthService } from './core/auth/auth.service';
|
|
import { CSSVariableService } from './shared/sass-helper/sass-helper.service';
|
|
import { MenuService } from './shared/menu/menu.service';
|
|
import { HostWindowService } from './shared/host-window.service';
|
|
import { ThemeConfig } from '../config/theme.model';
|
|
import { Angulartics2DSpace } from './statistics/angulartics/dspace-provider';
|
|
import { environment } from '../environments/environment';
|
|
import { models } from './core/core.module';
|
|
import { LocaleService } from './core/locale/locale.service';
|
|
import { hasValue, isNotEmpty } from './shared/empty.util';
|
|
import { KlaroService } from './shared/cookies/klaro.service';
|
|
import { GoogleAnalyticsService } from './statistics/google-analytics.service';
|
|
import { DOCUMENT, isPlatformBrowser } from '@angular/common';
|
|
import { ThemeService } from './shared/theme-support/theme.service';
|
|
import { BASE_THEME_NAME } from './shared/theme-support/theme.constants';
|
|
import { DEFAULT_THEME_CONFIG } from './shared/theme-support/theme.effects';
|
|
import { BreadcrumbsService } from './breadcrumbs/breadcrumbs.service';
|
|
|
|
@Component({
|
|
selector: 'ds-app',
|
|
templateUrl: './app.component.html',
|
|
styleUrls: ['./app.component.scss'],
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
})
|
|
export class AppComponent implements OnInit, AfterViewInit {
|
|
sidebarVisible: Observable<boolean>;
|
|
slideSidebarOver: Observable<boolean>;
|
|
collapsedSidebarWidth: Observable<string>;
|
|
totalSidebarWidth: Observable<string>;
|
|
theme: Observable<ThemeConfig> = of({} as any);
|
|
notificationOptions = environment.notifications;
|
|
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(true);
|
|
|
|
/**
|
|
* Whether or not the theme is in the process of being swapped
|
|
*/
|
|
isThemeLoading$: BehaviorSubject<boolean> = new BehaviorSubject(false);
|
|
|
|
|
|
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 metadata: MetadataService,
|
|
private angulartics2GoogleAnalytics: Angulartics2GoogleAnalytics,
|
|
private angulartics2DSpace: Angulartics2DSpace,
|
|
private authService: AuthService,
|
|
private router: Router,
|
|
private cssService: CSSVariableService,
|
|
private menuService: MenuService,
|
|
private windowService: HostWindowService,
|
|
private localeService: LocaleService,
|
|
private breadcrumbsService: BreadcrumbsService,
|
|
@Optional() private cookiesService: KlaroService,
|
|
@Optional() private googleAnalyticsService: GoogleAnalyticsService,
|
|
) {
|
|
|
|
/* Use models object so all decorators are actually called */
|
|
this.models = models;
|
|
|
|
this.themeService.getThemeName$().subscribe((themeName: string) => {
|
|
if (isPlatformBrowser(this.platformId)) {
|
|
// the theme css will never download server side, so this should only happen on the browser
|
|
this.isThemeLoading$.next(true);
|
|
}
|
|
if (hasValue(themeName)) {
|
|
this.setThemeCss(themeName);
|
|
} else if (hasValue(DEFAULT_THEME_CONFIG)) {
|
|
this.setThemeCss(DEFAULT_THEME_CONFIG.name);
|
|
} else {
|
|
this.setThemeCss(BASE_THEME_NAME);
|
|
}
|
|
});
|
|
|
|
// Load all the languages that are defined as active from the config file
|
|
translate.addLangs(environment.languages.filter((LangConfig) => LangConfig.active === true).map((a) => a.code));
|
|
|
|
// Load the default language from the config file
|
|
// translate.setDefaultLang(environment.defaultLanguage);
|
|
|
|
// set the current language code
|
|
this.localeService.setCurrentLanguageCode();
|
|
|
|
// analytics
|
|
if (hasValue(googleAnalyticsService)) {
|
|
googleAnalyticsService.addTrackingIdToPage();
|
|
}
|
|
angulartics2DSpace.startTracking();
|
|
|
|
metadata.listenForRouteChange();
|
|
breadcrumbsService.listenForRouteChanges();
|
|
|
|
if (environment.debug) {
|
|
console.info(environment);
|
|
}
|
|
this.storeCSSVariables();
|
|
|
|
}
|
|
|
|
ngOnInit() {
|
|
this.isAuthBlocking$ = this.store.pipe(select(isAuthenticationBlocking)).pipe(
|
|
distinctUntilChanged()
|
|
);
|
|
this.isAuthBlocking$
|
|
.pipe(
|
|
filter((isBlocking: boolean) => isBlocking === false),
|
|
take(1)
|
|
).subscribe(() => this.initializeKlaro());
|
|
|
|
const env: string = environment.production ? 'Production' : 'Development';
|
|
const color: string = environment.production ? 'red' : 'green';
|
|
console.info(`Environment: %c${env}`, `color: ${color}; font-weight: bold;`);
|
|
this.dispatchWindowSize(this._window.nativeWindow.innerWidth, this._window.nativeWindow.innerHeight);
|
|
}
|
|
|
|
private storeCSSVariables() {
|
|
this.cssService.addCSSVariable('xlMin', '1200px');
|
|
this.cssService.addCSSVariable('mdMin', '768px');
|
|
this.cssService.addCSSVariable('lgMin', '576px');
|
|
this.cssService.addCSSVariable('smMin', '0');
|
|
this.cssService.addCSSVariable('adminSidebarActiveBg', '#0f1b28');
|
|
this.cssService.addCSSVariable('sidebarItemsWidth', '250px');
|
|
this.cssService.addCSSVariable('collapsedSidebarWidth', '53.234px');
|
|
this.cssService.addCSSVariable('totalSidebarWidth', '303.234px');
|
|
// const vars = variables.locals || {};
|
|
// Object.keys(vars).forEach((name: string) => {
|
|
// this.cssService.addCSSVariable(name, vars[name]);
|
|
// })
|
|
}
|
|
|
|
ngAfterViewInit() {
|
|
this.router.events.pipe(
|
|
// This fixes an ExpressionChangedAfterItHasBeenCheckedError from being thrown while loading the component
|
|
// More information on this bug-fix: https://blog.angular-university.io/angular-debugging/
|
|
delay(0)
|
|
).subscribe((event) => {
|
|
if (event instanceof NavigationStart) {
|
|
this.isRouteLoading$.next(true);
|
|
} else if (
|
|
event instanceof NavigationEnd ||
|
|
event instanceof NavigationCancel
|
|
) {
|
|
this.isRouteLoading$.next(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 initializeKlaro() {
|
|
if (hasValue(this.cookiesService)) {
|
|
this.cookiesService.initialize();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update the theme css file in <head>
|
|
*
|
|
* @param themeName The name of the new theme
|
|
* @private
|
|
*/
|
|
private setThemeCss(themeName: string): void {
|
|
const head = this.document.getElementsByTagName('head')[0];
|
|
// Array.from to ensure we end up with an array, not an HTMLCollection, which would be
|
|
// automatically updated if we add nodes later
|
|
const currentThemeLinks = Array.from(this.document.getElementsByClassName('theme-css'));
|
|
const link = this.document.createElement('link');
|
|
link.setAttribute('rel', 'stylesheet');
|
|
link.setAttribute('type', 'text/css');
|
|
link.setAttribute('class', 'theme-css');
|
|
link.setAttribute('href', `/${encodeURIComponent(themeName)}-theme.css`);
|
|
// wait for the new css to download before removing the old one to prevent a
|
|
// flash of unstyled content
|
|
link.onload = () => {
|
|
if (isNotEmpty(currentThemeLinks)) {
|
|
currentThemeLinks.forEach((currentThemeLink: any) => {
|
|
if (hasValue(currentThemeLink)) {
|
|
currentThemeLink.remove();
|
|
}
|
|
});
|
|
}
|
|
// the fact that this callback is used, proves we're on the browser.
|
|
this.isThemeLoading$.next(false);
|
|
};
|
|
head.appendChild(link);
|
|
}
|
|
}
|