import { Inject, Injectable, InjectionToken } from '@angular/core'; import { ResolveEnd, Router } from '@angular/router'; import { BehaviorSubject, Observable } from 'rxjs'; import { filter, take } from 'rxjs/operators'; import { cloneDeep, isEqual, merge, set } from 'lodash-es'; import { Config } from './config'; import { environment } from 'projects/core/src//environment'; // Create the injection token for the custom settings export const MW_APP_CONFIG = new InjectionToken('mwAppCustomConfig'); const DefaultConfig: Config = { resetLayoutOnRoutingEnd: true, form: { sidebarPosition: 'left', bottomActionsPosition: 'nonSticky', }, layout: { fullWidth: false, }, }; @Injectable() export class MwAppConfigService { static nextId = 1; readonly id: string = `${ environment.clientId }-${MwAppConfigService.nextId++}`; private configSubject$: BehaviorSubject; private readonly localDefaultConfig: Config; constructor( private router: Router, @Inject(MW_APP_CONFIG) private config: any ) { this.localDefaultConfig = merge({}, DefaultConfig, this.config); this.configSubject$ = new BehaviorSubject( cloneDeep(this.localDefaultConfig) ); // Initialize the service this._init(); } set config$(value) { // Get the value from the behavior subject let config: Config = this.configSubject$.getValue(); // Merge the new config config = { ...config, ...value }; // Notify the observers this.configSubject$.next(config); } get config$(): Observable { return this.configSubject$.asObservable(); } get defaultConfig(): Config { return this.localDefaultConfig; } private _init(): void { // Set the config from the default config // Reload the default layout config on every RoutesRecognized event // if the current layout config is different from the default one this.router.events .pipe(filter((event) => event instanceof ResolveEnd)) .subscribe(() => { const config = this.getInstantConfig(); if (!config || !config.resetLayoutOnRoutingEnd) { return; } if (!isEqual(config.layout, this.localDefaultConfig.layout)) { // Clone the current config const newConfig = cloneDeep(config); // Reset the layout from the default config newConfig.layout = cloneDeep(this.localDefaultConfig.layout); // Set the config this.configSubject$.next(newConfig); } }); } setConfig(value: any, opts = { emitEvent: true }): void { // Get the value from the behavior subject let config = this.configSubject$.getValue(); // Merge the new config config = merge({}, config, value); // If emitEvent option is true... if (opts.emitEvent === true) { // Notify the observers this.configSubject$.next(config); } } setConfigChunk(path: string, value: any): void { // Get the value from the behavior subject let config = this.configSubject$.getValue(); // Set value based on path config = set(config, path, value); // Notify the observers this.configSubject$.next(config); } getConfig(): Observable { return this.configSubject$.asObservable(); } getInstantConfig(): Config | null { let config: Config | null = null; this.getConfig() .pipe(take(1)) .subscribe((_config) => (config = _config)); return config; } resetToDefaults(): void { // Set the config from the default config this.configSubject$.next(cloneDeep(this.localDefaultConfig)); } }