first commit
This commit is contained in:
commit
71a3a661dc
|
@ -0,0 +1,42 @@
|
|||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# Compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
/bazel-out
|
||||
|
||||
# Node
|
||||
/node_modules
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# IDEs and editors
|
||||
.idea/
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history/*
|
||||
|
||||
# Miscellaneous
|
||||
/.angular/cache
|
||||
.sass-cache/
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# System files
|
||||
.DS_Store
|
||||
Thumbs.db
|
|
@ -0,0 +1,108 @@
|
|||
# Modern Admin - Angular 15+ Bootstrap 5 Admin Dashboard Template
|
||||
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.0.1
|
||||
|
||||
## Prerequisite Softwares
|
||||
Min 2 GB free space on the drive
|
||||
Node Js - Version 12+
|
||||
Git 2+
|
||||
npm install -g typescript
|
||||
npm install -g @angular/cli
|
||||
|
||||
## Development server
|
||||
|
||||
Run `npm install` to install dependencies
|
||||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Running end-to-end tests
|
||||
|
||||
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
||||
|
||||
|
||||
## Firebase Deploy -- Only for production
|
||||
node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng build --output-hashing=all
|
||||
node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng s
|
||||
firebase login
|
||||
firebase projects:list
|
||||
firebase use <instance name>
|
||||
firebase deploy
|
||||
firebase firestore:indexes
|
||||
## Types of Layouts
|
||||
|
||||
Vertical Menu Template
|
||||
Semi Dark Vertical Menu Template
|
||||
Dark Nav Vertical Menu Template
|
||||
Light Vertical Menu Template
|
||||
|
||||
Vertical Modern Menu Template
|
||||
Vertical Overlay Menu Template
|
||||
Horizontal Menu Template
|
||||
Full Width Horizontal Menu Template
|
||||
|
||||
## Create New Module and Module
|
||||
|
||||
# Add Module
|
||||
ng g m components
|
||||
cd .\src\app\components\
|
||||
|
||||
# Add component
|
||||
ng g c <componentname>
|
||||
add new menu in menu setting
|
||||
add new route in module and refernce to new <componentname>
|
||||
copy html to component html
|
||||
|
||||
# c9 usage
|
||||
cd modern-admin-angular
|
||||
ng s --host 0.0.0.0 --port 8080 --disable-host-check
|
||||
https://modern-admin-joshijimit.c9users.io:8080/
|
||||
|
||||
# Git commands
|
||||
git pull origin wip_v1
|
||||
git push origin ui-dev-branch
|
||||
|
||||
# Angular 8 Migrate
|
||||
|
||||
git checkout angular8
|
||||
git pull origin angular8
|
||||
(likely to conflict with package lock file, needs to keep the existing file and avoid incoming changes.
|
||||
onece merge conflict resolved with other files if any, run npm install which updates the lock file.)
|
||||
git add .
|
||||
git commit -m "latest pull in v8"
|
||||
git push origin angular8
|
||||
|
||||
known change in Angular 8
|
||||
ViewChild should have second argument.
|
||||
@ViewChild('labelImport', { static: true })
|
||||
|
||||
# CI - Gitlab
|
||||
Auto deploy On merge to master branch
|
||||
|
||||
# Disable experimentalDecorators warning
|
||||
https://ihatetomatoes.net/how-to-remove-experimentaldecorators-warning-in-vscode/
|
||||
|
||||
# Open issue in Angular 10
|
||||
https://github.com/mattlewis92/angular-calendar/issues/1283
|
||||
|
||||
## Flickering issue
|
||||
Remove all occurences of below text from index.html generated in dist folder
|
||||
media="print" onload="this.media='all'"
|
|
@ -0,0 +1,164 @@
|
|||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"modern-admin": {
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"projectType": "application",
|
||||
"prefix": "app",
|
||||
"schematics": {},
|
||||
"architect": {
|
||||
"build": {
|
||||
"assets": [
|
||||
{
|
||||
"glob": "**/*.@(svg|png|gif)",
|
||||
"input": "./node_modules/photoswipe/src/css/default-skin",
|
||||
"output": "/assets/media"
|
||||
}
|
||||
],
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"aot": true,
|
||||
"outputPath": "dist",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "src/tsconfig.app.json",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.css",
|
||||
"node_modules/chartist/dist/chartist.css",
|
||||
"node_modules/angular-calendar/css/angular-calendar.css",
|
||||
"node_modules/flatpickr/dist/flatpickr.min.css",
|
||||
"node_modules/ngx-ui-switch/ui-switch.component.css",
|
||||
"node_modules/chartist-plugin-tooltips/dist/chartist-plugin-tooltip.css",
|
||||
"node_modules/@swimlane/ngx-datatable/themes/bootstrap.css",
|
||||
"src/assets/sass/main.scss",
|
||||
"src/assets/jkanban/jkanban.min.css",
|
||||
"node_modules/ngx-toastr/toastr.css",
|
||||
"node_modules/photoswipe/dist/photoswipe.css",
|
||||
"node_modules/photoswipe/dist/default-skin/default-skin.css"
|
||||
],
|
||||
"scripts": [
|
||||
"node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js",
|
||||
"node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"
|
||||
],
|
||||
"vendorChunk": true,
|
||||
"extractLicenses": false,
|
||||
"buildOptimizer": false,
|
||||
"sourceMap": true,
|
||||
"optimization": false,
|
||||
"namedChunks": true
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "6kb"
|
||||
}
|
||||
],
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"namedChunks": false,
|
||||
"aot": true,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"serviceWorker": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "modern-admin:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "modern-admin:build:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "modern-admin:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "src/tsconfig.spec.json",
|
||||
"karmaConfig": "src/karma.conf.js",
|
||||
"styles": [
|
||||
"src/styles.css"
|
||||
],
|
||||
"scripts": [],
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
]
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-eslint/builder:lint",
|
||||
"options": {
|
||||
"eslintConfig": ".eslintrc.json",
|
||||
"lintFilePatterns": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.html"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"modern-admin-e2e": {
|
||||
"root": "e2e/",
|
||||
"projectType": "application",
|
||||
"architect": {
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "e2e/protractor.conf.js",
|
||||
"devServerTarget": "modern-admin:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "modern-admin:serve:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-eslint/builder:lint",
|
||||
"options": {
|
||||
"eslintConfig": ".eslintrc.json",
|
||||
"lintFilePatterns": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.html"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "modern-admin",
|
||||
"cli": {
|
||||
"analytics": false,
|
||||
"defaultCollection": "@angular-eslint/schematics"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
# Modern Admin - Angular 11+ Bootstrap 5 Admin Dashboard Template
|
||||
|
||||
V1.2 : [12-06-2019] : Added live chat functionality
|
||||
V1.1 : [11-07-2019] : Added configuration to hide header icons
|
||||
Added ngx-toastr in TODO application.
|
||||
Added fully functional CRUD Firebase API integration for TODO App.
|
||||
V1.0 : [10-12-2019] : Initial Release
|
|
@ -0,0 +1,28 @@
|
|||
// Protractor configuration file, see link for more information
|
||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
||||
|
||||
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||
|
||||
exports.config = {
|
||||
allScriptsTimeout: 11000,
|
||||
specs: [
|
||||
'./src/**/*.e2e-spec.ts'
|
||||
],
|
||||
capabilities: {
|
||||
'browserName': 'chrome'
|
||||
},
|
||||
directConnect: true,
|
||||
baseUrl: 'http://localhost:4200/',
|
||||
framework: 'jasmine',
|
||||
jasmineNodeOpts: {
|
||||
showColors: true,
|
||||
defaultTimeoutInterval: 30000,
|
||||
print: function() {}
|
||||
},
|
||||
onPrepare() {
|
||||
require('ts-node').register({
|
||||
project: require('path').join(__dirname, './tsconfig.e2e.json')
|
||||
});
|
||||
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
|
||||
}
|
||||
};
|
|
@ -0,0 +1,14 @@
|
|||
import { AppPage } from './app.po';
|
||||
|
||||
describe('workspace-project App', () => {
|
||||
let page: AppPage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new AppPage();
|
||||
});
|
||||
|
||||
it('should display welcome message', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getParagraphText()).toEqual('Welcome to modern-admin!');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,11 @@
|
|||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class AppPage {
|
||||
navigateTo() {
|
||||
return browser.get('/');
|
||||
}
|
||||
|
||||
getParagraphText() {
|
||||
return element(by.css('app-root h1')).getText();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"outDir": "../out-tsc/app",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"jasminewd2",
|
||||
"node"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience.
|
||||
It is not intended to be used to perform a compilation.
|
||||
|
||||
To learn more about this file see: https://angular.io/config/solution-tsconfig.
|
||||
*/
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./src/tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./src/tsconfig.spec.json"
|
||||
},
|
||||
{
|
||||
"path": "./e2e/tsconfig.e2e.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"hosting": {
|
||||
"public": "dist",
|
||||
"ignore": [
|
||||
"firebase.json",
|
||||
"**/.*",
|
||||
"**/node_modules/**"
|
||||
],
|
||||
"rewrites": [
|
||||
{
|
||||
"source": "**",
|
||||
"destination": "/index.html"
|
||||
}
|
||||
],
|
||||
"headers": [
|
||||
{
|
||||
"source": "/**",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "no-cache, no-store, must-revalidate"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"firestore": {
|
||||
"rules": "firestore.rules",
|
||||
"indexes": "firestore.indexes.json"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"indexes": [
|
||||
{
|
||||
"collectionGroup": "todo",
|
||||
"queryScope": "COLLECTION",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "uid",
|
||||
"order": "ASCENDING"
|
||||
},
|
||||
{
|
||||
"fieldPath": "createdDate",
|
||||
"order": "DESCENDING"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collectionGroup": "TODO",
|
||||
"queryScope": "COLLECTION",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "uid",
|
||||
"order": "ASCENDING"
|
||||
},
|
||||
{
|
||||
"fieldPath": "createdDate",
|
||||
"order": "DESCENDING"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collectionGroup": "todo",
|
||||
"queryScope": "COLLECTION",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "uid",
|
||||
"order": "ASCENDING"
|
||||
},
|
||||
{
|
||||
"fieldPath": "createdDate",
|
||||
"order": "DESCENDING"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collectionGroup": "todo",
|
||||
"queryScope": "COLLECTION",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "assignedTo.uid",
|
||||
"order": "ASCENDING"
|
||||
},
|
||||
{
|
||||
"fieldPath": "createdDate",
|
||||
"order": "DESCENDING"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"fieldOverrides": [
|
||||
{
|
||||
"collectionGroup": "TODO",
|
||||
"fieldPath": "createdDate",
|
||||
"indexes": [
|
||||
{
|
||||
"order": "DESCENDING",
|
||||
"queryScope": "COLLECTION"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
rules_version = '2';
|
||||
service cloud.firestore {
|
||||
match /databases/{database}/documents {
|
||||
// A read rule can be divided into get and list rules
|
||||
match /todo/{todo} {
|
||||
// Applies to single document read requests
|
||||
allow get: if request.auth.uid == resource.data.uid;
|
||||
|
||||
// Applies to queries and collection read requests
|
||||
allow list;
|
||||
}
|
||||
|
||||
// A write rule can be divided into create, update, and delete rules
|
||||
match /todo/{todo} {
|
||||
// Applies to writes to nonexistent documents
|
||||
allow create;
|
||||
|
||||
// Applies to writes to existing documents
|
||||
allow update;
|
||||
|
||||
// Applies to delete operations
|
||||
allow delete;
|
||||
}
|
||||
|
||||
// A read rule can be divided into get and list rules
|
||||
match /users/ {users} {
|
||||
// Applies to single document read requests
|
||||
allow get;
|
||||
|
||||
// Applies to queries and collection read requests
|
||||
allow list;
|
||||
|
||||
// Applies to writes to nonexistent documents
|
||||
allow create;
|
||||
}
|
||||
|
||||
// A read rule can be divided into get and list rules
|
||||
match /chatroom/ {chatroom} {
|
||||
// Applies to single document read requests
|
||||
allow get;
|
||||
|
||||
// Applies to queries and collection read requests
|
||||
allow list;
|
||||
|
||||
// Applies to writes to nonexistent documents
|
||||
allow create;
|
||||
|
||||
// Applies to writes to existing documents
|
||||
allow update;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
module.exports = {
|
||||
packages: {
|
||||
'angular2-text-mask': {
|
||||
ignorableDeepImportMatchers: [
|
||||
/text-mask-core\//,
|
||||
]
|
||||
},
|
||||
},
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,139 @@
|
|||
{
|
||||
"name": "modern-admin-angular",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e",
|
||||
"ngcc": "ngcc --properties es2015 browser main module --async false --first-only",
|
||||
"postinstall": "npm run ngcc",
|
||||
"preinstall": "npx npm-force-resolutions",
|
||||
"pwa": "ng build --prod && sw-precache --root=dist --config=precache-config.js"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^15.0.4",
|
||||
"@angular/cdk": "^15.0.4",
|
||||
"@angular/common": "^15.0.4",
|
||||
"@angular/compiler": "^15.0.4",
|
||||
"@angular/core": "^15.0.4",
|
||||
"@angular/fire": "^7.5.0",
|
||||
"@angular/forms": "^15.0.4",
|
||||
"@angular/localize": "^15.0.4",
|
||||
"@angular/platform-browser": "^15.0.4",
|
||||
"@angular/platform-browser-dynamic": "^15.0.4",
|
||||
"@angular/router": "^15.0.4",
|
||||
"@cds/core": "^6.2.3",
|
||||
"@fnxone/ngx-photoswipe": "^1.0.11",
|
||||
"@fullcalendar/angular": "^6.0.2",
|
||||
"@ng-bootstrap/ng-bootstrap": "^14.0.0",
|
||||
"@ng-select/ng-select": "^10.0.1",
|
||||
"@ngx-loading-bar/core": "^6.0.2",
|
||||
"@ngx-loading-bar/router": "^6.0.2",
|
||||
"@ngx-translate/core": "^14.0.0",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@trafficguard/device-detector-js": "^2.2.1-3.13.0",
|
||||
"@types/google.maps": "^3.51.0",
|
||||
"@webcomponents/webcomponentsjs": "^2.7.0",
|
||||
"ajv-keywords": "^5.1.0",
|
||||
"angular-archwizard": "^7.0.0",
|
||||
"angular-calendar": "^0.31.0",
|
||||
"angularx-flatpickr": "^7.0.0",
|
||||
"autolinker": "^4.0.0",
|
||||
"bootstrap": "^5.2.3",
|
||||
"chart.js": "^4.1.1",
|
||||
"chartist": "^0.11.4",
|
||||
"chartist-plugin-tooltips": "0.0.17",
|
||||
"clone": "^2.1.2",
|
||||
"core-js": "^3.27.1",
|
||||
"css-select": "^5.1.0",
|
||||
"date-fns": "^2.28.0",
|
||||
"deep-equal": "^2.0.5",
|
||||
"echarts": "^5.4.1",
|
||||
"eventemitter3": "^5.0.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"flatpickr": "^4.6.13",
|
||||
"google-libphonenumber": "^3.2.31",
|
||||
"html2canvas": "^1.0.0-rc.7",
|
||||
"icheck": "^1.0.2",
|
||||
"js-datepicker": "^5.18.2",
|
||||
"jspdf": "^2.5.1",
|
||||
"jspdf-autotable": "^3.5.28",
|
||||
"lodash-es": "^4.17.21",
|
||||
"ng-chartist": "^4.1.0",
|
||||
"ng-multiselect-dropdown": "^0.3.9",
|
||||
"ngx-countdown": "^15.0.0",
|
||||
"ngx-drag-and-drop-lists": "^1.3.3",
|
||||
"ngx-dropzone": "^3.1.0",
|
||||
"ngx-echarts": "^15.0.1",
|
||||
"ngx-google-places-autocomplete": "^2.0.5",
|
||||
"ngx-image-cropper": "^6.3.2",
|
||||
"ngx-masonry": "^14.0.1",
|
||||
"ngx-perfect-scrollbar": "^10.1.1",
|
||||
"ngx-quill": "^20.0.1",
|
||||
"ngx-toastr": "^16.0.1",
|
||||
"ngx-ui-switch": "^14.0.3",
|
||||
"npm-force-resolutions": "0.0.10",
|
||||
"photoswipe": "^4.1.3",
|
||||
"pug": "^3.0.2",
|
||||
"quill": "^1.3.7",
|
||||
"quill-delta": "^5.0.0",
|
||||
"quill-mention": "^3.1.0",
|
||||
"rxjs": "^7.5.5",
|
||||
"sass": "^1.57.1",
|
||||
"save": "^2.9.0",
|
||||
"tree-ngx": "^4.3.0",
|
||||
"tslib": "^2.4.1",
|
||||
"util": "^0.12.5",
|
||||
"uuid": "^9.0.0",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^15.0.4",
|
||||
"@angular-devkit/build-webpack": "^0.1500.4",
|
||||
"@angular-eslint/builder": "15.1.0",
|
||||
"@angular-eslint/eslint-plugin": "15.1.0",
|
||||
"@angular-eslint/eslint-plugin-template": "15.1.0",
|
||||
"@angular-eslint/schematics": "15.1.0",
|
||||
"@angular-eslint/template-parser": "15.1.0",
|
||||
"@angular/cli": "^15.0.4",
|
||||
"@angular/compiler-cli": "^15.0.4",
|
||||
"@angular/language-service": "^15.0.4",
|
||||
"@swimlane/ngx-datatable": "20.1.0",
|
||||
"@types/chartist": "^0.9.38",
|
||||
"@types/echarts": "^4.9.15",
|
||||
"@types/jasmine": "^4.3.1",
|
||||
"@types/jasminewd2": "^2.0.8",
|
||||
"@types/jspdf": "^2.0.0",
|
||||
"@types/node": "^18.11.18",
|
||||
"@typescript-eslint/eslint-plugin": "5.48.0",
|
||||
"@typescript-eslint/parser": "5.48.0",
|
||||
"eslint": "^8.30.0",
|
||||
"firebase": "^9.15.0",
|
||||
"firebaseui": "^6.0.2",
|
||||
"jasmine-core": "~4.5.0",
|
||||
"jasmine-spec-reporter": "~7.0.0",
|
||||
"karma": "^6.4.1",
|
||||
"karma-chrome-launcher": "^3.1.1",
|
||||
"karma-coverage-istanbul-reporter": "^3.0.3",
|
||||
"karma-jasmine": "^5.1.0",
|
||||
"karma-jasmine-html-reporter": "^2.0.0",
|
||||
"ng-block-ui": "^3.0.2",
|
||||
"ng2-charts": "^4.1.1",
|
||||
"ngx-clipboard": "^15.1.0",
|
||||
"ngx-custom-validators": "^11.0.0",
|
||||
"ngx-spinner": "^15.0.1",
|
||||
"postcss": "^8.4.20",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"saas": "^1.0.0",
|
||||
"ts-node": "~10.9.1",
|
||||
"typescript": "^4.8.4",
|
||||
"zone.js": "~0.12.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"postcss": "^8.3.5"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
#
|
||||
# For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed
|
||||
|
||||
> 0.5%
|
||||
last 2 versions
|
||||
Firefox ESR
|
||||
not dead
|
||||
not IE 9-11
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 });
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<div *ngIf !="message" [ngClass]="{ 'alert': message, 'alert-success': message.type === 'success',
|
||||
'alert-danger': message.type === 'error' }">
|
||||
{{message.text}}
|
||||
</div>
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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() {
|
||||
}
|
||||
}
|
|
@ -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 { }
|
|
@ -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);
|
||||
}
|
|
@ -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>
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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,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>
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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,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>
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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>
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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,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>
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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']);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,50 @@
|
|||
import { Component, OnInit, Renderer2, Inject } from '@angular/core';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Router, NavigationStart, NavigationEnd, Event, NavigationError } from '@angular/router';
|
||||
@Component({
|
||||
selector: 'app-public-layout',
|
||||
templateUrl: './public-layout.component.html',
|
||||
styleUrls: ['./public-layout.component.css']
|
||||
})
|
||||
export class PublicLayoutComponent implements OnInit {
|
||||
|
||||
constructor(private renderer: Renderer2,
|
||||
private router: Router,
|
||||
@Inject(DOCUMENT) private document: Document) {}
|
||||
ngOnInit() {
|
||||
this.setBodyClass();
|
||||
}
|
||||
|
||||
rightbar(event) {
|
||||
const toggle = document.getElementById('sidenav-overlay');
|
||||
if (event.currentTarget.className === 'sidenav-overlay d-block') {
|
||||
this.renderer.removeClass(toggle, 'd-block');
|
||||
this.document.body.classList.remove('menu-open');
|
||||
this.document.body.classList.add('menu-close');
|
||||
this.renderer.addClass(toggle, 'd-none');
|
||||
} else if (event.currentTarget.className === 'sidenav-overlay d-none') {
|
||||
this.renderer.removeClass(toggle, 'd-none');
|
||||
this.document.body.classList.remove('menu-close');
|
||||
this.document.body.classList.add('menu-open');
|
||||
this.renderer.addClass(toggle, 'd-block');
|
||||
}
|
||||
}
|
||||
|
||||
setBodyClass() {
|
||||
const previosBodyClassList = [].slice.call(document.body.classList);
|
||||
const self = this;
|
||||
previosBodyClassList.forEach(function (c) {
|
||||
self.renderer.removeClass(document.body, c);
|
||||
});
|
||||
const currentBodyClassList = ['vertical-layout', 'bg-full-screen-image', 'vertical-overlay-menu',
|
||||
'2-columns', 'pace-done', 'menu-close', 'fixed-navbar'];
|
||||
currentBodyClassList.forEach(function (c) {
|
||||
self.renderer.addClass(document.body, c);
|
||||
});
|
||||
// if (this.router.url === '/login' || (this.router.url === '')) {
|
||||
// this.renderer.removeClass(document.body, 'fixed-navbar');
|
||||
// } else {
|
||||
// this.renderer.addClass(document.body, 'fixed-navbar');
|
||||
// }
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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'
|
||||
};
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue