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, EventEmitter, Input, OnInit, Output, ViewChild, ElementRef, OnDestroy } from '@angular/core';
\r
18 import { MatDialog, MatSnackBar } from '@angular/material';
\r
19 import { SelectTestHeadModalComponent } from '../select-test-head-modal/select-test-head-modal.component';
\r
20 import { GroupService } from '../../services/group.service';
\r
21 import { TestDefinitionService } from '../../services/test-definition.service';
\r
22 import { AlertModalComponent } from '../alert-modal/alert-modal.component';
\r
23 import { Alert } from 'selenium-webdriver';
\r
24 import { ListService } from '../../services/list.service';
\r
25 import { AlertSnackbarComponent } from '../alert-snackbar/alert-snackbar.component';
\r
26 import { TestHeadService } from 'app/shared/services/test-head.service';
\r
27 import { FileUploader, FileItem, ParsedResponseHeaders } from 'ng2-file-upload';
\r
28 import { AppGlobals } from 'app/app.global';
\r
29 import { HttpHeaders } from '@angular/common/http';
\r
30 import { CookieService } from 'ngx-cookie-service';
\r
31 import { stringify } from '@angular/core/src/render3/util';
\r
32 import Modeler from 'bpmn-js';
\r
33 import { FileService } from 'app/shared/services/file.service';
\r
34 import { FileTransferService } from 'app/shared/services/file-transfer.service';
\r
35 import { TestDefinition } from './test-definition.class';
\r
36 import { connectableObservableDescriptor } from 'rxjs/internal/observable/ConnectableObservable';
\r
37 import { Buffer } from 'buffer';
\r
38 import { ViewWorkflowModalComponent } from '../view-workflow-modal/view-workflow-modal.component';
\r
39 import { BpmnFactoryService } from 'app/shared/factories/bpmn-factory.service';
\r
40 import { Bpmn } from 'app/shared/models/bpmn.model';
\r
44 selector: 'app-create-test-form',
\r
45 templateUrl: './create-test-form.component.pug',
\r
46 styleUrls: ['./create-test-form.component.scss']
\r
48 export class CreateTestFormComponent implements OnInit, OnDestroy {
\r
51 public codeConfig = {
\r
59 public selectedTestHead;
\r
62 public successUpload = false;
\r
63 public processDefinitionKey = false;
\r
64 public validateResponse;
\r
67 public hasBeenSaved = false;
\r
68 public saved = false;
\r
70 public isZip = true;
\r
71 public viewer: Bpmn;
\r
72 public scriptFiles = [];
\r
75 @ViewChild('testDefinitionForm') form: any;
\r
76 @ViewChild('canvas') canvas;
\r
77 @ViewChild('scripts') scripts: ElementRef;
\r
78 @ViewChild('file') bpmnFileInput: ElementRef;
\r
80 @Input() public listKey;
\r
82 @Input() public formData;
\r
84 @Output() public childEvent = new EventEmitter();
\r
86 public uploader: FileUploader;
\r
87 public bpmnUploader: FileUploader;
\r
89 public inProgress = false;
\r
92 public ptd: TestDefinition;
\r
93 public isNew = true;
\r
96 public dialog: MatDialog,
\r
97 private list: ListService,
\r
98 private testHead: TestHeadService,
\r
99 private group: GroupService,
\r
100 private testDefinition: TestDefinitionService,
\r
101 private snack: MatSnackBar,
\r
102 private cookie: CookieService,
\r
103 private fileTransfer: FileTransferService,
\r
104 private fileService: FileService,
\r
105 private bpmnFactory: BpmnFactoryService
\r
109 console.log(this.ptd);
\r
115 this.viewer = await this.bpmnFactory.setup({
\r
118 container: this.canvas.nativeElement
\r
122 this.ptd = new TestDefinition();
\r
124 this.ptd.switchVersion();
\r
126 let uploadOptions = {
\r
127 url: AppGlobals.baseAPIUrl + 'file-transfer',
\r
128 authTokenHeader: 'Authorization',
\r
129 authToken: 'Bearer ' + JSON.parse(this.cookie.get('access_token'))
\r
133 this.uploader = new FileUploader(uploadOptions);
\r
134 this.bpmnUploader = new FileUploader(uploadOptions);
\r
136 if (this.formData && this.formData !== 'new') {
\r
137 this.hasBeenSaved = true;
\r
138 this.successUpload = true;
\r
139 this.isNew = false;
\r
140 this.setTestDefinition();
\r
143 this.group.find({$limit: -1}).subscribe((x) => {
\r
154 return new Promise((resolve, reject) => {
\r
155 console.log('waitsave')
\r
157 this.saveBpmnFile().then(bpmnFile => {
\r
158 console.log(bpmnFile)
\r
159 console.log('pass save bpmnfile')
\r
160 this.checkTestDataTemplate();
\r
162 let data = this.gatherTestDefinition(bpmnFile);
\r
164 //If this is not a new version
\r
165 if(!this.existingTd){
\r
168 this.create(data).then(
\r
171 this.setTestDefinition(result);
\r
172 this.showHasBeenSaved();
\r
176 this.showHasNotBeenSaved();
\r
179 //create version by updating definition
\r
180 this.saveVersion(data).then(
\r
183 this.setTestDefinition(result);
\r
184 this.showHasBeenSaved();
\r
188 this.showHasNotBeenSaved();
\r
195 // Saves Test Definition - Triggered by "Save" button
\r
198 this.inProgress = true;
\r
199 return this.waitSave();
\r
203 // Updates Test Definition - Triggered by "Update" button
\r
205 this.inProgress = true;
\r
206 return this.saveBpmnFile().then(bpmnFile => {
\r
207 this.checkTestDataTemplate();
\r
209 var data = this.gatherTestDefinition(bpmnFile);
\r
211 return this.testDefinition.patch(data)
\r
214 this.uploadResources(result).then(
\r
216 this.setTestDefinition(res);
\r
217 this.showHasBeenUpdated();
\r
223 this.showHasNotBeenUpdated(error);
\r
230 let deleteDialog = this.dialog.open(AlertModalComponent, {
\r
232 data: { type: 'confirmation', message: 'Are you sure you want to delete version ' + this.ptd.currentVersionName }
\r
235 deleteDialog.afterClosed().subscribe(
\r
238 this.inProgress = true;
\r
239 if(this.ptd.bpmnInstances.length == 1){
\r
240 this.testDefinition.delete(this.ptd._id).subscribe(
\r
242 this.childEvent.emit();
\r
246 this.ptd.removeBpmnInstance(this.ptd.currentVersionName);
\r
247 this.update().then(
\r
249 this.inProgress = false;
\r
258 // Deploys Test Definition version - Triggerd by "Deploy" button
\r
259 deploy(versionName?) {
\r
260 this.inProgress = true;
\r
261 //console.log(this.ptd)
\r
262 this.testDefinition.deploy(this.ptd, versionName)
\r
263 .subscribe(result => {
\r
265 this.handleResponse(result);
\r
266 this.inProgress = false;
\r
267 if (result['statusCode'] == 200) {
\r
268 this.snack.openFromComponent(AlertSnackbarComponent, {
\r
271 message: 'Test Definition Deployed!'
\r
274 this.ptd.currentInstance.isDeployed = true;
\r
276 this.dialog.open(AlertModalComponent, {
\r
280 message: JSON.stringify(result)
\r
286 this.inProgress = false;
\r
293 return new Promise((resolve, reject) => {
\r
294 this.testDefinition.create(data)
\r
297 this.uploadResources(result).then(
\r
304 this.dialog.open(AlertModalComponent, {
\r
308 message: JSON.stringify(error)
\r
317 newVersion(processDefinitionKey){
\r
318 this.hasBeenSaved = false;
\r
321 this.ptd.switchVersion();
\r
322 this.ptd.setProcessDefinitionKey(processDefinitionKey);
\r
325 checkProcessDefinitionKey() {
\r
326 this.pStatus = 'loading';
\r
327 this.testDefinition.check(this.ptd.getProcessDefinitionKey()).subscribe(result => {
\r
328 console.log(result);
\r
329 if (result['statusCode'] == 200) {
\r
330 this.pStatus = 'unique';
\r
332 this.pStatus = 'notUnique';
\r
335 this.ptd.bpmnInstances = this.ptd.bpmnInstances.filter((e, i) => {
\r
339 // this.ptd.bpmnInstances.forEach((elem, val) => {
\r
341 // this.ptd.bpmnInstances.splice(val, 1);
\r
346 if(result['body'] && result['body'][0]){
\r
347 //when changing bpmn dont
\r
348 //if(this.ptd.currentInstance.isDeployed){
\r
349 let res = result['body'][0];
\r
350 this.existingTd = true;
\r
351 this.ptd.setId(res._id);
\r
352 this.ptd.setName(res.testName);
\r
353 this.ptd.setDescription(res.testDescription);
\r
354 this.ptd.setGroupId(res.groupId);
\r
355 this.ptd.setVersion(res.bpmnInstances.length + 1);
\r
356 //this.ptd.bpmnInstances = [];
\r
358 for(let i = 0; i < res.bpmnInstances.length; i++){
\r
359 this.ptd.addBpmnInstance(res.bpmnInstances[i]);
\r
363 //this.ptd.addBpmnInstance (res.bpmnInstances);
\r
366 this.existingTd = false;
\r
367 this.ptd.setId(null);
\r
368 this.ptd.setName('');
\r
369 this.ptd.setDescription('');
\r
370 this.ptd.setGroupId('');
\r
371 this.ptd.setVersion(1);
\r
374 if(!this.ptd.currentInstance.version){
\r
375 this.ptd.setNewVersion();
\r
383 this.isUploading = true
\r
384 this.fetchFileContents(val => {
\r
386 this.ptd.currentInstance.bpmnXml = val;
\r
387 if (!this.ptd.currentInstance.bpmnXml) {
\r
388 this.isUploading = false;
\r
389 this.dialog.open(AlertModalComponent, {
\r
393 message: 'File was not selected. Please try again.'
\r
399 this.testDefinition.validate(this.ptd.getAll())
\r
402 this.handleResponse(result);
\r
404 this.isUploading = false;
\r
405 this.ptd.currentInstance.bpmnHasChanged = true;
\r
406 this.loadDiagram();
\r
409 this.dialog.open(AlertModalComponent, {
\r
413 message: 'Something went wrong. Please try again'
\r
416 this.isUploading = false;
\r
424 showHasNotBeenSaved(){
\r
425 this.dialog.open(AlertModalComponent, {
\r
429 message: 'There was a problem with saving the test definition.'
\r
432 this.inProgress = false;
\r
435 showHasBeenSaved(){
\r
436 this.snack.openFromComponent(AlertSnackbarComponent, {
\r
439 message: 'Test Definition Saved!'
\r
442 //this.switchVersion();
\r
443 this.ptd.switchVersion();
\r
444 this.hasBeenSaved = true;
\r
446 this.form.form.markAsPristine();
\r
447 this.inProgress = false;
\r
450 showHasBeenUpdated(){
\r
451 this.snack.openFromComponent(AlertSnackbarComponent, {
\r
454 message: 'Test Definition Updated!'
\r
457 //this.switchVersion();
\r
458 this.ptd.switchVersion(this.ptd.currentInstance.version);
\r
460 this.form.form.markAsPristine();
\r
461 this.ptd.currentInstance.bpmnHasChanged = false;
\r
462 this.inProgress = false;
\r
465 showHasNotBeenUpdated(error = null){
\r
466 this.dialog.open(AlertModalComponent, {
\r
470 message: JSON.stringify(error)
\r
473 this.inProgress = false;
\r
476 setTestDefinition(data = null){
\r
480 this.ptd.setAll(data);
\r
482 this.ptd.setAll(JSON.parse(JSON.stringify(this.formData)));
\r
485 this.switchVersion();
\r
487 //console.log(this.ptd);
\r
492 this.uploader.clearQueue();
\r
494 this.scripts.nativeElement.value = null;
\r
498 switchVersion(versionName = null){
\r
499 this.ptd.switchVersion(versionName);
\r
500 this.checkTestDataTemplate();
\r
503 this.bpmnFileInput.nativeElement.value = null;
\r
505 //Get bpmn file contents
\r
506 this.fileTransfer.get(this.ptd.currentInstance.bpmnFileId).subscribe(
\r
508 result = new Buffer(result as Buffer);
\r
509 this.ptd.currentInstance.bpmnXml = result.toString();
\r
510 this.loadDiagram();
\r
514 //get info on resource file
\r
515 if(this.ptd.currentInstance.resourceFileId){
\r
516 this.fileService.get(this.ptd.currentInstance.resourceFileId).subscribe(
\r
518 this.ptd.currentInstance.resourceFileName = result['filename'];
\r
523 if(this.ptd.currentInstance.testHeads){
\r
524 this.ptd.currentInstance.dataTestHeads = [];
\r
525 this.ptd.currentInstance.testHeads.forEach((elem, val) => {
\r
526 //Find test head info
\r
528 this.testHead.get(e.testHeadId).subscribe(
\r
530 this.ptd.currentInstance.dataTestHeads.push({
\r
531 testHeadId: e.testHeadId,
\r
532 bpmnVthTaskId: e.bpmnVthTaskId,
\r
533 testHead: JSON.parse(JSON.stringify(result))
\r
537 this.ptd.currentInstance.dataTestHeads.push({
\r
538 testHeadId: e.testHeadId,
\r
539 bpmnVthTaskId: e.bpmnVthTaskId,
\r
540 testHead: { _id: e.testHeadId, testHeadName: 'No Access' }
\r
548 gatherTestDefinition(bpmnFile = null) {
\r
551 this.ptd.currentInstance.bpmnFileId = bpmnFile._id;
\r
554 this.ptd.currentInstance.testHeads = [];
\r
555 this.ptd.currentInstance.dataTestHeads.forEach((elem, val) => {
\r
556 this.ptd.currentInstance.testHeads.push({
\r
557 testHeadId: elem.testHead._id,
\r
558 bpmnVthTaskId: elem.bpmnVthTaskId
\r
562 return this.ptd.getAll();
\r
567 let version = JSON.parse(JSON.stringify(this.ptd.currentInstance.version));
\r
568 console.log(version)
\r
569 this.save().then(x => {
\r
570 this.deploy(version);
\r
575 let version = JSON.parse(JSON.stringify(this.ptd.currentInstance.version));
\r
576 this.update().then(x => {
\r
577 this.deploy(version);
\r
581 handleResponse(result) {
\r
582 this.successUpload = true;
\r
583 this.processDefinitionKey = false;
\r
584 //this.validateResponse = result;
\r
585 if (result['body']['errors']) {
\r
588 if (result['body']['errors']['processDefinitionKey']) {
\r
589 this.openProcessDefinitionKeyModal();
\r
590 this.pStatus = 'notUnique';
\r
591 this.ptd.setProcessDefinitionKey(result['body'].errors.processDefinitionKey.key)
\r
592 //this.td.processDefinitionKey = result['body']['errors']['processDefinitionKey']['key'];
\r
593 this.processDefinitionKey = true;
\r
595 if (result['body']['errors']['notFound']) {
\r
596 this.dialog.open(AlertModalComponent, {
\r
598 data: { type: 'alert', message: result['body']['errors']['notFound']['error'] }
\r
600 this.successUpload = false;
\r
602 if (result['body']['errors']['startEvent']) {
\r
603 this.dialog.open(AlertModalComponent, {
\r
605 data: { type: 'alert', message: result['body']['errors']['startEvent']['error'] }
\r
607 this.successUpload = false;
\r
609 if (result['body']['errors']['required']) {
\r
610 this.dialog.open(AlertModalComponent, {
\r
612 data: { type: 'alert', message: result['body']['errors']['required']['error'] }
\r
614 this.successUpload = false;
\r
616 if (result['body']['errors']['permissions']) {
\r
618 result['body']['errors']['permissions'].forEach(elem => {
\r
619 mess += elem.error + '\n';
\r
621 this.dialog.open(AlertModalComponent, {
\r
623 data: { type: 'alert', message: mess }
\r
625 this.successUpload = false;
\r
629 this.markAsDirty();
\r
631 // Update list of test heads
\r
632 if (result['body']['bpmnVthTaskIds']) {
\r
633 this.ptd.currentInstance.dataTestHeads = result['body'].bpmnVthTaskIds;
\r
634 this.ptd.currentInstance.testHeads = [];
\r
635 //this.definitionInstance.testHeads = result['body']['bpmnVthTaskIds'];
\r
638 //Update plfos list
\r
639 if(result['body']['bpmnPfloTaskIds']){
\r
640 this.ptd.currentInstance.pflos = result['body'].bpmnPfloTaskIds;
\r
643 if (result['body']['processDefinitionKey']) {
\r
644 this.ptd.setProcessDefinitionKey(result['body'].processDefinitionKey);
\r
645 //this.td.processDefinitionKey = result['body']['processDefinitionKey'];
\r
646 this.checkProcessDefinitionKey()
\r
651 this.form.control.markAsDirty();
\r
654 //returns promise for file object
\r
656 return new Promise((resolve, reject) => {
\r
658 //check for bpmnXml
\r
659 if (!this.ptd.currentInstance.bpmnXml) {
\r
660 this.dialog.open(AlertModalComponent, {
\r
664 message: 'No File found. Please select a file to upload'
\r
670 if(this.ptd.currentInstance.bpmnHasChanged){
\r
672 console.log('validate save call')
\r
673 this.testDefinition.validateSave(this.ptd).subscribe(
\r
675 resolve(JSON.parse(result.toString())[0]);
\r
679 //bpmn has not changed, so did not save it.
\r
686 return new Promise((resolve, reject) => {
\r
688 let newBpmnInsance = JSON.parse(JSON.stringify(data.bpmnInstances[0]));
\r
689 delete data.bpmnInstances;
\r
691 bpmnInstances: newBpmnInsance
\r
696 this.testDefinition.patch(data).subscribe(
\r
698 this.uploadResources(result).then(
\r
711 uploadResources(td){
\r
712 return new Promise((resolve, reject) => {
\r
713 if(this.uploader.queue.length > 0){
\r
714 //console.log('has file');
\r
715 this.uploader.uploadAll();
\r
716 this.uploader.onCompleteItem = (item: FileItem, response: string, status: Number, headers: ParsedResponseHeaders) => {
\r
717 this.scriptFiles.push(JSON.parse(response)[0]);
\r
718 //console.log('in file')
\r
720 this.uploader.onCompleteAll = () => {
\r
721 //console.log('complete')
\r
722 let scriptFilesId = [];
\r
723 for (let i = 0; i < this.scriptFiles.length; i++) {
\r
724 scriptFilesId.push(this.scriptFiles[i]['_id']);
\r
726 td['bpmnInstances'][this.ptd.currentVersion]['resourceFileId'] = scriptFilesId[0];
\r
728 this.testDefinition.patch(td).subscribe(
\r
730 //console.log(res);
\r
744 checkTestDataTemplate() {
\r
745 if (this.ptd.currentInstance.testDataTemplate == null || this.ptd.currentInstance.testDataTemplate == '') {
\r
746 delete this.ptd.currentInstance.testDataTemplate;
\r
748 // if (this.definitionInstance.testDataTemplate == null || this.definitionInstance.testDataTemplate == '') {
\r
749 // delete this.definitionInstance.testDataTemplate;
\r
753 async loadDiagram() {
\r
754 if (this.ptd.currentInstance.bpmnXml) {
\r
755 //render xml and display
\r
756 this.viewer.setBpmnXml(this.ptd.currentInstance.bpmnXml);
\r
757 // if (!this.viewer) {
\r
758 // this.viewer = new Modeler({
\r
759 // container: this.canvas.nativeElement
\r
763 // this.viewer.importXML(this.ptd.currentInstance.bpmnXml, (err) => {
\r
765 // this.viewer.get('canvas').zoom('fit-viewport');
\r
775 this.dialog.open(ViewWorkflowModalComponent, {
\r
777 xml: this.ptd.currentInstance.bpmnXml
\r
784 fetchFileContents(callback) {
\r
786 var fileToLoad = (document.getElementById('file'))['files'][0];
\r
787 var fileReader = new FileReader();
\r
791 fileReader.onload = function (event) {
\r
793 val = event.target['result'] as string;
\r
798 fileReader.readAsText(fileToLoad);
\r
801 openProcessDefinitionKeyModal() {
\r
802 const dialogRef = this.dialog.open(AlertModalComponent, {
\r
804 data: { type: 'warning', message: 'You cannot use this process definition key. Please change it.' }
\r
808 checkVersionUnique(){
\r
809 let exists = false;
\r
810 this.ptd.bpmnInstances.forEach(elem => {
\r
811 if(elem != this.ptd.currentInstance && elem.version == this.ptd.currentInstance.version){
\r
817 this.form.controls['version'].setErrors({error: 'Version Already Exists'});
\r
819 this.form.controls['version'].setErrors(null);
\r