first commit

This commit is contained in:
2024-04-19 12:53:45 +07:00
commit 71a3a661dc
1943 changed files with 246917 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-block-temp',
styles: [`
:host {
text-align: center;
}
`],
template: `
<div class="block-ui-template">
<i class="feather ft-refresh-cw icon-spin font-medium-2" aria-hidden="true"></i>
<div><strong>{{message}}</strong></div>
</div>
`
})
export class BlockTemplateComponent {
message: any;
}

View File

@@ -0,0 +1,20 @@
.dropdown-menu-right {
right: 0;
left: auto !important;
}
.dropdown-menu.arrow:before {
left: 70px !important;
border-bottom-color: #ffffff;
}
.dropdown-menu.arrow:after {
top: 0px;
}
@media only screen and (max-width:767px) {
._dropdown_mob {
margin-left: 150px !important;
transform: translate(40px, 40px) !important;
}
}

View File

@@ -0,0 +1,27 @@
<div class="row">
<div class="content-header-left col-md-6 col-12 mb-2 breadcrumb-new" *ngIf="breadcrumb">
<h3 class="content-header-title mb-0 d-inline-block">{{breadcrumb.mainlabel}}</h3>
<div class="row breadcrumbs-top d-inline-block">
<div class="breadcrumb-wrapper col-12">
<ol class="breadcrumb">
<li class="breadcrumb-item" *ngFor="let link of breadcrumb.links">
<a *ngIf="link.isLink" routerLink="{{link.link}}">{{link.name}}</a>
<span *ngIf="!link.isLink">{{link.name}}</span>
</li>
</ol>
</div>
</div>
</div>
<div class="content-header-right col-md-6 col-12">
<div class="d-inline-block float-md-right" ngbDropdown>
<button class="btn btn-info" id="dropdownBasic1" ngbDropdownToggle>Action</button>
<div ngbDropdownMenu class="arrow _dropdown_mob dropdown-menu-right" aria-labelledby="dropdownBasic1">
<button class="dropdown-item">Calender</button>
<button class="dropdown-item">Cart</button>
<button class="dropdown-item">Support</button>
<div class="dropdown-divider"></div>
<button class="dropdown-item">Settings</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { BreadcrumbComponent } from './breadcrumb.component';
describe('BreadcrumbComponent', () => {
let component: BreadcrumbComponent;
let fixture: ComponentFixture<BreadcrumbComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ BreadcrumbComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(BreadcrumbComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,19 @@
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-breadcrumb',
templateUrl: './breadcrumb.component.html',
styleUrls: ['./breadcrumb.component.css']
})
export class BreadcrumbComponent implements OnInit {
constructor() { }
@Input() breadcrumb: object;
ngOnInit() {
this.processBreadCrumbLinks();
}
private processBreadCrumbLinks() {
}
}

View File

@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CardModule } from 'src/app/content/partials/general/card/card.module';
import { RouterModule } from '@angular/router';
import { BreadcrumbComponent } from './breadcrumb.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
@NgModule({
imports: [
CommonModule,
CardModule,
NgbModule,
RouterModule.forChild([])
],
declarations: [BreadcrumbComponent],
exports: [BreadcrumbComponent]
})
export class BreadcrumbModule { }

View File

@@ -0,0 +1,22 @@
.tabsborder{
border-bottom: none !important;
}
.h6, h6 {
font-size: 1rem;
}
:host ::ng-deep .tab-content{
padding: 1rem;
}
:host ::ng-deep .layout_space{
padding: 0%;
}
:host ::ng-deep .nav.nav-tabs.nav-underline .nav-item a.nav-link {
padding: 0.5rem 0rem;
}
:host ::ng-deep .btn-outline-info .active {
background: rgba(0, 0, 0, .05);
}

View File

@@ -0,0 +1,394 @@
<div class="customizer border-left-blue-grey border-left-lighten-4 d-none d-xl-block" id="customizer">
<a class="customizer-close" (click)="toggleCustomizer($event)"><i class="feather ft-x font-medium-3"></i></a>
<a class="customizer-toggle bg-danger box-shadow-3" (click)="toggleCustomizer($event)"><i
class="feather ft-settings font-medium-3 spinner white"></i></a>
<div class="customizer-content p-2" fxFlex="auto" [perfectScrollbar]="config">
<h4 class="text-uppercase mb-0">Theme Customizer</h4>
<hr>
<p>Customize & Preview in Real Time</p>
<h5 class="mt-1 mb-1 text-bold-500">Menu Color Options</h5>
<div class="form-group">
<!-- Outline Button group -->
<div class="btn-group customizer-sidebar-options" role="group" aria-label="Basic example">
<button type="button" class="btn btn-outline-info _light" (click)="setMenuColor('menu-light',$event)"
data-sidebar="menu-light" id="light-menu">Light Menu
</button>
<button type="button" class="btn btn-outline-info _dark active" (click)="setMenuColor('menu-dark',$event)"
data-sidebar="menu-dark" id="dark-menu">Dark Menu
</button>
</div>
</div>
<hr>
<h5 class="mt-1 text-bold-500">Layout Options</h5>
<ul class="nav nav-tabs nav-underline nav-justified layout-options tabsborder">
<div class="col-lg-12 layout_space">
<div class="ngtab">
<ul ngbNav #nav="ngbNav" class="nav-pills">
<li ngbNavItem>
<a ngbNavLink>Layout</a>
<ng-template ngbNavContent>
<div role="tabpanel" class="tab-panel active px-1 pt-1" id="tabIcon21" aria-expanded="true"
aria-labelledby="baseIcon-tab21">
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input" [checked]="_themeSettingsConfig.menu === 'collapse'" (change)="toggleFixMenu($event)"
[(ngModel)]="isCollapsedMenu" name="collapsed-sidebar" id="collapsed-sidebar" >
<label class="custom-control-label" for="collapsed-sidebar">Collapsed Menu</label>
</div>
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input"
name="fixed-layout" id="fixed-layout" (ngModelChange)="toggleLayout('fixed')" [(ngModel)]="isfixChecked">
<label class="custom-control-label" for="fixed-layout">Fixed Layout</label>
</div>
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input"
name="boxed-layout" id="boxed-layout" (ngModelChange)="toggleLayout('boxed')" [(ngModel)]="isboxChecked">
<label class="custom-control-label" for="boxed-layout">Boxed Layout</label>
</div>
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input" (change)="setLayout('static',$event)"
[(ngModel)]="isStaticLayout" name="static-layout" id="static-layout">
<label class="custom-control-label" for="static-layout">Static Layout</label>
</div>
</div>
</ng-template>
</li>
<li ngbNavItem>
<a ngbNavLink>Navigation</a>
<ng-template ngbNavContent>
<div class="tab-panel px-1 pt-1" id="tabIcon22" aria-labelledby="baseIcon-tab22">
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input" name="right-side-icons"
[(ngModel)]="isRightSideIcons" (change)="setNavigation('menu-icon-right',$event)" id="right-side-icons">
<label class="custom-control-label" for="right-side-icons">Right Side Icons</label>
</div>
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input" name="bordered-navigation"
[(ngModel)]="isBorderedNavigation" (change)="setNavigation('menu-bordered',$event)" id="bordered-navigation">
<label class="custom-control-label" for="bordered-navigation">Bordered Navigation</label>
</div>
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input" name="flipped-navigation"
[(ngModel)]="isFlippedNavigation" (change)="setNavigation('menu-flipped',$event)" id="flipped-navigation">
<label class="custom-control-label" for="flipped-navigation">Flipped Navigation</label>
</div>
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input" name="collapsible-navigation"
[(ngModel)]="isCollapsibleNavigation" (change)="setNavigation('menu-collapsible',$event)" id="collapsible-navigation">
<label class="custom-control-label" for="collapsible-navigation">Collapsible Navigation</label>
</div>
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input" name="static-navigation"
[(ngModel)]="isStaticNavigation" (change)="setNavigation('menu-static',$event)" id="static-navigation">
<label class="custom-control-label" for="static-navigation">Static Navigation</label>
</div>
</div>
</ng-template>
</li>
<li ngbNavItem>
<a ngbNavLink>Navbar</a>
<ng-template ngbNavContent>
<div class="tab-panel px-1 pt-1" id="tabIcon23" aria-labelledby="baseIcon-tab23">
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input" name="navbar-static-top"
[(ngModel)]="isStaticTop" (change)="setNavbar($event)" id="navbar-static-top">
<label class="custom-control-label" for="navbar-static-top">Static Top</label>
</div>
</div>
</ng-template>
</li>
</ul>
<div [ngbNavOutlet]="nav"></div>
</div>
</div>
</ul>
<hr>
<h5 class="mt-1 text-bold-500">Navigation Color Options</h5>
<ul class="nav nav-tabs nav-underline nav-justified color-options tabsborder">
<div class="col-lg-12 layout_space">
<div [ngbNavOutlet]="nav" class="mt-2"></div>
<div class="ngtab">
<ul ngbNav #navColor="ngbNav" class="nav-pills" (navChange)="changeNavbarFontColor($event)">
<li [ngbNavItem]="1">
<a ngbNavLink id="semi-dark">Semi Dark</a>
<ng-template ngbNavContent class="px-1" >
<div class="row">
<div class="col-6">
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-sdark-clr" checked class="custom-control-input bg-default"
(click)="setColor('bg-default')" id="opt-default">
<label class="custom-control-label" (click)="setColor('bg-default')"
for="opt-default">Default</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-sdark-clr" class="custom-control-input bg-primary"
(click)="setColor('bg-primary')" id="opt-primary">
<label class="custom-control-label" (click)="setColor('bg-primary')"
for="opt-primary">Primary</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-sdark-clr" class="custom-control-input bg-danger"
(click)="setColor('bg-danger')" id="opt-danger">
<label class="custom-control-label" (click)="setColor('bg-danger')"
for="opt-danger">Danger</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-sdark-clr" class="custom-control-input bg-success"
(click)="setColor('bg-success')" id="opt-success">
<label class="custom-control-label" (click)="setColor('bg-success')"
for="opt-success">Success</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-sdark-clr" class="custom-control-input bg-blue"
(click)="setColor('bg-blue')" id="opt-blue">
<label class="custom-control-label" (click)="setColor('bg-blue')" for="opt-blue">Blue</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-sdark-clr" class="custom-control-input bg-cyan"
(click)="setColor('bg-cyan')" id="opt-cyan">
<label class="custom-control-label" (click)="setColor('bg-cyan')" for="opt-cyan">Cyan</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-sdark-clr" class="custom-control-input bg-pink"
(click)="setColor('bg-pink')" id="opt-pink">
<label class="custom-control-label" (click)="setColor('bg-pink')" for="opt-pink">Pink</label>
</div>
</div>
</div>
</ng-template>
</li>
<li [ngbNavItem] ="2" >
<a ngbNavLink id="semi-light">Semi Light</a>
<ng-template ngbNavContent>
<div class="row">
<div class="col-6">
<h6>Solid</h6>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-blue-grey"
(click)="setColor('bg-blue-grey')" id="default">
<label class="custom-control-label" (click)="setColor('bg-blue-grey')"
for="default">Default</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-primary"
(click)="setColor('bg-primary')" id="primary">
<label class="custom-control-label" (click)="setColor('bg-primary')" for="primary">Primary</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-danger"
(click)="setColor('bg-danger')" id="danger">
<label class="custom-control-label" (click)="setColor('bg-danger')" for="danger">Danger</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-success"
(click)="setColor('bg-success')" id="success">
<label class="custom-control-label" (click)="setColor('bg-success')" for="success">Success</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-blue"
(click)="setColor('bg-blue')" id="blue">
<label class="custom-control-label" (click)="setColor('bg-blue')" for="blue">Blue</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-cyan"
(click)="setColor('bg-cyan')" id="cyan">
<label class="custom-control-label" (click)="setColor('bg-cyan')" for="cyan">Cyan</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-pink"
(click)="setColor('bg-pink')" id="pink">
<label class="custom-control-label" (click)="setColor('bg-pink')" for="pink">Pink</label>
</div>
</div>
<div class="col-6">
<h6>Gradient</h6>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-blue-grey"
(click)="setColor('bg-gradient-x-grey-blue')" id="bg-gradient-x-grey-blue">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-grey-blue')"
for="bg-gradient-x-grey-blue">Default</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-primary"
(click)="setColor('bg-gradient-x-primary')" id="bg-gradient-x-primary">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-primary')"
for="bg-gradient-x-primary">Primary</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-danger"
(click)="setColor('bg-gradient-x-danger')" id="bg-gradient-x-danger">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-danger')"
for="bg-gradient-x-danger">Danger</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-success"
(click)="setColor('bg-gradient-x-success')" id="bg-gradient-x-success">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-success')"
for="bg-gradient-x-success">Success</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-blue"
(click)="setColor('bg-gradient-x-blue')" id="bg-gradient-x-blue">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-blue')"
for="bg-gradient-x-blue">Blue</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-cyan"
(click)="setColor('bg-gradient-x-cyan')" id="bg-gradient-x-cyan">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-cyan')"
for="bg-gradient-x-cyan">Cyan</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-pink"
(click)="setColor('bg-gradient-x-pink')" id="bg-gradient-x-pink">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-pink')"
for="bg-gradient-x-pink">Pink</label>
</div>
</div>
</div>
</ng-template>
</li>
<li [ngbNavItem] = "3" >
<a ngbNavLink id="dark">Dark</a>
<ng-template ngbNavContent>
<div class="row">
<div class="col-6">
<h3>Solid</h3>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-blue-grey"
(click)="setColor('bg-blue-grey')" id="default">
<label class="custom-control-label" (click)="setColor('bg-blue-grey')"
for="default">Default</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-primary"
(click)="setColor('bg-primary')" id="primary">
<label class="custom-control-label" (click)="setColor('bg-primary')" for="primary">Primary</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-danger"
(click)="setColor('bg-danger')" id="danger">
<label class="custom-control-label" (click)="setColor('bg-danger')" for="danger">Danger</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-success"
(click)="setColor('bg-success')" id="success">
<label class="custom-control-label" (click)="setColor('bg-success')" for="success">Success</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-blue"
(click)="setColor('bg-blue')" id="blue">
<label class="custom-control-label" (click)="setColor('bg-blue')" for="blue">Blue</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-cyan"
(click)="setColor('bg-cyan')" id="cyan">
<label class="custom-control-label" (click)="setColor('bg-cyan')" for="cyan">Cyan</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-pink"
(click)="setColor('bg-pink')" id="pink">
<label class="custom-control-label" (click)="setColor('bg-pink')" for="pink">Pink</label>
</div>
</div>
<div class="col-6">
<h3>Gradient</h3>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-blue-grey"
(click)="setColor('bg-gradient-x-grey-blue')" id="bg-gradient-x-grey-blue">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-grey-blue')"
for="bg-gradient-x-grey-blue">Default</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-primary"
(click)="setColor('bg-gradient-x-primary')" id="bg-gradient-x-primary">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-primary')"
for="bg-gradient-x-primary">Primary</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-danger"
(click)="setColor('bg-gradient-x-danger')" id="bg-gradient-x-danger">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-danger')"
for="bg-gradient-x-danger">Danger</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-success"
(click)="setColor('bg-gradient-x-success')" id="bg-gradient-x-success">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-success')"
for="bg-gradient-x-success">Success</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-blue"
(click)="setColor('bg-gradient-x-blue')" id="bg-gradient-x-blue">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-blue')"
for="bg-gradient-x-blue">Blue</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-cyan"
(click)="setColor('bg-gradient-x-cyan')" id="bg-gradient-x-cyan">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-cyan')"
for="bg-gradient-x-cyan">Cyan</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-pink"
id="bg-gradient-x-pink" (click)="setColor('bg-gradient-x-pink')">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-pink')"
for="bg-gradient-x-pink">Pink</label>
</div>
</div>
</div>
</ng-template>
</li>
<li [ngbNavItem] ="4">
<a ngbNavLink id="light">Light</a>
<ng-template ngbNavContent>
<div class="tab-pane" id="clrOpt4" aria-labelledby="color-opt-4">
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-light-clr" class="custom-control-input bg-blue-grey"
(click)="setColor('bg-blue-grey bg-lighten-4')" id="light-blue-grey">
<label class="custom-control-label" (click)="setColor('bg-blue-grey bg-lighten-4')"
for="light-blue-grey">Default</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-light-clr" class="custom-control-input bg-primary"
(click)="setColor('bg-primary bg-lighten-4')" id="light-primary">
<label class="custom-control-label" (click)="setColor('bg-primary bg-lighten-4')"
for="light-primary">Primary</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-light-clr" class="custom-control-input bg-danger"
(click)="setColor('bg-danger bg-lighten-4')" id="light-danger">
<label class="custom-control-label" (click)="setColor('bg-danger bg-lighten-4')"
for="light-danger">Danger</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-light-clr" class="custom-control-input bg-success"
(click)="setColor('bg-success bg-lighten-4')" id="light-success">
<label class="custom-control-label" (click)="setColor('bg-success bg-lighten-4')"
for="light-success">Success</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-light-clr" class="custom-control-input bg-blue"
(click)="setColor('bg-blue bg-lighten-4')" id="light-blue">
<label class="custom-control-label" (click)="setColor('bg-blue bg-lighten-4')"
for="light-blue">Blue</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-light-clr" class="custom-control-input bg-cyan"
(click)="setColor('bg-cyan bg-lighten-4')" id="light-cyan">
<label class="custom-control-label" (click)="setColor('bg-cyan bg-lighten-4')"
for="light-cyan">Cyan</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-light-clr" class="custom-control-input bg-pink"
(click)="setColor('bg-pink bg-lighten-4')" id="light-pink">
<label class="custom-control-label" (click)="setColor('bg-pink bg-lighten-4')"
for="light-pink">Pink</label>
</div>
</div>
</ng-template>
</li>
</ul>
<div [ngbNavOutlet]="navColor"></div>
</div>
</div>
</ul>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { CustomizerComponent } from './customizer.component';
describe('CustomizerComponent', () => {
let component: CustomizerComponent;
let fixture: ComponentFixture<CustomizerComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ CustomizerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CustomizerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,386 @@
import { Component, OnInit, Renderer2, Inject, ViewChild, HostListener } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { NavbarService } from 'src/app/_services/navbar.service';
import { ThemeSettingsService } from '../settings/theme-settings.service';
import { MenuSettingsService } from '../settings/menu-settings.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { PerfectScrollbarConfigInterface, PerfectScrollbarComponent, PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
import { NgbNavChangeEvent } from '@ng-bootstrap/ng-bootstrap';
import { AppConstants } from 'src/app/_helpers/app.constants';
declare var require: any;
const colors = require('../../../assets/data/customizer/customizerColor.json');
@Component({
selector: 'app-customizer',
templateUrl: './customizer.component.html',
styleUrls: ['./customizer.component.css']
})
export class CustomizerComponent implements OnInit {
private _unsubscribeAll: Subject<any>;
private _unsubscribeAllMenu: Subject<any>;
public _themeCustomizerConfig: any;
public _menuCustomizerConfig: any;
public _themeSettingsConfig: any;
public selectColorClass: string;
public activebutton: any;
public isCollapsedMenu = false;
public isfixChecked = false;
public isboxChecked = false;
public isStaticLayout = false;
public isRightSideIcons = false;
public isBorderedNavigation = false;
public isFlippedNavigation = false;
public isCollapsibleNavigation = false;
public isStaticNavigation = false;
public isStaticTop = false;
public config: PerfectScrollbarConfigInterface = { wheelPropagation: false };
collapsed = true;
@ViewChild(PerfectScrollbarComponent) componentRef?: PerfectScrollbarComponent;
@ViewChild(PerfectScrollbarDirective, { static: true }) directiveRef?: PerfectScrollbarDirective;
constructor(
private _renderer: Renderer2,
@Inject(DOCUMENT) private document: Document,
private navbarService: NavbarService,
private _themeSettingsService: ThemeSettingsService,
private _menuSettingsService: MenuSettingsService
) {
this._unsubscribeAll = new Subject();
this._unsubscribeAllMenu = new Subject();
}
ngOnInit() {
// Subscribe to config changes
this._themeSettingsService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._themeCustomizerConfig = config;
});
this._menuSettingsService.config
.pipe(takeUntil(this._unsubscribeAllMenu))
.subscribe((config) => {
this._menuCustomizerConfig = config;
});
this._themeSettingsService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._themeSettingsConfig = config;
});
}
toggleCustomizer(event) {
const element = document.getElementById('customizer');
if (element && element.classList.contains('open')) {
this._renderer.removeClass(element, 'open');
} else {
this._renderer.addClass(element, 'open');
}
}
setLayout(layout, e) {
const footer = document.getElementById('footer');
const headerNavbar = document.getElementsByClassName('header-navbar');
const mainMenu = document.getElementsByClassName('main-menu');
if (layout === 'static' && e.currentTarget.checked === true) {
this.staticLayout(e);
} else if (layout === 'static' && e.currentTarget.checked === false) {
this._themeSettingsConfig.layout.pattern = '';
this._renderer.removeClass(headerNavbar.item(0), 'navbar-static-top');
this._renderer.removeClass(footer, 'footer-static');
this._renderer.addClass(headerNavbar.item(0), 'fixed-top');
this._renderer.addClass(document.body, 'fixed-navbar');
this._renderer.addClass(mainMenu.item(0), 'menu-fixed');
this.isStaticLayout = false;
}
}
toggleFixMenu(e) {
const toggleIcon = document.getElementsByClassName('toggle-icon');
if (this.document.body.classList.contains('menu-expanded') && e.currentTarget.checked === true) {
this._themeCustomizerConfig.navbar = 'collapse';
// show the left aside menu
this.navbarService.setFixedMenu(false);
this.document.body.classList.remove('menu-expanded');
this.document.body.classList.add('menu-collapsed');
// Change switch icon
this._renderer.removeClass(toggleIcon.item(0), 'ft-toggle-right');
this._renderer.addClass(toggleIcon.item(0), 'ft-toggle-left');
this.isCollapsedMenu = true;
} else {
this._themeCustomizerConfig.navbar = 'expand';
this.navbarService.setFixedMenu(true);
this.document.body.classList.remove('menu-collapsed');
this.document.body.classList.add('menu-expanded');
// Change switch icon
this._renderer.removeClass(toggleIcon.item(0), 'ft-toggle-left');
this._renderer.addClass(toggleIcon.item(0), 'ft-toggle-right');
this.isCollapsedMenu = false;
}
setTimeout(() => { AppConstants.fireRefreshEventOnWindow(); }, 300);
this.resetOpenMenu();
}
resetOpenMenu() {
for (let i = 0; i < this._menuCustomizerConfig.vertical_menu.items.length; i++) {
const menu = this._menuCustomizerConfig.vertical_menu.items[i];
if (!menu.submenu) {
menu['isOpen'] = false;
menu['isActive'] = false;
menu['hover'] = false;
} else if (menu.submenu) {
for (let j = 0; j < menu.submenu.items.length; j++) {
menu['isOpen'] = false;
menu['isActive'] = false;
menu['hover'] = false;
menu.submenu.items[j]['isOpen'] = false;
}
}
}
}
changeNavbarFontColor($event: NgbNavChangeEvent) {
const headerElement = document.getElementsByClassName('header-navbar');
if ($event.nextId === 1) {
console.log('hgdfh');
this._renderer.removeClass(headerElement.item(0), 'navbar-dark');
this._renderer.removeClass(headerElement.item(0), 'navbar-semi-light');
this._renderer.removeClass(headerElement.item(0), 'navbar-light');
this._renderer.addClass(headerElement.item(0), 'navbar-semi-dark');
this._themeCustomizerConfig.colorTheme = 'semi-dark';
} else if ($event.nextId === 2) {
this._renderer.removeClass(headerElement.item(0), 'navbar-dark');
this._renderer.removeClass(headerElement.item(0), 'navbar-semi-dark');
this._renderer.removeClass(headerElement.item(0), 'navbar-light');
this._renderer.addClass(headerElement.item(0), 'navbar-semi-light');
this._themeCustomizerConfig.colorTheme = 'semi-light';
} else if ($event.nextId === 3) {
this._renderer.removeClass(headerElement.item(0), 'navbar-semi-light');
this._renderer.removeClass(headerElement.item(0), 'navbar-semi-dark');
this._renderer.removeClass(headerElement.item(0), 'navbar-light');
this._renderer.addClass(headerElement.item(0), 'navbar-dark');
this._themeCustomizerConfig.colorTheme = 'dark';
} else if ($event.nextId === 4) {
this._renderer.removeClass(headerElement.item(0), 'navbar-dark');
this._renderer.removeClass(headerElement.item(0), 'navbar-semi-dark');
this._renderer.removeClass(headerElement.item(0), 'navbar-semi-light');
this._renderer.addClass(headerElement.item(0), 'navbar-light');
this._themeCustomizerConfig.colorTheme = 'light';
}
this._themeSettingsService.config = {
color: ''
};
}
setMenuColor(colorClass, event) {
const darkMenuButton = document.getElementById('dark-menu');
const lightMenuButton = document.getElementById('light-menu');
if (event.currentTarget.className === 'btn btn-outline-info _dark') {
this._renderer.removeClass(lightMenuButton, 'active');
this._renderer.addClass(darkMenuButton, 'active');
} else if (event.currentTarget.className === 'btn btn-outline-info _light') {
this._renderer.removeClass(darkMenuButton, 'active');
this._renderer.addClass(lightMenuButton, 'active');
}
this._themeSettingsService.config = {
menuColor: colorClass, // light-menu, dark-menu
};
}
setNavigation(navigationClass, event) {
const navigationElement = document.getElementById('main-menu');
const element = document.getElementById('customizer');
if (event.target.checked === true && navigationClass !== 'menu-collapsible') {
this._themeSettingsService.config = {
navigation: navigationClass
};
if (navigationClass === 'menu-flipped') {
this._renderer.removeClass(element, 'open');
} else if (navigationClass === 'menu-static') {
this._renderer.removeClass(navigationElement, 'menu-fixed');
}
} else if (event.target.checked === false && navigationClass !== 'menu-collapsible') {
this._themeSettingsConfig.navigation = AppConstants.NAVIGATION_TYPE_ACCORDATION;
this._renderer.removeClass(navigationElement, navigationClass);
this._renderer.removeClass(document.body, navigationClass);
if (navigationClass === 'menu-static') {
this._renderer.addClass(navigationElement, 'menu-fixed');
}
}
if (event.target.checked === true && navigationClass === 'menu-collapsible') {
this._themeSettingsConfig.navigation = AppConstants.NAVIGATION_TYPE_ACCORDATION;
this._renderer.removeClass(navigationElement, navigationClass);
} else if (event.target.checked === false && navigationClass === 'menu-collapsible') {
this._themeSettingsService.config = {
navigation: navigationClass
};
}
if (navigationClass === 'menu-icon-right' && event.currentTarget.checked === true) {
this.isRightSideIcons = true;
} else if (navigationClass === 'menu-icon-right' && event.currentTarget.checked === false) {
this.isRightSideIcons = false;
}
if (navigationClass === 'menu-bordered' && event.currentTarget.checked === true) {
this.isBorderedNavigation = true;
} else if (navigationClass === 'menu-bordered' && event.currentTarget.checked === false) {
this.isBorderedNavigation = false;
}
if (navigationClass === 'menu-flipped' && event.currentTarget.checked === true) {
this.isFlippedNavigation = true;
} else if (navigationClass === 'menu-flipped' && event.currentTarget.checked === false) {
this.isFlippedNavigation = false;
}
if (navigationClass === 'menu-collapsible' && event.currentTarget.checked === true) {
this.isCollapsibleNavigation = true;
} else if (navigationClass === 'menu-collapsible' && event.currentTarget.checked === false) {
this.isCollapsibleNavigation = false;
}
if (navigationClass === 'menu-static' && event.currentTarget.checked === true) {
this.isStaticNavigation = true;
} else if (navigationClass === 'menu-static' && event.currentTarget.checked === false) {
this.isStaticNavigation = false;
}
}
setNavbar(event) {
const navbarElement = document.getElementsByClassName('header-navbar');
const navigationElement = document.getElementById('main-menu');
if (event.target.checked === true) {
this._renderer.removeClass(document.body, 'fixed-navbar');
this._renderer.removeClass(navbarElement.item(0), 'fixed-top');
this._renderer.removeClass(navigationElement, 'menu-fixed');
this._renderer.addClass(navbarElement.item(0), 'navbar-static-top');
this._renderer.addClass(navigationElement, 'menu-static');
this.isStaticTop = true;
} else if (event.target.checked === false) {
this._renderer.removeClass(navbarElement.item(0), 'navbar-static-top');
this._renderer.removeClass(navigationElement, 'menu-static');
this._renderer.addClass(document.body, 'fixed-navbar');
this._renderer.addClass(navbarElement.item(0), 'fixed-top');
this._renderer.addClass(navigationElement, 'menu-fixed');
this.isStaticTop = false;
}
}
setColor(colorClass) {
for (let i = 0; i <= colors.colorArray.length; i++) {
if (colorClass === colors.colorArray[i].cssClass) {
this.selectColorClass = colorClass;
break;
}
}
this._themeSettingsService.config = {
color: this.selectColorClass
};
}
toggleLayout(layout) {
const footer = document.getElementById('footer');
const headerNavbar = document.getElementsByClassName('header-navbar');
if (layout === 'boxed' && this.isboxChecked === false) {
this.boxedLayout();
setTimeout(() => { AppConstants.fireRefreshEventOnWindow(); }, 300);
} else if (layout === 'boxed' && this.isboxChecked === true) {
this._renderer.removeClass(headerNavbar.item(0), 'container');
this._renderer.removeClass(headerNavbar.item(0), 'boxed-layout');
this._renderer.removeClass(document.body, 'boxed-layout');
this._renderer.removeClass(document.body, 'container');
setTimeout(() => { AppConstants.fireRefreshEventOnWindow(); }, 300);
this._themeSettingsConfig.layout.pattern = '';
} else if (layout === 'fixed' && this.isfixChecked === false) {
this.fixedLayout();
setTimeout(() => { AppConstants.fireRefreshEventOnWindow(); }, 300);
} else if (layout === 'fixed' && this.isfixChecked === true) {
this._renderer.removeClass(footer, 'fixed-bottom');
this._themeSettingsConfig.layout.pattern = '';
setTimeout(() => { AppConstants.fireRefreshEventOnWindow(); }, 300);
}
}
fixedLayout() {
const footer = document.getElementById('footer');
const headerNavbar = document.getElementsByClassName('header-navbar');
this._renderer.removeClass(headerNavbar.item(0), 'container');
this._renderer.removeClass(headerNavbar.item(0), 'boxed-layout');
this._renderer.removeClass(document.body, 'boxed-layout');
this._renderer.removeClass(document.body, 'container');
this._renderer.addClass(footer, 'fixed-bottom');
if (this.isStaticLayout === true) {
this._renderer.addClass(headerNavbar.item(0), 'fixed-top');
this._renderer.addClass(document.body, 'fixed-navbar');
this._renderer.removeClass(footer, 'fixed-bottom');
}
this.isfixChecked = true;
this.isboxChecked = false;
this._themeSettingsConfig.layout.pattern = 'fixed';
}
boxedLayout() {
const footer = document.getElementById('footer');
const headerNavbar = document.getElementsByClassName('header-navbar');
this._renderer.removeClass(footer, 'fixed-bottom');
this._renderer.addClass(headerNavbar.item(0), 'container');
this._renderer.addClass(headerNavbar.item(0), 'boxed-layout');
this._renderer.addClass(headerNavbar.item(0), 'fixed-top');
this._renderer.addClass(document.body, 'boxed-layout');
this._renderer.addClass(document.body, 'container');
if (this.isStaticLayout === true) {
this._renderer.removeClass(headerNavbar.item(0), 'fixed-top');
this._renderer.removeClass(document.body, 'fixed-navbar');
}
this.isboxChecked = true;
this.isfixChecked = false;
this._themeSettingsConfig.layout.pattern = 'boxed';
}
staticLayout(e) {
const footer = document.getElementById('footer');
const headerNavbar = document.getElementsByClassName('header-navbar');
const mainMenu = document.getElementsByClassName('main-menu');
this._renderer.removeClass(document.body, 'fixed-navbar');
this._renderer.removeClass(headerNavbar.item(0), 'fixed-top');
this._renderer.removeClass(mainMenu.item(0), 'menu-fixed');
this._renderer.addClass(headerNavbar.item(0), 'navbar-static-top');
this._renderer.addClass(footer, 'footer-static');
this._renderer.removeClass(footer, 'fixed-bottom');
this.isStaticLayout = true;
this._themeSettingsConfig.layout.pattern = 'static';
}
@HostListener('window:resize', ['$event'])
onResize() {
if (this.document.body.classList.contains('menu-expanded')) {
this.collapsed = false;
} else {
this.collapsed = true;
}
}
}

View File

@@ -0,0 +1,19 @@
.tabsborder{
border-bottom: none !important;
}
.h6, h6 {
font-size: 1rem;
}
:host ::ng-deep .tab-content{
padding: 1rem;
}
:host ::ng-deep .layout_space{
padding: 0%;
}
:host ::ng-deep .nav.nav-tabs.nav-underline .nav-item a.nav-link {
padding: 0.5rem 0rem;
}

View File

@@ -0,0 +1,226 @@
<div class="customizer border-left-blue-grey border-left-lighten-4 d-none d-xl-block" id="customizer">
<a [routerLink]="" class="customizer-close" (click)="toggleCustomizer($event)"><i class="feather ft-x font-medium-3"></i></a>
<a [routerLink]="" class="customizer-toggle bg-danger box-shadow-3" (click)="toggleCustomizer($event)"><i
class="feather ft-settings font-medium-3 spinner white"></i></a>
<div class="customizer-content p-2" fxFlex="auto" [perfectScrollbar]="config">
<h4 class="text-uppercase mb-0">Theme Customizer</h4>
<hr>
<p>Customize & Preview in Real Time</p>
<h5 class="mt-1 mb-1 text-bold-500">Menu Color Options</h5>
<div class="form-group">
<!-- Outline Button group -->
<div class="btn-group customizer-sidebar-options" role="group" aria-label="Basic example">
<button type="button" class="btn btn-outline-info _light active" (click)="setMenuColor($event)"
data-sidebar="navbar-light" id="light-menu">Light Menu
</button>
<button type="button" class="btn btn-outline-info _dark" (click)="setMenuColor($event)"
data-sidebar="navbar-dark" id="dark-menu">Dark Menu
</button>
</div>
</div>
<hr>
<h5 class="mt-1 text-bold-500">Layout Options</h5>
<ul class="nav nav-tabs nav-underline nav-justified layout-options tabsborder">
<div class="col-lg-12 layout_space">
<div class="ngtab">
<ul ngbNav #nav="ngbNav" class="nav-pills">
<li ngbNavItem>
<a ngbNavLink>Layout</a>
<ng-template ngbNavContent>
<div role="tabpanel" class="tab-panel active px-1 pt-1" id="tabIcon21" aria-expanded="true"
aria-labelledby="baseIcon-tab21">
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input" (change)="toggleFixMenu($event)"
[(ngModel)]="isCollapsedMenu" name="collapsed-sidebar" id="collapsed-sidebar">
<label class="custom-control-label" for="collapsed-sidebar">Collapsed Menu</label>
</div>
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input" name="fixed-layout" id="fixed-layout"
[(ngModel)]="isfixChecked" (ngModelChange)="toggleLayout('fixed')">
<label class="custom-control-label" for="fixed-layout">Fixed Layout</label>
</div>
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input" [(ngModel)]="isboxChecked"
(ngModelChange)="toggleLayout('boxed')" name="boxed-layout" id="boxed-layout">
<label class="custom-control-label" for="boxed-layout">Boxed Layout</label>
</div>
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input" (change)="setLayout('static',$event)"
[(ngModel)]="isStaticLayout" name="static-layout" id="static-layout">
<label class="custom-control-label" for="static-layout">Static Layout</label>
</div>
</div>
</ng-template>
</li>
<li ngbNavItem>
<a ngbNavLink>Navigation</a>
<ng-template ngbNavContent>
<div class="tab-panel px-1 pt-1" id="tabIcon22" aria-labelledby="baseIcon-tab22">
<div class="custom-control custom-checkbox mb-1">
<input type="checkbox" class="custom-control-input" name="right-side-icons"
[(ngModel)]="isRightSideIcons" (click)="setNavigation('navbar-icon-right',$event)"
id="right-side-icons">
<label class="custom-control-label" for="right-side-icons">Right Side Icons</label>
</div>
</div>
</ng-template>
</li>
</ul>
<div [ngbNavOutlet]="nav"></div>
</div>
</div>
</ul>
<hr>
<h5 class="mt-1 text-bold-500">Navigation Color Options</h5>
<ul class="nav nav-tabs nav-underline nav-justified color-options tabsborder">
<div class="col-lg-12 layout_space">
<div class="ngtab">
<ul ngbNav #navColor="ngbNav" class="nav-pills" (navChange)="changeNavbarFontColor($event)">
<li [ngbNavItem]="1">
<a ngbNavLink id="dark">Dark</a>
<ng-template ngbNavContent class="px-1" >
<div class="row">
<div class="col-6">
<h3>Solid</h3>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-blue-grey"
(click)="setColor('bg-blue-grey')" id="default">
<label class="custom-control-label" (click)="setColor('bg-blue-grey')"
for="default">Default</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-primary"
(click)="setColor('bg-primary')" id="primary">
<label class="custom-control-label" (click)="setColor('bg-primary')" for="primary">Primary</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-danger"
(click)="setColor('bg-danger')" id="danger">
<label class="custom-control-label" (click)="setColor('bg-danger')" for="danger">Danger</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-success"
(click)="setColor('bg-success')" id="success">
<label class="custom-control-label" (click)="setColor('bg-success')" for="success">Success</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-blue"
(click)="setColor('bg-blue')" id="blue">
<label class="custom-control-label" (click)="setColor('bg-blue')" for="blue">Blue</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-cyan"
(click)="setColor('bg-cyan')" id="cyan">
<label class="custom-control-label" (click)="setColor('bg-cyan')" for="cyan">Cyan</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-pink"
(click)="setColor('bg-pink')" id="pink">
<label class="custom-control-label" (click)="setColor('bg-pink')" for="pink">Pink</label>
</div>
</div>
<div class="col-6">
<h3>Gradient</h3>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-blue-grey"
(click)="setColor('bg-gradient-x-grey-blue')" id="bg-gradient-x-grey-blue">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-grey-blue')"
for="bg-gradient-x-grey-blue">Default</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-primary"
(click)="setColor('bg-gradient-x-primary')" id="bg-gradient-x-primary">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-primary')"
for="bg-gradient-x-primary">Primary</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-danger"
(click)="setColor('bg-gradient-x-danger')" id="bg-gradient-x-danger">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-danger')"
for="bg-gradient-x-danger">Danger</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-success"
(click)="setColor('bg-gradient-x-success')" id="bg-gradient-x-success">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-success')"
for="bg-gradient-x-success">Success</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-blue"
(click)="setColor('bg-gradient-x-blue')" id="bg-gradient-x-blue">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-blue')"
for="bg-gradient-x-blue">Blue</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-cyan"
(click)="setColor('bg-gradient-x-cyan')" id="bg-gradient-x-cyan">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-cyan')"
for="bg-gradient-x-cyan">Cyan</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-slight-clr" class="custom-control-input bg-pink"
id="bg-gradient-x-pink" (click)="setColor('bg-gradient-x-pink')">
<label class="custom-control-label" (click)="setColor('bg-gradient-x-pink')"
for="bg-gradient-x-pink">Pink</label>
</div>
</div>
</div>
</ng-template>
</li>
<li [ngbNavItem] ="2" >
<a ngbNavLink id="light">Light</a>
<ng-template ngbNavContent>
<div class="tab-pane" id="clrOpt4" aria-labelledby="color-opt-4">
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-light-clr" class="custom-control-input bg-blue-grey"
(click)="setColor('bg-blue-grey bg-lighten-4')" id="light-blue-grey">
<label class="custom-control-label" (click)="setColor('bg-blue-grey bg-lighten-4')"
for="light-blue-grey">Default</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-light-clr" class="custom-control-input bg-primary"
(click)="setColor('bg-primary bg-lighten-4')" id="light-primary">
<label class="custom-control-label" (click)="setColor('bg-primary bg-lighten-4')"
for="light-primary">Primary</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-light-clr" class="custom-control-input bg-danger"
(click)="setColor('bg-danger bg-lighten-4')" id="light-danger">
<label class="custom-control-label" (click)="setColor('bg-danger bg-lighten-4')"
for="light-danger">Danger</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-light-clr" class="custom-control-input bg-success"
(click)="setColor('bg-success bg-lighten-4')" id="light-success">
<label class="custom-control-label" (click)="setColor('bg-success bg-lighten-4')"
for="light-success">Success</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-light-clr" class="custom-control-input bg-blue"
(click)="setColor('bg-blue bg-lighten-4')" id="light-blue">
<label class="custom-control-label" (click)="setColor('bg-blue bg-lighten-4')"
for="light-blue">Blue</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-light-clr" class="custom-control-input bg-cyan"
(click)="setColor('bg-cyan bg-lighten-4')" id="light-cyan">
<label class="custom-control-label" (click)="setColor('bg-cyan bg-lighten-4')"
for="light-cyan">Cyan</label>
</div>
<div class="custom-control custom-radio mb-1">
<input type="radio" name="nav-light-clr" class="custom-control-input bg-pink"
(click)="setColor('bg-pink bg-lighten-4')" id="light-pink">
<label class="custom-control-label" (click)="setColor('bg-pink bg-lighten-4')"
for="light-pink">Pink</label>
</div>
</div>
</ng-template>
</li>
</ul>
<div [ngbNavOutlet]="navColor"></div>
</div>
</div>
</ul>
</div>
</div>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { HorizontalCustomizerComponent } from './horizontal-customizer.component';
describe('HorizontalCustomizerComponent', () => {
let component: HorizontalCustomizerComponent;
let fixture: ComponentFixture<HorizontalCustomizerComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ HorizontalCustomizerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HorizontalCustomizerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,273 @@
import { Component, OnInit, Renderer2, Inject, ViewChild } from '@angular/core';
import { ThemeSettingsService } from '../../settings/theme-settings.service';
import { DOCUMENT } from '@angular/common';
import { NavbarService } from 'src/app/_services/navbar.service';
import { NgbNavChangeEvent } from '@ng-bootstrap/ng-bootstrap';
import { MenuSettingsService } from '../../settings/menu-settings.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { PerfectScrollbarConfigInterface, PerfectScrollbarComponent, PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
import { AppConstants } from 'src/app/_helpers/app.constants';
declare var require: any;
const colors = require('../../../../assets/data/customizer/customizerColor.json');
@Component({
selector: 'app-horizontal-customizer',
templateUrl: './horizontal-customizer.component.html',
styleUrls: ['./horizontal-customizer.component.css']
})
export class HorizontalCustomizerComponent implements OnInit {
private _unsubscribeAll: Subject<any>;
public _themeCustomizerConfig: any;
public _menuCustomizerConfig: any;
private _themeSettingsConfig: any;
public selectColorClass: string;
public isCollapsedMenu = false;
public isfixChecked = false;
public isboxChecked = false;
public isStaticLayout = false;
public isRightSideIcons = false;
activeIdString = 'light';
public config: PerfectScrollbarConfigInterface = { wheelPropagation: false };
@ViewChild(PerfectScrollbarComponent) componentRef?: PerfectScrollbarComponent;
@ViewChild(PerfectScrollbarDirective, { static: true }) directiveRef?: PerfectScrollbarDirective;
constructor(private _renderer: Renderer2,
@Inject(DOCUMENT) private document: Document,
private navbarService: NavbarService,
private _themeSettingsService: ThemeSettingsService,
private _menuSettingsService: MenuSettingsService, ) {
this._unsubscribeAll = new Subject();
}
ngOnInit() {
this._themeSettingsService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._themeCustomizerConfig = config;
});
this._themeSettingsService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._themeSettingsConfig = config;
});
}
toggleCustomizer(event) {
const element = document.getElementById('customizer');
if (element && element.classList.contains('open')) {
this._renderer.removeClass(element, 'open');
} else {
this._renderer.addClass(element, 'open');
}
}
changeNavbarFontColor($event: NgbNavChangeEvent) {
const headerElement = document.getElementsByClassName('top-header');
if ($event.nextId === 1) {
this._renderer.removeClass(headerElement.item(0), 'navbar-semi-light');
this._renderer.removeClass(headerElement.item(0), 'navbar-semi-dark');
this._renderer.removeClass(headerElement.item(0), 'navbar-light');
this._renderer.removeClass(headerElement.item(0), 'navbar-shadow');
this._renderer.addClass(headerElement.item(0), 'navbar-dark');
} else if ($event.nextId === 2) {
this._renderer.removeClass(headerElement.item(0), 'navbar-semi-light');
this._renderer.removeClass(headerElement.item(0), 'navbar-semi-dark');
this._renderer.removeClass(headerElement.item(0), 'navbar-dark');
this._renderer.addClass(headerElement.item(0), 'navbar-light');
this._renderer.addClass(headerElement.item(0), 'navbar-shadow');
}
this._themeSettingsService.config = {
color: ''
};
}
setColor(colorClass) {
for (let i = 0; i <= colors.colorArray.length; i++) {
if (colorClass === colors.colorArray[i].cssClass) {
this.selectColorClass = colorClass;
break;
}
}
this._themeSettingsService.config = {
color: this.selectColorClass
};
}
setMenuColor(e) {
const darkMenuButton = document.getElementById('dark-menu');
const lightMenuButton = document.getElementById('light-menu');
const menuHeaderElement = document.getElementById('menu-header');
if (e.currentTarget.className === 'btn btn-outline-info _dark') {
this._renderer.removeClass(lightMenuButton, 'active');
this._renderer.removeClass(menuHeaderElement, 'navbar-light');
this._renderer.addClass(darkMenuButton, 'active');
this._renderer.addClass(menuHeaderElement, 'navbar-dark');
} else if (e.currentTarget.className === 'btn btn-outline-info _light') {
this._renderer.removeClass(menuHeaderElement, 'navbar-dark');
this._renderer.removeClass(darkMenuButton, 'active');
this._renderer.addClass(lightMenuButton, 'active');
this._renderer.addClass(menuHeaderElement, 'navbar-light');
}
// this._themeSettingsService.config = {
// menuColor: colorClass, // menu-dark, menu-light
// };
}
toggleFixMenu(e) {
if (this.document.body.classList.contains('menu-expanded') && e.currentTarget.checked === true) {
// show the left aside menu
this.navbarService.setFixedMenu(false);
this.document.body.classList.remove('menu-expanded');
this.document.body.classList.add('menu-collapsed');
// Change switch icon
e.srcElement.classList.remove('ft-toggle-right');
e.srcElement.classList.add('ft-toggle-left');
this.isCollapsedMenu = true;
} else {
this.navbarService.setFixedMenu(true);
this.document.body.classList.remove('menu-collapsed');
this.document.body.classList.add('menu-expanded');
// Change switch icon
e.srcElement.classList.remove('ft-toggle-left');
e.srcElement.classList.add('ft-toggle-right');
this.isCollapsedMenu = false;
}
}
setLayout(layout, e) {
const footer = document.getElementById('footer');
const headerNavbar = document.getElementsByClassName('header-navbar');
const menuHeader = document.getElementById('menu-header');
const isSticky = document.getElementsByClassName('sticky-wrapper');
const element = document.getElementById('sticky-wrapper');
if (e.currentTarget.checked === true && layout === 'static') {
// this._renderer.removeClass(headerNavbar.item(0), 'fixed-top');
this._renderer.addClass(headerNavbar.item(0), 'navbar-static-top');
this._renderer.addClass(menuHeader, 'navbar-static');
this._renderer.addClass(footer, 'footer-static');
this.isStaticLayout = true;
this._themeSettingsConfig.layout.pattern = 'static';
element.classList.add('is-static');
if (this.isboxChecked === false ) {
this._renderer.removeClass(footer, 'fixed-bottom');
}
} else {
this._themeSettingsConfig.layout.pattern = '';
this._renderer.removeClass(headerNavbar.item(0), 'navbar-static-top');
this._renderer.removeClass(footer, 'footer-static');
this._renderer.removeClass(menuHeader, 'navbar-static');
this._renderer.removeClass(isSticky.item(0), 'is-static');
this.isStaticLayout = false;
if (this.isboxChecked === true) {
this.boxedLayout();
}
if (this.isfixChecked === true) {
this.fixedLayout();
}
}
}
setNavigation(navigationClass, event) {
const navigationElement = document.getElementById('menu-header');
if (event.target.checked === true) {
this._themeSettingsService.config = {
navigation: navigationClass,
};
} else if (event.target.checked === false) {
this._renderer.removeClass(navigationElement, navigationClass);
this._renderer.removeClass(document.body, navigationClass);
}
if (navigationClass === 'menu-icon-right' && event.currentTarget.checked === true) {
this.isRightSideIcons = true;
} else if (navigationClass === 'menu-icon-right' && event.currentTarget.checked === false) {
this.isRightSideIcons = false;
}
}
toggleLayout(layout) {
const footer = document.getElementById('footer');
const headerNavbar = document.getElementsByClassName('header-navbar');
const element = document.getElementById('sticky-wrapper');
if (layout === 'boxed' && this.isboxChecked === true) {
this.boxedLayout();
setTimeout(() => { AppConstants.fireRefreshEventOnWindow(); }, 300);
} else if (layout === 'boxed' && this.isboxChecked === false) {
this._renderer.removeClass(headerNavbar.item(0), 'container');
this._renderer.removeClass(headerNavbar.item(0), 'boxed-layout');
this._renderer.removeClass(document.body, 'boxed-layout');
this._renderer.removeClass(document.body, 'container');
element.classList.remove('container');
setTimeout(() => { AppConstants.fireRefreshEventOnWindow(); }, 300);
this._themeSettingsConfig.layout.pattern = '';
} else if (layout === 'fixed' && this.isfixChecked === true) {
this.fixedLayout();
setTimeout(() => { AppConstants.fireRefreshEventOnWindow(); }, 300);
} else if (layout === 'fixed' && this.isfixChecked === false) {
this._renderer.removeClass(footer, 'fixed-bottom');
setTimeout(() => { AppConstants.fireRefreshEventOnWindow(); }, 300);
this._themeSettingsConfig.layout.pattern = '';
}
}
fixedLayout() {
const footer = document.getElementById('footer');
const headerNavbar = document.getElementsByClassName('header-navbar');
const menuHeader = document.getElementById('menu-header');
const element = document.getElementById('sticky-wrapper');
this._renderer.addClass(footer, 'fixed-bottom');
this._renderer.removeClass(document.body, 'boxed-layout');
this._renderer.removeClass(headerNavbar.item(0), 'boxed-layout');
this._renderer.removeClass(headerNavbar.item(0), 'container');
this._renderer.removeClass(document.body, 'container');
element.classList.remove('container');
if (this.isStaticLayout === true) {
this._renderer.removeClass(headerNavbar.item(0), 'fixed-top');
this._renderer.removeClass(footer, 'fixed-bottom');
this._renderer.addClass(headerNavbar.item(0), 'navbar-static-top');
this._renderer.addClass(menuHeader, 'navbar-static');
this._renderer.addClass(footer, 'footer-static');
}
this.isfixChecked = true;
this.isboxChecked = false;
this._themeSettingsConfig.layout.pattern = 'fixed';
}
boxedLayout() {
const footer = document.getElementById('footer');
const headerNavbar = document.getElementsByClassName('header-navbar');
const menuHeader = document.getElementById('menu-header');
const element = document.getElementById('sticky-wrapper');
this._renderer.removeClass(footer, 'fixed-bottom');
this._renderer.addClass(headerNavbar.item(0), 'container');
this._renderer.addClass(headerNavbar.item(0), 'boxed-layout');
this._renderer.addClass(document.body, 'boxed-layout');
this._renderer.addClass(document.body, 'container');
element.classList.add('container');
if (this.isStaticLayout === true) {
this._renderer.removeClass(headerNavbar.item(0), 'fixed-top');
this._renderer.addClass(headerNavbar.item(0), 'navbar-static-top');
this._renderer.addClass(menuHeader, 'navbar-static');
this._renderer.addClass(footer, 'footer-static');
}
this.isboxChecked = true;
this.isfixChecked = false;
this._themeSettingsConfig.layout.pattern = 'boxed';
}
}

View File

@@ -0,0 +1,29 @@
<footer id="footer" class="footer footer-static footer-light navbar-border navbar-shadow" *ngIf="showFooter">
<p class="clearfix blue-grey lighten-2 text-sm-center mb-0 px-2"><span
class="float-md-left d-block d-md-inline-block">Copyright &copy; 2022 <a [routerLink]=""
class="text-bold-800 grey darken-2" href="https://themeforest.net/user/pixinvent/portfolio?ref=pixinvent"
target="_blank">PIXINVENT </a></span><span *ngIf="!hideMadeWithLove"
class="float-md-right d-block d-md-inline-block d-none d-lg-block">Hand-crafted & Made with <i
class="feather ft-heart pink"></i>
<span id="scroll-top"></span></span></p>
</footer>
<footer id="footer" class="footer fixed-bottom footer-light navbar-border navbar-shadow" *ngIf="fixedFooter">
<p class="clearfix blue-grey lighten-2 text-sm-center mb-0 px-2"><span
class="float-md-left d-block d-md-inline-block">Copyright &copy; 2022 <a [routerLink]=""
class="text-bold-800 grey darken-2" href="https://themeforest.net/user/pixinvent/portfolio?ref=pixinvent"
target="_blank">PIXINVENT </a></span><span *ngIf="!hideMadeWithLove"
class="float-md-right d-block d-md-inline-block d-none d-lg-block">Hand-crafted & Made with <i
class="feather ft-heart pink"></i>
<span id="scroll-top"></span></span></p>
</footer>
<footer id="footer" class="footer fixed-bottom footer-dark navbar-border navbar-shadow" *ngIf="darkFooter">
<p class="clearfix blue-grey lighten-2 text-sm-center mb-0 px-2"><span
class="float-md-left d-block d-md-inline-block">Copyright &copy; 2022 <a [routerLink]=""
class="text-bold-800 grey darken-2" href="https://themeforest.net/user/pixinvent/portfolio?ref=pixinvent"
target="_blank">PIXINVENT </a></span><span *ngIf="!hideMadeWithLove"
class="float-md-right d-block d-md-inline-block d-none d-lg-block">Hand-crafted & Made with <i
class="feather ft-heart pink"></i>
<span id="scroll-top"></span></span></p>
</footer>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { FooterComponent } from './footer.component';
describe('FooterComponent', () => {
let component: FooterComponent;
let fixture: ComponentFixture<FooterComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ FooterComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FooterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,77 @@
import { Component, OnInit, Renderer2 } from '@angular/core';
import { ThemeSettingsService } from '../settings/theme-settings.service';
import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { Router, NavigationEnd, NavigationStart, Event } from '@angular/router';
import { FullLayoutComponent } from '../full-layout/full-layout.component';
import { AppConstants } from 'src/app/_helpers/app.constants';
@Component({
selector: 'app-footer',
templateUrl: './footer.component.html',
styleUrls: ['./footer.component.css']
})
export class FooterComponent implements OnInit {
public showFooter: boolean;
public fixedFooter: boolean;
public darkFooter: boolean;
public hideMadeWithLove: boolean;
private _unsubscribeAll: Subject<any>;
private _themeSettingsConfig: any;
constructor(private renderer: Renderer2,
private _renderer: Renderer2,
private router: Router,
private _themeSettingsService: ThemeSettingsService) {
this._unsubscribeAll = new Subject();
this.router.events.subscribe((event: Event) => {
const footerElement = document.getElementsByClassName('footer');
if (event instanceof NavigationStart) {
// Show loading indicator
}
if (event instanceof NavigationEnd) {
if (this.router.url === '/email' && footerElement.item(0)) {
this._renderer.removeClass(footerElement.item(0), 'footer-static');
this.renderer.addClass(footerElement.item(0), 'fixed-bottom');
} else if (footerElement.item(0)) {
this._renderer.removeClass(footerElement.item(0), 'fixed-bottom');
this.renderer.addClass(footerElement.item(0), 'footer-static');
}
}
});
}
ngOnInit() {
const isMobile = window.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH;
if ((this.router.url.indexOf('WithNavbar') >= 0) || (this.router.url.indexOf('Advanced') >= 0) ||
(this.router.url.indexOf('searchPage') >= 0)) {
this.showFooter = false;
this.darkFooter = true;
this.fixedFooter = false;
} else if (this.router.url.indexOf('email') >= 0) {
this.showFooter = false;
this.darkFooter = false;
this.fixedFooter = true;
} else if (FullLayoutComponent) {
this.showFooter = true;
this.darkFooter = false;
this.fixedFooter = false;
} else {
this.showFooter = true;
this.darkFooter = false;
this.fixedFooter = false;
}
if (isMobile) {
this.hideMadeWithLove = true;
}
// Subscribe to config changes
this._themeSettingsService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._themeSettingsConfig = config;
});
}
}

View File

@@ -0,0 +1,4 @@
<app-full-layout-navbar *ngIf="showNavbar"></app-full-layout-navbar>
<router-outlet></router-outlet>
<div class="sidenav-overlay d-none" id="sidenav-overlay" (click)="rightbar($event)"></div>
<app-footer *ngIf="showFooter"></app-footer>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { FullLayoutComponent } from './full-layout.component';
describe('FullLayoutComponent', () => {
let component: FullLayoutComponent;
let fixture: ComponentFixture<FullLayoutComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ FullLayoutComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FullLayoutComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,124 @@
import { Component, OnInit, Renderer2, Inject } from '@angular/core';
import { Router } from '@angular/router';
import { DOCUMENT } from '@angular/common';
@Component({
selector: 'app-full-layout',
templateUrl: './full-layout.component.html',
styleUrls: ['./full-layout.component.css']
})
export class FullLayoutComponent implements OnInit {
public showFooter = true;
public showNavbar = true;
constructor(private renderer: Renderer2,
private router: Router,
@Inject(DOCUMENT) private document: Document) {
}
ngOnInit() {
this.renderer.removeClass(document.body, 'vertical-overlay-menu');
this.renderer.removeClass(document.body, 'bg-full-screen-image');
this.renderer.removeClass(document.body, 'vertical-menu-modern');
this.renderer.addClass(document.body, 'blank-page');
this.renderer.addClass(document.body, 'pace-done');
if ((this.router.url.indexOf('WithNavbar') >= 0) || (this.router.url.indexOf('Advanced') >= 0)) {
this.showFooter = true;
this.showNavbar = true;
this.renderer.addClass(document.body, 'bg-cyan');
this.renderer.addClass(document.body, 'bg-lighten-2');
this.renderer.addClass(document.body, 'fixed-navbar');
this.renderer.removeClass(document.body, 'blank-page');
} else if (this.router.url.indexOf('WithBgImage') >= 0) {
this.showFooter = false;
this.showNavbar = false;
this.renderer.addClass(document.body, 'bg-full-screen-image');
this.renderer.removeClass(document.body, 'fixed-navbar');
} else if (this.router.url.indexOf('WithBg') >= 0) {
this.showFooter = false;
this.showNavbar = false;
this.renderer.addClass(document.body, 'bg-cyan');
this.renderer.addClass(document.body, 'bg-lighten-2');
this.renderer.removeClass(document.body, 'fixed-navbar');
} else if (this.router.url.indexOf('Simple') >= 0) {
this.showFooter = false;
this.showNavbar = false;
this.renderer.removeClass(document.body, 'fixed-navbar');
} else if (this.router.url.indexOf('searchPage') >= 0) {
this.showFooter = true;
this.showNavbar = true;
this.renderer.addClass(document.body, 'fixed-navbar');
} else if (this.router.url.indexOf('flat') >= 0) {
this.showFooter = false;
this.showNavbar = false;
this.renderer.removeClass(document.body, 'fixed-navbar');
this.renderer.addClass(document.body, 'comingsoonFlat');
} else if (this.router.url === '/others/bgImage') {
this.showFooter = false;
this.showNavbar = false;
this.renderer.removeClass(document.body, 'fixed-navbar');
this.renderer.addClass(document.body, 'comingsoonOne');
} else if (this.router.url.indexOf('bgVideo') >= 0) {
this.showFooter = false;
this.showNavbar = false;
this.renderer.removeClass(document.body, 'fixed-navbar');
this.renderer.addClass(document.body, 'comingsoonVideo');
} else if (this.router.url.indexOf('flat') >= 0) {
this.showFooter = false;
this.showNavbar = false;
this.renderer.removeClass(document.body, 'fixed-navbar');
this.renderer.addClass(document.body, 'comingsoonFlat');
} else if (this.router.url.indexOf('error400') >= 0 && this.router.url.indexOf('error400Withnavbar') <= 0 ) {
this.showFooter = false;
this.showNavbar = false;
this.renderer.removeClass(document.body, 'fixed-navbar');
} else if (this.router.url.indexOf('error401') >= 0 && this.router.url.indexOf('error401Withnavbar') <= 0 ) {
this.showFooter = false;
this.showNavbar = false;
this.renderer.removeClass(document.body, 'fixed-navbar');
} else if (this.router.url.indexOf('error403') >= 0 && this.router.url.indexOf('error403Withnavbar') <= 0 ) {
this.showFooter = false;
this.showNavbar = false;
this.renderer.removeClass(document.body, 'fixed-navbar');
} else if (this.router.url.indexOf('error404') >= 0 && this.router.url.indexOf('error404Withnavbar') <= 0 ) {
this.showFooter = false;
this.showNavbar = false;
this.renderer.removeClass(document.body, 'fixed-navbar');
} else if (this.router.url.indexOf('error500') >= 0 && this.router.url.indexOf('error500Withnavbar') <= 0 ) {
this.showFooter = false;
this.showNavbar = false;
this.renderer.removeClass(document.body, 'fixed-navbar');
} else if (this.router.url.indexOf('maintenance') >= 0 || this.router.url.indexOf('recoverPassword') >= 0) {
this.showFooter = false;
this.showNavbar = false;
this.renderer.removeClass(document.body, 'fixed-navbar');
} else if (this.router.url.indexOf('unlockUser') >= 0 ) {
this.showFooter = false;
this.showNavbar = false;
this.renderer.removeClass(document.body, 'fixed-navbar');
} else {
this.showFooter = false;
this.showNavbar = false;
this.renderer.removeClass(document.body, 'bg-cyan');
this.renderer.removeClass(document.body, 'bg-lighten-2');
}
}
rightbar(event) {
const toggle = document.getElementById('sidenav-overlay');
if (event.currentTarget.className === 'sidenav-overlay d-block') {
this.renderer.removeClass(toggle, 'd-block');
this.document.body.classList.remove('menu-open');
this.document.body.classList.add('menu-close');
this.renderer.addClass(toggle, 'd-none');
} else if (event.currentTarget.className === 'sidenav-overlay d-none') {
this.renderer.removeClass(toggle, 'd-none');
this.document.body.classList.remove('menu-close');
this.document.body.classList.add('menu-open');
this.renderer.addClass(toggle, 'd-block');
}
}
}

View File

@@ -0,0 +1,11 @@
@media (min-width: 767.98px) {
.collapse:not(.show) {
display: flex !important;
}
}
@media (min-width: 767.98px) {
.justify-content-end {
display: flex !important;
}
}

View File

@@ -0,0 +1,28 @@
<nav
class="header-navbar navbar-expand-md navbar navbar-with-menu navbar-without-dd-arrow fixed-top navbar-dark navbar-shadow">
<div class="navbar-wrapper">
<div class="navbar-header">
<ul class="nav navbar-nav flex-row">
<li class="nav-item mobile-menu d-md-none mr-auto"><a class="nav-link nav-menu-main menu-toggle hidden-xs"
[routerLink]="">
<i class="feather ft-menu font-large-1"></i></a></li>
<li class="nav-item"><a class="navbar-brand" [routerLink]="['/dashboard/sales']"><img class="brand-logo"
alt="modern admin logo" src="../../../../assets/images/logo/logo.png">
<h3 class="brand-text">Modern </h3>
</a></li>
<li class="nav-item d-md-none"><a class="nav-link open-navbar-container" data-toggle="collapse"
data-target="#navbar-mobile" (click)="toggleNavbar($event)"><i class="la la-ellipsis-v"></i></a></li>
</ul>
</div>
<div class="navbar-container">
<div class="collapse navbar-collapse justify-content-end" id="navbar-mobile">
<ul class="nav navbar-nav">
<li class="nav-item"><a class="nav-link mr-2 nav-link-label" [routerLink]="['/dashboard/sales']"><i
class="ficon feather ft-arrow-left"></i></a></li>
<li class="dropdown nav-item"><a class="nav-link mr-2 nav-link-label" [routerLink]=""
data-toggle="dropdown"><i class="ficon feather ft-settings"></i></a></li>
</ul>
</div>
</div>
</div>
</nav>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { FullLayoutNavbarComponent } from './full-layout-navbar.component';
describe('FullLayoutNavbarComponent', () => {
let component: FullLayoutNavbarComponent;
let fixture: ComponentFixture<FullLayoutNavbarComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ FullLayoutNavbarComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FullLayoutNavbarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,23 @@
import { Component, OnInit, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Component({
selector: 'app-full-layout-navbar',
templateUrl: './full-layout-navbar.component.html',
styleUrls: ['./full-layout-navbar.component.css']
})
export class FullLayoutNavbarComponent {
constructor(
@Inject(DOCUMENT) private document: Document) { }
toggleNavbar(e) {
const navbar = this.document.getElementById('navbar-mobile');
if (navbar.classList.contains('show')) {
navbar.classList.remove('show');
} else {
navbar.classList.add('show');
}
}
}

View File

@@ -0,0 +1,7 @@
<ng-container *ngIf="layout === 'vertical'">
<app-header-vertical></app-header-vertical>
</ng-container>
<ng-container *ngIf="layout === 'horizontal'" (window:resize)="onResize($event)">
<app-header-horizontal></app-header-horizontal>
</ng-container>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { HeaderComponent } from './header.component';
describe('HeaderComponent', () => {
let component: HeaderComponent;
let fixture: ComponentFixture<HeaderComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ HeaderComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,125 @@
import { Component, OnInit, Renderer2, AfterViewInit, HostListener, Inject } from '@angular/core';
import { takeUntil } from 'rxjs/operators';
import { ThemeSettingsService } from '../settings/theme-settings.service';
import { Subject } from 'rxjs';
import { AppConstants } from '../../_helpers/app.constants';
import { DeviceDetectorService } from '../../_services/device-detector.service';
import { DOCUMENT } from '@angular/common';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit, AfterViewInit {
layout: string;
private _themeSettingsConfig: any;
private _unsubscribeAll: Subject<any>;
private isMobile = false;
public selectedColorClass = '';
constructor(private _renderer: Renderer2,
@Inject(DOCUMENT) private document: Document,
private _themeSettingsService: ThemeSettingsService,
private deviceService: DeviceDetectorService) {
this._unsubscribeAll = new Subject();
}
ngOnInit() {
const self = this;
// Subscribe to config changes
this._themeSettingsService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._themeSettingsConfig = config;
if (config.layout && config.layout.style &&
config.layout.style === 'vertical') {
self.layout = 'vertical';
} else {
self.layout = 'horizontal';
}
this.refreshView();
});
}
refreshView() {
const self = this;
const headerElement = document.getElementsByClassName('header-navbar');
if (headerElement.item(0)) {
let currentHeaderClassList = [];
const navbar = this.document.getElementById('navbar-mobile');
// Layout
if (self._themeSettingsConfig.layout.style === 'horizontal') {
currentHeaderClassList = ['header-navbar', 'navbar-expand-md', 'navbar', 'navbar-with-menu',
'navbar-without-dd-arrow', 'navbar-static-top'];
const topHeaderElement = document.getElementById('top-header');
if (window.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH_HORIZONTAL) {
currentHeaderClassList.push('fixed-top');
this._renderer.removeClass(topHeaderElement, 'navbar-brand-center');
navbar.classList.remove('show');
} else {
currentHeaderClassList.push('navbar-brand-center');
this._renderer.removeClass(topHeaderElement, 'fixed-top');
navbar.classList.add('show');
}
} else {
currentHeaderClassList = ['header-navbar', 'navbar-expand-md', 'navbar', 'navbar-with-menu', 'navbar-without-dd-arrow', 'fixed-top',
'navbar-shadow'];
if (self._themeSettingsConfig.colorTheme === 'semi-light' && self._themeSettingsConfig.layout.style === 'vertical') {
if (self._themeSettingsConfig.layout.style === 'vertical') {
// currentHeaderClassList.push('bg-info');
}
self._renderer.addClass(headerElement.item(0), 'navbar-semi-light');
self._renderer.removeClass(headerElement.item(0), 'navbar-dark');
self._renderer.removeClass(headerElement.item(0), 'navbar-semi-dark');
self._renderer.removeClass(headerElement.item(0), 'navbar-light');
} else if (self._themeSettingsConfig.colorTheme === 'semi-dark' && self._themeSettingsConfig.layout.style === 'vertical') {
self._renderer.addClass(headerElement.item(0), 'navbar-semi-dark');
self._renderer.removeClass(headerElement.item(0), 'navbar-semi-light');
self._renderer.removeClass(headerElement.item(0), 'navbar-light');
self._renderer.removeClass(headerElement.item(0), 'navbar-dark');
// self._renderer.removeClass(headerElement.item(0), 'bg-info');
} else if (self._themeSettingsConfig.colorTheme === 'dark' && self._themeSettingsConfig.layout.style === 'vertical') {
self._renderer.addClass(headerElement.item(0), 'navbar-dark');
self._renderer.removeClass(headerElement.item(0), 'navbar-semi-light');
self._renderer.removeClass(headerElement.item(0), 'navbar-light');
self._renderer.removeClass(headerElement.item(0), 'navbar-semi-dark');
// self._renderer.removeClass(headerElement.item(0), 'bg-info');
} else if (self._themeSettingsConfig.colorTheme === 'light' && self._themeSettingsConfig.layout.style === 'vertical') {
self._renderer.addClass(headerElement.item(0), 'navbar-light');
self._renderer.removeClass(headerElement.item(0), 'navbar-semi-light');
self._renderer.removeClass(headerElement.item(0), 'navbar-semi-dark');
self._renderer.removeClass(headerElement.item(0), 'navbar-dark');
// self._renderer.removeClass(headerElement.item(0), 'bg-info');
}
}
currentHeaderClassList.forEach(function (c) {
self._renderer.addClass(headerElement.item(0), c);
});
}
}
ngAfterViewInit() {
this.refreshView();
}
@HostListener('window:resize', ['$event'])
onResize(event) {
if (event.target.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH) {
this.isMobile = true;
} else {
this.isMobile = false;
}
this.refreshView();
}
}

View File

@@ -0,0 +1,12 @@
@media (max-width: 767.98px) {
.header-navbar .navbar-header {
width: 100% !important;
top: 3px;
}
}
.dropdown-menu-right {
right: 0;
left: auto !important;
top: auto !important;
}

View File

@@ -0,0 +1,215 @@
<!-- fixed-top-->
<nav
class="top-header header-navbar navbar-expand-md navbar navbar-with-menu navbar-without-dd-arrow navbar-static-top navbar-light navbar-brand-center"
id="top-header" [ngClass]="selectedHeaderNavBarClass">
<div class="navbar-wrapper">
<div id="navbar-header" class="navbar-header">
<ul class="nav navbar-nav flex-row">
<li class="nav-item mobile-menu d-md-none mr-auto" ><a
class="nav-link nav-menu-main menu-toggle hidden-xs11" (click)="toggleNavigation($event)"><i
class="feather ft-menu font-large-1" ></i></a></li>
<li class="nav-item"><a [routerLink]="['/dashboard/sales']" class="navbar-brand"><img class="brand-logo" alt="modern admin logo"
src="../../../../assets/images/logo/logo.png">
<h3 class="brand-text">{{_themeSettingsConfig.brand.brand_name}}</h3>
</a></li>
<li class="nav-item d-md-none"><a class="nav-link open-navbar-container" data-toggle="collapse"
data-target="#navbar-mobile" (click)="toggleNavbar($event)"><i class="la la-ellipsis-v"></i></a></li>
</ul>
</div>
<div class="navbar-container content">
<div class="collapse navbar-collapse show" id="navbar-mobile">
<ul class="nav navbar-nav mr-auto float-left">
<li class="nav-item d-none d-md-block"><a [routerLink]="" class="nav-link nav-menu-main menu-toggle hidden-xs"
(click)="toggleFixMenu($event)" ><i class="feather ft-menu"></i></a></li>
<li class="nav-item d-none d-md-block"><a [routerLink]="" class="nav-link nav-link-expand"
(click)="toggleFullScreen()" *ngIf ="maximize === 'on'"><i class="ficon feather ft-maximize"></i></a></li>
<li class="nav-item nav-search"><a [routerLink]="" class="nav-link nav-link-search" (click)="clickSearch()" *ngIf ="search === 'on'"><i
class="ficon feather ft-search"></i></a>
<div class="search-input" [ngClass]="{'open': isHeaderSearchOpen}">
<input class="input" type="text" placeholder="Explore Modern...">
</div>
</li>
</ul>
<ul class="nav navbar-nav float-right" >
<li class="dropdown-language nav-item" ngbDropdown *ngIf ="internationalization === 'on'">
<a [routerLink]="" class="dropdown-toggle nav-link" ngbDropdownToggle id="dropdown-flag">
<i class="flag-icon flag-icon-gb"></i><span class="selected-language"></span>
</a>
<div ngbDropdownMenu class="dropdown-menu" aria-labelledby="dropdownLangMenu">
<a [routerLink]="" class="dropdown-item">
<i class="flag-icon flag-icon-gb"></i> English
</a>
<a [routerLink]="" class="dropdown-item">
<i class="flag-icon flag-icon-fr"></i> French
</a>
<a [routerLink]="" class="dropdown-item">
<i class="flag-icon flag-icon-cn"></i> Chinese
</a>
<a [routerLink]="" class="dropdown-item">
<i class="flag-icon flag-icon-de"></i> German
</a>
</div>
</li>
<li class="dropdown-notification nav-item dropdown" ngbDropdown *ngIf ="notification === 'on'">
<a class="nav-link nav-link-label" ngbDropdownToggle>
<i class="ficon feather ft-bell"></i>
<span class="badge badge-pill badge-danger badge-up badge-glow">5</span>
</a>
<ul class="dropdown-menu-media dropdown-menu-right" ngbDropdownMenu>
<li class="dropdown-menu-header">
<h6 class="dropdown-header m-0"><span class="grey darken-2">Notifications</span></h6><span
class="notification-tag badge badge-default badge-danger float-right m-0">5 New</span>
</li>
<li class="scrollable-container media-list w-100 ps-container ps-theme-dark ps-active-y" fxFlex="auto"
[perfectScrollbar]="config">
<a href="javascript:void(0)">
<div class="media">
<div class="media-left align-self-center"><i class="feather ft-plus-square icon-bg-circle bg-cyan"></i>
</div>
<div class="media-body">
<h6 class="media-heading">You have new order!</h6>
<p class="notification-text font-small-3 text-muted">Lorem ipsum dolor sit amet, consectetuer
elit.</p><small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">30 minutes
ago</time></small>
</div>
</div>
</a>
<a href="javascript:void(0)">
<div class="media">
<div class="media-left align-self-center"><i
class="feather ft-download-cloud icon-bg-circle bg-red bg-darken-1"></i></div>
<div class="media-body">
<h6 class="media-heading red darken-1">99% Server load</h6>
<p class="notification-text font-small-3 text-muted">Aliquam tincidunt mauris eu risus.</p><small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">Five hour
ago</time></small>
</div>
</div>
</a>
<a href="javascript:void(0)">
<div class="media">
<div class="media-left align-self-center"><i
class="feather ft-alert-triangle icon-bg-circle bg-yellow bg-darken-3"></i></div>
<div class="media-body">
<h6 class="media-heading yellow darken-3">Warning notifixation</h6>
<p class="notification-text font-small-3 text-muted">Vestibulum auctor dapibus neque.</p><small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">Today</time></small>
</div>
</div>
</a>
<a href="javascript:void(0)">
<div class="media">
<div class="media-left align-self-center"><i class="feather ft-check-circle icon-bg-circle bg-cyan"></i>
</div>
<div class="media-body">
<h6 class="media-heading">Complete the task</h6><small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">Last
week</time></small>
</div>
</div>
</a>
<a href="javascript:void(0)">
<div class="media">
<div class="media-left align-self-center"><i class="feather ft-file icon-bg-circle bg-teal"></i></div>
<div class="media-body">
<h6 class="media-heading">Generate monthly report</h6><small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">Last
month</time></small>
</div>
</div>
</a>
</li>
<li class="dropdown-menu-footer"><a class="dropdown-item text-muted text-center"
href="javascript:void(0)">Read all notifications</a></li>
</ul>
</li>
<li class="dropdown-notification nav-item" ngbDropdown *ngIf ="email === 'on'">
<a class="nav-link nav-link-label" ngbDropdownToggle><i class="ficon feather ft-mail"></i></a>
<ul class="dropdown-menu-media dropdown-menu-right" ngbDropdownMenu>
<li class="dropdown-menu-header">
<h6 class="dropdown-header m-0"><span class="grey darken-2">Messages</span></h6><span
class="notification-tag badge badge-default badge-warning float-right m-0">4 New</span>
</li>
<li class="scrollable-container media-list w-100 ps-container ps-theme-dark ps-active-y" fxFlex="auto"
[perfectScrollbar]="config">
<a href="javascript:void(0)">
<div class="media">
<div class="media-left"><span class="avatar avatar-sm avatar-online rounded-circle"><img
src="../../../../assets/images/portrait/small/avatar-s-19.png" alt="avatar"><i></i></span></div>
<div class="media-body">
<h6 class="media-heading">Margaret Govan</h6>
<p class="notification-text font-small-3 text-muted">I like your portfolio, let's start.</p>
<small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">Today</time></small>
</div>
</div>
</a>
<a href="javascript:void(0)">
<div class="media">
<div class="media-left"><span class="avatar avatar-sm avatar-busy rounded-circle"><img
src="../../../../assets/images/portrait/small/avatar-s-2.png" alt="avatar"><i></i></span></div>
<div class="media-body">
<h6 class="media-heading">Bret Lezama</h6>
<p class="notification-text font-small-3 text-muted">I have seen your work, there is</p><small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">Tuesday</time></small>
</div>
</div>
</a>
<a href="javascript:void(0)">
<div class="media">
<div class="media-left"><span class="avatar avatar-sm avatar-online rounded-circle"><img
src="../../../../assets/images/portrait/small/avatar-s-3.png" alt="avatar"><i></i></span></div>
<div class="media-body">
<h6 class="media-heading">Carie Berra</h6>
<p class="notification-text font-small-3 text-muted">Can we have call in this week ?</p><small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">Friday</time></small>
</div>
</div>
</a>
<a href="javascript:void(0)">
<div class="media border_bottom">
<div class="media-left"><span class="avatar avatar-sm avatar-away rounded-circle"><img
src="../../../../assets/images/portrait/small/avatar-s-6.png" alt="avatar"><i></i></span></div>
<div class="media-body">
<h6 class="media-heading">Eric Alsobrook</h6>
<p class="notification-text font-small-3 text-muted">We have project party this saturday.</p>
<small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">last
month</time></small>
</div>
</div>
</a>
</li>
<li class="dropdown-menu-footer"><a class="dropdown-item text-muted text-center"
href="javascript:void(0)">Read all messages</a></li>
</ul>
</li>
<li class="dropdown-user nav-item" ngbDropdown>
<a class="nav-link dropdown-user-link" ngbDropdownToggle>
<span *ngIf="currentUser.displayName"
class="mr-1 user-name text-bold-700">{{currentUser.displayName}}</span>
<span *ngIf="!currentUser.displayName" class="mr-1 user-name text-bold-700">John Doe</span>
<span class="avatar avatar-online">
<img *ngIf="currentUser.photoURL" src="{{currentUser.photoURL}}" alt="avatar">
<img *ngIf="!currentUser.photoURL" src="../../../../assets/images/portrait/small/avatar-s-19.png"
alt="avatar">
<i></i>
</span>
</a>
<div ngbDropdownMenu class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownProfileMenu">
<a class="dropdown-item" [routerLink]="['/user/user-profile']"><i class="feather ft-user"></i> Edit Profile </a>
<a class="dropdown-item" [routerLink]="['/email']"><i class="feather ft-mail"></i> My Inbox </a>
<a class="dropdown-item" [routerLink]="['/todos']"><i class="feather ft-check-square"></i> Task </a>
<a class="dropdown-item" [routerLink]="['/chats']"><i class="feather ft-message-square"></i> Chats </a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" [routerLink]="" (click)="logout()"><i class="feather ft-power"></i> Logout</a>
</div>
</li>
</ul>
</div>
</div>
</div>
</nav>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { HorizontalComponent } from './horizontal.component';
describe('HorizontalComponent', () => {
let component: HorizontalComponent;
let fixture: ComponentFixture<HorizontalComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ HorizontalComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HorizontalComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,280 @@
import { Component, OnInit, Inject, Renderer2, HostListener, AfterViewInit, ViewChild } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { NavbarService } from '../../../_services/navbar.service';
import { ThemeSettingsService } from '../../settings/theme-settings.service';
import { MenuSettingsService } from '../../settings/menu-settings.service';
import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { AppConstants } from 'src/app/_helpers/app.constants';
import { AuthService } from 'src/app/_services/auth.service';
import { Router } from '@angular/router';
import { DeviceDetectorService } from '../../../_services/device-detector.service';
import { PerfectScrollbarConfigInterface, PerfectScrollbarComponent, PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
const docElmWithBrowsersFullScreenFunctions = document.documentElement as HTMLElement & {
mozRequestFullScreen(): Promise<void>;
webkitRequestFullscreen(): Promise<void>;
msRequestFullscreen(): Promise<void>;
};
const docWithBrowsersExitFunctions = document as Document & {
mozCancelFullScreen(): Promise<void>;
webkitExitFullscreen(): Promise<void>;
msExitFullscreen(): Promise<void>;
};
@Component({
selector: 'app-header-horizontal',
templateUrl: './horizontal.component.html',
styleUrls: ['./horizontal.component.css']
})
export class HorizontalComponent implements OnInit, AfterViewInit {
insideTm: any;
outsideTm: any;
private _unsubscribeAll: Subject<any>;
brandName: string;
brandLogo: string;
public currentUser: any;
public _themeSettingsConfig: any;
private _menuSettingsConfig: any;
public displayName: boolean;
public isHeaderSearchOpen: any;
public maximize: any;
public search: any;
public internationalization: any;
public notification: any;
public email: any;
// public collapseOne = false;
// public collapseTwo = false;
// public collapseThree = false;
public selectedHeaderNavBarClass: string;
public selectedNavBarHeaderClass: string;
placement = 'bottom-right';
public config: PerfectScrollbarConfigInterface = { wheelPropagation: false };
@ViewChild(PerfectScrollbarComponent) componentRef?: PerfectScrollbarComponent;
@ViewChild(PerfectScrollbarDirective, { static: true }) directiveRef?: PerfectScrollbarDirective;
constructor(
@Inject(DOCUMENT) private document: Document,
private _renderer: Renderer2,
private renderer: Renderer2,
private navbarService: NavbarService,
public authService: AuthService,
private router: Router,
private _menuSettingsService: MenuSettingsService,
private _themeSettingsService: ThemeSettingsService,
private deviceService: DeviceDetectorService
) {
this._unsubscribeAll = new Subject();
}
ngOnInit() {
const _self = this;
if (localStorage.getItem('currentUser')) {
this.currentUser = JSON.parse(localStorage.getItem('currentUser'));
}
// Subscribe to config changes
this._themeSettingsService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._themeSettingsConfig = config;
this.refreshView();
});
this._menuSettingsService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._menuSettingsConfig = config;
});
const isMobile = this.deviceService.isMobile();
this.handleBody(isMobile);
this.maximize = this._themeSettingsConfig.headerIcons.maximize;
this.search = this._themeSettingsConfig.headerIcons.search;
this.internationalization = this._themeSettingsConfig.headerIcons.internationalization;
this.notification = this._themeSettingsConfig.headerIcons.notification;
this.email = this._themeSettingsConfig.headerIcons.email;
}
ngAfterViewInit(): void {
this.refreshView();
}
handleBody(isMobile: boolean) {
const _self = this;
let currentBodyClassList = [];
if (window.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH_HORIZONTAL && this._themeSettingsConfig.layout.style === 'horizontal') {
currentBodyClassList = ['horizontal-layout', '2-columns', 'vertical-overlay-menu', 'menu-hide'];
currentBodyClassList.push('fixed-navbar');
}
currentBodyClassList.forEach(function (c) {
_self.renderer.addClass(document.body, c);
});
}
logout() {
if (localStorage.getItem('currentUser')) {
this.authService.doLogout().then(res => {
this.router.navigate(['/login']);
}, err => {
console.log(err);
});
}
}
refreshView() {
const topHeaderElement = document.getElementsByClassName('top-header');
const menuColorElement = document.getElementsByClassName('menu-header');
const navigationElement = document.getElementsByClassName('menu-header');
if (topHeaderElement) {
if (this._themeSettingsConfig.colorTheme === 'light') {
this._renderer.removeClass(topHeaderElement.item(0), 'navbar-dark');
this._renderer.addClass(topHeaderElement.item(0), 'navbar-light');
} else if (this._themeSettingsConfig.colorTheme === 'dark') {
this._renderer.addClass(topHeaderElement.item(0), 'navbar-dark');
this._renderer.removeClass(topHeaderElement.item(0), 'navbar-light');
}
}
if (this._themeSettingsConfig.layout.style === 'horizontal') {
this.selectedHeaderNavBarClass = this._themeSettingsConfig.color;
} else if (this._themeSettingsConfig.layout.style === 'horizontal') {
this.selectedHeaderNavBarClass = this._themeSettingsConfig.color;
}
if (navigationElement) {
if (this._themeSettingsConfig.navigation === 'navbar-icon-right') {
this._renderer.addClass(navigationElement.item(0), 'navbar-icon-right');
}
}
if (menuColorElement) {
if (this._themeSettingsConfig.menuColor === 'navbar-dark') {
this._renderer.removeClass(menuColorElement.item(0), 'navbar-light');
this._renderer.addClass(menuColorElement.item(0), 'navbar-dark');
} else if (this._themeSettingsConfig.menuColor === 'navbar-light') {
this._renderer.removeClass(menuColorElement.item(0), 'navbar-dark');
this._renderer.addClass(menuColorElement.item(0), 'navbar-light');
}
}
}
toggleFixMenu(e) {
if (this.document.body.classList.contains('menu-expanded')) {
// show the left aside menu
this.document.body.classList.remove('menu-expanded');
this.document.body.classList.add('menu-collapsed');
} else {
this.document.body.classList.remove('menu-collapsed');
this.document.body.classList.add('menu-expanded');
}
}
toggleNavbar(e) {
const navbar = this.document.getElementById('navbar-mobile');
if (navbar.classList.contains('show')) {
navbar.classList.remove('show');
} else {
navbar.classList.add('show');
}
}
toggleNavigation(e) {
const sidenav = document.getElementById('sidenav-overlay');
const sidebarLeft = document.getElementById('sidebar-left') || document.getElementById('email-app-menu') ||
document.getElementById('sidebar-todo');
const contentOverlay = document.getElementById('content-overlay');
const navbar = this.document.getElementById('navbar-mobile');
if (this.document.body.classList.contains('menu-hide')) {
this.document.body.classList.remove('menu-hide');
this._renderer.removeClass(sidenav, 'd-none');
this._renderer.addClass(sidenav, 'd-block');
this.document.body.classList.remove('menu-close');
this.document.body.classList.add('menu-open');
this.document.body.classList.add('menu-expanded');
navbar.classList.remove('show');
} else if (!this.document.body.classList.contains('menu-hide') && !this.document.body.classList.contains('menu-open') ) {
this.document.body.classList.add('menu-open');
this._renderer.addClass(sidenav, 'd-block');
this._renderer.removeClass(sidenav, 'd-none');
} else {
this._renderer.removeClass(sidenav, 'd-block');
this.document.body.classList.remove('menu-open');
this.document.body.classList.add('menu-hide');
this._renderer.addClass(sidenav, 'd-none');
navbar.classList.remove('show');
}
if (sidebarLeft) {
this._renderer.removeClass(sidebarLeft, 'show');
this._renderer.removeClass(contentOverlay, 'show');
}
}
toggleFullScreen() {
const toggleIcon = document.getElementsByClassName('ficon');
if (toggleIcon.item(0).classList.contains('ft-maximize')) {
this.openfullscreen();
this._renderer.removeClass(toggleIcon.item(0), 'ft-maximize');
this._renderer.addClass(toggleIcon.item(0), 'ft-minimize');
} else if (toggleIcon.item(0).classList.contains('ft-minimize')) {
this.closefullscreen();
this._renderer.addClass(toggleIcon.item(0), 'ft-maximize');
this._renderer.removeClass(toggleIcon.item(0), 'ft-minimize');
}
}
openfullscreen() {
// Trigger fullscreen
// eslint-disable-next-line no-shadow,@typescript-eslint/no-shadow
const docElmWithBrowsersFullScreenFunctions = document.documentElement as HTMLElement & {
mozRequestFullScreen(): Promise<void>;
webkitRequestFullscreen(): Promise<void>;
msRequestFullscreen(): Promise<void>;
};
if (docElmWithBrowsersFullScreenFunctions.requestFullscreen) {
docElmWithBrowsersFullScreenFunctions.requestFullscreen();
} else if (docElmWithBrowsersFullScreenFunctions.mozRequestFullScreen) { /* Firefox */
docElmWithBrowsersFullScreenFunctions.mozRequestFullScreen();
} else if (docElmWithBrowsersFullScreenFunctions.webkitRequestFullscreen) { /* Chrome, Safari and Opera */
docElmWithBrowsersFullScreenFunctions.webkitRequestFullscreen();
} else if (docElmWithBrowsersFullScreenFunctions.msRequestFullscreen) { /* IE/Edge */
docElmWithBrowsersFullScreenFunctions.msRequestFullscreen();
}
}
closefullscreen() {
// eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
const docWithBrowsersExitFunctions = document as Document & {
mozCancelFullScreen(): Promise<void>;
webkitExitFullscreen(): Promise<void>;
msExitFullscreen(): Promise<void>;
};
if (docWithBrowsersExitFunctions.exitFullscreen) {
docWithBrowsersExitFunctions.exitFullscreen();
} else if (docWithBrowsersExitFunctions.mozCancelFullScreen) { /* Firefox */
docWithBrowsersExitFunctions.mozCancelFullScreen();
} else if (docWithBrowsersExitFunctions.webkitExitFullscreen) { /* Chrome, Safari and Opera */
docWithBrowsersExitFunctions.webkitExitFullscreen();
} else if (docWithBrowsersExitFunctions.msExitFullscreen) { /* IE/Edge */
docWithBrowsersExitFunctions.msExitFullscreen();
}
}
@HostListener('window:resize', ['$event'])
onResize(event) {
const sidenav = document.getElementById('sidenav-overlay');
if (event.target.innerWidth <= 767) {
this.document.body.classList.add('vertical-overlay-menu');
this._renderer.removeClass(sidenav, 'd-block');
this._renderer.addClass(sidenav, 'd-none');
}
}
public clickSearch() {
if (this.isHeaderSearchOpen) {
this.isHeaderSearchOpen = false;
} else {
this.isHeaderSearchOpen = true;
}
}
}

View File

@@ -0,0 +1,35 @@
.dropdown-menu-right {
right: 0;
left: auto !important;
top: auto !important;
}
.header-navbar .navbar-container ul.nav li a.dropdown-user-link .user-name {
margin-left: 0rem !important;
}
.border_bottom {
border-bottom: none !important;
}
:host ::ng-deep .dropdown-item:active {
color: #fff !important;
}
@media only screen and (max-width: 991.98px) {
.ft-toggle-right {
display: none !important;
}
.ft-toggle-left {
display: none !important;
}
.collapse:not(.show) {
display: unset !important;
}
}
.header-navbar .navbar-header .navbar-brand .brand-text {
padding-left: 11px !important;
}

View File

@@ -0,0 +1,226 @@
<nav class="header-navbar navbar-expand-md navbar navbar-with-menu navbar-without-dd-arrow fixed-top navbar-shadow"
[ngClass]="selectedHeaderNavBarClass">
<div class="navbar-wrapper">
<div id="navbar-header" class="navbar-header" [ngClass]="selectedNavBarHeaderClass"
(mouseenter)="mouseEnter($event)" (mouseleave)="mouseLeave($event)">
<ul class="nav navbar-nav flex-row">
<!-- Remove position relative in responsive -->
<li class="nav-item mobile-menu d-lg-none mr-auto"><a class="nav-link nav-menu-main menu-toggle hidden-xs11"
(click)="toggleNavigation($event)">
<i class="feather ft-menu font-large-1"></i></a></li>
<li class="nav-item mr-auto"><a [routerLink]="['/dashboard/sales']" class="navbar-brand"
routerLink="/dashboard/sales"><img class="brand-logo" alt="modern admin logo"
[src]="_themeSettingsConfig.brand.logo.value">
<h3 class="brand-text">{{_themeSettingsConfig.brand.brand_name}}</h3>
</a></li>
<li class="nav-item d-none d-md-block nav-toggle">
<a [routerLink]="" class="nav-link modern-nav-toggle pr-0" data-toggle="collapse"
(click)="toggleFixMenu($event)">
<i class="feather toggle-icon font-medium-3 white"
[ngClass]="{'ft-toggle-left': _themeSettingsConfig.menu === 'collapse','ft-toggle-right': _themeSettingsConfig.menu === 'expand'}"></i>
</a>
</li>
<li class="nav-item d-lg-none"><a class="nav-link open-navbar-container" data-toggle="collapse"
data-target="#navbar-mobile" (click)="toggleNavbar($event)"><i class="la la-ellipsis-v"></i></a></li>
</ul>
</div>
<!-- New-->
<div class="navbar-container content" [hidden]="isMobile && !showNavbar">
<div class="collapse navbar-collapse" id="navbar-mobile">
<ul class="nav navbar-nav mr-auto float-left">
<li class="nav-item d-none d-md-block"><a [routerLink]="" class="nav-link nav-link-expand"
(click)="toggleFullScreen()" *ngIf="maximize === 'on'"><i class="ficon feather ft-maximize"></i></a></li>
<li class="nav-item nav-search"><a [routerLink]="" class="nav-link nav-link-search" (click)="clickSearch()"
*ngIf="search === 'on'"><i class="ficon feather ft-search"></i></a>
<div class="search-input" [ngClass]="{'open': isHeaderSearchOpen}">
<input class="input" type="text" placeholder="Explore Modern...">
</div>
</li>
</ul>
<ul class="nav navbar-nav float-right">
<li class="dropdown-language nav-item" ngbDropdown *ngIf="internationalization === 'on'">
<a [routerLink]="" class="dropdown-toggle nav-link" ngbDropdownToggle id="dropdown-flag">
<i class="flag-icon flag-icon-gb"></i><span class="selected-language"></span>
</a>
<div ngbDropdownMenu class="dropdown-menu" aria-labelledby="dropdownLangMenu">
<a [routerLink]="" class="dropdown-item">
<i class="flag-icon flag-icon-gb"></i> English
</a>
<a [routerLink]="" class="dropdown-item">
<i class="flag-icon flag-icon-fr"></i> French
</a>
<a [routerLink]="" class="dropdown-item">
<i class="flag-icon flag-icon-cn"></i> Chinese
</a>
<a [routerLink]="" class="dropdown-item">
<i class="flag-icon flag-icon-de"></i> German
</a>
</div>
</li>
<li class="dropdown-notification nav-item dropdown" ngbDropdown *ngIf="notification === 'on'">
<a class="nav-link nav-link-label" ngbDropdownToggle>
<i class="ficon feather ft-bell"></i>
<span class="badge badge-pill badge-danger badge-up badge-glow">5</span>
</a>
<ul class="dropdown-menu-media dropdown-menu-right" ngbDropdownMenu>
<li class="dropdown-menu-header">
<h6 class="dropdown-header m-0"><span class="grey darken-2">Notifications</span></h6><span
class="notification-tag badge badge-default badge-danger float-right m-0">5 New</span>
</li>
<li class="scrollable-container media-list w-100 ps-container ps-theme-dark ps-active-y" fxFlex="auto" [perfectScrollbar]="config">
<a href="javascript:void(0)">
<div class="media">
<div class="media-left align-self-center"><i
class="feather ft-plus-square icon-bg-circle bg-cyan"></i>
</div>
<div class="media-body">
<h6 class="media-heading">You have new order!</h6>
<p class="notification-text font-small-3 text-muted">Lorem ipsum dolor sit amet, consectetuer
elit.</p><small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">30 minutes
ago</time></small>
</div>
</div>
</a>
<a href="javascript:void(0)">
<div class="media">
<div class="media-left align-self-center"><i
class="feather ft-download-cloud icon-bg-circle bg-red bg-darken-1"></i></div>
<div class="media-body">
<h6 class="media-heading red darken-1">99% Server load</h6>
<p class="notification-text font-small-3 text-muted">Aliquam tincidunt mauris eu risus.</p><small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">Five hour
ago</time></small>
</div>
</div>
</a>
<a href="javascript:void(0)">
<div class="media">
<div class="media-left align-self-center"><i
class="feather ft-alert-triangle icon-bg-circle bg-yellow bg-darken-3"></i></div>
<div class="media-body">
<h6 class="media-heading yellow darken-3">Warning notifixation</h6>
<p class="notification-text font-small-3 text-muted">Vestibulum auctor dapibus neque.</p><small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">Today</time></small>
</div>
</div>
</a>
<a href="javascript:void(0)">
<div class="media">
<div class="media-left align-self-center"><i
class="feather ft-check-circle icon-bg-circle bg-cyan"></i>
</div>
<div class="media-body">
<h6 class="media-heading">Complete the task</h6><small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">Last
week</time></small>
</div>
</div>
</a>
<a href="javascript:void(0)">
<div class="media">
<div class="media-left align-self-center"><i class="feather ft-file icon-bg-circle bg-teal"></i>
</div>
<div class="media-body">
<h6 class="media-heading">Generate monthly report</h6><small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">Last
month</time></small>
</div>
</div>
</a>
</li>
<li class="dropdown-menu-footer"><a class="dropdown-item text-muted text-center"
href="javascript:void(0)">Read all notifications</a></li>
</ul>
</li>
<li class="dropdown-notification nav-item" ngbDropdown>
<a class="nav-link nav-link-label" ngbDropdownToggle *ngIf="email === 'on'"><i
class="ficon feather ft-mail"></i></a>
<ul class="dropdown-menu-media dropdown-menu-right" ngbDropdownMenu>
<li class="dropdown-menu-header">
<h6 class="dropdown-header m-0"><span class="grey darken-2">Messages</span></h6><span
class="notification-tag badge badge-default badge-warning float-right m-0">4 New</span>
</li>
<li class="scrollable-container media-list w-100 ps-container ps-theme-dark ps-active-y" fxFlex="auto"
[perfectScrollbar]="config">
<a href="javascript:void(0)">
<div class="media">
<div class="media-left"><span class="avatar avatar-sm avatar-online rounded-circle"><img
src="../../../assets/images/portrait/small/avatar-s-19.png" alt="avatar"><i></i></span></div>
<div class="media-body">
<h6 class="media-heading">Margaret Govan</h6>
<p class="notification-text font-small-3 text-muted">I like your portfolio, let's start.</p>
<small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">Today</time></small>
</div>
</div>
</a>
<a href="javascript:void(0)">
<div class="media">
<div class="media-left"><span class="avatar avatar-sm avatar-busy rounded-circle"><img
src="../../../assets/images/portrait/small/avatar-s-2.png" alt="avatar"><i></i></span></div>
<div class="media-body">
<h6 class="media-heading">Bret Lezama</h6>
<p class="notification-text font-small-3 text-muted">I have seen your work, there is</p><small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">Tuesday</time></small>
</div>
</div>
</a>
<a href="javascript:void(0)">
<div class="media">
<div class="media-left"><span class="avatar avatar-sm avatar-online rounded-circle"><img
src="../../../assets/images/portrait/small/avatar-s-3.png" alt="avatar"><i></i></span></div>
<div class="media-body">
<h6 class="media-heading">Carie Berra</h6>
<p class="notification-text font-small-3 text-muted">Can we have call in this week ?</p><small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">Friday</time></small>
</div>
</div>
</a>
<a href="javascript:void(0)">
<div class="media border_bottom">
<div class="media-left"><span class="avatar avatar-sm avatar-away rounded-circle"><img
src="../../../assets/images/portrait/small/avatar-s-6.png" alt="avatar"><i></i></span></div>
<div class="media-body">
<h6 class="media-heading">Eric Alsobrook</h6>
<p class="notification-text font-small-3 text-muted">We have project party this saturday.</p>
<small>
<time class="media-meta text-muted" datetime="2015-06-11T18:29:20+08:00">last
month</time></small>
</div>
</div>
</a>
</li>
<li class="dropdown-menu-footer"><a class="dropdown-item text-muted text-center"
href="javascript:void(0)">Read all messages</a></li>
</ul>
</li>
<li class="dropdown-user nav-item" ngbDropdown>
<a class="nav-link dropdown-user-link" ngbDropdownToggle>
<span *ngIf="currentUser.displayName"
class="mr-1 user-name text-bold-700">{{currentUser.displayName}}</span>
<span *ngIf="!currentUser.displayName" class="mr-1 user-name text-bold-700">John Doe</span>
<span class="avatar avatar-online">
<img *ngIf="currentUser.photoURL" src="{{currentUser.photoURL}}" alt="avatar">
<img *ngIf="!currentUser.photoURL" src="../../../assets/images/portrait/small/avatar-s-19.png"
alt="avatar">
<i></i>
</span>
</a>
<div ngbDropdownMenu class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownProfileMenu">
<a class="dropdown-item" [routerLink]="['/user/user-profile']"><i class="feather ft-user"></i> Edit
Profile </a>
<a class="dropdown-item" [routerLink]="['/email']"><i class="feather ft-mail"></i> My Inbox </a>
<a class="dropdown-item" [routerLink]="['/todos']"><i class="feather ft-check-square"></i> Task </a>
<a class="dropdown-item" [routerLink]="['/chats']"><i class="feather ft-message-square"></i> Chats </a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" [routerLink]="" (click)="logout()"><i class="feather ft-power"></i> Logout</a>
</div>
</li>
</ul>
</div>
</div>
<!-- New-->
</div>
</nav>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { VerticalComponent } from './vertical.component';
describe('VerticalComponent', () => {
let component: VerticalComponent;
let fixture: ComponentFixture<VerticalComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ VerticalComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(VerticalComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,477 @@
import { Component, OnInit, Inject, Renderer2, ElementRef, ViewChild, AfterViewInit, HostListener } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { NavbarService } from '../../../_services/navbar.service';
import { ThemeSettingsService } from '../../settings/theme-settings.service';
import { MenuSettingsService } from '../../settings/menu-settings.service';
import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { AuthService } from 'src/app/_services/auth.service';
import { Router } from '@angular/router';
import { PerfectScrollbarConfigInterface, PerfectScrollbarComponent, PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
import { AppConstants } from 'src/app/_helpers/app.constants';
const docElmWithBrowsersFullScreenFunctions = document.documentElement as HTMLElement & {
mozRequestFullScreen(): Promise<void>;
webkitRequestFullscreen(): Promise<void>;
msRequestFullscreen(): Promise<void>;
};
const docWithBrowsersExitFunctions = document as Document & {
mozCancelFullScreen(): Promise<void>;
webkitExitFullscreen(): Promise<void>;
msExitFullscreen(): Promise<void>;
};
@Component({
selector: 'app-header-vertical',
templateUrl: './vertical.component.html',
styleUrls: ['./vertical.component.css']
})
export class VerticalComponent implements OnInit, AfterViewInit {
insideTm: any;
outsideTm: any;
private _unsubscribeAll: Subject<any>;
private _unsubscribeAllMenu: Subject<any>;
public _themeSettingsConfig: any;
private _menuSettingsConfig: any;
public selectedHeaderNavBarClass: string;
public selectedNavBarHeaderClass: string;
public currentUser: any;
public isHeaderSearchOpen: any;
isMobile = false;
showNavbar = false;
public maximize: any;
public search: any;
public internationalization: any;
public notification: any;
public email: any;
public config: PerfectScrollbarConfigInterface = { wheelPropagation: false };
@ViewChild(PerfectScrollbarComponent) componentRef?: PerfectScrollbarComponent;
@ViewChild(PerfectScrollbarDirective, { static: true }) directiveRef?: PerfectScrollbarDirective;
constructor(
@Inject(DOCUMENT) private document: Document,
private _renderer: Renderer2,
private navbarService: NavbarService,
private _themeSettingsService: ThemeSettingsService,
private _menuSettingsService: MenuSettingsService,
public authService: AuthService,
private router: Router,
private elementRef: ElementRef
) {
this._unsubscribeAll = new Subject();
this._unsubscribeAllMenu = new Subject();
}
logout() {
if (localStorage.getItem('currentUser')) {
this.authService.doLogout().then(res => {
window.location.href = '/login';
}, err => {
console.log(err);
});
}
}
ngOnInit() {
this.isMobile = window.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH;
if (!this.isMobile) {
this.showNavbar = true;
}
if (localStorage.getItem('currentUser')) {
this.currentUser = JSON.parse(localStorage.getItem('currentUser'));
}
// Subscribe to config changes
this._themeSettingsService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._themeSettingsConfig = config;
this.refreshView();
});
this._menuSettingsService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._menuSettingsConfig = config;
});
this.maximize = this._themeSettingsConfig.headerIcons.maximize;
this.search = this._themeSettingsConfig.headerIcons.search;
this.internationalization = this._themeSettingsConfig.headerIcons.internationalization;
this.notification = this._themeSettingsConfig.headerIcons.notification;
this.email = this._themeSettingsConfig.headerIcons.email;
}
ngAfterViewInit(): void {
this.refreshView();
}
refreshView() {
const iconElement = document.getElementsByClassName('toggle-icon');
const menuColorElement = document.getElementsByClassName('main-menu');
const navigationElement = document.getElementsByClassName('main-menu');
const navbarElement = document.getElementsByClassName('header-navbar');
const themeColorElement = document.getElementsByClassName('header-navbar');
const element = document.getElementsByClassName('navbar-header');
const boxelement = document.getElementById('customizer');
if (iconElement) {
if (this._themeSettingsConfig.colorTheme === 'semi-light' || this._themeSettingsConfig.colorTheme === 'light') {
this._renderer.removeClass(iconElement.item(0), 'white');
this._renderer.addClass(iconElement.item(0), 'blue-grey');
this._renderer.addClass(iconElement.item(0), 'darken-3');
} else if (this._themeSettingsConfig.colorTheme === 'semi-dark' || this._themeSettingsConfig.colorTheme === 'dark') {
this._renderer.addClass(iconElement.item(0), 'white');
this._renderer.removeClass(iconElement.item(0), 'blue-grey');
this._renderer.removeClass(iconElement.item(0), 'darken-3');
}
}
if (this._themeSettingsConfig.colorTheme === 'semi-light') {
this.selectedHeaderNavBarClass = this._themeSettingsConfig.color;
this.selectedNavBarHeaderClass = '';
} else if (this._themeSettingsConfig.colorTheme === 'semi-dark') {
this.selectedNavBarHeaderClass = this._themeSettingsConfig.color;
this.selectedHeaderNavBarClass = '';
} else if (this._themeSettingsConfig.colorTheme === 'dark') {
this.selectedHeaderNavBarClass = this._themeSettingsConfig.color;
this.selectedNavBarHeaderClass = '';
} else if (this._themeSettingsConfig.colorTheme === 'light') {
this.selectedHeaderNavBarClass = this._themeSettingsConfig.color;
this.selectedNavBarHeaderClass = this._themeSettingsConfig.color;
}
if (menuColorElement) {
if (this._themeSettingsConfig.menuColor === 'menu-dark') {
this._renderer.removeClass(menuColorElement.item(0), 'menu-light');
this._renderer.addClass(menuColorElement.item(0), 'menu-dark');
} else if (this._themeSettingsConfig.menuColor === 'menu-light') {
this._renderer.removeClass(menuColorElement.item(0), 'menu-dark');
this._renderer.addClass(menuColorElement.item(0), 'menu-light');
}
}
if (themeColorElement) {
if (this._themeSettingsConfig.colorTheme === 'semi-light') {
this._renderer.removeClass(themeColorElement.item(0), 'navbar-semi-dark');
this._renderer.removeClass(themeColorElement.item(0), 'navbar-dark');
this._renderer.removeClass(themeColorElement.item(0), 'navbar-light');
} else if (this._themeSettingsConfig.colorTheme === 'semi-dark') {
this._renderer.removeClass(themeColorElement.item(0), 'navbar-semi-light');
this._renderer.removeClass(themeColorElement.item(0), 'navbar-dark');
this._renderer.removeClass(themeColorElement.item(0), 'navbar-light');
} else if (this._themeSettingsConfig.colorTheme === 'dark') {
this._renderer.removeClass(themeColorElement.item(0), 'navbar-semi-dark');
this._renderer.removeClass(themeColorElement.item(0), 'navbar-semi-dark');
this._renderer.removeClass(themeColorElement.item(0), 'navbar-light');
} else if (this._themeSettingsConfig.colorTheme === 'light') {
this._renderer.removeClass(themeColorElement.item(0), 'navbar-semi-dark');
this._renderer.removeClass(themeColorElement.item(0), 'navbar-dark');
this._renderer.removeClass(themeColorElement.item(0), 'navbar-semi-light');
}
}
if (navigationElement) {
if (this._themeSettingsConfig.navigation === 'menu-native-scroll') {
this._renderer.addClass(navigationElement.item(0), 'menu-native-scroll');
} else if (this._themeSettingsConfig.navigation === 'menu-icon-right') {
this._renderer.addClass(navigationElement.item(0), 'menu-icon-right');
} else if (this._themeSettingsConfig.navigation === 'menu-bordered') {
this._renderer.addClass(navigationElement.item(0), 'menu-bordered');
} else if (this._themeSettingsConfig.navigation === 'menu-flipped') {
this._renderer.addClass(document.body, 'menu-flipped');
} else if (this._themeSettingsConfig.navigation === 'menu-collapsible') {
this._renderer.addClass(navigationElement.item(0), 'menu-collapsible');
} else if (this._themeSettingsConfig.navigation === 'menu-static') {
this._renderer.addClass(navigationElement.item(0), 'menu-static');
}
}
if (navbarElement) {
if (this._themeSettingsConfig.menu === 'navbar-static-top') {
this._renderer.addClass(navbarElement.item(0), 'navbar-static-top');
this._renderer.addClass(navigationElement.item(0), 'menu-static');
}
}
if (navbarElement) {
if (this._themeSettingsConfig.menu === 'semi-light') {
this._renderer.addClass(navbarElement.item(0), 'navbar-semi-light bg-gradient-x-grey-blue');
} else if (this._themeSettingsConfig.menu === 'semi-dark') {
this._renderer.addClass(navbarElement.item(0), 'navbar-semi-dark');
} else if (this._themeSettingsConfig.menu === 'dark') {
this._renderer.addClass(navbarElement.item(0), 'navbar-dark');
} else if (this._themeSettingsConfig.menu === 'light') {
this._renderer.addClass(navbarElement.item(0), 'navbar-light');
}
}
}
resetOpenMenu() {
for (let i = 0; i < this._menuSettingsConfig.vertical_menu.items.length; i++) {
const menu = this._menuSettingsConfig.vertical_menu.items[i];
if (!menu.submenu) {
menu['isOpen'] = false;
menu['isActive'] = false;
menu['hover'] = false;
} else if (menu.submenu) {
for (let j = 0; j < menu.submenu.items.length; j++) {
menu['isOpen'] = false;
menu['isActive'] = false;
menu['hover'] = false;
menu.submenu.items[j]['isOpen'] = false;
}
}
}
}
setOpenInNavbar(value) {
for (let i = 0; i < this._menuSettingsConfig.vertical_menu.items.length; i++) {
const menu = this._menuSettingsConfig.vertical_menu.items[i];
if (!menu.submenu &&
menu.page === this.router.url) {
menu['isOpen'] = value;
menu['isActive'] = value;
} else if (menu.submenu) {
for (let j = 0; j < menu.submenu.items.length; j++) {
if (menu.submenu.items[j].page === this.router.url) {
menu['isOpen'] = value;
menu['isActive'] = value;
menu.submenu.items[j]['isOpen'] = value;
menu.submenu.items[j]['isActive'] = value;
break;
}
}
}
}
}
/**
* Use for fixed left aside menu, to show menu on mouseenter event.
* @param e Event
*/
mouseEnter(e) {
if (this.navbarService.isFixedMenu()) {
return;
}
this.navbarService.setMouseInRegion(true);
const navBar = this.document.getElementById('navbar-header');
const mainMenu = this.document.getElementById('main-menu');
// check if the left aside menu is fixed
if (!navBar.classList.contains('expanded')) {
this._renderer.addClass(navBar, 'expanded');
this._renderer.addClass(mainMenu, 'expanded');
this.resetOpenMenu();
this.setOpenInNavbar(true);
}
}
/**
* Use for fixed left aside menu, to show menu on mouseenter event.
* @param e Event
*/
mouseLeave(event) {
if (this.navbarService.isFixedMenu()) {
return;
}
const _self = this;
const navBar = this.document.getElementById('navbar-header');
const mainMenu = this.document.getElementById('main-menu');
if (navBar && navBar.classList.contains('expanded')) {
this.insideTm = setTimeout(() => {
if (!_self.navbarService.isMouseInRegion()) {
this._renderer.removeClass(navBar, 'expanded');
this._renderer.removeClass(mainMenu, 'expanded');
this.resetOpenMenu();
this.setOpenInNavbar(false);
}
}, 100);
}
this.navbarService.setMouseInRegion(false);
}
// example to update badge value dynamically from another component
updateMenuBadgeValue() {
for (let i = 0; i < this._menuSettingsConfig.items.length; i++) {
if (this._menuSettingsConfig.items[i].badge) {
this._menuSettingsConfig.items[i].badge.value = 19;
}
}
this._menuSettingsService.config = this._menuSettingsConfig;
}
handleCollapseOfMenu(element) {
if (element.classList && element.classList.contains('has-sub') && element.classList.contains('open')) {
element.classList.remove('open');
element.classList.remove('hover');
element.classList.add('menu-collapsed-open');
}
}
handleExpandOfMenu(element) {
if (element.classList && element.classList.contains('has-sub') &&
element.classList.contains('menu-collapsed-open')) {
element.classList.remove('menu-collapsed-open');
element.classList.add('open');
element.classList.add('hover');
}
}
toggleMenu(event) {
const target = event.target || event.srcElement || event.currentTarget;
const parent = target.parentElement;
if (parent && parent.classList.contains('has-sub')) {
this.openSubMenuUsingParent(parent);
} else {
const parentOfParent = parent.parentElement;
this.openSubMenuUsingParent(parentOfParent);
}
}
openSubMenuUsingParent(parent) {
if (parent.classList && parent.classList.contains('has-sub') &&
!parent.classList.contains('open')) {
parent.classList.add('open');
} else if (parent.classList && parent.classList.contains('has-sub') &&
parent.classList.contains('open')) {
parent.classList.remove('open');
}
}
toggleFullScreen() {
const toggleIcon = document.getElementsByClassName('ficon');
if (toggleIcon.item(0).classList.contains('ft-maximize')) {
this.openfullscreen();
this._renderer.removeClass(toggleIcon.item(0), 'ft-maximize');
this._renderer.addClass(toggleIcon.item(0), 'ft-minimize');
} else if (toggleIcon.item(0).classList.contains('ft-minimize')) {
this.closefullscreen();
this._renderer.addClass(toggleIcon.item(0), 'ft-maximize');
this._renderer.removeClass(toggleIcon.item(0), 'ft-minimize');
}
}
openfullscreen() {
// Trigger fullscreen
// eslint-disable-next-line no-shadow,@typescript-eslint/no-shadow
const docElmWithBrowsersFullScreenFunctions = document.documentElement as HTMLElement & {
mozRequestFullScreen(): Promise<void>;
webkitRequestFullscreen(): Promise<void>;
msRequestFullscreen(): Promise<void>;
};
if (docElmWithBrowsersFullScreenFunctions.requestFullscreen) {
docElmWithBrowsersFullScreenFunctions.requestFullscreen();
} else if (docElmWithBrowsersFullScreenFunctions.mozRequestFullScreen) { /* Firefox */
docElmWithBrowsersFullScreenFunctions.mozRequestFullScreen();
} else if (docElmWithBrowsersFullScreenFunctions.webkitRequestFullscreen) { /* Chrome, Safari and Opera */
docElmWithBrowsersFullScreenFunctions.webkitRequestFullscreen();
} else if (docElmWithBrowsersFullScreenFunctions.msRequestFullscreen) { /* IE/Edge */
docElmWithBrowsersFullScreenFunctions.msRequestFullscreen();
}
}
closefullscreen() {
// eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
const docWithBrowsersExitFunctions = document as Document & {
mozCancelFullScreen(): Promise<void>;
webkitExitFullscreen(): Promise<void>;
msExitFullscreen(): Promise<void>;
};
if (docWithBrowsersExitFunctions.exitFullscreen) {
docWithBrowsersExitFunctions.exitFullscreen();
} else if (docWithBrowsersExitFunctions.mozCancelFullScreen) { /* Firefox */
docWithBrowsersExitFunctions.mozCancelFullScreen();
} else if (docWithBrowsersExitFunctions.webkitExitFullscreen) { /* Chrome, Safari and Opera */
docWithBrowsersExitFunctions.webkitExitFullscreen();
} else if (docWithBrowsersExitFunctions.msExitFullscreen) { /* IE/Edge */
docWithBrowsersExitFunctions.msExitFullscreen();
}
}
toggleFixMenu(e) {
if (this.document.body.classList.contains('menu-expanded')) {
// show the left aside menu
this.navbarService.setFixedMenu(false);
this.document.body.classList.remove('menu-expanded');
this.document.body.classList.add('menu-collapsed');
// Change switch icon
this._themeSettingsConfig.menu = 'collapse';
} else {
this.navbarService.setFixedMenu(true);
this.document.body.classList.remove('menu-collapsed');
this.document.body.classList.add('menu-expanded');
// Change switch icon
this._themeSettingsConfig.menu = 'expand';
}
const navBar = this.document.getElementById('navbar-header');
const mainMenu = this.document.getElementById('main-menu');
this._renderer.addClass(navBar, 'expanded');
this._renderer.addClass(mainMenu, 'expanded');
setTimeout(() => { AppConstants.fireRefreshEventOnWindow(); }, 300);
}
toggleNavigation(e) {
const sidenav = document.getElementById('sidenav-overlay');
const sidebarLeft = document.getElementById('sidebar-left') || document.getElementById('email-app-menu') ||
document.getElementById('sidebar-todo');
const contentOverlay = document.getElementById('content-overlay');
if (this.document.body.classList.contains('menu-open') && (this.router.url === '/todos' || this.router.url === '/contacts' ||
this.router.url === '/email' || this.router.url === '/chats' || this.router.url === '/chats/static-chat')) {
this.document.body.classList.remove('menu-open');
this._renderer.removeClass(sidenav, 'd-block');
this._renderer.removeClass(contentOverlay, 'show');
this.document.body.classList.add('menu-close');
this._renderer.addClass(sidenav, 'd-none');
this.showNavbar = false;
} else if (this.document.body.classList.contains('menu-open')) {
this.document.body.classList.remove('menu-open');
this._renderer.removeClass(sidenav, 'd-block');
this.document.body.classList.add('menu-close');
this._renderer.addClass(sidenav, 'd-none');
this.showNavbar = false;
} else {
this._renderer.removeClass(sidenav, 'd-none');
this.document.body.classList.remove('menu-close');
this.document.body.classList.add('menu-open');
this._renderer.addClass(sidenav, 'd-block');
this.showNavbar = false;
}
if (sidebarLeft) {
this._renderer.removeClass(sidebarLeft, 'show');
}
if(contentOverlay){
this._renderer.removeClass(contentOverlay, 'show');
}
}
toggleNavbar(e) {
if (this.showNavbar) {
this.showNavbar = false;
} else {
this.showNavbar = true;
}
}
public clickSearch() {
if (this.isHeaderSearchOpen) {
this.isHeaderSearchOpen = false;
} else {
this.isHeaderSearchOpen = true;
}
}
@HostListener('window:resize', ['$event'])
onResize(event) {
if (event.target.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH) {
this.isMobile = true;
this.showNavbar = false;
} else {
this.isMobile = false;
this.showNavbar = true;
}
}
}

View File

@@ -0,0 +1,39 @@
.is-sticky {
width: 100%;
position: fixed;
top: 0px;
z-index: 999;
}
.container {
padding-left: 0px !important;
padding-right: 0px !important;
}
.is-static {
width: 100%;
position: sticky;
top: 0px;
z-index: 999;
}
:host ::ng-deep .navbar-dark .navbar-nav .nav-link {
color: white !important;
}
:host ::ng-deep .navbar-light .navbar-nav .nav-link {
color: #6b6f82 !important;
}
.dropdown-menu .dropdown-submenu>a:after {
top: 14px;
}
.dropdown .dropdown-menu {
min-width: 13rem !important;
}
.navbar-horizontal .dropdown-menu .dropdown-submenu>a:after,
.navbar-horizontal .dropdown-menu .dropdown-submenu>button:after {
right: 0.5rem;
}

View File

@@ -0,0 +1,59 @@
<div id="sticky-wrapper" class="sticky-wrapper">
<div
class="menu-header header-navbar navbar-expand-sm navbar navbar-horizontal navbar-fixed navbar-dark navbar-without-dd-arrow navbar-shadow"
role="navigation" data-menu="menu-wrapper" (scroll)="onWindowScroll($event);" id="menu-header">
<div class="navbar-container main-menu-content" data-menu="menu-container">
<ul class="nav navbar-nav" id="main-menu-navigation" data-menu="menu-navigation">
<li *ngFor="let child of _menuSettingsConfig.horizontal_menu.items" class="nav-item" [ngClass]="{
'dropdown nav-item ':(child.title && child.submenu),
'nav-item' : true,
'open': child.isOpen,
'active': child.isSelected }" [attr.data-menu]="child.submenu? 'dropdown' : ''"
(mouseenter)="mouseEnter($event)" (mouseleave)="mouseLeave($event)">
<!-- Top Menu -->
<a class="nav-link " [ngClass]="{'dropdown-item dropdown-toggle active': child.submenu}"
[attr.data-toggle]="child.submenu? 'dropdown' : ''" (click)="toggleMenu($event, child)"
routerLink="{{child.page !== 'null'?child.page:router.url}}" *ngIf="!child.section">
<i class="la" [ngClass]="child.icon"></i><span data-i18n="nav.dash.main">{{child.title}}</span>
</a>
<ul class="dropdown-menu" *ngIf="child.submenu">
<li *ngFor="let subchild of child.submenu.items" class=""
[ngClass]="{'dropdown dropdown-submenu':(subchild.submenu), 'dropdown-divider':(subchild.title ==='horizontal-divider'), 'active': subchild.isSelected }"
(mouseenter)="mouseEnter($event)" (mouseleave)="mouseLeave($event)"
[attr.data-menu]="subchild.submenu? 'dropdown-submenu' : ''">
<a class="dropdown-item" (click)="toggleMenu($event, subchild)"
routerLink="{{subchild.page !== 'null'?subchild.page:router.url}}" data-toggle="dropdown"
*ngIf="!subchild.isExternalLink">
<i class="la" [ngClass]="subchild.icon"></i> <span data-i18n="nav.dash.main">{{subchild.title}}</span>
</a>
<a class="dropdown-item" (click)="toggleMenu($event, subchild)" [href]="subchild.page !== 'null'?subchild.page:router.url" target="_blank"
data-toggle="dropdown" *ngIf="subchild.isExternalLink">
<i class="la" [ngClass]="subchild.icon"></i> <span data-i18n="nav.dash.main">{{subchild.title}}</span>
</a>
<ul class="dropdown-menu" *ngIf="subchild.submenu">
<li *ngFor="let subchild of subchild.submenu.items"
[ngClass]="{'dropdown dropdown-submenu':(subchild.submenu), 'dropdown-divider':(subchild.title ==='horizontal-divider'), 'active': subchild.isSelected }"
(mouseenter)="mouseEnter($event)" (mouseleave)="mouseLeave($event)"
[attr.data-menu]="subchild.submenu? 'dropdown-submenu' : ''">
<a class="dropdown-item" *ngIf="!subchild.event" (click)="toggleMenu($event, subchild)"
routerLink="{{subchild.page !== 'null'?subchild.page:router.url}}" data-toggle="dropdown"><span
data-i18n="nav.dash.main">{{subchild.title}}</span></a>
<ul class="dropdown-menu" *ngIf="subchild.submenu">
<li *ngFor="let subchild of subchild.submenu.items" [ngClass]="{'active': subchild.isSelected}"
data-menu="">
<a class="dropdown-item" *ngIf="!subchild.event" (click)="toggleMenu($event, subchild)"
routerLink="{{subchild.page !== 'null'?subchild.page:router.url}}" data-toggle="dropdown"><span
data-i18n="nav.dash.main">{{subchild.title}}</span></a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { HorizontalnavComponent } from './horizontalnav.component';
describe('HorizontalnavComponent', () => {
let component: HorizontalnavComponent;
let fixture: ComponentFixture<HorizontalnavComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ HorizontalnavComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HorizontalnavComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,259 @@
import { Component, AfterViewInit, OnInit, Renderer2, HostListener } from '@angular/core';
import { trigger, state, transition, style, animate } from '@angular/animations';
import { ThemeSettingsService } from '../../settings/theme-settings.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { MenuSettingsService } from '../../settings/menu-settings.service';
import { isArray } from 'util';
import { Router } from '@angular/router';
import { AppConstants } from 'src/app/_helpers/app.constants';
@Component({
selector: 'app-horizontalnav',
templateUrl: './horizontalnav.component.html',
styleUrls: ['./horizontalnav.component.css'],
animations: [
trigger('fade',
[
state('void', style({ opacity: 0 })),
transition(':enter', [animate(300)]),
transition(':leave', [animate(500)]),
]
)]
})
export class HorizontalnavComponent implements OnInit, AfterViewInit {
insideTm: any;
private _themeSettingsConfig: any;
private _unsubscribeAll: Subject<any>;
private _unsubscribeAllMenu: Subject<any>;
public _menuSettingsConfig: any;
loggedInUser: any;
constructor(private _themeSettingsService: ThemeSettingsService,
public _menuSettingsService: MenuSettingsService,
private _renderer: Renderer2,
private router: Router) {
this._unsubscribeAll = new Subject();
this._unsubscribeAllMenu = new Subject();
}
ngAfterViewInit(): void {
this.refreshView();
}
ngOnInit() {
// Subscribe to config changes
this._themeSettingsService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._themeSettingsConfig = config;
this.refreshView();
});
this._menuSettingsService.config
.pipe(takeUntil(this._unsubscribeAllMenu))
.subscribe((config) => {
this._menuSettingsConfig = config;
});
this.setActiveRouteInNavbar();
}
setTheme(theme) {
this._themeSettingsService.config = {
colorTheme: theme, // semi-light, semi-dark
};
}
setLayout(layout) {
this._themeSettingsService.config = {
layout: {
pattern: layout
}
};
}
fixComponent(component, value) {
if (component === 'header') {
this._themeSettingsService.config = {
header: value
};
} else if (component === 'footer') {
this._themeSettingsService.config = {
footer: value
};
} else {
this._themeSettingsService.config = {
header: value,
footer: value
};
}
}
callFunction(event) {
const methodName = event.methodName;
if (this[methodName]) {
// method exists on the component
const param = event.methodParam;
if (!isArray(param)) {
this[methodName](param); // call it
} else {
this[methodName](param[0], param[1]); // call it
}
}
}
refreshView() {
const menuHeaderElement = document.getElementsByClassName('menu-header');
// Theme
if (menuHeaderElement && menuHeaderElement.length > 0) {
if (this._themeSettingsConfig.colorTheme === 'light') {
this._renderer.removeClass(menuHeaderElement.item(0), 'navbar-dark');
this._renderer.addClass(menuHeaderElement.item(0), 'navbar-light');
} else if (this._themeSettingsConfig.colorTheme === 'dark') {
this._renderer.addClass(menuHeaderElement.item(0), 'navbar-dark');
this._renderer.removeClass(menuHeaderElement.item(0), 'navbar-light');
}
if (this._themeSettingsConfig.layout.pattern === 'static') {
this._renderer.addClass(menuHeaderElement.item(0), 'menu-static');
} else if (this._themeSettingsConfig.layout.pattern === 'fixed') {
this._renderer.removeClass(menuHeaderElement.item(0), 'menu-static');
}
}
}
setActiveRouteInNavbar() {
for (let i = 0; i < this._menuSettingsConfig.horizontal_menu.items.length; i++) {
if (!this._menuSettingsConfig.horizontal_menu.items[i].submenu &&
this._menuSettingsConfig.horizontal_menu.items[i].page === this.router.url) {
this._menuSettingsConfig.horizontal_menu.items[i]['isSelected'] = true;
break;
} else if (this._menuSettingsConfig.horizontal_menu.items[i].submenu) {
// Level 1 menu
for (let j = 0; j < this._menuSettingsConfig.horizontal_menu.items[i].submenu.items.length; j++) {
if (!this._menuSettingsConfig.horizontal_menu.items[i].submenu.items[j].submenu &&
this._menuSettingsConfig.horizontal_menu.items[i].submenu.items[j].page === this.router.url) {
this._menuSettingsConfig.horizontal_menu.items[i]['isSelected'] = true;
this._menuSettingsConfig.horizontal_menu.items[i].submenu.items[j]['isSelected'] = true;
this._menuSettingsConfig.horizontal_menu.items[i].isOpen = true;
break;
} else if (this._menuSettingsConfig.horizontal_menu.items[i].submenu.items[j].submenu) {
// Level 2 menu
for (let k = 0; k < this._menuSettingsConfig.horizontal_menu.items[i].submenu.items[j].submenu.items.length; k++) {
if (this._menuSettingsConfig.horizontal_menu.items[i].submenu.items[j].submenu.items[k].page === this.router.url) {
this._menuSettingsConfig.horizontal_menu.items[i]['isSelected'] = true;
this._menuSettingsConfig.horizontal_menu.items[i].submenu.items[j]['isSelected'] = true;
this._menuSettingsConfig.horizontal_menu.items[i].isOpen = true;
this._menuSettingsConfig.horizontal_menu.items[i].submenu.items[j]['isSelected'] = true;
this._menuSettingsConfig.horizontal_menu.items[i].submenu.items[j].submenu.items[k]['isSelected'] = true;
this._menuSettingsConfig.horizontal_menu.items[i].submenu.items[j].isOpen = true;
}
}
}
}
}
}
}
toggleMenu(event, child, isSubmenuOfSubmenu) {
const toggle = document.getElementById('sidenav-overlay');
this.resetOtherActiveMenu(child, isSubmenuOfSubmenu);
this.loggedInUser = JSON.parse(localStorage.getItem('currentUser'));
child['isSelected'] = true;
if (this.router.url !== '') {
this._renderer.addClass(toggle, 'd-none');
this._renderer.removeClass(toggle, 'd-block');
}
if ( child.page === '/chats' && this.loggedInUser.email === 'john@pixinvent.com') {
this.router.navigate(['/chats/static-chat']);
} else if ( child.page === '/chats' && this.loggedInUser.email !== 'john@pixinvent.com') {
this.router.navigate(['/chats']);
}
}
resetOtherActiveMenu(selectedChild, isSubmenuOfSubmenu) {
for (let i = 0; i < this._menuSettingsConfig.horizontal_menu.items.length; i++) {
if (selectedChild.page !== 'null') {
this._menuSettingsConfig.horizontal_menu.items[i]['isSelected'] = false;
}
this.handleSubmenuItems(this._menuSettingsConfig.horizontal_menu.items[i], selectedChild, isSubmenuOfSubmenu);
}
}
handleSubmenuItems(parentItem, selectedChild, isSubmenuOfSubmenu) {
let isSelectedChildExist = false;
if (selectedChild['title'] === 'Horizontal') {
localStorage.setItem('currentLayoutStyle', AppConstants.LAYOUT_STYLE_HORIZONTAL);
window.location.reload();
} else if (selectedChild['title'] === 'Vertical') {
localStorage.setItem('currentLayoutStyle', AppConstants.LAYOUT_STYLE_VERTICAL);
window.location.reload();
} else if (parentItem['submenu'] &&
parentItem['submenu']['items'] &&
parentItem['submenu']['items'].length > 0) {
for (let j = 0; j < parentItem['submenu']['items'].length; j++) {
if (selectedChild.title === parentItem['submenu']['items'][j].title) {
isSelectedChildExist = true;
}
this.handleSubmenuItems(parentItem['submenu']['items'][j], selectedChild, isSubmenuOfSubmenu);
if (parentItem['submenu']['items'][j]['isSelected'] === true) {
isSelectedChildExist = true;
}
}
if (!isSelectedChildExist) {
parentItem['isSelected'] = false;
} else {
parentItem['isSelected'] = true;
}
} else if (parentItem.title !== selectedChild.title && !isSubmenuOfSubmenu) {
parentItem['isSelected'] = false;
}
}
@HostListener('window:scroll', ['$event'])
onWindowScroll(e) {
const element = document.getElementById('sticky-wrapper');
if (this._themeSettingsConfig.layout.style === 'horizontal') {
if (this._themeSettingsConfig.layout.pattern === 'fixed' ||
this._themeSettingsConfig.layout.pattern === '') {
if (window.pageYOffset > 70) { // 70 is the height of the horizontal header
element.classList.add('is-sticky');
element.classList.remove('container');
} else {
element.classList.remove('is-sticky');
}
} else if (this._themeSettingsConfig.layout.pattern === 'boxed') {
if (window.pageYOffset > 70) { // 70 is the height of the horizontal header
element.classList.add('is-sticky');
element.classList.add('container');
} else {
element.classList.remove('is-sticky');
element.classList.remove('container');
}
} else if (this._themeSettingsConfig.layout.pattern === 'static') {
element.classList.remove('is-sticky');
element.classList.remove('container');
element.classList.add('is-static');
}
}
}
mouseEnter(e) {
const _event = e;
_event.srcElement.classList.add('show');
}
/**
* Use for fixed left aside menu, to show menu on mouseenter event.
* @param e Event
*/
mouseLeave(event) {
const _event = event;
_event.srcElement.classList.remove('show');
}
}

View File

@@ -0,0 +1,10 @@
<div (window:resize)="onResize($event)">
<app-header></app-header>
<ng-container *ngIf="layout === 'vertical' || isMobile === true">
<app-verticalnav></app-verticalnav>
</ng-container>
<ng-container *ngIf="layout === 'horizontal' && isMobile === false">
<app-horizontalnav></app-horizontalnav>
</ng-container>
</div>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NavigationComponent } from './navigation.component';
describe('NavigationComponent', () => {
let component: NavigationComponent;
let fixture: ComponentFixture<NavigationComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ NavigationComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(NavigationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,47 @@
import { Component, OnInit, HostListener } from '@angular/core';
import { takeUntil } from 'rxjs/operators';
import { ThemeSettingsService } from '../settings/theme-settings.service';
import { Subject } from 'rxjs';
import { AppConstants } from 'src/app/_helpers/app.constants';
@Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.css']
})
export class NavigationComponent implements OnInit {
layout: string;
private _themeSettingsConfig: any;
private _unsubscribeAll: Subject<any>;
isMobile = false;
constructor(private _themeSettingsService: ThemeSettingsService) {
this._unsubscribeAll = new Subject();
}
ngOnInit() {
const self = this;
this.isMobile = window.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH_HORIZONTAL;
// Subscribe to config changes
this._themeSettingsService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._themeSettingsConfig = config;
if (config.layout && config.layout.style &&
config.layout.style === 'vertical') {
self.layout = 'vertical';
} else {
self.layout = 'horizontal';
}
});
}
@HostListener('window:resize', ['$event'])
onResize(event) {
if (event.target.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH_HORIZONTAL) {
this.isMobile = true;
} else {
this.isMobile = false;
}
}
}

View File

@@ -0,0 +1,57 @@
// Default theme settings configurations
export class NavigationConfig {
public config: any = {};
constructor() {
this.config = {
items: [
{
title: 'Dashboard',
root: true,
icon: 'la-home',
page: '/home',
badge: {type: 'badge-info', value: '2'}
},
{
title: 'Changelog',
root: true,
icon: 'la-file',
page: 'null',
submenu: {
items : [
{
}
]
}
},
{
title: 'Changelog',
root: true,
icon: 'la-file',
page: 'null',
badge: {type: 'badge-danger', value: '1.0'}
},
{
title: 'Support',
root: true,
icon: 'la-ellipsis-h feather ft-minus',
page: 'null'
},
{
title: 'Raise Support',
root: true,
icon: 'la-support',
page: 'null'
},
{
title: 'Documentation',
root: true,
icon: 'la-folder',
page: 'null'
}
]
};
}
}

View File

@@ -0,0 +1,83 @@
<div (mouseenter)="mouseEnter($event)" (mouseleave)="mouseLeave($event)" id="main-menu"
class="main-menu menu-fixed menu-dark menu-accordion menu-shadow" data-scroll-to-active="true">
<div id="main-menu-content" class="main-menu-content ps-container ps-theme-light" fxFlex="auto"
[perfectScrollbar]="config">
<ul class="navigation navigation-main" id="main-menu-navigation" data-menu="menu-navigation">
<!-- Menu -->
{{child?child.title:''}}
<li *ngFor="let child of _menuSettingsConfig.vertical_menu.items" class="" [ngClass]="{
'has-sub': child.submenu,
'open': child.isOpen && child.submenu,
'nav-item': child.title,
'navigation-header':child.section,
'active': child.isSelected && !child.submenu,
'menu-collapsed-open': child.isSelected && child.submenu,
'hover': child.hover
}">
<!-- Section -->
<span class="menu-title" *ngIf="child.section">{{child.section}}</span>
<i class="la" *ngIf="child.section" [ngClass]="child.icon" data-toggle="tooltip" data-placement="right"
data-original-title="Support"></i>
<!-- Root Menu -->
<a *ngIf="child.title && !child.submenu && !child.excludeInVertical && !child.isExternalLink && !child.issupportExternalLink && !child.isStarterkitExternalLink"
routerLink="{{child.page !== 'null'?child.page:router.url}}" (click)="toggleMenu($event, child)">
<i class="la" [ngClass]="child.icon"></i>
<span class="menu-title" data-i18n="">{{child.title}}</span>
<span *ngIf="child.badge" class="badge badge-pill float-right"
[ngClass]="{'badge-info mr-2': child.badge.type==='badge-info' , 'badge-danger':child.badge.type==='badge-danger'}">
{{child.badge.value}}
</span>
</a>
<a *ngIf="child.title && !child.submenu && !child.excludeInVertical && child.isExternalLink"
[href]="child.page" target="_blank" (click)="toggleMenu($event, child)">
<i class="la" [ngClass]="child.icon"></i>
<span class="menu-title" data-i18n="">{{child.title}}</span>
<span *ngIf="child.badge" class="badge badge-pill float-right"
[ngClass]="{'badge-info mr-2': child.badge.type==='badge-info' , 'badge-danger':child.badge.type==='badge-danger'}">
{{child.badge.value}}
</span>
</a>
<a *ngIf="child.title && !child.submenu && !child.excludeInVertical && child.isStarterkitExternalLink"
[href]="child.page" target="_blank" (click)="toggleMenu($event, child)">
<i class="la" [ngClass]="child.icon"></i>
<span class="menu-title" data-i18n="">{{child.title}}</span>
<span *ngIf="child.badge" class="badge badge-pill float-right"
[ngClass]="{'badge-info mr-2': child.badge.type==='badge-info' , 'badge-danger':child.badge.type==='badge-danger'}">
{{child.badge.value}}
</span>
</a>
<!-- Submenu -->
<a *ngIf="child.title && child.submenu && !child.excludeInVertical"
routerLink="{{child.page !== 'null'?child.page:router.url}}" (click)="toggleMenu($event, child)">
<i class="la" [ngClass]="child.icon"></i>
<span class="menu-title" data-i18n="">{{child.title}}</span>
<span *ngIf="child.badge" class="badge badge-pill float-right"
[ngClass]="{'badge-info mr-2': child.badge.type==='badge-info' , 'badge-danger':child.badge.type==='badge-danger'}">
{{child.badge.value}}
</span>
</a>
<ul *ngIf="child.submenu" class="menu-content" [@popOverState]="child.isOpen">
<!-- Submenu of Submenu -->
<li *ngFor="let subchild of child.submenu.items" class="isShown"
[ngClass]="{'has-sub':(subchild.submenu),'active': subchild.isSelected && !subchild.submenu, 'open': subchild.isOpen && subchild.submenu}">
<a class="menu-item" *ngIf="!subchild.submenu && !subchild.excludeInVertical" (click)="toggleMenu($event, subchild, true)"
routerLink="{{subchild.page !== 'null'?subchild.page:router.url}}">{{subchild.title}}</a>
<a class="menu-item" *ngIf="subchild.submenu && !subchild.excludeInVertical" (click)="toggleMenu($event, subchild, true)"
routerLink="{{subchild.page !== 'null'?subchild.page:router.url}}">{{subchild.title}}</a>
<ul *ngIf="subchild.submenu && !subchild.excludeInVertical" class="menu-content">
<li *ngFor="let subchild of subchild.submenu.items" [ngClass]="{'active': subchild.isSelected && !subchild.submenu}">
<a class="menu-item" *ngIf="!subchild.event"
routerLink="{{subchild.page}}" (click)="toggleMenu($event, subchild, true)">{{subchild.title}}</a>
<a class="menu-item" *ngIf="subchild.event"
(click)="callFunction(subchild.event, subchild)">{{subchild.title}}</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { VerticalnavComponent } from './verticalnav.component';
describe('VerticalnavComponent', () => {
let component: VerticalnavComponent;
let fixture: ComponentFixture<VerticalnavComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ VerticalnavComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(VerticalnavComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,389 @@
import { Component, Inject, OnInit, Renderer2, NgZone, ViewChild } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { NavbarService } from '../../../_services/navbar.service';
import { ThemeSettingsService } from '../../settings/theme-settings.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { PerfectScrollbarConfigInterface, PerfectScrollbarComponent, PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
import { MenuSettingsService } from '../../settings/menu-settings.service';
import { isArray } from 'util';
import { trigger, state, style, animate, transition } from '@angular/animations';
import { AppConstants } from 'src/app/_helpers/app.constants';
import { Router, NavigationEnd, Event } from '@angular/router';
@Component({
selector: 'app-verticalnav',
templateUrl: './verticalnav.component.html',
styleUrls: ['./verticalnav.component.css'],
animations: [
trigger('popOverState', [
state('show', style({
opacity: '1',
})),
state('hide', style({
opacity: '0',
height: '*',
})),
transition('show => hide', animate('200ms ease-in-out')),
transition('hide => show', animate('200ms ease-in-out'))
])
]
})
export class VerticalnavComponent implements OnInit {
child: any;
insideTm: any;
outsideTm: any;
loggedInUser: any;
public title;
private _themeSettingsConfig: any;
public _menuSettingsConfig: any;
private _unsubscribeAll: Subject<any>;
private _unsubscribeAllMenu: Subject<any>;
public config: PerfectScrollbarConfigInterface = { wheelPropagation: false };
@ViewChild(PerfectScrollbarComponent) componentRef?: PerfectScrollbarComponent;
@ViewChild(PerfectScrollbarDirective, { static: true }) directiveRef?: PerfectScrollbarDirective;
constructor(
@Inject(DOCUMENT) private document: Document,
private navbarService: NavbarService,
private _themeSettingsService: ThemeSettingsService,
private _menuSettingsService: MenuSettingsService,
private _renderer: Renderer2,
private router: Router
) {
this._unsubscribeAll = new Subject();
this._unsubscribeAllMenu = new Subject();
this.router.events.subscribe((event: Event) => {
if (event instanceof NavigationEnd) {
this.resetMainMenu();
this.setActiveRouteInNavbar();
}
});
}
ngOnInit() {
// Subscribe to config changes
this._themeSettingsService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._themeSettingsConfig = config;
this.refreshView();
});
this._menuSettingsService.config
.pipe(takeUntil(this._unsubscribeAllMenu))
.subscribe((config) => {
this._menuSettingsConfig = config;
});
// TODO Patch to reset menu after login
this.resetMainMenu();
this.setActiveRouteInNavbar();
}
resetMainMenu() {
const nodes = this.document.getElementById('main-menu-navigation').childNodes;
for (let i = 0; i < nodes.length; i++) {
this.resetCollapseMenu(nodes[i]);
}
for (let i = 0; i < this._menuSettingsConfig.vertical_menu.items.length; i++) {
this._menuSettingsConfig.vertical_menu.items[i]['isSelected'] = false;
this._menuSettingsConfig.vertical_menu.items[i]['hover'] = false;
this._menuSettingsConfig.vertical_menu.items[i]['isOpen'] = false;
this.resetSubmenuItems(this._menuSettingsConfig.vertical_menu.items[i]);
}
}
resetCollapseMenu(element) {
if (element.classList && element.classList.contains('has-sub') && element.classList.contains('open')) {
element.classList.remove('hover');
element.classList.remove('menu-collapsed-open');
}
}
resetSubmenuItems(parentItem) {
if (parentItem['submenu'] &&
parentItem['submenu']['items'] &&
parentItem['submenu']['items'].length > 0) {
parentItem['isOpen'] = false;
for (let j = 0; j < parentItem['submenu']['items'].length; j++) {
parentItem['submenu']['items'][j]['isSelected'] = false;
this.resetSubmenuItems(parentItem['submenu']['items'][j]);
}
}
}
refreshView() {
const mainMenuElement = document.getElementsByClassName('main-menu');
if (mainMenuElement && mainMenuElement.length > 0) {
if (this._themeSettingsConfig.colorTheme === 'semi-light' || this._themeSettingsConfig.colorTheme === 'light') {
this._renderer.removeClass(mainMenuElement.item(0), 'menu-dark');
this._renderer.addClass(mainMenuElement.item(0), 'menu-light');
} else if (this._themeSettingsConfig.colorTheme === 'semi-dark' || this._themeSettingsConfig.colorTheme === 'dark') {
this._renderer.addClass(mainMenuElement.item(0), 'menu-dark');
this._renderer.removeClass(mainMenuElement.item(0), 'menu-light');
}
if (this._themeSettingsConfig.layout.pattern === 'static') {
this._renderer.removeClass(mainMenuElement.item(0), 'menu-fixed');
this._renderer.addClass(mainMenuElement.item(0), 'menu-static');
} else if (this._themeSettingsConfig.layout.pattern === 'fixed') {
this._renderer.removeClass(mainMenuElement.item(0), 'menu-static');
this._renderer.addClass(mainMenuElement.item(0), 'menu-fixed');
}
}
}
setActiveRouteInNavbar() {
for (let i = 0; i < this._menuSettingsConfig.vertical_menu.items.length; i++) {
if (!this._menuSettingsConfig.vertical_menu.items[i].submenu &&
this._menuSettingsConfig.vertical_menu.items[i].page === this.router.url) {
this._menuSettingsConfig.vertical_menu.items[i]['isSelected'] = true;
break;
} else if (this._menuSettingsConfig.vertical_menu.items[i].submenu) {
// Level 1 menu
for (let j = 0; j < this._menuSettingsConfig.vertical_menu.items[i].submenu.items.length; j++) {
if (!this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j].submenu &&
this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j].page === this.router.url) {
this._menuSettingsConfig.vertical_menu.items[i]['isSelected'] = true;
this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j]['isSelected'] = true;
this._menuSettingsConfig.vertical_menu.items[i].isOpen = true;
break;
} else if (this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j].submenu) {
// Level 2 menu
for (let k = 0; k < this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j].submenu.items.length; k++) {
if (this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j].submenu.items[k].page === this.router.url) {
this._menuSettingsConfig.vertical_menu.items[i]['isSelected'] = true;
this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j]['isSelected'] = true;
this._menuSettingsConfig.vertical_menu.items[i].isOpen = true;
this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j]['isSelected'] = true;
this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j].submenu.items[k]['isSelected'] = true;
this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j].isOpen = true;
}
}
} else if(!this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j].submenu ){
let a,b;
let URL = localStorage.getItem('creatorurl');
let SurveyUrl = localStorage.getItem('surveyurl');
if( this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j].page ==='/creator' && this.router.url === URL){
a = j;
this._menuSettingsConfig.vertical_menu.items[i]['isSelected'] = true;
this._menuSettingsConfig.vertical_menu.items[i].submenu.items[a]['isSelected'] = true;
this._menuSettingsConfig.vertical_menu.items[i].isOpen = true;
// this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j]['isSelected'] = false;
} else if(this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j].page ==='/survey' && this.router.url === SurveyUrl){
b = j;
this._menuSettingsConfig.vertical_menu.items[i]['isSelected'] = true;
this._menuSettingsConfig.vertical_menu.items[i].submenu.items[b]['isSelected'] = true;
this._menuSettingsConfig.vertical_menu.items[i].isOpen = true;
if (this._menuSettingsConfig.vertical_menu.items[i].submenu.items[a]) {
this._menuSettingsConfig.vertical_menu.items[i].submenu.items[a]['isSelected'] = false;
}
}
}
}
}
}
}
resetOpenMenu() {
for (let i = 0; i < this._menuSettingsConfig.vertical_menu.items.length; i++) {
const menu = this._menuSettingsConfig.vertical_menu.items[i];
if (!menu.submenu) {
menu['isOpen'] = false;
menu['isActive'] = false;
menu['hover'] = false;
} else if (menu.submenu) {
for (let j = 0; j < menu.submenu.items.length; j++) {
menu['isOpen'] = false;
menu['isActive'] = false;
menu['hover'] = false;
menu.submenu.items[j]['isOpen'] = false;
}
}
}
}
setOpenInNavbar(value) {
for (let i = 0; i < this._menuSettingsConfig.vertical_menu.items.length; i++) {
const menu = this._menuSettingsConfig.vertical_menu.items[i];
if (!menu.submenu &&
menu.page === this.router.url) {
menu['isOpen'] = value;
menu['isActive'] = value;
} else if (menu.submenu) {
for (let j = 0; j < menu.submenu.items.length; j++) {
if (menu.submenu.items[j].page === this.router.url) {
menu['isOpen'] = value;
menu['isActive'] = value;
menu.submenu.items[j]['isOpen'] = value;
menu.submenu.items[j]['isActive'] = value;
break;
}
}
}
}
}
callFunction(event, child, isSubmenuOfSubmenu) {
const methodName = event.methodName;
if (this[methodName]) {
// method exists on the component
const param = event.methodParam;
if (!isArray(param)) {
this[methodName](param); // call it
} else {
this[methodName](param[0], param[1]); // call it
}
}
this.resetOtherActiveMenu(child, isSubmenuOfSubmenu);
child['isSelected'] = true;
}
setTheme(theme) {
this._themeSettingsService.config = {
colorTheme: theme, // semi-light, semi-dark
};
}
setLayout(layout) {
this._themeSettingsService.config = {
layout: {
pattern: layout
}
};
}
fixComponent(component, value) {
if (component === 'header') {
this._themeSettingsService.config = {
header: value
};
} else if (component === 'footer') {
this._themeSettingsService.config = {
footer: value
};
} else {
this._themeSettingsService.config = {
header: value,
footer: value
};
}
}
/**
* Use for fixed left aside menu, to show menu on mouseenter event.
* @param e Event
*/
mouseEnter(e) {
if (this.navbarService.isFixedMenu()) {
return;
}
this.navbarService.setMouseInRegion(true);
const navBar = this.document.getElementById('navbar-header');
const mainMenu = this.document.getElementById('main-menu');
// check if the left aside menu is fixed
if (!navBar.classList.contains('expanded')) {
this._renderer.addClass(navBar, 'expanded');
this._renderer.addClass(mainMenu, 'expanded');
this.resetOpenMenu();
this.setOpenInNavbar(true);
}
}
/**
* Use for fixed left aside menu, to show menu on mouseenter event.
* @param e Event
*/
mouseLeave(event) {
if (this.navbarService.isFixedMenu()) {
return;
}
const _self = this;
const navBar = this.document.getElementById('navbar-header');
const mainMenu = this.document.getElementById('main-menu');
if (navBar && navBar.classList.contains('expanded')) {
this.insideTm = setTimeout(() => {
if (!_self.navbarService.isMouseInRegion()) {
this._renderer.removeClass(navBar, 'expanded');
this._renderer.removeClass(mainMenu, 'expanded');
this.resetOpenMenu();
this.setOpenInNavbar(false);
}
}, 100);
}
this.navbarService.setMouseInRegion(false);
}
resetOtherActiveMenu(selectedChild, isSubmenuOfSubmenu) {
for (let i = 0; i < this._menuSettingsConfig.vertical_menu.items.length; i++) {
this._menuSettingsConfig.vertical_menu.items[i]['isSelected'] = false;
this._menuSettingsConfig.vertical_menu.items[i]['hover'] = false;
this.handleSubmenuItems(this._menuSettingsConfig.vertical_menu.items[i], selectedChild, isSubmenuOfSubmenu);
}
}
handleSubmenuItems(parentItem, selectedChild, isSubmenuOfSubmenu) {
if (selectedChild['title'] === 'Horizontal') {
localStorage.setItem('currentLayoutStyle', AppConstants.LAYOUT_STYLE_HORIZONTAL);
window.location.reload();
} else if (selectedChild['title'] === 'Vertical') {
localStorage.setItem('currentLayoutStyle', AppConstants.LAYOUT_STYLE_VERTICAL);
window.location.reload();
} else if (parentItem['submenu'] &&
parentItem['submenu']['items'] &&
parentItem['submenu']['items'].length > 0) {
if (parentItem.title !== selectedChild.title && parentItem['isOpen'] === true && !isSubmenuOfSubmenu &&
this._themeSettingsConfig.navigation === AppConstants.NAVIGATION_TYPE_COLLAPSIBLE) {
parentItem['isOpen'] = false;
}
for (let j = 0; j < parentItem['submenu']['items'].length; j++) {
if (selectedChild.page !== 'null') {
parentItem['submenu']['items'][j]['isSelected'] = false;
}
this.handleSubmenuItems(parentItem['submenu']['items'][j], selectedChild, isSubmenuOfSubmenu);
}
} else if (parentItem.title !== selectedChild.title && !selectedChild.submenu
&& this._themeSettingsConfig.navigation === AppConstants.NAVIGATION_TYPE_COLLAPSIBLE
&& parentItem['isOpen'] === true) {
parentItem['isOpen'] = false;
}
}
toggleMenu(event, child, isSubmenuOfSubmenu) {
const toggle = document.getElementById('sidenav-overlay');
this.resetOtherActiveMenu(child, isSubmenuOfSubmenu);
this.loggedInUser = JSON.parse(localStorage.getItem('currentUser'));
if (child['isSelected'] === true) {
child['isSelected'] = false;
} else {
child['isSelected'] = true;
}
if (child['hover'] === true) {
child['hover'] = false;
} else {
child['hover'] = true;
}
if (child['isOpen'] === true) {
child['isOpen'] = false;
} else {
child['isOpen'] = true;
}
if (this.router.url !== '') {
this._renderer.addClass(toggle, 'd-none');
this._renderer.removeClass(toggle, 'd-block');
}
if ( child.page === '/chats' && this.loggedInUser.email === 'john@pixinvent.com') {
this.router.navigate(['/chats/static-chat']);
} else if ( child.page === '/chats' && this.loggedInUser.email !== 'john@pixinvent.com') {
this.router.navigate(['/chats']);
}
}
}

View File

@@ -0,0 +1,14 @@
<div (window:resize)="onResize($event)"></div>
<app-navigation></app-navigation>
<router-outlet></router-outlet>
<div class="sidenav-overlay d-none" id="sidenav-overlay" (click)="rightbar($event)"></div>
<app-footer></app-footer>
<div *ngIf ="customizer === 'on'">
<app-customizer *ngIf="layout === 'vertical'"></app-customizer>
<app-horizontal-customizer *ngIf="layout === 'horizontal'"></app-horizontal-customizer>
</div>
<div *ngIf ="buybutton === 'on'">
<div class="buy-now" >
<a href="https://1.envato.market/modern_admin_angular" target="_blank" class="btn bg-gradient-directional-purple round white btn-purple btn-glow px-2">Buy Now</a>
</div>
</div>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { PrivateLayoutComponent } from './private-layout.component';
describe('PrivateLayoutComponent', () => {
let component: PrivateLayoutComponent;
let fixture: ComponentFixture<PrivateLayoutComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ PrivateLayoutComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PrivateLayoutComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,322 @@
import { Component, OnInit, Renderer2, HostListener, Inject } from '@angular/core';
import { ThemeSettingsService } from '../settings/theme-settings.service';
import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { DeviceDetectorService } from '../../_services/device-detector.service';
import { AppConstants } from '../../_helpers/app.constants';
import { Router, NavigationStart, NavigationEnd, Event, NavigationError } from '@angular/router';
import { DOCUMENT } from '@angular/common';
import { NavbarService } from 'src/app/_services/navbar.service';
@Component({
selector: 'app-private-layout',
templateUrl: './private-layout.component.html',
styleUrls: ['./private-layout.component.css']
})
export class PrivateLayoutComponent implements OnInit {
private _unsubscribeAll: Subject<any>;
private _themeSettingsConfig: any;
public layout: any;
public customizer: any;
public buybutton: any;
deviceInfo = null;
constructor(private renderer: Renderer2,
@Inject(DOCUMENT) private document: Document,
private router: Router,
private navbarService: NavbarService,
private _themeSettingsService: ThemeSettingsService,
private deviceService: DeviceDetectorService) {
this._unsubscribeAll = new Subject();
this.router.events.subscribe((event: Event) => {
if (event instanceof NavigationStart) {
// Show loading indicator
}
if (event instanceof NavigationEnd) {
// Hide loading indicator
if (this.router.url === '/chats' || this.router.url === '/chats/static-chat') {
this.renderer.addClass(document.body, 'chat-application');
} else {
this.renderer.removeClass(document.body, 'chat-application');
}
if (this.router.url === '/email') {
this.renderer.addClass(document.body, 'email-application');
} else {
this.renderer.removeClass(document.body, 'email-application');
}
if (this.router.url === '/contacts') {
this.renderer.addClass(document.body, 'app-contacts');
} else {
this.renderer.removeClass(document.body, 'app-contacts');
}
if (this.router.url === '/todos') {
this.renderer.addClass(document.body, 'todo');
} else {
this.renderer.removeClass(document.body, 'todo');
}
if (this.router.url === '/todo-app') {
this.renderer.addClass(document.body, 'todo-application');
} else {
this.renderer.removeClass(document.body, 'todo-application');
}
}
if (event instanceof NavigationError) {
// Hide loading indicator
}
});
}
ngOnInit() {
this.renderer.removeClass(document.body, 'bg-full-screen-image');
// Subscribe to config changes
this._themeSettingsService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._themeSettingsConfig = config;
if (localStorage.getItem('currentLayoutStyle')) {
this._themeSettingsConfig.layout.style = localStorage.getItem('currentLayoutStyle');
}
});
this.deviceInfo = this.deviceService.getDeviceInfo();
const isMobile = this.deviceService.isMobile();
this.handleBody(isMobile);
this.handleCollapsibleMenu();
}
handleBody(isMobile: boolean) {
const _self = this;
if (this._themeSettingsConfig.layout.style === 'vertical') {
_self.renderer.setAttribute(document.body, 'data-menu', 'vertical-menu-modern');
} else {
_self.renderer.setAttribute(document.body, 'data-menu', 'horizontal-menu-modern');
}
let currentBodyClassList = [];
this.layout = this._themeSettingsConfig.layout.style;
this.customizer = this._themeSettingsConfig.customizer;
this.buybutton = this._themeSettingsConfig.buybutton;
// Vertical resposive view
if (this._themeSettingsConfig.layout.style === 'vertical' &&
window.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH) {
const previosBodyClassList = [].slice.call(document.body.classList);
previosBodyClassList.forEach(function (c) {
_self.renderer.removeClass(document.body, c);
});
if (this._themeSettingsConfig.layout.style === 'vertical') {
currentBodyClassList = ['vertical-layout', 'vertical-overlay-menu', '2-columns', 'pace-done', 'menu-close', 'fixed-navbar'];
if (this._themeSettingsConfig.layout.pattern === 'fixed') {
currentBodyClassList.push('fixed-navbar');
}
} else {
currentBodyClassList = ['vertical-layout', '2-columns', 'vertical-overlay-menu', 'pace-done', 'menu-hide'];
}
if (this._themeSettingsConfig.layout.pattern === 'fixed') {
currentBodyClassList.push('fixed-navbar');
}
if (this._themeSettingsConfig.layout.pattern === '') {
currentBodyClassList.push('fixed-navbar');
}
if (this._themeSettingsConfig.layout.pattern === 'boxed') {
this.renderer.addClass(document.body, 'boxed-layout');
this.renderer.addClass(document.body, 'container');
this.renderer.addClass(document.body, 'fixed-navbar');
}
// Horizontal resposive view
} else if (this._themeSettingsConfig.layout.style === 'horizontal' &&
window.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH_HORIZONTAL) {
const previosBodyClassList = [].slice.call(document.body.classList);
previosBodyClassList.forEach(function (c) {
_self.renderer.removeClass(document.body, c);
});
currentBodyClassList = ['horizontal-layout', 'horizontal-menu', '2-columns', 'pace-done',
'fixed-navbar', 'menu-hide'];
if (this._themeSettingsConfig.layout.pattern === 'fixed') {
currentBodyClassList.push('fixed-navbar');
}
if (this._themeSettingsConfig.layout.pattern === '') {
currentBodyClassList.push('fixed-navbar');
}
if (this._themeSettingsConfig.layout.pattern === 'boxed') {
this.renderer.addClass(document.body, 'boxed-layout');
this.renderer.addClass(document.body, 'container');
this.renderer.addClass(document.body, 'fixed-navbar');
}
// Normal view
} else {
const previosBodyClassList = [].slice.call(document.body.classList);
let callapseOrExpanded = '';
previosBodyClassList.forEach(function (c) {
if (c === 'menu-collapsed') {
callapseOrExpanded = 'menu-collapsed';
} else if (c === 'menu-expanded') {
callapseOrExpanded = 'menu-expanded';
}
_self.renderer.removeClass(document.body, c);
});
if (this._themeSettingsConfig.layout.style === 'vertical') {
if (callapseOrExpanded === '') {
const toggleIcon = document.getElementsByClassName('toggle-icon');
if (toggleIcon.item && toggleIcon.item(0) &&
toggleIcon.item(0).classList.contains('ft-toggle-right')) {
callapseOrExpanded = 'menu-expanded';
} else {
callapseOrExpanded = 'menu-collapsed';
}
}
// callapseOrExpanded = callapseOrExpanded !== '' ? callapseOrExpanded : 'menu-collapsed';
currentBodyClassList = ['vertical-layout', 'vertical-menu-modern', '2-columns', 'pace-done', 'menu-close', callapseOrExpanded];
if (this._themeSettingsConfig.layout.pattern === 'fixed') {
currentBodyClassList.push('fixed-navbar');
}
if (this._themeSettingsConfig.layout.pattern === '') {
currentBodyClassList.push('fixed-navbar');
}
if (this._themeSettingsConfig.layout.pattern === 'boxed') {
this.renderer.addClass(document.body, 'boxed-layout');
this.renderer.addClass(document.body, 'container');
this.renderer.addClass(document.body, 'fixed-navbar');
}
} else {
currentBodyClassList = ['horizontal-layout', '2-columns', 'horizontal-menu'];
if (window.innerWidth >= AppConstants.MOBILE_RESPONSIVE_WIDTH) {
currentBodyClassList.push('menu-expanded');
} else {
currentBodyClassList.push('menu-collapsed');
}
if (this._themeSettingsConfig.layout.pattern === 'boxed') {
this.renderer.addClass(document.body, 'boxed-layout');
this.renderer.addClass(document.body, 'container');
}
}
}
const footer = document.getElementById('footer');
// if (this.router.url == '/chats') {
// const footer = document.getElementById('footer');
if (this.router.url === '/chats' || this.router.url === '/chats/static-chat') {
currentBodyClassList.push('chat-application');
// footer.classList.add('fixed-bottom');
} else if (currentBodyClassList.includes('fixed-bottom')) {
currentBodyClassList.push('chat-application');
currentBodyClassList = currentBodyClassList.filter(item => item !== 'fixed-bottom');
footer.classList.remove('fixed-bottom');
}
if (this.router.url === '/email') {
currentBodyClassList.push('email-application');
// footer.classList.add('fixed-bottom');
} else if (currentBodyClassList.includes('fixed-bottom')) {
currentBodyClassList.push('email-application');
currentBodyClassList = currentBodyClassList.filter(item => item !== 'fixed-bottom');
footer.classList.remove('fixed-bottom');
}
if (this.router.url === '/contacts') {
currentBodyClassList.push('app-contacts');
}
if (this.router.url === '/todos') {
currentBodyClassList.push('todo');
}
if (this.router.url === '/todo-app') {
currentBodyClassList.push('todo-application');
}
currentBodyClassList.forEach(function (c) {
_self.renderer.addClass(document.body, c);
});
this.handleFullScreen();
}
handleFullScreen() {
const toggleIcon = document.getElementsByClassName('ficon');
if (window.innerWidth === screen.width && window.innerHeight === screen.height && toggleIcon.item(0)) {
this.renderer.removeClass(toggleIcon.item(0), 'ft-maximize');
this.renderer.addClass(toggleIcon.item(0), 'ft-minimize');
} else if (toggleIcon.item(0)) {
this.renderer.addClass(toggleIcon.item(0), 'ft-maximize');
this.renderer.removeClass(toggleIcon.item(0), 'ft-minimize');
}
}
handleCollapsibleMenu() {
if (this._themeSettingsConfig.menu === 'collapse') {
// show the left aside menu
this.navbarService.setFixedMenu(false);
this.document.body.classList.remove('menu-expanded');
this.document.body.classList.add('menu-collapsed');
} else {
this.navbarService.setFixedMenu(true);
this.document.body.classList.remove('menu-collapsed');
this.document.body.classList.add('menu-expanded');
}
}
@HostListener('window:resize', ['$event'])
onResize(event) {
const menuClose = document.body.getElementsByClassName('menu-close');
const toggle = document.getElementsByClassName('content-overlay');
const sidenavOverlay = document.getElementsByClassName('sidenav-overlay');
const emailMenu = document.getElementsByClassName('email-app-menu');
const toggleIcon = document.getElementById('sidebar-left');
if (event.target.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH) {
this.handleBody(true);
if (menuClose) {
this.renderer.removeClass(sidenavOverlay.item(0), 'd-block');
this.renderer.addClass(sidenavOverlay.item(0), 'd-none');
}
} else {
this.handleBody(false);
}
if (toggle && (this.router.url === '/chats' || this.router.url === '/static-chat' ||
this.router.url === '/todos' || this.router.url === '/contacts') &&
event.target.innerWidth > AppConstants.MOBILE_RESPONSIVE_WIDTH) {
this.renderer.removeClass(toggle.item(0), 'show');
this.renderer.removeClass(sidenavOverlay.item(0), 'd-block');
this.renderer.addClass(sidenavOverlay.item(0), 'd-none');
this.renderer.removeClass(toggleIcon, 'show');
}
if ((toggle || sidenavOverlay) && this.router.url === '/email' && event.target.innerWidth > 767) {
this.renderer.removeClass(toggle.item(0), 'show');
this.renderer.removeClass(emailMenu.item(0), 'show');
this.renderer.removeClass(sidenavOverlay.item(0), 'd-block');
this.renderer.addClass(sidenavOverlay.item(0), 'd-none');
}
}
rightbar(event) {
const toggle = document.getElementById('sidenav-overlay');
if (event.currentTarget.className === 'sidenav-overlay d-block') {
this.renderer.removeClass(toggle, 'd-block');
this.document.body.classList.remove('menu-open');
this.document.body.classList.add('menu-close');
this.renderer.addClass(toggle, 'd-none');
} else if (event.currentTarget.className === 'sidenav-overlay d-none') {
this.renderer.removeClass(toggle, 'd-none');
this.document.body.classList.remove('menu-close');
this.document.body.classList.add('menu-open');
this.renderer.addClass(toggle, 'd-block');
}
}
}

View File

@@ -0,0 +1,2 @@
<router-outlet></router-outlet>
<div class="sidenav-overlay d-none" id="sidenav-overlay" (click)="rightbar($event)"></div>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { PublicLayoutComponent } from './public-layout.component';
describe('PublicLayoutComponent', () => {
let component: PublicLayoutComponent;
let fixture: ComponentFixture<PublicLayoutComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ PublicLayoutComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PublicLayoutComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,50 @@
import { Component, OnInit, Renderer2, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { Router, NavigationStart, NavigationEnd, Event, NavigationError } from '@angular/router';
@Component({
selector: 'app-public-layout',
templateUrl: './public-layout.component.html',
styleUrls: ['./public-layout.component.css']
})
export class PublicLayoutComponent implements OnInit {
constructor(private renderer: Renderer2,
private router: Router,
@Inject(DOCUMENT) private document: Document) {}
ngOnInit() {
this.setBodyClass();
}
rightbar(event) {
const toggle = document.getElementById('sidenav-overlay');
if (event.currentTarget.className === 'sidenav-overlay d-block') {
this.renderer.removeClass(toggle, 'd-block');
this.document.body.classList.remove('menu-open');
this.document.body.classList.add('menu-close');
this.renderer.addClass(toggle, 'd-none');
} else if (event.currentTarget.className === 'sidenav-overlay d-none') {
this.renderer.removeClass(toggle, 'd-none');
this.document.body.classList.remove('menu-close');
this.document.body.classList.add('menu-open');
this.renderer.addClass(toggle, 'd-block');
}
}
setBodyClass() {
const previosBodyClassList = [].slice.call(document.body.classList);
const self = this;
previosBodyClassList.forEach(function (c) {
self.renderer.removeClass(document.body, c);
});
const currentBodyClassList = ['vertical-layout', 'bg-full-screen-image', 'vertical-overlay-menu',
'2-columns', 'pace-done', 'menu-close', 'fixed-navbar'];
currentBodyClassList.forEach(function (c) {
self.renderer.addClass(document.body, c);
});
// if (this.router.url === '/login' || (this.router.url === '')) {
// this.renderer.removeClass(document.body, 'fixed-navbar');
// } else {
// this.renderer.addClass(document.body, 'fixed-navbar');
// }
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
import { Injectable, InjectionToken, Inject } from '@angular/core';
import { Router, RoutesRecognized } from '@angular/router';
import { BehaviorSubject, Observable } from 'rxjs';
import { filter } from 'rxjs/operators';
import * as _ from 'lodash';
export const MENU_SETTINGS_CONFIG = new InjectionToken('menuCustomConfig');
@Injectable({
providedIn: 'root'
})
export class MenuSettingsService {
private _configSubject: BehaviorSubject<any>;
private readonly _defaultConfig: any;
constructor(private _router: Router, @Inject(MENU_SETTINGS_CONFIG) private _config) {
// Set the default config from the user provided config (from forRoot)
this._defaultConfig = _config;
// Initialize the service
this._init();
}
private _init(): void {
// Set the config from the default config
this._configSubject = new BehaviorSubject(_.cloneDeep(this._defaultConfig));
// 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 RoutesRecognized))
.subscribe(() => {
if (!_.isEqual(this._configSubject.getValue().layout, this._defaultConfig.layout)) {
// Clone the current config
const config = _.cloneDeep(this._configSubject.getValue());
// Set the config
this._configSubject.next(config);
}
});
}
set config(value) {
// Get the value from the behavior subject
let config = this._configSubject.getValue();
// Merge the new config
config = _.merge({}, config, value);
// Notify the observers
this._configSubject.next(config);
}
get config(): any | Observable<any> {
return this._configSubject.asObservable();
}
}

View File

@@ -0,0 +1,28 @@
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
import { THEME_SETTINGS_CONFIG } from './theme-settings.service';
import { MENU_SETTINGS_CONFIG } from './menu-settings.service';
@NgModule()
export class SettingsModule {
constructor(@Optional() @SkipSelf() parentModule: SettingsModule) {
if (parentModule) {
throw new Error('SettingsModule is already loaded. Import it in the AppModule only!');
}
}
static forRoot(themeConfig, menuConfig): ModuleWithProviders<SettingsModule> {
return {
ngModule: SettingsModule,
providers: [
{
provide: THEME_SETTINGS_CONFIG,
useValue: themeConfig
},
{
provide: MENU_SETTINGS_CONFIG,
useValue: menuConfig
}
]
};
}
}

View File

@@ -0,0 +1,33 @@
// Default theme settings configurations
export const ThemeSettingsConfig = {
colorTheme: 'semi-dark', // light, semi-light, semi-dark, dark
layout: {
style: 'vertical', // style: 'vertical', horizontal,
pattern: 'fixed' // fixed, boxed, static
},
menuColor: 'menu-dark', // Vertical: [menu-dark, menu-light] , Horizontal: [navbar-dark, navbar-light]
navigation: 'menu-collapsible', // menu-collapsible, menu-accordation
menu: 'expand', // collapse, expand
header: 'fix', // fix, static
footer: 'static', // fix, static
customizer: 'on', // on,off
buybutton: 'on', // on, off
headerIcons: {
maximize: 'on', // on, off
search: 'on', // on, off
internationalization: 'on', // on, off
notification: 'on', // on, off
email: 'on' // on, off
},
brand: {
brand_name: 'Modern ',
logo: {
type: 'internal', // internal, url
value: 'assets/custom/images/logo.png' // recommended location for custom images
// type:'url',
// value:'http://evolvision.com/wp-content/uploads/2018/01/envelope4-green.png'
},
},
defaultTitleSuffix: 'Modern Admin - Angular 11+ Bootstrap 5 Admin Dashboard Template'
};

View File

@@ -0,0 +1,63 @@
import { Injectable, InjectionToken, Inject } from '@angular/core';
import { Router, RoutesRecognized } from '@angular/router';
import { BehaviorSubject, Observable } from 'rxjs';
import { filter } from 'rxjs/operators';
import * as _ from 'lodash';
export const THEME_SETTINGS_CONFIG = new InjectionToken('themeCustomConfig');
@Injectable({
providedIn: 'root'
})
export class ThemeSettingsService {
// Private
private _configSubject: BehaviorSubject<any>;
private readonly _defaultConfig: any;
constructor(private _router: Router, @Inject(THEME_SETTINGS_CONFIG) private _config) {
// Set the default config from the user provided config (from forRoot)
this._defaultConfig = _config;
// Initialize the service
this._init();
}
private _init(): void {
// Set the config from the default config
this._configSubject = new BehaviorSubject(_.cloneDeep(this._defaultConfig));
// 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 RoutesRecognized))
.subscribe(() => {
if (!_.isEqual(this._configSubject.getValue().layout, this._defaultConfig.layout)) {
// Clone the current config
const config = _.cloneDeep(this._configSubject.getValue());
// Reset the layout from the default config
// config.layout = _.cloneDeep(this._defaultConfig.layout);
// Set the config
this._configSubject.next(config);
}
});
}
set config(value) {
// Get the value from the behavior subject
let config = this._configSubject.getValue();
// Merge the new config
config = _.merge({}, config, value);
// Notify the observers
this._configSubject.next(config);
}
get config(): any | Observable<any> {
return this._configSubject.asObservable();
}
}