mirror of
https://github.com/simon987/task_tracker.git
synced 2025-04-19 18:16:45 +00:00
Merge pull request #2 from simon987/master-cf-autofix
Apply fixes from CodeFactor
This commit is contained in:
commit
ad4e613d4a
@ -1,17 +1,17 @@
|
|||||||
import {Component, OnInit} from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import {ApiService} from "../api.service";
|
import {ApiService} from '../api.service';
|
||||||
import {Project} from "../models/project";
|
import {Project} from '../models/project';
|
||||||
import {ActivatedRoute} from "@angular/router";
|
import {ActivatedRoute} from '@angular/router';
|
||||||
|
|
||||||
import {Chart} from "chart.js";
|
import {Chart} from 'chart.js';
|
||||||
import {AssignedTasks, MonitoringSnapshot} from "../models/monitoring";
|
import {AssignedTasks, MonitoringSnapshot} from '../models/monitoring';
|
||||||
import {TranslateService} from "@ngx-translate/core";
|
import {TranslateService} from '@ngx-translate/core';
|
||||||
import {MessengerService} from "../messenger.service";
|
import {MessengerService} from '../messenger.service';
|
||||||
import {AuthService} from "../auth.service";
|
import {AuthService} from '../auth.service';
|
||||||
import {MatDialog} from "@angular/material";
|
import {MatDialog} from '@angular/material';
|
||||||
import {AreYouSureComponent} from "../are-you-sure/are-you-sure.component";
|
import {AreYouSureComponent} from '../are-you-sure/are-you-sure.component';
|
||||||
|
|
||||||
import * as moment from "moment"
|
import * as moment from 'moment';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -33,16 +33,16 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
|
|
||||||
|
|
||||||
private colors = {
|
private colors = {
|
||||||
new: "#76FF03",
|
new: '#76FF03',
|
||||||
failed: "#FF3D00",
|
failed: '#FF3D00',
|
||||||
closed: "#E0E0E0",
|
closed: '#E0E0E0',
|
||||||
awaiting: "#FFB74D",
|
awaiting: '#FFB74D',
|
||||||
random: [
|
random: [
|
||||||
"#3D5AFE", "#2979FF", "#2196F3",
|
'#3D5AFE', '#2979FF', '#2196F3',
|
||||||
"#7C4DFF", "#673AB7", "#7C4DFF",
|
'#7C4DFF', '#673AB7', '#7C4DFF',
|
||||||
"#FFC400", "#FFD740", "#FFC107",
|
'#FFC400', '#FFD740', '#FFC107',
|
||||||
"#FF3D00", "#FF6E40", "#FF5722",
|
'#FF3D00', '#FF6E40', '#FF5722',
|
||||||
"#76FF03", "#B2FF59", "#8BC34A"
|
'#76FF03', '#B2FF59', '#8BC34A'
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -60,14 +60,14 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.route.params.subscribe(params => {
|
this.route.params.subscribe(params => {
|
||||||
this.projectId = params["id"];
|
this.projectId = params['id'];
|
||||||
this.getProject();
|
this.getProject();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public isSafeUrl(url: string) {
|
public isSafeUrl(url: string) {
|
||||||
if (url.substr(0, "http".length) == "http") {
|
if (url.substr(0, 'http'.length) == 'http') {
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
this.averageTaskPerSecond();
|
this.averageTaskPerSecond();
|
||||||
this.calculateEta();
|
this.calculateEta();
|
||||||
this.lastSnapshot = this.snapshots ? this.snapshots.sort((a, b) => {
|
this.lastSnapshot = this.snapshots ? this.snapshots.sort((a, b) => {
|
||||||
return b.time_stamp - a.time_stamp
|
return b.time_stamp - a.time_stamp;
|
||||||
})[0] : null;
|
})[0] : null;
|
||||||
|
|
||||||
if (this.lastSnapshot == null || (this.lastSnapshot.awaiting_verification_count == 0 &&
|
if (this.lastSnapshot == null || (this.lastSnapshot.awaiting_verification_count == 0 &&
|
||||||
@ -87,7 +87,7 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
this.lastSnapshot.new_task_count == 0 &&
|
this.lastSnapshot.new_task_count == 0 &&
|
||||||
this.lastSnapshot.failed_task_count == 0)) {
|
this.lastSnapshot.failed_task_count == 0)) {
|
||||||
this.noTasks = true;
|
this.noTasks = true;
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
this.noTasks = false;
|
this.noTasks = false;
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
this.timeline.update();
|
this.timeline.update();
|
||||||
this.statusPie.data.datasets = [
|
this.statusPie.data.datasets = [
|
||||||
{
|
{
|
||||||
label: "Task status",
|
label: 'Task status',
|
||||||
data: [
|
data: [
|
||||||
this.lastSnapshot.new_task_count,
|
this.lastSnapshot.new_task_count,
|
||||||
this.lastSnapshot.failed_task_count,
|
this.lastSnapshot.failed_task_count,
|
||||||
@ -116,27 +116,27 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
this.apiService.getAssigneeStats(this.projectId)
|
this.apiService.getAssigneeStats(this.projectId)
|
||||||
.subscribe((data: any) => {
|
.subscribe((data: any) => {
|
||||||
this.assignees = data.content.assignees;
|
this.assignees = data.content.assignees;
|
||||||
let colors = this.assignees.map(() => {
|
const colors = this.assignees.map(() => {
|
||||||
return this.colors.random[Math.floor(Math.random() * this.colors.random.length)]
|
return this.colors.random[Math.floor(Math.random() * this.colors.random.length)];
|
||||||
});
|
});
|
||||||
this.assigneesPie.data.labels = this.assignees.map(x => x.assignee);
|
this.assigneesPie.data.labels = this.assignees.map(x => x.assignee);
|
||||||
this.assigneesPie.data.datasets = [
|
this.assigneesPie.data.datasets = [
|
||||||
{
|
{
|
||||||
label: "Task status",
|
label: 'Task status',
|
||||||
data: this.assignees.map(x => x.task_count),
|
data: this.assignees.map(x => x.task_count),
|
||||||
backgroundColor: colors,
|
backgroundColor: colors,
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
this.assigneesPie.update();
|
this.assigneesPie.update();
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private makeTimelineDataset(snapshots: MonitoringSnapshot[]) {
|
private makeTimelineDataset(snapshots: MonitoringSnapshot[]) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: "New",
|
label: 'New',
|
||||||
type: "line",
|
type: 'line',
|
||||||
fill: false,
|
fill: false,
|
||||||
borderColor: this.colors.new,
|
borderColor: this.colors.new,
|
||||||
backgroundColor: this.colors.new,
|
backgroundColor: this.colors.new,
|
||||||
@ -145,8 +145,8 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
lineTension: 0.2,
|
lineTension: 0.2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Failed",
|
label: 'Failed',
|
||||||
type: "line",
|
type: 'line',
|
||||||
fill: false,
|
fill: false,
|
||||||
borderColor: this.colors.failed,
|
borderColor: this.colors.failed,
|
||||||
backgroundColor: this.colors.failed,
|
backgroundColor: this.colors.failed,
|
||||||
@ -155,8 +155,8 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
lineTension: 0.2,
|
lineTension: 0.2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Closed",
|
label: 'Closed',
|
||||||
type: "line",
|
type: 'line',
|
||||||
fill: false,
|
fill: false,
|
||||||
borderColor: this.colors.closed,
|
borderColor: this.colors.closed,
|
||||||
backgroundColor: this.colors.closed,
|
backgroundColor: this.colors.closed,
|
||||||
@ -165,8 +165,8 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
lineTension: 0.2,
|
lineTension: 0.2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Awaiting verification",
|
label: 'Awaiting verification',
|
||||||
type: "line",
|
type: 'line',
|
||||||
fill: false,
|
fill: false,
|
||||||
borderColor: this.colors.awaiting,
|
borderColor: this.colors.awaiting,
|
||||||
backgroundColor: this.colors.awaiting,
|
backgroundColor: this.colors.awaiting,
|
||||||
@ -174,15 +174,15 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
pointRadius: 0,
|
pointRadius: 0,
|
||||||
lineTension: 0.2,
|
lineTension: 0.2,
|
||||||
},
|
},
|
||||||
]
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupTimeline() {
|
private setupTimeline() {
|
||||||
let elem = document.getElementById("timeline") as any;
|
const elem = document.getElementById('timeline') as any;
|
||||||
let ctx = elem.getContext("2d");
|
const ctx = elem.getContext('2d');
|
||||||
|
|
||||||
this.timeline = new Chart(ctx, {
|
this.timeline = new Chart(ctx, {
|
||||||
type: "bar",
|
type: 'bar',
|
||||||
data: {
|
data: {
|
||||||
labels: this.snapshots.map(s => s.time_stamp * 1000 as any),
|
labels: this.snapshots.map(s => s.time_stamp * 1000 as any),
|
||||||
datasets: this.makeTimelineDataset(this.snapshots),
|
datasets: this.makeTimelineDataset(this.snapshots),
|
||||||
@ -190,30 +190,30 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
options: {
|
options: {
|
||||||
title: {
|
title: {
|
||||||
display: true,
|
display: true,
|
||||||
text: "Task status timeline",
|
text: 'Task status timeline',
|
||||||
position: "bottom"
|
position: 'bottom'
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
position: 'left',
|
position: 'left',
|
||||||
},
|
},
|
||||||
scales: {
|
scales: {
|
||||||
xAxes: [{
|
xAxes: [{
|
||||||
type: "time",
|
type: 'time',
|
||||||
distribution: "series",
|
distribution: 'series',
|
||||||
ticks: {
|
ticks: {
|
||||||
source: "auto"
|
source: 'auto'
|
||||||
},
|
},
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
tooltips: {
|
tooltips: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
intersect: false,
|
intersect: false,
|
||||||
mode: "index",
|
mode: 'index',
|
||||||
position: "nearest",
|
position: 'nearest',
|
||||||
},
|
},
|
||||||
responsive: true
|
responsive: true
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupStatusPie() {
|
private setupStatusPie() {
|
||||||
@ -227,24 +227,24 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
this.lastSnapshot = {
|
this.lastSnapshot = {
|
||||||
closed_task_count: 0, time_stamp: 0, failed_task_count: 0,
|
closed_task_count: 0, time_stamp: 0, failed_task_count: 0,
|
||||||
new_task_count: 0, awaiting_verification_count: 0
|
new_task_count: 0, awaiting_verification_count: 0
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let elem = document.getElementById("status-pie") as any;
|
const elem = document.getElementById('status-pie') as any;
|
||||||
let ctx = elem.getContext("2d");
|
const ctx = elem.getContext('2d');
|
||||||
|
|
||||||
this.statusPie = new Chart(ctx, {
|
this.statusPie = new Chart(ctx, {
|
||||||
type: "doughnut",
|
type: 'doughnut',
|
||||||
data: {
|
data: {
|
||||||
labels: [
|
labels: [
|
||||||
"New",
|
'New',
|
||||||
"Failed",
|
'Failed',
|
||||||
"Closed",
|
'Closed',
|
||||||
"Awaiting verification",
|
'Awaiting verification',
|
||||||
],
|
],
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
label: "Task status",
|
label: 'Task status',
|
||||||
data: [
|
data: [
|
||||||
this.lastSnapshot.new_task_count,
|
this.lastSnapshot.new_task_count,
|
||||||
this.lastSnapshot.failed_task_count,
|
this.lastSnapshot.failed_task_count,
|
||||||
@ -267,8 +267,8 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
display: true,
|
display: true,
|
||||||
text: "Current task status",
|
text: 'Current task status',
|
||||||
position: "bottom"
|
position: 'bottom'
|
||||||
|
|
||||||
},
|
},
|
||||||
animation: {
|
animation: {
|
||||||
@ -281,20 +281,20 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
|
|
||||||
private setupAssigneesPie() {
|
private setupAssigneesPie() {
|
||||||
|
|
||||||
let elem = document.getElementById("assignees-pie") as any;
|
const elem = document.getElementById('assignees-pie') as any;
|
||||||
let ctx = elem.getContext("2d");
|
const ctx = elem.getContext('2d');
|
||||||
|
|
||||||
let colors = this.assignees.map(() => {
|
const colors = this.assignees.map(() => {
|
||||||
return this.colors.random[Math.floor(Math.random() * this.colors.random.length)]
|
return this.colors.random[Math.floor(Math.random() * this.colors.random.length)];
|
||||||
});
|
});
|
||||||
|
|
||||||
this.assigneesPie = new Chart(ctx, {
|
this.assigneesPie = new Chart(ctx, {
|
||||||
type: "doughnut",
|
type: 'doughnut',
|
||||||
data: {
|
data: {
|
||||||
labels: this.assignees.map(x => x.assignee),
|
labels: this.assignees.map(x => x.assignee),
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
label: "Task status",
|
label: 'Task status',
|
||||||
data: this.assignees.map(x => x.task_count),
|
data: this.assignees.map(x => x.task_count),
|
||||||
backgroundColor: colors,
|
backgroundColor: colors,
|
||||||
}
|
}
|
||||||
@ -307,8 +307,8 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
display: true,
|
display: true,
|
||||||
text: "Task assignment",
|
text: 'Task assignment',
|
||||||
position: "bottom"
|
position: 'bottom'
|
||||||
|
|
||||||
},
|
},
|
||||||
animation: {
|
animation: {
|
||||||
@ -327,14 +327,14 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
.subscribe((data: any) => {
|
.subscribe((data: any) => {
|
||||||
this.snapshots = data.content.snapshots;
|
this.snapshots = data.content.snapshots;
|
||||||
this.lastSnapshot = this.snapshots ? this.snapshots.sort((a, b) => {
|
this.lastSnapshot = this.snapshots ? this.snapshots.sort((a, b) => {
|
||||||
return b.time_stamp - a.time_stamp
|
return b.time_stamp - a.time_stamp;
|
||||||
})[0] : null;
|
})[0] : null;
|
||||||
|
|
||||||
this.setupTimeline();
|
this.setupTimeline();
|
||||||
this.setupStatusPie();
|
this.setupStatusPie();
|
||||||
|
|
||||||
if (!this.snapshots) {
|
if (!this.snapshots) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.apiService.getAssigneeStats(this.projectId)
|
this.apiService.getAssigneeStats(this.projectId)
|
||||||
@ -345,12 +345,12 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
|
|
||||||
this.averageTaskPerSecond();
|
this.averageTaskPerSecond();
|
||||||
this.calculateEta();
|
this.calculateEta();
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
this.translate.get("messenger.unauthorized").subscribe(t =>
|
this.translate.get('messenger.unauthorized').subscribe(t =>
|
||||||
this.messenger.show(t))
|
this.messenger.show(t));
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
resetFailedTasks() {
|
resetFailedTasks() {
|
||||||
@ -360,52 +360,53 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
if (result) {
|
if (result) {
|
||||||
this.apiService.resetFailedTasks(this.projectId).subscribe(
|
this.apiService.resetFailedTasks(this.projectId).subscribe(
|
||||||
data => {
|
data => {
|
||||||
this.translate.get("project.reset_response").subscribe(t =>
|
this.translate.get('project.reset_response').subscribe(t =>
|
||||||
this.messenger.show(t + data["content"]["affected_tasks"]))
|
this.messenger.show(t + data['content']['affected_tasks']));
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
this.translate.get("messenger.unauthorized").subscribe(t =>
|
this.translate.get('messenger.unauthorized').subscribe(t =>
|
||||||
this.messenger.show(t))
|
this.messenger.show(t));
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pauseProject() {
|
pauseProject() {
|
||||||
this.setPaused(true)
|
this.setPaused(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
resumeProject() {
|
resumeProject() {
|
||||||
this.setPaused(false)
|
this.setPaused(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private averageTaskPerSecond() {
|
private averageTaskPerSecond() {
|
||||||
|
|
||||||
const averageDelta = ([x, ...xs]) => {
|
const averageDelta = ([x, ...xs]) => {
|
||||||
if (x === undefined)
|
if (x === undefined) {
|
||||||
return NaN;
|
return NaN;
|
||||||
else
|
} else {
|
||||||
return xs.reduce(
|
return xs.reduce(
|
||||||
([acc, last], x) => [acc + (x - last), x],
|
([acc, last], x) => [acc + (x - last), x],
|
||||||
[0, x]
|
[0, x]
|
||||||
) [0] / xs.length
|
) [0] / xs.length;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let interval = this.snapshots.length > 1 ? this.snapshots[0].time_stamp - this.snapshots[1].time_stamp : 0;
|
const interval = this.snapshots.length > 1 ? this.snapshots[0].time_stamp - this.snapshots[1].time_stamp : 0;
|
||||||
|
|
||||||
if (interval != 0) {
|
if (interval != 0) {
|
||||||
this.avgTask = averageDelta(this.snapshots.reverse().map(s => s.closed_task_count) as any) / interval;
|
this.avgTask = averageDelta(this.snapshots.reverse().map(s => s.closed_task_count) as any) / interval;
|
||||||
} else {
|
} else {
|
||||||
return 0
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private calculateEta() {
|
private calculateEta() {
|
||||||
if (this.snapshots.length > 0) {
|
if (this.snapshots.length > 0) {
|
||||||
this.eta = moment.utc(this.snapshots[0].new_task_count / this.avgTask * 1000).format("D[d] HH[h]mm[m]ss[s]")
|
this.eta = moment.utc(this.snapshots[0].new_task_count / this.avgTask * 1000).format('D[d] HH[h]mm[m]ss[s]');
|
||||||
} else {
|
} else {
|
||||||
this.eta = "N/A"
|
this.eta = 'N/A';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,12 +416,12 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
}).afterClosed().subscribe(result => {
|
}).afterClosed().subscribe(result => {
|
||||||
this.project.paused = paused;
|
this.project.paused = paused;
|
||||||
this.apiService.updateProject(this.project).subscribe(() => {
|
this.apiService.updateProject(this.project).subscribe(() => {
|
||||||
this.translate.get("messenger.acknowledged").subscribe(t =>
|
this.translate.get('messenger.acknowledged').subscribe(t =>
|
||||||
this.messenger.show(t))
|
this.messenger.show(t));
|
||||||
}, error => {
|
}, error => {
|
||||||
this.translate.get("messenger.unauthorized").subscribe(t =>
|
this.translate.get('messenger.unauthorized').subscribe(t =>
|
||||||
this.messenger.show(t))
|
this.messenger.show(t));
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user