UNPKG

angular-admin-lte

Version:
1,144 lines (1,120 loc) 113 kB
import { Injectable, Component, ChangeDetectorRef, Input, NgModule, ChangeDetectionStrategy, ElementRef, ViewChild, ContentChild, NgZone, Renderer2, EventEmitter, Directive, Output, ViewChildren, InjectionToken, Optional, SkipSelf, ContentChildren, ViewContainerRef, HostListener } from '@angular/core'; import { CommonModule } from '@angular/common'; import { NavigationEnd, PRIMARY_OUTLET, Router, RouterModule, NavigationStart, ActivationStart } from '@angular/router'; import { BehaviorSubject, Subject } from 'rxjs'; import { Title } from '@angular/platform-browser'; import { pluck, distinctUntilChanged } from 'rxjs/operators'; import { NgControl, FormsModule } from '@angular/forms'; class RoutingService { constructor(router) { this.router = router; this.onChange = new BehaviorSubject(undefined); this.events = new BehaviorSubject(undefined); this.init(); } static createUrl(route) { const url = route.url.map(urlSegment => urlSegment.toString()).join('/'); return url; } static isChildrenSelfRoute(route) { var _a, _b; let test = false; (_b = (_a = route === null || route === void 0 ? void 0 : route.routeConfig) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b.forEach(child => { if (child.path === '' && (child.component || child.loadChildren)) { test = true; } }); return test; } static createBreadcrumb(route, url) { var _a, _b, _c, _d; let isUrl = true; if (route.children.length !== 0 && ((_b = (_a = route === null || route === void 0 ? void 0 : route.firstChild) === null || _a === void 0 ? void 0 : _a.routeConfig) === null || _b === void 0 ? void 0 : _b.path)) { if (url !== '/' && !((_c = route === null || route === void 0 ? void 0 : route.routeConfig) === null || _c === void 0 ? void 0 : _c.loadChildren) && !((_d = route === null || route === void 0 ? void 0 : route.routeConfig) === null || _d === void 0 ? void 0 : _d.component) && !RoutingService.isChildrenSelfRoute(route)) { isUrl = false; } } return { data: route.data, params: route.params, url: isUrl ? url : null }; } init() { this.router.events.subscribe(routeEvent => { var _a; // https://github.com/angular/angular/issues/17473: event not fired anymore on load for routed component. if (routeEvent instanceof NavigationEnd) { this.events.next(routeEvent); let route = this.router.routerState.root.snapshot; let tmpUrl = ''; let url = ''; let rootRoot = true; const paths = []; while (route.children.length) { route = route.firstChild || route; tmpUrl = `/${RoutingService.createUrl(route)}`; if (route.outlet !== PRIMARY_OUTLET || (!((_a = route === null || route === void 0 ? void 0 : route.routeConfig) === null || _a === void 0 ? void 0 : _a.path) && !rootRoot)) { continue; } rootRoot = false; if (route.params && route.data) { for (const key in route.params) { if (!key) { continue; } if (route.data.hasOwnProperty('title')) { route.data.title = route.data.title.replace(`:${key}`, route.params[key]); route.data.title = route.data.title.replace(`:${key}`, route.params[key]); } if (route.data.hasOwnProperty('breadcrumbs')) { route.data.breadcrumbs = route.data.breadcrumbs.replace(`:${key}`, route.params[key]); } if (route.data.hasOwnProperty('description')) { route.data.description = route.data.description.replace(`:${key}`, route.params[key]); } } } if (tmpUrl === '/') { paths.push(RoutingService.createBreadcrumb(route, tmpUrl)); } else { url += tmpUrl; paths.push(RoutingService.createBreadcrumb(route, url)); } } this.onChange.next(paths); } }); } } RoutingService.decorators = [ { type: Injectable } ]; RoutingService.ctorParameters = () => [ { type: Router } ]; class BreadcrumbsComponent { constructor(routingService, changeDetectorRef) { this.routingService = routingService; this.changeDetectorRef = changeDetectorRef; this.homeIcon = 'fa fa-home'; } ngOnInit() { this.subscription = this.routingService.onChange.subscribe(paths => { this.breadcrumbs = paths; }); } ngOnDestroy() { if (this.subscription) { this.subscription.unsubscribe(); } } } BreadcrumbsComponent.decorators = [ { type: Component, args: [{ selector: 'mk-breadcrumbs', template: "<ol class=\"breadcrumb\">\n <li *ngFor=\"let breadcrumb of breadcrumbs; let first = first; let last = last\" [class.active]=\"last || !breadcrumb.url\">\n <a *ngIf=\"breadcrumb.url && !last; else noLink\" [routerLink]=\"breadcrumb.url\">\n <i *ngIf=\"first\" ngClass=\"{{homeIcon}}\"></i>\n <ng-template [ngIf]=\"breadcrumb.data.breadcrumbs\">{{breadcrumb.data.breadcrumbs}}</ng-template>\n <ng-template [ngIf]=\"breadcrumb.data.title\">{{breadcrumb.data.title}}</ng-template>\n </a>\n <ng-template #noLink>\n <i *ngIf=\"first\" ngClass=\"{{homeIcon}}\"></i>\n <ng-template [ngIf]=\"breadcrumb.data.breadcrumbs\">{{breadcrumb.data.breadcrumbs}}</ng-template>\n <ng-template [ngIf]=\"breadcrumb.data.title\">{{breadcrumb.data.title}}</ng-template>\n </ng-template>\n </li>\n</ol>\n", styles: [".breadcrumb{background:transparent;border-radius:2px;float:right;font-size:12px;margin-bottom:0;margin-top:0;padding:7px 5px;position:absolute;right:10px;top:15px}.breadcrumb>li>a{color:#444;display:inline-block;text-decoration:none}.breadcrumb>li .fa,.breadcrumb>li .glyphicon,.breadcrumb>li .ion{margin-right:5px}"] },] } ]; BreadcrumbsComponent.ctorParameters = () => [ { type: RoutingService }, { type: ChangeDetectorRef } ]; BreadcrumbsComponent.propDecorators = { homeIcon: [{ type: Input }] }; class BreadcrumbsModule { } BreadcrumbsModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule, RouterModule], exports: [BreadcrumbsComponent], declarations: [BreadcrumbsComponent] },] } ]; class LayoutState { constructor(config) { this.isSidebarLeftCollapsed = false; this.isSidebarLeftExpandOnOver = false; this.isSidebarLeftMouseOver = false; this.isSidebarLeftMini = true; this.sidebarRightSkin = 'dark'; this.isSidebarRightCollapsed = true; this.isSidebarRightOverContent = true; this.layout = 'normal'; this.sidebarLeftMenu = []; this.sidebarLeftMenuActiveUrl = ''; this.skin = 'blue'; Object.assign(this, config); } } class LayoutStore { constructor(layoutConfig) { this.initialLayoutState = new LayoutState(layoutConfig); this.state = new BehaviorSubject(this.initialLayoutState); this.layoutState = this.state.asObservable(); } get windowInnerHeight() { return this.layoutState.pipe(pluck('windowInnerHeight'), distinctUntilChanged()); } get windowInnerWidth() { return this.layoutState.pipe(pluck('windowInnerWidth'), distinctUntilChanged()); } get isSidebarLeftCollapsed() { return this.layoutState.pipe(pluck('isSidebarLeftCollapsed'), distinctUntilChanged()); } get isSidebarLeftExpandOnOver() { return this.layoutState.pipe(pluck('isSidebarLeftExpandOnOver'), distinctUntilChanged()); } get isSidebarLeftMouseOver() { return this.layoutState.pipe(pluck('isSidebarLeftMouseOver'), distinctUntilChanged()); } get isSidebarLeftMini() { return this.layoutState.pipe(pluck('isSidebarLeftMini'), distinctUntilChanged()); } get sidebarRightSkin() { return this.layoutState.pipe(pluck('sidebarRightSkin'), distinctUntilChanged()); } get isSidebarRightCollapsed() { return this.layoutState.pipe(pluck('isSidebarRightCollapsed'), distinctUntilChanged()); } get isSidebarRightOverContent() { return this.layoutState.pipe(pluck('isSidebarRightOverContent'), distinctUntilChanged()); } get sidebarLeftMenu() { return this.layoutState.pipe(pluck('sidebarLeftMenu'), distinctUntilChanged()); } get sidebarLeftMenuActiveUrl() { return this.layoutState.pipe(pluck('sidebarLeftMenuActiveUrl'), distinctUntilChanged()); } get sidebarLeftElementHeight() { return this.layoutState.pipe(pluck('sidebarLeftElementHeight'), distinctUntilChanged()); } get layout() { return this.layoutState.pipe(pluck('layout'), distinctUntilChanged()); } get skin() { return this.layoutState.pipe(pluck('skin'), distinctUntilChanged()); } sidebarLeftCollapsed(value) { this.state.next(Object.assign(this.state.value, { isSidebarLeftCollapsed: value })); } sidebarLeftExpandOnOver(value) { this.state.next(Object.assign(this.state.value, { isSidebarLeftExpandOnOver: value })); } setSidebarLeftElementHeight(value) { this.state.next(Object.assign(this.state.value, { sidebarLeftElementHeight: value })); } setSidebarRightSkin(value) { this.state.next(Object.assign(this.state.value, { sidebarRightSkin: value })); } sidebarLeftMouseOver(value) { this.state.next(Object.assign(this.state.value, { isSidebarLeftMouseOver: value })); } sidebarLeftMini(value) { this.state.next(Object.assign(this.state.value, { isSidebarLeftMini: value })); } sidebarRightCollapsed(value) { this.state.next(Object.assign(this.state.value, { isSidebarRightCollapsed: value })); } sidebarRightOverContent(value) { this.state.next(Object.assign(this.state.value, { isSidebarRightOverContent: value })); } setSidebarLeftMenu(value) { this.state.next(Object.assign(this.state.value, { sidebarLeftMenu: value })); } setSidebarLeftMenuActiveUrl(value) { this.state.next(Object.assign(this.state.value, { sidebarLeftMenuActiveUrl: value })); } setLayout(value) { this.state.next(Object.assign(this.state.value, { layout: value })); } setSkin(value) { this.state.next(Object.assign(this.state.value, { skin: value })); } setWindowInnerHeight(value) { this.state.next(Object.assign(this.state.value, { windowInnerHeight: value })); } setWindowInnerWidth(value) { this.state.next(Object.assign(this.state.value, { windowInnerWidth: value })); } } class SidebarRightService { get scrollHeight() { return this.elementRef ? this.elementRef.nativeElement.scrollHeight : 0; } } SidebarRightService.decorators = [ { type: Injectable } ]; class HeaderService { get offsetHeight() { return this.elementRef ? this.elementRef.nativeElement.offsetHeight : 0; } } HeaderService.decorators = [ { type: Injectable } ]; class FooterService { get offsetHeight() { return this.elementRef ? this.elementRef.nativeElement.offsetHeight : 0; } } FooterService.decorators = [ { type: Injectable } ]; function throttle(callback, delay) { let timeout = 0; return (...args) => { if (!timeout) { timeout = setTimeout(() => { // @ts-ignore callback.call(this, ...args); timeout = 0; }, delay); } }; } function removeSubscriptions(subscriptions) { if (subscriptions) { subscriptions.forEach((subscription) => { subscription.unsubscribe(); }); } return []; } function removeListeners(listeners = []) { if (listeners) { listeners.forEach((listener) => { listener(); }); } return []; } class ContentComponent { constructor(layoutStore, routingService, titleService, elementRef, changeDetectorRef, sidebarRightService, headerService, footerService, router) { this.layoutStore = layoutStore; this.routingService = routingService; this.titleService = titleService; this.elementRef = elementRef; this.changeDetectorRef = changeDetectorRef; this.sidebarRightService = sidebarRightService; this.headerService = headerService; this.footerService = footerService; this.router = router; this.navigationEnd = false; this.subscriptions = []; } ngOnInit() { this.titleTag = this.titleService.getTitle(); this.subscriptions.push(this.routingService.onChange.subscribe(value => { if (value && value[value.length - 1] && value[value.length - 1].data) { const data = value[value.length - 1].data; this.titleService.setTitle(this.getTitle(data.title) || ''); this.header = data.title; this.description = data.description; } this.changeDetectorRef.markForCheck(); })); this.subscriptions.push(this.router.events.subscribe(routeEvent => { if (routeEvent instanceof NavigationStart) { this.navigationEnd = false; } if (routeEvent instanceof NavigationEnd) { this.navigationEnd = true; this.setContentMinHeight(); } })); this.subscriptions.push(this.layoutStore.sidebarLeftElementHeight.subscribe(value => { this.sidebarLeftHeight = value; this.setContentMinHeight(); })); this.subscriptions.push(this.layoutStore.layout.subscribe(value => { this.layout = value; this.setContentMinHeight(); })); this.subscriptions.push(this.layoutStore.windowInnerHeight.subscribe(value => { this.windowInnerHeight = value; this.setContentMinHeight(); })); this.heightStyle = this.windowInnerHeight; } ngOnDestroy() { this.subscriptions = removeSubscriptions(this.subscriptions); } get scrollHeight() { return this.contentInnerElement.nativeElement.scrollHeight; } getTitle(title) { return title ? `${title} - ${this.titleTag}` : this.titleTag; } setContentMinHeight() { if (this.navigationEnd) { let heightStyle = 0; const headerFooterOffsetHeight = this.headerService.offsetHeight + this.footerService.offsetHeight; if (this.layout === 'fixed' && this.windowInnerHeight) { heightStyle = this.windowInnerHeight - this.footerService.offsetHeight; } else if (this.windowInnerHeight && this.sidebarLeftHeight) { const sidebarRight = this.sidebarRightService.scrollHeight ? this.sidebarRightService.scrollHeight - this.headerService.offsetHeight : 0; heightStyle = Math.max(this.windowInnerHeight - headerFooterOffsetHeight, this.sidebarLeftHeight - this.headerService.offsetHeight, sidebarRight); } if (heightStyle && heightStyle !== this.heightStyle) { if (this.scrollHeight > heightStyle) { heightStyle = 0; } this.heightStyle = heightStyle; this.changeDetectorRef.detectChanges(); } } } } ContentComponent.decorators = [ { type: Component, args: [{ selector: 'mk-layout-content', template: "<div class=\"content-wrapper\" [style.min-height.px]=\"heightStyle\">\n <div #contentInnerElement class=\"content-inner\">\n <ng-content select=\"[mk-layout-content-before-header]\"></ng-content>\n <section *ngIf=\"header || description\" class=\"content-header\">\n <h1>\n {{header}}\n <small *ngIf=\"description\">{{description}}</small>\n </h1>\n <mk-breadcrumbs></mk-breadcrumbs>\n </section>\n <ng-content select=\"[mk-layout-content-after-header]\"></ng-content>\n <section class=\"content\">\n <ng-content></ng-content>\n </section>\n </div>\n</div>\n", changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.content-wrapper{position:relative}"] },] } ]; ContentComponent.ctorParameters = () => [ { type: LayoutStore }, { type: RoutingService }, { type: Title }, { type: ElementRef }, { type: ChangeDetectorRef }, { type: SidebarRightService }, { type: HeaderService }, { type: FooterService }, { type: Router } ]; ContentComponent.propDecorators = { contentInnerElement: [{ type: ViewChild, args: ['contentInnerElement', { static: true },] }] }; class ContentModule { } ContentModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule, RouterModule, BreadcrumbsModule], exports: [ContentComponent], declarations: [ContentComponent] },] } ]; class FooterLeftComponent { } FooterLeftComponent.decorators = [ { type: Component, args: [{ selector: 'mk-layout-footer-left', template: '<ng-template #templateRef><ng-content></ng-content></ng-template>' },] } ]; FooterLeftComponent.propDecorators = { templateRef: [{ type: ViewChild, args: ['templateRef', { static: true },] }] }; class FooterRightComponent { } FooterRightComponent.decorators = [ { type: Component, args: [{ selector: 'mk-layout-footer-right', template: '<ng-template #templateRef><ng-content></ng-content></ng-template>' },] } ]; FooterRightComponent.propDecorators = { templateRef: [{ type: ViewChild, args: ['templateRef', { static: true },] }] }; class FooterComponent { constructor(elementRef, footerService) { this.elementRef = elementRef; this.footerService = footerService; } ngOnInit() { this.footerService.elementRef = this.elementRef; } } FooterComponent.decorators = [ { type: Component, args: [{ selector: 'mk-layout-footer', template: "<footer class=\"main-footer\">\n <div class=\"pull-right hidden-xs\">\n <ng-template *ngIf=\"footerRightComponent\" [ngTemplateOutlet]=\"footerRightComponent.templateRef\"></ng-template>\n </div>\n <ng-template *ngIf=\"footerLeftComponent\" [ngTemplateOutlet]=\"footerLeftComponent.templateRef\"></ng-template>\n</footer>\n", styles: [":host{display:block}"] },] } ]; FooterComponent.ctorParameters = () => [ { type: ElementRef }, { type: FooterService } ]; FooterComponent.propDecorators = { footerLeftComponent: [{ type: ContentChild, args: [FooterLeftComponent,] }], footerRightComponent: [{ type: ContentChild, args: [FooterRightComponent,] }] }; class FooterModule { } FooterModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule], exports: [FooterComponent, FooterLeftComponent, FooterRightComponent], declarations: [FooterComponent, FooterLeftComponent, FooterRightComponent] },] } ]; class HeaderLogoComponent { } HeaderLogoComponent.decorators = [ { type: Component, args: [{ selector: 'mk-layout-header-logo', template: '<ng-template #templateRef><ng-content></ng-content></ng-template>' },] } ]; HeaderLogoComponent.propDecorators = { templateRef: [{ type: ViewChild, args: ['templateRef', { static: true },] }] }; class HeaderLogoMiniComponent { } HeaderLogoMiniComponent.decorators = [ { type: Component, args: [{ selector: 'mk-layout-header-logo-mini', template: '<ng-template #templateRef><ng-content></ng-content></ng-template>' },] } ]; HeaderLogoMiniComponent.propDecorators = { templateRef: [{ type: ViewChild, args: ['templateRef', { static: true },] }] }; class HeaderComponent { constructor(layoutStore, ngZone, renderer2, elementRef, headerService) { this.layoutStore = layoutStore; this.ngZone = ngZone; this.renderer2 = renderer2; this.elementRef = elementRef; this.headerService = headerService; this.isSidebarLeftToggle = true; this.isSidebarRightToggle = true; this.logoLink = '/'; this.listeners = []; this.subscriptions = []; } ngAfterViewInit() { this.headerService.elementRef = this.headerElement; if (this.sidebarLeftToggleElement) { this.subscriptions.push(this.layoutStore.isSidebarLeftCollapsed.subscribe(value => { this.isSidebarLeftCollapsed = value; })); this.ngZone.runOutsideAngular(() => { var _a; this.listeners.push(this.renderer2.listen((_a = this.sidebarLeftToggleElement) === null || _a === void 0 ? void 0 : _a.nativeElement, 'click', event => { event.preventDefault(); this.layoutStore.sidebarLeftCollapsed(!this.isSidebarLeftCollapsed); })); }); } if (this.sidebarRightToggleElement) { this.subscriptions.push(this.layoutStore.isSidebarRightCollapsed.subscribe(value => { this.isSidebarRightCollapsed = value; })); this.ngZone.runOutsideAngular(() => { var _a; this.listeners.push(this.renderer2.listen((_a = this.sidebarRightToggleElement) === null || _a === void 0 ? void 0 : _a.nativeElement, 'click', event => { event.preventDefault(); this.layoutStore.sidebarRightCollapsed(!this.isSidebarRightCollapsed); })); }); } } ngOnDestroy() { this.listeners = removeListeners(this.listeners); this.subscriptions = removeSubscriptions(this.subscriptions); } } HeaderComponent.decorators = [ { type: Component, args: [{ selector: 'mk-layout-header', template: "<header #headerElement class=\"main-header\">\n <a [routerLink]=\"logoLink\" class=\"logo\">\n <span class=\"logo-mini\" *ngIf=\"headerLogoMiniComponent\"><ng-template [ngTemplateOutlet]=\"headerLogoMiniComponent.templateRef\"></ng-template></span>\n <span class=\"logo-lg\" *ngIf=\"headerLogoComponent\"><ng-template [ngTemplateOutlet]=\"headerLogoComponent.templateRef\"></ng-template></span>\n </a>\n <nav class=\"navbar navbar-static-top\">\n <a *ngIf=\"isSidebarLeftToggle\" #sidebarLeftToggleElement href=\"#\" class=\"sidebar-toggle {{sidebarLeftToggleIconClasses ? 'sidebar-toggle-custom-icon' : ''}}\">\n <span class=\"sr-only\">Toggle navigation</span>\n <ng-container *ngIf=\"sidebarLeftToggleIconClasses\">\n <i [class]=\"sidebarLeftToggleIconClasses\"></i>\n </ng-container>\n </a>\n <div *ngIf=\"isSidebarRightToggle\" class=\"sidebar-right-toggle\">\n <a #sidebarRightToggleElement href=\"#\">\n <i [class]=\"sidebarRightToggleIconClasses ? sidebarRightToggleIconClasses : 'fa fa-gears'\"></i>\n </a>\n </div>\n <ng-content></ng-content>\n </nav>\n</header>\n", styles: [":host{display:block}.sidebar-right-toggle{float:right}.sidebar-right-toggle a{cursor:pointer;display:block;line-height:20px;padding:15px}.sidebar-toggle-custom-icon:before{content:\"\"}"] },] } ]; HeaderComponent.ctorParameters = () => [ { type: LayoutStore }, { type: NgZone }, { type: Renderer2 }, { type: ElementRef }, { type: HeaderService } ]; HeaderComponent.propDecorators = { isSidebarLeftToggle: [{ type: Input }], sidebarLeftToggleIconClasses: [{ type: Input }], isSidebarRightToggle: [{ type: Input }], sidebarRightToggleIconClasses: [{ type: Input }], logoLink: [{ type: Input }], headerLogoComponent: [{ type: ContentChild, args: [HeaderLogoComponent,] }], headerLogoMiniComponent: [{ type: ContentChild, args: [HeaderLogoMiniComponent,] }], headerElement: [{ type: ViewChild, args: ['headerElement', { static: true },] }], sidebarLeftToggleElement: [{ type: ViewChild, args: ['sidebarLeftToggleElement',] }], sidebarRightToggleElement: [{ type: ViewChild, args: ['sidebarRightToggleElement',] }] }; class HeaderModule { } HeaderModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule, RouterModule], exports: [HeaderComponent, HeaderLogoComponent, HeaderLogoMiniComponent], declarations: [HeaderComponent, HeaderLogoComponent, HeaderLogoMiniComponent] },] } ]; class CollapseAnimationDirective { constructor(elementRef, ngZone, renderer2) { this.elementRef = elementRef; this.ngZone = ngZone; this.renderer2 = renderer2; this.collapseAnimationDuration = 350; // tslint:disable-next-line:no-output-rename this.startEventEmitter = new EventEmitter(); // tslint:disable-next-line:no-output-rename this.doneEventEmitter = new EventEmitter(); this.firstStart = true; this.isCollapsed = false; this.lastIsCollapsed = false; this.transitioning = false; } set _isCollapsed(value) { this.lastIsCollapsed = this.isCollapsed; this.isCollapsed = value; if (!this.firstStart) { this.emit('start'); if (value) { this.collapse(); } else if (!value) { this.unCollapse(); } } } ngOnInit() { if (this.collapseAnimationDuration && this.collapseAnimationDuration !== 350) { this.renderer2.setStyle(this.elementRef.nativeElement, 'transition-duration', `${this.collapseAnimationDuration}ms`); } if (this.collapseAnimationTiming) { this.renderer2.setStyle(this.elementRef.nativeElement, 'transition-timing-function', this.collapseAnimationTiming); } } ngAfterContentInit() { this.emit('start'); if (this.isCollapsed) { this.renderer2.setStyle(this.elementRef.nativeElement, 'display', 'none'); this.renderer2.addClass(this.elementRef.nativeElement, 'collapsing'); } this.emit('done'); this.firstStart = false; this.subscriptions(); } ngOnDestroy() { if (this.listener) { this.listener(); } } subscriptions() { this.ngZone.runOutsideAngular(() => { this.listener = this.renderer2.listen(this.elementRef.nativeElement, 'transitionend', () => { if (!this.isCollapsed) { this.renderer2.removeClass(this.elementRef.nativeElement, 'un-collapse'); this.renderer2.removeClass(this.elementRef.nativeElement, 'collapsing'); } else { this.renderer2.setStyle(this.elementRef.nativeElement, 'display', 'none'); } requestAnimationFrame(() => { this.renderer2.removeStyle(this.elementRef.nativeElement, 'height'); this.emit('done'); this.transitioning = false; }); }); }); } unCollapse() { this.transitioning = true; this.renderer2.addClass(this.elementRef.nativeElement, 'un-collapse'); this.renderer2.removeStyle(this.elementRef.nativeElement, 'display'); this.renderer2.setStyle(this.elementRef.nativeElement, 'height', `${this.elementRef.nativeElement.scrollHeight}px`); } collapse() { requestAnimationFrame(() => { if (!this.transitioning) { this.renderer2.setStyle(this.elementRef.nativeElement, 'height', `${this.elementRef.nativeElement.offsetHeight}px`); this.renderer2.addClass(this.elementRef.nativeElement, 'collapsing'); } this.transitioning = true; requestAnimationFrame(() => { this.renderer2.setStyle(this.elementRef.nativeElement, 'height', `0px`); }); }); } emit(phaseName) { const event = { element: this.elementRef.nativeElement, fromState: this.lastIsCollapsed === undefined ? 'void' : this.lastIsCollapsed ? '1' : '0', phaseName, toState: this.isCollapsed === undefined ? 'void' : this.isCollapsed ? '1' : '0', totalTime: this.collapseAnimationDuration, triggerName: 'mkCollapseAnimation' }; if (phaseName === 'done') { this.doneEventEmitter.emit(event); } else if (phaseName === 'start') { this.startEventEmitter.emit(event); } } } CollapseAnimationDirective.decorators = [ { type: Directive, args: [{ selector: '[mkCollapseAnimation]' },] } ]; CollapseAnimationDirective.ctorParameters = () => [ { type: ElementRef }, { type: NgZone }, { type: Renderer2 } ]; CollapseAnimationDirective.propDecorators = { collapseAnimationDuration: [{ type: Input }], collapseAnimationTiming: [{ type: Input }], _isCollapsed: [{ type: Input, args: ['mkCollapseAnimation',] }], startEventEmitter: [{ type: Output, args: ['mkCollapseAnimation.start',] }], doneEventEmitter: [{ type: Output, args: ['mkCollapseAnimation.done',] }] }; class AnimationsModule { } AnimationsModule.decorators = [ { type: NgModule, args: [{ exports: [CollapseAnimationDirective], declarations: [CollapseAnimationDirective] },] } ]; class SidebarLeftToggleDirective { constructor(elementRef) { this.elementRef = elementRef; } } SidebarLeftToggleDirective.decorators = [ { type: Directive, args: [{ selector: '[mkMenuToggle]' },] } ]; SidebarLeftToggleDirective.ctorParameters = () => [ { type: ElementRef } ]; SidebarLeftToggleDirective.propDecorators = { item: [{ type: Input, args: ['mkMenuToggle',] }] }; class WrapperService { } WrapperService.decorators = [ { type: Injectable } ]; class SidebarLeftComponent { constructor(changeDetectorRef, layoutStore, ngZone, renderer2, router, routingService, wrapperService, headerService) { this.changeDetectorRef = changeDetectorRef; this.layoutStore = layoutStore; this.ngZone = ngZone; this.renderer2 = renderer2; this.router = router; this.routingService = routingService; this.wrapperService = wrapperService; this.headerService = headerService; this.isSidebarLeftMouseOver = false; this.collapsedItems = []; this.activatedItems = []; this.toggleListeners = []; this.listeners = []; this.itemsByIds = {}; this.runningAnimations = 0; this.subscriptions = []; this.initialized = false; } ngOnInit() { this.subscriptions.push(this.layoutStore.sidebarLeftMenu.subscribe(value => { this.menu = value; this.monkeyPatchMenu(this.menu); if (this.initialized) { this.setMenuListeners(this.activeUrl); this.setSidebarListeners(); this.setMenuTogglesListeners(); } this.initialized = true; })); this.subscriptions.push(this.layoutStore.sidebarLeftMenuActiveUrl.subscribe(value => { this.activeUrl = value; this.setMenuListeners(value); })); this.subscriptions.push(this.routingService.events.subscribe(event => { if (event instanceof NavigationEnd) { this.activeUrl = event.url; this.setMenuListeners(event.url); } })); this.setSidebarListeners(); } ngAfterViewInit() { this.setMenuTogglesListeners(); this.checkMenuWithoutChildren(); } ngOnDestroy() { this.subscriptions = removeSubscriptions(this.subscriptions); this.listeners = removeListeners(this.listeners); this.toggleListeners = removeListeners(this.toggleListeners); } setSidebarListeners() { this.subscriptions.push(this.layoutStore.layout.subscribe((value) => { this.layout = value; this.setSidebarHeight(); })); this.subscriptions.push(this.layoutStore.windowInnerHeight.subscribe(value => { this.windowInnerHeight = value; this.setSidebarHeight(); })); this.subscriptions.push(this.layoutStore.sidebarLeftMenu.subscribe(() => { this.changeDetectorRef.detectChanges(); })); this.ngZone.runOutsideAngular(() => { this.listeners.push(this.renderer2.listen(this.sidebarElement.nativeElement, 'mouseenter', () => { this.layoutStore.sidebarLeftMouseOver(true); })); this.listeners.push(this.renderer2.listen(this.sidebarElement.nativeElement, 'mouseleave', () => { this.layoutStore.sidebarLeftMouseOver(false); })); }); this.subscriptions.push(this.layoutStore.windowInnerWidth.subscribe(value => { this.windowInnerWidth = value; if (!this.isSidebarLeftCollapsed && this.windowInnerWidth && this.windowInnerWidth <= 767) { this.layoutStore.sidebarLeftCollapsed(true); } else if (this.windowInnerWidth && this.windowInnerWidth > 767 && this.isSidebarLeftCollapsed && !this.isSidebarLeftExpandOnOver) { this.layoutStore.sidebarLeftCollapsed(false); } })); this.subscriptions.push(this.layoutStore.isSidebarLeftMouseOver.subscribe((value) => { this.isSidebarLeftMouseOver = value; if (this.isSidebarLeftExpandOnOver) { this.layoutStore.sidebarLeftCollapsed(!value); } })); this.subscriptions.push(this.layoutStore.isSidebarLeftExpandOnOver.subscribe((value) => { this.isSidebarLeftExpandOnOver = value; if (this.windowInnerWidth && this.windowInnerWidth > 767 && this.isSidebarLeftCollapsed !== undefined) { this.layoutStore.sidebarLeftCollapsed(value); } })); this.subscriptions.push(this.layoutStore.isSidebarLeftCollapsed.subscribe((value) => { this.isSidebarLeftCollapsed = value; if (this.windowInnerWidth && this.windowInnerWidth <= 767) { if (value) { this.renderer2.removeClass(this.wrapperService.wrapperElementRef.nativeElement, 'sidebar-open'); } else { this.renderer2.addClass(this.wrapperService.wrapperElementRef.nativeElement, 'sidebar-open'); } } else { if (this.isSidebarLeftExpandOnOver && !this.isSidebarLeftMouseOver && !value) { this.layoutStore.sidebarLeftExpandOnOver(false); } if (value) { this.renderer2.addClass(this.wrapperService.wrapperElementRef.nativeElement, 'sidebar-collapse'); if (this.isSidebarLeftExpandOnOver) { this.renderer2.removeClass(this.wrapperService.wrapperElementRef.nativeElement, 'sidebar-expanded-on-hover'); } } else { this.renderer2.removeClass(this.wrapperService.wrapperElementRef.nativeElement, 'sidebar-collapse'); if (this.isSidebarLeftExpandOnOver) { this.renderer2.addClass(this.wrapperService.wrapperElementRef.nativeElement, 'sidebar-expanded-on-hover'); } } } })); this.subscriptions.push(this.layoutStore.isSidebarLeftMini.subscribe((value) => { if (value) { this.renderer2.addClass(this.wrapperService.wrapperElementRef.nativeElement, 'sidebar-mini'); } else { this.renderer2.removeClass(this.wrapperService.wrapperElementRef.nativeElement, 'sidebar-mini'); } })); } getIconClasses(item) { if (item.iconClasses || item.iconClasses === '') { return item.iconClasses; } else { return 'fa fa-circle-o'; } } visibilityStateStart(event) { this.runningAnimations++; this.ngZone.runOutsideAngular(() => { setTimeout(() => { this.runningAnimations--; if (!this.runningAnimations) { this.layoutStore.setSidebarLeftElementHeight(this.sidebarElement.nativeElement.offsetHeight); } }, event.totalTime); }); } setMenuListeners(url) { if (url === '/') { this.activeItems(url); this.changeDetectorRef.detectChanges(); } else { const primaryOutlet = this.router.parseUrl(url).root.children[PRIMARY_OUTLET]; if (primaryOutlet) { this.activeItems(primaryOutlet.toString()); this.changeDetectorRef.detectChanges(); } } if (this.windowInnerWidth && this.windowInnerWidth <= 767 || this.isSidebarLeftExpandOnOver) { this.layoutStore.sidebarLeftCollapsed(true); } } uncollapseItemParents(item, isActive = false) { if (isActive) { item.isActive = true; this.activatedItems.push(item); } item.isCollapsed = false; this.collapsedItems.push(item); if (item.parentId) { this.uncollapseItemParents(this.itemsByIds[item.parentId], isActive); } } findItemsByUrl(url, items, returnItems = []) { items.forEach((item) => { if (item.route === url) { returnItems.push(item); } else if (item.children) { this.findItemsByUrl(url, item.children, returnItems); } }); return returnItems; } activeItems(url) { if (!this.menu) { return; } this.activatedItems.forEach((item) => { item.isActive = false; }); this.activatedItems = []; this.collapsedItems.forEach((item) => { item.isActive = false; item.isCollapsed = true; }); this.collapsedItems = []; const items = this.findItemsByUrl(url, this.menu); items.forEach(item => { item.isActive = true; this.uncollapseItemParents(item, true); this.activatedItems.push(item); }); } monkeyPatchMenu(items, parentId) { items.forEach((item, index) => { item.id = parentId ? Number(parentId + '' + (index + 1)) : index + 1; if (parentId) { item.parentId = parentId; } if (!item.disableCollapse) { item.isCollapsed = true; } item.isActive = false; if (parentId || item.children) { this.itemsByIds[item.id] = item; } if (item.children) { this.monkeyPatchMenu(item.children, item.id); } }); } setMenuTogglesListeners() { this.toggleListeners = removeListeners(this.toggleListeners); this.ngZone.runOutsideAngular(() => { this.sidebarLeftToggleDirectives.forEach((menuToggle) => { this.toggleListeners.push(this.renderer2.listen(menuToggle.elementRef.nativeElement, 'click', (event) => { event.preventDefault(); if (menuToggle.item.isCollapsed) { this.collapsedItems.forEach((item) => { if (!item.disableCollapse) { item.isCollapsed = true; } }); this.collapsedItems = []; this.uncollapseItemParents(menuToggle.item); } else { menuToggle.item.isCollapsed = !menuToggle.item.isCollapsed; } this.changeDetectorRef.detectChanges(); })); }); }); } checkMenuWithoutChildren() { if (!this.menu) { return; } let menuHaveChildren; this.menu.forEach(item => { if (item.children) { menuHaveChildren = true; } }); if (!menuHaveChildren) { this.ngZone.runOutsideAngular(() => { setTimeout(() => { this.layoutStore.setSidebarLeftElementHeight(this.sidebarElement.nativeElement.offsetHeight); }); }); } } setSidebarHeight() { if (this.layout === 'fixed' && this.windowInnerHeight) { const height = this.windowInnerHeight - this.headerService.offsetHeight; if (height && height !== this.sidebarHeight) { this.sidebarHeight = height; this.sidebarOverflow = 'auto'; this.changeDetectorRef.detectChanges(); } } else if (this.sidebarHeight) { this.sidebarOverflow = this.sidebarHeight = undefined; this.changeDetectorRef.detectChanges(); } } } SidebarLeftComponent.decorators = [ { type: Component, args: [{ selector: 'mk-layout-sidebar-left', template: "<aside class=\"main-sidebar\">\n <section class=\"sidebar\" #sidebarElement [style.height.px]=\"sidebarHeight\" [style.overflow]=\"sidebarOverflow\">\n <ng-content></ng-content>\n \t<ul class=\"sidebar-menu\">\n <ng-container *ngFor=\"let item of menu\">\n <ng-container *ngTemplateOutlet=\"sidebarInner; context: {item: item}\"></ng-container>\n </ng-container>\n \t</ul>\n </section>\n</aside>\n\n<ng-template #sidebarInner let-item=\"item\">\n <li [class.active]=\"item.isActive\" [class.header]=\"item.separator\" [class.menu-open]=\"!item.isCollapsed\">\n <span *ngIf=\"item.separator\">{{item.label}}</span>\n <a *ngIf=\"!item.separator && item.route\" [routerLink]=\"item.route\">\n \t<i [class]=\"getIconClasses(item)\"></i><span>{{item.label}}</span>\n \t<span *ngIf=\"item.children || item.pullRights\" class=\"pull-right-container\">\n \t\t<span *ngFor=\"let rightItem of item.pullRights\" class=\"pull-right {{rightItem.classes}}\">{{rightItem.text}}</span>\n \t <i *ngIf=\"!item.pullRights\" class=\"fa fa-angle-left pull-right\"></i>\n \t</span>\n </a>\n <a *ngIf=\"!item.separator && !item.route\" href=\"#\" [mkMenuToggle]=\"item\">\n \t<i [class]=\"getIconClasses(item)\"></i><span>{{item.label}}</span>\n \t<span *ngIf=\"item.children || item.pullRights\" class=\"pull-right-container\">\n \t\t<span *ngFor=\"let rightItem of item.pullRights\" class=\"pull-right {{rightItem.classes}}\">{{rightItem.text}}</span>\n \t <i *ngIf=\"!item.pullRights\" class=\"fa fa-angle-left pull-right\"></i>\n \t</span>\n </a>\n <ul *ngIf=\"item.children\" [mkCollapseAnimation]=\"item.isCollapsed\" (mkCollapseAnimation.start)=\"visibilityStateStart($event)\" class=\"treeview-menu\">\n <ng-container *ngFor=\"let item of item.children\">\n <ng-container *ngTemplateOutlet=\"sidebarInner; context: {item: item}\"></ng-container>\n </ng-container>\n </ul>\n </li>\n</ng-template>\n", changeDetection: ChangeDetectionStrategy.OnPush, styles: [".treeview-menu.collapse{display:none}.treeview-menu,.treeview-menu.collapse.in{display:block}"] },] } ]; SidebarLeftComponent.ctorParameters = () => [ { type: ChangeDetectorRef }, { type: LayoutStore }, { type: NgZone }, { type: Renderer2 }, { type: Router }, { type: RoutingService }, { type: WrapperService }, { type: HeaderService } ]; SidebarLeftComponent.propDecorators = { sidebarElement: [{ type: ViewChild, args: ['sidebarElement', { static: true },] }], sidebarLeftToggleDirectives: [{ type: ViewChildren, args: [SidebarLeftToggleDirective,] }] }; class SidebarLeftModule { } SidebarLeftModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule, RouterModule, AnimationsModule], exports: [SidebarLeftComponent], declarations: [SidebarLeftToggleDirective, SidebarLeftComponent] },] } ]; class SidebarRightComponent { constructor(elementRef, renderer2, layoutStore, sidebarRightService, wrapperService) { this.elementRef = elementRef; this.renderer2 = renderer2; this.layoutStore = layoutStore; this.sidebarRightService = sidebarRightService; this.wrapperService = wrapperService; this.listeners = []; this.subscriptions = []; } ngOnInit() { this.renderer2.addClass(this.elementRef.nativeElement, 'control-sidebar'); this.subscriptions.push(this.layoutStore.isSidebarRightCollapsed.subscribe(value => { this.isSidebarRightCollapsed = value; if (!value) { this.renderer2.addClass(this.elementRef.nativeElement, 'control-sidebar-open'); if (!this.isSidebarRightOverContent) { this.renderer2.addClass(this.wrapperService.wrapperElementRef.nativeElement, 'control-sidebar-open'); } } else { this.renderer2.removeClass(this.elementRef.nativeElement, 'control-sidebar-open'); if (!this.isSidebarRightOverContent) { this.renderer2.removeClass(this.wrapperService.wrapperElementRef.nativeElement, 'control-sidebar-open'); } } })); this.subscriptions.push(this.layoutStore.isSidebarRightOverContent.subscribe(value => { this.isSidebarRightOverContent = value; if (!this.isSidebarRightCollapsed) { if (value) { this.renderer2.removeClass(this.wrapperService.wrapperElementRef.nativeElement, 'control-sidebar-open'); } else { this.renderer2.addClass(this.wrapperService.wrapperElementRef.nativeElement, 'control-sidebar-open'); } } })); this.subscriptions.push(this.layoutStore.sidebarRightSkin.subscribe((value) => { if (this.skin !== value) { this.renderer2.removeClass(this.elementRef.nativeElement, `control-sidebar-${this.skin}`); } this.skin = value; this.renderer2.addClass(this.elementRef.nativeElement, `control-sidebar-${value}`); })); } ngAfterViewInit() { this.sidebarRightService.elementRef = this.sidebarContentElement; } ngOnDestroy() { this.listeners = removeListeners(this.listeners); this.subscriptions = removeSubscriptions(this.subscriptions); } } SidebarRightComponent.decorators = [ { type: Component, args: [{ selector: 'mk-layout-sidebar-right', template: "<div #sidebarContentElement class=\"control-sidebar-content\">\n <ng-content></ng-content>\n</div>\n<div class=\"control-sidebar-bg\"></div>\n", changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;height:100%}.control-sidebar-bg{z-index:-1}/deep/ .tab-content{padding:10px 15px}"] },] } ]; SidebarRightComponent.ctorParameters = () => [ { type: ElementRef }, { type: Renderer2 }, { type: LayoutStore }, { type: SidebarRightService }, { type: WrapperService } ]; SidebarRightComponent.propDecorators = { sidebarContentElement: [{ type: ViewChild, args: ['sidebarContentElement', { static: true },] }] }; class SidebarRightModule { } SidebarRightModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule], exports: [SidebarRightComponent], declarations: [SidebarRightComponent] },] } ]; class WrapperComponent { constructor(elementRef, renderer2, layoutStore, wrapperService, ngZone) { this.elementRef = elementRef; this.renderer2 = renderer2; this.layoutStore = layoutStore; this.wrapperService = wrapperService; this.ngZone = ngZone; this.listeners = []; this.subscriptions = []; } ngOnInit() { this.layoutStore.setWindowInnerHeight(window.innerHeight); this.layoutStore.setWindowInnerWidth(window.innerWidth); this.wra