Changes for MDONS usecase 45/101945/1
authorroot <preethamshyam.sathiyaseelan@us.fujitsu.com>
Wed, 19 Feb 2020 06:02:26 +0000 (06:02 +0000)
committerroot <preethamshyam.sathiyaseelan@us.fujitsu.com>
Wed, 19 Feb 2020 06:21:39 +0000 (06:21 +0000)
Added MDONS creation and Detail show pages and logic

Change-Id: If830fc0399af561e712b8deff745c8bd88e8117d
Issue-ID: USECASEUI-371
Signed-off-by: root <preethamshyam.sathiyaseelan@us.fujitsu.com>
16 files changed:
usecaseui-portal/src/app/Directives/disable-control.directive.ts [new file with mode: 0644]
usecaseui-portal/src/app/app.module.ts
usecaseui-portal/src/app/core/services/serviceList.service.ts
usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.ts
usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.html
usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.ts
usecaseui-portal/src/app/views/services/services-list/mdons-creation/mdons-creation.component.css [new file with mode: 0644]
usecaseui-portal/src/app/views/services/services-list/mdons-creation/mdons-creation.component.html [new file with mode: 0644]
usecaseui-portal/src/app/views/services/services-list/mdons-creation/mdons-creation.component.less [new file with mode: 0644]
usecaseui-portal/src/app/views/services/services-list/mdons-creation/mdons-creation.component.ts [new file with mode: 0644]
usecaseui-portal/src/app/views/services/services-list/mdons-detail/mdons-detail.component.html [new file with mode: 0644]
usecaseui-portal/src/app/views/services/services-list/mdons-detail/mdons-detail.component.less [new file with mode: 0644]
usecaseui-portal/src/app/views/services/services-list/mdons-detail/mdons-detail.component.ts [new file with mode: 0644]
usecaseui-portal/src/app/views/services/services-list/services-list.component.html
usecaseui-portal/src/app/views/services/services-list/services-list.component.ts
usecaseui-portal/src/assets/i18n/en.json

diff --git a/usecaseui-portal/src/app/Directives/disable-control.directive.ts b/usecaseui-portal/src/app/Directives/disable-control.directive.ts
new file mode 100644 (file)
index 0000000..8549540
--- /dev/null
@@ -0,0 +1,17 @@
+import { Directive, Input } from '@angular/core';
+import { NgControl } from '@angular/forms';
+
+@Directive({
+  selector: '[disableControl]'
+})
+export class DisableControlDirective {
+
+  @Input()
+  set disableControl(condition: boolean) {
+    const action = condition ? 'enable' : 'disable';
+    this.ngControl.control[action]();
+  }
+
+  constructor(private ngControl: NgControl) {
+  }
+}
\ No newline at end of file
index d46f9f5..9d14d8f 100644 (file)
 import { BrowserModule } from '@angular/platform-browser';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
 import { NgModule } from '@angular/core';
-import { FormsModule } from '@angular/forms';
+import { FormsModule, ReactiveFormsModule  } from '@angular/forms';
 import { HttpClientModule } from '@angular/common/http';
 import { HttpClient } from '@angular/common/http';
 import { NgZorroAntdModule } from 'ng-zorro-antd';
 import { NZ_I18N, en_US } from 'ng-zorro-antd';
 import { NgxEchartsModule } from 'ngx-echarts';
 
+//Custom Directive
+import { DisableControlDirective } from './Directives/disable-control.directive';
+
 import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
 import { TranslateHttpLoader } from '@ngx-translate/http-loader';
 export function HttpLoaderFactory(httpClient: HttpClient) {
@@ -49,6 +52,8 @@ import { PerformanceVmComponent } from './views/performance/performance-vm/perfo
 import { CcvpnNetworkComponent } from './views/ccvpn-network/ccvpn-network.component';
 import { CcvpnDetailComponent } from './views/services/services-list/ccvpn-detail/ccvpn-detail.component';
 import { CcvpnCreationComponent } from './views/services/services-list/ccvpn-creation/ccvpn-creation.component';
+import { MdonsDetailComponent } from './views/services/services-list/mdons-detail/mdons-detail.component';
+import { MdonsCreationComponent } from './views/services/services-list/mdons-creation/mdons-creation.component';
 
 import { DetailsComponent } from './shared/components/details/details.component';
 import { GraphiclistComponent } from './shared/components/graphiclist/graphiclist.component';
@@ -160,11 +165,15 @@ import { BusinessOrderComponent } from './views/services/slicing-management/csmf
       NsiModelComponent,
       NssiModelComponent,
       CsmfSlicingBusinessManagementComponent,
-      BusinessOrderComponent
+      BusinessOrderComponent,
+    MdonsCreationComponent,
+    MdonsDetailComponent,
+    DisableControlDirective
   ],
   imports: [
     BrowserModule,
     FormsModule,
+    ReactiveFormsModule ,
     HttpClientModule,
     TranslateModule.forRoot({
       loader: {
@@ -183,6 +192,10 @@ import { BusinessOrderComponent } from './views/services/slicing-management/csmf
         SlicingBusinessModelComponent,
         NsiModelComponent,
         NssiModelComponent
-    ]
+    ],
+  exports: [
+    FormsModule,
+    ReactiveFormsModule
+  ]
 })
-export class AppModule { }
\ No newline at end of file
+export class AppModule { }
index 1ada669..945d60c 100644 (file)
@@ -17,6 +17,7 @@ import { Injectable } from '@angular/core';
 import { HttpClient, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http';
 import { Observable } from 'rxjs/Observable';
 import {  servicesTableData,baseUrl } from '../models/dataInterface';
+import { retry, catchError } from 'rxjs/operators';
 
 @Injectable()
 export class ServiceListService {
@@ -52,11 +53,17 @@ export class ServiceListService {
     pnfDetail: this.baseUrl + "/uui-sotn/getPnfInfo/",
     connectivity: this.baseUrl + "/uui-sotn/getConnectivityInfo/",
     vpnBinding: this.baseUrl + "/uui-sotn/getPinterfaceByVpnId/",
+    getNIList: this.baseUrl + "/uui-lcm/getAllNI/"
   };
 
 
   //The following APIs are optimizable
 
+  //get all unni
+  getAllNI(type) {
+    return this.http.get<any>(this.url.getNIList+type);
+  }
+
   // Get all customers
   getAllCustomers() {
     return this.http.get<any>(this.url.customers);
@@ -89,8 +96,11 @@ export class ServiceListService {
   }
   // Create interface
   createInstance(requestBody, createParams) {
-    return this.http.post<any>(this.url.createService + createParams, requestBody);
+    return this.http.post<any>(this.url.createService + createParams, requestBody).pipe(
+      catchError(this.handleError)
+    );
   }
+
   // NS CreateInstance step one
   nsCreateInstance(requestBody) {
     return this.http.post<any>(this.url.ns_createService, requestBody);
@@ -136,7 +146,7 @@ export class ServiceListService {
         inputs: ""
       };
       return this.http.post<any>(this.url.nstemplateParameters, body);
-    } else if (type == "e2e") {
+    } else if (type == "e2e" || type == "MDONS") {
       let params = new HttpParams({ fromObject: {"toscaModelPath":template.toscaModelURL} });
       let url = this.url.e2etemplateParameters.replace("*_*", template.uuid);
       return this.http.get<any>(url,{params});
@@ -209,5 +219,17 @@ export class ServiceListService {
     return this.http.get<any>(url);
   }
 
-
+  
+  handleError(error) {
+    let errorMessage = '';
+    if (error.error instanceof ErrorEvent) {
+      // client-side error
+      errorMessage = `Error: ${error.error.message}`;
+    } else {
+      // server-side error
+      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
+    }
+    console.log("errorMessage : "+errorMessage);
+    return Observable.throw(error);
+  }
 }
index 752fddd..abbe6d6 100644 (file)
@@ -27,7 +27,7 @@ export class CcvpnCreationComponent implements OnInit {
 
     constructor(private myhttp: ServiceListService) { }
     @Input() createParams;
-    @Input() ccvpn_temParametersContent;
+    @Input() ccvpn_temParametersContent; 
     @Output() closeCreate = new EventEmitter();
 
 
index e093b3b..93a2bd5 100644 (file)
@@ -26,6 +26,7 @@
             <nz-option nzValue="CCVPN" nzLabel="CCVPN"></nz-option>
             <nz-option nzValue="E2E Service" nzLabel="E2E Service"></nz-option>
             <nz-option nzValue="Network Service" nzLabel="Network Service"></nz-option>
+            <nz-option nzValue="MDONS" nzLabel="MDONS"></nz-option>
         </nz-select>
     </div>
     <div class="select-list">
index f7cce45..72817bc 100644 (file)
@@ -6,7 +6,7 @@ import { ServiceListService } from '../../../../core/services/serviceList.servic
   templateUrl: './create-model.component.html',
   styleUrls: ['./create-model.component.less'],
 })
-export class CreateModelComponent implements OnInit {
+export class CreateModelComponent implements OnInit { 
   @Input()isVisible: boolean;
   @Input()customerList;
   @Input()serviceTypeList;
@@ -95,7 +95,7 @@ export class CreateModelComponent implements OnInit {
   }
 
   handleOk(): void {
-    if (this.templateTypeSelected === "SOTN" || this.templateTypeSelected === "CCVPN") {
+    if (this.templateTypeSelected === "SOTN" || this.templateTypeSelected === "CCVPN" || this.templateTypeSelected === "MDONS") {
         this.createData = {
             commonParams: {
               customer: this.currentCustomer,
diff --git a/usecaseui-portal/src/app/views/services/services-list/mdons-creation/mdons-creation.component.css b/usecaseui-portal/src/app/views/services/services-list/mdons-creation/mdons-creation.component.css
new file mode 100644 (file)
index 0000000..934d38d
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+    Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+
+    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.
+*/
+.title {
+    font: 700 18px/18px "思源黑体";
+    color: #4c5e70;
+    margin-bottom: 18px;
+  }
+  hr {
+    border: none;
+    height: 2px;
+    background-color: #dce1e7;
+    margin-bottom: 10px;
+  }
+  .model {
+    background-color: #fff;
+    height: 90%;
+    overflow-y: auto;
+  }
+  .model .back {
+    position: absolute;
+    top: 10px;
+    right: 20px;
+  }
+  .model .creation {
+    position: relative;
+    width: 60%;
+    height: 100%;
+    overflow-y: auto;
+    border-radius: 5px;
+    padding: 20px;
+  }
+  .model .creation .baseparms h3 {
+    color: #3fa8eb;
+    font: 700 16px "Arial";
+  }
+  .model .creation .baseparms h4 {
+    font: 700 16px "Arial";
+  }
+  .model .creation .baseparms ul li {
+    margin: 3px 0;
+  }
+  .model .creation .baseparms ul li span {
+    display: inline-block;
+    width: 40%;
+    font: 700 14px "Arial";
+    vertical-align: middle;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    text-align: right;
+  }
+  .model .creation .baseparms ul li input {
+    width: 165px;
+  }
+  .model .creation .submit {
+    position: absolute;
+    top: 10px;
+    right: 20px;
+  }
+  .model .chart {
+    width: 40%;
+    padding: 10px;
+    height: 100%;
+    border-left: 10px solid #f3f3f3;
+  }
+
+
+  
\ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services-list/mdons-creation/mdons-creation.component.html b/usecaseui-portal/src/app/views/services/services-list/mdons-creation/mdons-creation.component.html
new file mode 100644 (file)
index 0000000..47e22fe
--- /dev/null
@@ -0,0 +1,49 @@
+<div class="model creation-model">
+        <!-- Create data -->
+        <div class="top-title">
+            <h3 class="title fl">{{templateParameters.type}} {{"i18nTextDefine_InstanceCreation" | translate}} </h3>
+            <div class="fl" style="width: 20%">
+                <button class="submit" [disabled]="!mdons_creation_form.valid" nz-button (click)="createService()">
+                    <span> {{"i18nTextDefine_Create" | translate}} </span> 
+                </button>
+                <button class="back" nz-button (click)="goback()"></button>
+            </div>
+        </div>
+<div [formGroup]="mdons_creation_form">
+<div class="e2ecreate-content">
+        <div class="creation fl" style="width:95%">
+            <div *ngIf="mdonsModelShow" class="baseparms clearfix">
+                <div class="vnf-box  form-group" *ngIf="templateParameters.inputs.length>0">
+                        <h3>{{"i18nTextDefine_templateInputs" | translate}}</h3>
+                        <ul >
+                            <li *ngFor="let parameter of templateParameters.inputs; let i = index;">
+                                <span *ngIf="parameter.isRequired.includes('true')" style="color: red;width:10px;min-width:1px;">*</span>
+                                <span title="{{parameter.name}}">{{parameter.name}}:</span>
+                                <input *ngIf="!(parameter.name.includes('uni_id') || parameter.name.includes('enni_id') || parameter.name.includes('date'))" formControlName="{{parameter.name}}" nz-input [(ngModel)]="parameter.value" style="margin-left: auto;">
+                                <!--<pre>{{mdons_creation_form.get(parameter.name).valid}}</pre>-->
+                                <input style="margin-left: 2px;" *ngIf="parameter.name.includes('date')" type="date" formControlName="{{parameter.name}}" nz-input [(ngModel)]="parameter.value" placeholder="yyyy-MM-dd"/>
+                                <span style="color: red;width:10px;" *ngIf="mdons_creation_form.controls[parameter.name].errors?.required && (mdons_creation_form.controls[parameter.name].dirty || mdons_creation_form.controls[parameter.name].touched)">Required</span>
+                                <nz-dropdown class = "customclass" [nzTrigger]="'click'" [nzPlacement]="'bottomLeft'" *ngIf="(parameter.name.includes('uni_id') || parameter.name.includes('enni_id'))">
+                                    <button style="width: 300px;" nz-button nz-dropdown><span *ngIf="parameter.name.includes('uni_id')">{{uniIdSelected.id}}</span><span *ngIf="parameter.name.includes('enni_id')">{{enniIdSelected.id}}</span> <i class="anticon anticon-down"></i>
+                                    </button>
+                                    <ul nz-menu  *ngIf="parameter.name.includes('uni_id')" class="dropDownScroller">
+                                        <li nz-menu-item (click)="chooseUni(item)" *ngFor="let item of uniList" > 
+                                            <a title="{{item.id}}">{{item.id}}</a>
+                                        </li>
+                                    </ul>
+                                    <ul nz-menu *ngIf="parameter.name.includes('enni_id')" class="dropDownScroller" >
+                                        <li nz-menu-item (click)="chooseEnni(item)" *ngFor="let item of enniList" > 
+                                            <a title="{{item.id}}">{{item.id}}</a> 
+                                        </li>
+                                    </ul>
+                                </nz-dropdown>
+                            </li>
+                        </ul>
+                    </div>
+            </div>
+        </div>
+        
+    </div>
+  </div>
+</div>
+
diff --git a/usecaseui-portal/src/app/views/services/services-list/mdons-creation/mdons-creation.component.less b/usecaseui-portal/src/app/views/services/services-list/mdons-creation/mdons-creation.component.less
new file mode 100644 (file)
index 0000000..5084bb9
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+    Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+
+    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.
+*/
+.title {
+    font: 700 18px/18px "思源黑体";
+    color: #4c5e70;
+    margin-bottom: 18px;
+}
+hr {
+    border: none;
+    height: 2px;
+    background-color: #dce1e7;
+    margin-bottom: 10px;
+}
+.dropDownScroller{
+    max-height: 250px;
+    overflow: auto;
+  }
+.astrixRequired{
+    color: red;
+    width:1%;
+    min-width:1px;
+}
+
+.customclass  .anticon-down  { 
+    float: right 
+}
+
+.model {
+    background-color: #F7F8FC;
+    height: 100%;
+    overflow-y: auto;
+    position: relative;
+    .top-title{ 
+        width: 100%;
+        padding: 20px;
+        position: relative;
+        display: inline-block;
+    }
+    .submit{
+        position: absolute;
+        width:84px;
+        height: 35px;
+        top: 10px;
+        right: 85px;
+        color: #fff;
+        font-size: 18px;
+        background:linear-gradient(90deg,rgba(99,194,246,1) 0%,rgba(62,155,255,1) 100%) !important;
+        border-radius:4px;
+        border: none!important;
+        border-color:rgba(0,0,0,0)!important;
+    }
+    .submit:hover{
+        background:linear-gradient(90deg, rgb(103, 207, 246) 0%, rgb(69, 175, 255) 100%) !important;
+        border: none;
+    }
+    .back,.back:hover{
+        position: absolute;
+        top: 10px;
+        right: 20px;
+        display: inline-block;
+        width: 35px;
+        height: 35px;
+        background:url("../../../../../assets/images/Return-icon.png") no-repeat!important;
+        background-size: 100%!important;
+        border-radius:4px;
+        color: #D7D7D7;
+        cursor: pointer;
+    }
+    .back:hover{
+        background: url("../../../../../assets/images/Return-icon-active.png")!important;
+        background-size: 100%!important;
+    }
+    .top-title h3.title {
+        height: 35px;
+        width: 80%;
+        font-size:16px;
+        font-family:ArialMT;
+        color:#3C4F8C;
+        line-height:35px;
+        display: inline-block;
+    }
+    .e2ecreate-content{
+        position: relative;
+        width: 98%;
+        height: 100%;
+        margin-left: 30px;
+        box-shadow:0px 10px 15px 2px rgba(222,222,222,0.5);
+        background: #fff;
+        border-radius:2px;
+    }
+    .creation{
+        position: relative;
+        width: 58%;
+        height: 100%;
+        overflow-y: auto;
+        padding: 20px;
+        background: #fff;
+        .baseparms {
+            h3,h4{
+                color: #06A7E2;
+                width: 96%;
+                height: 40px;
+                line-height: 35px;
+                font-size: 18px;
+                font-weight: 500;
+                margin: 10px auto;
+                border-bottom: 2px solid;
+                border-image: -webkit-linear-gradient(#07A9E1,#30D9C4) 100 100;
+                border-image: -moz-linear-gradient(#07A9E1,#30D9C4) 100 100;
+                border-image: linear-gradient(#07A9E1,#30D9C4) 100 100;
+                border-radius:2px;
+            }
+            h4 {
+                font: 700 16px "Arial";
+                margin-left: 25px;
+            }
+            .vnf-box{
+                clear: both;
+            }
+            ul{
+                margin-left: 30px;
+            }
+            ul li {
+                margin: 10px 0;
+                width: 42%;
+                margin-right: 5%;
+                float: left;
+                text-align: left;
+                span {
+                    display: inline-block;
+                    width: 30%;
+                    min-width: 80px;
+                    font: 700 14px "Arial";
+                    overflow: hidden;
+                    text-align: left;
+                    word-break: break-all;
+                    vertical-align: top;
+                }
+                input,nz-select{
+                    width: 49%;
+                           margin-left:3%
+                }
+            }
+        }
+    }
+    .dividing-line{
+        width: 0;
+        height: 85%;
+        margin: 4% 0;
+        border-left: 1px #cccccc dashed;
+    }
+    .chart {
+        width: 38%;
+        padding: 10px;
+        height: 95%;
+        margin: 0 auto;
+        #createChart{
+            height: 100%;
+            width: 100%;
+        }
+    }
+}
diff --git a/usecaseui-portal/src/app/views/services/services-list/mdons-creation/mdons-creation.component.ts b/usecaseui-portal/src/app/views/services/services-list/mdons-creation/mdons-creation.component.ts
new file mode 100644 (file)
index 0000000..3123bfc
--- /dev/null
@@ -0,0 +1,160 @@
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
+import { ServiceListService } from '../../../../core/services/serviceList.service';
+import { FormGroup, FormBuilder, Validators, FormArray } from '@angular/forms';
+
+import * as d3 from 'd3';
+
+@Component({
+  selector: 'app-mdons-creation',
+  templateUrl: './mdons-creation.component.html',
+  styleUrls: ['./mdons-creation.component.less']
+})
+export class MdonsCreationComponent implements OnInit {
+  mdons_creation_form: FormGroup;
+
+  uniList= [];
+  uniIdSelected = { id: null };
+  enniList= [];
+  enniIdSelected = { id: null };
+  templateParameters = {
+    invariantUUID: "",
+    uuid: "",
+    name: "",
+    type: "",
+    version: "",
+    description: "",
+    category: "",
+    subcategory: "",
+    customizationUuid: "",
+    inputs: [],
+    nestedTemplates: []
+  };
+
+  // mdons requstbody
+  service = {
+    name: "", // <== service instance name
+    description: "",
+    serviceInvariantUuid: "",
+    serviceUuid: "", // uuid ??
+    globalSubscriberId: "",   // "customer.id",
+    serviceType: "",    // "serviceType.value",
+    parameters: {
+      locationConstraints: [
+
+      ],
+      resources: [],
+      requestInputs: {
+            name:"",
+            customer:"",
+            service_provider:"",
+            due_date:"",
+            end_date:"",
+            uni_id:"",
+            enni_id:""
+      }
+    }
+  }
+
+  mdonsModelShow : boolean = false;
+  constructor(private myhttp: ServiceListService,private fb: FormBuilder) {
+
+    
+   }
+  @Input() createParams;
+  @Input() mdons_temParametersContent;
+  @Output() mdonsCloseCreate = new EventEmitter();
+
+  ngOnInit() {
+    this.getalluni();
+    this.getallenni();
+    this.templateParameters=this.mdons_temParametersContent;
+    this.mdonsModelShow = true;
+    this.mdons_creation_form = this.fb.group({});
+    this.buildFormArrayOfGroupsFromArr();
+    console.log("Controls "+this.mdons_creation_form.controls['terms'])
+  }
+
+  buildFormArrayOfGroupsFromArr() {
+    for(let i of this.templateParameters.inputs){
+      if(i.isRequired === "true" && !(i.name.includes('uni_id') || i.name.includes('enni_id'))){
+      this.mdons_creation_form.addControl(i.name, this.fb.control('', [Validators.required]))
+      } else {
+        this.mdons_creation_form.addControl(i.name, this.fb.control('')) 
+      }
+    }
+  }
+
+  getalluni() {
+    this.myhttp.getAllNI("UNI")
+        .subscribe((data) => {
+            this.uniList = data.map(item => ({id: item }) );
+            if(data.length !== 0){
+                this.uniIdSelected = this.uniList[0];
+            }
+        })
+}
+
+getallenni() {
+  this.myhttp.getAllNI("NNI")
+      .subscribe((data) => {
+          this.enniList = data.map(item => ({id: item }) );
+          if(data.length !== 0){
+              this.enniIdSelected = this.enniList[0];
+          }
+      })
+}
+
+chooseUni(item = this.uniIdSelected){
+  if(this.uniIdSelected !== item) this.uniIdSelected = item;
+}
+
+chooseEnni(item = this.enniIdSelected){
+  if(this.enniIdSelected !== item) this.enniIdSelected = item;
+}
+
+  goback() {
+    this.mdonsCloseCreate.emit();
+  }
+
+
+
+  createService() {
+    if (this.mdons_creation_form.invalid) {
+      return;
+    } else {
+    this.service.serviceInvariantUuid = this.templateParameters.invariantUUID;
+    this.service.name = this.templateParameters.name;
+    this.service.description = this.templateParameters.description;
+      this.service.serviceUuid = this.templateParameters.uuid;
+      this.service.globalSubscriberId = this.createParams.commonParams.customer.id;
+      this.service.serviceType = this.createParams.commonParams.serviceType.name;
+
+      this.templateParameters.inputs.forEach((ipnut) => {
+        this.service.parameters.requestInputs[ipnut.name] = ipnut.value == undefined ? ipnut.defaultValue : ipnut.value;
+        if(ipnut.name.includes('uni_id')) {
+          this.service.parameters.requestInputs[ipnut.name] = this.uniIdSelected.id == undefined ? ipnut.defaultValue : this.uniIdSelected.id;
+        }
+        if(ipnut.name.includes('enni_id')) {
+          this.service.parameters.requestInputs[ipnut.name] = this.enniIdSelected.id == undefined ? ipnut.defaultValue : this.enniIdSelected.id;
+        }
+        if(ipnut.name==='name') {
+          this.service.name = ipnut.value == undefined ? ipnut.defaultValue : ipnut.value;
+        } 
+      })
+
+      console.log(this.service)
+      this.mdonsCloseCreate.emit({ service: this.service });
+    }
+  }
+
+  markFormTouched(group: FormGroup | FormArray) {
+    Object.keys(group.controls).forEach((key: string) => {
+      const control = group.controls[key];
+      if (control instanceof FormGroup || control instanceof FormArray) { control.markAsTouched(); this.markFormTouched(control); }
+      else { control.markAsTouched(); };
+    });
+  };
+
+
+
+}
\ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services-list/mdons-detail/mdons-detail.component.html b/usecaseui-portal/src/app/views/services/services-list/mdons-detail/mdons-detail.component.html
new file mode 100644 (file)
index 0000000..dd62298
--- /dev/null
@@ -0,0 +1,44 @@
+<div class="model creation-model">
+
+    <div class="top-title">
+      <h3 class="title fl">{{serviceInstanceName}} Instance Detail</h3>
+      <div class="fl" style="width: 20%">
+        <button class="back" nz-button (click)="goback()"></button>
+      </div>
+    </div>
+    <div class="detaildata fl">
+      <div class="baseparms clearfix">
+        <div class="vnf-box">
+          <h3> {{"i18nTextDefine_Base" | translate}} </h3>
+          <ul class="clearfix">
+            <li>
+              <span style="width:15%">Name:</span>
+              <span class="input-content">{{service.name}}</span>
+            </li>
+            <li>
+              <span style="width:25%">Description:</span>
+              <span class="input-content">{{service.description}}</span>
+            </li>
+          </ul>
+        </div>
+        <div class="vnf-box" *ngIf="getKeys(e2e_requestInputs).length>0">
+            <h3>{{"i18nTextDefine_templateInputs" | translate}}</h3>
+            <ul class="clearfix">
+              <li *ngFor="let key of getKeys(e2e_requestInputs);">
+                <span title="{{key}}">{{key}}:</span>
+                <span class="input-content">{{e2e_requestInputs[key]}}</span>
+              </li>
+            </ul>
+          </div>
+    </div>
+</div>
+
+<!-- chart -->
+<div class="chart fr">
+  <div id="createChart">
+    <svg width="100%" height="100%">
+    </svg>
+  </div>
+</div>
+
+</div>
\ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services-list/mdons-detail/mdons-detail.component.less b/usecaseui-portal/src/app/views/services/services-list/mdons-detail/mdons-detail.component.less
new file mode 100644 (file)
index 0000000..9a0f192
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+    Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+
+    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.
+*/
+.title {
+    font: 700 18px/18px "思源黑体";
+    color: #4c5e70;
+    margin-bottom: 18px;
+  }
+  hr {
+    border: none;
+    height: 2px;
+    background-color: #dce1e7;
+    margin-bottom: 10px;
+  }
+  .creation-model{
+    position: relative;
+  }
+  .model {
+    background-color: #F7F8FC;
+    height: 100%;
+    overflow-y: auto;
+    position: relative;
+    .top-title{ 
+      width: 100%;
+      padding: 20px;
+      position: relative;
+      display: inline-block;
+    }
+    .back,.back:hover{
+      position: absolute;
+      top: 10px;
+      right: 20px;
+      display: inline-block;
+      width: 35px;
+      height: 35px;
+      background:url("../../../../../assets/images/Return-icon.png") no-repeat!important;
+      background-size: 100%!important;
+      border-radius:4px;
+      color: #D7D7D7;
+      cursor: pointer;
+    }
+    .back:hover{
+      background: url("../../../../../assets/images/Return-icon-active.png")!important;
+      background-size: 100%!important;
+    }
+    .top-title h3.title {
+      height: 35px;
+      width: 80%;
+      font-size:16px;
+      font-family:ArialMT;
+      color:#3C4F8C;
+      line-height:35px;
+      display: inline-block;
+    }
+    .detaildata{
+      position: relative;
+      width: 58%;
+      height: 100%;
+      overflow-y: auto;
+      border-radius: 5px;
+      padding: 20px;
+      background: #fff;
+      margin-left: 30px;
+      box-shadow:0px 10px 15px 2px rgba(222,222,222,0.5);
+      .baseparms {
+        h3,h4{
+          color: #06A7E2;
+          width: 96%;
+          height: 40px;
+          line-height: 35px;
+          font-size: 18px;
+          font-weight: 500;
+          margin: 10px auto;
+          border-bottom: 2px solid;
+          border-image: -webkit-linear-gradient(#07A9E1,#30D9C4) 100 100;
+          border-image: -moz-linear-gradient(#07A9E1,#30D9C4) 100 100;
+          border-image: linear-gradient(#07A9E1,#30D9C4) 100 100;
+          border-radius:2px;
+        }
+        h4 {
+          font: 700 16px "Arial";
+          margin-left: 25px;
+        }
+        .vnf-box{
+          clear: both;
+        }
+        ul{
+          margin-left: 30px;
+        }
+        ul li {
+          margin: 10px 0;
+          width: 49%;
+          float: left;
+          text-align: left;
+          color:rgba(60,79,140,1);
+          font-size: 14px;
+          span {
+            display: inline-block;
+            width: 50%;
+            font: 700 14px "Arial";
+            vertical-align: top;
+            overflow: hidden;
+            text-align: left;
+            color:rgba(60,79,140,0.5);
+            word-break: break-all;
+          }
+          span.input-content{
+            width: 42%;
+            color: #3C4F8C;
+            margin-left: 5%;
+            word-break: break-all;
+            vertical-align: top;
+          }
+        }
+      }
+    }
+    .chart {
+      width: 35%;
+      padding: 10px;
+      height: 95%;
+      box-shadow: 0px 10px 35px 10px rgba(222, 222, 222, 0.5);
+      margin-right: 1%;
+      background:linear-gradient(180deg,rgba(183, 230, 247, 1) 0%,rgba(214, 240, 254, 1) 100%);
+      border-radius: 4px;
+      #createChart{
+        height: 100%;
+        width: 100%;
+      }
+    }
+  }
+  
\ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services-list/mdons-detail/mdons-detail.component.ts b/usecaseui-portal/src/app/views/services/services-list/mdons-detail/mdons-detail.component.ts
new file mode 100644 (file)
index 0000000..ee4c71d
--- /dev/null
@@ -0,0 +1,50 @@
+import { Component, Input, Output, OnInit, EventEmitter } from '@angular/core';
+import { ServiceListService } from '../../../../core/services/serviceList.service';
+
+@Component({
+  selector: 'app-mdons-detail',
+  templateUrl: './mdons-detail.component.html',
+  styleUrls: ['./mdons-detail.component.less']
+})
+export class MdonsDetailComponent implements OnInit {
+
+  constructor(private myhttp: ServiceListService) { }
+
+  @Input() detailParams;
+  @Output() closeDetail = new EventEmitter();
+  serviceInstanceName: any;
+  serviceType: any;
+  input_parameters: any;
+  e2e_requestInputs: any;
+
+  service = {
+    name: "",
+    description: "",
+  };
+
+  getKeys(item) {
+    return Object.keys(item);
+  }
+
+  ngOnInit() {
+
+    console.log(this.detailParams);
+    this.serviceInstanceName = this.detailParams['serviceDomain'] || this.detailParams["nsName"];
+    this.input_parameters = JSON.parse(this.detailParams['input-parameters']);
+      console.log(this.input_parameters);
+    this.service = {
+      name: this.input_parameters.service.name,
+        description: this.input_parameters.service.description,
+    };   
+    if (this.input_parameters.service.parameters.requestInputs != undefined && Object.keys(this.input_parameters.service.parameters.requestInputs).length > 0) {
+      this.e2e_requestInputs = this.input_parameters.service.parameters.requestInputs;
+    }
+  }
+
+  goback() {
+    this.closeDetail.emit();
+  }
+
+  
+
+}
\ No newline at end of file
index 1092b33..b444274 100644 (file)
@@ -24,7 +24,7 @@
         <button nz-button nz-dropdown><span>{{customerSelected.name}}</span> <i class="anticon anticon-down"></i>
         </button>
         <ul nz-menu>
-            <li nz-menu-item (click)="choseCustomer(item)" *ngFor="let item of customerList">
+            <li nz-menu-item (click)="choseCustomer(item)" *ngFor="let item of customerList"> 
                 <a title="{{item.name}}">{{item.name}}</a>
             </li>
         </ul>
                     'updating':data.statusClass==='Updating','deleting':data.statusClass==='1002','creating':data.statusClass==='1001',
                     'scaling':data.statusClass==='1003','healing':data.statusClass==='1004'}"
                                 *ngIf="data.tips !== 'Available' && data.tips !== 'Unavailable'">{{data.tips}}</span>
-                            <span *ngIf="data.tips === 'Available' " class="marginLeft10">
+                            <span *ngIf="data.tips === 'Available' " class="marginLeft10" title = "{{data.serviceStatusInfo}}">
                                 <img src="assets/images/wancheng-icon.png" alt="Available">
                             </span>
-                            <span *ngIf="data.tips === 'Unavailable' " class="marginLeft10">
+                            <span *ngIf="data.tips === 'Unavailable' " class="marginLeft10" title = "{{data.serviceStatusInfo}}">
                                 <img src="assets/images/shibai-icon.png" alt="Unavailable">
                             </span>
-                            <nz-progress *ngIf="data.status === 'In Progress'" [nzPercent]="data.rate"
+                            <nz-progress *ngIf="data.status === 'In Progress'" [nzPercent]="data.rate" title = "{{data.serviceStatusInfo}}"
                                 [nzShowInfo]="false" nzStatus="active"></nz-progress>
                         </td>
                         <td>
                         <img src="assets/images/execute-inproess.png" alt="instance temination is starting">
                     </span>
                     <div class="ant-notification-notice-message"
-                        *ngIf="createData['commonParams']['templateType'] === 'CCVPN' || thisService['serviceDomain'] === 'SOTN'">
-                        {{ createData['commonParams']['templateType'] }} &nbsp; {{"i18nTextDefine_InstanceCreationStarting" |
+                        *ngIf="thisCreateService['serviceDomain'] === 'CCVPN' || thisService['serviceDomain'] === 'SOTN' || thisService['serviceDomain'] === 'MDONS'">
+                        {{ thisService['serviceDomain'] }} &nbsp; {{"i18nTextDefine_InstanceCreationStarting" |
                         translate}}
                     </div>
                     <div class="ant-notification-notice-message"
                             *ngIf="thisCreateService.status == 'Failed'">
                     </span>
                     <div class="ant-notification-notice-message"
-                        *ngIf="(createData['commonParams']['templateType'] == 'CCVPN' || thisCreateService['serviceDomain'] == 'SOTN') && thisCreateService.status == 'Successful'">
-                        {{ createData['commonParams']['templateType'] }} &nbsp; {{"i18nTextDefine_InstanceCreatedSuccessfully" |
+                        *ngIf="(thisCreateService['serviceDomain'] == 'CCVPN' || thisCreateService['serviceDomain'] == 'SOTN' || thisCreateService['serviceDomain'] == 'MDONS') && thisCreateService.status == 'Successful'">
+                        {{ thisCreateService['serviceDomain'] }} &nbsp; {{"i18nTextDefine_InstanceCreatedSuccessfully" |
                         translate}}
                     </div>
                     <div class="ant-notification-notice-message"
                         NS &nbsp; {{"i18nTextDefine_InstanceCreatedSuccessfully" | translate}}
                     </div>
                     <div class="ant-notification-notice-message"
-                        *ngIf="(createData['commonParams']['templateType'] == 'CCVPN' || thisCreateService['serviceDomain'] == 'SOTN') && thisCreateService.status == 'Failed'">
-                        {{ createData['commonParams']['templateType'] }} &nbsp; {{"i18nTextDefine_InstanceCreationFailed" |
+                        *ngIf="(thisCreateService['serviceDomain'] == 'CCVPN' || thisCreateService['serviceDomain'] == 'SOTN' || thisCreateService['serviceDomain'] == 'MDONS') && thisCreateService.status == 'Failed'">
+                        {{ thisCreateService['serviceDomain'] }} &nbsp; {{"i18nTextDefine_InstanceCreationFailed" |
                         translate}}
                     </div>
                     <div class="ant-notification-notice-message"
                             *ngIf="thisService.status == 'Failed'">
                     </span>
                     <div class="ant-notification-notice-message"
-                        *ngIf="(thisService['serviceDomain'] == 'CCVPN' || thisService['serviceDomain'] == 'SOTN') && thisService.status == 'Successful'">
+                        *ngIf="(thisService['serviceDomain'] == 'CCVPN' || thisService['serviceDomain'] == 'SOTN' || thisCreateService['serviceDomain'] == 'MDONS') && thisService.status == 'Successful'">
                         {{ thisService['serviceDomain'] }} &nbsp; {{"i18nTextDefine_InstanceTeminatedSuccessfully" |
                         translate}}
                     </div>
                     </div>
                     
                     <div class="ant-notification-notice-message"
-                        *ngIf="(thisService['serviceDomain'] == 'CCVPN' || thisService['serviceDomain'] == 'SOTN') && thisService.status == 'Failed'">
+                        *ngIf="(thisService['serviceDomain'] == 'CCVPN' || thisService['serviceDomain'] == 'SOTN' || thisCreateService['serviceDomain'] == 'MDONS') && thisService.status == 'Failed'">
                         {{ thisService['serviceDomain'] }} &nbsp; {{"i18nTextDefine_InstanceTeminationFailed" |
                         translate}}
                     </div>
         <app-e2e-detail [detailParams]="detailData" (closeDetail)="detailshow2 = false;listDisplay = false;">
         </app-e2e-detail> 
     </div>
+    <div class="detailComponent" *ngIf="detailshow2">
+        <app-mdons-detail [detailParams]="detailData" (closeDetail)="detailshow2 = false;listDisplay = false;">
+        </app-mdons-detail> 
+    </div>
     <div class="createComponent" *ngIf="createshow">
         <app-ccvpn-creation [createParams]="createData" [ccvpn_temParametersContent]="ccvpn_temParametersContent"
             (closeCreate)="closeCreate($event,templateCreatestarting,templateCreateSuccessFaild)">
             (e2eCloseCreate)="e2eCloseCreate($event,templateCreatestarting,templateCreateSuccessFaild)">
         </app-e2e-creation>
     </div>
+    <div class="createComponent" *ngIf="showCreateMDONS">
+        <app-mdons-creation [createParams]="createData" [mdons_temParametersContent]="mdons_temParametersContent"
+        (mdonsCloseCreate)="mdonsCloseCreate($event,templateCreatestarting,templateCreateSuccessFaild)">
+        </app-mdons-creation>
+    </div>
     <!--</div>-->
 </nz-layout>
 <div class="loading" *ngIf="loadingAnimateShow">
     <img src="assets/images/loading-animate2.gif" alt="loading">
     <p>Please wating……</p>
-</div>
\ No newline at end of file
+</div>
index 6ee5c27..adac12d 100644 (file)
@@ -61,7 +61,7 @@ export class ServicesListComponent implements OnInit {
     language = sessionStorage.getItem("DefaultLang");
     iconMore = false;
     loadingAnimateShow = false;
-    serviceNunber = [ // top: E2E/NS/CCVPN data
+    serviceNunber = [ // top: E2E/NS/CCVPN/MDONS data
         {
             "serviceDomain": "E2E",
             "Success": 0,
@@ -82,6 +82,13 @@ export class ServicesListComponent implements OnInit {
             "failed": 0,
             "InProgress": 0,
             "detailName": "i18nTextDefine_Cross_Domain_and_Cross_Layer_VPN"
+        },
+        {
+            "serviceDomain": "MDONS",
+            "Success": 0,
+            "failed": 0,
+            "InProgress": 0,
+            "detailName": "i18nTextDefine_MDONS"
         }
     ];
 
@@ -157,10 +164,12 @@ export class ServicesListComponent implements OnInit {
 
     createshow: boolean = false;
     createshow2: boolean = false;
+    showCreateMDONS: boolean = false;
     listDisplay: boolean = false;
     createData: Object = {};
     ccvpn_temParametersContent: any;
     e2e_ns_temParametersContent: any;
+    mdons_temParametersContent: any;
 
     createdModalShow(obj: any): void{
         this.createData = obj.createData;
@@ -171,6 +180,9 @@ export class ServicesListComponent implements OnInit {
         } else if (obj.templateType === "E2E Service" || obj.templateType === "Network Service") {
             this.e2e_ns_temParametersContent = obj.data;
             this.createshow2 = true;
+        } else if(obj.templateType === "MDONS"){
+            this.mdons_temParametersContent = obj.data;
+            this.showCreateMDONS = true;
         }
            this.listDisplay = true;
     }
@@ -231,6 +243,7 @@ export class ServicesListComponent implements OnInit {
                     }
 
                     //
+                    item["serviceStatusInfo"] = item["orchestration-status"]
                     if (item["operationResult"] === "2001") { 
                         item["status"] = "Available";
                         item["tips"] = "Available";
@@ -338,6 +351,15 @@ export class ServicesListComponent implements OnInit {
                             this.serviceNunber[2]["InProgress"] += 1;
                         }
                     }
+                    else if (item.serviceDomain === 'MDONS') {
+                        if (item.operationResult === "2001") {
+                            this.serviceNunber[3]["Success"] += 1;
+                        } else if (item.operationResult === "2002") {
+                            this.serviceNunber[3]["failed"] += 1;
+                        } else if (item.operationResult === "2003") {
+                            this.serviceNunber[3]["InProgress"] += 1;
+                        }
+                    }
                 })
                 console.log(this.tableData)
                 this.loading = false;
@@ -436,6 +458,7 @@ export class ServicesListComponent implements OnInit {
     // show detail
     detailshow = false;
     detailshow2 = false;
+    detailshowMDONS = false;
     upDateShow = false;
     detailData: Object;
 
@@ -459,7 +482,7 @@ export class ServicesListComponent implements OnInit {
             } else {
                 this.upDateShow = true;
             }
-        } else if (service["serviceDomain"] === 'E2E Service' || service["serviceDomain"] === 'Network Service') {
+        } else if (service["serviceDomain"] === 'E2E Service' || service["serviceDomain"] === 'Network Service' || service["serviceDomain"] === 'MDONS') {
             this.detailshow2 = true;
         }
         this.listDisplay = true;
@@ -569,6 +592,91 @@ export class ServicesListComponent implements OnInit {
         })
     }
 
+    mdonsCloseCreate(obj, templateCreatestarting, templateCreateSuccessFaild) {
+        if (!obj) {
+            this.showCreateMDONS = false; //
+            this.listDisplay = false; //
+            return false;
+        }
+        this.showCreateMDONS = false; //
+        this.listDisplay = false; //
+        this.loadingAnimateShow = true;
+        console.log(obj);
+        let newData; //
+        let createParams = "?customerId=" + this.customerSelected.id +
+            "&serviceType=" + obj.service.serviceType +
+            "&serviceDomain=" + "MDONS" +
+            "&parentServiceInstanceId=" +
+            "&uuid=" + obj.service.serviceUuid +
+            "&invariantUuuid=" + obj.service.serviceInvariantUuid;
+        this.createService(obj, createParams, templateCreatestarting, templateCreateSuccessFaild).then((data) => {
+            console.log("mdons: "+data);
+            this.loadingAnimateShow = false;
+            
+            newData = {  //
+                'service-instance-id': data["serviceId"],
+                'service-instance-name': obj.service.name,
+                serviceDomain: "MDONS",
+                childServiceInstances: [],
+                status: "In Progress",
+                statusClass: 1001,
+                rate: 0,
+                tips: ""
+            }
+  
+            
+            if (data == "FAILED") {
+                console.log("create ns service Failed :" + JSON.stringify(data));
+                newData.status = "Failed";
+                newData.tips = "Unavailable";
+                this.thisCreateService = newData;
+                this.tableData = [newData, ...this.tableData];
+                this.createNotification(templateCreateSuccessFaild);
+                return false;
+            }
+
+            this.thisCreateService = newData;
+            this.tableData = [newData, ...this.tableData];
+            this.createNotification(templateCreatestarting);
+            let updata = (prodata) => {
+                newData.rate = prodata.progress;
+                newData.tips = this.listSortMasters["operationTypes"].find((its) => {
+                    return its["sortCode"] == newData["statusClass"] && its["language"] == this.language
+                })["sortValue"] + newData.rate + "%";
+                if (newData["rate"] > 100) {
+                    newData["status"] = prodata.status;
+                    newData.tips = this.listSortMasters["operationTypes"].find((its) => {
+                        return its["sortCode"] == newData["statusClass"] && its["language"] == this.language
+                    })["sortValue"] + '\xa0\xa0\xa0' + newData["status"];
+                }
+            }
+            let queryParams = { serviceId: data["serviceId"], operationId: data["operationId"], operationType: "1001" };
+            return this.queryProgress(queryParams, updata);
+        }).then((data) => {
+            console.log(data);
+            if(data == false){
+                return false;
+            }
+            newData.rate = 100;
+            newData.status = "Successful";
+            this.createSuccessNotification(templateCreateSuccessFaild);
+            newData.tips = this.listSortMasters["operationTypes"].find((its) => {
+                return its["sortCode"] == newData["statusClass"] && its["language"] == this.language
+            })["sortValue"] + '\xa0\xa0\xa0' + this.listSortMasters["operationResults"].find((its) => {
+                return its["sortCode"] == 2001 && its["language"] == this.language
+            })["sortValue"];
+            let hasUndone = this.tableData.some((item) => {
+                return item.rate < 100;
+            })
+            if (!hasUndone) {
+                setTimeout(() => {
+                    this.getTableData();
+                }, 1000)
+            }
+        })
+
+    }
+
     e2eCloseCreate(obj, templateCreatestarting, templateCreateSuccessFaild) {
         if (!obj) {
             this.createshow2 = false; //
@@ -736,6 +844,7 @@ export class ServicesListComponent implements OnInit {
         let mypromise = new Promise((res, rej) => {
             this.myhttp.createInstance(requestBody, createParams)
                 .subscribe((data) => {
+                    console.log(data);
                     if (data.status == "FAILED") {
                         this.loadingAnimateShow = false;
                         res("Failed");
@@ -743,6 +852,12 @@ export class ServicesListComponent implements OnInit {
                         return false;
                     }
                     res(data.service);
+                },
+                (error) => {
+                    console.log('HTTP error '+error.message)
+                    this.loadingAnimateShow = false;
+            res("FAILED");
+            return false;
                 })
         })
         return mypromise;
index dcc1c92..9691bc6 100644 (file)
   "i18nTextDefine_PartnerNetwork": "Partner Network",
   "i18nTextDefine_HostUrl": "Host Url",
   "i18nTextDefine_DeleteLink": "Delete Link"
-}
\ No newline at end of file
+}