mirror of
https://github.com/richard-loafle/fuse-angular.git
synced 2025-12-22 08:57:06 +00:00
Compare commits
421 Commits
v5.2.8
...
v8.1.2-ske
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88949b4ab6 | ||
|
|
116721dd33 | ||
|
|
3ec49abcf2 | ||
|
|
b2f56fcd12 | ||
|
|
612a4827dc | ||
|
|
72fd2dd22d | ||
|
|
09bc137fa0 | ||
|
|
00e228ab5a | ||
|
|
455e7f6f47 | ||
|
|
2f2b302cb6 | ||
|
|
8b358cc6ff | ||
|
|
8bd1e58db5 | ||
|
|
9db5f0b04a | ||
|
|
226f3fb440 | ||
|
|
bb3764aaff | ||
|
|
7ec117202d | ||
|
|
f1e1ddc236 | ||
|
|
bc2fc44bcf | ||
|
|
4ce34b2234 | ||
|
|
838132ce68 | ||
|
|
8c555a1fb5 | ||
|
|
3827b10fc5 | ||
|
|
6f3ce4059d | ||
|
|
8dbd71f122 | ||
|
|
5870131ab2 | ||
|
|
c764089061 | ||
|
|
a7cf8c236b | ||
|
|
79d2ed8cfe | ||
|
|
84696aed79 | ||
|
|
44550ecdd8 | ||
|
|
68bd4436f4 | ||
|
|
6db86a6b25 | ||
|
|
9523e3724a | ||
|
|
8e4e4bf401 | ||
|
|
b184c839da | ||
|
|
017ce59254 | ||
|
|
842cb37fcb | ||
|
|
3c45bd49e4 | ||
|
|
430fe0c0c1 | ||
|
|
1850fd7eb1 | ||
|
|
8118f94b50 | ||
|
|
bc2b4aefac | ||
|
|
83ba318fb7 | ||
|
|
1dd59db09f | ||
|
|
60ab983730 | ||
|
|
6fadc29e4c | ||
|
|
4da339cef1 | ||
|
|
cbd1c3e21c | ||
|
|
e67887f379 | ||
|
|
eeed00b30e | ||
|
|
06c8903f91 | ||
|
|
23b943a765 | ||
|
|
8961d75241 | ||
|
|
ab7bd882a0 | ||
|
|
63bd95ea1e | ||
|
|
98297ea787 | ||
|
|
5251a6305f | ||
|
|
790549a92d | ||
|
|
0643d8c348 | ||
|
|
c2d5a5a2a5 | ||
|
|
94275c507f | ||
|
|
31b4c300f0 | ||
|
|
5f127e4721 | ||
|
|
768d20c481 | ||
|
|
b2a28c36ed | ||
|
|
7dc0892c83 | ||
|
|
ef216718b9 | ||
|
|
f337df17e4 | ||
|
|
4a4220c123 | ||
|
|
ed9c024e13 | ||
|
|
94d9118df7 | ||
|
|
3d85b172c4 | ||
|
|
bfa1dd9e84 | ||
|
|
a5b6e545a7 | ||
|
|
0b2af161f4 | ||
|
|
9630d0154f | ||
|
|
62b64cb78c | ||
|
|
8fc20fef8f | ||
|
|
8b97e6623b | ||
|
|
a184be1650 | ||
|
|
09bd4b9fee | ||
|
|
d8782a78d5 | ||
|
|
c4e338cda1 | ||
|
|
77c05ce4e0 | ||
|
|
e92f34b38f | ||
|
|
ecbc370064 | ||
|
|
498b9647e6 | ||
|
|
962df7fe9a | ||
|
|
763111aae3 | ||
|
|
715e77776e | ||
|
|
c8c0b4a609 | ||
|
|
5d62c58725 | ||
|
|
f1b4546a73 | ||
|
|
38a03da265 | ||
|
|
34ffe7e53b | ||
|
|
6960a2ba26 | ||
|
|
27dbbef6e1 | ||
|
|
f7f3a60ff5 | ||
|
|
08e2d5f331 | ||
|
|
fee608cb44 | ||
|
|
343d7902fa | ||
|
|
927b4fd322 | ||
|
|
a52b1f7687 | ||
|
|
0331db4384 | ||
|
|
0f1048cb3c | ||
|
|
bbd59ab6c3 | ||
|
|
620583f99c | ||
|
|
e49771a5e0 | ||
|
|
42095bfe26 | ||
|
|
0d2b5a9662 | ||
|
|
1d1ac4b04a | ||
|
|
6afa55bb0f | ||
|
|
8454526ef5 | ||
|
|
f8292af81e | ||
|
|
46a0ac1aa9 | ||
|
|
37d5e097b5 | ||
|
|
92d7986c8a | ||
|
|
38177c3d68 | ||
|
|
b08ab47715 | ||
|
|
798e2632bc | ||
|
|
19c960cc4c | ||
|
|
8dfc3e854b | ||
|
|
0ccb4211c5 | ||
|
|
04b80ca168 | ||
|
|
54451bb19e | ||
|
|
5e98d986e2 | ||
|
|
293192557f | ||
|
|
d61549d9e6 | ||
|
|
b2ceb02709 | ||
|
|
d25ce3601a | ||
|
|
ffbd000fe2 | ||
|
|
b6ebd2b839 | ||
|
|
4d4d52ba05 | ||
|
|
251732f221 | ||
|
|
4642b730cb | ||
|
|
0982d5369b | ||
|
|
1c34a65034 | ||
|
|
b8803a055f | ||
|
|
6b8cd41d5e | ||
|
|
fe7fdf0a00 | ||
|
|
2c7ef4de00 | ||
|
|
adc93d5d40 | ||
|
|
77f6062a55 | ||
|
|
fdb572fadd | ||
|
|
cef9e8a9c0 | ||
|
|
2f0d1e406f | ||
|
|
528c3f95e7 | ||
|
|
f395046945 | ||
|
|
b099022f5a | ||
|
|
25a6ca2684 | ||
|
|
0cd5d613e0 | ||
|
|
f45ad11861 | ||
|
|
b7ab5ea273 | ||
|
|
d7e65460bf | ||
|
|
3cbe302b54 | ||
|
|
e1c906f08b | ||
|
|
585709cf93 | ||
|
|
ac70ecc616 | ||
|
|
d5b64f3258 | ||
|
|
59d838ef51 | ||
|
|
8b14366763 | ||
|
|
23b86a7e3d | ||
|
|
2f497f1c7b | ||
|
|
18009c9275 | ||
|
|
20d5a68bf3 | ||
|
|
59d53ba0b9 | ||
|
|
a6c91dd744 | ||
|
|
5045482ef5 | ||
|
|
c7d9a7808a | ||
|
|
e4c0340cd7 | ||
|
|
67cb05be6b | ||
|
|
634ff42f1a | ||
|
|
0149beb33c | ||
|
|
42d9748b10 | ||
|
|
8355e8a17c | ||
|
|
dbb925334a | ||
|
|
49c8e32dce | ||
|
|
595b16275b | ||
|
|
fb003bc96f | ||
|
|
d781e59928 | ||
|
|
89f71735a8 | ||
|
|
51d7c6fd6f | ||
|
|
e182f19644 | ||
|
|
d4d57480a1 | ||
|
|
a1aed2998d | ||
|
|
0d6d08aa85 | ||
|
|
7ff1d2aed0 | ||
|
|
09d1b1034e | ||
|
|
4e98ab1682 | ||
|
|
984004d07a | ||
|
|
64e0451dc6 | ||
|
|
224bbf479a | ||
|
|
1aa79c257b | ||
|
|
8e5fdb1d31 | ||
|
|
4d93b6acef | ||
|
|
2eb952e9bc | ||
|
|
ae29f1f03d | ||
|
|
f35c1add1c | ||
|
|
b418049d94 | ||
|
|
388b724e90 | ||
|
|
34d77c1d1a | ||
|
|
023bfea4df | ||
|
|
fd4da1e060 | ||
|
|
85226e6094 | ||
|
|
723c289a47 | ||
|
|
26a7cc41de | ||
|
|
23f8547be5 | ||
|
|
3deba51322 | ||
|
|
b54bbc8abe | ||
|
|
1835c060d6 | ||
|
|
f75d458abe | ||
|
|
6320e98938 | ||
|
|
94d20f8d8d | ||
|
|
ba2f50bf62 | ||
|
|
13746c2a73 | ||
|
|
faef6ec6f8 | ||
|
|
b46b253c1c | ||
|
|
3abd764715 | ||
|
|
1acfe2dfb3 | ||
|
|
41a93857b6 | ||
|
|
6d3cfe8ace | ||
|
|
147525d16a | ||
|
|
29f8ddda9e | ||
|
|
1f77e201a1 | ||
|
|
0e2dca00c0 | ||
|
|
c93cecdddd | ||
|
|
75b7e4e270 | ||
|
|
9efab7ed20 | ||
|
|
65523c3c95 | ||
|
|
22b3a3c799 | ||
|
|
2b4bd45ad6 | ||
|
|
1e47c79f15 | ||
|
|
58ab766edf | ||
|
|
8db1206c91 | ||
|
|
562ae61098 | ||
|
|
e43ae86a58 | ||
|
|
5459579d04 | ||
|
|
95759be710 | ||
|
|
edb4683dcb | ||
|
|
58dd3b93c3 | ||
|
|
91e8d88488 | ||
|
|
ddcf1d5483 | ||
|
|
0b5727ff15 | ||
|
|
20f80e3fe4 | ||
|
|
5bf9fd177b | ||
|
|
507fe97e84 | ||
|
|
a6a7442607 | ||
|
|
43189728e5 | ||
|
|
9c88524185 | ||
|
|
52cfeec2e7 | ||
|
|
ffb134f1ec | ||
|
|
8520ca77be | ||
|
|
a174c00072 | ||
|
|
42ab15d9e1 | ||
|
|
a87e68251e | ||
|
|
436bd0aa91 | ||
|
|
d5f1fcfefa | ||
|
|
234dec3d6a | ||
|
|
928be05725 | ||
|
|
bcf5a9e6cb | ||
|
|
e79bfb7bce | ||
|
|
86815b7737 | ||
|
|
73a81699ec | ||
|
|
c2970e34ba | ||
|
|
7d6a92fada | ||
|
|
acbed8e305 | ||
|
|
b46f81b6ac | ||
|
|
a284063d22 | ||
|
|
1c8cc35693 | ||
|
|
6cc7d03430 | ||
|
|
f8f97f8ad4 | ||
|
|
bd79830cb4 | ||
|
|
5ed04c3925 | ||
|
|
90fe94a417 | ||
|
|
a39021188e | ||
|
|
ba35ebae94 | ||
|
|
97f864bb76 | ||
|
|
ea15a8b832 | ||
|
|
5c1f2ad1e3 | ||
|
|
420d8d1a1b | ||
|
|
f693298f3a | ||
|
|
a29c4b01ad | ||
|
|
1b94d8d14e | ||
|
|
232b4de752 | ||
|
|
b918fa4122 | ||
|
|
83c395b866 | ||
|
|
387077882b | ||
|
|
70d895c6ed | ||
|
|
0ac4e6c220 | ||
|
|
850e43c653 | ||
|
|
1e6bd8139c | ||
|
|
c6969cf9df | ||
|
|
745c51878d | ||
|
|
9635165316 | ||
|
|
02f305be1f | ||
|
|
27197a55dc | ||
|
|
5d000a849d | ||
|
|
07341c5ffa | ||
|
|
742da904da | ||
|
|
880529ad62 | ||
|
|
126ba35d3d | ||
|
|
0039f44936 | ||
|
|
ced0853af8 | ||
|
|
3d483b5a4b | ||
|
|
96813406a2 | ||
|
|
7fa892d7cc | ||
|
|
832a08208a | ||
|
|
3bd2ad9519 | ||
|
|
7580176042 | ||
|
|
725719317a | ||
|
|
5ce276de8e | ||
|
|
d330b42dec | ||
|
|
6bf2fe0b17 | ||
|
|
eb231c5ca8 | ||
|
|
954d61b73a | ||
|
|
a2187e0134 | ||
|
|
a1cf7dba91 | ||
|
|
b8039899db | ||
|
|
26e55d7f3d | ||
|
|
1a9229a3ae | ||
|
|
ebf865e2c7 | ||
|
|
5fd146b8da | ||
|
|
3401a67959 | ||
|
|
10dad46d7c | ||
|
|
1c4983c756 | ||
|
|
f4636d9a37 | ||
|
|
46c37042a2 | ||
|
|
02df48ab4e | ||
|
|
831d48f5a3 | ||
|
|
ca42f71b0e | ||
|
|
ed4a3cb8d7 | ||
|
|
5c66d95951 | ||
|
|
44663342f4 | ||
|
|
47ee65a980 | ||
|
|
4e6207fef5 | ||
|
|
bd67b660c8 | ||
|
|
5f974c4ed2 | ||
|
|
174789930d | ||
|
|
605f4d9463 | ||
|
|
7af9c57977 | ||
|
|
874ef26f0b | ||
|
|
329fbb5a38 | ||
|
|
4be77a19ed | ||
|
|
8374c7d059 | ||
|
|
7db4715eb2 | ||
|
|
e57061b133 | ||
|
|
da615585d0 | ||
|
|
096e1b47d2 | ||
|
|
7c50487164 | ||
|
|
97c7f136bf | ||
|
|
1cddda02b1 | ||
|
|
c178eeedaa | ||
|
|
43b22e609e | ||
|
|
a914ad6dc1 | ||
|
|
b2e840cb60 | ||
|
|
d7c67ca5a8 | ||
|
|
cf7ab3861d | ||
|
|
ab4ed81cfc | ||
|
|
2022b7307e | ||
|
|
46de82a7fa | ||
|
|
bc2b2c75fa | ||
|
|
02653cd0f4 | ||
|
|
ff14879a94 | ||
|
|
49c49c46d1 | ||
|
|
915e9203ef | ||
|
|
33d295f42c | ||
|
|
91e277ce3f | ||
|
|
b7a3d35eb8 | ||
|
|
f29f11232f | ||
|
|
16ffb09350 | ||
|
|
643a129a46 | ||
|
|
de16f4f866 | ||
|
|
415d7cebfa | ||
|
|
f7d1995f63 | ||
|
|
3741abc063 | ||
|
|
54ccdd7de2 | ||
|
|
8b2e6b95b1 | ||
|
|
e86cea1e73 | ||
|
|
b81638690e | ||
|
|
20ac3abb25 | ||
|
|
f634cb06a7 | ||
|
|
7d67a481ff | ||
|
|
4659da7390 | ||
|
|
2a5d15694c | ||
|
|
8e6024c3ee | ||
|
|
f4c47daadc | ||
|
|
381bc6c0fe | ||
|
|
b5a139f81d | ||
|
|
914477da41 | ||
|
|
410802808e | ||
|
|
56dbc58d5e | ||
|
|
d7c6b2d617 | ||
|
|
80627bdde9 | ||
|
|
6595975f2b | ||
|
|
dcb8032758 | ||
|
|
fb214da5fe | ||
|
|
e20687034f | ||
|
|
f9bda99deb | ||
|
|
1d81e37a0f | ||
|
|
83f0ed5ec1 | ||
|
|
e486413872 | ||
|
|
576e167ef1 | ||
|
|
cf9e9fc209 | ||
|
|
ff0f2933d9 | ||
|
|
62467c8ddf | ||
|
|
024ab15b25 | ||
|
|
915ad52863 | ||
|
|
97bfaa9979 | ||
|
|
6ae3e154c3 | ||
|
|
49b6ff7292 | ||
|
|
903688ab43 | ||
|
|
19f822cbab | ||
|
|
1d21a14d0e | ||
|
|
4bf2ba73ad | ||
|
|
6a3972fff8 | ||
|
|
dca16238eb | ||
|
|
2b91119d00 | ||
|
|
ff4899e8d2 | ||
|
|
e818c53f1d | ||
|
|
ca96fffadf | ||
|
|
d7003711ee |
@@ -1,74 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
|
||||||
"project": {
|
|
||||||
"name": "fuse2"
|
|
||||||
},
|
|
||||||
"apps": [
|
|
||||||
{
|
|
||||||
"root": "src",
|
|
||||||
"outDir": "dist",
|
|
||||||
"assets": [
|
|
||||||
"assets",
|
|
||||||
"app/main/content/components/angular-material",
|
|
||||||
"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",
|
|
||||||
"hmr": "environments/environment.hmr.ts",
|
|
||||||
"prod": "environments/environment.prod.ts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"e2e": {
|
|
||||||
"protractor": {
|
|
||||||
"config": "./protractor.conf.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lint": [
|
|
||||||
{
|
|
||||||
"project": "src/tsconfig.app.json",
|
|
||||||
"exclude": [
|
|
||||||
"**/node_modules/**",
|
|
||||||
"**/src/app/fuse-fake-db/**/*",
|
|
||||||
"**/src/assets/angular-material-examples/**/*"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"project": "src/tsconfig.spec.json",
|
|
||||||
"exclude": [
|
|
||||||
"**/node_modules/**",
|
|
||||||
"**/src/app/fuse-fake-db/**/*",
|
|
||||||
"**/src/assets/angular-material-examples/**/*"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"project": "e2e/tsconfig.e2e.json",
|
|
||||||
"exclude": [
|
|
||||||
"**/node_modules/**",
|
|
||||||
"**/src/app/fuse-fake-db/**/*",
|
|
||||||
"**/src/assets/angular-material-examples/**/*"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"test": {
|
|
||||||
"karma": {
|
|
||||||
"config": "./karma.conf.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"defaults": {
|
|
||||||
"styleExt": "scss",
|
|
||||||
"component": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,6 @@
|
|||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
charset = utf-8
|
charset=utf-8
|
||||||
indent_style = space
|
end_of_line=lf
|
||||||
indent_size = 2
|
insert_final_newline=false
|
||||||
insert_final_newline = true
|
indent_style=space
|
||||||
trim_trailing_whitespace = true
|
indent_size=4
|
||||||
|
|
||||||
[*.md]
|
|
||||||
max_line_length = off
|
|
||||||
trim_trailing_whitespace = false
|
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -30,13 +30,10 @@
|
|||||||
/coverage
|
/coverage
|
||||||
/libpeerconnection.log
|
/libpeerconnection.log
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
testem.log
|
testem.log
|
||||||
/typings
|
/typings
|
||||||
|
|
||||||
# e2e
|
|
||||||
/e2e/*.js
|
|
||||||
/e2e/*.map
|
|
||||||
|
|
||||||
# System Files
|
# System Files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|||||||
16
CREDITS
Normal file
16
CREDITS
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Image/Vector/Icon Credits
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
Avatars - https://uifaces.co/
|
||||||
|
Flag icons - http://www.famfamfam.com/lab/icons/flags/
|
||||||
|
Frame vector created by Freepik - https://www.freepik.com/free-photos-vectors/frame
|
||||||
|
A Walk Amongst Friends - Photo by Kristin Ellis on Unsplash - https://unsplash.com/photos/CbZOGbazDWQ
|
||||||
|
Sunrise at Moraine Lake - Photo by Marlon Martinez on Unsplash - https://unsplash.com/photos/woNYcfrnp9M
|
||||||
|
Braies Lake - Photo by Luca Nicoletti on Unsplash - https://unsplash.com/photos/dH-L5zPcv3E
|
||||||
|
Lago di Sorapis - Photo by eberhard grossgasteiger on Unsplash - https://unsplash.com/photos/6uDg_zb20EM
|
||||||
|
Lago di Braies - Photo by Salmen Bejaoui on Unsplash - https://unsplash.com/photos/uXTozY3CcQg
|
||||||
|
Reaching - Photo by Justin Novello on Unsplash - https://unsplash.com/photos/Y14TNvIDllM
|
||||||
|
Yosemite - Photo by Tim Mossholder on Unsplash - https://unsplash.com/photos/ZCrtRSSUpGI
|
||||||
|
Never Stop Changing - Photo by John Westrock on Unsplash - https://unsplash.com/photos/_GY56uSG70U
|
||||||
|
Fall glow - Photo by Casey Horner on Unsplash - https://unsplash.com/photos/gz19zOdgN7w
|
||||||
|
First snow - Photo by eberhard grossgasteiger on Unsplash - https://unsplash.com/photos/LRrGf6dBjA4
|
||||||
3
LICENSE
3
LICENSE
@@ -1 +1,2 @@
|
|||||||
https://themeforest.net/licenses/terms/regular
|
This project is protected by Envato's Regular License. For more information,
|
||||||
|
check the official license page at https://themeforest.net/licenses/terms/regular
|
||||||
14
README.md
14
README.md
@@ -1,6 +1,6 @@
|
|||||||
# Fuse2
|
# Fuse - Angular
|
||||||
|
|
||||||
Material Design Admin Template with Angular 5+ and Angular Material 2
|
Material Design Admin Template with Angular 8 and Angular Material
|
||||||
|
|
||||||
## The Community
|
## The Community
|
||||||
|
|
||||||
@@ -14,11 +14,11 @@ Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app w
|
|||||||
|
|
||||||
## Code scaffolding
|
## Code scaffolding
|
||||||
|
|
||||||
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|module`.
|
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
|
||||||
|
|
||||||
## Build
|
## 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
|
## Running unit tests
|
||||||
|
|
||||||
@@ -27,4 +27,8 @@ Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.
|
|||||||
## Running end-to-end tests
|
## Running end-to-end tests
|
||||||
|
|
||||||
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
|
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).
|
||||||
|
|
||||||
|
|||||||
144
angular.json
Normal file
144
angular.json
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
|
"version": 1,
|
||||||
|
"newProjectRoot": "projects",
|
||||||
|
"projects": {
|
||||||
|
"fuse": {
|
||||||
|
"projectType": "application",
|
||||||
|
"schematics": {
|
||||||
|
"@schematics/angular:component": {
|
||||||
|
"style": "scss"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "",
|
||||||
|
"sourceRoot": "src",
|
||||||
|
"prefix": "app",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-angular:browser",
|
||||||
|
"options": {
|
||||||
|
"outputPath": "dist/fuse",
|
||||||
|
"index": "src/index.html",
|
||||||
|
"main": "src/main.ts",
|
||||||
|
"polyfills": "src/polyfills.ts",
|
||||||
|
"tsConfig": "tsconfig.app.json",
|
||||||
|
"assets": [
|
||||||
|
"src/favicon.ico",
|
||||||
|
"src/assets"
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
"src/styles.scss"
|
||||||
|
],
|
||||||
|
"scripts": [],
|
||||||
|
"showCircularDependencies": false
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"budgets": [
|
||||||
|
{
|
||||||
|
"type": "initial",
|
||||||
|
"maximumWarning": "4mb",
|
||||||
|
"maximumError": "6mb"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"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": "tsconfig.spec.json",
|
||||||
|
"karmaConfig": "karma.conf.js",
|
||||||
|
"assets": [
|
||||||
|
"src/favicon.ico",
|
||||||
|
"src/assets"
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
"src/styles.scss"
|
||||||
|
],
|
||||||
|
"scripts": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": [
|
||||||
|
"tsconfig.app.json",
|
||||||
|
"tsconfig.spec.json",
|
||||||
|
"e2e/tsconfig.json"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"**/node_modules/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"e2e": {
|
||||||
|
"builder": "@angular-devkit/build-angular:protractor",
|
||||||
|
"options": {
|
||||||
|
"protractorConfig": "e2e/protractor.conf.js",
|
||||||
|
"devServerTarget": "fuse:serve"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"devServerTarget": "fuse:serve:production"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultProject": "fuse"
|
||||||
|
}
|
||||||
12
browserslist
Normal file
12
browserslist
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||||
|
# For additional information regarding the format and rule options, please see:
|
||||||
|
# https://github.com/browserslist/browserslist#queries
|
||||||
|
|
||||||
|
# You can see what browsers were selected by your queries by running:
|
||||||
|
# npx browserslist
|
||||||
|
|
||||||
|
> 0.5%
|
||||||
|
last 2 versions
|
||||||
|
Firefox ESR
|
||||||
|
not dead
|
||||||
|
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
||||||
@@ -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 app!');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
35
e2e/protractor.conf.js
Normal file
35
e2e/protractor.conf.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// @ts-check
|
||||||
|
// Protractor configuration file, see link for more information
|
||||||
|
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
||||||
|
|
||||||
|
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type { import("protractor").Config }
|
||||||
|
*/
|
||||||
|
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.json')
|
||||||
|
});
|
||||||
|
jasmine.getEnv().addReporter(new SpecReporter({spec: {displayStacktrace: true}}));
|
||||||
|
}
|
||||||
|
};
|
||||||
23
e2e/src/app.e2e-spec.ts
Normal file
23
e2e/src/app.e2e-spec.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { FusePage } from './app.po';
|
||||||
|
import { browser, logging } from 'protractor';
|
||||||
|
|
||||||
|
describe('Fuse App', () => {
|
||||||
|
let page: FusePage;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
page = new FusePage();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display welcome message', () => {
|
||||||
|
page.navigateTo();
|
||||||
|
expect(page.getParagraphText()).toEqual('Welcome to Fuse!');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
// Assert that there are no errors emitted from the browser
|
||||||
|
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
||||||
|
expect(logs).not.toContain(jasmine.objectContaining({
|
||||||
|
level: logging.Level.SEVERE
|
||||||
|
} as logging.Entry));
|
||||||
|
});
|
||||||
|
});
|
||||||
14
e2e/src/app.po.ts
Normal file
14
e2e/src/app.po.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { browser, by, element } from 'protractor';
|
||||||
|
|
||||||
|
export class FusePage
|
||||||
|
{
|
||||||
|
navigateTo(): Promise<any>
|
||||||
|
{
|
||||||
|
return browser.get('/') as Promise<any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
getParagraphText(): Promise<string>
|
||||||
|
{
|
||||||
|
return element(by.css('app #main')).getText() as Promise<string>;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
{
|
{
|
||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "../out-tsc/e2e",
|
"outDir": "../out-tsc/app",
|
||||||
"baseUrl": "./",
|
"module": "commonjs",
|
||||||
"module": "commonjs",
|
"target": "es5",
|
||||||
"target": "es5",
|
"types": [
|
||||||
"types": [
|
"jasmine",
|
||||||
"jasmine",
|
"jasminewd2",
|
||||||
"jasminewd2",
|
"node"
|
||||||
"node"
|
]
|
||||||
]
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,13 @@
|
|||||||
{
|
{
|
||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "../out-tsc/spec",
|
"outDir": "../out-tsc/e2e",
|
||||||
"baseUrl": "./",
|
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"types": [
|
"types": [
|
||||||
"jasmine",
|
"jasmine",
|
||||||
|
"jasminewd2",
|
||||||
"node"
|
"node"
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
"files": [
|
|
||||||
"test.ts"
|
|
||||||
],
|
|
||||||
"include": [
|
|
||||||
"**/*.spec.ts",
|
|
||||||
"**/*.d.ts"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
@@ -1,33 +1,33 @@
|
|||||||
// Karma configuration file, see link for more information
|
// Karma configuration file, see link for more information
|
||||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||||
|
|
||||||
module.exports = function (config) {
|
module.exports = function (config)
|
||||||
|
{
|
||||||
config.set({
|
config.set({
|
||||||
basePath: '',
|
basePath : '',
|
||||||
frameworks: ['jasmine', '@angular/cli'],
|
frameworks : ['jasmine', '@angular-devkit/build-angular'],
|
||||||
plugins: [
|
plugins : [
|
||||||
require('karma-jasmine'),
|
require('karma-jasmine'),
|
||||||
require('karma-chrome-launcher'),
|
require('karma-chrome-launcher'),
|
||||||
require('karma-jasmine-html-reporter'),
|
require('karma-jasmine-html-reporter'),
|
||||||
require('karma-coverage-istanbul-reporter'),
|
require('karma-coverage-istanbul-reporter'),
|
||||||
require('@angular/cli/plugins/karma')
|
require('@angular-devkit/build-angular/plugins/karma')
|
||||||
],
|
],
|
||||||
client:{
|
client : {
|
||||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||||
},
|
},
|
||||||
coverageIstanbulReporter: {
|
coverageIstanbulReporter: {
|
||||||
reports: [ 'html', 'lcovonly' ],
|
dir : require('path').join(__dirname, './coverage/fuse'),
|
||||||
|
reports : ['html', 'lcovonly', 'text-summary'],
|
||||||
fixWebpackSourcePaths: true
|
fixWebpackSourcePaths: true
|
||||||
},
|
},
|
||||||
angularCli: {
|
reporters : ['progress', 'kjhtml'],
|
||||||
environment: 'dev'
|
port : 9876,
|
||||||
},
|
colors : true,
|
||||||
reporters: ['progress', 'kjhtml'],
|
logLevel : config.LOG_INFO,
|
||||||
port: 9876,
|
autoWatch : true,
|
||||||
colors: true,
|
browsers : ['Chrome'],
|
||||||
logLevel: config.LOG_INFO,
|
singleRun : false,
|
||||||
autoWatch: true,
|
restartOnFileChange : true
|
||||||
browsers: ['Chrome'],
|
|
||||||
singleRun: false
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
23712
package-lock.json
generated
23712
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
169
package.json
169
package.json
@@ -1,85 +1,88 @@
|
|||||||
{
|
{
|
||||||
"name": "fuse",
|
"name": "fuse",
|
||||||
"version": "5.2.8",
|
"version": "8.1.2",
|
||||||
"license": "https://themeforest.net/licenses/terms/regular",
|
"license": "https://themeforest.net/licenses/terms/regular",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"start": "ng serve --open",
|
"start": "ng serve --open",
|
||||||
"start-hmr": "ng serve --hmr -e=hmr -sm=false",
|
"start-hmr": "ng serve --configuration hmr --source-map=false --hmr-warning=false",
|
||||||
"start-hmr-sourcemaps": "ng serve --hmr -e=hmr",
|
"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": "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-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": "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",
|
"build-prod-stats": "node --max_old_space_size=6144 ./node_modules/@angular/cli/bin/ng build --prod --stats-json",
|
||||||
"test": "ng test",
|
"test": "ng test",
|
||||||
"lint": "ng lint",
|
"lint": "ng lint",
|
||||||
"e2e": "ng e2e",
|
"e2e": "ng e2e",
|
||||||
"bundle-report": "webpack-bundle-analyzer dist/stats.json"
|
"bundle-report": "webpack-bundle-analyzer dist/stats.json"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@agm/core": "1.0.0-beta.2",
|
"@agm/core": "1.0.0-beta.7",
|
||||||
"@angular/animations": "5.2.8",
|
"@angular/animations": "8.1.2",
|
||||||
"@angular/cdk": "5.2.4",
|
"@angular/cdk": "8.1.1",
|
||||||
"@angular/common": "5.2.8",
|
"@angular/common": "8.1.2",
|
||||||
"@angular/compiler": "5.2.8",
|
"@angular/compiler": "8.1.2",
|
||||||
"@angular/core": "5.2.8",
|
"@angular/core": "8.1.2",
|
||||||
"@angular/flex-layout": "5.0.0-beta.13",
|
"@angular/flex-layout": "8.0.0-beta.26",
|
||||||
"@angular/forms": "5.2.8",
|
"@angular/forms": "8.1.2",
|
||||||
"@angular/http": "5.2.8",
|
"@angular/material": "8.1.1",
|
||||||
"@angular/material": "5.2.4",
|
"@angular/material-moment-adapter": "8.1.1",
|
||||||
"@angular/material-moment-adapter": "5.2.4",
|
"@angular/platform-browser": "8.1.2",
|
||||||
"@angular/platform-browser": "5.2.8",
|
"@angular/platform-browser-dynamic": "8.1.2",
|
||||||
"@angular/platform-browser-dynamic": "5.2.8",
|
"@angular/router": "8.1.2",
|
||||||
"@angular/router": "5.2.8",
|
"@ngrx/effects": "8.1.0",
|
||||||
"@ngrx/effects": "5.2.0",
|
"@ngrx/router-store": "8.1.0",
|
||||||
"@ngrx/router-store": "5.2.0",
|
"@ngrx/store": "8.1.0",
|
||||||
"@ngrx/store": "5.2.0",
|
"@ngrx/store-devtools": "8.1.0",
|
||||||
"@ngrx/store-devtools": "5.2.0",
|
"@ngx-translate/core": "11.0.1",
|
||||||
"@ngx-translate/core": "9.1.1",
|
"@swimlane/dragula": "3.8.0",
|
||||||
"@swimlane/ngx-charts": "7.1.1",
|
"@swimlane/ngx-charts": "12.0.1",
|
||||||
"@swimlane/ngx-datatable": "11.2.0",
|
"@swimlane/ngx-datatable": "15.0.2",
|
||||||
"@swimlane/ngx-dnd": "3.1.0",
|
"@swimlane/ngx-dnd": "8.0.0",
|
||||||
"@types/prismjs": "1.9.0",
|
"@types/prismjs": "1.16.0",
|
||||||
"angular-calendar": "0.23.6",
|
"angular-calendar": "0.27.13",
|
||||||
"angular-in-memory-web-api": "0.5.3",
|
"angular-in-memory-web-api": "0.8.0",
|
||||||
"chart.js": "2.7.2",
|
"chart.js": "2.8.0",
|
||||||
"classlist.js": "1.1.20150312",
|
"classlist.js": "1.1.20150312",
|
||||||
"core-js": "2.5.3",
|
"d3": "5.9.7",
|
||||||
"d3": "4.13.0",
|
"date-fns": "1.30.1",
|
||||||
"hammerjs": "2.0.8",
|
"hammerjs": "2.0.8",
|
||||||
"intl": "1.2.5",
|
"lodash": "4.17.15",
|
||||||
"moment": "2.21.0",
|
"moment": "2.24.0",
|
||||||
"ng2-charts": "1.6.0",
|
"ng2-charts": "2.3.0",
|
||||||
"ngrx-store-freeze": "0.2.1",
|
"ngrx-store-freeze": "0.2.4",
|
||||||
"ngx-color-picker": "5.3.4",
|
"ngx-color-picker": "8.1.0",
|
||||||
"ngx-cookie-service": "1.0.10",
|
"ngx-cookie-service": "2.2.0",
|
||||||
"perfect-scrollbar": "1.3.0",
|
"perfect-scrollbar": "1.4.0",
|
||||||
"prismjs": "1.11.0",
|
"prismjs": "1.16.0",
|
||||||
"rxjs": "5.5.6",
|
"rxjs": "6.5.2",
|
||||||
"web-animations-js": "2.3.1",
|
"web-animations-js": "2.3.2",
|
||||||
"zone.js": "0.8.20"
|
"zone.js": "0.9.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular/cli": "1.7.3",
|
"@angular/cli": "8.1.2",
|
||||||
"@angular/compiler-cli": "5.2.8",
|
"@angular/compiler-cli": "8.1.2",
|
||||||
"@angular/language-service": "5.2.8",
|
"@angular/language-service": "8.1.2",
|
||||||
"@angularclass/hmr": "2.1.3",
|
"@angular-devkit/build-angular": "0.801.2",
|
||||||
"@types/jasmine": "2.8.6",
|
"@angularclass/hmr": "2.1.3",
|
||||||
"@types/jasminewd2": "2.0.3",
|
"@types/jasmine": "3.3.14",
|
||||||
"@types/node": "6.0.101",
|
"@types/jasminewd2": "2.0.6",
|
||||||
"codelyzer": "4.2.1",
|
"@types/lodash": "4.14.136",
|
||||||
"jasmine-core": "2.8.0",
|
"@types/node": "8.9.5",
|
||||||
"jasmine-spec-reporter": "4.2.1",
|
"codelyzer": "5.1.0",
|
||||||
"karma": "2.0.0",
|
"jasmine-core": "3.4.0",
|
||||||
"karma-chrome-launcher": "2.2.0",
|
"jasmine-spec-reporter": "4.2.1",
|
||||||
"karma-coverage-istanbul-reporter": "1.4.2",
|
"karma": "4.1.0",
|
||||||
"karma-jasmine": "1.1.1",
|
"karma-chrome-launcher": "2.2.0",
|
||||||
"karma-jasmine-html-reporter": "0.2.2",
|
"karma-coverage-istanbul-reporter": "2.0.5",
|
||||||
"protractor": "5.1.2",
|
"karma-jasmine": "2.0.1",
|
||||||
"ts-node": "4.1.0",
|
"karma-jasmine-html-reporter": "1.4.2",
|
||||||
"tslint": "5.9.1",
|
"protractor": "5.4.2",
|
||||||
"typescript": "2.6.2",
|
"ts-node": "7.0.1",
|
||||||
"webpack-bundle-analyzer": "2.11.1"
|
"tslib": "1.10.0",
|
||||||
}
|
"tslint": "5.15.0",
|
||||||
|
"typescript": "3.4.5",
|
||||||
|
"webpack-bundle-analyzer": "3.3.2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +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: [
|
|
||||||
'./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 } }));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -51,26 +51,23 @@ export const fuseAnimations = [
|
|||||||
]),
|
]),
|
||||||
|
|
||||||
trigger('fadeInOut', [
|
trigger('fadeInOut', [
|
||||||
state('0', style({
|
state('0, void', style({
|
||||||
display: 'none',
|
|
||||||
opacity: 0
|
opacity: 0
|
||||||
})),
|
})),
|
||||||
state('1', style({
|
state('1, *', style({
|
||||||
display: 'block',
|
|
||||||
opacity: 1
|
opacity: 1
|
||||||
})),
|
})),
|
||||||
transition('1 => 0', animate('300ms ease-out')),
|
transition('1 => 0', animate('300ms ease-out')),
|
||||||
transition('0 => 1', animate('300ms ease-in'))
|
transition('0 => 1', animate('300ms ease-in')),
|
||||||
|
transition('void <=> *', animate('300ms ease-in'))
|
||||||
]),
|
]),
|
||||||
|
|
||||||
trigger('slideInOut', [
|
trigger('slideInOut', [
|
||||||
state('0', style({
|
state('0', style({
|
||||||
height : '0px',
|
height: '0px'
|
||||||
display: 'none'
|
|
||||||
})),
|
})),
|
||||||
state('1', style({
|
state('1', style({
|
||||||
height : '*',
|
height: '*'
|
||||||
display: 'block'
|
|
||||||
})),
|
})),
|
||||||
transition('1 => 0', animate('300ms ease-out')),
|
transition('1 => 0', animate('300ms ease-out')),
|
||||||
transition('0 => 1', animate('300ms ease-in'))
|
transition('0 => 1', animate('300ms ease-in'))
|
||||||
@@ -120,17 +117,15 @@ export const fuseAnimations = [
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
),
|
)
|
||||||
]),
|
]),
|
||||||
|
|
||||||
trigger('slideInLeft', [
|
trigger('slideInLeft', [
|
||||||
state('void', style({
|
state('void', style({
|
||||||
transform: 'translateX(-100%)',
|
transform: 'translateX(-100%)',
|
||||||
display : 'none'
|
|
||||||
})),
|
})),
|
||||||
state('*', style({
|
state('*', style({
|
||||||
transform: 'translateX(0)',
|
transform: 'translateX(0)',
|
||||||
display : 'flex'
|
|
||||||
})),
|
})),
|
||||||
transition('void => *', animate('300ms')),
|
transition('void => *', animate('300ms')),
|
||||||
transition('* => void', animate('300ms'))
|
transition('* => void', animate('300ms'))
|
||||||
@@ -139,11 +134,9 @@ export const fuseAnimations = [
|
|||||||
trigger('slideInRight', [
|
trigger('slideInRight', [
|
||||||
state('void', style({
|
state('void', style({
|
||||||
transform: 'translateX(100%)',
|
transform: 'translateX(100%)',
|
||||||
display : 'none'
|
|
||||||
})),
|
})),
|
||||||
state('*', style({
|
state('*', style({
|
||||||
transform: 'translateX(0)',
|
transform: 'translateX(0)',
|
||||||
display : 'flex'
|
|
||||||
})),
|
})),
|
||||||
transition('void => *', animate('300ms')),
|
transition('void => *', animate('300ms')),
|
||||||
transition('* => void', animate('300ms'))
|
transition('* => void', animate('300ms'))
|
||||||
@@ -152,11 +145,9 @@ export const fuseAnimations = [
|
|||||||
trigger('slideInTop', [
|
trigger('slideInTop', [
|
||||||
state('void', style({
|
state('void', style({
|
||||||
transform: 'translateY(-100%)',
|
transform: 'translateY(-100%)',
|
||||||
display : 'none'
|
|
||||||
})),
|
})),
|
||||||
state('*', style({
|
state('*', style({
|
||||||
transform: 'translateY(0)',
|
transform: 'translateY(0)',
|
||||||
display : 'flex'
|
|
||||||
})),
|
})),
|
||||||
transition('void => *', animate('300ms')),
|
transition('void => *', animate('300ms')),
|
||||||
transition('* => void', animate('300ms'))
|
transition('* => void', animate('300ms'))
|
||||||
@@ -166,11 +157,9 @@ export const fuseAnimations = [
|
|||||||
state('void',
|
state('void',
|
||||||
style({
|
style({
|
||||||
transform: 'translateY(100%)',
|
transform: 'translateY(100%)',
|
||||||
display : 'none'
|
|
||||||
})),
|
})),
|
||||||
state('*', style({
|
state('*', style({
|
||||||
transform: 'translateY(0)',
|
transform: 'translateY(0)',
|
||||||
display : 'flex'
|
|
||||||
})),
|
})),
|
||||||
transition('void => *', animate('300ms')),
|
transition('void => *', animate('300ms')),
|
||||||
transition('* => void', animate('300ms'))
|
transition('* => void', animate('300ms'))
|
||||||
@@ -187,10 +176,14 @@ export const fuseAnimations = [
|
|||||||
transition('* => void', animate('300ms ease-in'))
|
transition('* => void', animate('300ms ease-in'))
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Router animations
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
trigger('routerTransitionLeft', [
|
trigger('routerTransitionLeft', [
|
||||||
|
|
||||||
transition('* => *', [
|
transition('* => *', [
|
||||||
query('fuse-content > :enter, fuse-content > :leave', [
|
query('content > :enter, content > :leave', [
|
||||||
style({
|
style({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top : 0,
|
top : 0,
|
||||||
@@ -199,7 +192,7 @@ export const fuseAnimations = [
|
|||||||
right : 0
|
right : 0
|
||||||
})
|
})
|
||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
query('fuse-content > :enter', [
|
query('content > :enter', [
|
||||||
style({
|
style({
|
||||||
transform: 'translateX(100%)',
|
transform: 'translateX(100%)',
|
||||||
opacity : 0
|
opacity : 0
|
||||||
@@ -207,7 +200,7 @@ export const fuseAnimations = [
|
|||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
sequence([
|
sequence([
|
||||||
group([
|
group([
|
||||||
query('fuse-content > :leave', [
|
query('content > :leave', [
|
||||||
style({
|
style({
|
||||||
transform: 'translateX(0)',
|
transform: 'translateX(0)',
|
||||||
opacity : 1
|
opacity : 1
|
||||||
@@ -218,7 +211,7 @@ export const fuseAnimations = [
|
|||||||
opacity : 0
|
opacity : 0
|
||||||
}))
|
}))
|
||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
query('fuse-content > :enter', [
|
query('content > :enter', [
|
||||||
style({transform: 'translateX(100%)'}),
|
style({transform: 'translateX(100%)'}),
|
||||||
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
||||||
style({
|
style({
|
||||||
@@ -227,8 +220,8 @@ export const fuseAnimations = [
|
|||||||
}))
|
}))
|
||||||
], {optional: true})
|
], {optional: true})
|
||||||
]),
|
]),
|
||||||
query('fuse-content > :leave', animateChild(), {optional: true}),
|
query('content > :leave', animateChild(), {optional: true}),
|
||||||
query('fuse-content > :enter', animateChild(), {optional: true})
|
query('content > :enter', animateChild(), {optional: true})
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
@@ -236,7 +229,7 @@ export const fuseAnimations = [
|
|||||||
trigger('routerTransitionRight', [
|
trigger('routerTransitionRight', [
|
||||||
|
|
||||||
transition('* => *', [
|
transition('* => *', [
|
||||||
query('fuse-content > :enter, fuse-content > :leave', [
|
query('content > :enter, content > :leave', [
|
||||||
style({
|
style({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top : 0,
|
top : 0,
|
||||||
@@ -245,7 +238,7 @@ export const fuseAnimations = [
|
|||||||
right : 0
|
right : 0
|
||||||
})
|
})
|
||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
query('fuse-content > :enter', [
|
query('content > :enter', [
|
||||||
style({
|
style({
|
||||||
transform: 'translateX(-100%)',
|
transform: 'translateX(-100%)',
|
||||||
opacity : 0
|
opacity : 0
|
||||||
@@ -253,7 +246,7 @@ export const fuseAnimations = [
|
|||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
sequence([
|
sequence([
|
||||||
group([
|
group([
|
||||||
query('fuse-content > :leave', [
|
query('content > :leave', [
|
||||||
style({
|
style({
|
||||||
transform: 'translateX(0)',
|
transform: 'translateX(0)',
|
||||||
opacity : 1
|
opacity : 1
|
||||||
@@ -264,7 +257,7 @@ export const fuseAnimations = [
|
|||||||
opacity : 0
|
opacity : 0
|
||||||
}))
|
}))
|
||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
query('fuse-content > :enter', [
|
query('content > :enter', [
|
||||||
style({transform: 'translateX(-100%)'}),
|
style({transform: 'translateX(-100%)'}),
|
||||||
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
||||||
style({
|
style({
|
||||||
@@ -273,8 +266,8 @@ export const fuseAnimations = [
|
|||||||
}))
|
}))
|
||||||
], {optional: true})
|
], {optional: true})
|
||||||
]),
|
]),
|
||||||
query('fuse-content > :leave', animateChild(), {optional: true}),
|
query('content > :leave', animateChild(), {optional: true}),
|
||||||
query('fuse-content > :enter', animateChild(), {optional: true})
|
query('content > :enter', animateChild(), {optional: true})
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
@@ -282,7 +275,7 @@ export const fuseAnimations = [
|
|||||||
trigger('routerTransitionUp', [
|
trigger('routerTransitionUp', [
|
||||||
|
|
||||||
transition('* => *', [
|
transition('* => *', [
|
||||||
query('fuse-content > :enter, fuse-content > :leave', [
|
query('content > :enter, content > :leave', [
|
||||||
style({
|
style({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top : 0,
|
top : 0,
|
||||||
@@ -291,14 +284,14 @@ export const fuseAnimations = [
|
|||||||
right : 0
|
right : 0
|
||||||
})
|
})
|
||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
query('fuse-content > :enter', [
|
query('content > :enter', [
|
||||||
style({
|
style({
|
||||||
transform: 'translateY(100%)',
|
transform: 'translateY(100%)',
|
||||||
opacity : 0
|
opacity : 0
|
||||||
})
|
})
|
||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
group([
|
group([
|
||||||
query('fuse-content > :leave', [
|
query('content > :leave', [
|
||||||
style({
|
style({
|
||||||
transform: 'translateY(0)',
|
transform: 'translateY(0)',
|
||||||
opacity : 1
|
opacity : 1
|
||||||
@@ -309,7 +302,7 @@ export const fuseAnimations = [
|
|||||||
opacity : 0
|
opacity : 0
|
||||||
}))
|
}))
|
||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
query('fuse-content > :enter', [
|
query('content > :enter', [
|
||||||
style({transform: 'translateY(100%)'}),
|
style({transform: 'translateY(100%)'}),
|
||||||
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
||||||
style({
|
style({
|
||||||
@@ -318,15 +311,15 @@ export const fuseAnimations = [
|
|||||||
}))
|
}))
|
||||||
], {optional: true})
|
], {optional: true})
|
||||||
]),
|
]),
|
||||||
query('fuse-content > :leave', animateChild(), {optional: true}),
|
query('content > :leave', animateChild(), {optional: true}),
|
||||||
query('fuse-content > :enter', animateChild(), {optional: true})
|
query('content > :enter', animateChild(), {optional: true})
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
|
|
||||||
trigger('routerTransitionDown', [
|
trigger('routerTransitionDown', [
|
||||||
|
|
||||||
transition('* => *', [
|
transition('* => *', [
|
||||||
query('fuse-content > :enter, fuse-content > :leave', [
|
query('content > :enter, content > :leave', [
|
||||||
style({
|
style({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top : 0,
|
top : 0,
|
||||||
@@ -335,7 +328,7 @@ export const fuseAnimations = [
|
|||||||
right : 0
|
right : 0
|
||||||
})
|
})
|
||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
query('fuse-content > :enter', [
|
query('content > :enter', [
|
||||||
style({
|
style({
|
||||||
transform: 'translateY(-100%)',
|
transform: 'translateY(-100%)',
|
||||||
opacity : 0
|
opacity : 0
|
||||||
@@ -343,7 +336,7 @@ export const fuseAnimations = [
|
|||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
sequence([
|
sequence([
|
||||||
group([
|
group([
|
||||||
query('fuse-content > :leave', [
|
query('content > :leave', [
|
||||||
style({
|
style({
|
||||||
transform: 'translateY(0)',
|
transform: 'translateY(0)',
|
||||||
opacity : 1
|
opacity : 1
|
||||||
@@ -354,7 +347,7 @@ export const fuseAnimations = [
|
|||||||
opacity : 0
|
opacity : 0
|
||||||
}))
|
}))
|
||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
query('fuse-content > :enter', [
|
query('content > :enter', [
|
||||||
style({transform: 'translateY(-100%)'}),
|
style({transform: 'translateY(-100%)'}),
|
||||||
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
animate('600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
||||||
style({
|
style({
|
||||||
@@ -363,8 +356,8 @@ export const fuseAnimations = [
|
|||||||
}))
|
}))
|
||||||
], {optional: true})
|
], {optional: true})
|
||||||
]),
|
]),
|
||||||
query('fuse-content > :leave', animateChild(), {optional: true}),
|
query('content > :leave', animateChild(), {optional: true}),
|
||||||
query('fuse-content > :enter', animateChild(), {optional: true})
|
query('content > :enter', animateChild(), {optional: true})
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
@@ -373,7 +366,7 @@ export const fuseAnimations = [
|
|||||||
|
|
||||||
transition('* => *', group([
|
transition('* => *', group([
|
||||||
|
|
||||||
query('fuse-content > :enter, fuse-content > :leave ', [
|
query('content > :enter, content > :leave ', [
|
||||||
style({
|
style({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top : 0,
|
top : 0,
|
||||||
@@ -383,12 +376,12 @@ export const fuseAnimations = [
|
|||||||
})
|
})
|
||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
|
|
||||||
query('fuse-content > :enter', [
|
query('content > :enter', [
|
||||||
style({
|
style({
|
||||||
opacity: 0
|
opacity: 0
|
||||||
})
|
})
|
||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
query('fuse-content > :leave', [
|
query('content > :leave', [
|
||||||
style({
|
style({
|
||||||
opacity: 1
|
opacity: 1
|
||||||
}),
|
}),
|
||||||
@@ -397,7 +390,7 @@ export const fuseAnimations = [
|
|||||||
opacity: 0
|
opacity: 0
|
||||||
}))
|
}))
|
||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
query('fuse-content > :enter', [
|
query('content > :enter', [
|
||||||
style({
|
style({
|
||||||
opacity: 0
|
opacity: 0
|
||||||
}),
|
}),
|
||||||
@@ -406,8 +399,8 @@ export const fuseAnimations = [
|
|||||||
opacity: 1
|
opacity: 1
|
||||||
}))
|
}))
|
||||||
], {optional: true}),
|
], {optional: true}),
|
||||||
query('fuse-content > :enter', animateChild(), {optional: true}),
|
query('content > :enter', animateChild(), {optional: true}),
|
||||||
query('fuse-content > :leave', animateChild(), {optional: true})
|
query('content > :leave', animateChild(), {optional: true})
|
||||||
]))
|
]))
|
||||||
])
|
])
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { MatDialogRef } from '@angular/material';
|
import { MatDialogRef } from '@angular/material/dialog';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector : 'fuse-confirm-dialog',
|
selector : 'fuse-confirm-dialog',
|
||||||
@@ -10,7 +10,14 @@ export class FuseConfirmDialogComponent
|
|||||||
{
|
{
|
||||||
public confirmMessage: string;
|
public confirmMessage: string;
|
||||||
|
|
||||||
constructor(public dialogRef: MatDialogRef<FuseConfirmDialogComponent>)
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param {MatDialogRef<FuseConfirmDialogComponent>} dialogRef
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
public dialogRef: MatDialogRef<FuseConfirmDialogComponent>
|
||||||
|
)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { MatButtonModule, MatDialogModule } from '@angular/material';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
|
|
||||||
import { FuseConfirmDialogComponent } from '@fuse/components/confirm-dialog/confirm-dialog.component';
|
import { FuseConfirmDialogComponent } from '@fuse/components/confirm-dialog/confirm-dialog.component';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
:host {
|
fuse-countdown {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -1,55 +1,110 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { interval, Subject } from 'rxjs';
|
||||||
import 'rxjs/add/observable/interval';
|
import { map, takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector : 'fuse-countdown',
|
selector : 'fuse-countdown',
|
||||||
templateUrl: './countdown.component.html',
|
templateUrl: './countdown.component.html',
|
||||||
styleUrls : ['./countdown.component.scss']
|
styleUrls : ['./countdown.component.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class FuseCountdownComponent implements OnInit
|
export class FuseCountdownComponent implements OnInit, OnDestroy
|
||||||
{
|
{
|
||||||
@Input('eventDate') eventDate;
|
// Event date
|
||||||
|
@Input('eventDate')
|
||||||
|
eventDate;
|
||||||
|
|
||||||
countdown: any;
|
countdown: any;
|
||||||
|
|
||||||
|
// Private
|
||||||
|
private _unsubscribeAll: Subject<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
constructor()
|
constructor()
|
||||||
{
|
{
|
||||||
|
// Set the defaults
|
||||||
this.countdown = {
|
this.countdown = {
|
||||||
days : '',
|
days : '',
|
||||||
hours : '',
|
hours : '',
|
||||||
minutes: '',
|
minutes: '',
|
||||||
seconds: ''
|
seconds: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Set the private defaults
|
||||||
|
this._unsubscribeAll = new Subject();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit()
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Lifecycle hooks
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On init
|
||||||
|
*/
|
||||||
|
ngOnInit(): void
|
||||||
{
|
{
|
||||||
const currDate = moment();
|
const currDate = moment();
|
||||||
const eventDate = moment(this.eventDate);
|
const eventDate = moment(this.eventDate);
|
||||||
|
|
||||||
|
// Get the difference in between the current date and event date in seconds
|
||||||
let diff = eventDate.diff(currDate, 'seconds');
|
let diff = eventDate.diff(currDate, 'seconds');
|
||||||
|
|
||||||
const countDown =
|
// Calculate the remaining time for the first time so there will be no
|
||||||
Observable
|
// delay on the countdown
|
||||||
.interval(1000)
|
this.countdown = this._secondsToRemaining(diff);
|
||||||
.map(value => {
|
|
||||||
return diff = diff - 1;
|
|
||||||
})
|
|
||||||
.map(value => {
|
|
||||||
const timeLeft = moment.duration(value, 'seconds');
|
|
||||||
|
|
||||||
return {
|
// Create a subscribable interval
|
||||||
days : timeLeft.asDays().toFixed(0),
|
const countDown = interval(1000)
|
||||||
hours : timeLeft.hours(),
|
.pipe(
|
||||||
minutes: timeLeft.minutes(),
|
map(value => {
|
||||||
seconds: timeLeft.seconds()
|
return diff = diff - 1;
|
||||||
};
|
}),
|
||||||
});
|
map(value => {
|
||||||
|
return this._secondsToRemaining(value);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
countDown.subscribe(value => {
|
// Subscribe to the countdown interval
|
||||||
this.countdown = value;
|
countDown
|
||||||
});
|
.pipe(takeUntil(this._unsubscribeAll))
|
||||||
|
.subscribe(value => {
|
||||||
|
this.countdown = value;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On destroy
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void
|
||||||
|
{
|
||||||
|
// Unsubscribe from all subscriptions
|
||||||
|
this._unsubscribeAll.next();
|
||||||
|
this._unsubscribeAll.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Private methods
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts given seconds to a remaining time
|
||||||
|
*
|
||||||
|
* @param seconds
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private _secondsToRemaining(seconds): any
|
||||||
|
{
|
||||||
|
const timeLeft = moment.duration(seconds, 'seconds');
|
||||||
|
|
||||||
|
return {
|
||||||
|
days : timeLeft.asDays().toFixed(0),
|
||||||
|
hours : timeLeft.hours(),
|
||||||
|
minutes: timeLeft.minutes(),
|
||||||
|
seconds: timeLeft.seconds()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/@fuse/components/countdown/countdown.theme.scss
Normal file
17
src/@fuse/components/countdown/countdown.theme.scss
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
@mixin fuse-countdown-theme($theme) {
|
||||||
|
|
||||||
|
$foreground: map-get($theme, foreground);
|
||||||
|
|
||||||
|
fuse-countdown {
|
||||||
|
|
||||||
|
.fuse-countdown {
|
||||||
|
|
||||||
|
.time {
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: map-get($foreground, secondary-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
<!-- DEMO CONTENT -->
|
<!-- DEMO CONTENT -->
|
||||||
<div class="demo-content">
|
<div class="demo-content line-height-1.75">
|
||||||
|
|
||||||
<img src="assets/images/beach.jpg" alt="beach" style="max-width: 640px; width: 100%;">
|
<h1 class="m-0">Early Sunrise in Winter</h1>
|
||||||
|
<h4 class="mt-0 secondary-text">Demo Content</h4>
|
||||||
<h1>Early Sunrise</h1>
|
|
||||||
<h4 class="secondary-text">Demo Content</h4>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse tortor nibh, convallis sed purus nec,
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse tortor nibh, convallis sed purus nec,
|
||||||
@@ -12,7 +10,7 @@
|
|||||||
vestibulum. Suspendisse euismod in urna eu posuere.
|
vestibulum. Suspendisse euismod in urna eu posuere.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<blockquote>
|
<blockquote class="my-24">
|
||||||
<p>
|
<p>
|
||||||
Nunc vel lacinia lorem. Nullam tincidunt sed purus eu placerat. Donec id dictum erat. Etiam enim ex, dapibus
|
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
|
et tortor id, posuere pretium est. Maecenas fringilla ipsum vitae neque elementum, at eleifend ante
|
||||||
@@ -24,16 +22,12 @@
|
|||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Ut ornare sit amet velit vel congue. Ut nec tristique eros. Lorem ipsum dolor sit amet, consectetur adipiscing
|
Ut ornare sit amet velit vel congue. Ut nec tristique eros. Lorem ipsum dolor sit amet, consectetur
|
||||||
elit. Vivamus sed lorem quis nibh porta iaculis. Vestibulum ut eleifend ante, at semper mi. Nam imperdiet est
|
<b>adipiscing elit</b>. Vivamus sed lorem quis nibh porta iaculis. Vestibulum ut eleifend ante, at semper mi.
|
||||||
nisi, quis hendrerit tellus convallis et. Morbi in luctus neque. Curabitur elementum ut est et gravida. In hac
|
Nam imperdiet est nisi, quis hendrerit tellus convallis et. Morbi in luctus neque. Curabitur elementum ut est et
|
||||||
habitasse platea dictumst.
|
gravida. In hac habitasse platea dictumst. In et placerat eros, eu tempor turpis. Curabitur ac felis finibus,
|
||||||
</p>
|
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>
|
|
||||||
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>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@@ -43,6 +37,12 @@
|
|||||||
velit.
|
velit.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<img class="mt-24 w-100-p" src="assets/images/demo-content/morain-lake.jpg" style="max-width: 640px">
|
||||||
|
|
||||||
|
<p class="mt-8 mb-24 secondary-text">
|
||||||
|
<em>Nullam tincidunt sed purus eu placerat. Donec id dictum erat. Etiam enim ex, dapibus et tortor id.</em>
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Quisque sit amet risus enim. Aliquam sit amet interdum justo, at ultricies sapien. Suspendisse et semper urna,
|
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
|
in gravida eros. Quisque id nibh iaculis, euismod urna sed, egestas nisi. Donec eros metus, congue a imperdiet
|
||||||
@@ -52,10 +52,18 @@
|
|||||||
<p>
|
<p>
|
||||||
Ut auctor, metus sed dapibus tempus, urna diam auctor odio, in malesuada odio risus vitae nisi. Etiam blandit
|
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
|
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
|
sagittis augue. Sed venenatis rhoncus enim eget ornare. <a href="#">Donec viverra sed felis at venenatis.</a>
|
||||||
fringilla nulla, sit amet congue felis dignissim at.
|
Mauris aliquam fringilla nulla, sit amet congue felis dignissim at.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Orci varius</li>
|
||||||
|
<li>Magnis dis</li>
|
||||||
|
<li>Conubia nostra</li>
|
||||||
|
<li>Semper urna</li>
|
||||||
|
<li>Donec viverra</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Quisque accumsan augue tempor ante mollis, sed placerat diam porttitor. Vestibulum dignissim sem vel velit
|
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
|
eleifend, non pellentesque quam convallis. Pellentesque est dolor, dignissim ac tortor tristique, hendrerit
|
||||||
@@ -69,7 +77,7 @@
|
|||||||
Etiam blandit nunc arcu, et consectetur orci blandit a. Aliquam condimentum pharetra quam at ultricies. Nunc vel
|
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
|
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
|
id, posuere pretium est. Maecenas fringilla ipsum vitae neque elementum, at eleifend ante sollicitudin. Donec
|
||||||
viverra augue dolor, a venenatis tellus consectetur sit amet...
|
viverra augue dolor, a venenatis tellus consectetur sit amet.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<!-- / DEMO CONTENT -->
|
<!-- / DEMO CONTENT -->
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import { Component } from '@angular/core';
|
|||||||
})
|
})
|
||||||
export class FuseDemoContentComponent
|
export class FuseDemoContentComponent
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
constructor()
|
constructor()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,99 +1,99 @@
|
|||||||
<div class="demo-sidenav">
|
<div class="demo-sidebar">
|
||||||
<mat-list>
|
<mat-list>
|
||||||
<h3 matSubheader>Sidenav Demo</h3>
|
<h3 matSubheader>Sidebar Demo</h3>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 1</span>
|
<span>Sidebar Item 1</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 2</span>
|
<span>Sidebar Item 2</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 3</span>
|
<span>Sidebar Item 3</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 4</span>
|
<span>Sidebar Item 4</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 5</span>
|
<span>Sidebar Item 5</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 6</span>
|
<span>Sidebar Item 6</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 7</span>
|
<span>Sidebar Item 7</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 8</span>
|
<span>Sidebar Item 8</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 9</span>
|
<span>Sidebar Item 9</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 10</span>
|
<span>Sidebar Item 10</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 11</span>
|
<span>Sidebar Item 11</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 12</span>
|
<span>Sidebar Item 12</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 13</span>
|
<span>Sidebar Item 13</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 14</span>
|
<span>Sidebar Item 14</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 15</span>
|
<span>Sidebar Item 15</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-list-item>
|
<mat-list-item>
|
||||||
<span>Sidenav Item 16</span>
|
<span>Sidebar Item 16</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
</mat-list>
|
</mat-list>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector : 'fuse-demo-sidenav',
|
|
||||||
templateUrl: './demo-sidenav.component.html',
|
|
||||||
styleUrls : ['./demo-sidenav.component.scss']
|
|
||||||
})
|
|
||||||
export class FuseDemoSidenavComponent
|
|
||||||
{
|
|
||||||
constructor()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
|
|
||||||
import { MatDividerModule, MatListModule } from '@angular/material';
|
import { MatDividerModule } from '@angular/material/divider';
|
||||||
|
import { MatListModule } from '@angular/material/list';
|
||||||
|
|
||||||
import { FuseDemoContentComponent } from './demo-content/demo-content.component';
|
import { FuseDemoContentComponent } from './demo-content/demo-content.component';
|
||||||
import { FuseDemoSidenavComponent } from './demo-sidenav/demo-sidenav.component';
|
import { FuseDemoSidebarComponent } from './demo-sidebar/demo-sidebar.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
FuseDemoContentComponent,
|
FuseDemoContentComponent,
|
||||||
FuseDemoSidenavComponent
|
FuseDemoSidebarComponent
|
||||||
],
|
],
|
||||||
imports : [
|
imports : [
|
||||||
RouterModule,
|
RouterModule,
|
||||||
@@ -19,7 +20,7 @@ import { FuseDemoSidenavComponent } from './demo-sidenav/demo-sidenav.component'
|
|||||||
],
|
],
|
||||||
exports : [
|
exports : [
|
||||||
FuseDemoContentComponent,
|
FuseDemoContentComponent,
|
||||||
FuseDemoSidenavComponent
|
FuseDemoSidebarComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class FuseDemoModule
|
export class FuseDemoModule
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
:host {
|
:host {
|
||||||
display: block;
|
display: block;
|
||||||
|
width: 100%;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
background: #263238;
|
background: #263238;
|
||||||
cursor: text;
|
cursor: text;
|
||||||
|
overflow: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
@@ -1,28 +1,55 @@
|
|||||||
import { Component, ContentChild, ElementRef, Input, OnInit } from '@angular/core';
|
import { Component, ContentChild, ElementRef, Input, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
import * as Prism from 'prismjs/prism';
|
import * as Prism from 'prismjs/prism';
|
||||||
import './prism-languages';
|
import '@fuse/components/highlight/prism-languages';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector : 'fuse-highlight',
|
selector : 'fuse-highlight',
|
||||||
template : ' ',
|
template : '',
|
||||||
styleUrls: ['./highlight.component.scss']
|
styleUrls: ['./highlight.component.scss']
|
||||||
})
|
})
|
||||||
export class FuseHighlightComponent implements OnInit
|
export class FuseHighlightComponent implements OnInit, OnDestroy
|
||||||
{
|
{
|
||||||
@ContentChild('source') source: ElementRef;
|
// Source
|
||||||
@Input('lang') lang: string;
|
@ContentChild('source', {static: true})
|
||||||
@Input('path') path: string;
|
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(
|
constructor(
|
||||||
private elementRef: ElementRef,
|
private _elementRef: ElementRef,
|
||||||
private http: HttpClient
|
private _httpClient: HttpClient
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
// Set the private defaults
|
||||||
|
this._unsubscribeAll = new Subject();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit()
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Lifecycle hooks
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On init
|
||||||
|
*/
|
||||||
|
ngOnInit(): void
|
||||||
{
|
{
|
||||||
// If there is no language defined, return...
|
// If there is no language defined, return...
|
||||||
if ( !this.lang )
|
if ( !this.lang )
|
||||||
@@ -34,11 +61,13 @@ export class FuseHighlightComponent implements OnInit
|
|||||||
if ( this.path )
|
if ( this.path )
|
||||||
{
|
{
|
||||||
// Get the source
|
// Get the source
|
||||||
this.http.get(this.path, {responseType: 'text'}).subscribe((response) => {
|
this._httpClient.get(this.path, {responseType: 'text'})
|
||||||
|
.pipe(takeUntil(this._unsubscribeAll))
|
||||||
|
.subscribe((response) => {
|
||||||
|
|
||||||
// Highlight it
|
// Highlight it
|
||||||
this.highlight(response);
|
this.highlight(response);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the path is not defined and the source element exists...
|
// If the path is not defined and the source element exists...
|
||||||
@@ -49,7 +78,26 @@ export class FuseHighlightComponent implements OnInit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
highlight(sourceCode)
|
/**
|
||||||
|
* 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
|
// Split the source into lines
|
||||||
const sourceLines = sourceCode.split('\n');
|
const sourceLines = sourceCode.split('\n');
|
||||||
@@ -94,9 +142,8 @@ export class FuseHighlightComponent implements OnInit
|
|||||||
const highlightedCode = Prism.highlight(source, Prism.languages[this.lang]);
|
const highlightedCode = Prism.highlight(source, Prism.languages[this.lang]);
|
||||||
|
|
||||||
// Replace the innerHTML of the component with the highlighted code
|
// Replace the innerHTML of the component with the highlighted code
|
||||||
this.elementRef.nativeElement.innerHTML =
|
this._elementRef.nativeElement.innerHTML =
|
||||||
'<pre><code class="highlight language-' + this.lang + '">' + highlightedCode + '</code></pre>';
|
'<pre><code class="highlight language-' + this.lang + '">' + highlightedCode + '</code></pre>';
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import 'prismjs/prism';
|
import 'prismjs/prism';
|
||||||
|
import 'prismjs/components/prism-bash';
|
||||||
import 'prismjs/components/prism-c';
|
import 'prismjs/components/prism-c';
|
||||||
import 'prismjs/components/prism-cpp';
|
import 'prismjs/components/prism-cpp';
|
||||||
import 'prismjs/components/prism-csharp';
|
import 'prismjs/components/prism-csharp';
|
||||||
import 'prismjs/components/prism-css';
|
import 'prismjs/components/prism-css';
|
||||||
import 'prismjs/components/prism-diff';
|
import 'prismjs/components/prism-diff';
|
||||||
import 'prismjs/components/prism-markup';
|
import 'prismjs/components/prism-markup';
|
||||||
|
import 'prismjs/components/prism-markup-templating';
|
||||||
import 'prismjs/components/prism-java';
|
import 'prismjs/components/prism-java';
|
||||||
import 'prismjs/components/prism-javascript';
|
import 'prismjs/components/prism-javascript';
|
||||||
import 'prismjs/components/prism-json';
|
import 'prismjs/components/prism-json';
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export * from './demo/demo.module';
|
|||||||
export * from './highlight/highlight.module';
|
export * from './highlight/highlight.module';
|
||||||
export * from './material-color-picker/material-color-picker.module';
|
export * from './material-color-picker/material-color-picker.module';
|
||||||
export * from './navigation/navigation.module';
|
export * from './navigation/navigation.module';
|
||||||
|
export * from './progress-bar/progress-bar.module';
|
||||||
export * from './search-bar/search-bar.module';
|
export * from './search-bar/search-bar.module';
|
||||||
export * from './shortcuts/shortcuts.module';
|
export * from './shortcuts/shortcuts.module';
|
||||||
export * from './sidebar/sidebar.module';
|
export * from './sidebar/sidebar.module';
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
<button mat-icon-button
|
<button mat-icon-button
|
||||||
type="button"
|
|
||||||
class="mat-elevation-z1"
|
class="mat-elevation-z1"
|
||||||
[matMenuTriggerFor]="colorMenu"
|
[matMenuTriggerFor]="colorMenu"
|
||||||
(menuOpened)="onMenuOpen()"
|
(menuOpened)="onMenuOpen()"
|
||||||
[ngClass]="'mat-'+selectedPalette+'-'+selectedHue+'-bg'">
|
[ngClass]="selectedPalette + '-' + selectedHue">
|
||||||
<mat-icon>palette</mat-icon>
|
<mat-icon>palette</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<mat-menu #colorMenu="matMenu" class="fuse-material-color-picker-menu">
|
<mat-menu #colorMenu="matMenu" class="fuse-material-color-picker-menu mat-elevation-z8">
|
||||||
|
|
||||||
<header [ngClass]="selectedColor?.class || 'mat-accent-bg'" class="mat-elevation-z4"
|
<header [ngClass]="selectedColor?.class || 'accent'" class="mat-elevation-z4"
|
||||||
fxLayout="row" fxLayoutAlign="space-between center">
|
fxLayout="row" fxLayoutAlign="space-between center">
|
||||||
|
|
||||||
<button mat-icon-button
|
<button mat-icon-button
|
||||||
[style.visibility]="view==='hues'?'visible':'hidden'"
|
class="secondary-text"
|
||||||
(click)="$event.stopPropagation();backToPaletteSelection()" aria-label="Palette">
|
[style.visibility]="view === 'hues' ? 'visible' : 'hidden'"
|
||||||
|
(click)="goToPalettesView($event)" aria-label="Palette">
|
||||||
<mat-icon class="s-20">arrow_back</mat-icon>
|
<mat-icon class="s-20">arrow_back</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -23,45 +23,40 @@
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span *ngIf="!selectedColor?.palette">
|
<span *ngIf="!selectedColor?.palette">
|
||||||
Select Color
|
Select a Color
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<button mat-icon-button
|
<button mat-icon-button
|
||||||
class="remove-color-button"
|
class="remove-color-button secondary-text"
|
||||||
(click)="$event.stopPropagation();removeColor()"
|
(click)="removeColor($event)"
|
||||||
aria-label="Remove Color">
|
aria-label="Remove color"
|
||||||
|
matTooltip="Remove color">
|
||||||
<mat-icon class="s-20">delete</mat-icon>
|
<mat-icon class="s-20">delete</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|
||||||
<div [ngSwitch]="view" class="views">
|
<div [ngSwitch]="view" class="views">
|
||||||
|
|
||||||
<div class="view" *ngSwitchCase="'palettes'">
|
<div class="view" *ngSwitchCase="'palettes'">
|
||||||
|
|
||||||
<div fxLayout="row wrap" fxLayoutAlign="start start" class="colors" fusePerfectScrollbar>
|
<div fxLayout="row wrap" fxLayoutAlign="start start" class="colors" fusePerfectScrollbar>
|
||||||
<div class="color"
|
<div class="color" fxLayout="row" fxLayoutAlign="center center"
|
||||||
[ngClass]="'mat-'+color.key+'-bg'"
|
|
||||||
*ngFor="let color of (colors | keys)"
|
*ngFor="let color of (colors | keys)"
|
||||||
(click)="$event.stopPropagation();selectPalette(color.key)"
|
[ngClass]="color.key"
|
||||||
fxLayout="row" fxLayoutAlign="start end" mat-ink-ripple>
|
[class.selected]="selectedPalette === color.key"
|
||||||
<span class="label">
|
(click)="selectPalette($event, color.key)">
|
||||||
{{color.key}}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="view" *ngSwitchCase="'hues'" >
|
<div class="view" *ngSwitchCase="'hues'">
|
||||||
<div fxLayout="row wrap" fxLayoutAlign="start start" class="colors" fusePerfectScrollbar>
|
<div fxLayout="row wrap" fxLayoutAlign="start start" class="colors" fusePerfectScrollbar>
|
||||||
<div class="color" *ngFor="let hue of hues"
|
<div class="color" fxLayout="row" fxLayoutAlign="center center"
|
||||||
[fxHide]="selectedPalette === 'white' && hue !== '500'|| selectedPalette === 'black' && hue !== '500'"
|
*ngFor="let hue of hues"
|
||||||
[ngClass]="'mat-'+selectedPalette+'-'+hue+'-bg'"
|
[fxHide]="selectedPalette === 'fuse-white' && hue !== '500' || selectedPalette === 'fuse-black' && hue !== '500'"
|
||||||
(click)="selectHue(hue)" fxLayout="row" fxLayoutAlign="start end" mat-ink-ripple>
|
[ngClass]="selectedPalette + '-' + hue"
|
||||||
<span class="label">
|
[class.selected]="selectedHue === hue"
|
||||||
{{hue}}
|
(click)="selectHue($event, hue)">
|
||||||
</span>
|
|
||||||
<mat-icon *ngIf="selectedHue === hue" class="s-16">check</mat-icon>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
.fuse-material-color-picker-menu {
|
.fuse-material-color-picker-menu {
|
||||||
width: 208px;
|
width: 245px;
|
||||||
|
|
||||||
.mat-menu-content {
|
.mat-menu-content {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -7,44 +7,29 @@
|
|||||||
.views {
|
.views {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: relative;
|
min-height: 165px;
|
||||||
overflow: hidden;
|
|
||||||
min-height: 258px;
|
|
||||||
height: 308px;
|
|
||||||
background-color: #F7F7F7;
|
|
||||||
|
|
||||||
.view {
|
.view {
|
||||||
position: absolute;
|
overflow: hidden;
|
||||||
width: 208px;
|
|
||||||
height: 100%;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
|
|
||||||
.colors {
|
.colors {
|
||||||
position: relative;
|
padding: 1px 0 0 0;
|
||||||
padding: 4px;
|
margin-left: -1px;
|
||||||
|
|
||||||
.color {
|
.color {
|
||||||
position: relative;
|
width: 40px;
|
||||||
width: 46px;
|
height: 40px;
|
||||||
height: 46px;
|
margin: 0 0 1px 1px;
|
||||||
margin: 2px;
|
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: border-radius .4s cubic-bezier(.25, .8, .25, 1);
|
||||||
|
|
||||||
.label {
|
&:hover {
|
||||||
padding: 2px;
|
border-radius: 20%;
|
||||||
font-size: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-icon {
|
&.selected {
|
||||||
position: absolute;
|
border-radius: 50% !important;
|
||||||
top: 2px;
|
|
||||||
right: 2px;
|
|
||||||
font-size: 16px;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,179 +1,253 @@
|
|||||||
import { Component, EventEmitter, Input, OnChanges, Output, ViewEncapsulation } from '@angular/core';
|
import { Component, EventEmitter, forwardRef, Input, Output, ViewEncapsulation } from '@angular/core';
|
||||||
|
|
||||||
import { fuseAnimations } from '@fuse/animations';
|
import { fuseAnimations } from '@fuse/animations';
|
||||||
import { MatColors } from '@fuse/mat-colors';
|
import { MatColors } from '@fuse/mat-colors';
|
||||||
|
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
|
|
||||||
|
export const FUSE_MATERIAL_COLOR_PICKER_VALUE_ACCESSOR: any = {
|
||||||
|
provide : NG_VALUE_ACCESSOR,
|
||||||
|
useExisting: forwardRef(() => FuseMaterialColorPickerComponent),
|
||||||
|
multi : true
|
||||||
|
};
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector : 'fuse-material-color-picker',
|
selector : 'fuse-material-color-picker',
|
||||||
templateUrl : './material-color-picker.component.html',
|
templateUrl : './material-color-picker.component.html',
|
||||||
styleUrls : ['./material-color-picker.component.scss'],
|
styleUrls : ['./material-color-picker.component.scss'],
|
||||||
animations : fuseAnimations,
|
animations : fuseAnimations,
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
providers : [FUSE_MATERIAL_COLOR_PICKER_VALUE_ACCESSOR]
|
||||||
})
|
})
|
||||||
export class FuseMaterialColorPickerComponent implements OnChanges
|
export class FuseMaterialColorPickerComponent implements ControlValueAccessor
|
||||||
{
|
{
|
||||||
colors: any;
|
colors: any;
|
||||||
selectedColor: any;
|
|
||||||
hues: string[];
|
hues: string[];
|
||||||
view = 'palettes';
|
view: string;
|
||||||
|
selectedColor: any;
|
||||||
|
selectedPalette: string;
|
||||||
|
selectedHue: string;
|
||||||
|
|
||||||
@Input() selectedPalette = '';
|
// Color changed
|
||||||
@Input() selectedHue = '';
|
@Output()
|
||||||
@Input() selectedFg = '';
|
colorChanged: EventEmitter<any>;
|
||||||
@Input() value: any;
|
|
||||||
@Output() onValueChange = new EventEmitter();
|
|
||||||
@Output() selectedPaletteChange = new EventEmitter();
|
|
||||||
@Output() selectedHueChange = new EventEmitter();
|
|
||||||
@Output() selectedClassChange = new EventEmitter();
|
|
||||||
@Output() selectedBgChange = new EventEmitter();
|
|
||||||
@Output() selectedFgChange = new EventEmitter();
|
|
||||||
|
|
||||||
_selectedClass = '';
|
// Private
|
||||||
@Input()
|
private _color: string;
|
||||||
set selectedClass(value)
|
private _modelChange: (value: any) => void;
|
||||||
{
|
private _modelTouched: (value: any) => void;
|
||||||
if ( value && value !== '' && this._selectedClass !== value )
|
|
||||||
{
|
|
||||||
const color = value.split('-');
|
|
||||||
if ( color.length >= 5 )
|
|
||||||
{
|
|
||||||
this.selectedPalette = color[1] + '-' + color[2];
|
|
||||||
this.selectedHue = color[3];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.selectedPalette = color[1];
|
|
||||||
this.selectedHue = color[2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._selectedClass = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
get selectedClass(): string
|
|
||||||
{
|
|
||||||
return this._selectedClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
_selectedBg = '';
|
|
||||||
@Input()
|
|
||||||
set selectedBg(value)
|
|
||||||
{
|
|
||||||
if ( value && value !== '' && this._selectedBg !== value )
|
|
||||||
{
|
|
||||||
for ( const palette in this.colors )
|
|
||||||
{
|
|
||||||
if ( !this.colors.hasOwnProperty(palette) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( const hue of this.hues )
|
|
||||||
{
|
|
||||||
if ( this.colors[palette][hue] === value )
|
|
||||||
{
|
|
||||||
this.selectedPalette = palette;
|
|
||||||
this.selectedHue = hue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._selectedBg = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
get selectedBg(): string
|
|
||||||
{
|
|
||||||
return this._selectedBg;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
constructor()
|
constructor()
|
||||||
{
|
{
|
||||||
|
// Set the defaults
|
||||||
|
this.colorChanged = new EventEmitter();
|
||||||
this.colors = MatColors.all;
|
this.colors = MatColors.all;
|
||||||
this.hues = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', 'A100', 'A200', 'A400', 'A700'];
|
this.hues = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', 'A100', 'A200', 'A400', 'A700'];
|
||||||
|
this.selectedHue = '500';
|
||||||
|
this.view = 'palettes';
|
||||||
|
|
||||||
|
// Set the private defaults
|
||||||
|
this._color = '';
|
||||||
|
this._modelChange = () => {
|
||||||
|
};
|
||||||
|
this._modelTouched = () => {
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: any)
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Accessors
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selected class
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
set color(value)
|
||||||
{
|
{
|
||||||
if ( changes.selectedBg && changes.selectedBg.currentValue === '' ||
|
if ( !value || value === '' || this._color === value )
|
||||||
changes.selectedClass && changes.selectedClass.currentValue === '' ||
|
|
||||||
changes.selectedPalette && changes.selectedPalette.currentValue === '' )
|
|
||||||
{
|
{
|
||||||
this.removeColor();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( changes.selectedPalette || changes.selectedHue || changes.selectedClass || changes.selectedBg )
|
|
||||||
|
// Split the color value (red-400, blue-500, fuse-navy-700 etc.)
|
||||||
|
const colorParts = value.split('-');
|
||||||
|
|
||||||
|
// Take the very last part as the selected hue value
|
||||||
|
this.selectedHue = colorParts[colorParts.length - 1];
|
||||||
|
|
||||||
|
// Remove the last part
|
||||||
|
colorParts.pop();
|
||||||
|
|
||||||
|
// Rejoin the remaining parts as the selected palette name
|
||||||
|
this.selectedPalette = colorParts.join('-');
|
||||||
|
|
||||||
|
// Store the color value
|
||||||
|
this._color = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get color(): string
|
||||||
|
{
|
||||||
|
return this._color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Control Value Accessor implementation
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register on change function
|
||||||
|
*
|
||||||
|
* @param fn
|
||||||
|
*/
|
||||||
|
registerOnChange(fn: any): void
|
||||||
|
{
|
||||||
|
this._modelChange = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register on touched function
|
||||||
|
*
|
||||||
|
* @param fn
|
||||||
|
*/
|
||||||
|
registerOnTouched(fn: any): void
|
||||||
|
{
|
||||||
|
this._modelTouched = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write value to the view from model
|
||||||
|
*
|
||||||
|
* @param color
|
||||||
|
*/
|
||||||
|
writeValue(color: any): void
|
||||||
|
{
|
||||||
|
// Return if null
|
||||||
|
if ( !color )
|
||||||
{
|
{
|
||||||
this.updateSelectedColor();
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// Set the color
|
||||||
selectPalette(palette)
|
this.color = color;
|
||||||
{
|
|
||||||
this.selectedPalette = palette;
|
// Update the selected color
|
||||||
this.updateSelectedColor();
|
this.updateSelectedColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Public methods
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select palette
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* @param palette
|
||||||
|
*/
|
||||||
|
selectPalette(event, palette): void
|
||||||
|
{
|
||||||
|
// Stop propagation
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
// Go to 'hues' view
|
||||||
this.view = 'hues';
|
this.view = 'hues';
|
||||||
}
|
|
||||||
|
|
||||||
selectHue(hue)
|
// Update the selected palette
|
||||||
{
|
this.selectedPalette = palette;
|
||||||
this.selectedHue = hue;
|
|
||||||
|
// Update the selected color
|
||||||
this.updateSelectedColor();
|
this.updateSelectedColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
removeColor()
|
/**
|
||||||
|
* Select hue
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* @param hue
|
||||||
|
*/
|
||||||
|
selectHue(event, hue): void
|
||||||
{
|
{
|
||||||
|
// Stop propagation
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
// Update the selected huse
|
||||||
|
this.selectedHue = hue;
|
||||||
|
|
||||||
|
// Update the selected color
|
||||||
|
this.updateSelectedColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove color
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
removeColor(event): void
|
||||||
|
{
|
||||||
|
// Stop propagation
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
// Return to the 'palettes' view
|
||||||
|
this.view = 'palettes';
|
||||||
|
|
||||||
|
// Clear the selected palette and hue
|
||||||
this.selectedPalette = '';
|
this.selectedPalette = '';
|
||||||
this.selectedHue = '';
|
this.selectedHue = '';
|
||||||
|
|
||||||
|
// Update the selected color
|
||||||
this.updateSelectedColor();
|
this.updateSelectedColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update selected color
|
||||||
|
*/
|
||||||
|
updateSelectedColor(): void
|
||||||
|
{
|
||||||
|
if ( this.selectedColor && this.selectedColor.palette === this.selectedPalette && this.selectedColor.hue === this.selectedHue )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the selected color object
|
||||||
|
this.selectedColor = {
|
||||||
|
palette: this.selectedPalette,
|
||||||
|
hue : this.selectedHue,
|
||||||
|
class : this.selectedPalette + '-' + this.selectedHue,
|
||||||
|
bg : this.selectedPalette === '' ? '' : MatColors.getColor(this.selectedPalette)[this.selectedHue],
|
||||||
|
fg : this.selectedPalette === '' ? '' : MatColors.getColor(this.selectedPalette).contrast[this.selectedHue]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Emit the color changed event
|
||||||
|
this.colorChanged.emit(this.selectedColor);
|
||||||
|
|
||||||
|
// Mark the model as touched
|
||||||
|
this._modelTouched(this.selectedColor.class);
|
||||||
|
|
||||||
|
// Update the model
|
||||||
|
this._modelChange(this.selectedColor.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Go to palettes view
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
goToPalettesView(event): void
|
||||||
|
{
|
||||||
|
// Stop propagation
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
this.view = 'palettes';
|
this.view = 'palettes';
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSelectedColor()
|
/**
|
||||||
{
|
* On menu open
|
||||||
setTimeout(() => {
|
*/
|
||||||
|
onMenuOpen(): void
|
||||||
if ( this.selectedColor && this.selectedPalette === this.selectedColor.palette && this.selectedHue === this.selectedColor.hue )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( this.selectedPalette !== '' && this.selectedHue !== '' )
|
|
||||||
{
|
|
||||||
this.selectedBg = MatColors.getColor(this.selectedPalette)[this.selectedHue];
|
|
||||||
this.selectedFg = MatColors.getColor(this.selectedPalette).contrast[this.selectedHue];
|
|
||||||
this.selectedClass = 'mat-' + this.selectedPalette + '-' + this.selectedHue + '-bg';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.selectedBg = '';
|
|
||||||
this.selectedFg = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
this.selectedColor = {
|
|
||||||
palette: this.selectedPalette,
|
|
||||||
hue : this.selectedHue,
|
|
||||||
class : this.selectedClass,
|
|
||||||
bg : this.selectedBg,
|
|
||||||
fg : this.selectedFg
|
|
||||||
};
|
|
||||||
|
|
||||||
this.selectedPaletteChange.emit(this.selectedPalette);
|
|
||||||
this.selectedHueChange.emit(this.selectedHue);
|
|
||||||
this.selectedClassChange.emit(this.selectedClass);
|
|
||||||
this.selectedBgChange.emit(this.selectedBg);
|
|
||||||
this.selectedFgChange.emit(this.selectedFg);
|
|
||||||
|
|
||||||
this.value = this.selectedColor;
|
|
||||||
this.onValueChange.emit(this.selectedColor);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
backToPaletteSelection()
|
|
||||||
{
|
|
||||||
this.view = 'palettes';
|
|
||||||
}
|
|
||||||
|
|
||||||
onMenuOpen()
|
|
||||||
{
|
{
|
||||||
if ( this.selectedPalette === '' )
|
if ( this.selectedPalette === '' )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatButtonModule, MatIconModule, MatMenuModule, MatRippleModule } from '@angular/material';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
|
|
||||||
import { FusePipesModule } from '@fuse/pipes/pipes.module';
|
import { FusePipesModule } from '@fuse/pipes/pipes.module';
|
||||||
|
|
||||||
@@ -20,7 +22,7 @@ import { FuseMaterialColorPickerComponent } from '@fuse/components/material-colo
|
|||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
MatRippleModule,
|
MatTooltipModule,
|
||||||
|
|
||||||
FusePipesModule
|
FusePipesModule
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
@mixin fuse-material-color-picker-theme($theme) {
|
||||||
|
|
||||||
|
$background: map-get($theme, background);
|
||||||
|
|
||||||
|
.fuse-material-color-picker-menu {
|
||||||
|
|
||||||
|
.mat-menu-content {
|
||||||
|
|
||||||
|
.views {
|
||||||
|
background: #303030;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
<ng-container *ngIf="!item.hidden">
|
||||||
|
|
||||||
|
<!-- normal collapse -->
|
||||||
|
<a class="nav-link" [ngClass]="item.classes" *ngIf="!item.url && !item.function">
|
||||||
|
<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', 'accent']"
|
||||||
|
[routerLinkActiveOptions]="{exact: item.exactMatch || false}"
|
||||||
|
[target]="item.openInNewTab ? '_blank' : '_self'">
|
||||||
|
<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'">
|
||||||
|
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- item.function -->
|
||||||
|
<span class="nav-link" [ngClass]="item.classes" *ngIf="!item.url && item.function"
|
||||||
|
(click)="item.function()">
|
||||||
|
<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', 'accent']"
|
||||||
|
[routerLinkActiveOptions]="{exact: item.exactMatch || false}">
|
||||||
|
<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'">
|
||||||
|
<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.primaryBackground}}">
|
||||||
|
|
||||||
|
<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>
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<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', 'accent']"
|
||||||
|
[routerLinkActiveOptions]="{exact: item.exactMatch || false}"
|
||||||
|
[target]="item.openInNewTab ? '_blank' : '_self'">
|
||||||
|
<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'">
|
||||||
|
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- item.function -->
|
||||||
|
<span class="nav-link" [ngClass]="item.classes" *ngIf="!item.url && item.function"
|
||||||
|
(click)="item.function()">
|
||||||
|
<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', 'accent']"
|
||||||
|
[routerLinkActiveOptions]="{exact: item.exactMatch || false}"
|
||||||
|
[target]="item.openInNewTab ? '_blank' : '_self'">
|
||||||
|
<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'">
|
||||||
|
<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>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
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()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<a class="nav-link" matRipple>
|
|
||||||
<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="collapse-arrow">keyboard_arrow_right</mat-icon>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<div class="children" [ngClass]="{'open': isOpen}">
|
|
||||||
|
|
||||||
<div class="{{fuseSettings.colorClasses.navbar}}">
|
|
||||||
|
|
||||||
<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-collapse *ngIf="item.type=='collapse'" [item]="item"></fuse-nav-horizontal-collapse>
|
|
||||||
<fuse-nav-horizontal-collapse *ngIf="item.type=='group'" [item]="item"></fuse-nav-horizontal-collapse>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
import { Component, HostBinding, HostListener, Input, OnDestroy } from '@angular/core';
|
|
||||||
import { fuseAnimations } from '../../../../animations/index';
|
|
||||||
import { FuseConfigService } from '../../../../services/config.service';
|
|
||||||
import { Subscription } from 'rxjs/Subscription';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector : 'fuse-nav-horizontal-collapse',
|
|
||||||
templateUrl: './nav-horizontal-collapse.component.html',
|
|
||||||
styleUrls : ['./nav-horizontal-collapse.component.scss'],
|
|
||||||
animations : fuseAnimations
|
|
||||||
})
|
|
||||||
export class FuseNavHorizontalCollapseComponent implements OnDestroy
|
|
||||||
{
|
|
||||||
onConfigChanged: Subscription;
|
|
||||||
fuseSettings: any;
|
|
||||||
isOpen = false;
|
|
||||||
|
|
||||||
@HostBinding('class') classes = 'nav-item nav-collapse';
|
|
||||||
@Input() item: any;
|
|
||||||
|
|
||||||
@HostListener('mouseenter')
|
|
||||||
open()
|
|
||||||
{
|
|
||||||
this.isOpen = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@HostListener('mouseleave')
|
|
||||||
close()
|
|
||||||
{
|
|
||||||
this.isOpen = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private fuseConfig: FuseConfigService
|
|
||||||
)
|
|
||||||
{
|
|
||||||
this.onConfigChanged =
|
|
||||||
this.fuseConfig.onConfigChanged
|
|
||||||
.subscribe(
|
|
||||||
(newSettings) => {
|
|
||||||
this.fuseSettings = newSettings;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy()
|
|
||||||
{
|
|
||||||
this.onConfigChanged.unsubscribe();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<a class="nav-link" *ngIf="item.url" [routerLink]="[item.url]" routerLinkActive="active"
|
|
||||||
[routerLinkActiveOptions]="{exact: item.exactMatch || false}" matRipple>
|
|
||||||
<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>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<span class="nav-link" *ngIf="item.function" (click)="item.function()" matRipple>
|
|
||||||
<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>
|
|
||||||
</span>
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import { Component, HostBinding, Input } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector : 'fuse-nav-horizontal-item',
|
|
||||||
templateUrl: './nav-horizontal-item.component.html',
|
|
||||||
styleUrls : ['./nav-horizontal-item.component.scss']
|
|
||||||
})
|
|
||||||
export class FuseNavHorizontalItemComponent
|
|
||||||
{
|
|
||||||
@HostBinding('class') classes = 'nav-item';
|
|
||||||
@Input() item: any;
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
<div id="main-navigation" class="nav"
|
<div class="nav" [ngClass]="{'horizontal':layout === 'horizontal', 'vertical':layout === 'vertical'}">
|
||||||
[ngClass]="{'horizontal':layout === 'horizontal', 'vertical':layout === 'vertical'}">
|
|
||||||
|
|
||||||
<!-- Vertical Navigation Layout -->
|
<!-- Vertical Navigation Layout -->
|
||||||
<ng-container *ngIf="layout === 'vertical'">
|
<ng-container *ngIf="layout === 'vertical'">
|
||||||
@@ -7,7 +6,8 @@
|
|||||||
<ng-container *ngFor="let item of navigation">
|
<ng-container *ngFor="let item of navigation">
|
||||||
|
|
||||||
<fuse-nav-vertical-group *ngIf="item.type=='group'" [item]="item"></fuse-nav-vertical-group>
|
<fuse-nav-vertical-group *ngIf="item.type=='group'" [item]="item"></fuse-nav-vertical-group>
|
||||||
<fuse-nav-vertical-collapse *ngIf="item.type=='collapse'" [item]="item"></fuse-nav-vertical-collapse>
|
<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>
|
<fuse-nav-vertical-item *ngIf="item.type=='item'" [item]="item"></fuse-nav-vertical-item>
|
||||||
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
@@ -20,8 +20,9 @@
|
|||||||
|
|
||||||
<ng-container *ngFor="let item of navigation">
|
<ng-container *ngFor="let item of navigation">
|
||||||
|
|
||||||
<fuse-nav-horizontal-collapse *ngIf="item.type=='group'" [item]="item"></fuse-nav-horizontal-collapse>
|
<fuse-nav-horizontal-collapsable *ngIf="item.type=='group'" [item]="item"></fuse-nav-horizontal-collapsable>
|
||||||
<fuse-nav-horizontal-collapse *ngIf="item.type=='collapse'" [item]="item"></fuse-nav-horizontal-collapse>
|
<fuse-nav-horizontal-collapsable *ngIf="item.type=='collapsable'"
|
||||||
|
[item]="item"></fuse-nav-horizontal-collapsable>
|
||||||
<fuse-nav-horizontal-item *ngIf="item.type=='item'" [item]="item"></fuse-nav-horizontal-item>
|
<fuse-nav-horizontal-item *ngIf="item.type=='item'" [item]="item"></fuse-nav-horizontal-item>
|
||||||
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ fuse-navigation {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex: 1 0 auto;
|
flex: 1 0 auto;
|
||||||
|
|
||||||
#main-navigation {
|
> .nav {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -1,18 +1,75 @@
|
|||||||
import { Component, Input, ViewEncapsulation } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { merge, Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector : 'fuse-navigation',
|
selector : 'fuse-navigation',
|
||||||
templateUrl : './navigation.component.html',
|
templateUrl : './navigation.component.html',
|
||||||
styleUrls : ['./navigation.component.scss'],
|
styleUrls : ['./navigation.component.scss'],
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation : ViewEncapsulation.None,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class FuseNavigationComponent
|
export class FuseNavigationComponent implements OnInit
|
||||||
{
|
{
|
||||||
@Input() layout = 'vertical';
|
@Input()
|
||||||
@Input() navigation: any;
|
layout = 'vertical';
|
||||||
|
|
||||||
constructor()
|
@Input()
|
||||||
|
navigation: any;
|
||||||
|
|
||||||
|
// Private
|
||||||
|
private _unsubscribeAll: Subject<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {ChangeDetectorRef} _changeDetectorRef
|
||||||
|
* @param {FuseNavigationService} _fuseNavigationService
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private _changeDetectorRef: ChangeDetectorRef,
|
||||||
|
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(() => {
|
||||||
|
|
||||||
|
// Load the navigation
|
||||||
|
this.navigation = this._fuseNavigationService.getCurrentNavigation();
|
||||||
|
|
||||||
|
// Mark for check
|
||||||
|
this._changeDetectorRef.markForCheck();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Subscribe to navigation item
|
||||||
|
merge(
|
||||||
|
this._fuseNavigationService.onNavigationItemAdded,
|
||||||
|
this._fuseNavigationService.onNavigationItemUpdated,
|
||||||
|
this._fuseNavigationService.onNavigationItemRemoved
|
||||||
|
).pipe(takeUntil(this._unsubscribeAll))
|
||||||
|
.subscribe(() => {
|
||||||
|
|
||||||
|
// Mark for check
|
||||||
|
this._changeDetectorRef.markForCheck();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { MatIconModule, MatRippleModule } from '@angular/material';
|
import { MatRippleModule } from '@angular/material/core';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { FuseNavigationComponent } from './navigation.component';
|
import { FuseNavigationComponent } from './navigation.component';
|
||||||
import { FuseNavVerticalItemComponent } from './vertical/nav-item/nav-vertical-item.component';
|
import { FuseNavVerticalItemComponent } from './vertical/item/item.component';
|
||||||
import { FuseNavVerticalCollapseComponent } from './vertical/nav-collapse/nav-vertical-collapse.component';
|
import { FuseNavVerticalCollapsableComponent } from './vertical/collapsable/collapsable.component';
|
||||||
import { FuseNavVerticalGroupComponent } from './vertical/nav-group/nav-vertical-group.component';
|
import { FuseNavVerticalGroupComponent } from './vertical/group/group.component';
|
||||||
import { FuseNavHorizontalItemComponent } from './horizontal/nav-item/nav-horizontal-item.component';
|
import { FuseNavHorizontalItemComponent } from './horizontal/item/item.component';
|
||||||
import { FuseNavHorizontalCollapseComponent } from './horizontal/nav-collapse/nav-horizontal-collapse.component';
|
import { FuseNavHorizontalCollapsableComponent } from './horizontal/collapsable/collapsable.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports : [
|
imports : [
|
||||||
@@ -29,9 +30,9 @@ import { FuseNavHorizontalCollapseComponent } from './horizontal/nav-collapse/na
|
|||||||
FuseNavigationComponent,
|
FuseNavigationComponent,
|
||||||
FuseNavVerticalGroupComponent,
|
FuseNavVerticalGroupComponent,
|
||||||
FuseNavVerticalItemComponent,
|
FuseNavVerticalItemComponent,
|
||||||
FuseNavVerticalCollapseComponent,
|
FuseNavVerticalCollapsableComponent,
|
||||||
FuseNavHorizontalItemComponent,
|
FuseNavHorizontalItemComponent,
|
||||||
FuseNavHorizontalCollapseComponent
|
FuseNavHorizontalCollapsableComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class FuseNavigationModule
|
export class FuseNavigationModule
|
||||||
|
|||||||
@@ -1,48 +1,425 @@
|
|||||||
import { EventEmitter, Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Subject } from 'rxjs/Subject';
|
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
@Injectable()
|
import { FuseNavigationItem } from '@fuse/types';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
export class FuseNavigationService
|
export class FuseNavigationService
|
||||||
{
|
{
|
||||||
flatNavigation: any[] = [];
|
onItemCollapsed: Subject<any>;
|
||||||
|
onItemCollapseToggled: Subject<any>;
|
||||||
|
|
||||||
onItemCollapsed: Subject<any> = new Subject;
|
// Private
|
||||||
onItemCollapseToggled: Subject<any> = new Subject;
|
private _onNavigationChanged: BehaviorSubject<any>;
|
||||||
|
private _onNavigationRegistered: BehaviorSubject<any>;
|
||||||
|
private _onNavigationUnregistered: BehaviorSubject<any>;
|
||||||
|
private _onNavigationItemAdded: BehaviorSubject<any>;
|
||||||
|
private _onNavigationItemUpdated: BehaviorSubject<any>;
|
||||||
|
private _onNavigationItemRemoved: BehaviorSubject<any>;
|
||||||
|
|
||||||
|
private _currentNavigationKey: string;
|
||||||
|
private _registry: { [key: string]: any } = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
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);
|
||||||
|
this._onNavigationItemAdded = new BehaviorSubject(null);
|
||||||
|
this._onNavigationItemUpdated = new BehaviorSubject(null);
|
||||||
|
this._onNavigationItemRemoved = 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get onNavigationItemAdded
|
||||||
|
*
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
get onNavigationItemAdded(): Observable<any>
|
||||||
|
{
|
||||||
|
return this._onNavigationItemAdded.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get onNavigationItemUpdated
|
||||||
|
*
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
get onNavigationItemUpdated(): Observable<any>
|
||||||
|
{
|
||||||
|
return this._onNavigationItemUpdated.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get onNavigationItemRemoved
|
||||||
|
*
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
get onNavigationItemRemoved(): Observable<any>
|
||||||
|
{
|
||||||
|
return this._onNavigationItemRemoved.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
|
* Get flattened navigation array
|
||||||
|
*
|
||||||
* @param navigation
|
* @param navigation
|
||||||
|
* @param flatNavigation
|
||||||
* @returns {any[]}
|
* @returns {any[]}
|
||||||
*/
|
*/
|
||||||
getFlatNavigation(navigation)
|
getFlatNavigation(navigation, flatNavigation: FuseNavigationItem[] = []): any
|
||||||
{
|
{
|
||||||
for ( const navItem of navigation )
|
for ( const item of navigation )
|
||||||
{
|
{
|
||||||
if ( navItem.type === 'item' )
|
if ( item.type === 'item' )
|
||||||
{
|
{
|
||||||
this.flatNavigation.push({
|
flatNavigation.push(item);
|
||||||
title: navItem.title,
|
|
||||||
type : navItem.type,
|
|
||||||
icon : navItem.icon || false,
|
|
||||||
url : navItem.url
|
|
||||||
});
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( navItem.type === 'collapse' || navItem.type === 'group' )
|
if ( item.type === 'collapsable' || item.type === 'group' )
|
||||||
{
|
{
|
||||||
if ( navItem.children )
|
if ( item.children )
|
||||||
{
|
{
|
||||||
this.getFlatNavigation(navItem.children);
|
this.getFlatNavigation(item.children, flatNavigation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.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);
|
||||||
|
|
||||||
|
// Trigger the observable
|
||||||
|
this._onNavigationItemAdded.next(true);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to the start of the navigation
|
||||||
|
if ( id === 'start' )
|
||||||
|
{
|
||||||
|
navigation.unshift(item);
|
||||||
|
|
||||||
|
// Trigger the observable
|
||||||
|
this._onNavigationItemAdded.next(true);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger the observable
|
||||||
|
this._onNavigationItemAdded.next(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update navigation item with the given id
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* @param properties
|
||||||
|
*/
|
||||||
|
updateNavigationItem(id, properties): void
|
||||||
|
{
|
||||||
|
// Get the navigation item
|
||||||
|
const navigationItem = this.getNavigationItem(id);
|
||||||
|
|
||||||
|
// If there is no navigation with the give id, return
|
||||||
|
if ( !navigationItem )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge the navigation properties
|
||||||
|
_.merge(navigationItem, properties);
|
||||||
|
|
||||||
|
// Trigger the observable
|
||||||
|
this._onNavigationItemUpdated.next(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
// Trigger the observable
|
||||||
|
this._onNavigationItemRemoved.next(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<ng-container *ngIf="!item.hidden">
|
||||||
|
|
||||||
|
<!-- normal collapsable -->
|
||||||
|
<a class="nav-link" [ngClass]="item.classes" *ngIf="!item.url && !item.function"
|
||||||
|
(click)="toggleOpen($event)">
|
||||||
|
<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', 'accent']"
|
||||||
|
[routerLinkActiveOptions]="{exact: item.exactMatch || false}"
|
||||||
|
[target]="item.openInNewTab ? '_blank' : '_self'">
|
||||||
|
<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'">
|
||||||
|
<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()">
|
||||||
|
<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', 'accent']"
|
||||||
|
[routerLinkActiveOptions]="{exact: item.exactMatch || false}">
|
||||||
|
<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'">
|
||||||
|
<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>
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
.nav-link {
|
.nav-link {
|
||||||
|
|
||||||
.collapse-arrow {
|
.collapsable-arrow {
|
||||||
transition: transform .3s ease-in-out, opacity .25s ease-in-out .1s;
|
transition: transform .3s ease-in-out, opacity .25s ease-in-out .1s;
|
||||||
transform: rotate(0);
|
transform: rotate(0);
|
||||||
}
|
}
|
||||||
@@ -34,13 +34,9 @@
|
|||||||
|
|
||||||
> .nav-link {
|
> .nav-link {
|
||||||
|
|
||||||
.collapse-arrow {
|
.collapsable-arrow {
|
||||||
transform: rotate(90deg);
|
transform: rotate(90deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .children {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,268 @@
|
|||||||
|
import { ChangeDetectorRef, Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
import { NavigationEnd, Router } from '@angular/router';
|
||||||
|
import { merge, 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 {ChangeDetectorRef} _changeDetectorRef
|
||||||
|
* @param {FuseNavigationService} _fuseNavigationService
|
||||||
|
* @param {Router} _router
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private _changeDetectorRef: ChangeDetectorRef,
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subscribe to navigation item
|
||||||
|
merge(
|
||||||
|
this._fuseNavigationService.onNavigationItemAdded,
|
||||||
|
this._fuseNavigationService.onNavigationItemUpdated,
|
||||||
|
this._fuseNavigationService.onNavigationItemRemoved
|
||||||
|
).pipe(takeUntil(this._unsubscribeAll))
|
||||||
|
.subscribe(() => {
|
||||||
|
|
||||||
|
// Mark for check
|
||||||
|
this._changeDetectorRef.markForCheck();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
// Mark for check
|
||||||
|
this._changeDetectorRef.markForCheck();
|
||||||
|
|
||||||
|
this._fuseNavigationService.onItemCollapseToggled.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collapse the collapsable navigation
|
||||||
|
*/
|
||||||
|
collapse(): void
|
||||||
|
{
|
||||||
|
if ( !this.isOpen )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isOpen = false;
|
||||||
|
|
||||||
|
// Mark for check
|
||||||
|
this._changeDetectorRef.markForCheck();
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
const children = parent.children;
|
||||||
|
|
||||||
|
if ( !children )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( children.indexOf(item) > -1 )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( const child of children )
|
||||||
|
{
|
||||||
|
if ( child.children )
|
||||||
|
{
|
||||||
|
if ( this.isChildrenOf(child, item) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
const children = parent.children;
|
||||||
|
|
||||||
|
if ( !children )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( const child of children )
|
||||||
|
{
|
||||||
|
if ( child.children )
|
||||||
|
{
|
||||||
|
if ( this.isUrlInChildren(child, url) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( child.url === url || url.includes(child.url) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
<ng-container *ngIf="!item.hidden">
|
<ng-container *ngIf="!item.hidden">
|
||||||
|
|
||||||
<div class="group-title">
|
<div class="group-title" [ngClass]="item.classes">
|
||||||
<span class="hint-text" [translate]="item.translate">{{ item.title }}</span>
|
<span class="hint-text" [translate]="item.translate">{{ item.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="group-items">
|
<div class="group-items">
|
||||||
<ng-container *ngFor="let item of item.children">
|
<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-group *ngIf="item.type=='group'" [item]="item"></fuse-nav-vertical-group>
|
||||||
<fuse-nav-vertical-collapse *ngIf="item.type=='collapse'" [item]="item"></fuse-nav-vertical-collapse>
|
<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>
|
<fuse-nav-vertical-item *ngIf="item.type=='item'" [item]="item"></fuse-nav-vertical-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import { ChangeDetectorRef, Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
import { merge, Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { FuseNavigationItem } from '@fuse/types';
|
||||||
|
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector : 'fuse-nav-vertical-group',
|
||||||
|
templateUrl: './group.component.html',
|
||||||
|
styleUrls : ['./group.component.scss']
|
||||||
|
})
|
||||||
|
export class FuseNavVerticalGroupComponent implements OnInit, OnDestroy
|
||||||
|
{
|
||||||
|
@HostBinding('class')
|
||||||
|
classes = 'nav-group nav-item';
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
item: FuseNavigationItem;
|
||||||
|
|
||||||
|
// Private
|
||||||
|
private _unsubscribeAll: Subject<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {ChangeDetectorRef} _changeDetectorRef
|
||||||
|
* @param {FuseNavigationService} _fuseNavigationService
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private _changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private _fuseNavigationService: FuseNavigationService
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Set the private defaults
|
||||||
|
this._unsubscribeAll = new Subject();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Lifecycle hooks
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On init
|
||||||
|
*/
|
||||||
|
ngOnInit(): void
|
||||||
|
{
|
||||||
|
// Subscribe to navigation item
|
||||||
|
merge(
|
||||||
|
this._fuseNavigationService.onNavigationItemAdded,
|
||||||
|
this._fuseNavigationService.onNavigationItemUpdated,
|
||||||
|
this._fuseNavigationService.onNavigationItemRemoved
|
||||||
|
).pipe(takeUntil(this._unsubscribeAll))
|
||||||
|
.subscribe(() => {
|
||||||
|
|
||||||
|
// Mark for check
|
||||||
|
this._changeDetectorRef.markForCheck();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On destroy
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void
|
||||||
|
{
|
||||||
|
// Unsubscribe from all subscriptions
|
||||||
|
this._unsubscribeAll.next();
|
||||||
|
this._unsubscribeAll.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<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', 'accent']"
|
||||||
|
[routerLinkActiveOptions]="{exact: item.exactMatch || false}"
|
||||||
|
[target]="item.openInNewTab ? '_blank' : '_self'">
|
||||||
|
<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'">
|
||||||
|
<ng-container *ngTemplateOutlet="itemContent"></ng-container>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- item.function -->
|
||||||
|
<span class="nav-link" [ngClass]="item.classes" *ngIf="!item.url && item.function"
|
||||||
|
(click)="item.function()">
|
||||||
|
<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', 'accent']"
|
||||||
|
[routerLinkActiveOptions]="{exact: item.exactMatch || false}"
|
||||||
|
[target]="item.openInNewTab ? '_blank' : '_self'">
|
||||||
|
<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'">
|
||||||
|
<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>
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import { ChangeDetectorRef, Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
import { merge, Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { FuseNavigationItem } from '@fuse/types';
|
||||||
|
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector : 'fuse-nav-vertical-item',
|
||||||
|
templateUrl: './item.component.html',
|
||||||
|
styleUrls : ['./item.component.scss']
|
||||||
|
})
|
||||||
|
export class FuseNavVerticalItemComponent implements OnInit, OnDestroy
|
||||||
|
{
|
||||||
|
@HostBinding('class')
|
||||||
|
classes = 'nav-item';
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
item: FuseNavigationItem;
|
||||||
|
|
||||||
|
// Private
|
||||||
|
private _unsubscribeAll: Subject<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {ChangeDetectorRef} _changeDetectorRef
|
||||||
|
* @param {FuseNavigationService} _fuseNavigationService
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private _changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private _fuseNavigationService: FuseNavigationService
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Set the private defaults
|
||||||
|
this._unsubscribeAll = new Subject();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Lifecycle hooks
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On init
|
||||||
|
*/
|
||||||
|
ngOnInit(): void
|
||||||
|
{
|
||||||
|
// Subscribe to navigation item
|
||||||
|
merge(
|
||||||
|
this._fuseNavigationService.onNavigationItemAdded,
|
||||||
|
this._fuseNavigationService.onNavigationItemUpdated,
|
||||||
|
this._fuseNavigationService.onNavigationItemRemoved
|
||||||
|
).pipe(takeUntil(this._unsubscribeAll))
|
||||||
|
.subscribe(() => {
|
||||||
|
|
||||||
|
// Mark for check
|
||||||
|
this._changeDetectorRef.markForCheck();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On destroy
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void
|
||||||
|
{
|
||||||
|
// Unsubscribe from all subscriptions
|
||||||
|
this._unsubscribeAll.next();
|
||||||
|
this._unsubscribeAll.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<ng-container *ngIf="!item.hidden">
|
|
||||||
|
|
||||||
<a class="nav-link" matRipple (click)="toggleOpen($event)">
|
|
||||||
<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="collapse-arrow">keyboard_arrow_right</mat-icon>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<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-collapse *ngIf="item.type=='collapse'" [item]="item"></fuse-nav-vertical-collapse>
|
|
||||||
<fuse-nav-vertical-group *ngIf="item.type=='group'" [item]="item"></fuse-nav-vertical-group>
|
|
||||||
</ng-container>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</ng-container>
|
|
||||||
@@ -1,193 +0,0 @@
|
|||||||
import { Component, HostBinding, Input, OnInit } from '@angular/core';
|
|
||||||
import { FuseNavigationService } from '../../navigation.service';
|
|
||||||
import { NavigationEnd, Router } from '@angular/router';
|
|
||||||
import { fuseAnimations } from '../../../../animations/index';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector : 'fuse-nav-vertical-collapse',
|
|
||||||
templateUrl: './nav-vertical-collapse.component.html',
|
|
||||||
styleUrls : ['./nav-vertical-collapse.component.scss'],
|
|
||||||
animations : fuseAnimations
|
|
||||||
})
|
|
||||||
export class FuseNavVerticalCollapseComponent implements OnInit
|
|
||||||
{
|
|
||||||
@Input() item: any;
|
|
||||||
@HostBinding('class') classes = 'nav-collapse nav-item';
|
|
||||||
@HostBinding('class.open') public isOpen = false;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private navigationService: FuseNavigationService,
|
|
||||||
private router: Router
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Listen for route changes
|
|
||||||
router.events.subscribe(
|
|
||||||
(event) => {
|
|
||||||
if ( event instanceof 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.navigationService.onItemCollapsed
|
|
||||||
.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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit()
|
|
||||||
{
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle collapse
|
|
||||||
*
|
|
||||||
* @param ev
|
|
||||||
*/
|
|
||||||
toggleOpen(ev)
|
|
||||||
{
|
|
||||||
ev.preventDefault();
|
|
||||||
|
|
||||||
this.isOpen = !this.isOpen;
|
|
||||||
|
|
||||||
// Navigation collapse toggled...
|
|
||||||
this.navigationService.onItemCollapsed.next(this.item);
|
|
||||||
this.navigationService.onItemCollapseToggled.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expand the collapsable navigation
|
|
||||||
*/
|
|
||||||
expand()
|
|
||||||
{
|
|
||||||
if ( this.isOpen )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isOpen = true;
|
|
||||||
this.navigationService.onItemCollapseToggled.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collapse the collapsable navigation
|
|
||||||
*/
|
|
||||||
collapse()
|
|
||||||
{
|
|
||||||
if ( !this.isOpen )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isOpen = false;
|
|
||||||
this.navigationService.onItemCollapseToggled.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the given parent has the
|
|
||||||
* given item in one of its children
|
|
||||||
*
|
|
||||||
* @param parent
|
|
||||||
* @param item
|
|
||||||
* @return {any}
|
|
||||||
*/
|
|
||||||
isChildrenOf(parent, item)
|
|
||||||
{
|
|
||||||
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 {any}
|
|
||||||
*/
|
|
||||||
isUrlInChildren(parent, url)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import { Component, HostBinding, Input } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector : 'fuse-nav-vertical-group',
|
|
||||||
templateUrl: './nav-vertical-group.component.html',
|
|
||||||
styleUrls : ['./nav-vertical-group.component.scss']
|
|
||||||
})
|
|
||||||
export class FuseNavVerticalGroupComponent
|
|
||||||
{
|
|
||||||
@HostBinding('class') classes = 'nav-group nav-item';
|
|
||||||
@Input() item: any;
|
|
||||||
|
|
||||||
constructor()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
<ng-container *ngIf="!item.hidden">
|
|
||||||
|
|
||||||
<a class="nav-link" *ngIf="item.url" [routerLink]="[item.url]" routerLinkActive="active"
|
|
||||||
[routerLinkActiveOptions]="{exact: item.exactMatch || false}" matRipple>
|
|
||||||
<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>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<span class="nav-link" *ngIf="item.function" (click)="item.function()" matRipple>
|
|
||||||
<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>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
</ng-container>
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import { Component, HostBinding, Input } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector : 'fuse-nav-vertical-item',
|
|
||||||
templateUrl: './nav-vertical-item.component.html',
|
|
||||||
styleUrls : ['./nav-vertical-item.component.scss']
|
|
||||||
})
|
|
||||||
export class FuseNavVerticalItemComponent
|
|
||||||
{
|
|
||||||
@HostBinding('class') classes = 'nav-item';
|
|
||||||
@Input() item: any;
|
|
||||||
|
|
||||||
constructor()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<ng-container *ngIf="visible">
|
||||||
|
|
||||||
|
<mat-progress-bar color="accent" [bufferValue]="bufferValue" [mode]="mode" [value]="value"></mat-progress-bar>
|
||||||
|
|
||||||
|
</ng-container>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
@import "src/@fuse/scss/fuse";
|
||||||
|
|
||||||
|
fuse-progress-bar {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 99998;
|
||||||
|
|
||||||
|
mat-progress-bar {
|
||||||
|
|
||||||
|
.mat-progress-bar-buffer {
|
||||||
|
background-color: #C5C6CB !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
93
src/@fuse/components/progress-bar/progress-bar.component.ts
Normal file
93
src/@fuse/components/progress-bar/progress-bar.component.ts
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { FuseProgressBarService } from '@fuse/components/progress-bar/progress-bar.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector : 'fuse-progress-bar',
|
||||||
|
templateUrl : './progress-bar.component.html',
|
||||||
|
styleUrls : ['./progress-bar.component.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
|
})
|
||||||
|
export class FuseProgressBarComponent implements OnInit, OnDestroy
|
||||||
|
{
|
||||||
|
bufferValue: number;
|
||||||
|
mode: 'determinate' | 'indeterminate' | 'buffer' | 'query';
|
||||||
|
value: number;
|
||||||
|
visible: boolean;
|
||||||
|
|
||||||
|
// Private
|
||||||
|
private _unsubscribeAll: Subject<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param {FuseProgressBarService} _fuseProgressBarService
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private _fuseProgressBarService: FuseProgressBarService
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Set the defaults
|
||||||
|
|
||||||
|
// Set the private defaults
|
||||||
|
this._unsubscribeAll = new Subject();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Lifecycle hooks
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On init
|
||||||
|
*/
|
||||||
|
ngOnInit(): void
|
||||||
|
{
|
||||||
|
// Subscribe to the progress bar service properties
|
||||||
|
|
||||||
|
// Buffer value
|
||||||
|
this._fuseProgressBarService.bufferValue
|
||||||
|
.pipe(takeUntil(this._unsubscribeAll))
|
||||||
|
.subscribe((bufferValue) => {
|
||||||
|
this.bufferValue = bufferValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mode
|
||||||
|
this._fuseProgressBarService.mode
|
||||||
|
.pipe(takeUntil(this._unsubscribeAll))
|
||||||
|
.subscribe((mode) => {
|
||||||
|
this.mode = mode;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Value
|
||||||
|
this._fuseProgressBarService.value
|
||||||
|
.pipe(takeUntil(this._unsubscribeAll))
|
||||||
|
.subscribe((value) => {
|
||||||
|
this.value = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Visible
|
||||||
|
this._fuseProgressBarService.visible
|
||||||
|
.pipe(takeUntil(this._unsubscribeAll))
|
||||||
|
.subscribe((visible) => {
|
||||||
|
this.visible = visible;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On destroy
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void
|
||||||
|
{
|
||||||
|
// Unsubscribe from all subscriptions
|
||||||
|
this._unsubscribeAll.next();
|
||||||
|
this._unsubscribeAll.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Public methods
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
}
|
||||||
29
src/@fuse/components/progress-bar/progress-bar.module.ts
Normal file
29
src/@fuse/components/progress-bar/progress-bar.module.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||||
|
|
||||||
|
import { FuseProgressBarComponent } from './progress-bar.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
FuseProgressBarComponent
|
||||||
|
],
|
||||||
|
imports : [
|
||||||
|
CommonModule,
|
||||||
|
RouterModule,
|
||||||
|
|
||||||
|
MatButtonModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatProgressBarModule
|
||||||
|
],
|
||||||
|
exports : [
|
||||||
|
FuseProgressBarComponent
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class FuseProgressBarModule
|
||||||
|
{
|
||||||
|
}
|
||||||
132
src/@fuse/components/progress-bar/progress-bar.service.ts
Normal file
132
src/@fuse/components/progress-bar/progress-bar.service.ts
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router';
|
||||||
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
import { filter } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class FuseProgressBarService
|
||||||
|
{
|
||||||
|
// Private
|
||||||
|
private _bufferValue: BehaviorSubject<number>;
|
||||||
|
private _mode: BehaviorSubject<string>;
|
||||||
|
private _value: BehaviorSubject<number>;
|
||||||
|
private _visible: BehaviorSubject<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param {Router} _router
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private _router: Router
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Initialize the service
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Accessors
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer value
|
||||||
|
*/
|
||||||
|
get bufferValue(): Observable<any>
|
||||||
|
{
|
||||||
|
return this._bufferValue.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
setBufferValue(value: number): void
|
||||||
|
{
|
||||||
|
this._bufferValue.next(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mode
|
||||||
|
*/
|
||||||
|
get mode(): Observable<any>
|
||||||
|
{
|
||||||
|
return this._mode.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
setMode(value: 'determinate' | 'indeterminate' | 'buffer' | 'query'): void
|
||||||
|
{
|
||||||
|
this._mode.next(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value
|
||||||
|
*/
|
||||||
|
get value(): Observable<any>
|
||||||
|
{
|
||||||
|
return this._value.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue(value: number): void
|
||||||
|
{
|
||||||
|
this._value.next(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visible
|
||||||
|
*/
|
||||||
|
get visible(): Observable<any>
|
||||||
|
{
|
||||||
|
return this._visible.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Private methods
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private _init(): void
|
||||||
|
{
|
||||||
|
// Initialize the behavior subjects
|
||||||
|
this._bufferValue = new BehaviorSubject(0);
|
||||||
|
this._mode = new BehaviorSubject('indeterminate');
|
||||||
|
this._value = new BehaviorSubject(0);
|
||||||
|
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.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
this._router.events
|
||||||
|
.pipe(filter((event) => event instanceof NavigationEnd || event instanceof NavigationError || event instanceof NavigationCancel))
|
||||||
|
.subscribe(() => {
|
||||||
|
this.hide();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Public methods
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the progress bar
|
||||||
|
*/
|
||||||
|
show(): void
|
||||||
|
{
|
||||||
|
this._visible.next(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide the progress bar
|
||||||
|
*/
|
||||||
|
hide(): void
|
||||||
|
{
|
||||||
|
this._visible.next(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,21 +1,22 @@
|
|||||||
<div class="fuse-search-bar" [ngClass]="{'expanded':!collapsed}" fxFlex="0 1 auto">
|
<div class="fuse-search-bar" [ngClass]="{'expanded':!collapsed}">
|
||||||
<div [ngClass]="toolbarColor" fxLayout="row" fxLayoutAlign="start center" fxFlex>
|
|
||||||
|
<div class="fuse-search-bar-content">
|
||||||
|
|
||||||
<label for="fuse-search-bar-input">
|
<label for="fuse-search-bar-input">
|
||||||
<button mat-icon-button class="fuse-search-bar-expander" aria-label="Expand Search Bar" (click)="expand()"
|
<button mat-icon-button class="fuse-search-bar-expander" aria-label="Expand Search Bar" (click)="expand()"
|
||||||
*ngIf="collapsed">
|
*ngIf="collapsed">
|
||||||
<mat-icon class="s-24">search</mat-icon>
|
<mat-icon class="s-24 secondary-text">search</mat-icon>
|
||||||
</button>
|
</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>
|
</label>
|
||||||
|
|
||||||
<input id="fuse-search-bar-input" class="ml-24" type="text" placeholder="Search" (input)="search($event)" fxFlex>
|
<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 mat-icon-button" (click)="collapse()"
|
<button mat-icon-button class="fuse-search-bar-collapser" (click)="collapse()"
|
||||||
aria-label="Collapse Search Bar">
|
aria-label="Collapse Search Bar">
|
||||||
<mat-icon class="s-24">close</mat-icon>
|
<mat-icon class="s-24 secondary-text">close</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -3,48 +3,60 @@
|
|||||||
:host {
|
:host {
|
||||||
|
|
||||||
.fuse-search-bar {
|
.fuse-search-bar {
|
||||||
|
display: flex;
|
||||||
|
flex: 0 1 auto;
|
||||||
min-width: 64px;
|
min-width: 64px;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|
||||||
@include media-breakpoint-down('sm') {
|
@include media-breakpoint('xs') {
|
||||||
height: 56px;
|
height: 56px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuse-search-bar-expander,
|
.fuse-search-bar-content {
|
||||||
.fuse-search-bar-collapser {
|
display: flex;
|
||||||
cursor: pointer;
|
flex: 1 1 auto;
|
||||||
padding: 0 20px;
|
align-items: center;
|
||||||
margin: 0;
|
justify-content: flex-start;
|
||||||
width: 64px !important;
|
|
||||||
height: 64px !important;
|
|
||||||
line-height: 64px !important;
|
|
||||||
|
|
||||||
@include media-breakpoint-down('sm') {
|
.fuse-search-bar-expander,
|
||||||
height: 56px !important;
|
.fuse-search-bar-collapser {
|
||||||
line-height: 56px !important;
|
cursor: pointer;
|
||||||
|
padding: 0 20px;
|
||||||
|
margin: 0;
|
||||||
|
width: 64px !important;
|
||||||
|
height: 64px !important;
|
||||||
|
line-height: 64px !important;
|
||||||
|
|
||||||
|
@include media-breakpoint('xs') {
|
||||||
|
height: 56px !important;
|
||||||
|
line-height: 56px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.fuse-search-bar-loader {
|
.fuse-search-bar-loader {
|
||||||
width: 64px !important;
|
width: 64px !important;
|
||||||
height: 64px !important;
|
height: 64px !important;
|
||||||
line-height: 64px !important;
|
line-height: 64px !important;
|
||||||
@include media-breakpoint-down('sm') {
|
|
||||||
height: 56px !important;
|
@include media-breakpoint('xs') {
|
||||||
line-height: 56px !important;
|
height: 56px !important;
|
||||||
|
line-height: 56px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.fuse-search-bar-collapser {
|
.fuse-search-bar-collapser {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#fuse-search-bar-input {
|
#fuse-search-bar-input {
|
||||||
display: none;
|
display: none;
|
||||||
min-height: 64px;
|
flex: 1 0 auto;
|
||||||
background-color: transparent;
|
min-height: 64px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
background-color: transparent;
|
||||||
|
color: currentColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.expanded {
|
&.expanded {
|
||||||
@@ -55,12 +67,15 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
|
||||||
#fuse-search-bar-input {
|
.fuse-search-bar-content {
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fuse-search-bar-collapser {
|
#fuse-search-bar-input {
|
||||||
display: block;
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fuse-search-bar-collapser {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Component, EventEmitter, Output } from '@angular/core';
|
import { Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs/Subscription';
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
import { FuseConfigService } from '@fuse/services/config.service';
|
import { FuseConfigService } from '@fuse/services/config.service';
|
||||||
|
|
||||||
@@ -8,42 +9,91 @@ import { FuseConfigService } from '@fuse/services/config.service';
|
|||||||
templateUrl: './search-bar.component.html',
|
templateUrl: './search-bar.component.html',
|
||||||
styleUrls : ['./search-bar.component.scss']
|
styleUrls : ['./search-bar.component.scss']
|
||||||
})
|
})
|
||||||
export class FuseSearchBarComponent
|
export class FuseSearchBarComponent implements OnInit, OnDestroy
|
||||||
{
|
{
|
||||||
collapsed: boolean;
|
collapsed: boolean;
|
||||||
toolbarColor: string;
|
fuseConfig: any;
|
||||||
@Output() onInput: EventEmitter<any> = new EventEmitter();
|
|
||||||
onConfigChanged: Subscription;
|
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
input: EventEmitter<any>;
|
||||||
|
|
||||||
|
// Private
|
||||||
|
private _unsubscribeAll: Subject<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param {FuseConfigService} _fuseConfigService
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private fuseConfig: FuseConfigService
|
private _fuseConfigService: FuseConfigService
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
// Set the defaults
|
||||||
|
this.input = new EventEmitter();
|
||||||
this.collapsed = true;
|
this.collapsed = true;
|
||||||
this.onConfigChanged =
|
|
||||||
this.fuseConfig.onConfigChanged
|
// Set the private defaults
|
||||||
.subscribe(
|
this._unsubscribeAll = new Subject();
|
||||||
(newSettings) => {
|
|
||||||
this.toolbarColor = newSettings.colorClasses.toolbar;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
collapse()
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ 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;
|
this.collapsed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
expand()
|
/**
|
||||||
|
* Expand
|
||||||
|
*/
|
||||||
|
expand(): void
|
||||||
{
|
{
|
||||||
this.collapsed = false;
|
this.collapsed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
search(event)
|
/**
|
||||||
|
* Search
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
search(event): void
|
||||||
{
|
{
|
||||||
const value = event.target.value;
|
this.input.emit(event.target.value);
|
||||||
|
|
||||||
this.onInput.emit(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import { NgModule } from '@angular/core';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
|
|
||||||
import { MatButtonModule, MatIconModule } from '@angular/material';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
|
||||||
import { FuseSearchBarComponent } from './search-bar.component';
|
import { FuseSearchBarComponent } from './search-bar.component';
|
||||||
|
|
||||||
|
|||||||
11
src/@fuse/components/search-bar/search-bar.theme.scss
Normal file
11
src/@fuse/components/search-bar/search-bar.theme.scss
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
@mixin fuse-search-bar-theme($theme) {
|
||||||
|
|
||||||
|
$background: map-get($theme, background);
|
||||||
|
|
||||||
|
.fuse-search-bar {
|
||||||
|
|
||||||
|
&.expanded {
|
||||||
|
background-color: map-get($background, background);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="shortcuts" fxHide fxShow.gt-sm [ngClass]="toolbarColor">
|
<div class="shortcuts" fxLayout="row" fxHide fxShow.gt-sm>
|
||||||
|
|
||||||
<div fxLayout="row" fxLayoutAlign="space-between center" fxFlex="0 1 auto">
|
<div fxLayout="row" fxLayoutAlign="space-between center" fxFlex="0 1 auto">
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
*ngFor="let shortcutItem of shortcutItems">
|
*ngFor="let shortcutItem of shortcutItems">
|
||||||
|
|
||||||
<a mat-icon-button matTooltip="{{shortcutItem.title}}" [routerLink]="shortcutItem.url">
|
<a mat-icon-button matTooltip="{{shortcutItem.title}}" [routerLink]="shortcutItem.url">
|
||||||
<mat-icon *ngIf="shortcutItem.icon">{{shortcutItem.icon}}</mat-icon>
|
<mat-icon class="secondary-text" *ngIf="shortcutItem.icon">{{shortcutItem.icon}}</mat-icon>
|
||||||
<span *ngIf="!shortcutItem.icon" class="h2 secondary-text text-bold">
|
<span *ngIf="!shortcutItem.icon" class="h2 secondary-text text-bold">
|
||||||
{{shortcutItem.title.substr(0, 1).toUpperCase()}}
|
{{shortcutItem.title.substr(0, 1).toUpperCase()}}
|
||||||
</span>
|
</span>
|
||||||
@@ -42,46 +42,70 @@
|
|||||||
|
|
||||||
<mat-menu #addMenu="matMenu" class="w-240">
|
<mat-menu #addMenu="matMenu" class="w-240">
|
||||||
|
|
||||||
<mat-form-field class="px-16 w-100-p" (click)="$event.stopPropagation()" floatPlaceholder="never">
|
<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)">
|
<input #searchInput matInput placeholder="Search for an app or a page" (input)="search($event)">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-nav-list *ngIf="!searching" style="max-height: 312px; overflow: auto" fusePerfectScrollbar>
|
<mat-nav-list *ngIf="!searching" style="max-height: 312px; overflow: auto" fusePerfectScrollbar>
|
||||||
|
|
||||||
<mat-list-item *ngFor="let shortcutItem of shortcutItems"
|
<mat-list-item *ngFor="let shortcutItem of shortcutItems"
|
||||||
(click)="toggleShortcut($event, shortcutItem)">
|
(click)="toggleShortcut($event, shortcutItem)">
|
||||||
|
|
||||||
<div class="w-100-p" fxLayout="row" fxLayoutAlign="start center">
|
<div class="w-100-p" fxLayout="row" fxLayoutAlign="start center">
|
||||||
<mat-icon mat-list-icon class="mr-8" *ngIf="shortcutItem.icon">{{shortcutItem.icon}}</mat-icon>
|
|
||||||
|
<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"
|
<span class="h2 w-32 h-32 p-4 mr-8 secondary-text text-bold" fxLayout="row"
|
||||||
fxLayoutAlign="center center" *ngIf="!shortcutItem.icon">
|
fxLayoutAlign="center center" *ngIf="!shortcutItem.icon">
|
||||||
{{shortcutItem.title.substr(0, 1).toUpperCase()}}
|
{{shortcutItem.title.substr(0, 1).toUpperCase()}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<p matLine fxFlex>{{shortcutItem.title}}</p>
|
<p matLine fxFlex>{{shortcutItem.title}}</p>
|
||||||
<mat-icon class="ml-8">star</mat-icon>
|
|
||||||
|
<mat-icon class="ml-8 amber-fg">star</mat-icon>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-list-item *ngIf="shortcutItems.length === 0">
|
<mat-list-item *ngIf="shortcutItems.length === 0">
|
||||||
<p>
|
<p>
|
||||||
<small>No shortcuts yet!</small>
|
<small>No shortcuts yet!</small>
|
||||||
</p>
|
</p>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
||||||
|
|
||||||
<mat-nav-list *ngIf="searching" style="max-height: 312px; overflow: auto" fusePerfectScrollbar>
|
<mat-nav-list *ngIf="searching" style="max-height: 312px; overflow: auto" fusePerfectScrollbar>
|
||||||
|
|
||||||
<mat-list-item *ngFor="let navigationItem of filteredNavigationItems"
|
<mat-list-item *ngFor="let navigationItem of filteredNavigationItems"
|
||||||
(click)="toggleShortcut($event, navigationItem)">
|
(click)="toggleShortcut($event, navigationItem)">
|
||||||
|
|
||||||
<div class="w-100-p" fxLayout="row" fxLayoutAlign="start center">
|
<div class="w-100-p" fxLayout="row" fxLayoutAlign="start center">
|
||||||
<mat-icon mat-list-icon class="mr-8" *ngIf="navigationItem.icon">{{navigationItem.icon}}</mat-icon>
|
|
||||||
|
<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"
|
<span class="h2 w-32 h-32 p-4 mr-8 secondary-text text-bold" fxLayout="row"
|
||||||
fxLayoutAlign="center center" *ngIf="!navigationItem.icon">
|
fxLayoutAlign="center center" *ngIf="!navigationItem.icon">
|
||||||
{{navigationItem.title.substr(0, 1).toUpperCase()}}
|
{{navigationItem.title.substr(0, 1).toUpperCase()}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<p matLine fxFlex>{{navigationItem.title}}</p>
|
<p matLine fxFlex>{{navigationItem.title}}</p>
|
||||||
<mat-icon class="ml-8" *ngIf="isInShortcuts(navigationItem)">star</mat-icon>
|
|
||||||
|
<mat-icon class="ml-8 amber-fg" *ngIf="isInShortcuts(navigationItem)">star</mat-icon>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
||||||
|
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
:host {
|
:host {
|
||||||
|
|
||||||
@include media-breakpoint-down('sm') {
|
@include media-breakpoint('lt-md') {
|
||||||
|
|
||||||
#fuse-shortcuts {
|
#fuse-shortcuts {
|
||||||
|
|
||||||
@@ -19,6 +19,10 @@
|
|||||||
display: flex !important;
|
display: flex !important;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
flex: 1 1 auto !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,107 +1,145 @@
|
|||||||
import { Component, ElementRef, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core';
|
import { AfterViewInit, Component, ElementRef, Input, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs/Subscription';
|
import { MediaObserver } from '@angular/flex-layout';
|
||||||
import { ObservableMedia } from '@angular/flex-layout';
|
|
||||||
import { CookieService } from 'ngx-cookie-service';
|
import { CookieService } from 'ngx-cookie-service';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
import { FuseMatchMediaService } from '@fuse/services/match-media.service';
|
import { FuseMatchMediaService } from '@fuse/services/match-media.service';
|
||||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||||
import { FuseConfigService } from '@fuse/services/config.service';
|
|
||||||
|
|
||||||
import { navigation } from 'app/navigation/navigation';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector : 'fuse-shortcuts',
|
selector : 'fuse-shortcuts',
|
||||||
templateUrl: './shortcuts.component.html',
|
templateUrl: './shortcuts.component.html',
|
||||||
styleUrls : ['./shortcuts.component.scss']
|
styleUrls : ['./shortcuts.component.scss']
|
||||||
})
|
})
|
||||||
export class FuseShortcutsComponent implements OnInit, OnDestroy
|
export class FuseShortcutsComponent implements OnInit, AfterViewInit, OnDestroy
|
||||||
{
|
{
|
||||||
shortcutItems: any[] = [];
|
shortcutItems: any[];
|
||||||
navigationItems: any[];
|
navigationItems: any[];
|
||||||
filteredNavigationItems: any[];
|
filteredNavigationItems: any[];
|
||||||
searching = false;
|
searching: boolean;
|
||||||
mobileShortcutsPanelActive = false;
|
mobileShortcutsPanelActive: boolean;
|
||||||
toolbarColor: string;
|
|
||||||
matchMediaSubscription: Subscription;
|
|
||||||
onConfigChanged: Subscription;
|
|
||||||
|
|
||||||
@ViewChild('searchInput') searchInputField;
|
@Input()
|
||||||
@ViewChild('shortcuts') shortcutsEl: ElementRef;
|
navigation: any;
|
||||||
|
|
||||||
|
@ViewChild('searchInput', {static: false})
|
||||||
|
searchInputField;
|
||||||
|
|
||||||
|
@ViewChild('shortcuts', {static: false})
|
||||||
|
shortcutsEl: ElementRef;
|
||||||
|
|
||||||
|
// Private
|
||||||
|
private _unsubscribeAll: Subject<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param {CookieService} _cookieService
|
||||||
|
* @param {FuseMatchMediaService} _fuseMatchMediaService
|
||||||
|
* @param {FuseNavigationService} _fuseNavigationService
|
||||||
|
* @param {MediaObserver} _mediaObserver
|
||||||
|
* @param {Renderer2} _renderer
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private renderer: Renderer2,
|
private _cookieService: CookieService,
|
||||||
private observableMedia: ObservableMedia,
|
private _fuseMatchMediaService: FuseMatchMediaService,
|
||||||
private fuseMatchMedia: FuseMatchMediaService,
|
private _fuseNavigationService: FuseNavigationService,
|
||||||
private fuseNavigationService: FuseNavigationService,
|
private _mediaObserver: MediaObserver,
|
||||||
private fuseConfig: FuseConfigService,
|
private _renderer: Renderer2
|
||||||
private cookieService: CookieService
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.filteredNavigationItems = this.navigationItems = this.fuseNavigationService.getFlatNavigation(navigation);
|
// Set the defaults
|
||||||
|
this.shortcutItems = [];
|
||||||
|
this.searching = false;
|
||||||
|
this.mobileShortcutsPanelActive = false;
|
||||||
|
|
||||||
this.onConfigChanged =
|
// Set the private defaults
|
||||||
this.fuseConfig.onConfigChanged
|
this._unsubscribeAll = new Subject();
|
||||||
.subscribe(
|
|
||||||
(newSettings) => {
|
|
||||||
this.toolbarColor = newSettings.colorClasses.toolbar;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit()
|
// -----------------------------------------------------------------------------------------------------
|
||||||
{
|
// @ Lifecycle hooks
|
||||||
const cookieExists = this.cookieService.check('FUSE2.shortcuts');
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
if ( cookieExists )
|
/**
|
||||||
|
* On init
|
||||||
|
*/
|
||||||
|
ngOnInit(): void
|
||||||
|
{
|
||||||
|
// Get the navigation items and flatten them
|
||||||
|
this.filteredNavigationItems = this.navigationItems = this._fuseNavigationService.getFlatNavigation(this.navigation);
|
||||||
|
|
||||||
|
if ( this._cookieService.check('FUSE2.shortcuts') )
|
||||||
{
|
{
|
||||||
this.shortcutItems = JSON.parse(this.cookieService.get('FUSE2.shortcuts'));
|
this.shortcutItems = JSON.parse(this._cookieService.get('FUSE2.shortcuts'));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// User's shortcut items
|
// User's shortcut items
|
||||||
this.shortcutItems = [
|
this.shortcutItems = [
|
||||||
{
|
{
|
||||||
'title': 'Calendar',
|
title: 'Calendar',
|
||||||
'type' : 'nav-item',
|
type : 'item',
|
||||||
'icon' : 'today',
|
icon : 'today',
|
||||||
'url' : '/apps/calendar'
|
url : '/apps/calendar'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Mail',
|
title: 'Mail',
|
||||||
'type' : 'nav-item',
|
type : 'item',
|
||||||
'icon' : 'email',
|
icon : 'email',
|
||||||
'url' : '/apps/mail'
|
url : '/apps/mail'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Contacts',
|
title: 'Contacts',
|
||||||
'type' : 'nav-item',
|
type : 'item',
|
||||||
'icon' : 'account_box',
|
icon : 'account_box',
|
||||||
'url' : '/apps/contacts'
|
url : '/apps/contacts'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'To-Do',
|
title: 'To-Do',
|
||||||
'type' : 'nav-item',
|
type : 'item',
|
||||||
'icon' : 'check_box',
|
icon : 'check_box',
|
||||||
'url' : '/apps/todo'
|
url : '/apps/todo'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.matchMediaSubscription =
|
}
|
||||||
this.fuseMatchMedia.onMediaChange.subscribe(() => {
|
|
||||||
if ( this.observableMedia.isActive('gt-sm') )
|
ngAfterViewInit(): void
|
||||||
|
{
|
||||||
|
// Subscribe to media changes
|
||||||
|
this._fuseMatchMediaService.onMediaChange
|
||||||
|
.pipe(takeUntil(this._unsubscribeAll))
|
||||||
|
.subscribe(() => {
|
||||||
|
if ( this._mediaObserver.isActive('gt-sm') )
|
||||||
{
|
{
|
||||||
this.hideMobileShortcutsPanel();
|
this.hideMobileShortcutsPanel();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy()
|
/**
|
||||||
|
* On destroy
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void
|
||||||
{
|
{
|
||||||
this.matchMediaSubscription.unsubscribe();
|
// Unsubscribe from all subscriptions
|
||||||
|
this._unsubscribeAll.next();
|
||||||
|
this._unsubscribeAll.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
search(event)
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Public methods
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
search(event): void
|
||||||
{
|
{
|
||||||
const value = event.target.value.toLowerCase();
|
const value = event.target.value.toLowerCase();
|
||||||
|
|
||||||
@@ -120,7 +158,13 @@ export class FuseShortcutsComponent implements OnInit, OnDestroy
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleShortcut(event, itemToToggle)
|
/**
|
||||||
|
* Toggle shortcut
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* @param itemToToggle
|
||||||
|
*/
|
||||||
|
toggleShortcut(event, itemToToggle): void
|
||||||
{
|
{
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
@@ -131,7 +175,7 @@ export class FuseShortcutsComponent implements OnInit, OnDestroy
|
|||||||
this.shortcutItems.splice(i, 1);
|
this.shortcutItems.splice(i, 1);
|
||||||
|
|
||||||
// Save to the cookies
|
// Save to the cookies
|
||||||
this.cookieService.set('FUSE2.shortcuts', JSON.stringify(this.shortcutItems));
|
this._cookieService.set('FUSE2.shortcuts', JSON.stringify(this.shortcutItems));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -140,32 +184,47 @@ export class FuseShortcutsComponent implements OnInit, OnDestroy
|
|||||||
this.shortcutItems.push(itemToToggle);
|
this.shortcutItems.push(itemToToggle);
|
||||||
|
|
||||||
// Save to the cookies
|
// Save to the cookies
|
||||||
this.cookieService.set('FUSE2.shortcuts', JSON.stringify(this.shortcutItems));
|
this._cookieService.set('FUSE2.shortcuts', JSON.stringify(this.shortcutItems));
|
||||||
}
|
}
|
||||||
|
|
||||||
isInShortcuts(navigationItem)
|
/**
|
||||||
|
* Is in shortcuts?
|
||||||
|
*
|
||||||
|
* @param navigationItem
|
||||||
|
* @returns {any}
|
||||||
|
*/
|
||||||
|
isInShortcuts(navigationItem): any
|
||||||
{
|
{
|
||||||
return this.shortcutItems.find(item => {
|
return this.shortcutItems.find(item => {
|
||||||
return item.url === navigationItem.url;
|
return item.url === navigationItem.url;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMenuOpen()
|
/**
|
||||||
|
* On menu open
|
||||||
|
*/
|
||||||
|
onMenuOpen(): void
|
||||||
{
|
{
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.searchInputField.nativeElement.focus();
|
this.searchInputField.nativeElement.focus();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
showMobileShortcutsPanel()
|
/**
|
||||||
|
* Show mobile shortcuts
|
||||||
|
*/
|
||||||
|
showMobileShortcutsPanel(): void
|
||||||
{
|
{
|
||||||
this.mobileShortcutsPanelActive = true;
|
this.mobileShortcutsPanelActive = true;
|
||||||
this.renderer.addClass(this.shortcutsEl.nativeElement, 'show-mobile-panel');
|
this._renderer.addClass(this.shortcutsEl.nativeElement, 'show-mobile-panel');
|
||||||
}
|
}
|
||||||
|
|
||||||
hideMobileShortcutsPanel()
|
/**
|
||||||
|
* Hide mobile shortcuts
|
||||||
|
*/
|
||||||
|
hideMobileShortcutsPanel(): void
|
||||||
{
|
{
|
||||||
this.mobileShortcutsPanelActive = false;
|
this.mobileShortcutsPanelActive = false;
|
||||||
this.renderer.removeClass(this.shortcutsEl.nativeElement, 'show-mobile-panel');
|
this._renderer.removeClass(this.shortcutsEl.nativeElement, 'show-mobile-panel');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,14 @@ import { NgModule } from '@angular/core';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||||
import { MatButtonModule, MatDividerModule, MatFormFieldModule, MatIconModule, MatInputModule, MatListModule, MatMenuModule, MatTooltipModule } from '@angular/material';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatDividerModule } from '@angular/material/divider';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatListModule } from '@angular/material/list';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
import { CookieService } from 'ngx-cookie-service';
|
import { CookieService } from 'ngx-cookie-service';
|
||||||
|
|
||||||
import { FuseShortcutsComponent } from './shortcuts.component';
|
import { FuseShortcutsComponent } from './shortcuts.component';
|
||||||
|
|||||||
11
src/@fuse/components/shortcuts/shortcuts.theme.scss
Normal file
11
src/@fuse/components/shortcuts/shortcuts.theme.scss
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
@mixin fuse-shortcuts-theme($theme) {
|
||||||
|
|
||||||
|
$background: map-get($theme, background);
|
||||||
|
|
||||||
|
#fuse-shortcuts {
|
||||||
|
|
||||||
|
&.show-mobile-panel {
|
||||||
|
background-color: map-get($background, background);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@import "src/@fuse/scss/fuse";
|
||||||
|
|
||||||
fuse-sidebar {
|
fuse-sidebar {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -5,22 +7,27 @@ fuse-sidebar {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
overflow: hidden;
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
width: 280px;
|
width: 280px;
|
||||||
min-width: 280px;
|
min-width: 280px;
|
||||||
max-width: 280px;
|
max-width: 280px;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
transition-property: transform, width, min-width, max-width;
|
|
||||||
transition-duration: 150ms;
|
|
||||||
transition-timing-function: ease-in-out;
|
|
||||||
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.35);
|
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.35);
|
||||||
|
|
||||||
&.left-aligned {
|
@include media-breakpoint('xs') {
|
||||||
|
min-width: 0 !important;
|
||||||
|
max-width: 80vw !important;
|
||||||
|
width: 80vw !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.left-positioned {
|
||||||
left: 0;
|
left: 0;
|
||||||
transform: translateX(-100%);
|
transform: translateX(-100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.right-aligned {
|
&.right-positioned {
|
||||||
right: 0;
|
right: 0;
|
||||||
transform: translateX(100%);
|
transform: translateX(100%);
|
||||||
}
|
}
|
||||||
@@ -38,12 +45,12 @@ fuse-sidebar {
|
|||||||
position: absolute !important;
|
position: absolute !important;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
&:not(.unfolded) {
|
&.animations-enabled {
|
||||||
width: 64px;
|
transition-property: transform, width, min-width, max-width;
|
||||||
min-width: 64px;
|
transition-duration: 150ms;
|
||||||
max-width: 64px;
|
transition-timing-function: ease-in-out;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +60,6 @@ fuse-sidebar {
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 3;
|
z-index: 999;
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
import { Component, ElementRef, HostBinding, HostListener, Inject, Input, OnDestroy, OnInit, Renderer2, ViewEncapsulation } from '@angular/core';
|
import {
|
||||||
|
ChangeDetectorRef, Component, ElementRef, EventEmitter, HostBinding, HostListener, Input, OnDestroy, OnInit, Output, Renderer2, ViewEncapsulation
|
||||||
|
} from '@angular/core';
|
||||||
import { animate, AnimationBuilder, AnimationPlayer, style } from '@angular/animations';
|
import { animate, AnimationBuilder, AnimationPlayer, style } from '@angular/animations';
|
||||||
import { ObservableMedia } from '@angular/flex-layout';
|
import { MediaObserver } from '@angular/flex-layout';
|
||||||
import { Subscription } from 'rxjs/Subscription';
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
import { FuseSidebarService } from './sidebar.service';
|
import { FuseSidebarService } from './sidebar.service';
|
||||||
import { FuseMatchMediaService } from '@fuse/services/match-media.service';
|
import { FuseMatchMediaService } from '@fuse/services/match-media.service';
|
||||||
import { DOCUMENT } from '@angular/common';
|
import { FuseConfigService } from '@fuse/services/config.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector : 'fuse-sidebar',
|
selector : 'fuse-sidebar',
|
||||||
@@ -19,9 +22,13 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
|
|||||||
@Input()
|
@Input()
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
// Align
|
// Key
|
||||||
@Input()
|
@Input()
|
||||||
align: string;
|
key: string;
|
||||||
|
|
||||||
|
// Position
|
||||||
|
@Input()
|
||||||
|
position: 'left' | 'right';
|
||||||
|
|
||||||
// Open
|
// Open
|
||||||
@HostBinding('class.open')
|
@HostBinding('class.open')
|
||||||
@@ -35,61 +42,196 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
|
|||||||
@HostBinding('class.locked-open')
|
@HostBinding('class.locked-open')
|
||||||
isLockedOpen: boolean;
|
isLockedOpen: boolean;
|
||||||
|
|
||||||
// Folded
|
// Folded width
|
||||||
@HostBinding('class.folded')
|
|
||||||
@Input()
|
@Input()
|
||||||
folded: boolean;
|
foldedWidth: number;
|
||||||
|
|
||||||
|
// Folded auto trigger on hover
|
||||||
|
@Input()
|
||||||
|
foldedAutoTriggerOnHover: boolean;
|
||||||
|
|
||||||
// Folded unfolded
|
// Folded unfolded
|
||||||
@HostBinding('class.unfolded')
|
@HostBinding('class.unfolded')
|
||||||
unfolded: boolean;
|
unfolded: boolean;
|
||||||
|
|
||||||
|
// Invisible overlay
|
||||||
|
@Input()
|
||||||
|
invisibleOverlay: boolean;
|
||||||
|
|
||||||
|
// Folded changed
|
||||||
|
@Output()
|
||||||
|
foldedChanged: EventEmitter<boolean>;
|
||||||
|
|
||||||
|
// Opened changed
|
||||||
|
@Output()
|
||||||
|
openedChanged: EventEmitter<boolean>;
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
|
private _folded: boolean;
|
||||||
|
private _fuseConfig: any;
|
||||||
private _wasActive: boolean;
|
private _wasActive: boolean;
|
||||||
|
private _wasFolded: boolean;
|
||||||
private _backdrop: HTMLElement | null = null;
|
private _backdrop: HTMLElement | null = null;
|
||||||
private _player: AnimationPlayer;
|
private _player: AnimationPlayer;
|
||||||
private _matchMediaWatcher: Subscription;
|
private _unsubscribeAll: Subject<any>;
|
||||||
|
|
||||||
|
@HostBinding('class.animations-enabled')
|
||||||
|
private _animationsEnabled: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param renderer
|
* @param {AnimationBuilder} _animationBuilder
|
||||||
* @param elementRef
|
* @param {ChangeDetectorRef} _changeDetectorRef
|
||||||
* @param animationBuilder
|
* @param {ElementRef} _elementRef
|
||||||
* @param sidebarService
|
* @param {FuseConfigService} _fuseConfigService
|
||||||
* @param matchMedia
|
* @param {FuseMatchMediaService} _fuseMatchMediaService
|
||||||
* @param media
|
* @param {FuseSidebarService} _fuseSidebarService
|
||||||
* @param document
|
* @param {MediaObserver} _mediaObserver
|
||||||
|
* @param {Renderer2} _renderer
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private renderer: Renderer2,
|
private _animationBuilder: AnimationBuilder,
|
||||||
private elementRef: ElementRef,
|
private _changeDetectorRef: ChangeDetectorRef,
|
||||||
private animationBuilder: AnimationBuilder,
|
private _elementRef: ElementRef,
|
||||||
private sidebarService: FuseSidebarService,
|
private _fuseConfigService: FuseConfigService,
|
||||||
private matchMedia: FuseMatchMediaService,
|
private _fuseMatchMediaService: FuseMatchMediaService,
|
||||||
private media: ObservableMedia,
|
private _fuseSidebarService: FuseSidebarService,
|
||||||
@Inject(DOCUMENT) private document: any
|
private _mediaObserver: MediaObserver,
|
||||||
|
private _renderer: Renderer2
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Set the defaults
|
// Set the defaults
|
||||||
|
this.foldedAutoTriggerOnHover = true;
|
||||||
|
this.foldedWidth = 64;
|
||||||
|
this.foldedChanged = new EventEmitter();
|
||||||
|
this.openedChanged = new EventEmitter();
|
||||||
this.opened = false;
|
this.opened = false;
|
||||||
this.folded = false;
|
this.position = 'left';
|
||||||
this.align = '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);
|
||||||
|
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
|
* On init
|
||||||
*/
|
*/
|
||||||
ngOnInit(): void
|
ngOnInit(): void
|
||||||
{
|
{
|
||||||
// Register the sidebar
|
// Subscribe to config changes
|
||||||
this.sidebarService.register(this.name, this);
|
this._fuseConfigService.config
|
||||||
|
.pipe(takeUntil(this._unsubscribeAll))
|
||||||
|
.subscribe((config) => {
|
||||||
|
this._fuseConfig = config;
|
||||||
|
});
|
||||||
|
|
||||||
// Setup alignment
|
// Register the sidebar
|
||||||
this._setupAlignment();
|
this._fuseSidebarService.register(this.name, this);
|
||||||
|
|
||||||
|
// Setup visibility
|
||||||
|
this._setupVisibility();
|
||||||
|
|
||||||
|
// Setup position
|
||||||
|
this._setupPosition();
|
||||||
|
|
||||||
// Setup lockedOpen
|
// Setup lockedOpen
|
||||||
this._setupLockedOpen();
|
this._setupLockedOpen();
|
||||||
|
|
||||||
|
// Setup folded
|
||||||
|
this._setupFolded();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,27 +239,54 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
|
|||||||
*/
|
*/
|
||||||
ngOnDestroy(): void
|
ngOnDestroy(): void
|
||||||
{
|
{
|
||||||
// Unregister the sidebar
|
// If the sidebar is folded, unfold it to revert modifications
|
||||||
this.sidebarService.unregister(this.name);
|
if ( this.folded )
|
||||||
|
{
|
||||||
|
this.unfold();
|
||||||
|
}
|
||||||
|
|
||||||
// Unregister the media watcher
|
// Unregister the sidebar
|
||||||
this._matchMediaWatcher.unsubscribe();
|
this._fuseSidebarService.unregister(this.name);
|
||||||
|
|
||||||
|
// Unsubscribe from all subscriptions
|
||||||
|
this._unsubscribeAll.next();
|
||||||
|
this._unsubscribeAll.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Private methods
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup the alignment
|
* Setup the visibility of the sidebar
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private _setupAlignment(): void
|
private _setupVisibility(): void
|
||||||
{
|
{
|
||||||
if ( this.align === 'left' )
|
// 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, 'left-aligned');
|
this._renderer.addClass(this._elementRef.nativeElement, 'right-positioned');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.renderer.addClass(this.elementRef.nativeElement, 'right-aligned');
|
this._renderer.addClass(this._elementRef.nativeElement, 'left-positioned');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,19 +300,26 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
|
|||||||
// Return if the lockedOpen wasn't set
|
// Return if the lockedOpen wasn't set
|
||||||
if ( !this.lockedOpen )
|
if ( !this.lockedOpen )
|
||||||
{
|
{
|
||||||
|
// Return
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the wasActive for the first time
|
// Set the wasActive for the first time
|
||||||
this._wasActive = false;
|
this._wasActive = false;
|
||||||
|
|
||||||
// Act on every media change
|
// Set the wasFolded
|
||||||
this._matchMediaWatcher =
|
this._wasFolded = this.folded;
|
||||||
|
|
||||||
this.matchMedia.onMediaChange.subscribe(() => {
|
// Show the sidebar
|
||||||
|
this._showSidebar();
|
||||||
|
|
||||||
|
// Act on every media change
|
||||||
|
this._fuseMatchMediaService.onMediaChange
|
||||||
|
.pipe(takeUntil(this._unsubscribeAll))
|
||||||
|
.subscribe(() => {
|
||||||
|
|
||||||
// Get the active status
|
// Get the active status
|
||||||
const isActive = this.media.isActive(this.lockedOpen);
|
const isActive = this._mediaObserver.isActive(this.lockedOpen);
|
||||||
|
|
||||||
// If the both status are the same, don't act
|
// If the both status are the same, don't act
|
||||||
if ( this._wasActive === isActive )
|
if ( this._wasActive === isActive )
|
||||||
@@ -151,14 +327,36 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the new active status
|
|
||||||
this._wasActive = isActive;
|
|
||||||
|
|
||||||
// Activate the lockedOpen
|
// Activate the lockedOpen
|
||||||
if ( isActive )
|
if ( isActive )
|
||||||
{
|
{
|
||||||
// Set the lockedOpen status
|
// Set the lockedOpen status
|
||||||
this.isLockedOpen = true;
|
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
|
// De-Activate the lockedOpen
|
||||||
else
|
else
|
||||||
@@ -168,10 +366,225 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
|
|||||||
|
|
||||||
// Unfold the sidebar in case if it was folded
|
// Unfold the sidebar in case if it was folded
|
||||||
this.unfold();
|
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);
|
||||||
|
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 the sidebar
|
||||||
*/
|
*/
|
||||||
@@ -182,14 +595,23 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable the animations
|
||||||
|
this._enableAnimations();
|
||||||
|
|
||||||
|
// Show the sidebar
|
||||||
|
this._showSidebar();
|
||||||
|
|
||||||
// Show the backdrop
|
// Show the backdrop
|
||||||
this.showBackdrop();
|
this._showBackdrop();
|
||||||
|
|
||||||
// Set the opened status
|
// Set the opened status
|
||||||
this.opened = true;
|
this.opened = true;
|
||||||
|
|
||||||
// Add a css class to the body
|
// Emit the 'openedChanged' event
|
||||||
this.renderer.addClass(this.document.body, 'fuse-sidebar-opened');
|
this.openedChanged.emit(this.opened);
|
||||||
|
|
||||||
|
// Mark for check
|
||||||
|
this._changeDetectorRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -197,19 +619,28 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
|
|||||||
*/
|
*/
|
||||||
close(): void
|
close(): void
|
||||||
{
|
{
|
||||||
if ( !this.opened )
|
if ( !this.opened || this.isLockedOpen )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable the animations
|
||||||
|
this._enableAnimations();
|
||||||
|
|
||||||
// Hide the backdrop
|
// Hide the backdrop
|
||||||
this.hideBackdrop();
|
this._hideBackdrop();
|
||||||
|
|
||||||
// Set the opened status
|
// Set the opened status
|
||||||
this.opened = false;
|
this.opened = false;
|
||||||
|
|
||||||
// Remove the css class from the body
|
// Emit the 'openedChanged' event
|
||||||
this.renderer.removeClass(this.document.body, 'fuse-sidebar-opened');
|
this.openedChanged.emit(this.opened);
|
||||||
|
|
||||||
|
// Hide the sidebar
|
||||||
|
this._hideSidebar();
|
||||||
|
|
||||||
|
// Mark for check
|
||||||
|
this._changeDetectorRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -233,17 +664,13 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
|
|||||||
@HostListener('mouseenter')
|
@HostListener('mouseenter')
|
||||||
onMouseEnter(): void
|
onMouseEnter(): void
|
||||||
{
|
{
|
||||||
// Only work if the sidebar is folded
|
// Only work if the auto trigger is enabled
|
||||||
if ( !this.folded )
|
if ( !this.foldedAutoTriggerOnHover )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unfold the sidebar temporarily
|
this.unfoldTemporarily();
|
||||||
this.unfolded = true;
|
|
||||||
|
|
||||||
// Add a css class to the body
|
|
||||||
this.renderer.addClass(this.document.body, 'fuse-sidebar-folded-unfolded');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -252,17 +679,13 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
|
|||||||
@HostListener('mouseleave')
|
@HostListener('mouseleave')
|
||||||
onMouseLeave(): void
|
onMouseLeave(): void
|
||||||
{
|
{
|
||||||
// Only work if the sidebar is folded
|
// Only work if the auto trigger is enabled
|
||||||
if ( !this.folded )
|
if ( !this.foldedAutoTriggerOnHover )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fold the sidebar back
|
this.foldTemporarily();
|
||||||
this.unfolded = false;
|
|
||||||
|
|
||||||
// Remove the css class from the body
|
|
||||||
this.renderer.removeClass(this.document.body, 'fuse-sidebar-folded-unfolded');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -270,10 +693,20 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
|
|||||||
*/
|
*/
|
||||||
fold(): void
|
fold(): void
|
||||||
{
|
{
|
||||||
|
// Only work if the sidebar is not folded
|
||||||
|
if ( this.folded )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable the animations
|
||||||
|
this._enableAnimations();
|
||||||
|
|
||||||
|
// Fold
|
||||||
this.folded = true;
|
this.folded = true;
|
||||||
|
|
||||||
// Add a css class to the body
|
// Mark for check
|
||||||
this.renderer.addClass(this.document.body, 'fuse-sidebar-folded');
|
this._changeDetectorRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -281,10 +714,20 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
|
|||||||
*/
|
*/
|
||||||
unfold(): void
|
unfold(): void
|
||||||
{
|
{
|
||||||
|
// Only work if the sidebar is folded
|
||||||
|
if ( !this.folded )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable the animations
|
||||||
|
this._enableAnimations();
|
||||||
|
|
||||||
|
// Unfold
|
||||||
this.folded = false;
|
this.folded = false;
|
||||||
|
|
||||||
// Remove the css class from the body
|
// Mark for check
|
||||||
this.renderer.removeClass(this.document.body, 'fuse-sidebar-folded');
|
this._changeDetectorRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -303,66 +746,56 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the backdrop
|
* Fold the temporarily unfolded sidebar back
|
||||||
*/
|
*/
|
||||||
showBackdrop(): void
|
foldTemporarily(): void
|
||||||
{
|
{
|
||||||
// Create the backdrop element
|
// Only work if the sidebar is folded
|
||||||
this._backdrop = this.renderer.createElement('div');
|
if ( !this.folded )
|
||||||
|
|
||||||
// Add a class to the backdrop element
|
|
||||||
this._backdrop.classList.add('fuse-sidebar-overlay');
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hide the backdrop
|
|
||||||
*/
|
|
||||||
hideBackdrop(): void
|
|
||||||
{
|
|
||||||
if ( !this._backdrop )
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the leave animation and attach it to the player
|
// Enable the animations
|
||||||
this._player =
|
this._enableAnimations();
|
||||||
this.animationBuilder
|
|
||||||
.build([
|
|
||||||
animate('300ms ease', style({opacity: 0}))
|
|
||||||
]).create(this._backdrop);
|
|
||||||
|
|
||||||
// Play the animation
|
// Fold the sidebar back
|
||||||
this._player.play();
|
this.unfolded = false;
|
||||||
|
|
||||||
// Once the animation is done...
|
// Set the folded width
|
||||||
this._player.onDone(() => {
|
const styleValue = this.foldedWidth + 'px';
|
||||||
|
|
||||||
// If the backdrop still exists...
|
this._renderer.setStyle(this._elementRef.nativeElement, 'width', styleValue);
|
||||||
if ( this._backdrop )
|
this._renderer.setStyle(this._elementRef.nativeElement, 'min-width', styleValue);
|
||||||
{
|
this._renderer.setStyle(this._elementRef.nativeElement, 'max-width', styleValue);
|
||||||
// Remove the backdrop
|
|
||||||
this._backdrop.parentNode.removeChild(this._backdrop);
|
// Mark for check
|
||||||
this._backdrop = null;
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ import { Injectable } from '@angular/core';
|
|||||||
|
|
||||||
import { FuseSidebarComponent } from './sidebar.component';
|
import { FuseSidebarComponent } from './sidebar.component';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
export class FuseSidebarService
|
export class FuseSidebarService
|
||||||
{
|
{
|
||||||
// Private
|
// Private
|
||||||
@@ -46,7 +48,7 @@ export class FuseSidebarService
|
|||||||
// Check if the sidebar exists
|
// Check if the sidebar exists
|
||||||
if ( !this._registry[key] )
|
if ( !this._registry[key] )
|
||||||
{
|
{
|
||||||
console.error(`The sidebar with the key '${key}' doesn't exist in the registry.`);
|
console.warn(`The sidebar with the key '${key}' doesn't exist in the registry.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unregister the sidebar
|
// Unregister the sidebar
|
||||||
@@ -57,13 +59,14 @@ export class FuseSidebarService
|
|||||||
* Return the sidebar with the given key
|
* Return the sidebar with the given key
|
||||||
*
|
*
|
||||||
* @param key
|
* @param key
|
||||||
|
* @returns {FuseSidebarComponent}
|
||||||
*/
|
*/
|
||||||
getSidebar(key): any
|
getSidebar(key): FuseSidebarComponent
|
||||||
{
|
{
|
||||||
// Check if the sidebar exists
|
// Check if the sidebar exists
|
||||||
if ( !this._registry[key] )
|
if ( !this._registry[key] )
|
||||||
{
|
{
|
||||||
console.error(`The sidebar with the key '${key}' doesn't exist in the registry.`);
|
console.warn(`The sidebar with the key '${key}' doesn't exist in the registry.`);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/@fuse/components/sidebar/sidebar.theme.scss
Normal file
16
src/@fuse/components/sidebar/sidebar.theme.scss
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
@mixin fuse-sidebar-theme($theme) {
|
||||||
|
|
||||||
|
$background: map-get($theme, background);
|
||||||
|
|
||||||
|
fuse-sidebar {
|
||||||
|
background: map-get($background, background);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fuse-sidebar-overlay {
|
||||||
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
|
|
||||||
|
&.fuse-sidebar-overlay-invisible {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,105 +1,547 @@
|
|||||||
<button #openButton mat-icon-button class="open-button mat-primary-bg mat-elevation-z2" (click)="openBar()">
|
<div class="theme-options-panel" fusePerfectScrollbar>
|
||||||
<mat-icon>settings</mat-icon>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div class="theme-options-panel-overlay" #overlay [fxHide]="barClosed" [@fadeInOut]="!barClosed"></div>
|
<div class="header">
|
||||||
|
|
||||||
<div #panel class="theme-options-panel mat-white-bg mat-elevation-z8">
|
<span class="title">Theme Options</span>
|
||||||
|
|
||||||
<button mat-icon-button class="close-button" (click)="closeBar()">
|
<button mat-icon-button class="close-button" (click)="toggleSidebarOpen('themeOptionsPanel')">
|
||||||
<mat-icon>close</mat-icon>
|
<mat-icon>close</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="theme-options-panel-inner" fxLayout="column" fxLayoutAlign="start start">
|
</div>
|
||||||
|
|
||||||
<h3>Navigation:</h3>
|
<form [formGroup]="form">
|
||||||
<mat-radio-group [(ngModel)]="config.layout.navigation" (ngModelChange)="onSettingsChange()"
|
|
||||||
fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign="start start">
|
|
||||||
<mat-radio-button class="mr-8 mb-8" value="top">Top</mat-radio-button>
|
|
||||||
<mat-radio-button class="mr-8 mb-8" value="left">Left</mat-radio-button>
|
|
||||||
<mat-radio-button class="mr-8 mb-8" value="right">Right</mat-radio-button>
|
|
||||||
<mat-radio-button class="mr-8 mb-8" value="none">None</mat-radio-button>
|
|
||||||
</mat-radio-group>
|
|
||||||
|
|
||||||
<h3>Navigation Fold (for vertical navigation):</h3>
|
<!-- COLOR THEME -->
|
||||||
<mat-slide-toggle [(ngModel)]="config.layout.navigationFolded"
|
<div class="group">
|
||||||
(change)="onSettingsChange()">
|
|
||||||
Folded
|
|
||||||
</mat-slide-toggle>
|
|
||||||
|
|
||||||
<h3 class="mt-24">Toolbar:</h3>
|
<h2>Color themes</h2>
|
||||||
<mat-radio-group [(ngModel)]="config.layout.toolbar" (ngModelChange)="onSettingsChange()"
|
|
||||||
fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign="start start">
|
|
||||||
<mat-radio-button class="mr-8 mb-8" value="below">Below</mat-radio-button>
|
|
||||||
<mat-radio-button class="mr-8 mb-8" value="above">Above</mat-radio-button>
|
|
||||||
<mat-radio-button class="mr-8 mb-8" value="none">None</mat-radio-button>
|
|
||||||
</mat-radio-group>
|
|
||||||
|
|
||||||
<h3 class="mt-24">Footer:</h3>
|
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="colorTheme">
|
||||||
<mat-radio-group [(ngModel)]="config.layout.footer" (ngModelChange)="onSettingsChange()"
|
<mat-radio-button class="mb-12" value="theme-default">Default Light</mat-radio-button>
|
||||||
fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign="start start">
|
<mat-radio-button class="mb-12" value="theme-yellow-light">Yellow Light</mat-radio-button>
|
||||||
<mat-radio-button class="mr-8 mb-8" value="below">Below</mat-radio-button>
|
<mat-radio-button class="mb-12" value="theme-blue-gray-dark">Blue-Gray Dark</mat-radio-button>
|
||||||
<mat-radio-button class="mr-8 mb-8" value="above">Above</mat-radio-button>
|
<mat-radio-button class="mb-12" value="theme-pink-dark">Pink Dark</mat-radio-button>
|
||||||
<mat-radio-button class="mr-8 mb-8" value="none">None</mat-radio-button>
|
</mat-radio-group>
|
||||||
</mat-radio-group>
|
|
||||||
|
|
||||||
<h3 class="mt-24">Layout Mode:</h3>
|
|
||||||
<mat-radio-group [(ngModel)]="config.layout.mode" (ngModelChange)="onSettingsChange()"
|
|
||||||
fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign="start start">
|
|
||||||
<mat-radio-button class="mr-8 mb-8" value="boxed">Boxed</mat-radio-button>
|
|
||||||
<mat-radio-button class="mr-8 mb-8" value="fullwidth">Fullwidth</mat-radio-button>
|
|
||||||
</mat-radio-group>
|
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
|
||||||
|
|
||||||
<h3>Colors:</h3>
|
|
||||||
<div class="colors">
|
|
||||||
|
|
||||||
<div fxFlex fxLayout="row" fxLayoutAlign="space-between center">
|
|
||||||
<h4 class="mr-8">Toolbar Color</h4>
|
|
||||||
<fuse-material-color-picker [(selectedClass)]="config.colorClasses.toolbar"
|
|
||||||
(onValueChange)="onSettingsChange()"></fuse-material-color-picker>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div fxFlex fxLayout="row" fxLayoutAlign="space-between center">
|
|
||||||
<h4 class="mr-8">Navigation Bar Color</h4>
|
|
||||||
<fuse-material-color-picker [(selectedClass)]="config.colorClasses.navbar"
|
|
||||||
(onValueChange)="onSettingsChange()"></fuse-material-color-picker>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div fxFlex fxLayout="row" fxLayoutAlign="space-between center">
|
|
||||||
<h4 class="mr-8">Footer Color</h4>
|
|
||||||
<fuse-material-color-picker [(selectedClass)]="config.colorClasses.footer"
|
|
||||||
(onValueChange)="onSettingsChange()"></fuse-material-color-picker>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<!-- LAYOUT STYLES -->
|
||||||
|
<div class="group" formGroupName="layout">
|
||||||
|
|
||||||
<h3>Router Animation:</h3>
|
<h2>Layout Styles</h2>
|
||||||
<mat-form-field class="w-100-p">
|
|
||||||
<mat-select class="p-0" [(ngModel)]="config.routerAnimation">
|
<mat-radio-group fxLayout="column" fxLayoutAlign="start start" formControlName="style">
|
||||||
<mat-option value="none">
|
|
||||||
None
|
<mat-radio-button class="mb-12" value="vertical-layout-1">
|
||||||
</mat-option>
|
Vertical Layout #1
|
||||||
<mat-option value="slideUp">
|
</mat-radio-button>
|
||||||
Slide up
|
|
||||||
</mat-option>
|
<mat-radio-button class="mb-12" value="vertical-layout-2">
|
||||||
<mat-option value="slideDown">
|
Vertical Layout #2
|
||||||
Slide down
|
</mat-radio-button>
|
||||||
</mat-option>
|
|
||||||
<mat-option value="slideRight">
|
<mat-radio-button class="mb-12" value="vertical-layout-3">
|
||||||
Slide right
|
Vertical Layout #3
|
||||||
</mat-option>
|
</mat-radio-button>
|
||||||
<mat-option value="slideLeft">
|
|
||||||
Slide left
|
<mat-radio-button class="mb-12" value="horizontal-layout-1">
|
||||||
</mat-option>
|
Horizontal Layout #1
|
||||||
<mat-option value="fadeIn">
|
</mat-radio-button>
|
||||||
Fade in
|
|
||||||
</mat-option>
|
</mat-radio-group>
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
<!-- DIFFERENT FORMS BASED ON LAYOUT STYLES -->
|
||||||
</div>
|
<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-16 mb-8">Primary background:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="primaryBackground"></fuse-material-color-picker>
|
||||||
|
|
||||||
|
<h3 class="mt-16 mb-8">Secondary background:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="secondaryBackground"></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>
|
||||||
|
|
||||||
|
<mat-checkbox class="mt-24" formControlName="customBackgroundColor">
|
||||||
|
Use custom background color
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<h3 class="mt-24 mb-8">Background color:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="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>
|
||||||
|
|
||||||
|
<mat-checkbox class="mt-24" formControlName="customBackgroundColor">
|
||||||
|
Use custom background color
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<h3 class="mt-24 mb-8">Color:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="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-16 mb-8">Primary background:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="primaryBackground"></fuse-material-color-picker>
|
||||||
|
|
||||||
|
<h3 class="mt-16 mb-8">Secondary background:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="secondaryBackground"></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>
|
||||||
|
|
||||||
|
<mat-checkbox class="mt-24" formControlName="customBackgroundColor">
|
||||||
|
Use custom background color
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<h3 class="mt-24 mb-8">Background color:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="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>
|
||||||
|
|
||||||
|
<mat-checkbox class="mt-24" formControlName="customBackgroundColor">
|
||||||
|
Use custom background color
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<h3 class="mt-24 mb-8">Background color:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="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-16 mb-8">Primary background:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="primaryBackground"></fuse-material-color-picker>
|
||||||
|
|
||||||
|
<h3 class="mt-16 mb-8">Secondary background:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="secondaryBackground"></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>
|
||||||
|
|
||||||
|
<mat-checkbox class="mt-24" formControlName="customBackgroundColor">
|
||||||
|
Use custom background color
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<h3 class="mt-24 mb-8">Background color:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="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>
|
||||||
|
|
||||||
|
<mat-checkbox class="mt-24" formControlName="customBackgroundColor">
|
||||||
|
Use custom background color
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<h3 class="mt-24 mb-8">Background color:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="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-16 mb-8">Primary background:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="primaryBackground">
|
||||||
|
</fuse-material-color-picker>
|
||||||
|
|
||||||
|
<h3 class="mt-16 mb-8">Secondary background (Vertical):</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="secondaryBackground">
|
||||||
|
</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>
|
||||||
|
|
||||||
|
<mat-checkbox class="mt-24" formControlName="customBackgroundColor">
|
||||||
|
Use custom background color
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<h3 class="mt-24 mb-8">Background color:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="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>
|
||||||
|
|
||||||
|
<mat-checkbox class="mt-24" formControlName="customBackgroundColor">
|
||||||
|
Use custom background color
|
||||||
|
</mat-checkbox>
|
||||||
|
|
||||||
|
<h3 class="mt-24 mb-8">Background color:</h3>
|
||||||
|
<fuse-material-color-picker class="mb-16"
|
||||||
|
formControlName="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>
|
</div>
|
||||||
|
|||||||
@@ -9,107 +9,67 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:host {
|
fuse-theme-options {
|
||||||
position: fixed;
|
display: flex;
|
||||||
display: block;
|
overflow: hidden;
|
||||||
right: 0;
|
|
||||||
top: 160px;
|
|
||||||
z-index: 998;
|
|
||||||
|
|
||||||
&.bar-closed .theme-options-panel {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-options-panel {
|
.theme-options-panel {
|
||||||
position: absolute;
|
display: flex;
|
||||||
right: 0;
|
flex-direction: column;
|
||||||
top: 0;
|
flex: 1 0 auto;
|
||||||
width: 360px;
|
padding: 40px 24px 24px 24px;
|
||||||
transform: translate3d(100%, 0, 0);
|
|
||||||
z-index: 999;
|
|
||||||
max-height: calc(100vh - 200px);
|
|
||||||
padding: 24px;
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
|
||||||
@include media-breakpoint-down('xs') {
|
.header {
|
||||||
top: -120px;
|
display: flex;
|
||||||
max-height: calc(100vh - 100px);
|
flex: 0 1 auto;
|
||||||
width: 90vw;
|
margin-bottom: 32px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-button {
|
form {
|
||||||
position: absolute;
|
display: flex;
|
||||||
top: 8px;
|
flex: 1 1 auto;
|
||||||
right: 8px;
|
flex-direction: column;
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
.group {
|
||||||
font-size: 14px;
|
display: flex;
|
||||||
font-weight: 500;
|
flex: 1 0 auto;
|
||||||
color: rgba(0, 0, 0, 0.54);
|
flex-direction: column;
|
||||||
}
|
position: relative;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 28px 16px 8px 16px;
|
||||||
|
margin: 16px 0;
|
||||||
|
|
||||||
.mat-divider {
|
h2 {
|
||||||
display: block !important;
|
position: absolute;
|
||||||
width: 100%;
|
top: -11px;
|
||||||
margin: 24px 0 16px 0;
|
left: 8px;
|
||||||
}
|
margin: 0;
|
||||||
|
padding: 0 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
.colors {
|
h3 {
|
||||||
display: block !important;
|
font-size: 14px;
|
||||||
width: 100%;
|
font-weight: 600;
|
||||||
|
margin: 24px 0 16px 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
&:first-of-type {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-options-panel-overlay {
|
|
||||||
position: fixed;
|
|
||||||
display: block;
|
|
||||||
background: rgba(0, 0, 0, 0);
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
z-index: 998;
|
|
||||||
|
|
||||||
@include media-breakpoint-down('sm') {
|
|
||||||
background: rgba(0, 0, 0, 0.37);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mat-list .mat-list-item {
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mat-divider {
|
|
||||||
margin: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.open-button {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: -48px;
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
line-height: 48px;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 0;
|
|
||||||
margin: 0;
|
|
||||||
pointer-events: auto;
|
|
||||||
opacity: .75;
|
|
||||||
z-index: 998;
|
|
||||||
|
|
||||||
mat-icon {
|
|
||||||
animation: rotating 3s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,115 +1,341 @@
|
|||||||
import { Component, ElementRef, HostBinding, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core';
|
import { Component, HostBinding, Inject, OnDestroy, OnInit, Renderer2, ViewEncapsulation } from '@angular/core';
|
||||||
import { style, animate, AnimationBuilder, AnimationPlayer } from '@angular/animations';
|
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
|
||||||
import { Subscription } from 'rxjs/Subscription';
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
import { fuseAnimations } from '@fuse/animations';
|
import { fuseAnimations } from '@fuse/animations';
|
||||||
import { FuseConfigService } from '@fuse/services/config.service';
|
import { FuseConfigService } from '@fuse/services/config.service';
|
||||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||||
|
import { FuseSidebarService } from '@fuse/components/sidebar/sidebar.service';
|
||||||
import { navigation } from 'app/navigation/navigation';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector : 'fuse-theme-options',
|
selector : 'fuse-theme-options',
|
||||||
templateUrl: './theme-options.component.html',
|
templateUrl : './theme-options.component.html',
|
||||||
styleUrls : ['./theme-options.component.scss'],
|
styleUrls : ['./theme-options.component.scss'],
|
||||||
animations : fuseAnimations
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
animations : fuseAnimations
|
||||||
})
|
})
|
||||||
export class FuseThemeOptionsComponent implements OnInit, OnDestroy
|
export class FuseThemeOptionsComponent implements OnInit, OnDestroy
|
||||||
{
|
{
|
||||||
@ViewChild('openButton') openButton;
|
fuseConfig: any;
|
||||||
@ViewChild('panel') panel;
|
form: FormGroup;
|
||||||
@ViewChild('overlay') overlay: ElementRef;
|
|
||||||
|
|
||||||
public player: AnimationPlayer;
|
@HostBinding('class.bar-closed')
|
||||||
config: any;
|
barClosed: boolean;
|
||||||
|
|
||||||
onConfigChanged: Subscription;
|
// Private
|
||||||
|
private _unsubscribeAll: Subject<any>;
|
||||||
@HostBinding('class.bar-closed') barClosed: boolean;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param {DOCUMENT} document
|
||||||
|
* @param {FormBuilder} _formBuilder
|
||||||
|
* @param {FuseConfigService} _fuseConfigService
|
||||||
|
* @param {FuseNavigationService} _fuseNavigationService
|
||||||
|
* @param {FuseSidebarService} _fuseSidebarService
|
||||||
|
* @param {Renderer2} _renderer
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private animationBuilder: AnimationBuilder,
|
@Inject(DOCUMENT) private document: any,
|
||||||
private fuseConfig: FuseConfigService,
|
private _formBuilder: FormBuilder,
|
||||||
private navigationService: FuseNavigationService,
|
private _fuseConfigService: FuseConfigService,
|
||||||
private renderer: Renderer2
|
private _fuseNavigationService: FuseNavigationService,
|
||||||
|
private _fuseSidebarService: FuseSidebarService,
|
||||||
|
private _renderer: Renderer2
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
// Set the defaults
|
||||||
this.barClosed = true;
|
this.barClosed = true;
|
||||||
|
|
||||||
this.onConfigChanged =
|
// Set the private defaults
|
||||||
this.fuseConfig.onConfigChanged
|
this._unsubscribeAll = new Subject();
|
||||||
.subscribe(
|
}
|
||||||
(newConfig) => {
|
|
||||||
this.config = newConfig;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get the nav model and add customize nav item
|
// -----------------------------------------------------------------------------------------------------
|
||||||
// that opens the bar programmatically
|
// @ Lifecycle hooks
|
||||||
const nav: any = navigation;
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
nav.push({
|
/**
|
||||||
'id' : 'custom-function',
|
* On init
|
||||||
'title' : 'Custom Function',
|
*/
|
||||||
'type' : 'group',
|
ngOnInit(): void
|
||||||
'children': [
|
{
|
||||||
|
// Build the config form
|
||||||
|
// noinspection TypeScriptValidateTypes
|
||||||
|
this.form = this._formBuilder.group({
|
||||||
|
colorTheme : new FormControl(),
|
||||||
|
customScrollbars: new FormControl(),
|
||||||
|
layout : this._formBuilder.group({
|
||||||
|
style : new FormControl(),
|
||||||
|
width : new FormControl(),
|
||||||
|
navbar : this._formBuilder.group({
|
||||||
|
primaryBackground : new FormControl(),
|
||||||
|
secondaryBackground: new FormControl(),
|
||||||
|
folded : new FormControl(),
|
||||||
|
hidden : new FormControl(),
|
||||||
|
position : new FormControl(),
|
||||||
|
variant : new FormControl()
|
||||||
|
}),
|
||||||
|
toolbar : this._formBuilder.group({
|
||||||
|
background : new FormControl(),
|
||||||
|
customBackgroundColor: new FormControl(),
|
||||||
|
hidden : new FormControl(),
|
||||||
|
position : new FormControl()
|
||||||
|
}),
|
||||||
|
footer : this._formBuilder.group({
|
||||||
|
background : new FormControl(),
|
||||||
|
customBackgroundColor: new FormControl(),
|
||||||
|
hidden : new FormControl(),
|
||||||
|
position : new FormControl()
|
||||||
|
}),
|
||||||
|
sidepanel: this._formBuilder.group({
|
||||||
|
hidden : new FormControl(),
|
||||||
|
position: 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',
|
id : 'customize',
|
||||||
'title' : 'Customize',
|
title : 'Customize',
|
||||||
'type' : 'item',
|
type : 'item',
|
||||||
'icon' : 'settings',
|
icon : 'settings',
|
||||||
'function': () => {
|
function: () => {
|
||||||
this.openBar();
|
this.toggleSidebarOpen('themeOptionsPanel');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
};
|
||||||
|
|
||||||
|
this._fuseNavigationService.addNavigationItem(customFunctionNavItem, 'end');
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit()
|
/**
|
||||||
|
* On destroy
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void
|
||||||
{
|
{
|
||||||
this.renderer.listen(this.overlay.nativeElement, 'click', () => {
|
// Unsubscribe from all subscriptions
|
||||||
this.closeBar();
|
this._unsubscribeAll.next();
|
||||||
});
|
this._unsubscribeAll.complete();
|
||||||
|
|
||||||
|
// Remove the custom function menu
|
||||||
|
this._fuseNavigationService.removeNavigationItem('custom-function');
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy()
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Private methods
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the form values based on the
|
||||||
|
* selected layout style
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private _resetFormValues(value): void
|
||||||
{
|
{
|
||||||
this.onConfigChanged.unsubscribe();
|
switch ( value )
|
||||||
|
{
|
||||||
|
// Vertical Layout #1
|
||||||
|
case 'vertical-layout-1':
|
||||||
|
{
|
||||||
|
this.form.patchValue({
|
||||||
|
layout: {
|
||||||
|
width : 'fullwidth',
|
||||||
|
navbar : {
|
||||||
|
primaryBackground : 'fuse-navy-700',
|
||||||
|
secondaryBackground: 'fuse-navy-900',
|
||||||
|
folded : false,
|
||||||
|
hidden : false,
|
||||||
|
position : 'left',
|
||||||
|
variant : 'vertical-style-1'
|
||||||
|
},
|
||||||
|
toolbar : {
|
||||||
|
background : 'fuse-white-500',
|
||||||
|
customBackgroundColor: false,
|
||||||
|
hidden : false,
|
||||||
|
position : 'below-static'
|
||||||
|
},
|
||||||
|
footer : {
|
||||||
|
background : 'fuse-navy-900',
|
||||||
|
customBackgroundColor: true,
|
||||||
|
hidden : false,
|
||||||
|
position : 'below-static'
|
||||||
|
},
|
||||||
|
sidepanel: {
|
||||||
|
hidden : false,
|
||||||
|
position: 'right'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertical Layout #2
|
||||||
|
case 'vertical-layout-2':
|
||||||
|
{
|
||||||
|
this.form.patchValue({
|
||||||
|
layout: {
|
||||||
|
width : 'fullwidth',
|
||||||
|
navbar : {
|
||||||
|
primaryBackground : 'fuse-navy-700',
|
||||||
|
secondaryBackground: 'fuse-navy-900',
|
||||||
|
folded : false,
|
||||||
|
hidden : false,
|
||||||
|
position : 'left',
|
||||||
|
variant : 'vertical-style-1'
|
||||||
|
},
|
||||||
|
toolbar : {
|
||||||
|
background : 'fuse-white-500',
|
||||||
|
customBackgroundColor: false,
|
||||||
|
hidden : false,
|
||||||
|
position : 'below'
|
||||||
|
},
|
||||||
|
footer : {
|
||||||
|
background : 'fuse-navy-900',
|
||||||
|
customBackgroundColor: true,
|
||||||
|
hidden : false,
|
||||||
|
position : 'below'
|
||||||
|
},
|
||||||
|
sidepanel: {
|
||||||
|
hidden : false,
|
||||||
|
position: 'right'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertical Layout #3
|
||||||
|
case 'vertical-layout-3':
|
||||||
|
{
|
||||||
|
this.form.patchValue({
|
||||||
|
layout: {
|
||||||
|
width : 'fullwidth',
|
||||||
|
navbar : {
|
||||||
|
primaryBackground : 'fuse-navy-700',
|
||||||
|
secondaryBackground: 'fuse-navy-900',
|
||||||
|
folded : false,
|
||||||
|
hidden : false,
|
||||||
|
position : 'left',
|
||||||
|
layout : 'vertical-style-1'
|
||||||
|
},
|
||||||
|
toolbar : {
|
||||||
|
background : 'fuse-white-500',
|
||||||
|
customBackgroundColor: false,
|
||||||
|
hidden : false,
|
||||||
|
position : 'above-static'
|
||||||
|
},
|
||||||
|
footer : {
|
||||||
|
background : 'fuse-navy-900',
|
||||||
|
customBackgroundColor: true,
|
||||||
|
hidden : false,
|
||||||
|
position : 'above-static'
|
||||||
|
},
|
||||||
|
sidepanel: {
|
||||||
|
hidden : false,
|
||||||
|
position: 'right'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Horizontal Layout #1
|
||||||
|
case 'horizontal-layout-1':
|
||||||
|
{
|
||||||
|
this.form.patchValue({
|
||||||
|
layout: {
|
||||||
|
width : 'fullwidth',
|
||||||
|
navbar : {
|
||||||
|
primaryBackground : 'fuse-navy-700',
|
||||||
|
secondaryBackground: 'fuse-navy-900',
|
||||||
|
folded : false,
|
||||||
|
hidden : false,
|
||||||
|
position : 'top',
|
||||||
|
variant : 'vertical-style-1'
|
||||||
|
},
|
||||||
|
toolbar : {
|
||||||
|
background : 'fuse-white-500',
|
||||||
|
customBackgroundColor: false,
|
||||||
|
hidden : false,
|
||||||
|
position : 'above'
|
||||||
|
},
|
||||||
|
footer : {
|
||||||
|
background : 'fuse-navy-900',
|
||||||
|
customBackgroundColor: true,
|
||||||
|
hidden : false,
|
||||||
|
position : 'above-fixed'
|
||||||
|
},
|
||||||
|
sidepanel: {
|
||||||
|
hidden : false,
|
||||||
|
position: 'right'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onSettingsChange()
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Public methods
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle sidebar open
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
toggleSidebarOpen(key): void
|
||||||
{
|
{
|
||||||
this.fuseConfig.setConfig(this.config);
|
this._fuseSidebarService.getSidebar(key).toggleOpen();
|
||||||
}
|
|
||||||
|
|
||||||
closeBar()
|
|
||||||
{
|
|
||||||
this.player =
|
|
||||||
this.animationBuilder
|
|
||||||
.build([
|
|
||||||
style({transform: 'translate3d(0,0,0)'}),
|
|
||||||
animate('400ms ease', style({transform: 'translate3d(100%,0,0)'}))
|
|
||||||
]).create(this.panel.nativeElement);
|
|
||||||
|
|
||||||
this.player.play();
|
|
||||||
|
|
||||||
this.player.onDone(() => {
|
|
||||||
this.barClosed = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
openBar()
|
|
||||||
{
|
|
||||||
this.barClosed = false;
|
|
||||||
|
|
||||||
this.player =
|
|
||||||
this.animationBuilder
|
|
||||||
.build([
|
|
||||||
style({transform: 'translate3d(100%,0,0)'}),
|
|
||||||
animate('400ms ease', style({transform: 'translate3d(0,0,0)'}))
|
|
||||||
]).create(this.panel.nativeElement);
|
|
||||||
|
|
||||||
this.player.play();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,21 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||||
import { MatButtonModule, MatDividerModule, MatFormFieldModule, MatIconModule, MatOptionModule, MatRadioModule, MatSelectModule, MatSlideToggleModule } from '@angular/material';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatOptionModule } from '@angular/material/core';
|
||||||
|
import { MatDividerModule } from '@angular/material/divider';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatRadioModule } from '@angular/material/radio';
|
||||||
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
|
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||||
|
|
||||||
|
import { FuseDirectivesModule } from '@fuse/directives/directives';
|
||||||
import { FuseMaterialColorPickerModule } from '@fuse/components/material-color-picker/material-color-picker.module';
|
import { FuseMaterialColorPickerModule } from '@fuse/components/material-color-picker/material-color-picker.module';
|
||||||
|
import { FuseSidebarModule } from '@fuse/components/sidebar/sidebar.module';
|
||||||
|
|
||||||
import { FuseThemeOptionsComponent } from '@fuse/components/theme-options/theme-options.component';
|
import { FuseThemeOptionsComponent } from '@fuse/components/theme-options/theme-options.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@@ -14,10 +25,12 @@ import { FuseThemeOptionsComponent } from '@fuse/components/theme-options/theme-
|
|||||||
imports : [
|
imports : [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
|
||||||
FlexLayoutModule,
|
FlexLayoutModule,
|
||||||
|
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
|
MatCheckboxModule,
|
||||||
MatDividerModule,
|
MatDividerModule,
|
||||||
MatFormFieldModule,
|
MatFormFieldModule,
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
@@ -26,7 +39,9 @@ import { FuseThemeOptionsComponent } from '@fuse/components/theme-options/theme-
|
|||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
MatSlideToggleModule,
|
MatSlideToggleModule,
|
||||||
|
|
||||||
FuseMaterialColorPickerModule
|
FuseDirectivesModule,
|
||||||
|
FuseMaterialColorPickerModule,
|
||||||
|
FuseSidebarModule
|
||||||
],
|
],
|
||||||
exports : [
|
exports : [
|
||||||
FuseThemeOptionsComponent
|
FuseThemeOptionsComponent
|
||||||
|
|||||||
27
src/@fuse/components/theme-options/theme-options.theme.scss
Normal file
27
src/@fuse/components/theme-options/theme-options.theme.scss
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
@mixin fuse-theme-options-theme($theme) {
|
||||||
|
|
||||||
|
$background: map-get($theme, background);
|
||||||
|
$foreground: map-get($theme, foreground);
|
||||||
|
|
||||||
|
fuse-theme-options {
|
||||||
|
|
||||||
|
.theme-options-panel {
|
||||||
|
|
||||||
|
form {
|
||||||
|
|
||||||
|
.group {
|
||||||
|
border: 1px solid map-get($foreground, divider);
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
background: map-get($background, background);
|
||||||
|
color: map-get($foreground, secondary-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: map-get($foreground, secondary-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,14 @@ import { Directive, ElementRef } from '@angular/core';
|
|||||||
})
|
})
|
||||||
export class FuseWidgetToggleDirective
|
export class FuseWidgetToggleDirective
|
||||||
{
|
{
|
||||||
constructor(public el: ElementRef)
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param {ElementRef} elementRef
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
public elementRef: ElementRef
|
||||||
|
)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,13 @@ fuse-widget {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
border-radius: 2px;
|
border-radius: 8px;
|
||||||
transition: transform 0.5s ease-out 0s, visibility 0s ease-in 0.2s, opacity 0s ease-in 0.2s;
|
transition: transform 0.5s ease-out 0s, visibility 0s ease-in 0.2s, opacity 0s ease-in 0.2s;
|
||||||
transform: rotateY(0deg);
|
transform: rotateY(0deg);
|
||||||
backface-visibility: hidden;
|
backface-visibility: hidden;
|
||||||
|
border: 1px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .fuse-widget-back {
|
> .fuse-widget-back {
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -36,9 +38,11 @@ fuse-widget {
|
|||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
border-radius: 8px;
|
||||||
transition: transform 0.5s ease-out 0s, visibility 0s ease-in 0.2s, opacity 0s ease-in 0.2s;
|
transition: transform 0.5s ease-out 0s, visibility 0s ease-in 0.2s, opacity 0s ease-in 0.2s;
|
||||||
transform: rotateY(180deg);
|
transform: rotateY(180deg);
|
||||||
backface-visibility: hidden;
|
backface-visibility: hidden;
|
||||||
|
border: 1px solid;
|
||||||
|
|
||||||
[fuseWidgetToggle] {
|
[fuseWidgetToggle] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -67,16 +71,16 @@ fuse-widget {
|
|||||||
|
|
||||||
&.mat-form-field-type-mat-select {
|
&.mat-form-field-type-mat-select {
|
||||||
|
|
||||||
.mat-input-wrapper {
|
.mat-form-field-wrapper {
|
||||||
padding: 16px 0;
|
padding: 16px 0;
|
||||||
|
|
||||||
.mat-input-infix {
|
.mat-form-field-infix {
|
||||||
border: none;
|
border: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-input-underline {
|
.mat-form-field-underline {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,19 +10,38 @@ import { FuseWidgetToggleDirective } from './widget-toggle.directive';
|
|||||||
|
|
||||||
export class FuseWidgetComponent implements AfterContentInit
|
export class FuseWidgetComponent implements AfterContentInit
|
||||||
{
|
{
|
||||||
@HostBinding('class.flipped') flipped = false;
|
@HostBinding('class.flipped')
|
||||||
@ContentChildren(FuseWidgetToggleDirective, {descendants: true}) toggleButtons: QueryList<FuseWidgetToggleDirective>;
|
flipped = false;
|
||||||
|
|
||||||
constructor(private el: ElementRef, private renderer: Renderer2)
|
@ContentChildren(FuseWidgetToggleDirective, {descendants: true})
|
||||||
|
toggleButtons: QueryList<FuseWidgetToggleDirective>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param {ElementRef} _elementRef
|
||||||
|
* @param {Renderer2} _renderer
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private _elementRef: ElementRef,
|
||||||
|
private _renderer: Renderer2
|
||||||
|
)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterContentInit()
|
// -----------------------------------------------------------------------------------------------------
|
||||||
{
|
// @ Lifecycle hooks
|
||||||
setTimeout(() => {
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After content init
|
||||||
|
*/
|
||||||
|
ngAfterContentInit(): void
|
||||||
|
{
|
||||||
|
// Listen for the flip button click
|
||||||
|
setTimeout(() => {
|
||||||
this.toggleButtons.forEach(flipButton => {
|
this.toggleButtons.forEach(flipButton => {
|
||||||
this.renderer.listen(flipButton.el.nativeElement, 'click', (event) => {
|
this._renderer.listen(flipButton.elementRef.nativeElement, 'click', (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
this.toggle();
|
this.toggle();
|
||||||
@@ -31,7 +50,14 @@ export class FuseWidgetComponent implements AfterContentInit
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle()
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Public methods
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle the flipped status
|
||||||
|
*/
|
||||||
|
toggle(): void
|
||||||
{
|
{
|
||||||
this.flipped = !this.flipped;
|
this.flipped = !this.flipped;
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/@fuse/components/widget/widget.theme.scss
Normal file
14
src/@fuse/components/widget/widget.theme.scss
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
@mixin fuse-widget-theme($theme) {
|
||||||
|
|
||||||
|
$background: map-get($theme, background);
|
||||||
|
$foreground: map-get($theme, foreground);
|
||||||
|
|
||||||
|
fuse-widget {
|
||||||
|
|
||||||
|
> .fuse-widget-front,
|
||||||
|
> .fuse-widget-back {
|
||||||
|
background: map-get($background, card);
|
||||||
|
border-color: map-get($foreground, divider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
|
|
||||||
import { FuseIfOnDomDirective } from '@fuse/directives/fuse-if-on-dom/fuse-if-on-dom.directive';
|
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 { FusePerfectScrollbarDirective } from '@fuse/directives/fuse-perfect-scrollbar/fuse-perfect-scrollbar.directive';
|
||||||
import { FuseMatSidenavHelperDirective, FuseMatSidenavTogglerDirective } from '@fuse/directives/fuse-mat-sidenav/fuse-mat-sidenav.directive';
|
import { FuseMatSidenavHelperDirective, FuseMatSidenavTogglerDirective } from '@fuse/directives/fuse-mat-sidenav/fuse-mat-sidenav.directive';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
FuseIfOnDomDirective,
|
FuseIfOnDomDirective,
|
||||||
|
FuseInnerScrollDirective,
|
||||||
FuseMatSidenavHelperDirective,
|
FuseMatSidenavHelperDirective,
|
||||||
FuseMatSidenavTogglerDirective,
|
FuseMatSidenavTogglerDirective,
|
||||||
FusePerfectScrollbarDirective
|
FusePerfectScrollbarDirective
|
||||||
@@ -14,6 +16,7 @@ import { FuseMatSidenavHelperDirective, FuseMatSidenavTogglerDirective } from '@
|
|||||||
imports : [],
|
imports : [],
|
||||||
exports : [
|
exports : [
|
||||||
FuseIfOnDomDirective,
|
FuseIfOnDomDirective,
|
||||||
|
FuseInnerScrollDirective,
|
||||||
FuseMatSidenavHelperDirective,
|
FuseMatSidenavHelperDirective,
|
||||||
FuseMatSidenavTogglerDirective,
|
FuseMatSidenavTogglerDirective,
|
||||||
FusePerfectScrollbarDirective
|
FusePerfectScrollbarDirective
|
||||||
|
|||||||
@@ -5,28 +5,44 @@ import { AfterContentChecked, Directive, ElementRef, TemplateRef, ViewContainerR
|
|||||||
})
|
})
|
||||||
export class FuseIfOnDomDirective implements AfterContentChecked
|
export class FuseIfOnDomDirective implements AfterContentChecked
|
||||||
{
|
{
|
||||||
isCreated = false;
|
isCreated: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param {ElementRef} _elementRef
|
||||||
|
* @param {TemplateRef<any>} _templateRef
|
||||||
|
* @param {ViewContainerRef} _viewContainerRef
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private templateRef: TemplateRef<any>,
|
private _elementRef: ElementRef,
|
||||||
private viewContainer: ViewContainerRef,
|
private _templateRef: TemplateRef<any>,
|
||||||
private element: ElementRef
|
private _viewContainerRef: ViewContainerRef
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
// Set the defaults
|
||||||
|
this.isCreated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterContentChecked()
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Lifecycle hooks
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After content checked
|
||||||
|
*/
|
||||||
|
ngAfterContentChecked(): void
|
||||||
{
|
{
|
||||||
if ( document.body.contains(this.element.nativeElement) && !this.isCreated )
|
if ( document.body.contains(this._elementRef.nativeElement) && !this.isCreated )
|
||||||
{
|
{
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.viewContainer.createEmbeddedView(this.templateRef);
|
this._viewContainerRef.createEmbeddedView(this._templateRef);
|
||||||
}, 300);
|
}, 300);
|
||||||
this.isCreated = true;
|
this.isCreated = true;
|
||||||
}
|
}
|
||||||
else if ( this.isCreated && !document.body.contains(this.element.nativeElement) )
|
else if ( this.isCreated && !document.body.contains(this._elementRef.nativeElement) )
|
||||||
{
|
{
|
||||||
this.viewContainer.clear();
|
this._viewContainerRef.clear();
|
||||||
this.isCreated = false;
|
this.isCreated = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user