Compare commits

...

15 Commits

Author SHA1 Message Date
Sercan Yemen
43b85ca3b6 Reverted the ngx-dnd back to 3.1.0
+ Added missing debounceTime imports to prevent errors
2018-02-05 17:04:22 +03:00
Sercan Yemen
99696cabf7 Finished up the Analytics Dashboard
+ Updated the Angular Material version along with couple other libraries
+ Increased the version number of the Fuse
2018-02-05 15:08:18 +03:00
Sercan Yemen
f246fab1f4 Make sure the splash screen element exists before adding an event to it 2018-02-05 11:29:30 +03:00
Sercan Yemen
b0101a1f8c Fix the wrong api url 2018-02-05 11:28:24 +03:00
Sercan Yemen
8f5e947c28 Added a new dashboard (Analytics) 2018-02-01 15:30:44 +03:00
Sercan Yemen
dfd430712d Fixed some naming inconsistencies in Project dashboard
+ Added fake db for Analytics Dashboard
2018-02-01 15:30:30 +03:00
Sercan Yemen
8431c19133 Added Chart.js
+ Some improvements on Helper classes and Fuse Card
2018-02-01 15:28:40 +03:00
Sercan Yemen
6ee6934e0d Fixed a small typo in multi-language component page 2018-01-30 15:18:50 +03:00
Sercan Yemen
3253fbfaf4 Updated readme with slack workspace invitation 2018-01-29 11:24:47 +03:00
mustafahlvc
985a8dd3a9 ngrx updated to v5.0.0 2018-01-23 13:37:58 +03:00
Sercan Yemen
0c99c075f3 Updated Angular CLI and couple other packages to fix the devkit issue
+ Increase the Fuse version number
2018-01-23 12:47:31 +03:00
Sercan Yemen
c79db27092 Updated package-lock.json file 2018-01-18 13:37:57 +03:00
Sercan Yemen
a92cb8b7b6 Quick panel width is too wide for smaller screens
+ (Academy app) Course page doesn't scroll on mobile
2018-01-18 13:18:09 +03:00
Sercan Yemen
bb3d6d4839 Updated Angular, Angular Material and various other packages
+ Increased the Fuse version
+ Replaced datatable icons
+ Removed broken css imports
2018-01-18 13:13:40 +03:00
Sercan Yemen
9c06622efb Small fixes 2018-01-12 10:19:10 +03:00
37 changed files with 7090 additions and 1581 deletions

View File

@@ -2,6 +2,12 @@
Material Design Admin Template with Angular 5+ and Angular Material 2 Material Design Admin Template with Angular 5+ and Angular Material 2
## The Community
Share your ideas, discuss Fuse and help each other.
[Click here](https://join.slack.com/t/fuse-theme/shared_invite/enQtMzA1NDE4NzYwMjcyLWQxODE4ODM1MWU4MWJjMDhlMGEwYzM4Mzg3N2E4YzVlZThhZjNlOTQ1Y2Q5OTBlNDNkMzJhZDIwMjgxOWQ3YWU) to join our Slack workspace.
## Development server ## Development server
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.

6677
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "fuse2", "name": "fuse2",
"version": "1.3.3", "version": "1.3.6",
"license": "https://themeforest.net/licenses/terms/regular", "license": "https://themeforest.net/licenses/terms/regular",
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
@@ -19,66 +19,67 @@
"private": true, "private": true,
"dependencies": { "dependencies": {
"@agm/core": "1.0.0-beta.2", "@agm/core": "1.0.0-beta.2",
"@angular/animations": "5.2.0", "@angular/animations": "5.2.3",
"@angular/cdk": "5.0.4", "@angular/cdk": "5.1.1",
"@angular/common": "5.2.0", "@angular/common": "5.2.3",
"@angular/compiler": "5.2.0", "@angular/compiler": "5.2.3",
"@angular/core": "5.2.0", "@angular/core": "5.2.3",
"@angular/flex-layout": "2.0.0-beta.12", "@angular/flex-layout": "2.0.0-beta.12",
"@angular/forms": "5.2.0", "@angular/forms": "5.2.3",
"@angular/http": "5.2.0", "@angular/http": "5.2.3",
"@angular/material": "5.0.4", "@angular/material": "5.1.1",
"@angular/material-moment-adapter": "5.0.4", "@angular/material-moment-adapter": "5.1.1",
"@angular/platform-browser": "5.2.0", "@angular/platform-browser": "5.2.3",
"@angular/platform-browser-dynamic": "5.2.0", "@angular/platform-browser-dynamic": "5.2.3",
"@angular/router": "5.2.0", "@angular/router": "5.2.3",
"@ngrx/effects": "4.1.1", "@ngrx/effects": "5.0.0",
"@ngrx/router-store": "4.1.1", "@ngrx/router-store": "5.0.0",
"@ngrx/store": "4.1.1", "@ngrx/store": "5.0.0",
"@ngrx/store-devtools": "4.1.1", "@ngrx/store-devtools": "5.0.0",
"@ngx-translate/core": "9.0.2", "@ngx-translate/core": "9.1.1",
"@swimlane/ngx-charts": "7.0.1", "@swimlane/ngx-charts": "7.0.1",
"@swimlane/ngx-datatable": "11.1.7", "@swimlane/ngx-datatable": "11.1.7",
"@swimlane/ngx-dnd": "3.1.0", "@swimlane/ngx-dnd": "3.1.0",
"@types/prismjs": "1.9.0", "@types/prismjs": "1.9.0",
"angular-calendar": "0.23.2", "angular-calendar": "0.23.3",
"angular-in-memory-web-api": "0.5.2", "angular-in-memory-web-api": "0.5.3",
"chart.js": "2.7.1",
"classlist.js": "1.1.20150312", "classlist.js": "1.1.20150312",
"core-js": "2.5.3", "core-js": "2.5.3",
"d3": "4.12.2", "d3": "4.13.0",
"hammerjs": "2.0.8", "hammerjs": "2.0.8",
"intl": "1.2.5", "intl": "1.2.5",
"moment": "2.20.1", "moment": "2.20.1",
"ngrx-store-freeze": "0.2.0", "ng2-charts": "1.6.0",
"ngx-color-picker": "5.3.0", "ngrx-store-freeze": "0.2.1",
"ngx-color-picker": "5.3.1",
"ngx-cookie-service": "1.0.10", "ngx-cookie-service": "1.0.10",
"perfect-scrollbar": "1.3.0", "perfect-scrollbar": "1.3.0",
"prismjs": "1.9.0", "prismjs": "1.11.0",
"rxjs": "5.5.6", "rxjs": "5.5.6",
"web-animations-js": "2.3.1", "web-animations-js": "2.3.1",
"zone.js": "0.8.20" "zone.js": "0.8.20"
}, },
"devDependencies": { "devDependencies": {
"@angular/cli": "1.6.3", "@angular/cli": "1.6.7",
"@angular/compiler-cli": "5.2.0", "@angular/compiler-cli": "5.2.3",
"@angular/language-service": "5.2.0", "@angular/language-service": "5.2.3",
"@angularclass/hmr": "2.1.3", "@angularclass/hmr": "2.1.3",
"@types/jasmine": "2.5.54", "@types/jasmine": "2.8.6",
"@types/jasminewd2": "2.0.3", "@types/jasminewd2": "2.0.3",
"@types/node": "6.0.96", "@types/node": "6.0.96",
"codelyzer": "4.0.2", "codelyzer": "4.1.0",
"jasmine-core": "2.6.4", "jasmine-core": "2.8.0",
"jasmine-spec-reporter": "4.1.1", "jasmine-spec-reporter": "4.2.1",
"karma": "1.7.1", "karma": "2.0.0",
"karma-chrome-launcher": "2.1.1", "karma-chrome-launcher": "2.2.0",
"karma-cli": "1.0.1", "karma-coverage-istanbul-reporter": "1.4.1",
"karma-coverage-istanbul-reporter": "1.3.3",
"karma-jasmine": "1.1.1", "karma-jasmine": "1.1.1",
"karma-jasmine-html-reporter": "0.2.2", "karma-jasmine-html-reporter": "0.2.2",
"protractor": "5.1.2", "protractor": "5.1.2",
"ts-node": "3.2.2", "ts-node": "4.1.0",
"tslint": "5.7.0", "tslint": "5.9.1",
"typescript": "2.4.2", "typescript": "2.6.2",
"webpack-bundle-analyzer": "2.9.2" "webpack-bundle-analyzer": "2.10.0"
} }
} }

View File

@@ -42,7 +42,7 @@ const appRoutes: Routes = [
}, },
{ {
path : '**', path : '**',
redirectTo: 'apps/dashboards/project' redirectTo: 'apps/dashboards/analytics'
} }
]; ];

View File

@@ -22,6 +22,7 @@ import { FuseMaterialColorPickerComponent } from '../components/material-color-p
import { FuseTranslationLoaderService } from '../services/translation-loader.service'; import { FuseTranslationLoaderService } from '../services/translation-loader.service';
import { CookieService } from 'ngx-cookie-service'; import { CookieService } from 'ngx-cookie-service';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { ChartsModule } from 'ng2-charts';
@NgModule({ @NgModule({
declarations : [ declarations : [
@@ -43,7 +44,8 @@ import { TranslateModule } from '@ngx-translate/core';
ReactiveFormsModule, ReactiveFormsModule,
ColorPickerModule, ColorPickerModule,
NgxDnDModule, NgxDnDModule,
NgxDatatableModule NgxDatatableModule,
ChartsModule
], ],
exports : [ exports : [
FlexLayoutModule, FlexLayoutModule,
@@ -62,7 +64,8 @@ import { TranslateModule } from '@ngx-translate/core';
NgxDatatableModule, NgxDatatableModule,
FuseIfOnDomDirective, FuseIfOnDomDirective,
FuseMaterialColorPickerComponent, FuseMaterialColorPickerComponent,
TranslateModule TranslateModule,
ChartsModule
], ],
entryComponents: [ entryComponents: [
FuseConfirmDialogComponent FuseConfirmDialogComponent

View File

@@ -1,9 +1,9 @@
// ngx-datatable // ngx-datatable
@import '~@swimlane/ngx-datatable/release/index.css'; @import '~@swimlane/ngx-datatable/release/themes/material';
@import '~@swimlane/ngx-datatable/release/themes/material.css';
@import '~@swimlane/ngx-datatable/release/assets/icons.css';
// Perfect scrollbar // Perfect scrollbar
@import '~perfect-scrollbar/css/perfect-scrollbar.css'; @import '~perfect-scrollbar/css/perfect-scrollbar';
// Fuse // Fuse
@import "fuse"; @import "fuse";

View File

@@ -9,6 +9,11 @@
min-width: 0; min-width: 0;
} }
&.auto-width {
min-width: 0;
max-width: none;
}
// Buttons // Buttons
.mat-button { .mat-button {
min-width: 0 !important; min-width: 0 !important;

View File

@@ -215,4 +215,31 @@ $border-style: 1px solid rgba(0, 0, 0, 0.12);
// ###################### // ######################
.border-radius-100 { .border-radius-100 {
border-radius: 100%; border-radius: 100%;
}
.border-radius-2 {
border-radius: 2px;
}
.border-radius-4 {
border-radius: 4px;
}
.border-radius-8 {
border-radius: 8px;
}
.border-radius-16 {
border-radius: 16px;
}
// ######################
// CURSOR HELPERS
// ######################
.cursor-pointer {
cursor: pointer;
}
.cursor-default {
cursor: default;
} }

View File

@@ -98,3 +98,68 @@
} }
} }
} }
[class*="datatable-icon-"] {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 24px;
line-height: 1;
letter-spacing: normal;
text-transform: none;
display: inline-block;
white-space: nowrap;
word-wrap: normal;
direction: ltr;
-webkit-font-feature-settings: 'liga';
-webkit-font-smoothing: antialiased;
}
.datatable-icon-filter:before {
content: "filter_list";
}
.datatable-icon-collapse:before {
content: "unfold_less";
}
.datatable-icon-expand:before {
content: "unfold_more";
}
.datatable-icon-close:before {
content: "close";
}
.datatable-icon-up:before {
content: "keyboard_arrow_up";
}
.datatable-icon-down:before {
content: "keyboard_arrow_down";
}
.datatable-icon-sort:before {
content: "sort";
}
.datatable-icon-done:before {
content: "done";
}
.datatable-icon-done-all:before {
content: "done_all";
}
.datatable-icon-search:before {
content: "search";
}
.datatable-icon-pin:before {
content: "lock";
}
.datatable-icon-add:before {
content: "add";
}
.datatable-icon-left:before {
content: "chevron_left";
}
.datatable-icon-right:before {
content: "chevron_right";
}
.datatable-icon-skip:before {
content: "skip_next";
}
.datatable-icon-prev:before {
content: "skip_previous";
}

View File

@@ -15,18 +15,27 @@ export class FuseSplashScreenService
private router: Router private router: Router
) )
{ {
// Get the splash screen element
this.splashScreenEl = this.document.body.querySelector('#fuse-splash-screen'); this.splashScreenEl = this.document.body.querySelector('#fuse-splash-screen');
const hideOnLoad = this.router.events.subscribe((event) => { // If the splash screen element exists...
if ( event instanceof NavigationEnd ) if ( this.splashScreenEl )
{ {
setTimeout(() => { // Hide it on the first NavigationEnd event
this.hide(); const hideOnLoad = this.router.events.subscribe((event) => {
hideOnLoad.unsubscribe(); if ( event instanceof NavigationEnd )
}, 0); {
setTimeout(() => {
this.hide();
// Unsubscribe from this event so it
// won't get triggered again
hideOnLoad.unsubscribe();
}, 0);
}
} }
} );
); }
} }
show() show()

View File

@@ -0,0 +1,602 @@
export class AnalyticsDashboardDb
{
public static widgets = {
widget1: {
chartType: 'line',
datasets : {
'2015': [
{
label: 'Sales',
data : [1.9, 3, 3.4, 2.2, 2.9, 3.9, 2.5, 3.8, 4.1, 3.8, 3.2, 2.9],
fill : 'start'
}
],
'2016': [
{
label: 'Sales',
data : [2.2, 2.9, 3.9, 2.5, 3.8, 3.2, 2.9, 1.9, 3, 3.4, 4.1, 3.8],
fill : 'start'
}
],
'2017': [
{
label: 'Sales',
data : [3.9, 2.5, 3.8, 4.1, 1.9, 3, 3.8, 3.2, 2.9, 3.4, 2.2, 2.9],
fill : 'start'
}
]
},
labels : ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'],
colors : [
{
borderColor : '#42a5f5',
backgroundColor : '#42a5f5',
pointBackgroundColor : '#1e88e5',
pointHoverBackgroundColor: '#1e88e5',
pointBorderColor : '#ffffff',
pointHoverBorderColor : '#ffffff'
}
],
options : {
spanGaps : false,
legend : {
display: false
},
maintainAspectRatio: false,
layout : {
padding: {
top : 32,
left : 32,
right: 32
}
},
elements : {
point: {
radius : 4,
borderWidth : 2,
hoverRadius : 4,
hoverBorderWidth: 2
},
line : {
tension: 0
}
},
scales : {
xAxes: [
{
gridLines: {
display : false,
drawBorder : false,
tickMarkLength: 18
},
ticks : {
fontColor: '#ffffff'
}
}
],
yAxes: [
{
display: false,
ticks : {
min : 1.5,
max : 5,
stepSize: 0.5
}
}
]
},
plugins : {
filler : {
propagate: false
},
xLabelsOnTop: {
active: true
}
}
}
},
widget2: {
conversion: {
value : 492,
ofTarget: 13
},
chartType : 'bar',
datasets : [
{
label: 'Conversion',
data : [221, 428, 492, 471, 413, 344, 294]
}
],
labels : ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
colors : [
{
borderColor : '#42a5f5',
backgroundColor: '#42a5f5'
}
],
options : {
spanGaps : false,
legend : {
display: false
},
maintainAspectRatio: false,
layout : {
padding: {
top : 24,
left : 16,
right : 16,
bottom: 16
}
},
scales : {
xAxes: [
{
display: false
}
],
yAxes: [
{
display: false,
ticks : {
min: 100,
max: 500
}
}
]
}
}
},
widget3: {
impressions: {
value : '87k',
ofTarget: 12
},
chartType : 'line',
datasets : [
{
label: 'Impression',
data : [67000, 54000, 82000, 57000, 72000, 57000, 87000, 72000, 89000, 98700, 112000, 136000, 110000, 149000, 98000],
fill : false
}
],
labels : ['Jan 1', 'Jan 2', 'Jan 3', 'Jan 4', 'Jan 5', 'Jan 6', 'Jan 7', 'Jan 8', 'Jan 9', 'Jan 10', 'Jan 11', 'Jan 12', 'Jan 13', 'Jan 14', 'Jan 15'],
colors : [
{
borderColor: '#5c84f1'
}
],
options : {
spanGaps : false,
legend : {
display: false
},
maintainAspectRatio: false,
elements : {
point: {
radius : 2,
borderWidth : 1,
hoverRadius : 2,
hoverBorderWidth: 1
},
line : {
tension: 0
}
},
layout : {
padding: {
top : 24,
left : 16,
right : 16,
bottom: 16
}
},
scales : {
xAxes: [
{
display: false
}
],
yAxes: [
{
display: false,
ticks : {
// min: 100,
// max: 500
}
}
]
}
}
},
widget4: {
visits : {
value : 882,
ofTarget: -9
},
chartType: 'bar',
datasets : [
{
label: 'Visits',
data : [432, 428, 327, 363, 456, 267, 231]
}
],
labels : ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
colors : [
{
borderColor : '#f44336',
backgroundColor: '#f44336'
}
],
options : {
spanGaps : false,
legend : {
display: false
},
maintainAspectRatio: false,
layout : {
padding: {
top : 24,
left : 16,
right : 16,
bottom: 16
}
},
scales : {
xAxes: [
{
display: false
}
],
yAxes: [
{
display: false,
ticks : {
min: 150,
max: 500
}
}
]
}
}
},
widget5: {
chartType: 'line',
datasets : {
'yesterday': [
{
label: 'Visitors',
data : [190, 300, 340, 220, 290, 390, 250, 380, 410, 380, 320, 290],
fill : 'start'
},
{
label: 'Page views',
data : [2200, 2900, 3900, 2500, 3800, 3200, 2900, 1900, 3000, 3400, 4100, 3800],
fill : 'start'
}
],
'today' : [
{
label: 'Visitors',
data : [410, 380, 320, 290, 190, 390, 250, 380, 300, 340, 220, 290],
fill : 'start'
},
{
label: 'Page Views',
data : [3000, 3400, 4100, 3800, 2200, 3200, 2900, 1900, 2900, 3900, 2500, 3800],
fill : 'start'
}
]
},
labels : ['12am', '2am', '4am', '6am', '8am', '10am', '12pm', '2pm', '4pm', '6pm', '8pm', '10pm'],
colors : [
{
borderColor : '#3949ab',
backgroundColor : '#3949ab',
pointBackgroundColor : '#3949ab',
pointHoverBackgroundColor: '#3949ab',
pointBorderColor : '#ffffff',
pointHoverBorderColor : '#ffffff'
},
{
borderColor : 'rgba(30, 136, 229, 0.87)',
backgroundColor : 'rgba(30, 136, 229, 0.87)',
pointBackgroundColor : 'rgba(30, 136, 229, 0.87)',
pointHoverBackgroundColor: 'rgba(30, 136, 229, 0.87)',
pointBorderColor : '#ffffff',
pointHoverBorderColor : '#ffffff'
}
],
options : {
spanGaps : false,
legend : {
display: false
},
maintainAspectRatio: false,
tooltips : {
position : 'nearest',
mode : 'index',
intersect: false
},
layout : {
padding: {
left : 24,
right: 32
}
},
elements : {
point: {
radius : 4,
borderWidth : 2,
hoverRadius : 4,
hoverBorderWidth: 2
}
},
scales : {
xAxes: [
{
gridLines: {
display: false
},
ticks : {
fontColor: 'rgba(0,0,0,0.54)'
}
}
],
yAxes: [
{
gridLines: {
tickMarkLength: 16
},
ticks : {
stepSize: 1000
}
}
]
},
plugins : {
filler: {
propagate: false
}
}
}
},
widget6: {
markers: [
{
lat : 52,
lng : -73,
label: '120'
},
{
lat : 37,
lng : -104,
label: '498'
},
{
lat : 21,
lng : -7,
label: '443'
},
{
lat : 55,
lng : 75,
label: '332'
},
{
lat : 51,
lng : 7,
label: '50'
},
{
lat : 31,
lng : 12,
label: '221'
},
{
lat : 45,
lng : 44,
label: '455'
},
{
lat : -26,
lng : 134,
label: '231'
},
{
lat : -9,
lng : -60,
label: '67'
},
{
lat : 33,
lng : 104,
label: '665'
}
],
styles : [
{
'featureType': 'administrative',
'elementType': 'labels.text.fill',
'stylers' : [
{
'color': '#444444'
}
]
},
{
'featureType': 'landscape',
'elementType': 'all',
'stylers' : [
{
'color': '#f2f2f2'
}
]
},
{
'featureType': 'poi',
'elementType': 'all',
'stylers' : [
{
'visibility': 'off'
}
]
},
{
'featureType': 'road',
'elementType': 'all',
'stylers' : [
{
'saturation': -100
},
{
'lightness': 45
}
]
},
{
'featureType': 'road.highway',
'elementType': 'all',
'stylers' : [
{
'visibility': 'simplified'
}
]
},
{
'featureType': 'road.arterial',
'elementType': 'labels.icon',
'stylers' : [
{
'visibility': 'off'
}
]
},
{
'featureType': 'transit',
'elementType': 'all',
'stylers' : [
{
'visibility': 'off'
}
]
},
{
'featureType': 'water',
'elementType': 'all',
'stylers' : [
{
'color': '#039be5'
},
{
'visibility': 'on'
}
]
}
]
},
widget7: {
scheme : {
domain: ['#4867d2', '#5c84f1', '#89a9f4']
},
devices: [
{
name : 'Desktop',
value : 92.8,
change: -0.6
},
{
name : 'Mobile',
value : 6.1,
change: 0.7
},
{
name : 'Tablet',
value : 1.1,
change: 0.1
}
]
},
widget8: {
scheme : {
domain: ['#5c84f1']
},
today : '12,540',
change : {
value : 321,
percentage: 2.05
},
data : [
{
name : 'Sales',
series: [
{
name : 'Jan 1',
value: 540
},
{
name : 'Jan 2',
value: 539
},
{
name : 'Jan 3',
value: 538
},
{
name : 'Jan 4',
value: 539
},
{
name : 'Jan 5',
value: 540
},
{
name : 'Jan 6',
value: 539
},
{
name : 'Jan 7',
value: 540
}
]
}
],
dataMin: 538,
dataMax: 541
},
widget9: {
rows: [
{
title : 'Holiday Travel',
clicks : 3621,
conversion: 90
},
{
title : 'Get Away Deals',
clicks : 703,
conversion: 7
},
{
title : 'Airfare',
clicks : 532,
conversion: 0
},
{
title : 'Vacation',
clicks : 201,
conversion: 8
},
{
title : 'Hotels',
clicks : 94,
conversion: 4
}
]
}
};
}

View File

@@ -1,4 +1,4 @@
export class ProjectsDashboardDb export class ProjectDashboardDb
{ {
public static projects = [ public static projects = [
{ {

View File

@@ -1,62 +1,97 @@
import { InMemoryDbService } from 'angular-in-memory-web-api'; import { InMemoryDbService } from 'angular-in-memory-web-api';
import { MailFakeDb } from './mail'; import { ProjectDashboardDb } from './dashboard-project';
import { ChatFakeDb } from './chat'; import { AnalyticsDashboardDb } from './dashboard-analytics';
import { CalendarFakeDb } from './calendar'; import { CalendarFakeDb } from './calendar';
import { TodoFakeDb } from './todo';
import { ProfileFakeDb } from './profile';
import { ContactsFakeDb } from './contacts';
import { InvoiceFakeDb } from './invoice';
import { FileManagerFakeDb } from './file-manager';
import { SearchFakeDb } from './search';
import { QuickPanelFakeDb } from './quick-panel';
import { IconsFakeDb } from './icons';
import { ProjectsDashboardDb } from './projects-dashboard';
import { ScrumboardFakeDb } from './scrumboard';
import { FaqFakeDb } from './faq';
import { KnowledgeBaseFakeDb } from './knowledge-base';
import { ECommerceFakeDb } from './e-commerce'; import { ECommerceFakeDb } from './e-commerce';
import { AcademyFakeDb } from './academy'; import { AcademyFakeDb } from './academy';
import { MailFakeDb } from './mail';
import { ChatFakeDb } from './chat';
import { FileManagerFakeDb } from './file-manager';
import { ContactsFakeDb } from './contacts';
import { TodoFakeDb } from './todo';
import { ScrumboardFakeDb } from './scrumboard';
import { InvoiceFakeDb } from './invoice';
import { ProfileFakeDb } from './profile';
import { SearchFakeDb } from './search';
import { FaqFakeDb } from './faq';
import { KnowledgeBaseFakeDb } from './knowledge-base';
import { IconsFakeDb } from './icons';
import { QuickPanelFakeDb } from './quick-panel';
export class FuseFakeDbService implements InMemoryDbService export class FuseFakeDbService implements InMemoryDbService
{ {
createDb() createDb()
{ {
return { return {
'mail-mails' : MailFakeDb.mails, // Dashboards
'mail-folders' : MailFakeDb.folders, 'project-dashboard-projects' : ProjectDashboardDb.projects,
'mail-filters' : MailFakeDb.filters, 'project-dashboard-widgets' : ProjectDashboardDb.widgets,
'mail-labels' : MailFakeDb.labels, 'analytics-dashboard-widgets': AnalyticsDashboardDb.widgets,
'chat-contacts' : ChatFakeDb.contacts,
'chat-chats' : ChatFakeDb.chats, // Calendar
'chat-user' : ChatFakeDb.user, 'calendar': CalendarFakeDb.data,
'calendar' : CalendarFakeDb.data,
'todo-todos' : TodoFakeDb.todos, // E-Commerce
'todo-filters' : TodoFakeDb.filters, 'e-commerce-dashboard': ECommerceFakeDb.dashboard,
'todo-tags' : TodoFakeDb.tags, 'e-commerce-products' : ECommerceFakeDb.products,
'profile-timeline' : ProfileFakeDb.timeline, 'e-commerce-orders' : ECommerceFakeDb.orders,
'profile-photos-videos' : ProfileFakeDb.photosVideos,
'profile-about' : ProfileFakeDb.about, // Academy
'contacts-contacts' : ContactsFakeDb.contacts, 'academy-categories': AcademyFakeDb.categories,
'contacts-user' : ContactsFakeDb.user, 'academy-courses' : AcademyFakeDb.courses,
'invoice' : InvoiceFakeDb.invoice, 'academy-course' : AcademyFakeDb.course,
'file-manager' : FileManagerFakeDb.files,
'search-classic' : SearchFakeDb.classic, // Mail
'search-table' : SearchFakeDb.table, 'mail-mails' : MailFakeDb.mails,
'quick-panel-notes' : QuickPanelFakeDb.notes, 'mail-folders': MailFakeDb.folders,
'quick-panel-events' : QuickPanelFakeDb.events, 'mail-filters': MailFakeDb.filters,
'icons' : IconsFakeDb.icons, 'mail-labels' : MailFakeDb.labels,
'projects-dashboard-projects': ProjectsDashboardDb.projects,
'projects-dashboard-widgets' : ProjectsDashboardDb.widgets, // Chat
'scrumboard-boards' : ScrumboardFakeDb.boards, 'chat-contacts': ChatFakeDb.contacts,
'faq' : FaqFakeDb.data, 'chat-chats' : ChatFakeDb.chats,
'knowledge-base' : KnowledgeBaseFakeDb.data, 'chat-user' : ChatFakeDb.user,
'e-commerce-dashboard' : ECommerceFakeDb.dashboard,
'e-commerce-products' : ECommerceFakeDb.products, // File Manager
'e-commerce-orders' : ECommerceFakeDb.orders, 'file-manager': FileManagerFakeDb.files,
'academy-categories' : AcademyFakeDb.categories,
'academy-courses' : AcademyFakeDb.courses, // Contacts
'academy-course' : AcademyFakeDb.course 'contacts-contacts': ContactsFakeDb.contacts,
'contacts-user' : ContactsFakeDb.user,
// Todo
'todo-todos' : TodoFakeDb.todos,
'todo-filters': TodoFakeDb.filters,
'todo-tags' : TodoFakeDb.tags,
// Scrumboard
'scrumboard-boards': ScrumboardFakeDb.boards,
// Invoice
'invoice': InvoiceFakeDb.invoice,
// Profile
'profile-timeline' : ProfileFakeDb.timeline,
'profile-photos-videos': ProfileFakeDb.photosVideos,
'profile-about' : ProfileFakeDb.about,
// Search
'search-classic': SearchFakeDb.classic,
'search-table' : SearchFakeDb.table,
// FAQ
'faq': FaqFakeDb.data,
// Knowledge base
'knowledge-base': KnowledgeBaseFakeDb.data,
// Icons
'icons': IconsFakeDb.icons,
// Quick Panel
'quick-panel-notes' : QuickPanelFakeDb.notes,
'quick-panel-events': QuickPanelFakeDb.events
}; };
} }
} }

View File

@@ -161,6 +161,7 @@
bottom: 0; bottom: 0;
left: 0; left: 0;
padding: 48px; padding: 48px;
overflow: auto;
@media (max-width: 720px) { @media (max-width: 720px) {
padding: 0 0 120px 0; padding: 0 0 120px 0;

View File

@@ -8,6 +8,10 @@ const routes = [
path : 'dashboards/project', path : 'dashboards/project',
loadChildren: './dashboards/project/project.module#FuseProjectDashboardModule' loadChildren: './dashboards/project/project.module#FuseProjectDashboardModule'
}, },
{
path : 'dashboards/analytics',
loadChildren: './dashboards/analytics/analytics.module#FuseAnalyticsDashboardModule'
},
{ {
path : 'mail', path : 'mail',
loadChildren: './mail/mail.module#FuseMailModule' loadChildren: './mail/mail.module#FuseMailModule'

View File

@@ -1,6 +1,7 @@
import { Component, OnDestroy, OnInit } from '@angular/core'; import { Component, OnDestroy, OnInit } from '@angular/core';
import { ChatService } from '../../../chat.service'; import { ChatService } from '../../../chat.service';
import { FormControl, FormGroup } from '@angular/forms'; import { FormControl, FormGroup } from '@angular/forms';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged'; import 'rxjs/add/operator/distinctUntilChanged';
@Component({ @Component({

View File

@@ -4,6 +4,7 @@ import { fuseAnimations } from '../../../../core/animations';
import { FormControl, FormGroup } from '@angular/forms'; import { FormControl, FormGroup } from '@angular/forms';
import { FuseContactsContactFormDialogComponent } from './contact-form/contact-form.component'; import { FuseContactsContactFormDialogComponent } from './contact-form/contact-form.component';
import { MatDialog } from '@angular/material'; import { MatDialog } from '@angular/material';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged'; import 'rxjs/add/operator/distinctUntilChanged';
import { Subscription } from 'rxjs/Subscription'; import { Subscription } from 'rxjs/Subscription';

View File

@@ -0,0 +1,510 @@
<div id="dashboard-analytics" class="page-layout blank grey-100-bg" fusePerfectScrollbar>
<div class="main-widget">
<div class="position-relative p-24 mat-blue-600-bg"
fxLayout="row" fxLayoutAlign="space-between center">
<div fxLayout="column" fxLayoutAlign="start start">
<span class="h2">Visitors</span>
<span class="h5 secondary-text">Unique visitors by month</span>
</div>
<div fxLayout="row" fxLayoutAlign="start center">
<div class="py-8 px-12 border-radius-2 line-height-1 mr-8 cursor-pointer"
(click)="widget1SelectedYear = '2015'"
[ngClass]="{'blue-300-bg': widget1SelectedYear === '2015'}">
2015
</div>
<div class="py-8 px-12 border-radius-2 line-height-1 mr-8 cursor-pointer"
(click)="widget1SelectedYear = '2016'"
[ngClass]="{'blue-300-bg': widget1SelectedYear === '2016'}">
2016
</div>
<div class="py-8 px-12 border-radius-2 line-height-1 cursor-pointer"
(click)="widget1SelectedYear = '2017'"
[ngClass]="{'blue-300-bg': widget1SelectedYear === '2017'}">
2017
</div>
</div>
</div>
<div class="position-relative h-256 pb-16 mat-blue-600-bg">
<canvas baseChart
[datasets]="widgets.widget1.datasets[widget1SelectedYear]"
[labels]="widgets.widget1.labels"
[colors]="widgets.widget1.colors"
[options]="widgets.widget1.options"
[chartType]="widgets.widget1.chartType">
</canvas>
</div>
</div>
<div class="content">
<div class="left mr-32">
<div class="pb-24 font-size-18 font-weight-300">
How are your active users trending over time?
</div>
<div fxLayout="column" fxLayoutAlign="start"
fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="start start">
<!-- Widget 2 -->
<div class="widget" fxFlex="100" fxFlex.gt-sm="33">
<div class="fuse-card auto-width mb-32" [ngClass.gt-sm]="'mb-0 mr-32'">
<div class="p-16 pb-0" fxLayout="row" fxLayoutAlign="start end" fxLayoutWrap>
<div class="pr-16">
<div class="h3 secondary-text">Conversion</div>
<div class="font-size-54 font-weight-300 line-height-1 mt-8">
{{widgets.widget2.conversion.value}}
</div>
</div>
<div class="py-4 font-size-16" fxLayout="row" fxLayoutAlign="start center">
<div fxFlex="row" fxLayoutAlign="start center" class="green-fg"
*ngIf="widgets.widget2.conversion.ofTarget > 0">
<mat-icon class="green-fg mr-4">trending_up</mat-icon>
<span>{{widgets.widget2.conversion.ofTarget}}%</span>
</div>
<div fxFlex="row" fxLayoutAlign="start center" class="red-fg"
*ngIf="widgets.widget2.conversion.ofTarget < 0">
<mat-icon class="red-fg mr-4">trending_down</mat-icon>
<span>{{widgets.widget2.conversion.ofTarget}}%</span>
</div>
<div class="ml-4 text-nowrap">of target</div>
</div>
</div>
<div class="h-96 w-100-p">
<canvas baseChart
[datasets]="widgets.widget2.datasets"
[labels]="widgets.widget2.labels"
[colors]="widgets.widget2.colors"
[options]="widgets.widget2.options"
[chartType]="widgets.widget2.chartType">
</canvas>
</div>
</div>
</div>
<!-- / Widget 2 -->
<!-- Widget 3 -->
<div class="widget" fxFlex="100" fxFlex.gt-sm="34">
<div class="fuse-card auto-width mb-32" [ngClass.gt-sm]="'mb-0 mr-32'">
<div class="p-16 pb-0" fxLayout="row" fxLayoutAlign="start end" fxLayoutWrap>
<div class="pr-16">
<div class="h3 secondary-text">Impressions</div>
<div class="font-size-54 font-weight-300 line-height-1 mt-8">
{{widgets.widget3.impressions.value}}
</div>
</div>
<div class="py-4 font-size-16" fxLayout="row" fxLayoutAlign="start center">
<div fxFlex="row" fxLayoutAlign="start center" class="green-fg"
*ngIf="widgets.widget3.impressions.ofTarget > 0">
<mat-icon class="green-fg mr-4">trending_up</mat-icon>
<span>{{widgets.widget3.impressions.ofTarget}}%</span>
</div>
<div fxFlex="row" fxLayoutAlign="start center" class="red-fg"
*ngIf="widgets.widget3.impressions.ofTarget < 0">
<mat-icon class="red-fg mr-4">trending_down</mat-icon>
<span>{{widgets.widget3.impressions.ofTarget}}%</span>
</div>
<div class="ml-4 text-nowrap">of target</div>
</div>
</div>
<div class="h-96 w-100-p">
<canvas baseChart
[datasets]="widgets.widget3.datasets"
[labels]="widgets.widget3.labels"
[colors]="widgets.widget3.colors"
[options]="widgets.widget3.options"
[chartType]="widgets.widget3.chartType">
</canvas>
</div>
</div>
</div>
<!-- / Widget 3 -->
<!-- Widget 4 -->
<div class="widget" fxFlex="100" fxFlex.gt-sm="33">
<div class="fuse-card auto-width">
<div class="p-16 pb-0" fxLayout="row" fxLayoutAlign="start end" fxLayoutWrap>
<div class="pr-16">
<div class="h3 secondary-text">Visits</div>
<div class="font-size-54 font-weight-300 line-height-1 mt-8">
{{widgets.widget4.visits.value}}
</div>
</div>
<div class="py-4 font-size-16" fxLayout="row" fxLayoutAlign="start center">
<div fxFlex="row" fxLayoutAlign="start center" class="green-fg"
*ngIf="widgets.widget4.visits.ofTarget > 0">
<mat-icon class="green-fg mr-4">trending_up</mat-icon>
<span>{{widgets.widget4.visits.ofTarget}}%</span>
</div>
<div fxFlex="row" fxLayoutAlign="start center" class="red-fg"
*ngIf="widgets.widget4.visits.ofTarget < 0">
<mat-icon class="red-fg mr-4">trending_down</mat-icon>
<span>{{widgets.widget4.visits.ofTarget}}%</span>
</div>
<div class="ml-4 text-nowrap">of target</div>
</div>
</div>
<div class="h-96 w-100-p">
<canvas baseChart
[datasets]="widgets.widget4.datasets"
[labels]="widgets.widget4.labels"
[colors]="widgets.widget4.colors"
[options]="widgets.widget4.options"
[chartType]="widgets.widget4.chartType">
</canvas>
</div>
</div>
</div>
<!-- / Widget 4 -->
</div>
<!-- Widget 5 -->
<div class="pt-48 pb-24 font-size-18 font-weight-300">
How many pages your users visit?
</div>
<div class="fuse-card auto-width">
<div class="position-relative p-24"
fxLayout="row" fxLayoutAlign="space-between center">
<div fxLayout="column" fxLayoutAlign="start start">
<span class="h2">Visitors & Page views</span>
</div>
<div fxLayout="row" fxLayoutAlign="start center">
<div class="py-8 px-12 border-radius-2 line-height-1 mr-8 cursor-pointer"
(click)="widget5SelectedDay = 'yesterday'"
[ngClass]="{'grey-300-bg': widget5SelectedDay === 'yesterday'}">
Yesterday
</div>
<div class="py-8 px-12 border-radius-2 line-height-1 mr-8 cursor-pointer"
(click)="widget5SelectedDay = 'today'"
[ngClass]="{'grey-300-bg': widget5SelectedDay === 'today'}">
Today
</div>
</div>
</div>
<div class="position-relative h-368 pb-16">
<canvas baseChart
[datasets]="widgets.widget5.datasets[widget5SelectedDay]"
[labels]="widgets.widget5.labels"
[colors]="widgets.widget5.colors"
[options]="widgets.widget5.options"
[chartType]="widgets.widget5.chartType">
</canvas>
</div>
</div>
<!-- / Widget 5 -->
<!-- Widget 6 -->
<div class="pt-48 pb-24 font-size-18 font-weight-300">
Where are your users?
</div>
<div class="fuse-card auto-width p-16">
<agm-map class="h-640 w-100-p"
[minZoom]="2"
[maxZoom]="2"
[fullscreenControl]="false"
[rotateControl]="false"
[zoomControl]="false"
[scaleControl]="false"
[streetViewControl]="false"
[scrollwheel]="false"
[styles]="widgets.widget6.styles">
<agm-marker
*ngFor="let marker of widgets.widget6.markers"
[latitude]="marker.lat"
[longitude]="marker.lng">
<agm-info-window>
<strong>{{marker.label}}</strong>
</agm-info-window>
</agm-marker>
</agm-map>
</div>
<!-- / Widget 6 -->
</div>
<div class="right">
<div fxLayout="row" fxLayoutWrap
fxLayout.gt-md="column">
<!-- Widget 7 -->
<div class="mb-48" [ngClass.lt-lg]="'mr-32'">
<div class="pb-24 font-size-18 font-weight-300">
What are your top devices?
</div>
<div class="fuse-card">
<div class="p-16">
<div class="h1 font-weight-300">Sessions by device</div>
</div>
<div class="h-200">
<ngx-charts-pie-chart
*fuseIfOnDom
[scheme]="widgets.widget7.scheme"
[results]="widgets.widget7.devices"
[doughnut]="true">
</ngx-charts-pie-chart>
</div>
<div class="p-16" fxLayout="row" fxLayoutAlign="center center">
<div class="px-16" fxLayout="column" fxLayoutAlign="start center"
*ngFor="let device of widgets.widget7.devices">
<div class="h4 secondary-text">{{device.name}}</div>
<div class="h2 font-weight-300 py-8">{{device.value}}%</div>
<div fxLayout="row" fxLayoutAlign="center center">
<mat-icon class="s-18 pr-4 red-fg"
*ngIf="device.change < 0">
arrow_downward
</mat-icon>
<mat-icon class="s-18 pr-4 green-fg"
*ngIf="device.change > 0">
arrow_upward
</mat-icon>
<div class="h5 red-fg"
[ngClass]="{'red-fg': device.change < 0, 'green-fg': device.change > 0}">
{{device.change}}%
</div>
</div>
</div>
</div>
<div class="card-divider mb-0"></div>
<div class="px-16" fxLayout="row" fxLayoutAlign="space-between center">
<mat-form-field>
<mat-select class="simplified" value="7days">
<mat-option value="today">Today</mat-option>
<mat-option value="yesterday">Yesterday</mat-option>
<mat-option value="7days">Last 7 days</mat-option>
<mat-option value="28days">Last 28 days</mat-option>
<mat-option value="90days">Last 90 days</mat-option>
</mat-select>
</mat-form-field>
<button mat-button color="accent">OVERVIEW</button>
</div>
</div>
</div>
<!-- / Widget 7 -->
<!-- Widget 8 -->
<div class="mb-48" [ngClass.lt-lg]="'mr-32'">
<div class="pb-24 font-size-18 font-weight-300">
How are your sales?
</div>
<div class="fuse-card">
<div class="mat-light-blue-600-bg">
<div class="p-16" fxLayout="row" fxLayoutAlign="space-between center">
<div class="pr-16">
<div class="h1 font-weight-300">Sales</div>
<div class="h5 secondary-text">Lifetime sum of your sales</div>
</div>
<div>
<button mat-icon-button [matMenuTriggerFor]="card19Menu" aria-label="more">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #card19Menu="matMenu">
<button mat-menu-item>
<mat-icon>trending_up</mat-icon>
<span>Trend</span>
</button>
<button mat-menu-item>
<mat-icon>history</mat-icon>
<span>History</span>
</button>
<button mat-menu-item>
<mat-icon>notifications_off</mat-icon>
<span>Disable alerts</span>
</button>
</mat-menu>
</div>
</div>
<div class="p-16 pt-8" fxLayout="row" fxLayoutAlign="space-between end">
<div class="font-size-48 font-weight-300 line-height-1">{{widgets.widget8.today}}</div>
<div fxLayout="row" fxLayoutAlign="start center">
<mat-icon *ngIf="widgets.widget8.change.value > 0">trending_up</mat-icon>
<mat-icon *ngIf="widgets.widget8.change.value < 0">trending_down</mat-icon>
<div class="ml-8">{{widgets.widget8.change.value}}
({{widgets.widget8.change.percentage}}%)
</div>
</div>
</div>
</div>
<mat-tab-group backgroundColor="accent">
<mat-tab label="1DAY">
<div class="h-200 my-16">
<ngx-charts-line-chart
*fuseIfOnDom
[scheme]="widgets.widget8.scheme"
[results]="widgets.widget8.data"
[xAxis]="false"
[yAxis]="true"
[yScaleMin]="widgets.widget8.dataMin"
[yScaleMax]="widgets.widget8.dataMax">
</ngx-charts-line-chart>
</div>
</mat-tab>
<mat-tab label="1WEEK">
<div class="h-200 my-16">
<ngx-charts-line-chart
*fuseIfOnDom
[scheme]="widgets.widget8.scheme"
[results]="widgets.widget8.data"
[xAxis]="false"
[yAxis]="true"
[yScaleMin]="widgets.widget8.dataMin"
[yScaleMax]="widgets.widget8.dataMax">
</ngx-charts-line-chart>
</div>
</mat-tab>
<mat-tab label="1MONTH">
<div class="h-200 my-16">
<ngx-charts-line-chart
*fuseIfOnDom
[scheme]="widgets.widget8.scheme"
[results]="widgets.widget8.data"
[xAxis]="false"
[yAxis]="true"
[yScaleMin]="widgets.widget8.dataMin"
[yScaleMax]="widgets.widget8.dataMax">
</ngx-charts-line-chart>
</div>
</mat-tab>
</mat-tab-group>
</div>
</div>
<!-- / Widget 8 -->
<!-- Widget 9 -->
<div class="mb-48" [ngClass.lt-lg]="'mr-32'">
<div class="pb-24 font-size-18 font-weight-300" [ngClass.lt-lg]="'pt-0'">
What are your top campaigns?
</div>
<div class="fuse-card">
<div class="p-16" fxLayout="row" fxLayoutAlign="space-between center">
<div class="h1 pr-16">Top campaigns</div>
<div>
<button mat-icon-button [matMenuTriggerFor]="card20Menu" aria-label="more">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #card20Menu="matMenu">
<button fxLayout="row" fxLayoutAlign="start center" mat-menu-item>
<mat-icon color="accent">check_box</mat-icon>
<span>Show Clicks</span>
</button>
<button fxLayout="row" fxLayoutAlign="start center" mat-menu-item>
<mat-icon color="accent">check_box</mat-icon>
<span>Show Conversion</span>
</button>
<button fxLayout="row" fxLayoutAlign="start center" mat-menu-item>
<mat-icon>check_box_outline_blank</mat-icon>
<span>Show CPC</span>
</button>
</mat-menu>
</div>
</div>
<table class="simple clickable">
<thead>
<tr>
<th></th>
<th class="text-right">Clicks</th>
<th class="text-right">Conv</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of widgets.widget9.rows">
<td>{{row.title}}</td>
<td class="text-right">{{row.clicks}}</td>
<td class="text-right">{{row.conversion}}</td>
</tr>
</tbody>
</table>
<div class="card-divider full-width"></div>
<div class="p-8 pt-16" fxLayout="row" fxLayoutAlign="start center">
<button mat-button color="accent">GO TO CAMPAIGNS</button>
</div>
</div>
</div>
<!-- / widget 9 -->
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,49 @@
@import "src/app/core/scss/fuse";
#dashboard-analytics {
.main-widget {
display: flex;
flex-direction: column;
}
.content {
display: flex;
flex: 1 1 auto;
padding: 32px;
min-width: 0;
@include media-breakpoint-down('md') {
flex-direction: column;
}
.left {
display: flex;
flex-direction: column;
flex: 1 1 auto;
min-width: 0;
.widget {
flex: 1 1 auto;
min-width: 0;
}
}
.right {
display: flex;
flex: 0 0 auto;
width: 320px;
min-width: 320px;
max-width: 320px;
@include media-breakpoint-down('md') {
flex: 1 0 100%;
margin-top: 32px;
width: 100%;
min-width: 0;
max-width: none;
}
}
}
}

View File

@@ -0,0 +1,91 @@
import { Component, ViewEncapsulation } from '@angular/core';
import { AnalyticsDashboardService } from './analytics.service';
import { fuseAnimations } from '../../../../../core/animations';
@Component({
selector : 'fuse-analytics-dashboard',
templateUrl : './analytics.component.html',
styleUrls : ['./analytics.component.scss'],
encapsulation: ViewEncapsulation.None,
animations : fuseAnimations
})
export class FuseAnalyticsDashboardComponent
{
widgets: any;
widget1SelectedYear = '2016';
widget5SelectedDay = 'today';
constructor(
private analyticsDashboardService: AnalyticsDashboardService
)
{
// Get the widgets from the service
this.widgets = this.analyticsDashboardService.widgets;
// Register the custom chart.js plugin
this.registerCustomChartJSPlugin();
}
/**
* Register a custom plugin
*/
registerCustomChartJSPlugin()
{
(<any>window).Chart.plugins.register({
afterDatasetsDraw: function (chart, easing) {
// Only activate the plugin if it's made available
// in the options
if (
!chart.options.plugins.xLabelsOnTop ||
(chart.options.plugins.xLabelsOnTop && chart.options.plugins.xLabelsOnTop.active === false)
)
{
return;
}
// To only draw at the end of animation, check for easing === 1
const ctx = chart.ctx;
chart.data.datasets.forEach(function (dataset, i) {
const meta = chart.getDatasetMeta(i);
if ( !meta.hidden )
{
meta.data.forEach(function (element, index) {
// Draw the text in black, with the specified font
ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';
const fontSize = 13;
const fontStyle = 'normal';
const fontFamily = 'Roboto, Helvetica Neue, Arial';
ctx.font = (<any>window).Chart.helpers.fontString(fontSize, fontStyle, fontFamily);
// Just naively convert to string for now
const dataString = dataset.data[index].toString() + 'k';
// Make sure alignment settings are correct
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const padding = 15;
const startY = 24;
const position = element.tooltipPosition();
ctx.fillText(dataString, position.x, startY);
ctx.save();
ctx.beginPath();
ctx.setLineDash([5, 3]);
ctx.moveTo(position.x, startY + padding);
ctx.lineTo(position.x, position.y - padding);
ctx.strokeStyle = 'rgba(255,255,255,0.12)';
ctx.stroke();
ctx.restore();
});
}
});
}
});
}
}

View File

@@ -0,0 +1,41 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { SharedModule } from '../../../../../core/modules/shared.module';
import { NgxChartsModule } from '@swimlane/ngx-charts';
import { AgmCoreModule } from '@agm/core';
import { FuseAnalyticsDashboardComponent } from './analytics.component';
import { AnalyticsDashboardService } from './analytics.service';
import { FuseWidgetModule } from '../../../../../core/components/widget/widget.module';
const routes: Routes = [
{
path : '**',
component: FuseAnalyticsDashboardComponent,
resolve : {
data: AnalyticsDashboardService
}
}
];
@NgModule({
imports : [
SharedModule,
RouterModule.forChild(routes),
FuseWidgetModule,
NgxChartsModule,
AgmCoreModule.forRoot({
apiKey: 'AIzaSyD81ecsCj4yYpcXSLFcYU97PvRsE_X8Bx8'
})
],
declarations: [
FuseAnalyticsDashboardComponent
],
providers : [
AnalyticsDashboardService
]
})
export class FuseAnalyticsDashboardModule
{
}

View File

@@ -0,0 +1,48 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class AnalyticsDashboardService implements Resolve<any>
{
widgets: any[];
constructor(
private http: HttpClient
)
{
}
/**
* Resolve
* @param {ActivatedRouteSnapshot} route
* @param {RouterStateSnapshot} state
* @returns {Observable<any> | Promise<any> | any}
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any
{
return new Promise((resolve, reject) => {
Promise.all([
this.getWidgets()
]).then(
() => {
resolve();
},
reject
);
});
}
getWidgets(): Promise<any>
{
return new Promise((resolve, reject) => {
this.http.get('api/analytics-dashboard-widgets')
.subscribe((response: any) => {
this.widgets = response;
resolve(response);
}, reject);
});
}
}

View File

@@ -10,7 +10,9 @@
<div fxLayout="row" fxLayoutAlign="space-between start"> <div fxLayout="row" fxLayoutAlign="space-between start">
<span class="mat-display-1 mb-0 welcome-message" *fuseIfOnDom [@animate]="{value:'*',params:{x:'50px'}}">Welcome back, John!</span> <span class="mat-display-1 mb-0 welcome-message" *fuseIfOnDom
[@animate]="{value:'*',params:{x:'50px'}}">Welcome back, John!
</span>
<button mat-icon-button fuseMatSidenavToggler="dashboards-right-sidenav" fxHide.gt-md> <button mat-icon-button fuseMatSidenavToggler="dashboards-right-sidenav" fxHide.gt-md>
<mat-icon>menu</mat-icon> <mat-icon>menu</mat-icon>
@@ -21,7 +23,8 @@
<div class="selected-project">{{selectedProject.name}}</div> <div class="selected-project">{{selectedProject.name}}</div>
<button mat-icon-button class="project-selector" [matMenuTriggerFor]="projectsMenu" aria-label="Select project"> <button mat-icon-button class="project-selector" [matMenuTriggerFor]="projectsMenu"
aria-label="Select project">
<mat-icon>more_horiz</mat-icon> <mat-icon>more_horiz</mat-icon>
</button> </button>
@@ -41,16 +44,20 @@
<mat-tab label="Home"> <mat-tab label="Home">
<div class="widget-group p-12" fxLayout="row" fxFlex="100" fxLayoutWrap *fuseIfOnDom [@animateStagger]="{value:'50'}"> <div class="widget-group grey-100-bg p-12" fxLayout="row" fxFlex="100" fxLayoutWrap *fuseIfOnDom
[@animateStagger]="{value:'50'}">
<!-- WIDGET 1 --> <!-- WIDGET 1 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column" fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25"> <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25">
<!-- Front --> <!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2"> <div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="pl-16 pr-8 py-16 h-52" fxLayout="row" fxLayoutAlign="space-between center"> <div class="pl-16 pr-8 py-16 h-52" fxLayout="row"
fxLayoutAlign="space-between center">
<mat-form-field> <mat-form-field>
<mat-select class="simplified font-size-16" [(ngModel)]="widgets.widget1.currentRange" <mat-select class="simplified font-size-16"
[(ngModel)]="widgets.widget1.currentRange"
aria-label="Change range"> aria-label="Change range">
<mat-option *ngFor="let range of widgets.widget1.ranges | keys" <mat-option *ngFor="let range of widgets.widget1.ranges | keys"
[value]="range.key"> [value]="range.key">
@@ -67,12 +74,17 @@
<div class="light-blue-fg font-size-72 line-height-72"> <div class="light-blue-fg font-size-72 line-height-72">
{{widgets.widget1.data.count[widgets.widget1.currentRange]}} {{widgets.widget1.data.count[widgets.widget1.currentRange]}}
</div> </div>
<div class="h3 secondary-text font-weight-500">{{widgets.widget1.data.label}}</div> <div class="h3 secondary-text font-weight-500">{{widgets.widget1.data.label}}
</div>
</div> </div>
<div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center"> <div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center">
<span class="h4 secondary-text text-truncate">{{widgets.widget1.data.extra.label}}:</span> <span class="h4 secondary-text text-truncate">
<span class="h4 ml-8">{{widgets.widget1.data.extra.count[widgets.widget1.currentRange]}}</span> {{widgets.widget1.data.extra.label}}:
</span>
<span class="h4 ml-8">
{{widgets.widget1.data.extra.count[widgets.widget1.currentRange]}}
</span>
</div> </div>
</div> </div>
<!-- / Front --> <!-- / Front -->
@@ -94,14 +106,17 @@
<!-- / WIDGET 1 --> <!-- / WIDGET 1 -->
<!-- WIDGET 2 --> <!-- WIDGET 2 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column" fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25"> <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25">
<!-- Front --> <!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2"> <div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="pl-16 pr-8 py-16 h-52" fxLayout="row" fxLayoutAlign="space-between center"> <div class="pl-16 pr-8 py-16 h-52" fxLayout="row"
fxLayoutAlign="space-between center">
<div class="h3">{{widgets.widget2.title}}</div> <div class="h3">{{widgets.widget2.title}}</div>
<button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button" aria-label="more"> <button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button"
aria-label="more">
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
</button> </button>
</div> </div>
@@ -110,11 +125,14 @@
<div class="red-fg font-size-72 line-height-72"> <div class="red-fg font-size-72 line-height-72">
{{widgets.widget2.data.count}} {{widgets.widget2.data.count}}
</div> </div>
<div class="h3 secondary-text font-weight-500">{{widgets.widget2.data.label}}</div> <div class="h3 secondary-text font-weight-500">{{widgets.widget2.data.label}}
</div>
</div> </div>
<div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center"> <div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center">
<span class="h4 secondary-text text-truncate">{{widgets.widget2.data.extra.label}}:</span> <span class="h4 secondary-text text-truncate">
{{widgets.widget2.data.extra.label}}:
</span>
<span class="h4 ml-8">{{widgets.widget2.data.extra.count}}</span> <span class="h4 ml-8">{{widgets.widget2.data.extra.count}}</span>
</div> </div>
</div> </div>
@@ -137,14 +155,17 @@
<!-- / WIDGET 2 --> <!-- / WIDGET 2 -->
<!-- WIDGET 3 --> <!-- WIDGET 3 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column" fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25"> <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25">
<!-- Front --> <!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2"> <div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="pl-16 pr-8 py-16 h-52" fxLayout="row" fxLayoutAlign="space-between center"> <div class="pl-16 pr-8 py-16 h-52" fxLayout="row"
fxLayoutAlign="space-between center">
<div class="h3">{{widgets.widget3.title}}</div> <div class="h3">{{widgets.widget3.title}}</div>
<button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button" aria-label="more"> <button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button"
aria-label="more">
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
</button> </button>
</div> </div>
@@ -153,11 +174,14 @@
<div class="orange-fg font-size-72 line-height-72"> <div class="orange-fg font-size-72 line-height-72">
{{widgets.widget3.data.count}} {{widgets.widget3.data.count}}
</div> </div>
<div class="h3 secondary-text font-weight-500">{{widgets.widget3.data.label}}</div> <div class="h3 secondary-text font-weight-500">{{widgets.widget3.data.label}}
</div>
</div> </div>
<div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center"> <div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center">
<span class="h4 secondary-text text-truncate">{{widgets.widget3.data.extra.label}}:</span> <span class="h4 secondary-text text-truncate">
{{widgets.widget3.data.extra.label}}:
</span>
<span class="h4 ml-8">{{widgets.widget3.data.extra.count}}</span> <span class="h4 ml-8">{{widgets.widget3.data.extra.count}}</span>
</div> </div>
</div> </div>
@@ -180,26 +204,33 @@
<!-- / WIDGET 3 --> <!-- / WIDGET 3 -->
<!-- WIDGET 4 --> <!-- WIDGET 4 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column" fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25"> <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25">
<!-- Front --> <!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2"> <div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="pl-16 pr-8 py-16 h-52" fxLayout="row" fxLayoutAlign="space-between center"> <div class="pl-16 pr-8 py-16 h-52" fxLayout="row"
fxLayoutAlign="space-between center">
<div class="h3">{{widgets.widget4.title}}</div> <div class="h3">{{widgets.widget4.title}}</div>
<button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button" aria-label="more"> <button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button"
aria-label="more">
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
</button> </button>
</div> </div>
<div class="pt-8 pb-32" fxLayout="column" fxLayoutAlign="center center"> <div class="pt-8 pb-32" fxLayout="column" fxLayoutAlign="center center">
<div class="blue-grey-fg font-size-72 line-height-72">{{widgets.widget4.data.count}} <div class="blue-grey-fg font-size-72 line-height-72">
{{widgets.widget4.data.count}}
</div>
<div class="h3 secondary-text font-weight-500">{{widgets.widget4.data.label}}
</div> </div>
<div class="h3 secondary-text font-weight-500">{{widgets.widget4.data.label}}</div>
</div> </div>
<div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center"> <div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center">
<span class="h4 secondary-text text-truncate">{{widgets.widget4.data.extra.label}}:</span> <span class="h4 secondary-text text-truncate">
{{widgets.widget4.data.extra.label}}:
</span>
<span class="h4 ml-8">{{widgets.widget4.data.extra.count}}</span> <span class="h4 ml-8">{{widgets.widget4.data.extra.count}}</span>
</div> </div>
</div> </div>
@@ -221,18 +252,19 @@
</fuse-widget> </fuse-widget>
<!-- / WIDGET 4 --> <!-- / WIDGET 4 -->
<!-- WIDGET 5 --> <!-- WIDGET 5 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="row" fxFlex="100"> <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" fxLayout="row" fxFlex="100"
class="widget widget5">
<!-- Front --> <!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2"> <div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="px-16 border-bottom" fxLayout="row" fxLayoutAlign="space-between center" fxLayoutWrap> <div class="px-16 border-bottom" fxLayout="row" fxLayoutAlign="space-between center"
fxLayoutWrap>
<div fxFlex class="py-8 h3">{{widgets.widget5.title}}</div> <div fxFlex class="py-16 h3">{{widgets.widget5.title}}</div>
<div fxFlex="0 1 auto" class="py-8" fxLayout="row"> <div fxFlex="0 1 auto" class="py-16" fxLayout="row">
<button mat-button class="px-16" <button mat-button class="px-16"
*ngFor="let range of widgets.widget5.ranges | keys" *ngFor="let range of widgets.widget5.ranges | keys"
(click)="widget5.currentRange = range.key" (click)="widget5.currentRange = range.key"
@@ -242,8 +274,9 @@
</div> </div>
</div> </div>
<div fxLayout="row" fxLayoutAlign="start end" fxLayoutWrap> <div fxLayout="row" fxLayoutAlign="start start" fxLayoutWrap>
<div class="h-420 mb-16" fxLayout="row" fxFlex="100" fxFlex.gt-sm="50">
<div class="h-420 my-16" fxLayout="row" fxFlex="100" fxFlex.gt-sm="50">
<ngx-charts-bar-vertical-stacked <ngx-charts-bar-vertical-stacked
*fuseIfOnDom *fuseIfOnDom
[scheme]="widget5.scheme" [scheme]="widget5.scheme"
@@ -260,10 +293,12 @@
</ngx-charts-bar-vertical-stacked> </ngx-charts-bar-vertical-stacked>
</div> </div>
<div class="mb-16" fxFlex="100" fxFlex.gt-sm="50" fxLayoutAlign="row" fxLayoutWrap> <div class="my-16" fxFlex="100" fxFlex.gt-sm="50" fxLayoutAlign="row"
fxLayoutWrap>
<div fxLayout="column" fxFlex="100" fxFlex.gt-sm="50" fxLayoutAlign="center" <div fxLayout="column" fxFlex="100" fxFlex.gt-sm="50" fxLayoutAlign="center"
*ngFor="let widget of widgets.widget5.supporting | keys"> *ngFor="let widget of widgets.widget5.supporting | keys"
class="mb-24">
<div class="px-24"> <div class="px-24">
<div class="h4 secondary-text">{{widget.value.label}}</div> <div class="h4 secondary-text">{{widget.value.label}}</div>
@@ -297,17 +332,19 @@
</fuse-widget> </fuse-widget>
<!-- / WIDGET 5 --> <!-- / WIDGET 5 -->
<!-- WIDGET 6 --> <!-- WIDGET 6 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column" fxFlex="100" fxFlex.gt-sm="50"> <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-sm="50">
<!-- Front --> <!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2"> <div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="px-16 border-bottom" fxLayout="row" fxLayoutAlign="space-between center"> <div class="px-16 py-8 border-bottom" fxLayout="row"
fxLayoutAlign="space-between center">
<div class="h3">{{widgets.widget6.title}}</div> <div class="h3">{{widgets.widget6.title}}</div>
<mat-form-field> <mat-form-field>
<mat-select class="simplified" [(ngModel)]="widget6.currentRange" aria-label="Change range"> <mat-select class="simplified" [(ngModel)]="widget6.currentRange"
aria-label="Change range">
<mat-option *ngFor="let range of widgets.widget6.ranges | keys" <mat-option *ngFor="let range of widgets.widget6.ranges | keys"
[value]="range.key"> [value]="range.key">
{{range.value}} {{range.value}}
@@ -330,14 +367,21 @@
</ngx-charts-pie-chart> </ngx-charts-pie-chart>
</div> </div>
<div class="py-8 mh-16 border-top" fxLayout="row" fxLayoutAlign="start center" fxLayoutWrap> <div class="py-8 mh-16 border-top" fxLayout="row" fxLayoutAlign="start center"
<div class="py-8 border-right" fxLayout="column" fxLayoutAlign="center center" fxFlex="100" fxFlex.gt-sm="50"> fxLayoutWrap>
<span class="mat-display-1 mb-0">{{widgets.widget6.footerLeft.count[widget6.currentRange]}}</span> <div class="py-8 border-right" fxLayout="column" fxLayoutAlign="center center"
fxFlex="100" fxFlex.gt-sm="50">
<span class="mat-display-1 mb-0">
{{widgets.widget6.footerLeft.count[widget6.currentRange]}}
</span>
<span class="h4">{{widgets.widget6.footerLeft.title}}</span> <span class="h4">{{widgets.widget6.footerLeft.title}}</span>
</div> </div>
<div class="py-8" fxLayout="column" fxLayoutAlign="center center" fxFlex="100" fxFlex.gt-sm="50"> <div class="py-8" fxLayout="column" fxLayoutAlign="center center" fxFlex="100"
<span class="mat-display-1 mb-0">{{widgets.widget6.footerRight.count[widget6.currentRange]}}</span> fxFlex.gt-sm="50">
<span class="mat-display-1 mb-0">
{{widgets.widget6.footerRight.count[widget6.currentRange]}}
</span>
<span class="h4">{{widgets.widget6.footerRight.title}}</span> <span class="h4">{{widgets.widget6.footerRight.title}}</span>
</div> </div>
</div> </div>
@@ -349,12 +393,14 @@
<!-- / WIDGET 6 --> <!-- / WIDGET 6 -->
<!-- WIDGET 7 --> <!-- WIDGET 7 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column" fxFlex="100" fxFlex.gt-sm="50"> <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-sm="50">
<!-- Front --> <!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2"> <div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="px-16 border-bottom" fxLayout="row" fxLayoutAlign="space-between center"> <div class="px-16 py-8 border-bottom" fxLayout="row"
fxLayoutAlign="space-between center">
<div class="h3">{{widgets.widget7.title}}</div> <div class="h3">{{widgets.widget7.title}}</div>
<mat-form-field> <mat-form-field>
<mat-select class="simplified" [(ngModel)]="widget7.currentRange" <mat-select class="simplified" [(ngModel)]="widget7.currentRange"
@@ -391,20 +437,21 @@
</div> </div>
<!-- / WIDGET GROUP --> <!-- / WIDGET GROUP -->
</mat-tab> </mat-tab>
<mat-tab label="Budget Summary"> <mat-tab label="Budget Summary">
<!-- WIDGET GROUP --> <!-- WIDGET GROUP -->
<div class="widget-group" fxLayout="row" fxFlex="100" fxLayoutWrap *fuseIfOnDom [@animateStagger]="{value:'50'}"> <div class="widget-group grey-100-bg" fxLayout="row" fxFlex="100" fxLayoutWrap *fuseIfOnDom
[@animateStagger]="{value:'50'}">
<!-- WIDGET 8 --> <!-- WIDGET 8 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column" fxFlex="100" fxFlex.gt-sm="50"> <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-sm="50">
<!-- Front --> <!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2"> <div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="h3 p-16"> <div class="h3 px-16 py-24">
{{widgets.widget8.title}} {{widgets.widget8.title}}
</div> </div>
@@ -431,11 +478,13 @@
<!-- / WIDGET 8 --> <!-- / WIDGET 8 -->
<!-- WIDGET 9 --> <!-- WIDGET 9 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column" fxFlex="100" fxFlex.gt-sm="50"> <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-sm="50">
<!-- Front --> <!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2"> <div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="px-16 border-bottom" fxLayout="row" fxLayoutAlign="space-between center"> <div class="px-16 py-12 border-bottom" fxLayout="row"
fxLayoutAlign="space-between center">
<div class="h3">{{widgets.widget9.title}}</div> <div class="h3">{{widgets.widget9.title}}</div>
<mat-form-field> <mat-form-field>
<mat-select [(ngModel)]="widget9.currentRange" aria-label="Change range"> <mat-select [(ngModel)]="widget9.currentRange" aria-label="Change range">
@@ -447,7 +496,7 @@
</mat-form-field> </mat-form-field>
</div> </div>
<div class="p-16" fxLayout="column" fxLayoutAlign="center" fxLayout.gt-xs="row" <div class="px-16 py-24" fxLayout="column" fxLayoutAlign="center" fxLayout.gt-xs="row"
fxLayoutAlign.gt-xs="space-between end"> fxLayoutAlign.gt-xs="space-between end">
<div fxFlex="0 1 auto"> <div fxFlex="0 1 auto">
<div class="h4 secondary-text">{{widgets.widget9.weeklySpent.title}}</div> <div class="h4 secondary-text">{{widgets.widget9.weeklySpent.title}}</div>
@@ -474,7 +523,7 @@
</div> </div>
</div> </div>
<div class="p-16" fxLayout="column" fxLayoutAlign="center" fxLayout.gt-xs="row" <div class="px-16 py-24" fxLayout="column" fxLayoutAlign="center" fxLayout.gt-xs="row"
fxLayoutAlign.gt-xs="space-between end"> fxLayoutAlign.gt-xs="space-between end">
<div fxFlex="0 1 auto"> <div fxFlex="0 1 auto">
<div class="h4 secondary-text">{{widgets.widget9.totalSpent.title}}</div> <div class="h4 secondary-text">{{widgets.widget9.totalSpent.title}}</div>
@@ -501,7 +550,7 @@
</div> </div>
</div> </div>
<div class="p-16" fxLayout="column" fxLayoutAlign="center" fxLayout.gt-xs="row" <div class="px-16 py-24" fxLayout="column" fxLayoutAlign="center" fxLayout.gt-xs="row"
fxLayoutAlign.gt-xs="space-between end"> fxLayoutAlign.gt-xs="space-between end">
<div fxFlex="0 1 auto"> <div fxFlex="0 1 auto">
<div class="h4 secondary-text">{{widgets.widget9.remaining.title}}</div> <div class="h4 secondary-text">{{widgets.widget9.remaining.title}}</div>
@@ -528,7 +577,7 @@
</div> </div>
</div> </div>
<div class="p-16 border-top"> <div class="px-16 py-24 border-top">
<div class="h4 secondary-text">{{widgets.widget9.totalBudget.title}}</div> <div class="h4 secondary-text">{{widgets.widget9.totalBudget.title}}</div>
<div class="pt-8 mat-display-1 m-0 font-weight-300"> <div class="pt-8 mat-display-1 m-0 font-weight-300">
<span class="secondary-text">$</span> <span class="secondary-text">$</span>
@@ -543,7 +592,8 @@
<!-- / WIDGET 9 --> <!-- / WIDGET 9 -->
<!-- WIDGET 10 --> <!-- WIDGET 10 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="row" fxFlex="100"> <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="row"
fxFlex="100">
<!-- Front --> <!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2"> <div class="fuse-widget-front mat-white-bg mat-elevation-z2">
@@ -569,7 +619,8 @@
<span class="p-4" [ngClass]="cell.classes"> <span class="p-4" [ngClass]="cell.classes">
{{cell.value}} {{cell.value}}
</span> </span>
<mat-icon *ngIf="cell.icon" class="s-16">{{cell.icon}}</mat-icon> <mat-icon *ngIf="cell.icon" class="s-16">{{cell.icon}}
</mat-icon>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@@ -590,17 +641,21 @@
<mat-tab label="Team Members"> <mat-tab label="Team Members">
<!-- WIDGET GROUP --> <!-- WIDGET GROUP -->
<div class="widget-group" fxLayout="row" fxFlex="100" fxLayoutWrap *fuseIfOnDom [@animateStagger]="{value:'50'}"> <div class="widget-group grey-100-bg" fxLayout="row" fxFlex="100" fxLayoutWrap *fuseIfOnDom
[@animateStagger]="{value:'50'}">
<!-- WIDGET 11 --> <!-- WIDGET 11 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="row" fxFlex="100"> <fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="row"
fxFlex="100">
<!-- Front --> <!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2"> <div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="p-24 mb-8 border-bottom" fxLayout="row" fxLayoutAlign="space-between center"> <div class="p-24 mb-8 border-bottom" fxLayout="row"
fxLayoutAlign="space-between center">
<div class="h2">{{widgets.widget11.title}}</div> <div class="h2">{{widgets.widget11.title}}</div>
<div class="text-boxed red-bg white-fg m-0">{{widgets.widget11.table.rows.length}} <div class="text-boxed red-bg white-fg m-0">
{{widgets.widget11.table.rows.length}}
members members
</div> </div>
</div> </div>
@@ -620,13 +675,15 @@
<ng-container cdkColumnDef="name"> <ng-container cdkColumnDef="name">
<mat-header-cell *cdkHeaderCellDef>Name</mat-header-cell> <mat-header-cell *cdkHeaderCellDef>Name</mat-header-cell>
<mat-cell *cdkCellDef="let contact"> <mat-cell *cdkCellDef="let contact">
<p class="text-truncate font-weight-600">{{contact.name}} {{contact.lastName}}</p> <p class="text-truncate font-weight-600">{{contact.name}}
{{contact.lastName}}</p>
</mat-cell> </mat-cell>
</ng-container> </ng-container>
<!-- Position Column --> <!-- Position Column -->
<ng-container cdkColumnDef="position"> <ng-container cdkColumnDef="position">
<mat-header-cell *cdkHeaderCellDef fxHide fxShow.gt-sm>Position</mat-header-cell> <mat-header-cell *cdkHeaderCellDef fxHide fxShow.gt-sm>Position
</mat-header-cell>
<mat-cell *cdkCellDef="let contact" fxHide fxShow.gt-sm> <mat-cell *cdkCellDef="let contact" fxHide fxShow.gt-sm>
<p class="position text-truncate"> <p class="position text-truncate">
{{contact.position}} {{contact.position}}
@@ -636,7 +693,8 @@
<!-- Office Column --> <!-- Office Column -->
<ng-container cdkColumnDef="office"> <ng-container cdkColumnDef="office">
<mat-header-cell *cdkHeaderCellDef fxHide fxShow.gt-md>Office</mat-header-cell> <mat-header-cell *cdkHeaderCellDef fxHide fxShow.gt-md>Office
</mat-header-cell>
<mat-cell *cdkCellDef="let contact" fxHide fxShow.gt-md> <mat-cell *cdkCellDef="let contact" fxHide fxShow.gt-md>
<p class="office text-truncate"> <p class="office text-truncate">
{{contact.office}} {{contact.office}}
@@ -644,10 +702,10 @@
</mat-cell> </mat-cell>
</ng-container> </ng-container>
<!-- Email Column --> <!-- Email Column -->
<ng-container cdkColumnDef="email"> <ng-container cdkColumnDef="email">
<mat-header-cell *cdkHeaderCellDef fxHide fxShow.gt-sm>Email</mat-header-cell> <mat-header-cell *cdkHeaderCellDef fxHide fxShow.gt-sm>Email
</mat-header-cell>
<mat-cell *cdkCellDef="let contact" fxHide fxShow.gt-sm> <mat-cell *cdkCellDef="let contact" fxHide fxShow.gt-sm>
<p class="email text-truncate"> <p class="email text-truncate">
{{contact.email}} {{contact.email}}
@@ -657,7 +715,8 @@
<!-- Phone Column --> <!-- Phone Column -->
<ng-container cdkColumnDef="phone"> <ng-container cdkColumnDef="phone">
<mat-header-cell *cdkHeaderCellDef fxHide fxShow.gt-md>Phone</mat-header-cell> <mat-header-cell *cdkHeaderCellDef fxHide fxShow.gt-md>Phone
</mat-header-cell>
<mat-cell *cdkCellDef="let contact" fxHide fxShow.gt-md> <mat-cell *cdkCellDef="let contact" fxHide fxShow.gt-md>
<p class="phone text-truncate"> <p class="phone text-truncate">
{{contact.phone}} {{contact.phone}}
@@ -665,7 +724,8 @@
</mat-cell> </mat-cell>
</ng-container> </ng-container>
<mat-header-row *cdkHeaderRowDef="widgets.widget11.table.columns"></mat-header-row> <mat-header-row
*cdkHeaderRowDef="widgets.widget11.table.columns"></mat-header-row>
<mat-row *cdkRowDef="let contact; columns: widgets.widget11.table.columns;"> <mat-row *cdkRowDef="let contact; columns: widgets.widget11.table.columns;">
</mat-row> </mat-row>
</mat-table> </mat-table>
@@ -688,7 +748,8 @@
<!-- / CENTER --> <!-- / CENTER -->
<!-- SIDENAV --> <!-- SIDENAV -->
<mat-sidenav class="sidenav" align="end" mode="side" opened="true" fuseMatSidenavHelper="dashboards-right-sidenav" mat-is-locked-open="gt-md"> <mat-sidenav class="sidenav" align="end" mode="side" opened="true"
fuseMatSidenavHelper="dashboards-right-sidenav" mat-is-locked-open="gt-md">
<div class="sidenav-content" fusePerfectScrollbar> <div class="sidenav-content" fusePerfectScrollbar>
@@ -768,7 +829,8 @@
<div class="p-16 pb-32" fxLayout="column" fxLayoutAlign="center center"> <div class="p-16 pb-32" fxLayout="column" fxLayoutAlign="center center">
<div fxLayout="row" fxLayoutAlign="center center"> <div fxLayout="row" fxLayoutAlign="center center">
<mat-icon fontSet="meteocons" [fontIcon]="widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].icon" <mat-icon fontSet="meteocons"
[fontIcon]="widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].icon"
class="icon s-40 mr-16"></mat-icon> class="icon s-40 mr-16"></mat-icon>
<span class="mat-display-2 m-0 font-weight-300 secondary-text"> <span class="mat-display-2 m-0 font-weight-300 secondary-text">
{{widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].temp[widgets.weatherWidget.tempUnit]}} {{widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].temp[widgets.weatherWidget.tempUnit]}}
@@ -789,12 +851,16 @@
<div fxLayout="row" fxLayoutAlign="start center"> <div fxLayout="row" fxLayoutAlign="start center">
<mat-icon fontSet="meteocons" fontIcon="icon-compass" class="mr-8 s-16"></mat-icon> <mat-icon fontSet="meteocons" fontIcon="icon-compass" class="mr-8 s-16"></mat-icon>
<span>{{widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].windDirection}}</span> <span>
{{widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].windDirection}}
</span>
</div> </div>
<div fxLayout="row" fxLayoutAlign="start center"> <div fxLayout="row" fxLayoutAlign="start center">
<mat-icon fontSet="meteocons" fontIcon="icon-rainy" class="mr-8 s-16"></mat-icon> <mat-icon fontSet="meteocons" fontIcon="icon-rainy" class="mr-8 s-16"></mat-icon>
<span>{{widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].rainProbability}}</span> <span>
{{widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].rainProbability}}
</span>
</div> </div>
</div> </div>
@@ -806,7 +872,9 @@
<mat-icon fontSet="meteocons" [fontIcon]="day.icon" class="mr-16"></mat-icon> <mat-icon fontSet="meteocons" [fontIcon]="day.icon" class="mr-16"></mat-icon>
<span class="h2">{{day.temp[widgets.weatherWidget.tempUnit]}}</span> <span class="h2">{{day.temp[widgets.weatherWidget.tempUnit]}}</span>
<span class="h2 font-weight-300 secondary-text text-super">&deg;</span> <span class="h2 font-weight-300 secondary-text text-super">&deg;</span>
<span class="h2 font-weight-300 secondary-text">{{widgets.weatherWidget.tempUnit}}</span> <span class="h2 font-weight-300 secondary-text">
{{widgets.weatherWidget.tempUnit}}
</span>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -56,5 +56,15 @@
min-width: 250px !important; min-width: 250px !important;
max-width: 250px !important; max-width: 250px !important;
} }
.widget {
&.widget5 {
.gridline-path.gridline-path-horizontal {
display: none;
}
}
}
} }
} }

View File

@@ -1,19 +1,20 @@
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { ProjectsDashboardService } from './projects.service';
import * as shape from 'd3-shape'; import * as shape from 'd3-shape';
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { DataSource } from '@angular/cdk/collections'; import { DataSource } from '@angular/cdk/collections';
import { ProjectDashboardService } from './project.service';
import { fuseAnimations } from '../../../../../core/animations'; import { fuseAnimations } from '../../../../../core/animations';
@Component({ @Component({
selector : 'fuse-project', selector : 'fuse-project-dashboard',
templateUrl : './project.component.html', templateUrl : './project.component.html',
styleUrls : ['./project.component.scss'], styleUrls : ['./project.component.scss'],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
animations : fuseAnimations animations : fuseAnimations
}) })
export class FuseProjectComponent implements OnInit, OnDestroy export class FuseProjectDashboardComponent implements OnInit, OnDestroy
{ {
projects: any[]; projects: any[];
selectedProject: any; selectedProject: any;
@@ -28,13 +29,11 @@ export class FuseProjectComponent implements OnInit, OnDestroy
dateNow = Date.now(); dateNow = Date.now();
constructor(private projectsDashboardService: ProjectsDashboardService) constructor(private projectDashboardService: ProjectDashboardService)
{ {
this.projects = this.projectsDashboardService.projects; this.projects = this.projectDashboardService.projects;
this.selectedProject = this.projects[0]; this.selectedProject = this.projects[0];
this.widgets = this.projectDashboardService.widgets;
this.widgets = this.projectsDashboardService.widgets;
/** /**
* Widget 5 * Widget 5

View File

@@ -1,17 +1,18 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { FuseProjectComponent } from './project.component';
import { SharedModule } from '../../../../../core/modules/shared.module'; import { SharedModule } from '../../../../../core/modules/shared.module';
import { ProjectsDashboardService } from './projects.service';
import { FuseProjectDashboardComponent } from './project.component';
import { ProjectDashboardService } from './project.service';
import { FuseWidgetModule } from '../../../../../core/components/widget/widget.module'; import { FuseWidgetModule } from '../../../../../core/components/widget/widget.module';
import { NgxChartsModule } from '@swimlane/ngx-charts'; import { NgxChartsModule } from '@swimlane/ngx-charts';
const routes: Routes = [ const routes: Routes = [
{ {
path : '**', path : '**',
component: FuseProjectComponent, component: FuseProjectDashboardComponent,
resolve : { resolve : {
data: ProjectsDashboardService data: ProjectDashboardService
} }
} }
]; ];
@@ -24,10 +25,10 @@ const routes: Routes = [
NgxChartsModule NgxChartsModule
], ],
declarations: [ declarations: [
FuseProjectComponent FuseProjectDashboardComponent
], ],
providers : [ providers : [
ProjectsDashboardService ProjectDashboardService
] ]
}) })
export class FuseProjectDashboardModule export class FuseProjectDashboardModule

View File

@@ -4,7 +4,7 @@ import { Observable } from 'rxjs/Observable';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
@Injectable() @Injectable()
export class ProjectsDashboardService implements Resolve<any> export class ProjectDashboardService implements Resolve<any>
{ {
projects: any[]; projects: any[];
widgets: any[]; widgets: any[];
@@ -41,7 +41,7 @@ export class ProjectsDashboardService implements Resolve<any>
getProjects(): Promise<any> getProjects(): Promise<any>
{ {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.http.get('api/projects-dashboard-projects') this.http.get('api/project-dashboard-projects')
.subscribe((response: any) => { .subscribe((response: any) => {
this.projects = response; this.projects = response;
resolve(response); resolve(response);
@@ -52,7 +52,7 @@ export class ProjectsDashboardService implements Resolve<any>
getWidgets(): Promise<any> getWidgets(): Promise<any>
{ {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.http.get('api/projects-dashboard-widgets') this.http.get('api/project-dashboard-widgets')
.subscribe((response: any) => { .subscribe((response: any) => {
this.widgets = response; this.widgets = response;
resolve(response); resolve(response);

View File

@@ -41,7 +41,7 @@ export class EcommerceDashboardService implements Resolve<any>
getProjects(): Promise<any> getProjects(): Promise<any>
{ {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.http.get('api/projects-dashboard-projects') this.http.get('api/project-dashboard-projects')
.subscribe((response: any) => { .subscribe((response: any) => {
this.projects = response; this.projects = response;
resolve(response); resolve(response);

View File

@@ -4,8 +4,8 @@
position: relative; position: relative;
display: block; display: block;
width: 100%; width: 100%;
margin: 16px 0; margin: 16px 0 !important;
background-color: white; background-color: white !important;
color: #000; color: #000;
border-radius: 2px; border-radius: 2px;
transition: box-shadow 150ms ease; transition: box-shadow 150ms ease;

View File

@@ -4,7 +4,7 @@
width: 344px; width: 344px;
min-width: 344px; min-width: 344px;
max-width: 344px; max-width: 344px;
padding-right: 24px; padding-right: 24px !important;
height: 100%; height: 100%;
.list { .list {
@@ -36,6 +36,7 @@
position: relative; position: relative;
min-height: 32px; min-height: 32px;
padding: 0 16px; padding: 0 16px;
background: mat-color($mat-grey, 200) !important;
} }
} }

View File

@@ -5,6 +5,7 @@ import { Subscription } from 'rxjs/Subscription';
import { FormBuilder, FormGroup } from '@angular/forms'; import { FormBuilder, FormGroup } from '@angular/forms';
import { FuseUtils } from '../../../../../core/fuseUtils'; import { FuseUtils } from '../../../../../core/fuseUtils';
import { fuseAnimations } from '../../../../../core/animations'; import { fuseAnimations } from '../../../../../core/animations';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged'; import 'rxjs/add/operator/distinctUntilChanged';
@Component({ @Component({

View File

@@ -4,6 +4,7 @@ import { TodoService } from './todo.service';
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';
import { Todo } from './todo.model'; import { Todo } from './todo.model';
import { fuseAnimations } from '../../../../core/animations'; import { fuseAnimations } from '../../../../core/animations';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged'; import 'rxjs/add/operator/distinctUntilChanged';
@Component({ @Component({

View File

@@ -13,6 +13,7 @@
.card { .card {
display: flex; display: flex;
align-items: flex-start;
padding: 24px 24px 48px 24px; padding: 24px 24px 48px 24px;
margin-bottom: 96px; margin-bottom: 96px;

View File

@@ -56,7 +56,7 @@
// i18n/tr.ts // i18n/tr.ts
export const locale = { export const locale = {
lang: 'en', lang: 'tr',
data: { data: {
'MAIL': { 'MAIL': {
'COMPOSE': 'YENİ E-POSTA' 'COMPOSE': 'YENİ E-POSTA'

View File

@@ -3,6 +3,7 @@ import { FormControl } from '@angular/forms';
import { Subscription } from 'rxjs/Subscription'; import { Subscription } from 'rxjs/Subscription';
import { FaqService } from './faq.service'; import { FaqService } from './faq.service';
import { FuseUtils } from '../../../../core/fuseUtils'; import { FuseUtils } from '../../../../core/fuseUtils';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged'; import 'rxjs/add/operator/distinctUntilChanged';
@Component({ @Component({

View File

@@ -1,8 +1,8 @@
fuse-quick-panel { fuse-quick-panel {
display: flex; display: flex;
width: 330px; width: 280px;
min-width: 330px; min-width: 280px;
max-width: 330px; max-width: 280px;
z-index: 99; z-index: 99;
flex-direction: column; flex-direction: column;

View File

@@ -21,12 +21,18 @@ export class FuseNavigationModel implements FuseNavigationModelInterface
'type' : 'collapse', 'type' : 'collapse',
'icon' : 'dashboard', 'icon' : 'dashboard',
'children' : [ 'children' : [
{
'id' : 'analytics',
'title': 'Analytics',
'type' : 'item',
'url' : '/apps/dashboards/analytics'
},
{ {
'id' : 'project', 'id' : 'project',
'title': 'Project', 'title': 'Project',
'type' : 'item', 'type' : 'item',
'url' : '/apps/dashboards/project' 'url' : '/apps/dashboards/project'
} },
] ]
}, },
{ {