diff options
40 files changed, 723 insertions, 592 deletions
diff --git a/cds-ui/designer-client/angular.json b/cds-ui/designer-client/angular.json index e503c1535..59ad17a7a 100644 --- a/cds-ui/designer-client/angular.json +++ b/cds-ui/designer-client/angular.json @@ -77,13 +77,13 @@ "buildOptimizer": true, "budgets": [{ "type": "initial", - "maximumWarning": "2mb", - "maximumError": "5mb" + "maximumWarning": "4mb", + "maximumError": "8mb" }, { "type": "anyComponentStyle", - "maximumWarning": "6kb", - "maximumError": "10kb" + "maximumWarning": "16kb", + "maximumError": "20kb" } ] } diff --git a/cds-ui/designer-client/package.json b/cds-ui/designer-client/package.json index a8427ee9e..59cc5b550 100644 --- a/cds-ui/designer-client/package.json +++ b/cds-ui/designer-client/package.json @@ -3,8 +3,8 @@ "version": "0.0.0", "scripts": { "ng": "ng", - "start": "npm run lint && ng serve --proxy-config proxy.conf.json", - "build": "npm run lint && ng build", + "start": "npm run lint && ng build --prod --aot && ng serve --proxy-config proxy.conf.json", + "build": "npm run lint && ng build --prod --aot ", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" @@ -77,4 +77,4 @@ "tslint": "~5.15.0", "typescript": "~3.5.3" } -} +}
\ No newline at end of file diff --git a/cds-ui/designer-client/src/app/common/core/services/api.typed.service.ts b/cds-ui/designer-client/src/app/common/core/services/api.typed.service.ts index d4851ded5..b73d48ed9 100644 --- a/cds-ui/designer-client/src/app/common/core/services/api.typed.service.ts +++ b/cds-ui/designer-client/src/app/common/core/services/api.typed.service.ts @@ -22,9 +22,9 @@ limitations under the License. ============LICENSE_END============================================ */ -import {Injectable} from '@angular/core'; -import {HttpClient, HttpParams} from '@angular/common/http'; -import {Observable} from 'rxjs'; +import { Injectable } from '@angular/core'; +import { HttpClient, HttpParams } from '@angular/common/http'; +import { Observable } from 'rxjs'; @Injectable() export class ApiService<T> { @@ -40,7 +40,7 @@ export class ApiService<T> { httpParams = httpParams.append(key, params[key]); } } - const options = {params: httpParams}; + const options = { params: httpParams }; return this.httpClient.get<T[]>(url, options); } @@ -49,6 +49,11 @@ export class ApiService<T> { return this.httpClient.post(url, body, options); } + delete(url: string, body: any | null): Observable<any> { + + return this.httpClient.delete(url, body); + } + getOne(url: string, params?: {}): Observable<T> { console.log('params', params); let httpParams = new HttpParams(); @@ -57,7 +62,7 @@ export class ApiService<T> { httpParams = httpParams.append(key, params[key]); } } - const options = {params: httpParams}; + const options = { params: httpParams }; return this.httpClient.get<T>(url, options); } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html index bf6bf1251..8e2ae5dbb 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.html @@ -8,7 +8,7 @@ <ul class="breadcrumb-header"> <li><a routerLink="/packages">CBA Packages</a></li> <i class="fa fa-angle-right ml-2 mr-2"></i> - <li>{{viewedPackage.artifactName}}</li> + <li>{{viewedPackage.artifactName}}</li> </ul> </h2> <div class="col"> @@ -22,8 +22,8 @@ <div class="container"> <div class="creat-action-container"> - <a class="action-button save" (click)="editBluePrint()" > - <i class="icon-save-sm" aria-hidden="true" ></i> + <a class="action-button save" (click)="editBluePrint()"> + <i class="icon-save-sm" aria-hidden="true"></i> <span>Save</span> </a> <a href="#" class="action-button" (click)="goBacktoDashboard()"> @@ -43,12 +43,12 @@ </a> <a class="action-button" - (click)="downloadPackage(viewedPackage.artifactName,viewedPackage.artifactVersion)"> + (click)="downloadPackage(viewedPackage.artifactName,viewedPackage.artifactVersion)"> <i class="icon-download" aria-hidden="true"></i> <span>Download</span> </a> - <a class="action-button delete"> + <a data-target="#removePackageModal" data-toggle="modal" class="action-button"> <i class="icon-delete-sm" aria-hidden="true"></i> <span>Delete</span> </a> @@ -83,19 +83,19 @@ <ul class="package-contributers"> <li> <button type="button" class="border-fade" data-toggle="tooltip" - data-placement="bottom" title="User name"> + data-placement="bottom" title="User name"> <img src="/assets/img/img-user1.jpeg"> </button> </li> <li> <button type="button" data-toggle="tooltip" data-placement="bottom" - title="User name"> + title="User name"> <img src="/assets/img/img-user2.jpg"> </button> </li> <li> <button type="button" data-toggle="tooltip" data-placement="bottom" - title="User name"> + title="User name"> <img src="/assets/img/img-user3.jpg"> </button> </li> @@ -138,7 +138,8 @@ <div class="row"> <!--Custom Action--> <div class="col-3 d-flex"> - <a class="d-flex" data-target="#carouselExampleIndicators" + <a class="d-flex" + data-target="#carouselExampleIndicators" data-slide-to="1"> <div class="card actionType custom"> <div class="card-body"> @@ -155,7 +156,8 @@ </div> <!--Default Action--> <div class="col-3 d-flex"> - <a class="d-flex" data-target="#carouselExampleIndicators" + <a class="d-flex" + data-target="#carouselExampleIndicators" data-slide-to="2"> <div class="card actionType default"> <div class="card-body"> @@ -173,7 +175,8 @@ </div> <!--Recent Action--> <div class="col-3 d-flex"> - <a class="d-flex" data-target="#carouselExampleIndicators" + <a class="d-flex" + data-target="#carouselExampleIndicators" data-slide-to="3"> <div class="card actionType recent"> <div class="card-body"> @@ -192,7 +195,8 @@ </div> <!--Import Action--> <div class="col-3 d-flex"> - <a class="d-flex" data-target="#carouselExampleIndicators" + <a class="d-flex" + data-target="#carouselExampleIndicators" data-slide-to="4"> <div class="card actionType import"> <div class="card-body"> @@ -209,7 +213,9 @@ </div> <div class="row"> <div class="col text-center"> - <button class="btn skip-btn" (click)="goToDesignerMode(viewedPackage.id)">Skip to Designer Canvas</button> + <button class="btn skip-btn" + (click)="goToDesignerMode(viewedPackage.id)">Skip + to Designer Canvas</button> </div> </div> </div> @@ -220,9 +226,12 @@ class="icon-action-back"></i></button> <h1>Create Custom Action</h1> <div class="form-group text-center"> - <input type="text" [(ngModel)]="customActionName" class="form-control customAction" + <input type="text" [(ngModel)]="customActionName" + class="form-control customAction" placeholder="Type Action Name" autofocus> - <button type="button" (click)="goToDesignerMode(viewedPackage.id)" class="btn submit">Start</button> + <button type="button" + (click)="goToDesignerMode(viewedPackage.id)" + class="btn submit">Start</button> </div> </div> @@ -392,7 +401,8 @@ <div class="row"> <div class="col text-center"> <p class="selectedActions">0 selected</p> - <button type="button" (click)="goToDesignerMode(viewedPackage.id)" + <button type="button" + (click)="goToDesignerMode(viewedPackage.id)" class="btn submit">Start</button> </div> </div> @@ -661,17 +671,17 @@ <div class="col"> <div class="nav nav-tabs " id="nav-tab" role="tablist"> <a class="nav-item nav-link active complete" id="nav-metadata-tab" data-toggle="tab" - href="#nav-metadata" role="tab" aria-controls="nav-metadata" aria-selected="true" - autofocus #nameit (focusout)="saveMetaData()">METADATA</a> + href="#nav-metadata" role="tab" aria-controls="nav-metadata" aria-selected="true" + autofocus #nameit (focusout)="saveMetaData()">METADATA</a> <a class="nav-item nav-link" id="nav-template-tab" data-toggle="tab" href="#nav-template" - role="tab" aria-controls="nav-template" aria-selected="false">TEMPLATE & MAPPING</a> + role="tab" aria-controls="nav-template" aria-selected="false">TEMPLATE & MAPPING</a> <a class="nav-item nav-link" id="nav-scripts-tab" data-toggle="tab" href="#nav-scripts" - role="tab" aria-controls="nav-scripts" aria-selected="false">SCRIPTS</a> + role="tab" aria-controls="nav-scripts" aria-selected="false">SCRIPTS</a> <a class="nav-item nav-link" id="nav-imports-tab" data-toggle="tab" href="#nav-imports" - role="tab" aria-controls="nav-imports" aria-selected="false">DEFINITIONS</a> + role="tab" aria-controls="nav-imports" aria-selected="false">DEFINITIONS</a> <a class="nav-item nav-link" id="nav-authentication-tab" data-toggle="tab" - href="#nav-authentication" role="tab" aria-controls="nav-authentication" - aria-selected="false">EXTERNAL SYSTEM AUTHENTICATION PROPERTIES</a> + href="#nav-authentication" role="tab" aria-controls="nav-authentication" + aria-selected="false">EXTERNAL SYSTEM AUTHENTICATION PROPERTIES</a> </div> </div> @@ -680,24 +690,24 @@ <div class="col"> <div class="tab-content" id="nav-tabContent"> <div class="tab-pane fade show active" id="nav-metadata" role="tabpanel" - aria-labelledby="nav-metadata-tab"> + aria-labelledby="nav-metadata-tab"> <app-metadata-tab></app-metadata-tab> </div> <div class="tab-pane fade" id="nav-template" role="tabpanel" - aria-labelledby="nav-template-tab"> + aria-labelledby="nav-template-tab"> <app-template-mapping></app-template-mapping> </div> <div class="tab-pane fade" id="nav-scripts" role="tabpanel" - aria-labelledby="nav-scripts-tab"> + aria-labelledby="nav-scripts-tab"> <app-scripts-tab></app-scripts-tab> </div> <div class="tab-pane fade" id="nav-imports" role="tabpanel" - aria-labelledby="nav-imports-tab"> + aria-labelledby="nav-imports-tab"> <app-imports-tab></app-imports-tab> </div> <div class="tab-pane fade" id="nav-authentication" role="tabpanel" - aria-labelledby="nav-authentication-tab"> + aria-labelledby="nav-authentication-tab"> <div class="card creat-card"> <div class="editor-container"> <app-dsl-definitions-tab></app-dsl-definitions-tab> @@ -711,3 +721,27 @@ </div> </div> </div> + + +<!-- Delete Modal --> +<div class="modal fade" id="removePackageModal" tabindex="-1" role="dialog" aria-labelledby="removePackageModalLabel" + aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="removePackageModalLabel">Delete Script</h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body"> + <p>Are you sure you want to delete this package?</p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button> + <button type="button" (click)="deletePackage()" data-dismiss="modal" + class="btn btn-primary">Delete</button> + </div> + </div> + </div> +</div>
\ No newline at end of file diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.ts index 471b25383..0e1d4cd11 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.component.ts @@ -1,20 +1,21 @@ -import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; -import {ActivatedRoute, Router} from '@angular/router'; -import {BluePrintDetailModel} from '../model/BluePrint.detail.model'; -import {PackageCreationStore} from '../package-creation/package-creation.store'; -import {FilesContent, FolderNodeElement, MetaDataTabModel} from '../package-creation/mapping-models/metadata/MetaDataTab.model'; -import {MetadataTabComponent} from '../package-creation/metadata-tab/metadata-tab.component'; +import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { BluePrintDetailModel } from '../model/BluePrint.detail.model'; +import { PackageCreationStore } from '../package-creation/package-creation.store'; +import { FilesContent, FolderNodeElement, MetaDataTabModel } from '../package-creation/mapping-models/metadata/MetaDataTab.model'; +import { MetadataTabComponent } from '../package-creation/metadata-tab/metadata-tab.component'; import * as JSZip from 'jszip'; -import {ConfigurationDashboardService} from './configuration-dashboard.service'; -import {VlbDefinition} from '../package-creation/mapping-models/definitions/VlbDefinition'; -import {DslDefinition} from '../package-creation/mapping-models/CBAPacakge.model'; -import {PackageCreationUtils} from '../package-creation/package-creation.utils'; -import {PackageCreationModes} from '../package-creation/creationModes/PackageCreationModes'; -import {PackageCreationBuilder} from '../package-creation/creationModes/PackageCreationBuilder'; -import {saveAs} from 'file-saver'; -import {DesignerStore} from '../designer/designer.store'; -import {DesignerService} from '../designer/designer.service'; -import {ToastrService} from 'ngx-toastr'; +import { ConfigurationDashboardService } from './configuration-dashboard.service'; +import { VlbDefinition } from '../package-creation/mapping-models/definitions/VlbDefinition'; +import { DslDefinition } from '../package-creation/mapping-models/CBAPacakge.model'; +import { PackageCreationUtils } from '../package-creation/package-creation.utils'; +import { PackageCreationModes } from '../package-creation/creationModes/PackageCreationModes'; +import { PackageCreationBuilder } from '../package-creation/creationModes/PackageCreationBuilder'; +import { saveAs } from 'file-saver'; +import { DesignerStore } from '../designer/designer.store'; +import { DesignerService } from '../designer/designer.service'; +import { ToastrService } from 'ngx-toastr'; +import { NgxFileDropEntry } from 'ngx-file-drop'; @Component({ selector: 'app-configuration-dashboard', @@ -23,35 +24,37 @@ import {ToastrService} from 'ngx-toastr'; }) export class ConfigurationDashboardComponent implements OnInit { viewedPackage: BluePrintDetailModel = new BluePrintDetailModel(); - @ViewChild(MetadataTabComponent, {static: false}) - private metadataTabComponent: MetadataTabComponent; + @ViewChild(MetadataTabComponent, { static: false }) + metadataTabComponent: MetadataTabComponent; public customActionName = ''; entryDefinitionKeys: string[] = ['template_tags', 'user-groups', 'author-email', 'template_version', 'template_name', 'template_author', 'template_description']; - @ViewChild('nameit', {static: true}) - private elementRef: ElementRef; - - private zipFile: JSZip = new JSZip(); - private filesData: any = []; - private folder: FolderNodeElement = new FolderNodeElement(); - - private currentBlob = new Blob(); - - constructor(private route: ActivatedRoute, private configurationDashboardService: ConfigurationDashboardService, - private packageCreationStore: PackageCreationStore, - private packageCreationUtils: PackageCreationUtils, - private router: Router, - private designerStore: DesignerStore, - private designerService: DesignerService, - private toastService: ToastrService + @ViewChild('nameit', { static: true }) + elementRef: ElementRef; + uploadedFiles = []; + zipFile: JSZip = new JSZip(); + filesData: any = []; + folder: FolderNodeElement = new FolderNodeElement(); + id: any; + + currentBlob = new Blob(); + + constructor( + private route: ActivatedRoute, + private configurationDashboardService: ConfigurationDashboardService, + private packageCreationStore: PackageCreationStore, + private packageCreationUtils: PackageCreationUtils, + private router: Router, + private designerStore: DesignerStore, + private toastService: ToastrService ) { } ngOnInit() { this.elementRef.nativeElement.focus(); - const id = this.route.snapshot.paramMap.get('id'); - this.configurationDashboardService.getPagedPackages(id).subscribe( + this.id = this.route.snapshot.paramMap.get('id'); + this.configurationDashboardService.getPagedPackages(this.id).subscribe( (bluePrintDetailModels) => { if (bluePrintDetailModels) { this.viewedPackage = bluePrintDetailModels[0]; @@ -59,45 +62,48 @@ export class ConfigurationDashboardComponent implements OnInit { this.packageCreationStore.clear(); } }); - } + if (this.route.snapshot.paramMap.has('id')) { + console.log('The id is equal to ' + this.route.snapshot.paramMap.get('id')); + } + } private downloadCBAPackage(bluePrintDetailModels: BluePrintDetailModel) { this.configurationDashboardService.downloadResource( bluePrintDetailModels[0].artifactName + '/' + bluePrintDetailModels[0].artifactVersion).subscribe(response => { - const blob = new Blob([response], {type: 'application/octet-stream'}); - this.currentBlob = blob; - this.zipFile.loadAsync(blob).then((zip) => { - Object.keys(zip.files).forEach((filename) => { - zip.files[filename].async('string').then((fileData) => { - if (fileData) { - if (filename.includes('Scripts/')) { - this.setScripts(filename, fileData); - } else if (filename.includes('Templates/')) { - if (filename.includes('-mapping.')) { - this.setMapping(filename, fileData); - } else if (filename.includes('-template.')) { - this.setTemplates(filename, fileData); + const blob = new Blob([response], { type: 'application/octet-stream' }); + this.currentBlob = blob; + this.zipFile.loadAsync(blob).then((zip) => { + Object.keys(zip.files).forEach((filename) => { + zip.files[filename].async('string').then((fileData) => { + if (fileData) { + if (filename.includes('Scripts/')) { + this.setScripts(filename, fileData); + } else if (filename.includes('Templates/')) { + if (filename.includes('-mapping.')) { + this.setMapping(filename, fileData); + } else if (filename.includes('-template.')) { + this.setTemplates(filename, fileData); + } + + } else if (filename.includes('Definitions/')) { + this.setImports(filename, fileData, bluePrintDetailModels); + } else if (filename.includes('TOSCA-Metadata/')) { + const metaDataTabInfo: MetaDataTabModel = this.getMetaDataTabInfo(fileData); + this.setMetaData(metaDataTabInfo, bluePrintDetailModels[0]); } - - } else if (filename.includes('Definitions/')) { - this.setImports(filename, fileData, bluePrintDetailModels); - } else if (filename.includes('TOSCA-Metadata/')) { - const metaDataTabInfo: MetaDataTabModel = this.getMetaDataTabInfo(fileData); - this.setMetaData(metaDataTabInfo, bluePrintDetailModels[0]); } - } + }); }); }); }); - }); } - private setScripts(filename: string, fileData: any) { + setScripts(filename: string, fileData: any) { this.packageCreationStore.addScripts(filename, fileData); } - private setImports(filename: string, fileData: any, bluePrintDetailModels: BluePrintDetailModel) { + setImports(filename: string, fileData: any, bluePrintDetailModels: BluePrintDetailModel) { if (filename.includes(bluePrintDetailModels[0].artifactName)) { let definition = new VlbDefinition(); definition = fileData as VlbDefinition; @@ -121,11 +127,11 @@ export class ConfigurationDashboardComponent implements OnInit { } } - private setTemplates(filename: string, fileData: any) { + setTemplates(filename: string, fileData: any) { this.packageCreationStore.addTemplate(filename, fileData); } - private setMapping(fileName: string, fileData: string) { + setMapping(fileName: string, fileData: string) { this.packageCreationStore.addMapping(fileName, fileData); } @@ -143,7 +149,7 @@ export class ConfigurationDashboardComponent implements OnInit { }); } - private setMetaData(metaDataObject: MetaDataTabModel, bluePrintDetailModel: BluePrintDetailModel) { + setMetaData(metaDataObject: MetaDataTabModel, bluePrintDetailModel: BluePrintDetailModel) { metaDataObject.description = bluePrintDetailModel.artifactDescription; this.packageCreationStore.changeMetaData(metaDataObject); @@ -166,7 +172,7 @@ export class ConfigurationDashboardComponent implements OnInit { saveBluePrintToDataBase() { this.create(); - this.zipFile.generateAsync({type: 'blob'}) + this.zipFile.generateAsync({ type: 'blob' }) .then(blob => { this.packageCreationStore.saveBluePrint(blob).subscribe( bluePrintDetailModels => { @@ -182,7 +188,15 @@ export class ConfigurationDashboardComponent implements OnInit { }); } - + deletePackage() { + this.configurationDashboardService.deletePackage(this.id).subscribe(res => { + console.log('Deleted'); + console.log(res); + this.router.navigate(['/packages']); + }, err => { + console.log(err); + }); + } create() { this.zipFile = new JSZip(); FilesContent.getMapOfFilesNamesAndContent().forEach((value, key) => { @@ -198,7 +212,7 @@ export class ConfigurationDashboardComponent implements OnInit { downloadPackage(artifactName: string, artifactVersion: string) { this.configurationDashboardService.downloadResource(artifactName + '/' + artifactVersion).subscribe(response => { - const blob = new Blob([response], {type: 'application/octet-stream'}); + const blob = new Blob([response], { type: 'application/octet-stream' }); saveAs(blob, artifactName + '-' + artifactVersion + '-CBA.zip'); }); } @@ -221,6 +235,17 @@ export class ConfigurationDashboardComponent implements OnInit { goToDesignerMode(id) { // this.designerService.setActionName(this.customActionName); - this.router.navigate(['/packages/designer', id, {actionName: this.customActionName}]); + this.router.navigate(['/packages/designer', id, { actionName: this.customActionName }]); + } + + public dropped(files: NgxFileDropEntry[]) { + + } + public fileOver(event) { + console.log(event); + } + + public fileLeave(event) { + console.log(event); } } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.service.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.service.ts index 164d76601..c7f557121 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.service.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/configuration-dashboard/configuration-dashboard.service.ts @@ -1,8 +1,8 @@ -import {Injectable} from '@angular/core'; -import {ApiService} from '../../../../common/core/services/api.typed.service'; -import {BlueprintURLs} from '../../../../common/constants/app-constants'; -import {Observable} from 'rxjs'; -import {BluePrintDetailModel} from '../model/BluePrint.detail.model'; +import { Injectable } from '@angular/core'; +import { ApiService } from '../../../../common/core/services/api.typed.service'; +import { BlueprintURLs } from '../../../../common/constants/app-constants'; +import { Observable } from 'rxjs'; +import { BluePrintDetailModel } from '../model/BluePrint.detail.model'; @Injectable({ @@ -22,10 +22,13 @@ export class ConfigurationDashboardService { } public downloadResource(path: string) { - return this.api.getCustomized(BlueprintURLs.download + path, {responseType: 'blob'}); + return this.api.getCustomized(BlueprintURLs.download + path, { responseType: 'blob' }); } deployPost(body: any | null): Observable<any> { - return this.api.post(BlueprintURLs.deploy, body, {responseType: 'text'}); + return this.api.post(BlueprintURLs.deploy, body, { responseType: 'text' }); + } + deletePackage(id: string) { + return this.api.delete(BlueprintURLs.getOneBlueprint + '/' + id, { observe: 'response' }); } } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.ts index e2a8d642b..9462caf68 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/designer.component.ts @@ -49,8 +49,8 @@ import { isDefined } from '@angular/compiler/src/util'; }) export class DesignerComponent implements OnInit, OnDestroy { - private controllerSideBar: boolean; - private attributesSideBar: boolean; + controllerSideBar: boolean; + attributesSideBar: boolean; functionAttributeSidebar: boolean; viewedPackage: BluePrintDetailModel = new BluePrintDetailModel(); customActionName: string; @@ -62,31 +62,32 @@ export class DesignerComponent implements OnInit, OnDestroy { paletteGraph: joint.dia.Graph; palettePaper: joint.dia.Paper; - private ngUnsubscribe = new Subject(); - private opt = { tx: 100, ty: 100 }; - - constructor(private designerStore: DesignerStore, - private functionStore: FunctionsStore, - private graphUtil: GraphUtil, - private graphGenerator: GraphGenerator, - private route: ActivatedRoute, - private designerService: DesignerService) { + ngUnsubscribe = new Subject(); + opt = { tx: 100, ty: 100 }; + + constructor( + private designerStore: DesignerStore, + private functionStore: FunctionsStore, + private graphUtil: GraphUtil, + private graphGenerator: GraphGenerator, + private route: ActivatedRoute, + private designerService: DesignerService) { this.controllerSideBar = true; this.attributesSideBar = false; this.showAction = false; this.functionAttributeSidebar = false; } - private _toggleSidebar1() { + _toggleSidebar1() { this.controllerSideBar = !this.controllerSideBar; if (this.controllerSideBar === false) { this.cl = 'editBar2'; - } + } if (this.controllerSideBar === true) { - this.cl = 'editBar'; - } + this.cl = 'editBar'; + } } - private _toggleSidebar2() { + _toggleSidebar2() { this.attributesSideBar = !this.attributesSideBar; } // private _toggleSidebar3() { @@ -164,7 +165,7 @@ export class DesignerComponent implements OnInit, OnDestroy { * auto arrange elements in graph * https://resources.jointjs.com/docs/jointjs/v3.1/joint.html#layout.DirectedGraph */ - joint.layout.DirectedGraph.layout( this.boardGraph.getCells(), { + joint.layout.DirectedGraph.layout(this.boardGraph.getCells(), { dagre, graphlib, setLinkVertices: false, @@ -203,17 +204,17 @@ export class DesignerComponent implements OnInit, OnDestroy { console.log('initializeBoard...'); this.boardGraph = new joint.dia.Graph(); this.boardPaper = new joint.dia.Paper({ - el: $('#board-paper'), - model: this.boardGraph, - // height: 720, - // width: 1100, - gridSize: 10, - drawGrid: true, - // background: { - // color: 'rgba(0, 255, 0, 0.3)' - // }, - cellViewNamespace: joint.shapes - }); + el: $('#board-paper'), + model: this.boardGraph, + // height: 720, + // width: 1100, + gridSize: 10, + drawGrid: true, + // background: { + // color: 'rgba(0, 255, 0, 0.3)' + // }, + cellViewNamespace: joint.shapes + }); this.boardPaper.on('all', element => { // console.log(element); @@ -273,13 +274,13 @@ export class DesignerComponent implements OnInit, OnDestroy { $('body').append(` <div id="flyPaper" style="position:fixed;z-index:100;opacity:.7;pointer-event:none;background-color: transparent !important;"></div>` - ); + ); const flyGraph = new joint.dia.Graph(); const flyPaper = new joint.dia.Paper({ - el: $('#flyPaper'), - model: flyGraph, - interactive: true - }); + el: $('#flyPaper'), + model: flyGraph, + interactive: true + }); const flyShape = draggedCell.model.clone(); const pos = draggedCell.model.position(); const offset = { @@ -312,15 +313,15 @@ export class DesignerComponent implements OnInit, OnDestroy { // step name is CDS realted terminology, please refer to tosca types const stepName = functionType; const functionElementForBoard = this.graphUtil.dropFunctionOverActionWithPosition( - stepName, functionType, - mouseupX, mouseupY, - target, offset, - this.boardGraph); + stepName, functionType, + mouseupX, mouseupY, + target, offset, + this.boardGraph); const parentCell = this.graphUtil.getParent(functionElementForBoard, this.boardPaper); if (parentCell && - parentCell.model.attributes.type === ActionElementTypeName && + parentCell.model.attributes.type === ActionElementTypeName && this.graphUtil.canEmpedMoreChildern(parentCell.model, this.boardGraph)) { if (this.graphUtil.isEmptyParent(parentCell.model)) { diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.ts index a092e0c0f..69401928f 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/designer/source-view/source-view.component.ts @@ -17,17 +17,18 @@ export class DesignerSourceViewComponent implements OnInit, OnDestroy { content = ''; lang = 'json'; - private controllerSideBar: boolean; - private ngUnsubscribe = new Subject(); + controllerSideBar: boolean; + ngUnsubscribe = new Subject(); viewedPackage: BluePrintDetailModel = new BluePrintDetailModel(); public customActionName = ''; cl = 'editBar'; - constructor(private store: DesignerStore, - private packageCreationUtils: PackageCreationUtils, - private router: Router, - private route: ActivatedRoute, - private sourceViewService: SourceViewService) { + constructor( + private store: DesignerStore, + private packageCreationUtils: PackageCreationUtils, + private router: Router, + private route: ActivatedRoute, + private sourceViewService: SourceViewService) { this.controllerSideBar = true; } private _toggleSidebar1() { @@ -60,7 +61,7 @@ export class DesignerSourceViewComponent implements OnInit, OnDestroy { // TODO validate json against scheme console.log('convertAndOpenInDesingerView ...', this.content); this.store.saveSourceContent(this.content); - this.router.navigate(['/packages/designer', id, {actionName: this.customActionName}]); + this.router.navigate(['/packages/designer', id, { actionName: this.customActionName }]); } ngOnDestroy() { diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.html index 28f8938a7..9bd08b7cb 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.html @@ -32,7 +32,7 @@ <div class="single-line-model"> <label class="label-name">Name <span>*</span></label> <div class="label-input"> - <input type="input" [readOnly]="!packageNameAndVersionEnables" [(ngModel)]="metaDataTab.name" + <input type="input" [readOnly]="!packageNameAndVersionEnables" (change)="checkRequiredElements()" [(ngModel)]="metaDataTab.name" placeholder="Package name"> </div> <!--<div class="model-note-container error-message"> @@ -44,7 +44,7 @@ <div class="single-line-model"> <label class="label-name">Version <span>*</span></label> <div class="label-input"> - <input type="input" [readOnly]="!packageNameAndVersionEnables" [(ngModel)]="metaDataTab.version" + <input type="input" [readOnly]="!packageNameAndVersionEnables" (change)="checkRequiredElements()" [(ngModel)]="metaDataTab.version" (input)="validatePackageNameAndVersion()" [pattern]="versionPattern" placeholder="Example: 1.0.0"> </div> <div class="model-note-container error-message">{{errorMessage}}</div> @@ -52,15 +52,14 @@ <div class="single-line-model"> <label class="label-name">Description <span>*</span></label> <div class="label-input"> - <input type="input" [(ngModel)]="metaDataTab.description" placeholder="Descripe the package"> + <input type="input" [(ngModel)]="metaDataTab.description" (change)="checkRequiredElements()" placeholder="Descripe the package"> </div> </div> <div class="single-line-model"> <label class="label-name">Tags</label> <div class="label-input"> - <input type="input" (keyup.enter)="addTag($event)" [(ngModel)]="metaDataTab.tags" - placeholder="Ex., vDNS-CDS"> + <input type="input" (keyup.enter)="addTag($event)" placeholder="Ex., vDNS-CDS"> </div> <div class="model-note-container tag-notes">Use ENTER to add tag</div> <div class="model-note-container tages-container"> @@ -75,7 +74,7 @@ <div class="card creat-card"> <div class="single-line customKeyTitle"> <h5 class="label-name w-100 "> - Custom key + Custom key </h5> <span>To add New Custom Key, fill the first key then <b>Press ENTER</b></span> diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.ts index dd9f45bf4..c82ccc6b6 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/metadata-tab/metadata-tab.component.ts @@ -1,8 +1,8 @@ -import { Component, OnInit } from '@angular/core'; -import { PackageCreationService } from '../package-creation.service'; -import { MetaDataTabModel } from '../mapping-models/metadata/MetaDataTab.model'; -import { PackageCreationStore } from '../package-creation.store'; -import { ActivatedRoute } from '@angular/router'; +import {Component, OnInit} from '@angular/core'; +import {PackageCreationService} from '../package-creation.service'; +import {MetaDataTabModel} from '../mapping-models/metadata/MetaDataTab.model'; +import {PackageCreationStore} from '../package-creation.store'; +import {ActivatedRoute} from '@angular/router'; @Component({ @@ -16,12 +16,12 @@ export class MetadataTabComponent implements OnInit { tags = new Set<string>(); customKeysMap = new Map(); modes: any[] = [ - { name: 'Designer Mode', style: 'mode-icon icon-topologyView-active' }]; + {name: 'Designer Mode', style: 'mode-icon icon-topologyView-active'}]; /* {name: 'Scripting Mode', style: 'mode-icon icon-topologySource'}, {name: 'Generic Script Mode', style: 'mode-icon icon-topologySource'}];*/ modeType = this.modes[0].name; - private metaDataTab: MetaDataTabModel = new MetaDataTabModel(); - private errorMessage: string; + metaDataTab: MetaDataTabModel = new MetaDataTabModel(); + errorMessage: string; versionPattern = '^(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)$'; constructor( @@ -104,8 +104,10 @@ export class MetadataTabComponent implements OnInit { this.packageCreationService.checkBluePrintNameAndVersion(this.metaDataTab.name, this.metaDataTab.version).then(element => { if (element) { this.errorMessage = 'Package name already exists with this version. Use different name or different version number.'; + } else if (!this.metaDataTab.version.match(this.versionPattern)) { + this.errorMessage = 'version should be as example 1.0.0'; } else { - this.errorMessage = ' '; + this.errorMessage = ''; } }); } @@ -115,4 +117,17 @@ export class MetadataTabComponent implements OnInit { saveMetaDataToStore() { this.packageCreationStore.changeMetaData(this.metaDataTab); } + + checkRequiredElements() { + const newMetaData = new MetaDataTabModel(); + newMetaData.description = this.metaDataTab.description; + newMetaData.name = this.metaDataTab.name; + newMetaData.version = this.metaDataTab.version; + newMetaData.templateTags = this.metaDataTab.templateTags; + newMetaData.mapOfCustomKey = this.metaDataTab.mapOfCustomKey; + newMetaData.mode = this.metaDataTab.mode; + this.packageCreationStore.changeMetaData(newMetaData); + } + + } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.html index baf6ea9e3..7afea6b9a 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.html @@ -20,35 +20,13 @@ <div class="container-fluid body-container"> <div class="container"> <div class="creat-action-container"> - <a class="action-button save" (click)="saveBluePrint()"> - <i class="icon-save-sm" aria-hidden="true"></i> - <span>Save</span> - </a> - <a href="#" class="action-button" (click)="goBackToDashBorad()"> - <i class="icon-discard-sm" aria-hidden="true"></i> - <span>Discard Changes</span> - </a> - - <hr> - <a href="#" class="action-button"> - <i class="icon-clone-sm" aria-hidden="true"></i> - <span>Clone</span> - </a> - - <a href="#" class="action-button"> - <i class="icon-archive-sm" aria-hidden="true"></i> - <span>Archive</span> - </a> - - <a href="#" class="action-button"> - <i class="icon-download" aria-hidden="true"></i> - <span>Download</span> - </a> - - <a href="#" class="action-button delete"> - <i class="icon-delete-sm" aria-hidden="true"></i> - <span>Delete</span> - </a> + <!-- <a class="action-button save" [hidden]="!isSaveEnabled" (click)="saveBluePrint()"> + <i class="icon-save-sm" aria-hidden="true"></i> + <span>Save</span>--> + <button (click)="saveBluePrint()" [disabled]="!isSaveEnabled" + class="action-button save" aria-hidden="true"><i class="icon-save-sm" + aria-hidden="true"></i> + <span>Save</span></button> </div> @@ -57,17 +35,17 @@ <div class="col"> <div class="nav nav-tabs " id="nav-tab" role="tablist"> <a class="nav-item nav-link active" id="nav-metadata-tab" data-toggle="tab" - href="#nav-metadata" role="tab" aria-controls="nav-metadata" aria-selected="false" - autofocus #nameit (focusout)="test()">METADATA</a> + href="#nav-metadata" role="tab" aria-controls="nav-metadata" aria-selected="false" + autofocus #nameit (focusout)="test()">METADATA</a> <a class="nav-item nav-link" id="nav-template-tab" data-toggle="tab" href="#nav-template" - role="tab" aria-controls="nav-template" aria-selected="false">TEMPLATE & MAPPING</a> + role="tab" aria-controls="nav-template" aria-selected="false">TEMPLATE & MAPPING</a> <a class="nav-item nav-link" id="nav-scripts-tab" data-toggle="tab" href="#nav-scripts" - role="tab" aria-controls="nav-scripts" aria-selected="false">SCRIPTS</a> + role="tab" aria-controls="nav-scripts" aria-selected="false">SCRIPTS</a> <a class="nav-item nav-link" id="nav-imports-tab" data-toggle="tab" href="#nav-imports" - role="tab" aria-controls="nav-imports" aria-selected="false">DEFINITIONS</a> + role="tab" aria-controls="nav-imports" aria-selected="false">DEFINITIONS</a> <a class="nav-item nav-link" id="nav-authentication-tab" data-toggle="tab" - href="#nav-authentication" role="tab" aria-controls="nav-authentication" - aria-selected="false">EXTERNAL SYSTEM AUTHENTICATION PROPERTIES</a> + href="#nav-authentication" role="tab" aria-controls="nav-authentication" + aria-selected="false">EXTERNAL SYSTEM AUTHENTICATION PROPERTIES</a> </div> </div> @@ -76,24 +54,24 @@ <div class="col"> <div class="tab-content" id="nav-tabContent"> <div class="tab-pane fade show active" id="nav-metadata" role="tabpanel" - aria-labelledby="nav-metadata-tab"> + aria-labelledby="nav-metadata-tab"> <app-metadata-tab></app-metadata-tab> </div> <div class="tab-pane fade" id="nav-template" role="tabpanel" - aria-labelledby="nav-template-tab"> + aria-labelledby="nav-template-tab"> <app-template-mapping></app-template-mapping> </div> <div class="tab-pane fade" id="nav-scripts" role="tabpanel" - aria-labelledby="nav-scripts-tab"> + aria-labelledby="nav-scripts-tab"> <app-scripts-tab></app-scripts-tab> </div> <div class="tab-pane fade" id="nav-imports" role="tabpanel" - aria-labelledby="nav-imports-tab"> + aria-labelledby="nav-imports-tab"> <app-imports-tab></app-imports-tab> </div> <div class="tab-pane fade" id="nav-authentication" role="tabpanel" - aria-labelledby="nav-authentication-tab"> + aria-labelledby="nav-authentication-tab"> <div class="card creat-card"> <div class="editor-container"> <app-dsl-definitions-tab></app-dsl-definitions-tab> diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.ts index 57c849761..bba45c810 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.component.ts @@ -43,30 +43,43 @@ export class PackageCreationComponent implements OnInit { // adding initial referencing to designer mode - constructor(private packageCreationStore: PackageCreationStore, - private packageCreationUtils: PackageCreationUtils, - private router: Router, - private toastService: ToastrService) { + constructor( + private packageCreationStore: PackageCreationStore, + private packageCreationUtils: PackageCreationUtils, + private router: Router, + private toastService: ToastrService) { } counter = 0; modes: object[] = [ {name: 'Designer Mode', style: 'mode-icon icon-designer-mode'}, {name: 'Scripting Mode', style: 'mode-icon icon-scripting-mode'}]; - private metaDataTab: MetaDataTabModel = new MetaDataTabModel(); - private folder: FolderNodeElement = new FolderNodeElement(); - private zipFile: JSZip = new JSZip(); - private filesData: any = []; - private definition: Definition = new Definition(); + metaDataTab: MetaDataTabModel = new MetaDataTabModel(); + folder: FolderNodeElement = new FolderNodeElement(); + zipFile: JSZip = new JSZip(); + filesData: any = []; + definition: Definition = new Definition(); + isSaveEnabled = false; @ViewChild(MetadataTabComponent, {static: false}) - private metadataTabComponent: MetadataTabComponent; + metadataTabComponent: MetadataTabComponent; @ViewChild('nameit', {static: true}) - private elementRef: ElementRef; + elementRef: ElementRef; + versionPattern = '^(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)$'; ngOnInit() { this.elementRef.nativeElement.focus(); + const regexp = RegExp(this.versionPattern); + this.packageCreationStore.state$.subscribe(cbaPackage => { + if (cbaPackage && cbaPackage.metaData && cbaPackage.metaData.description + && cbaPackage.metaData.name && cbaPackage.metaData.version && + regexp.test(cbaPackage.metaData.version)) { + this.isSaveEnabled = true; + } else { + this.isSaveEnabled = false; + } + }); } saveBluePrint() { @@ -99,7 +112,7 @@ export class PackageCreationComponent implements OnInit { this.router.navigate(['/packages/package/' + id]); } }, error => { - // this.toastService.error('error happened when editing ' + error.message); + // this.toastService.error('error happened when editing ' + error.message); console.log('Error -' + error.message); }); }); diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.store.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.store.ts index ce5dc4884..55e715654 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.store.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/package-creation.store.ts @@ -19,16 +19,16 @@ limitations under the License. ============LICENSE_END============================================ */ -import {Injectable} from '@angular/core'; +import { Injectable } from '@angular/core'; -import {Store} from '../../../../common/core/stores/Store'; +import { Store } from '../../../../common/core/stores/Store'; -import {CBAPackage, DslDefinition} from './mapping-models/CBAPacakge.model'; -import {PackageCreationService} from './package-creation.service'; -import {MetaDataTabModel} from './mapping-models/metadata/MetaDataTab.model'; -import {Observable} from 'rxjs'; -import {ResourceDictionary} from './mapping-models/ResourceDictionary.model'; -import {BluePrintDetailModel} from '../model/BluePrint.detail.model'; +import { CBAPackage, DslDefinition } from './mapping-models/CBAPacakge.model'; +import { PackageCreationService } from './package-creation.service'; +import { MetaDataTabModel } from './mapping-models/metadata/MetaDataTab.model'; +import { Observable } from 'rxjs'; +import { ResourceDictionary } from './mapping-models/ResourceDictionary.model'; +import { BluePrintDetailModel } from '../model/BluePrint.detail.model'; @Injectable({ @@ -56,6 +56,9 @@ export class PackageCreationStore extends Store<CBAPackage> { }); } + istemplateExist(): boolean { + return this.state.templates.files.size > 0 && this.state.mapping.files.size > 0; + } changeDslDefinition(dslDefinition: DslDefinition) { this.setState({ diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.html index cdc73f1b9..e1b0f83d6 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.html @@ -1,12 +1,12 @@ <div class="row template-mapping-action"> <div class="col"> <h6 [hidden]="edit" class="create-title">Create Template</h6> - <button (click)="closeCreationForm()" [hidden]="!edit" class="btn btn-outline-secondary"><i + <button (click)="openListView()" [hidden]="!edit" class="btn btn-outline-secondary"><i class="fa fa-chevron-left mr-2"></i>Template List</button> </div> <div class="col text-right"> - <button data-toggle="modal" [hidden]="!edit" (click)="initDelete()" data-target="#templateDeletionModal2" + <button data-toggle="modal" [hidden]="!edit" data-target="#templateDeletionModal2" class="btn btn-outline-danger" title="Delete Template">Delete</button> @@ -301,4 +301,4 @@ </div> </div> </div> -</div> +</div>
\ No newline at end of file diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.ts index f6bae0600..af7acc2d0 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-creation/templ-mapp-creation.component.ts @@ -18,11 +18,11 @@ declare var $: any; styleUrls: ['./templ-mapp-creation.component.css'] }) export class TemplMappCreationComponent implements OnInit, OnDestroy { - @Output() showListViewParent = new EventEmitter<any>(); - @Output() openList = new EventEmitter<any>(); + @Output() showListView = new EventEmitter<any>(); + @Output() showCreationView = new EventEmitter<any>(); public uploadedFiles: FileSystemFileEntry[] = []; - private fileNames: Set<string> = new Set(); - private jsonConvert = new JsonConvert(); + fileNames: Set<string> = new Set(); + jsonConvert = new JsonConvert(); public files: NgxFileDropEntry[] = []; fileName: any; templateInfo = new TemplateInfo(); @@ -179,8 +179,6 @@ export class TemplMappCreationComponent implements OnInit, OnDestroy { this.uploadedFiles.splice(index, 1); } - initDelete(file) { - } confirmDelete() { // Delete from templates this.sharedService.deleteFromList(this.fileName); @@ -191,7 +189,7 @@ export class TemplMappCreationComponent implements OnInit, OnDestroy { this.packageCreationStore.state.templates.files.size > 0 || this.packageCreationStore.state.mapping.files.size > 0 ) { - this.closeCreationForm(); + this.openListView(); } } @@ -267,11 +265,13 @@ export class TemplMappCreationComponent implements OnInit, OnDestroy { } openListView() { - this.showListViewParent.emit('tell parent to open create views'); + console.log('open List view'); + this.showListView.emit('tell parent to open create views'); } - closeCreationForm() { - this.openList.emit('close create form and open list'); + openCreationView() { + console.log('close creation view'); + this.showCreationView.emit('close create form and open list'); } getMappingTableFromTemplate(e) { @@ -337,7 +337,7 @@ export class TemplMappCreationComponent implements OnInit, OnDestroy { // } this.fileName = ''; this.toastr.success('File is created', 'success'); - this.closeCreationForm(); + this.openListView(); } else { console.log('this file already exist'); this.toastr.error('File name already exist', 'Error'); @@ -351,6 +351,7 @@ export class TemplMappCreationComponent implements OnInit, OnDestroy { selectSource(dict, e) { const source = e.target.value; let keyDepend = null; + this.dependancies.set(dict.name, null); try { keyDepend = dict.definition.sources[source].properties['key-dependencies'] || null; } catch (e) { } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.html index e49b25a0c..3e377981e 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.html @@ -1,4 +1,4 @@ -<a (click)="openCreationView()" class="create-template-mapping-button"> +<a (click)="createNewTemplate()" class="create-template-mapping-button"> <i class="fa fa-plus"></i> <span>Create Template</span> </a> diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.ts index c790422c1..26740f3e1 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/templ-mapp-listing/templ-mapp-listing.component.ts @@ -13,11 +13,11 @@ import { SharedService } from '../shared-service'; styleUrls: ['./templ-mapp-listing.component.css'] }) export class TemplMappListingComponent implements OnInit { - @Output() showCreationViewParentNotification = new EventEmitter<any>(); - @Output() showFullView = new EventEmitter<any>(); - private templateAndMappingMap = new Map<string, TemplateAndMapping>(); - private templates: Template; - private mapping: Mapping; + @Output() showCreationView = new EventEmitter<any>(); + @Output() showListView = new EventEmitter<any>(); + templateAndMappingMap = new Map<string, TemplateAndMapping>(); + templates: Template; + mapping: Mapping; isCreate = true; currentFile: string; edit = false; @@ -40,6 +40,11 @@ export class TemplMappListingComponent implements OnInit { } this.packageCreationStore.state$.subscribe(cba => { + if (this.packageCreationStore.state.mapping.files.size > 0 || this.packageCreationStore.state.templates.files.size > 0) { + this.openListView(); + } else { + this.openCreationView(); + } if (cba.templates) { this.templates = cba.templates; this.mapping = cba.mapping; @@ -58,7 +63,6 @@ export class TemplMappListingComponent implements OnInit { const isFromTemplate = false; this.setIsMappingOrTemplate(key, templateAndMapping, isFromTemplate); }); - console.log('hello there '); console.log(this.templateAndMappingMap); } this.deleteFromList(); @@ -83,6 +87,7 @@ export class TemplMappListingComponent implements OnInit { console.log('response from actionList'); console.log(res); if (res) { + console.log('xccccccccccvvvvvv'); this.templateAndMappingMap.delete(res); if (this.templateAndMappingMap.size <= 0) { this.openCreationView(); @@ -91,14 +96,17 @@ export class TemplMappListingComponent implements OnInit { }); } + createNewTemplate() { + this.openCreationView(); + this.sharedService.disableEdit(); + } openCreationView() { - this.showCreationViewParentNotification.emit('tell parent to open create views'); + this.showCreationView.emit('tell parent to open create views'); console.log('disable edit mode'); - this.sharedService.disableEdit(); - } - FullView() { - this.showFullView.emit('show full view'); + openListView() { + console.log('open list view'); + this.showListView.emit('show full view'); } setSourceCodeEditor(key: string) { @@ -125,7 +133,7 @@ export class TemplMappListingComponent implements OnInit { templateInfo.type += 'mapping'; } this.templateStore.changeTemplateInfo(templateInfo); - this.FullView(); + this.openCreationView(); this.sharedService.enableEdit(); }); } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.html b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.html index f4f305ee9..48a503321 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.html +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.html @@ -1,10 +1,9 @@ <div [hidden]="listView"> - <app-templ-mapp-listing [hidden]="!creationView" (showCreationViewParentNotification)="openCreationView($event)" - (showFullView)="openListView($event)"> + <app-templ-mapp-listing (showCreationView)="openCreationView()" (showListView)="openListView()"> </app-templ-mapp-listing> </div> <div [hidden]="creationView"> - <app-templ-mapp-creation (showListViewParent)="openListView($event)" (openList)="closeCreationView()"> + <app-templ-mapp-creation (showListView)="openListView()" (showCreationView)="openCreationView()"> </app-templ-mapp-creation> </div>
\ No newline at end of file diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.ts index af6ced092..341d29f66 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/package-creation/template-mapping/template-mapping.component.ts @@ -26,9 +26,8 @@ export class TemplateMappingComponent implements OnInit { this.creationView = true; this.listView = false; console.log('URL contains Id'); - this.sharedService.enableEdit(); - if (this.pakcageStore.state.mapping.files.size > 0 || this.pakcageStore.state.templates.files.size > 0) { - this.openListView(); + if (this.pakcageStore.istemplateExist()) { + this.sharedService.enableEdit(); } } else { console.log('Create mode'); @@ -37,18 +36,16 @@ export class TemplateMappingComponent implements OnInit { } } openCreationView() { + console.log('open creation view'); this.creationView = false; this.listView = true; } openListView() { - this.listView = false; - this.creationView = false; - } - - closeCreationView() { + console.log('open list view'); this.creationView = true; this.listView = false; + } } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/filter-by-tags/filter-by-tags.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/filter-by-tags/filter-by-tags.component.ts index 28be5f5c8..228b6d6ab 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/filter-by-tags/filter-by-tags.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/filter-by-tags/filter-by-tags.component.ts @@ -19,9 +19,9 @@ limitations under the License. ============LICENSE_END============================================ */ -import {Component, OnDestroy, OnInit} from '@angular/core'; -import {PackagesStore} from '../../packages.store'; -import {BlueprintModel, BluePrintPage} from '../../model/BluePrint.model'; +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { PackagesStore } from '../../packages.store'; +import { BlueprintModel, BluePrintPage } from '../../model/BluePrint.model'; @Component({ selector: 'app-filter-by-tags', @@ -36,7 +36,7 @@ export class TagsFilteringComponent implements OnInit { viewedTags: string[] = []; searchTag = ''; viewedPackages: BlueprintModel[] = []; - private checkBoxTages = ''; + checkBoxTages = ''; currentPage = 0; constructor(private packagesStore: PackagesStore, diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/search-by-packages/search-by-packages.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/search-by-packages/search-by-packages.component.ts index 91304e5c2..dc1965fde 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/search-by-packages/search-by-packages.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/packages/packages-dashboard/search-by-packages/search-by-packages.component.ts @@ -1,5 +1,5 @@ -import {Component, OnInit} from '@angular/core'; -import {PackagesStore} from '../../packages.store'; +import { Component, OnInit } from '@angular/core'; +import { PackagesStore } from '../../packages.store'; @Component({ selector: 'app-packages-search', @@ -8,7 +8,7 @@ import {PackagesStore} from '../../packages.store'; }) export class PackagesSearchComponent implements OnInit { - private searchQuery = ''; + searchQuery = ''; constructor(private packagesStore: PackagesStore) { } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.ts index 92b27c24c..157a5aa25 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-editor/dictionary-editor.component.ts @@ -25,8 +25,9 @@ import { Component, OnInit } from '@angular/core'; styleUrls: ['./dictionary-editor.component.css'] }) export class DictionaryEditorComponent implements OnInit { + text = ''; constructor() { - } + } ngOnInit() { } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.ts index d5c4a109b..aa975f87a 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/dictionary-metadata/dictionary-metadata.component.ts @@ -25,22 +25,22 @@ import { DictionaryCreationStore } from '../dictionary-creation.store'; import { MetaData } from '../../model/metaData.model'; @Component({ - selector: 'app-dictionary-metadata', - templateUrl: './dictionary-metadata.component.html', - styleUrls: ['./dictionary-metadata.component.css'] + selector: 'app-dictionary-metadata', + templateUrl: './dictionary-metadata.component.html', + styleUrls: ['./dictionary-metadata.component.css'] }) export class DictionaryMetadataComponent implements OnInit { - packageNameAndVersionEnables = true; + packageNameAndVersionEnables = true; counter = 0; tags = new Set<string>(); - private metaDataTab: MetaData = new MetaData(); - private errorMessage: string; + metaDataTab: MetaData = new MetaData(); + errorMessage: string; constructor( private route: ActivatedRoute, private dictionaryCreationService: DictionaryCreationService, private dictionaryCreationStore: DictionaryCreationStore - ) {} + ) { } ngOnInit() { this.dictionaryCreationStore.state$.subscribe(element => { diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.ts index 1a3484bae..e32db8a37 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.ts @@ -36,20 +36,21 @@ export class ResourceDictionaryCreationComponent implements OnInit { } modes: object[] = [ - {name: 'Designer Mode', style: 'mode-icon icon-designer-mode'}, - {name: 'Scripting Mode', style: 'mode-icon icon-scripting-mode'} + { name: 'Designer Mode', style: 'mode-icon icon-designer-mode' }, + { name: 'Scripting Mode', style: 'mode-icon icon-scripting-mode' } ]; - private metaDataTab: DictionaryModel = new DictionaryModel(); - private definition: Definition = new Definition(); + metaDataTab: DictionaryModel = new DictionaryModel(); + definition: Definition = new Definition(); + createDate = ''; - @ViewChild(DictionaryMetadataComponent, {static: false}) + @ViewChild(DictionaryMetadataComponent, { static: false }) private metadataTabComponent: DictionaryMetadataComponent; - @ViewChild(SourcesTemplateComponent, {static: false}) + @ViewChild(SourcesTemplateComponent, { static: false }) private sourcesTemplateComponent: SourcesTemplateComponent; - @ViewChild('nameit', {static: true}) + @ViewChild('nameit', { static: true }) private elementRef: ElementRef; ngOnInit() { diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.ts index 4a4f215cd..1b70a17ef 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/sources-template/sources-template.component.ts @@ -17,7 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -import { Component, OnInit} from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop'; import { SourcesStore } from './sources.store'; @@ -36,13 +36,15 @@ export class SourcesTemplateComponent implements OnInit { selectItem: boolean; ddSource = []; checked: boolean; + searchText = ''; + text = ''; selectedArray = []; constructor(private sourcesStore: SourcesStore) { this.sourcesStore.state$.subscribe(sources => { this.sources = sources.sources; for (const key in this.sources) { if (key) { - const sourceObj = { name: key, value: JSON.stringify(this.sources[key] )}; + const sourceObj = { name: key, value: JSON.stringify(this.sources[key]) }; this.option.push(sourceObj); } } @@ -58,27 +60,27 @@ export class SourcesTemplateComponent implements OnInit { } drop(event: CdkDragDrop<string[]>) { - this.ddSource = []; - if (event.previousContainer === event.container) { - moveItemInArray(event.container.data, event.previousIndex, event.currentIndex); - } else { - transferArrayItem(event.previousContainer.data, - event.container.data, - event.previousIndex, - event.currentIndex); - } + this.ddSource = []; + if (event.previousContainer === event.container) { + moveItemInArray(event.container.data, event.previousIndex, event.currentIndex); + } else { + transferArrayItem(event.previousContainer.data, + event.container.data, + event.previousIndex, + event.currentIndex); + } - for (const key2 in this.sources) { - if (key2) { - const originalSources = this.sourcesOptions; - for (const key of originalSources) { - if (key.name === key2) { - const obj = `{${key.name}: ${key.value}}`; - this.ddSource.push(obj); - } + for (const key2 in this.sources) { + if (key2) { + const originalSources = this.sourcesOptions; + for (const key of originalSources) { + if (key.name === key2) { + const obj = `{${key.name}: ${key.value}}`; + this.ddSource.push(obj); } } } + } } searchDictionary(event: any) { @@ -98,9 +100,9 @@ export class SourcesTemplateComponent implements OnInit { const editedData = JSON.parse(event); const originalSources = this.sources; for (const key in originalSources) { - if (key === item.name) { - this.sources[key] = editedData; - } + if (key === item.name) { + this.sources[key] = editedData; + } } this.option = []; this.sourcesStore.changeSources(this.sources); diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-dashboard/filterby-tags/filterby-tags.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-dashboard/filterby-tags/filterby-tags.component.ts index bdf6bd1ea..3ad1b34e0 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-dashboard/filterby-tags/filterby-tags.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-dashboard/filterby-tags/filterby-tags.component.ts @@ -23,78 +23,78 @@ import { DictionaryModel, DictionaryPage } from '../../model/dictionary.model'; import { DictionaryStore } from '../../dictionary.store'; @Component({ - selector: 'app-filterby-tags', - templateUrl: './filterby-tags.component.html', - styleUrls: ['./filterby-tags.component.css'] + selector: 'app-filterby-tags', + templateUrl: './filterby-tags.component.html', + styleUrls: ['./filterby-tags.component.css'] }) export class FilterbyTagsComponent implements OnInit { - page: DictionaryPage; - tags: string[] = []; - viewedTags: string[] = []; - searchTag = ''; - viewedDictionary: DictionaryModel[] = []; - private checkBoxTages = ''; - currentPage = 0; + page: DictionaryPage; + tags: string[] = []; + viewedTags: string[] = []; + searchTag = ''; + viewedDictionary: DictionaryModel[] = []; + checkBoxTages = ''; + currentPage = 0; - constructor(private dictionaryStore: DictionaryStore) { - this.dictionaryStore.state$.subscribe(state => { - console.log(state); - if (state.page) { - this.viewedDictionary = state.page.content; - this.tags = []; - if (state.currentPage !== this.currentPage) { - this.checkBoxTages = ''; - this.currentPage = state.currentPage; - } - this.viewedDictionary.forEach(element => { - element.tags.split(',').forEach(tag => { - this.tags.push(tag.trim()); - }); - this.tags.push('All'); - this.tags = this.tags.filter((value, index, self) => self.indexOf(value) === index); - this.assignTags(); - }); - } - }); - } + constructor(private dictionaryStore: DictionaryStore) { + this.dictionaryStore.state$.subscribe(state => { + console.log(state); + if (state.page) { + this.viewedDictionary = state.page.content; + this.tags = []; + if (state.currentPage !== this.currentPage) { + this.checkBoxTages = ''; + this.currentPage = state.currentPage; + } + this.viewedDictionary.forEach(element => { + element.tags.split(',').forEach(tag => { + this.tags.push(tag.trim()); + }); + this.tags.push('All'); + this.tags = this.tags.filter((value, index, self) => self.indexOf(value) === index); + this.assignTags(); + }); + } + }); + } - ngOnInit() { + ngOnInit() { - } + } - reloadChanges(event: any) { - this.searchTag = event.target.value; - this.filterItem(this.searchTag); - } + reloadChanges(event: any) { + this.searchTag = event.target.value; + this.filterItem(this.searchTag); + } - private assignTags() { - this.viewedTags = this.tags; - } + private assignTags() { + this.viewedTags = this.tags; + } - private filterItem(value) { - if (!value) { - this.assignTags(); - } - this.viewedTags = this.tags.filter( - item => item.toLowerCase().indexOf(value.toLowerCase()) > -1 - ); - } + private filterItem(value) { + if (!value) { + this.assignTags(); + } + this.viewedTags = this.tags.filter( + item => item.toLowerCase().indexOf(value.toLowerCase()) > -1 + ); + } - reloadDictionary(event: any) { - if (!event.target.checked) { - this.checkBoxTages = this.checkBoxTages.replace(event.target.id + ',', '') - .replace(event.target.id, ''); - } else { - this.checkBoxTages += event.target.id.trim() + ','; - } - const tagsSelected = this.checkBoxTages.split(',').filter(item => { - if (item) { - return true; - } - }).map((item) => { - return item.trim(); - }); - this.dictionaryStore.filterByTags(tagsSelected); - } + reloadDictionary(event: any) { + if (!event.target.checked) { + this.checkBoxTages = this.checkBoxTages.replace(event.target.id + ',', '') + .replace(event.target.id, ''); + } else { + this.checkBoxTages += event.target.id.trim() + ','; + } + const tagsSelected = this.checkBoxTages.split(',').filter(item => { + if (item) { + return true; + } + }).map((item) => { + return item.trim(); + }); + this.dictionaryStore.filterByTags(tagsSelected); + } } diff --git a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-dashboard/search-dictionary/search-dictionary.component.ts b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-dashboard/search-dictionary/search-dictionary.component.ts index 76e40cf7d..d1fb4fc85 100644 --- a/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-dashboard/search-dictionary/search-dictionary.component.ts +++ b/cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-dashboard/search-dictionary/search-dictionary.component.ts @@ -27,16 +27,16 @@ import { DictionaryStore } from '../../dictionary.store'; styleUrls: ['./search-dictionary.component.css'] }) export class SearchDictionaryComponent implements OnInit { - private searchQuery = ''; + searchQuery = ''; constructor(private dictionaryStore: DictionaryStore) { } ngOnInit() { } searchDictionary(event: any) { - this.searchQuery = event.target.value; - this.searchQuery = this.searchQuery.trim(); - this.dictionaryStore.search(this.searchQuery); + this.searchQuery = event.target.value; + this.searchQuery = this.searchQuery.trim(); + this.dictionaryStore.search(this.searchQuery); } } diff --git a/cds-ui/server/src/controllers/blueprint-rest.controller.ts b/cds-ui/server/src/controllers/blueprint-rest.controller.ts index 2319e0a5e..870f9793f 100644 --- a/cds-ui/server/src/controllers/blueprint-rest.controller.ts +++ b/cds-ui/server/src/controllers/blueprint-rest.controller.ts @@ -20,16 +20,16 @@ limitations under the License. */ -import {get, param, post, Request, requestBody, Response, RestBindings} from '@loopback/rest'; -import {Blueprint} from '../models'; -import {inject} from '@loopback/core'; -import {BlueprintService} from '../services'; +import { get, param, post, Request, requestBody, Response, RestBindings, del } from '@loopback/rest'; +import { Blueprint } from '../models'; +import { inject } from '@loopback/core'; +import { BlueprintService } from '../services'; import * as fs from 'fs'; import * as multiparty from 'multiparty'; import * as request_lib from 'request'; -import {appConfig, processorApiConfig} from '../config/app-config'; -import {bluePrintManagementServiceGrpcClient} from '../clients/blueprint-management-service-grpc-client'; -import {BlueprintDetail} from '../models/blueprint.detail.model'; +import { appConfig, processorApiConfig } from '../config/app-config'; +import { bluePrintManagementServiceGrpcClient } from '../clients/blueprint-management-service-grpc-client'; +import { BlueprintDetail } from '../models/blueprint.detail.model'; export class BlueprintRestController { constructor( @@ -42,7 +42,7 @@ export class BlueprintRestController { responses: { '200': { description: 'Blueprint model instance', - content: {'application/json': {schema: {'x-ts-type': Blueprint}}}, + content: { 'application/json': { schema: { 'x-ts-type': Blueprint } } }, }, }, }) @@ -54,7 +54,7 @@ export class BlueprintRestController { responses: { '200': { description: 'Blueprint model instance', - content: {'application/json': {schema: {'x-ts-type': BlueprintDetail}}}, + content: { 'application/json': { schema: { 'x-ts-type': BlueprintDetail } } }, }, }, }) @@ -62,12 +62,24 @@ export class BlueprintRestController { return await this.bpservice.getOneBluePrint(id); } + @del('/controllerblueprint/{id}', { + responses: { + '200': { + description: 'Blueprint model instance', + content: { 'application/json': { schema: { 'x-ts-type': BlueprintDetail } } }, + }, + }, + }) + async deleteBluePrint(@param.path.string('id') id: string) { + return await this.bpservice.deleteBluePrint(id); + } + @get('/controllerblueprint/paged', { responses: { '200': { description: 'Blueprint model instance with pagination', - content: {'application/json': {schema: {'x-ts-type': Blueprint}}}, + content: { 'application/json': { schema: { 'x-ts-type': Blueprint } } }, }, }, }) @@ -83,7 +95,7 @@ export class BlueprintRestController { responses: { '200': { description: 'Blueprint model instance with pagination', - content: {'application/json': {schema: {'x-ts-type': Blueprint}}}, + content: { 'application/json': { schema: { 'x-ts-type': Blueprint } } }, }, }, }) @@ -100,7 +112,7 @@ export class BlueprintRestController { responses: { '200': { description: 'Blueprint model instance', - content: {'application/json': {schema: {'x-ts-type': Blueprint}}}, + content: { 'application/json': { schema: { 'x-ts-type': Blueprint } } }, }, }, }) @@ -112,7 +124,7 @@ export class BlueprintRestController { responses: { '200': { description: 'Blueprint model instance', - content: {'application/json': {schema: {'x-ts-type': Blueprint}}}, + content: { 'application/json': { schema: { 'x-ts-type': Blueprint } } }, }, }, }) @@ -123,7 +135,7 @@ export class BlueprintRestController { @get('/controllerblueprint/searchByTags/{tags}', { responses: { '200': { - content: {'application/json': {}}, + content: { 'application/json': {} }, }, }, }) @@ -140,11 +152,11 @@ export class BlueprintRestController { 'multipart/form-data': { // Skip body parsing 'x-parser': 'stream', - schema: {type: 'object'}, + schema: { type: 'object' }, }, }, }) - request: Request, + request: Request, @inject(RestBindings.Http.RESPONSE) response: Response, ): Promise<Response> { return new Promise((resolve, reject) => { @@ -180,11 +192,11 @@ export class BlueprintRestController { 'multipart/form-data': { // Skip body parsing 'x-parser': 'stream', - schema: {type: 'object'}, + schema: { type: 'object' }, }, }, }) - request: Request, + request: Request, @inject(RestBindings.Http.RESPONSE) response: Response, ): Promise<Response> { return new Promise((resolve, reject) => { @@ -220,11 +232,11 @@ export class BlueprintRestController { 'multipart/form-data': { // Skip body parsing 'x-parser': 'stream', - schema: {type: 'object'}, + schema: { type: 'object' }, }, }, }) - request: Request, + request: Request, @inject(RestBindings.Http.RESPONSE) response: Response, ): Promise<Response> { return new Promise((resolve, reject) => { @@ -261,7 +273,7 @@ export class BlueprintRestController { async getFileFromMultiPartForm(request: Request): Promise<multiparty.File> { return new Promise((resolve, reject) => { let form = new multiparty.Form(); - form.parse(request, (err: any, fields: any, files: {[x: string]: any[];}) => { + form.parse(request, (err: any, fields: any, files: { [x: string]: any[]; }) => { if (err) reject(err); let file = files['file'][0]; // get the file from the returned files object if (!file) { @@ -282,11 +294,11 @@ export class BlueprintRestController { 'multipart/form-data': { // Skip body parsing 'x-parser': 'stream', - schema: {type: 'object'}, + schema: { type: 'object' }, }, }, }) - request: Request, + request: Request, @inject(RestBindings.Http.RESPONSE) response: Response, ): Promise<Response> { return new Promise((resolve, reject) => { diff --git a/cds-ui/server/src/datasources/blueprint.datasource-template.ts b/cds-ui/server/src/datasources/blueprint.datasource-template.ts index 9b8e06a13..3b502d334 100644 --- a/cds-ui/server/src/datasources/blueprint.datasource-template.ts +++ b/cds-ui/server/src/datasources/blueprint.datasource-template.ts @@ -1,4 +1,4 @@ -import {processorApiConfig} from '../config/app-config'; +import { processorApiConfig } from '../config/app-config'; export default { "name": "blueprint", @@ -37,84 +37,100 @@ export default { } }, - - { - "template": { - "method": "GET", - "url": processorApiConfig.http.url + "/blueprint-model/search/{tags}", - "headers": { - "accepts": "application/json", - "content-type": "application/json", - "authorization": processorApiConfig.http.authToken - }, - "responsePath": "$.*" + { + "template": { + "method": "DELETE", + "url": processorApiConfig.http.url + "/blueprint-model/{id}", + "headers": { + "accepts": "application/json", + "content-type": "application/json", + "authorization": processorApiConfig.http.authToken }, - "functions": { - "getByTags": ["tags"] - - } + "responsePath": "$.*" }, - { - "template": { - "method": "GET", - "url": processorApiConfig.http.url + "/blueprint-model/meta-data/{keyword}", - "headers": { - "accepts": "application/json", - "content-type": "application/json", - "authorization": processorApiConfig.http.authToken - }, - "responsePath": "$.*" + "functions": { + "deleteBluePrint": ["id"] + + } + }, + + { + "template": { + "method": "GET", + "url": processorApiConfig.http.url + "/blueprint-model/search/{tags}", + "headers": { + "accepts": "application/json", + "content-type": "application/json", + "authorization": processorApiConfig.http.authToken }, - "functions": { - "getBlueprintsByKeyword": ["keyword"] + "responsePath": "$.*" + }, + "functions": { + "getByTags": ["tags"] - } + } + }, + { + "template": { + "method": "GET", + "url": processorApiConfig.http.url + "/blueprint-model/meta-data/{keyword}", + "headers": { + "accepts": "application/json", + "content-type": "application/json", + "authorization": processorApiConfig.http.authToken + }, + "responsePath": "$.*" }, - { - "template": { - "method": "GET", - "url": processorApiConfig.http.url + "/blueprint-model/paged?limit={limit}&offset={offset}&sort={sort}&sortType={sortType}", - "headers": { - "accepts": "application/json", - "content-type": "application/json", - "authorization": processorApiConfig.http.authToken - }, - "responsePath": "$", + "functions": { + "getBlueprintsByKeyword": ["keyword"] + + } + }, + { + "template": { + "method": "GET", + "url": processorApiConfig.http.url + "/blueprint-model/paged?limit={limit}&offset={offset}&sort={sort}&sortType={sortType}", + "headers": { + "accepts": "application/json", + "content-type": "application/json", + "authorization": processorApiConfig.http.authToken }, - "functions": { - "getPagedBueprints": ["limit", "offset", "sort","sortType"], - } + "responsePath": "$", }, - { - "template": { - "method": "GET", - "url": processorApiConfig.http.url + "/blueprint-model/paged/meta-data/{keyword}?limit={limit}&offset={offset}&sort={sort}&sortType={sortType}", - "headers": { - "accepts": "application/json", - "content-type": "application/json", - "authorization": processorApiConfig.http.authToken - }, - "responsePath": "$", + "functions": { + "getPagedBueprints": ["limit", "offset", "sort", "sortType"], + } + }, + { + "template": { + "method": "GET", + "url": processorApiConfig.http.url + "/blueprint-model/paged/meta-data/{keyword}?limit={limit}&offset={offset}&sort={sort}&sortType={sortType}", + "headers": { + "accepts": "application/json", + "content-type": "application/json", + "authorization": processorApiConfig.http.authToken }, - "functions": { - "getMetaDataPagedBlueprints": ["limit", "offset", "sort", "keyword","sortType"], - } + "responsePath": "$", }, - { - "template": { - "method": "GET", - "url": processorApiConfig.http.url + "/blueprint-model/by-name/{name}/version/{version}", - "headers": { - "accepts": "application/json", - "content-type": "application/json", - "authorization": processorApiConfig.http.authToken - }, - "responsePath": "$", + "functions": { + "getMetaDataPagedBlueprints": ["limit", "offset", "sort", "keyword", "sortType"], + } + }, + { + "template": { + "method": "GET", + "url": processorApiConfig.http.url + "/blueprint-model/by-name/{name}/version/{version}", + "headers": { + "accepts": "application/json", + "content-type": "application/json", + "authorization": processorApiConfig.http.authToken }, - "functions": { - "getBlueprintByNameAndVersion": ["name", "version"], - } + "responsePath": "$", }, + "functions": { + "getBlueprintByNameAndVersion": ["name", "version"], + } + }, ] }; diff --git a/cds-ui/server/src/services/blueprint.service.ts b/cds-ui/server/src/services/blueprint.service.ts index 2680e105a..379f8d4d5 100644 --- a/cds-ui/server/src/services/blueprint.service.ts +++ b/cds-ui/server/src/services/blueprint.service.ts @@ -1,15 +1,16 @@ -import {getService} from '@loopback/service-proxy'; -import {inject, Provider} from '@loopback/core'; -import {BlueprintDataSource} from '../datasources'; +import { getService } from '@loopback/service-proxy'; +import { inject, Provider } from '@loopback/core'; +import { BlueprintDataSource } from '../datasources'; export interface BlueprintService { - getOneBluePrint(id: string): any; - getAllblueprints(): Promise<any>; - getBlueprintsByKeyword(keyword: string): Promise<any>; - getByTags(tags: string): Promise<JSON>; - getPagedBueprints(limit: number, offset: number , sort: string,sortType: String): Promise<any>; - getMetaDataPagedBlueprints(limit: number, offset: number, sort: string, keyword: string,sortType: String): Promise<any>; - getBlueprintByNameAndVersion(name:string, version:string): Promise<any>; + getOneBluePrint(id: string): any; + deleteBluePrint(id: string): any; + getAllblueprints(): Promise<any>; + getBlueprintsByKeyword(keyword: string): Promise<any>; + getByTags(tags: string): Promise<JSON>; + getPagedBueprints(limit: number, offset: number, sort: string, sortType: String): Promise<any>; + getMetaDataPagedBlueprints(limit: number, offset: number, sort: string, keyword: string, sortType: String): Promise<any>; + getBlueprintByNameAndVersion(name: string, version: string): Promise<any>; } @@ -19,7 +20,7 @@ export class BlueprintServiceProvider implements Provider<BlueprintService> { // blueprint must match the name property in the datasource json file @inject('datasources.blueprint') protected dataSource: BlueprintDataSource = new BlueprintDataSource(), - ) {} + ) { } value(): Promise<BlueprintService> { return getService(this.dataSource); diff --git a/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt b/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt index 848647405..50f0b1499 100644 --- a/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt +++ b/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt @@ -123,8 +123,8 @@ open class ComponentRemotePythonExecutor( val executionTimeout = getOptionalOperationInput(INPUT_EXECUTE_TIMEOUT)?.asInt() ?: DEFAULT_EXECUTE_TIMEOUT_IN_SEC - // set the component level timeout as envPrepTimeout + executionTimeout (small delta will be applied in AbstractComponentFunction - val timeout = envPrepTimeout + executionTimeout + // component level timeout should be => env_prep_timeout + execution_timeout + val timeout = implementation.timeout var scriptCommand = command.replace(pythonScript.name, pythonScript.absolutePath) if (args != null && args.isNotEmpty()) { @@ -161,17 +161,17 @@ open class ComponentRemotePythonExecutor( if (prepareEnvOutput.status != StatusType.SUCCESS) { val errorMessage = prepareEnvOutput.payload setNodeOutputErrors(prepareEnvOutput.status.name, - STEP_PREPARE_ENV, - logs, - errorMessage, - isLogResponseEnabled + STEP_PREPARE_ENV, + logs, + errorMessage, + isLogResponseEnabled ) } else { setNodeOutputProperties(prepareEnvOutput.status.name.asJsonPrimitive(), - STEP_PREPARE_ENV, - logsEnv, - "".asJsonPrimitive(), - isLogResponseEnabled + STEP_PREPARE_ENV, + logsEnv, + "".asJsonPrimitive(), + isLogResponseEnabled ) } } else { @@ -180,17 +180,15 @@ open class ComponentRemotePythonExecutor( } } catch (grpcEx: io.grpc.StatusRuntimeException) { val componentLevelWarningMsg = if (timeout < envPrepTimeout) "Note: component-level timeout ($timeout) is shorter than env-prepare timeout ($envPrepTimeout). " else "" - val grpcErrMsg = "Command failed during env. preparation... timeout($envPrepTimeout) requestId ($processId). $componentLevelWarningMsg" + val grpcErrMsg = "Command failed during env. preparation... timeout($envPrepTimeout) requestId ($processId). $componentLevelWarningMsg grpcError: ${grpcEx.status}" setAttribute(ATTRIBUTE_PREPARE_ENV_LOG, grpcErrMsg.asJsonPrimitive()) - setNodeOutputErrors(status = grpcErrMsg, step = STEP_PREPARE_ENV, error = "${grpcEx.status}".asJsonPrimitive(), logging = isLogResponseEnabled) + setNodeOutputErrors(status = StatusType.FAILURE.name, step = STEP_PREPARE_ENV, error = grpcErrMsg.asJsonPrimitive(), logging = isLogResponseEnabled) log.error(grpcErrMsg, grpcEx) - addError(grpcErrMsg) } catch (e: Exception) { - val timeoutErrMsg = "Command executor failed during env. preparation.. timeout($envPrepTimeout) requestId ($processId)." + val timeoutErrMsg = "Command executor failed during env. preparation.. catch-all case timeout($envPrepTimeout) requestId ($processId). exception msg: ${e.message}" setAttribute(ATTRIBUTE_PREPARE_ENV_LOG, e.message.asJsonPrimitive()) - setNodeOutputErrors(status = timeoutErrMsg, step = STEP_PREPARE_ENV, error = "${e.message}".asJsonPrimitive(), logging = isLogResponseEnabled) - log.error("Failed to process on remote executor requestId ($processId)", e) - addError(timeoutErrMsg) + setNodeOutputErrors(status = StatusType.FAILURE.name, step = STEP_PREPARE_ENV, error = timeoutErrMsg.asJsonPrimitive(), logging = isLogResponseEnabled) + log.error(timeoutErrMsg, e) } // if Env preparation was successful, then proceed with command execution in this Env if (bluePrintRuntimeService.getBluePrintError().errors.isEmpty()) { @@ -214,45 +212,47 @@ open class ComponentRemotePythonExecutor( } checkNotNull(remoteExecutionOutput) { - "Error: Request-id $processId did not return a restul from remote command execution." + "Error: Request-id $processId did not return a result from remote command execution." } val logs = JacksonUtils.jsonNodeFromObject(remoteExecutionOutput.response) if (remoteExecutionOutput.status != StatusType.SUCCESS) { setNodeOutputErrors(remoteExecutionOutput.status.name, - STEP_EXEC_CMD, - logs, - remoteExecutionOutput.payload, - isLogResponseEnabled + STEP_EXEC_CMD, + logs, + remoteExecutionOutput.payload, + isLogResponseEnabled ) } else { setNodeOutputProperties(remoteExecutionOutput.status.name.asJsonPrimitive(), - STEP_EXEC_CMD, - logs, - remoteExecutionOutput.payload, - isLogResponseEnabled + STEP_EXEC_CMD, + logs, + remoteExecutionOutput.payload, + isLogResponseEnabled ) } } catch (timeoutEx: TimeoutCancellationException) { val componentLevelWarningMsg = if (timeout < executionTimeout) "Note: component-level timeout ($timeout) is shorter than execution timeout ($executionTimeout). " else "" val timeoutErrMsg = "Command executor execution timeout. DetailedMessage: (${timeoutEx.message}) requestId ($processId). $componentLevelWarningMsg" - setNodeOutputErrors(status = timeoutErrMsg, - step = STEP_EXEC_CMD, - logs = "".asJsonPrimitive(), - error = "".asJsonPrimitive(), - logging = isLogResponseEnabled + setNodeOutputErrors(status = StatusType.FAILURE.name, + step = STEP_EXEC_CMD, + logs = "".asJsonPrimitive(), + error = timeoutErrMsg.asJsonPrimitive(), + logging = isLogResponseEnabled ) log.error(timeoutErrMsg, timeoutEx) } catch (grpcEx: io.grpc.StatusRuntimeException) { - val timeoutErrMsg = "Command executor failed to execute requestId ($processId) error (${grpcEx.status.cause?.message})" - setNodeOutputErrors(status = timeoutErrMsg, - step = STEP_EXEC_CMD, - logs = "".asJsonPrimitive(), - error = "".asJsonPrimitive(), - logging = isLogResponseEnabled + val timeoutErrMsg = "Command executor timed out executing after $executionTimeout seconds requestId ($processId) grpcErr: ${grpcEx.status}" + setNodeOutputErrors(status = StatusType.FAILURE.name, + step = STEP_EXEC_CMD, + logs = "".asJsonPrimitive(), + error = timeoutErrMsg.asJsonPrimitive(), + logging = isLogResponseEnabled ) - log.error("Command executor time out during GRPC call", grpcEx) + log.error(timeoutErrMsg, grpcEx) } catch (e: Exception) { - log.error("Failed to process on remote executor requestId ($processId)", e) + val timeoutErrMsg = "Command executor failed during process catch-all case requestId ($processId) timeout($envPrepTimeout) exception msg: ${e.message}" + setNodeOutputErrors(status = StatusType.FAILURE.name, step = STEP_PREPARE_ENV, error = timeoutErrMsg.asJsonPrimitive(), logging = isLogResponseEnabled) + log.error(timeoutErrMsg, e) } } log.debug("Trying to close GRPC channel. request ($processId)") @@ -277,7 +277,14 @@ open class ComponentRemotePythonExecutor( /** * Utility function to set the output properties of the executor node */ - private fun setNodeOutputProperties(status: JsonNode, step: String, message: JsonNode, artifacts: JsonNode, logging: Boolean = true) { + private fun setNodeOutputProperties( + status: JsonNode = StatusType.FAILURE.name.asJsonPrimitive(), + step: String, + message: JsonNode, + artifacts: JsonNode, + logging: Boolean = true + ) { + setAttribute(ATTRIBUTE_EXEC_CMD_STATUS, status) setAttribute(ATTRIBUTE_RESPONSE_DATA, artifacts) setAttribute(ATTRIBUTE_EXEC_CMD_LOG, message) diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/BluePrintClusterExtensions.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/BluePrintClusterExtensions.kt index 81fc0d709..0a58857f7 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/BluePrintClusterExtensions.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/BluePrintClusterExtensions.kt @@ -29,10 +29,10 @@ import org.onap.ccsdk.cds.controllerblueprints.core.MDCContext import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService /** - * Exposed Dependency Service by this Hazlecast Lib Module + * Exposed Dependency Service by this Hazelcast Lib Module */ fun BluePrintDependencyService.clusterService(): BluePrintClusterService = - instance(HazlecastClusterService::class) + instance(HazelcastClusterService::class) /** Optional Cluster Service, returns only if Cluster is enabled */ fun BluePrintDependencyService.optionalClusterService(): BluePrintClusterService? { diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterService.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazelcastClusterService.kt index feb2a8e2a..d3c88d732 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterService.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazelcastClusterService.kt @@ -45,9 +45,9 @@ import java.time.Duration import java.util.concurrent.TimeUnit @Service -open class HazlecastClusterService : BluePrintClusterService { +open class HazelcastClusterService : BluePrintClusterService { - private val log = logger(HazlecastClusterService::class) + private val log = logger(HazelcastClusterService::class) lateinit var hazelcast: HazelcastInstance lateinit var cpSubsystemManagementService: CPSubsystemManagementService var joinedClient = false @@ -179,14 +179,14 @@ open class HazlecastClusterService : BluePrintClusterService { override suspend fun shutDown(duration: Duration) { if (::hazelcast.isInitialized && clusterJoined()) { delay(duration.toMillis()) - HazlecastClusterUtils.terminate(hazelcast) + HazelcastClusterUtils.terminate(hazelcast) } } /** Utils */ suspend fun promoteAsCPMember(hazelcastInstance: HazelcastInstance) { if (!joinedClient && !joinedLite) { - HazlecastClusterUtils.promoteAsCPMember(hazelcastInstance) + HazelcastClusterUtils.promoteAsCPMember(hazelcastInstance) } } @@ -243,17 +243,18 @@ open class ClusterLockImpl(private val hazelcast: HazelcastInstance, private val } override suspend fun unLock() { - // Added condition to avoid failures like - "Current thread is not owner of the lock!" - if (distributedLock.isLockedByCurrentThread) { - distributedLock.unlock() - log.trace("Cluster unlock(${name()}) successfully..") - } + distributedLock.unlock() + log.trace("Cluster unlock(${name()}) successfully..") } override fun isLocked(): Boolean { return distributedLock.isLocked } + override fun isLockedByCurrentThread(): Boolean { + return distributedLock.isLockedByCurrentThread + } + override suspend fun fenceLock(): String { val fence = distributedLock.lockAndGetFence() log.trace("Cluster lock($name) fence($fence) created..") diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterUtils.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazelcastClusterUtils.kt index 70970f6da..e5f488a0e 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterUtils.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazelcastClusterUtils.kt @@ -25,9 +25,9 @@ import org.onap.ccsdk.cds.controllerblueprints.core.logger import java.util.UUID import java.util.concurrent.TimeUnit -object HazlecastClusterUtils { +object HazelcastClusterUtils { - private val log = logger(HazlecastClusterUtils::class) + private val log = logger(HazelcastClusterUtils::class) /** Promote [hazelcastInstance] member to CP Member */ fun promoteAsCPMember(hazelcastInstance: HazelcastInstance) { diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/service/BluePrintClusterService.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/service/BluePrintClusterService.kt index 9725553a5..2d957c289 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/service/BluePrintClusterService.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/service/BluePrintClusterService.kt @@ -78,6 +78,7 @@ interface ClusterLock { suspend fun tryFenceLock(timeout: Long): String suspend fun unLock() fun isLocked(): Boolean + fun isLockedByCurrentThread(): Boolean fun close() } diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterServiceTest.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazelcastClusterServiceTest.kt index 80cf41558..e214b6593 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterServiceTest.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazelcastClusterServiceTest.kt @@ -20,13 +20,17 @@ import com.fasterxml.jackson.databind.JsonNode import com.hazelcast.client.config.YamlClientConfigBuilder import com.hazelcast.cluster.Member import com.hazelcast.config.FileSystemYamlConfig +import com.hazelcast.instance.impl.HazelcastInstanceFactory import com.hazelcast.map.IMap import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.delay +import kotlinx.coroutines.newSingleThreadContext import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext +import org.junit.After +import org.junit.Before import org.junit.Test import org.onap.ccsdk.cds.blueprintsprocessor.core.service.BluePrintClusterService import org.onap.ccsdk.cds.blueprintsprocessor.core.service.ClusterInfo @@ -35,16 +39,21 @@ import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive import org.onap.ccsdk.cds.controllerblueprints.core.logger import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile import java.io.Serializable -import java.time.Duration import java.util.Properties import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertTrue -class HazlecastClusterServiceTest { - private val log = logger(HazlecastClusterServiceTest::class) +class HazelcastClusterServiceTest { + private val log = logger(HazelcastClusterServiceTest::class) private val clusterSize = 3 + @Before + @After + fun killAllHazelcastInstances() { + HazelcastInstanceFactory.terminateAll() + } + @Test fun testClientFileSystemYamlConfig() { System.setProperty(BluePrintConstants.PROPERTY_CLUSTER_ID, "test-cluster") @@ -74,33 +83,23 @@ class HazlecastClusterServiceTest { fun testClusterJoin() { runBlocking { val bluePrintClusterServiceOne = - createCluster(arrayListOf(5679, 5680, 5681)).toMutableList() - // delay(1000) - // Join as Hazlecast Management Node - // val bluePrintClusterServiceTwo = createCluster(arrayListOf(5682), true) - // val bluePrintClusterServiceTwo = createCluster(arrayListOf(5682), false) - // bluePrintClusterServiceOne.addAll(bluePrintClusterServiceTwo) + createCluster(arrayListOf(1, 2, 3)).toMutableList() printReachableMembers(bluePrintClusterServiceOne) testDistributedStore(bluePrintClusterServiceOne) testDistributedLock(bluePrintClusterServiceOne) - - // executeScheduler(bluePrintClusterServiceOne[0]) - // delay(1000) - // Shutdown - shutdown(bluePrintClusterServiceOne) } } private suspend fun createCluster( - ports: List<Int>, + ids: List<Int>, joinAsClient: Boolean? = false ): List<BluePrintClusterService> { return withContext(Dispatchers.Default) { - val deferred = ports.map { port -> + val deferred = ids.map { id -> async(Dispatchers.IO) { - val nodeId = "node-$port" - log.info("********** Starting node($nodeId) on port($port)") + val nodeId = "node-$id" + log.info("********** Starting ($nodeId)") val properties = Properties() properties["hazelcast.logging.type"] = "slf4j" val clusterInfo = @@ -117,21 +116,15 @@ class HazlecastClusterServiceTest { properties = properties ) } - val hazlecastClusterService = HazlecastClusterService() - hazlecastClusterService.startCluster(clusterInfo) - hazlecastClusterService + val hazelcastClusterService = HazelcastClusterService() + hazelcastClusterService.startCluster(clusterInfo) + hazelcastClusterService } } deferred.awaitAll() } } - private suspend fun shutdown(bluePrintClusterServices: List<BluePrintClusterService>) { - bluePrintClusterServices.forEach { bluePrintClusterService -> - bluePrintClusterService.shutDown(Duration.ofMillis(10)) - } - } - private suspend fun testDistributedStore(bluePrintClusterServices: List<BluePrintClusterService>) { /** Test Distributed store creation */ repeat(2) { storeId -> @@ -159,13 +152,25 @@ class HazlecastClusterServiceTest { val lockName = "sample-lock" withContext(Dispatchers.IO) { val deferred = async { - executeLock(bluePrintClusterServices[0], "first", lockName) + newSingleThreadContext("first").use { + withContext(it) { + executeLock(bluePrintClusterServices[0], "first", lockName) + } + } } val deferred2 = async { - executeLock(bluePrintClusterServices[1], "second", lockName) + newSingleThreadContext("second").use { + withContext(it) { + executeLock(bluePrintClusterServices[1], "second", lockName) + } + } } val deferred3 = async { - executeLock(bluePrintClusterServices[2], "third", lockName) + newSingleThreadContext("third").use { + withContext(it) { + executeLock(bluePrintClusterServices[2], "third", lockName) + } + } } deferred.start() deferred2.start() @@ -195,12 +200,12 @@ class HazlecastClusterServiceTest { private suspend fun executeScheduler(bluePrintClusterService: BluePrintClusterService) { log.info("initialising ...") - val hazlecastClusterService = bluePrintClusterService as HazlecastClusterService + val hazelcastClusterService = bluePrintClusterService as HazelcastClusterService val memberNameMap = bluePrintClusterService.clusterMapStore<Member>("member-name-map") as IMap assertEquals(3, memberNameMap.size, "failed to match member size") memberNameMap.forEach { (key, value) -> log.info("nodeId($key), Member($value)") } - val scheduler = hazlecastClusterService.clusterScheduler("cleanup") + val scheduler = hazelcastClusterService.clusterScheduler("cleanup") // scheduler.scheduleOnAllMembers(SampleSchedulerTask(), 0, TimeUnit.SECONDS) // scheduler.scheduleOnKeyOwnerAtFixedRate(SampleSchedulerTask(), "node-5680",0, 1, TimeUnit.SECONDS) // scheduler.scheduleAtFixedRate(SampleSchedulerTask(), 0, 1, TimeUnit.SECONDS) @@ -209,15 +214,15 @@ class HazlecastClusterServiceTest { private suspend fun printReachableMembers(bluePrintClusterServices: List<BluePrintClusterService>) { bluePrintClusterServices.forEach { bluePrintClusterService -> - val hazlecastClusterService = bluePrintClusterService as HazlecastClusterService - val hazelcast = hazlecastClusterService.hazelcast + val hazelcastClusterService = bluePrintClusterService as HazelcastClusterService + val hazelcast = hazelcastClusterService.hazelcast val self = if (!bluePrintClusterService.isClient()) hazelcast.cluster.localMember else null - val master = hazlecastClusterService.masterMember("system").memberAddress - val members = hazlecastClusterService.allMembers().map { it.memberAddress } + val master = hazelcastClusterService.masterMember("system").memberAddress + val members = hazelcastClusterService.allMembers().map { it.memberAddress } log.info("Cluster Members for($self): master($master) Members($members)") } - val applicationMembers = bluePrintClusterServices[0].applicationMembers("node-56") + val applicationMembers = bluePrintClusterServices[0].applicationMembers("node-") assertEquals(clusterSize, applicationMembers.size, "failed to match applications member size") log.info("Cluster applicationMembers ($applicationMembers)") } diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-cluster.yaml b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-cluster.yaml index de6047a90..b4dc3454a 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-cluster.yaml +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/test/resources/hazelcast/hazelcast-cluster.yaml @@ -7,10 +7,15 @@ hazelcast: session-time-to-live-seconds: 60 session-heartbeat-interval-seconds: 5 missing-cp-member-auto-removal-seconds: 120 + metrics: + enabled: false network: join: - multicast: + tcp-ip: enabled: true + interface: 127.0.0.1 + multicast: + enabled: false # Specify 224.0.0.1 instead of default 224.2.2.3 since there's some issue # on macOs with docker installed and multicast address different than 224.0.0.1 # https://stackoverflow.com/questions/46341715/hazelcast-multicast-does-not-work-because-of-vboxnet-which-is-used-by-docker-mac diff --git a/ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionService.kt b/ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionService.kt index 06100f1fc..2aa408527 100644 --- a/ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionService.kt +++ b/ms/blueprintsprocessor/modules/services/workflow-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionService.kt @@ -31,17 +31,14 @@ import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintWorkflow import org.onap.ccsdk.cds.controllerblueprints.core.logger import org.onap.ccsdk.cds.controllerblueprints.core.service.AbstractBluePrintWorkFlowService import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService -import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintWorkFlowService import org.onap.ccsdk.cds.controllerblueprints.core.service.NodeExecuteMessage import org.onap.ccsdk.cds.controllerblueprints.core.service.NodeSkipMessage import org.onap.ccsdk.cds.controllerblueprints.core.service.WorkflowExecuteMessage -import org.springframework.beans.factory.config.ConfigurableBeanFactory -import org.springframework.context.annotation.Scope import org.springframework.stereotype.Service @Service("imperativeWorkflowExecutionService") class ImperativeWorkflowExecutionService( - private val imperativeBluePrintWorkflowService: BluePrintWorkFlowService<ExecutionServiceInput, ExecutionServiceOutput> + private val nodeTemplateExecutionService: NodeTemplateExecutionService ) : BluePrintWorkflowExecutionService<ExecutionServiceInput, ExecutionServiceOutput> { @@ -57,15 +54,11 @@ class ImperativeWorkflowExecutionService( val graph = bluePrintContext.workflowByName(workflowName).asGraph() - return imperativeBluePrintWorkflowService.executeWorkflow( - graph, bluePrintRuntimeService, - executionServiceInput - ) + return ImperativeBluePrintWorkflowService(nodeTemplateExecutionService) + .executeWorkflow(graph, bluePrintRuntimeService, executionServiceInput) } } -@Service -@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) open class ImperativeBluePrintWorkflowService(private val nodeTemplateExecutionService: NodeTemplateExecutionService) : AbstractBluePrintWorkFlowService<ExecutionServiceInput, ExecutionServiceOutput>() { diff --git a/ms/blueprintsprocessor/modules/services/workflow-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionServiceTest.kt b/ms/blueprintsprocessor/modules/services/workflow-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionServiceTest.kt index 1d4738c8d..c200f4ae2 100644 --- a/ms/blueprintsprocessor/modules/services/workflow-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionServiceTest.kt +++ b/ms/blueprintsprocessor/modules/services/workflow-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/workflow/ImperativeWorkflowExecutionServiceTest.kt @@ -119,8 +119,7 @@ class ImperativeWorkflowExecutionServiceTest { ExecutionServiceInput::class.java )!! - val bluePrintWorkFlowService = ImperativeBluePrintWorkflowService(NodeTemplateExecutionService(mockk())) - val imperativeWorkflowExecutionService = ImperativeWorkflowExecutionService(bluePrintWorkFlowService) + val imperativeWorkflowExecutionService = ImperativeWorkflowExecutionService(NodeTemplateExecutionService(mockk())) val output = imperativeWorkflowExecutionService .executeBluePrintWorkflow(bluePrintRuntimeService, executionServiceInput, hashMapOf()) assertNotNull(output, "failed to get imperative workflow output") diff --git a/ms/command-executor/src/main/python/command_executor_handler.py b/ms/command-executor/src/main/python/command_executor_handler.py index 0c476b23e..7c9ef84c1 100644 --- a/ms/command-executor/src/main/python/command_executor_handler.py +++ b/ms/command-executor/src/main/python/command_executor_handler.py @@ -151,7 +151,12 @@ class CommandExecutorHandler(): if rc == 0: return utils.build_ret_data(True, results=result, results_log=results_log) else: - err_msg = "{} - Something wrong happened during command execution. See execute command logs for more information.".format(self.blueprint_id) + err_msg = "" + if len(results_log) > 0: + # get exception message + err_msg = "{} - {}".format(self.blueprint_id, results_log[-1:][0]) + else: + err_msg = "{} - Process exited with return code {}".format(self.blueprint_id, rc) return utils.build_ret_data(False, results=result, results_log=results_log, error=err_msg) def install_packages(self, request, type, f, results): |