Compare commits

..

4 Commits

Author SHA1 Message Date
Sercan Yemen
ff4899e8d2 Merge branch 'master' into skeleton
# Conflicts:
#	src/app/app.module.ts
#	src/app/main/content/apps/calendar/calendar.component.html
#	src/app/main/content/apps/contacts/contact-list/contact-list.component.html
#	src/app/main/content/apps/contacts/contacts.component.html
#	src/app/main/content/apps/contacts/contacts.component.scss
#	src/app/main/content/apps/contacts/contacts.module.ts
#	src/app/main/content/apps/contacts/contacts.service.ts
#	src/app/main/content/apps/contacts/selected-bar/selected-bar.component.html
#	src/app/main/content/apps/mail/sidenavs/main/main-sidenav.component.html
#	src/app/navigation.model.ts
2017-08-24 11:18:24 +03:00
Sercan Yemen
e818c53f1d navbar fixes 2017-08-22 16:05:32 +03:00
Sercan Yemen
ca96fffadf removed fuse fake db 2017-08-22 15:58:35 +03:00
Sercan Yemen
d7003711ee skeleton branch 2017-08-22 15:55:48 +03:00
1427 changed files with 10048 additions and 94983 deletions

57
.angular-cli.json Normal file
View File

@@ -0,0 +1,57 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"project": {
"name": "fuse2"
},
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": [
"assets",
"favicon.ico"
],
"index": "index.html",
"main": "main.ts",
"polyfills": "polyfills.ts",
"test": "test.ts",
"tsconfig": "tsconfig.app.json",
"testTsconfig": "tsconfig.spec.json",
"prefix": "app",
"styles": [
"styles.scss"
],
"scripts": [],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}
],
"e2e": {
"protractor": {
"config": "./protractor.conf.js"
}
},
"lint": [
{
"project": "src/tsconfig.app.json"
},
{
"project": "src/tsconfig.spec.json"
},
{
"project": "e2e/tsconfig.e2e.json"
}
],
"test": {
"karma": {
"config": "./karma.conf.js"
}
},
"defaults": {
"styleExt": "scss",
"component": {}
}
}

View File

@@ -1,6 +1,12 @@
root = true
[*]
charset=utf-8
end_of_line=lf
insert_final_newline=false
indent_style=space
indent_size=4
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false

5
.gitignore vendored
View File

@@ -30,10 +30,13 @@
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
# e2e
/e2e/*.js
/e2e/*.map
# System Files
.DS_Store
Thumbs.db

1
.npmrc
View File

@@ -1 +0,0 @@
save-prefix=''

View File

@@ -1 +0,0 @@
https://themeforest.net/licenses/terms/regular

View File

@@ -1,12 +1,6 @@
# Fuse - Angular
# Fuse2
Material Design Admin Template with Angular 6+ and Angular Material
## The Community
Share your ideas, discuss Fuse and help each other.
[Click here](http://fusetheme.com/community) to see our Community page.
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.1.3.
## Development server
@@ -14,11 +8,11 @@ Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app w
## 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`.
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|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.
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
@@ -27,8 +21,8 @@ Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.
## Running end-to-end tests
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
Before running the tests make sure you are serving the app via `ng serve`.
## 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).

View File

@@ -1,150 +0,0 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"fuse": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"prefix": "app",
"schematics": {
"@schematics/angular:component": {
"styleext": "scss"
}
},
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"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",
"src/app/main/angular-material-elements"
],
"styles": [
"src/styles.scss"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true
},
"ec": {
"sourceMap": true,
"extractCss": true
},
"hmr": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.hmr.ts"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "fuse:build"
},
"configurations": {
"production": {
"browserTarget": "fuse:build:production"
},
"hmr": {
"hmr": true,
"browserTarget": "fuse:build:hmr"
},
"ec": {
"browserTarget": "fuse:build:ec"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "fuse: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": [
"styles.scss"
],
"scripts": [],
"assets": [
"src/favicon.ico",
"src/assets"
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**",
"**/src/app/fake-db/**/*",
"**/src/assets/angular-material-examples/**/*"
]
}
}
}
},
"fuse-e2e": {
"root": "e2e/",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "fuse:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": "e2e/tsconfig.e2e.json",
"exclude": [
"**/node_modules/**",
"**/src/app/fake-db/**/*",
"**/src/assets/angular-material-examples/**/*"
]
}
}
}
}
},
"defaultProject": "fuse"
}

14
e2e/app.e2e-spec.ts Normal file
View File

@@ -0,0 +1,14 @@
import { Fuse2Page } from './app.po';
describe('fuse2 App', () => {
let page: Fuse2Page;
beforeEach(() => {
page = new Fuse2Page();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('Welcome to app!!');
});
});

11
e2e/app.po.ts Normal file
View File

@@ -0,0 +1,11 @@
import { browser, by, element } from 'protractor';
export class Fuse2Page {
navigateTo() {
return browser.get('/');
}
getParagraphText() {
return element(by.css('app-root h1')).getText();
}
}

View File

@@ -1,31 +0,0 @@
// 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}}));
}
};

View File

@@ -1,14 +0,0 @@
import { Fuse2Page } from './app.po';
describe('Fuse2 App', () => {
let page: Fuse2Page;
beforeEach(() => {
page = new Fuse2Page();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('Welcome to Fuse2!');
});
});

View File

@@ -1,11 +0,0 @@
import { browser, by, element } from 'protractor';
export class Fuse2Page {
navigateTo() {
return browser.get('/');
}
getParagraphText() {
return element(by.css('app-root h1')).getText();
}
}

View File

@@ -1,13 +1,12 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"outDir": "../out-tsc/e2e",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}
}

33
karma.conf.js Normal file
View File

@@ -0,0 +1,33 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular/cli'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular/cli/plugins/karma')
],
client:{
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
angularCli: {
environment: 'dev'
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};

15694
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,88 +1,68 @@
{
"name": "fuse",
"version": "6.2.2",
"license": "https://themeforest.net/licenses/terms/regular",
"name": "fuse2",
"version": "1.0.1",
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "ng serve --open",
"start-hmr": "ng serve --configuration hmr --source-map=false --hmr-warning=false",
"start-hmr-sourcemaps": "ng serve --configuration hmr --source-map=true --hmr-warning=false",
"build": "node --max_old_space_size=6144 ./node_modules/@angular/cli/bin/ng build --dev",
"build-stats": "node --max_old_space_size=6144 ./node_modules/@angular/cli/bin/ng build --dev --stats-json",
"build-prod": "node --max_old_space_size=6144 ./node_modules/@angular/cli/bin/ng build --prod",
"build-prod-stats": "node --max_old_space_size=6144 ./node_modules/@angular/cli/bin/ng build --prod --stats-json",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"bundle-report": "webpack-bundle-analyzer dist/stats.json"
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@agm/core": "1.0.0-beta.3",
"@angular/animations": "6.0.7",
"@angular/cdk": "6.3.3",
"@angular/common": "6.0.7",
"@angular/compiler": "6.0.7",
"@angular/core": "6.0.7",
"@angular/flex-layout": "6.0.0-beta.16",
"@angular/forms": "6.0.7",
"@angular/http": "6.0.7",
"@angular/material": "6.3.3",
"@angular/material-moment-adapter": "6.3.3",
"@angular/platform-browser": "6.0.7",
"@angular/platform-browser-dynamic": "6.0.7",
"@angular/router": "6.0.7",
"@ngrx/effects": "6.0.1",
"@ngrx/router-store": "6.0.1",
"@ngrx/store": "6.0.1",
"@ngrx/store-devtools": "6.0.1",
"@ngx-translate/core": "10.0.2",
"@swimlane/ngx-charts": "8.1.0",
"@swimlane/ngx-datatable": "13.0.1",
"@swimlane/ngx-dnd": "4.0.0",
"@types/prismjs": "1.9.0",
"angular-calendar": "0.25.2",
"angular-in-memory-web-api": "0.6.0",
"chart.js": "2.7.2",
"classlist.js": "1.1.20150312",
"core-js": "2.5.7",
"d3": "5.5.0",
"hammerjs": "2.0.8",
"lodash": "4.17.10",
"moment": "2.22.2",
"ng2-charts": "1.6.0",
"ngrx-store-freeze": "0.2.4",
"ngx-color-picker": "6.4.0",
"ngx-cookie-service": "1.0.10",
"perfect-scrollbar": "1.4.0",
"prismjs": "1.15.0",
"rxjs": "6.2.1",
"rxjs-compat": "6.2.1",
"web-animations-js": "2.3.1",
"zone.js": "0.8.26"
"@angular/animations": "4.3.5",
"@angular/cdk": "^2.0.0-beta.8",
"@angular/common": "4.3.5",
"@angular/compiler": "4.3.5",
"@angular/core": "4.3.5",
"@angular/flex-layout": "2.0.0-beta.8",
"@angular/forms": "4.3.5",
"@angular/http": "4.3.5",
"@angular/material": "^2.0.0-beta.8",
"@angular/platform-browser": "4.3.5",
"@angular/platform-browser-dynamic": "4.3.5",
"@angular/router": "4.3.5",
"@swimlane/ngx-charts": "^6.0.2",
"@swimlane/ngx-datatable": "^9.3.1",
"@swimlane/ngx-dnd": "^3.0.0",
"angular-calendar": "^0.19.0",
"angular-in-memory-web-api": "^0.3.2",
"classlist.js": "^1.1.20150312",
"core-js": "^2.5.0",
"d3": "^4.10.0",
"hammerjs": "^2.0.8",
"highlight.js": "^9.12.0",
"intl": "^1.2.5",
"moment": "^2.18.1",
"ngx-color-picker": "^4.3.1",
"ngx-perfect-scrollbar": "^4.5.6",
"rxjs": "^5.4.3",
"web-animations-js": "^2.3.1",
"zone.js": "^0.8.17"
},
"devDependencies": {
"@angular/cli": "6.0.8",
"@angular/compiler-cli": "6.0.7",
"@angular/language-service": "6.0.7",
"@angular-devkit/build-angular": "0.6.8",
"@angularclass/hmr": "2.1.3",
"@types/jasmine": "2.8.8",
"@types/jasminewd2": "2.0.3",
"@types/lodash": "4.14.110",
"@types/node": "8.9.5",
"codelyzer": "4.2.1",
"jasmine-core": "2.99.1",
"jasmine-spec-reporter": "4.2.1",
"karma": "1.7.1",
"karma-chrome-launcher": "2.2.0",
"karma-coverage-istanbul-reporter": "2.0.1",
"karma-jasmine": "1.1.2",
"karma-jasmine-html-reporter": "0.2.2",
"protractor": "5.3.2",
"ts-node": "5.0.1",
"tslint": "5.9.1",
"typescript": "2.7.2",
"webpack-bundle-analyzer": "2.13.1"
"@angular/cli": "^1.3.2",
"@angular/compiler-cli": "4.3.5",
"@angular/language-service": "4.3.5",
"@ngtools/webpack": "^1.6.2",
"@types/jasmine": "^2.5.54",
"@types/jasminewd2": "^2.0.2",
"@types/node": "^6.0.87",
"codelyzer": "~3.0.1",
"jasmine-core": "~2.6.2",
"jasmine-spec-reporter": "~4.1.0",
"karma": "~1.7.0",
"karma-chrome-launcher": "~2.1.1",
"karma-cli": "~1.0.1",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"node-sass": "^4.5.3",
"protractor": "~5.1.2",
"ts-node": "~3.0.4",
"tslint": "~5.3.2",
"typescript": "~2.3.3"
}
}

28
protractor.conf.js Normal file
View File

@@ -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: [
'./e2e/**/*.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: 'e2e/tsconfig.e2e.json'
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};

View File

@@ -1,417 +0,0 @@
import { sequence, trigger, animate, style, group, query, transition, animateChild, state, animation, useAnimation, stagger } from '@angular/animations';
const customAnimation = animation([
style({
opacity : '{{opacity}}',
transform: 'scale({{scale}}) translate3d({{x}}, {{y}}, {{z}})'
}),
animate('{{duration}} {{delay}} cubic-bezier(0.0, 0.0, 0.2, 1)', style('*'))
], {
params: {
duration: '200ms',
delay : '0ms',
opacity : '0',
scale : '1',
x : '0',
y : '0',
z : '0'
}
});
export const fuseAnimations = [
trigger('animate', [transition('void => *', [useAnimation(customAnimation)])]),
trigger('animateStagger', [
state('50', style('*')),
state('100', style('*')),
state('200', style('*')),
transition('void => 50',
query('@*',
[
stagger('50ms', [
animateChild()
])
], {optional: true})),
transition('void => 100',
query('@*',
[
stagger('100ms', [
animateChild()
])
], {optional: true})),
transition('void => 200',
query('@*',
[
stagger('200ms', [
animateChild()
])
], {optional: true}))
]),
trigger('fadeInOut', [
state('0', style({
display: 'none',
opacity: 0
})),
state('1', style({
display: 'block',
opacity: 1
})),
transition('1 => 0', animate('300ms ease-out')),
transition('0 => 1', animate('300ms ease-in'))
]),
trigger('slideInOut', [
state('0', style({
height : '0px',
display: 'none'
})),
state('1', style({
height : '*',
display: 'block'
})),
transition('1 => 0', animate('300ms ease-out')),
transition('0 => 1', animate('300ms ease-in'))
]),
trigger('slideIn', [
transition('void => left', [
style({
transform: 'translateX(100%)'
}),
animate('300ms ease-in',
style({
transform: 'translateX(0)'
})
)
]
),
transition('left => void', [
style({
transform: 'translateX(0)'
}),
animate('300ms ease-in',
style({
transform: 'translateX(-100%)'
})
)
]
),
transition('void => right', [
style({
transform: 'translateX(-100%)'
}),
animate('300ms ease-in',
style({
transform: 'translateX(0)'
})
)
]
),
transition('right => void', [
style({
transform: 'translateX(0)'
}),
animate('300ms ease-in',
style({
transform: 'translateX(100%)'
})
)
]
),
]),
trigger('slideInLeft', [
state('void', style({
transform: 'translateX(-100%)',
display : 'none'
})),
state('*', style({
transform: 'translateX(0)',
display : 'flex'
})),
transition('void => *', animate('300ms')),
transition('* => void', animate('300ms'))
]),
trigger('slideInRight', [
state('void', style({
transform: 'translateX(100%)',
display : 'none'
})),
state('*', style({
transform: 'translateX(0)',
display : 'flex'
})),
transition('void => *', animate('300ms')),
transition('* => void', animate('300ms'))
]),
trigger('slideInTop', [
state('void', style({
transform: 'translateY(-100%)',
display : 'none'
})),
state('*', style({
transform: 'translateY(0)',
display : 'flex'
})),
transition('void => *', animate('300ms')),
transition('* => void', animate('300ms'))
]),
trigger('slideInBottom', [
state('void',
style({
transform: 'translateY(100%)',
display : 'none'
})),
state('*', style({
transform: 'translateY(0)',
display : 'flex'
})),
transition('void => *', animate('300ms')),
transition('* => void', animate('300ms'))
]),
trigger('expandCollapse', [
state('void', style({
height: '0px'
})),
state('*', style({
height: '*'
})),
transition('void => *', animate('300ms ease-out')),
transition('* => void', animate('300ms ease-in'))
]),
// -----------------------------------------------------------------------------------------------------
// @ Router animations
// -----------------------------------------------------------------------------------------------------
trigger('routerTransitionLeft', [
transition('* => *', [
query('content > :enter, content > :leave', [
style({
position: 'absolute',
top : 0,
bottom : 0,
left : 0,
right : 0
})
], {optional: true}),
query('content > :enter', [
style({
transform: 'translateX(100%)',
opacity : 0
})
], {optional: true}),
sequence([
group([
query('content > :leave', [
style({
transform: 'translateX(0)',
opacity : 1
}),
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
style({
transform: 'translateX(-100%)',
opacity : 0
}))
], {optional: true}),
query('content > :enter', [
style({transform: 'translateX(100%)'}),
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
style({
transform: 'translateX(0%)',
opacity : 1
}))
], {optional: true})
]),
query('content > :leave', animateChild(), {optional: true}),
query('content > :enter', animateChild(), {optional: true})
])
])
]),
trigger('routerTransitionRight', [
transition('* => *', [
query('content > :enter, content > :leave', [
style({
position: 'absolute',
top : 0,
bottom : 0,
left : 0,
right : 0
})
], {optional: true}),
query('content > :enter', [
style({
transform: 'translateX(-100%)',
opacity : 0
})
], {optional: true}),
sequence([
group([
query('content > :leave', [
style({
transform: 'translateX(0)',
opacity : 1
}),
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
style({
transform: 'translateX(100%)',
opacity : 0
}))
], {optional: true}),
query('content > :enter', [
style({transform: 'translateX(-100%)'}),
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
style({
transform: 'translateX(0%)',
opacity : 1
}))
], {optional: true})
]),
query('content > :leave', animateChild(), {optional: true}),
query('content > :enter', animateChild(), {optional: true})
])
])
]),
trigger('routerTransitionUp', [
transition('* => *', [
query('content > :enter, content > :leave', [
style({
position: 'absolute',
top : 0,
bottom : 0,
left : 0,
right : 0
})
], {optional: true}),
query('content > :enter', [
style({
transform: 'translateY(100%)',
opacity : 0
})
], {optional: true}),
group([
query('content > :leave', [
style({
transform: 'translateY(0)',
opacity : 1
}),
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
style({
transform: 'translateY(-100%)',
opacity : 0
}))
], {optional: true}),
query('content > :enter', [
style({transform: 'translateY(100%)'}),
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
style({
transform: 'translateY(0%)',
opacity : 1
}))
], {optional: true})
]),
query('content > :leave', animateChild(), {optional: true}),
query('content > :enter', animateChild(), {optional: true})
])
]),
trigger('routerTransitionDown', [
transition('* => *', [
query('content > :enter, content > :leave', [
style({
position: 'absolute',
top : 0,
bottom : 0,
left : 0,
right : 0
})
], {optional: true}),
query('content > :enter', [
style({
transform: 'translateY(-100%)',
opacity : 0
})
], {optional: true}),
sequence([
group([
query('content > :leave', [
style({
transform: 'translateY(0)',
opacity : 1
}),
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
style({
transform: 'translateY(100%)',
opacity : 0
}))
], {optional: true}),
query('content > :enter', [
style({transform: 'translateY(-100%)'}),
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
style({
transform: 'translateY(0%)',
opacity : 1
}))
], {optional: true})
]),
query('content > :leave', animateChild(), {optional: true}),
query('content > :enter', animateChild(), {optional: true})
])
])
]),
trigger('routerTransitionFade', [
transition('* => *', group([
query('content > :enter, content > :leave ', [
style({
position: 'absolute',
top : 0,
bottom : 0,
left : 0,
right : 0
})
], {optional: true}),
query('content > :enter', [
style({
opacity: 0
})
], {optional: true}),
query('content > :leave', [
style({
opacity: 1
}),
animate('300ms cubic-bezier(0.0, 0.0, 0.2, 1)',
style({
opacity: 0
}))
], {optional: true}),
query('content > :enter', [
style({
opacity: 0
}),
animate('300ms cubic-bezier(0.0, 0.0, 0.2, 1)',
style({
opacity: 1
}))
], {optional: true}),
query('content > :enter', animateChild(), {optional: true}),
query('content > :leave', animateChild(), {optional: true})
]))
])
];

View File

@@ -1,6 +0,0 @@
<h1 matDialogTitle>Confirm</h1>
<div mat-dialog-content>{{confirmMessage}}</div>
<div mat-dialog-actions class="pt-24">
<button mat-raised-button class="mat-accent mr-16" (click)="dialogRef.close(true)">Confirm</button>
<button mat-button (click)="dialogRef.close(false)">Cancel</button>
</div>

View File

@@ -1,24 +0,0 @@
import { Component } from '@angular/core';
import { MatDialogRef } from '@angular/material';
@Component({
selector : 'fuse-confirm-dialog',
templateUrl: './confirm-dialog.component.html',
styleUrls : ['./confirm-dialog.component.scss']
})
export class FuseConfirmDialogComponent
{
public confirmMessage: string;
/**
* Constructor
*
* @param {MatDialogRef<FuseConfirmDialogComponent>} dialogRef
*/
constructor(
public dialogRef: MatDialogRef<FuseConfirmDialogComponent>
)
{
}
}

View File

@@ -1,20 +0,0 @@
import { NgModule } from '@angular/core';
import { MatButtonModule, MatDialogModule } from '@angular/material';
import { FuseConfirmDialogComponent } from '@fuse/components/confirm-dialog/confirm-dialog.component';
@NgModule({
declarations: [
FuseConfirmDialogComponent
],
imports: [
MatDialogModule,
MatButtonModule
],
entryComponents: [
FuseConfirmDialogComponent
],
})
export class FuseConfirmDialogModule
{
}

View File

@@ -1,89 +0,0 @@
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { interval, Subject } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import * as moment from 'moment';
@Component({
selector : 'fuse-countdown',
templateUrl: './countdown.component.html',
styleUrls : ['./countdown.component.scss']
})
export class FuseCountdownComponent implements OnInit, OnDestroy
{
// Event date
@Input('eventDate')
eventDate;
countdown: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*/
constructor()
{
// Set the defaults
this.countdown = {
days : '',
hours : '',
minutes: '',
seconds: ''
};
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
const currDate = moment();
const eventDate = moment(this.eventDate);
// Get the difference in between the current date and event date
let diff = eventDate.diff(currDate, 'seconds');
// Create a subscribable interval
const countDown = interval(1000)
.pipe(
map(value => {
return diff = diff - 1;
}),
map(value => {
const timeLeft = moment.duration(value, 'seconds');
return {
days : timeLeft.asDays().toFixed(0),
hours : timeLeft.hours(),
minutes: timeLeft.minutes(),
seconds: timeLeft.seconds()
};
})
);
// Subscribe to the countdown interval
countDown
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(value => {
this.countdown = value;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

View File

@@ -1,15 +0,0 @@
import { NgModule } from '@angular/core';
import { FuseCountdownComponent } from '@fuse/components/countdown/countdown.component';
@NgModule({
declarations: [
FuseCountdownComponent
],
exports: [
FuseCountdownComponent
],
})
export class FuseCountdownModule
{
}

View File

@@ -1,75 +0,0 @@
<!-- DEMO CONTENT -->
<div class="demo-content">
<img src="assets/images/beach.jpg" alt="beach" style="max-width: 640px; width: 100%;">
<h1>Early Sunrise</h1>
<h4 class="secondary-text">Demo Content</h4>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse tortor nibh, convallis sed purus nec,
auctor venenatis nisl. Suspendisse potenti. Nullam sagittis nulla in diam finibus, sed pharetra velit
vestibulum. Suspendisse euismod in urna eu posuere.
</p>
<blockquote>
<p>
Nunc vel lacinia lorem. Nullam tincidunt sed purus eu placerat. Donec id dictum erat. Etiam enim ex, dapibus
et tortor id, posuere pretium est. Maecenas fringilla ipsum vitae neque elementum, at eleifend ante
sollicitudin. Donec viverra augue dolor, a venenatis tellus consectetur sit amet.
</p>
<footer>
John Doe
</footer>
</blockquote>
<p>
Ut ornare sit amet velit vel congue. Ut nec tristique eros. Lorem ipsum dolor sit amet, consectetur adipiscing
elit. Vivamus sed lorem quis nibh porta iaculis. Vestibulum ut eleifend ante, at semper mi. Nam imperdiet est
nisi, quis hendrerit tellus convallis et. Morbi in luctus neque. Curabitur elementum ut est et gravida. In hac
habitasse platea dictumst.
</p>
<p>
In et placerat eros, eu tempor turpis. Curabitur ac felis finibus, elementum lectus vitae, venenatis est.
Integer mollis nisl a eros scelerisque varius. Etiam venenatis lectus vel erat condimentum tristique vel vel mi.
Nulla id euismod mi, et mollis tellus.
</p>
<p>
Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Class aptent taciti
sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur vitae sagittis odio.
Suspendisse ullamcorper nunc non pellentesque laoreet. Curabitur eu tortor id quam pretium mattis. Proin ut quam
velit.
</p>
<p>
Quisque sit amet risus enim. Aliquam sit amet interdum justo, at ultricies sapien. Suspendisse et semper urna,
in gravida eros. Quisque id nibh iaculis, euismod urna sed, egestas nisi. Donec eros metus, congue a imperdiet
feugiat, sagittis nec ipsum. Quisque dapibus mollis felis non tristique.
</p>
<p>
Ut auctor, metus sed dapibus tempus, urna diam auctor odio, in malesuada odio risus vitae nisi. Etiam blandit
ante urna, vitae placerat massa mollis in. Duis nec urna ac purus semper dictum ut eget justo. Aenean non
sagittis augue. Sed venenatis rhoncus enim eget ornare. Donec viverra sed felis at venenatis. Mauris aliquam
fringilla nulla, sit amet congue felis dignissim at.
</p>
<p>
Quisque accumsan augue tempor ante mollis, sed placerat diam porttitor. Vestibulum dignissim sem vel velit
eleifend, non pellentesque quam convallis. Pellentesque est dolor, dignissim ac tortor tristique, hendrerit
iaculis metus. Praesent pulvinar quam eu leo consectetur faucibus. Vestibulum purus diam, gravida sagittis
feugiat sit amet, tincidunt in ligula. Sed semper vestibulum magna. Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Suspendisse tortor nibh, convallis sed purus nec, auctor venenatis nisl. Suspendisse potenti.
</p>
<p>
Nullam sagittis nulla in diam finibus, sed pharetra velit vestibulum. Suspendisse euismod in urna eu posuere.
Etiam blandit nunc arcu, et consectetur orci blandit a. Aliquam condimentum pharetra quam at ultricies. Nunc vel
lacinia lorem. Nullam tincidunt sed purus eu placerat. Donec id dictum erat. Etiam enim ex, dapibus et tortor
id, posuere pretium est. Maecenas fringilla ipsum vitae neque elementum, at eleifend ante sollicitudin. Donec
viverra augue dolor, a venenatis tellus consectetur sit amet...
</p>
</div>
<!-- / DEMO CONTENT -->

View File

@@ -1,100 +0,0 @@
<div class="demo-sidebar">
<mat-list>
<h3 matSubheader>Sidebar Demo</h3>
<mat-list-item>
<span>Sidebar Item 1</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 2</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 3</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 4</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 5</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 6</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 7</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 8</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 9</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 10</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 11</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 12</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 13</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 14</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 15</span>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item>
<span>Sidebar Item 16</span>
</mat-list-item>
</mat-list>
</div>

View File

@@ -1,16 +0,0 @@
import { Component } from '@angular/core';
@Component({
selector : 'fuse-demo-sidebar',
templateUrl: './demo-sidebar.component.html',
styleUrls : ['./demo-sidebar.component.scss']
})
export class FuseDemoSidebarComponent
{
/**
* Constructor
*/
constructor()
{
}
}

View File

@@ -1,7 +0,0 @@
:host {
display: block;
padding: 8px;
background: #263238;
cursor: text;
overflow: auto;
}

View File

@@ -1,149 +0,0 @@
import { Component, ContentChild, ElementRef, Input, OnDestroy, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import * as Prism from 'prismjs/prism';
import '@fuse/components/highlight/prism-languages';
@Component({
selector : 'fuse-highlight',
template : '',
styleUrls: ['./highlight.component.scss']
})
export class FuseHighlightComponent implements OnInit, OnDestroy
{
// Source
@ContentChild('source')
source: ElementRef;
// Lang
@Input('lang')
lang: string;
// Path
@Input('path')
path: string;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ElementRef} _elementRef
* @param {HttpClient} _httpClient
*/
constructor(
private _elementRef: ElementRef,
private _httpClient: HttpClient
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// If there is no language defined, return...
if ( !this.lang )
{
return;
}
// If the path is defined...
if ( this.path )
{
// Get the source
this._httpClient.get(this.path, {responseType: 'text'})
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((response) => {
// Highlight it
this.highlight(response);
});
}
// If the path is not defined and the source element exists...
if ( !this.path && this.source )
{
// Highlight it
this.highlight(this.source.nativeElement.value);
}
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Highlight the given source code
*
* @param sourceCode
*/
highlight(sourceCode): void
{
// Split the source into lines
const sourceLines = sourceCode.split('\n');
// Remove the first and the last line of the source
// code if they are blank lines. This way, the html
// can be formatted properly while using fuse-highlight
// component
if ( !sourceLines[0].trim() )
{
sourceLines.shift();
}
if ( !sourceLines[sourceLines.length - 1].trim() )
{
sourceLines.pop();
}
// Find the first non-whitespace char index in
// the first line of the source code
const indexOfFirstChar = sourceLines[0].search(/\S|$/);
// Generate the trimmed source
let source = '';
// Iterate through all the lines
sourceLines.forEach((line, index) => {
// Trim the beginning white space depending on the index
// and concat the source code
source = source + line.substr(indexOfFirstChar, line.length);
// If it's not the last line...
if ( index !== sourceLines.length - 1 )
{
// Add a line break at the end
source = source + '\n';
}
});
// Generate the highlighted code
const highlightedCode = Prism.highlight(source, Prism.languages[this.lang]);
// Replace the innerHTML of the component with the highlighted code
this._elementRef.nativeElement.innerHTML =
'<pre><code class="highlight language-' + this.lang + '">' + highlightedCode + '</code></pre>';
}
}

View File

@@ -1,15 +0,0 @@
import { NgModule } from '@angular/core';
import { FuseHighlightComponent } from '@fuse/components/highlight/highlight.component';
@NgModule({
declarations: [
FuseHighlightComponent
],
exports: [
FuseHighlightComponent
],
})
export class FuseHighlightModule
{
}

View File

@@ -1,18 +0,0 @@
import 'prismjs/prism';
import 'prismjs/components/prism-bash';
import 'prismjs/components/prism-c';
import 'prismjs/components/prism-cpp';
import 'prismjs/components/prism-csharp';
import 'prismjs/components/prism-css';
import 'prismjs/components/prism-diff';
import 'prismjs/components/prism-markup';
import 'prismjs/components/prism-markup-templating';
import 'prismjs/components/prism-java';
import 'prismjs/components/prism-javascript';
import 'prismjs/components/prism-json';
import 'prismjs/components/prism-perl';
import 'prismjs/components/prism-php';
import 'prismjs/components/prism-python';
import 'prismjs/components/prism-sass';
import 'prismjs/components/prism-scss';
import 'prismjs/components/prism-typescript';

View File

@@ -1,11 +0,0 @@
export * from './confirm-dialog/confirm-dialog.module';
export * from './countdown/countdown.module';
export * from './demo/demo.module';
export * from './highlight/highlight.module';
export * from './material-color-picker/material-color-picker.module';
export * from './navigation/navigation.module';
export * from './search-bar/search-bar.module';
export * from './shortcuts/shortcuts.module';
export * from './sidebar/sidebar.module';
export * from './theme-options/theme-options.module';
export * from './widget/widget.module';

View File

@@ -1,70 +0,0 @@
<button mat-icon-button
type="button"
class="mat-elevation-z1"
[matMenuTriggerFor]="colorMenu"
(menuOpened)="onMenuOpen()"
[ngClass]="'mat-'+selectedPalette+'-'+selectedHue+'-bg'">
<mat-icon>palette</mat-icon>
</button>
<mat-menu #colorMenu="matMenu" class="fuse-material-color-picker-menu">
<header [ngClass]="selectedColor?.class || 'mat-accent-bg'" class="mat-elevation-z4"
fxLayout="row" fxLayoutAlign="space-between center">
<button mat-icon-button
[style.visibility]="view==='hues'?'visible':'hidden'"
(click)="$event.stopPropagation();backToPaletteSelection()" aria-label="Palette">
<mat-icon class="s-20">arrow_back</mat-icon>
</button>
<span *ngIf="selectedColor?.palette">
{{selectedColor.palette}} {{selectedColor.hue}}
</span>
<span *ngIf="!selectedColor?.palette">
Select Color
</span>
<button mat-icon-button
class="remove-color-button"
(click)="$event.stopPropagation();removeColor()"
aria-label="Remove Color">
<mat-icon class="s-20">delete</mat-icon>
</button>
</header>
<div [ngSwitch]="view" class="views">
<div class="view" *ngSwitchCase="'palettes'">
<div fxLayout="row wrap" fxLayoutAlign="start start" class="colors" fusePerfectScrollbar>
<div class="color"
[ngClass]="'mat-'+color.key+'-bg'"
*ngFor="let color of (colors | keys)"
(click)="$event.stopPropagation();selectPalette(color.key)"
fxLayout="row" fxLayoutAlign="start end" mat-ink-ripple>
<span class="label">
{{color.key}}
</span>
</div>
</div>
</div>
<div class="view" *ngSwitchCase="'hues'" >
<div fxLayout="row wrap" fxLayoutAlign="start start" class="colors" fusePerfectScrollbar>
<div class="color" *ngFor="let hue of hues"
[fxHide]="selectedPalette === 'white' && hue !== '500'|| selectedPalette === 'black' && hue !== '500'"
[ngClass]="'mat-'+selectedPalette+'-'+hue+'-bg'"
(click)="selectHue(hue)" fxLayout="row" fxLayoutAlign="start end" mat-ink-ripple>
<span class="label">
{{hue}}
</span>
<mat-icon *ngIf="selectedHue === hue" class="s-16">check</mat-icon>
</div>
</div>
</div>
</div>
</mat-menu>

View File

@@ -1,32 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatButtonModule, MatIconModule, MatMenuModule, MatRippleModule } from '@angular/material';
import { FusePipesModule } from '@fuse/pipes/pipes.module';
import { FuseMaterialColorPickerComponent } from '@fuse/components/material-color-picker/material-color-picker.component';
@NgModule({
declarations: [
FuseMaterialColorPickerComponent
],
imports: [
CommonModule,
FlexLayoutModule,
MatButtonModule,
MatIconModule,
MatMenuModule,
MatRippleModule,
FusePipesModule
],
exports: [
FuseMaterialColorPickerComponent
],
})
export class FuseMaterialColorPickerModule
{
}

View File

@@ -1,69 +0,0 @@
<ng-container *ngIf="!item.hidden">
<!-- normal collapse -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="!item.url && !item.function" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<!-- item.url -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && !item.externalUrl && !item.function"
[routerLink]="[item.url]" [routerLinkActive]="['active', 'mat-accent-bg']"
[routerLinkActiveOptions]="{exact: item.exactMatch || false}"
[target]="item.openInNewTab ? '_blank' : '_self'" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<!-- item.externalUrl -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && item.externalUrl && !item.function"
[href]="item.url" [target]="item.openInNewTab ? '_blank' : '_self'" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<!-- item.function -->
<span class="nav-link" [ngClass]="item.classes" *ngIf="!item.url && item.function"
(click)="item.function()" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</span>
<!-- item.url && item.function -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && !item.externalUrl && item.function"
(click)="item.function()"
[routerLink]="[item.url]" [routerLinkActive]="['active', 'mat-accent-bg']"
[routerLinkActiveOptions]="{exact: item.exactMatch || false}" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<!-- item.externalUrl && item.function -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && item.externalUrl && item.function"
(click)="item.function()"
[href]="item.url" [target]="item.openInNewTab ? '_blank' : '_self'" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<ng-template #itemContent>
<mat-icon class="nav-link-icon" *ngIf="item.icon">{{item.icon}}</mat-icon>
<span class="nav-link-title" [translate]="item.translate">{{item.title}}</span>
<span class="nav-link-badge" *ngIf="item.badge" [translate]="item.badge.translate"
[ngStyle]="{'background-color': item.badge.bg,'color': item.badge.fg}">
{{item.badge.title}}
</span>
<mat-icon class="collapsable-arrow">keyboard_arrow_right</mat-icon>
</ng-template>
<div class="children" [ngClass]="{'open': isOpen}">
<div class="{{fuseConfig.layout.navbar.background}}">
<ng-container *ngFor="let item of item.children">
<fuse-nav-horizontal-item *ngIf="item.type=='item'" [item]="item"></fuse-nav-horizontal-item>
<fuse-nav-horizontal-collapsable *ngIf="item.type=='collapsable'"
[item]="item"></fuse-nav-horizontal-collapsable>
<fuse-nav-horizontal-collapsable *ngIf="item.type=='group'"
[item]="item"></fuse-nav-horizontal-collapsable>
</ng-container>
</div>
</div>
</ng-container>

View File

@@ -1,86 +0,0 @@
import { Component, HostBinding, HostListener, Input, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseConfigService } from '@fuse/services/config.service';
@Component({
selector : 'fuse-nav-horizontal-collapsable',
templateUrl: './collapsable.component.html',
styleUrls : ['./collapsable.component.scss'],
animations : fuseAnimations
})
export class FuseNavHorizontalCollapsableComponent implements OnInit, OnDestroy
{
fuseConfig: any;
isOpen = false;
@HostBinding('class')
classes = 'nav-collapsable nav-item';
@Input()
item: any;
// Private
private _unsubscribeAll: Subject<any>;
constructor(
private _fuseConfigService: FuseConfigService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to config changes
this._fuseConfigService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(
(config) => {
this.fuseConfig = config;
}
);
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Open
*/
@HostListener('mouseenter')
open(): void
{
this.isOpen = true;
}
/**
* Close
*/
@HostListener('mouseleave')
close(): void
{
this.isOpen = false;
}
}

View File

@@ -1,48 +0,0 @@
<ng-container *ngIf="!item.hidden">
<!-- item.url -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && !item.externalUrl && !item.function"
[routerLink]="[item.url]" [routerLinkActive]="['active', 'mat-accent-bg']"
[routerLinkActiveOptions]="{exact: item.exactMatch || false}"
[target]="item.openInNewTab ? '_blank' : '_self'" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<!-- item.externalUrl -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && item.externalUrl && !item.function"
[href]="item.url" [target]="item.openInNewTab ? '_blank' : '_self'" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<!-- item.function -->
<span class="nav-link" [ngClass]="item.classes" *ngIf="!item.url && item.function"
(click)="item.function()" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</span>
<!-- item.url && item.function -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && !item.externalUrl && item.function"
(click)="item.function()"
[routerLink]="[item.url]" [routerLinkActive]="['active', 'mat-accent-bg']"
[routerLinkActiveOptions]="{exact: item.exactMatch || false}"
[target]="item.openInNewTab ? '_blank' : '_self'" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<!-- item.externalUrl && item.function -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && item.externalUrl && item.function"
(click)="item.function()"
[href]="item.url" [target]="item.openInNewTab ? '_blank' : '_self'" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<ng-template #itemContent>
<mat-icon class="nav-link-icon" *ngIf="item.icon">{{item.icon}}</mat-icon>
<span class="nav-link-title" [translate]="item.translate">{{item.title}}</span>
<span class="nav-link-badge" *ngIf="item.badge" [translate]="item.badge.translate"
[ngStyle]="{'background-color': item.badge.bg,'color': item.badge.fg}">
{{item.badge.title}}
</span>
</ng-template>
</ng-container>

View File

@@ -1,23 +0,0 @@
import { Component, HostBinding, Input } from '@angular/core';
@Component({
selector : 'fuse-nav-horizontal-item',
templateUrl: './item.component.html',
styleUrls : ['./item.component.scss']
})
export class FuseNavHorizontalItemComponent
{
@HostBinding('class')
classes = 'nav-item';
@Input()
item: any;
/**
* Constructor
*/
constructor()
{
}
}

View File

@@ -1,32 +0,0 @@
<div class="nav" [ngClass]="{'horizontal':layout === 'horizontal', 'vertical':layout === 'vertical'}">
<!-- Vertical Navigation Layout -->
<ng-container *ngIf="layout === 'vertical'">
<ng-container *ngFor="let item of navigation">
<fuse-nav-vertical-group *ngIf="item.type=='group'" [item]="item"></fuse-nav-vertical-group>
<fuse-nav-vertical-collapsable *ngIf="item.type=='collapse'" [item]="item"></fuse-nav-vertical-collapsable>
<fuse-nav-vertical-item *ngIf="item.type=='item'" [item]="item"></fuse-nav-vertical-item>
</ng-container>
</ng-container>
<!-- / Vertical Navigation Layout -->
<!-- Horizontal Navigation Layout -->
<ng-container *ngIf="layout === 'horizontal'">
<ng-container *ngFor="let item of navigation">
<fuse-nav-horizontal-collapsable *ngIf="item.type=='group'" [item]="item"></fuse-nav-horizontal-collapsable>
<fuse-nav-horizontal-collapsable *ngIf="item.type=='collapse'"
[item]="item"></fuse-nav-horizontal-collapsable>
<fuse-nav-horizontal-item *ngIf="item.type=='item'" [item]="item"></fuse-nav-horizontal-item>
</ng-container>
</ng-container>
<!-- / Horizontal Navigation Layout -->
</div>

View File

@@ -1,12 +0,0 @@
@import 'src/@fuse/scss/fuse';
fuse-navigation {
display: flex;
flex: 1 0 auto;
> .nav {
margin: 0;
padding: 0;
width: 100%;
}
}

View File

@@ -1,54 +0,0 @@
import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
@Component({
selector : 'fuse-navigation',
templateUrl : './navigation.component.html',
styleUrls : ['./navigation.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class FuseNavigationComponent implements OnInit
{
@Input()
layout = 'vertical';
@Input()
navigation: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*/
constructor(
private _fuseNavigationService: FuseNavigationService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Load the navigation either from the input or from the service
this.navigation = this.navigation || this._fuseNavigationService.getCurrentNavigation();
// Subscribe to the current navigation changes
this._fuseNavigationService.onNavigationChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
this.navigation = this._fuseNavigationService.getCurrentNavigation();
});
}
}

View File

@@ -1,39 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { MatIconModule, MatRippleModule } from '@angular/material';
import { TranslateModule } from '@ngx-translate/core';
import { FuseNavigationComponent } from './navigation.component';
import { FuseNavVerticalItemComponent } from './vertical/item/item.component';
import { FuseNavVerticalCollapsableComponent } from './vertical/collapsable/collapsable.component';
import { FuseNavVerticalGroupComponent } from './vertical/group/group.component';
import { FuseNavHorizontalItemComponent } from './horizontal/item/item.component';
import { FuseNavHorizontalCollapsableComponent } from './horizontal/collapsable/collapsable.component';
@NgModule({
imports : [
CommonModule,
RouterModule,
MatIconModule,
MatRippleModule,
TranslateModule.forChild()
],
exports : [
FuseNavigationComponent
],
declarations: [
FuseNavigationComponent,
FuseNavVerticalGroupComponent,
FuseNavVerticalItemComponent,
FuseNavVerticalCollapsableComponent,
FuseNavHorizontalItemComponent,
FuseNavHorizontalCollapsableComponent
]
})
export class FuseNavigationModule
{
}

View File

@@ -1,350 +0,0 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { FuseNavigationItem } from '@fuse/types';
@Injectable({
providedIn: 'root'
})
export class FuseNavigationService
{
onItemCollapsed: Subject<any>;
onItemCollapseToggled: Subject<any>;
// Private
private _onNavigationChanged: BehaviorSubject<any>;
private _onNavigationRegistered: BehaviorSubject<any>;
private _onNavigationUnregistered: BehaviorSubject<any>;
private _currentNavigationKey: string;
private _registry: { [key: string]: any } = {};
/**
* Constructor
*/
constructor()
{
// Set the defaults
this.onItemCollapsed = new Subject();
this.onItemCollapseToggled = new Subject();
// Set the private defaults
this._currentNavigationKey = null;
this._onNavigationChanged = new BehaviorSubject(null);
this._onNavigationRegistered = new BehaviorSubject(null);
this._onNavigationUnregistered = new BehaviorSubject(null);
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Get onNavigationChanged
*
* @returns {Observable<any>}
*/
get onNavigationChanged(): Observable<any>
{
return this._onNavigationChanged.asObservable();
}
/**
* Get onNavigationRegistered
*
* @returns {Observable<any>}
*/
get onNavigationRegistered(): Observable<any>
{
return this._onNavigationRegistered.asObservable();
}
/**
* Get onNavigationUnregistered
*
* @returns {Observable<any>}
*/
get onNavigationUnregistered(): Observable<any>
{
return this._onNavigationUnregistered.asObservable();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Register the given navigation
* with the given key
*
* @param key
* @param navigation
*/
register(key, navigation): void
{
// Check if the key already being used
if ( this._registry[key] )
{
console.error(`The navigation with the key '${key}' already exists. Either unregister it first or use a unique key.`);
return;
}
// Add to the registry
this._registry[key] = navigation;
// Notify the subject
this._onNavigationRegistered.next([key, navigation]);
}
/**
* Unregister the navigation from the registry
* @param key
*/
unregister(key): void
{
// Check if the navigation exists
if ( !this._registry[key] )
{
console.warn(`The navigation with the key '${key}' doesn't exist in the registry.`);
}
// Unregister the sidebar
delete this._registry[key];
// Notify the subject
this._onNavigationUnregistered.next(key);
}
/**
* Get navigation from registry by key
*
* @param key
* @returns {any}
*/
getNavigation(key): any
{
// Check if the navigation exists
if ( !this._registry[key] )
{
console.warn(`The navigation with the key '${key}' doesn't exist in the registry.`);
return;
}
// Return the sidebar
return this._registry[key];
}
/**
* Get flattened navigation array
*
* @param navigation
* @param flatNavigation
* @returns {any[]}
*/
getFlatNavigation(navigation, flatNavigation: FuseNavigationItem[] = []): any
{
for ( const item of navigation )
{
if ( item.type === 'item' )
{
flatNavigation.push(item);
continue;
}
if ( item.type === 'collapsable' || item.type === 'group' )
{
if ( item.children )
{
this.getFlatNavigation(item.children, flatNavigation);
}
}
}
return flatNavigation;
}
/**
* Get the current navigation
*
* @returns {any}
*/
getCurrentNavigation(): any
{
if ( !this._currentNavigationKey )
{
console.warn(`The current navigation is not set.`);
return;
}
return this.getNavigation(this._currentNavigationKey);
}
/**
* Set the navigation with the key
* as the current navigation
*
* @param key
*/
setCurrentNavigation(key): void
{
// Check if the sidebar exists
if ( !this._registry[key] )
{
console.warn(`The navigation with the key '${key}' doesn't exist in the registry.`);
return;
}
// Set the current navigation key
this._currentNavigationKey = key;
// Notify the subject
this._onNavigationChanged.next(key);
}
/**
* Get navigation item by id from the
* current navigation
*
* @param id
* @param {any} navigation
* @returns {any | boolean}
*/
getNavigationItem(id, navigation = null): any | boolean
{
if ( !navigation )
{
navigation = this.getCurrentNavigation();
}
for ( const item of navigation )
{
if ( item.id === id )
{
return item;
}
if ( item.children )
{
const childItem = this.getNavigationItem(id, item.children);
if ( childItem )
{
return childItem;
}
}
}
return false;
}
/**
* Get the parent of the navigation item
* with the id
*
* @param id
* @param {any} navigation
* @param parent
*/
getNavigationItemParent(id, navigation = null, parent = null): any
{
if ( !navigation )
{
navigation = this.getCurrentNavigation();
parent = navigation;
}
for ( const item of navigation )
{
if ( item.id === id )
{
return parent;
}
if ( item.children )
{
const childItem = this.getNavigationItemParent(id, item.children, item);
if ( childItem )
{
return childItem;
}
}
}
return false;
}
/**
* Add a navigation item to the specified location
*
* @param item
* @param id
*/
addNavigationItem(item, id): void
{
// Get the current navigation
const navigation: any[] = this.getCurrentNavigation();
// Add to the end of the navigation
if ( id === 'end' )
{
navigation.push(item);
return;
}
// Add to the start of the navigation
if ( id === 'start' )
{
navigation.unshift(item);
}
// Add it to a specific location
const parent: any = this.getNavigationItem(id);
if ( parent )
{
// Check if parent has a children entry,
// and add it if it doesn't
if ( !parent.children )
{
parent.children = [];
}
// Add the item
parent.children.push(item);
}
}
/**
* Remove navigation item with the given id
*
* @param id
*/
removeNavigationItem(id): void
{
const item = this.getNavigationItem(id);
// Return, if there is not such an item
if ( !item )
{
return;
}
// Get the parent of the item
let parent = this.getNavigationItemParent(id);
// This check is required because of the first level
// of the navigation, since the first level is not
// inside the 'children' array
parent = parent.children || parent;
// Remove the item
parent.splice(parent.indexOf(item), 1);
}
}

View File

@@ -1,65 +0,0 @@
<ng-container *ngIf="!item.hidden">
<!-- normal collapse -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="!item.url && !item.function"
(click)="toggleOpen($event)" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<!-- item.url -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && !item.externalUrl && !item.function"
(click)="toggleOpen($event)"
[routerLink]="[item.url]" [routerLinkActive]="['active', 'mat-accent-bg']"
[routerLinkActiveOptions]="{exact: item.exactMatch || false}"
[target]="item.openInNewTab ? '_blank' : '_self'" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<!-- item.externalUrl -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && item.externalUrl && !item.function"
(click)="toggleOpen($event)"
[href]="item.url" [target]="item.openInNewTab ? '_blank' : '_self'" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<!-- item.function -->
<span class="nav-link" [ngClass]="item.classes" *ngIf="!item.url && item.function"
(click)="toggleOpen($event);item.function()" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</span>
<!-- item.url && item.function -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && !item.externalUrl && item.function"
(click)="toggleOpen($event);item.function()"
[routerLink]="[item.url]" [routerLinkActive]="['active', 'mat-accent-bg']"
[routerLinkActiveOptions]="{exact: item.exactMatch || false}" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<!-- item.externalUrl && item.function -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && item.externalUrl && item.function"
(click)="toggleOpen($event);item.function()"
[href]="item.url" [target]="item.openInNewTab ? '_blank' : '_self'" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<ng-template #itemContent>
<mat-icon class="nav-link-icon" *ngIf="item.icon">{{item.icon}}</mat-icon>
<span class="nav-link-title" [translate]="item.translate">{{item.title}}</span>
<span class="nav-link-badge" *ngIf="item.badge" [translate]="item.badge.translate"
[ngStyle]="{'background-color': item.badge.bg,'color': item.badge.fg}">
{{item.badge.title}}
</span>
<mat-icon class="collapsable-arrow">keyboard_arrow_right</mat-icon>
</ng-template>
<div class="children" [@slideInOut]="isOpen">
<ng-container *ngFor="let item of item.children">
<fuse-nav-vertical-item *ngIf="item.type=='item'" [item]="item"></fuse-nav-vertical-item>
<fuse-nav-vertical-collapsable *ngIf="item.type=='collapsable'"
[item]="item"></fuse-nav-vertical-collapsable>
<fuse-nav-vertical-group *ngIf="item.type=='group'" [item]="item"></fuse-nav-vertical-group>
</ng-container>
</div>
</ng-container>

View File

@@ -1,237 +0,0 @@
import { Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';
import { FuseNavigationItem } from '@fuse/types';
import { fuseAnimations } from '@fuse/animations';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
@Component({
selector : 'fuse-nav-vertical-collapsable',
templateUrl: './collapsable.component.html',
styleUrls : ['./collapsable.component.scss'],
animations : fuseAnimations
})
export class FuseNavVerticalCollapsableComponent implements OnInit, OnDestroy
{
@Input()
item: FuseNavigationItem;
@HostBinding('class')
classes = 'nav-collapsable nav-item';
@HostBinding('class.open')
public isOpen = false;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {FuseNavigationService} _fuseNavigationService
* @param {Router} _router
*/
constructor(
private _fuseNavigationService: FuseNavigationService,
private _router: Router
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Listen for router events
this._router.events
.pipe(
filter(event => event instanceof NavigationEnd),
takeUntil(this._unsubscribeAll)
)
.subscribe((event: NavigationEnd) => {
// Check if the url can be found in
// one of the children of this item
if ( this.isUrlInChildren(this.item, event.urlAfterRedirects) )
{
this.expand();
}
else
{
this.collapse();
}
});
// Listen for collapsing of any navigation item
this._fuseNavigationService.onItemCollapsed
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(
(clickedItem) => {
if ( clickedItem && clickedItem.children )
{
// Check if the clicked item is one
// of the children of this item
if ( this.isChildrenOf(this.item, clickedItem) )
{
return;
}
// Check if the url can be found in
// one of the children of this item
if ( this.isUrlInChildren(this.item, this._router.url) )
{
return;
}
// If the clicked item is not this item, collapse...
if ( this.item !== clickedItem )
{
this.collapse();
}
}
}
);
// Check if the url can be found in
// one of the children of this item
if ( this.isUrlInChildren(this.item, this._router.url) )
{
this.expand();
}
else
{
this.collapse();
}
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle collapse
*
* @param ev
*/
toggleOpen(ev): void
{
ev.preventDefault();
this.isOpen = !this.isOpen;
// Navigation collapse toggled...
this._fuseNavigationService.onItemCollapsed.next(this.item);
this._fuseNavigationService.onItemCollapseToggled.next();
}
/**
* Expand the collapsable navigation
*/
expand(): void
{
if ( this.isOpen )
{
return;
}
this.isOpen = true;
this._fuseNavigationService.onItemCollapseToggled.next();
}
/**
* Collapse the collapsable navigation
*/
collapse(): void
{
if ( !this.isOpen )
{
return;
}
this.isOpen = false;
this._fuseNavigationService.onItemCollapseToggled.next();
}
/**
* Check if the given parent has the
* given item in one of its children
*
* @param parent
* @param item
* @returns {boolean}
*/
isChildrenOf(parent, item): boolean
{
if ( !parent.children )
{
return false;
}
if ( parent.children.indexOf(item) !== -1 )
{
return true;
}
for ( const children of parent.children )
{
if ( children.children )
{
return this.isChildrenOf(children, item);
}
}
}
/**
* Check if the given url can be found
* in one of the given parent's children
*
* @param parent
* @param url
* @returns {boolean}
*/
isUrlInChildren(parent, url): boolean
{
if ( !parent.children )
{
return false;
}
for ( let i = 0; i < parent.children.length; i++ )
{
if ( parent.children[i].children )
{
if ( this.isUrlInChildren(parent.children[i], url) )
{
return true;
}
}
if ( parent.children[i].url === url || url.includes(parent.children[i].url) )
{
return true;
}
}
return false;
}
}

View File

@@ -1,16 +0,0 @@
<ng-container *ngIf="!item.hidden">
<div class="group-title" [ngClass]="item.classes">
<span class="hint-text" [translate]="item.translate">{{ item.title }}</span>
</div>
<div class="group-items">
<ng-container *ngFor="let item of item.children">
<fuse-nav-vertical-group *ngIf="item.type=='group'" [item]="item"></fuse-nav-vertical-group>
<fuse-nav-vertical-collapsable *ngIf="item.type=='collapsable'"
[item]="item"></fuse-nav-vertical-collapsable>
<fuse-nav-vertical-item *ngIf="item.type=='item'" [item]="item"></fuse-nav-vertical-item>
</ng-container>
</div>
</ng-container>

View File

@@ -1,23 +0,0 @@
:host {
.folded:not(.unfolded) & {
> .group-title {
align-items: center;
> span {
opacity: 0;
transition: opacity 200ms ease;
}
&:before {
content: '';
display: block;
position: absolute;
min-width: 1.6rem;
border-top: 2px solid;
opacity: 0.2;
}
}
}
}

View File

@@ -1,25 +0,0 @@
import { Component, HostBinding, Input } from '@angular/core';
import { FuseNavigationItem } from '@fuse/types';
@Component({
selector : 'fuse-nav-vertical-group',
templateUrl: './group.component.html',
styleUrls : ['./group.component.scss']
})
export class FuseNavVerticalGroupComponent
{
@HostBinding('class')
classes = 'nav-group nav-item';
@Input()
item: FuseNavigationItem;
/**
* Constructor
*/
constructor()
{
}
}

View File

@@ -1,48 +0,0 @@
<ng-container *ngIf="!item.hidden">
<!-- item.url -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && !item.externalUrl && !item.function"
[routerLink]="[item.url]" [routerLinkActive]="['active', 'mat-accent-bg']"
[routerLinkActiveOptions]="{exact: item.exactMatch || false}"
[target]="item.openInNewTab ? '_blank' : '_self'" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<!-- item.externalUrl -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && item.externalUrl && !item.function"
[href]="item.url" [target]="item.openInNewTab ? '_blank' : '_self'" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<!-- item.function -->
<span class="nav-link" [ngClass]="item.classes" *ngIf="!item.url && item.function"
(click)="item.function()" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</span>
<!-- item.url && item.function -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && !item.externalUrl && item.function"
(click)="item.function()"
[routerLink]="[item.url]" [routerLinkActive]="['active', 'mat-accent-bg']"
[routerLinkActiveOptions]="{exact: item.exactMatch || false}"
[target]="item.openInNewTab ? '_blank' : '_self'" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<!-- item.externalUrl && item.function -->
<a class="nav-link" [ngClass]="item.classes" *ngIf="item.url && item.externalUrl && item.function"
(click)="item.function()"
[href]="item.url" [target]="item.openInNewTab ? '_blank' : '_self'" matRipple>
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
</a>
<ng-template #itemContent>
<mat-icon class="nav-link-icon" *ngIf="item.icon">{{item.icon}}</mat-icon>
<span class="nav-link-title" [translate]="item.translate">{{item.title}}</span>
<span class="nav-link-badge" *ngIf="item.badge" [translate]="item.badge.translate"
[ngStyle]="{'background-color': item.badge.bg,'color': item.badge.fg}">
{{item.badge.title}}
</span>
</ng-template>
</ng-container>

View File

@@ -1,24 +0,0 @@
import { Component, HostBinding, Input } from '@angular/core';
import { FuseNavigationItem } from '@fuse/types';
@Component({
selector : 'fuse-nav-vertical-item',
templateUrl: './item.component.html',
styleUrls : ['./item.component.scss']
})
export class FuseNavVerticalItemComponent
{
@HostBinding('class')
classes = 'nav-item';
@Input()
item: FuseNavigationItem;
/**
* Constructor
*/
constructor()
{
}
}

View File

@@ -1,25 +0,0 @@
<div class="fuse-search-bar" [ngClass]="{'expanded':!collapsed}">
<div class="fuse-search-bar-content" [ngClass]="fuseConfig.layout.toolbar.background">
<label for="fuse-search-bar-input">
<button mat-icon-button class="fuse-search-bar-expander" aria-label="Expand Search Bar" (click)="expand()"
*ngIf="collapsed">
<mat-icon class="s-24 secondary-text">search</mat-icon>
</button>
<!--<span class="fuse-search-bar-loader" fxLayout="row" fxLayoutAlign="center center" *ngIf="!collapsed">
<mat-progress-spinner color="mat-accent" mode="indeterminate"></mat-progress-spinner>
</span>-->
</label>
<input id="fuse-search-bar-input" class="ml-24" type="text" placeholder="Search" (input)="search($event)"
fxFlex>
<button mat-icon-button class="fuse-search-bar-collapser" (click)="collapse()"
aria-label="Collapse Search Bar">
<mat-icon class="s-24 secondary-text">close</mat-icon>
</button>
</div>
</div>

View File

@@ -1,91 +0,0 @@
@import "src/@fuse/scss/fuse";
:host {
.fuse-search-bar {
display: flex;
flex: 0 1 auto;
min-width: 64px;
height: 64px;
font-size: 13px;
@include media-breakpoint-down('xs') {
height: 56px;
}
.fuse-search-bar-content {
display: flex;
flex: 1 1 auto;
align-items: center;
justify-content: flex-start;
.fuse-search-bar-expander,
.fuse-search-bar-collapser {
cursor: pointer;
padding: 0 20px;
margin: 0;
width: 64px !important;
height: 64px !important;
line-height: 64px !important;
@include media-breakpoint-down('xs') {
height: 56px !important;
line-height: 56px !important;
}
}
.fuse-search-bar-loader {
width: 64px !important;
height: 64px !important;
line-height: 64px !important;
@include media-breakpoint-down('xs') {
height: 56px !important;
line-height: 56px !important;
}
}
.fuse-search-bar-collapser {
display: none;
}
#fuse-search-bar-input {
display: none;
flex: 1 0 auto;
min-height: 64px;
background-color: transparent;
font-size: 16px;
}
}
&.expanded {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 10;
.fuse-search-bar-content {
#fuse-search-bar-input {
display: flex;
}
.fuse-search-bar-collapser {
display: flex;
}
}
}
}
body {
&.fuse-search-bar-expanded {
#toolbar {
z-index: 999 !important;
}
}
}
}

View File

@@ -1,99 +0,0 @@
import { Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FuseConfigService } from '@fuse/services/config.service';
@Component({
selector : 'fuse-search-bar',
templateUrl: './search-bar.component.html',
styleUrls : ['./search-bar.component.scss']
})
export class FuseSearchBarComponent implements OnInit, OnDestroy
{
collapsed: boolean;
fuseConfig: any;
@Output()
input: EventEmitter<any>;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {FuseConfigService} _fuseConfigService
*/
constructor(
private _fuseConfigService: FuseConfigService
)
{
// Set the defaults
this.input = new EventEmitter();
this.collapsed = true;
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to config changes
this._fuseConfigService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(
(config) => {
this.fuseConfig = config;
}
);
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Collapse
*/
collapse(): void
{
this.collapsed = true;
}
/**
* Expand
*/
expand(): void
{
this.collapsed = false;
}
/**
* Search
*
* @param event
*/
search(event): void
{
this.input.emit(event.target.value);
}
}

View File

@@ -1,113 +0,0 @@
<div id="fuse-shortcuts" #shortcuts>
<div class="shortcuts-mobile-toggle" *ngIf="!mobileShortcutsPanelActive" fxLayout="row" fxLayoutAlign="start center"
fxHide fxShow.lt-md>
<button mat-icon-button (click)="showMobileShortcutsPanel()">
<mat-icon class="amber-600-fg">star</mat-icon>
</button>
</div>
<div class="shortcuts" fxHide fxShow.gt-sm>
<div fxLayout="row" fxLayoutAlign="space-between center" fxFlex="0 1 auto">
<div fxLayout="row" fxLayoutAlign="start center">
<div class="w-40 h-40 p-4" fxLayout="row" fxLayoutAlign="center center"
*ngFor="let shortcutItem of shortcutItems">
<a mat-icon-button matTooltip="{{shortcutItem.title}}" [routerLink]="shortcutItem.url">
<mat-icon class="secondary-text" *ngIf="shortcutItem.icon">{{shortcutItem.icon}}</mat-icon>
<span *ngIf="!shortcutItem.icon" class="h2 secondary-text text-bold">
{{shortcutItem.title.substr(0, 1).toUpperCase()}}
</span>
</a>
</div>
<button mat-icon-button [matMenuTriggerFor]="addMenu" matTooltip="Click to add/remove shortcut"
(menuOpened)="onMenuOpen()">
<mat-icon class="amber-600-fg">star</mat-icon>
</button>
</div>
<div class="shortcuts-mobile-close" fxLayout="row" fxLayoutAlign="start center" fxHide fxShow.lt-md>
<button mat-icon-button (click)="hideMobileShortcutsPanel()">
<mat-icon>close</mat-icon>
</button>
</div>
</div>
<mat-menu #addMenu="matMenu" class="w-240">
<mat-form-field class="px-16 w-100-p" (click)="$event.stopPropagation()" floatLabel="never">
<input #searchInput matInput placeholder="Search for an app or a page" (input)="search($event)">
</mat-form-field>
<mat-divider></mat-divider>
<mat-nav-list *ngIf="!searching" style="max-height: 312px; overflow: auto" fusePerfectScrollbar>
<mat-list-item *ngFor="let shortcutItem of shortcutItems"
(click)="toggleShortcut($event, shortcutItem)">
<div class="w-100-p" fxLayout="row" fxLayoutAlign="start center">
<mat-icon mat-list-icon class="mr-8 secondary-text" *ngIf="shortcutItem.icon">
{{shortcutItem.icon}}
</mat-icon>
<span class="h2 w-32 h-32 p-4 mr-8 secondary-text text-bold" fxLayout="row"
fxLayoutAlign="center center" *ngIf="!shortcutItem.icon">
{{shortcutItem.title.substr(0, 1).toUpperCase()}}
</span>
<p matLine fxFlex>{{shortcutItem.title}}</p>
<mat-icon class="ml-8 amber-fg">star</mat-icon>
</div>
</mat-list-item>
<mat-list-item *ngIf="shortcutItems.length === 0">
<p>
<small>No shortcuts yet!</small>
</p>
</mat-list-item>
</mat-nav-list>
<mat-nav-list *ngIf="searching" style="max-height: 312px; overflow: auto" fusePerfectScrollbar>
<mat-list-item *ngFor="let navigationItem of filteredNavigationItems"
(click)="toggleShortcut($event, navigationItem)">
<div class="w-100-p" fxLayout="row" fxLayoutAlign="start center">
<mat-icon mat-list-icon class="mr-8 secondary-text" *ngIf="navigationItem.icon">
{{navigationItem.icon}}
</mat-icon>
<span class="h2 w-32 h-32 p-4 mr-8 secondary-text text-bold" fxLayout="row"
fxLayoutAlign="center center" *ngIf="!navigationItem.icon">
{{navigationItem.title.substr(0, 1).toUpperCase()}}
</span>
<p matLine fxFlex>{{navigationItem.title}}</p>
<mat-icon class="ml-8 amber-fg" *ngIf="isInShortcuts(navigationItem)">star</mat-icon>
</div>
</mat-list-item>
</mat-nav-list>
</mat-menu>
</div>
</div>

View File

@@ -1,227 +0,0 @@
import { Component, ElementRef, Input, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core';
import { ObservableMedia } from '@angular/flex-layout';
import { CookieService } from 'ngx-cookie-service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FuseMatchMediaService } from '@fuse/services/match-media.service';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
@Component({
selector : 'fuse-shortcuts',
templateUrl: './shortcuts.component.html',
styleUrls : ['./shortcuts.component.scss']
})
export class FuseShortcutsComponent implements OnInit, OnDestroy
{
shortcutItems: any[];
navigationItems: any[];
filteredNavigationItems: any[];
searching: boolean;
mobileShortcutsPanelActive: boolean;
@Input()
navigation: any;
@ViewChild('searchInput')
searchInputField;
@ViewChild('shortcuts')
shortcutsEl: ElementRef;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {Renderer2} _renderer
* @param {CookieService} _cookieService
* @param {FuseMatchMediaService} _fuseMatchMediaService
* @param {FuseNavigationService} _fuseNavigationService
* @param {ObservableMedia} _observableMedia
*/
constructor(
private _cookieService: CookieService,
private _fuseMatchMediaService: FuseMatchMediaService,
private _fuseNavigationService: FuseNavigationService,
private _observableMedia: ObservableMedia,
private _renderer: Renderer2
)
{
// Set the defaults
this.shortcutItems = [];
this.searching = false;
this.mobileShortcutsPanelActive = false;
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Get the navigation items and flatten them
this.filteredNavigationItems = this.navigationItems = this._fuseNavigationService.getFlatNavigation(this.navigation);
const cookieExists = this._cookieService.check('FUSE2.shortcuts');
if ( cookieExists )
{
this.shortcutItems = JSON.parse(this._cookieService.get('FUSE2.shortcuts'));
}
else
{
// User's shortcut items
this.shortcutItems = [
{
'title': 'Calendar',
'type' : 'item',
'icon' : 'today',
'url' : '/apps/calendar'
},
{
'title': 'Mail',
'type' : 'item',
'icon' : 'email',
'url' : '/apps/mail'
},
{
'title': 'Contacts',
'type' : 'item',
'icon' : 'account_box',
'url' : '/apps/contacts'
},
{
'title': 'To-Do',
'type' : 'item',
'icon' : 'check_box',
'url' : '/apps/todo'
}
];
}
this._fuseMatchMediaService.onMediaChange
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
if ( this._observableMedia.isActive('gt-sm') )
{
this.hideMobileShortcutsPanel();
}
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Search
*
* @param event
*/
search(event): void
{
const value = event.target.value.toLowerCase();
if ( value === '' )
{
this.searching = false;
this.filteredNavigationItems = this.navigationItems;
return;
}
this.searching = true;
this.filteredNavigationItems = this.navigationItems.filter((navigationItem) => {
return navigationItem.title.toLowerCase().includes(value);
});
}
/**
* Toggle shortcut
*
* @param event
* @param itemToToggle
*/
toggleShortcut(event, itemToToggle): void
{
event.stopPropagation();
for ( let i = 0; i < this.shortcutItems.length; i++ )
{
if ( this.shortcutItems[i].url === itemToToggle.url )
{
this.shortcutItems.splice(i, 1);
// Save to the cookies
this._cookieService.set('FUSE2.shortcuts', JSON.stringify(this.shortcutItems));
return;
}
}
this.shortcutItems.push(itemToToggle);
// Save to the cookies
this._cookieService.set('FUSE2.shortcuts', JSON.stringify(this.shortcutItems));
}
/**
* Is in shortcuts?
*
* @param navigationItem
* @returns {any}
*/
isInShortcuts(navigationItem): any
{
return this.shortcutItems.find(item => {
return item.url === navigationItem.url;
});
}
/**
* On menu open
*/
onMenuOpen(): void
{
setTimeout(() => {
this.searchInputField.nativeElement.focus();
});
}
/**
* Show mobile shortcuts
*/
showMobileShortcutsPanel(): void
{
this.mobileShortcutsPanelActive = true;
this._renderer.addClass(this.shortcutsEl.nativeElement, 'show-mobile-panel');
}
/**
* Hide mobile shortcuts
*/
hideMobileShortcutsPanel(): void
{
this.mobileShortcutsPanelActive = false;
this._renderer.removeClass(this.shortcutsEl.nativeElement, 'show-mobile-panel');
}
}

View File

@@ -1,38 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatButtonModule, MatDividerModule, MatFormFieldModule, MatIconModule, MatInputModule, MatListModule, MatMenuModule, MatTooltipModule } from '@angular/material';
import { CookieService } from 'ngx-cookie-service';
import { FuseShortcutsComponent } from './shortcuts.component';
@NgModule({
declarations: [
FuseShortcutsComponent
],
imports : [
CommonModule,
RouterModule,
FlexLayoutModule,
MatButtonModule,
MatDividerModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatMenuModule,
MatListModule,
MatTooltipModule
],
exports : [
FuseShortcutsComponent
],
providers : [
CookieService
]
})
export class FuseShortcutsModule
{
}

View File

@@ -1 +0,0 @@
<ng-content></ng-content>

View File

@@ -1,70 +0,0 @@
@import "src/@fuse/scss/fuse";
fuse-sidebar {
display: flex;
flex-direction: column;
flex: 1 0 auto;
position: absolute;
top: 0;
bottom: 0;
overflow-x: hidden;
overflow-y: auto;
width: 280px;
min-width: 280px;
max-width: 280px;
z-index: 1000;
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.35);
background: white;
@include media-breakpoint-down('xs') {
min-width: 0 !important;
max-width: 80vw !important;
width: 80vw !important;
}
&.left-positioned {
left: 0;
transform: translateX(-100%);
}
&.right-positioned {
right: 0;
transform: translateX(100%);
}
&.open {
transform: translateX(0);
}
&.locked-open {
position: relative !important;
transform: translateX(0) !important;
}
&.folded {
position: absolute !important;
top: 0;
bottom: 0;
}
&.animations-enabled {
transition-property: transform, width, min-width, max-width;
transition-duration: 150ms;
transition-timing-function: ease-in-out;
}
}
.fuse-sidebar-overlay {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 999;
background-color: rgba(0, 0, 0, 0.6);
opacity: 0;
&.fuse-sidebar-overlay-invisible {
background-color: transparent;
}
}

View File

@@ -1,799 +0,0 @@
import { ChangeDetectorRef, Component, ElementRef, EventEmitter, HostBinding, HostListener, Input, OnDestroy, OnInit, Output, Renderer2, RendererStyleFlags2, ViewEncapsulation } from '@angular/core';
import { animate, AnimationBuilder, AnimationPlayer, style } from '@angular/animations';
import { ObservableMedia } from '@angular/flex-layout';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FuseSidebarService } from './sidebar.service';
import { FuseMatchMediaService } from '@fuse/services/match-media.service';
import { FuseConfigService } from '@fuse/services/config.service';
@Component({
selector : 'fuse-sidebar',
templateUrl : './sidebar.component.html',
styleUrls : ['./sidebar.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class FuseSidebarComponent implements OnInit, OnDestroy
{
// Name
@Input()
name: string;
// Key
@Input()
key: string;
// Position
@Input()
position: 'left' | 'right';
// Open
@HostBinding('class.open')
opened: boolean;
// Locked Open
@Input()
lockedOpen: string;
// isLockedOpen
@HostBinding('class.locked-open')
isLockedOpen: boolean;
// Folded width
@Input()
foldedWidth: number;
// Folded auto trigger on hover
@Input()
foldedAutoTriggerOnHover: boolean;
// Folded unfolded
@HostBinding('class.unfolded')
unfolded: boolean;
// Invisible overlay
@Input()
invisibleOverlay: boolean;
// Folded changed
@Output()
foldedChanged: EventEmitter<boolean>;
// Opened changed
@Output()
openedChanged: EventEmitter<boolean>;
// Private
private _folded: boolean;
private _fuseConfig: any;
private _wasActive: boolean;
private _wasFolded: boolean;
private _backdrop: HTMLElement | null = null;
private _player: AnimationPlayer;
private _unsubscribeAll: Subject<any>;
@HostBinding('class.animations-enabled')
private _animationsEnabled: boolean;
/**
* Constructor
*
* @param {AnimationBuilder} _animationBuilder
* @param {ChangeDetectorRef} _changeDetectorRef
* @param {ElementRef} _elementRef
* @param {FuseConfigService} _fuseConfigService
* @param {FuseMatchMediaService} _fuseMatchMediaService
* @param {FuseSidebarService} _fuseSidebarService
* @param {ObservableMedia} _observableMedia
* @param {Renderer2} _renderer
*/
constructor(
private _animationBuilder: AnimationBuilder,
private _changeDetectorRef: ChangeDetectorRef,
private _elementRef: ElementRef,
private _fuseConfigService: FuseConfigService,
private _fuseMatchMediaService: FuseMatchMediaService,
private _fuseSidebarService: FuseSidebarService,
private _observableMedia: ObservableMedia,
private _renderer: Renderer2
)
{
// Set the defaults
this.foldedAutoTriggerOnHover = true;
this.foldedWidth = 64;
this.foldedChanged = new EventEmitter();
this.openedChanged = new EventEmitter();
this.opened = false;
this.position = 'left';
this.invisibleOverlay = false;
// Set the private defaults
this._animationsEnabled = false;
this._folded = false;
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Folded
*
* @param {boolean} value
*/
@Input()
set folded(value: boolean)
{
// Set the folded
this._folded = value;
// Return if the sidebar is closed
if ( !this.opened )
{
return;
}
// Programmatically add/remove padding to the element
// that comes after or before based on the position
let sibling,
styleRule;
const styleValue = this.foldedWidth + 'px';
// Get the sibling and set the style rule
if ( this.position === 'left' )
{
sibling = this._elementRef.nativeElement.nextElementSibling;
styleRule = 'padding-left';
}
else
{
sibling = this._elementRef.nativeElement.previousElementSibling;
styleRule = 'padding-right';
}
// If there is no sibling, return...
if ( !sibling )
{
return;
}
// If folded...
if ( value )
{
// Fold the sidebar
this.fold();
// Set the folded width
this._renderer.setStyle(this._elementRef.nativeElement, 'width', styleValue);
this._renderer.setStyle(this._elementRef.nativeElement, 'min-width', styleValue);
this._renderer.setStyle(this._elementRef.nativeElement, 'max-width', styleValue);
// Set the style and class
this._renderer.setStyle(sibling, styleRule, styleValue, RendererStyleFlags2.Important + RendererStyleFlags2.DashCase);
this._renderer.addClass(this._elementRef.nativeElement, 'folded');
}
// If unfolded...
else
{
// Unfold the sidebar
this.unfold();
// Remove the folded width
this._renderer.removeStyle(this._elementRef.nativeElement, 'width');
this._renderer.removeStyle(this._elementRef.nativeElement, 'min-width');
this._renderer.removeStyle(this._elementRef.nativeElement, 'max-width');
// Remove the style and class
this._renderer.removeStyle(sibling, styleRule);
this._renderer.removeClass(this._elementRef.nativeElement, 'folded');
}
// Emit the 'foldedChanged' event
this.foldedChanged.emit(this.folded);
}
get folded(): boolean
{
return this._folded;
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to config changes
this._fuseConfigService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._fuseConfig = config;
});
// Register the sidebar
this._fuseSidebarService.register(this.name, this);
// Setup visibility
this._setupVisibility();
// Setup position
this._setupPosition();
// Setup lockedOpen
this._setupLockedOpen();
// Setup folded
this._setupFolded();
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// If the sidebar is folded, unfold it to revert modifications
if ( this.folded )
{
this.unfold();
}
// Unregister the sidebar
this._fuseSidebarService.unregister(this.name);
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Setup the visibility of the sidebar
*
* @private
*/
private _setupVisibility(): void
{
// Remove the existing box-shadow
this._renderer.setStyle(this._elementRef.nativeElement, 'box-shadow', 'none');
// Make the sidebar invisible
this._renderer.setStyle(this._elementRef.nativeElement, 'visibility', 'hidden');
}
/**
* Setup the sidebar position
*
* @private
*/
private _setupPosition(): void
{
// Add the correct class name to the sidebar
// element depending on the position attribute
if ( this.position === 'right' )
{
this._renderer.addClass(this._elementRef.nativeElement, 'right-positioned');
}
else
{
this._renderer.addClass(this._elementRef.nativeElement, 'left-positioned');
}
}
/**
* Setup the lockedOpen handler
*
* @private
*/
private _setupLockedOpen(): void
{
// Return if the lockedOpen wasn't set
if ( !this.lockedOpen )
{
// Return
return;
}
// Set the wasActive for the first time
this._wasActive = false;
// Set the wasFolded
this._wasFolded = this.folded;
// Show the sidebar
this._showSidebar();
// Act on every media change
this._fuseMatchMediaService.onMediaChange
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Get the active status
const isActive = this._observableMedia.isActive(this.lockedOpen);
// If the both status are the same, don't act
if ( this._wasActive === isActive )
{
return;
}
// Activate the lockedOpen
if ( isActive )
{
// Set the lockedOpen status
this.isLockedOpen = true;
// Show the sidebar
this._showSidebar();
// Force the the opened status to true
this.opened = true;
// Emit the 'openedChanged' event
this.openedChanged.emit(this.opened);
// If the sidebar was folded, forcefully fold it again
if ( this._wasFolded )
{
// Enable the animations
this._enableAnimations();
// Fold
this.folded = true;
// Mark for check
this._changeDetectorRef.markForCheck();
}
// Hide the backdrop if any exists
this._hideBackdrop();
}
// De-Activate the lockedOpen
else
{
// Set the lockedOpen status
this.isLockedOpen = false;
// Unfold the sidebar in case if it was folded
this.unfold();
// Force the the opened status to close
this.opened = false;
// Emit the 'openedChanged' event
this.openedChanged.emit(this.opened);
// Hide the sidebar
this._hideSidebar();
}
// Store the new active status
this._wasActive = isActive;
});
}
/**
* Setup the initial folded status
*
* @private
*/
private _setupFolded(): void
{
// Return, if sidebar is not folded
if ( !this.folded )
{
return;
}
// Return if the sidebar is closed
if ( !this.opened )
{
return;
}
// Programmatically add/remove padding to the element
// that comes after or before based on the position
let sibling,
styleRule;
const styleValue = this.foldedWidth + 'px';
// Get the sibling and set the style rule
if ( this.position === 'left' )
{
sibling = this._elementRef.nativeElement.nextElementSibling;
styleRule = 'padding-left';
}
else
{
sibling = this._elementRef.nativeElement.previousElementSibling;
styleRule = 'padding-right';
}
// If there is no sibling, return...
if ( !sibling )
{
return;
}
// Fold the sidebar
this.fold();
// Set the folded width
this._renderer.setStyle(this._elementRef.nativeElement, 'width', styleValue);
this._renderer.setStyle(this._elementRef.nativeElement, 'min-width', styleValue);
this._renderer.setStyle(this._elementRef.nativeElement, 'max-width', styleValue);
// Set the style and class
this._renderer.setStyle(sibling, styleRule, styleValue, RendererStyleFlags2.Important + RendererStyleFlags2.DashCase);
this._renderer.addClass(this._elementRef.nativeElement, 'folded');
}
/**
* Show the backdrop
*
* @private
*/
private _showBackdrop(): void
{
// Create the backdrop element
this._backdrop = this._renderer.createElement('div');
// Add a class to the backdrop element
this._backdrop.classList.add('fuse-sidebar-overlay');
// Add a class depending on the invisibleOverlay option
if ( this.invisibleOverlay )
{
this._backdrop.classList.add('fuse-sidebar-overlay-invisible');
}
// Append the backdrop to the parent of the sidebar
this._renderer.appendChild(this._elementRef.nativeElement.parentElement, this._backdrop);
// Create the enter animation and attach it to the player
this._player =
this._animationBuilder
.build([
animate('300ms ease', style({opacity: 1}))
]).create(this._backdrop);
// Play the animation
this._player.play();
// Add an event listener to the overlay
this._backdrop.addEventListener('click', () => {
this.close();
}
);
// Mark for check
this._changeDetectorRef.markForCheck();
}
/**
* Hide the backdrop
*
* @private
*/
private _hideBackdrop(): void
{
if ( !this._backdrop )
{
return;
}
// Create the leave animation and attach it to the player
this._player =
this._animationBuilder
.build([
animate('300ms ease', style({opacity: 0}))
]).create(this._backdrop);
// Play the animation
this._player.play();
// Once the animation is done...
this._player.onDone(() => {
// If the backdrop still exists...
if ( this._backdrop )
{
// Remove the backdrop
this._backdrop.parentNode.removeChild(this._backdrop);
this._backdrop = null;
}
});
// Mark for check
this._changeDetectorRef.markForCheck();
}
/**
* Change some properties of the sidebar
* and make it visible
*
* @private
*/
private _showSidebar(): void
{
// Remove the box-shadow style
this._renderer.removeStyle(this._elementRef.nativeElement, 'box-shadow');
// Make the sidebar invisible
this._renderer.removeStyle(this._elementRef.nativeElement, 'visibility');
// Mark for check
this._changeDetectorRef.markForCheck();
}
/**
* Change some properties of the sidebar
* and make it invisible
*
* @private
*/
private _hideSidebar(delay = true): void
{
const delayAmount = delay ? 300 : 0;
// Add a delay so close animation can play
setTimeout(() => {
// Remove the box-shadow
this._renderer.setStyle(this._elementRef.nativeElement, 'box-shadow', 'none');
// Make the sidebar invisible
this._renderer.setStyle(this._elementRef.nativeElement, 'visibility', 'hidden');
}, delayAmount);
// Mark for check
this._changeDetectorRef.markForCheck();
}
/**
* Enable the animations
*
* @private
*/
private _enableAnimations(): void
{
// Return if animations already enabled
if ( this._animationsEnabled )
{
return;
}
// Enable the animations
this._animationsEnabled = true;
// Mark for check
this._changeDetectorRef.markForCheck();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Open the sidebar
*/
open(): void
{
if ( this.opened || this.isLockedOpen )
{
return;
}
// Enable the animations
this._enableAnimations();
// Show the sidebar
this._showSidebar();
// Show the backdrop
this._showBackdrop();
// Set the opened status
this.opened = true;
// Emit the 'openedChanged' event
this.openedChanged.emit(this.opened);
// Mark for check
this._changeDetectorRef.markForCheck();
}
/**
* Close the sidebar
*/
close(): void
{
if ( !this.opened || this.isLockedOpen )
{
return;
}
// Enable the animations
this._enableAnimations();
// Hide the backdrop
this._hideBackdrop();
// Set the opened status
this.opened = false;
// Emit the 'openedChanged' event
this.openedChanged.emit(this.opened);
// Hide the sidebar
this._hideSidebar();
// Mark for check
this._changeDetectorRef.markForCheck();
}
/**
* Toggle open/close the sidebar
*/
toggleOpen(): void
{
if ( this.opened )
{
this.close();
}
else
{
this.open();
}
}
/**
* Mouseenter
*/
@HostListener('mouseenter')
onMouseEnter(): void
{
// Only work if the auto trigger is enabled
if ( !this.foldedAutoTriggerOnHover )
{
return;
}
this.unfoldTemporarily();
}
/**
* Mouseleave
*/
@HostListener('mouseleave')
onMouseLeave(): void
{
// Only work if the auto trigger is enabled
if ( !this.foldedAutoTriggerOnHover )
{
return;
}
this.foldTemporarily();
}
/**
* Fold the sidebar permanently
*/
fold(): void
{
// Only work if the sidebar is not folded
if ( this.folded )
{
return;
}
// Enable the animations
this._enableAnimations();
// Fold
this.folded = true;
// Mark for check
this._changeDetectorRef.markForCheck();
}
/**
* Unfold the sidebar permanently
*/
unfold(): void
{
// Only work if the sidebar is folded
if ( !this.folded )
{
return;
}
// Enable the animations
this._enableAnimations();
// Unfold
this.folded = false;
// Mark for check
this._changeDetectorRef.markForCheck();
}
/**
* Toggle the sidebar fold/unfold permanently
*/
toggleFold(): void
{
if ( this.folded )
{
this.unfold();
}
else
{
this.fold();
}
}
/**
* Fold the temporarily unfolded sidebar back
*/
foldTemporarily(): void
{
// Only work if the sidebar is folded
if ( !this.folded )
{
return;
}
// Enable the animations
this._enableAnimations();
// Fold the sidebar back
this.unfolded = false;
// Set the folded width
const styleValue = this.foldedWidth + 'px';
this._renderer.setStyle(this._elementRef.nativeElement, 'width', styleValue);
this._renderer.setStyle(this._elementRef.nativeElement, 'min-width', styleValue);
this._renderer.setStyle(this._elementRef.nativeElement, 'max-width', styleValue);
// Mark for check
this._changeDetectorRef.markForCheck();
}
/**
* Unfold the sidebar temporarily
*/
unfoldTemporarily(): void
{
// Only work if the sidebar is folded
if ( !this.folded )
{
return;
}
// Enable the animations
this._enableAnimations();
// Unfold the sidebar temporarily
this.unfolded = true;
// Remove the folded width
this._renderer.removeStyle(this._elementRef.nativeElement, 'width');
this._renderer.removeStyle(this._elementRef.nativeElement, 'min-width');
this._renderer.removeStyle(this._elementRef.nativeElement, 'max-width');
// Mark for check
this._changeDetectorRef.markForCheck();
}
}

View File

@@ -1,15 +0,0 @@
import { NgModule } from '@angular/core';
import { FuseSidebarComponent } from './sidebar.component';
@NgModule({
declarations: [
FuseSidebarComponent
],
exports : [
FuseSidebarComponent
]
})
export class FuseSidebarModule
{
}

View File

@@ -1,77 +0,0 @@
import { Injectable } from '@angular/core';
import { FuseSidebarComponent } from './sidebar.component';
@Injectable({
providedIn: 'root'
})
export class FuseSidebarService
{
// Private
private _registry: { [key: string]: FuseSidebarComponent } = {};
/**
* Constructor
*/
constructor()
{
}
/**
* Add the sidebar to the registry
*
* @param key
* @param sidebar
*/
register(key, sidebar): void
{
// Check if the key already being used
if ( this._registry[key] )
{
console.error(`The sidebar with the key '${key}' already exists. Either unregister it first or use a unique key.`);
return;
}
// Add to the registry
this._registry[key] = sidebar;
}
/**
* Remove the sidebar from the registry
*
* @param key
*/
unregister(key): void
{
// Check if the sidebar exists
if ( !this._registry[key] )
{
console.warn(`The sidebar with the key '${key}' doesn't exist in the registry.`);
}
// Unregister the sidebar
delete this._registry[key];
}
/**
* Return the sidebar with the given key
*
* @param key
* @returns {FuseSidebarComponent}
*/
getSidebar(key): FuseSidebarComponent
{
// Check if the sidebar exists
if ( !this._registry[key] )
{
console.warn(`The sidebar with the key '${key}' doesn't exist in the registry.`);
return;
}
// Return the sidebar
return this._registry[key];
}
}

View File

@@ -1,495 +0,0 @@
<div class="theme-options-panel" fusePerfectScrollbar>
<div class="header">
<span class="title">Theme Options</span>
<button mat-icon-button class="close-button" (click)="toggleSidebarOpen('themeOptionsPanel')">
<mat-icon>close</mat-icon>
</button>
</div>
<form [formGroup]="form">
<!-- LAYOUT STYLES -->
<div class="group" formGroupName="layout">
<h2>Layout Styles</h2>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="style">
<mat-radio-button class="mb-12" value="vertical-layout-1">
Vertical Layout #1
</mat-radio-button>
<mat-radio-button class="mb-12" value="vertical-layout-2">
Vertical Layout #2
</mat-radio-button>
<mat-radio-button class="mb-12" value="vertical-layout-3">
Vertical Layout #3
</mat-radio-button>
<mat-radio-button class="mb-12" value="horizontal-layout-1">
Horizontal Layout #1
</mat-radio-button>
</mat-radio-group>
<!-- DIFFERENT FORMS BASED ON LAYOUT STYLES -->
<ng-container [ngSwitch]="fuseConfig.layout.style">
<!-- VERTICAL LAYOUT #1 -->
<ng-container *ngSwitchCase="'vertical-layout-1'">
<!-- LAYOUT WIDTH -->
<div class="group mt-32">
<h2>Layout Width</h2>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="width">
<mat-radio-button class="mb-12" value="fullwidth">Fullwidth</mat-radio-button>
<mat-radio-button class="mb-12" value="boxed">Boxed</mat-radio-button>
</mat-radio-group>
</div>
<!-- NAVBAR -->
<div class="group" formGroupName="navbar">
<h2>Navbar</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<mat-slide-toggle class="mt-24" formControlName="folded">
Folded
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-16" value="left">Left</mat-radio-button>
<mat-radio-button class="mb-16" value="right">Right</mat-radio-button>
</mat-radio-group>
<h3 class="mt-8">Variant:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="variant">
<mat-radio-button class="mb-16" value="vertical-style-1">Style 1</mat-radio-button>
<mat-radio-button class="mb-16" value="vertical-style-2">Style 2</mat-radio-button>
</mat-radio-group>
<h3 class="mt-24 mb-8">Color:</h3>
<fuse-material-color-picker class="mb-16"
[(selectedClass)]="fuseConfig.layout.navbar.background">
</fuse-material-color-picker>
</div>
<!-- TOOLBAR -->
<div class="group" formGroupName="toolbar">
<h2>Toolbar</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-12" value="above">Above</mat-radio-button>
<mat-radio-button class="mb-12" value="below-static">Below Static</mat-radio-button>
<mat-radio-button class="mb-12" value="below-fixed">Below Fixed</mat-radio-button>
</mat-radio-group>
<h3 class="mt-24 mb-8">Color:</h3>
<fuse-material-color-picker class="mb-16"
[(selectedClass)]="fuseConfig.layout.toolbar.background">
</fuse-material-color-picker>
</div>
<!-- FOOTER -->
<div class="group" formGroupName="footer">
<h2>Footer</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-12" value="above">Above</mat-radio-button>
<mat-radio-button class="mb-12" value="below-static">Below Static</mat-radio-button>
<mat-radio-button class="mb-12" value="below-fixed">Below Fixed</mat-radio-button>
</mat-radio-group>
<h3 class="mt-24 mb-8">Color:</h3>
<fuse-material-color-picker class="mb-16"
[(selectedClass)]="fuseConfig.layout.footer.background">
</fuse-material-color-picker>
</div>
<!-- SIDE PANEL -->
<div class="group" formGroupName="sidepanel">
<h2>Side Panel</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-12" value="left">Left</mat-radio-button>
<mat-radio-button class="mb-12" value="right">Right</mat-radio-button>
</mat-radio-group>
</div>
</ng-container>
<!-- VERTICAL LAYOUT #2 -->
<ng-container *ngSwitchCase="'vertical-layout-2'">
<!-- LAYOUT WIDTH -->
<div class="group mt-32">
<h2>Layout Width</h2>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="width">
<mat-radio-button class="mb-12" value="fullwidth">Fullwidth</mat-radio-button>
<mat-radio-button class="mb-12" value="boxed">Boxed</mat-radio-button>
</mat-radio-group>
</div>
<!-- NAVBAR -->
<div class="group" formGroupName="navbar">
<h2>Navbar</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<mat-slide-toggle class="mt-24" formControlName="folded">
Folded
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-16" value="left">Left</mat-radio-button>
<mat-radio-button class="mb-16" value="right">Right</mat-radio-button>
</mat-radio-group>
<h3 class="mt-8">Variant:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="variant">
<mat-radio-button class="mb-16" value="vertical-style-1">Style 1</mat-radio-button>
<mat-radio-button class="mb-16" value="vertical-style-2">Style 2</mat-radio-button>
</mat-radio-group>
<h3 class="mt-24 mb-8">Color:</h3>
<fuse-material-color-picker class="mb-16"
[(selectedClass)]="fuseConfig.layout.navbar.background">
</fuse-material-color-picker>
</div>
<!-- TOOLBAR -->
<div class="group" formGroupName="toolbar">
<h2>Toolbar</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-12" value="above-static">Above Static</mat-radio-button>
<mat-radio-button class="mb-12" value="above-fixed">Above Fixed</mat-radio-button>
<mat-radio-button class="mb-12" value="below">Below</mat-radio-button>
</mat-radio-group>
<h3 class="mt-24 mb-8">Color:</h3>
<fuse-material-color-picker class="mb-16"
[(selectedClass)]="fuseConfig.layout.toolbar.background">
</fuse-material-color-picker>
</div>
<!-- FOOTER -->
<div class="group" formGroupName="footer">
<h2>Footer</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-12" value="above-static">Above Static</mat-radio-button>
<mat-radio-button class="mb-12" value="above-fixed">Above Fixed</mat-radio-button>
<mat-radio-button class="mb-12" value="below">Below</mat-radio-button>
</mat-radio-group>
<h3 class="mt-24 mb-8">Color:</h3>
<fuse-material-color-picker class="mb-16"
[(selectedClass)]="fuseConfig.layout.footer.background">
</fuse-material-color-picker>
</div>
<!-- SIDE PANEL -->
<div class="group" formGroupName="sidepanel">
<h2>Side Panel</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-12" value="left">Left</mat-radio-button>
<mat-radio-button class="mb-12" value="right">Right</mat-radio-button>
</mat-radio-group>
</div>
</ng-container>
<!-- VERTICAL LAYOUT #3 -->
<ng-container *ngSwitchCase="'vertical-layout-3'">
<!-- LAYOUT WIDTH -->
<div class="group mt-32">
<h2>Layout Width</h2>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="width">
<mat-radio-button class="mb-12" value="fullwidth">Fullwidth</mat-radio-button>
<mat-radio-button class="mb-12" value="boxed">Boxed</mat-radio-button>
</mat-radio-group>
</div>
<!-- NAVBAR -->
<div class="group" formGroupName="navbar">
<h2>Navbar</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<mat-slide-toggle class="mt-24" formControlName="folded">
Folded
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-16" value="left">Left</mat-radio-button>
<mat-radio-button class="mb-16" value="right">Right</mat-radio-button>
</mat-radio-group>
<h3 class="mt-8">Variant:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="variant">
<mat-radio-button class="mb-16" value="vertical-style-1">Style 1</mat-radio-button>
<mat-radio-button class="mb-16" value="vertical-style-2">Style 2</mat-radio-button>
</mat-radio-group>
<h3 class="mt-24 mb-8">Color:</h3>
<fuse-material-color-picker class="mb-16"
[(selectedClass)]="fuseConfig.layout.navbar.background">
</fuse-material-color-picker>
</div>
<!-- TOOLBAR -->
<div class="group" formGroupName="toolbar">
<h2>Toolbar</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-12" value="above-static">Above Static</mat-radio-button>
<mat-radio-button class="mb-12" value="above-fixed">Above Fixed</mat-radio-button>
</mat-radio-group>
<h3 class="mt-24 mb-8">Color:</h3>
<fuse-material-color-picker class="mb-16"
[(selectedClass)]="fuseConfig.layout.toolbar.background">
</fuse-material-color-picker>
</div>
<!-- FOOTER -->
<div class="group" formGroupName="footer">
<h2>Footer</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-12" value="above-static">Above Static</mat-radio-button>
<mat-radio-button class="mb-12" value="above-fixed">Above Fixed</mat-radio-button>
</mat-radio-group>
<h3 class="mt-24 mb-8">Color:</h3>
<fuse-material-color-picker class="mb-16"
[(selectedClass)]="fuseConfig.layout.footer.background">
</fuse-material-color-picker>
</div>
<!-- SIDE PANEL -->
<div class="group" formGroupName="sidepanel">
<h2>Side Panel</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-12" value="left">Left</mat-radio-button>
<mat-radio-button class="mb-12" value="right">Right</mat-radio-button>
</mat-radio-group>
</div>
</ng-container>
<!-- HORIZONTAL LAYOUT #1 -->
<ng-container *ngSwitchCase="'horizontal-layout-1'">
<!-- LAYOUT WIDTH -->
<div class="group mt-32">
<h2>Layout Width</h2>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="width">
<mat-radio-button class="mb-12" value="fullwidth">Fullwidth</mat-radio-button>
<mat-radio-button class="mb-12" value="boxed">Boxed</mat-radio-button>
</mat-radio-group>
</div>
<!-- NAVBAR -->
<div class="group" formGroupName="navbar">
<h2>Navbar</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-16" value="top">Top</mat-radio-button>
</mat-radio-group>
<h3 class="mt-8">Variant (Vertical):</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="variant">
<mat-radio-button class="mb-16" value="vertical-style-1">Style 1</mat-radio-button>
<mat-radio-button class="mb-16" value="vertical-style-2">Style 2</mat-radio-button>
</mat-radio-group>
<h3 class="mt-24 mb-8">Color:</h3>
<fuse-material-color-picker class="mb-16"
[(selectedClass)]="fuseConfig.layout.navbar.background">
</fuse-material-color-picker>
</div>
<!-- TOOLBAR -->
<div class="group" formGroupName="toolbar">
<h2>Toolbar</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-12" value="above">Above</mat-radio-button>
<mat-radio-button class="mb-12" value="below">Below</mat-radio-button>
</mat-radio-group>
<h3 class="mt-24 mb-8">Color:</h3>
<fuse-material-color-picker class="mb-16"
[(selectedClass)]="fuseConfig.layout.toolbar.background">
</fuse-material-color-picker>
</div>
<!-- FOOTER -->
<div class="group" formGroupName="footer">
<h2>Footer</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-12" value="above-fixed">Above Fixed</mat-radio-button>
<mat-radio-button class="mb-12" value="above-static">Above Static</mat-radio-button>
</mat-radio-group>
<h3 class="mt-24 mb-8">Color:</h3>
<fuse-material-color-picker class="mb-16"
[(selectedClass)]="fuseConfig.layout.footer.background">
</fuse-material-color-picker>
</div>
<!-- SIDE PANEL -->
<div class="group" formGroupName="sidepanel">
<h2>Side Panel</h2>
<mat-slide-toggle formControlName="hidden">
Hide
</mat-slide-toggle>
<h3 class="mt-24">Position:</h3>
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="position">
<mat-radio-button class="mb-12" value="left">Left</mat-radio-button>
<mat-radio-button class="mb-12" value="right">Right</mat-radio-button>
</mat-radio-group>
</div>
</ng-container>
</ng-container>
</div>
<!-- CUSTOM SCROLLBARS -->
<div class="group">
<h2>Custom scrollbars</h2>
<mat-slide-toggle class="mb-12" formControlName="customScrollbars">
Enable custom scrollbars
</mat-slide-toggle>
</div>
</form>
</div>

View File

@@ -1,78 +0,0 @@
@import "src/@fuse/scss/fuse";
@keyframes rotating {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
:host {
display: flex;
overflow: hidden;
.theme-options-panel {
display: flex;
flex-direction: column;
flex: 1 0 auto;
padding: 40px 24px 24px 24px;
overflow: auto;
.header {
display: flex;
flex: 0 1 auto;
margin-bottom: 32px;
align-items: center;
justify-content: space-between;
.title {
font-size: 20px;
font-weight: 500;
padding-left: 4px;
}
}
form {
display: flex;
flex: 1 1 auto;
flex-direction: column;
.group {
display: flex;
flex: 1 0 auto;
flex-direction: column;
position: relative;
border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 2px;
padding: 28px 16px 8px 16px;
margin: 16px 0;
h2 {
position: absolute;
top: -11px;
left: 8px;
margin: 0;
padding: 0 8px;
font-size: 16px;
font-weight: 500;
background: white;
color: rgba(0, 0, 0, 0.54);
}
h3 {
font-size: 14px;
font-weight: 500;
color: rgba(0, 0, 0, 0.54);
margin: 24px 0 16px 0;
padding: 0;
&:first-of-type {
margin-top: 0;
}
}
}
}
}
}

View File

@@ -1,307 +0,0 @@
import { Component, HostBinding, OnDestroy, OnInit, Renderer2 } from '@angular/core';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseConfigService } from '@fuse/services/config.service';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { FuseSidebarService } from '@fuse/components/sidebar/sidebar.service';
@Component({
selector : 'fuse-theme-options',
templateUrl: './theme-options.component.html',
styleUrls : ['./theme-options.component.scss'],
animations : fuseAnimations
})
export class FuseThemeOptionsComponent implements OnInit, OnDestroy
{
fuseConfig: any;
form: FormGroup;
@HostBinding('class.bar-closed')
barClosed: boolean;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {FormBuilder} _formBuilder
* @param {FuseConfigService} _fuseConfigService
* @param {FuseNavigationService} _fuseNavigationService
* @param {FuseSidebarService} _fuseSidebarService
* @param {Renderer2} _renderer
*/
constructor(
private _formBuilder: FormBuilder,
private _fuseConfigService: FuseConfigService,
private _fuseNavigationService: FuseNavigationService,
private _fuseSidebarService: FuseSidebarService,
private _renderer: Renderer2
)
{
// Set the defaults
this.barClosed = true;
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Build the config form
// noinspection TypeScriptValidateTypes
this.form = this._formBuilder.group({
layout : this._formBuilder.group({
style : new FormControl(),
width : new FormControl(),
navbar : this._formBuilder.group({
background: new FormControl(),
folded : new FormControl(),
hidden : new FormControl(),
position : new FormControl(),
variant : new FormControl()
}),
toolbar : this._formBuilder.group({
background: new FormControl(),
hidden : new FormControl(),
position : new FormControl()
}),
footer : this._formBuilder.group({
background: new FormControl(),
hidden : new FormControl(),
position : new FormControl()
}),
sidepanel: this._formBuilder.group({
hidden: new FormControl(),
position : new FormControl()
})
}),
customScrollbars: new FormControl()
});
// Subscribe to the config changes
this._fuseConfigService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
// Update the stored config
this.fuseConfig = config;
// Set the config form values without emitting an event
// so that we don't end up with an infinite loop
this.form.setValue(config, {emitEvent: false});
});
// Subscribe to the specific form value changes (layout.style)
this.form.get('layout.style').valueChanges
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((value) => {
// Reset the form values based on the
// selected layout style
this._resetFormValues(value);
});
// Subscribe to the form value changes
this.form.valueChanges
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
// Update the config
this._fuseConfigService.config = config;
});
// Add customize nav item that opens the bar programmatically
const customFunctionNavItem = {
'id' : 'custom-function',
'title' : 'Custom Function',
'type' : 'group',
'icon' : 'settings',
'children': [
{
'id' : 'customize',
'title' : 'Customize',
'type' : 'item',
'icon' : 'settings',
'function': () => {
this.toggleSidebarOpen('themeOptionsPanel');
}
}
]
};
this._fuseNavigationService.addNavigationItem(customFunctionNavItem, 'end');
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
// Remove the custom function menu
this._fuseNavigationService.removeNavigationItem('custom-function');
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Reset the form values based on the
* selected layout style
*
* @param value
* @private
*/
private _resetFormValues(value): void
{
switch ( value )
{
// Vertical Layout #1
case 'vertical-layout-1':
{
this.form.patchValue({
layout: {
width : 'fullwidth',
navbar : {
background: 'mat-fuse-dark-700-bg',
folded : false,
hidden : false,
position : 'left',
variant : 'vertical-style-1'
},
toolbar: {
background: 'mat-white-500-bg',
hidden : false,
position : 'below-static'
},
footer : {
background: 'mat-fuse-dark-900-bg',
hidden : false,
position : 'below-static'
}
}
});
break;
}
// Vertical Layout #2
case 'vertical-layout-2':
{
this.form.patchValue({
layout: {
width : 'fullwidth',
navbar : {
background: 'mat-fuse-dark-700-bg',
folded : false,
hidden : false,
position : 'left',
variant : 'vertical-style-1'
},
toolbar: {
background: 'mat-white-500-bg',
hidden : false,
position : 'below'
},
footer : {
background: 'mat-fuse-dark-900-bg',
hidden : false,
position : 'below'
}
}
});
break;
}
// Vertical Layout #3
case 'vertical-layout-3':
{
this.form.patchValue({
layout: {
width : 'fullwidth',
navbar : {
background: 'mat-fuse-dark-700-bg',
folded : false,
hidden : false,
position : 'left',
layout : 'vertical-style-1'
},
toolbar: {
background: 'mat-white-500-bg',
hidden : false,
position : 'above-static'
},
footer : {
background: 'mat-fuse-dark-900-bg',
hidden : false,
position : 'above-static'
}
}
});
break;
}
// Horizontal Layout #1
case 'horizontal-layout-1':
{
this.form.patchValue({
layout: {
width : 'fullwidth',
navbar : {
background: 'mat-fuse-dark-700-bg',
folded : false,
hidden : false,
position : 'top',
variant : 'vertical-style-1'
},
toolbar: {
background: 'mat-white-500-bg',
hidden : false,
position : 'above'
},
footer : {
background: 'mat-fuse-dark-900-bg',
hidden : false,
position : 'above-fixed'
}
}
});
break;
}
}
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle sidebar open
*
* @param key
*/
toggleSidebarOpen(key): void
{
this._fuseSidebarService.getSidebar(key).toggleOpen();
}
}

View File

@@ -1,43 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatButtonModule, MatDividerModule, MatFormFieldModule, MatIconModule, MatOptionModule, MatRadioModule, MatSelectModule, MatSlideToggleModule } from '@angular/material';
import { FuseDirectivesModule } from '@fuse/directives/directives';
import { FuseSidebarModule } from '@fuse/components/sidebar/sidebar.module';
import { FuseMaterialColorPickerModule } from '@fuse/components/material-color-picker/material-color-picker.module';
import { FuseThemeOptionsComponent } from '@fuse/components/theme-options/theme-options.component';
@NgModule({
declarations: [
FuseThemeOptionsComponent
],
imports : [
CommonModule,
FormsModule,
ReactiveFormsModule,
FlexLayoutModule,
MatButtonModule,
MatDividerModule,
MatFormFieldModule,
MatIconModule,
MatOptionModule,
MatRadioModule,
MatSelectModule,
MatSlideToggleModule,
FuseDirectivesModule,
FuseMaterialColorPickerModule,
FuseSidebarModule
],
exports : [
FuseThemeOptionsComponent
]
})
export class FuseThemeOptionsModule
{
}

View File

@@ -1,18 +0,0 @@
import { Directive, ElementRef } from '@angular/core';
@Directive({
selector: '[fuseWidgetToggle]'
})
export class FuseWidgetToggleDirective
{
/**
* Constructor
*
* @param {ElementRef} elementRef
*/
constructor(
public elementRef: ElementRef
)
{
}
}

View File

@@ -1,65 +0,0 @@
import { AfterContentInit, Component, ContentChildren, ElementRef, HostBinding, QueryList, Renderer2, ViewEncapsulation } from '@angular/core';
import { FuseWidgetToggleDirective } from './widget-toggle.directive';
@Component({
selector : 'fuse-widget',
templateUrl : './widget.component.html',
styleUrls : ['./widget.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class FuseWidgetComponent implements AfterContentInit
{
@HostBinding('class.flipped')
flipped = false;
@ContentChildren(FuseWidgetToggleDirective, {descendants: true})
toggleButtons: QueryList<FuseWidgetToggleDirective>;
/**
* Constructor
*
* @param {ElementRef} _elementRef
* @param {Renderer2} _renderer
*/
constructor(
private _elementRef: ElementRef,
private _renderer: Renderer2
)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* After content init
*/
ngAfterContentInit(): void
{
// Listen for the flip button click
setTimeout(() => {
this.toggleButtons.forEach(flipButton => {
this._renderer.listen(flipButton.elementRef.nativeElement, 'click', (event) => {
event.preventDefault();
event.stopPropagation();
this.toggle();
});
});
});
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle the flipped status
*/
toggle(): void
{
this.flipped = !this.flipped;
}
}

View File

@@ -1,27 +0,0 @@
import { NgModule } from '@angular/core';
import { FuseIfOnDomDirective } from '@fuse/directives/fuse-if-on-dom/fuse-if-on-dom.directive';
import { FuseInnerScrollDirective } from '@fuse/directives/fuse-inner-scroll/fuse-inner-scroll.directive';
import { FusePerfectScrollbarDirective } from '@fuse/directives/fuse-perfect-scrollbar/fuse-perfect-scrollbar.directive';
import { FuseMatSidenavHelperDirective, FuseMatSidenavTogglerDirective } from '@fuse/directives/fuse-mat-sidenav/fuse-mat-sidenav.directive';
@NgModule({
declarations: [
FuseIfOnDomDirective,
FuseInnerScrollDirective,
FuseMatSidenavHelperDirective,
FuseMatSidenavTogglerDirective,
FusePerfectScrollbarDirective
],
imports : [],
exports : [
FuseIfOnDomDirective,
FuseInnerScrollDirective,
FuseMatSidenavHelperDirective,
FuseMatSidenavTogglerDirective,
FusePerfectScrollbarDirective
]
})
export class FuseDirectivesModule
{
}

View File

@@ -1,49 +0,0 @@
import { AfterContentChecked, Directive, ElementRef, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[fuseIfOnDom]'
})
export class FuseIfOnDomDirective implements AfterContentChecked
{
isCreated: boolean;
/**
* Constructor
*
* @param {ElementRef} _elementRef
* @param {TemplateRef<any>} _templateRef
* @param {ViewContainerRef} _viewContainerRef
*/
constructor(
private _elementRef: ElementRef,
private _templateRef: TemplateRef<any>,
private _viewContainerRef: ViewContainerRef
)
{
// Set the defaults
this.isCreated = false;
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* After content checked
*/
ngAfterContentChecked(): void
{
if ( document.body.contains(this._elementRef.nativeElement) && !this.isCreated )
{
setTimeout(() => {
this._viewContainerRef.createEmbeddedView(this._templateRef);
}, 300);
this.isCreated = true;
}
else if ( this.isCreated && !document.body.contains(this._elementRef.nativeElement) )
{
this._viewContainerRef.clear();
this.isCreated = false;
}
}
}

View File

@@ -1,115 +0,0 @@
import { Directive, ElementRef, OnDestroy, OnInit, Renderer2 } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FuseMatchMediaService } from '@fuse/services/match-media.service';
@Directive({
selector: '.inner-scroll'
})
export class FuseInnerScrollDirective implements OnInit, OnDestroy
{
// Private
private _parent: any;
private _grandParent: any;
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ElementRef} _elementRef
* @param {FuseMatchMediaService} _fuseMediaMatchService
* @param {Renderer2} _renderer
*/
constructor(
private _elementRef: ElementRef,
private _fuseMediaMatchService: FuseMatchMediaService,
private _renderer: Renderer2
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Get the parent
this._parent = this._renderer.parentNode(this._elementRef.nativeElement);
// Return, if there is no parent
if ( !this._parent )
{
return;
}
// Get the grand parent
this._grandParent = this._renderer.parentNode(this._parent);
// Register to the media query changes
this._fuseMediaMatchService.onMediaChange
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((alias) => {
if ( alias === 'xs' )
{
this._removeClass();
}
else
{
this._addClass();
}
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Return, if there is no parent
if ( !this._parent )
{
return;
}
// Remove the class
this._removeClass();
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Add the class name
*
* @private
*/
private _addClass(): void
{
// Add the inner-scroll class
this._renderer.addClass(this._grandParent, 'inner-scroll');
}
/**
* Remove the class name
* @private
*/
private _removeClass(): void
{
// Remove the inner-scroll class
this._renderer.removeClass(this._grandParent, 'inner-scroll');
}
}

View File

@@ -1,133 +0,0 @@
import { Directive, Input, OnInit, HostListener, OnDestroy, HostBinding } from '@angular/core';
import { MatSidenav } from '@angular/material';
import { ObservableMedia } from '@angular/flex-layout';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FuseMatchMediaService } from '@fuse/services/match-media.service';
import { FuseMatSidenavHelperService } from '@fuse/directives/fuse-mat-sidenav/fuse-mat-sidenav.service';
@Directive({
selector: '[fuseMatSidenavHelper]'
})
export class FuseMatSidenavHelperDirective implements OnInit, OnDestroy
{
@HostBinding('class.mat-is-locked-open')
isLockedOpen: boolean;
@Input('fuseMatSidenavHelper')
id: string;
@Input('mat-is-locked-open')
matIsLockedOpenBreakpoint: string;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {FuseMatchMediaService} _fuseMatchMediaService
* @param {FuseMatSidenavHelperService} _fuseMatSidenavHelperService
* @param {MatSidenav} _matSidenav
* @param {ObservableMedia} _observableMedia
*/
constructor(
private _fuseMatchMediaService: FuseMatchMediaService,
private _fuseMatSidenavHelperService: FuseMatSidenavHelperService,
private _matSidenav: MatSidenav,
private _observableMedia: ObservableMedia
)
{
// Set the defaults
this.isLockedOpen = true;
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Register the sidenav to the service
this._fuseMatSidenavHelperService.setSidenav(this.id, this._matSidenav);
if ( this._observableMedia.isActive(this.matIsLockedOpenBreakpoint) )
{
this.isLockedOpen = true;
this._matSidenav.mode = 'side';
this._matSidenav.toggle(true);
}
else
{
this.isLockedOpen = false;
this._matSidenav.mode = 'over';
this._matSidenav.toggle(false);
}
this._fuseMatchMediaService.onMediaChange
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
if ( this._observableMedia.isActive(this.matIsLockedOpenBreakpoint) )
{
this.isLockedOpen = true;
this._matSidenav.mode = 'side';
this._matSidenav.toggle(true);
}
else
{
this.isLockedOpen = false;
this._matSidenav.mode = 'over';
this._matSidenav.toggle(false);
}
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}
@Directive({
selector: '[fuseMatSidenavToggler]'
})
export class FuseMatSidenavTogglerDirective
{
@Input('fuseMatSidenavToggler')
id;
/**
* Constructor
*
* @param {FuseMatSidenavHelperService} _fuseMatSidenavHelperService
*/
constructor(
private _fuseMatSidenavHelperService: FuseMatSidenavHelperService)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* On click
*/
@HostListener('click')
onClick()
{
this._fuseMatSidenavHelperService.getSidenav(this.id).toggle();
}
}

View File

@@ -1,44 +0,0 @@
import { Injectable } from '@angular/core';
import { MatSidenav } from '@angular/material';
@Injectable({
providedIn: 'root'
})
export class FuseMatSidenavHelperService
{
sidenavInstances: MatSidenav[];
/**
* Constructor
*/
constructor()
{
this.sidenavInstances = [];
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Set sidenav
*
* @param id
* @param instance
*/
setSidenav(id, instance): void
{
this.sidenavInstances[id] = instance;
}
/**
* Get sidenav
*
* @param id
* @returns {any}
*/
getSidenav(id): any
{
return this.sidenavInstances[id];
}
}

View File

@@ -1,410 +0,0 @@
import { AfterViewInit, Directive, ElementRef, HostListener, Input, OnDestroy } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { Platform } from '@angular/cdk/platform';
import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';
import PerfectScrollbar from 'perfect-scrollbar';
import * as _ from 'lodash';
import { FuseConfigService } from '@fuse/services/config.service';
@Directive({
selector: '[fusePerfectScrollbar]'
})
export class FusePerfectScrollbarDirective implements AfterViewInit, OnDestroy
{
isInitialized: boolean;
isMobile: boolean;
ps: PerfectScrollbar;
// Private
private _enabled: boolean | '';
private _debouncedUpdate: any;
private _options: any;
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ElementRef} elementRef
* @param {FuseConfigService} _fuseConfigService
* @param {Platform} _platform
* @param {Router} _router
*/
constructor(
public elementRef: ElementRef,
private _fuseConfigService: FuseConfigService,
private _platform: Platform,
private _router: Router
)
{
// Set the defaults
this.isInitialized = false;
this.isMobile = false;
// Set the private defaults
this._enabled = false;
this._debouncedUpdate = _.debounce(this.update, 150);
this._options = {
updateOnRouteChange: false
};
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Perfect Scrollbar options
*
* @param value
*/
@Input()
set fusePerfectScrollbarOptions(value)
{
// Merge the options
this._options = _.merge({}, this._options, value);
}
get fusePerfectScrollbarOptions(): any
{
// Return the options
return this._options;
}
/**
* Is enabled
*
* @param {boolean | ""} value
*/
@Input('fusePerfectScrollbar')
set enabled(value: boolean | '')
{
// If nothing is provided with the directive (empty string),
// we will take that as a true
if ( value === '' )
{
value = true;
}
// Return, if both values are the same
if ( this.enabled === value )
{
return;
}
// Store the value
this._enabled = value;
// If enabled...
if ( this.enabled )
{
// Init the directive
this._init();
}
else
{
// Otherwise destroy it
this._destroy();
}
}
get enabled(): boolean | ''
{
// Return the enabled status
return this._enabled;
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* After view init
*/
ngAfterViewInit(): void
{
// Check if scrollbars enabled or not from the main config
this._fuseConfigService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(
(settings) => {
this.enabled = settings.customScrollbars;
}
);
// Scroll to the top on every route change
if ( this.fusePerfectScrollbarOptions.updateOnRouteChange )
{
this._router.events
.pipe(
takeUntil(this._unsubscribeAll),
filter(event => event instanceof NavigationEnd)
)
.subscribe(() => {
setTimeout(() => {
this.scrollToTop();
this.update();
}, 0);
});
}
}
/**
* On destroy
*/
ngOnDestroy(): void
{
this._destroy();
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Initialize
*
* @private
*/
_init(): void
{
// Return, if already initialized
if ( this.isInitialized )
{
return;
}
// Check if is mobile
if ( this._platform.ANDROID || this._platform.IOS )
{
this.isMobile = true;
}
// Return if it's mobile
if ( this.isMobile )
{
// Return...
return;
}
// Set as initialized
this.isInitialized = true;
// Initialize the perfect-scrollbar
this.ps = new PerfectScrollbar(this.elementRef.nativeElement, {
...this.fusePerfectScrollbarOptions
});
}
/**
* Destroy
*
* @private
*/
_destroy(): void
{
if ( !this.isInitialized || !this.ps )
{
return;
}
// Destroy the perfect-scrollbar
this.ps.destroy();
// Clean up
this.ps = null;
this.isInitialized = false;
}
/**
* Update scrollbars on window resize
*
* @private
*/
@HostListener('window:resize')
_updateOnResize(): void
{
this._debouncedUpdate();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Document click
*
* @param {Event} event
*/
@HostListener('document:click', ['$event'])
documentClick(event: Event): void
{
if ( !this.isInitialized || !this.ps )
{
return;
}
// Update the scrollbar on document click..
// This isn't the most elegant solution but there is no other way
// of knowing when the contents of the scrollable container changes.
// Therefore, we update scrollbars on every document click.
this.ps.update();
}
/**
* Update the scrollbar
*/
update(): void
{
if ( !this.isInitialized )
{
return;
}
// Update the perfect-scrollbar
this.ps.update();
}
/**
* Destroy the scrollbar
*/
destroy(): void
{
this.ngOnDestroy();
}
/**
* Scroll to X
*
* @param {number} x
* @param {number} speed
*/
scrollToX(x: number, speed?: number): void
{
this.animateScrolling('scrollLeft', x, speed);
}
/**
* Scroll to Y
*
* @param {number} y
* @param {number} speed
*/
scrollToY(y: number, speed?: number): void
{
this.animateScrolling('scrollTop', y, speed);
}
/**
* Scroll to top
*
* @param {number} offset
* @param {number} speed
*/
scrollToTop(offset?: number, speed?: number): void
{
this.animateScrolling('scrollTop', (offset || 0), speed);
}
/**
* Scroll to left
*
* @param {number} offset
* @param {number} speed
*/
scrollToLeft(offset?: number, speed?: number): void
{
this.animateScrolling('scrollLeft', (offset || 0), speed);
}
/**
* Scroll to right
*
* @param {number} offset
* @param {number} speed
*/
scrollToRight(offset?: number, speed?: number): void
{
const width = this.elementRef.nativeElement.scrollWidth;
this.animateScrolling('scrollLeft', width - (offset || 0), speed);
}
/**
* Scroll to bottom
*
* @param {number} offset
* @param {number} speed
*/
scrollToBottom(offset?: number, speed?: number): void
{
const height = this.elementRef.nativeElement.scrollHeight;
this.animateScrolling('scrollTop', height - (offset || 0), speed);
}
/**
* Animate scrolling
*
* @param {string} target
* @param {number} value
* @param {number} speed
*/
animateScrolling(target: string, value: number, speed?: number): void
{
if ( !speed )
{
this.elementRef.nativeElement[target] = value;
// PS has weird event sending order, this is a workaround for that
this.update();
this.update();
}
else if ( value !== this.elementRef.nativeElement[target] )
{
let newValue = 0;
let scrollCount = 0;
let oldTimestamp = performance.now();
let oldValue = this.elementRef.nativeElement[target];
const cosParameter = (oldValue - value) / 2;
const step = (newTimestamp) => {
scrollCount += Math.PI / (speed / (newTimestamp - oldTimestamp));
newValue = Math.round(value + cosParameter + cosParameter * Math.cos(scrollCount));
// Only continue animation if scroll position has not changed
if ( this.elementRef.nativeElement[target] === oldValue )
{
if ( scrollCount >= Math.PI )
{
this.elementRef.nativeElement[target] = value;
// PS has weird event sending order, this is a workaround for that
this.update();
this.update();
}
else
{
this.elementRef.nativeElement[target] = oldValue = newValue;
oldTimestamp = newTimestamp;
window.requestAnimationFrame(step);
}
}
};
window.requestAnimationFrame(step);
}
}
}

View File

@@ -1,28 +0,0 @@
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
import { FUSE_CONFIG } from '@fuse/services/config.service';
@NgModule()
export class FuseModule
{
constructor(@Optional() @SkipSelf() parentModule: FuseModule)
{
if ( parentModule )
{
throw new Error('FuseModule is already loaded. Import it in the AppModule only!');
}
}
static forRoot(config): ModuleWithProviders
{
return {
ngModule : FuseModule,
providers: [
{
provide : FUSE_CONFIG,
useValue: config
}
]
};
}
}

View File

@@ -1,5 +0,0 @@
// Material theming
@import "theming";
// Breakpoint mixins
@import "mixins/breakpoints";

View File

@@ -1,92 +0,0 @@
// Fix: "Icon button ripple radius is not correct on Edge & Safari"
.mat-icon-button {
.mat-button-ripple {
border-radius: 50%;
}
}
// Fix: "Inconsistent font sizes across elements"
.mat-form-field-wrapper {
font-size: 16px;
}
.mat-checkbox {
font-size: 16px;
}
.mat-radio-button {
font-size: 16px;
}
.mat-pseudo-checkbox-checked:after {
width: 14px !important;
height: 7px !important;
}
// Fix: "Input underlines has wrong color opacity value"
.mat-form-field-underline {
background-color: rgba(0, 0, 0, 0.12);
}
// Fix: "Some idiots using table-cell and inline-table in mat-select"
.mat-form-field {
&.mat-form-field-type-mat-select {
.mat-form-field-infix {
display: inline-flex;
width: auto;
.mat-select-trigger {
display: inline-flex;
align-items: center;
width: 100%;
.mat-select-value {
display: flex;
max-width: none;
margin-right: 8px;
}
.mat-select-arrow-wrapper {
display: inline-flex;
}
}
}
}
}
// Fix: Stepper icons are broken due to Fuse's icon helpers
mat-horizontal-stepper,
mat-vertical-stepper {
mat-step-header {
mat-icon {
height: 16px !important;
width: 16px !important;
min-width: 0 !important;
min-height: 0 !important;
color: inherit !important;
}
}
}
mat-vertical-stepper {
padding: 16px 0;
}
// Fix: Chip remove icon is broken due to Fuse's icon helpers
mat-chip {
mat-icon {
min-width: 0 !important;
min-height: 0 !important;
}
}
// Fix: Mat-card-image requires a bigger width than 100%
.mat-card-image {
max-width: none !important;
}

View File

@@ -1,61 +0,0 @@
.fuse-card {
max-width: 320px;
min-width: 320px;
background: white;
border-radius: 2px;
@include mat-elevation(2);
&.variable-width {
min-width: 0;
}
&.auto-width {
min-width: 0;
max-width: none;
}
// Buttons
.mat-button {
min-width: 0 !important;
padding: 0 8px !important;
}
// Button Toggle Group
.mat-button-toggle-group,
.mat-button-toggle-standalone {
box-shadow: none !important;
}
// Tabs
.mat-tab-labels {
justify-content: center;
}
.mat-tab-label {
min-width: 0 !important;
}
// Divider
.card-divider {
border-top: 1px solid rgba(0, 0, 0, 0.12);
margin: 16px;
&.light {
border-top-color: rgba(255, 255, 255, 0.12);
}
&.full-width {
margin: 0;
}
}
// Expand Area
.card-expand-area {
overflow: hidden;
.card-expanded-content {
padding: 8px 16px 16px 16px;
line-height: 1.75;
}
}
}

View File

@@ -1,358 +0,0 @@
.secondary-text,
.icon,
i {
color: rgba(0, 0, 0, 0.54);
}
.hint-text,
.disabled-text {
color: rgba(0, 0, 0, 0.38);
}
.divider {
color: rgba(0, 0, 0, 0.12);
}
// Material colors map
$matPalettes: (
primary: $primary,
accent: $accent,
warn: $warn,
red: $mat-red,
pink: $mat-pink,
purple: $mat-purple,
deep-purple: $mat-deep-purple,
indigo: $mat-indigo,
blue: $mat-blue,
light-blue: $mat-light-blue,
cyan: $mat-cyan,
teal: $mat-teal,
green: $mat-green,
light-green: $mat-light-green,
lime: $mat-lime,
yellow: $mat-yellow,
amber: $mat-amber,
orange: $mat-orange,
deep-orange: $mat-deep-orange,
brown: $mat-brown,
grey: $mat-grey,
blue-grey: $mat-blue-grey,
white: $mat-white,
black: $mat-black,
fuse-dark: $mat-fusedark
);
// Material color hues list
$matHues: 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, A100, A200, A400, A700;
// Text color levels generator mixin
@mixin generateTextColorLevels($classes, $contrast) {
// If the contrast is dark...
@if ($contrast == 'dark') {
// Put down the color classes
#{$classes} {
i,
.icon {
color: rgba(0, 0, 0, 0.54);
}
&.secondary-text,
.secondary-text {
color: rgba(0, 0, 0, 0.54) !important;
}
&.hint-text,
.hint-text,
&.disabled-text,
.disabled-text {
color: rgba(0, 0, 0, 0.38) !important;
}
&.divider,
.divider {
color: rgba(0, 0, 0, 0.12) !important;
}
.mat-ripple-element {
background: rgba(0, 0, 0, 0.1);
}
.adaptive-border-color {
border-color: rgba(0, 0, 0, 0.12);
}
}
}
// If the base text color is white...
@else {
// Put down the color classes
#{$classes} {
i,
.icon {
color: rgba(255, 255, 255, 1);
}
&.secondary-text,
.secondary-text {
color: rgba(255, 255, 255, 0.70) !important;
}
&.hint-text,
.hint-text,
&.disabled-text,
.disabled-text {
color: rgba(255, 255, 255, 0.50) !important;
}
&.divider,
.divider {
color: rgba(255, 255, 255, 0.12) !important;
}
.mat-ripple-element {
background: rgba(255, 255, 255, 0.1);
}
.adaptive-border-color {
border-color: rgba(255, 255, 255, 0.12);
}
}
}
}
@mixin generateMaterialElementColors($classes, $contrast) {
// If the contrast color is light...
$fuseForeground: (
base: white,
text: white,
hint-text: rgba(white, 0.5),
divider: rgba(white, 0.12),
);
// If the contrast color is dark...
@if ($contrast == 'dark') {
$fuseForeground: (
base: black,
hint-text: rgba(black, 0.38),
divider: rgba(black, 0.12),
);
}
// Put down the color classes
#{$classes} {
// Native Input
input[type="text"] {
color: map_get($fuseForeground, base);
}
// Input
.mat-form-field-label {
color: map_get($fuseForeground, hint-text);
}
.mat-form-field-underline {
background-color: map_get($fuseForeground, divider);
}
// Select
.mat-select-trigger,
.mat-select-arrow {
color: map_get($fuseForeground, hint-text);
}
.mat-select-underline {
background-color: map_get($fuseForeground, divider);
}
.mat-select-disabled .mat-select-value,
.mat-select-arrow,
.mat-select-trigger {
color: map_get($fuseForeground, hint-text);
}
.mat-select-content,
.mat-select-panel-done-animating {
background: map_get($background, card);
}
.mat-select-value {
color: map_get($fuseForeground, text);
}
}
}
// Color classes generator mixin
@mixin generateColorClasses($colorName, $color, $contrastColor, $hue) {
.#{$colorName}#{$hue}-bg {
background-color: $color !important;
}
.mat-#{$colorName}#{$hue}-bg {
background-color: $color !important;
color: $contrastColor !important;
&[disabled] {
background-color: rgba($color, .12) !important;
color: rgba($contrastColor, .26) !important;
}
}
.#{$colorName}#{$hue}-fg {
color: $color !important;
}
.#{$colorName}#{$hue}-border {
border-color: $color !important;
}
.#{$colorName}#{$hue}-border-top {
border-top-color: $color !important;
}
.#{$colorName}#{$hue}-border-right {
border-right-color: $color !important;
}
.#{$colorName}#{$hue}-border-bottom {
border-bottom-color: $color !important;
}
.#{$colorName}#{$hue}-border-left {
border-left-color: $color !important;
}
}
@mixin generateFuseColorClasses($primary, $accent, $warn) {
$palettes: (
primary: $primary,
accent: $accent,
warn: $warn
);
// Define contrast lists
$light-contrasting-classes: ();
$dark-contrasting-classes: ();
// Generate the color classes...
@each $paletteName, $palette in $palettes {
// Get the contrasts map
$contrasts: map-get($palette, 'contrast');
@each $hue in $matHues {
// Get the color and the contrasting color
$color: map-get($palette, $hue);
$contrast: map-get($contrasts, $hue);
@if ($color != null and $contrast != null) {
// Generate color classes
@include generateColorClasses($paletteName, $color, $contrast, '-#{$hue}');
// If the contrast color is dark
@if (rgba(black, 1) == rgba($contrast, 1)) {
$dark-contrasting-classes: append($dark-contrasting-classes, unquote('.mat-#{$paletteName}-#{$hue}-bg'), 'comma');
}
// if the contrast color is light
@else {
$light-contrasting-classes: append($light-contrasting-classes, unquote('.mat-#{$paletteName}-#{$hue}-bg'), 'comma');
}
// Run the generator one more time for default values (500)
@if ($hue == 500) {
// Generate color classes
@include generateColorClasses($paletteName, $color, $contrast, '');
// Add color to the correct list depending on the contrasting color
// If the contrast color is dark
@if (rgba(black, 1) == rgba($contrast, 1)) {
$dark-contrasting-classes: append($dark-contrasting-classes, unquote('.mat-#{$paletteName}-bg'), 'comma');
}
// if the contrast color is light
@else {
$light-contrasting-classes: append($light-contrasting-classes, unquote('.mat-#{$paletteName}-bg'), 'comma');
}
}
}
}
}
// Generate contrasting colors
@include generateTextColorLevels($dark-contrasting-classes, 'dark');
@include generateTextColorLevels($light-contrasting-classes, 'light');
@include generateMaterialElementColors($dark-contrasting-classes, 'dark');
@include generateMaterialElementColors($light-contrasting-classes, 'light');
}
// Generate the color classes...
// Define contrast lists
$light-contrasting-classes: ();
$dark-contrasting-classes: ();
@each $paletteName, $palette in $matPalettes {
// Get the contrasts map
$contrasts: map-get($palette, 'contrast');
@each $hue in $matHues {
// Get the color and the contrasting color
$color: map-get($palette, $hue);
$contrast: map-get($contrasts, $hue);
@if ($color != null and $contrast != null) {
// Generate color classes
@include generateColorClasses($paletteName, $color, $contrast, '-#{$hue}');
// Add color to the correct list depending on the contrasting color
// If the contrast color is dark
@if (rgba(black, 1) == rgba($contrast, 1)) {
$dark-contrasting-classes: append($dark-contrasting-classes, unquote('.mat-#{$paletteName}-#{$hue}-bg'), 'comma');
}
// if the contrast color is light
@else {
$light-contrasting-classes: append($light-contrasting-classes, unquote('.mat-#{$paletteName}-#{$hue}-bg'), 'comma');
}
// Run the generator one more time for default values (500)
@if ($hue == 500) {
// Generate color classes
@include generateColorClasses($paletteName, $color, $contrast, '');
// Add color to the correct list depending on the contrasting color
// If the contrast color is dark
@if (rgba(black, 1) == rgba($contrast, 1)) {
$dark-contrasting-classes: append($dark-contrasting-classes, unquote('.mat-#{$paletteName}-bg'), 'comma');
}
// if the contrast color is light
@else {
$light-contrasting-classes: append($light-contrasting-classes, unquote('.mat-#{$paletteName}-bg'), 'comma');
}
}
}
}
}
// Generate contrasting colors
@include generateTextColorLevels($dark-contrasting-classes, 'dark');
@include generateTextColorLevels($light-contrasting-classes, 'light');
@include generateMaterialElementColors($dark-contrasting-classes, 'dark');
@include generateMaterialElementColors($light-contrasting-classes, 'light');

View File

@@ -1,42 +0,0 @@
.docs {
font-size: 16px;
> .content {
max-width: 980px;
> .main-title {
&:first-child {
margin-top: 0;
}
}
}
.main-title {
display: flex;
margin-top: 72px;
font-size: 24px;
}
.section-title {
display: inline-flex;
font-size: 18px;
margin-top: 24px;
border-bottom: 1px solid #F44336;
color: #F44336;
}
ol,
ul {
padding-left: 24px;
li {
margin-bottom: 12px;
line-height: 1.7;
}
}
p {
line-height: 1.7;
}
}

View File

@@ -1,13 +0,0 @@
html,
body {
display: flex;
flex: 1 0 auto;
width: 100%;
height: 100%;
max-height: 100%;
min-height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
background: #F5F5F5;
}

View File

@@ -1,244 +0,0 @@
.nav {
.nav-subheader {
display: flex;
align-items: center;
height: 48px;
font-weight: 500;
padding-left: 24px;
margin-top: 8px;
font-size: 12px;
white-space: nowrap;
}
.nav-group {
display: block;
> .group-title {
position: relative;
display: flex;
align-items: center;
height: 48px;
font-weight: 500;
padding-left: 24px;
margin-top: 8px;
font-size: 12px;
white-space: nowrap;
}
}
.nav-item {
.nav-link {
text-decoration: none !important;
display: flex;
align-items: center;
height: 48px;
padding: 0 24px;
position: relative;
overflow: hidden;
cursor: pointer;
user-select: none;
color: currentColor;
> .nav-link-title {
flex: 1 1 auto;
white-space: nowrap;
}
.nav-link-badge {
display: flex;
align-items: center;
min-width: 20px;
height: 20px;
padding: 0 7px;
font-size: 11px;
font-weight: 500;
border-radius: 20px;
transition: opacity 0.2s ease-in-out 0.1s;
margin-left: 8px;
+ .collapsable-arrow {
margin-left: 8px;
}
}
&:hover {
background-color: map-get($background, hover);
}
.mat-ripple-element {
background-color: map-get($background, hover);
}
&.active {
.nav-link-icon {
opacity: 1;
}
.nav-link-badge {
background: #FFFFFF !important;
color: rgba(0, 0, 0, 0.87) !important;
}
}
.nav-link-icon {
margin-right: 16px;
opacity: 0.7;
}
.nav-link-icon,
.collapsable-arrow {
font-size: 16px;
width: 16px;
height: 16px;
min-width: 16px;
min-height: 16px;
line-height: 16px;
}
}
&.nav-collapsable {
display: block;
> .children {
> .nav-item {
> .nav-link,
&.nav-group > .group-title,
&.nav-group > .group-items > .nav-item > .nav-link {
padding-left: 56px;
}
> .children {
> .nav-item {
> .nav-link,
&.nav-group > .group-title,
&.nav-group > .group-items > .nav-item > .nav-link {
padding-left: 72px;
}
}
}
}
}
}
}
> .nav-item {
&.nav-collapsable {
background: transparent;
transition: background 200ms ease-in-out;
&.open {
background: rgba(0, 0, 0, 0.12);
}
}
}
> .nav-group {
> .group-items {
> .nav-collapsable {
background: transparent;
transition: background 200ms ease-in-out;
&.open {
background: rgba(0, 0, 0, 0.12);
}
}
}
}
&.vertical {
.nav-group {
.group-title {
text-transform: uppercase;
}
}
}
&.horizontal {
display: flex;
flex-direction: row;
.nav-item {
&.nav-collapsable {
position: relative;
.children {
display: none;
position: absolute;
top: 0;
left: 100%;
z-index: 999;
min-width: 200px;
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, .2), 0 8px 10px 1px rgba(0, 0, 0, .14), 0 3px 14px 2px rgba(0, 0, 0, .12);
&.open {
display: block;
}
.nav-link {
padding-left: 24px !important;
}
}
}
}
> .nav-item {
> .nav-link {
height: 56px;
}
&.nav-collapsable {
position: relative;
> .nav-link {
height: 56px;
.collapsable-arrow {
display: none;
}
}
> .children {
top: 100%;
left: 0;
}
}
}
}
// Material style
&.material {
.nav-subheader {
border-top: 1px solid rgba(0, 0, 0, 0.12);
&:first-child {
border-top: none;
}
}
.nav-item {
.nav-link {
height: 40px;
padding: 0 16px;
margin: 4px 8px;
border-radius: 4px;
}
}
}
}

View File

@@ -1,621 +0,0 @@
// Page Layouts
$carded-header-height: 200px !default;
$carded-header-height-sm: 160px !default;
$carded-toolbar-height: 64px !default;
$header-height: 120px !default;
$header-height-sm: 100px !default;
// Calculate toolbarless header height
$carded-header-height-without-toolbar: $carded-header-height - $carded-toolbar-height;
$carded-header-height-without-toolbar-sm: $carded-header-height-sm - $carded-toolbar-height;
.page-layout {
position: relative;
overflow: hidden;
// Carded layout
&.carded {
display: flex;
flex-direction: column;
flex: 1 0 auto;
width: 100%;
min-width: 100%;
// Top bg
> .top-bg {
position: absolute;
z-index: 1;
top: 0;
right: 0;
left: 0;
height: $carded-header-height;
@include media-breakpoint-down('sm') {
height: $carded-header-height-sm;
}
}
// Fullwidth
&.fullwidth {
// Center
> .center {
display: flex;
flex-direction: column;
flex: 1 0 auto;
position: relative;
z-index: 2;
padding: 0 32px;
width: 100%;
min-width: 0;
max-width: 100%;
max-height: 100%;
> .header {
height: $carded-header-height-without-toolbar !important;
min-height: $carded-header-height-without-toolbar !important;
max-height: $carded-header-height-without-toolbar !important;
@include media-breakpoint-down('sm') {
height: $carded-header-height-without-toolbar-sm !important;
min-height: $carded-header-height-without-toolbar-sm !important;
max-height: $carded-header-height-without-toolbar-sm !important;
}
}
> .content-card {
display: flex;
flex-direction: column;
flex: 1 0 auto;
overflow: hidden;
@include mat-elevation(7);
> .toolbar {
display: flex;
justify-content: flex-start;
align-items: center;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
height: $carded-toolbar-height;
min-height: $carded-toolbar-height;
max-height: $carded-toolbar-height;
}
> .content {
flex: 1 0 auto;
}
}
}
// Tabbed
&.tabbed {
> .center {
width: 100%;
min-width: 0;
> .header {
flex: 1 1 auto;
}
> .content-card {
> .content {
display: flex;
> .mat-tab-group {
overflow: hidden;
.mat-tab-header {
.mat-tab-label {
height: 64px;
}
}
.mat-tab-body {
overflow: hidden;
.mat-tab-body-content {
overflow: hidden;
.tab-content {
position: relative;
width: 100%;
height: 100%;
}
}
}
}
}
}
}
}
// Inner scroll
&.inner-scroll {
flex: 1 1 auto;
> .center {
flex: 1 1 auto;
> .content-card {
flex: 1 1 auto;
> .content {
overflow: auto;
flex: 1 1 auto;
}
}
}
// Tabbed
&.tabbed {
> .center {
> .content-card {
> .content {
> .mat-tab-group {
.mat-tab-body {
.mat-tab-body-content {
.tab-content {
overflow: auto;
}
}
}
}
}
}
}
}
}
}
// Left / Right sidebar
&.left-sidebar,
&.right-sidebar {
flex-direction: row;
// Sidebar
> .sidebar {
display: flex;
flex-direction: column;
flex: 1 1 auto;
width: 240px;
min-width: 240px;
max-width: 240px;
height: auto;
overflow: hidden;
@include mat-elevation(7);
&.locked-open {
background: none;
box-shadow: none;
+ .center {
z-index: 1001;
}
&.left-positioned {
+ .center {
margin-left: 0;
}
}
&.right-positioned {
+ .center {
margin-right: 0;
}
}
}
.header {
height: $carded-header-height;
min-height: $carded-header-height;
max-height: $carded-header-height;
@include media-breakpoint-down('sm') {
height: $carded-header-height-sm;
min-height: $carded-header-height-sm;
max-height: $carded-header-height-sm;
}
}
.content {
background: transparent;
flex: 1 1 auto;
}
}
// Center
> .center {
display: flex;
flex-direction: column;
flex: 1 1 auto;
position: relative;
z-index: 3;
margin-left: 32px;
margin-right: 32px;
min-width: 0;
> .header {
display: flex;
height: $carded-header-height-without-toolbar;
min-height: $carded-header-height-without-toolbar;
max-height: $carded-header-height-without-toolbar;
@include media-breakpoint-down('sm') {
height: $carded-header-height-without-toolbar-sm;
min-height: $carded-header-height-without-toolbar-sm;
max-height: $carded-header-height-without-toolbar-sm;
}
}
> .content-card {
display: flex;
flex-direction: column;
flex: 1 1 auto;
overflow: hidden;
@include mat-elevation(7);
> .toolbar {
display: flex;
justify-content: flex-start;
align-items: center;
flex: 1 1 auto;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
height: $carded-toolbar-height;
min-height: $carded-toolbar-height;
max-height: $carded-toolbar-height;
.sidebar-toggle {
margin: 0 8px 0 0 !important;
padding: 0 !important;
border-radius: 0;
}
}
> .content {
flex: 1 1 auto;
}
}
}
// Tabbed
&.tabbed {
> .center {
width: calc(100% - 32px);
min-width: 0;
@include media-breakpoint-down('md') {
width: calc(100% - 64px);
}
> .header {
flex: 1 1 auto;
}
> .content-card {
> .content {
display: flex;
> .mat-tab-group {
overflow: hidden;
.mat-tab-header {
.mat-tab-label {
height: 64px;
}
}
.mat-tab-body {
overflow: hidden;
.mat-tab-body-content {
overflow: hidden;
.tab-content {
position: relative;
width: 100%;
height: 100%;
}
}
}
}
}
}
}
}
// Inner scroll
&.inner-scroll {
flex: 1 1 auto;
> .sidebar {
.content {
overflow: auto;
}
}
> .center {
flex: 1 1 auto;
> .content-card {
flex: 1 1 auto;
> .content {
flex: 1 1 auto;
overflow: auto;
}
}
}
// Tabbed
&.tabbed {
> .center {
> .content-card {
> .content {
> .mat-tab-group {
.mat-tab-body {
.mat-tab-body-content {
.tab-content {
overflow: auto;
}
}
}
}
}
}
}
}
}
}
// Right sidebar specific
&.right-sidebar {
> .sidebar {
order: 2;
}
> .center {
order: 1;
}
}
}
// Simple layout
&.simple {
display: flex;
flex-direction: column;
flex: 1 0 auto;
width: 100%;
min-width: 100%;
// Fullwidth
&.fullwidth {
> .content {
flex: 1 1 auto;
min-width: 0;
}
}
&.fullwidth,
&.inner-sidebar {
> .header {
height: $header-height;
min-height: $header-height;
max-height: $header-height;
}
}
// Left / Right sidebar
&.left-sidebar,
&.right-sidebar {
flex-direction: row;
// Sidebar
> .sidebar {
width: 240px;
min-width: 240px;
max-width: 240px;
overflow: hidden;
@include mat-elevation(7);
&.locked-open {
background: none;
box-shadow: none;
+ .center {
z-index: 1001;
}
&.left-positioned {
+ .center {
margin-left: 0;
}
}
&.right-positioned {
+ .center {
margin-right: 0;
}
}
}
.content {
flex: 1 1 auto;
}
}
// Center
> .center {
position: relative;
display: flex;
flex-direction: column;
flex: 1 1 auto;
z-index: 3;
min-width: 0;
@include mat-elevation(7);
> .header {
height: $header-height;
min-height: $header-height;
max-height: $header-height;
}
> .content {
flex: 1 0 auto;
}
}
// Inner scroll
&.inner-scroll {
flex: 1 1 auto;
> .sidebar {
.content {
overflow: auto;
}
}
> .center {
flex: 1 1 auto;
overflow: auto;
}
}
// Inner Sidebar
&.inner-sidebar {
flex-direction: column;
overflow: hidden;
height: 100%;
> .content {
display: flex;
min-height: 0;
> .sidebar {
&.locked-open {
background: none;
box-shadow: none;
}
.content {
overflow: auto;
}
}
> .center {
flex: 1 1 auto;
overflow: auto;
}
}
}
}
// Right sidebar specific
&.right-sidebar {
> .sidebar {
order: 2;
}
> .center {
order: 1;
}
// Inner sidebar
&.inner-sidebar {
> .content {
> .sidebar {
order: 2;
}
> .center {
order: 1;
}
}
}
}
// Tabbed
&.tabbed {
min-height: 100%;
> .header {
height: $header-height;
min-height: $header-height;
max-height: $header-height;
}
> .content {
> .mat-tab-group {
.mat-tab-labels {
padding: 0 24px;
}
}
}
}
}
// Blank layout
&.blank {
width: 100%;
min-height: 100%;
}
@include media-breakpoint-down('xs') {
// Smaller margins
&.carded {
&.fullwidth {
> .center {
padding: 0 16px;
}
}
&.left-sidebar,
&.right-sidebar {
> .center {
margin: 0 16px;
}
}
}
// End - Smaller margins
}
}

View File

@@ -1,65 +0,0 @@
/*----------------------------------------------------------------*/
/* Print
/*----------------------------------------------------------------*/
@media all {
/* Never show page breaks in normal view */
.page-break-after,
.page-break-before {
display: none;
}
}
@media print {
/* html and body tweaks */
html, body {
height: auto !important;
overflow: initial !important;
}
/* Page breaks */
.page-break-after {
display: block;
page-break-after: always;
position: relative;
}
.page-break-before {
display: block;
page-break-before: always;
position: relative;
}
/* General styles */
app {
fuse-sidebar,
navbar,
toolbar,
footer,
.theme-options-button,
fuse-theme-options,
.ps > .ps__rail-x,
.ps > .ps__rail-y {
display: none !important;
}
.ps {
overflow: visible !important;
}
.mat-drawer-container,
.mat-sidenav-container {
background-color: white !important;
.mat-drawer-content,
.mat-sidenav-content {
overflow: initial !important;
height: auto !important
}
}
}
}

View File

@@ -1,23 +0,0 @@
body:not(.is-mobile) {
::-webkit-scrollbar {
width: 12px;
height: 12px;
background-color: rgba(0, 0, 0, 0);
}
::-webkit-scrollbar:hover {
background-color: rgba(0, 0, 0, 0.12);
}
::-webkit-scrollbar-thumb {
border: 2px solid transparent;
box-shadow: inset 0 0 0 24px rgba(0, 0, 0, 0.37);
border-radius: 24px;
}
::-webkit-scrollbar-thumb:active {
box-shadow: inset 0 0 0 24px rgba(0, 0, 0, 0.54);
border-radius: 24px;
}
}

View File

@@ -1,360 +0,0 @@
/*@font-face {
font-family: 'fontello';
src: url('../font/fontello.eot?81091010');
src: url('../font/fontello.eot?81091010#iefix') format('embedded-opentype'),
url('../font/fontello.woff2?81091010') format('woff2'),
url('../font/fontello.woff?81091010') format('woff'),
url('../font/fontello.ttf?81091010') format('truetype'),
url('../font/fontello.svg?81091010#fontello') format('svg');
font-weight: normal;
font-style: normal;
}*/
owl-date-time {
[class^="icon-"]:before, [class*=" icon-"]:before {
font-family: "Material Icons";
font-style: normal;
font-weight: normal;
speak: none;
display: flex;
align-items: center;
justify-content: center;
/* For safety - reset parent styles, that can break glyph codes*/
font-variant: normal;
text-transform: none;
/* Font smoothing. That was taken from TWBS */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-cancel:before {
content: 'close';
}
.icon-up-open:before {
content: 'keyboard_arrow_up';
}
.icon-down-open:before {
content: 'keyboard_arrow_down';
}
.icon-left-open:before {
content: 'chevron_left';
}
.icon-right-open:before {
content: 'chevron_right';
}
$white: #FFFFFF;
$black: #000000;
$grey: #DDDDDD;
$blue: #0070BA;
.owl-widget,
.owl-widget * {
box-sizing: border-box;
}
.owl-widget {
font-size: 1em;
}
.owl-state-focus {
}
.owl-corner-all {
border-radius: 2px;
}
.owl-corner-top {
border-top-left-radius: 2px;
border-top-right-radius: 2px;
}
.owl-state-default {
background: #FFFFFF;
color: rgba(0, 0, 0, 0.87);
}
.owl-dateTime-inputWrapper {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
.owl-dateTime-input {
background: none !important;
padding: 0 !important;
cursor: pointer;
.owl-inputtext {
margin: 0;
padding: 8px;
background: none !important;
color: rgba(0, 0, 0, 0.87);
}
}
.owl-dateTime-cancel {
position: relative !important;
right: 0 !important;
top: 0 !important;
transform: none !important;
font-size: 16px !important;
width: 16px !important;
height: 16px !important;
min-width: 16px !important;
min-height: 16px !important;
line-height: 16px !important;
color: rgba(0, 0, 0, 0.54) !important;
}
}
.owl-dateTime {
position: relative;
width: 140px;
&.owl-dateTime-inline {
width: auto;
.owl-dateTime-dialog {
position: relative;
z-index: auto;
}
}
}
.owl-dateTime-dialog {
width: 256px;
user-select: none;
z-index: 99999;
top: 24px !important;
right: 0 !important;
left: auto !important;
@include mat-elevation(4);
}
.owl-dateTime-dialogHeader {
height: 2.5em;
padding: .25em;
background-color: rgba(0, 0, 0, .1);
overflow-y: auto;
}
.owl-calendar-wrapper {
padding: 16px !important;
}
.owl-calendar-control {
.owl-calendar-controlNav {
display: flex;
align-items: center;
justify-content: center;
.nav-prev,
.nav-next {
display: flex;
&:before {
font-family: "Material Icons";
position: relative !important;
right: 0 !important;
top: 0 !important;
transform: none !important;
font-size: 20px !important;
width: 20px !important;
height: 20px !important;
min-width: 20px !important;
min-height: 20px !important;
line-height: 20px !important;
content: "chevron_left";
color: rgba(0, 0, 0, 0.54);
}
}
.nav-next:before {
content: "chevron_right";
}
}
.owl-calendar-controlContent {
.month-control,
.year-control {
font-size: 14px;
font-weight: 500;
cursor: pointer;
}
.month-control {
margin-right: 8px;
}
.year-control {
}
}
}
.owl-calendar {
table {
border-spacing: 0 !important;
}
tbody td {
&.owl-calendar-selected {
background-color: $blue;
color: $white;
}
&.owl-calendar-invalid {
color: #ACACAC;
}
&.owl-calendar-outFocus {
color: $grey;
}
&.owl-calendar-hidden {
visibility: hidden;
}
&:not(.owl-calendar-selected):not(.owl-calendar-invalid):hover {
background-color: lighten($blue, 50%);
color: $black;
}
}
}
.owl-years,
.owl-months {
td.owl-year,
td.owl-month {
padding: 0;
font-size: 16px;
width: 72px;
height: 48px;
line-height: 48px;
cursor: pointer;
}
}
.owl-calendar-yearArrow {
width: 24px !important;
height: 24px !important;
&.left {
left: -16px !important;
}
&.right {
right: -16px !important;
}
}
.owl-weekdays {
th.owl-weekday {
height: 32px;
line-height: 32px;
text-align: center;
font-size: 12px;
padding: 0;
color: rgba(0, 0, 0, 0.37);
}
}
.owl-days {
td.owl-day {
height: 32px;
width: 32px;
line-height: 32px;
cursor: pointer;
border-radius: 100%;
padding: 0;
&.owl-day-today:before {
content: '';
display: block;
position: absolute;
right: 2px;
top: 2px;
border-top: .5em solid lighten($blue, 20%);
border-left: .5em solid transparent;
}
}
}
.owl-timer-wrapper {
height: 88px;
padding: 8px !important;
background-color: rgba(0, 0, 0, 0.06);
.owl-timer-input {
background: none;
width: 100% !important;
text-align: center;
}
.owl-timer-text {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 40%;
font-size: 20px;
}
.owl-meridian-btn {
font-size: .8em;
color: $blue;
background-image: none;
background-color: transparent;
border-color: $blue;
&:hover {
color: $white;
background-color: $blue;
border-color: $blue;
}
}
}
.owl-timer-divider {
display: inline-block;
position: absolute;
width: 8px;
height: 100%;
left: -2px;
.owl-timer-dot {
display: block;
background: rgba(0, 0, 0, 0.37);
width: 3px;
height: 3px;
position: absolute;
left: 50%;
border-radius: 100%;
transform: translateX(-50%);
&.dot-top {
top: 40%;
}
&.dot-bottom {
bottom: 40%;
}
}
}
}

View File

@@ -1,12 +0,0 @@
.ps {
position: relative;
> .ps__rail-x {
z-index: 99999;
}
> .ps__rail-y {
z-index: 99999;
left: auto !important;
}
}

View File

@@ -1,269 +0,0 @@
// Edit the sixteen color-value variables, and create your own syntax highlighter colorscheme
$base00: #263238;
$base01: #2C393F;
$base02: #62727A;
$base03: #707880;
$base04: #C9CCD3;
$base05: #CDD3DE;
$base06: #D5DBE5;
$base07: #FFFFFF;
$base08: #EC5F67;
$base09: #EA9560;
$base0A: #FFCC00;
$base0B: #8BD649;
$base0C: #80CBC4;
$base0D: #89DDFF;
$base0E: #82AAFF;
$base0F: #EC5F67;
$red: $base08;
$orange: $base09;
$yellow: $base0A;
$green: $base0B;
$cyan: $base0C;
$blue: $base0D;
$violet: $base0E;
$magenta: $base0F;
$code-font-family: Consolas, Menlo, Monaco, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", "Courier New", Courier, monospace;
$code-font-size: 14px;
$code-line-height: 1.6;
$code-background: $base00;
$code-color: $base05;
$code-color-fade: $base05;
// $code-text-shadow: none;
$code-color-comment: $base02;
$code-color-keyword: $base0B;
$code-color-value: $base0C;
$code-color-attr-name: $base09;
$code-color-string: $base0C;
$code-color-name: $base0A;
$code-color-number: $base09;
$code-color-variable: $base0D;
$code-color-selector: $base0E;
$code-color-property: $base0A;
$code-color-important: $base08;
$code-color-tag: $base0D;
$code-color-atrule: $base0C;
// @import "../partials/prism";
/**
* Prism base code highlighter theme using Sass
*
* @author @MoOx
* https://github.com/MoOx/sass-prism-theme-base/blob/master/_prism.scss
* slightly adapted by me, Bram de Haan
*/
// prism selector
$code-selector: "code[class*=\"language-\"], pre[class*=\"language-\"]";
$code-selector-block: "pre[class*=\"language-\"]";
$code-selector-inline: ":not(pre) > code[class*=\"language-\"]";
// generic stuff
$code-font-family: Menlo, Monaco, "Courier New", monospace !default;
$code-font-size: 14px !default;
$code-line-height: 1.6 !default;
$code-tab-size: 4 !default;
$code-hyphens: none !default;
$code-block-padding: 12px !default;
$code-inline-padding: 2px 6px !default;
$code-border-radius: 0 !default;
$code-border: none !default;
$code-background: #2A2A2A !default;
$code-color: #FFF !default;
$code-color-fade: #BEBEC5 !default;
// $code-text-shadow: 0 1px 0 #000 !default;
$code-box-shadow: none !default;
$code-color-property: #B58900 !default;
$code-color-important: #CB4B16 !default;
$code-color-tag: #268BD2 !default;
$code-color-atrule: #2AA198 !default;
$code-color-attr-name: #B65611 !default;
// $code-linenums-padding: 7px !default;
// $code-linenums-width: 40px !default;
// $code-linenums-background: #444 !default;
// $code-linenums-border-color: #555 !default;
// $code-linenums-border-width: 1px !default;
@if $code-selector != null {
#{$code-selector} {
-moz-tab-size: $code-tab-size;
-o-tab-size: $code-tab-size;
tab-size: $code-tab-size;
-webkit-hyphens: $code-hyphens;
-moz-hyphens: $code-hyphens;
-ms-hyphens: $code-hyphens;
hyphens: $code-hyphens;
// whitespace management
white-space: pre; // fallback
//white-space: pre-wrap;
//word-break: break-all;
//word-wrap: break-word;
font-family: $code-font-family;
font-size: $code-font-size;
line-height: $code-line-height;
color: $code-color;
// text-shadow: $code-text-shadow;
background: $code-background;
}
}
%code-background {
border-radius: $code-border-radius;
border: $code-border;
box-shadow: $code-box-shadow;
}
@if $code-selector-block != null {
#{$code-selector-block} {
@extend %code-background;
padding: $code-block-padding;
}
}
@if $code-selector-inline != null {
#{$code-selector-inline} {
@extend %code-background;
padding: $code-inline-padding;
}
}
// pre[class*="language-"],
// :not(pre) > code[class*="language-"] {
// background: $code-background;
// }
// prism tokens
//
$code-color-comment: null !default;
$code-color-keyword: null !default;
$code-color-value: null !default;
$code-color-string: null !default;
$code-color-name: null !default;
$code-color-number: null !default;
$code-color-variable: null !default;
$code-color-selector: null !default;
$code-color-punctuation: $code-color-fade !default;
#{$code-selector} {
.namespace {
opacity: .7;
}
.token {
&.comment,
&.prolog,
&.doctype,
&.cdata {
color: $code-color-comment;
}
&.null,
&.operator,
&.boolean,
&.number {
color: $code-color-number;
}
&.string {
color: $code-color-string;
}
&.attr-name {
color: $code-color-attr-name;
}
&.entity,
&.url,
.language-css &.string,
.style &.string {
color: $code-color-string;
}
&.selector {
color: $code-color-selector;
}
&.attr-value,
&.keyword,
&.control,
&.directive,
&.unit {
color: $code-color-keyword;
}
&.important {
color: $code-color-important;
}
&.atrule {
color: $code-color-atrule;
}
&.regex,
&.statement {
color: $code-color-value;
}
&.placeholder,
&.variable {
color: $code-color-variable;
}
&.property,
&.tag {
// font-style: italic;
}
&.property {
color: $code-color-property;
}
&.tag {
color: $code-color-tag;
}
&.important,
&.statement {
font-weight: bold;
}
// todo ?
// &.mixin
// &.gradient
// &.abslength
// &.easing
// &.time
// &.angle
// &.fontfamily
// ruby/vim https://github.com/LeaVerou/prism/pull/18
// &.inst-var
// &.builtin
// &.const
// &.symbol
//
// php https://github.com/LeaVerou/prism/pull/20
// &.deliminator
// &.function
&.punctuation {
color: $code-color-punctuation;
}
&.entity {
cursor: help;
}
// for dev :)
&.debug {
color: red
}
}
}

View File

@@ -1,157 +0,0 @@
import { Inject, Injectable, InjectionToken } from '@angular/core';
import { NavigationStart, Router } from '@angular/router';
import { Platform } from '@angular/cdk/platform';
import { BehaviorSubject, Observable } from 'rxjs';
import { filter } from 'rxjs/operators';
import * as _ from 'lodash';
// Create the injection token for the custom settings
export const FUSE_CONFIG = new InjectionToken('fuseCustomConfig');
@Injectable({
providedIn: 'root'
})
export class FuseConfigService
{
// Private
private _configSubject: BehaviorSubject<any>;
private readonly _defaultConfig: any;
/**
* Constructor
*
* @param {Platform} _platform
* @param {Router} _router
* @param _config
*/
constructor(
private _platform: Platform,
private _router: Router,
@Inject(FUSE_CONFIG) private _config
)
{
// Set the default config from the user provided config (from forRoot)
this._defaultConfig = _config;
// Initialize the service
this._init();
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Set and get the 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();
}
/**
* Get default config
*
* @returns {any}
*/
get defaultConfig(): any
{
return this._defaultConfig;
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Initialize
*
* @private
*/
private _init(): void
{
/**
* Disable custom scrollbars if browser is mobile
*/
if ( this._platform.ANDROID || this._platform.IOS )
{
this._defaultConfig.customScrollbars = false;
}
// Set the config from the default config
this._configSubject = new BehaviorSubject(_.cloneDeep(this._defaultConfig));
// Reload the default config on every navigation start if
// the current config is different from the default one
this._router.events
.pipe(filter(event => event instanceof NavigationStart))
.subscribe(() => {
if ( !_.isEqual(this._configSubject.getValue(), this._defaultConfig) )
{
// Clone the default config
const config = _.cloneDeep(this._defaultConfig);
// Set the config
this._configSubject.next(config);
}
});
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Set config
*
* @param value
* @param {{emitEvent: boolean}} opts
*/
setConfig(value, opts = {emitEvent: true}): void
{
// Get the value from the behavior subject
let config = this._configSubject.getValue();
// Merge the new config
config = _.merge({}, config, value);
// If emitEvent option is true...
if ( opts.emitEvent === true )
{
// Notify the observers
this._configSubject.next(config);
}
}
/**
* Get config
*
* @returns {Observable<any>}
*/
getConfig(): Observable<any>
{
return this._configSubject.asObservable();
}
/**
* Reset to the default config
*/
resetToDefaults(): void
{
// Set the config from the default config
this._configSubject.next(_.cloneDeep(this._defaultConfig));
}
}

View File

@@ -1,76 +0,0 @@
/**
* This class is based on the code in the following projects:
* https://github.com/zenorocha/select
* https://github.com/zenorocha/clipboard.js/
*
* Both released under MIT license - © Zeno Rocha
*/
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class FuseCopierService
{
private textarea: HTMLTextAreaElement;
/**
* Copy the text value to the clipboard
*
* @param {string} text
* @returns {boolean}
*/
copyText(text: string): boolean
{
this.createTextareaAndSelect(text);
const copySuccessful = document.execCommand('copy');
this._removeFake();
return copySuccessful;
}
/**
* Creates a hidden textarea element, sets its value from `text` property,
* and makes a selection on it.
*
* @param {string} text
*/
private createTextareaAndSelect(text: string): void
{
// Create a fake element to hold the contents to copy
this.textarea = document.createElement('textarea');
// Prevent zooming on iOS
this.textarea.style.fontSize = '12pt';
// Hide the element
this.textarea.classList.add('cdk-visually-hidden');
// Move element to the same position vertically
const yPosition = window.pageYOffset || document.documentElement.scrollTop;
this.textarea.style.top = yPosition + 'px';
this.textarea.setAttribute('readonly', '');
this.textarea.value = text;
document.body.appendChild(this.textarea);
this.textarea.select();
this.textarea.setSelectionRange(0, this.textarea.value.length);
}
/**
* Remove the text area from the DOM
*
* @private
*/
private _removeFake(): void
{
if ( this.textarea )
{
document.body.removeChild(this.textarea);
this.textarea = null;
}
}
}

View File

@@ -1,91 +0,0 @@
import { Injectable } from '@angular/core';
import { NavigationEnd, NavigationStart, Router } from '@angular/router';
import { BehaviorSubject, Observable } from 'rxjs';
import { filter } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class FuseLoadingBarService
{
// Private
private _visible: BehaviorSubject<boolean>;
/**
* Constructor
*
* @param {Router} _router
*/
constructor(
private _router: Router
)
{
// Initialize the service
this._init();
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
get visible(): Observable<any>
{
// Return the _visible as observable
return this._visible.asObservable();
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Initialize
*
* @private
*/
private _init(): void
{
// Initialize the behavior subject
this._visible = new BehaviorSubject(false);
// Subscribe to the router events to show/hide the loading bar
this._router.events
.pipe(
filter((event) => event instanceof NavigationStart)
)
.subscribe(() => {
this.showLoadingBar();
});
this._router.events
.pipe(
filter((event) => event instanceof NavigationEnd)
)
.subscribe(() => {
this.hideLoadingBar();
});
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Show the loading bar
*/
showLoadingBar(): void
{
// Show
this._visible.next(true);
}
/**
* Hide the loading bar
*/
hideLoadingBar(): void
{
// Hide
this._visible.next(false);
}
}

View File

@@ -1,51 +0,0 @@
import { MediaChange, ObservableMedia } from '@angular/flex-layout';
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class FuseMatchMediaService
{
activeMediaQuery: string;
onMediaChange: BehaviorSubject<string> = new BehaviorSubject<string>('');
/**
* Constructor
*
* @param {ObservableMedia} _observableMedia
*/
constructor(
private _observableMedia: ObservableMedia
)
{
// Set the defaults
this.activeMediaQuery = '';
// Initialize
this._init();
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Initialize
*
* @private
*/
private _init(): void
{
this._observableMedia
.subscribe((change: MediaChange) => {
if ( this.activeMediaQuery !== change.mqAlias )
{
this.activeMediaQuery = change.mqAlias;
this.onMediaChange.next(change.mqAlias);
}
});
}
}

View File

@@ -1,108 +0,0 @@
import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { animate, AnimationBuilder, AnimationPlayer, style } from '@angular/animations';
import { NavigationEnd, Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class FuseSplashScreenService
{
splashScreenEl: any;
player: AnimationPlayer;
/**
* Constructor
*
* @param {AnimationBuilder} _animationBuilder
* @param _document
* @param {Router} _router
*/
constructor(
private _animationBuilder: AnimationBuilder,
@Inject(DOCUMENT) private _document: any,
private _router: Router
)
{
// Initialize
this._init();
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Initialize
*
* @private
*/
private _init(): void
{
// Get the splash screen element
this.splashScreenEl = this._document.body.querySelector('#fuse-splash-screen');
// If the splash screen element exists...
if ( this.splashScreenEl )
{
// Hide it on the first NavigationEnd event
const hideOnLoad = this._router.events.subscribe((event) => {
if ( event instanceof NavigationEnd )
{
setTimeout(() => {
this.hide();
// Unsubscribe from this event so it
// won't get triggered again
hideOnLoad.unsubscribe();
}, 0);
}
}
);
}
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Show the splash screen
*/
show(): void
{
this.player =
this._animationBuilder
.build([
style({
opacity: '0',
zIndex : '99999'
}),
animate('400ms ease', style({opacity: '1'}))
]).create(this.splashScreenEl);
setTimeout(() => {
this.player.play();
}, 0);
}
/**
* Hide the splash screen
*/
hide(): void
{
this.player =
this._animationBuilder
.build([
style({opacity: '1'}),
animate('400ms ease', style({
opacity: '0',
zIndex : '-10'
}))
]).create(this.splashScreenEl);
setTimeout(() => {
this.player.play();
}, 0);
}
}

View File

@@ -1,45 +0,0 @@
import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
export interface Locale
{
lang: string;
data: Object;
}
@Injectable({
providedIn: 'root'
})
export class FuseTranslationLoaderService
{
/**
* Constructor
*
* @param {TranslateService} _translateService
*/
constructor(
private _translateService: TranslateService
)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Load translations
*
* @param {Locale} args
*/
loadTranslations(...args: Locale[]): void
{
const locales = [...args];
locales.forEach((locale) => {
// use setTranslation() with the third argument set to true
// to append translations instead of replacing them
this._translateService.setTranslation(locale.lang, locale.data, true);
});
}
}

View File

@@ -1,34 +0,0 @@
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { FlexLayoutModule } from '@angular/flex-layout';
import { FuseDirectivesModule } from '@fuse/directives/directives';
import { FusePipesModule } from '@fuse/pipes/pipes.module';
@NgModule({
imports : [
CommonModule,
FormsModule,
ReactiveFormsModule,
FlexLayoutModule,
FuseDirectivesModule,
FusePipesModule
],
exports : [
CommonModule,
FormsModule,
ReactiveFormsModule,
FlexLayoutModule,
FuseDirectivesModule,
FusePipesModule
]
})
export class FuseSharedModule
{
}

View File

@@ -1,29 +0,0 @@
export interface FuseConfig
{
layout: {
style: string,
width: 'fullwidth' | 'boxed',
navbar: {
background: string,
hidden: boolean,
folded: boolean,
position: 'left' | 'right' | 'top',
variant: string
},
toolbar: {
background: string,
hidden: boolean,
position: 'above' | 'above-static' | 'above-fixed' | 'below' | 'below-static' | 'below-fixed'
}
footer: {
background: string,
hidden: boolean,
position: 'above' | 'above-static' | 'above-fixed' | 'below' | 'below-static' | 'below-fixed'
},
sidepanel: {
hidden: boolean,
position: 'left' | 'right'
}
};
customScrollbars: boolean;
}

View File

@@ -1,27 +0,0 @@
export interface FuseNavigationItem
{
id: string;
title: string;
type: 'item' | 'group' | 'collapsable';
translate?: string;
icon?: string;
hidden?: boolean;
url?: string;
classes?: string;
exactMatch?: boolean;
externalUrl?: boolean;
openInNewTab?: boolean;
function?: any;
badge?: {
title?: string;
translate?: string;
bg?: string;
fg?: string;
};
children?: FuseNavigationItem[];
}
export interface FuseNavigation extends FuseNavigationItem
{
children?: FuseNavigationItem[];
}

View File

@@ -1,2 +0,0 @@
export * from './fuse-config';
export * from './fuse-navigation';

View File

@@ -1,159 +0,0 @@
export class FuseUtils
{
/**
* Filter array by string
*
* @param mainArr
* @param searchText
* @returns {any}
*/
public static filterArrayByString(mainArr, searchText): any
{
if ( searchText === '' )
{
return mainArr;
}
searchText = searchText.toLowerCase();
return mainArr.filter(itemObj => {
return this.searchInObj(itemObj, searchText);
});
}
/**
* Search in object
*
* @param itemObj
* @param searchText
* @returns {boolean}
*/
public static searchInObj(itemObj, searchText): boolean
{
for ( const prop in itemObj )
{
if ( !itemObj.hasOwnProperty(prop) )
{
continue;
}
const value = itemObj[prop];
if ( typeof value === 'string' )
{
if ( this.searchInString(value, searchText) )
{
return true;
}
}
else if ( Array.isArray(value) )
{
if ( this.searchInArray(value, searchText) )
{
return true;
}
}
if ( typeof value === 'object' )
{
if ( this.searchInObj(value, searchText) )
{
return true;
}
}
}
}
/**
* Search in array
*
* @param arr
* @param searchText
* @returns {boolean}
*/
public static searchInArray(arr, searchText): boolean
{
for ( const value of arr )
{
if ( typeof value === 'string' )
{
if ( this.searchInString(value, searchText) )
{
return true;
}
}
if ( typeof value === 'object' )
{
if ( this.searchInObj(value, searchText) )
{
return true;
}
}
}
}
/**
* Search in string
*
* @param value
* @param searchText
* @returns {any}
*/
public static searchInString(value, searchText): any
{
return value.toLowerCase().includes(searchText);
}
/**
* Generate a unique GUID
*
* @returns {string}
*/
public static generateGUID(): string
{
function S4(): string
{
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return S4() + S4();
}
/**
* Toggle in array
*
* @param item
* @param array
*/
public static toggleInArray(item, array): void
{
if ( array.indexOf(item) === -1 )
{
array.push(item);
}
else
{
array.splice(array.indexOf(item), 1);
}
}
/**
* Handleize
*
* @param text
* @returns {string}
*/
public static handleize(text): string
{
return text.toString().toLowerCase()
.replace(/\s+/g, '-') // Replace spaces with -
.replace(/[^\w\-]+/g, '') // Remove all non-word chars
.replace(/\-\-+/g, '-') // Replace multiple - with single -
.replace(/^-+/, '') // Trim - from start of text
.replace(/-+$/, ''); // Trim - from end of text
}
}

View File

@@ -1,31 +1 @@
<!-- VERTICAL LAYOUT 1 -->
<ng-container *ngIf="fuseConfig.layout.style === 'vertical-layout-1'">
<vertical-layout-1></vertical-layout-1>
</ng-container>
<!-- VERTICAL LAYOUT 2 -->
<ng-container *ngIf="fuseConfig.layout.style === 'vertical-layout-2'">
<vertical-layout-2></vertical-layout-2>
</ng-container>
<!-- VERTICAL LAYOUT 3 -->
<ng-container *ngIf="fuseConfig.layout.style === 'vertical-layout-3'">
<vertical-layout-3></vertical-layout-3>
</ng-container>
<!-- HORIZONTAL LAYOUT 1 -->
<ng-container *ngIf="fuseConfig.layout.style === 'horizontal-layout-1'">
<horizontal-layout-1></horizontal-layout-1>
</ng-container>
<!-- THEME OPTIONS PANEL -->
<button mat-icon-button class="mat-primary-bg mat-elevation-z2 theme-options-button"
[ngClass]="{'right-side-panel': fuseConfig.layout.sidepanel.position === 'right',
'side-panel-hidden': fuseConfig.layout.sidepanel.hidden === true}"
(click)="toggleSidebarOpen('themeOptionsPanel')">
<mat-icon>settings</mat-icon>
</button>
<fuse-sidebar name="themeOptionsPanel" class="theme-options-sidebar" position="right" [invisibleOverlay]="true">
<fuse-theme-options></fuse-theme-options>
</fuse-sidebar>
<fuse-main></fuse-main>

Some files were not shown because too many files have changed in this diff Show More