Feature 11009 Ns Config Template as first class citizens in OSM 56/14456/2 master
authorSANDHYA.JS <sandhya.j@tataelxsi.co.in>
Mon, 1 Jul 2024 16:20:48 +0000 (21:50 +0530)
committerSANDHYA.JS <sandhya.j@tataelxsi.co.in>
Thu, 4 Jul 2024 18:24:08 +0000 (23:54 +0530)
        - Added UI support
- Added New page for NS config template under packages section
- User can create, edit & delete template
- Added template field under ns instance

Change-Id: I3e9a895b4415165d6c96b9840dee64cc197b40e4
Signed-off-by: SANDHYA.JS <sandhya.j@tataelxsi.co.in>
22 files changed:
src/app/AppModule.ts
src/app/packages/PackagesModule.ts
src/app/packages/instantiate-ns/InstantiateNsComponent.html
src/app/packages/instantiate-ns/InstantiateNsComponent.ts
src/app/packages/ns-config-template/NSConfigTemplateComponent.html [new file with mode: 0644]
src/app/packages/ns-config-template/NSConfigTemplateComponent.scss [new file with mode: 0644]
src/app/packages/ns-config-template/NSConfigTemplateComponent.ts [new file with mode: 0644]
src/app/utilities/compose-packages/ComposePackages.html
src/app/utilities/compose-packages/ComposePackages.ts
src/app/utilities/delete/DeleteComponent.ts
src/app/utilities/ns-config-template-action/NSConfigTemplateActionComponent.html [new file with mode: 0644]
src/app/utilities/ns-config-template-action/NSConfigTemplateActionComponent.scss [new file with mode: 0644]
src/app/utilities/ns-config-template-action/NSConfigTemplateActionComponent.ts [new file with mode: 0644]
src/assets/i18n/de.json
src/assets/i18n/en.json
src/assets/i18n/es.json
src/assets/i18n/pt.json
src/environments/environment.prod.ts
src/environments/environment.ts
src/models/MenuModel.ts
src/models/NSConfigtemplateModel.ts [new file with mode: 0644]
tsconfig.json

index 1f58a5f..d9a089f 100644 (file)
@@ -55,6 +55,7 @@ import { NetsliceInstancesActionComponent } from 'NetsliceInstancesActionCompone
 import { NetslicePackagesActionComponent } from 'NetslicePackagesAction';
 import { Ng2SmartTableModule } from 'ng2-smart-table';
 import { ToastrModule } from 'ngx-toastr';
+import { NSConfigTemplateActionComponent } from 'NSCONFIGTEMPLATEACTION';
 import { NSInstancesActionComponent } from 'NSInstancesActionComponent';
 import { NsPackagesActionComponent } from 'NsPackagesAction';
 import { NsUpdateComponent } from 'NsUpdateComponent';
@@ -134,7 +135,8 @@ const customNotifierOptions: NotifierOptions = {
         NsUpdateComponent,
         WarningComponent,
         StartStopRebuildComponent,
-        HealingComponent
+        HealingComponent,
+        NSConfigTemplateActionComponent
     ],
     imports: [
         NotifierModule.withConfig(customNotifierOptions),
index 5a8ea2e..1cd7e81 100644 (file)
@@ -36,6 +36,7 @@ import { NetsliceTemplateComponent } from 'NetsliceTemplate';
 import { SidebarModule } from 'ng-sidebar';
 import { Ng2SmartTableModule } from 'ng2-smart-table';
 import { NSComposerComponent } from 'NSComposer';
+import { NSConfigTemplateComponent } from 'NSCONFIGTEMPLATE';
 import { NSPackagesComponent } from 'NSPackages';
 import { PackagesComponent } from 'Packages';
 import { PagePerRowModule } from 'PagePerRowModule';
@@ -102,6 +103,14 @@ const routes: Routes = [
                         projectInfo, { title: 'VNFPACKAGES', url: '/packages/vnf' }, { title: '{id}', url: null }]
                 },
                 component: VNFComposerComponent
+            },
+            {
+                path: 'nsconfigtemplate',
+                data: {
+                    breadcrumb: [{ title: 'PAGE.DASHBOARD.DASHBOARD', url: '/' }, { title: 'PAGE.DASHBOARD.PROJECTS', url: '/projects' },
+                        projectInfo, { title: 'PAGE.DASHBOARD.NSCONFIGTEMPLATE', url: null }]
+                },
+                component: NSConfigTemplateComponent
             }
         ]
     }
@@ -115,7 +124,7 @@ const routes: Routes = [
         CodemirrorModule, TranslateModule, RouterModule.forChild(routes), NgbModule, NgSelectModule,
         PagePerRowModule, SidebarModule.forRoot(), LoaderModule, PageReloadModule],
     declarations: [PackagesComponent, NSPackagesComponent, VNFPackagesComponent, NetsliceTemplateComponent,
-        DragDirective, ShowContentComponent, NSComposerComponent, VNFComposerComponent, EditPackagesComponent, ClonePackageComponent],
+        DragDirective, ShowContentComponent, NSComposerComponent, VNFComposerComponent, EditPackagesComponent, ClonePackageComponent, NSConfigTemplateComponent],
     providers: [DataService],
     schemas: [CUSTOM_ELEMENTS_SCHEMA]
 })
index 428515e..11f3a2e 100644 (file)
@@ -47,7 +47,7 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
         <div class="form-group row mb-3">
             <label class="col-sm-4 col-form-label" for="nsdId">{{'PAGE.INSTANCEINSTANTIATE.NSID' | translate}}*</label>
             <div class="col-sm-8">
-                <ng-select [items]="nsdSelect" bindLabel="name" bindValue="_id"
+                <ng-select (change)="getDetailsconfigtemplateAccount()" [items]="nsdSelect" bindLabel="name" bindValue="_id"
                     placeholder="{{'SELECT' | translate}} {{'PAGE.INSTANCEINSTANTIATE.NSID' | translate}}"
                     formControlName="nsdId" [(ngModel)]="nsdId" id="nsdId"
                     [ngClass]="{ 'is-invalid': submitted && f.nsdId.errors }" required>
@@ -98,6 +98,12 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
         <div class="form-group row mb-3">
             <label class="col-sm-4 col-form-label" for="config">{{'CONFIG' | translate}}</label>
             <div class="col-sm-8">
+                <ng-select [items]="nsConfigSelect" bindLabel="name" bindValue="_id"
+                    placeholder="{{'SELECT' | translate}} {{'PAGE.DASHBOARD.NSCONFIGTEMPLATE' | translate}}"
+                    formControlName="nsConfigTemplateId" id="nsConfigTemplateId"
+                    [ngClass]="{ 'is-invalid': submitted && f.nsConfigTemplateId.errors }">
+                </ng-select>
+                <div class="fileupload-text mt-1 mb-1">{{'CONFIGFILEUPLOADLABEL' | translate}}</div>
                 <textarea class="form-control" placeholder="{{'YAMLCONFIG' | translate}}" formControlName="config"
                     id="config"></textarea>
                 <div class="fileupload-text mt-1 mb-1">{{'FILEUPLOADLABEL' | translate}}</div>
index 9ba89da..08d6232 100644 (file)
 /**
  * @file Instantiate NS Modal Component.
  */
-import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core';
+import { Component, ElementRef, Injector, Input, OnInit, ViewChild } from '@angular/core';
 import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 import { Router } from '@angular/router';
 import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
 import { TranslateService } from '@ngx-translate/core';
 import { NotifierService } from 'angular-notifier';
-import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA, URLPARAMS } from 'CommonModel';
 import { DataService } from 'DataService';
 import { environment } from 'environment';
 import * as jsyaml from 'js-yaml';
-import { NSCREATEPARAMS, NSData, NSDDetails } from 'NSDModel';
+import { NSCONFIG } from 'NSCONFIGTEMPLATEMODEL';
+import { NSData, NSDDetails } from 'NSDModel';
 import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
 import { SharedService, isNullOrUndefined } from 'SharedService';
 import { VimAccountDetails } from 'VimAccountModel';
 
@@ -56,9 +58,15 @@ export class InstantiateNsComponent implements OnInit {
   /** Contains all vim account collections */
   public vimAccountSelect: VimAccountDetails;
 
+  /** Contains all NS Config template details */
+  public nsConfigSelect: NSCONFIG;
+
   /** Instance for active modal service @public */
   public activeModal: NgbActiveModal;
 
+  /** Used to subscribe nsdId @public */
+  public nsdID: Subscription;
+
   /** Variable set for twoway binding @public */
   public nsdId: string;
 
@@ -66,13 +74,13 @@ export class InstantiateNsComponent implements OnInit {
   public vimAccountId: string;
 
   /** Form submission Add */
-  public submitted: boolean = false;
+  public submitted = false;
 
   /** Check the loading results @public */
-  public isLoadingResults: boolean = false;
+  public isLoadingResults = false;
 
   /** Give the message for the loading @public */
-  public message: string = 'PLEASEWAIT';
+  public message = 'PLEASEWAIT';
 
   /** Contains Selected VIM Details @public */
   public selectedVIMDetails: VimAccountDetails = null;
@@ -113,6 +121,9 @@ export class InstantiateNsComponent implements OnInit {
   /** Contains the ssh key to be hosted in dom @private */
   private copySSHKey: string;
 
+  /** Input contains component objects @private */
+  @Input() private params: URLPARAMS;
+
   constructor(injector: Injector) {
     this.injector = injector;
     this.restService = this.injector.get(RestService);
@@ -127,10 +138,11 @@ export class InstantiateNsComponent implements OnInit {
 
   public ngOnInit(): void {
     /** Setting up initial value for NSD */
-    this.dataService.currentMessage.subscribe((event: NSData) => {
-      if (event.identifier !== undefined || event.identifier !== '' || event.identifier !== null) {
+    this.nsdID = this.dataService.currentMessage.subscribe((event: NSData) => {
+      if (!isNullOrUndefined(event?.identifier) || event?.identifier !== '') {
         this.nsdId = event.identifier;
       }
+      this.getDetailsconfigtemplateAccount();
     });
     /** On Initializing call the methods */
     this.instantiateFormAction();
@@ -143,10 +155,11 @@ export class InstantiateNsComponent implements OnInit {
     this.instantiateForm = this.formBuilder.group({
       nsName: ['', [Validators.required]],
       nsDescription: ['', [Validators.required]],
-      nsdId: ['', [Validators.required]],
+      nsdId: [null, [Validators.required]],
       vimAccountId: ['', [Validators.required]],
       ssh_keys: [null],
-      config: [null]
+      config: [null],
+      nsConfigTemplateId: [null]
     });
   }
 
@@ -171,6 +184,15 @@ export class InstantiateNsComponent implements OnInit {
     });
   }
 
+  /** Call the ns config template details in the selection options @public */
+  public getDetailsconfigtemplateAccount(): void {
+    this.restService.getResource(environment.NSCONFIGTEMPLATE_URL + '?nsdId=' + this.nsdId).subscribe((template: NSCONFIG) => {
+      this.nsConfigSelect = template;
+    }, (error: ERRORDATA) => {
+      this.restService.handleError(error, 'get');
+    });
+  }
+
   /** On modal submit instantiateNsSubmit will called @public */
   public instantiateNsSubmit(): void {
     this.submitted = true;
@@ -181,6 +203,9 @@ export class InstantiateNsComponent implements OnInit {
     const modalData: MODALCLOSERESPONSEDATA = {
       message: 'Done'
     };
+    if (isNullOrUndefined(this.instantiateForm.value.nsConfigTemplateId)) {
+      delete this.instantiateForm.value.nsConfigTemplateId;
+    }
     if (isNullOrUndefined(this.instantiateForm.value.ssh_keys) || this.instantiateForm.value.ssh_keys === '') {
       delete this.instantiateForm.value.ssh_keys;
     } else {
@@ -206,6 +231,7 @@ export class InstantiateNsComponent implements OnInit {
         });
         delete this.instantiateForm.value.config;
       }
+      delete this.instantiateForm.value.nsConfigTemplateId;
     }
     const apiURLHeader: APIURLHEADER = {
       url: environment.NSINSTANCESCONTENT_URL
@@ -217,7 +243,7 @@ export class InstantiateNsComponent implements OnInit {
         this.translateService.instant('PAGE.NSINSTANCE.CREATEDSUCCESSFULLY'));
       this.router.navigate(['/instances/ns']).catch((): void => {
         // Catch Navigation Error
-    });
+      });
     }, (error: ERRORDATA) => {
       this.isLoadingResults = false;
       this.restService.handleError(error, 'post');
@@ -292,4 +318,11 @@ export class InstantiateNsComponent implements OnInit {
       this.selectedVIMDetails = vimDetails;
     }
   }
+
+  /**
+   * Lifecyle Hooks the trigger before component is deleted
+   */
+  public ngOnDestroy(): void {
+    this.nsdID.unsubscribe();
+  }
 }
diff --git a/src/app/packages/ns-config-template/NSConfigTemplateComponent.html b/src/app/packages/ns-config-template/NSConfigTemplateComponent.html
new file mode 100644 (file)
index 0000000..b508609
--- /dev/null
@@ -0,0 +1,35 @@
+<!--
+Copyright 2020 TATA ELXSI
+
+Licensed under the Apache License, Version 2.0 (the 'License');
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
+-->
+<div class="d-flex flex-row justify-content-between">
+    <div class="d-flex align-items-center header-style">{{'PAGE.DASHBOARD.NSCONFIGTEMPLATE' | translate}}</div>
+    <span class="button">
+        <button class="btn btn-primary" type="button" placement="top" container="body" ngbTooltip="{{'PAGE.NSCONFIGTEMPLATE.NEWNSCONFIGTEMPLATE' | translate}}"
+            (click)="composeTemplate()">
+            <i class="fas fa-plus-circle" aria-hidden="true"></i>&nbsp; {{'PAGE.NSCONFIGTEMPLATE.NEWNSCONFIGTEMPLATE' | translate}}
+        </button>
+    </span>
+</div>
+<div class="mt-2 mb-0 form-group justify-content-end list-utilites-actions">
+    <page-per-row class="me-2" (pagePerRow)="onChange($event)"></page-per-row>
+    <page-reload></page-reload>
+</div>
+<div class="smarttable-style bg-white mt-1">
+    <ng2-smart-table [ngClass]="checkDataClass" [settings]="settings" [source]="dataSource" (userRowSelect)="onUserRowSelect($event)">
+    </ng2-smart-table>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
diff --git a/src/app/packages/ns-config-template/NSConfigTemplateComponent.scss b/src/app/packages/ns-config-template/NSConfigTemplateComponent.scss
new file mode 100644 (file)
index 0000000..c55461a
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ Copyright 2020 TATA ELXSI
+
+ Licensed under the Apache License, Version 2.0 (the 'License');
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
+*/
\ No newline at end of file
diff --git a/src/app/packages/ns-config-template/NSConfigTemplateComponent.ts b/src/app/packages/ns-config-template/NSConfigTemplateComponent.ts
new file mode 100644 (file)
index 0000000..298207a
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ Copyright 2020 TATA ELXSI
+
+ Licensed under the Apache License, Version 2.0 (the 'License');
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
+*/
+/**
+ * @file NS Config Template details Component.
+ */
+import { HttpHeaders } from '@angular/common/http';
+import { Component, Injector, OnInit } from '@angular/core';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { TranslateService } from '@ngx-translate/core';
+import { ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { ComposePackages } from 'ComposePackages';
+import { DataService } from 'DataService';
+import { environment } from 'environment';
+import { LocalDataSource } from 'ng2-smart-table';
+import { NSConfigTemplateActionComponent } from 'NSCONFIGTEMPLATEACTION';
+import { NSCONFIG, NSConfigData } from 'NSCONFIGTEMPLATEMODEL';
+import { RestService } from 'RestService';
+import { Subscription } from 'rxjs';
+import { SharedService } from 'SharedService';
+import { VNFData } from 'VNFDModel';
+
+/**
+ * Creating component
+ * @Component takes NSConfigTemplateComponent.html as template url
+ */
+@Component({
+    selector: 'app-ns-config-template',
+    templateUrl: './NSConfigTemplateComponent.html',
+    styleUrls: ['./NSConfigTemplateComponent.scss']
+})
+/** Exporting a class @exports NSConfigTemplateComponent */
+export class NSConfigTemplateComponent implements OnInit {
+    /** To inject services @public */
+    public injector: Injector;
+
+    /** Data of smarttable populate through LocalDataSource @public */
+    public dataSource: LocalDataSource = new LocalDataSource();
+
+    /** handle translate @public */
+    public translateService: TranslateService;
+
+    /** Columns list of the smart table @public */
+    public columnLists: object = {};
+
+    /** Settings for smarttable to populate the table with columns @public */
+    public settings: object = {};
+
+    /** Check the loading results @public */
+    public isLoadingResults: boolean = true;
+
+    /** Give the message for the loading @public */
+    public message: string = 'PLEASEWAIT';
+
+    /** Class for empty and present data @public */
+    public checkDataClass: string;
+
+    /** Instance of the rest service @private */
+    private restService: RestService;
+
+    /** dataService to pass the data from one component to another @private */
+    private dataService: DataService;
+
+    /** Formation of appropriate Data for LocalDatasource @private */
+    private nsConfigData: NSConfigData[] = [];
+
+    /** Contains all methods related to shared @private */
+    private sharedService: SharedService;
+
+    /** Controls the header form @private */
+    private headers: HttpHeaders;
+
+    /** Instance of the modal service @private */
+    private modalService: NgbModal;
+
+    /** Instance of subscriptions @private */
+    private generateDataSub: Subscription;
+
+    constructor(injector: Injector) {
+        this.injector = injector;
+        this.restService = this.injector.get(RestService);
+        this.dataService = this.injector.get(DataService);
+        this.sharedService = this.injector.get(SharedService);
+        this.translateService = this.injector.get(TranslateService);
+        this.modalService = this.injector.get(NgbModal);
+    }
+
+    /**
+     * Lifecyle Hooks the trigger before component is instantiate
+     */
+    public ngOnInit(): void {
+        this.generateColumns();
+        this.generateSettings();
+        this.generateData();
+        this.headers = new HttpHeaders({
+            'Content-Type': 'application/gzip',
+            Accept: 'application/json',
+            'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+        });
+        this.generateDataSub = this.sharedService.dataEvent.subscribe((): void => { this.generateData(); });
+    }
+
+    /** smart table Header Colums @public */
+    public generateColumns(): void {
+        this.columnLists = {
+            name: { title: this.translateService.instant('NAME'), width: '25%' },
+            identifier: { title: this.translateService.instant('IDENTIFIER'), width: '25%' },
+            nsdId: { title: this.translateService.instant('PAGE.INSTANCEINSTANTIATE.NSID'), width: '25%' },
+            created: { title: this.translateService.instant('Created'), width: '15%' },
+            Actions: {
+                name: 'Action', width: '15%', filter: false, sort: false, type: 'custom',
+                title: this.translateService.instant('ACTIONS'),
+                valuePrepareFunction: (cell: VNFData, row: VNFData): VNFData => row, renderComponent: NSConfigTemplateActionComponent
+            }
+        };
+    }
+
+    /** smart table Data Settings @public */
+    public generateSettings(): void {
+        this.settings = {
+            edit: {
+                editButtonContent: '<i class="fa fa-edit" title="Edit"></i>',
+                confirmSave: true
+            },
+            delete: {
+                deleteButtonContent: '<i class="far fa-trash-alt" title="delete"></i>',
+                confirmDelete: true
+            },
+            columns: this.columnLists,
+            actions: {
+                add: false,
+                edit: false,
+                delete: false,
+                position: 'right'
+            },
+            attr: this.sharedService.tableClassConfig(),
+            pager: this.sharedService.paginationPagerConfig(),
+            noDataMessage: this.translateService.instant('NODATAMSG')
+        };
+    }
+
+    /** smart table listing manipulation @public */
+    public onChange(perPageValue: number): void {
+        this.dataSource.setPaging(1, perPageValue, true);
+    }
+
+    /** OnUserRowSelect Function @public */
+    public onUserRowSelect(event: MessageEvent): void {
+        Object.assign(event.data, { page: 'ns-config-template' });
+        this.dataService.changeMessage(event.data);
+    }
+
+
+    /** Generate nsData object from loop and return for the datasource @public */
+    public generatetemplateData(nsData: NSCONFIG): NSConfigData {
+        return {
+            nsdId: nsData.nsdId,
+            identifier: nsData._id,
+            operationalState: nsData._admin.operationalState,
+            created: this.sharedService.convertEpochTime(Number(nsData._admin.created)),
+            modified: this.sharedService.convertEpochTime(Number(nsData._admin.modified)),
+            name: nsData.name
+        };
+    }
+    /** Handle compose new ns package method  @public */
+    public composeTemplate(): void {
+        // eslint-disable-next-line security/detect-non-literal-fs-filename
+        const modalRef: NgbModalRef = this.modalService.open(ComposePackages, { backdrop: 'static' });
+        modalRef.componentInstance.params = { page: 'ns-config-template' };
+        modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+            if (result) {
+                this.sharedService.callData();
+            }
+        }).catch((): void => {
+            // Catch Navigation Error
+        });
+    }
+
+    /**
+     * Lifecyle hook which get trigger on component destruction
+     */
+    public ngOnDestroy(): void {
+        this.generateDataSub.unsubscribe();
+    }
+
+    /** Fetching the data from server to Load in the smarttable @protected */
+    protected generateData(): void {
+        this.isLoadingResults = true;
+        this.restService.getResource(environment.NSCONFIGTEMPLATE_URL).subscribe((nsdConfigData: NSCONFIG[]): void => {
+            this.nsConfigData = [];
+            nsdConfigData.forEach((nsddata: NSCONFIG): void => {
+                const vnfDataObj: NSConfigData = this.generatetemplateData(nsddata);
+                this.nsConfigData.push(vnfDataObj);
+            });
+            if (this.nsConfigData.length > 0) {
+                this.checkDataClass = 'dataTables_present';
+            } else {
+                this.checkDataClass = 'dataTables_empty';
+            }
+            this.dataSource.load(this.nsConfigData).then((data: boolean): void => {
+                this.isLoadingResults = false;
+            }).catch((): void => {
+                this.isLoadingResults = false;
+            });
+        }, (error: ERRORDATA): void => {
+            this.restService.handleError(error, 'get');
+            this.isLoadingResults = false;
+        });
+    }
+}
index 1067054..03ec3b7 100644 (file)
@@ -17,24 +17,56 @@ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.i
 -->
 <form [formGroup]="packagesForm" (ngSubmit)="createPackages()" autocomplete="off">
   <div class="modal-header">
-    <h4 class="modal-title" id="modal-basic-title">{{'CREATEPACKAGE' | translate}}</h4>
+    <h4 class="modal-title" *ngIf="!template" id="modal-basic-title">{{'CREATEPACKAGE' | translate}}</h4>
+    <h4 class="modal-title" *ngIf="params.page === 'ns-config-template'" id="modal-basic-title">
+      {{'PAGE.NSCONFIGTEMPLATE.CREATENSCONFIGTEMPLATE' | translate}}</h4>
+    <h4 class="modal-title" *ngIf="params.page === 'ns-config-template-edit'" id="modal-basic-title">
+      {{'PAGE.NSCONFIGTEMPLATE.EDITNSCONFIGTEMPLATE' | translate}}</h4>
     <button class="button-xs" type="button" class="close" (click)="activeModal.close()">
       <i class="fas fa-times-circle text-danger"></i>
     </button>
   </div>
   <div class="modal-body">
     <div class="form-group row mb-3">
-      <label class="col-sm-12 col-form-label mandatory-label" [ngClass]="{'text-danger': packagesForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' | translate}}</label>
-      <label class="col-sm-6 col-form-label">{{'PACKAGE' | translate}} {{'NAME' | translate}}*</label>
+      <label class="col-sm-12 col-form-label mandatory-label"
+        [ngClass]="{'text-danger': packagesForm.invalid === true && submitted === true}">{{'MANDATORYCHECK' |
+        translate}}</label>
+      <label class="col-sm-6 col-form-label" *ngIf="!template else configtemplate">{{'PACKAGE' | translate}} {{'NAME' | translate}}*</label>
+      <ng-template #configtemplate>
+        <label class="col-sm-6 col-form-label">{{'NAME' | translate}}*</label>
+      </ng-template>
       <div class="col-sm-6">
-        <input type="text" class="form-control" placeholder="{{'PACKAGE' | translate}} {{'NAME' | translate}}"
-          formControlName="name" id="name" [ngClass]="{ 'is-invalid': submitted && f.name.errors }" required>
+        <input type="text" class="form-control" placeholder="{{'NAME' | translate}}" formControlName="name" id="name"
+          [ngClass]="{ 'is-invalid': submitted && f.name.errors }" required>
+      </div>
+    </div>
+    <div class="form-group row mb-3" *ngIf="template">
+      <label class="col-sm-6 col-form-label">{{'NSD' | translate}} {{'NAME' | translate}}*</label>
+      <div class="col-sm-6">
+        <ng-select formControlName="nsdId" id="nsd" [items]="nsdDetails"
+          placeholder="{{'SELECT' | translate}} {{'NSDNAME' | translate}}" bindLabel="nsName" bindValue="nsName"
+          [ngClass]="{ 'is-invalid': submitted && f.nsdId.errors }">
+        </ng-select>
+      </div>
+    </div>
+    <div class="form-group row mb-3" *ngIf="template">
+      <label class="col-sm-6 col-form-label">{{'CONFIG' | translate}}*</label>
+      <div class="col-sm-6">
+        <textarea rows="10" cols="50" class="form-control" placeholder="{{'YAMLCONFIG' | translate}}"
+          formControlName="config" id="config"></textarea>
+        <div class="fileupload-text mt-1 mb-1">{{'FILEUPLOADLABEL' | translate}}</div>
+        <div class="custom-file">
+          <input type="file" #fileInputConfig class="fileupload custom-file-input"
+            (change)="configFile($event.target.files)" id="customConfigFile">
+        </div>
       </div>
     </div>
   </div>
   <div class="modal-footer">
     <button type="button" class="btn btn-danger" (click)="activeModal.close()">{{'CANCEL' | translate}}</button>
     <button type="submit" class="btn btn-primary">{{'CREATE' | translate}}</button>
+    <button *ngIf="params.page === 'ns-config-template-edit'" type="submit" class="btn btn-primary">{{'EDIT' |
+      translate}}</button>
   </div>
 </form>
 <app-loader [waitingMessage]="message" *ngIf="isLoadingResults"></app-loader>
\ No newline at end of file
index 6f2a031..0dff17a 100644 (file)
  * @file Info Compose Package Model
  */
 import { HttpClient, HttpHeaders } from '@angular/common/http';
-import { Component, Injector, Input, OnInit } from '@angular/core';
-import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { Component, ElementRef, Injector, Input, OnInit, ViewChild } from '@angular/core';
+import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
 import { Router } from '@angular/router';
 import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
 import { TranslateService } from '@ngx-translate/core';
 import { NotifierService } from 'angular-notifier';
-import { APIURLHEADER, ERRORDATA, URLPARAMS } from 'CommonModel';
+import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA, URLPARAMS } from 'CommonModel';
 import { DataService } from 'DataService';
 import { environment } from 'environment';
 import * as jsyaml from 'js-yaml';
+import { NSConfigData } from 'NSCONFIGTEMPLATEMODEL';
+import { NSDDetails } from 'NSDModel';
 import * as pako from 'pako';
 import { RestService } from 'RestService';
-import { SharedService } from 'SharedService';
+import { SharedService, isNullOrUndefined } from 'SharedService';
 
 /** This is added globally by the tar.js library */
 // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -64,13 +66,43 @@ export class ComposePackages implements OnInit {
   public packagesForm: FormGroup;
 
   /** Form submission Add */
-  public submitted: boolean = false;
+  public submitted = false;
 
   /** To handle loader status for API call @public */
-  public isLoadingResults: boolean = false;
+  public isLoadingResults = false;
 
   /** Give the message for the loading @public */
-  public message: string = 'PLEASEWAIT';
+  public message = 'PLEASEWAIT';
+
+  /** contains NSD name @public */
+  public nsName: {}[] = [];
+
+  /** contains NSD details @public */
+  public nsdDetails: {}[];
+
+  /** contains NSD details filtered by id @public */
+  public nsdName: string;
+
+  /** Contains config details @public */
+  public config: string;
+
+  /** contains NSD details filtered by name @public */
+  public nsId: string;
+
+  /** Check if template or not @public */
+  public template = false;
+
+  /** Data of NS config @public */
+  public details: NSConfigData;
+
+  /** Data of NF packages @public */
+  public nsConfigData: NSConfigData[] = [];
+
+  /** Element ref for fileInputConfig @public */
+  @ViewChild('fileInputConfig') fileInputConfig: ElementRef<HTMLInputElement>;
+
+  /** Element ref for fileInputConfigLabel @public */
+  @ViewChild('fileInputConfigLabel') fileInputConfigLabel: ElementRef<HTMLLabelElement>;
 
   /** FormBuilder instance added to the formBuilder @private */
   private formBuilder: FormBuilder;
@@ -84,15 +116,15 @@ export class ComposePackages implements OnInit {
   /** Controls the header form @private */
   private headers: HttpHeaders;
 
-  /** Create URL holds the end point of any packages @private */
-  private createURL: string;
-
-  /** Input contains component objects @private */
-  @Input() private params: URLPARAMS;
+  /** Input contains component objects @public */
+  @Input() public params: URLPARAMS;
 
   /** Holds the end point @private */
   private endPoint: string;
 
+  /** ModalData instance of modal @private  */
+  private modalData: MODALCLOSERESPONSEDATA;
+
   /** Contains all methods related to shared @private */
   private sharedService: SharedService;
 
@@ -121,48 +153,191 @@ export class ComposePackages implements OnInit {
    * Lifecyle Hooks the trigger before component is instantiate
    */
   public ngOnInit(): void {
-    this.headers = new HttpHeaders({
-      'Content-Type': 'application/gzip',
-      Accept: 'application/json',
-      'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
-    });
     this.initializeForm();
+    if (this.params.page === 'ns-config-template') {
+      this.template = true;
+      this.getNsdPackageDetails();
+    } else if (this.params.page === 'ns-config-template-edit') {
+      this.template = true;
+      this.getNsdPackageDetails();
+      this.getFormControl('nsdId').disable();
+    } else {
+      this.getFormControl('nsdId').disable();
+      this.getFormControl('config').disable();
+    }
   }
 
   /** initialize Forms @public */
   public initializeForm(): void {
     this.packagesForm = this.formBuilder.group({
-      name: ['', [Validators.required]]
+      name: ['', [Validators.required]],
+      nsdId: [null, [Validators.required]],
+      config: [null]
+    });
+  }
+
+  /** Get NSD Package details @public */
+  public getNsdPackageDetails(): void {
+    this.restService.getResource(environment.NSDESCRIPTORSCONTENT_URL)
+      .subscribe((nsdPackageData: NSDDetails[]): void => {
+        nsdPackageData.forEach((nsData: NSDDetails): void => {
+          const names: {} = {
+            nsName: nsData.name,
+            nsId: nsData._id
+          };
+          this.nsName.push(names);
+        });
+        this.nsdDetails = this.nsName;
+        if (this.params.page === 'ns-config-template-edit') {
+          this.getNSConfigDetails(environment.NSCONFIGTEMPLATE_URL + '/' + this.params.id, this.nsdDetails);
+        }
+      }, (error: ERRORDATA): void => {
+        this.restService.handleError(error, 'get');
+      });
+  }
+
+  /** Get the NSD Content List & patch value in edit form @public */
+  public getNSConfigDetails(URL: string, name: {}[]): void {
+    this.restService.getResource(URL).subscribe((content: NSConfigData): void => {
+      this.nsConfigData.push(content);
+      this.details = this.nsConfigData[0];
+      const nsId: string = 'nsId';
+      // eslint-disable-next-line security/detect-object-injection
+      const nsdId: {}[] = name.filter((nsdData: {}[]): boolean => nsdData[nsId] === this.details.nsdId);
+      const nsName: string = 'nsName';
+      for (const data of nsdId) {
+        // eslint-disable-next-line security/detect-object-injection
+        this.nsdName = data[nsName];
+      }
+      if (!isNullOrUndefined(this.details.config)) {
+        this.config = jsyaml.dump(this.details.config);
+      }
+      this.packagesForm.patchValue({ name: this.details.name, nsdId: this.nsdName, config: this.config });
+      this.isLoadingResults = false;
+    }, (error: ERRORDATA): void => {
+      this.restService.handleError(error, 'get');
+      this.isLoadingResults = false;
     });
   }
 
   /** Create packages @public */
   public createPackages(): void {
     this.submitted = true;
+    this.modalData = {
+      message: 'Done'
+    };
     this.sharedService.cleanForm(this.packagesForm);
     if (!this.packagesForm.invalid) {
       this.isLoadingResults = true;
-      if (this.params.page === 'ns-package') {
-        this.endPoint = environment.NSDESCRIPTORSCONTENT_URL;
-      } else if (this.params.page === 'vnf-package') {
-        this.endPoint = environment.VNFPACKAGESCONTENT_URL;
+      if (this.params.page === 'ns-package' || this.params.page === 'vnf-package') {
+        if (this.params.page === 'ns-package') {
+          this.endPoint = environment.NSDESCRIPTORSCONTENT_URL;
+        } else if (this.params.page === 'vnf-package') {
+          this.endPoint = environment.VNFPACKAGESCONTENT_URL;
+        }
+        const descriptor: string = this.packageYaml(this.params.page);
+        try {
+          // eslint-disable-next-line @typescript-eslint/no-explicit-any
+          const tar: any = new Tar();
+          const out: Uint8Array = tar.append(this.packagesForm.value.name + '/' + this.packagesForm.value.name + '.yaml',
+            descriptor, { type: '0' });
+          const gzipContent: Uint8Array = pako.gzip(out);
+          this.createPackageApi(gzipContent.buffer);
+        } catch (e) {
+          this.isLoadingResults = false;
+          this.notifierService.notify('error', this.translateService.instant('ERROR'));
+        }
+      } else {
+        try {
+          this.headers = new HttpHeaders({
+            Accept: 'application/json',
+            'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+          });
+          if (this.params.page === 'ns-config-template') {
+            this.endPoint = environment.NSCONFIGTEMPLATE_URL;
+            this.createTemplate(this.endPoint);
+          } else if (this.params.page === 'ns-config-template-edit') {
+            this.endPoint = environment.NSCONFIGTEMPLATE_URL + '/' + this.params.id + '/' + 'template_content';
+            this.editTemplate(this.endPoint);
+          }
+        } catch (e) {
+          this.isLoadingResults = false;
+          this.notifierService.notify('error', this.translateService.instant('ERROR'));
+        }
+      }
+    }
+  }
+
+  /** Post config template @public */
+  public createTemplate(urlHeader: string): void {
+    this.isLoadingResults = true;
+    const apiURLHeader: APIURLHEADER = {
+      url: urlHeader,
+      httpOptions: { headers: this.headers }
+    };
+    if (isNullOrUndefined(this.packagesForm.value.config) || this.packagesForm.value.config === '') {
+      delete this.packagesForm.value.config;
+    } else {
+      const validJSON: boolean = this.sharedService.checkJson(this.packagesForm.value.config);
+      if (validJSON) {
+        this.packagesForm.value.config = JSON.parse(this.packagesForm.value.config);
+      } else {
+        const getConfigJson: string = jsyaml.load(this.packagesForm.value.config, { json: true });
+        this.packagesForm.value.config = getConfigJson;
       }
-      const descriptor: string = this.packageYaml(this.params.page);
-      try {
-        // eslint-disable-next-line @typescript-eslint/no-explicit-any
-        const tar: any = new Tar();
-        const out: Uint8Array = tar.append(this.packagesForm.value.name + '/' + this.packagesForm.value.name + '.yaml',
-          descriptor, { type: '0' });
-        const gzipContent: Uint8Array = pako.gzip(out);
-        this.createPackageApi(gzipContent.buffer);
-      } catch (e) {
-        this.isLoadingResults = false;
-        this.notifierService.notify('error', this.translateService.instant('ERROR'));
+    }
+    const nsName: string = 'nsName';
+    // eslint-disable-next-line security/detect-object-injection
+    const nsdId: {}[] = this.nsdDetails.filter((nsdData: {}[]): boolean => nsdData[nsName] === this.packagesForm.value.nsdId);
+    for (const data of nsdId) {
+      // eslint-disable-next-line @typescript-eslint/dot-notation
+      this.nsId = data['nsId'];
+    }
+    this.packagesForm.value.nsdId = this.nsId;
+    this.restService.postResource(apiURLHeader, (this.packagesForm.value)).subscribe((result: {}): void => {
+      this.activeModal.close(this.modalData);
+      this.isLoadingResults = false;
+      this.notifierService.notify('success', this.translateService.instant('PAGE.NSCONFIGTEMPLATE.TEMPLATECREATEDSUCCESSFULLY'));
+    }, (error: ERRORDATA): void => {
+      this.restService.handleError(error, 'post');
+      this.isLoadingResults = false;
+    });
+  }
+
+  /** Edit config template @public */
+  public editTemplate(urlHeader: string): void {
+    this.isLoadingResults = true;
+    const apiURLHeader: APIURLHEADER = {
+      url: urlHeader,
+      httpOptions: { headers: this.headers }
+    };
+    if (isNullOrUndefined(this.packagesForm.value.config) || this.packagesForm.value.config === '') {
+      delete this.packagesForm.value.config;
+    } else {
+      const validJSON: boolean = this.sharedService.checkJson(this.packagesForm.value.config);
+      if (validJSON) {
+        this.packagesForm.value.config = JSON.parse(this.packagesForm.value.config);
+      } else {
+        const getConfigJson: string = jsyaml.load(this.packagesForm.value.config, { json: true });
+        this.packagesForm.value.config = getConfigJson;
       }
     }
+    this.restService.putResource(apiURLHeader, (this.packagesForm.value)).subscribe((result: {}): void => {
+      this.activeModal.close(this.modalData);
+      this.isLoadingResults = false;
+      this.notifierService.notify('success', this.translateService.instant('PAGE.NSCONFIGTEMPLATE.TEMPLATEEDITEDSUCCESSFULLY'));
+    }, (error: ERRORDATA): void => {
+      this.restService.handleError(error, 'post');
+      this.isLoadingResults = false;
+    });
   }
   /** Create packages @public */
   private createPackageApi(packageContent: ArrayBuffer | SharedArrayBuffer): void {
+    this.headers = new HttpHeaders({
+      'Content-Type': 'application/gzip',
+      Accept: 'application/json',
+      'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+    });
     const apiURLHeader: APIURLHEADER = {
       url: this.endPoint,
       httpOptions: { headers: this.headers }
@@ -176,6 +351,42 @@ export class ComposePackages implements OnInit {
       this.restService.handleError(error, 'post');
     });
   }
+  /** Config file process @private */
+  public configFile(files: FileList): void {
+    if (files && files.length === 1) {
+      const fileFormat: string = this.sharedService.fetchFileExtension(files).toLocaleLowerCase();
+      if (fileFormat === 'yaml' || fileFormat === 'yml') {
+        this.sharedService.getFileString(files, 'yaml').then((fileContent: string): void => {
+          this.packagesForm.get('config').setValue(fileContent);
+        }).catch((err: string): void => {
+          if (err === 'typeError') {
+            this.notifierService.notify('error', this.translateService.instant('YAMLFILETYPEERRROR'));
+          } else {
+            this.notifierService.notify('error', this.translateService.instant('ERROR'));
+          }
+          this.fileInputConfigLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
+          this.fileInputConfig.nativeElement.value = null;
+        });
+      } else if (fileFormat === 'json') {
+        this.sharedService.getFileString(files, 'json').then((fileContent: string): void => {
+          const getConfigJson: string = jsyaml.load(fileContent, { json: true });
+          this.packagesForm.get('config').setValue(JSON.stringify(getConfigJson));
+        }).catch((err: string): void => {
+          if (err === 'typeError') {
+            this.notifierService.notify('error', this.translateService.instant('JSONFILETYPEERRROR'));
+          } else {
+            this.notifierService.notify('error', this.translateService.instant('ERROR'));
+          }
+          this.fileInputConfigLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
+          this.fileInputConfig.nativeElement.value = null;
+        });
+      }
+    } else if (files && files.length > 1) {
+      this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
+    }
+    this.fileInputConfigLabel.nativeElement.innerText = files[0].name;
+    this.fileInputConfig.nativeElement.value = null;
+  }
   /** Compose NS Packages @private */
   private composeNSPackages(id: string): void {
     let packageUrl: string;
@@ -241,4 +452,10 @@ export class ComposePackages implements OnInit {
     }
     return jsyaml.dump(packageYaml, { sortKeys: true });
   }
+
+  /** Used to get the AbstractControl of controlName passed @private */
+  private getFormControl(controlName: string): AbstractControl {
+    // eslint-disable-next-line security/detect-object-injection
+    return this.packagesForm.controls[controlName];
+  }
 }
index d79d4e4..445c511 100644 (file)
@@ -202,6 +202,9 @@ export class DeleteComponent {
     } else if (data.page === 'osmrepo') {
       this.deleteURL = environment.OSMREPOS_URL;
       this.notifyMessage = 'DELETEDSUCCESSFULLY';
+    } else if (data.page === 'ns-config-template') {
+      this.deleteURL = environment.NSCONFIGTEMPLATE_URL;
+      this.notifyMessage = 'DELETEDSUCCESSFULLY';
     }
   }
   /** Generate Data function @public */
diff --git a/src/app/utilities/ns-config-template-action/NSConfigTemplateActionComponent.html b/src/app/utilities/ns-config-template-action/NSConfigTemplateActionComponent.html
new file mode 100644 (file)
index 0000000..e36916f
--- /dev/null
@@ -0,0 +1,28 @@
+<!--
+Copyright 2020 TATA ELXSI
+
+Licensed under the Apache License, Version 2.0 (the 'License');
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
+-->
+<div class="btn-group list action" role="group">
+  <button type="button" class="btn btn-primary" (click)="deleteTemplate()" placement="top" container="body"
+    ngbTooltip="{{'DELETE' | translate}}">
+    <i class="far fa-trash-alt icons"></i>
+  </button>
+  <button type="button" class="btn btn-primary" (click)="templateEdit()" placement="top" container="body"
+    ngbTooltip="{{'EDIT' | translate}}">
+    <i class="far fa-edit icons"></i>
+  </button>
+</div>
+<app-loader [waitingMessage]="message" *ngIf="isLoadingDownloadResult"></app-loader>
\ No newline at end of file
diff --git a/src/app/utilities/ns-config-template-action/NSConfigTemplateActionComponent.scss b/src/app/utilities/ns-config-template-action/NSConfigTemplateActionComponent.scss
new file mode 100644 (file)
index 0000000..c55461a
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ Copyright 2020 TATA ELXSI
+
+ Licensed under the Apache License, Version 2.0 (the 'License');
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
+*/
\ No newline at end of file
diff --git a/src/app/utilities/ns-config-template-action/NSConfigTemplateActionComponent.ts b/src/app/utilities/ns-config-template-action/NSConfigTemplateActionComponent.ts
new file mode 100644 (file)
index 0000000..b653c5d
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ Copyright 2020 TATA ELXSI
+
+ Licensed under the Apache License, Version 2.0 (the 'License');
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
+*/
+/**
+ * @file NSConfigTemplateAction Component
+ */
+import { Component, Injector } from '@angular/core';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { MODALCLOSERESPONSEDATA } from 'CommonModel';
+import { ComposePackages } from 'ComposePackages';
+import { DeleteComponent } from 'DeleteComponent';
+import { NSConfigData } from 'NSCONFIGTEMPLATEMODEL';
+import { SharedService } from 'SharedService';
+
+/**
+ * Creating component
+ * @Component takes NSConfigTemplateActionComponent.html as template url
+ */
+@Component({
+    templateUrl: './NSConfigTemplateActionComponent.html',
+    styleUrls: ['./NSConfigTemplateActionComponent.scss']
+})
+/** Exporting a class @exports NSConfigTemplateActionComponent */
+export class NSConfigTemplateActionComponent {
+    /** To get the value from the vnfpackage via valuePrepareFunction default Property of ng-smarttable @public */
+    public value: NSConfigData;
+
+    /** To inject services @public */
+    public injector: Injector;
+
+    /** Check the loading results for loader status @public */
+    public isLoadingDownloadResult: boolean = false;
+
+    /** Give the message for the loading @public */
+    public message: string = 'PLEASEWAIT';
+
+    /** Instance of the modal service @private */
+    private modalService: NgbModal;
+
+    /** Variables holds Template ID @private */
+    private templateID: string;
+
+    /** Contains all methods related to shared @private */
+    private sharedService: SharedService;
+
+    constructor(injector: Injector) {
+        this.injector = injector;
+        this.sharedService = this.injector.get(SharedService);
+        this.modalService = this.injector.get(NgbModal);
+    }
+
+    /**
+     * Lifecyle Hooks the trigger before component is instantiate
+     */
+    public ngOnInit(): void {
+        this.templateID = this.value.identifier;
+    }
+
+    /** Delete NS Config template @public */
+    public deleteTemplate(): void {
+        // eslint-disable-next-line security/detect-non-literal-fs-filename
+        const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, { backdrop: 'static' });
+        modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+            if (result) {
+                this.sharedService.callData();
+            }
+        }).catch((): void => {
+            // Catch Navigation Error
+        });
+    }
+
+    /** Set instance for Template Edit @public */
+    public templateEdit(): void {
+          // eslint-disable-next-line security/detect-non-literal-fs-filename
+          const modalRef: NgbModalRef = this.modalService.open(ComposePackages, { backdrop: 'static' });
+          modalRef.componentInstance.params = {id: this.templateID, page: 'ns-config-template-edit'};
+          modalRef.result.then((result: MODALCLOSERESPONSEDATA) => {
+              if (result) {
+                  this.sharedService.callData();
+              }
+          }).catch((): void => {
+              // Catch Navigation Error
+          });
+    }
+}
index 870897c..87aaf98 100644 (file)
@@ -94,7 +94,7 @@
     "DELETELOADERMESSAGE": "Bitte warten Sie, während der Löschvorgang ausgeführt wird",
     "DELETELOADMESSAGE": "Bitte warten Sie, während der Löschvorgang ausgeführt wird",
     "WARNINGMESSAGE": "Es können nicht mehr als 25 Instanzen gelöscht werden",
-    "DELETENS":"NS löschen",
+    "DELETENS": "NS löschen",
     "VALUE": "Wert",
     "PERFORMACTION": "Aktion ausführen",
     "EXECUTE": "Execute",
     "NODATE": "Keine Datumsinformationen gefunden",
     "TYPEINFO": "Um einen neuen TYPW hinzuzufügen, geben Sie oben die Eingabe ein",
     "UPLOADCONFIGLABEL": "Bitte laden Sie eine Datei im .yaml- oder .yml-Format hoch",
+    "CONFIGFILEUPLOADLABEL": "Oder geben Sie Konfigurationsparameter ein",
     "NEWVERSIONTAG": "Hier ist die neue Version {{appVersion}} von OSM!",
     "SCALEOUT": "Scale Out",
     "SCALEIN": "Scale In",
             "RUNNINGINSTANCES": "Laufende Instanzen",
             "NETSLICETEMPLATE": "NetSlice Vorlage",
             "NETSLICEINSTANCE": "NetSlice Instanzen",
+            "NSCONFIGTEMPLATE": "NS-Konfigurationsvorlage",
             "USERS": "Benutzer",
             "PROJECTS": "Projekte",
             "USERSETTINGS": "Benutzereinstellungen",
         "NETSLICETEMPLATE": {
             "NETSLICETEMPLATEDETAILS": "Netzwerk-Slices-Vorlagendetails"
         },
+        "NSCONFIGTEMPLATE": {
+            "NEWNSCONFIGTEMPLATE": "Neue NS-Konfigurationsvorlage",
+            "CREATENSCONFIGTEMPLATE": "Erstellen Sie eine NS-Konfigurationsvorlage",
+            "EDITNSCONFIGTEMPLATE": "Bearbeiten Sie die NS-Konfigurationsvorlage",
+            "TEMPLATECREATEDSUCCESSFULLY": "NS-Konfigurationsvorlage erfolgreich erstellt",
+            "TEMPLATEEDITEDSUCCESSFULLY": "NS-Konfigurationsvorlage erfolgreich bearbeitet"
+        },
         "NSTINSTANCEINSTANTIATE": {
             "NEWINSTANCE": "Neue Instanz",
             "NSNAME": "Ns Name",
index 375b9a5..99fbb15 100644 (file)
@@ -94,7 +94,7 @@
     "DELETELOADERMESSAGE": "Please wait while {{title}} deletion is in progress",
     "DELETELOADMESSAGE": "Please wait while deletion is in progress",
     "WARNINGMESSAGE": "Cannot delete more than 25 instances",
-    "DELETENS":"Delete NS",
+    "DELETENS": "Delete NS",
     "VALUE": "Value",
     "PERFORMACTION": "Perform Action",
     "EXECUTE": "Execute",
     "NODATE": "No date information found",
     "TYPEINFO": "To add a new TYPE, Please enter input above",
     "UPLOADCONFIGLABEL": "Please upload file with .yaml or .yml format",
+    "CONFIGFILEUPLOADLABEL": "Or enter config parameters",
     "NEWVERSIONTAG": "Here is the new version {{appVersion}} of OSM!",
     "SCALEOUT": "Scale Out",
     "SCALEIN": "Scale In",
             "RUNNINGINSTANCES": "Running Instances",
             "NETSLICETEMPLATE": "NetSlice Template",
             "NETSLICEINSTANCE": "NetSlice Instances",
+            "NSCONFIGTEMPLATE": "NS Config Template",
             "USERS": "Users",
             "PROJECTS": "Projects",
             "USERSETTINGS": "User Settings",
         "NETSLICETEMPLATE": {
             "NETSLICETEMPLATEDETAILS": "Network Slices Template Details"
         },
+        "NSCONFIGTEMPLATE": {
+            "NEWNSCONFIGTEMPLATE": "New NS Config Template",
+            "CREATENSCONFIGTEMPLATE": "Create NS Config Template",
+            "EDITNSCONFIGTEMPLATE": "Edit NS Config Template",
+            "TEMPLATECREATEDSUCCESSFULLY": "NS Config Template Created Successfully",
+            "TEMPLATEEDITEDSUCCESSFULLY": "NS Config Template Edited Successfully"
+        },
         "NSTINSTANCEINSTANTIATE": {
             "NEWINSTANCE": "New Instance",
             "NSNAME": "Ns Name",
index 2a5c884..34619a6 100644 (file)
@@ -94,7 +94,7 @@
     "DELETELOADERMESSAGE": "Por favor, espere mientras la eliminación está en progreso",
     "DELETELOADMESSAGE": "Por favor, espere mientras la eliminación está en progreso",
     "WARNINGMESSAGE": "No se pueden eliminar más de 25 instancias",
-    "DELETENS":"Eliminar NS",
+    "DELETENS": "Eliminar NS",
     "VALUE": "Valor",
     "PERFORMACTION": "Realizar una acción",
     "EXECUTE": "Ejecutar",
     "NODATE": "No se encontró información de fecha",
     "TYPEINFO": "Para agregar un nuevo TIPO, ingrese la entrada de arriba",
     "UPLOADCONFIGLABEL": "Cargue el archivo con formato .yaml o .yml",
+    "CONFIGFILEUPLOADLABEL": "O ingrese los parámetros de configuración",
     "NEWVERSIONTAG": "¡Aquí está la nueva versión {{appVersion}} de OSM!",
     "SCALEOUT": "Desescalar",
     "SCALEIN": "Escalar",
     "HEALING": "Curación Manual",
     "DAY1OPERATION": "Operación día 1",
     "SELECTVDU": "Seleccionar VDU",
-    "DATE":"Fecha",
+    "DATE": "Fecha",
     "PAGE": {
         "DASHBOARD": {
             "DASHBOARD": "Tablero",
             "RUNNINGINSTANCES": "Corriendo Instancias",
             "NETSLICETEMPLATE": "Plantilla NetSlice",
             "NETSLICEINSTANCE": "NetSlice Instancias",
+            "NSCONFIGTEMPLATE": "Plantilla de configuración NS",
             "USERS": "Usuarios",
             "PROJECTS": "Proyectos",
             "USERSETTINGS": "Ajustes de usuario",
         "NETSLICETEMPLATE": {
             "NETSLICETEMPLATEDETAILS": "Detalles de la plantilla Network Slices"
         },
+        "NSCONFIGTEMPLATE": {
+            "NEWNSCONFIGTEMPLATE": "Nueva plantilla de configuración NS",
+            "CREATENSCONFIGTEMPLATE": "Crear plantilla de configuración NS",
+            "EDITNSCONFIGTEMPLATE": "Editar plantilla de configuración NS",
+            "TEMPLATECREATEDSUCCESSFULLY": "Plantilla de configuración NS creada correctamente",
+            "TEMPLATEEDITEDSUCCESSFULLY": "Plantilla de configuración NS editada correctamente"
+        },
         "NSTINSTANCEINSTANTIATE": {
             "NEWINSTANCE": "Nueva instancia",
             "NSNAME": "Nombre de Ns",
index e24b3ed..75eb921 100644 (file)
@@ -94,7 +94,7 @@
     "DELETELOADERMESSAGE": "Aguarde enquanto a exclusão está em andamento",
     "DELETELOADMESSAGE": "Aguarde enquanto a exclusão está em andamento",
     "WARNINGMESSAGE": "Não é possível excluir mais de 25 instâncias",
-    "DELETENS":"Excluir NS",
+    "DELETENS": "Excluir NS",
     "VALUE": "Valor",
     "PERFORMACTION": "Executar a ação",
     "EXECUTE": "Executar",
     "NODATE": "Nenhuma informação de data encontrada",
     "TYPEINFO": "Para adicionar um novo TIPO, insira a entrada acima",
     "UPLOADCONFIGLABEL": "Faça o upload do arquivo no formato .yaml ou .yml",
+    "CONFIGFILEUPLOADLABEL": "Ou insira os parâmetros de configuração",
     "NEWVERSIONTAG": "Aqui está a nova versão {{appVersion}} do OSM!",
     "SCALEOUT": "Dimensionar",
     "SCALEIN": "Escala em",
     "HEALING": "Cura Manual",
     "DAY1OPERATION": "Operação dia 1",
     "SELECTVDU": "Selecione VDU",
-    "DATE":"Data",
+    "DATE": "Data",
     "PAGE": {
         "DASHBOARD": {
             "DASHBOARD": "painel de controle",
             "RUNNINGINSTANCES": "Instâncias em execução",
             "NETSLICETEMPLATE": "Modelo de fatia líquida",
             "NETSLICEINSTANCE": "Instâncias de fatia líquida",
+            "NSCONFIGTEMPLATE": "Modelo de configuração NS",
             "USERS": "Comercial",
             "PROJECTS": "Projetos",
             "USERSETTINGS": "Configurações do usuário",
         "NETSLICETEMPLATE": {
             "NETSLICETEMPLATEDETAILS": "Detalhes do modelo de fatias de rede"
         },
+        "NSCONFIGTEMPLATE": {
+            "NEWNSCONFIGTEMPLATE": "Novo modelo de configuração NS",
+            "CREATENSCONFIGTEMPLATE": "Criar modelo de configuração NS",
+            "EDITNSCONFIGTEMPLATE": "Editar modelo de configuração NS",
+            "TEMPLATECREATEDSUCCESSFULLY": "Modelo de configuração NS criado com sucesso",
+            "TEMPLATEEDITEDSUCCESSFULLY": "Modelo de configuração NS editado com sucesso"
+        },
         "NSTINSTANCEINSTANTIATE": {
             "NEWINSTANCE": "Nova Instância",
             "NSNAME": "Ns Name",
index b3b625d..5168356 100644 (file)
@@ -79,5 +79,6 @@ export const environment = {
     GRAFANA_URL: GRAFANA_ENDPOINT + '/d',
     DOMAIN_URL: OSM_ADMIN_ENDPOINT + 'domains',
     OSM_VERSION_URL: OSM_VERSION,
-    OSMREPOS_URL: OSM_ADMIN_ENDPOINT + 'osmrepos'
+    OSMREPOS_URL: OSM_ADMIN_ENDPOINT + 'osmrepos',
+    NSCONFIGTEMPLATE_URL: OSM_NSD_ENDPOINT + 'ns_config_template'
 };
index 3f80777..de8ae5c 100644 (file)
@@ -79,5 +79,6 @@ export const environment = {
     GRAFANA_URL: GRAFANA_ENDPOINT + '/d',
     DOMAIN_URL: OSM_ADMIN_ENDPOINT + 'domains',
     OSM_VERSION_URL: OSM_VERSION,
-    OSMREPOS_URL: OSM_ADMIN_ENDPOINT + 'osmrepos'
+    OSMREPOS_URL: OSM_ADMIN_ENDPOINT + 'osmrepos',
+    NSCONFIGTEMPLATE_URL: OSM_NSD_ENDPOINT + 'ns_config_template'
 };
index 5944aef..9ec1472 100644 (file)
@@ -80,6 +80,16 @@ export const MENU_ITEMS: MENUITEMS[] = [
                 icon: 'fas fa-layer-group',
                 menuName: 'PAGE.DASHBOARD.NETSLICETEMPLATE',
                 isChildExists: false
+            },
+            {
+                liClass: '',
+                anchorTagClass: 'link',
+                routerLink: '/packages/nsconfigtemplate',
+                routerLinkActive: childActiveClass,
+                routerLinkActiveOptions: false,
+                icon: 'fas fa-file',
+                menuName: 'PAGE.DASHBOARD.NSCONFIGTEMPLATE',
+                isChildExists: false
             }
         ]
     },
diff --git a/src/models/NSConfigtemplateModel.ts b/src/models/NSConfigtemplateModel.ts
new file mode 100644 (file)
index 0000000..59de05b
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ Copyright 2020 TATA ELXSI
+
+ Licensed under the Apache License, Version 2.0 (the 'License');
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
+ */
+/**
+ * @file  Model for NS Config template related information.
+ */
+export interface NSCONFIG {
+    _admin: ADMINDETAILS;
+    _id: string;
+    vnf: ADDITIONAL[];
+    nsdId: string;
+    name: string;
+}
+
+export interface ADMINDETAILS {
+    created?: string;
+    modified?: string;
+    onboardingState?: string;
+    operationalState?: string;
+    projects_read?: string[];
+    projects_write?: string[];
+}
+
+export interface ADDITIONAL {
+    vdu: PARAMS[];
+    'member-vnf-index'?: string;
+}
+
+export interface PARAMS {
+    id?: string;
+    'vim-flavor-id'?: string;
+}
+
+/** Interface for VNFData */
+export interface NSConfigData {
+    nsdId?: string;
+    identifier?: string;
+    created?: string;
+    modified?: string;
+    onboardingState?: string;
+    operationalState?: string;
+    name?: string;
+    config?: {};
+    vnf?: {};
+    additionalParamsForVnf?: {};
+    additionalParamsForNs?: {};
+    vld?: {};
+}
index 556f954..1a46126 100644 (file)
         "NsUpdateComponent": ["src/app/utilities/ns-update/NsUpdateComponent"],
         "WarningComponent": ["src/app/utilities/warning/WarningComponent"],
         "StartStopRebuildComponent": ["src/app/utilities/start-stop-rebuild/StartStopRebuildComponent"],
-        "HealingComponent": ["src/app/utilities/healing/HealingComponent"]
+        "HealingComponent": ["src/app/utilities/healing/HealingComponent"],
+        "NSCONFIGTEMPLATE": ["src/app/packages/ns-config-template/NSConfigTemplateComponent"],
+        "NSCONFIGTEMPLATEACTION" :["src/app/utilities/ns-config-template-action/NSConfigTemplateActionComponent"],
+        "NSCONFIGTEMPLATEMODEL": ["src/models/NSConfigtemplateModel"]
       },
       "useDefineForClassFields": false
     }