2 ============LICENSE_START==========================================
3 ===================================================================
4 Copyright (C) 2018-19 IBM Intellectual Property. All rights reserved.
5 ===================================================================
7 Unless otherwise specified, all software contained herein is licensed
8 under the Apache License, Version 2.0 (the License);
9 you may not use this software except in compliance with the License.
10 You may obtain a copy of the License at
12 http://www.apache.org/licenses/LICENSE-2.0
14 Unless required by applicable law or agreed to in writing, software
15 distributed under the License is distributed on an "AS IS" BASIS,
16 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 See the License for the specific language governing permissions and
18 limitations under the License.
19 ============LICENSE_END============================================
22 import { Component, OnInit, ViewChild } from '@angular/core';
23 import { FlatTreeControl } from '@angular/cdk/tree';
24 import { MatTreeFlatDataSource, MatTreeFlattener } from '@angular/material/tree';
25 import { IBlueprint } from 'src/app/common/core/store/models/blueprint.model';
26 import "ace-builds/webpack-resolver";
28 import 'brace/ext/language_tools';
29 import 'ace-builds/src-min-noconflict/snippets/html';
30 import * as JSZip from 'jszip';
31 import { saveAs } from 'file-saver';
33 import { IAppState } from '../../../../common/core/store/state/app.state';
34 import { Store } from '@ngrx/store';
35 import { Observable } from 'rxjs';
36 import { IBlueprintState } from 'src/app/common/core/store/models/blueprintState.model';
37 import { LoadBlueprintSuccess, SetBlueprintState } from '../../../../common/core/store/actions/blueprint.action'
38 import { ApiService } from 'src/app/common/core/services/api.service';
39 import { IMetaData } from 'src/app/common/core/store/models/metadata.model';
40 import { EditorService } from './editor.service';
48 const TREE_DATA: Node[] = [
52 { name: 'activation-blueprint.json' },
53 { name: 'artifacts_types.json' },
54 { name: 'data_types.json' },
59 /** Flat node with expandable and level information */
60 interface ExampleFlatNode {
68 selector: 'app-editor',
69 templateUrl: './editor.component.html',
70 styleUrls: ['./editor.component.scss']
72 export class EditorComponent implements OnInit {
74 @ViewChild('editor') editor;
75 blueprintdata: IBlueprint;
76 blueprint: IBlueprint;
77 bpState: Observable<IBlueprintState>;
83 blueprintName: string;
84 fileExtension: string;
86 private zipFile: JSZip = new JSZip();
88 selectedFolder: string;
89 activationBlueprint: string;
90 isNameTextboxEnablled: boolean = false;
93 currentFilePath: string = '';
94 selectedFileObj = { name: '', type: '' };
95 viewTemplateMode: boolean = false;
97 'capability-data': [],
98 'resourceAccumulatorResolvedData': []
100 validfile: boolean = false;
101 @ViewChild('fileInput') fileInput;
105 private fileObject: any;
106 private tocsaMetadaData: any;
109 private transformer = (node: Node, level: number) => {
111 expandable: !!node.children && node.children.length > 0,
117 treeControl = new FlatTreeControl<ExampleFlatNode>(
118 node => node.level, node => node.expandable);
120 treeFlattener = new MatTreeFlattener(
121 this.transformer, node => node.level, node => node.expandable, node => node.children);
123 dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
125 artifactVersion: any;
127 constructor(private store: Store<IAppState>, private apiservice: EditorService) {
128 this.dataSource.data = TREE_DATA;
129 this.bpState = this.store.select('blueprint');
130 // this.dataSource.data = TREE_DATA;
133 hasChild = (_: number, node: ExampleFlatNode) => node.expandable;
136 this.editorContent();
137 this.dataSource.data = this.filesTree;
141 this.editor.setTheme("eclipse");
142 this.editor.getEditor().setOptions({
143 // enableBasicAutocompletion: true,
147 this.editor.getEditor().commands.addCommand({
148 name: "showOtherCompletions",
150 exec: function (editor) {
154 this.bpState.subscribe(
156 var blueprintState: IBlueprintState = { blueprint: blueprintdata.blueprint, isLoadSuccess: blueprintdata.isLoadSuccess, isSaveSuccess: blueprintdata.isSaveSuccess, isUpdateSuccess: blueprintdata.isUpdateSuccess };
157 this.blueprintdata = blueprintState.blueprint;
158 this.filesTree = blueprintdata.files;
159 this.filesData = blueprintdata.filesData;
160 this.dataSource.data = this.filesTree;
161 this.blueprintName = blueprintdata.name;
163 for (let key in this.blueprintdata) {
164 if (this.blueprintdata.hasOwnProperty(key)) {
165 blueprint.push(this.blueprintdata[key]);
168 this.metadata = blueprintState.blueprint.metadata;
169 let metadatavalues = [];
170 for (let key in this.metadata) {
171 if (this.metadata.hasOwnProperty(key)) {
172 metadatavalues.push(this.metadata[key]);
175 this.artifactName = metadatavalues[3];
176 this.artifactVersion = metadatavalues[4];
177 this.editor.getEditor().getSession().setTabSize(2);
178 this.editor.getEditor().getSession().setUseWrapMode(true);
179 this.editor.getEditor().getSession().setValue("");
180 this.setEditorMode();
185 // console.log(this.blueprint);
186 // this.filesData.forEach(fileNode => {
187 // if (this.selectedFile && fileNode.name.includes(this.blueprintName.trim()) && fileNode.name.includes(this.selectedFile.trim())) {
188 // fileNode.data = this.text;
189 // } else if (this.selectedFile && fileNode.name.includes(this.currentFilePath)) {
190 // // this.selectedFile && fileNode.name.includes(this.selectedFile.trim())) {
191 // fileNode.data = this.text;
195 // if (this.selectedFile && this.selectedFile == this.blueprintName.trim()) {
196 // this.blueprint = JSON.parse(this.text);
198 // this.blueprint = this.blueprintdata;
201 let blueprintState = {
202 blueprint: this.blueprint,
203 name: this.blueprintName,
204 files: this.filesTree,
205 filesData: this.filesData
207 this.store.dispatch(new SetBlueprintState(blueprintState));
208 // console.log(this.text);
211 selectFileToView(file) {
212 if (file.name.includes('.vtl')) { this.viewTemplateMode = true; } else { this.viewTemplateMode = false; }
213 this.currentFilePath = '';
214 this.expandParents(file);
215 this.selectedFileObj.name = file.name;
216 this.selectedFileObj.type = 'file';
217 this.selectedFile = file.name;
218 this.filetoDelete = file.name;
219 this.currentFilePath = this.currentFilePath + this.selectedFile;
220 this.filesData.forEach((fileNode) => {
221 if (fileNode.name.includes(file.name)) {
222 this.text = fileNode.data;
225 this.fileExtension = this.selectedFile.substr(this.selectedFile.lastIndexOf('.') + 1);
226 // console.log(this.fileExtension);
227 this.setEditorMode();
232 this.zipFile.generateAsync({ type: "blob" })
234 const formData = new FormData();
235 formData.append("file", blob);
236 this.apiservice.enrich("/enrich-blueprint/", formData)
239 this.zipFile.files = {};
240 this.zipFile.loadAsync(response)
243 this.buildFileViewData(zip);
244 console.log("processed");
247 window.alert('Blueprint enriched successfully');
256 this.zipFile.generateAsync({ type: "blob" })
258 const formData = new FormData();
259 formData.append("file", blob);
260 this.apiservice.post("/create-blueprint/", formData)
263 // console.log(data);
264 window.alert('Success:' + JSON.stringify(data));
273 this.zipFile.generateAsync({ type: "blob" })
275 const formData = new FormData();
276 formData.append("file", blob);
277 this.apiservice.deployPost("/deploy-blueprint/", formData)
279 // console.log(data);
280 window.alert('Saved Successfully:' + JSON.stringify(data));
288 this.zipFile.generateAsync({ type: "blob" })
290 const formData = new FormData();
291 formData.append("file", blob);
292 this.apiservice.post("/publish/", formData)
294 // console.log(data);
295 window.alert('Published:' + JSON.stringify(data));
303 this.filesData.forEach((path) => {
304 let index = path.name.indexOf("/");
305 let name = path.name.slice(index + 1, path.name.length);
306 this.zipFile.file(name, path.data);
311 console.log(this.artifactName);
312 status = this.apiservice.downloadCBA("/download-blueprint/" + this.artifactName + "/" + this.artifactVersion);
313 window.alert(status);
314 // .subscribe(response => {
315 // console.log(response);
316 // var blob = new Blob([response], { type: 'application/zip' });
317 // const fileName = 'CBA';
318 // saveAs(blob, fileName);
321 // console.log(error);
326 // var zipFilename = "baseconfiguration.zip";
327 // this.zipFile.generateAsync({ type: "blob" })
329 // saveAs(blob, zipFilename);
333 switch (this.fileExtension) {
338 this.mode = 'python';
341 this.mode = 'kotlin';
350 this.mode = 'velocity';
358 this.currentFilePath = '';
359 this.expandParents(node);
360 this.selectedFolder = node.name;
361 this.filetoDelete = node.name;
362 this.selectedFileObj.name = node.name;
363 this.selectedFileObj.type = 'folder';
364 this.currentFilePath = this.currentFilePath + this.selectedFolder + '/';
367 createFolderOrFile(name) {
368 if (name && name.srcElement.value !== null && name.srcElement.value !== '') {
369 let newFilesData: [any] = this.filesData;
378 if (this.fileAction == 'createFolder') {
379 newFileNode.name = this.currentFilePath + name.srcElement.value + '/'
380 newFileNode.data = '';
381 newFileNode1.name = this.currentFilePath + name.srcElement.value + '/README.md'
382 newFileNode1.data = name.srcElement.value + ' Folder';
383 this.filesData.push(newFileNode);
384 this.filesData.push(newFileNode1);
386 newFileNode.name = this.currentFilePath + name.srcElement.value;
387 newFileNode.data = '';
388 this.filesData.push(newFileNode);
390 this.arrangeTreeData(this.filesData);
394 findIndexForNewNode() {
396 for (let i = 0; i < this.filesData.length; i++) {
397 if (this.filesData[i].name.includes(this.selectedFolder)) {
401 return indexForNewNode;
404 async buildFileViewData(zip) {
405 this.validfile = false;
407 for (var file in zip.files) {
409 name: zip.files[file].name,
412 const value = <any>await zip.files[file].async('string');
413 this.fileObject.data = value;
414 this.paths.push(this.fileObject);
418 this.paths.forEach(path => {
419 if (path.name.includes("TOSCA.meta")) {
420 this.validfile = true
424 alert('Please update proper file');
427 if (this.validfile) {
428 this.fetchTOSACAMetadata();
429 this.filesData = this.paths;
430 this.tree = this.arrangeTreeData(this.paths);
432 alert('Please update proper file with TOSCA metadata');
436 fetchTOSACAMetadata() {
438 this.paths.forEach(file => {
439 if (file.name.includes('TOSCA.meta')) {
440 let keys = file.data.split("\n");
441 keys.forEach((key) => {
442 let propertyData = key.split(':');
443 toscaData[propertyData[0]] = propertyData[1];
447 this.blueprintName = (((toscaData['Entry-Definitions']).split('/'))[1]).toString();;
448 console.log(toscaData);
451 arrangeTreeData(paths) {
454 paths.forEach((path) => {
456 const pathParts = path.name.split('/');
457 let currentLevel = tree;
459 pathParts.forEach((part) => {
460 const existingPath = currentLevel.filter(level => level.name === part);
462 if (existingPath.length > 0) {
463 currentLevel = existingPath[0].children;
471 if (part.trim() == this.blueprintName.trim()) {
472 this.activationBlueprint = path.data;
473 newPart.data = JSON.parse(this.activationBlueprint.toString());
474 console.log('newpart', newPart);
476 if (newPart.name !== '') {
477 currentLevel.push(newPart);
478 currentLevel = newPart.children;
483 this.dataSource.data = tree;
484 this.filesTree = tree;
485 this.isNameTextboxEnablled = false;
486 this.updateBlueprint();
489 enableNameInputEl(action) {
490 this.fileAction = action;
491 if (action == 'createFolder' || action == 'createFile') {
492 this.isNameTextboxEnablled = true;
496 deleteFolderOrFile(action) {
497 for (let i = 0; i < this.filesData.length; i++) {
498 if (this.filesData[i].name.includes(this.filetoDelete.trim()) && this.filesData[i].name.includes(this.currentFilePath)) {
499 this.filesData.splice(i, 1);
503 this.arrangeTreeData(this.filesData);
506 expandParents(node) {
507 const parent = this.getParent(node);
508 this.treeControl.expand(parent);
510 if (parent && parent.level > 0) {
511 this.expandParents(parent);
514 console.log(this.currentFilePath);
518 const { treeControl } = this;
519 const currentLevel = treeControl.getLevel(node);
521 if (currentLevel < 1) {
522 // this.currentFilePath = this.currentFilePath + this.selectedFolder;
526 const startIndex = treeControl.dataNodes.indexOf(node) - 1;
528 for (let i = startIndex; i >= 0; i--) {
529 const currentNode = treeControl.dataNodes[i];
531 if (treeControl.getLevel(currentNode) < currentLevel) {
532 this.currentFilePath = currentNode.name + '/' + this.currentFilePath;
538 console.log(this.currentFilePath);
539 console.log(this.selectedFile);
540 console.log(this.selectedFileObj);
541 console.log(this.selectedFolder);
542 console.log(this.text);
544 let parsedData = JSON.parse(this.text);
545 this.paramData.resourceAccumulatorResolvedData = parsedData['resource-accumulator-resolved-data'];
548 this.paramData.resourceAccumulatorResolvedData.forEach(element => {
550 let tempElement = element['param-value'];
551 let indexLength = tempElement.length;
552 tempElement = tempElement.slice(2, indexLength);
553 let index = tempElement.indexOf('}');
554 tempElement = this.removeItemByIndex(tempElement, index);
555 element['param-value'] = tempElement;
561 removeItemByIndex(paramValue, index) {
563 return paramValue.slice(1)
564 } else if (index > 0) {
565 let indexLength = paramValue.length;
566 return paramValue.slice(0, index) + paramValue.slice(index + 1, indexLength);
572 saveEditedChanges() {
573 this.filesData.forEach(fileNode => {
574 if (this.selectedFile && fileNode.name.includes(this.blueprintName.trim()) && fileNode.name.includes(this.selectedFile.trim())) {
575 fileNode.data = this.text;
576 } else if (this.selectedFile && fileNode.name.includes(this.currentFilePath)) {
577 // this.selectedFile && fileNode.name.includes(this.selectedFile.trim())) {
578 fileNode.data = this.text;
582 if (this.selectedFile && this.selectedFile == this.blueprintName.trim()) {
583 this.blueprint = JSON.parse(this.text);
585 this.blueprint = this.blueprintdata;
588 this.updateBlueprint();