mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-12 12:33:07 +00:00
83628: Dynamic theme fixes
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { delay, distinctUntilChanged, filter, switchMap, take, withLatestFrom } from 'rxjs/operators';
|
import { distinctUntilChanged, filter, switchMap, take, withLatestFrom } from 'rxjs/operators';
|
||||||
import {
|
import {
|
||||||
AfterViewInit,
|
AfterViewInit,
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
@@ -13,9 +13,8 @@ import {
|
|||||||
ActivatedRouteSnapshot,
|
ActivatedRouteSnapshot,
|
||||||
NavigationCancel,
|
NavigationCancel,
|
||||||
NavigationEnd,
|
NavigationEnd,
|
||||||
NavigationStart,
|
NavigationStart, ResolveEnd,
|
||||||
Router,
|
Router,
|
||||||
RoutesRecognized
|
|
||||||
} from '@angular/router';
|
} from '@angular/router';
|
||||||
|
|
||||||
import { BehaviorSubject, Observable, of } from 'rxjs';
|
import { BehaviorSubject, Observable, of } from 'rxjs';
|
||||||
@@ -113,7 +112,6 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||||||
this.themeService.getThemeName$().subscribe((themeName: string) => {
|
this.themeService.getThemeName$().subscribe((themeName: string) => {
|
||||||
if (isPlatformBrowser(this.platformId)) {
|
if (isPlatformBrowser(this.platformId)) {
|
||||||
// the theme css will never download server side, so this should only happen on the browser
|
// the theme css will never download server side, so this should only happen on the browser
|
||||||
this.isThemeLoading$.next(true);
|
|
||||||
this.isThemeCSSLoading$.next(true);
|
this.isThemeCSSLoading$.next(true);
|
||||||
}
|
}
|
||||||
if (hasValue(themeName)) {
|
if (hasValue(themeName)) {
|
||||||
@@ -186,14 +184,14 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
this.router.events.pipe(
|
let resolveEndFound = false;
|
||||||
// This fixes an ExpressionChangedAfterItHasBeenCheckedError from being thrown while loading the component
|
this.router.events.subscribe((event) => {
|
||||||
// More information on this bug-fix: https://blog.angular-university.io/angular-debugging/
|
|
||||||
delay(0)
|
|
||||||
).subscribe((event) => {
|
|
||||||
if (event instanceof NavigationStart) {
|
if (event instanceof NavigationStart) {
|
||||||
|
resolveEndFound = false;
|
||||||
this.isRouteLoading$.next(true);
|
this.isRouteLoading$.next(true);
|
||||||
} else if (event instanceof RoutesRecognized) {
|
this.isThemeLoading$.next(true);
|
||||||
|
} else if (event instanceof ResolveEnd) {
|
||||||
|
resolveEndFound = true;
|
||||||
const activatedRouteSnapShot: ActivatedRouteSnapshot = event.state.root;
|
const activatedRouteSnapShot: ActivatedRouteSnapshot = event.state.root;
|
||||||
this.themeService.updateThemeOnRouteChange$(event.urlAfterRedirects, activatedRouteSnapShot).pipe(
|
this.themeService.updateThemeOnRouteChange$(event.urlAfterRedirects, activatedRouteSnapShot).pipe(
|
||||||
switchMap((changed) => {
|
switchMap((changed) => {
|
||||||
@@ -210,6 +208,9 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||||||
event instanceof NavigationEnd ||
|
event instanceof NavigationEnd ||
|
||||||
event instanceof NavigationCancel
|
event instanceof NavigationCancel
|
||||||
) {
|
) {
|
||||||
|
if (!resolveEndFound) {
|
||||||
|
this.isThemeLoading$.next(false);
|
||||||
|
}
|
||||||
this.isRouteLoading$.next(false);
|
this.isRouteLoading$.next(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -3,9 +3,9 @@ import { Store, createFeatureSelector, createSelector, select, Action } from '@n
|
|||||||
import { Observable } from 'rxjs/internal/Observable';
|
import { Observable } from 'rxjs/internal/Observable';
|
||||||
import { ThemeState } from './theme.reducer';
|
import { ThemeState } from './theme.reducer';
|
||||||
import { SetThemeAction, ThemeActionTypes } from './theme.actions';
|
import { SetThemeAction, ThemeActionTypes } from './theme.actions';
|
||||||
import { expand, filter, map, startWith, switchMap, take, toArray } from 'rxjs/operators';
|
import { expand, filter, map, startWith, switchMap, take, tap, toArray } from 'rxjs/operators';
|
||||||
import { hasValue, isNotEmpty } from '../empty.util';
|
import { hasValue, isNotEmpty } from '../empty.util';
|
||||||
import { Actions, ofType } from '@ngrx/effects';
|
import { act, Actions, ofType } from '@ngrx/effects';
|
||||||
import { ResolvedAction, ResolverActionTypes } from '../../core/resolving/resolver.actions';
|
import { ResolvedAction, ResolverActionTypes } from '../../core/resolving/resolver.actions';
|
||||||
import { RemoteData } from '../../core/data/remote-data';
|
import { RemoteData } from '../../core/data/remote-data';
|
||||||
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
||||||
@@ -86,9 +86,10 @@ export class ThemeService {
|
|||||||
|
|
||||||
const action$ = currentTheme$.pipe(
|
const action$ = currentTheme$.pipe(
|
||||||
switchMap((currentTheme: string) => {
|
switchMap((currentTheme: string) => {
|
||||||
|
const snapshotWithData = this.findRouteData(activatedRouteSnapshot);
|
||||||
if (this.hasDynamicTheme === true && isNotEmpty(this.themes)) {
|
if (this.hasDynamicTheme === true && isNotEmpty(this.themes)) {
|
||||||
if (hasValue(activatedRouteSnapshot) && hasValue(activatedRouteSnapshot.data) && hasValue(activatedRouteSnapshot.data.dso)) {
|
if (hasValue(snapshotWithData) && hasValue(snapshotWithData.data) && hasValue(snapshotWithData.data.dso)) {
|
||||||
const dsoRD: RemoteData<DSpaceObject> = activatedRouteSnapshot.data.dso;
|
const dsoRD: RemoteData<DSpaceObject> = snapshotWithData.data.dso;
|
||||||
if (dsoRD.hasSucceeded) {
|
if (dsoRD.hasSucceeded) {
|
||||||
// Start with the resolved dso and go recursively through its parents until you reach the top-level community
|
// Start with the resolved dso and go recursively through its parents until you reach the top-level community
|
||||||
return observableOf(dsoRD.payload).pipe(
|
return observableOf(dsoRD.payload).pipe(
|
||||||
@@ -123,10 +124,10 @@ export class ThemeService {
|
|||||||
// If there are no themes configured, do nothing
|
// If there are no themes configured, do nothing
|
||||||
return [new NoOpAction()];
|
return [new NoOpAction()];
|
||||||
}),
|
}),
|
||||||
|
take(1),
|
||||||
);
|
);
|
||||||
|
|
||||||
action$.pipe(
|
action$.pipe(
|
||||||
take(1),
|
|
||||||
filter((action) => action.type !== NO_OP_ACTION_TYPE),
|
filter((action) => action.type !== NO_OP_ACTION_TYPE),
|
||||||
).subscribe((action) => {
|
).subscribe((action) => {
|
||||||
this.store.dispatch(action);
|
this.store.dispatch(action);
|
||||||
@@ -137,6 +138,22 @@ export class ThemeService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
findRouteData(...routes: ActivatedRouteSnapshot[]) {
|
||||||
|
const result = routes.find((route) => hasValue(route.data.dso));
|
||||||
|
if (hasValue(result)) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
const nextLevelRoutes = routes
|
||||||
|
.map((route: ActivatedRouteSnapshot) => route.children)
|
||||||
|
.reduce((combined: ActivatedRouteSnapshot[], current: ActivatedRouteSnapshot[]) => [...combined, ...current]);
|
||||||
|
if (isNotEmpty(nextLevelRoutes)) {
|
||||||
|
return this.findRouteData(...nextLevelRoutes);
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An rxjs operator that will return an array of all the ancestors of the DSpaceObject used as
|
* An rxjs operator that will return an array of all the ancestors of the DSpaceObject used as
|
||||||
* input. The initial DSpaceObject will be the first element of the output array, followed by
|
* input. The initial DSpaceObject will be the first element of the output array, followed by
|
||||||
|
Reference in New Issue
Block a user