@@ -2679,6 +2679,11 @@ | |||
"integrity": "sha512-g38K9Cm5WRwlaH6g03B9OEz/0qRizI+2I7n+Gz+L5DxXJAPAiWQvwlYNm1V1jkdpUv95bOe/ASm2vfi/G560jQ==", | |||
"dev": true | |||
}, | |||
"claygl": { | |||
"version": "1.3.0", | |||
"resolved": "https://registry.npmjs.org/claygl/-/claygl-1.3.0.tgz", | |||
"integrity": "sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ==" | |||
}, | |||
"clean-stack": { | |||
"version": "2.2.0", | |||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", | |||
@@ -3419,6 +3424,31 @@ | |||
"domhandler": "^4.2.0" | |||
} | |||
}, | |||
"echarts": { | |||
"version": "5.3.0", | |||
"resolved": "https://registry.npmjs.org/echarts/-/echarts-5.3.0.tgz", | |||
"integrity": "sha512-zENufmwFE6WjM+24tW3xQq4ICqQtI0CGj4bDVDNd3BK3LtaA/5wBp+64ykIyKy3QElz0cieKqSYP4FX9Lv9MwQ==", | |||
"requires": { | |||
"tslib": "2.3.0", | |||
"zrender": "5.3.0" | |||
}, | |||
"dependencies": { | |||
"tslib": { | |||
"version": "2.3.0", | |||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", | |||
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" | |||
} | |||
} | |||
}, | |||
"echarts-gl": { | |||
"version": "2.0.8", | |||
"resolved": "https://registry.npmjs.org/echarts-gl/-/echarts-gl-2.0.8.tgz", | |||
"integrity": "sha512-ayFmjLxdF9pRpnh1Lz5aOgjnLqL3WIGu0t4Bt+oFwXGsViU2XcjCkHZARsZdv05lySow8eMD9JYZGXfLpuqYng==", | |||
"requires": { | |||
"claygl": "^1.2.1", | |||
"zrender": "^5.1.1" | |||
} | |||
}, | |||
"ee-first": { | |||
"version": "1.1.1", | |||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", | |||
@@ -5650,6 +5680,14 @@ | |||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", | |||
"dev": true | |||
}, | |||
"ngx-echarts": { | |||
"version": "8.0.1", | |||
"resolved": "https://registry.npmjs.org/ngx-echarts/-/ngx-echarts-8.0.1.tgz", | |||
"integrity": "sha512-CP+WnCcnMCNpCL9BVmDIZmhGSVPnkJhhFbQEKt0nrwV0L6d4QTAGZ+e4y6G1zTTFKkIMPHpaO0nhtDRgSXAW/w==", | |||
"requires": { | |||
"tslib": "^2.3.0" | |||
} | |||
}, | |||
"nice-napi": { | |||
"version": "1.0.2", | |||
"resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", | |||
@@ -8229,6 +8267,21 @@ | |||
"requires": { | |||
"tslib": "^2.0.0" | |||
} | |||
}, | |||
"zrender": { | |||
"version": "5.3.0", | |||
"resolved": "https://registry.npmjs.org/zrender/-/zrender-5.3.0.tgz", | |||
"integrity": "sha512-Ln2QB5uqI1ftNYMtCRxd+XDq6MOttLgam2tmhKAVA+j0ko47UT+VNlDvKTkqe4K2sJhBvB0EhYNLebqlCTjatQ==", | |||
"requires": { | |||
"tslib": "2.3.0" | |||
}, | |||
"dependencies": { | |||
"tslib": { | |||
"version": "2.3.0", | |||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", | |||
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -18,6 +18,9 @@ | |||
"@angular/platform-browser": "~13.1.0", | |||
"@angular/platform-browser-dynamic": "~13.1.0", | |||
"@angular/router": "~13.1.0", | |||
"echarts": "^5.3.0", | |||
"echarts-gl": "^2.0.8", | |||
"ngx-echarts": "^8.0.1", | |||
"rxjs": "~7.4.0", | |||
"tslib": "^2.3.0", | |||
"zone.js": "~0.11.4" | |||
@@ -1,7 +1,8 @@ | |||
import { NgModule } from '@angular/core'; | |||
import { BrowserModule } from '@angular/platform-browser'; | |||
import { NgxEchartsModule } from 'ngx-echarts'; | |||
import { AppRoutingModule } from './app-routing.module'; | |||
import { AppComponent } from './app.component'; | |||
import { LoginComponent } from './login/login.component'; | |||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; | |||
@@ -12,21 +13,24 @@ import { ReportComponent } from './dashboard/report/report.component'; | |||
import { SettingsComponent } from './dashboard/settings/settings.component'; | |||
@NgModule({ | |||
declarations: [ | |||
AppComponent, | |||
LoginComponent, | |||
DashboardComponent, | |||
GraphComponent, | |||
TableComponent, | |||
ReportComponent, | |||
SettingsComponent | |||
], | |||
imports: [ | |||
BrowserModule, | |||
AppRoutingModule, | |||
BrowserAnimationsModule | |||
], | |||
providers: [], | |||
bootstrap: [AppComponent] | |||
declarations: [ | |||
AppComponent, | |||
LoginComponent, | |||
DashboardComponent, | |||
GraphComponent, | |||
TableComponent, | |||
ReportComponent, | |||
SettingsComponent | |||
], | |||
imports: [ | |||
BrowserModule, | |||
AppRoutingModule, | |||
BrowserAnimationsModule, | |||
NgxEchartsModule.forRoot({ | |||
echarts: () => import('echarts'), | |||
}), | |||
], | |||
providers: [], | |||
bootstrap: [AppComponent] | |||
}) | |||
export class AppModule { } |
@@ -1,11 +1,27 @@ | |||
<div class="subpage"> | |||
<header> | |||
<header class="main-header"> | |||
<h2> Dashboard </h2> | |||
</header> | |||
<section class="analytics"> | |||
<div class="card"> | |||
<div class="line-chart"></div> | |||
<div echarts [options]="chartOption"></div> | |||
</div> | |||
<div class="card"> | |||
<div echarts [options]="chartOption1"></div> | |||
</div> | |||
<div class="card"> | |||
<div echarts [options]="options"></div> | |||
</div> | |||
<div class="card"> | |||
<div echarts [options]="chartOption4"></div> | |||
</div> | |||
<div class="card"> | |||
<div echarts [options]="chartOption5"></div> | |||
</div> | |||
</section> | |||
</div> |
@@ -0,0 +1,18 @@ | |||
.analytics { | |||
display: grid; | |||
grid-template-columns: 1fr 1fr 1fr; | |||
grid-gap: 20px; | |||
} | |||
.card { | |||
padding: 0; | |||
height: 300px; | |||
&:nth-child(3) { | |||
height: 450px; | |||
} | |||
&:nth-child(4), &:nth-child(5) { | |||
margin-top: -150px; | |||
} | |||
} |
@@ -1,15 +1,184 @@ | |||
import { Component, OnInit } from '@angular/core'; | |||
import { EChartsOption } from 'echarts'; | |||
@Component({ | |||
selector: 'app-graph', | |||
templateUrl: './graph.component.html', | |||
styleUrls: ['./graph.component.scss'] | |||
selector: 'app-graph', | |||
templateUrl: './graph.component.html', | |||
styleUrls: ['./graph.component.scss'] | |||
}) | |||
export class GraphComponent implements OnInit { | |||
primaryColor = window.getComputedStyle(document.documentElement).getPropertyValue('--primary'); | |||
secondaryColor = window.getComputedStyle(document.documentElement).getPropertyValue('--secondary'); | |||
constructor() { } | |||
chartOption: EChartsOption = { | |||
title: { | |||
text: 'Partners registered this week', | |||
left: 'center', | |||
top: 15, | |||
textStyle: { | |||
fontSize: 15, | |||
color: window.getComputedStyle(document.documentElement).getPropertyValue('--secondary-text'), | |||
}, | |||
}, | |||
height: 180, | |||
offset: 0, | |||
xAxis: { | |||
type: 'category', | |||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], | |||
}, | |||
yAxis: { | |||
type: 'value', | |||
}, | |||
series: [ | |||
{ | |||
data: [820, 932, 901, 934, 1290, 1330, 1320], | |||
type: 'line', | |||
color: this.primaryColor | |||
}, | |||
], | |||
}; | |||
ngOnInit(): void { | |||
} | |||
chartOption4: EChartsOption = { | |||
title: { | |||
text: 'Goals completed', | |||
left: 'center', | |||
top: 15, | |||
textStyle: { | |||
fontSize: 15, | |||
color: window.getComputedStyle(document.documentElement).getPropertyValue('--secondary-text'), | |||
}, | |||
}, | |||
height: 180, | |||
offset: 0, | |||
xAxis: { | |||
type: 'category', | |||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], | |||
}, | |||
yAxis: { | |||
type: 'value', | |||
}, | |||
series: [ | |||
{ | |||
data: [11, 200, 300, 50, 0, 60, 0], | |||
type: 'line', | |||
color: this.primaryColor | |||
}, | |||
], | |||
}; | |||
chartOption5: EChartsOption = { | |||
title: { | |||
text: 'Goals missed vs completed', | |||
left: 'center', | |||
top: 15, | |||
textStyle: { | |||
fontSize: 15, | |||
color: window.getComputedStyle(document.documentElement).getPropertyValue('--secondary-text'), | |||
}, | |||
}, | |||
height: 180, | |||
offset: 0, | |||
xAxis: { | |||
type: 'category', | |||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], | |||
}, | |||
yAxis: { | |||
type: 'value', | |||
}, | |||
series: [ | |||
{ | |||
data: [220, 0, 100, 20, 0, 290, 0], | |||
type: 'line', | |||
color: this.secondaryColor | |||
}, | |||
{ | |||
data: [11, 200, 300, 50, 0, 60, 0], | |||
type: 'line', | |||
color: this.primaryColor | |||
} | |||
], | |||
}; | |||
chartOption1: EChartsOption = { | |||
title: { | |||
text: 'Relative registeration count', | |||
left: 'center', | |||
top: 15, | |||
textStyle: { | |||
fontSize: 15, | |||
color: window.getComputedStyle(document.documentElement).getPropertyValue('--secondary-text'), | |||
}, | |||
}, | |||
height: 180, | |||
offset: 0, | |||
xAxis: { | |||
type: 'category', | |||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], | |||
}, | |||
yAxis: { | |||
type: 'value', | |||
}, | |||
series: [ | |||
{ | |||
data: [820, 932, 901, 934, 1290, 1330, 1320], | |||
type: 'bar', | |||
color: this.primaryColor | |||
}, | |||
{ | |||
data: [1320, 901, 934, 932, 1290, 1330, 820], | |||
type: 'bar', | |||
color: this.secondaryColor | |||
}, | |||
], | |||
animationEasing: 'elasticOut', | |||
animationDelayUpdate: (idx) => idx * 5, | |||
}; | |||
options: EChartsOption = { | |||
title: { | |||
text: 'Partners by category', | |||
left: 'center', | |||
top: 20, | |||
textStyle: { | |||
fontSize: 20, | |||
color: window.getComputedStyle(document.documentElement).getPropertyValue('--secondary-text'), | |||
}, | |||
}, | |||
height: 500, | |||
visualMap: { | |||
show: false, | |||
min: 80, | |||
max: 600, | |||
inRange: { | |||
colorLightness: [0, 1], | |||
}, | |||
}, | |||
series: [ | |||
{ | |||
name: 'Counters', | |||
type: 'pie', | |||
radius: '55%', | |||
center: ['50%', '50%'], | |||
color: this.primaryColor, | |||
data: [ | |||
{ value: 335, name: 'C-1' }, | |||
{ value: 310, name: 'C-2' }, | |||
{ value: 274, name: 'C-3' }, | |||
{ value: 235, name: 'C-4' }, | |||
{ value: 400, name: 'C-5' }, | |||
].sort((a, b) => a.value - b.value), | |||
roseType: 'radius', | |||
animationType: 'scale', | |||
animationEasing: 'elasticOut', | |||
animationDelay: () => Math.random() * 200, | |||
}, | |||
], | |||
}; | |||
constructor() { } | |||
ngOnInit(): void { | |||
} | |||
} |
@@ -102,4 +102,16 @@ | |||
.subpage { | |||
padding: 20px; | |||
height: 100vh; | |||
width: 100%; | |||
overflow: auto; | |||
.main-header { | |||
margin-bottom: 20px; | |||
h2 { | |||
color: var(--secondary-text); | |||
font-size: 30px; | |||
} | |||
} | |||
} |