first commit
This commit is contained in:
12
src/app/_api/chat/chat.service.spec.ts
Normal file
12
src/app/_api/chat/chat.service.spec.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ChatService } from './chat.service';
|
||||
|
||||
describe('ChatService', () => {
|
||||
beforeEach(() => TestBed.configureTestingModule({}));
|
||||
|
||||
it('should be created', () => {
|
||||
const service: ChatService = TestBed.get(ChatService);
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
45
src/app/_api/chat/chat.service.ts
Normal file
45
src/app/_api/chat/chat.service.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AngularFirestore } from '@angular/fire/compat/firestore';
|
||||
import { Chats } from 'src/app/content/applications/chat/chats';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Timestamp, FieldValue, arrayUnion } from "firebase/firestore";
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ChatService {
|
||||
|
||||
constructor(private afs: AngularFirestore) { }
|
||||
|
||||
getChats() {
|
||||
return this.afs.collection('chatroom').snapshotChanges();
|
||||
}
|
||||
|
||||
createChatRoom(data) {
|
||||
return this.afs.collection('chatroom').add(data);
|
||||
}
|
||||
|
||||
showChat(id): Observable<Chats> {
|
||||
const chat = this.afs.doc<Chats>('chatroom/' + id);
|
||||
return chat.snapshotChanges()
|
||||
.pipe(
|
||||
map(changes => {
|
||||
const data = changes.payload.data() as Chats;
|
||||
const chatId = changes.payload.id;
|
||||
return { chatId, ...data };
|
||||
}));
|
||||
}
|
||||
|
||||
sendMessage(chatId, data) {
|
||||
return this.afs.collection('chatroom').doc(chatId).update({
|
||||
chatHistory: arrayUnion(data)
|
||||
});
|
||||
}
|
||||
|
||||
updateChatStatus (chatId, history) {
|
||||
return this.afs.collection('chatroom').doc(chatId).update({
|
||||
chatHistory: history
|
||||
});
|
||||
}
|
||||
}
|
||||
12
src/app/_api/todo/todo.service.spec.ts
Normal file
12
src/app/_api/todo/todo.service.spec.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TodoService } from './todo.service';
|
||||
|
||||
describe('TodoService', () => {
|
||||
beforeEach(() => TestBed.configureTestingModule({}));
|
||||
|
||||
it('should be created', () => {
|
||||
const service: TodoService = TestBed.get(TodoService);
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
53
src/app/_api/todo/todo.service.ts
Normal file
53
src/app/_api/todo/todo.service.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AngularFirestore } from '@angular/fire/compat/firestore';
|
||||
import firebase from 'firebase/compat/app';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class TodoService {
|
||||
|
||||
formData;
|
||||
loggedInUser = JSON.parse(localStorage.getItem('currentUser'));
|
||||
ref = firebase.firestore().collection('todo');
|
||||
|
||||
constructor(private firestore: AngularFirestore) {
|
||||
}
|
||||
|
||||
getTODOS(userId) {
|
||||
return this.firestore.collection('todo', ref => ref.orderBy('createdDate', 'desc')
|
||||
.where('uid', '==', userId)).snapshotChanges();
|
||||
}
|
||||
|
||||
getAssignedTODOS(userId) {
|
||||
return this.firestore.collection('todo', ref => ref.orderBy('createdDate', 'desc')
|
||||
.where('assignedTo.uid', '==', userId)).snapshotChanges();
|
||||
}
|
||||
|
||||
createTodo(todo): Observable<any> {
|
||||
return new Observable((observer) => {
|
||||
this.ref.add(todo).then((doc) => {
|
||||
observer.next({
|
||||
data: doc
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
sendMessage(todoId, data) {
|
||||
return this.firestore.collection('todo').doc(todoId).update({
|
||||
todoComments: data
|
||||
});
|
||||
}
|
||||
updateTODO(id: string, data): Observable<any> {
|
||||
return new Observable((observer) => {
|
||||
this.ref.doc(id).set(data).then(() => {
|
||||
observer.next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
deleteTodo(id: string): Promise<void> {
|
||||
return this.ref.doc(id).delete();
|
||||
}
|
||||
}
|
||||
12
src/app/_api/user/user.service.spec.ts
Normal file
12
src/app/_api/user/user.service.spec.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { UserService } from './user.service';
|
||||
|
||||
describe('UserService', () => {
|
||||
beforeEach(() => TestBed.configureTestingModule({}));
|
||||
|
||||
it('should be created', () => {
|
||||
const service: UserService = TestBed.get(UserService);
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
27
src/app/_api/user/user.service.ts
Normal file
27
src/app/_api/user/user.service.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AngularFirestore } from '@angular/fire/compat/firestore';
|
||||
import firebase from 'firebase/compat/app';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UserService {
|
||||
ref = firebase.firestore().collection('users');
|
||||
|
||||
constructor(private firestore: AngularFirestore) {
|
||||
}
|
||||
|
||||
getUsers() {
|
||||
return this.firestore.collection('users').snapshotChanges();
|
||||
}
|
||||
|
||||
getCurrentUser(userId): Observable<any> {
|
||||
return this.firestore.collection('users', ref => ref.where('uid', '==', userId)).snapshotChanges();
|
||||
}
|
||||
|
||||
createUser(user) {
|
||||
return this.ref.add(user);
|
||||
}
|
||||
|
||||
}
|
||||
30
src/app/_directives/card.directive.ts
Normal file
30
src/app/_directives/card.directive.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import {
|
||||
Directive,
|
||||
AfterViewInit,
|
||||
OnDestroy,
|
||||
ElementRef,
|
||||
OnInit,
|
||||
Input,
|
||||
HostBinding
|
||||
} from '@angular/core';
|
||||
|
||||
interface CardOptions {
|
||||
enableSticky?: boolean;
|
||||
headOverlay?: boolean;
|
||||
headLarge?: boolean;
|
||||
class?: string[];
|
||||
}
|
||||
|
||||
@Directive({
|
||||
selector: '[mCard]'
|
||||
})
|
||||
export class CardDirective {
|
||||
card: any;
|
||||
|
||||
@Input() options: CardOptions;
|
||||
@HostBinding('class') class: any;
|
||||
|
||||
constructor(private el: ElementRef) {
|
||||
this.class = this.el.nativeElement.classList;
|
||||
}
|
||||
}
|
||||
23
src/app/_directives/image.preload.directive.ts
Normal file
23
src/app/_directives/image.preload.directive.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Directive, Input, HostBinding } from '@angular/core'
|
||||
/* eslint-disable @angular-eslint/no-host-metadata-property */
|
||||
/* eslint-disable @angular-eslint/directive-selector */
|
||||
@Directive({
|
||||
selector: 'img[default]',
|
||||
host: {
|
||||
'(error)': 'updateUrl()',
|
||||
'(load)': 'load()',
|
||||
'[src]': 'src'
|
||||
}
|
||||
})
|
||||
export class ImagePreloadDirective {
|
||||
@Input() src: string;
|
||||
@Input() default: string;
|
||||
@HostBinding('class') className;
|
||||
|
||||
updateUrl() {
|
||||
this.src = this.default;
|
||||
}
|
||||
load() {
|
||||
this.className = 'image-loaded';
|
||||
}
|
||||
}
|
||||
64
src/app/_directives/match-height.directive.ts
Normal file
64
src/app/_directives/match-height.directive.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { Directive, ElementRef, Input, HostListener, AfterViewInit } from '@angular/core';
|
||||
/* eslint-disable @angular-eslint/directive-selector */
|
||||
@Directive({
|
||||
selector: '[matchHeight]'
|
||||
})
|
||||
export class MatchHeightDirective implements AfterViewInit {
|
||||
// class name to match height
|
||||
@Input()
|
||||
matchHeight: string;
|
||||
|
||||
constructor(private el: ElementRef) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
// call our matchHeight function here
|
||||
setTimeout(() => {
|
||||
this.matchHeights(this.el.nativeElement, this.matchHeight);
|
||||
}, 700);
|
||||
}
|
||||
|
||||
matchHeights(parent: HTMLElement, className: string) {
|
||||
if (!parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
// step 1: find all the child elements with the selected class name
|
||||
const children = parent.getElementsByClassName(className);
|
||||
|
||||
if (!children) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Match hight - fix --- comment below code
|
||||
Array.from(children).forEach((x: HTMLElement) => {
|
||||
x.style.height = 'initial';
|
||||
});
|
||||
|
||||
// step 2a: get all the child elements heights
|
||||
const itemHeights = Array.from(children).map(
|
||||
x => x.getBoundingClientRect().height
|
||||
);
|
||||
|
||||
// step 2b: find out the tallest
|
||||
const maxHeight = itemHeights.reduce((prev, curr) => {
|
||||
return curr > prev ? curr : prev;
|
||||
}, 0);
|
||||
|
||||
// step 3: update all the child elements to the tallest height
|
||||
if (window.innerWidth > 1200) {
|
||||
Array.from(children).forEach(
|
||||
(x: HTMLElement) => (x.style.height = `${maxHeight}px`)
|
||||
);
|
||||
} else if (window.innerWidth < 1199) {
|
||||
Array.from(children).forEach(
|
||||
(x: HTMLElement) => (x.style.height = `initial`)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('window:resize')
|
||||
onResize() {
|
||||
// call our matchHeight function here
|
||||
this.matchHeights(this.el.nativeElement, this.matchHeight);
|
||||
}
|
||||
}
|
||||
33
src/app/_directives/sortable.directive.ts
Normal file
33
src/app/_directives/sortable.directive.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Directive, EventEmitter, Input, Output } from '@angular/core';
|
||||
export type SortDirection = 'asc' | 'desc' | '';
|
||||
const rotate: { [key: string]: SortDirection } = {
|
||||
asc: 'desc',
|
||||
desc: '',
|
||||
'': 'asc'
|
||||
};
|
||||
|
||||
export interface SortEvent {
|
||||
column: string;
|
||||
direction: SortDirection;
|
||||
}
|
||||
/* eslint-disable @angular-eslint/directive-selector */
|
||||
/* eslint-disable @angular-eslint/no-host-metadata-property */
|
||||
/* eslint-disable @angular-eslint/directive-class-suffix */
|
||||
@Directive({
|
||||
selector: 'th[sortable]',
|
||||
host: {
|
||||
'[class.asc]': 'direction === "asc"',
|
||||
'[class.desc]': 'direction === "desc"',
|
||||
'(click)': 'rotate()'
|
||||
}
|
||||
})
|
||||
export class NgbdSortableHeader {
|
||||
@Input() sortable: string;
|
||||
@Input() direction: SortDirection = '';
|
||||
@Output() sort = new EventEmitter<SortEvent>();
|
||||
|
||||
rotate() {
|
||||
this.direction = rotate[this.direction];
|
||||
this.sort.emit({ column: this.sortable, direction: this.direction });
|
||||
}
|
||||
}
|
||||
20
src/app/_guards/auth.guard.ts
Normal file
20
src/app/_guards/auth.guard.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { AuthService } from '../_services/auth.service';
|
||||
|
||||
@Injectable()
|
||||
export class AuthGuard implements CanActivate {
|
||||
constructor(private router: Router) {}
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
if (localStorage.getItem('currentUser')) {
|
||||
// Logged in so return true
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Not logged in so redirect to login page with the return url
|
||||
this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
4
src/app/_helpers/alert.component.html
Normal file
4
src/app/_helpers/alert.component.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<div *ngIf !="message" [ngClass]="{ 'alert': message, 'alert-success': message.type === 'success',
|
||||
'alert-danger': message.type === 'error' }">
|
||||
{{message.text}}
|
||||
</div>
|
||||
25
src/app/_helpers/alert.component.ts
Normal file
25
src/app/_helpers/alert.component.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { AlertService } from '../_services/alert.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-alert',
|
||||
templateUrl: 'alert.component.html'
|
||||
})
|
||||
export class AlertComponent implements OnInit, OnDestroy {
|
||||
private subscription: Subscription;
|
||||
message: any;
|
||||
|
||||
constructor(private alertService: AlertService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.subscription = this.alertService.getMessage().subscribe(message => {
|
||||
this.message = message;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
14
src/app/_helpers/app.constants.ts
Normal file
14
src/app/_helpers/app.constants.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export class AppConstants {
|
||||
public static MOBILE_RESPONSIVE_WIDTH = 992;
|
||||
public static MOBILE_RESPONSIVE_WIDTH_HORIZONTAL = 768;
|
||||
public static NAVIGATION_TYPE_COLLAPSIBLE = 'menu-collapsible';
|
||||
public static NAVIGATION_TYPE_ACCORDATION = 'menu-accordation';
|
||||
public static LAYOUT_STYLE_HORIZONTAL = 'horizontal';
|
||||
public static LAYOUT_STYLE_VERTICAL = 'vertical';
|
||||
|
||||
public static fireRefreshEventOnWindow = function() {
|
||||
const evt = document.createEvent('HTMLEvents');
|
||||
evt.initEvent('resize', true, false);
|
||||
window.dispatchEvent(evt);
|
||||
};
|
||||
}
|
||||
95
src/app/_helpers/customwidget.ts
Normal file
95
src/app/_helpers/customwidget.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
export function init(Survey: any) {
|
||||
var widget = {
|
||||
//the widget name. It should be unique and written in lowcase.
|
||||
name: "textwithbutton",
|
||||
//the widget title. It is how it will appear on the toolbox of the SurveyJS Editor/Builder
|
||||
title: "Text with button",
|
||||
//the name of the icon on the toolbox. We will leave it empty to use the standard one
|
||||
iconName: "",
|
||||
//If the widgets depends on third-party library(s) then here you may check if this library(s) is loaded
|
||||
widgetIsLoaded: function () {
|
||||
//return typeof $ == "function" && !!$.fn.select2; //return true if jQuery and select2 widget are loaded on the page
|
||||
return true; //we do not require anything so we just return true.
|
||||
},
|
||||
//SurveyJS library calls this function for every question to check, if it should use this widget instead of default rendering/behavior
|
||||
isFit: function (question) {
|
||||
//we return true if the type of question is textwithbutton
|
||||
return question.getType() === "textwithbutton";
|
||||
//the following code will activate the widget for a text question with inputType equals to date
|
||||
//return question.getType() === 'text' && question.inputType === "date";
|
||||
},
|
||||
//Use this function to create a new class or add new properties or remove unneeded properties from your widget
|
||||
//activatedBy tells how your widget has been activated by: property, type or customType
|
||||
//property - it means that it will activated if a property of the existing question type is set to particular value, for example inputType = "date"
|
||||
//type - you are changing the behaviour of entire question type. For example render radiogroup question differently, have a fancy radio buttons
|
||||
//customType - you are creating a new type, like in our example "textwithbutton"
|
||||
activatedByChanged: function (activatedBy) {
|
||||
//we do not need to check acticatedBy parameter, since we will use our widget for customType only
|
||||
//We are creating a new class and derived it from text question type. It means that text model (properties and fuctions) will be available to us
|
||||
Survey.JsonObject.metaData.addClass("textwithbutton", [], null, "text");
|
||||
//signaturepad is derived from "empty" class - basic question class
|
||||
//Survey.JsonObject.metaData.addClass("signaturepad", [], null, "empty");
|
||||
|
||||
//Add new property(s)
|
||||
//For more information go to https://surveyjs.io/Examples/Builder/?id=addproperties#content-docs
|
||||
Survey.JsonObject.metaData.addProperties("textwithbutton", [
|
||||
{ name: "buttonText", default: "Click Me" },
|
||||
]);
|
||||
},
|
||||
//If you want to use the default question rendering then set this property to true. We do not need any default rendering, we will use our our htmlTemplate
|
||||
isDefaultRender: false,
|
||||
//You should use it if your set the isDefaultRender to false
|
||||
htmlTemplate: "<div><input /><button></button></div>",
|
||||
//The main function, rendering and two-way binding
|
||||
afterRender: function (question, el) {
|
||||
//el is our root element in htmlTemplate, is "div" in our case
|
||||
//get the text element
|
||||
var text = el.getElementsByTagName("input")[0];
|
||||
//set some properties
|
||||
text.inputType = question.inputType;
|
||||
text.placeholder = question.placeHolder;
|
||||
//get button and set some rpoeprties
|
||||
var button = el.getElementsByTagName("button")[0];
|
||||
button.innerText = question.buttonText;
|
||||
button.onclick = function () {
|
||||
question.value = "You have clicked me";
|
||||
};
|
||||
|
||||
//set the changed value into question value
|
||||
text.onchange = function () {
|
||||
question.value = text.value;
|
||||
};
|
||||
var onValueChangedCallback = function () {
|
||||
text.value = question.value ? question.value : "";
|
||||
};
|
||||
var onReadOnlyChangedCallback = function () {
|
||||
if (question.isReadOnly) {
|
||||
text.setAttribute("disabled", "disabled");
|
||||
button.setAttribute("disabled", "disabled");
|
||||
} else {
|
||||
text.removeAttribute("disabled");
|
||||
button.removeAttribute("disabled");
|
||||
}
|
||||
};
|
||||
//if question becomes readonly/enabled add/remove disabled attribute
|
||||
question.readOnlyChangedCallback = onReadOnlyChangedCallback;
|
||||
//if the question value changed in the code, for example you have changed it in JavaScript
|
||||
question.valueChangedCallback = onValueChangedCallback;
|
||||
//set initial value
|
||||
onValueChangedCallback();
|
||||
//make elements disabled if needed
|
||||
onReadOnlyChangedCallback();
|
||||
},
|
||||
//Use it to destroy the widget. It is typically needed by jQuery widgets
|
||||
willUnmount: function (question, el) {
|
||||
//We do not need to clear anything in our simple example
|
||||
//Here is the example to destroy the image picker
|
||||
//var $el = $(el).find("select");
|
||||
//$el.data('picker').destroy();
|
||||
},
|
||||
};
|
||||
|
||||
//Register our widget in singleton custom widget collection
|
||||
Survey.CustomWidgetCollection.Instance.addCustomWidget(widget, "customtype");
|
||||
}
|
||||
|
||||
19
src/app/_layout/blockui/block-template.component.ts
Normal file
19
src/app/_layout/blockui/block-template.component.ts
Normal 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;
|
||||
}
|
||||
20
src/app/_layout/breadcrumb/breadcrumb.component.css
Normal file
20
src/app/_layout/breadcrumb/breadcrumb.component.css
Normal 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;
|
||||
}
|
||||
}
|
||||
27
src/app/_layout/breadcrumb/breadcrumb.component.html
Normal file
27
src/app/_layout/breadcrumb/breadcrumb.component.html
Normal 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>
|
||||
25
src/app/_layout/breadcrumb/breadcrumb.component.spec.ts
Normal file
25
src/app/_layout/breadcrumb/breadcrumb.component.spec.ts
Normal 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();
|
||||
});
|
||||
});
|
||||
19
src/app/_layout/breadcrumb/breadcrumb.component.ts
Normal file
19
src/app/_layout/breadcrumb/breadcrumb.component.ts
Normal 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() {
|
||||
}
|
||||
}
|
||||
19
src/app/_layout/breadcrumb/breadcrumb.module.ts
Normal file
19
src/app/_layout/breadcrumb/breadcrumb.module.ts
Normal 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 { }
|
||||
22
src/app/_layout/customizer/customizer.component.css
Normal file
22
src/app/_layout/customizer/customizer.component.css
Normal 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);
|
||||
}
|
||||
394
src/app/_layout/customizer/customizer.component.html
Normal file
394
src/app/_layout/customizer/customizer.component.html
Normal 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>
|
||||
25
src/app/_layout/customizer/customizer.component.spec.ts
Normal file
25
src/app/_layout/customizer/customizer.component.spec.ts
Normal 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();
|
||||
});
|
||||
});
|
||||
386
src/app/_layout/customizer/customizer.component.ts
Normal file
386
src/app/_layout/customizer/customizer.component.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
0
src/app/_layout/footer/footer.component.css
Normal file
0
src/app/_layout/footer/footer.component.css
Normal file
29
src/app/_layout/footer/footer.component.html
Normal file
29
src/app/_layout/footer/footer.component.html
Normal 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 © 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 © 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 © 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>
|
||||
25
src/app/_layout/footer/footer.component.spec.ts
Normal file
25
src/app/_layout/footer/footer.component.spec.ts
Normal 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();
|
||||
});
|
||||
});
|
||||
77
src/app/_layout/footer/footer.component.ts
Normal file
77
src/app/_layout/footer/footer.component.ts
Normal 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;
|
||||
});
|
||||
}
|
||||
}
|
||||
4
src/app/_layout/full-layout/full-layout.component.html
Normal file
4
src/app/_layout/full-layout/full-layout.component.html
Normal 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>
|
||||
25
src/app/_layout/full-layout/full-layout.component.spec.ts
Normal file
25
src/app/_layout/full-layout/full-layout.component.spec.ts
Normal 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();
|
||||
});
|
||||
});
|
||||
124
src/app/_layout/full-layout/full-layout.component.ts
Normal file
124
src/app/_layout/full-layout/full-layout.component.ts
Normal 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');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
0
src/app/_layout/header/header.component.css
Normal file
0
src/app/_layout/header/header.component.css
Normal file
7
src/app/_layout/header/header.component.html
Normal file
7
src/app/_layout/header/header.component.html
Normal 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>
|
||||
25
src/app/_layout/header/header.component.spec.ts
Normal file
25
src/app/_layout/header/header.component.spec.ts
Normal 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();
|
||||
});
|
||||
});
|
||||
125
src/app/_layout/header/header.component.ts
Normal file
125
src/app/_layout/header/header.component.ts
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
12
src/app/_layout/header/horizontal/horizontal.component.css
Normal file
12
src/app/_layout/header/horizontal/horizontal.component.css
Normal 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;
|
||||
}
|
||||
215
src/app/_layout/header/horizontal/horizontal.component.html
Normal file
215
src/app/_layout/header/horizontal/horizontal.component.html
Normal 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>
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
280
src/app/_layout/header/horizontal/horizontal.component.ts
Normal file
280
src/app/_layout/header/horizontal/horizontal.component.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/app/_layout/header/vertical/vertical.component.css
Normal file
35
src/app/_layout/header/vertical/vertical.component.css
Normal 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;
|
||||
}
|
||||
226
src/app/_layout/header/vertical/vertical.component.html
Normal file
226
src/app/_layout/header/vertical/vertical.component.html
Normal 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>
|
||||
25
src/app/_layout/header/vertical/vertical.component.spec.ts
Normal file
25
src/app/_layout/header/vertical/vertical.component.spec.ts
Normal 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();
|
||||
});
|
||||
});
|
||||
477
src/app/_layout/header/vertical/vertical.component.ts
Normal file
477
src/app/_layout/header/vertical/vertical.component.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
0
src/app/_layout/navigation/navigation.component.css
Normal file
0
src/app/_layout/navigation/navigation.component.css
Normal file
10
src/app/_layout/navigation/navigation.component.html
Normal file
10
src/app/_layout/navigation/navigation.component.html
Normal 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>
|
||||
25
src/app/_layout/navigation/navigation.component.spec.ts
Normal file
25
src/app/_layout/navigation/navigation.component.spec.ts
Normal 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();
|
||||
});
|
||||
});
|
||||
47
src/app/_layout/navigation/navigation.component.ts
Normal file
47
src/app/_layout/navigation/navigation.component.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
57
src/app/_layout/navigation/navigation.config.ts
Normal file
57
src/app/_layout/navigation/navigation.config.ts
Normal 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'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
389
src/app/_layout/navigation/verticalnav/verticalnav.component.ts
Normal file
389
src/app/_layout/navigation/verticalnav/verticalnav.component.ts
Normal 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']);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
14
src/app/_layout/private-layout/private-layout.component.html
Normal file
14
src/app/_layout/private-layout/private-layout.component.html
Normal 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>
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
322
src/app/_layout/private-layout/private-layout.component.ts
Normal file
322
src/app/_layout/private-layout/private-layout.component.ts
Normal 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');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<router-outlet></router-outlet>
|
||||
<div class="sidenav-overlay d-none" id="sidenav-overlay" (click)="rightbar($event)"></div>
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
50
src/app/_layout/public-layout/public-layout.component.ts
Normal file
50
src/app/_layout/public-layout/public-layout.component.ts
Normal 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');
|
||||
// }
|
||||
}
|
||||
}
|
||||
1620
src/app/_layout/settings/menu-settings.config.ts
Normal file
1620
src/app/_layout/settings/menu-settings.config.ts
Normal file
File diff suppressed because it is too large
Load Diff
60
src/app/_layout/settings/menu-settings.service.ts
Normal file
60
src/app/_layout/settings/menu-settings.service.ts
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
28
src/app/_layout/settings/settings.module.ts
Normal file
28
src/app/_layout/settings/settings.module.ts
Normal 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
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
33
src/app/_layout/settings/theme-settings.config.ts
Normal file
33
src/app/_layout/settings/theme-settings.config.ts
Normal 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'
|
||||
};
|
||||
63
src/app/_layout/settings/theme-settings.service.ts
Normal file
63
src/app/_layout/settings/theme-settings.service.ts
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
38
src/app/_services/alert.service.ts
Normal file
38
src/app/_services/alert.service.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router, NavigationStart } from '@angular/router';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
|
||||
@Injectable()
|
||||
export class AlertService {
|
||||
private subject = new Subject<any>();
|
||||
private keepAfterNavigationChange = false;
|
||||
|
||||
constructor(private router: Router) {
|
||||
// Clear alert message on route change
|
||||
router.events.subscribe(event => {
|
||||
if (event instanceof NavigationStart) {
|
||||
if (this.keepAfterNavigationChange) {
|
||||
// Only keep for a single location change
|
||||
this.keepAfterNavigationChange = false;
|
||||
} else {
|
||||
// Clear alert
|
||||
this.subject.next({});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
success(message: string, keepAfterNavigationChange = false) {
|
||||
this.keepAfterNavigationChange = keepAfterNavigationChange;
|
||||
this.subject.next({ type: 'success', text: message });
|
||||
}
|
||||
|
||||
error(message: string, keepAfterNavigationChange = false) {
|
||||
this.keepAfterNavigationChange = keepAfterNavigationChange;
|
||||
this.subject.next({ type: 'error', text: message });
|
||||
}
|
||||
|
||||
getMessage(): Observable<any> {
|
||||
return this.subject.asObservable();
|
||||
}
|
||||
}
|
||||
12
src/app/_services/application-api.service.spec.ts
Normal file
12
src/app/_services/application-api.service.spec.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ApplicationApiService } from './application-api.service';
|
||||
|
||||
describe('ApplicationApiService', () => {
|
||||
beforeEach(() => TestBed.configureTestingModule({}));
|
||||
|
||||
it('should be created', () => {
|
||||
const service: ApplicationApiService = TestBed.get(ApplicationApiService);
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
49
src/app/_services/application-api.service.ts
Normal file
49
src/app/_services/application-api.service.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
|
||||
const httpOptions = {
|
||||
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
|
||||
};
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ApplicationApiService {
|
||||
apiBaseURL = 'assets/data';
|
||||
loadChatsDataURL = null;
|
||||
loadEmailDataURL = null;
|
||||
loadChatContactDataURL = null;
|
||||
constructor(private http: HttpClient) {
|
||||
this.loadChatsDataURL = `${this.apiBaseURL}/application/chats.json`;
|
||||
this.loadChatContactDataURL = `${this.apiBaseURL}/application/chatcontact.json`;
|
||||
this.loadEmailDataURL = `${this.apiBaseURL}/application/email.json`;
|
||||
}
|
||||
private handleError(error: HttpErrorResponse) {
|
||||
if (error.error instanceof ErrorEvent) {
|
||||
// Error
|
||||
console.error('error:', error.error.message);
|
||||
} else {
|
||||
// Error
|
||||
console.error(
|
||||
`Api server returned ${error.status}, ` +
|
||||
`error body: ${error.error}`);
|
||||
}
|
||||
// throwError is observable
|
||||
return throwError('Error has happened');
|
||||
}
|
||||
|
||||
private extractData(res: Response) {
|
||||
const body = res;
|
||||
return body || {};
|
||||
}
|
||||
getChatsData(): Observable<any> {
|
||||
return this.http.get(this.loadChatsDataURL, httpOptions);
|
||||
}
|
||||
getChatContactData(): Observable<any> {
|
||||
return this.http.get(this.loadChatContactDataURL, httpOptions);
|
||||
}
|
||||
getEmailData(): Observable<any> {
|
||||
return this.http.get(this.loadEmailDataURL, httpOptions);
|
||||
}
|
||||
}
|
||||
|
||||
120
src/app/_services/auth.service.ts
Normal file
120
src/app/_services/auth.service.ts
Normal file
@@ -0,0 +1,120 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AngularFireAuth } from '@angular/fire/compat/auth';
|
||||
import firebase from 'firebase/compat/app';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
constructor(public afAuth: AngularFireAuth) {}
|
||||
|
||||
// Facebook login
|
||||
doFacebookLogin() {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
const provider = new firebase.auth.FacebookAuthProvider();
|
||||
this.afAuth.signInWithPopup(provider).then(
|
||||
res => {
|
||||
resolve(res);
|
||||
},
|
||||
err => {
|
||||
console.log(err);
|
||||
reject(err);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Github login
|
||||
doGitHubLogin() {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
const provider = new firebase.auth.GithubAuthProvider();
|
||||
this.afAuth.signInWithPopup(provider).then(
|
||||
res => {
|
||||
resolve(res);
|
||||
},
|
||||
err => {
|
||||
console.log(err);
|
||||
reject(err);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Twitter login
|
||||
doTwitterLogin() {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
const provider = new firebase.auth.TwitterAuthProvider();
|
||||
this.afAuth.signInWithPopup(provider).then(
|
||||
res => {
|
||||
resolve(res);
|
||||
},
|
||||
err => {
|
||||
console.log(err);
|
||||
reject(err);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Google login
|
||||
doGoogleLogin() {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
const provider = new firebase.auth.GoogleAuthProvider();
|
||||
provider.addScope('profile');
|
||||
provider.addScope('email');
|
||||
this.afAuth.signInWithPopup(provider).then(
|
||||
res => {
|
||||
resolve(res);
|
||||
},
|
||||
err => {
|
||||
console.log(err);
|
||||
reject(err);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Register
|
||||
doRegister(value) {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
firebase
|
||||
.auth()
|
||||
.createUserWithEmailAndPassword(value.email, value.password)
|
||||
.then(
|
||||
res => {
|
||||
resolve(res);
|
||||
},
|
||||
err => reject(err)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Login
|
||||
doLogin(value) {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
firebase
|
||||
.auth()
|
||||
.signInWithEmailAndPassword(value.email, value.password)
|
||||
.then(
|
||||
res => {
|
||||
resolve(res);
|
||||
},
|
||||
err => reject(err)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Logout
|
||||
doLogout() {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (firebase.auth().currentUser) {
|
||||
localStorage.removeItem('currentUser');
|
||||
localStorage.removeItem('remember');
|
||||
this.afAuth.signOut();
|
||||
resolve();
|
||||
} else {
|
||||
localStorage.removeItem('currentUser');
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
66
src/app/_services/chart.api.ts
Normal file
66
src/app/_services/chart.api.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
|
||||
import { catchError, tap, map } from 'rxjs/operators';
|
||||
|
||||
const httpOptions = {
|
||||
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class ChartApiService {
|
||||
|
||||
apiBaseURL = 'assets/data';
|
||||
loadDataURL = null;
|
||||
loadSalesDataURL = null;
|
||||
loadEcommerceDataURL = null;
|
||||
loadStatisticsDataURL = null;
|
||||
loadTimelineDataURL = null;
|
||||
loadInvoiceDataURL = null;
|
||||
constructor(private http: HttpClient) {
|
||||
this.loadDataURL = `${this.apiBaseURL}/chartist/charts/chartist.json`;
|
||||
this.loadSalesDataURL = `${this.apiBaseURL}/dashboard/sales/chartist.json`;
|
||||
this.loadEcommerceDataURL = `${this.apiBaseURL}/dashboard/ecommerce/chartist.json`;
|
||||
this.loadStatisticsDataURL = `${this.apiBaseURL}/advancecard/statistics/chartist.json`;
|
||||
this.loadStatisticsDataURL = `${this.apiBaseURL}/advancecard/statistics/chartist.json`;
|
||||
this.loadTimelineDataURL = `${this.apiBaseURL}/user-profile/user-profile.json`;
|
||||
this.loadInvoiceDataURL = `${this.apiBaseURL}/invoice-summary/invoice-summary.json`;
|
||||
}
|
||||
private handleError(error: HttpErrorResponse) {
|
||||
if (error.error instanceof ErrorEvent) {
|
||||
// Error
|
||||
console.error('error:', error.error.message);
|
||||
} else {
|
||||
// Error
|
||||
console.error(
|
||||
`Api server returned ${error.status}, ` +
|
||||
`error body: ${error.error}`);
|
||||
}
|
||||
// throwError is observable
|
||||
return throwError('Error has happened');
|
||||
}
|
||||
|
||||
private extractData(res: Response) {
|
||||
const body = res;
|
||||
return body || {};
|
||||
}
|
||||
|
||||
getChartistData(): Observable<any> {
|
||||
return this.http.get(this.loadDataURL, httpOptions);
|
||||
}
|
||||
getSalesData(): Observable<any> {
|
||||
return this.http.get(this.loadSalesDataURL, httpOptions);
|
||||
}
|
||||
getEcommerceData(): Observable<any> {
|
||||
return this.http.get(this.loadEcommerceDataURL, httpOptions);
|
||||
}
|
||||
getStatisticsData(): Observable<any> {
|
||||
return this.http.get(this.loadStatisticsDataURL, httpOptions);
|
||||
}
|
||||
getTimelineData(): Observable<any> {
|
||||
return this.http.get(this.loadTimelineDataURL, httpOptions);
|
||||
}
|
||||
getInvoiceData(): Observable<any> {
|
||||
return this.http.get(this.loadInvoiceDataURL, httpOptions);
|
||||
}
|
||||
}
|
||||
105
src/app/_services/country.service.ts
Normal file
105
src/app/_services/country.service.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import {Injectable, PipeTransform} from '@angular/core';
|
||||
|
||||
import {BehaviorSubject, Observable, of, Subject} from 'rxjs';
|
||||
import {COUNTRIES, Country} from '../content/table/boostraptables/ngxboostraptables/countries';
|
||||
import {DecimalPipe} from '@angular/common';
|
||||
import {debounceTime, delay, switchMap, tap} from 'rxjs/operators';
|
||||
import {SortDirection} from '../_directives/sortable.directive';
|
||||
|
||||
interface SearchResult {
|
||||
countries: Country[];
|
||||
total: number;
|
||||
}
|
||||
|
||||
interface State {
|
||||
page: number;
|
||||
pageSize: number;
|
||||
searchTerm: string;
|
||||
sortColumn: string;
|
||||
sortDirection: SortDirection;
|
||||
}
|
||||
|
||||
function compare(v1, v2) {
|
||||
return v1 < v2 ? -1 : v1 > v2 ? 1 : 0;
|
||||
}
|
||||
|
||||
function sort(countries: Country[], column: string, direction: string): Country[] {
|
||||
if (direction === '') {
|
||||
return countries;
|
||||
} else {
|
||||
return [...countries].sort((a, b) => {
|
||||
const res = compare(a[column], b[column]);
|
||||
return direction === 'asc' ? res : -res;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function matches(country: Country, term: string, pipe: PipeTransform) {
|
||||
return country.firstname.toLowerCase().includes(term.toLowerCase())
|
||||
|| country.lastname.toLowerCase().includes(term.toLowerCase())
|
||||
|| country.username.toLowerCase().includes(term.toLowerCase());
|
||||
}
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class CountryService {
|
||||
private _loading$ = new BehaviorSubject<boolean>(true);
|
||||
private _search$ = new Subject<void>();
|
||||
private _countries$ = new BehaviorSubject<Country[]>([]);
|
||||
private _total$ = new BehaviorSubject<number>(0);
|
||||
|
||||
private _state: State = {
|
||||
page: 1,
|
||||
pageSize: 4,
|
||||
searchTerm: '',
|
||||
sortColumn: '',
|
||||
sortDirection: ''
|
||||
};
|
||||
|
||||
constructor(private pipe: DecimalPipe) {
|
||||
this._search$.pipe(
|
||||
tap(() => this._loading$.next(true)),
|
||||
debounceTime(200),
|
||||
switchMap(() => this._search()),
|
||||
delay(200),
|
||||
tap(() => this._loading$.next(false))
|
||||
).subscribe(result => {
|
||||
this._countries$.next(result.countries);
|
||||
this._total$.next(result.total);
|
||||
});
|
||||
|
||||
this._search$.next();
|
||||
}
|
||||
|
||||
get countries$() { return this._countries$.asObservable(); }
|
||||
get total$() { return this._total$.asObservable(); }
|
||||
get loading$() { return this._loading$.asObservable(); }
|
||||
get page() { return this._state.page; }
|
||||
get pageSize() { return this._state.pageSize; }
|
||||
get searchTerm() { return this._state.searchTerm; }
|
||||
|
||||
set page(page: number) { this._set({page}); }
|
||||
set pageSize(pageSize: number) { this._set({pageSize}); }
|
||||
set searchTerm(searchTerm: string) { this._set({searchTerm}); }
|
||||
set sortColumn(sortColumn: string) { this._set({sortColumn}); }
|
||||
set sortDirection(sortDirection: SortDirection) { this._set({sortDirection}); }
|
||||
|
||||
private _set(patch: Partial<State>) {
|
||||
Object.assign(this._state, patch);
|
||||
this._search$.next();
|
||||
}
|
||||
|
||||
private _search(): Observable<SearchResult> {
|
||||
const {sortColumn, sortDirection, pageSize, page, searchTerm} = this._state;
|
||||
|
||||
// 1. sort
|
||||
let countries = sort(COUNTRIES, sortColumn, sortDirection);
|
||||
|
||||
// 2. filter
|
||||
countries = countries.filter(country => matches(country, searchTerm, this.pipe));
|
||||
const total = countries.length;
|
||||
|
||||
// 3. paginate
|
||||
countries = countries.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize);
|
||||
return of({countries, total});
|
||||
}
|
||||
}
|
||||
86
src/app/_services/device-detector.service.ts
Normal file
86
src/app/_services/device-detector.service.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { PLATFORM_ID, Inject , Injectable} from '@angular/core'
|
||||
import { isPlatformBrowser } from '@angular/common'
|
||||
import { DeviceInfo, DevicePlatform, DeviceOs, DeviceMobile, DeviceTablet } from './device-detector'
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
||||
export class DeviceDetectorService {
|
||||
userAgent: string
|
||||
|
||||
constructor(@Inject(PLATFORM_ID) private platformId) {
|
||||
this.userAgent = isPlatformBrowser(this.platformId) ? window.navigator.userAgent.toLowerCase() : ''
|
||||
}
|
||||
|
||||
private find(match) {
|
||||
return this.userAgent.indexOf(match) !== -1
|
||||
}
|
||||
|
||||
private findMatch(type) {
|
||||
return Object.entries(type).find(([key, val]) => !!val) || []
|
||||
}
|
||||
|
||||
private deviceOS() {
|
||||
const isWindows = this.find('windows')
|
||||
const isIos = this.deviceShared()[DeviceMobile.Iphone] || this.deviceShared()[DeviceTablet.Ipad]
|
||||
|
||||
return {
|
||||
[DeviceOs.Windows]: isWindows,
|
||||
[DeviceOs.Macos]: !isIos && this.find('mac'),
|
||||
[DeviceOs.Android]: !isWindows && this.find('android'),
|
||||
[DeviceOs.Ios]: isIos,
|
||||
[DeviceOs.Blackberry]: this.find('blackberry') || this.find('bb10'),
|
||||
[DeviceOs.Fxos]: (this.find('(mobile') || this.find('(tablet')) && this.find(' rv:')
|
||||
}
|
||||
}
|
||||
|
||||
private deviceShared() {
|
||||
return {
|
||||
[DeviceMobile.Iphone]: !this.find('windows') && this.find('iphone'),
|
||||
[DeviceTablet.Ipad]: this.find('ipad') || navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1,
|
||||
}
|
||||
}
|
||||
|
||||
private deviceMobile() {
|
||||
return {
|
||||
[DeviceMobile.Iphone]: this.deviceShared()[DeviceMobile.Iphone],
|
||||
[DeviceMobile.AndroidPhone]: this.deviceOS()[DeviceOs.Android] && this.find('mobile'),
|
||||
[DeviceMobile.WindowsPhone]: this.deviceOS()[DeviceOs.Windows] && this.find('phone'),
|
||||
[DeviceMobile.BlackberryPhone]: this.deviceOS()[DeviceOs.Blackberry] && !this.find('tablet'),
|
||||
[DeviceMobile.Meego]: this.find('meego'),
|
||||
[DeviceMobile.FxosPhone]: this.deviceOS()[DeviceOs.Fxos] && this.find('mobile')
|
||||
}
|
||||
}
|
||||
|
||||
private deviceTablet() {
|
||||
return {
|
||||
[DeviceTablet.Ipad]: this.deviceShared()[DeviceTablet.Ipad],
|
||||
[DeviceTablet.AndroidTablet]: this.deviceOS()[DeviceOs.Android] && !this.find('mobile'),
|
||||
[DeviceTablet.BlackberryTablet]: this.deviceOS()[DeviceOs.Blackberry] && this.find('tablet'),
|
||||
[DeviceTablet.WindowsTablet]: this.deviceOS()[DeviceOs.Windows] && (this.find('touch') && !this.deviceMobile()[DeviceMobile.WindowsPhone]),
|
||||
[DeviceTablet.FxosTablet]: this.deviceOS()[DeviceOs.Fxos] && this.find('tablet'),
|
||||
}
|
||||
}
|
||||
|
||||
isMobile() {
|
||||
return this.findMatch(this.deviceMobile()).length > 0
|
||||
}
|
||||
|
||||
isTablet() {
|
||||
return this.findMatch(this.deviceTablet()).length > 0
|
||||
}
|
||||
|
||||
isDesktop() {
|
||||
return !this.isTablet() && !this.isMobile()
|
||||
}
|
||||
|
||||
getDeviceInfo(): DeviceInfo {
|
||||
const touchDevices = this.findMatch({ ...this.deviceMobile(), ...this.deviceTablet() })
|
||||
return {
|
||||
platform: this.isDesktop() ? DevicePlatform.Desktop : (this.isMobile() ? DevicePlatform.Mobile : DevicePlatform.Tablet),
|
||||
os: this.findMatch(this.deviceOS())[0],
|
||||
device: touchDevices.length ? touchDevices[0] : DevicePlatform.Desktop
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/app/_services/device-detector.ts
Normal file
38
src/app/_services/device-detector.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
export enum DevicePlatform {
|
||||
Mobile = 'mobile',
|
||||
Tablet = 'tablet',
|
||||
Desktop = 'desktop'
|
||||
}
|
||||
|
||||
export enum DeviceOs {
|
||||
Ios = 'ios',
|
||||
Android = 'android',
|
||||
Macos = 'macos',
|
||||
Windows = 'windows',
|
||||
Blackberry = 'blackberry',
|
||||
Fxos = 'fxos'
|
||||
}
|
||||
|
||||
export enum DeviceMobile {
|
||||
AndroidPhone = 'androidPhone',
|
||||
Iphone = 'iphone',
|
||||
WindowsPhone = 'windowsPhone',
|
||||
BlackberryPhone = 'blackberryPhone',
|
||||
Meego = 'meego',
|
||||
FxosPhone = 'fxosPhone'
|
||||
}
|
||||
|
||||
export enum DeviceTablet {
|
||||
Ipad = 'ipad',
|
||||
AndroidTablet = 'androidTablet',
|
||||
BlackberryTablet = 'blackberryTablet',
|
||||
WindowsTablet = 'windowsTablet',
|
||||
FxosTablet = 'fxosTablet'
|
||||
}
|
||||
|
||||
export interface DeviceInfo {
|
||||
platform: DevicePlatform
|
||||
os: DeviceOs | string
|
||||
device: DeviceMobile | DeviceTablet | string
|
||||
}
|
||||
|
||||
56
src/app/_services/geocoding.service.ts
Normal file
56
src/app/_services/geocoding.service.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MapsAPILoader } from '@agm/core';
|
||||
import { from } from 'rxjs';
|
||||
import { tap, map, switchMap } from 'rxjs/operators';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { Location } from '../content/maps/services/services.component';
|
||||
|
||||
declare var google: any;
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class GeocodingService {
|
||||
private geocoder: any;
|
||||
|
||||
constructor(private mapLoader: MapsAPILoader) {}
|
||||
|
||||
private initGeocoder() {
|
||||
console.log('Init geocoder!');
|
||||
this.geocoder = new google.maps.Geocoder();
|
||||
}
|
||||
|
||||
private waitForMapsToLoad(): Observable<boolean> {
|
||||
if (!this.geocoder) {
|
||||
return from(this.mapLoader.load()).pipe(
|
||||
tap(() => this.initGeocoder()),
|
||||
map(() => true)
|
||||
);
|
||||
}
|
||||
return of(true);
|
||||
}
|
||||
|
||||
geocodeAddress(location: string): Observable<Location> {
|
||||
console.log('Start geocoding!');
|
||||
return this.waitForMapsToLoad().pipe(
|
||||
// filter(loaded => loaded),
|
||||
switchMap(() => {
|
||||
return new Observable<Location>(observer => {
|
||||
this.geocoder.geocode({ address: location }, (results, status) => {
|
||||
if (status === google.maps.GeocoderStatus.OK) {
|
||||
console.log('Geocoding complete!');
|
||||
observer.next({
|
||||
lat: results[0].geometry.location.lat(),
|
||||
lng: results[0].geometry.location.lng()
|
||||
});
|
||||
} else {
|
||||
console.log('Error - ', results, ' & Status - ', status);
|
||||
observer.next({ lat: 0, lng: 0 });
|
||||
}
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
24
src/app/_services/navbar.service.ts
Normal file
24
src/app/_services/navbar.service.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
@Injectable()
|
||||
export class NavbarService {
|
||||
private mouseInMenuRegion = false;
|
||||
private fixedMenu = false;
|
||||
constructor() {}
|
||||
|
||||
isMouseInRegion() {
|
||||
return this.mouseInMenuRegion;
|
||||
}
|
||||
|
||||
setMouseInRegion(flag) {
|
||||
this.mouseInMenuRegion = flag;
|
||||
}
|
||||
|
||||
isFixedMenu() {
|
||||
return this.fixedMenu;
|
||||
}
|
||||
|
||||
setFixedMenu(flag) {
|
||||
this.fixedMenu = flag;
|
||||
}
|
||||
}
|
||||
37
src/app/_services/ng-select-data.service.ts
Normal file
37
src/app/_services/ng-select-data.service.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { delay } from 'rxjs/operators';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
|
||||
export interface City {
|
||||
item_id: number;
|
||||
item_text: string;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class NgSelectDataService {
|
||||
|
||||
constructor(private http: HttpClient) { }
|
||||
|
||||
getPeople(term: string = null): Observable<City[]> {
|
||||
let items = getMockCity();
|
||||
if (term) {
|
||||
items = items.filter(x => x.item_text.toLocaleLowerCase().indexOf(term.toLocaleLowerCase()) > -1);
|
||||
}
|
||||
return of(items).pipe(delay(500));
|
||||
}
|
||||
}
|
||||
|
||||
function getMockCity() {
|
||||
return [
|
||||
{ item_id: 1, item_text: 'Alaska' },
|
||||
{ item_id: 2, item_text: 'California' },
|
||||
{ item_id: 3, item_text: 'Colorado' },
|
||||
{ item_id: 4, item_text: 'New Mexico' },
|
||||
{ item_id: 5, item_text: 'Alabama' },
|
||||
{ item_id: 6, item_text: 'Connecticut' },
|
||||
{ item_id: 7, item_text: 'New York' }
|
||||
];
|
||||
}
|
||||
16
src/app/_services/quill-initialize-service.service.spec.ts
Normal file
16
src/app/_services/quill-initialize-service.service.spec.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { QuillInitializeServiceService } from './quill-initialize-service.service';
|
||||
|
||||
describe('QuillInitializeServiceService', () => {
|
||||
let service: QuillInitializeServiceService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(QuillInitializeServiceService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
20
src/app/_services/quill-initialize-service.service.ts
Normal file
20
src/app/_services/quill-initialize-service.service.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import Quill from 'quill';
|
||||
import QuillAutoLink from '../content/applications/quill/quillAutolinks';
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class QuillInitializeServiceService {
|
||||
|
||||
constructor() {
|
||||
var Link = Quill.import('formats/link');
|
||||
Link.sanitize = (url) => {
|
||||
if(url.indexOf("http") <= -1){
|
||||
url = "https://" + url;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
Quill.register('modules/autoLink', QuillAutoLink);
|
||||
}
|
||||
|
||||
}
|
||||
12
src/app/_services/table-api.service.spec.ts
Normal file
12
src/app/_services/table-api.service.spec.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TableApiService } from './table-api.service';
|
||||
|
||||
describe('TableApiService', () => {
|
||||
beforeEach(() => TestBed.configureTestingModule({}));
|
||||
|
||||
it('should be created', () => {
|
||||
const service: TableApiService = TestBed.get(TableApiService);
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
99
src/app/_services/table-api.service.ts
Normal file
99
src/app/_services/table-api.service.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
|
||||
import { catchError, tap, map } from 'rxjs/operators';
|
||||
|
||||
const httpOptions = {
|
||||
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
|
||||
};
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class TableApiService {
|
||||
|
||||
apiBaseURL = 'assets/data';
|
||||
loadEcommerceTableDataURL = null;
|
||||
loadInvoiceTableDataURL = null;
|
||||
loadBasicTableDataURL = null;
|
||||
loadTableBorderDataURL = null;
|
||||
loadTableStylingDataURL = null;
|
||||
loadTableApiDataURL = null;
|
||||
loadTableInitialisationDataURL = null;
|
||||
loadStylingDataURL = null;
|
||||
loadTableButtonDataURL = null;
|
||||
loadTableExportDataURL = null;
|
||||
loadTableHiddenDataURL = null;
|
||||
loadTableNgxDataURL = null;
|
||||
constructor(private http: HttpClient) {
|
||||
this.loadEcommerceTableDataURL = `${this.apiBaseURL}/dashboard/ecommerce/datatable.json`;
|
||||
this.loadInvoiceTableDataURL = `${this.apiBaseURL}/invoice/invoicelist/invoicetable.json`;
|
||||
this.loadBasicTableDataURL = `${this.apiBaseURL}/boostraptable/basictable.json`;
|
||||
this.loadTableBorderDataURL = `${this.apiBaseURL}/boostraptable/tableborder.json`;
|
||||
this.loadTableStylingDataURL = `${this.apiBaseURL}/boostraptable/tablestyling.json`;
|
||||
this.loadTableApiDataURL = `${this.apiBaseURL}/datatables/tableapi/tableapi.json`;
|
||||
this.loadTableInitialisationDataURL = `${this.apiBaseURL}/datatables/tableinitialisation/tableinitialisation.json`;
|
||||
this.loadStylingDataURL = `${this.apiBaseURL}/datatables/tablestyling/tablestyling.json`;
|
||||
this.loadTableButtonDataURL = `${this.apiBaseURL}/datatables/buttons/tablebuttons.json`;
|
||||
this.loadTableExportDataURL = `${this.apiBaseURL}/datatables/html5dataexport/html5dataexport.json`;
|
||||
this.loadTableHiddenDataURL = `${this.apiBaseURL}/datatables/hiddentable/hiddentable.json`;
|
||||
this.loadTableNgxDataURL = `${this.apiBaseURL}/boostraptable/ngxboostraptables.json`;
|
||||
}
|
||||
private handleError(error: HttpErrorResponse) {
|
||||
if (error.error instanceof ErrorEvent) {
|
||||
// Error
|
||||
console.error('error:', error.error.message);
|
||||
} else {
|
||||
// Error
|
||||
console.error(
|
||||
`Api server returned ${error.status}, ` +
|
||||
`error body: ${error.error}`);
|
||||
}
|
||||
// throwError is observable
|
||||
return throwError('Error has happened');
|
||||
}
|
||||
|
||||
private extractData(res: Response) {
|
||||
const body = res;
|
||||
return body || {};
|
||||
}
|
||||
|
||||
|
||||
getEcommerceTableData(): Observable<any> {
|
||||
return this.http.get(this.loadEcommerceTableDataURL, httpOptions);
|
||||
}
|
||||
|
||||
getInvoiceTableData(): Observable<any> {
|
||||
return this.http.get(this.loadInvoiceTableDataURL, httpOptions);
|
||||
}
|
||||
getBasicTableData(): Observable<any> {
|
||||
return this.http.get(this.loadBasicTableDataURL, httpOptions);
|
||||
}
|
||||
getTableBorderData(): Observable<any> {
|
||||
return this.http.get(this.loadTableBorderDataURL, httpOptions);
|
||||
}
|
||||
getTableStylingData(): Observable<any> {
|
||||
return this.http.get(this.loadTableStylingDataURL, httpOptions);
|
||||
}
|
||||
getTableApiData(): Observable<any> {
|
||||
return this.http.get(this.loadTableApiDataURL, httpOptions);
|
||||
}
|
||||
getTableInitialisationData(): Observable<any> {
|
||||
return this.http.get(this.loadTableInitialisationDataURL, httpOptions);
|
||||
}
|
||||
getStylingData(): Observable<any> {
|
||||
return this.http.get(this.loadStylingDataURL, httpOptions);
|
||||
}
|
||||
getTableButtonData(): Observable<any> {
|
||||
return this.http.get(this.loadTableButtonDataURL, httpOptions);
|
||||
}
|
||||
getTableExportData(): Observable<any> {
|
||||
return this.http.get(this.loadTableExportDataURL, httpOptions);
|
||||
}
|
||||
getTableHiddenData(): Observable<any> {
|
||||
return this.http.get(this.loadTableHiddenDataURL, httpOptions);
|
||||
}
|
||||
getTableNgxData(): Observable<any> {
|
||||
return this.http.get(this.loadTableNgxDataURL, httpOptions);
|
||||
}
|
||||
}
|
||||
|
||||
12
src/app/_services/tableexcel.service.spec.ts
Normal file
12
src/app/_services/tableexcel.service.spec.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TableexcelService } from './tableexcel.service';
|
||||
|
||||
describe('TableexcelService', () => {
|
||||
beforeEach(() => TestBed.configureTestingModule({}));
|
||||
|
||||
it('should be created', () => {
|
||||
const service: TableexcelService = TestBed.get(TableexcelService);
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
37
src/app/_services/tableexcel.service.ts
Normal file
37
src/app/_services/tableexcel.service.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import * as FileSaver from 'file-saver';
|
||||
import * as XLSX from 'xlsx';
|
||||
|
||||
const EXCEL_TYPE =
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8';
|
||||
const EXCEL_EXTENSION = '.xlsx';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class TableexcelService {
|
||||
constructor() { }
|
||||
public exportAsExcelFile(json: any[], excelFileName: string): void {
|
||||
const worksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(json);
|
||||
console.log('worksheet', worksheet);
|
||||
const workbook: XLSX.WorkBook = {
|
||||
Sheets: { data: worksheet },
|
||||
SheetNames: ['data']
|
||||
};
|
||||
const excelBuffer: any = XLSX.write(workbook, {
|
||||
bookType: 'xlsx',
|
||||
type: 'array'
|
||||
});
|
||||
this.saveAsExcelFile(excelBuffer, excelFileName);
|
||||
}
|
||||
|
||||
private saveAsExcelFile(buffer: any, fileName: string): void {
|
||||
const data: Blob = new Blob([buffer], {
|
||||
type: EXCEL_TYPE
|
||||
});
|
||||
FileSaver.saveAs(
|
||||
data,
|
||||
fileName + '_export_' + new Date().getTime() + EXCEL_EXTENSION
|
||||
);
|
||||
}
|
||||
}
|
||||
0
src/app/app.component.css
Normal file
0
src/app/app.component.css
Normal file
4
src/app/app.component.html
Normal file
4
src/app/app.component.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<!-- main app container -->
|
||||
<ngx-loading-bar [includeSpinner]='false' height='3px' color="#FF4961"></ngx-loading-bar>
|
||||
<app-alert></app-alert>
|
||||
<router-outlet *ngIf="showContent"></router-outlet>
|
||||
27
src/app/app.component.spec.ts
Normal file
27
src/app/app.component.spec.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
it('should create the app', waitForAsync(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
}));
|
||||
it(`should have as title 'modern-admin'`, waitForAsync(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app.title).toEqual('modern-admin');
|
||||
}));
|
||||
it('should render title in a h1 tag', waitForAsync(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.debugElement.nativeElement;
|
||||
expect(compiled.querySelector('h1').textContent).toContain('Welcome to modern-admin!');
|
||||
}));
|
||||
});
|
||||
145
src/app/app.component.ts
Normal file
145
src/app/app.component.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import { Component, Inject, OnInit, Injectable } from '@angular/core';
|
||||
import { NgxSpinnerService } from 'ngx-spinner';
|
||||
import { LoadingBarService } from '@ngx-loading-bar/core';
|
||||
import { NavigationStart, RouteConfigLoadStart, RouteConfigLoadEnd, NavigationEnd, NavigationCancel } from '@angular/router';
|
||||
import { DeviceDetectorService } from './_services/device-detector.service';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Router } from '@angular/router';
|
||||
import { AppConstants } from './_helpers/app.constants';
|
||||
import { MenuSettingsService } from './_layout/settings/menu-settings.service';
|
||||
import { ThemeSettingsService } from './_layout/settings/theme-settings.service';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
|
||||
@Component({
|
||||
selector: 'app-main',
|
||||
templateUrl: 'app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
|
||||
export class AppComponent implements OnInit {
|
||||
public _menuSettingsConfig: any;
|
||||
public _themeSettingsConfig: any;
|
||||
public _unsubscribeAll: Subject<any>;
|
||||
private _unsubscribeAllMenu: Subject<any>;
|
||||
public showContent = false;
|
||||
public title;
|
||||
constructor(private spinner: NgxSpinnerService,
|
||||
@Inject(DOCUMENT) private document: Document,
|
||||
private router: Router,
|
||||
public loader: LoadingBarService,
|
||||
private deviceService: DeviceDetectorService,
|
||||
public _menuSettingsService: MenuSettingsService,
|
||||
public _themeSettingsService: ThemeSettingsService,
|
||||
private titleService: Title
|
||||
) {
|
||||
this._unsubscribeAll = new Subject();
|
||||
this._unsubscribeAllMenu = new Subject();
|
||||
this.setTitle();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this._menuSettingsService.config
|
||||
.pipe(takeUntil(this._unsubscribeAllMenu))
|
||||
.subscribe((config) => {
|
||||
this._menuSettingsConfig = config;
|
||||
});
|
||||
this._themeSettingsService.config
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe((config) => {
|
||||
this._themeSettingsConfig = config;
|
||||
});
|
||||
// page progress bar percentage
|
||||
this.router.events.subscribe(event => {
|
||||
if (event instanceof NavigationStart) {
|
||||
// set page progress bar loading to start on NavigationStart event router
|
||||
this.loader.start();
|
||||
}
|
||||
if (event instanceof RouteConfigLoadStart) {
|
||||
this.loader.increment(35);
|
||||
}
|
||||
if (event instanceof RouteConfigLoadEnd) {
|
||||
this.loader.increment(75);
|
||||
}
|
||||
if (event instanceof NavigationEnd || event instanceof NavigationCancel) {
|
||||
// set page progress bar loading to end on NavigationEnd event router
|
||||
this.loader.complete();
|
||||
this.showContent = true;
|
||||
// close menu for mobile view
|
||||
if (this.deviceService.isMobile() || window.innerWidth < AppConstants.MOBILE_RESPONSIVE_WIDTH) {
|
||||
if (document.body.classList.contains('menu-open')) {
|
||||
document.body.classList.remove('menu-open');
|
||||
document.body.classList.add('menu-close');
|
||||
}
|
||||
}
|
||||
if (this.title && this.router.url !== '/') {
|
||||
this.titleService.setTitle(this.title + ' - ' + this._themeSettingsConfig.defaultTitleSuffix);
|
||||
} else {
|
||||
if ((this.router.url === '/' || this.router.url === '/login' || this.router.url === '/register') &&
|
||||
!localStorage.getItem('remember')) {
|
||||
this.title = 'Login with Background Image';
|
||||
this.titleService.setTitle(this.title + '' + this._themeSettingsConfig.defaultTitleSuffix);
|
||||
this.title = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setTitle() {
|
||||
this.router.events.subscribe(event => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
if (this._themeSettingsConfig.layout.style === 'vertical') {
|
||||
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.title = this._menuSettingsConfig.vertical_menu.items[i].title;
|
||||
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.title = this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j].title;
|
||||
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.title = this._menuSettingsConfig.vertical_menu.items[i].submenu.items[j].submenu.items[k].title;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (this._themeSettingsConfig.layout.style === 'horizontal') {
|
||||
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.title = this._menuSettingsConfig.horizontal_menu.items[i].title;
|
||||
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.title = this._menuSettingsConfig.horizontal_menu.items[i].submenu.items[j].title;
|
||||
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.title = this._menuSettingsConfig.horizontal_menu.items[i].submenu.items[j].submenu.items[k].title;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user