diff options
author | Skip Wonnell <skip@att.com> | 2018-03-01 08:30:15 -0600 |
---|---|---|
committer | Skip Wonnell <skip@att.com> | 2018-03-01 08:33:56 -0600 |
commit | 2c977e2b66ced314a4f51121801f62fe5c3c05e4 (patch) | |
tree | d93b360d7a6502a6aff1f30ba7f96c3e14f8911c /src/app/vnfs/build-artifacts/template-holder | |
parent | 912f105d12fe6f8dc3a2d409938c87016204debe (diff) |
Initial seed code contribution for CDT
Issue-ID: APPC-682
Change-Id: I0331ffce2a430195c29d0d1b2295966f9eb28699
Signed-off-by: Skip Wonnell <skip@att.com>
Diffstat (limited to 'src/app/vnfs/build-artifacts/template-holder')
13 files changed, 2416 insertions, 0 deletions
diff --git a/src/app/vnfs/build-artifacts/template-holder/param-name-value/param-name-value.component.css b/src/app/vnfs/build-artifacts/template-holder/param-name-value/param-name-value.component.css new file mode 100644 index 0000000..94ef767 --- /dev/null +++ b/src/app/vnfs/build-artifacts/template-holder/param-name-value/param-name-value.component.css @@ -0,0 +1,35 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + +.file { + visibility: hidden; + position: absolute; +} + +.mt-30 { + margin-top: 30px; +} + +.active-tab > a { + border-bottom: 5px solid #4B515D; +}
\ No newline at end of file diff --git a/src/app/vnfs/build-artifacts/template-holder/param-name-value/param-name-value.component.html b/src/app/vnfs/build-artifacts/template-holder/param-name-value/param-name-value.component.html new file mode 100644 index 0000000..150d5ad --- /dev/null +++ b/src/app/vnfs/build-artifacts/template-holder/param-name-value/param-name-value.component.html @@ -0,0 +1,119 @@ +<!-- +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +--> + +<simple-notifications [options]="options"></simple-notifications> +<ng-progress [positionUsing]="'marginLeft'" [minimum]="0.15" [maximum]="1" [speed]="200" [showSpinner]="false" [direction]="'leftToRightIncreased'" [color]="'#6ab344'" + [trickleSpeed]="250" [thick]="true" [ease]="'linear'"></ng-progress> + +<tabs> + <tab [tabTitle]="'Template Configuration'"> + <div> + <app-golden-configuration [(configMappingEditorContent)]="configMappingEditorContent" [isMappingComp]="true" #mappingComponent> + </app-golden-configuration> + </div> + </tab> + <tab [tabTitle]="'Param Values'"> + <div class="form-group"> + <div [hidden]="true"> + <button type="button" id="modalButton" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--primary" (click)="modal.open()">Open me! + </button> + </div> + <div> + <modal #modal> + <modal-header [show-close]="true"> + <h4 class="modal-title">{{title}}</h4> + </modal-header> + <modal-body> + {{message}} + </modal-body> + <modal-footer> + <button type="button" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent" data-dismiss="modal">Close + </button> + </modal-footer> + </modal> + </div> + <div class="card" style=" margin-bottom: 23px;"> + <img class="card-img-top" data-src="holder.js/100%x180/" alt=""> + <div class="card-block" style="border-top: 5px solid #6ab344;border-top-right-radius: 7px;border-top-left-radius: 7px;"> + <div class="row" style="padding: 15px 25px"> + <div class="col-lg-3 col-sm-6 col-md-3 col-xs-12"> + <label>Action</label> + <input class="form-control" type="text" disabled value="{{action}}" /> + </div> + <div class="col-lg-3 col-sm-6 col-md-3 col-xs-12"> + <label>Vnf Type</label><input class="form-control" type="text" disabled value="{{vnfType}}" /> + </div> + <div class="col-lg-3 col-sm-6 col-md-3 col-xs-12"> + <label>Vnfc Type</label><input class="form-control" type="text" disabled value="{{vnfcType}}" /> + </div> + <div class="col-lg-3 col-sm-6 col-md-3 col-xs-12"> + <label>Protocol</label><input class="form-control" type="text" disabled value="{{protocol}}" /> + </div> + </div> + </div> + </div> + + <div class="col-12"> + <div class="input-group"> + <input id="inputFile2" class="file" #myInput type='file' (change)='fileChange(myInput)'> + <input type="text" class="input-lg" [(ngModel)]="myfileName" disabled placeholder="Upload Param file from PC" style="width:80%"> + <button (click)="browseOption($event)" [disabled]="!enableMappingBrowse" class="browse mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--primary input-lg"> + Upload Param file + </button> + </div> + </div> + + <input type="file" id="filesparam" style="visibility:hidden;" class="form-control-file" (change)="fileParamChange(myInputParam)" #myInputParam placeholder="Upload file..." + /> + <div class="row" style="margin-bottom: 20px;"> + <div class="col-md-12 text-right"> + <button type="button" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--primary" (click)="retrieveNameValueFromAppc()">Retrieve Name/Value from APPC + </button> + <button type="button" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--primary" (click)="syncParam()">Synchronize with name values + </button> + </div> + </div> + </div> + <hr> + <!--Commenting out 1712 changes here--> + <!--<div class="col-md-12" [hidden]="!showMappingDownloadDiv"><label>Download Name/Value pair as : </label> + <select class="form-control col-md-3" [(ngModel)]="mapppingDownloadType" (ngModelChange)="onDownloadParameter()"> + <option value="">Select</option> + <option value="Json">JSON</option> + <option value="Xls">XLS</option> + </select> +</div>--> + + <div class="col-md-12"></div> + <div><label for="textAreaGeneratedTemplate"> + <div class="mdl-card__title-text">Param Name Value List</div> + <div><font size="1">(Please click anywhere on the editor to see the synced name value pairs)</font></div> + </label> + <!-- <ace-editor [(text)]="this.artifactRequest.paramsContent" [theme]="'chrome'" [mode]="'velocity'" (textChanged)="onParamChanges($event)" [options]="{maxLines: 'Infinity', fontSize: '13pt'}" + style="min-height: 500px; width: fit-content;"></ace-editor> --> + <ace-editor [(text)]="this.artifactRequest.paramsContent" #templateeditor [theme]="'chrome'" [mode]="'velocity'" (textChanged)="onParamChanges($event)" + [options]="{maxLines: 'Infinity', fontSize: '13pt' }" style="min-height: 500px; width: 100%"></ace-editor> + </div> + + </tab> +</tabs>
\ No newline at end of file diff --git a/src/app/vnfs/build-artifacts/template-holder/param-name-value/param-name-value.component.ts b/src/app/vnfs/build-artifacts/template-holder/param-name-value/param-name-value.component.ts new file mode 100644 index 0000000..9ea95ec --- /dev/null +++ b/src/app/vnfs/build-artifacts/template-holder/param-name-value/param-name-value.component.ts @@ -0,0 +1,711 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + +import { Component, ContentChildren, OnInit, QueryList, ViewChild } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { MappingEditorService } from '../../../../shared/services/mapping-editor.service'; +import { HttpUtilService } from '../../../../shared/services/httpUtil/http-util.service'; +import { GoldenConfigurationComponent } from '../template-configuration/template-configuration.component'; +import { ArtifactRequest } from '../../../../shared/models/index'; +import { NotificationService } from '../../../../shared/services/notification.service'; +import { ModalComponent } from '../../../../shared/modal/modal.component'; +import { saveAs } from 'file-saver'; +import { DialogService } from 'ng2-bootstrap-modal'; +import { ConfirmComponent } from '../../../../shared/confirmModal/confirm.component'; +import { BuildDesignComponent } from '../../build-artifacts.component'; +import { ParamShareService } from '../../../../shared/services/paramShare.service'; +import { NotificationsService } from 'angular2-notifications'; +import { Tab } from './tab'; +import { environment } from '../../../../../environments/environment'; +import { NgProgress } from 'ngx-progressbar'; +import * as XLSX from 'xlsx'; + +type AOA = Array<Array<any>>; + +function s2ab(s: string): ArrayBuffer { + const buf = new ArrayBuffer(s.length); + const view = new Uint8Array(buf); + for (let i = 0; i !== s.length; ++i) { + view[i] = s.charCodeAt(i) & 0xFF; + } + return buf; +} + +declare var $: any; + +@Component({ + selector: 'app-golden-configuration-mapping', + templateUrl: './param-name-value.component.html', + styleUrls: ['./param-name-value.component.css'] +}) +export class GoldenConfigurationMappingComponent implements OnInit { + enableMappingSave: boolean = false; + aceText: string = ''; + fileName: string = ''; + actionType: any; + modal: any; + configMappingEditorContent: any; + fileType: any = ''; + myfileName: any; + initialData: any; + scopeName: any; + downloadedFileName: any; + enableSaveToAppc: boolean = false; + versionNo: any = '0.0.1'; + showVersionDiv: boolean = false; + initialAction: any; + title: any; + message: any; + enableMappingBrowse: boolean = true; + enableDownload: boolean = false; + showMappingDownloadDiv: boolean = false; + mapppingDownloadType: any; + action: any; + artifactName: any; + enableMerge: boolean = false; + apiToken = localStorage['apiToken']; + userId = localStorage['userId']; + public uploadTypes = [ + { + value: 'Mapping Data', + display: 'Sample Json Param File' + } + ]; + selectedUploadType: string = this.uploadTypes[0].value; + options = { + timeOut: 1000, + showProgressBar: true, + pauseOnHover: true, + clickToClose: true, + maxLength: 200 + }; + artifactRequest: ArtifactRequest = new ArtifactRequest(); + @ViewChild(GoldenConfigurationComponent) mappingComponent: GoldenConfigurationComponent; + @ViewChild('templateeditor') templateeditor; + @ViewChild('myInputParam') myInputParam: any; + @ViewChild(ModalComponent) modalComponent: ModalComponent; + @ContentChildren(Tab) tabs: QueryList<Tab>; + public subscription: any; + public item: any = {}; + + public Actions = [ + { action: 'ConfigBackup', value: 'ConfigBackup' }, + { action: 'ConfigModify', value: 'ConfigModify' }, + { action: 'ConfigRestore', value: 'ConfigRestore' }, + { action: 'Configure', value: 'Configure' }, + { action: 'GetRunningConfig', value: 'GetRunningConfig' }, + { action: 'HealthCheck', value: 'HealthCheck' }, + { action: 'StartApplication', value: 'StartApplication' }, + { action: 'StopApplication', value: 'StopApplication' } + ]; + vnfType: any; + vnfcType: any; + protocol: any; + refObj: any; + public paramsContent = localStorage['paramsContent']; + + constructor (private buildDesignComponent: BuildDesignComponent, private paramShareService: ParamShareService, private router: Router, private httpUtil: HttpUtilService, private dialogService: DialogService, private activeRoutes: ActivatedRoute, private mappingEditorService: MappingEditorService, private notificationService: NotificationService, private nService: NotificationsService, private ngProgress: NgProgress) { + this.artifactRequest.action = ''; + this.artifactRequest.version = ''; + this.artifactRequest.paramKeysContent = ''; + } + + ngOnInit() { + var refObj = this.refObj = this.prepareFileName(); + if (refObj && refObj != undefined) { + if (this.paramsContent && this.paramsContent != undefined && this.paramsContent !== '{}') { + this.artifactRequest.paramsContent = this.formatNameValuePairs(this.paramsContent); + // this.artifactRequest.paramsContent = this.paramsContent; + + } + else { + this.artifactRequest.paramsContent = '{}'; + } + + // refObj = refObj[refObj.length - 1]; + this.item = refObj; + this.vnfType = this.item.scope['vnf-type']; + this.vnfcType = this.item.scope['vnfc-type']; + this.protocol = this.item['device-protocol']; + this.action = this.item.action; + var artifactList = this.item['artifact-list']; + for (var i = 0; i < artifactList.length; i++) { + var artifactName = artifactList[i]['artifact-name']; + var array = artifactName.split('_'); + if (array[0].toUpperCase() === 'TEMPLATE') { + this.artifactName = artifactName; + } + } + } + else { + this.item = { + 'action': '', + 'scope': { 'vnf-type': '', 'vnfc-type': '' }, + 'vm': [], + 'protocol': '', + 'download-dg-reference': '', + 'user-name': '', + 'port-number': '', + 'artifact-list': [], + 'deviceTemplate': '', + 'scopeType': '' + }; + } + this.initialAction = this.item.action; + this.activeRoutes.url.subscribe(UrlSegment => { + this.actionType = UrlSegment[0].path; + }); + if (this.actionType === 'configureTemplate') { + this.mappingEditorService.fromScreen = 'TemplateScreen'; + } + if (this.actionType === 'myTemplates') { + this.mappingEditorService.fromScreen = 'MappingScreen'; + } + this.mappingEditorService.paramData = []; + + + } + + //========================== End of ngOnInit() Method============================================ + browseOption() { + $('#filesparam').trigger('click'); + } + + //========================== End of browseOption() Method============================================ + selectedNavItem(item: any) { + this.item = item; + } + + //========================== End of selectedNavItem() Method============================================ + ngOnDestroy() { + this.prepareFileName(); + } + + //========================== End of ngOnDestroy() Method============================================ + ngAfterViewInit() { + if (this.mappingEditorService.fromScreen === 'MappingScreen') { + this.configMappingEditorContent = this.mappingEditorService.getTemplateMappingDataFromStore(); + this.fileType = sessionStorage.getItem('fileType'); + if (this.configMappingEditorContent) + this.mappingEditorService.initialise(this.mappingComponent.templateeditor.getEditor(), this.configMappingEditorContent, this.modal); + } + if (this.refObj) { + + this.artifactRequest.action = this.item.action; + this.artifactRequest.vnfType = this.vnfType; + if (this.vnfcType && this.vnfcType.length != 0) { + this.scopeName = this.vnfcType; + } + else { + this.scopeName = this.vnfType; + } + } + else { + this.Actions = []; + this.enableMappingBrowse = false; + } + } + + //========================== End of ngAfterViewInit() Method============================================ + upload(evt: any) { + /* wire up file reader */ + if (evt.target.files[0]) { + const target: DataTransfer = <DataTransfer>(evt.target); + this.myfileName = evt.target.files[0].name; + var fileExtension = this.myfileName.substr(this.myfileName.lastIndexOf('.') + 1); + if (fileExtension.toUpperCase() === 'xls'.toUpperCase()) { + if (target.files.length != 1) { + throw new Error('Cannot upload multiple files on the entry'); + } + const reader = new FileReader(); + reader.onload = (e: any) => { + /* read workbook */ + const bstr = e.target.result; + const wb = XLSX.read(bstr, { type: 'binary' }); + /* grab first sheet */ + const wsname = wb.SheetNames[0]; + const ws = wb.Sheets[wsname]; + /* save data */ + let arrData = (<AOA>(XLSX.utils.sheet_to_json(ws, { header: 1 }))); + var jsonStr = arrData.toString(); + var JsonArr = jsonStr.split(','); + var finalStr = '{\r\n'; + for (var i = 0; i < JsonArr.length; i = i + 2) { + var key = JsonArr[i]; + var value = JsonArr[i + 1]; + finalStr = finalStr + key + ':' + value + ',\r\n'; + } + finalStr = finalStr.substring(0, finalStr.length - 3) + '\r\n}'; + this.artifactRequest.paramsContent = finalStr; + this.initialData = finalStr; + this.enableMappingSave = true; + }; + reader.readAsBinaryString(target.files[0]); + if ('Mapping Data' === this.selectedUploadType) { + this.notificationService.notifySuccessMessage('Configuration Template file successfully uploaded..'); + this.mappingEditorService.setParamContent(this.artifactRequest.paramsContent); + } + } + else { + let reader = new FileReader(); + this.readFile(evt.target.files[0], reader, (result) => { + if ('Mapping Data' === this.selectedUploadType) { + var jsonObject = JSON.parse(result); + this.artifactRequest.paramsContent = JSON.stringify(jsonObject, null, 1); + this.notificationService.notifySuccessMessage('Configuration Template file successfully uploaded..'); + this.mappingEditorService.setParamContent(this.artifactRequest.paramsContent); + } + this.initialData = result; + this.enableMappingSave = true; + }); + } + } + else { + this.notificationService.notifyErrorMessage('Failed to reading file..'); + } + this.myInputParam.nativeElement.value = ''; + } + + //========================== End of upload() Method============================================ + //uncommenting for 1710 + public fileParamChange(input) { + if (input.files && input.files[0]) { + this.enableMappingSave = true; + this.myfileName = input.files[0].name; + var fileExtension = this.myfileName.substr(this.myfileName.lastIndexOf('.') + 1); + if (this.validateUploadedFile(fileExtension)) { + // Create the file reader + let reader = new FileReader(); + this.readFile(input.files[0], reader, (result) => { + if ('Mapping Data' === this.selectedUploadType) { + var jsonObject = JSON.parse(result); + this.artifactRequest.paramsContent = JSON.stringify(jsonObject, null, 1); + this.notificationService.notifySuccessMessage('Configuration Template file successfully uploaded..'); + this.mappingEditorService.setParamContent(this.artifactRequest.paramsContent); + localStorage['paramsContent'] = this.artifactRequest.paramsContent; + } + this.enableMerge = true; + this.initialData = result; + }); + } + else { + this.nService.error("Error", "Incorrect File Format") + this.artifactRequest.paramsContent = '' + } + } + else { + this.nService.error("Error", "Failed to read file"); + } + this.myInputParam.nativeElement.value = ''; + } + + //========================== End of fileParamChange() Method============================================ + validateUploadedFile(fileExtension) { + + if (fileExtension.toUpperCase() === 'json'.toUpperCase()) { + return true; + } + else { + return false; + } + + } + //========================== End of validateUploadedFile() Method============================================ + public readFile(file, reader, callback) { + // Set a callback funtion to fire after the file is fully loaded + reader.onload = () => { + // callback with the results + callback(reader.result); + }; + this.notificationService.notifySuccessMessage('Uploading File ' + file.name + ':' + file.type + ':' + file.size); + // Read the file + reader.readAsText(file, 'UTF-8'); + } + + //========================== End of readFile() Method============================================ + public onParamChanges(data) { + this.artifactRequest.paramsContent = data; + localStorage['paramsContent'] = this.artifactRequest.paramsContent; + } + + //========================== End of onParamChanges() Method============================================ + onDownloadParameter() { + let refObj = this.refObj; + if (refObj) { + // refObj = refObj[refObj.length - 1]; + let paramsKeyValueFromEditor: JSON; + this.initialData = this.artifactRequest.paramsContent; + paramsKeyValueFromEditor = JSON.parse(this.artifactRequest.paramsContent); + let theJSON = JSON.stringify(paramsKeyValueFromEditor, null, '\t'); + var blob = new Blob([theJSON], { + type: 'text/json' + }); + this.showVersionDiv = true; + let fileName: any; + fileName = this.updateFileName(refObj.action, this.scopeName, this.versionNo); + saveAs(blob, fileName); + } + else { + this.nService.error('Error', 'Please enter Action and VNF type in Reference Data screen'); + + } + } + + //========================== End of onDownloadParameter() Method============================================ + JSONToCSVConvertor(JSONData, fileName, ShowLabel) { + //If JSONData is not an object then JSON.parse will parse the JSON string in an Object + var arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData; + var CSV = ''; + //This condition will generate the Label/Header + if (ShowLabel) { + var testRow = ''; + for (var index in arrData[0]) { + CSV += index + '\t' + arrData[0][index] + '\r\n'; + } + } + if (CSV == '') { + return; + } + //Initialize file format you want csv or xls + var uri = 'data:application/vnd.ms-excel,' + encodeURI(CSV); + var link = document.createElement('a'); + link.href = uri; + link.download = fileName + '.xls'; + //this part will append the anchor tag and remove it after automatic click + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } + + //========================== End of JSONToCSVConvertor() Method============================================ + updateFileNameForXls(action: any, scopeName: any, versionNo: any) { + let fileName = 'param_' + action + '_' + scopeName + '_' + versionNo + 'V'; + return fileName; + } + + //========================== End of updateFileNameForXls() Method============================================ + appendSlashes(artifactData) { + let x = artifactData.replace(new RegExp(',"', 'g'), ',\"'); + let y = x.replace(new RegExp('":', 'g'), '\":'); + let z = y.replace(new RegExp('{"', 'g'), '{\"'); + let t = z.replace(new RegExp(':"', 'g'), ':\"'); + let m = t.replace(new RegExp('",', 'g'), '\",'); + let n = y.replace(new RegExp('"}', 'g'), '\"}'); + let nw = n.replace(new RegExp('{"', 'g'), '{\"'); + let nw1 = nw.replace(new RegExp(':"', 'g'), ':\"'); + let nw2 = nw1.replace(new RegExp('",', 'g'), '\",'); + return nw2; + } + + //========================== End of appendSlashes() Method============================================ + updateFileName(action: any, scopeName: any, versionNo: any) { + let fileName = 'param_' + action + '_' + scopeName + '_' + versionNo + 'V.json'; + this.downloadedFileName = fileName; + return fileName; + } + + //========================== End of updateFileName() Method============================================ + prepareFileName(): any { + let fileNameObject: any = this.mappingEditorService.latestAction; + return fileNameObject; + } + + //========================== End of prepareFileName() Method============================================ + openModel(toShow: any, message: any, title: any) { + this.message = message; + this.title = title; + $('#modalButton').trigger('click'); + } + + //========================== End of openModel() Method============================================ + checkSave(selectedAction): void { + if (this.actionType === 'updateTemplate') { + if (!this.buildDesignComponent.isReferenceFound(selectedAction, this.mappingEditorService.getReferenceList())) { + this.nService.error('Error', 'Reference Data not found. Please add Reference Data for Action:' + selectedAction); + } + } + if (this.initialData != this.artifactRequest.paramsContent) { + this.showConfirm(this.initialData); + } + else { + this.initialAction = this.item.action; + } + } + + //========================== End of checkSave() Method============================================ + showConfirm(initialData) { + let disposable = this.dialogService.addDialog(ConfirmComponent, { + title: 'Confirm title', + message: 'Confirm message' + }) + .subscribe((isConfirmed) => { + //We get dialog result + if (isConfirmed) { + this.artifactRequest.paramsContent = initialData; + this.initialAction = this.item.action; + } + else { + this.item.action = this.initialAction; + } + }); + } + + //========================== End of showConfirm() Method============================================ + retrieveNameValueFromAppc() { + let refObj = this.refObj; + if (refObj && refObj != undefined) { + // console.log("REF OBJECT IN RETRIVE"+JSON.stringify(refObj)); + this.enableMerge = true; + var scopeName = this.scopeName.replace(/ /g, '').replace(new RegExp('/', "g"), '_').replace(/ /g, ''); + let fileName = this.updateFileName(this.item.action, scopeName, this.versionNo); + let payload = '{"userID": "' + this.userId + '", "action": "' + this.item.action + '", "vnf-type" : "' + this.vnfType + '", "artifact-type":"APPC-CONFIG", "artifact-name":"' + fileName + '"}'; + // console.log("payload OBJECT IN RETRIVE"+JSON.stringify(payload)); + let input = { + 'input': { + 'design-request': { + 'request-id': this.apiToken, + 'action': 'getArtifact', + 'payload': payload + } + } + }; + + console.log('Retrieve name value from appc payload===>>' + payload); + let artifactContent: any; + this.ngProgress.start(); + this.httpUtil.post({ + url: environment.getDesigns, + data: input + }).subscribe(resp => { + if (resp.output.status.code === '400' && resp.output.status.message === 'success') { + this.nService.success('Success', 'Name/value pairs retrieved successfully from APPC'); + this.enableMerge = true; + let result = JSON.parse(resp.output.data.block).artifactInfo[0]; + result = result['artifact-content']; + var string = result.substring(2, result.length - 2); + var stringArr = string.split(','); + var newStringArr = []; + var resultStr = '{\r\n'; + for (var index in stringArr) { + newStringArr[index] = stringArr[index] + ',\r\n'; + } + for (var index in newStringArr) { + resultStr = resultStr + newStringArr[index]; + } + resultStr = resultStr.substring(0, resultStr.length - 3) + '\r\n}'; + this.artifactRequest.paramsContent = resultStr; + this.mappingEditorService.setParamContent(resultStr); + localStorage['paramsContent'] = resultStr; + this.enableMappingSave = true; + } + else { + this.nService.info('Information', 'There are no name value pairs saved in APPC for the selected action!'); + } + this.ngProgress.done(); + }, + error => this.nService.error('Error', 'Error in connecting to APPC Server')); + } + setTimeout(() => { + this.ngProgress.done(); + }, 3500); + } + + //========================== End of retrieveNameValueFromAppc() Method============================================ + saveNameValueToAppc() { + let refObj = this.refObj; + if (refObj && refObj != undefined) { + // refObj = refObj[refObj.length - 1]; + let paramsKeyValueFromEditor = JSON.parse(this.artifactRequest.paramsContent); + let action = this.item.action; + let fileName = this.updateFileName(refObj.action, this.scopeName, this.versionNo); + let vnfType = this.vnfType; + let Json = [paramsKeyValueFromEditor]; + let slashedPayload = this.appendSlashes(JSON.stringify(Json)); + let newPayload = + { + 'userID': this.userId, + 'vnf-type': this.vnfType, + 'action': action, + 'artifact-name': fileName, + 'artifact-type': 'APPC-CONFIG', + 'artifact-version': this.versionNo, + 'artifact-contents': slashedPayload + }; + let data = + { + 'input': { + 'design-request': { + 'request-id': this.apiToken, + 'action': 'uploadArtifact', + 'payload': JSON.stringify(newPayload) + } + } + }; + this + .httpUtil + .post( + { url: environment.getDesigns, data: data }) + .subscribe(resp => { + if (resp.output.status.code === '400' && resp.output.status.message === 'success') { + this.nService.success('Success', 'Name/value pairs saved successfully to APPC'); + } + if (resp.output.status.code === '401') { + this.nService.error('Error', resp.output.status.message); + } + }, + error => this.nService.error('Error', 'Could not save name value pairs. Error in connecting APPC Server')); + } + setTimeout(() => { + this.ngProgress.done(); + }, 3500); + } + + //========================== End of saveNameValueToAppc() Method============================================ + formatNameValuePairs(namevaluePairs: string) { + //var string = namevaluePairs.substring(2, namevaluePairs.length - 2); + /* var stringArr = string.split(","); + var newStringArr = []; + var resultStr = "{\r\n\""; + for (var index in stringArr) { + newStringArr[index] = stringArr[index] + ",\r\n"; + } + for (var index in newStringArr) { + resultStr = resultStr + newStringArr[index]; + } + resultStr = resultStr.substring(0, resultStr.length - 3) + "\"\r\n}" + return resultStr;*/ + + var string = namevaluePairs.substring(1, namevaluePairs.length - 1); + var stringArr = string.split(','); + var newStringArr = []; + var resultStr = '{\r\n'; + for (var index in stringArr) { + newStringArr[index] = stringArr[index] + ',\r\n'; + } + for (var index in newStringArr) { + resultStr = resultStr + newStringArr[index]; + } + resultStr = resultStr.substring(0, resultStr.length - 3) + '\r\n}'; + return resultStr; + } + + //========================== End of formatNameValuePairs() Method============================================ + + public syncParam() { + var paramNameValuesStr = localStorage['paramsContent']; + var pdData = this.paramShareService.getSessionParamData(); + var paramNameValues = []; + var pdDataArrayForParamShare = []; + var pdDataArrayForSession = []; + try { + paramNameValues = JSON.parse(paramNameValuesStr); + console.log('Param Name values array==' + JSON.stringify(paramNameValues)); + if (paramNameValues && paramNameValues != undefined) { + for (var index in paramNameValues) { + var json = { + 'paramName': index, + 'paramValue': paramNameValues[index] + }; + pdDataArrayForParamShare.push(json); + + pdDataArrayForSession.push({ + 'name': index, + 'type': null, + 'description': null, + 'required': null, + 'default': null, + 'source': 'Manual', + 'rule-type': null, + 'request-keys': [{ + 'key-name': null, + 'key-value': null + }, { + 'key-name': null, + 'key-value': null + }, { + 'key-name': null, + 'key-value': null + }], + 'response-keys': [{ + 'key-name': null, + 'key-value': null + }, { + 'key-name': null, + 'key-value': null + }, { + 'key-name': null, + 'key-value': null + }, { + 'key-name': null, + 'key-value': null + }, { + 'key-name': null, + 'key-value': null + }], + 'ruleTypeValues': [null] + + }); + + } + this.paramShareService.setTemplateData(pdDataArrayForParamShare); + + if (pdData && pdData != undefined) { + for (var i = 0; i < pdDataArrayForSession.length; i++) { + + pdData.forEach(function (arr2item) { + if (pdDataArrayForSession[i].name === arr2item.name) { + + var json = { + 'name': arr2item.name, + 'type': arr2item.type, + 'description': arr2item.description, + 'required': arr2item.required, + 'default': arr2item.default, + 'source': arr2item.source, + 'rule-type': arr2item['rule-type'], + 'request-keys': arr2item['request-keys'], + 'response-keys': arr2item['response-keys'], + 'ruleTypeValues': arr2item.ruleTypeValues + }; + pdDataArrayForSession.splice(i, 1, json); + // console.log("Result array index ==" + JSON.stringify(resultArr[i])) + } + + }); + + } + } + + this.paramShareService.setSessionParamData(pdDataArrayForSession); + + this.router.navigate(['../../../vnfs/design/parameterDefinitions/create']); + + } + } + catch (error) { + console.log('Error occured in syncing param names' + JSON.stringify(error)); + this.nService.error('Error', 'Error synchronising with name values. Please check the format of json uploaded/ retrieved'); + } + } + +}
\ No newline at end of file diff --git a/src/app/vnfs/build-artifacts/template-holder/param-name-value/tab.ts b/src/app/vnfs/build-artifacts/template-holder/param-name-value/tab.ts new file mode 100644 index 0000000..5e4fa6c --- /dev/null +++ b/src/app/vnfs/build-artifacts/template-holder/param-name-value/tab.ts @@ -0,0 +1,43 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + +import {Component, Input} from '@angular/core'; + +@Component({ + selector: 'tab', + styles: [` + .pane { + padding: 1em; + } + `], + template: ` + <div [hidden]="!isactive" class="pane"> + <ng-content></ng-content> + </div> + ` +}) +export class Tab { + @Input('tabTitle') title: string; + @Input() isactive = false; + @Input() isParamTab = false; +}
\ No newline at end of file diff --git a/src/app/vnfs/build-artifacts/template-holder/param-name-value/tabs.ts b/src/app/vnfs/build-artifacts/template-holder/param-name-value/tabs.ts new file mode 100644 index 0000000..92f489e --- /dev/null +++ b/src/app/vnfs/build-artifacts/template-holder/param-name-value/tabs.ts @@ -0,0 +1,63 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + +import {AfterContentInit, Component, ContentChildren, QueryList} from '@angular/core'; +import {Tab} from './tab'; + +@Component({ + selector: 'tabs', + template: ` + <ul class="nav nav-tabs"> + <li [ngClass]="{'active-tab':(tab.isactive==true)}" class="nav-item" *ngFor="let tab of tabs" (click)="selectTab(tab)" + [class.active]="tab.isactive"> + <a class="nav-link" ng-href=''>{{tab.title}}</a> + </li> + </ul> + <ng-content></ng-content> + `, styleUrls: ['./param-name-value.component.css'] +}) +export class Tabs implements AfterContentInit { + + @ContentChildren(Tab) tabs: QueryList<Tab>; + + + // contentChildren are set + ngAfterContentInit() { + // get all active tabs + let activeTabs = this.tabs.filter((tab) => tab.isactive); + + // if there is no active tab set, activate the first + if (activeTabs.length === 0) { + this.selectTab(this.tabs.first); + } + } + + public selectTab(tab: Tab) { + // deactivate all tabs + this.tabs.toArray().forEach(tab => tab.isactive = false); + + // activate the tab the user has clicked on. + tab.isactive = true; + } + +} diff --git a/src/app/vnfs/build-artifacts/template-holder/template-configuration/template-configuration.component.css b/src/app/vnfs/build-artifacts/template-holder/template-configuration/template-configuration.component.css new file mode 100644 index 0000000..c8100e3 --- /dev/null +++ b/src/app/vnfs/build-artifacts/template-holder/template-configuration/template-configuration.component.css @@ -0,0 +1,35 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + +.file { + visibility: hidden; + position: absolute; +} + +.mt-30 { + margin-top: 30px; +} + +.options-menu { + padding: 3px 20px; +}
\ No newline at end of file diff --git a/src/app/vnfs/build-artifacts/template-holder/template-configuration/template-configuration.component.html b/src/app/vnfs/build-artifacts/template-holder/template-configuration/template-configuration.component.html new file mode 100644 index 0000000..c1fb030 --- /dev/null +++ b/src/app/vnfs/build-artifacts/template-holder/template-configuration/template-configuration.component.html @@ -0,0 +1,100 @@ +<!-- +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +--> +<simple-notifications [options]="options"></simple-notifications> +<ng-progress [positionUsing]="'marginLeft'" [minimum]="0.15" [maximum]="1" [speed]="200" [showSpinner]="false" [direction]="'leftToRightIncreased'" [color]="'#6ab344'" + [trickleSpeed]="250" [thick]="true" [ease]="'linear'"></ng-progress> +<div> + <div> + <div class="card" style="margin-bottom: 23px;"> + <img class="card-img-top" data-src="holder.js/100%x180/" alt=""> + <div class="card-block" style="border-top: 5px solid #6ab344;border-top-right-radius: 7px;border-top-left-radius: 7px;"> + <div class="row" style="padding: 15px 25px"> + <div class="col-lg-3 col-sm-6 col-md-3 col-xs-12"> + <label>Action</label> + <input class="form-control" type="text" disabled value="{{action}}" /> + </div> + <div class="col-lg-3 col-sm-6 col-md-3 col-xs-12"> + <label>Vnf Type</label><input class="form-control" type="text" disabled value="{{vnfType}}" /> + </div> + <div class="col-lg-3 col-sm-6 col-md-3 col-xs-12"> + <label>Vnfc Type</label><input class="form-control" type="text" disabled value="{{vnfcType}}" /> + </div> + <div class="col-lg-3 col-sm-6 col-md-3 col-xs-12"> + <label>Protocol</label><input class="form-control" type="text" disabled value="{{protocol}}" /> + </div> + <div *ngIf="(action === 'ConfigScaleOut')" class="col-lg-3 col-sm-6 col-md-3 col-xs-12"> + <label>templateIdentifier</label><input class="form-control" type="text" disabled value="{{identifier}}" /> + </div> + </div> + </div> + </div> + + <div class="col-12"> + <div class="input-group"> + <input id="inputFile" class="file" #myInput type='file' (change)='fileChange(myInput)'> + <input [(ngModel)]="fileName" type="text" class="input-lg" disabled placeholder="Upload template from PC" style="width:80%"> + <button (click)="browseOption($event)" [disabled]="!enableBrowse" class="browse mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--primary input-lg" + type="button">Upload Template File + </button> + </div> + </div> + + <br> + <div class="row" style="margin-bottom: 20px;"> + <div class="col-md-12 text-right"> + <button type="button" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--primary" (click)="syncTemplate()">Synchronize Template Parameters + </button> + <button type="button" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--primary" (click)="mergeParams()"> Merge from Param + </button> + </div> + </div> + </div> + <hr> + <div><label for="textAreaGeneratedTemplate"> + <div class="mdl-card__title-text">File Editor</div> + </label> + <!-- <ace-editor [(text)]="configMappingEditorContent" #templateeditor [theme]="'chrome'" [mode]="'velocity'" [options]="{maxLines: 'Infinity', fontSize: '13pt'}" + style="min-height: 500px; width: fit-content;scroll-snap-coordinate: 3%"></ace-editor> --> + <ace-editor [(text)]="configMappingEditorContent" #templateeditor [theme]="'chrome'" [mode]="'velocity'" [options]="{maxLines: 'Infinity', fontSize: '13pt' }" + style="min-height: 500px; width: 100%"></ace-editor> + </div> + <app-modal [title]="'Confirmation'" [isShow]="false" [message]="'Template is saved and ready for creating parameter definition'" #modalComponent> + </app-modal> + <modal #myModal> + <modal-header [show-close]="true"> + <h4 class="modal-title">Enter Name for {{selectedWord}}</h4> + </modal-header> + <modal-body> + <div class="form-group row"> + <label for="example-text-input" class="col-12 col-form-label">Name</label> + <div class="col-12"> + <input class="form-control" [(ngModel)]="tempName" name="templateName" type="text" id="tempName"> + <span class="error-message" [hidden]="checkNameEntered" style="color: red;">Required Field</span> + </div> + </div> + </modal-body> + <modal-footer [show-default-buttons]="false"> + <button type="button" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent" (click)="submitNameValues()">Submit + </button> + </modal-footer> + </modal>
\ No newline at end of file diff --git a/src/app/vnfs/build-artifacts/template-holder/template-configuration/template-configuration.component.spec.ts b/src/app/vnfs/build-artifacts/template-holder/template-configuration/template-configuration.component.spec.ts new file mode 100644 index 0000000..f26e5fd --- /dev/null +++ b/src/app/vnfs/build-artifacts/template-holder/template-configuration/template-configuration.component.spec.ts @@ -0,0 +1,199 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + +/* tslint:disable:no-unused-variable */ +import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing'; +import { By, BrowserModule } from '@angular/platform-browser'; +import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; +import { Component, OnInit, ViewChild, Input } from '@angular/core'; +//import { ModalComponent } from '../../modal/modal.component'; +import { HttpUtilService } from '../../../../shared/services/httpUtil/http-util.service'; +import { MappingEditorService } from '../../../../shared/services/mapping-editor.service'; +import { ArtifactRequest } from '../../../../shared/models/index'; +import { ActivatedRoute, Router } from "@angular/router"; +import { saveAs } from "file-saver"; +import { NotificationService } from '../../../../shared/services/notification.service'; +import { NotificationsService } from "angular2-notifications" +import { ParamShareService } from '../../../../shared/services/paramShare.service'; +import { DialogService } from "ng2-bootstrap-modal"; +import {ConfirmComponent} from '../../../../shared/confirmModal/confirm.component'; +import {BuildDesignComponent} from '../../build-artifacts.component'; +import { environment } from '../../../../../environments/environment'; +import { ModalComponent } from 'ng2-bs3-modal/ng2-bs3-modal' +import { FormsModule } from '@angular/forms'; +import { RouterTestingModule } from '@angular/router/testing'; +import { HomeComponent } from '../../../../home/home/home.component'; +import { LogoutComponent } from '../../../../shared/components/logout/logout.component'; +import { HelpComponent } from '../../../../shared/components/help/help/help.component'; +import { AboutUsComponent } from '../../../../about-us/aboutus.component'; +import { TestComponent } from '../../../../test/test.component'; +import { HttpModule } from '@angular/http'; +import { AceEditorComponent } from 'ng2-ace-editor'; +import { Ng2Bs3ModalModule } from 'ng2-bs3-modal/ng2-bs3-modal'; +import { SimpleNotificationsModule } from 'angular2-notifications'; +import { GoldenConfigurationComponent } from './template-configuration.component'; +import { NgProgress } from 'ngx-progressbar'; + +describe('GoldenConfigurationComponent', () => { + let component: GoldenConfigurationComponent; + let fixture: ComponentFixture<GoldenConfigurationComponent>; + let buildDesignComponent: BuildDesignComponent; + let paramShareService: ParamShareService; + let dialogService: DialogService; + let notificationService: NotificationService; + let httpUtil: HttpUtilService; + let mappingEditorService: MappingEditorService; + let activeRoutes: ActivatedRoute; + let router: Router; + let nService: NotificationsService + const routes = [ + { + path: 'home', + component: HomeComponent + }, { + path: 'vnfs', + loadChildren: '../../../../vnfs/vnfs.module#VnfsModule' + }, { + path: 'test', + component: TestComponent + }, + { + path: 'help', + component: HelpComponent + }, { + path: 'aboutUs', + component: AboutUsComponent + }, { + path: 'logout', + component: LogoutComponent + }, { + path: '', + redirectTo: '/home', + pathMatch: 'full' + } + ]; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [FormsModule, BrowserModule, RouterTestingModule.withRoutes(routes), HttpModule, Ng2Bs3ModalModule, SimpleNotificationsModule.forRoot()], + declarations: [GoldenConfigurationComponent, HomeComponent, TestComponent, HelpComponent, AboutUsComponent, LogoutComponent, AceEditorComponent], + providers: [BuildDesignComponent, NgProgress, ParamShareService, DialogService, NotificationService, HttpUtilService, MappingEditorService, NotificationsService], + schemas: [NO_ERRORS_SCHEMA], + }) + + }); + + beforeEach(async(() => { + TestBed.compileComponents() + + })); + + + it('validate if uploaded file should be xml or json', () => { + fixture = TestBed.createComponent(GoldenConfigurationComponent); + component = fixture.componentInstance; + expect(component.validateUploadedFile('xls')).toBe(false); + expect(component.validateUploadedFile('json')).toBe(true); + expect(component.validateUploadedFile('xml')).toBe(true); + }); + + + it('validate initialisation of variables in ngOnit() function', inject([MappingEditorService], (mappingEditorService: MappingEditorService) => { + fixture = TestBed.createComponent(GoldenConfigurationComponent); + component = fixture.componentInstance; + mappingEditorService.latestAction = { "action": "Configure", "action-level": "vnf", "scope": { "vnf-type": "testVnf", "vnfc-type": "" }, "template": "Y", "vm": [], "device-protocol": "CHEF", "user-name": "", "port-number": "", "artifact-list": [{ "artifact-name": "template_Configure_test_0.0.1V.json", "artifact-type": "config_template" }, { "artifact-name": "pd_Configure_test_0.0.1V.yaml", "artifact-type": "parameter_definitions" }], "scopeType": "vnf-type" } + + expect(component.ngOnInit()); + expect(component.ngAfterViewInit()); + expect(component.action).toEqual('Configure'); + expect(component.vnfType).toEqual('testVnf'); + expect(component.vnfcType).toEqual(''); + expect(component.protocol).toEqual('CHEF'); + + expect(component.artifactName).toEqual('template_Configure_test_0.0.1V.json'); + + mappingEditorService.latestAction = { "action": "Configure", "action-level": "vnf", "scope": { "vnf-type": "testVnf", "vnfc-type": "testVnfc" }, "template": "Y", "vm": [], "device-protocol": "CHEF", "user-name": "", "port-number": "", "artifact-list": [{ "artifact-name": "template_Configure_test_0.0.1V.json", "artifact-type": "config_template" }, { "artifact-name": "pd_Configure_test_0.0.1V.yaml", "artifact-type": "parameter_definitions" }], "scopeType": "vnf-type" } + expect(component.ngOnInit()); + expect(component.vnfcType).toEqual('testVnfc'); + + + })); + + it('check if variables are empty when reference data object is empty', inject([MappingEditorService], (mappingEditorService: MappingEditorService) => { + fixture = TestBed.createComponent(GoldenConfigurationComponent); + component = fixture.componentInstance; + mappingEditorService.latestAction = { "action": "", "scope": { "vnf-type": "", "vnfc-type": "" }, "vm": [], "protocol": "", "download-dg-reference": "", "user-name": "", "port-number": "", "artifact-list": [], "deviceTemplate": "", "scopeType": "" }; + + expect(component.ngAfterViewInit()); + expect(component.action).toEqual(''); + expect(component.vnfType).toEqual(''); + expect(component.vnfcType).toEqual(''); + expect(component.protocol).toEqual(''); + expect(component.artifactName).toEqual(''); + + })); + + it('check if correct notification is fired while initialising if reference data object is undefined',()=>{ + fixture = TestBed.createComponent(GoldenConfigurationComponent); + component = fixture.componentInstance; + expect(component.ngAfterViewInit()); + expect(component.Actions.length).toBe(0) + expect(component.enableBrowse).toBe(false) + }); + + it('test sync template when template data, param data and pd data are available', inject([MappingEditorService, ParamShareService], (mappingEditorService: MappingEditorService, paramShareService:ParamShareService) => { + fixture = TestBed.createComponent(GoldenConfigurationComponent); + component = fixture.componentInstance; + mappingEditorService.fromScreen === 'MappingScreen' + component.configMappingEditorContent="<configuration xmlns=\"http://xml.juniper.net/xnm/1.1/xnm\" \n xmlns:a=\"http://xml.juniper.net/junos/15.1X49/junos\" >\n <version>15.1X49-D50.3</version>\n <groups>\n <name>node0</name>\n <system>\n <tacplus-server>\n <name>${sync_auto-pop_name1}</name>\n <source-address>${sync_auto-pop_address1}</source-address>\n </tacplus-server>\n <tacplus-server>\n <name>${node0_tacplus_server_name2}</name>\n <source-address>${sync_auto-pop_address1}</source-address>\n </tacplus-server>\n </system> \n </groups>\n </configuration>" + mappingEditorService.initialise(component.templateeditor.getEditor(), component.configMappingEditorContent, component.modal); + + var pdData=[{"name":"sync_auto-pop_name1","type":null,"description":null,"required":null,"default":null,"source":"A&AI","rule-type":"vnfc-oam-ipv4-address-list","request-keys":[{"key-name":null,"key-value":null},{"key-name":null,"key-value":null},{"key-name":null,"key-value":null}],"response-keys":[{"key-name":"unique-key-name","key-value":"parent-name"},{"key-name":"unique-key-value","key-value":"vnfc"},{"key-name":"field-key-name","key-value":"ipaddress-v4-oam-vip"},{"key-name":null,"key-value":"vm-number"},{"key-name":null,"key-value":"test"}],"ruleTypeValues":[null,"vnf-name","vm-name-list","vnfc-name-list","vnf-oam-ipv4-address","vnfc-oam-ipv4-address-list"],"showFilterFields":true,"enableFilterByValue":true},{"name":"sync_auto-pop_address1","type":null,"description":null,"required":null,"default":null,"source":"A&AI","rule-type":"vm-name-list","request-keys":[{"key-name":null,"key-value":null},{"key-name":null,"key-value":null},{"key-name":null,"key-value":null}],"response-keys":[{"key-name":"unique-key-name","key-value":"parent-name"},{"key-name":"unique-key-value","key-value":"vserver"},{"key-name":"field-key-name","key-value":"vserver-name"},{"key-name":null,"key-value":"vnfc-function-code"},{"key-name":null,"key-value":null}],"ruleTypeValues":[null,"vnf-name","vm-name-list","vnfc-name-list","vnf-oam-ipv4-address","vnfc-oam-ipv4-address-list"],"showFilterFields":true,"enableFilterByValue":true},{"name":"node0_tacplus_server_name2","type":null,"description":null,"required":null,"default":null,"source":"Manual","rule-type":null,"request-keys":[{"key-name":null,"key-value":null},{"key-name":null,"key-value":null},{"key-name":null,"key-value":null}],"response-keys":[{"key-name":null,"key-value":null},{"key-name":null,"key-value":null},{"key-name":null,"key-value":null},{"key-name":null,"key-value":null},{"key-name":null,"key-value":null}],"ruleTypeValues":[null]}]; + paramShareService.setSessionParamData([pdData]); + localStorage["paramsContent"]={ + "sync_auto-pop_name1":"10.0.1.34", + "sync_auto-pop_address1":"", + "node0_tacplus_server_name2":"192.34.45.5" + }; + expect(component.syncTemplate()); + + + })); + + it('test sync template when template data, param data and pd data are not available', inject([MappingEditorService, ParamShareService], (mappingEditorService: MappingEditorService, paramShareService:ParamShareService) => { + fixture = TestBed.createComponent(GoldenConfigurationComponent); + component = fixture.componentInstance; + mappingEditorService.fromScreen === 'MappingScreen' + component.configMappingEditorContent="<configuration xmlns=\"http://xml.juniper.net/xnm/1.1/xnm\" \n xmlns:a=\"http://xml.juniper.net/junos/15.1X49/junos\" >\n <version>15.1X49-D50.3</version>\n <groups>\n <name>node0</name>\n <system>\n <tacplus-server>\n <name>${sync_auto-pop_name1}</name>\n <source-address>${sync_auto-pop_address1}</source-address>\n </tacplus-server>\n <tacplus-server>\n <name>${node0_tacplus_server_name2}</name>\n <source-address>${sync_auto-pop_address1}</source-address>\n </tacplus-server>\n </system> \n </groups>\n </configuration>" + mappingEditorService.initialise(component.templateeditor.getEditor(), component.configMappingEditorContent, component.modal); + + var pdData=[]; + paramShareService.setSessionParamData([pdData]); + localStorage["paramsContent"]={}; + expect(component.syncTemplate()); + + + })); + + +}); diff --git a/src/app/vnfs/build-artifacts/template-holder/template-configuration/template-configuration.component.ts b/src/app/vnfs/build-artifacts/template-holder/template-configuration/template-configuration.component.ts new file mode 100644 index 0000000..8514e24 --- /dev/null +++ b/src/app/vnfs/build-artifacts/template-holder/template-configuration/template-configuration.component.ts @@ -0,0 +1,977 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + +import { Component, Input, OnInit, ViewChild } from '@angular/core'; +//import { ModalComponent } from '../../modal/modal.component'; +import { HttpUtilService } from '../../../../shared/services/httpUtil/http-util.service'; +import { MappingEditorService } from '../../../../shared/services/mapping-editor.service'; +import { ArtifactRequest } from '../../../../shared/models/index'; +import { ActivatedRoute, Router } from '@angular/router'; +import { saveAs } from 'file-saver'; +import { NotificationService } from '../../../../shared/services/notification.service'; +import { NotificationsService } from 'angular2-notifications'; +import { ParamShareService } from '../../../../shared/services/paramShare.service'; +import { DialogService } from 'ng2-bootstrap-modal'; +import { ConfirmComponent } from '../../../../shared/confirmModal/confirm.component'; +import { BuildDesignComponent } from '../../build-artifacts.component'; +import { environment } from '../../../../../environments/environment'; +import { ModalComponent } from 'ng2-bs3-modal/ng2-bs3-modal'; +import { NgProgress } from 'ngx-progressbar'; +declare var $: any + +@Component({ selector: 'app-golden-configuration', templateUrl: './template-configuration.component.html', styleUrls: ['./template-configuration.component.css'] }) +export class GoldenConfigurationComponent implements OnInit { + @ViewChild('templateeditor') templateeditor; + @Input() configMappingEditorContent: string; + @Input() isMappingComp: boolean; + @ViewChild('myInput') myInputVariable: any; + // @ViewChild(ModalComponent) modalComponent: ModalComponent; + @ViewChild('myModal') modal: ModalComponent; + aceText: string = "" + fileName: string = "" + showTemplateVersionDiv: any; + downloadedTemplateFileName: any; + downloadedParamFileName: any; + templateVersionNo: any = '0.0.1'; + saveToGuiCacheFlag = 'false'; + initialAction: any; + public referenceData: Array<Object> = []; + public scopeName: any; + public subscription: any; + public item: any = {}; + public goldenActions: Array<string> = []; + public refNameObj = {}; + public action = ''; + public artifactName = ''; + public type; + public showError: boolean = false; + public tempretrieveFlag: boolean = false; + public fileNameForTempSave; + initialData: any; + showDownloadDiv: boolean = false; + downloadType: any; + enableBrowse: boolean = true; + enableMerge: boolean = false; + uploadValidationSuccess: boolean = false; + fileExtension: any = "xml"; + apiToken = localStorage['apiToken']; + public appDataObject: any; + public downloadDataObject: any; + public checkNameEntered: boolean = true; + public selectedWord: any = this.mappingEditorService.getSelectedWord(); + public Actions = [ + { action: "ConfigBackup", value: "ConfigBackup" }, + { action: "ConfigModify", value: "ConfigModify" }, + { action: "ConfigRestore", value: "ConfigRestore" }, + { action: "Configure", value: "Configure" }, + { action: "GetRunningConfig", value: "GetRunningConfig" }, + { action: "HealthCheck", value: "HealthCheck" }, + { action: "StartApplication", value: "StartApplication" }, + { action: "StopApplication", value: "StopApplication" } + ]; + options = { + timeOut: 1000, + showProgressBar: true, + pauseOnHover: true, + clickToClose: true, + maxLength: 200 + } + public enableDownloadButtons: boolean = false; + constructor(private buildDesignComponent: BuildDesignComponent, private paramShareService: ParamShareService, private dialogService: DialogService, private notificationService: NotificationService, private httpUtil: HttpUtilService, private mappingEditorService: MappingEditorService, private activeRoutes: ActivatedRoute, private router: Router, private nService: NotificationsService, private ngProgress: NgProgress) { + this.artifactRequest.action = ''; + this.artifactRequest.version = ''; + this.artifactRequest.paramsContent = '{}'; + this.artifactRequest.paramKeysContent = ''; + } + public templateEditor: any; + public fileType: any = ''; + public actionType: any; + public myfileName: any; + userId = localStorage['userId']; + public artifactRequest: ArtifactRequest = new ArtifactRequest(); + public showUploadStatus: boolean = false; + public uploadStatus: boolean = false; + public uploadTypes = [ + { + value: 'Generated Template', + display: 'Sample Json Param File' + }, + { + value: 'Mapping Data', + display: 'Sample Json Param File' + } + ]; + vnfType: any = ''; + vnfcType: any = ''; + protocol: any = ''; + refObj: any; + editor: any; + editorContent: any; + tempName: any; + enableValidateTemplate: boolean = false;; + public selectedUploadType: string = this.uploadTypes[0].value; + identifier: any; + //this.mappingeditorservice.referenceNameObjects = object;PLEASE USE THIS OBJECT TO GET TEMPALLDATA + //==================================================== + ngOnInit() { + var refObj = this.refObj = this.prepareFileName(); + // console.log("Ref object: " + JSON.stringify(refObj)) + if (refObj && refObj != undefined) { + // refObj = refObj[refObj.length - 1]; + this.item = refObj; + + this.vnfType = this.item.scope["vnf-type"]; + this.vnfcType = this.item.scope["vnfc-type"]; + this.protocol = this.item['device-protocol']; + this.action = this.item.action; + this.artifactRequest.action = this.item.action; + this.artifactRequest.vnfType = this.vnfType; + if (this.vnfcType != undefined && this.vnfcType.length != 0) { + this.scopeName = this.vnfcType; + } + else { + this.scopeName = this.vnfType; + } + } + else { + this.item = { "action": "", "scope": { "vnf-type": "", "vnfc-type": "" }, "vm": [], "protocol": "", "download-dg-reference": "", "user-name": "", "port-number": "", "artifact-list": [], "deviceTemplate": "", "scopeType": "" }; + } + this.initialAction = this.item.action; + this.activeRoutes.url.subscribe(UrlSegment => { + this.actionType = UrlSegment[0].path + }) + /*if (this.actionType === 'createTemplate') { + this.mappingEditorService.fromScreen = 'TemplateScreen'; + } + if (this.actionType === 'updateTemplate') {*/ + this.mappingEditorService.fromScreen = 'MappingScreen'; + // } + this.identifier = this.mappingEditorService.identifier; + } + //========================== End of ngOnInit() Method============================================ + ngOnDestroy() { + //console.log("Reference object =="+ JSON.stringify(this.refObj)); + if (this.refObj && this.refObj != undefined) { + if (this.configMappingEditorContent && this.configMappingEditorContent != undefined) { + this.saveTemplate(); + this.prepareAppData(); + this.prepareDownloadData(); + this.mappingEditorService.changeNavAppData(this.appDataObject); + this.mappingEditorService.changeNavDownloadData(this.downloadDataObject); + } + } + } + //========================== End of ngOnDestroy() Method============================================ + ngAfterViewInit() { + if (this.mappingEditorService.latestAction) { + this.refNameObj = this.mappingEditorService.latestAction; + if (this.vnfcType !== 'null') { + this.type = this.vnfcType; + } + else { + this.type = this.vnfType; + } + for (let i = 0; i < this.refNameObj['artifact-list'].length; i++) { + let artifactList = this.refNameObj['artifact-list']; + if (artifactList[i]['artifact-type'] === 'config_template') { + this.artifactName = artifactList[i]['artifact-name']; + } + } + } + let self = this; + this.templateEditor = self.templateeditor.getEditor(); + /* this.templateeditor.getEditor().commands.addCommand({ + name: 'annotateCommand', + bindKey: { win: 'Ctrl-4', mac: 'Command-4' }, + exec: function (editor) { + self.mappingEditorService.checkMethodCall(this.modal); + } + });*/ + this.templateeditor.getEditor().commands.addCommand({ + name: 'annotateCommand', + bindKey: { win: 'ENTER', mac: 'ENTER' }, + exec: (editor: any) => { + this.handleAnnotation(this.modal); + } + }); + if (this.mappingEditorService.fromScreen === 'MappingScreen') { + this.configMappingEditorContent = this.mappingEditorService.getTemplateMappingDataFromStore(); + this.fileType = sessionStorage.getItem('fileType'); + } + /* else if (this.mappingEditorService.fromScreen === 'TemplateScreen') { + this.configMappingEditorContent = this.mappingEditorService.getTemplateDataFromStore(); + this.fileType = sessionStorage.getItem('fileType'); + }*/ + if (this.configMappingEditorContent) { + this.artifactRequest.templateContent = this.configMappingEditorContent; + this.mappingEditorService.initialise(this.templateeditor.getEditor(), this.artifactRequest.templateContent, this.modal); + } + if (this.refObj) { + if (this.mappingEditorService.getTemplateMappingDataFromStore() && this.mappingEditorService.getTemplateMappingDataFromStore() != undefined) { + this.configMappingEditorContent = this.mappingEditorService.getTemplateMappingDataFromStore(); + } + else { + if (this.artifactName) this.retrieveTemplateFromAppc(); + } + } + else { + this.Actions = []; + this.enableBrowse = false; + this.nService.error("Error", "Please enter Action and VNF type in Reference Data screen"); + } + } + + //========================== End of ngAfterViewInit() Method============================================ + browseOption() { + $("#inputFile").trigger('click'); + } + //========================== End of browseOption() Method============================================ + /* openFile(event) { + let input = event.target; + this.fileName = event.currentTarget.value.replace(/C:\\fakepath\\/i, ''); + for (let index = 0; index < input.files.length; index++) { + let reader = new FileReader(); + reader.onload = () => { + this.configMappingEditorContent = reader.result; + } + reader.readAsText(input.files[index]); + }; + } + //========================== End of openFile() Method============================================*/ + //save to GUI + public saveTemplate() { + this.saveToGuiCacheFlag = 'true'; + this.mappingEditorService.paramData = []; + if (this.configMappingEditorContent) { + this.initialData = this.configMappingEditorContent; + this.mappingEditorService.refreshEditor(); + let paramArr: any = [] + if (this.mappingEditorService.paramData && this.mappingEditorService.paramData != undefined) { + if (this.mappingEditorService.paramData.length === 0 && this.mappingEditorService.hasErrorCode === true) { + this.nService.error("Error", 'Special characters error', 'Error') + return; + } + else { + this.showError = false; + } + } + this.showTemplateVersionDiv = true; + + if (this.mappingEditorService.fromScreen === 'MappingScreen') { + this.mappingEditorService.setTemplateMappingDataFromStore(this.configMappingEditorContent); + } + if (this.fileType === 'text/xml') { + sessionStorage.setItem('fileType', 'text/xml'); + } + if (this.fileType === '') { + sessionStorage.setItem('fileType', ''); + } + // paramArr = this.mappingEditorService.paramData; + // this.paramShareService.setTemplateData(paramArr) + } + } + //========================== End of saveTemplate() Method============================================ + /* clearHighlight() { + this.mappingEditorService.removeTheSelectedMarkers(); + } + //========================== End of clearHighlight() Method============================================*/ + /*validateTemplate() { + var fileExtensionArr = this.fileType.split("/"); + let data = { + "input": { + "design-request": { + "request-id": this.apiToken, + "action": "validateTemplate", + "data-type": fileExtensionArr[1].toUpperCase(), + "payload": this.configMappingEditorContent + } + } + }; + let url = environment.validateTemplate; + this + .httpUtil + .post( + { url: url, data: data }) + .subscribe(resp => { + if (resp.output.status.code === '400' && resp.output.status.message === "success") { + this.uploadValidationSuccess = true; + this.nService.success("Success", "Template Validated succesfully"); + return true; + } + else if (resp.output.status.code === '401') { + this.nService.error("Error", resp.output.status.message); + return false; + } + }, + error => this.nService.error("Error", "Unable to validate the uploaded template. Error in connecting APPC Server")); + } + //========================== End of validateTemplate() Method============================================*/ + retrieveTemplateFromAppc() { + let refObj = this.refObj; + if (refObj && refObj != undefined) { + + let fileName = this.artifactName; + let payload = '{"userID": "' + this.userId + '","action": "' + this.item.action + '", "vnf-type" : "' + this.vnfType + '", "artifact-type":"APPC-CONFIG", "artifact-name":"' + fileName + '"}'; + let input = { + "input": { + "design-request": { + "request-id": this.apiToken, + "action": "getArtifact", + "payload": payload + } + } + }; + // console.log("Retrieve artifact payload=="+ payload); + let artifactContent: any; + this.ngProgress.start(); + this.httpUtil.post({ + url: environment.getDesigns, + data: input + }).subscribe(resp => { + if (resp.output.status.code === '400' && resp.output.status.message === "success") { + this.nService.success("Success", "Template retrieved successfully from APPC"); + let result = JSON.parse(resp.output.data.block).artifactInfo[0]; + result = result['artifact-content']; + if ('Generated Template' === this.selectedUploadType) { + this.configMappingEditorContent = result + this.artifactRequest.templateContent = this.configMappingEditorContent; + this.notificationService.notifySuccessMessage('Configuration Template file successfully uploaded..'); + if (this.artifactRequest.templateContent) { + this.mappingEditorService.initialise(this.templateeditor.getEditor(), this.artifactRequest.templateContent, this.modal); + } + } + this.tempretrieveFlag = true; + this.fileNameForTempSave = fileName; + this.enableDownloadButtons = true; + this.initialData = result; + this.saveTemplate(); + } + else { + this.nService.info("Information", "There is no template saved in APPC for the selected action!"); + } + this.ngProgress.done(); + }, + /* (error) => { + // this.showUploadErrorStatus = true; + // this.nService.error('Status','Error Connecting to the APPC Network') + //this.notificationService.notifyErrorMessage('Configuration Template file successfully uploaded..') + //this.uploadStatusError = true; + //window.scrollTo(0, 0) + // this. nService.error('Status','Error Connecting to the APPC Network') + this.openModel(true, "Could not retrieve latest template for given action""Error in connecting to APPC database") + });*/ + error => this.nService.error("Error", "Error in connecting to APPC Server")); + setTimeout(() => { + this.ngProgress.done(); + }, 3500); + } + } + //========================== End of retrieveTemplateFromAppc() Method============================================ + prepareAppData() { + let refObj = this.refObj; + //console.log("Reference object =="+ JSON.stringify(refObj)); + if (refObj && refObj != undefined) { + // refObj = refObj[refObj.length - 1]; + let paramsKeyValueFromEditor: JSON; + /* if (this.fileExtension.toUpperCase() === "XML") + paramsKeyValueFromEditor = this.mappingEditorService.generateParams(this.templateeditor.getEditor(), this.artifactRequest.templateContent); + else*/ + // paramsKeyValueFromEditor = this.mappingEditorService.generateParams(this.templateeditor.getEditor(), this.artifactRequest.templateContent); + try { + paramsKeyValueFromEditor = JSON.parse(localStorage["paramsContent"]); + } + catch (error) { + console.log("Could not parse name value pairs==" + error); + } + if (paramsKeyValueFromEditor) { + this.showTemplateVersionDiv = true; + let action = this.item.action; + var scopeName = this.scopeName.replace(/ /g, '').replace(new RegExp('/', "g"), '_').replace(/ /g, ''); + let fileName = this.updateParamFileName(refObj.action, scopeName, this.templateVersionNo); + let vnfType = this.vnfType; + let Json = [paramsKeyValueFromEditor]; + let slashedPayload = this.appendSlashes(JSON.stringify(Json)); + let newPayload = + { + "userID": this.userId, + "vnf-type": this.vnfType, + "action": action, + "artifact-name": fileName, + "artifact-type": "APPC-CONFIG", + "artifact-version": this.templateVersionNo, + "artifact-contents": slashedPayload + } + let data = + { + "input": { + "design-request": { + "request-id": this.apiToken, + "action": "uploadArtifact", + "payload": JSON.stringify(newPayload) + + } + } + } + this.appDataObject.template.nameValueData = data; + } + if (this.configMappingEditorContent) { + let actualContent = this.configMappingEditorContent; + this.mappingEditorService.generateTemplate(this.templateEditor); + this.showTemplateVersionDiv = true; + let action = this.item.action; + let versionandFileType: any; + if (this.fileType === "text/xml") { + + versionandFileType = this.templateVersionNo + 'V.xml' + } else { + + versionandFileType = this.templateVersionNo + 'V.json' + } + let fileName: any; + if (this.tempretrieveFlag) { + fileName = this.fileNameForTempSave; + } + else { + // fileName = this.updateDownloadTemplateFileName(refObj.action, this.scopeName, versionandFileType); + fileName = this.artifactName; + } + let vnfType = this.vnfType; + let newPayload = + { + "userID": this.userId, + "vnf-type": this.vnfType, + "action": action, + "artifact-name": fileName, + "artifact-type": "APPC-CONFIG", + "artifact-version": this.templateVersionNo, + //"artifact-contents": this.configMappingEditorContent + "artifact-contents": this.configMappingEditorContent.replace(/\(([^()]|(R))*\)=\(/g, '').replace(/\)}/g, '}') + + } + let data = + { + "input": { + "design-request": { + "request-id": this.apiToken, + "action": "uploadArtifact", + "payload": JSON.stringify(newPayload) + + } + } + } + this.appDataObject.template.templateData = data; + this.mappingEditorService.initialise(this.templateeditor.getEditor(), actualContent, this.modal); + } + } + } + //========================== End of prepareAppData() Method============================================ + /*retrieveNameValueFromAppc() { + let refObj: any = this.prepareFileName(); + if (refObj && refObj != undefined) { + let fileName = this.updateParamFileName(this.item.action, this.scopeName, this.templateVersionNo); + let payload = '{"userID": "' + this.userId + '","action": "' + this.item.action + '", "vnf-type" : "' + this.vnfType + '", "artifact-type":"APPC-CONFIG", "artifact-name":"' + fileName + '"}'; + let input = { + "input": { + "design-request": { + "request-id": this.apiToken, + "action": "getArtifact", + "payload": payload + } + } + }; + + let artifactContent: any; + this.httpUtil.post({ + // url:"https://mtanjv9apdb51.aic.cip.att.com:8443/restconf/operations/design-services:dbservice", + url: environment.getDesigns, + data: input + }).subscribe(resp => { + if (resp.output.status.code === '400' && resp.output.status.message === "success") { + this.openModel(true, 'Name/value pairs retrieved successfully from APPC', 'Success'); + let result = JSON.parse(resp.output.data.block).artifactInfo[0]; + result = JSON.parse(result['artifact-content']); + var jsonString = JSON.stringify(result[0]); + var string = jsonString.substring(1, jsonString.length - 1); + var stringArr = string.split(","); + var newStringArr = []; + var resultStr = "{\r\n" + for (var index in stringArr) { + newStringArr[index] = stringArr[index] + ",\r\n"; + } + for (var index in newStringArr) { + resultStr = resultStr + newStringArr[index]; + } + resultStr = resultStr.substring(0, resultStr.length - 3) + "\r\n}" + this.configMappingEditorContent = resultStr; + + } + }, + error => this.openModel(true, "Could not retrieve the name value pairs. Error in connecting to APPC Server", "ERROR")); + } + }*/ + //========================== End of retrieveNameValueFromAppc() Method============================================ + prepareFileName(): any { + let fileNameObject: any = this.mappingEditorService.latestAction; + this.appDataObject = this.mappingEditorService.appDataObject; + this.downloadDataObject = this.mappingEditorService.downloadDataObject; + this.referenceData = fileNameObject; + return fileNameObject; + } + //========================== End of prepareFileName() Method============================================ + onDownloadParameter() { + let refObj = this.refObj; + if (refObj) { + // refObj = refObj[refObj.length - 1]; + let paramsKeyValueFromEditor: JSON; + if (this.fileExtension.toUpperCase() === "XML") + paramsKeyValueFromEditor = this.mappingEditorService.generateParams(this.templateeditor.getEditor(), this.artifactRequest.templateContent); + else + paramsKeyValueFromEditor = this.mappingEditorService.generateParams(this.templateeditor.getEditor(), this.artifactRequest.templateContent); + + try { + paramsKeyValueFromEditor = JSON.parse(localStorage["paramsContent"]); + } + catch (error) { + console.log("Could not parse name value pairs==" + error); + } + let theJSON = JSON.stringify(paramsKeyValueFromEditor, null, "\t") + var blob = new Blob([theJSON], { + type: "text/json" + }); + this.showTemplateVersionDiv = true; + let fileName: any; + var scopeName = this.scopeName.replace(/ /g, '').replace(new RegExp('/', "g"), '_').replace(/ /g, ''); + fileName = this.updateParamFileName(refObj.action, scopeName, this.templateVersionNo); + this.downloadDataObject.template.nameValueData = theJSON; + this.downloadDataObject.template.nameValueFileName = fileName; + } + else { + this.nService.error("Error", "Please enter Action and VNF type in Reference Data screen"); + } + + } + //========================== End of onDownloadParameter() Method============================================ + /* JSONToCSVConvertor(JSONData, fileName, ShowLabel) { + //If JSONData is not an object then JSON.parse will parse the JSON string in an Object + var arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData; + var CSV = ''; + //This condition will generate the Label/Header + if (ShowLabel) { + var testRow = ""; + for (var index in arrData[0]) { + CSV += index + '\t' + arrData[0][index] + '\r\n'; + } + } + if (CSV == '') { + return; + } + //Initialize file format you want csv or xls + var uri = 'data:application/vnd.ms-excel,' + encodeURI(CSV); + var link = document.createElement("a"); + link.href = uri; + link.download = fileName + ".xls"; + //this part will append the anchor tag and remove it after automatic click + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } + //========================== End of JSONToCSVConvertor() Method============================================ + updateParamFileNameForXls(action: any, scopeName: any, versionNo: any) { + let fileName = 'param_' + action + '_' + scopeName + '_' + versionNo + 'V'; + this.downloadedParamFileName = fileName; + return fileName; + } + //========================== End of updateParamFileNameForXls() Method============================================*/ + updateParamFileName(action: any, scopeName: any, versionNo: any) { + let fileName = 'param_' + action + '_' + scopeName + '_' + versionNo + 'V.json'; + this.downloadedParamFileName = fileName; + return fileName; + } + //========================== End of updateParamFileName() Method============================================ + public onDownloadTemplate(artifact: string) { + let actualContent = this.configMappingEditorContent; + var textToSaveAsBlob: any; + var config_template_fileName: any + let refObj = this.refObj; + let versionandFileType: string; + this.mappingEditorService.generateTemplate(this.templateEditor); + if (artifact == 'Template' && this.artifactRequest && this.configMappingEditorContent && refObj) { + // refObj = refObj[refObj.length - 1]; + this.showTemplateVersionDiv = true; + if (this.fileType === "text/xml") { + textToSaveAsBlob = new Blob([this.configMappingEditorContent], { + type: "text/xml" + }); + versionandFileType = this.templateVersionNo + 'V.xml' + } + if (this.fileType === "text/plain") { + textToSaveAsBlob = new Blob([this.configMappingEditorContent], { + type: "text/plain" + }); + versionandFileType = this.templateVersionNo + 'V.txt' + } + if (this.fileType === "text/json") { + textToSaveAsBlob = new Blob([this.configMappingEditorContent], { + type: "text/json" + }); + versionandFileType = this.templateVersionNo + 'V.json' + } + if (this.tempretrieveFlag) { + config_template_fileName = this.fileNameForTempSave; + var filextension = config_template_fileName.substring(config_template_fileName.indexOf("V") + 2, config_template_fileName.length); + + textToSaveAsBlob = new Blob([this.configMappingEditorContent], { + type: "text/" + filextension + }); + } + else { + // config_template_fileName = this.updateDownloadTemplateFileName(refObj.action, this.scopeName, versionandFileType); + config_template_fileName = this.artifactName; + } + // saveAs(textToSaveAsBlob, config_template_fileName); + this.mappingEditorService.initialise(this.templateeditor.getEditor(), actualContent, this.modal); + //this.downloadDataObject.template.templateData = this.configMappingEditorContent; + this.downloadDataObject.template.templateData = this.configMappingEditorContent.replace(/\(([^()]|(R))*\)=\(/g, '').replace(/\)}/g, '}'); + this.downloadDataObject.template.templateFileName = config_template_fileName; + } + + } + //========================== End of onDownloadTemplate() Method============================================ + updateDownloadTemplateFileName(action: any, scopeName: any, versionandFileType: any) { + let fileName = 'template_' + action + '_' + scopeName + '_' + versionandFileType; + this.downloadedTemplateFileName = fileName; + return fileName; + } + //========================== End of updateDownloadTemplateFileName() Method============================================ + /* openModel(toShow: any, message: any, title: any) { + //this.modalComponent.isShow = toShow; + //this.modalComponent.message = message; + //this.modalComponent.title = title; + } + //========================== End of openModel() Method============================================*/ + fileChange(input) { + + let self = this; + let refObj = this.refObj; + this.enableValidateTemplate = true; + + if (refObj && refObj != undefined) { + // refObj = refObj[refObj.length - 1]; + if (input.files && input.files[0]) { + console.log("input files0" + JSON.stringify(input.files[0])) + this.myfileName = input.files[0].name; + this.fileName = input.files[0].name; + this.fileType = input.files[0].type; + // var fileExtension = this.myfileName.substr(this.myfileName.lastIndexOf('.') + 1); + + let reader = new FileReader(); + // if(this.validateUploadedFile(fileExtension)) + //{ + this.readFile(input.files[0], reader, (result) => { + if (this.fileType === 'text/xml') { + sessionStorage.setItem('fileType', 'text/xml'); + } + if (this.fileName.endsWith(".json")) { + this.fileType = "text/json"; + sessionStorage.setItem('fileType', 'text/json'); + } + if (this.fileType === '') { + sessionStorage.setItem('fileType', ''); + } + + + if ('Generated Template' === this.selectedUploadType) { + this.configMappingEditorContent = result + this.artifactRequest.templateContent = this.configMappingEditorContent; + console.log("editor content==" + JSON.stringify(this.configMappingEditorContent)) + this.notificationService.notifySuccessMessage('Configuration Template file successfully uploaded..'); + if (this.artifactRequest.templateContent) { + this.mappingEditorService.initialise(this.templateeditor.getEditor(), this.artifactRequest.templateContent, this.modal); + } + } + this.enableDownloadButtons = true; + this.initialData = result; + this.saveTemplate(); + + }); + // } + // else{ + // this.nService.error("Error", "Incorrect File Format") + //this.configMappingEditorContent='' + //} + } + else { + this.nService.error("Error", "Failed to read file"); + } + this.myInputVariable.nativeElement.value = ""; + } + else { + this.nService.error("Error", "Please enter Action and VNF type in Reference Data screen"); + return false; + } + } + //========================== End of fileChange() Method============================================ + public readFile(file, reader, callback) { + // Set a callback funtion to fire after the file is fully loaded + reader.onload = () => { + // callback with the results + callback(reader.result); + } + this.notificationService.notifySuccessMessage('Uploading File ' + file.name + ':' + file.type + ':' + file.size); + // Read the file + reader.readAsText(file, "UTF-8"); + } + //========================== End of readFile() Method============================================ + validateUploadedFile(fileExtension) { + + if (fileExtension.toUpperCase() === 'json'.toUpperCase() || fileExtension.toUpperCase() === 'xml'.toUpperCase()) { + return true; + } + else { + return false; + } + + } + //========================== End of validateUploadedFile() Method============================================ + appendSlashes(artifactData) { + let x = artifactData.replace(new RegExp(',"', "g"), ',\"'); + let y = x.replace(new RegExp('":', 'g'), '\":'); + let z = y.replace(new RegExp('{"', 'g'), '{\"') + let t = z.replace(new RegExp(':"', 'g'), ':\"') + let m = t.replace(new RegExp('",', 'g'), '\",'); + let n = y.replace(new RegExp('"}', 'g'), '\"}') + let nw = n.replace(new RegExp('{"', 'g'), '{\"'); + let nw1 = nw.replace(new RegExp(':"', 'g'), ':\"'); + let nw2 = nw1.replace(new RegExp('",', 'g'), '\",'); + return nw2; + } + //========================== End of appendSlashes() Method============================================ + prepareDownloadData() { + this.onDownloadParameter(); + this.onDownloadTemplate('Template'); + } + //========================== End of prepareDownloadData() Method============================================ + syncTemplate() { + this.mappingEditorService.replaceNamesWithBlankValues(); + this.saveTemplate(); + + var templateData = this.mappingEditorService.paramData; //template data array + // this.paramShareService.setTemplateData(templateData); + + //console.log("Template Name value pairs ===" + JSON.stringify(templateData)) + var pdData = this.paramShareService.getSessionParamData(); //PD data array + console.log("PD name value pairs===" + JSON.stringify(pdData)) + + + var paramsContent = localStorage["paramsContent"]; + console.log("Param content before==" + paramsContent); + + if (paramsContent && paramsContent != undefined) { + try { + var paramTabData = JSON.parse(paramsContent); + //console.log("Param content after==" + paramsContent); + //console.log("Param tab data after==" + JSON.stringify(paramTabData)) + } + catch (error) { + console.log("error is : " + error) + } + } + var resultArr = []; + var json = {}; + var resultParamObj = {}; + let checkNamesOnlyCondition: boolean = true; + + if (templateData && templateData != undefined) { + templateData.forEach(function (item) { + if (item.paramValue !== "" && item.paramValue != undefined && item.paramValue != null) { + checkNamesOnlyCondition = false; + } + + }); + + templateData.forEach(function (item) { + resultParamObj[item.paramName] = item.paramValue; + }); + // console.log("pARAM Result array before is " + JSON.stringify(resultParamObj)) + if (paramTabData && paramTabData != undefined) { + templateData.forEach(function (item) { + for (var index in paramTabData) { + if (item.paramName === index) { + if (checkNamesOnlyCondition) { + resultParamObj[index] = paramTabData[index]; + } + else { + if (item.paramValue === "") { + resultParamObj[index] = paramTabData[index]; + } + else { + resultParamObj[index] = item.paramValue; + } + } + } + + } + + }); + + } + localStorage["paramsContent"] = JSON.stringify(resultParamObj); + //console.log("param content after==" +JSON.stringify(resultParamObj)); + + //removing duplicate elements from the array + templateData = Array.from(new Set(templateData.map((itemInArray) => itemInArray.paramName))) + + //reformatting arr1 to match with PD + templateData.forEach(function (item) { + + resultArr.push({ + "name": item, + "type": null, + "description": null, + "required": null, + "default": null, + "source": "Manual", + "rule-type": null, + "request-keys": [{ + "key-name": null, + "key-value": null + }, { + "key-name": null, + "key-value": null + }, { + "key-name": null, + "key-value": null + }], + "response-keys": [{ + "key-name": null, + "key-value": null + }, { + "key-name": null, + "key-value": null + }, { + "key-name": null, + "key-value": null + }, { + "key-name": null, + "key-value": null + }, { + "key-name": null, + "key-value": null + }], + "ruleTypeValues": [null] + + }) + }); + } + //console.log("Result array before is " + JSON.stringify(resultArr)) + // console.log("Length before is: " + resultArr.length) + + if (pdData && pdData != undefined) { + for (var i = 0; i < resultArr.length; i++) { + + pdData.forEach(function (arr2item) { + if (resultArr[i].name === arr2item.name) { + + var json = { + "name": arr2item.name, + "type": arr2item.type, + "description": arr2item.description, + "required": arr2item.required, + "default": arr2item.default, + "source": arr2item.source, + "rule-type": arr2item["rule-type"], + "request-keys": arr2item["request-keys"], + "response-keys": arr2item["response-keys"], + "ruleTypeValues": arr2item.ruleTypeValues + }; + resultArr.splice(i, 1, json) + // console.log("Result array index ==" + JSON.stringify(resultArr[i])) + } + + }); + + }; + + } + this.paramShareService.setSessionParamData(resultArr); + //console.log("Result array after is " + JSON.stringify(resultArr)) + //console.log("Length after is: " + resultArr.length) + this.mappingEditorService.paramData = []; + //navigate to PD page after sync + this + .router + .navigate(['../../../vnfs/design/parameterDefinitions/create']); + } + + //========================== End of syncTemplate() Method============================================ + mergeParams() { + var mergeStatus: boolean = this.mappingEditorService.autoAnnotateDataForParams(this.fileType); + if (mergeStatus) { + this.nService.success("Success", "Merge Successful"); + } + else { + this.nService.error("Error", "Merge Unsuccessful"); + } + this.saveTemplate(); + } + //========================== End of mergeParams() Method============================================ + public handleAnnotation(modal) { + + let selectedWord: string = this.templateeditor.getEditor().session.getTextRange(this.templateeditor.getEditor().selectionRange); + this.selectedWord = selectedWord; + modal.open(); + } + //========================== End of handleAnnotations() Method============================================ + public submitNameValues() { + /*var editor = this.templateeditor.getEditor() + this.editor = editor; + this.editor.session = editor.session; + this.editor.selection.session.$backMarkers = {}; + this.editorContent = this.artifactRequest.templateContent; + this.editor.$blockScrolling = Infinity; + this.editor.$blockSelectEnabled = false;*/ + if (this.tempName) { + this.checkNameEntered = true; + + if (this.selectedWord) { + if (this.selectedWord.startsWith('${(')) { + var replaceWord: any = this.selectedWord.substring(3, this.selectedWord.indexOf(')=(')) + this.tempName; + this.templateeditor.getEditor().session.replace(this.templateeditor.getEditor().session.selection.getRange(), replaceWord); + } else { + let mappingKey = this.mappingEditorService.getKeysForValues(this.selectedWord); + var replaceWord: any = '${(' + this.selectedWord + ')=(' + this.tempName + ')}'; + this.templateeditor.getEditor().session.replace(this.templateeditor.getEditor().session.selection.getRange(), replaceWord); + } + } + this.mappingEditorService.refreshEditor(); + this.tempName = ''; + this.modal.close(); + + } + else { + this.checkNameEntered = false; + } + + } + //========================== End of submitNameValues() Method============================================ +} diff --git a/src/app/vnfs/build-artifacts/template-holder/template-holder.component.css b/src/app/vnfs/build-artifacts/template-holder/template-holder.component.css new file mode 100644 index 0000000..7c075eb --- /dev/null +++ b/src/app/vnfs/build-artifacts/template-holder/template-holder.component.css @@ -0,0 +1,22 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/
\ No newline at end of file diff --git a/src/app/vnfs/build-artifacts/template-holder/template-holder.component.html b/src/app/vnfs/build-artifacts/template-holder/template-holder.component.html new file mode 100644 index 0000000..6668ed1 --- /dev/null +++ b/src/app/vnfs/build-artifacts/template-holder/template-holder.component.html @@ -0,0 +1,24 @@ +<!-- +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +--> + +<router-outlet></router-outlet>
\ No newline at end of file diff --git a/src/app/vnfs/build-artifacts/template-holder/template-holder.component.spec.ts b/src/app/vnfs/build-artifacts/template-holder/template-holder.component.spec.ts new file mode 100644 index 0000000..22c71d1 --- /dev/null +++ b/src/app/vnfs/build-artifacts/template-holder/template-holder.component.spec.ts @@ -0,0 +1,49 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + +/* tslint:disable:no-unused-variable */ +import {async, ComponentFixture, TestBed} from '@angular/core/testing'; + +import {GoldenConfigurationHolderComponent} from './template-holder.component'; + +describe('GoldenConfigurationHolderComponent', () => { + let component: GoldenConfigurationHolderComponent; + let fixture: ComponentFixture<GoldenConfigurationHolderComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [GoldenConfigurationHolderComponent] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(GoldenConfigurationHolderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/vnfs/build-artifacts/template-holder/template-holder.component.ts b/src/app/vnfs/build-artifacts/template-holder/template-holder.component.ts new file mode 100644 index 0000000..33bed31 --- /dev/null +++ b/src/app/vnfs/build-artifacts/template-holder/template-holder.component.ts @@ -0,0 +1,39 @@ +/* +============LICENSE_START========================================== +=================================================================== +Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. +=================================================================== + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the License); +you may not use this software except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +ECOMP is a trademark and service mark of AT&T Intellectual Property. +============LICENSE_END============================================ +*/ + +import {Component, OnInit} from '@angular/core'; + +@Component({ + selector: 'app-golden-configuration-holder', + templateUrl: './template-holder.component.html', + styleUrls: ['./template-holder.component.css'] +}) +export class GoldenConfigurationHolderComponent implements OnInit { + + constructor() { + } + + ngOnInit() { + } + +} |