added svcapi ui and camunda code
[it/otf.git] / otf-frontend / client / src / app / layout / components / stats / test-definition-executions-bar-chart / test-definition-executions-bar-chart.component.ts
1 /*  Copyright (c) 2019 AT&T Intellectual Property.                             #\r
2 #                                                                              #\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
6 #                                                                              #\r
7 #       http://www.apache.org/licenses/LICENSE-2.0                             #\r
8 #                                                                              #\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
15 \r
16 \r
17 import { Component, OnInit, ViewChild, ElementRef, Input, OnDestroy } from '@angular/core';\r
18 import { StatsService } from '../stats.service';\r
19 import * as am4core from "@amcharts/amcharts4/core";\r
20 import * as am4charts from "@amcharts/amcharts4/charts";\r
21 import { e } from '@angular/core/src/render3';\r
22 import * as moment from 'moment';\r
23 import { Router } from '@angular/router';\r
24 import { Subscription } from 'rxjs';\r
25 \r
26 @Component({\r
27   selector: 'app-test-definition-executions-bar-chart',\r
28   templateUrl: './test-definition-executions-bar-chart.component.pug',\r
29   styleUrls: ['./test-definition-executions-bar-chart.component.scss']\r
30 })\r
31 export class TestDefinitionExecutionsBarChartComponent implements OnInit, OnDestroy {\r
32 \r
33   private toDestroy: Array<Subscription> = [];\r
34 \r
35   @ViewChild('chart') chartElement: ElementRef;\r
36   @Input() height: string;\r
37 \r
38   public chart: am4charts.XYChart;\r
39   public testInstanceData;\r
40   public loadingIndicator;\r
41 \r
42   constructor(private stats: StatsService, private router: Router) {}\r
43 \r
44 \r
45   ngOnInit() {\r
46     this.renderChart();\r
47 \r
48     this.toDestroy.push(this.stats.onDefaultDataCallStarted().subscribe(res => {\r
49       this.showLoadingIndicator();\r
50     }));\r
51 \r
52     this.toDestroy.push(this.stats.onTIExecutionChangeStarted().subscribe(res => {\r
53       this.showLoadingIndicator();\r
54     }));\r
55 \r
56     this.toDestroy.push(this.stats.onDefaultDataCallFinished().subscribe(res => {\r
57       this.setChartData();\r
58     }));\r
59 \r
60     this.toDestroy.push(this.stats.onTIExecutionChangeFinished().subscribe(res => {\r
61       this.setChartData()\r
62     }));\r
63 \r
64   }\r
65 \r
66   ngOnDestroy() {\r
67     this.toDestroy.forEach(e => e.unsubscribe());\r
68     this.chart.dispose();\r
69   }\r
70 \r
71   showLoadingIndicator() {\r
72     if(!this.loadingIndicator){\r
73       this.loadingIndicator = this.chart.tooltipContainer.createChild(am4core.Container);\r
74       this.loadingIndicator.background.fill = am4core.color("#fff");\r
75       this.loadingIndicator.background.fillOpacity = 0.8;\r
76       this.loadingIndicator.width = am4core.percent(100);\r
77       this.loadingIndicator.height = am4core.percent(100);\r
78 \r
79       let indicatorLabel = this.loadingIndicator.createChild(am4core.Label);\r
80       indicatorLabel.text = "Loading..";\r
81       indicatorLabel.align = "center";\r
82       indicatorLabel.valign = "middle";\r
83       indicatorLabel.fontSize = 18;\r
84       indicatorLabel.fontWeight= "bold";\r
85       indicatorLabel.dy = 50;\r
86 \r
87       let loadingImage = this.loadingIndicator.createChild(am4core.Image);\r
88       //loadingImage.href = "https://img.devrant.com/devrant/rant/r_647810_4FeCH.gif";\r
89       loadingImage.href = "/assets/images/equalizer.gif";\r
90       //loadingImage.dataSource = "/loading-pies.svg"\r
91       loadingImage.align = "center";\r
92       loadingImage.valign = "middle";\r
93       loadingImage.horizontalCenter = "middle";\r
94       loadingImage.verticalCenter = "middle";\r
95       loadingImage.scale = 3.0;\r
96     }else{\r
97       this.loadingIndicator.show();\r
98     }\r
99 \r
100   }\r
101 \r
102   hideLoadingIndicator() {\r
103     this.loadingIndicator.hide();\r
104   }\r
105 \r
106   setChartData() {\r
107 \r
108     let data = [];\r
109     this.stats.executionList.forEach((execution, i) => {\r
110       let index = data.findIndex(e => e.id === execution.historicTestDefinition._id);\r
111       let executionTime = moment(execution.endTime).diff(moment(execution.startTime), 'seconds');\r
112       if(index == -1){\r
113         data.push({\r
114           id: execution.historicTestDefinition._id,\r
115           name: execution.historicTestDefinition.testName,\r
116           testResult: execution.testResult,\r
117           executionTime: executionTime,\r
118           count: 1,\r
119           average: executionTime\r
120         })\r
121       }else{\r
122         data[index].count += 1;\r
123         data[index].executionTime += executionTime;\r
124         data[index].average = (data[index].executionTime / data[index].count);\r
125       }\r
126     });\r
127     data.sort((a, b) => b.count - a.count);\r
128     this.chart.data = data;\r
129     \r
130 \r
131     // Displays the average time for each bar. \r
132     // If there is no time recorded for the Test Instance, display No Time Recorded.\r
133     let series = this.chart.series.values[0] as am4charts.ColumnSeries;\r
134     \r
135     series.columns.template.adapter.add("tooltipText", (text, target) => {\r
136       if (target.dataItem) {\r
137         if (this.chart.data[target.dataItem.index].average > 0) {\r
138           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
139         } else\r
140           return this.chart.data[target.dataItem.index].count.toString() + " Executions \n No Time Recorded";\r
141       }\r
142     });\r
143     series.columns.template.adapter.add("fill", (fill, target) => this.chart.colors.getIndex(target.dataItem.index));\r
144     \r
145     \r
146     series.columns.template.events.on("doublehit", (click) => {\r
147       this.router.navigate(['/test-definitions', click.target.dataItem.dataContext['id']]);\r
148     });\r
149     this.chart.appear();\r
150     this.hideLoadingIndicator();\r
151     \r
152   }\r
153 \r
154   renderChart() {\r
155     this.chart = am4core.create(this.chartElement.nativeElement, am4charts.XYChart);\r
156     this.chart.cursor = new am4charts.XYCursor();\r
157     this.showLoadingIndicator();\r
158 \r
159     this.chart.responsive.enabled = true;\r
160 \r
161     // Create axes\r
162     var categoryAxis = this.chart.yAxes.push(new am4charts.CategoryAxis());\r
163     categoryAxis.dataFields.category = "name";\r
164     categoryAxis.numberFormatter.numberFormat = "#";\r
165     categoryAxis.renderer.inversed = true;\r
166     categoryAxis.renderer.minGridDistance = 5;\r
167     categoryAxis.title.fontSize = "10px";\r
168 \r
169     var valueAxis = this.chart.xAxes.push(new am4charts.ValueAxis());\r
170     valueAxis.renderer.minWidth = 10;\r
171 \r
172     // Create series\r
173     var series = this.chart.series.push(new am4charts.ColumnSeries());\r
174     series.dataFields.valueX = "count";\r
175     series.dataFields.categoryY = "name";\r
176     series.columns.template.tooltipText = " ";\r
177 \r
178     let label = categoryAxis.renderer.labels.template;\r
179     label.truncate = true;\r
180     label.maxWidth = 130;\r
181     label.fontSize = 13;\r
182 \r
183     //Scrollbar on the right. \r
184     let scrollBarY = new am4charts.XYChartScrollbar();\r
185     //scrollBarY.series.push(series);\r
186     this.chart.scrollbarY = scrollBarY;\r
187     this.chart.scrollbarY.contentHeight = 100;\r
188     this.chart.scrollbarY.minWidth = 20;\r
189     this.chart.scrollbarY.thumb.minWidth = 20;\r
190 \r
191     //set initial Scrollbar Zoom to the Top 6 Instances. \r
192     this.chart.events.on("appeared", () => {\r
193       \r
194       categoryAxis.zoomToIndexes(0, 6, false, true);\r
195     });\r
196    }\r
197 \r
198 }\r