1 /* Copyright (c) 2019 AT&T Intellectual Property. #
\r
3 # Licensed under the Apache License, Version 2.0 (the "License"); #
\r
4 # you may not use this file except in compliance with the License. #
\r
5 # You may obtain a copy of the License at #
\r
7 # http://www.apache.org/licenses/LICENSE-2.0 #
\r
9 # Unless required by applicable law or agreed to in writing, software #
\r
10 # distributed under the License is distributed on an "AS IS" BASIS, #
\r
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
\r
12 # See the License for the specific language governing permissions and #
\r
13 # limitations under the License. #
\r
14 ##############################################################################*/
\r
17 import { Component, OnInit, ViewChild, ElementRef, Input, OnDestroy } from '@angular/core';
\r
18 import * as moment from 'moment';
\r
19 import { Subscription } from 'rxjs';
\r
20 import { StatsService } from '../stats.service';
\r
21 import { Router } from '@angular/router';
\r
22 import * as am4core from "@amcharts/amcharts4/core";
\r
23 import * as am4charts from "@amcharts/amcharts4/charts";
\r
25 selector: 'app-test-head-execution-bar-chart',
\r
26 templateUrl: './test-head-execution-bar-chart.component.pug',
\r
27 styleUrls: ['./test-head-execution-bar-chart.component.scss']
\r
29 export class TestHeadExecutionBarChartComponent implements OnInit, OnDestroy {
\r
31 private toDestroy: Array<Subscription> = [];
\r
33 @ViewChild('chart') chartElement: ElementRef;
\r
34 @Input() height: string;
\r
36 public chart: am4charts.XYChart;
\r
37 public testInstanceData;
\r
38 public loadingIndicator;
\r
40 constructor(private stats: StatsService, private router: Router) {}
\r
47 this.toDestroy.push(this.stats.onDefaultDataCallStarted().subscribe(res => {
\r
48 this.showLoadingIndicator();
\r
51 this.toDestroy.push(this.stats.onTIExecutionChangeStarted().subscribe(res => {
\r
52 this.showLoadingIndicator();
\r
55 this.toDestroy.push(this.stats.onDefaultDataCallFinished().subscribe(res => {
\r
56 this.setChartData();
\r
59 this.toDestroy.push(this.stats.onTIExecutionChangeFinished().subscribe(res => {
\r
66 this.toDestroy.forEach(e => e.unsubscribe());
\r
67 this.chart.dispose();
\r
70 showLoadingIndicator() {
\r
71 if(!this.loadingIndicator){
\r
72 this.loadingIndicator = this.chart.tooltipContainer.createChild(am4core.Container);
\r
73 this.loadingIndicator.background.fill = am4core.color("#fff");
\r
74 this.loadingIndicator.background.fillOpacity = 0.8;
\r
75 this.loadingIndicator.width = am4core.percent(100);
\r
76 this.loadingIndicator.height = am4core.percent(100);
\r
78 let indicatorLabel = this.loadingIndicator.createChild(am4core.Label);
\r
79 indicatorLabel.text = "Loading..";
\r
80 indicatorLabel.align = "center";
\r
81 indicatorLabel.valign = "middle";
\r
82 indicatorLabel.fontSize = 18;
\r
83 indicatorLabel.fontWeight= "bold";
\r
84 indicatorLabel.dy = 50;
\r
86 let loadingImage = this.loadingIndicator.createChild(am4core.Image);
\r
87 //loadingImage.href = "https://img.devrant.com/devrant/rant/r_647810_4FeCH.gif";
\r
88 loadingImage.href = "/assets/images/equalizer.gif";
\r
89 //loadingImage.dataSource = "/loading-pies.svg"
\r
90 loadingImage.align = "center";
\r
91 loadingImage.valign = "middle";
\r
92 loadingImage.horizontalCenter = "middle";
\r
93 loadingImage.verticalCenter = "middle";
\r
94 loadingImage.scale = 3.0;
\r
96 this.loadingIndicator.show();
\r
101 hideLoadingIndicator() {
\r
102 this.loadingIndicator.hide();
\r
105 incrementStatus(data, code){
\r
107 if(code >= 200 && code < 300){
\r
109 }else if(code >= 300 && code < 400){
\r
111 }else if(code >= 400 && code < 500){
\r
113 }else if(code >= 500 && code < 600){
\r
124 this.stats.executionList.forEach((execution, i) => {
\r
125 execution.testHeadResults.forEach((result, val) => {
\r
126 let index = data.findIndex(e => e.id === result.testHeadId);
\r
127 let executionTime = moment(result.endTime).diff(moment(result.startTime), 'seconds');
\r
130 id: result.testHeadId,
\r
131 name: result.testHeadName,
\r
132 executionTime: executionTime,
\r
134 average: executionTime,
\r
141 this.incrementStatus(toPush, result.statusCode);
\r
144 this.incrementStatus(data[index], result.statusCode);
\r
145 data[index].count += 1;
\r
146 data[index].executionTime += executionTime;
\r
147 data[index].average = (data[index].executionTime / data[index].count);
\r
151 data.sort((a, b) => b.count - a.count);
\r
152 this.chart.data = data;
\r
154 // Displays the average time for each bar.
\r
155 // If there is no time recorded for the Test Instance, display No Time Recorded.
\r
156 let series = this.chart.series.values as Array<am4charts.ColumnSeries>;
\r
158 // series.columns.template.adapter.add("tooltipText", (text, target) => {
\r
159 // if (target.dataItem) {
\r
160 // if (this.chart.data[target.dataItem.index].average > 0) {
\r
161 // return this.chart.data[target.dataItem.index].count.toString() + " Executions \n Avg Time: " + this.chart.data[target.dataItem.index].average.toFixed(2).toString() + " seconds";
\r
163 // return this.chart.data[target.dataItem.index].count.toString() + " Executions \n No Time Recorded";
\r
167 series.forEach(elem => {
\r
168 // elem.columns.template.adapter.add("fill", (fill, target) => this.chart.colors.getIndex(target.dataItem.index));
\r
171 elem.columns.template.events.on("doublehit", (click) => {
\r
172 this.router.navigate(['/test-heads', click.target.dataItem.dataContext['id']]);
\r
176 this.chart.appear();
\r
177 this.hideLoadingIndicator();
\r
181 this.chart = am4core.create(this.chartElement.nativeElement, am4charts.XYChart);
\r
183 this.showLoadingIndicator();
\r
185 this.chart.responsive.enabled = true;
\r
188 var categoryAxis = this.chart.yAxes.push(new am4charts.CategoryAxis());
\r
189 categoryAxis.dataFields.category = "name";
\r
190 categoryAxis.numberFormatter.numberFormat = "#";
\r
191 categoryAxis.renderer.inversed = true;
\r
192 categoryAxis.renderer.minGridDistance = 5;
\r
193 categoryAxis.title.fontSize = "10px";
\r
195 var valueAxis = this.chart.xAxes.push(new am4charts.ValueAxis());
\r
196 valueAxis.renderer.minWidth = 10;
\r
198 this.createSeries("200", "200s")
\r
199 this.createSeries("300", "300s")
\r
200 this.createSeries("400", "400s")
\r
201 this.createSeries("500", "500s")
\r
202 this.createSeries("other", "Other")
\r
204 this.chart.legend = new am4charts.Legend();
\r
205 this.chart.legend.scale = .7;
\r
206 this.chart.legend.width = am4core.percent(150);
\r
208 let label = categoryAxis.renderer.labels.template;
\r
209 label.truncate = true;
\r
210 label.maxWidth = 130;
\r
211 label.fontSize = 13;
\r
213 //Scrollbar on the right.
\r
214 let scrollBarY = new am4charts.XYChartScrollbar();
\r
215 //scrollBarY.series.push(series);
\r
216 this.chart.scrollbarY = scrollBarY;
\r
217 this.chart.scrollbarY.contentHeight = 100;
\r
218 this.chart.scrollbarY.minWidth = 20;
\r
219 this.chart.scrollbarY.thumb.minWidth = 20;
\r
221 //set initial Scrollbar Zoom to the Top 6 Instances.
\r
222 this.chart.events.on("appeared", () => {
\r
223 categoryAxis.zoomToIndexes(0, 6, false, true);
\r
227 createSeries(field, name){
\r
229 var series = this.chart.series.push(new am4charts.ColumnSeries());
\r
230 series.dataFields.valueX = field;
\r
231 series.dataFields.categoryY = "name";
\r
232 series.stacked = true;
\r
233 series.name = name;
\r