Update to new structure
This commit is contained in:
4
src/app/layout/api/menuchangeevent.ts
Normal file
4
src/app/layout/api/menuchangeevent.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface MenuChangeEvent {
|
||||
key: string;
|
||||
routeEvent?: boolean;
|
||||
}
|
||||
5
src/app/layout/app.footer.component.html
Normal file
5
src/app/layout/app.footer.component.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<div class="layout-footer">
|
||||
<img src="assets/layout/images/{{layoutService.config.colorScheme === 'light' ? 'logo-dark' : 'logo-white'}}.svg" alt="Logo" height="20" class="mr-2"/>
|
||||
by
|
||||
<span class="font-medium ml-2">PrimeNG</span>
|
||||
</div>
|
||||
10
src/app/layout/app.footer.component.ts
Normal file
10
src/app/layout/app.footer.component.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { LayoutService } from "./service/app.layout.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-footer',
|
||||
templateUrl: './app.footer.component.html'
|
||||
})
|
||||
export class AppFooterComponent {
|
||||
constructor(public layoutService: LayoutService) { }
|
||||
}
|
||||
14
src/app/layout/app.layout.component.html
Normal file
14
src/app/layout/app.layout.component.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<div class="layout-wrapper" [ngClass]="containerClass">
|
||||
<app-topbar></app-topbar>
|
||||
<div class="layout-sidebar">
|
||||
<app-sidebar></app-sidebar>
|
||||
</div>
|
||||
<div class="layout-main-container">
|
||||
<div class="layout-main">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
<app-footer></app-footer>
|
||||
</div>
|
||||
<app-config></app-config>
|
||||
<div class="layout-mask"></div>
|
||||
</div>
|
||||
97
src/app/layout/app.layout.component.ts
Normal file
97
src/app/layout/app.layout.component.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { Component, OnDestroy, Renderer2, ViewChild } from '@angular/core';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { filter, Subscription } from 'rxjs';
|
||||
import { MenuService } from './app.menu.service';
|
||||
import { LayoutService } from "./service/app.layout.service";
|
||||
import { AppSidebarComponent } from "./app.sidebar.component";
|
||||
import { AppTopBarComponent } from './app.topbar.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-layout',
|
||||
templateUrl: './app.layout.component.html'
|
||||
})
|
||||
export class AppLayoutComponent implements OnDestroy {
|
||||
|
||||
overlayMenuOpenSubscription: Subscription;
|
||||
|
||||
menuOutsideClickListener: any;
|
||||
|
||||
@ViewChild(AppSidebarComponent) appSidebar!: AppSidebarComponent;
|
||||
|
||||
constructor(private menuService: MenuService, public layoutService: LayoutService, public renderer: Renderer2, public router: Router) {
|
||||
this.overlayMenuOpenSubscription = this.layoutService.overlayOpen$.subscribe(() => {
|
||||
if (!this.menuOutsideClickListener) {
|
||||
this.menuOutsideClickListener = this.renderer.listen('document', 'click', event => {
|
||||
const isOutsideClicked = !(this.appSidebar.el.nativeElement.isSameNode(event.target) || this.appSidebar.el.nativeElement.contains(event.target)
|
||||
|| event.target.classList.contains('p-trigger') || event.target.parentNode.classList.contains('p-trigger'));
|
||||
|
||||
if (isOutsideClicked) {
|
||||
this.layoutService.state.profileSidebarVisible = false;
|
||||
this.layoutService.state.overlayMenuActive = false;
|
||||
this.layoutService.state.staticMenuMobileActive = false;
|
||||
this.layoutService.state.menuHoverActive = false;
|
||||
this.menuService.reset();
|
||||
this.menuOutsideClickListener();
|
||||
this.menuOutsideClickListener = null;
|
||||
this.unblockBodyScroll();
|
||||
}
|
||||
else {
|
||||
if (this.layoutService.state.staticMenuMobileActive) {
|
||||
this.blockBodyScroll();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.router.events.pipe(filter(event => event instanceof NavigationEnd))
|
||||
.subscribe(() => {
|
||||
this.unblockBodyScroll();
|
||||
});
|
||||
}
|
||||
|
||||
blockBodyScroll(): void {
|
||||
if (document.body.classList) {
|
||||
document.body.classList.add('blocked-scroll');
|
||||
}
|
||||
else {
|
||||
document.body.className += ' blocked-scroll';
|
||||
}
|
||||
}
|
||||
|
||||
unblockBodyScroll(): void {
|
||||
if (document.body.classList) {
|
||||
document.body.classList.remove('blocked-scroll');
|
||||
}
|
||||
else {
|
||||
document.body.className = document.body.className.replace(new RegExp('(^|\\b)' +
|
||||
'blocked-scroll'.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
|
||||
}
|
||||
}
|
||||
|
||||
get containerClass() {
|
||||
return {
|
||||
'layout-theme-light': this.layoutService.config.colorScheme === 'light',
|
||||
'layout-theme-dark': this.layoutService.config.colorScheme === 'dark',
|
||||
'layout-overlay': this.layoutService.config.menuMode === 'overlay',
|
||||
'layout-static': this.layoutService.config.menuMode === 'static',
|
||||
'layout-slim': this.layoutService.config.menuMode === 'slim',
|
||||
'layout-horizontal': this.layoutService.config.menuMode === 'horizontal',
|
||||
'layout-static-inactive': this.layoutService.state.staticMenuDesktopInactive && this.layoutService.config.menuMode === 'static',
|
||||
'layout-overlay-active': this.layoutService.state.overlayMenuActive,
|
||||
'layout-mobile-active': this.layoutService.state.staticMenuMobileActive,
|
||||
'p-input-filled': this.layoutService.config.inputStyle === 'filled',
|
||||
'p-ripple-disabled': !this.layoutService.config.ripple
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.overlayMenuOpenSubscription) {
|
||||
this.overlayMenuOpenSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
if (this.menuOutsideClickListener) {
|
||||
this.menuOutsideClickListener();
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/app/layout/app.layout.module.ts
Normal file
46
src/app/layout/app.layout.module.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { InputTextModule } from 'primeng/inputtext';
|
||||
import { SidebarModule } from 'primeng/sidebar';
|
||||
import { BadgeModule } from 'primeng/badge';
|
||||
import { RadioButtonModule } from 'primeng/radiobutton';
|
||||
import { InputSwitchModule } from 'primeng/inputswitch';
|
||||
import { RippleModule } from 'primeng/ripple';
|
||||
import { AppMenuComponent } from './app.menu.component';
|
||||
import { AppMenuitemComponent } from './app.menuitem.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AppTopBarComponent } from './app.topbar.component';
|
||||
import { AppFooterComponent } from './app.footer.component';
|
||||
import { AppConfigModule } from './config/config.module';
|
||||
import { AppSidebarComponent } from "./app.sidebar.component";
|
||||
import { AppLayoutComponent } from "./app.layout.component";
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppMenuitemComponent,
|
||||
AppTopBarComponent,
|
||||
AppFooterComponent,
|
||||
AppMenuComponent,
|
||||
AppSidebarComponent,
|
||||
AppLayoutComponent,
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpClientModule,
|
||||
BrowserAnimationsModule,
|
||||
InputTextModule,
|
||||
SidebarModule,
|
||||
BadgeModule,
|
||||
RadioButtonModule,
|
||||
InputSwitchModule,
|
||||
RippleModule,
|
||||
RouterModule,
|
||||
AppConfigModule
|
||||
],
|
||||
exports: [AppLayoutComponent]
|
||||
})
|
||||
export class AppLayoutModule { }
|
||||
11
src/app/layout/app.menu.component.html
Normal file
11
src/app/layout/app.menu.component.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<ul class="layout-menu">
|
||||
<ng-container *ngFor="let item of model; let i = index;">
|
||||
<li app-menuitem *ngIf="!item.separator" [item]="item" [index]="i" [root]="true"></li>
|
||||
<li *ngIf="item.separator" class="menu-separator"></li>
|
||||
</ng-container>
|
||||
<li>
|
||||
<a href="https://www.primefaces.org/primeblocks-ng/#/">
|
||||
<img src="assets/layout/images/{{layoutService.config.colorScheme === 'light' ? 'banner-primeblocks' : 'banner-primeblocks-dark'}}.png" alt="Prime Blocks" class="w-full mt-3"/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
166
src/app/layout/app.menu.component.ts
Normal file
166
src/app/layout/app.menu.component.ts
Normal file
@@ -0,0 +1,166 @@
|
||||
import { OnInit } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
import { LayoutService } from './service/app.layout.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-menu',
|
||||
templateUrl: './app.menu.component.html'
|
||||
})
|
||||
export class AppMenuComponent implements OnInit {
|
||||
|
||||
model: any[] = [];
|
||||
|
||||
constructor(public layoutService: LayoutService) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.model = [
|
||||
{
|
||||
label: 'Home',
|
||||
items: [
|
||||
{ label: 'Dashboard', icon: 'pi pi-fw pi-home', routerLink: ['/'] }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'UI Components',
|
||||
items: [
|
||||
{ label: 'Form Layout', icon: 'pi pi-fw pi-id-card', routerLink: ['/uikit/formlayout'] },
|
||||
{ label: 'Input', icon: 'pi pi-fw pi-check-square', routerLink: ['/uikit/input'] },
|
||||
{ label: 'Float Label', icon: 'pi pi-fw pi-bookmark', routerLink: ['/uikit/floatlabel'] },
|
||||
{ label: 'Invalid State', icon: 'pi pi-fw pi-exclamation-circle', routerLink: ['/uikit/invalidstate'] },
|
||||
{ label: 'Button', icon: 'pi pi-fw pi-mobile', routerLink: ['/uikit/button'], class: 'rotated-icon' },
|
||||
{ label: 'Table', icon: 'pi pi-fw pi-table', routerLink: ['/uikit/table'] },
|
||||
{ label: 'List', icon: 'pi pi-fw pi-list', routerLink: ['/uikit/list'] },
|
||||
{ label: 'Tree', icon: 'pi pi-fw pi-share-alt', routerLink: ['/uikit/tree'] },
|
||||
{ label: 'Panel', icon: 'pi pi-fw pi-tablet', routerLink: ['/uikit/panel'] },
|
||||
{ label: 'Overlay', icon: 'pi pi-fw pi-clone', routerLink: ['/uikit/overlay'] },
|
||||
{ label: 'Media', icon: 'pi pi-fw pi-image', routerLink: ['/uikit/media'] },
|
||||
{ label: 'Menu', icon: 'pi pi-fw pi-bars', routerLink: ['/uikit/menu'], preventExact: true },
|
||||
{ label: 'Message', icon: 'pi pi-fw pi-comment', routerLink: ['/uikit/message'] },
|
||||
{ label: 'File', icon: 'pi pi-fw pi-file', routerLink: ['/uikit/file'] },
|
||||
{ label: 'Chart', icon: 'pi pi-fw pi-chart-bar', routerLink: ['/uikit/charts'] },
|
||||
{ label: 'Misc', icon: 'pi pi-fw pi-circle', routerLink: ['/uikit/misc'] }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Prime Blocks',
|
||||
items: [
|
||||
{ label: 'Free Blocks', icon: 'pi pi-fw pi-eye', routerLink: ['/blocks'], badge: 'NEW' },
|
||||
{ label: 'All Blocks', icon: 'pi pi-fw pi-globe', url: ['https://www.primefaces.org/primeblocks-ng'], target: '_blank' },
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Utilities',
|
||||
items: [
|
||||
{ label: 'PrimeIcons', icon: 'pi pi-fw pi-prime', routerLink: ['/utilities/icons'] },
|
||||
{ label: 'PrimeFlex', icon: 'pi pi-fw pi-desktop', url: ['https://www.primefaces.org/primeflex/'], target: '_blank' },
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Pages',
|
||||
icon: 'pi pi-fw pi-briefcase',
|
||||
routerLink: ['/pages'],
|
||||
items: [
|
||||
{
|
||||
label: 'Landing',
|
||||
icon: 'pi pi-fw pi-globe',
|
||||
routerLink: ['/landing']
|
||||
},
|
||||
{
|
||||
label: 'Auth',
|
||||
icon: 'pi pi-fw pi-user',
|
||||
items: [
|
||||
{
|
||||
label: 'Login',
|
||||
icon: 'pi pi-fw pi-sign-in',
|
||||
routerLink: ['/auth/login']
|
||||
},
|
||||
{
|
||||
label: 'Error',
|
||||
icon: 'pi pi-fw pi-times-circle',
|
||||
routerLink: ['/auth/error']
|
||||
},
|
||||
{
|
||||
label: 'Access Denied',
|
||||
icon: 'pi pi-fw pi-lock',
|
||||
routerLink: ['/auth/access']
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Crud',
|
||||
icon: 'pi pi-fw pi-pencil',
|
||||
routerLink: ['/pages/crud']
|
||||
},
|
||||
{
|
||||
label: 'Timeline',
|
||||
icon: 'pi pi-fw pi-calendar',
|
||||
routerLink: ['/pages/timeline']
|
||||
},
|
||||
{
|
||||
label: 'Not Found',
|
||||
icon: 'pi pi-fw pi-exclamation-circle',
|
||||
routerLink: ['/pages/notfound']
|
||||
},
|
||||
{
|
||||
label: 'Empty',
|
||||
icon: 'pi pi-fw pi-circle-off',
|
||||
routerLink: ['/pages/empty']
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Hierarchy',
|
||||
items: [
|
||||
{
|
||||
label: 'Submenu 1', icon: 'pi pi-fw pi-bookmark',
|
||||
items: [
|
||||
{
|
||||
label: 'Submenu 1.1', icon: 'pi pi-fw pi-bookmark',
|
||||
items: [
|
||||
{ label: 'Submenu 1.1.1', icon: 'pi pi-fw pi-bookmark' },
|
||||
{ label: 'Submenu 1.1.2', icon: 'pi pi-fw pi-bookmark' },
|
||||
{ label: 'Submenu 1.1.3', icon: 'pi pi-fw pi-bookmark' },
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Submenu 1.2', icon: 'pi pi-fw pi-bookmark',
|
||||
items: [
|
||||
{ label: 'Submenu 1.2.1', icon: 'pi pi-fw pi-bookmark' }
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Submenu 2', icon: 'pi pi-fw pi-bookmark',
|
||||
items: [
|
||||
{
|
||||
label: 'Submenu 2.1', icon: 'pi pi-fw pi-bookmark',
|
||||
items: [
|
||||
{ label: 'Submenu 2.1.1', icon: 'pi pi-fw pi-bookmark' },
|
||||
{ label: 'Submenu 2.1.2', icon: 'pi pi-fw pi-bookmark' },
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Submenu 2.2', icon: 'pi pi-fw pi-bookmark',
|
||||
items: [
|
||||
{ label: 'Submenu 2.2.1', icon: 'pi pi-fw pi-bookmark' },
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Get Started',
|
||||
items: [
|
||||
{
|
||||
label: 'Documentation', icon: 'pi pi-fw pi-question', routerLink: ['/documentation']
|
||||
},
|
||||
{
|
||||
label: 'View Source', icon: 'pi pi-fw pi-search', url: ['https://github.com/primefaces/sakai-ng'], target: '_blank'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
23
src/app/layout/app.menu.service.ts
Normal file
23
src/app/layout/app.menu.service.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { MenuChangeEvent } from './api/menuchangeevent';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MenuService {
|
||||
|
||||
private menuSource = new Subject<MenuChangeEvent>();
|
||||
private resetSource = new Subject();
|
||||
|
||||
menuSource$ = this.menuSource.asObservable();
|
||||
resetSource$ = this.resetSource.asObservable();
|
||||
|
||||
onMenuStateChange(event: MenuChangeEvent) {
|
||||
this.menuSource.next(event);
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.resetSource.next(true);
|
||||
}
|
||||
}
|
||||
166
src/app/layout/app.menuitem.component.ts
Normal file
166
src/app/layout/app.menuitem.component.ts
Normal file
@@ -0,0 +1,166 @@
|
||||
import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { MenuService } from './app.menu.service';
|
||||
import { LayoutService } from './service/app.layout.service';
|
||||
|
||||
@Component({
|
||||
/* tslint:disable:component-selector */
|
||||
selector: '[app-menuitem]',
|
||||
/* tslint:enable:component-selector */
|
||||
template: `
|
||||
<ng-container>
|
||||
<div *ngIf="root && item.visible !== false" class="layout-menuitem-root-text">{{item.label}}</div>
|
||||
<a *ngIf="(!item.routerLink || item.items) && item.visible !== false" [attr.href]="item.url" (click)="itemClick($event)"
|
||||
[ngClass]="item.class" [attr.target]="item.target" tabindex="0" pRipple>
|
||||
<i [ngClass]="item.icon" class="layout-menuitem-icon"></i>
|
||||
<span class="layout-menuitem-text">{{item.label}}</span>
|
||||
<i class="pi pi-fw pi-angle-down layout-submenu-toggler" *ngIf="item.items"></i>
|
||||
</a>
|
||||
<a *ngIf="(item.routerLink && !item.items) && item.visible !== false" (click)="itemClick($event)" [ngClass]="item.class"
|
||||
[routerLink]="item.routerLink" routerLinkActive="active-route" [routerLinkActiveOptions]="item.routerLinkOptions||{exact: true}"
|
||||
[fragment]="item.fragment" [queryParamsHandling]="item.queryParamsHandling" [preserveFragment]="item.preserveFragment"
|
||||
[skipLocationChange]="item.skipLocationChange" [replaceUrl]="item.replaceUrl" [state]="item.state" [queryParams]="item.queryParams"
|
||||
[attr.target]="item.target" tabindex="0" pRipple>
|
||||
<i [ngClass]="item.icon" class="layout-menuitem-icon"></i>
|
||||
<span class="layout-menuitem-text">{{item.label}}</span>
|
||||
<i class="pi pi-fw pi-angle-down layout-submenu-toggler" *ngIf="item.items"></i>
|
||||
</a>
|
||||
|
||||
<ul *ngIf="item.items && item.visible !== false" [@children]="submenuAnimation">
|
||||
<ng-template ngFor let-child let-i="index" [ngForOf]="item.items">
|
||||
<li app-menuitem [item]="child" [index]="i" [parentKey]="key" [class]="child.badgeClass"></li>
|
||||
</ng-template>
|
||||
</ul>
|
||||
</ng-container>
|
||||
`,
|
||||
host: {
|
||||
'[class.layout-root-menuitem]': 'root',
|
||||
'[class.active-menuitem]': 'active'
|
||||
},
|
||||
animations: [
|
||||
trigger('children', [
|
||||
state('collapsed', style({
|
||||
height: '0'
|
||||
})),
|
||||
state('expanded', style({
|
||||
height: '*'
|
||||
})),
|
||||
state('hidden', style({
|
||||
display: 'none'
|
||||
})),
|
||||
state('visible', style({
|
||||
display: 'block'
|
||||
})),
|
||||
transition('collapsed <=> expanded', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
|
||||
])
|
||||
]
|
||||
})
|
||||
export class AppMenuitemComponent implements OnInit, OnDestroy {
|
||||
|
||||
@Input() item: any;
|
||||
|
||||
@Input() index!: number;
|
||||
|
||||
@Input() root!: boolean;
|
||||
|
||||
@Input() parentKey!: string;
|
||||
|
||||
active = false;
|
||||
|
||||
menuSourceSubscription: Subscription;
|
||||
|
||||
menuResetSubscription: Subscription;
|
||||
|
||||
key: string = "";
|
||||
|
||||
constructor(public layoutService: LayoutService, private cd: ChangeDetectorRef, public router: Router, private menuService: MenuService) {
|
||||
this.menuSourceSubscription = this.menuService.menuSource$.subscribe(value => {
|
||||
Promise.resolve(null).then(() => {
|
||||
if (value.routeEvent) {
|
||||
this.active = (value.key === this.key || value.key.startsWith(this.key + '-')) ? true : false;
|
||||
}
|
||||
else {
|
||||
if (value.key !== this.key && !value.key.startsWith(this.key + '-')) {
|
||||
this.active = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.menuResetSubscription = this.menuService.resetSource$.subscribe(() => {
|
||||
this.active = false;
|
||||
});
|
||||
|
||||
this.router.events.pipe(filter(event => event instanceof NavigationEnd))
|
||||
.subscribe(params => {
|
||||
if (this.item.routerLink) {
|
||||
this.updateActiveStateFromRoute();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.key = this.parentKey ? this.parentKey + '-' + this.index : String(this.index);
|
||||
|
||||
if (this.item.routerLink) {
|
||||
this.updateActiveStateFromRoute();
|
||||
}
|
||||
}
|
||||
|
||||
updateActiveStateFromRoute() {
|
||||
let activeRoute = this.router.isActive(this.item.routerLink[0], { paths: 'exact', queryParams: 'ignored', matrixParams: 'ignored', fragment: 'ignored' });
|
||||
|
||||
if (activeRoute) {
|
||||
this.menuService.onMenuStateChange({ key: this.key, routeEvent: true });
|
||||
}
|
||||
}
|
||||
|
||||
itemClick(event: Event) {
|
||||
// avoid processing disabled items
|
||||
if (this.item.disabled) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
// execute command
|
||||
if (this.item.command) {
|
||||
this.item.command({ originalEvent: event, item: this.item });
|
||||
}
|
||||
|
||||
// toggle active state
|
||||
if (this.item.items) {
|
||||
this.active = !this.active;
|
||||
|
||||
if (this.root && this.active) {
|
||||
this.layoutService.onOverlaySubmenuOpen();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.layoutService.isMobile()) {
|
||||
this.layoutService.state.staticMenuMobileActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
this.menuService.onMenuStateChange({ key: this.key });
|
||||
}
|
||||
|
||||
get submenuAnimation() {
|
||||
if (this.layoutService.isDesktop() && (this.layoutService.isHorizontal() || this.layoutService.isSlim()))
|
||||
return this.active ? 'visible' : 'hidden';
|
||||
else
|
||||
return this.root ? 'expanded' : (this.active ? 'expanded' : 'collapsed');
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.menuSourceSubscription) {
|
||||
this.menuSourceSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
if (this.menuResetSubscription) {
|
||||
this.menuResetSubscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/app/layout/app.sidebar.component.html
Normal file
1
src/app/layout/app.sidebar.component.html
Normal file
@@ -0,0 +1 @@
|
||||
<app-menu></app-menu>
|
||||
11
src/app/layout/app.sidebar.component.ts
Normal file
11
src/app/layout/app.sidebar.component.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Component, ElementRef } from '@angular/core';
|
||||
import { LayoutService } from "./service/app.layout.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-sidebar',
|
||||
templateUrl: './app.sidebar.component.html'
|
||||
})
|
||||
export class AppSidebarComponent {
|
||||
constructor(public layoutService: LayoutService, public el: ElementRef) { }
|
||||
}
|
||||
|
||||
31
src/app/layout/app.topbar.component.html
Normal file
31
src/app/layout/app.topbar.component.html
Normal file
@@ -0,0 +1,31 @@
|
||||
<div class="layout-topbar">
|
||||
<a class="layout-topbar-logo" routerLink="">
|
||||
<img src="assets/layout/images/{{layoutService.config.colorScheme === 'light' ? 'logo-dark' : 'logo-white'}}.svg" alt="logo">
|
||||
<span>SAKAI</span>
|
||||
</a>
|
||||
|
||||
<button class="p-link layout-menu-button layout-topbar-button p-trigger" (click)="layoutService.onMenuToggle()">
|
||||
<i class="pi pi-bars"></i>
|
||||
</button>
|
||||
|
||||
<button class="p-link layout-topbar-menu-button layout-topbar-button p-trigger" (click)="layoutService.showProfileSidebar()">
|
||||
<i class="pi pi-ellipsis-v"></i>
|
||||
</button>
|
||||
|
||||
<div class="layout-topbar-menu" [ngClass]="{'layout-topbar-menu-mobile-active': layoutService.state.profileSidebarVisible}">
|
||||
<button class="p-link layout-topbar-button">
|
||||
<i class="pi pi-calendar"></i>
|
||||
<span>Calendar</span>
|
||||
</button>
|
||||
|
||||
<button class="p-link layout-topbar-button">
|
||||
<i class="pi pi-cog"></i>
|
||||
<span>Settings</span>
|
||||
</button>
|
||||
|
||||
<button class="p-link layout-topbar-button">
|
||||
<i class="pi pi-user"></i>
|
||||
<span>Profile</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
14
src/app/layout/app.topbar.component.ts
Normal file
14
src/app/layout/app.topbar.component.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MenuItem } from 'primeng/api';
|
||||
import { LayoutService } from "./service/app.layout.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-topbar',
|
||||
templateUrl: './app.topbar.component.html'
|
||||
})
|
||||
export class AppTopBarComponent {
|
||||
|
||||
items!: MenuItem[];
|
||||
|
||||
constructor(public layoutService: LayoutService) { }
|
||||
}
|
||||
242
src/app/layout/config/app.config.component.html
Normal file
242
src/app/layout/config/app.config.component.html
Normal file
@@ -0,0 +1,242 @@
|
||||
<button class="layout-config-button p-link" type="button" (click)="onConfigButtonClick()">
|
||||
<i class="pi pi-cog"></i>
|
||||
</button>
|
||||
|
||||
<p-sidebar [(visible)]="visible" position="right" [transitionOptions]="'.3s cubic-bezier(0, 0, 0.2, 1)'" styleClass="layout-config-sidebar w-20rem">
|
||||
<h5>Scale</h5>
|
||||
<div class="flex align-items-center">
|
||||
<button icon="pi pi-minus" type="button" pButton (click)="decrementScale()" class="p-button-text p-button-rounded w-2rem h-2rem mr-2" [disabled]="scale === scales[0]"></button>
|
||||
<div class="flex gap-2 align-items-center">
|
||||
<i class="pi pi-circle-fill text-300" *ngFor="let s of scales" [ngClass]="{'text-primary-500': s === scale}"></i>
|
||||
</div>
|
||||
<button icon="pi pi-plus" type="button" pButton (click)="incrementScale()" class="p-button-text p-button-rounded w-2rem h-2rem ml-2" [disabled]="scale === scales[scales.length - 1]"></button>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="!minimal">
|
||||
<h5>Menu Type</h5>
|
||||
<div class="field-radiobutton">
|
||||
<p-radioButton name="menuMode" value="static" [(ngModel)]="menuMode" inputId="mode1"></p-radioButton>
|
||||
<label for="mode1">Static</label>
|
||||
</div>
|
||||
<div class="field-radiobutton">
|
||||
<p-radioButton name="menuMode" value="overlay" [(ngModel)]="menuMode" inputId="mode2"></p-radioButton>
|
||||
<label for="mode2">Overlay</label>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="!minimal">
|
||||
<h5>Input Style</h5>
|
||||
<div class="flex">
|
||||
<div class="field-radiobutton flex-1">
|
||||
<p-radioButton name="inputStyle" value="outlined" [(ngModel)]="inputStyle" inputId="outlined_input"></p-radioButton>
|
||||
<label for="outlined_input">Outlined</label>
|
||||
</div>
|
||||
<div class="field-radiobutton flex-1">
|
||||
<p-radioButton name="inputStyle" value="filled" [(ngModel)]="inputStyle" inputId="filled_input"></p-radioButton>
|
||||
<label for="filled_input">Filled</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5>Ripple Effect</h5>
|
||||
<p-inputSwitch [(ngModel)]="ripple"></p-inputSwitch>
|
||||
</ng-container>
|
||||
|
||||
|
||||
<h5>Bootstrap</h5>
|
||||
<div class="grid">
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('bootstrap4-light-blue', 'light')">
|
||||
<img src="assets/layout/images/themes/bootstrap4-light-blue.svg" class="w-2rem h-2rem" alt="Bootstrap Light Blue">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('bootstrap4-light-purple', 'light')">
|
||||
<img src="assets/layout/images/themes/bootstrap4-light-purple.svg" class="w-2rem h-2rem" alt="Bootstrap Light Purple">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('bootstrap4-dark-blue', 'dark')">
|
||||
<img src="assets/layout/images/themes/bootstrap4-dark-blue.svg" class="w-2rem h-2rem" alt="Bootstrap Dark Blue">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('bootstrap4-dark-purple', 'dark')">
|
||||
<img src="assets/layout/images/themes/bootstrap4-dark-purple.svg" class="w-2rem h-2rem" alt="Bootstrap Dark Purple">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5>Material Design</h5>
|
||||
<div class="grid">
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('md-light-indigo', 'light')">
|
||||
<img src="assets/layout/images/themes/md-light-indigo.svg" class="w-2rem h-2rem" alt="Material Light Indigo">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('md-light-deeppurple', 'light')">
|
||||
<img src="assets/layout/images/themes/md-light-deeppurple.svg" class="w-2rem h-2rem" alt="Material Light DeepPurple">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('md-dark-indigo', 'dark')">
|
||||
<img src="assets/layout/images/themes/md-dark-indigo.svg" class="w-2rem h-2rem" alt="Material Dark Indigo">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('md-dark-deeppurple', 'dark')">
|
||||
<img src="assets/layout/images/themes/md-dark-deeppurple.svg" class="w-2rem h-2rem" alt="Material Dark DeepPurple">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5>Material Design Compact</h5>
|
||||
<div class="grid">
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('mdc-light-indigo', 'light')">
|
||||
<img src="assets/layout/images/themes/md-light-indigo.svg" class="w-2rem h-2rem" alt="Material Light Indigo">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('mdc-light-deeppurple', 'light')">
|
||||
<img src="assets/layout/images/themes/md-light-deeppurple.svg" class="w-2rem h-2rem" alt="Material Light Deep Purple">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('mdc-dark-indigo', 'dark')">
|
||||
<img src="assets/layout/images/themes/md-dark-indigo.svg" class="w-2rem h-2rem" alt="Material Dark Indigo">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('mdc-dark-deeppurple', 'dark')">
|
||||
<img src="assets/layout/images/themes/md-dark-deeppurple.svg" class="w-2rem h-2rem" alt="Material Dark Deep Purple">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5>Tailwind</h5>
|
||||
<div class="grid">
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('tailwind-light', 'light')">
|
||||
<img src="assets/layout/images/themes/tailwind-light.png" class="w-2rem h-2rem" alt="Tailwind Light">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5>Fluent UI</h5>
|
||||
<div class="grid">
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('fluent-light', 'light')">
|
||||
<img src="assets/layout/images/themes/fluent-light.png" class="w-2rem h-2rem" alt="Fluent Light">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5>PrimeOne Design - 2022</h5>
|
||||
<div class="grid">
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('lara-light-indigo', 'light')">
|
||||
<img src="assets/layout/images/themes/lara-light-indigo.png" class="w-2rem h-2rem" alt="Lara Light Indigo">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('lara-light-blue', 'light')">
|
||||
<img src="assets/layout/images/themes/lara-light-blue.png" class="w-2rem h-2rem" alt="Lara Light Blue">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('lara-light-purple', 'light')">
|
||||
<img src="assets/layout/images/themes/lara-light-purple.png" class="w-2rem h-2rem" alt="Lara Light Purple">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('lara-light-teal', 'light')">
|
||||
<img src="assets/layout/images/themes/lara-light-teal.png" class="w-2rem h-2rem" alt="Lara Light Teal">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('lara-dark-indigo', 'dark')">
|
||||
<img src="assets/layout/images/themes/lara-dark-indigo.png" class="w-2rem h-2rem" alt="Lara Dark Indigo">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('lara-dark-blue', 'dark')">
|
||||
<img src="assets/layout/images/themes/lara-dark-blue.png" class="w-2rem h-2rem" alt="Lara Dark Blue">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('lara-dark-purple', 'dark')">
|
||||
<img src="assets/layout/images/themes/lara-dark-purple.png" class="w-2rem h-2rem" alt="Lara Dark Purple">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('lara-dark-teal', 'dark')">
|
||||
<img src="assets/layout/images/themes/lara-dark-teal.png" class="w-2rem h-2rem" alt="Lara Dark Teal">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5>PrimeOne Design - 2021</h5>
|
||||
<div class="grid">
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('saga-blue', 'light')">
|
||||
<img src="assets/layout/images/themes/saga-blue.png" class="w-2rem h-2rem" alt="Saga Blue">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('saga-green', 'light')">
|
||||
<img src="assets/layout/images/themes/saga-green.png" class="w-2rem h-2rem" alt="Saga Green">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('saga-orange', 'light')">
|
||||
<img src="assets/layout/images/themes/saga-orange.png" class="w-2rem h-2rem" alt="Saga Orange">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('saga-purple', 'light')">
|
||||
<img src="assets/layout/images/themes/saga-purple.png" class="w-2rem h-2rem" alt="Saga Purple">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('vela-blue', 'dark')">
|
||||
<img src="assets/layout/images/themes/vela-blue.png" class="w-2rem h-2rem" alt="Vela Blue">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('vela-green', 'dark')">
|
||||
<img src="assets/layout/images/themes/vela-green.png" class="w-2rem h-2rem" alt="Vela Green">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('vela-orange', 'dark')">
|
||||
<img src="assets/layout/images/themes/vela-orange.png" class="w-2rem h-2rem" alt="Vela Orange">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('vela-purple', 'dark')">
|
||||
<img src="assets/layout/images/themes/vela-purple.png" class="w-2rem h-2rem" alt="Vela Purple">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('arya-blue', 'dark')">
|
||||
<img src="assets/layout/images/themes/arya-blue.png" class="w-2rem h-2rem" alt="Arya Blue">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('arya-green', 'dark')">
|
||||
<img src="assets/layout/images/themes/arya-green.png" class="w-2rem h-2rem" alt="Arya Green">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('arya-orange', 'dark')">
|
||||
<img src="assets/layout/images/themes/arya-orange.png" class="w-2rem h-2rem" alt="Arya Orange">
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button class="p-link w-2rem h-2rem" (click)="changeTheme('arya-purple', 'dark')">
|
||||
<img src="assets/layout/images/themes/arya-purple.png" class="w-2rem h-2rem" alt="Arya Purple">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</p-sidebar>
|
||||
105
src/app/layout/config/app.config.component.ts
Normal file
105
src/app/layout/config/app.config.component.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { LayoutService } from "../service/app.layout.service";
|
||||
import { MenuService } from "../app.menu.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-config',
|
||||
templateUrl: './app.config.component.html'
|
||||
})
|
||||
export class AppConfigComponent {
|
||||
|
||||
@Input() minimal: boolean = false;
|
||||
|
||||
scales: number[] = [12, 13, 14, 15, 16];
|
||||
|
||||
constructor(public layoutService: LayoutService, public menuService: MenuService) { }
|
||||
|
||||
get visible(): boolean {
|
||||
return this.layoutService.state.configSidebarVisible;
|
||||
}
|
||||
|
||||
set visible(_val: boolean) {
|
||||
this.layoutService.state.configSidebarVisible = _val;
|
||||
}
|
||||
|
||||
get scale(): number {
|
||||
return this.layoutService.config.scale;
|
||||
}
|
||||
|
||||
set scale(_val: number) {
|
||||
this.layoutService.config.scale = _val;
|
||||
}
|
||||
|
||||
get menuMode(): string {
|
||||
return this.layoutService.config.menuMode;
|
||||
}
|
||||
|
||||
set menuMode(_val: string) {
|
||||
this.layoutService.config.menuMode = _val;
|
||||
if (this.layoutService.isSlim() || this.layoutService.isHorizontal()) {
|
||||
this.menuService.reset();
|
||||
}
|
||||
}
|
||||
|
||||
get inputStyle(): string {
|
||||
return this.layoutService.config.inputStyle;
|
||||
}
|
||||
|
||||
set inputStyle(_val: string) {
|
||||
this.layoutService.config.inputStyle = _val;
|
||||
}
|
||||
|
||||
get ripple(): boolean {
|
||||
return this.layoutService.config.ripple;
|
||||
}
|
||||
|
||||
set ripple(_val: boolean) {
|
||||
this.layoutService.config.ripple = _val;
|
||||
}
|
||||
|
||||
onConfigButtonClick() {
|
||||
this.layoutService.showConfigSidebar();
|
||||
}
|
||||
|
||||
changeTheme(theme: string, colorScheme: string) {
|
||||
const themeLink = <HTMLLinkElement>document.getElementById('theme-css');
|
||||
const newHref = themeLink.getAttribute('href')!.replace(this.layoutService.config.theme, theme);
|
||||
this.layoutService.config.colorScheme
|
||||
this.replaceThemeLink(newHref, () => {
|
||||
this.layoutService.config.theme = theme;
|
||||
this.layoutService.config.colorScheme = colorScheme;
|
||||
this.layoutService.onConfigUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
replaceThemeLink(href: string, onComplete: Function) {
|
||||
const id = 'theme-css';
|
||||
const themeLink = <HTMLLinkElement>document.getElementById('theme-css');
|
||||
const cloneLinkElement = <HTMLLinkElement>themeLink.cloneNode(true);
|
||||
|
||||
cloneLinkElement.setAttribute('href', href);
|
||||
cloneLinkElement.setAttribute('id', id + '-clone');
|
||||
|
||||
themeLink.parentNode!.insertBefore(cloneLinkElement, themeLink.nextSibling);
|
||||
|
||||
cloneLinkElement.addEventListener('load', () => {
|
||||
themeLink.remove();
|
||||
cloneLinkElement.setAttribute('id', id);
|
||||
onComplete();
|
||||
});
|
||||
}
|
||||
|
||||
decrementScale() {
|
||||
this.scale--;
|
||||
this.applyScale();
|
||||
}
|
||||
|
||||
incrementScale() {
|
||||
this.scale++;
|
||||
this.applyScale();
|
||||
}
|
||||
|
||||
applyScale() {
|
||||
document.documentElement.style.fontSize = this.scale + 'px';
|
||||
}
|
||||
}
|
||||
26
src/app/layout/config/config.module.ts
Normal file
26
src/app/layout/config/config.module.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { SidebarModule } from 'primeng/sidebar';
|
||||
import { RadioButtonModule } from 'primeng/radiobutton';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import { InputSwitchModule } from 'primeng/inputswitch';
|
||||
import { AppConfigComponent } from './app.config.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
SidebarModule,
|
||||
RadioButtonModule,
|
||||
ButtonModule,
|
||||
InputSwitchModule
|
||||
],
|
||||
declarations: [
|
||||
AppConfigComponent
|
||||
],
|
||||
exports: [
|
||||
AppConfigComponent
|
||||
]
|
||||
})
|
||||
export class AppConfigModule { }
|
||||
112
src/app/layout/service/app.layout.service.ts
Normal file
112
src/app/layout/service/app.layout.service.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
export interface AppConfig {
|
||||
inputStyle: string;
|
||||
colorScheme: string;
|
||||
theme: string;
|
||||
ripple: boolean;
|
||||
menuMode: string;
|
||||
scale: number;
|
||||
}
|
||||
|
||||
interface LayoutState {
|
||||
staticMenuDesktopInactive: boolean;
|
||||
overlayMenuActive: boolean;
|
||||
profileSidebarVisible: boolean;
|
||||
configSidebarVisible: boolean;
|
||||
staticMenuMobileActive: boolean;
|
||||
menuHoverActive: boolean;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class LayoutService {
|
||||
|
||||
config: AppConfig = {
|
||||
ripple: false,
|
||||
inputStyle: 'outlined',
|
||||
menuMode: 'static',
|
||||
colorScheme: 'light',
|
||||
theme: 'lara-light-indigo',
|
||||
scale: 14,
|
||||
};
|
||||
|
||||
state: LayoutState = {
|
||||
staticMenuDesktopInactive: false,
|
||||
overlayMenuActive: false,
|
||||
profileSidebarVisible: false,
|
||||
configSidebarVisible: false,
|
||||
staticMenuMobileActive: false,
|
||||
menuHoverActive: false
|
||||
};
|
||||
|
||||
private configUpdate = new Subject<AppConfig>();
|
||||
|
||||
private overlayOpen = new Subject<any>();
|
||||
|
||||
configUpdate$ = this.configUpdate.asObservable();
|
||||
|
||||
overlayOpen$ = this.overlayOpen.asObservable();
|
||||
|
||||
onMenuToggle() {
|
||||
if (this.isOverlay()) {
|
||||
this.state.overlayMenuActive = !this.state.overlayMenuActive;
|
||||
if (this.state.overlayMenuActive) {
|
||||
this.overlayOpen.next(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isDesktop()) {
|
||||
this.state.staticMenuDesktopInactive = !this.state.staticMenuDesktopInactive;
|
||||
}
|
||||
else {
|
||||
this.state.staticMenuMobileActive = !this.state.staticMenuMobileActive;
|
||||
|
||||
if (this.state.staticMenuMobileActive) {
|
||||
this.overlayOpen.next(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onOverlaySubmenuOpen() {
|
||||
this.overlayOpen.next(null);
|
||||
}
|
||||
|
||||
showProfileSidebar() {
|
||||
this.state.profileSidebarVisible = !this.state.profileSidebarVisible;
|
||||
if (this.state.profileSidebarVisible) {
|
||||
this.overlayOpen.next(null);
|
||||
}
|
||||
}
|
||||
|
||||
showConfigSidebar() {
|
||||
this.state.configSidebarVisible = true;
|
||||
}
|
||||
|
||||
isOverlay() {
|
||||
return this.config.menuMode === 'overlay';
|
||||
}
|
||||
|
||||
isDesktop() {
|
||||
return window.innerWidth > 991;
|
||||
}
|
||||
|
||||
isSlim() {
|
||||
return this.config.menuMode === 'slim';
|
||||
}
|
||||
|
||||
isHorizontal() {
|
||||
return this.config.menuMode === 'horizontal';
|
||||
}
|
||||
|
||||
isMobile() {
|
||||
return !this.isDesktop();
|
||||
}
|
||||
|
||||
onConfigUpdate() {
|
||||
this.configUpdate.next(this.config);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user