mirror of
https://github.com/simon987/task_tracker.git
synced 2025-04-20 10:36:46 +00:00
project dashboard basic setup
This commit is contained in:
parent
920647b4aa
commit
be8dce10ea
6
web/angular/package-lock.json
generated
6
web/angular/package-lock.json
generated
@ -838,6 +838,12 @@
|
||||
"semver-intersect": "1.4.0"
|
||||
}
|
||||
},
|
||||
"@types/chart.js": {
|
||||
"version": "2.7.42",
|
||||
"resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.7.42.tgz",
|
||||
"integrity": "sha512-+0v+PV2J9wsV7u36Vqt5Oke7ugtiZqNeYJgNk5mgNMkEkqtjxo2Q9N5Q9znHlgmXeOTfQL6e1sfcAbTnPHAzlA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/jasmine": {
|
||||
"version": "2.8.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.15.tgz",
|
||||
|
@ -36,6 +36,7 @@
|
||||
"@angular/cli": "~7.2.2",
|
||||
"@angular/compiler-cli": "~7.2.0",
|
||||
"@angular/language-service": "~7.2.0",
|
||||
"@types/chart.js": "^2.7.42",
|
||||
"@types/jasmine": "~2.8.8",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"@types/node": "~8.9.4",
|
||||
|
@ -1,44 +1,14 @@
|
||||
#status {
|
||||
height: 360px;
|
||||
position: relative;
|
||||
width: 360px;
|
||||
margin: 1em;
|
||||
#timeline-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#assignees {
|
||||
height: 360px;
|
||||
position: relative;
|
||||
width: 360px;
|
||||
margin: 1em;
|
||||
#status-pie-wrapper {
|
||||
height: 50%;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.pie-label {
|
||||
left: 130px;
|
||||
padding: 10px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
top: 150px;
|
||||
width: 80px;
|
||||
z-index: 10;
|
||||
font-family: Roboto, "Helvetica Neue", sans-serif;
|
||||
font-weight: bold;
|
||||
#assignees-pie-wrapper {
|
||||
margin-top: 1em;
|
||||
height: 50%;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
background: #eee;
|
||||
box-shadow: 0 0 5px #999999;
|
||||
color: #333;
|
||||
display: none;
|
||||
font-size: 12px;
|
||||
left: 130px;
|
||||
padding: 10px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
top: 95px;
|
||||
width: 80px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/*---------*/
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<mat-card class="mat-elevation-z8">
|
||||
<mat-card-title *ngIf="project">{{"dashboard.title" | translate}} "{{project.name}}"</mat-card-title>
|
||||
<mat-card-content style="padding: 2em 0 1em">
|
||||
|
||||
@ -11,10 +11,18 @@
|
||||
<pre *ngIf="project">{{project.motd}}</pre>
|
||||
|
||||
<div style="display: flex; align-items: center; justify-content: center">
|
||||
<div id="timeline"></div>
|
||||
<div id="timeline-wrapper">
|
||||
<canvas id="timeline"></canvas>
|
||||
</div>
|
||||
|
||||
<div id="status-pie"></div>
|
||||
<div id="assignees-pie"></div>
|
||||
<div>
|
||||
<div id="status-pie-wrapper">
|
||||
<canvas id="status-pie"></canvas>
|
||||
</div>
|
||||
<div id="assignees-pie-wrapper">
|
||||
<canvas id="assignees-pie"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-expansion-panel *ngIf="project" style="margin-top: 1em">
|
||||
@ -26,7 +34,7 @@
|
||||
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button mat-raised-button color="primary"
|
||||
<button mat-raised-button color="primary" *ngIf="project"
|
||||
[routerLink]="'/project/' + project.id + '/update'">{{"project.update" | translate}}</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
|
@ -3,6 +3,8 @@ import {ApiService} from "../api.service";
|
||||
import {Project} from "../models/project";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
|
||||
import {Chart, ChartData, Point} from "chart.js";
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-project-dashboard',
|
||||
@ -13,7 +15,22 @@ export class ProjectDashboardComponent implements OnInit {
|
||||
|
||||
private projectId;
|
||||
project: Project;
|
||||
private timeline: Chart;
|
||||
private statusPie: Chart;
|
||||
private assigneesPir: Chart;
|
||||
|
||||
private colors = {
|
||||
new: "#76FF03",
|
||||
failed: "#FF3D00",
|
||||
closed: "#E0E0E0",
|
||||
awaiting: "#FFB74D"
|
||||
};
|
||||
|
||||
tmpLabels = [];
|
||||
tmpNew = [];
|
||||
tmpFailed = [];
|
||||
tmpClosed = [];
|
||||
tmpAwaiting = [];
|
||||
|
||||
constructor(private apiService: ApiService, private route: ActivatedRoute) {
|
||||
}
|
||||
@ -23,9 +40,208 @@ export class ProjectDashboardComponent implements OnInit {
|
||||
this.route.params.subscribe(params => {
|
||||
this.projectId = params["id"];
|
||||
this.getProject();
|
||||
});
|
||||
|
||||
|
||||
let n = 40;
|
||||
for (let i = 0; i < n; i++) {
|
||||
this.tmpLabels.push((1549501926 + 600 * i) * 1000);
|
||||
this.tmpNew.push(Math.ceil(Math.random() * 30))
|
||||
this.tmpClosed.push(Math.ceil(Math.random() * 100))
|
||||
this.tmpFailed.push(Math.ceil(Math.random() * 13))
|
||||
this.tmpAwaiting.push(Math.ceil(Math.random() * 40))
|
||||
}
|
||||
|
||||
this.setupTimeline();
|
||||
this.setupStatusPie();
|
||||
this.setupAssigneesPie();
|
||||
}
|
||||
|
||||
private setupTimeline() {
|
||||
let elem = document.getElementById("timeline") as any;
|
||||
let ctx = elem.getContext("2d");
|
||||
|
||||
this.timeline = new Chart(ctx, {
|
||||
type: "bar",
|
||||
data: {
|
||||
labels: this.tmpLabels,
|
||||
datasets: [
|
||||
{
|
||||
label: "New",
|
||||
type: "line",
|
||||
fill: false,
|
||||
borderColor: this.colors.new,
|
||||
backgroundColor: this.colors.new,
|
||||
data: this.tmpNew,
|
||||
pointRadius: 0,
|
||||
lineTension: 0.2,
|
||||
},
|
||||
{
|
||||
label: "Failed",
|
||||
type: "line",
|
||||
fill: false,
|
||||
borderColor: this.colors.failed,
|
||||
backgroundColor: this.colors.failed,
|
||||
data: this.tmpFailed,
|
||||
pointRadius: 0,
|
||||
lineTension: 0.2,
|
||||
},
|
||||
{
|
||||
label: "Closed",
|
||||
type: "line",
|
||||
fill: false,
|
||||
borderColor: this.colors.closed,
|
||||
backgroundColor: this.colors.closed,
|
||||
pointRadius: 0,
|
||||
data: this.tmpClosed,
|
||||
lineTension: 0.2,
|
||||
},
|
||||
{
|
||||
label: "Awaiting verification",
|
||||
type: "line",
|
||||
fill: false,
|
||||
borderColor: this.colors.awaiting,
|
||||
backgroundColor: this.colors.awaiting,
|
||||
data: this.tmpAwaiting,
|
||||
pointRadius: 0,
|
||||
lineTension: 0.2,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
title: {
|
||||
display: true,
|
||||
text: "Task status timeline",
|
||||
position: "bottom"
|
||||
},
|
||||
legend: {
|
||||
position: 'left',
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "time",
|
||||
distribution: "series",
|
||||
ticks: {
|
||||
source: "auto"
|
||||
},
|
||||
time: {
|
||||
unit: "minute",
|
||||
unitStepSize: 10,
|
||||
}
|
||||
}]
|
||||
},
|
||||
tooltips: {
|
||||
enabled: true,
|
||||
intersect: false,
|
||||
mode: "index",
|
||||
position: "nearest",
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private setupStatusPie() {
|
||||
|
||||
let elem = document.getElementById("status-pie") as any;
|
||||
let ctx = elem.getContext("2d");
|
||||
|
||||
this.statusPie = new Chart(ctx, {
|
||||
type: "doughnut",
|
||||
data: {
|
||||
labels: [
|
||||
"New",
|
||||
"Failed",
|
||||
"Closed",
|
||||
"Awaiting verification",
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
label: "Task status",
|
||||
data: [
|
||||
10,
|
||||
24,
|
||||
301,
|
||||
90,
|
||||
],
|
||||
backgroundColor: [
|
||||
this.colors.new,
|
||||
this.colors.failed,
|
||||
this.colors.closed,
|
||||
this.colors.awaiting
|
||||
],
|
||||
}
|
||||
],
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'left',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: "Current task status",
|
||||
position: "bottom"
|
||||
|
||||
},
|
||||
animation: {
|
||||
animateScale: true,
|
||||
animateRotate: true
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private setupAssigneesPie() {
|
||||
|
||||
let elem = document.getElementById("assignees-pie") as any;
|
||||
let ctx = elem.getContext("2d");
|
||||
|
||||
this.statusPie = new Chart(ctx, {
|
||||
type: "doughnut",
|
||||
data: {
|
||||
labels: [
|
||||
"marc",
|
||||
"simon",
|
||||
"bernie",
|
||||
"natasha",
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
label: "Task status",
|
||||
data: [
|
||||
10,
|
||||
24,
|
||||
1,
|
||||
23,
|
||||
],
|
||||
backgroundColor: [
|
||||
this.colors.new,
|
||||
this.colors.failed,
|
||||
this.colors.closed,
|
||||
this.colors.awaiting
|
||||
],
|
||||
}
|
||||
],
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'left',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: "Task assignment",
|
||||
position: "bottom"
|
||||
|
||||
},
|
||||
animation: {
|
||||
animateScale: true,
|
||||
animateRotate: true
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getProject() {
|
||||
this.apiService.getProject(this.projectId).subscribe(data => {
|
||||
this.project = <Project>{
|
||||
|
Loading…
x
Reference in New Issue
Block a user