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, 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
36 //import 'datatables.net';
\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
50 export class ControlPanelComponent implements OnInit, OnDestroy {
\r
52 @ViewChild('canvas-card') canvas: ElementRef;
\r
55 public displayedColumns = ['startTime', 'endTime', 'totalTime'];
\r
56 public dataSource = {};
\r
57 public instanceDataSource = {};
\r
59 public testHeads = [];
\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
73 public isResizing = false;
\r
76 public viewer: Bpmn;
\r
77 public taskLog = '';
\r
79 public executionJobLog = [];
\r
80 public executionExternalTaskLog = [];
\r
81 public executionVariables = [];
\r
83 public executionJobLogDataSource;
\r
84 public executionExternalTaskLogDataSource;
\r
85 public executionVariablesDataSource;
\r
87 public selectedExecutionJobLog;
\r
88 public selectedExecutionExternalTaskLog;
\r
89 public selectedExecutionVariable;
\r
92 public codeConfig = {
\r
93 mode: "application/json",
\r
99 public taskLogConfig = {
\r
101 theme: "3024-night",
\r
105 private processInstanceId;
\r
106 public processState;
\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
119 this.route.queryParams.subscribe(params => {
\r
120 this.params = params;
\r
122 this.refreshData = false;
\r
123 this.populateData();
\r
125 this.refreshCounter.subscribe(n => {
\r
126 if (this.pullData){
\r
127 this.populateData(n + 1);
\r
128 this.updateFlowData();
\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
140 $(document).on('mousemove', (e) => {
\r
141 if(!this.isResizing){
\r
145 var bottom = $('#canvas-card').position().top + $('#canvas-card').outerHeight(true);//$('#canvas-card').height() - (e.clientY - $('#canvas-card').offset().top);
\r
147 if(bottom != this.lastDownY){
\r
148 this.lastDownY = $('#canvas-card').position().top + $('#canvas-card').outerHeight(true);
\r
149 this.onResize(null);
\r
152 }).on('mouseup', () => {
\r
153 this.isResizing = false;
\r
158 this.pullData = false;
\r
163 this.refreshData = true;
\r
164 this.populateData();
\r
165 this.updateFlowData();
\r
169 populateData(loopNum = 0) {
\r
170 this.testExecution.get(this.params.id).subscribe(
\r
173 let result = JSON.parse(JSON.stringify(data));
\r
175 this.processInstanceId = result['processInstanceId'];
\r
177 this.calcTime(result);
\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
193 this.instanceDataSource[elem.historicTestInstance._id] = [elem];
\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
205 this.instanceDataSource[elem.historicTestInstance._id].push(elem);
\r
209 this.selectTestInstance(elem.historicTestInstance._id);
\r
214 if (result['testHeadResults']) {
\r
215 for (var i = 0 + this.lastVTHResultsLength; i < result['testHeadResults'].length; i++) {
\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
225 this.testHeads.push(result['testHeadResults'][i]);
\r
226 this.dataSource[result['testHeadResults'][i].testHeadId + result['testHeadResults'][i].bpmnVthTaskId] = [];
\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
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
241 //result['testHeadResults'][i].testHeadResponse = beautify(result['testHeadResults'][i].testHeadResponse, null, 2, 50);
\r
243 this.dataSource[result['testHeadResults'][i].testHeadId + result['testHeadResults'][i].bpmnVthTaskId].push(result['testHeadResults'][i]);
\r
246 this.selectTestHead(result['testHeadResults'][i].testHeadId + result['testHeadResults'][i].bpmnVthTaskId);
\r
249 //keep track of previous results so you don't reload them
\r
250 this.lastVTHResultsLength = result['testHeadResults'].length;
\r
252 this.testResult = Object.assign({}, result);
\r
253 // this.user.get(result['executor']).subscribe(res => {
\r
254 // this.testResult['executor'] = res;
\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
268 this.bpmnFactory.setup({
\r
271 container: '#canvas'
\r
276 this.updateFlowData();
\r
279 this.bpmnFactory.getXml({
\r
282 this.viewer.setBpmnXml(res);
\r
283 this.updateFlowData();
\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
299 let exists = false;
\r
300 Object.keys(this.executionJobLogDataSource).forEach((e, val) => {
\r
301 if(e == elem.activityId){
\r
308 this.executionJobLogDataSource[elem.activityId] = [elem];
\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
320 this.executionJobLogDataSource[elem.activityId].push(elem);
\r
324 this.selectExecutionJobLog(elem.activityId);
\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
334 let exists = false;
\r
335 Object.keys(this.executionExternalTaskLogDataSource).forEach((e, val) => {
\r
336 if(e == elem.activityId){
\r
343 this.executionExternalTaskLogDataSource[elem.activityId] = [elem];
\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
355 this.executionExternalTaskLogDataSource[elem.activityId].push(elem);
\r
359 this.selectExecutionExternalTaskLog(elem.activityId);
\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
371 let exists = false;
\r
372 Object.keys(this.executionVariablesDataSource).forEach((e, val) => {
\r
373 if(e == elem.variableName){
\r
380 this.executionVariablesDataSource[elem.variableName] = [elem];
\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
392 this.executionVariablesDataSource[elem.variableName].push(elem);
\r
396 this.selectExecutionVariable(elem.variableName);
\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
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
417 console.log(this.processInstanceId);
\r
418 this.testExecution.status(this.processInstanceId).subscribe(
\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
429 this.processState = 'Failed';
\r
430 this.pullData = false;
\r
433 if(data.historicJobLog){
\r
434 this.executionJobLog = data.historicJobLog;
\r
436 if(data.historicExternalTaskLog){
\r
437 this.executionExternalTaskLog = data.historicExternalTaskLog;
\r
439 if(data.historicVariableInstance){
\r
440 this.executionVariables = data.historicVariableInstance;
\r
442 //update execution tabs -- job log, external task log, variables
\r
443 this.updateExecutionData();
\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
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
454 } else if (p.canceled) {
\r
460 //highlight task boxes based on their state
\r
461 this.viewer.getModel().get('canvas').addMarker(p.activityId, 'highlight-task-' + state);
\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
471 this.viewer.getModel().get('canvas').addMarker(p.activityId, 'highlight-task-failed');
\r
481 cancelExecution() {
\r
482 this.executionService.delete(this.testResult._id).subscribe(result => {
\r
483 this.updateFlowData();
\r
488 if (this.expandedElement == element)
\r
489 this.expandedElement = null;
\r
491 this.expandedElement = element;
\r
495 return beautify(json, null, 2, 50);
\r
498 @HostListener('window:resize', ['$event'])
\r
500 // console.log("hi")
\r
502 this.viewer.resize();
\r
506 json2html(json: any = [{ }], tabs = 0) {
\r
509 if (typeof json === 'string') {
\r
510 json = JSON.parse(json);
\r
512 for (let i = 0; i < tabs; i++) {
\r
513 tabHtml += ' ';
\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
522 html += this.json2html(json[key], ++tabs);
\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
528 html += tabHtml + json[key] + '<br/>';
\r
536 selectTestHead(key) {
\r
537 this.selectedTestHead = key;
\r
540 selectTestInstance(key){
\r
541 this.selectedTestInstance = key;
\r
545 selectExecutionJobLog(key){
\r
546 this.selectedExecutionJobLog = key;
\r
550 selectExecutionExternalTaskLog(key){
\r
551 this.selectedExecutionExternalTaskLog = key;
\r
555 selectExecutionVariable(key){
\r
556 this.selectedExecutionVariable = key;
\r