--- /dev/null
+/* Copyright (c) 2019 AT&T Intellectual Property. #\r
+# #\r
+# Licensed under the Apache License, Version 2.0 (the "License"); #\r
+# you may not use this file except in compliance with the License. #\r
+# You may obtain a copy of the License at #\r
+# #\r
+# http://www.apache.org/licenses/LICENSE-2.0 #\r
+# #\r
+# Unless required by applicable law or agreed to in writing, software #\r
+# distributed under the License is distributed on an "AS IS" BASIS, #\r
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #\r
+# See the License for the specific language governing permissions and #\r
+# limitations under the License. #\r
+##############################################################################*/\r
+\r
+\r
+import { Component, OnInit, OnDestroy, HostListener, ViewChild, ElementRef } from '@angular/core';\r
+import { routerTransition } from 'app/router.animations';\r
+import { ActivatedRoute } from '@angular/router';\r
+import { TestExecutionService } from 'app/shared/services/test-execution.service';\r
+import { TestDefinitionService } from 'app/shared/services/test-definition.service';\r
+import BpmnJS from 'bpmn-js/lib/NavigatedViewer';\r
+import beautify from 'json-beautify';\r
+import { trigger, state, style, transition, animate } from '@angular/animations';\r
+import { interval } from 'rxjs';\r
+import { FileTransferService } from 'app/shared/services/file-transfer.service';\r
+import { Buffer } from 'buffer';\r
+import 'codemirror/mode/javascript/javascript.js';\r
+import { toInteger } from '@ng-bootstrap/ng-bootstrap/util/util';\r
+import { RequiredValidator } from '@angular/forms';\r
+import { UserService } from 'app/shared/services/user.service';\r
+import { ExecuteService } from 'app/shared/services/execute.service';\r
+import { BpmnFactoryService } from 'app/shared/factories/bpmn-factory.service';\r
+import { Bpmn } from 'app/shared/models/bpmn.model';\r
+\r
+//import 'datatables.net';\r
+\r
+@Component({\r
+ selector: 'app-control-panel',\r
+ templateUrl: './control-panel.component.pug',\r
+ styleUrls: ['./control-panel.component.scss'],\r
+ animations: [routerTransition(),\r
+ trigger('detailExpand', [\r
+ state('collapsed', style({ height: '0px', minHeight: '0', display: 'none' })),\r
+ state('expanded', style({ height: '*' })),\r
+ transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),\r
+ ])\r
+ ]\r
+})\r
+export class ControlPanelComponent implements OnInit, OnDestroy {\r
+\r
+ @ViewChild('canvas-card') canvas: ElementRef;\r
+\r
+ public params;\r
+ public displayedColumns = ['startTime', 'endTime', 'totalTime'];\r
+ public dataSource = {};\r
+ public instanceDataSource = {};\r
+ public data = {};\r
+ public testHeads = [];\r
+ public testResult;\r
+ public expandedElement;\r
+ public selectedTestHead;\r
+ public selectedTestInstance;\r
+ public objectKeys = Object.keys;\r
+ private pullData = true;\r
+ public showFireworks = false;\r
+ public refreshData = false;\r
+ public spin = false;\r
+ public lastVTHResultsLength = 0;\r
+ // Create an Observable that will publish a value on an interval\r
+ public refreshCounter = interval(5000);\r
+\r
+ public isResizing = false;\r
+ public lastDownY;\r
+\r
+ public viewer: Bpmn;\r
+ public taskLog = '';\r
+\r
+ public executionJobLog = [];\r
+ public executionExternalTaskLog = [];\r
+ public executionVariables = [];\r
+\r
+ public executionJobLogDataSource;\r
+ public executionExternalTaskLogDataSource;\r
+ public executionVariablesDataSource;\r
+\r
+ public selectedExecutionJobLog;\r
+ public selectedExecutionExternalTaskLog;\r
+ public selectedExecutionVariable;\r
+\r
+\r
+ public codeConfig = {\r
+ mode: "application/json",\r
+ theme: "eclipse",\r
+ readonly: true,\r
+ lineNumbers: true\r
+ };\r
+\r
+ public taskLogConfig = {\r
+ mode: "Shell",\r
+ theme: "3024-night",\r
+ readonly: true\r
+ };\r
+\r
+ private processInstanceId;\r
+ public processState;\r
+\r
+\r
+ constructor(\r
+ private route: ActivatedRoute,\r
+ private executionService: ExecuteService,\r
+ private user: UserService,\r
+ private testExecution: TestExecutionService,\r
+ private fileTransfer: FileTransferService,\r
+ private bpmnFactory: BpmnFactoryService\r
+ ) { }\r
+\r
+ ngOnInit() {\r
+ this.route.queryParams.subscribe(params => {\r
+ this.params = params;\r
+ if(params.id){\r
+ this.refreshData = false;\r
+ this.populateData();\r
+\r
+ this.refreshCounter.subscribe(n => {\r
+ if (this.pullData){\r
+ this.populateData(n + 1);\r
+ this.updateFlowData();\r
+\r
+ }\r
+ });\r
+ }\r
+ });\r
+\r
+ $('#canvas-card').on('mousedown', (e) => {\r
+ this.isResizing = true;\r
+ this.lastDownY = $('#canvas-card').position().top + $('#canvas-card').outerHeight(true);\r
+ })\r
+\r
+ $(document).on('mousemove', (e) => {\r
+ if(!this.isResizing){\r
+ return;\r
+ }\r
+\r
+ var bottom = $('#canvas-card').position().top + $('#canvas-card').outerHeight(true);//$('#canvas-card').height() - (e.clientY - $('#canvas-card').offset().top);\r
+\r
+ if(bottom != this.lastDownY){\r
+ this.lastDownY = $('#canvas-card').position().top + $('#canvas-card').outerHeight(true);\r
+ this.onResize(null);\r
+ }\r
+\r
+ }).on('mouseup', () => {\r
+ this.isResizing = false;\r
+ })\r
+ }\r
+\r
+ ngOnDestroy() {\r
+ this.pullData = false;\r
+ }\r
+\r
+ refreshAllData() {\r
+ this.spin = true;\r
+ this.refreshData = true;\r
+ this.populateData();\r
+ this.updateFlowData();\r
+\r
+ }\r
+\r
+ populateData(loopNum = 0) {\r
+ this.testExecution.get(this.params.id).subscribe(\r
+ data => {\r
+ console.log(data);\r
+ let result = JSON.parse(JSON.stringify(data));\r
+\r
+ this.processInstanceId = result['processInstanceId'];\r
+\r
+ this.calcTime(result);\r
+\r
+ if(result['testInstanceResults']){\r
+ this.instanceDataSource = {};\r
+ for(var val = 0; val < result['testInstanceResults'].length; val++){\r
+ var elem = result['testInstanceResults'][val];\r
+ this.calcTime(elem);\r
+ let exists = false;\r
+ Object.keys(this.instanceDataSource).forEach((e, val) => {\r
+ if(e == elem.historicTestInstance._id){\r
+ exists = true;\r
+ return;\r
+ }\r
+ });\r
+\r
+ if(!exists){\r
+ this.instanceDataSource[elem.historicTestInstance._id] = [elem];\r
+ }\r
+ else{\r
+ var found = false;\r
+\r
+ this.instanceDataSource[elem.historicTestInstance._id].forEach( (value, index) => {\r
+ if(this.instanceDataSource[elem.historicTestInstance._id][index]._id == elem._id){\r
+ this.instanceDataSource[elem.historicTestInstance._id][index] = elem;\r
+ found = true;\r
+ }\r
+ })\r
+ if(!found){\r
+ this.instanceDataSource[elem.historicTestInstance._id].push(elem);\r
+ }\r
+ }\r
+ if(val == 0){\r
+ this.selectTestInstance(elem.historicTestInstance._id);\r
+ }\r
+ };\r
+ }\r
+\r
+ if (result['testHeadResults']) {\r
+ for (var i = 0 + this.lastVTHResultsLength; i < result['testHeadResults'].length; i++) {\r
+\r
+ var exists = false;\r
+ this.testHeads.forEach(elem => {\r
+ if (elem.testHeadId == result['testHeadResults'][i].testHeadId && elem.bpmnVthTaskId == result['testHeadResults'][i].bpmnVthTaskId) {\r
+ exists = true;\r
+ }\r
+ });\r
+\r
+ if (!exists) {\r
+ this.testHeads.push(result['testHeadResults'][i]);\r
+ this.dataSource[result['testHeadResults'][i].testHeadId + result['testHeadResults'][i].bpmnVthTaskId] = [];\r
+ }\r
+\r
+ let sDate = new Date(result['testHeadResults'][i].startTime);\r
+ let eDate = new Date(result['testHeadResults'][i].endTime);\r
+ let tDate = (eDate.getTime() - sDate.getTime()) / 1000;\r
+\r
+ result['testHeadResults'][i].startTime = sDate.getHours() + ":" + sDate.getMinutes() + ":" + sDate.getSeconds(); // + " " + sDate.getMonth() + "/" + sDate.getDate() + "/" + sDate.getFullYear();\r
+ result['testHeadResults'][i].endTime = eDate.getHours() + ":" + eDate.getMinutes() + ":" + eDate.getSeconds(); // + " " + eDate.getMonth() + "/" + eDate.getDate() + "/" + eDate.getFullYear();\r
+ result['testHeadResults'][i].totalTime = tDate + " secs";\r
+ result['testHeadResults'][i].testHeadRequestResponse = {\r
+ "testHeadRequest": result['testHeadResults'][i].testHeadRequest,\r
+ "testHeadResponse": result['testHeadResults'][i].testHeadResponse,\r
+ "statusCode": result['testHeadResults'][i].statusCode\r
+ };\r
+ //result['testHeadResults'][i].testHeadResponse = beautify(result['testHeadResults'][i].testHeadResponse, null, 2, 50);\r
+\r
+ this.dataSource[result['testHeadResults'][i].testHeadId + result['testHeadResults'][i].bpmnVthTaskId].push(result['testHeadResults'][i]);\r
+\r
+ if (i == 0) {\r
+ this.selectTestHead(result['testHeadResults'][i].testHeadId + result['testHeadResults'][i].bpmnVthTaskId);\r
+ }\r
+ }\r
+ //keep track of previous results so you don't reload them\r
+ this.lastVTHResultsLength = result['testHeadResults'].length;\r
+\r
+ this.testResult = Object.assign({}, result);\r
+ // this.user.get(result['executor']).subscribe(res => {\r
+ // this.testResult['executor'] = res;\r
+ // });\r
+ //\r
+\r
+\r
+ this.spin = false;\r
+ }\r
+\r
+\r
+ //only gets called once\r
+ if (!this.refreshData && loopNum == 0 && (result['historicTestDefinition'] && result['historicTestDefinition']['bpmnInstances'][0])) {\r
+ let id = result['historicTestDefinition']['bpmnInstances'][0]['bpmnFileId']\r
+\r
+ if(!this.viewer){\r
+ this.bpmnFactory.setup({\r
+ mode: 'viewer',\r
+ options: {\r
+ container: '#canvas'\r
+ },\r
+ fileId: id\r
+ }).then(res => {\r
+ this.viewer = res;\r
+ this.updateFlowData();\r
+ });\r
+ }else{\r
+ this.bpmnFactory.getXml({\r
+ fileId: id\r
+ }).then(res => {\r
+ this.viewer.setBpmnXml(res);\r
+ this.updateFlowData();\r
+ })\r
+ }\r
+\r
+ }\r
+ }\r
+ );\r
+\r
+ }\r
+\r
+ updateExecutionData(){\r
+ if(this.executionJobLog){\r
+ this.executionJobLogDataSource = {};\r
+ for(var val = 0; val < this.executionJobLog.length; val++){\r
+ var elem = this.executionJobLog[val];\r
+\r
+ let exists = false;\r
+ Object.keys(this.executionJobLogDataSource).forEach((e, val) => {\r
+ if(e == elem.activityId){\r
+ exists = true;\r
+ return;\r
+ }\r
+ });\r
+\r
+ if(!exists){\r
+ this.executionJobLogDataSource[elem.activityId] = [elem];\r
+ }\r
+ else{\r
+ var found = false;\r
+\r
+ this.executionJobLogDataSource[elem.activityId].forEach( (value, index) => {\r
+ if(this.executionJobLogDataSource[elem.activityId][index].id == elem.id){\r
+ this.executionJobLogDataSource[elem.activityId][index] = elem;\r
+ found = true;\r
+ }\r
+ })\r
+ if(!found){\r
+ this.executionJobLogDataSource[elem.activityId].push(elem);\r
+ }\r
+ }\r
+ if(val == 0){\r
+ this.selectExecutionJobLog(elem.activityId);\r
+ }\r
+ };\r
+ }\r
+\r
+ if(this.executionExternalTaskLog){\r
+ this.executionExternalTaskLogDataSource = {};\r
+ for(var val = 0; val < this.executionExternalTaskLog.length; val++){\r
+ var elem = this.executionExternalTaskLog[val];\r
+\r
+ let exists = false;\r
+ Object.keys(this.executionExternalTaskLogDataSource).forEach((e, val) => {\r
+ if(e == elem.activityId){\r
+ exists = true;\r
+ return;\r
+ }\r
+ });\r
+\r
+ if(!exists){\r
+ this.executionExternalTaskLogDataSource[elem.activityId] = [elem];\r
+ }\r
+ else{\r
+ var found = false;\r
+\r
+ this.executionExternalTaskLogDataSource[elem.activityId].forEach( (value, index) => {\r
+ if(this.executionExternalTaskLogDataSource[elem.activityId][index].id == elem.id){\r
+ this.executionExternalTaskLogDataSource[elem.activityId][index] = elem;\r
+ found = true;\r
+ }\r
+ })\r
+ if(!found){\r
+ this.executionExternalTaskLogDataSource[elem.activityId].push(elem);\r
+ }\r
+ }\r
+ if(val == 0){\r
+ this.selectExecutionExternalTaskLog(elem.activityId);\r
+ }\r
+ };\r
+ }\r
+\r
+\r
+\r
+ if(this.executionVariables){\r
+ this.executionVariablesDataSource = {};\r
+ for(var val = 0; val < this.executionVariables.length; val++){\r
+ var elem = this.executionVariables[val];\r
+\r
+ let exists = false;\r
+ Object.keys(this.executionVariablesDataSource).forEach((e, val) => {\r
+ if(e == elem.variableName){\r
+ exists = true;\r
+ return;\r
+ }\r
+ });\r
+\r
+ if(!exists){\r
+ this.executionVariablesDataSource[elem.variableName] = [elem];\r
+ }\r
+ else{\r
+ var found = false;\r
+\r
+ this.executionVariablesDataSource[elem.variableName].forEach( (value, index) => {\r
+ if(this.executionVariablesDataSource[elem.variableName][index].id == elem.id){\r
+ this.executionVariablesDataSource[elem.variableName][index] = elem;\r
+ found = true;\r
+ }\r
+ })\r
+ if(!found){\r
+ this.executionVariablesDataSource[elem.variableName].push(elem);\r
+ }\r
+ }\r
+ if(val == 0){\r
+ this.selectExecutionVariable(elem.variableName);\r
+ }\r
+ };\r
+ }\r
+\r
+ }\r
+\r
+ calcTime(result) {\r
+ let tsDate = new Date(result['startTime']);\r
+ let teDate = new Date(result['endTime']);\r
+ let ttDate = (teDate.getTime() - tsDate.getTime()) / 1000;\r
+\r
+ result['date'] = tsDate.getMonth() + 1 + "/" + tsDate.getDate() + "/" + tsDate.getFullYear();\r
+ result['startTime'] = tsDate.getHours() + ":" + tsDate.getMinutes() + ":" + tsDate.getSeconds();\r
+ result['endTime'] = teDate.getHours() + ":" + teDate.getMinutes() + ":" + teDate.getSeconds();\r
+ result['totalTime'] = ttDate + ' secs';\r
+\r
+\r
+ }\r
+\r
+ updateFlowData() {\r
+ console.log(this.processInstanceId);\r
+ this.testExecution.status(this.processInstanceId).subscribe(\r
+ result => {\r
+ if (result) {\r
+ let data = result['body'];\r
+ //check process state\r
+ if (data.historicProcessInstance.state == 'COMPLETED') {\r
+ this.processState = 'Completed';\r
+ this.pullData = false;\r
+ } else if (data.historicProcessInstance.state == 'ACTIVE') {\r
+ this.processState = 'Running';\r
+ } else {\r
+ this.processState = 'Failed';\r
+ this.pullData = false;\r
+ }\r
+\r
+ if(data.historicJobLog){\r
+ this.executionJobLog = data.historicJobLog;\r
+ }\r
+ if(data.historicExternalTaskLog){\r
+ this.executionExternalTaskLog = data.historicExternalTaskLog;\r
+ }\r
+ if(data.historicVariableInstance){\r
+ this.executionVariables = data.historicVariableInstance;\r
+ }\r
+ //update execution tabs -- job log, external task log, variables\r
+ this.updateExecutionData();\r
+\r
+\r
+ //loop through processes to get their info\r
+ for (let i = 0; i < data.historicActivityInstance.length; i++) {\r
+ let p = data.historicActivityInstance[i];\r
+ let state = null;\r
+ if (p.startTime && p.endTime && !p.canceled) { // process completed successfully\r
+ state = 'completed';\r
+ } else if (p.startTime && !p.endTime) { // process is still running\r
+ state = 'running';\r
+ } else if (p.canceled) {\r
+ state = 'failed';\r
+ }\r
+\r
+ //get task id\r
+\r
+ //highlight task boxes based on their state\r
+ this.viewer.getModel().get('canvas').addMarker(p.activityId, 'highlight-task-' + state);\r
+ }\r
+\r
+\r
+\r
+ for (let i = 0; i < data.historicIncident.length; i++) {\r
+ let p = data.historicIncident[i];\r
+ if (p.incidentMessage) {\r
+ this.taskLog += p.activityId + ': ' + p.incidentMessage + '\n';\r
+ }\r
+ this.viewer.getModel().get('canvas').addMarker(p.activityId, 'highlight-task-failed');\r
+ }\r
+ }\r
+ },\r
+ err => {\r
+\r
+ }\r
+ );\r
+ }\r
+\r
+ cancelExecution() {\r
+ this.executionService.delete(this.testResult._id).subscribe(result => {\r
+ this.updateFlowData();\r
+ });\r
+ }\r
+\r
+ expand(element) {\r
+ if (this.expandedElement == element)\r
+ this.expandedElement = null;\r
+ else\r
+ this.expandedElement = element;\r
+ }\r
+\r
+ beauty(json) {\r
+ return beautify(json, null, 2, 50);\r
+ }\r
+\r
+ @HostListener('window:resize', ['$event'])\r
+ onResize(event){\r
+ // console.log("hi")\r
+ if(this.viewer)\r
+ this.viewer.resize();\r
+ }\r
+\r
+\r
+ json2html(json: any = [{ }], tabs = 0) {\r
+ var html = '';\r
+ var tabHtml = '';\r
+ if (typeof json === 'string') {\r
+ json = JSON.parse(json);\r
+ }\r
+ for (let i = 0; i < tabs; i++) {\r
+ tabHtml += ' ';\r
+ }\r
+ for (let key in json) {\r
+ if (json.hasOwnProperty(key)) {\r
+ if (typeof json[key] === "object") {\r
+ html += tabHtml + '<b><u>' + key + ':</u></b><br/>';\r
+ if (json.constructor === Array && toInteger(key) > 0) {\r
+ tabs--;\r
+ }\r
+ html += this.json2html(json[key], ++tabs);\r
+ } else {\r
+ html += tabHtml + '<b><u>' + key + ':</u></b>' + '<br/>';\r
+ if (typeof json[key] === 'string') {\r
+ json[key] = json[key].replace(/\\n/g, '<br/>' + tabHtml);\r
+ }\r
+ html += tabHtml + json[key] + '<br/>';\r
+ html += '<br/>';\r
+ }\r
+ }\r
+ }\r
+ return html;\r
+ }\r
+\r
+ selectTestHead(key) {\r
+ this.selectedTestHead = key;\r
+ }\r
+\r
+ selectTestInstance(key){\r
+ this.selectedTestInstance = key;\r
+\r
+ }\r
+\r
+ selectExecutionJobLog(key){\r
+ this.selectedExecutionJobLog = key;\r
+\r
+ }\r
+\r
+ selectExecutionExternalTaskLog(key){\r
+ this.selectedExecutionExternalTaskLog = key;\r
+\r
+ }\r
+\r
+ selectExecutionVariable(key){\r
+ this.selectedExecutionVariable = key;\r
+\r
+ }\r
+\r
+ call() {\r
+ //\r
+ }\r
+\r
+}\r