import { DOCUMENT } from '@angular/common';
import { Component, ContentChildren, ElementRef, Inject, Input, OnDestroy, OnInit, QueryList, Renderer2, TemplateRef } from '@angular/core';
import { NavigationCancel, NavigationEnd, NavigationError, RouteConfigLoadEnd, RouteConfigLoadStart, Router, Event } from '@angular/router';
import { SettingsService } from '@delon/theme';
import { updateHostClass } from '@delon/util/browser';
import type { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzMessageService } from 'ng-zorro-antd/message';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { LayoutDefaultHeaderItemComponent } from './layout-header-item.component';
import { LayoutDefaultOptions } from './types';
@Component({
selector: 'layout-default',
exportAs: 'layoutDefault',
template: `
`
})
export class LayoutDefaultComponent implements OnInit, OnDestroy {
@ContentChildren(LayoutDefaultHeaderItemComponent, { descendants: false })
headerItems!: QueryList;
@Input() options!: LayoutDefaultOptions;
@Input() asideUser: TemplateRef | null = null;
@Input() nav: TemplateRef | null = null;
@Input() content: TemplateRef | null = null;
@Input() customError?: string | null;
private destroy$ = new Subject();
isFetching = false;
constructor(
router: Router,
private msgSrv: NzMessageService,
private settings: SettingsService,
private el: ElementRef,
private renderer: Renderer2,
@Inject(DOCUMENT) private doc: NzSafeAny
) {
router.events.pipe(takeUntil(this.destroy$)).subscribe(ev => this.processEv(ev));
}
processEv(ev: Event): void {
if (!this.isFetching && ev instanceof RouteConfigLoadStart) {
this.isFetching = true;
}
if (ev instanceof NavigationError || ev instanceof NavigationCancel) {
this.isFetching = false;
const err = this.customError === null ? null : this.customError ?? `Could not load ${ev.url} route`;
if (err && ev instanceof NavigationError) {
this.msgSrv.error(err, { nzDuration: 1000 * 3 });
}
return;
}
if (!(ev instanceof NavigationEnd || ev instanceof RouteConfigLoadEnd)) {
return;
}
if (this.isFetching) {
setTimeout(() => {
this.isFetching = false;
}, 100);
}
}
private setClass(): void {
const { el, doc, renderer, settings } = this;
const layout = settings.layout;
updateHostClass(el.nativeElement, renderer, {
['alain-default']: true,
[`alain-default__fixed`]: layout['fixed'],
[`alain-default__collapsed`]: layout.collapsed,
[`alain-default__hide-aside`]: this.options!.hideAside
});
doc.body.classList[layout.colorWeak ? 'add' : 'remove']('color-weak');
}
ngOnInit(): void {
this.options = {
logoExpanded: `./assets/logo-full.svg`,
logoCollapsed: `./assets/logo.svg`,
logoLink: `/`,
hideAside: false,
...this.options
};
const { settings, destroy$ } = this;
settings.notify.pipe(takeUntil(destroy$)).subscribe(() => this.setClass());
this.setClass();
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
}