added svcapi ui and camunda code
[it/otf.git] / otf-frontend / client / src / app / layout / control-panel / control-panel.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, OnDestroy, HostListener, ViewChild, ElementRef } from '@angular/core';\r
18 import { routerTransition } from 'app/router.animations';\r
19 import { ActivatedRoute } from '@angular/router';\r
20 import { TestExecutionService } from 'app/shared/services/test-execution.service';\r
21 import { TestDefinitionService } from 'app/shared/services/test-definition.service';\r
22 import BpmnJS from 'bpmn-js/lib/NavigatedViewer';\r
23 import beautify from 'json-beautify';\r
24 import { trigger, state, style, transition, animate } from '@angular/animations';\r
25 import { interval } from 'rxjs';\r
26 import { FileTransferService } from 'app/shared/services/file-transfer.service';\r
27 import { Buffer } from 'buffer';\r
28 import 'codemirror/mode/javascript/javascript.js';\r
29 import { toInteger } from '@ng-bootstrap/ng-bootstrap/util/util';\r
30 import { RequiredValidator } from '@angular/forms';\r
31 import { UserService } from 'app/shared/services/user.service';\r
32 import { ExecuteService } from 'app/shared/services/execute.service';\r
33 import { BpmnFactoryService } from 'app/shared/factories/bpmn-factory.service';\r
34 import { Bpmn } from 'app/shared/models/bpmn.model';\r
35 \r
36 //import 'datatables.net';\r
37 \r
38 @Component({\r
39   selector: 'app-control-panel',\r
40   templateUrl: './control-panel.component.pug',\r
41   styleUrls: ['./control-panel.component.scss'],\r
42   animations: [routerTransition(),\r
43   trigger('detailExpand', [\r
44     state('collapsed', style({ height: '0px', minHeight: '0', display: 'none' })),\r
45     state('expanded', style({ height: '*' })),\r
46     transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),\r
47   ])\r
48   ]\r
49 })\r
50 export class ControlPanelComponent implements OnInit, OnDestroy {\r
51 \r
52   @ViewChild('canvas-card') canvas: ElementRef;\r
53 \r
54   public params;\r
55   public displayedColumns = ['startTime', 'endTime', 'totalTime'];\r
56   public dataSource = {};\r
57   public instanceDataSource = {};\r
58   public data = {};\r
59   public testHeads = [];\r
60   public testResult;\r
61   public expandedElement;\r
62   public selectedTestHead;\r
63   public selectedTestInstance;\r
64   public objectKeys = Object.keys;\r
65   private pullData = true;\r
66   public showFireworks = false;\r
67   public refreshData = false;\r
68   public spin = false;\r
69   public lastVTHResultsLength = 0;\r
70   // Create an Observable that will publish a value on an interval\r
71   public refreshCounter = interval(5000);\r
72 \r
73   public isResizing = false;\r
74   public lastDownY;\r
75 \r
76   public viewer: Bpmn;\r
77   public taskLog = '';\r
78 \r
79   public executionJobLog = [];\r
80   public executionExternalTaskLog = [];\r
81   public executionVariables = [];\r
82 \r
83   public executionJobLogDataSource;\r
84   public executionExternalTaskLogDataSource;\r
85   public executionVariablesDataSource;\r
86 \r
87   public selectedExecutionJobLog;\r
88   public selectedExecutionExternalTaskLog;\r
89   public selectedExecutionVariable;\r
90 \r
91 \r
92   public codeConfig = {\r
93     mode: "application/json",\r
94     theme: "eclipse",\r
95     readonly: true,\r
96     lineNumbers: true\r
97   };\r
98 \r
99   public taskLogConfig = {\r
100     mode: "Shell",\r
101     theme: "3024-night",\r
102     readonly: true\r
103   };\r
104 \r
105   private processInstanceId;\r
106   public processState;\r
107 \r
108 \r
109   constructor(\r
110     private route: ActivatedRoute,\r
111     private executionService: ExecuteService,\r
112     private user: UserService,\r
113     private testExecution: TestExecutionService,\r
114     private fileTransfer: FileTransferService,\r
115     private bpmnFactory: BpmnFactoryService\r
116   ) { }\r
117 \r
118   ngOnInit() {\r
119     this.route.queryParams.subscribe(params => {\r
120       this.params = params;\r
121       if(params.id){\r
122         this.refreshData = false;\r
123         this.populateData();\r
124 \r
125         this.refreshCounter.subscribe(n => {\r
126           if (this.pullData){\r
127             this.populateData(n + 1);\r
128             this.updateFlowData();\r
129 \r
130           }\r
131         });\r
132       }\r
133     });\r
134 \r
135     $('#canvas-card').on('mousedown', (e) => {\r
136       this.isResizing = true;\r
137       this.lastDownY = $('#canvas-card').position().top + $('#canvas-card').outerHeight(true);\r
138     })\r
139 \r
140     $(document).on('mousemove', (e) => {\r
141       if(!this.isResizing){\r
142         return;\r
143       }\r
144 \r
145       var bottom = $('#canvas-card').position().top + $('#canvas-card').outerHeight(true);//$('#canvas-card').height() - (e.clientY - $('#canvas-card').offset().top);\r
146 \r
147       if(bottom != this.lastDownY){\r
148         this.lastDownY = $('#canvas-card').position().top + $('#canvas-card').outerHeight(true);\r
149         this.onResize(null);\r
150       }\r
151 \r
152     }).on('mouseup', () => {\r
153       this.isResizing = false;\r
154     })\r
155   }\r
156 \r
157   ngOnDestroy() {\r
158     this.pullData = false;\r
159   }\r
160 \r
161   refreshAllData() {\r
162     this.spin = true;\r
163     this.refreshData = true;\r
164     this.populateData();\r
165     this.updateFlowData();\r
166 \r
167   }\r
168 \r
169   populateData(loopNum = 0) {\r
170     this.testExecution.get(this.params.id).subscribe(\r
171       data => {\r
172         console.log(data);\r
173         let result = JSON.parse(JSON.stringify(data));\r
174 \r
175         this.processInstanceId = result['processInstanceId'];\r
176 \r
177         this.calcTime(result);\r
178 \r
179         if(result['testInstanceResults']){\r
180           this.instanceDataSource = {};\r
181           for(var val = 0; val < result['testInstanceResults'].length; val++){\r
182             var elem = result['testInstanceResults'][val];\r
183             this.calcTime(elem);\r
184             let exists = false;\r
185             Object.keys(this.instanceDataSource).forEach((e, val) => {\r
186                 if(e == elem.historicTestInstance._id){\r
187                     exists = true;\r
188                     return;\r
189                   }\r
190             });\r
191 \r
192             if(!exists){\r
193               this.instanceDataSource[elem.historicTestInstance._id] = [elem];\r
194             }\r
195             else{\r
196                 var found = false;\r
197 \r
198                 this.instanceDataSource[elem.historicTestInstance._id].forEach( (value, index) => {\r
199                     if(this.instanceDataSource[elem.historicTestInstance._id][index]._id == elem._id){\r
200                         this.instanceDataSource[elem.historicTestInstance._id][index] = elem;\r
201                         found = true;\r
202                     }\r
203                 })\r
204                 if(!found){\r
205                     this.instanceDataSource[elem.historicTestInstance._id].push(elem);\r
206                 }\r
207             }\r
208             if(val == 0){\r
209               this.selectTestInstance(elem.historicTestInstance._id);\r
210             }\r
211           };\r
212         }\r
213 \r
214         if (result['testHeadResults']) {\r
215           for (var i = 0 + this.lastVTHResultsLength; i < result['testHeadResults'].length; i++) {\r
216 \r
217             var exists = false;\r
218             this.testHeads.forEach(elem => {\r
219               if (elem.testHeadId == result['testHeadResults'][i].testHeadId && elem.bpmnVthTaskId == result['testHeadResults'][i].bpmnVthTaskId) {\r
220                 exists = true;\r
221               }\r
222             });\r
223 \r
224             if (!exists) {\r
225               this.testHeads.push(result['testHeadResults'][i]);\r
226               this.dataSource[result['testHeadResults'][i].testHeadId + result['testHeadResults'][i].bpmnVthTaskId] = [];\r
227             }\r
228 \r
229             let sDate = new Date(result['testHeadResults'][i].startTime);\r
230             let eDate = new Date(result['testHeadResults'][i].endTime);\r
231             let tDate = (eDate.getTime() - sDate.getTime()) / 1000;\r
232 \r
233             result['testHeadResults'][i].startTime = sDate.getHours() + ":" + sDate.getMinutes() + ":" + sDate.getSeconds(); // + " " + sDate.getMonth() + "/" + sDate.getDate() + "/" + sDate.getFullYear();\r
234             result['testHeadResults'][i].endTime = eDate.getHours() + ":" + eDate.getMinutes() + ":" + eDate.getSeconds(); // + " " + eDate.getMonth() + "/" + eDate.getDate() + "/" + eDate.getFullYear();\r
235             result['testHeadResults'][i].totalTime = tDate + " secs";\r
236             result['testHeadResults'][i].testHeadRequestResponse = {\r
237                 "testHeadRequest": result['testHeadResults'][i].testHeadRequest,\r
238                 "testHeadResponse": result['testHeadResults'][i].testHeadResponse,\r
239                 "statusCode": result['testHeadResults'][i].statusCode\r
240             };\r
241             //result['testHeadResults'][i].testHeadResponse = beautify(result['testHeadResults'][i].testHeadResponse, null, 2, 50);\r
242 \r
243             this.dataSource[result['testHeadResults'][i].testHeadId + result['testHeadResults'][i].bpmnVthTaskId].push(result['testHeadResults'][i]);\r
244 \r
245             if (i == 0) {\r
246               this.selectTestHead(result['testHeadResults'][i].testHeadId + result['testHeadResults'][i].bpmnVthTaskId);\r
247             }\r
248           }\r
249           //keep track of previous results so you don't reload them\r
250           this.lastVTHResultsLength = result['testHeadResults'].length;\r
251 \r
252           this.testResult = Object.assign({}, result);\r
253           // this.user.get(result['executor']).subscribe(res => {\r
254           //   this.testResult['executor'] = res;\r
255           // });\r
256           //\r
257 \r
258 \r
259           this.spin = false;\r
260         }\r
261 \r
262 \r
263           //only gets called once\r
264         if (!this.refreshData && loopNum == 0 && (result['historicTestDefinition'] && result['historicTestDefinition']['bpmnInstances'][0])) {\r
265           let id = result['historicTestDefinition']['bpmnInstances'][0]['bpmnFileId']\r
266 \r
267           if(!this.viewer){\r
268             this.bpmnFactory.setup({\r
269               mode: 'viewer',\r
270               options: {\r
271                 container: '#canvas'\r
272               },\r
273               fileId: id\r
274             }).then(res => {\r
275               this.viewer = res;\r
276               this.updateFlowData();\r
277             });\r
278           }else{\r
279             this.bpmnFactory.getXml({\r
280               fileId: id\r
281             }).then(res => {\r
282               this.viewer.setBpmnXml(res);\r
283               this.updateFlowData();\r
284             })\r
285           }\r
286 \r
287         }\r
288       }\r
289     );\r
290 \r
291   }\r
292 \r
293   updateExecutionData(){\r
294       if(this.executionJobLog){\r
295           this.executionJobLogDataSource = {};\r
296           for(var val = 0; val < this.executionJobLog.length; val++){\r
297               var elem = this.executionJobLog[val];\r
298 \r
299               let exists = false;\r
300               Object.keys(this.executionJobLogDataSource).forEach((e, val) => {\r
301                   if(e == elem.activityId){\r
302                       exists = true;\r
303                       return;\r
304                   }\r
305               });\r
306 \r
307               if(!exists){\r
308                   this.executionJobLogDataSource[elem.activityId] = [elem];\r
309               }\r
310               else{\r
311                   var found = false;\r
312 \r
313                   this.executionJobLogDataSource[elem.activityId].forEach( (value, index) => {\r
314                       if(this.executionJobLogDataSource[elem.activityId][index].id == elem.id){\r
315                           this.executionJobLogDataSource[elem.activityId][index] = elem;\r
316                           found = true;\r
317                       }\r
318                   })\r
319                   if(!found){\r
320                       this.executionJobLogDataSource[elem.activityId].push(elem);\r
321                   }\r
322               }\r
323               if(val == 0){\r
324                   this.selectExecutionJobLog(elem.activityId);\r
325               }\r
326           };\r
327       }\r
328 \r
329       if(this.executionExternalTaskLog){\r
330           this.executionExternalTaskLogDataSource = {};\r
331           for(var val = 0; val < this.executionExternalTaskLog.length; val++){\r
332               var elem = this.executionExternalTaskLog[val];\r
333 \r
334               let exists = false;\r
335               Object.keys(this.executionExternalTaskLogDataSource).forEach((e, val) => {\r
336                   if(e == elem.activityId){\r
337                       exists = true;\r
338                       return;\r
339                   }\r
340               });\r
341 \r
342               if(!exists){\r
343                   this.executionExternalTaskLogDataSource[elem.activityId] = [elem];\r
344               }\r
345               else{\r
346                   var found = false;\r
347 \r
348                   this.executionExternalTaskLogDataSource[elem.activityId].forEach( (value, index) => {\r
349                       if(this.executionExternalTaskLogDataSource[elem.activityId][index].id == elem.id){\r
350                           this.executionExternalTaskLogDataSource[elem.activityId][index] = elem;\r
351                           found = true;\r
352                       }\r
353                   })\r
354                   if(!found){\r
355                       this.executionExternalTaskLogDataSource[elem.activityId].push(elem);\r
356                   }\r
357               }\r
358               if(val == 0){\r
359                   this.selectExecutionExternalTaskLog(elem.activityId);\r
360               }\r
361           };\r
362       }\r
363 \r
364 \r
365 \r
366       if(this.executionVariables){\r
367           this.executionVariablesDataSource = {};\r
368           for(var val = 0; val < this.executionVariables.length; val++){\r
369               var elem = this.executionVariables[val];\r
370 \r
371               let exists = false;\r
372               Object.keys(this.executionVariablesDataSource).forEach((e, val) => {\r
373                   if(e == elem.variableName){\r
374                       exists = true;\r
375                       return;\r
376                   }\r
377               });\r
378 \r
379               if(!exists){\r
380                   this.executionVariablesDataSource[elem.variableName] = [elem];\r
381               }\r
382               else{\r
383                   var found = false;\r
384 \r
385                   this.executionVariablesDataSource[elem.variableName].forEach( (value, index) => {\r
386                       if(this.executionVariablesDataSource[elem.variableName][index].id == elem.id){\r
387                           this.executionVariablesDataSource[elem.variableName][index] = elem;\r
388                           found = true;\r
389                       }\r
390                   })\r
391                   if(!found){\r
392                       this.executionVariablesDataSource[elem.variableName].push(elem);\r
393                   }\r
394               }\r
395               if(val == 0){\r
396                   this.selectExecutionVariable(elem.variableName);\r
397               }\r
398           };\r
399       }\r
400 \r
401   }\r
402 \r
403   calcTime(result) {\r
404     let tsDate = new Date(result['startTime']);\r
405     let teDate = new Date(result['endTime']);\r
406     let ttDate = (teDate.getTime() - tsDate.getTime()) / 1000;\r
407 \r
408     result['date'] = tsDate.getMonth() + 1 + "/" + tsDate.getDate() + "/" + tsDate.getFullYear();\r
409     result['startTime'] = tsDate.getHours() + ":" + tsDate.getMinutes() + ":" + tsDate.getSeconds();\r
410     result['endTime'] = teDate.getHours() + ":" + teDate.getMinutes() + ":" + teDate.getSeconds();\r
411     result['totalTime'] = ttDate + ' secs';\r
412 \r
413 \r
414   }\r
415 \r
416   updateFlowData() {\r
417     console.log(this.processInstanceId);\r
418     this.testExecution.status(this.processInstanceId).subscribe(\r
419       result => {\r
420         if (result) {\r
421           let data = result['body'];\r
422           //check process state\r
423           if (data.historicProcessInstance.state == 'COMPLETED') {\r
424             this.processState = 'Completed';\r
425             this.pullData = false;\r
426           } else if (data.historicProcessInstance.state == 'ACTIVE') {\r
427             this.processState = 'Running';\r
428           } else {\r
429             this.processState = 'Failed';\r
430             this.pullData = false;\r
431           }\r
432 \r
433           if(data.historicJobLog){\r
434             this.executionJobLog =  data.historicJobLog;\r
435           }\r
436           if(data.historicExternalTaskLog){\r
437             this.executionExternalTaskLog =  data.historicExternalTaskLog;\r
438           }\r
439           if(data.historicVariableInstance){\r
440             this.executionVariables =  data.historicVariableInstance;\r
441           }\r
442           //update execution tabs -- job log, external task log, variables\r
443           this.updateExecutionData();\r
444 \r
445 \r
446             //loop through processes to get their info\r
447           for (let i = 0; i < data.historicActivityInstance.length; i++) {\r
448             let p = data.historicActivityInstance[i];\r
449             let state = null;\r
450             if (p.startTime && p.endTime && !p.canceled) { // process completed successfully\r
451               state = 'completed';\r
452             } else if (p.startTime && !p.endTime) { // process is still running\r
453               state = 'running';\r
454             } else if (p.canceled) {\r
455               state = 'failed';\r
456             }\r
457 \r
458             //get task id\r
459 \r
460             //highlight task boxes based on their state\r
461             this.viewer.getModel().get('canvas').addMarker(p.activityId, 'highlight-task-' + state);\r
462           }\r
463 \r
464 \r
465 \r
466           for (let i = 0; i < data.historicIncident.length; i++) {\r
467             let p = data.historicIncident[i];\r
468             if (p.incidentMessage) {\r
469               this.taskLog += p.activityId + ': ' + p.incidentMessage + '\n';\r
470             }\r
471             this.viewer.getModel().get('canvas').addMarker(p.activityId, 'highlight-task-failed');\r
472           }\r
473         }\r
474       },\r
475       err => {\r
476 \r
477       }\r
478     );\r
479   }\r
480 \r
481   cancelExecution() {\r
482     this.executionService.delete(this.testResult._id).subscribe(result => {\r
483       this.updateFlowData();\r
484     });\r
485   }\r
486 \r
487   expand(element) {\r
488     if (this.expandedElement == element)\r
489       this.expandedElement = null;\r
490     else\r
491       this.expandedElement = element;\r
492   }\r
493 \r
494   beauty(json) {\r
495     return beautify(json, null, 2, 50);\r
496   }\r
497 \r
498   @HostListener('window:resize', ['$event'])\r
499   onResize(event){\r
500     // console.log("hi")\r
501     if(this.viewer)\r
502       this.viewer.resize();\r
503   }\r
504 \r
505 \r
506   json2html(json: any = [{  }], tabs = 0) {\r
507     var html = '';\r
508     var tabHtml = '';\r
509     if (typeof json === 'string') {\r
510       json = JSON.parse(json);\r
511     }\r
512     for (let i = 0; i < tabs; i++) {\r
513       tabHtml += '&nbsp;&nbsp;&nbsp;&nbsp;';\r
514     }\r
515     for (let key in json) {\r
516       if (json.hasOwnProperty(key)) {\r
517         if (typeof json[key] === "object") {\r
518           html += tabHtml + '<b><u>' + key + ':</u></b><br/>';\r
519           if (json.constructor === Array && toInteger(key) > 0) {\r
520             tabs--;\r
521           }\r
522           html += this.json2html(json[key], ++tabs);\r
523         } else {\r
524           html += tabHtml + '<b><u>' + key + ':</u></b>' + '<br/>';\r
525           if (typeof json[key] === 'string') {\r
526             json[key] = json[key].replace(/\\n/g, '<br/>' + tabHtml);\r
527           }\r
528           html += tabHtml + json[key] + '<br/>';\r
529           html += '<br/>';\r
530         }\r
531       }\r
532     }\r
533     return html;\r
534   }\r
535 \r
536   selectTestHead(key) {\r
537     this.selectedTestHead = key;\r
538   }\r
539 \r
540   selectTestInstance(key){\r
541     this.selectedTestInstance = key;\r
542 \r
543   }\r
544 \r
545     selectExecutionJobLog(key){\r
546         this.selectedExecutionJobLog = key;\r
547 \r
548     }\r
549 \r
550     selectExecutionExternalTaskLog(key){\r
551         this.selectedExecutionExternalTaskLog = key;\r
552 \r
553     }\r
554 \r
555     selectExecutionVariable(key){\r
556         this.selectedExecutionVariable = key;\r
557 \r
558     }\r
559 \r
560   call() {\r
561     //\r
562   }\r
563 \r
564 }\r