@@ -2679,6 +2679,11 @@ | |||||
"integrity": "sha512-g38K9Cm5WRwlaH6g03B9OEz/0qRizI+2I7n+Gz+L5DxXJAPAiWQvwlYNm1V1jkdpUv95bOe/ASm2vfi/G560jQ==", | "integrity": "sha512-g38K9Cm5WRwlaH6g03B9OEz/0qRizI+2I7n+Gz+L5DxXJAPAiWQvwlYNm1V1jkdpUv95bOe/ASm2vfi/G560jQ==", | ||||
"dev": true | "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": { | "clean-stack": { | ||||
"version": "2.2.0", | "version": "2.2.0", | ||||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", | "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", | ||||
@@ -3419,6 +3424,31 @@ | |||||
"domhandler": "^4.2.0" | "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": { | "ee-first": { | ||||
"version": "1.1.1", | "version": "1.1.1", | ||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", | ||||
@@ -5650,6 +5680,14 @@ | |||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", | "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", | ||||
"dev": true | "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": { | "nice-napi": { | ||||
"version": "1.0.2", | "version": "1.0.2", | ||||
"resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", | "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", | ||||
@@ -8229,6 +8267,21 @@ | |||||
"requires": { | "requires": { | ||||
"tslib": "^2.0.0" | "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": "~13.1.0", | ||||
"@angular/platform-browser-dynamic": "~13.1.0", | "@angular/platform-browser-dynamic": "~13.1.0", | ||||
"@angular/router": "~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", | "rxjs": "~7.4.0", | ||||
"tslib": "^2.3.0", | "tslib": "^2.3.0", | ||||
"zone.js": "~0.11.4" | "zone.js": "~0.11.4" | ||||
@@ -1,7 +1,8 @@ | |||||
import { NgModule } from '@angular/core'; | import { NgModule } from '@angular/core'; | ||||
import { BrowserModule } from '@angular/platform-browser'; | import { BrowserModule } from '@angular/platform-browser'; | ||||
import { NgxEchartsModule } from 'ngx-echarts'; | |||||
import { AppRoutingModule } from './app-routing.module'; | import { AppRoutingModule } from './app-routing.module'; | ||||
import { AppComponent } from './app.component'; | import { AppComponent } from './app.component'; | ||||
import { LoginComponent } from './login/login.component'; | import { LoginComponent } from './login/login.component'; | ||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; | 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'; | import { SettingsComponent } from './dashboard/settings/settings.component'; | ||||
@NgModule({ | @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 { } | export class AppModule { } |
@@ -1,11 +1,27 @@ | |||||
<div class="subpage"> | <div class="subpage"> | ||||
<header> | |||||
<header class="main-header"> | |||||
<h2> Dashboard </h2> | <h2> Dashboard </h2> | ||||
</header> | </header> | ||||
<section class="analytics"> | <section class="analytics"> | ||||
<div class="card"> | <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> | </div> | ||||
</section> | </section> | ||||
</div> | </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 { Component, OnInit } from '@angular/core'; | ||||
import { EChartsOption } from 'echarts'; | |||||
@Component({ | @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 { | 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 { | .subpage { | ||||
padding: 20px; | padding: 20px; | ||||
height: 100vh; | |||||
width: 100%; | |||||
overflow: auto; | |||||
.main-header { | |||||
margin-bottom: 20px; | |||||
h2 { | |||||
color: var(--secondary-text); | |||||
font-size: 30px; | |||||
} | |||||
} | |||||
} | } |