diff options
Diffstat (limited to 'usecaseui-portal/src/app/views')
56 files changed, 3827 insertions, 1866 deletions
diff --git a/usecaseui-portal/src/app/views/alarm/alarm.component.spec.ts b/usecaseui-portal/src/app/views/alarm/alarm.component.spec.ts index 9f01597e..8276e423 100644 --- a/usecaseui-portal/src/app/views/alarm/alarm.component.spec.ts +++ b/usecaseui-portal/src/app/views/alarm/alarm.component.spec.ts @@ -60,7 +60,7 @@ fdescribe('AlarmComponent', () => { const req = httpMock.expectOne('http://.../data/contacts'); expect(req.request.method).toEqual('GET'); // Then we set the fake data to be returned by the mock - req.flush({ data: ...}); + req.flush({ data: {pageInfo: {totalRecordCount: 21, pageNumber: 0}, data: []}}); }) ); }); diff --git a/usecaseui-portal/src/app/views/ccvpn-network/ccvpn-network.component.html b/usecaseui-portal/src/app/views/ccvpn-network/ccvpn-network.component.html index 25687f67..fb025d96 100644 --- a/usecaseui-portal/src/app/views/ccvpn-network/ccvpn-network.component.html +++ b/usecaseui-portal/src/app/views/ccvpn-network/ccvpn-network.component.html @@ -145,7 +145,7 @@ </li> </ul> <button nz-button nzType="primary" nzSize="small" class="del-button" style="width: 90px;" (click)="delLink()" *ngIf="!delcloud"> {{"i18nTextDefine_DeleteLink" | translate}} </button> - <button nz-button nzType="primary" nzSize="small" class="del-button" style="width: 90px;" (click)="delCloudLink()" *ngIf="delcloud"> {{"i18nTextDefine_deleteLink" | translate}} </button> + <button nz-button nzType="primary" nzSize="small" class="del-button" style="width: 90px;" (click)="delCloudLink()" *ngIf="delcloud"> {{"i18nTextDefine_DeleteLink" | translate}} </button> <button nz-button nzType="default" nzSize="small" class="del-button" style="width: 60px;" (click)="hideForm()"> {{"i18nTextDefine_Cancel" | translate}} </button> </div> </div> diff --git a/usecaseui-portal/src/app/views/ccvpn-network/ccvpn-network.component.ts b/usecaseui-portal/src/app/views/ccvpn-network/ccvpn-network.component.ts index d02149d0..a2f9561c 100644 --- a/usecaseui-portal/src/app/views/ccvpn-network/ccvpn-network.component.ts +++ b/usecaseui-portal/src/app/views/ccvpn-network/ccvpn-network.component.ts @@ -688,7 +688,7 @@ export class CcvpnNetworkComponent implements OnInit { let params = { pnfName: this.selectedNode1, }; - this.myhttp.getPInterfacesData1(params) + this.myhttp.getPInterfacesData(params) .subscribe((data) => { this.tpOption1 = []; for (let i = 0; i < data.length; i++) { @@ -716,7 +716,7 @@ export class CcvpnNetworkComponent implements OnInit { let params = { pnfName: this.selectedNode2, }; - this.myhttp.getPInterfacesData2(params) + this.myhttp.getPInterfacesData(params) .subscribe((data) => { this.tpOption2 = []; for (let i = 0; i < data.length; i++) { diff --git a/usecaseui-portal/src/app/views/home/home.component.html b/usecaseui-portal/src/app/views/home/home.component.html index 0946b587..faa5dcd4 100644 --- a/usecaseui-portal/src/app/views/home/home.component.html +++ b/usecaseui-portal/src/app/views/home/home.component.html @@ -17,9 +17,9 @@ <div class="content"> <!-- left-content --> <div class="left-content"> - <div class="services"> + <div class="services" #services> <h4>{{"i18nTextDefine_SERVICES" | translate}}</h4> - <app-pie [initData]="serviceChartInit" [chartData]="serviceChartData"></app-pie> + <app-pie [initData]="serviceChartInit" [chartData]="serviceChartData" #seriverChart></app-pie> <div> <h5><span>{{"i18nTextDefine_Total" | translate}}:</span> {{serviceNumber}} <span>{{"i18nTextDefine_cutomers_and" | translate}}</span> {{serviceNumber}} @@ -34,7 +34,7 @@ <div class="details"> <li class="detailstoplinContent"> <div class="detailstoplin"> - <div><span></span> NS</div> + <div>NS</div> <div> <app-bar [initData]="serviceBarChartInit" [chartData]="servicesBarChartData"></app-bar> </div> @@ -43,7 +43,7 @@ </li> <li class="detailstoplinContent"> <div class="detailstoplin"> - <div><span style="background-color:#BCECB8;"></span> VNF</div> + <div>VNF</div> <div> <app-bar [initData]="serviceBarChartInit" [chartData]="servicesBarChartData1"></app-bar> </div> @@ -52,7 +52,7 @@ </li> <li class="detailstoplinContent"> <div class="detailstoplin"> - <div><span style="background-color:#ACCAF4;"></span> PNF</div> + <div>PNF</div> <div> <app-bar [initData]="serviceBarChartInit" [chartData]="servicesBarChartData2"></app-bar> </div> diff --git a/usecaseui-portal/src/app/views/home/home.component.less b/usecaseui-portal/src/app/views/home/home.component.less index dc736f18..cb0d877e 100644 --- a/usecaseui-portal/src/app/views/home/home.component.less +++ b/usecaseui-portal/src/app/views/home/home.component.less @@ -15,12 +15,17 @@ */ .content { - padding: 20px 20px; - overflow: hidden; + padding: 20px; + min-height: 937px; + height: 100vh; .left-content{ + height: 100%; float: left; width:30%; .services,.PACKAGE{ + display:flex; + flex-direction: column; + justify-content: space-between; width: 100%; background:rgba(255,255,255,1); box-shadow:0px 10px 10px 2px rgba(222,222,222,0.5); @@ -34,27 +39,27 @@ font: 400 14px/14px "Arial"; } .tip { - float: right; + align-self: flex-end; width: 110px; line-height: 35px; border-radius: 5px; background-color: #eceff4; font-size: 16px; color: #3C4F8C; - margin-top: 20px; - margin-bottom: 0; text-align: center; + cursor: pointer; span{ color: #3C4F8C; } } } .services{ - height:466px; - h4{ - margin-bottom: 20px; - } + min-height:467px; + height: 49vh; + flex-wrap: wrap; h5 { + position: relative; + z-index: 3; font: 500 18px/18px "ArialMT"; color:#0DA9E2; margin: -2em 0 1em 0 ; @@ -78,23 +83,20 @@ } } .PACKAGE{ - height:422px; + min-height:410px; + height: 43vh; margin-top: 20px; - h4{ - margin-bottom: 50px; - } .details { .detailstoplinContent{ border-bottom:0.5px solid rgba(237,237,237,1); border-radius:4px; - line-height: 45px; + line-height: 58px; font-size: 14px; color: #3C4F8C; font-family:"ArialMT"; .detailstoplin { width: 100%; - height: 50px; - border-top: 0.5px solid #ededed; + height: 58px; border-radius: 4px; div:first-child{ width: 20%; @@ -112,18 +114,22 @@ color:rgba(60,79,140,0.5); } } - } + &:first-child{ + border-top: 0.5px solid rgba(237,237,237,1); + } + } } } } .right-content { + height: 100%; float: left; width: 70%; - height: 96vh; padding-left: 15px; .rt-content { - height: 40%; + min-height: 327px; + height: 34vh; margin-bottom: 18px; background:rgba(255,255,255,1); box-shadow:0px 10px 10px 2px rgba(222,222,222,0.5); @@ -201,7 +207,8 @@ } .rb-content { position: relative; - height: 58%; + min-height: 550px; + height: 58vh; background-color: #fff; padding: 24px 30px; box-shadow:0px 10px 15px 2px rgba(222,222,222,0.5); diff --git a/usecaseui-portal/src/app/views/home/home.component.ts b/usecaseui-portal/src/app/views/home/home.component.ts index 153e2219..a7f312e6 100644 --- a/usecaseui-portal/src/app/views/home/home.component.ts +++ b/usecaseui-portal/src/app/views/home/home.component.ts @@ -13,12 +13,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Component, OnInit, Input, Output, EventEmitter, HostBinding } from '@angular/core'; +import { Component, OnInit, HostBinding, ViewChild, ElementRef } from '@angular/core'; import { HomesService } from '../../core/services/homes.service'; import { slideToRight } from '../../shared/utils/animates'; import { Util } from '../../shared/utils/utils'; import { TranslateService } from "@ngx-translate/core"; import { Router } from '@angular/router'; +import { Observable } from 'rxjs' @Component({ selector: 'app-home', @@ -28,12 +29,16 @@ import { Router } from '@angular/router'; }) export class HomeComponent implements OnInit { @HostBinding('@routerAnimate') routerAnimateState; + @ViewChild('seriverChart') seriverChart; + @ViewChild('services') services: ElementRef; + resizeMark constructor( - private myhttp: HomesService, - private router: Router, - private Util: Util - ) { } + private myhttp: HomesService, + private router: Router, + private Util: Util + ) { + } ngOnInit() { this.getListSortMasters(); @@ -44,16 +49,27 @@ export class HomeComponent implements OnInit { this.getHomeServiceBarNsData(); this.getHomeServiceBarVnfData(); this.getHomeServiceBarPnfData(); + this.resizeMark = Observable.fromEvent(window,'resize') + .subscribe((event) => { + this.seriverChart.resize(this.services.nativeElement.offsetHeight,250) + }) + } + + ngAfterViewInit(){ + this.seriverChart.resize(this.services.nativeElement.offsetHeight,250) } + ngOnDestroy(){ + this.resizeMark.unsubscribe() + } // services serviceNumber: number = 0; serviceChartData: Object; serviceChartInit: Object = { - backgroundColor: '#fff', - height: 200, + height: 280, option: { + backgroundColor: '#fff', legend: { orient: 'vertical', left: '0px', @@ -100,17 +116,11 @@ export class HomeComponent implements OnInit { } }; // gethomeServiceData - serviceChart = true; getHomeServiceData() { this.myhttp.getHomeServiceData() .subscribe( (data) => { this.serviceNumber = data.serviceTotalNum; - if (this.serviceNumber > 0) { - this.serviceChart = true; - } else { - this.serviceChart = false; - } this.serviceChartData = { series: [{ data: data.customerServiceList }] }; @@ -165,7 +175,7 @@ export class HomeComponent implements OnInit { show: false, }, emphasis: { - show: true, + show: false, formatter: '{b}\n{c},{d}%', color: "#3C4F8C" } @@ -230,7 +240,7 @@ export class HomeComponent implements OnInit { show: false, }, emphasis: { - show: true, + show: false, formatter: '{b}\n{c},{d}%', color: "#3C4F8C" } @@ -301,7 +311,7 @@ export class HomeComponent implements OnInit { servicesBarChartData1: Object; servicesBarChartData2: Object; serviceBarChartInit: Object = { - height: 40, + height: 58, width: 160, option: { tooltip: { diff --git a/usecaseui-portal/src/app/views/management/customer/customer.component.html b/usecaseui-portal/src/app/views/management/customer/customer.component.html new file mode 100644 index 00000000..63b0a5b8 --- /dev/null +++ b/usecaseui-portal/src/app/views/management/customer/customer.component.html @@ -0,0 +1,118 @@ +<!-- + 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. +--> +<div class="content"> + <div class="chearts"> + <div class="Cu" #chart> + <p> {{"i18nTextDefine_Instance_Count_of_Customer" | translate}} </p> + <app-pie [initData]="CUChartInit" [chartData]="CUChartData" *ngIf="serviceChart" #pie></app-pie> + <div *ngIf="!serviceChart">No Service Instances </div> + </div> + <div class="type"> + <p> {{"i18nTextDefine_Instance_Count_of_ServiceType" | translate}} </p> + <app-bar [initData]="serviceInit" [chartData]="serviceData"></app-bar> + <div class="footname"> + <img src="assets/images/customerBarUser.png" alt="customerName"> + {{this.serviceInit["customer"]}} + </div> + </div> + </div> + <div class="customer"> + <div class="customer_title"> + <div class="customers"> + <span> {{"i18nTextDefine_Customer" | translate}} </span> + <img src="assets/images/customer04.png" alt="" (click)="this.customeradd = !this.customeradd"> + </div> + </div> + <div class="customer_detail"> + <div class="customer_add" *ngIf="customeradd"> + <input nz-input placeholder=" {{'i18nTextDefine_Input_customerName' | translate}} " class="customer_name" + nzSize="default" [(ngModel)]="addNewCustomer"> + <button nz-button nzType="primary" class="customer_addbut" + (click)="createNewCustomer()">{{"i18nTextDefine_Add" | translate}}</button> + </div> + <div class="customer_list"> + <ul> + <li *ngFor="let item of AllCustomersdata,let i = index" [ngClass]="{active: chose ==i}" + (click)="choseCustomer(i,item)"> + <img src="assets/images/customer05.png" alt=""> + <span>{{item.name}}</span> + <i class="anticon anticon-delete" (click)="deleteCustomerModel(item)"></i> + </li> + </ul> + </div> + </div> + </div> + <div class="services_type"> + <div class="services_type_title"> + <div class="servicess"> + <span> {{"i18nTextDefine_ServiceType" | translate}} </span> + <img src="assets/images/customer03.png" alt="" (click)="this.servicesadd = !this.servicesadd "> + </div> + </div> + <div class="services_type_detail"> + <div class="services_add" *ngIf="servicesadd"> + <input nz-input placeholder=" {{'i18nTextDefine_Input_ServicesType' | translate}} " class="services_name" + nzSize="default" [(ngModel)]="addNewServiceType"> + <button nz-button nzType="primary" class="services_addbut" + (click)="createNewServiceType()">{{"i18nTextDefine_Add" | translate}}</button> + </div> + <div class="services_list_content"> + <div class="border_size"></div> + <div class="services_list"> + <ul> + <li *ngFor="let item of AllServiceTypes"> + <span>{{item.type}}</span> + <i class="anticon anticon-delete" (click)="deleteServiceTypeModel(item)"></i> + </li> + </ul> + </div> + </div> + </div> + </div> + + <nz-modal nzWidth="428" [(nzVisible)]="deleteCustomerModelVisible" nzTitle=" {{'i18nTextDefine_delete' | translate}} " + (nzOnCancel)="deleteCustomerCancel()" (nzOnOk)="deleteCustomerOk()" nzClassName="deleteModel" + nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} " nzOkText=" {{'i18nTextDefine_modelOk' | translate}} "> + <h3><span style="color: red">* </span> {{"i18nTextDefine_Input_Sure_deleteCustomer" | translate}} </h3> + <div class="question"> + <h4> {{"i18nTextDefine_CustomerName" | translate}} :</h4> + <div class="deleteModelContent">{{thisdeleteCustomer["name"]}}</div> + </div> + <div class="question"> + <h4> {{"i18nTextDefine_CustomerID" | translate}} :</h4> + <div class="deleteModelContent">{{thisdeleteCustomer["id"]}}</div> + </div> + </nz-modal> + <nz-modal nzWidth="428" [(nzVisible)]="deleteServiceTypeModelVisible" + nzTitle=" {{'i18nTextDefine_delete' | translate}} " (nzOnCancel)="deleteServiceTypeCancel()" + (nzOnOk)="deleteServiceTypeOk()" nzClassName="deleteModel deleteServiceTypeModel" + nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} " nzOkText=" {{'i18nTextDefine_modelOk' | translate}} "> + <h3><span style="color: red">* </span> {{"i18nTextDefine_Input_Sure_deleteServiceType" | translate}} </h3> + <div class="question"> + <h4> {{"i18nTextDefine_CustomerName" | translate}} :</h4> + <div class="deleteModelContent">{{selectCustomer.name}}</div> + </div> + <div class="question"> + <h4> {{"i18nTextDefine_CustomerID" | translate}} :</h4> + <div class="deleteModelContent">{{selectCustomer.id}}</div> + </div> + <div class="question"> + <h4> {{"i18nTextDefine_ServiceType" | translate}} :</h4> + <div class="deleteModelContent">{{thisdeleteServiceType["type"]}}</div> + </div> + </nz-modal> + <app-notification #notification [isServicesList]="false"></app-notification> +</div>
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/management/customer/customer.component.less b/usecaseui-portal/src/app/views/management/customer/customer.component.less new file mode 100644 index 00000000..93e14455 --- /dev/null +++ b/usecaseui-portal/src/app/views/management/customer/customer.component.less @@ -0,0 +1,292 @@ +/* + 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. +*/ +.content { + display: flex; + width: 100%; + min-height: 917px; + i.anticon { + cursor: pointer; + font-size: 18px; + padding: 2px; + &:hover{ + color: #0DA9E2; + } + } + li.active{ + &:hover{ + cursor: pointer; + color: #3C4F8C; + // background:linear-gradient(to right, #E5F6FF, #CFEEFA) + background-color: #e6f7ff; + } + } + .chearts { + display: inline-block; + width: 32%; + margin-right: 1.5%; + vertical-align: top; + height: 100%; + >div{ + padding: 20px 20px; + } + .Cu,.type{ + min-height: 438px; + height: 46.5vh; + width: 100%; + margin-right: 2.5%; + border-radius: 5px; + background-color: #fff; + box-shadow: 0 2px 23px 0 rgba(0, 0, 0, 0.1), 0 2px 49px 0 rgba(0, 0, 0, 0.06); + p{ + color: #0DA9E2; + font-family:"ArialMT"; + } + } + .Cu { + margin-bottom: 20px; + p{ + margin-bottom: 60px; + } + div:last-child{ + color: #ddd; + font-weight: 700; + font-size: 19px; + height: 200px; + text-align: center; + line-height: 8; + } + } + .type { + display: flex; + flex-direction: column; + justify-content: space-between; + app-bar{ + position: relative; + left: 0px; + top: -6%; + width: 100%; + } + .footname{ + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: 100%; + height: 40px; + line-height: 40px; + text-align: center; + color: #3C4F8C; + margin-bottom: 20px; + + img{ + margin-right: 5px; + margin-bottom: 3px; + } + } + // &::after{ + // display: block; + // content: ''; + // height: 1px; + // } + + } + } + .customer { + min-height: 897px; + height: 95.7vh; + overflow: hidden; + width: 32%; + margin-right: 1.5%; + border-radius: 5px; + background-color: #fff; + box-shadow: 0 2px 23px 0 rgba(0, 0, 0, 0.1), 0 2px 49px 0 rgba(0, 0, 0, 0.06); + display: inline-block; + vertical-align: top; + .customer_title { + line-height: 3.5em; + width: 100%; + border-bottom: 1px #07A9E1 solid; + .customers { + padding: 0 20px; + span { + color: #0DA9E2; + font-family:"ArialMT"; + } + img { + width: 30px; + height: 30px; + float: right; + margin-top: 7px; + cursor: pointer; + } + } + } + .customer_detail { + height: 95%; + width: 100%; + overflow: auto; + border-top: 1px #07A9E1 solid; + .customer_add { + line-height: 3.5; + height: 50px; + width: 100%; + padding: 0 20px; + background-color: #F4F5F8; + .customer_name { + width: 52%; + font-size: 12px; + color: #CCCCCC; + font-family: ArialMT; + border-color: #3F9CFF; + } + .customer_addbut { + float: right; + margin-top: 9px; + width: 28%; + background-color: #0DA9E2; + } + } + .customer_list { + .active { + background:linear-gradient(to right, #E5F6FF, #CFEEFA); + color: #3C4F8C; + } + li { + display:flex; + align-items: center; + padding: 0 20px; + height: 50px; + line-height: 3.5; + width: 100%; + cursor: pointer; + color: rgba(60,79,140,0.5); + img { + width: 30px; + height: 30px; + } + span { + width: 70%; + padding-left: 10%; + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + } + } + + } + .services_type { + min-height: 897px; + height: 95.7vh; + overflow: hidden; + border-radius: 5px; + width: 32%; + background-color: #fff; + box-shadow: 0 2px 23px 0 rgba(0, 0, 0, 0.1), 0 2px 49px 0 rgba(0, 0, 0, 0.06); + display: inline-block; + vertical-align: top; + .services_type_title { + line-height: 3.5em; + //height: 5%; + width: 100%; + border-bottom: 1px #07A9E1 solid; + .servicess { + padding: 0 20px; + span { + color: #0DA9E2; + font-family:"ArialMT"; + } + img { + width: 40px; + height:40px; + float: right; + margin-right: -10px; + margin-top: 5px; + cursor: pointer; + } + } + } + .services_type_detail { + height: 95%; + width: 100%; + overflow: auto; + border-top: 1px #07A9E1 solid; + .services_add { + line-height: 3.5; + height: 50px; + width: 100%; + padding: 0 20px; + background-color: #F4F5F8; + .services_name { + width: 52%; + font-size: 12px; + color: #CCCCCC; + font-family: ArialMT; + border-color: #3F9CFF; + } + .services_addbut { + float: right; + margin-top: 5px; + width: 28%; + clear: both; + background-color: #0DA9E2; + } + } + + .services_list_content { + background:linear-gradient(to right, #E5F6FF, #CFEEFA); + height: 100%; + .border_size{ + position: absolute; + margin-left: -8px; + width: 0; + height: 0; + border-top: 24px solid transparent; + border-bottom: 24px solid transparent; + border-right: 10px solid #E5F6FF; + } + .services_list{ + padding:0 20px; + li { + height: 50px; + line-height: 50px; + width: 100%; + vertical-align: middle; + border-bottom: 2px #FFFFFF dashed; + position: relative; + color: #3C4F8C; + i { + display: inline-block; + vertical-align: middle; + position: absolute; + width: 48px; + height: 48px; + top: 0; + right: -16px; + line-height: 46px; + } + } + } + + } + + } + } + + +}
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/services/services.component.spec.ts b/usecaseui-portal/src/app/views/management/customer/customer.component.spec.ts index 2e76b9f9..f185e7a7 100644 --- a/usecaseui-portal/src/app/views/services/services.component.spec.ts +++ b/usecaseui-portal/src/app/views/management/customer/customer.component.spec.ts @@ -1,20 +1,20 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { ServicesComponent } from './services.component'; +import { CustomerComponent } from './customer.component'; -describe('ServicesComponent', () => { - let component: ServicesComponent; - let fixture: ComponentFixture<ServicesComponent>; +describe('CustomerComponent', () => { + let component: CustomerComponent; + let fixture: ComponentFixture<CustomerComponent>; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ ServicesComponent ] + declarations: [ CustomerComponent ] }) .compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(ServicesComponent); + fixture = TestBed.createComponent(CustomerComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/usecaseui-portal/src/app/views/management/customer/customer.component.ts b/usecaseui-portal/src/app/views/management/customer/customer.component.ts new file mode 100644 index 00000000..20cebccb --- /dev/null +++ b/usecaseui-portal/src/app/views/management/customer/customer.component.ts @@ -0,0 +1,489 @@ +/* + 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. +*/ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { ManagemencsService } from '../../../core/services/managemencs.service'; +import { Observable } from 'rxjs'; + +@Component({ + selector: 'app-customer', + templateUrl: './customer.component.html', + styleUrls: ['./customer.component.less'] +}) +export class CustomerComponent implements OnInit { + @ViewChild('chart') chart; + @ViewChild('pie') pie; + @ViewChild('notification')notification:any; + public chose = ''; + + resizeMark; + constructor( + private managemencs: ManagemencsService, + ) { + } + + ngOnInit() { + this.getAllCustomers(); + this.resizeMark = Observable.fromEvent(window,'resize') + .subscribe((event) => { + this.pie.resize(this.chart.nativeElement.offsetHeight,210) + }) + } + + ngAfterViewInit(){ + this.pie.resize(this.chart.nativeElement.offsetHeight,210) + } + + ngOnDestroy(){ + this.resizeMark.unsubscribe() + } + + AllCustomersdata = []; + AllServiceTypes = []; + customerber = []; + // Get all customers + selectCustomer = { + name: null, + id: null + }; + addNewCustomer = null; + addNewServiceType = null; + deleteCustomerModelVisible = false; + deleteServiceTypeModelVisible = false; + getAllCustomers() { + this.managemencs.getAllCustomers().subscribe((data) => { + this.AllCustomersdata = data.map((item) => { + return { name: item["subscriber-name"], id: item["global-customer-id"] } + }); + this.selectCustomer = this.AllCustomersdata[0]; + this.serviceInit["customer"] = this.AllCustomersdata[0].name; + this.getCustomersPie(); + this.getServiceTypes(this.selectCustomer); + this.getCustomersColumn(this.selectCustomer); + }) + + } + + // Get all servicetype + getServiceTypes(item) { + this.managemencs.getServiceTypes(item).subscribe((data) => { + this.AllServiceTypes = data.map((item) => { + return { type: item["service-type"], id: item["global-customer-id"] } + }); + }) + } + + // Switch user data + choseCustomer(index, item) { + this.chose = index; + this.selectCustomer = item; + this.serviceInit["customer"] = this.selectCustomer.name; + this.getServiceTypes(item); + this.getCustomersColumn(item); + } + + customeradd = false; + servicesadd = false; + //Customer pie + CUChartData: Object; + CUChartInit: Object = { + height: 200, + option: { + color: ["#F2F6FD"], + series: [{ + type: 'pie', + name: "customer", + radius: '90%', + center: ['50%', '50%'], + data: [], + label: { + normal: { + position: 'center', + show: false, + formatter: ' {b|{b}:{c}} ', + backgroundColor: 'rgba(51,51,51,0.9)', + borderColor: 'rgba(51,51,51,0.9)', + borderWidth: 1, + borderRadius: 4, + rich: { + b: { + fontSize: 16, + color: '#fff', + lineHeight: 33 + } + } + }, + emphasis: { + show: true, + + } + }, + labelLine: { + normal: { + show: false + } + }, + itemStyle: { + normal: { + borderWidth: 3, + borderColor: '#ffffff', + }, + emphasis: { + color: { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: '#7DCEFB' + }, { + offset: 1, color: '#0DA9E2' + }], + global: false + }, + borderWidth: 0, + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 10, 5, 0)' + } + } + }] + } + }; + + // get customers chart pie + Pie_name = []; + Pie_value = []; + serviceChart = true; + getCustomersPie() { + this.managemencs.getCustomersPie().subscribe((data) => { + this.serviceChart =data.serviceTotalNum > 0 ? true : false + this.CUChartData = { + series: [{ + data: data.customerServiceList + }] + } + }, (err) => { + console.log(err); + }); + } + + // service bar + serviceData: Object; + serviceInit: Object = { + customer: '', + height: 190, + option: { + tooltip: { + show: true, + trigger: 'item', + formatter: "{b}:\n{c}" + }, + grid: { + top: '5%', + left: '0%', + bottom: '3%', + containLabel: true + }, + xAxis: [ + { + type: 'value', + splitLine: { + show: false, + }, + axisTick: { + show: false + }, + axisLine: { + lineStyle: { + color: "#EDEDED" + } + }, + axisLabel: { + color: "#3C4F8C" + } + } + + ], + yAxis: [ + { + type: 'category', + splitLine: { + show: false, + }, + axisTick: { + show: false + }, + axisLine: { + lineStyle: { + color: "#EDEDED" + } + }, + axisLabel: { + color: "#3C4F8C" + }, + data: [], + }, + + ], + series: [ + { + name: '', + barWidth: '40%', + type: 'bar', + data: [], + itemStyle: { + normal: { + color: function (params) { + // build a color map as your need. + var colorList = [ + { + type: 'bar', + colorStops: [{ + offset: 0, + color: '#FCCE2B' + }, { + offset: 1, + color: '#FEE956' + }], + globalCoord: false, + }, + { + type: 'bar', + colorStops: [{ + offset: 0, + color: '#F43A59' + }, { + offset: 1, + color: '#FA6C92' + }], + globalCoord: false, + }, + { + type: 'bar', + colorStops: [{ + offset: 0, + color: '#4F5B60' + }, { + offset: 1, + color: '#879499' + }], + globalCoord: false, + }, + { + type: 'bar', + colorStops: [{ + offset: 0, + color: '#31DAC3' + }, { + offset: 1, + color: '#5FEFE3' + }], + globalCoord: false, + }, + { + type: 'bar', + colorStops: [{ + offset: 0, + color: '#999999' + }, { + offset: 1, + color: '#C9C9C9' + }], + globalCoord: false, + } + ]; + return colorList[params.dataIndex] + }, + } + } + }, + { + name: 'Type4', + type: 'bar', + stack: '', + data: '', + + }, + { + name: 'Type1', + type: 'bar', + stack: '', + data: '' + }, + { + name: 'Type2', + type: 'bar', + stack: '', + data: '' + }, + { + name: 'Type3', + type: 'bar', + stack: '', + data: '' + }, + { + name: 'Other', + type: 'bar', + stack: '', + data: '', + + } + ] + } + }; + name_s = []; + value_s = []; + getCustomersColumn(item) { + this.name_s = []; + this.value_s = []; + this.managemencs.getCustomersColumn(item).subscribe((data) => { + data.list.forEach((item) => { + this.name_s.push(item.name); + this.value_s.push(item.value); + }) + this.serviceData = { + yAxis: [{ + data: this.name_s + }], + series: [{ + data: this.value_s + }] + } + }) + } + + createNewCustomer(): void { + let createParams = { + customerId: this.addNewCustomer, + 'global-customer-id': this.addNewCustomer, + 'subscriber-name': this.addNewCustomer, + 'subscriber-type': 'INFRA' + }; + this.managemencs.createCustomer(this.addNewCustomer, createParams).subscribe((data) => { + if (data["status"] == 'SUCCESS') { + this.notification.notificationSuccess('Customer','Create',this.addNewCustomer); + this.getAllCustomers(); + } else { + this.notification.notificationFailed('Customer','Create',this.addNewCustomer); + } + }) + } + + // Customer delete model + thisdeleteCustomer = { + name: null, + id: null + }; + deleteCustomerModel(itemCustomer) { + this.thisdeleteCustomer = itemCustomer; + this.deleteCustomerModelVisible = true; + } + deleteCustomerCancel() { + this.deleteCustomerModelVisible = false; + } + deleteCustomerOk() { + this.deleteCustomerModelVisible = false; + this.getCustomerVersion(this.thisdeleteCustomer,); + } + getCustomerVersion(thisdeleteCustomer) { + this.managemencs.getdeleteCustomerVersion(thisdeleteCustomer).subscribe((data) => { + if (data["status"] == 'SUCCESS') { + let params = { + customerId: thisdeleteCustomer.id, + resourceVersion: data["result"]["resource-version"] + }; + this.deleteCustomer(params) + } else { + console.error(data, "Interface returned error") + } + }) + } + deleteCustomer(paramsObj) { + this.managemencs.deleteSelectCustomer(paramsObj).subscribe((data) => { + if (data["status"] == 'SUCCESS') { + this.notification.notificationSuccess('Customer','delete',this.thisdeleteCustomer.name); + this.getAllCustomers(); + } else { + this.notification.notificationFailed('Customer','delete',this.thisdeleteCustomer.name); + } + }) + } + + createNewServiceType() { + let createParams = { + customer: this.selectCustomer, + ServiceType: this.addNewServiceType, + "service-type": this.addNewServiceType, + "temp-ub-sub-account-id": "sotnaccount" + }; + this.managemencs.createServiceType(createParams).subscribe((data) => { + if (data["status"] == 'SUCCESS') { + this.notification.notificationSuccess('ServiceType','Create',this.addNewServiceType); + this.getAllCustomers(); + } else { + this.notification.notificationFailed('ServiceType','Create',this.addNewServiceType); + } + }) + } + + // ServiceType delete model + thisdeleteServiceType = { + type: null + }; + deleteServiceTypeModel(itemServiceType) { + this.thisdeleteServiceType = itemServiceType; + this.deleteServiceTypeModelVisible = true; + } + deleteServiceTypeCancel() { + this.deleteServiceTypeModelVisible = false; + } + deleteServiceTypeOk() { + this.deleteServiceTypeModelVisible = false; + this.getServiceTypeVersion(); + } + getServiceTypeVersion() { + let paramss = { + customerId: this.selectCustomer, + ServiceType: this.thisdeleteServiceType["type"] + }; + this.managemencs.getdeleteServiceTypeVersion(paramss).subscribe((data) => { + if (data["status"] == 'SUCCESS') { + let params = { + customerId: this.selectCustomer, + ServiceType: this.thisdeleteServiceType["type"], + version: data["result"]["resource-version"] + }; + this.deleteServiceType(params); + } else { + console.error(data, "Interface returned error") + } + }) + } + deleteServiceType(params) { + this.managemencs.deleteSelectServiceType(params).subscribe((data) => { + if (data["status"] == 'SUCCESS') { + this.notification.notificationSuccess('ServiceType','delete',this.thisdeleteServiceType["type"]); + this.getAllCustomers(); + } else { + this.notification.notificationFailed('ServiceType','delete',this.thisdeleteServiceType["type"]); + } + }) + } + + +} diff --git a/usecaseui-portal/src/app/views/management/management.component.ts b/usecaseui-portal/src/app/views/management/management.component.ts index 8220a166..b1a88e1e 100644 --- a/usecaseui-portal/src/app/views/management/management.component.ts +++ b/usecaseui-portal/src/app/views/management/management.component.ts @@ -28,27 +28,21 @@ import { ManagemencsService } from '../../core/services/managemencs.service'; export class ManagementComponent implements OnInit { @HostBinding('@routerAnimate') routerAnimateState; //Routing animation + nocuster: boolean; + firstCustomer: string; + constructor(private managemencs: ManagemencsService) { } ngOnInit() { this.getAllCustomers(); } - - nocuster = true; - firstCustomer = null; - AllCustomersdata = []; - + // Get all customers getAllCustomers() { this.managemencs.getAllCustomers().subscribe((data) => { - if (data.length > 0) { - this.nocuster = false; - } else { - this.nocuster = true; - } + this.nocuster = data.length > 0 ? false : true; }) } - createNewCustomer(customer) { let createParams = { customerId: customer @@ -63,6 +57,6 @@ export class ManagementComponent implements OnInit { }) } clearCustomerInput() { - this.firstCustomer = null; + this.firstCustomer = ''; } } diff --git a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.html b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.html index 4f865ff3..c48d68f9 100644 --- a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.html +++ b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.html @@ -13,274 +13,111 @@ See the License for the specific language governing permissions and limitations under the License. --> -<nz-tabset [nzTabPosition]="'top'" [nzType]="'card'"> - <nz-tab *ngFor="let tab of tabs" [nzTitle]="tab" (nzClick)="handleTabChange(tab)"> - <!-- nsList --> - <div class="list" *ngIf="tab === 'NS'"> - <div style="width:100%;height: 30%;margin-bottom: 1%"> - <div class="listupload"> - <nz-upload nzType="drag" [(nzFileList)]="fileListNS" [nzBeforeUpload]="beforeUploadNS"> - <p class="ant-upload-drag-icon"> - <i nz-icon type="inbox" class="anticon anticon-inbox"></i> - </p> - <p class="ant-upload-text"> {{"i18nTextDefine_Click_CSAR_File" | translate}} </p> - <p class="ant-upload-hint"></p> - </nz-upload> - <button nz-button [nzLoading]="nsuploading" (click)="onClick(tab)" [disabled]="fileListNS.length == 0" - style="margin-top: 16px;margin-left: 55px;color: #FFFFFF;font-size: 13px;background-color: #3E9BFF;font-family: ArialMT;"> - {{ nsuploading ? 'Uploading' : 'Start Upload' }} - </button> - </div> - <div class="listlin"></div> - <div class="listfile"> - <div style="color: rgba(66,84,143,1);font-family:ArialMT;padding-bottom: 15px;height: 15%"> {{"i18nTextDefine_Uploaded_files" | translate}} </div> - <div class="nouploadfile">{{"i18nTextDefine_Nofileuploading" | translate}}</div> - <div style="height:80%;overflow: auto"> - <div class="listfilebgc" *ngFor="let itemns of nsRightList"> - <div> - <i class="anticon anticon-link"></i> - </div> - <div class="color" [ngClass]="{'progress':itemns.status == true}">{{itemns.name}}</div> - <div class="color" *ngIf="itemns.status"> - <nz-progress [nzPercent]="itemns.progress" [nzShowInfo]="false"></nz-progress> - </div> - <div class="color" *ngIf="!itemns.status"> - <span *ngIf="itemns.success == 0">{{"i18nTextDefine_File_upload_completed" | translate}}</span> - <span *ngIf="itemns.success == 1">{{"i18nTextDefine_File_upload_failed" | translate}}</span> - </div> - <div *ngIf="!itemns.status"> - <i class="anticon anticon-check-circle" *ngIf="itemns.success == 0" style="color:#7BC7F3!important;"></i> - <i class="anticon anticon-exclamation-circle" *ngIf="itemns.success == 1" style="color:#fb5c5c!important;"></i> - </div> - </div> - </div> - </div> - </div> - <nz-spin [nzSpinning]="isSpinning" style="height: 69%"> - <div class="mask" *ngIf="isSpinning"></div> - <nz-table #nzTable [nzData]="nstableData" nzShowSizeChanger [nzFrontPagination]="true" - [nzShowQuickJumper]="true" [nzPageSizeOptions]="[5,10,15,20]" [nzTotal]='total' [(nzPageSize)]="nspageSize" - [(nzPageIndex)]='nspageIndex' [nzLoading]="loading" nzSize="middle"> - <thead (nzSortChange)="sort($event)" nzSingleSort> - <tr> - <th nzWidth="15%"> {{"i18nTextDefine_NO" | translate}} </th> - <th nzWidth="15%" nzShowSort nzSortKey="name"> {{"i18nTextDefine_Name" | translate}} </th> - <th nzWidth="15%"> {{"i18nTextDefine_Version" | translate}} </th> - <th nzWidth="15%"> {{"i18nTextDefine_OnboardingState" | translate}} </th> - <th nzWidth="15%"> {{"i18nTextDefine_OperationalState" | translate}} </th> - <th nzWidth="10%"> {{"i18nTextDefine_UsageState" | translate}} </th> - <th nzWidth="15%"> {{"i18nTextDefine_Operationbutton" | translate}} </th> - </tr> - </thead> - <tbody> - <tr *ngFor="let item of nzTable.data; let i = index; "> - <td>{{i+1}}</td> - - <td *ngIf="item.nsdName">{{item.nsdName}}</td> - <td *ngIf="item.nsdName === null || item.nsdName === ''"> </td> - <td *ngIf="item.name">{{item.name}}</td> - <td *ngIf="item.name===null || item.name=== ''"> </td> - <td *ngIf="item.nsdVersion">{{item.nsdVersion}}</td> - <td *ngIf="item.nsdVersion === null || item.nsdVersion === ''"> </td> - <td *ngIf="item.version">{{item.version}}</td> - <td *ngIf="item.version === null || item.version === ''"> </td> - <td> - <span *ngIf="item.nsdOnboardingState">{{item.nsdOnboardingState}}</span> - <span *ngIf="item.nsdOnboardingState === null || item.nsdOnboardingState === ''"> </span> - <span *ngIf="item.uuid">{{status}}</span> - - </td> - <td>{{item.nsdOperationalState}}</td> - <td>{{item.nsdUsageState}}</td> - <td> - <i [ngClass]="{'cannotclick':onboardData.status == 'onboarding' && i == currentIndex}" - class="anticon anticon-upload upicon" #upload_icon (click)="updataNsService(item.uuid,i,notificationModel)" - *ngIf="item.uuid"></i> - <i class="anticon anticon-delete" nzType="info" (click)="showConfirm(i,item.id,tab,notificationModel)" - *ngIf="item.id"></i> - - </td> - </tr> - </tbody> - </nz-table> - </nz-spin> - - </div> - <!-- VNFList --> - <div class="list" *ngIf="tab === 'VNF'"> - <div style="width:100%;height: 30%;margin-bottom: 1%"> - <div class="listupload"> - <nz-upload nzType="drag" [(nzFileList)]="fileListVNF" [nzBeforeUpload]="beforeUploadVNF"> - <p class="ant-upload-drag-icon"> - <i nz-icon type="inbox" class="anticon anticon-inbox"></i> - </p> - <p class="ant-upload-text">Click or drag CSAR File here</p> - <p class="ant-upload-hint"></p> - </nz-upload> - <button nz-button [nzLoading]="vnfuploading" (click)="onClick(tab)" [disabled]="fileListVNF.length == 0" - style="margin-top: 16px;margin-left: 55px;color: #FFFFFF;font-size: 13px;background-color: #3E9BFF;font-family: ArialMT;"> - {{ vnfuploading ? 'Uploading' : 'Start Upload' }} - </button> - </div> - <div class="listlin"></div> - <div class="listfile"> - <div style="color: rgba(66,84,143,1);font-family:ArialMT;padding-bottom: 15px;height: 15%"> {{"i18nTextDefine_Uploaded_files" | translate}} </div> - <div class="nouploadfile">{{"i18nTextDefine_Nofileuploading" | translate}}</div> - <div style="height:80%;overflow: auto"> - <div class="listfilebgc" *ngFor="let itemns of vnfRightList"> - <div> - <i class="anticon anticon-link"></i> - </div> - <div class="color" [ngClass]="{'progress':itemns.status == true}">{{itemns.name}}</div> - <div class="color" *ngIf="itemns.status"> - <nz-progress [nzPercent]="itemns.progress" [nzShowInfo]="false"></nz-progress> - </div> - <div class="color" *ngIf="!itemns.status"> - <span *ngIf="itemns.success == 0">{{"i18nTextDefine_File_upload_completed" | translate}}</span> - <span *ngIf="itemns.success == 1">{{"i18nTextDefine_File_upload_failed" | translate}}</span> - </div> - <div *ngIf="!itemns.status"> - <i class="anticon anticon-check-circle" *ngIf="itemns.success == 0" style="color:#7BC7F3!important;"></i> - <i class="anticon anticon-exclamation-circle" *ngIf="itemns.success == 1" style="color:#fb5c5c!important;"></i> - </div> - </div> - </div> - </div> - </div> - <nz-spin [nzSpinning]="isSpinning" style="height: 69%"> - <div class="mask" *ngIf="isSpinning"></div> - <nz-table #nzTable [nzData]="vnftableData" nzShowSizeChanger [nzFrontPagination]="true" - [nzShowQuickJumper]="true" [nzPageSizeOptions]="[5,10,15,20]" [nzTotal]='total' [(nzPageSize)]="vnfpageSize" - [(nzPageIndex)]='vnfpageIndex' [nzLoading]="loading" nzSize="middle"> - <thead (nzSortChange)="sort($event)" nzSingleSort> - <tr> - <th nzWidth="15%"> {{"i18nTextDefine_NO" | translate}} </th> - <th nzWidth="15%" nzShowSort nzSortKey="name"> {{"i18nTextDefine_Name" | translate}} </th> - <th nzWidth="15%"> {{"i18nTextDefine_Version" | translate}} </th> - <th nzWidth="15%"> {{"i18nTextDefine_OnboardingState" | translate}} </th> - <th nzWidth="15%"> {{"i18nTextDefine_OperationalState" | translate}} </th> - <th nzWidth="10%"> {{"i18nTextDefine_UsageState" | translate}} </th> - <th nzWidth="15%"> {{"i18nTextDefine_Operationbutton" | translate}} </th> - </tr> - </thead> - <tbody> - <tr *ngFor="let item of nzTable.data; let i = index; "> - <td>{{i+1}}</td> - <td *ngIf="item.vnfProductName">{{item.vnfProductName}}</td> - <td *ngIf="item.vnfProductName === null || item.vnfProductName === ''"> </td> - <td *ngIf="item.name">{{item.name}}</td> - <td *ngIf="item.vnfdVersion">{{item.vnfdVersion}}</td> - <td *ngIf="item.vnfdVersion === null || item.vnfdVersion === ''"> </td> - <td *ngIf="item.version">{{item.version}}</td> - <td>{{item.onboardingState}}</td> - <td>{{item.operationalState}}</td> - <td>{{item.usageState}}</td> - <td> - <i [ngClass]="{'cannotclick':onboardData.status == 'onboarding' && i == currentIndex}" - class="anticon anticon-upload upicon" #upload_icon (click)="updataVnfService(item.uuid,i,notificationModel)" - *ngIf="item.uuid"></i> - <i class="anticon anticon-delete" nzType="info" (click)="showConfirm(i,item.id,tab,notificationModel)" - *ngIf="item.id"></i> - </td> - </tr> - </tbody> - </nz-table> - </nz-spin> +<!-- tab --> +<nz-tabset [nzTabPosition]="'top'" [nzType]="'card'"> + <nz-tab *ngFor="let tab of tabs" [nzTitle]="tab" (nzClick)="handleTabChange(tab)"></nz-tab> +</nz-tabset> +<div class="list"> + <!-- upload --> + <div class="listUploadContainer"> + <div class="listupload"> + <nz-upload nzType="drag" [(nzFileList)]="fileList" [nzBeforeUpload]="beforeUpload"> + <p class="ant-upload-drag-icon"> + <i nz-icon type="inbox" class="anticon anticon-inbox"></i> + </p> + <p class="ant-upload-text"> {{"i18nTextDefine_Click_CSAR_File" | translate}} </p> + <p class="ant-upload-hint"></p> + </nz-upload> + <button nz-button [nzLoading]="uploading" (click)="onClick()" [disabled]="fileList.length == 0" class="upload"> + {{ uploading ? 'Uploading' : 'Start Upload' }} + </button> </div> - <!-- PNFList --> - <div class="list" *ngIf="tab === 'PNF'"> - <div style="width:100%;height: 30%;margin-bottom: 1%"> - <div class="listupload"> - <nz-upload nzType="drag" [(nzFileList)]="fileListPNF" [nzBeforeUpload]="beforeUploadPNF"> - <p class="ant-upload-drag-icon"> - <i nz-icon type="inbox" class="anticon anticon-inbox"></i> - </p> - <p class="ant-upload-text">Click or drag CSAR File here</p> - <p class="ant-upload-hint"></p> - </nz-upload> - <button nz-button [nzLoading]="pnfuploading" (click)="onClick(tab)" [disabled]="fileListPNF.length == 0" - style="margin-top: 16px;margin-left: 55px;color: #FFFFFF;font-size: 13px;background-color: #3E9BFF;font-family: ArialMT;"> - {{ pnfuploading ? 'Uploading' : 'Start Upload' }} - </button> - </div> - <div class="listlin"></div> - <div class="listfile"> - <div style="color: rgba(66,84,143,1);font-family:ArialMT;padding-bottom: 15px;height: 15%"> {{"i18nTextDefine_Uploaded_files" | translate}} </div> - <div class="nouploadfile">{{"i18nTextDefine_Nofileuploading" | translate}}</div> - <div style="height:80%;overflow: auto"> - <div class="listfilebgc" *ngFor="let itemns of pnfRightList"> - <div> - <i class="anticon anticon-link"></i> - </div> - <div class="color" [ngClass]="{'progress':itemns.status == true}">{{itemns.name}}</div> - <div class="color" *ngIf="itemns.status"> - <nz-progress [nzPercent]="itemns.progress" [nzShowInfo]="false"></nz-progress> - </div> - <div class="color" *ngIf="!itemns.status"> - <span *ngIf="itemns.success == 0">{{"i18nTextDefine_File_upload_completed" | translate}}</span> - <span *ngIf="itemns.success == 1">{{"i18nTextDefine_File_upload_failed" | translate}}</span> - </div> - <div *ngIf="!itemns.status"> - <i class="anticon anticon-check-circle" *ngIf="itemns.success == 0" style="color:#7BC7F3!important;"></i> - <i class="anticon anticon-exclamation-circle" *ngIf="itemns.success == 1" style="color:#fb5c5c!important;"></i> - </div> - </div> + <div class="listlin"></div> + <div class="listfile"> + <div class="listFileTitle"> {{"i18nTextDefine_Uploaded_files" | translate}} </div> + <div class="nouploadfile" [style.display]="display">{{"i18nTextDefine_Nofileuploading" | translate}}</div> + <div class="listfilebgc" *ngIf="file"> + <i class="anticon anticon-link icon"></i> + <div class="color" [ngClass]="{'progress':file.status}">{{file.name}}</div> + <div class="color" *ngIf="file.status"> + <nz-progress [nzPercent]="file.progress" [nzShowInfo]="false"></nz-progress> </div> - </div> - </div> - <nz-spin [nzSpinning]="isSpinning" style="height: 69%"> - <div class="mask" *ngIf="isSpinning"></div> - <nz-table #nzTable [nzData]="pnftableData" nzShowSizeChanger [nzFrontPagination]="true" - [nzShowQuickJumper]="true" [nzPageSizeOptions]="[5,10,15,20]" [nzTotal]='total' [(nzPageSize)]="pnfpageSize" - [(nzPageIndex)]='pnfpageIndex' [nzLoading]="loading" nzSize="middle"> - <thead (nzSortChange)="sort($event)" nzSingleSort> - <tr> - <th nzWidth="15%"> {{"i18nTextDefine_NO" | translate}} </th> - <th nzWidth="15%" nzShowSort nzSortKey="name"> {{"i18nTextDefine_Name" | translate}} </th> - <th nzWidth="15%"> {{"i18nTextDefine_Version" | translate}} </th> - <th nzWidth="15%"> {{"i18nTextDefine_OnboardingState" | translate}} </th> - <th nzWidth="10%"> {{"i18nTextDefine_UsageState" | translate}} </th> - <th nzWidth="15%"> {{"i18nTextDefine_Operationbutton" | translate}} </th> - </tr> - </thead> - <tbody> - <tr *ngFor="let item of nzTable.data; let i = index; "> - <td>{{i+1}}</td> - <td>{{item.pnfdName}}</td> - <td>{{item.pnfdVersion}}</td> - <td>{{item.pnfdOnboardingState}}</td> - <td>{{item.pnfdUsageState}}</td> - <td> - <i class="anticon anticon-delete" nzType="info" (click)="showConfirm(i,item.id,tab,notificationModel)"></i> - </td> - </tr> - </tbody> - </nz-table> - </nz-spin> - - </div> - </nz-tab> - <!--2019.08.14 add notification--> - <ng-template #notificationModel > - <div class="ant-notification-notice-content"> - <div class="ant-notification-notice-with-icon"> - <span class="ant-notification-notice-icon"> - <img src="{{notificationAttributes.imgPath}}" alt="{{notificationAttributes.status}}"> - </span> - <div class="ant-notification-notice-message"> - {{notificationAttributes.title}} - {{"i18nTextDefine_"+notificationAttributes.action | translate}} {{"i18nTextDefine_"+notificationAttributes.status | translate}} + <div class="color" *ngIf="!file.status"> + <span *ngIf="file.success === 0">{{"i18nTextDefine_File_upload_completed" | translate}}</span> + <span *ngIf="file.success === 1">{{"i18nTextDefine_File_upload_failed" | translate}}</span> </div> - <div class="ant-notification-notice-description"> - <div class="notificationlist"> - <p>{{notificationAttributes.title}} id: </p> - <span>{{ notificationAttributes.id }}</span> - </div> + <div *ngIf="!file.status"> + <i class="anticon anticon-check-circle success" *ngIf="file.success === 0"></i> + <i class="anticon anticon-exclamation-circle fail" *ngIf="file.success === 1"></i> </div> - <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> </div> </div> - </ng-template> -</nz-tabset> - + </div> + <!-- table --> + <nz-spin [nzSpinning]="isSpinning" class="listContainer"> + <div class="mask" *ngIf="isSpinning"></div> + <nz-table #nzTable [nzData]="currentTab === 'NS'? nsTableData: (currentTab === 'VNF'? vnfTableData : pnfTableData)" nzShowSizeChanger [nzFrontPagination]="true" + [nzShowQuickJumper]="true" [nzPageSizeOptions]="[5,10,15,20]" [(nzPageSize)]="pageSize" + [(nzPageIndex)]='pageIndex' nzSize="middle"> + <thead> + <tr class="theadColor"> + <th nzWidth="15%"> {{"i18nTextDefine_NO" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_Name" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_Version" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_OnboardingState" | translate}} </th> + <th nzWidth="15%" *ngIf="currentTab !== 'PNF'"> {{"i18nTextDefine_OperationalState" | translate}} </th> + <th nzWidth="10%"> {{"i18nTextDefine_UsageState" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_Operationbutton" | translate}} </th> + </tr> + </thead> + <tbody *ngIf="currentTab === 'NS'"> + <tr *ngFor="let item of nzTable.data;let i = index;"> + <td>{{i+1}}</td> + <td>{{item.nsdName || item.name }}</td> + <td>{{item.nsdVersion || item.version}}</td> + <td>{{item.nsdOnboardingState ? item.nsdOnboardingState : status}}</td> + <td>{{item.nsdOperationalState}}</td> + <td>{{item.nsdUsageState}}</td> + <td> + <i [ngClass]="{'cannotclick': isUpdate}" + class="anticon anticon-upload upicon" #upload_icon (click)="updataService(item.uuid)" + *ngIf="item.uuid"></i> + <i class="anticon anticon-delete" (click)="showDeleteConfirm(item.id)" + *ngIf="item.id"></i> + </td> + </tr> + </tbody> + <tbody *ngIf="currentTab === 'VNF'"> + <tr *ngFor="let item of nzTable.data;let i = index;"> + <td>{{i+1}}</td> + <td>{{item.vnfProductName || item.name }}</td> + <td>{{item.vnfdVersion || item.version}}</td> + <td>{{item.onboardingState}}</td> + <td>{{item.operationalState}}</td> + <td>{{item.usageState}}</td> + <td> + <i [ngClass]="{'cannotclick': isUpdate}" + class="anticon anticon-upload upicon" #upload_icon (click)="updataService(item.uuid)" + *ngIf="item.uuid"></i> + <i class="anticon anticon-delete" (click)="showDeleteConfirm(item.id)" + *ngIf="item.id"></i> + </td> + </tr> + </tbody> + <tbody *ngIf="currentTab === 'PNF'" > + <tr *ngFor="let item of nzTable.data; let i = index;"> + <td>{{i+1}}</td> + <td>{{item.pnfdName}}</td> + <td>{{item.pnfdVersion}}</td> + <td>{{item.pnfdOnboardingState}}</td> + <td>{{item.pnfdUsageState}}</td> + <td> + <i class="anticon anticon-delete" (click)="showDeleteConfirm(item.id)"></i> + </td> + </tr> + </tbody> + </nz-table> + </nz-spin> +</div> +<app-notification #notification [isServicesList]="false"></app-notification>
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.less b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.less index 5ba479de..f877e1ca 100644 --- a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.less +++ b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.less @@ -13,141 +13,112 @@ See the License for the specific language governing permissions and limitations under the License. */ -.title { - font: 700 18px/18px "思源黑体"; - color: #4c5e70; - margin-bottom: 18px; +th{ + background-color: rgba(241,243,244,.9) !important; } -hr { - border: none; - height: 2px; - background-color: #dce1e7; - margin-bottom: 20px; -} -.switch_btn { - position: absolute; - right: 6%; - top: 18px; - border: 1px solid #3fa8eb; - width: 8%; - border-radius: 10px; - margin-bottom: 18px; - span { - display: block; - float: left; - text-align: center; - width: 50%; - color: #3fa8eb; - font-weight: 700; - cursor: pointer; - } - span:first-child { - border-radius: 10px 0 0 10px; - } - span:last-child { - border-radius: 0 10px 10px 0; - } - span.left_b { - border-left: 1px solid #3fa8eb; - } - span.active { - color: #fff; - background: #3fa8eb; - } -} - .list { - border-radius: 5px; - .listupload { - width: 22%; - vertical-align: top; - display: inline-block; - margin-left: 13%; - } - .listlin { - vertical-align: top; - display: inline-block; - width: 1%; - margin-left: 10%; - height: 177px; - margin-bottom: 30px; - border-right: 2px solid #EEEEEE; - } - .listfile { - width: 43%; - height: 100%; - vertical-align: top; - display: inline-block; - margin-left: 10%; - .nouploadfile{ - height: 80%; - width: 100%; - text-align: center; - font-size: 22px; - margin-top: 5%; + padding: 20px; + .listUploadContainer{ + display: flex; + align-items: flex-start; + width: 100%; + height: 30%; + margin-bottom: 1%; + .listupload { + position: relative; + width: 22%; + margin-left: 13%; + .upload{ + position: absolute; + left: 50%; + bottom: -48px; + transform: translateX(-50%); + color: #FFFFFF; + font-size: 13px; + background-color: #3E9BFF; + font-family: ArialMT; + } } - .listfilebgc { - background-color: #fff; - border-bottom: 8px solid #F7F8FC; + .listlin { + width: 1%; + margin-left: 10%; + height: 177px; + margin-bottom: 30px; + border-right: 2px solid #EEEEEE; } - .listfilebgc { - background-color: #fff; - height: 30px; - border-radius: 2px; - line-height: 2; - color: #42548F; - border-bottom: 4px solid #F7F8FC; - >div { - float: left; + .listfile { + width: 43%; + height: 100%; + margin-left: 10%; + .listFileTitle{ + height: 15%; + padding-bottom: 15px; + color: rgba(66,84,143,1); + font-family: ArialMT; } - :first-child { - width: 6%; - margin-left: 5px; - } - :nth-child(2){ - width:20%; - } - :nth-child(3){ - width: 60%; - text-align: center; - } - :nth-child(4){ - padding-left: 4%; - } - .color { - color:rgba(66,84,143,1); - span{ - color:rgba(66,84,143,0.7); - } - } - .progress{ - color:rgba(66,84,143,0.7); + .nouploadfile{ + height: 80%; + width: 100%; + text-align: center; + font-size: 22px; + margin: 5% 0 10px; } + .listfilebgc { + display: flex; + justify-content: space-around; + align-items: center; + width:100%; + height: 80%; + padding: 5px; + background-color: #fff; + border-radius: 2px; + color: #42548F; + .icon{ + width: 15px; + } + :nth-child(3){ + width: 50%; + } + :nth-child(4){ + width: 5%; + height:100%; + .success{ + color:#7BC7F3!important; + } + .fail{ + color:#fb5c5c!important; + } + } + .color { + color:rgba(66,84,143,1); + span{ + color:rgba(66,84,143,0.7); + } + .progress{ + color:rgba(66,84,143,0.7); + } + } + } + + } + + } + .listContainer{ + height: 69%; + .mask { + top: 0; + left: 0; + position: fixed; + width: 100%; + height: 100%; + opacity: 0.1; + background: black; + z-index: 1049; } } nz-table { tbody { td { - span.onboarding { - font-size: 12px; - color: #147dc2; - } - span.onboarded { - font-size: 14px; - color: #147dc2; - } - span.updating { - font-size: 12px; - color: blue; - } - span.deleting { - font-size: 12px; - color: red; - } - span.invalid { - font-size: 14px; - color: purple; - } i.anticon { cursor: pointer; font-size: 18px; @@ -161,20 +132,7 @@ hr { color: #aaa; opacity: 0.6; } - .fileIcon{ - display: none; - } } } } } -.mask { - top: 0; - left: 0; - position: fixed; - width: 100%; - height: 100%; - opacity: 0.1; - background: black; - z-index: 1049; -}
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.ts b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.ts index 33385e32..3d312c5c 100644 --- a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.ts +++ b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.ts @@ -14,14 +14,11 @@ limitations under the License. */ import { HttpClient, HttpRequest, HttpResponse } from '@angular/common/http'; -import { Component, OnInit, HostBinding, TemplateRef } from '@angular/core'; -import { NzNotificationService } from 'ng-zorro-antd'; -// import { MyhttpService } from '../../myhttp.service'; +import { Component, OnInit, HostBinding, TemplateRef, ViewChild } from '@angular/core'; import { onboardService } from '../../../core/services/onboard.service'; import { slideToRight } from '../../../shared/utils/animates'; import { NzMessageService, UploadFile, NzModalRef, NzModalService } from 'ng-zorro-antd'; import { filter } from 'rxjs/operators'; -import { Title } from '@angular/platform-browser'; @Component({ selector: 'app-onboard-vnf-vm', @@ -31,114 +28,75 @@ import { Title } from '@angular/platform-browser'; }) export class OnboardVnfVmComponent implements OnInit { @HostBinding('@routerAnimate') routerAnimateState; + @ViewChild('notification') notification: any; - // delete Modal - confirmModal: NzModalRef; - nsdInfoId = ''; - vnfPkgId = ''; - pnfdInfoId = ''; - tabTitle = "NS"; - nsuploading = false; - vnfuploading = false; - pnfloading = false; + // upload + tabs: string[] = ['NS', 'VNF', 'PNF']; + currentTab: string = 'NS' fileList: UploadFile[] = []; - fileListNS: UploadFile[] = []; - fileListVNF: UploadFile[] = []; - fileListPNF: UploadFile[] = []; - // onboard initial value - status = "Onboard Available"; - jobId = ''; + uploading:boolean = false; + infoId: string; + display: string = 'block'; + + // table + isSpinning: boolean = false; + nsTableData: any[]; + vnfTableData: any[]; + pnfTableData: any[]; + status: string = "Onboard Available"; + pageIndex: number = 1; + pageSize: number = 10; + + // update or delete + isUpdate: boolean = false; + jobId: string; + //url url = { - // line up ns: '/api/nsd/v1/ns_descriptors/*_*/nsd_content', vnf: '/api/vnfpkgm/v1/vnf_packages/*_*/package_content', pnf: '/api/nsd/v1/pnf_descriptors/*_*/pnfd_content' - // line local - //ns: 'https://jsonplaceholder.typicode.com/posts/', - //vnf: 'https://jsonplaceholder.typicode.com/posts/', - //pnf: 'https://jsonplaceholder.typicode.com/posts/', }; + + file: { + name: string, + uid: string, + progress: number, + status: boolean, + success: number + }; + constructor( private myhttp: onboardService, private http: HttpClient, private msg: NzMessageService, - private titleService: Title, - private modal: NzModalService, - private modalService: NzModalService, - private notification: NzNotificationService + private modalService: NzModalService ) { } + //default Call ns data by default ngOnInit() { this.getTableData(); } - //Tabular data - nstableData: any; - vnftableData: any; - pnftableData: any; - nssdcData: any; - nsvfcData: any; - - vnfsdcData: any; - vnfvfcData: any; - nspageIndex = 1; - nspageSize = 10; - vnfpageIndex = 1; - vnfpageSize = 10; - pnfpageIndex = 1; - pnfpageSize = 10; - total; - nsloading = false; - sortName = null; - sortValue = null; - tabs = ['NS', 'VNF', 'PNF']; - isSpinning = false; - - //2019.08.14 add - notificationAttributes = { - "title": this.tabs[0], - "imgPath": "../../../../assets/images/execute-inproess.png", - "action": "OnboardingState", - "status": "InProgress", - "id": null - }; - notificationModelShow(template: TemplateRef<{}>): void { - this.notification.template(template); - } - notificationSuccess(notificationModel) { - this.notificationAttributes.imgPath = "../../../../assets/images/execute-success.png"; - this.notificationAttributes.status = "Success"; - this.notificationModelShow(notificationModel); - } - notificationFailed(notificationModel) { - this.notificationAttributes.imgPath = "../../../../assets/images/execute-faild.png"; - this.notificationAttributes.status = "Failed"; - this.notificationModelShow(notificationModel); - } // Handling tab switching request data - handleTabChange(tab) { - this.tabTitle = tab; + handleTabChange(tab: string): void { + this.currentTab = tab; + this.fileList = []; + this.display = 'block'; + delete this.file; switch (tab) { case 'NS': - this.nstableData = []; this.getTableData(); - this.fileList = []; //Empty uploaded files when switching break case 'VNF': - this.vnftableData = []; this.getTableVnfData() - this.fileList = []; break case 'PNF': - this.pnftableData = []; this.getTablePnfData() - this.fileList = []; break } } - //before put create--Drag and drop files to the page before uploading requestBody = { "userDefinedData": { @@ -148,302 +106,128 @@ export class OnboardVnfVmComponent implements OnInit { } } - //NS/VNF List add file beforeUpload = (file: UploadFile): boolean => { - this.fileList.push(file); - return false; - } - - // ns beforeUpload - beforeUploadNS = (file: UploadFile): boolean => { - this.fileListNS.push(file); - this.myhttp.getCreatensData("createNetworkServiceData", this.requestBody)//on-line - // this.myhttp.getCreatensData("creatensDataNS") //local - .subscribe((data) => { - this.nsdInfoId = data["id"]; - }, (err) => { - console.log(err); - }) - return false; - } - - //vnf beforeUpload - beforeUploadVNF = (file: UploadFile): boolean => { - this.fileListVNF.push(file); - this.myhttp.getCreatensData("createVnfData", this.requestBody)//on-line - // this.myhttp.getCreatensData("creatensDataVNF") //local - .subscribe((data) => { - this.vnfPkgId = data["id"]; - }, (err) => { - console.log(err); - }) - return false; - } - - // //pnf eforeUpload - beforeUploadPNF = (file: UploadFile): boolean => { - this.fileListPNF.push(file); - this.myhttp.getCreatensData("createPnfData", this.requestBody) //on-line - // this.myhttp.getCreatensData("creatensDataPNF") //local + this.fileList.splice(0,1,file); + let API: string; + if(this.currentTab === 'NS'){ + API = 'createNetworkServiceData'; + }else if(this.currentTab === 'VNF'){ + API = 'createVnfData'; + }else { + API = 'createPnfData'; + } + this.myhttp.getCreatensData(API, this.requestBody)//on-line .subscribe((data) => { - this.pnfdInfoId = data["id"]; + this.infoId = data["id"]; }, (err) => { console.log(err); }) return false; } - //Get list list id - onClickId(id, tab) { - switch (tab) { - case 'NS': - this.nsdInfoId = id; - break - case 'VNF': - this.vnfPkgId = id; - break - case 'PNF': - this.pnfdInfoId = id; - break - } - } - - //Drag and drop and click the upload button - onClick(tab) { - switch (tab) { - case 'NS': - // this.handleUpload('/api/nsd/v1/ns_descriptors/'+this.nsdInfoId+'/nsd_content',tab); - this.handleUpload(this.url.ns.replace("*_*", this.nsdInfoId), tab); - this.getTableData(); - break - case 'VNF': - // this.handleUpload('/api/vnfpkgm/v1/vnf_packages/'+this.vnfPkgId+'/package_content',tab); - this.handleUpload(this.url.vnf.replace("*_*", this.vnfPkgId), tab); - this.getTableVnfData() - break - case 'PNF': - // this.handleUpload('/api/nsd/v1/pnf_descriptors/'+this.pnfdInfoId+'/pnfd_content',tab); - this.handleUpload(this.url.pnf.replace("*_*", this.pnfdInfoId), tab); - this.getTablePnfData(); - break - } + // Drag and drop and click the upload button + onClick(): void { + this.display = 'none'; + let tab = this.currentTab === 'NS' ? 'ns' : (this.currentTab === 'VNF' ? 'vnf' : 'pnf') + this.handleUpload(this.url[tab].replace("*_*", this.infoId)); } - nsRightList = []; - nsNum = 0; - vnfRightList = []; - vnfNum = 0; - pnfRightList = []; - pnfNum = 0; - //put Upload Upload - handleUpload(url, tab): void { + handleUpload(url: string): void { const formData = new FormData(); // tslint:disable-next-line:no-any - switch (tab) { - case "NS": - this.fileListNS.forEach((file: any) => { - formData.append('file', file); - }); - this.nsuploading = true; - let lastNs = this.fileListNS[this.fileListNS.length - 1]; - let nsfile = { - name: lastNs.name, - uid: lastNs.uid, - progress: 0, - status: true, - success: 0 - }; - this.nsNum += 1; - this.nsRightList.push(nsfile); - let requeryNs = (nsfile) => { - setTimeout(() => { - nsfile.progress += 2; - if (nsfile.progress < 100) { - requeryNs(nsfile) - } else { - nsfile.progress = 100; - nsfile.status = false; - } - }, 100) - }; - requeryNs(nsfile); - break - case "VNF": - this.fileListVNF.forEach((file: any) => { - formData.append('file', file); - }); - this.vnfuploading = true; - let lastVnf = this.fileListVNF[this.fileListVNF.length - 1]; - let vnffile = { - name: lastVnf.name, - uid: lastVnf.uid, - progress: 0, - status: true, - success: 0 - }; - this.vnfNum += 1; - this.vnfRightList.push(vnffile); - let requeryVnf = (vnffile) => { - setTimeout(() => { - vnffile.progress += 2; - if (vnffile.progress < 100) { - requeryVnf(vnffile) - } else { - vnffile.progress = 100; - vnffile.status = false; - } - }, 100) - }; - requeryVnf(vnffile); - break - case "PNF": - this.fileListPNF.forEach((file: any) => { - formData.append('file', file); - }); - this.pnfloading = true; - let lastPnf = this.fileListPNF[this.fileListPNF.length - 1]; - let pnffile = { - name: lastPnf.name, - uid: lastPnf.uid, - progress: 0, - status: true, - success: 0 - }; - this.pnfNum += 1; - this.pnfRightList.push(pnffile); - let requeryPnf = (pnffile) => { - setTimeout(() => { - pnffile.progress += 2; - if (pnffile.progress < 100) { - requeryPnf(pnffile) - } else { - pnffile.progress = 100; - pnffile.status = false; - } - }, 100) - }; - requeryPnf(pnffile); - break - } - // line PUT + this.fileList.forEach((file: any) => { + formData.set('file', file); + }); + this.uploading = true; + this.file = { + name: this.fileList[0].name, + uid: this.fileList[0].uid, + progress: 0, + status: true, + success: 0 + }; + let requery = (file) => { + file.progress += 3; + setTimeout(() => { + if (file.progress < 100) { + requery(file) + } + }, 100) + }; + requery(this.file); const req = new HttpRequest('PUT', url, formData, { reportProgress: true, withCredentials: true }); //Upload pre-empty array this.fileList = []; - this.fileListNS = []; - this.fileListVNF = []; - this.fileListPNF = []; this.http.request(req) .pipe(filter(e => e instanceof HttpResponse)) .subscribe( (event: {}) => { - if (tab == "NS") { - this.nsRightList[this.nsNum - 1].progress = 100; - this.nsRightList[this.nsNum - 1].status = false; - this.nsRightList[this.nsNum - 1].success = 0; - } - if (tab == "VNF") { - this.vnfRightList[this.vnfNum - 1].progress = 100; - this.vnfRightList[this.vnfNum - 1].status = false; - this.vnfRightList[this.vnfNum - 1].success = 0; - } - if (tab == "PNF") { - this.pnfRightList[this.pnfNum - 1].progress = 100; - this.pnfRightList[this.pnfNum - 1].status = false; - this.pnfRightList[this.pnfNum - 1].success = 0; - } - this.changeUploadingSta(tab); + this.file.progress = 100; + this.file.status = false; + this.uploading = false; this.msg.success('upload successfully.'); + this.currentTab === 'NS' ? this.getTableData() : (this.currentTab === 'VNF' ? this.getTableVnfData() : this.getTablePnfData()); }, err => { - if (tab == "NS") { - this.nsRightList[this.nsNum - 1].progress = 100; - this.nsRightList[this.nsNum - 1].status = false; - this.nsRightList[this.nsNum - 1].success = 1; - } - if (tab == "VNF") { - this.vnfRightList[this.vnfNum - 1].progress = 100; - this.vnfRightList[this.vnfNum - 1].status = false; - this.vnfRightList[this.vnfNum - 1].success = 1; - } - if (tab == "PNF") { - this.pnfRightList[this.pnfNum - 1].progress = 100; - this.pnfRightList[this.pnfNum - 1].status = false; - this.pnfRightList[this.pnfNum - 1].success = 1; - } - this.changeUploadingSta(tab); + this.file.progress = 100; + this.file.status = false; + this.file.success = 1; + this.uploading = false; this.msg.error('upload failed.'); } ); } - // Control the status of uploading - changeUploadingSta(tab) { - switch (tab) { - case "NS": - this.nsuploading = false; - break - case "VNF": - this.vnfuploading = false; - break - case "PNF": - this.pnfloading = false; - } - } - - //---------------------------------------------------------------------------------------------- - // Get the NS list - getTableData() { + getTableData(): void{ this.isSpinning = true; //ns vfc lists this.myhttp.getOnboardTableData() .subscribe((data) => { - this.nsvfcData = data; - this.nstableData = this.nsvfcData; + this.nsTableData = data; //ns sdc list this.myhttp.getSDC_NSTableData() .subscribe((data) => { this.isSpinning = false; //loading hide - this.nssdcData = data; - this.nsvfcData.map((nsvfc) => { nsvfc.sameid = this.nssdcData.find((nssdc) => { return nsvfc.id == nssdc.uuid }) && nsvfc.id; return nsvfc; }); - let sameData = this.nssdcData.filter((nssdc) => { return !this.nsvfcData.find((nsvfc) => { return nsvfc.id == nssdc.uuid }) }); - this.nstableData = this.nstableData.concat(sameData); + let nsData = data; + // this.NSTableData.map((nsvfc) => { nsvfc.sameid = nsData.find((nssdc) => { return nsvfc.id == nssdc.uuid }) && nsvfc.id; return nsvfc; }); + let sameData = nsData.filter((nssdc) => { return !this.nsTableData.find((nsvfc) => { return nsvfc.id == nssdc.uuid }) }); + this.nsTableData = this.nsTableData.concat(sameData); }, (err) => { - console.log(err); + console.error(err); this.isSpinning = false; }) }, (err) => { - console.log(err); + console.error(err); this.isSpinning = false; }) - } // Get the vnf list - getTableVnfData() { + getTableVnfData(): void{ this.isSpinning = true; //vnf vfc lists this.myhttp.getOnboardTableVnfData() .subscribe((data) => { - this.vnfvfcData = data; - this.vnftableData = this.vnfvfcData; + this.vnfTableData = data; //vnf sdc lists this.myhttp.getSDC_VNFTableData() .subscribe((data) => { this.isSpinning = false; //loading hide - this.vnfsdcData = data; - this.vnfvfcData.map((vnfvfc) => { vnfvfc.sameid = this.vnfsdcData.find((nssdc) => { return vnfvfc.id == nssdc.uuid }) && vnfvfc.id; return vnfvfc; }); - let sameData = this.vnfsdcData.filter((vnfsdc) => { return !this.vnfvfcData.find((vnfvfc) => { return vnfvfc.id == vnfsdc.uuid }) }); - this.vnftableData = this.vnftableData.concat(sameData); + let vnfData = data; + // this.VNFTableData.map((vnfvfc) => { vnfvfc.sameid = this.vnfData.find((nssdc) => { return vnfvfc.id == nssdc.uuid }) && vnfvfc.id; return vnfvfc; }); + let sameData = vnfData.filter((vnfsdc) => { return !this.vnfTableData.find((vnfvfc) => { return vnfvfc.id == vnfsdc.uuid }) }); + this.vnfTableData = this.vnfTableData.concat(sameData); }, (err) => { - console.log(err); + console.error(err); + this.isSpinning = false; }) - }, (err) => { - console.log(err); + console.error(err); + this.isSpinning = false; }) } @@ -452,133 +236,76 @@ export class OnboardVnfVmComponent implements OnInit { this.isSpinning = true; this.myhttp.getOnboardTablePnfData() .subscribe((data) => { - this.pnftableData = data; + this.pnfTableData = data; this.isSpinning = false; //loading hide }, (err) => { - console.log(err); + console.error(err); + this.isSpinning = false; }) } - //----------------------------------------------------------------------------------- - /* onboard */ - //Successful frame - success(tab): void { - const modal = this.modalService.success({ - nzTitle: 'This is an success message', - nzContent: 'Package Onboard Completed.' - }); - switch (tab) { - case "NS": - this.getTableData(); - break - case "VNF": - this.getTableVnfData(); - break - } + // confirm + showConfirm(requestBody: object, id: string): void{ + let API = this.currentTab === 'NS'? 'getNsonboard' : 'getVnfonboard'; + this.modalService.confirm({ + nzTitle: '<p>Are you sure you want to do this?</p>', + nzOnOk: () => { + this.myhttp[API](requestBody) + .subscribe((data) => { + if (data.status == "success") { + if(this.currentTab === 'NS'){ + this.isUpdate = false; + this.notification.notificationSuccess(this.currentTab, "OnboardingState", id); + this.getTableData(); + }else{ + this.jobId = data.jobId; + this.queryProgress(this.jobId, id); + this.getTableVnfData(); + } + } else { + this.isUpdate = false; + this.notification.notificationFailed(this.currentTab, "OnboardingState", id); + return false + } + }, (err) => { + console.log(err); + }) + } + }) } - //Failure frame - error(): void { - this.modalService.error({ - nzTitle: 'This is an error message', - nzContent: 'Package Onboard Failed!' - }); - } - //onboard status - onboardData = { - status: "onboard", - progress: 0, - } - currentIndex = 0; // ns onboard Upload button - updataNsService(id, index, notificationModel) { - this.currentIndex = index; - this.onboardData.status = "onboarding"; //Disabled - this.onboardData.progress = 0; - let requestBody = { - "csarId": id - }; - this.notificationAttributes = { - "title": this.tabs[0], - "imgPath": "../../../../assets/images/execute-inproess.png", - "action": "OnboardingState", - "status": "InProgress", - "id": id - }; - this.notificationModelShow(notificationModel); - this.myhttp.getNsonboard(requestBody) - .subscribe((data) => { - if (data.status == "failed") { - this.onboardData.status = "Failed"; - this.notificationFailed(notificationModel); - this.error(); - return false - } else if (data.status == "success") { - this.success("NS"); - this.onboardData.status = "onboarded"; - this.notificationSuccess(notificationModel); - } - }, (err) => { - console.log(err); - }) - } - - // vnf onboard Upload button - updataVnfService(id, index, notificationModel) { - this.currentIndex = index; - this.onboardData.status = "onboarding"; //Disabled button - this.onboardData.progress = 0; - - - let requestBody = { - "csarId": id - }; - this.notificationAttributes = { - "title": this.tabs[1], - "imgPath": "../../../../assets/images/execute-inproess.png", - "action": "OnboardingState", - "status": "InProgress", - "id": id - }; - this.notificationModelShow(notificationModel); - this.myhttp.getVnfonboard(requestBody) - .subscribe((data) => { - this.jobId = data.jobId; - this.queryProgress(this.jobId, 0, notificationModel); //vnf Need to query progress interface - }, (err) => { - console.log(err); - }) - } + updataService(id: string) { + this.isUpdate = true; + let requestBody = { "csarId": id }; + this.showConfirm(requestBody, id) + } //Progress Progress inquiry - queryProgress(jobId, responseId, notificationModel) { + queryProgress(jobId: string, id: string): any{ let mypromise = new Promise((res) => { - this.myhttp.getProgress(jobId, responseId) + this.myhttp.getProgress(jobId, 0) .subscribe((data) => { if (data.responseDescriptor == null || data.responseDescriptor == "null" || data.responseDescriptor.progress == undefined || data.responseDescriptor.progress == null) { - this.onboardData.status = "onboarding"; + this.isUpdate = true; setTimeout(() => { - this.queryProgress(this.jobId, 0, notificationModel); + this.queryProgress(this.jobId, id); }, 10000) return false } if (data.responseDescriptor.progress > 100) { - this.onboardData.status = "Failed"; - this.notificationFailed(notificationModel); - this.error(); - return false - } - if (data.responseDescriptor.progress < 100) { - this.onboardData.status = "onboarding"; + this.isUpdate = false; + this.notification.notificationFailed(this.currentTab, 'OnboardingState', id); + }else if (data.responseDescriptor.progress < 100) { + this.isUpdate = true; setTimeout(() => { - this.queryProgress(this.jobId, 0, notificationModel); + this.queryProgress(this.jobId, id); }, 5000) - } else if (data.responseDescriptor.progress == 100) { + } else { res(data); - this.success("VNF"); - this.onboardData.status = "onboarded"; - this.notificationSuccess(notificationModel); + this.isUpdate = false; + this.notification.notificationSuccess(this.currentTab, 'OnboardingState', id); } return false }) @@ -586,83 +313,48 @@ export class OnboardVnfVmComponent implements OnInit { return mypromise; } - //-------------------------------------------------------------------------------- /* delete button */ - showConfirm(index, pkgid, tab, notificationModel): void { - this.notificationAttributes = { - "title": this.tabs[0], - "imgPath": "../../../../assets/images/execute-inproess.png", - "action": "OnboardingState", - "status": "InProgress", - "id": pkgid - }; - this.confirmModal = this.modal.confirm({ + showDeleteConfirm(pkgid: string): void { + this.modalService.confirm({ nzTitle: 'Do you Want to delete these items?', nzContent: 'Do you Want to delete these items?', nzOkText: 'Yes', nzCancelText: 'No', - nzOnOk: () => new Promise((resolve, reject) => { - switch (tab) { - case 'NS': - this.notificationAttributes.title = this.tabs[0]; - this.notificationModelShow(notificationModel); - this.deleteNsService(index, pkgid, notificationModel); - setTimeout(Math.random() > 0.5 ? resolve : reject, 2000); - break - case 'VNF': - this.notificationAttributes.title = this.tabs[1]; - this.notificationModelShow(notificationModel); - this.deleteVnfService(index, pkgid, notificationModel); - setTimeout(Math.random() > 0.5 ? resolve : reject, 2000); - break - case 'PNF': - this.notificationAttributes.title = this.tabs[2]; - this.notificationModelShow(notificationModel); - this.deletePnfService(index, pkgid, notificationModel); - setTimeout(Math.random() > 0.5 ? resolve : reject, 2000); - break - } + nzOnOk: () => new Promise((resolve) => { + this.deleteService(pkgid, resolve); }).catch(() => console.log('Oops errors!')) }); } //delete nsItem - deleteNsService(index, pkgid, notificationModel) { - this.myhttp.deleteNsIdData(pkgid) - .subscribe((data) => { - this.notificationSuccess(notificationModel); - //refresh list after successful deletion - this.getTableData(); - }, (err) => { - console.log(err); - this.notificationFailed(notificationModel); - }) - } - - //delete vnfItem - deleteVnfService(index, pkgid, notificationModel) { - this.myhttp.deleteVnfIdData(pkgid) - .subscribe((data) => { - this.notificationSuccess(notificationModel); - //refresh list after successful deletion - this.getTableVnfData() - }, (err) => { - console.log(err); - this.notificationFailed(notificationModel); - }) - } - - //delete PnfItem - deletePnfService(index, pkgid, notificationModel) { - this.myhttp.deletePnfIdData(pkgid) + deleteService(pkgid, resolve) { + let API: string; + if(this.currentTab === 'NS'){ + API = 'deleteNsIdData'; + }else if(this.currentTab === 'VNF'){ + API = 'deleteVnfIdData'; + }else{ + API = 'deletePnfIdData'; + } + this.myhttp[API](pkgid) .subscribe((data) => { + this.notification.notificationSuccess(this.currentTab, 'OnboardingState', pkgid); + resolve() //refresh list after successful deletion - this.notificationSuccess(notificationModel); - this.getTablePnfData() + switch(this.currentTab){ + case 'NS': + this.getTableData(); + break + case 'VNF': + this.getTableVnfData(); + break + case 'PNF': + this.getTablePnfData(); + break + } }, (err) => { console.log(err); - this.notificationFailed(notificationModel); + this.notification.notificationFailed(this.currentTab, 'OnboardingState', pkgid); }) } - } diff --git a/usecaseui-portal/src/app/views/ccvpn-creation/ccvpn-creation.component.css b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.css index efeec683..8ea1b621 100644 --- a/usecaseui-portal/src/app/views/ccvpn-creation/ccvpn-creation.component.css +++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.css @@ -44,14 +44,14 @@ hr { display: inline-block; width: 35px; height: 35px; - background:url("../../../assets/images/Return-icon.png") no-repeat!important; + background:url("../../../../../assets/images/Return-icon.png") no-repeat!important; background-size: 100%!important; border-radius:4px; color: #D7D7D7; cursor: pointer; } .model .back:hover{ - background: url("../../../assets/images/Return-icon-active.png")!important; + background: url("../../../../../assets/images/Return-icon-active.png")!important; background-size: 100%!important; } .top-title h3.title { @@ -109,16 +109,16 @@ hr { } .model .creation .service-title .lable{ display: inline-block; - width: 100px; font: 700 14px "Arial"; color: #3C4F8C; height: 42px; line-height: 42px; vertical-align: middle; margin-left: 5px; + margin-right: 10px; } .model .creation .service-title input { - width: 230px; + width: 20%; height: 42px; border-radius:4px; outline: none; @@ -129,20 +129,14 @@ hr { .model .sitemodel,.model .sotnnpnmodel{ position: absolute; z-index: 1001; - left: 50px; - top: 60px; + left: 50%; + top: 50%; background-color: #fff; - width:1500px; - height: 81%; + width:90%; + min-width: 725px; border-radius:2px; overflow:auto; -} -.model .sotnnpnmodel{ - width: 1000px; - height: 53%; - top:200px; - left: 50%; - margin-left: -500px; + transform: translate(-50%, -50%); } .model .sitemodel h3,.model .sotnnpnmodel h3{ width: 96%; @@ -182,14 +176,14 @@ hr { float: left; } .model .sitemodel .inputs input,.model .sitemodel .inputs nz-select { - width: 186px; + width: 42%; float: right; - margin-right: 60px; + margin-right: 2%; } .model .sotnnpnmodel .inputs input{ - width: 186px; - float: left; - margin-left: 20px; + width: 42%; + float: right; + margin-right: 2%; } .model .sitemodel .action,.model .sotnnpnmodel .action { text-align: center; diff --git a/usecaseui-portal/src/app/views/ccvpn-creation/ccvpn-creation.component.html b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.html index 1fc9a500..6a05ff11 100644 --- a/usecaseui-portal/src/app/views/ccvpn-creation/ccvpn-creation.component.html +++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.html @@ -81,7 +81,7 @@ </nz-table> </div> </nz-tab> - <nz-tab nzTitle="Sdwansiteresource List"> + <nz-tab nzTitle="Sdwansiteresource List" nzVirtualScroll> <div class="site"> <div style="height: 10px"> <h3 style="float: left;color: #3C4F8C">Site List</h3> @@ -90,12 +90,12 @@ style="transform: scale(1.2);font-weight: 700"></i>{{"i18nTextDefine_Add" | translate}} </button> </div> - <nz-table #siteTable [nzData]="siteTableData" [nzShowPagination]="false" nzSize="small"> + <nz-table #siteTable [nzData]="siteTableData" [nzShowPagination]="false" nzSize="small" nzVirtualScroll [nzScroll]="siteTableWidth"> <thead> <tr> - <th nzWidth="10%"> NO.</th> + <th nzWidth="10%" nzLeft="0px"> NO.</th> <th *ngFor="let key of getKeys(this.siteBaseData)">{{key.split("_")[1] || key}}</th> - <th nzWidth="20%" style="text-align: center"> Action</th> + <th nzWidth="20%" style="text-align: center" nzRight="0px"> Action</th> </tr> </thead> <tbody> @@ -234,17 +234,17 @@ style="transform: scale(1.2);font-weight: 700;"></i>{{"i18nTextDefine_Add" | translate}} </button> </div> - <table class="siteWanTab"> + <nz-table class="siteWanTab" nzVirtualScroll #nzTable [nzData]="siteWanData" [nzScroll]="{ x: '2500px'}"> <thead> <tr> - <th width="4%"> NO.</th> + <th width="4%" nzLeft="0px"> NO.</th> <th *ngFor="let key of getKeys(this.siteWanParams)">{{key}}</th> - <th width="7%"> Action</th> + <th width="7%" nzRight="0px"> Action</th> </tr> </thead> <tbody> - <tr *ngFor="let item of siteWanData; let i = index;" - [ngClass]="{'tr-border':item.tabInputShowWanPort ==false}"> + <ng-template ngFor let-item [ngForOf]="nzTable.data" let-i="index"> + <tr [ngClass]="{'tr-border':item.tabInputShowWanPort ==false}"> <td>{{i+1}}</td> <td *ngFor="let key of getKeys(item);let a = index;"> <span *ngIf="!tabInputShowWanPort[i]" @@ -260,8 +260,9 @@ class="anticon anticon-delete"></i></span> </td> </tr> + </ng-template> </tbody> - </table> + </nz-table> </div> </div> diff --git a/usecaseui-portal/src/app/views/ccvpn-creation/ccvpn-creation.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.spec.ts index 30402412..30402412 100644 --- a/usecaseui-portal/src/app/views/ccvpn-creation/ccvpn-creation.component.spec.ts +++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.spec.ts diff --git a/usecaseui-portal/src/app/views/ccvpn-creation/ccvpn-creation.component.ts b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.ts index cb1c61df..752fddd6 100644 --- a/usecaseui-portal/src/app/views/ccvpn-creation/ccvpn-creation.component.ts +++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.ts @@ -15,7 +15,8 @@ */ import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; import * as d3 from 'd3'; -import { MyhttpService } from '../../core/services/myhttp.service'; +import { ServiceListService } from '../../../../core/services/serviceList.service'; +import {Observable} from "../../../../../../node_modules/rxjs"; @Component({ selector: 'app-ccvpn-creation', @@ -24,24 +25,31 @@ import { MyhttpService } from '../../core/services/myhttp.service'; }) export class CcvpnCreationComponent implements OnInit { - constructor(private myhttp: MyhttpService) { } + constructor(private myhttp: ServiceListService) { } @Input() createParams; @Input() ccvpn_temParametersContent; @Output() closeCreate = new EventEmitter(); + ngOnInit() { this.getccvpnTemParameters(this.ccvpn_temParametersContent); + Observable.fromEvent(window, 'resize').subscribe((event) => { + this.siteTableWidth["x"] = document.documentElement.clientWidth > 1400 ?"78%":"961px"; + }); } //tabBarStyle - tabBarStyle = { + tabBarStyle: object = { "height": "58px", "width": "694px", "box-shadow": "none", "margin": "0", "border-radius": "4px 4px 0px 0px" }; - templateParameters = { + siteTableWidth: object = { + x:"" + }; + templateParameters: any = { service: {}, sotnvpn: { info: {}, @@ -56,31 +64,31 @@ export class CcvpnCreationComponent implements OnInit { } }; - bodyTemplateParameter = {}; + bodyTemplateParameter: object = {}; // SOTN VPN List - sotnVpnTableData = []; - sotnInfo = {};//sotnmodel The first part of sotnInfo - sotnSdwansitelanData = [];//sotnmodel The second part of the data sdwansitelan Table - sotnSdwansitelanParams = {};//sdwansitelan Table Detailed parameters of each line of data - tabInputShowSdwansitelan = [];//sdwansitelan Table input&span The status identifier of the label switching display + sotnVpnTableData: any[] = []; + sotnInfo: object = {};//sotnmodel The first part of sotnInfo + sotnSdwansitelanData: any[] = [];//sotnmodel The second part of the data sdwansitelan Table + sotnSdwansitelanParams: object = {};//sdwansitelan Table Detailed parameters of each line of data + tabInputShowSdwansitelan: any[] = [];//sdwansitelan Table input&span The status identifier of the label switching display // Site List - siteTableData = []; - siteBaseData = {}; //sitemodel one sdwansiteresource_list + siteTableData: any[] = []; + siteBaseData: object = {}; //sitemodel one sdwansiteresource_list // cpe - siteSdwanDevice = []; //sitemodel SdwanDevice port Table data - siteCpeData = {}; //sitemodel two sdwandevice_list - tabInputShowDevice = [];//Device port Table input和span The status identifier of the label switching display + siteSdwanDevice: any[] = []; //sitemodel SdwanDevice port Table data + siteCpeData: object = {}; //sitemodel two sdwandevice_list + tabInputShowDevice: any[] = [];//Device port Table input和span The status identifier of the label switching display // Wan Port - siteWanData = []; //sitemodel three wan port Table data - siteWanParams = {}; //wan port Table Detailed parameters of each line of data - tabInputShowWanPort = [];//wan port Table input和span The status identifier of the label switching display + siteWanData: any[] = []; //sitemodel three wan port Table data + siteWanParams: object = {}; //wan port Table Detailed parameters of each line of data + tabInputShowWanPort: any[] = [];//wan port Table input和span The status identifier of the label switching display getKeys(item) { return Object.keys(item); } getccvpnTemParameters(data) { //Get template parameters - if (typeof data["model"] == 'string') { + if (data.hasOwnProperty("model") && typeof data["model"] == 'string') { data = JSON.parse(data["model"]); } let inputss = data["inputs"]; @@ -260,19 +268,19 @@ export class CcvpnCreationComponent implements OnInit { //add,edit,delete SdwanDevice addSdwanDevice() { - if (this.tabInputShowDevice.indexOf(true) > -1) {//当有正在编辑的一行数据时,不允许添加新的行 + if (this.tabInputShowDevice.indexOf(true) > -1) {//Adding new rows is not allowed when there is a row of data being edited return false; } let addNum = this.siteSdwanDevice.length; let inputsData = Object.assign({}, this.siteCpeData); - Object.keys(inputsData).forEach((item) => {//新增一行空数据 + Object.keys(inputsData).forEach((item) => {//Add a new line of empty data if (item != "description") { inputsData[item] = null; } }); this.siteSdwanDevice[addNum] = inputsData; this.tabInputShowDevice[addNum] = true; - this.siteSdwanDevice = [...this.siteSdwanDevice]; //表格刷新 + this.siteSdwanDevice = [...this.siteSdwanDevice]; //Table refresh } editDevicePort(num, item, siteSdwanDevice) { diff --git a/usecaseui-portal/src/app/views/ccvpn-detail/ccvpn-detail.component.css b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.css index d5ad960d..8d005d40 100644 --- a/usecaseui-portal/src/app/views/ccvpn-detail/ccvpn-detail.component.css +++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.css @@ -58,14 +58,14 @@ hr { display: inline-block; width: 35px; height: 35px; - background:url("../../../assets/images/Return-icon.png") no-repeat!important; + background:url("../../../../../assets/images/Return-icon.png") no-repeat!important; background-size: 100%!important; border-radius:4px; color: #D7D7D7; cursor: pointer; } .model .back:hover{ - background: url("../../../assets/images/Return-icon-active.png")!important; + background: url("../../../../../assets/images/Return-icon-active.png")!important; background-size: 100%!important; } .top-title h3.title { @@ -156,34 +156,28 @@ hr { float: left; } .model .sitemodel .inputs input,.model .sitemodel .inputs nz-select{ - width: 186px; + width: 42%; float: right; - margin-right: 60px; + margin-right: 2%; } .model .sotnnpnmodel .inputs input{ - width: 186px; - float: left; - margin-left: 20px; + width: 42%; + float: right; + margin-right: 2%; } /* addsite model */ .model .sitemodel,.model .sotnnpnmodel{ position: absolute; z-index: 1001; - left: 50px; - top: 60px; + left: 50%; + top: 50%; background-color: #fff; - width:1500px; - height: 81%; + width:90%; + min-width: 725px; border-radius:2px; overflow:auto; -} -.model .sotnnpnmodel{ - width: 1000px; - height: 53%; - top:200px; - left: 50%; - margin-left: -500px; + transform: translate(-50%, -50%); } .model .sitemodel h3,.model .sotnnpnmodel h3{ width: 96%; @@ -223,14 +217,14 @@ hr { float: left; } .model .sitemodel .inputs input,.model .sitemodel .inputs nz-select{ - width: 186px; + width: 42%; float: right; - margin-right: 60px; + margin-right: 2%; } .model .sotnnpnmodel .inputs div{ - width: 186px; - float: left; - margin-left: 20px; + width: 42%; + float: right; + margin-right: 2%; } .model .sitemodel .action,.model .sotnnpnmodel .action { text-align: center; diff --git a/usecaseui-portal/src/app/views/ccvpn-detail/ccvpn-detail.component.html b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.html index e2b5159e..e2b5159e 100644 --- a/usecaseui-portal/src/app/views/ccvpn-detail/ccvpn-detail.component.html +++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.html diff --git a/usecaseui-portal/src/app/views/ccvpn-detail/ccvpn-detail.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.spec.ts index 3d112bf8..b6f3171f 100644 --- a/usecaseui-portal/src/app/views/ccvpn-detail/ccvpn-detail.component.spec.ts +++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.spec.ts @@ -20,7 +20,7 @@ import { NZ_I18N, en_US } from 'ng-zorro-antd'; import { TranslateModule, TranslateLoader, TranslateService, TranslateFakeLoader } from '@ngx-translate/core'; import { CcvpnDetailComponent } from './ccvpn-detail.component'; -import { MyhttpService } from '../../core/services/myhttp.service'; +import { ServiceListService } from '../../core/services/serviceList.service'; describe('CcvpnDetailComponent', () => { let component: CcvpnDetailComponent; @@ -31,7 +31,7 @@ describe('CcvpnDetailComponent', () => { declarations: [CcvpnDetailComponent], imports: [TranslateModule.forRoot({ loader: { provide: TranslateLoader, useClass: TranslateFakeLoader } }), NgZorroAntdModule.forRoot(), HttpClientModule], - providers: [MyhttpService, { provide: NZ_I18N, useValue: en_US }] + providers: [ServiceListService, { provide: NZ_I18N, useValue: en_US }] }) .compileComponents(); })); diff --git a/usecaseui-portal/src/app/views/ccvpn-detail/ccvpn-detail.component.ts b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.ts index 8e4d6f1d..a253b044 100644 --- a/usecaseui-portal/src/app/views/ccvpn-detail/ccvpn-detail.component.ts +++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.ts @@ -14,7 +14,7 @@ limitations under the License. */ import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; -import { MyhttpService } from '../../core/services/myhttp.service'; +import { ServiceListService } from '../../../../core/services/serviceList.service'; import * as d3 from 'd3'; @Component({ @@ -24,7 +24,7 @@ import * as d3 from 'd3'; }) export class CcvpnDetailComponent implements OnInit { - constructor(private myhttp: MyhttpService) { } + constructor(private myhttp: ServiceListService) { } ngOnInit() { this.dataInit(); diff --git a/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.html b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.html new file mode 100644 index 00000000..e093b3b8 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.html @@ -0,0 +1,59 @@ +<nz-modal nzWidth="428" [(nzVisible)]="isVisible" nzTitle=" {{'i18nTextDefine_ServiceCreation' | translate}} " + (nzOnCancel)="handleCancel()" + (nzOnOk)="handleOk()" nzClassName="serviceCreationModel" + nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} " + nzOkText=" {{'i18nTextDefine_modelOk' | translate}} " +> + <div class="select-list"> + <span> {{"i18nTextDefine_Customer" | translate}} : </span> + <nz-select [(ngModel)]="currentCustomer.name" nzAllowClear + (ngModelChange)="customerChange()"> + <nz-option *ngFor="let item of customerList" [nzValue]="item.name" [nzLabel]="item.name"></nz-option> + </nz-select> + </div> + <div class="select-list"> + <span> {{"i18nTextDefine_ServiceType" | translate}} : </span> + <nz-select [(ngModel)]="currentServiceType.name" nzAllowClear> + <nz-option *ngFor="let item of serviceTypes" [nzValue]="item.name" [nzLabel]="item.name"> + </nz-option> + </nz-select> + </div> + <div class="select-list"> + <span> {{"i18nTextDefine_UseCase" | translate}} : </span> + <nz-select [(ngModel)]="templateTypeSelected" nzAllowClear + (ngModelChange)="choseTemplateType()"> + <nz-option nzValue="SOTN" nzLabel="SOTN"></nz-option> + <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-select> + </div> + <div class="select-list"> + <span> {{"i18nTextDefine_Template" | translate}} : </span> + <nz-select [(ngModel)]="currentTemplate" nzAllowClear> + <nz-option *ngFor="let item of templates" [nzValue]="item" [nzLabel]="item.name"></nz-option> + </nz-select> + </div> + <div *ngIf="templateTypeSelected === 'E2E Service'"> + <div class="select-list"> + <span> {{"i18nTextDefine_Orchestrator" | translate}} : </span> + <nz-select [(ngModel)]="orchestratorSelected" nzAllowClear> + <nz-option *ngFor="let item of orchestratorList" [nzValue]="item" [nzLabel]="item.name"></nz-option> + </nz-select> + </div> + <div class="checkbox select-list"> + <span>Sol005 :</span> + <input type="checkbox" + [(ngModel)]="isSol005Interface" value="true" nzAllowClear> + + </div> + </div> + <div class="select-list" *ngIf="temParametersTips"> + {{"i18nTextDefine_Templateparsingfailed" | translate}} + </div> +</nz-modal> +<div class="loading" *ngIf="loadingAnimateShow"> + <img src="assets/images/loading-animate2.gif" alt="loading"> + <p>Please wating……</p> +</div> + diff --git a/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.less b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.less new file mode 100644 index 00000000..fdee93c8 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.less @@ -0,0 +1,59 @@ +.select-list{
+ width: 320px;
+ height: 32px;
+ line-height: 32px;
+ margin: 35px auto;
+ .select-list>span{
+ display:inline-block;
+ text-align: right;
+ line-height: 32px;
+ }
+ nz-select{
+ width: 176px;
+ float: right;
+ }
+ &.checkbox{
+ margin: 0 auto;
+ line-height: 32px;
+ input[type="checkbox"]{
+ zoom: 1.3;
+ width: 140px;
+ }
+ }
+}
+::ng-deep nz-modal button.ant-btn {
+ margin-top:20px !important;
+}
+
+.loading{
+ width: 100%;
+ height: 100%;
+ position: fixed;
+ top: 0;
+ margin-top: -50px;
+ margin-left: -50px;
+ z-index: 1001;
+ text-align: center;
+ background: transparent;
+ p{
+ color: #0DA9E2;
+ text-align: center;
+ position: absolute;
+ width: 300px;
+ height: 30px;
+ line-height: 30px;
+ top: 71%;
+ left: 36%;
+ margin-top: -150px;
+ margin-left: -150px;
+ }
+ img{
+ width: 300px;
+ height: 300px;
+ position: absolute;
+ top: 50%;
+ left: 36%;
+ margin-top: -150px;
+ margin-left: -150px;
+ }
+}
diff --git a/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.spec.ts new file mode 100644 index 00000000..fd57b3a7 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.spec.ts @@ -0,0 +1,26 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateModelComponent } from './create-model.component'; + +describe('CreateModelComponent', () => { + let component: CreateModelComponent; + let fixture: ComponentFixture<CreateModelComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CreateModelComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateModelComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); + diff --git a/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.ts b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.ts new file mode 100644 index 00000000..f7cce450 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.ts @@ -0,0 +1,144 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { ServiceListService } from '../../../../core/services/serviceList.service'; + +@Component({ + selector: 'app-create-model', + templateUrl: './create-model.component.html', + styleUrls: ['./create-model.component.less'], +}) +export class CreateModelComponent implements OnInit { + @Input()isVisible: boolean; + @Input()customerList; + @Input()serviceTypeList; + @Input()customerSelected; + @Input()serviceTypeSelected; + + @Output() cancel = new EventEmitter<boolean>(); + @Output() createdModalShow = new EventEmitter<any>(); + + serviceTypes: any[]; + currentCustomer: any; + currentServiceType: any; + templateTypeSelected:string = "CCVPN"; + templates: any[] = []; + currentTemplate: object = { name: null }; + orchestratorList: any[] = []; + orchestratorSelected: object = { name: null, id: null }; + isSol005Interface: boolean = false; + temParametersTips: boolean = false; + createData: Object = {}; + loadingAnimateShow: boolean = false; + + constructor( private http: ServiceListService) {} + + ngOnInit() { + this.serviceTypes = this.serviceTypeList; + this.currentCustomer = JSON.parse(JSON.stringify(this.customerSelected)); + this.currentServiceType = JSON.parse(JSON.stringify(this.serviceTypeSelected)); + this.getAlltemplates(); + } + + getServiceType(): void{ + this.http.getServiceTypes(this.currentCustomer) + .subscribe((data) => { + this.serviceTypes = data.map((item) => { + return { name: item["service-type"] } + }); + }) + } + + getAlltemplates() { + this.http.getAllServiceTemplates(this.templateTypeSelected) + .subscribe((data) => { + this.templates = data; + if (this.templateTypeSelected == "Network Service") { + this.templates = data.filter((d) => { + return typeof d.packageInfo.csarName == "string"; + }).map((item) => { + let cName = item.packageInfo.csarName.split("/").reverse()[0]; + return { name: cName, id: item.csarId, packageInfo: item.packageInfo } + }); + } + this.currentTemplate = this.templates[0]; + }, (err) => { + console.log(err); + }) + } + + getallOrchestrators() { + this.http.getAllOrchestrators() + .subscribe((data) => { + if(data.length > 0){ + this.orchestratorList = data.map((item) => { + return { name: item["name"], id: item["name"] } + }); + this.orchestratorSelected = this.orchestratorList[0]; + } + }) + } + + handleCancel(): void { + this.isVisible = false; + this.cancel.emit(false); + this.loadingAnimateShow = false; + } + + customerChange(): void { + this.getServiceType(); + } + + choseTemplateType() { + if(this.templateTypeSelected === 'E2E Service'){ + this.getallOrchestrators(); + } + this.getAlltemplates(); + } + + handleOk(): void { + if (this.templateTypeSelected === "SOTN" || this.templateTypeSelected === "CCVPN") { + this.createData = { + commonParams: { + customer: this.currentCustomer, + serviceType: this.currentServiceType, + templateType: this.templateTypeSelected + }, + template: this.currentTemplate + }; + } else if (this.templateTypeSelected === "E2E Service" || this.templateTypeSelected === "Network Service") { + this.createData = { + commonParams: { + customer: this.currentCustomer, + serviceType: this.currentServiceType, + templateType: this.templateTypeSelected + }, + template: this.currentTemplate, + orchestrator: this.orchestratorSelected, + isSol005Interface: this.isSol005Interface + }; + } + this.getTemParameters(); + } + + getTemParameters() { + let chosedtemplates = this.createData["template"]; + let types = this.createData["commonParams"].templateType; + if (types == "E2E Service") { + types = "e2e"; + } else if (types == "Network Service") { + types = "ns"; + } + this.loadingAnimateShow = true; + this.http.getTemplateParameters(types, chosedtemplates) + .subscribe((data) => { + this.loadingAnimateShow = false; + if (data.status == "FAILED") { + this.temParametersTips = true; + this.isVisible = true; + } else { + this.cancel.emit(false); + this.temParametersTips = false; + this.createdModalShow.emit({templateType: this.templateTypeSelected, data, createData: this.createData}) + } + }) + } +}
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.html b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.html new file mode 100644 index 00000000..5b516a0f --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.html @@ -0,0 +1,34 @@ +<nz-modal nzWidth="428" [(nzVisible)]="deleteModalVisible" nzTitle=" {{'i18nTextDefine_delete' | translate}}" + (nzOnCancel)="deleteCancel()" (nzOnOk)="deleteOk()" + nzClassName="{{thisService['serviceDomain'] == 'Network Service'?'nsdeleteModel':'deleteModel'}}" + nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} " + nzOkText=" {{'i18nTextDefine_modelOk' | translate}} "> + <h3><span style="color: red">* </span> {{"i18nTextDefine_SureDelete" | translate}} </h3> + <div class="question"> + <h4> {{"i18nTextDefine_InstanceName" | translate}} :</h4> + <div class="deleteModelContent">{{ thisService["service-instance-name"] || + thisService["nsInstanceName"] }} + </div> + </div> + <div class="question"> + <h4> {{"i18nTextDefine_InstanceID" | translate}} :</h4> + <div class="deleteModelContent">{{ thisService["service-instance-id"] || + thisService["nsInstanceId"] }} + </div> + </div> + <div *ngIf="thisService['serviceDomain'] == 'Network Service'"> + <div class="question"> + <h4> {{"i18nTextDefine_terminationType" | translate}} :</h4> + <nz-select style="width: 306px;" [(ngModel)]="terminationType"> + <nz-option nzValue="graceful" nzLabel=" {{'i18nTextDefine_graceful' | translate}} "></nz-option> + <nz-option nzValue="forceful" nzLabel=" {{'i18nTextDefine_forceful' | translate}} "></nz-option> + </nz-select> + </div> + <div class="question"> + <h4 *ngIf="terminationType=='graceful'"> {{"i18nTextDefine_gracefulTerminationTimeout" | translate}} + :</h4> + <input *ngIf="terminationType=='graceful'" style="width: 306px;" nz-input + [(ngModel)]="gracefulTerminationTimeout"> + </div> + </div> +</nz-modal> diff --git a/usecaseui-portal/src/app/views/services/services.component.less b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.less index e69de29b..e69de29b 100644 --- a/usecaseui-portal/src/app/views/services/services.component.less +++ b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.less diff --git a/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.spec.ts new file mode 100644 index 00000000..e5e94c94 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DeleteModelComponent } from './delete-model.component'; + +describe('DeleteModelComponent', () => { + let component: DeleteModelComponent; + let fixture: ComponentFixture<DeleteModelComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DeleteModelComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DeleteModelComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.ts b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.ts new file mode 100644 index 00000000..f9bf9a9c --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.ts @@ -0,0 +1,42 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; + +@Component({ + selector: 'app-delete-model', + templateUrl: './delete-model.component.html', + styleUrls: ['./delete-model.component.less'] +}) +export class DeleteModelComponent implements OnInit { + @Input()deleteModalVisible: boolean; + @Input()thisService; + @Input()terminationType; + @Input()loadingAnimateShow; + @Input()templateDeleteSuccessFaild; + @Input()gracefulTerminationTimeout; + + @Output() cancel = new EventEmitter<boolean>(); + @Output() deleteModalOK = new EventEmitter<any>(); + + constructor() { } + + ngOnInit() { + } + + deleteOk() { + this.deleteModalVisible = false; + this.loadingAnimateShow = true; + + if (this.thisService["serviceDomain"] === "Network Service") { + this.deleteModalOK.emit({ + terminationType: this.terminationType, + gracefulTerminationTimeout: this.gracefulTerminationTimeout + }) + } else { + this.deleteModalOK.emit() + } + } + deleteCancel() { + this.deleteModalVisible = false; + } + + +} diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.css b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.css new file mode 100644 index 00000000..5dce6c92 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.css @@ -0,0 +1,77 @@ +/* + 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; +} diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.html b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.html new file mode 100644 index 00000000..da673bf0 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.html @@ -0,0 +1,139 @@ +<!-- + 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. +--> +<!--<h3 class="title"> Services List </h3>--> +<div class="model creation-model"> + <!-- Create data --> + <div class="top-title"> + <h3 class="title fl">{{createParams.commonParams.templateType}} {{"i18nTextDefine_InstanceCreation" | translate}} </h3> + <div class="fl" style="width: 20%"> + <button class="submit" nz-button (click)="submit()"> + <span> {{"i18nTextDefine_Create" | translate}} </span> + </button> + <button class="back" nz-button (click)="goback()"></button> + </div> + </div> + <div class="e2ecreate-content"> + <div class="creation fl"> + <div *ngIf="createParams.commonParams.templateType=='E2E Service'" class="baseparms clearfix"> + <div class="vnf-box"> + <h3> {{"i18nTextDefine_Base" | translate}} </h3> + <ul class="clearfix"> + <li> + <span>Name:</span> + <input nz-input [(ngModel)]="service.name"> + </li> + <li> + <span>Description:</span> + <input nz-input [(ngModel)]="service.description"> + </li> + <li> + <span>COS:</span> + <input nz-input [(ngModel)]="service.COS"> + </li> + <li> + <span>EBS:</span> + <input nz-input [(ngModel)]="service.EBS"> + </li> + </ul> + </div> + <div class="vnf-box" *ngIf="templateParameters.inputs.length>0"> + <h3>{{"i18nTextDefine_templateInputs" | translate}}</h3> + <ul> + <li *ngFor="let parameter of templateParameters.inputs; let i = index;"> + <span *ngIf="parameter.type !== 'vf_location' && parameter.type !== 'sdn_controller'" title="{{parameter.name}}">{{parameter.name}}:</span> + <input *ngIf="parameter.type !== 'vf_location' && parameter.type !== 'sdn_controller'" nz-input [(ngModel)]="parameter.value"> + + <h5 *ngIf="parameter.type === 'vf_location'" style="padding-left:10px;">id: {{parameter.name}} + </h5> + <span *ngIf="parameter.type === 'vf_location'"> vf_location: </span> + <nz-select *ngIf="parameter.type === 'vf_location'" [(ngModel)]="parameter.value" nzAllowClear> + <nz-option *ngFor="let vim of vimInfos" [nzValue]="vim" [nzLabel]="vim.name"></nz-option> + </nz-select> + </li> + </ul> + </div> + <div class="vnf-box" *ngFor="let template of templateParameters.nestedTemplates;"> + <h3>{{template.name}}</h3> + <ul> + <li *ngFor="let input of template.inputs; let i = index;"> + <span *ngIf="input.type !== 'vf_location' && input.type !== 'sdn_controller'" title="{{input.name}}"> {{input.name}}: </span> + <input *ngIf="input.type !== 'vf_location' && input.type !== 'sdn_controller'" nz-input [(ngModel)]="input.value"> + + <h5 *ngIf="input.type === 'vf_location'" style="padding-left:10px;">id: {{input.name}}</h5> + <span *ngIf="input.type === 'vf_location'"> vf_location: </span> + <nz-select *ngIf="input.type === 'vf_location'" [(ngModel)]="input.value" nzAllowClear> + <nz-option *ngFor="let vim of vimInfos" [nzValue]="vim" [nzLabel]="vim.name"></nz-option> + </nz-select> + </li> + </ul> + </div> + </div> + + <div *ngIf="createParams.commonParams.templateType=='Network Service'" class="baseparms clearfix"> + <div class="vnf-box"> + <h3> {{"i18nTextDefine_Base" | translate}} </h3> + <ul class="clearfix"> + <li> + <span>Name:</span> + <input nz-input [(ngModel)]="ns_service.nsName"> + </li> + <li> + <span>Description:</span> + <input nz-input [(ngModel)]="ns_service.description"> + </li> + </ul> + </div> + <div class="vnf-box" *ngIf="nsTemplateParameters.inputs2.length>0"> + <h4>{{"i18nTextDefine_templateInputs" | translate}}</h4> + <ul> + <li *ngFor="let parameter of nsTemplateParameters.inputs2; let i = index;"> + <span *ngIf="parameter.type !== 'vf_location' && parameter.type !== 'sdn_controller'" title="{{parameter.name}}">{{parameter.name}}:</span> + <input *ngIf="parameter.type !== 'vf_location' && parameter.type !== 'sdn_controller'" nz-input [(ngModel)]="parameter.value"> + + <h5 *ngIf="parameter.type === 'vf_location'" style="padding-left:10px;">id: {{parameter.name}} + </h5> + <span *ngIf="parameter.type === 'vf_location'"> vf_location: </span> + <nz-select *ngIf="parameter.type === 'vf_location'" [(ngModel)]="parameter.value" nzAllowClear> + <nz-option *ngFor="let vim of vimInfos" [nzValue]="vim" [nzLabel]="vim.name"></nz-option> + </nz-select> + </li> + </ul> + </div> + <div class="vnf-box"> + <h4 *ngIf="nsTemplateParameters.vnfs.length>0">vnfs Inputs</h4> + <ul> + <li *ngFor="let vnf of nsTemplateParameters.vnfs;"> + <h5 style="padding-left:10px;">id: {{vnf.vnf_id}}</h5> + <span> vf_location: </span> + <nz-select [(ngModel)]="vnf.value" nzAllowClear> + <nz-option *ngFor="let vim of vimInfos" [nzValue]="vim" [nzLabel]="vim.name"></nz-option> + </nz-select> + </li> + </ul> + </div> + </div> + </div> + <div class="dividing-line fl"></div> + <!-- chart --> + <div class="chart fr"> + <div id="createChart"> + <svg width="100%" height="100%"> + </svg> + </div> + </div> + </div> + +</div>
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.less b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.less new file mode 100644 index 00000000..3679079e --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.less @@ -0,0 +1,161 @@ +/* + 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: #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/e2e-creation/e2e-creation.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.spec.ts new file mode 100644 index 00000000..de00c43f --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { E2eCreationComponent } from './e2e-creation.component'; + +describe('E2eCreationComponent', () => { + let component: E2eCreationComponent; + let fixture: ComponentFixture<E2eCreationComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ E2eCreationComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(E2eCreationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.ts b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.ts new file mode 100644 index 00000000..f1df9636 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.ts @@ -0,0 +1,357 @@ +/* + 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. +*/ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { ServiceListService } from '../../../../core/services/serviceList.service'; +import * as d3 from 'd3'; + +@Component({ + selector: 'app-e2e-creation', + templateUrl: './e2e-creation.component.html', + styleUrls: ['./e2e-creation.component.less'] +}) +export class E2eCreationComponent implements OnInit { + + constructor(private myhttp: ServiceListService) { } + + ngOnInit() { + this.gete2eTemParameters(this.e2e_ns_temParametersContent); + this.getVimInfo(); + this.getSdnControllers(); + console.log(this.createParams); + } + + @Output() e2eCloseCreate = new EventEmitter(); + @Output() nsCloseCreate = new EventEmitter(); + @Input() createParams; + @Input() e2e_ns_temParametersContent; + + + // e2e serviceTemplateParameters + templateParameters = { + invariantUUID: "", + uuid: "", + name: "", + type: "", + version: "", + description: "", + category: "", + subcategory: "", + customizationUuid: "", + inputs: [], + nestedTemplates: [] + }; + // ns serviceTemplateParameters + nsTemplateParameters = { + inputs: {}, + inputs2: [], + vnfs: [] + } + roote2e = { + "name": "e2e", + "type": "e2e", + "children": [] + }; + + rootns = { + "name": "ns", + "type": "ns", + "children": [] + }; + + imgmap = { + '1': '../../../../assets/images/create-e2e.png', + '2': '../../../../assets/images/create-ns.png', + '3': '../../../../assets/images/create-vnf.png', + }; + gete2eTemParameters(data) { //Get template parameters + let type = this.createParams.commonParams.templateType == "E2E Service" ? "e2e" : "ns"; + console.log(this.createParams); + console.log(data); + if (type == "e2e") { + this.templateParameters = data; + this.templateParameters.nestedTemplates.forEach((item) => { + item.inputs = item.inputs.filter((input) => { return input.type !== "sdn_controller" }); + }) + this.templateParameters.nestedTemplates.map((item, index) => { + let nsIndex = { + "name": "ns", + "type": "ns", + "children": [] + }; + nsIndex.children = item.nestedTemplates.map((item, index) => { + return { + "name": "vnf", + "type": "vnf", + } + }); + this.roote2e.children.push(nsIndex); + }); + console.log(this.templateParameters); + console.log(this.roote2e) + } else if (type == "ns") { + if (data["model"] != undefined && typeof data["model"] == 'string') { + this.nsTemplateParameters = JSON.parse(data["model"]); + console.log(data["model"]); + } else { + this.nsTemplateParameters = data; + } + console.log(this.nsTemplateParameters); + this.nsTemplateParameters["inputs2"] = []; + let inputs = this.nsTemplateParameters.inputs; + for (let key in inputs) { + this.nsTemplateParameters["inputs2"].push({ name: key, type: inputs[key].type, value: inputs[key].value }) + } + this.rootns.children = this.nsTemplateParameters.vnfs.map((item, index) => { + return { + "name": "vnf", + "type": "vnf", + } + }); + console.log(this.nsTemplateParameters); + } + + this.drawImage(type) + + } + vimInfos = []; + getVimInfo() { + this.myhttp.getVimInfo() + .subscribe((data) => { + this.vimInfos = data.map((item) => { return { name: item['cloud-owner'], id: item['cloud-region-id'] } }); + }) + }; + sdnControllers = []; + getSdnControllers() { + this.myhttp.getSdnControllers() + .subscribe((data) => { + this.sdnControllers = data.map((item) => { return { name: item['thirdparty-sdnc-id'], id: item['thirdparty-sdnc-id'] } }); + }) + } + + // e2e requstbody + service = { + name: "", + description: "", + COS: "", + EBS: "", + serviceInvariantUuid: "", + serviceUuid: "", // uuid ?? + globalSubscriberId: "", // "customer.id", + serviceType: "", // "serviceType.value", + parameters: { + locationConstraints: [ + + ], + resources: [], + requestInputs: {}, + } + + } + + // ns requstbody + ns_service = { + csarId: "", + nsName: "", + description: "", + context: { + globalCustomerId: "", + serviceType: "" + } + } + ns_service2 = { + locationConstraints: [ + + ], + additionalParamForNs: { + } + } + submit() { + let type = this.createParams.commonParams.templateType == "E2E Service" ? "e2e" : "ns"; + if (type == "e2e") { + this.service.serviceInvariantUuid = this.templateParameters.invariantUUID; + 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; + }) + + this.templateParameters.nestedTemplates.forEach((item) => { + let nsService = { + resourceName: item.name, + resourceInvariantUuid: item.invariantUUID, + resourceUuid: item.uuid, + resourceCustomizationUuid: item.customizationUuid, + parameters: { + locationConstraints: [], + resources: [], + requestInputs: {} + } + } + item.inputs.forEach((input) => { + if (input.type == "vf_location") { + let location = { + vnfProfileId: input.name, + locationConstraints: { + cloudOwner: input.value.name, + cloudRegionId: input.value.id + } + } + nsService.parameters.locationConstraints.push(location); + } else { + nsService.parameters.requestInputs[input.name] = input.value == undefined ? input.defaultValue : input.value; + } + }) + this.service.parameters.resources.push(nsService); + }) + console.log(this.service) + this.service.parameters.requestInputs['orchestrator'] = this.createParams.orchestrator.name; + if (this.createParams.isSol005Interface) { + this.service.parameters.requestInputs['isSol005Interface'] = this.createParams.isSol005Interface; + } + this.e2eCloseCreate.emit({ service: this.service }); + + } else if (type == "ns") { + //create ns instance + this.ns_service.csarId = this.createParams.template.id; + this.ns_service.context.globalCustomerId = this.createParams.commonParams.customer.id; + this.ns_service.context.serviceType = this.createParams.commonParams.serviceType.name; + + this.nsTemplateParameters.inputs2.forEach((input) => { + this.ns_service2.additionalParamForNs[input.name] = input.value == undefined ? input.defaultValue : input.value; + }) + this.nsTemplateParameters.vnfs.forEach((vnf) => { + let vnfparams = { + vnfProfileId: vnf.properties.id, + locationConstraints: { + cloudOwner: vnf.value.name, + cloudRegionId: vnf.value.id + } + } + this.ns_service2.locationConstraints.push(vnfparams); + }) + console.log(this.ns_service2); + + let requstbody = { + step1: this.ns_service, + step2: this.ns_service2 + } + this.nsCloseCreate.emit(requstbody); + } + + } + goback() { + this.e2eCloseCreate.emit(); + } + + + + drawImage(type) { + if (type == "e2e") { + this.render(this.roote2e, this.imgmap) + } else if (type == "ns") { + this.render(this.rootns, this.imgmap) + } + + + } + + render(data, imgmap) { + var width = document.getElementById("createChart").clientWidth, + height = document.getElementById("createChart").clientHeight; + var cluster = d3.layout.tree() + .size([width, height]); + var diagonal = d3.svg.diagonal() + .projection(function (d) { + return [d.x - 18, d.y + 40]; + }); + var svg = d3.select("svg"); + + //marker + var marker = + svg.append("marker") + .attr("id", "resolved") + .attr("markerUnits", "strokeWidth") + .attr("markerUnits", "userSpaceOnUse") + .attr("viewBox", "0 -5 10 10") + .attr("refX", 22) + .attr("refY", 0) + .attr("markerWidth", 20) + .attr("markerHeight", 20) + .attr("orient", "auto") + .attr("stroke-width", 1) + .append("circle") + .attr("cx", 5) + .attr("cy", 0) + .attr("r", 2) + .attr("stroke-width", 1) + .style("stroke", "#2F8BF7") + .attr('fill', 'white'); + var i = 0; + var nodes = cluster.nodes(data).reverse(); + nodes.forEach(function (d) { + d.y = d.depth * 200 + 100; + + }); + + var links = cluster.links(nodes); + + var linkEnter = svg.selectAll("path.link") + .data(links); + + linkEnter.enter().append("path") + .attr("class", "link") + .attr("d", diagonal) + .style("stroke", "#2F8BF7") + .style('stroke-width', '1px') + .attr("marker-end", "url(#resolved)") + .style("fill", "none") + // .style("fill-opacity", 1) + .attr("id", function (d, i) { + return "mypath" + i; + }); + + var node = svg.selectAll(".node") + .data(nodes) + .enter() + .append("g") + .attr("class", "node") + .attr("transform", function (d) { + return "translate(" + (d.x + -50) + "," + (d.y) + ")"; + }); + + node.append('image') + .attr('xlink:href', function (d) { + if (d.type == "e2e") { + return imgmap[1]; + } else if (d.type == "ns") { + return imgmap[2]; + } else if (d.type == "vnf") { + return imgmap[3]; + } + + }) + .style('width', '12%') + .style("cursor", "pointer") + .attr("x", 0) + .attr("y", 0) + .attr("rx", 3); + + + } + +} diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.html b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.html new file mode 100644 index 00000000..976a9f6c --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.html @@ -0,0 +1,109 @@ +<!-- + 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. +--> +<!--<h3 class="title"> Services List </h3>--> +<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 *ngIf="detailParams.serviceDomain == 'E2E Service'" 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 class="vnf-box" *ngFor="let template of e2e_nestedTemplates;"> + <h3>{{template.name}}</h3> + <ul class="clearfix"> + <li *ngFor="let input of template.vnfs; let i = index;"> + <span style="width: 26%;min-width: 80px!important"> vf_location: </span> + <span class="input-content">{{input["vf_location"]}}</span> + </li> + </ul> + </div> + </div> + + <div *ngIf="detailParams.serviceDomain=='Network Service'" 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">{{ns_service.name}}</span> + </li> + <li> + <span style="width:25%">Description:</span> + <span class="input-content">{{ns_service.description}}</span> + </li> + </ul> + </div> + <div class="vnf-box" *ngIf="getKeys(ns_requestInputs).length>0"> + <h4>{{"i18nTextDefine_templateInputs" | translate}}</h4> + <ul> + <li *ngFor="let key of getKeys(ns_requestInputs);"> + <span title="{{key}}">{{key}}:</span> + <span class="input-content">{{ns_requestInputs[key]}}</span> + </li> + </ul> + </div> + <div class="vnf-box" *ngIf="ns_nestedTemplates.length>0"> + <h4>vnfs Inputs</h4> + <ul> + <li *ngFor="let vnf of ns_nestedTemplates;"> + <h5> + <span style="width: 26%;min-width: 80px!important"> id: </span> + <span class="input-content"> {{vnf.vnfInstanceId}}</span> + </h5> + <h5> + <span style="width: 26%;min-width: 80px!important"> vf_location: </span> + <span class="input-content">{{vnf["vnfInstanceName"]}}</span> + </h5> + </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/e2e-detail/e2e-detail.component.less b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.less new file mode 100644 index 00000000..ad28a518 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.less @@ -0,0 +1,142 @@ +/* + 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%; + } + } +} diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.spec.ts new file mode 100644 index 00000000..ad24a477 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { E2eDetailComponent } from './e2e-detail.component'; + +describe('E2eDetailComponent', () => { + let component: E2eDetailComponent; + let fixture: ComponentFixture<E2eDetailComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ E2eDetailComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(E2eDetailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.ts b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.ts new file mode 100644 index 00000000..50f63b3e --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.ts @@ -0,0 +1,246 @@ +/* + 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. +*/ + +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { ServiceListService } from '../../../../core/services/serviceList.service'; +import * as d3 from 'd3'; + +@Component({ + selector: 'app-e2e-detail', + templateUrl: './e2e-detail.component.html', + styleUrls: ['./e2e-detail.component.less'] +}) +export class E2eDetailComponent implements OnInit { + + constructor(private myhttp: ServiceListService) { + } + + ngOnInit() { + // this.getDetails(); + this.dataInit(); + } + + @Input() detailParams; + + @Output() closeDetail = new EventEmitter(); + serviceInstanceName: any; + serviceType: any; + input_parameters: any; + nsinput_parameters: any; + + // e2e + service = { + name: "", + description: "", + }; + e2e_nestedTemplates = []; + e2e_requestInputs: any; + + ns_service = { + name: "", + description: "" + } + ns_nestedTemplates = []; + ns_requestInputs = {}; + roote2e = { + "name": "e2e", + "type": "e2e", + "children": [] + }; + + rootns = { + "name": "ns", + "type": "ns", + "children": [] + }; + + imgmap = { + '1': '../../../../assets/images/create-e2e.png', + '2': '../../../../assets/images/create-ns.png', + '3': '../../../../assets/images/create-vnf.png', + }; + + getKeys(item) { + return Object.keys(item); + } + + dataInit() { + console.log(this.detailParams); + this.serviceInstanceName = this.detailParams['service-instance-name'] || this.detailParams["nsName"]; + if (this.detailParams.serviceDomain == 'E2E Service') { + this.input_parameters = JSON.stringify(this.detailParams['input-parameters']); + this.input_parameters = JSON.parse(this.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; + } + if (this.input_parameters.service.parameters.resources != undefined && this.input_parameters.service.parameters.resources.length > 0) { + this.input_parameters.service.parameters.resources.map((item, i) => { + let nestedTemplates = { + name: null, + vnfs: [] + }; + nestedTemplates.name = item.resourceName; + item.parameters.locationConstraints.map((its, k) => { + nestedTemplates.vnfs.push({ + "vf_location": its.locationConstraints.cloudOwner + }) + }); + this.e2e_nestedTemplates.push(nestedTemplates); + + let nsIndex = { + "name": "ns", + "type": "ns", + "children": [] + }; + nsIndex.children = item.parameters.locationConstraints.map((itemits, index) => { + return { + "name": "vnf", + "type": "vnf", + } + }); + this.roote2e.children.push(nsIndex); + }); + console.log(this.e2e_nestedTemplates); + console.log(this.e2e_requestInputs); + console.log(this.roote2e) + } + } else if (this.detailParams.serviceDomain == 'Network Service') { + this.ns_service = { + name: this.detailParams.name || this.detailParams['service-instance-name'], + description: this.detailParams.description || null + }; + if (this.detailParams.requestInputs != undefined && Object.keys(this.detailParams.requestInputs).length > 0) { + this.ns_requestInputs = this.detailParams.requestInputs; + } + this.ns_nestedTemplates = this.detailParams.childServiceInstances; + this.rootns.children = this.ns_nestedTemplates.map((item, index) => { + return { + "name": "vnf", + "type": "vnf" + } + }); + console.log(this.ns_nestedTemplates); + console.log(this.ns_requestInputs); + console.log(this.rootns) + } + this.drawImage(this.detailParams.serviceDomain) + } + + goback() { + this.closeDetail.emit(); + } + + drawImage(type) { + if (type == "E2E Service") { + this.render(this.roote2e, this.imgmap) + } else if (type == "Network Service") { + this.render(this.rootns, this.imgmap) + } + + + } + + render(data, imgmap) { + var width = document.getElementById("createChart").clientWidth, + height = document.getElementById("createChart").clientHeight; + var cluster = d3.layout.tree() + .size([width, height]); + var diagonal = d3.svg.diagonal() + .projection(function (d) { + return [d.x - 18, d.y + 40]; + }); + var svg = d3.select("svg"); + + //marker + var marker = + svg.append("marker") + .attr("id", "resolved") + .attr("markerUnits", "strokeWidth") + .attr("markerUnits", "userSpaceOnUse") + .attr("viewBox", "0 -5 10 10") + .attr("refX", 22) + .attr("refY", 0) + .attr("markerWidth", 20) + .attr("markerHeight", 20) + .attr("orient", "auto") + .attr("stroke-width", 1) + .append("circle") + .attr("cx", 5) + .attr("cy", 0) + .attr("r", 2) + .attr("stroke-width", 1) + .style("stroke", "#2F8BF7") + .attr('fill', 'white'); + var i = 0; + var nodes = cluster.nodes(data).reverse(); + nodes.forEach(function (d) { + d.y = d.depth * 200 + 100; + + }); + + var links = cluster.links(nodes); + + var linkEnter = svg.selectAll("path.link") + .data(links); + + linkEnter.enter().append("path") + .attr("class", "link") + .attr("d", diagonal) + .style("stroke", "#2F8BF7") + .style('stroke-width', '1px') + .attr("marker-end", "url(#resolved)") + .style("fill", "none") + // .style("fill-opacity", 1) + .attr("id", function (d, i) { + return "mypath" + i; + }); + + var node = svg.selectAll(".node") + .data(nodes) + .enter() + .append("g") + .attr("class", "node") + .attr("transform", function (d) { + return "translate(" + (d.x + -50) + "," + (d.y) + ")"; + }); + + node.append('image') + .attr('xlink:href', function (d) { + if (d.type == "e2e") { + return imgmap[1]; + } else if (d.type == "ns") { + return imgmap[2]; + } else if (d.type == "vnf") { + return imgmap[3]; + } + + }) + .style('width', '12%') + .style("cursor", "pointer") + .attr("x", 0) + .attr("y", 0) + .attr("rx", 3); + + + } + + +} diff --git a/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.html b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.html new file mode 100644 index 00000000..0117669f --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.html @@ -0,0 +1,72 @@ +<nz-modal nzWidth="428" [nzVisible]="healModelVisible" nzTitle=" {{'i18nTextDefine_Heal' | translate}} " + (nzOnCancel)="healCancel()" (nzOnOk)="healOk()" + nzClassName="healModel" nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} " + nzOkText=" {{'i18nTextDefine_modelOk' | translate}} "> + <h3><span style="color: red">* </span> {{"i18nTextDefine_SureHeal" | translate}} </h3> + <div class="heal-question"> + <p class="heal-label"> {{"i18nTextDefine_InstanceID" | translate}} : </p> + <div class="healModelContent" title="{{ thisService['service-instance-id'] || thisService['nsInstanceId'] || + thisService['vnfInstanceId']}}"> {{ thisService["service-instance-id"] || + thisService["nsInstanceId"] || + thisService["vnfInstanceId"]}} + </div> + </div> + <!-- NS --> + <div *ngIf="thisService['serviceDomain'] == 'Network Service'"> + <div class="question"> + <p class="heal-label"> {{"i18nTextDefine_degreeHealing" | translate}} :</p> + <nz-select style="width: 200px;height:42px;margin-left: 15px;border-radius: 6px" + [(ngModel)]="nsParams.degreeHealing"> + <nz-option nzValue="HEAL_RESTORE" nzLabel="HEAL_RESTORE"></nz-option> + <nz-option nzValue="HEAL_QOS" nzLabel="HEAL_QOS"></nz-option> + <nz-option nzValue="HEAL_RESET" nzLabel="HEAL_RESET"></nz-option> + <nz-option nzValue="PARTIAL_HEALING" nzLabel="PARTIAL_HEALING"></nz-option> + </nz-select> + </div> + <div> + <span style="display:inline-block;"> {{"i18nTextDefine_actionsHealing" | translate}} :</span> + <button nz-button [nzType]="'default'" (click)="addActionsHealing()"><i + class="anticon anticon-plus-circle-o"></i></button> + <br> + <div *ngFor="let item of healActions;let i = index;" style="display:inline-block;"> + <input style="width: 165px;" nz-input [(ngModel)]="item.value"> + <button nz-button [nzType]="'dashed'" (click)="minusActionsHealing(i)"><i + class="anticon anticon-minus-circle-o"></i></button> + + </div> + </div> + <span style="display:inline-block;width:50%;"> {{"i18nTextDefine_healScript" | translate}} :</span> + <input style="width: 165px;" nz-input [(ngModel)]="nsParams.healScript"> + <div> + <span style="display:inline-block;"> {{"i18nTextDefine_additionalParamsforNs" | translate}} :</span> + <button nz-button [nzType]="'default'" (click)="addNsAdditional()"><i + class="anticon anticon-plus-circle-o"></i></button> + <br> + <div *ngFor="let item of nsAdditional;let i = index;"> + Key: <input style="width: 165px;" nz-input [(ngModel)]="item.key"> + Value: <input style="width: 165px;" nz-input [(ngModel)]="item.value"> + <button nz-button [nzType]="'dashed'" (click)="minusNsAdditional(i)"><i + class="anticon anticon-minus-circle-o"></i></button> + </div> + </div> + </div> + <!-- vnf --> + <div *ngIf="thisService['serviceDomain'] == 'vnf'" style="clear: both"> + <div class="heal-question"> + <p class="heal-label"> {{"i18nTextDefine_cause" | translate}} :</p> + <input nz-input [(ngModel)]="vnfParams.cause" class="heal-input"> + </div> + <div class="heal-question"> + <p class="heal-label"> {{"i18nTextDefine_action" | translate}} :</p> + <input nz-input [(ngModel)]="vnfParams.additionalParams.action" class="heal-input"> + </div> + <div class="heal-question"> + <p class="heal-label"> {{"i18nTextDefine_actionvminfo" | translate}}:</p> + <nz-select + style=" float: right;width: 200px;margin-left: 15px;border-radius: 6px;margin-right: 30px" + [(ngModel)]="vmSelected"> + <nz-option *ngFor="let item of vnfVms" [nzValue]="item" [nzLabel]="item.vmName"></nz-option> + </nz-select> + </div> + </div> +</nz-modal>
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.less b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.less new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.less diff --git a/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.spec.ts new file mode 100644 index 00000000..af1c07bd --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HealModelComponent } from './heal-model.component'; + +describe('HealModelComponent', () => { + let component: HealModelComponent; + let fixture: ComponentFixture<HealModelComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ HealModelComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(HealModelComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.ts b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.ts new file mode 100644 index 00000000..a7ffe663 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.ts @@ -0,0 +1,68 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; + +@Component({ + selector: 'app-heal-model', + templateUrl: './heal-model.component.html', + styleUrls: ['./heal-model.component.less'] +}) +export class HealModelComponent implements OnInit { + @Input()healModelVisible: boolean; + @Input()thisService; + @Input()nsParams; + @Input()healActions; + @Input()nsAdditional; + @Input()vnfParams; + @Input()vmSelected; + @Input()vnfVms; + @Input()templatehealstarting; + @Input()templatehealSuccessFaild; + + @Output() cancel = new EventEmitter<boolean>(); + @Output() healModalOK = new EventEmitter<any>(); + + constructor() { } + + ngOnInit() { + } + + + addActionsHealing() { + this.healActions.push({ value: "" }) + } + + minusActionsHealing(index) { + this.healActions.splice(index, 1); + } + + addNsAdditional() { + this.nsAdditional.push({ key: "", value: "" }) + } + + minusNsAdditional(index) { + this.nsAdditional.splice(index, 1); + } + + healOk() { + this.healModelVisible = false; + // nsParams + this.nsParams.actionsHealing = this.healActions.map((item) => { + return item.value + }); + let additional = {}; + this.nsAdditional.forEach((item) => { + additional[item.key] = item.value; + }); + this.nsParams.additionalParamsforNs = JSON.stringify(additional); + // vnfParams + this.vnfParams.additionalParams.actionvminfo.vmid = this.vmSelected["vmId"]; + this.vnfParams.additionalParams.actionvminfo.vmname = this.vmSelected["vmName"]; + + let requestBody = this.thisService["serviceDomain"] == "Network Service" ? { healNsData: this.nsParams } : { healVnfData: this.vnfParams }; + this.healModalOK.emit(requestBody) + } + + healCancel() { + this.healModelVisible = false; + } + +} diff --git a/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.html b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.html new file mode 100644 index 00000000..cb873149 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.html @@ -0,0 +1,40 @@ +<nz-modal nzWidth="428" [nzVisible]="scaleModelVisible" nzTitle=" {{'i18nTextDefine_Scale' | translate}} " + (nzOnCancel)="scaleCancel()" (nzOnOk)="scaleOk()" + nzClassName="scaleModel" nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} " + nzOkText=" {{'i18nTextDefine_modelOk' | translate}} "> + <h3><span style="color: red">* </span> {{"i18nTextDefine_SureScale" | translate}} </h3> + <div class="question"> + <h4> {{"i18nTextDefine_InstanceID" | translate}} :</h4> + <div class="scaleModelContent" style="width: 100%">{{ thisService["service-instance-id"] || + thisService["nsInstanceId"] || + thisService["vnfInstanceId"]}} + </div> + </div> + <div *ngFor="let item of e2e_nsData" style="margin-top: 20px"> + <h3>{{ item.netWorkServiceName }}</h3> + <div class="e2eScaleContent"> + <span class="e2eScaleLable"> {{"i18nTextDefine_ScaleType" | translate}} :</span> + <nz-select style="width: 165px;" [(ngModel)]="item.scaleType"> + <nz-option nzValue="SCALE_NS" nzLabel="SCALE_NS"></nz-option> + <nz-option nzValue="SCALE_VNF" nzLabel="SCALE_VNF"></nz-option> + </nz-select> + </div> + <div class="e2eScaleContent"> + <span class="e2eScaleLable"> {{"i18nTextDefine_AspectId" | translate}} :</span> + <input style="width: 165px;" nz-input [(ngModel)]="item.aspectId" placeholder="string"> + </div> + <div class="e2eScaleContent"> + <span class="e2eScaleLable"> {{"i18nTextDefine_Number_Of_Steps" | translate}} :</span> + <nz-input-number style="width: 165px;" [(ngModel)]="item.numberOfSteps" [nzMin]="1" [nzMax]="100" + nzPrecision=0 [nzStep]="1" nzPlaceHolder="number"></nz-input-number> + </div> + <div class="e2eScaleContent"> + <span class="e2eScaleLable"> {{"i18nTextDefine_ScalingDirection" | translate}} :</span> + <nz-select style="width: 165px;" nzPlaceHolder="Chose" [(ngModel)]="item.scalingDirection"> + <nz-option nzValue="SCALE_IN" nzLabel="SCALE_IN"></nz-option> + <nz-option nzValue="SCALE_OUT" nzLabel="SCALE_OUT"></nz-option> + </nz-select> + </div> + </div> + +</nz-modal>
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.less b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.less new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.less diff --git a/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.spec.ts new file mode 100644 index 00000000..5d069ee4 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ScaleModelComponent } from './scale-model.component'; + +describe('ScaleModelComponent', () => { + let component: ScaleModelComponent; + let fixture: ComponentFixture<ScaleModelComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ScaleModelComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ScaleModelComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.ts b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.ts new file mode 100644 index 00000000..c1b9a86e --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.ts @@ -0,0 +1,53 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; + +@Component({ + selector: 'app-scale-model', + templateUrl: './scale-model.component.html', + styleUrls: ['./scale-model.component.less'] +}) +export class ScaleModelComponent implements OnInit { + @Input()scaleModelVisible: boolean; + @Input()templatescalestarting; + @Input()templateScaleSuccessFaild; + @Input()thisService; + @Input()e2e_nsData; + @Input()customerSelected; + @Input()serviceTypeSelected; + + @Output() cancel = new EventEmitter<boolean>(); + @Output() scaleModalOK = new EventEmitter<any>(); + constructor() { } + + ngOnInit() { + } + + scaleOk() { + this.scaleModelVisible = false; + let requestBody = { + "service": { + "serviceInstanceName": this.thisService["service-instance-name"], + "serviceType": this.serviceTypeSelected.name, + "globalSubscriberId": this.customerSelected.id, + "resources": this.e2e_nsData.map((item) => { + return { + "resourceInstanceId": item["netWorkServiceId"], + "scaleType": item["scaleType"], + "scaleNsData": { + "scaleNsByStepsData": { + "aspectId": item["aspectId"], + "numberOfSteps": item["numberOfSteps"], + "scalingDirection": item["scalingDirection"] + } + } + } + }) + } + }; + this.scaleModalOK.emit(requestBody) + } + + scaleCancel() { + this.scaleModelVisible = false; + } + +} diff --git a/usecaseui-portal/src/app/views/services/services-list/services-list.component.html b/usecaseui-portal/src/app/views/services/services-list/services-list.component.html index a995b485..216e92df 100644 --- a/usecaseui-portal/src/app/views/services/services-list/services-list.component.html +++ b/usecaseui-portal/src/app/views/services/services-list/services-list.component.html @@ -14,7 +14,6 @@ limitations under the License. --> <div class="action ant-tabs-bar"> - <span> <i class="icon"> <img src="assets/images/customer.png" alt=""> @@ -51,88 +50,26 @@ <i *ngIf="width>1200" class="anticon anticon-plus"></i> <span> {{"i18nTextDefine_Create" | translate}} </span> </button> - <nz-modal nzWidth="428" [(nzVisible)]="isVisible" nzTitle=" {{'i18nTextDefine_ServiceCreation' | translate}} " - (nzOnCancel)="handleCancel()" - (nzOnOk)="handleOk()" nzClassName="serviceCreationModel" - nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} " - nzOkText=" {{'i18nTextDefine_modelOk' | translate}} "> - <div class="select-list"> - <span style="display:inline-block;"> {{"i18nTextDefine_Customer" | translate}} : </span> - <nz-select style="width: 176px;float: right;" [(ngModel)]="customerSelected2.name" nzAllowClear - (ngModelChange)="customerChange()"> - <nz-option *ngFor="let item of customerList2" [nzValue]="item.name" [nzLabel]="item.name"></nz-option> - </nz-select> - </div> - <div class="select-list"> - <span style="display:inline-block;"> {{"i18nTextDefine_ServiceType" | translate}} : </span> - <nz-select style="width: 176px;float: right;" [(ngModel)]="serviceTypeSelectedName" nzAllowClear - (ngModelChange)="serviceTypeChange()"> - <nz-option *ngFor="let item of serviceTypeList2" [nzValue]="item.name" [nzLabel]="item.name"> - </nz-option> - </nz-select> - </div> - <div class="select-list"> - <span style="display:inline-block;"> {{"i18nTextDefine_UseCase" | translate}} : </span> - <nz-select style="width: 176px;float: right;" [(ngModel)]="templateTypeSelected" nzAllowClear - (ngModelChange)="choseTemplateType()"> - <nz-option nzValue="SOTN" nzLabel="SOTN"></nz-option> - <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-select> - </div> - - <div class="select-list"> - <span style="display:inline-block;width:70px;"> {{"i18nTextDefine_Template" | translate}} : </span> - <nz-select style="width: 176px;float: right;" [(ngModel)]="template1" nzAllowClear> - <nz-option *ngFor="let item of templates" [nzValue]="item" [nzLabel]="item.name"></nz-option> - </nz-select> - </div> - <div *ngIf="templateTypeSelected == 'E2E Service'"> - <div class="select-list"> - <span style="display:inline-block;width:70px;"> {{"i18nTextDefine_Orchestrator" | translate}} : </span> - <nz-select style="width: 176px;float: right;" [(ngModel)]="orchestratorSelected" nzAllowClear> - <nz-option *ngFor="let item of orchestratorList" [nzValue]="item" [nzLabel]="item.name"></nz-option> - </nz-select> - </div> - </div> - <div *ngIf="templateTypeSelected == 'E2E Service'"> - <div class="check-box" style="margin:30px; height: 50px"> - <input class="check-box-style" style="zoom: 1.8; width: 70px" type="checkbox" - [(ngModel)]="isSol005Interface" value="true" nzAllowClear> - <label class="label" style="font-size: 20px; color: rgb(60,79,140,0.5)">Sol005</label> - </div> - </div> - <div class="select-list" style="color: red;margin-left: 66px;" *ngIf="temParametersTips"> - {{"i18nTextDefine_Templateparsingfailed" | translate}} - </div> - </nz-modal> + <app-create-model *ngIf="isVisible" [isVisible]="isVisible" (cancel)="isVisible=$event" (createdModalShow)="createdModalShow($event)" + [customerList]="customerList" [serviceTypeList]="serviceTypeList" [customerSelected]="customerSelected" [serviceTypeSelected]="serviceTypeSelected"> + </app-create-model> + </div> -<nz-layout style=" padding: 20px 32px; "> - <ul class="top-num"> - <li *ngFor="let item of serviceMunber" class="top-list"> - <span class="round">{{item.serviceDomain}}</span> - <div class="top-list-text"> - <p> - <span>{{item.failed}}</span> - <span> {{"i18nTextDefine_Failed" | translate}} </span> - </p> - <p> - <span>{{item.Success}}</span> - <span> {{"i18nTextDefine_Success" | translate}} </span> - </p> - <p> - <span>{{item.InProgress}}</span> - <span> {{"i18nTextDefine_InProgress" | translate}} </span> - </p> - <p class="service-description"> {{item.detailName | translate}} </p> - </div> - </li> - </ul> - <div class="list" id="services-list" [ngClass]="{'listdisplay':listDisplay == true}"> - <nz-table *ngIf="1" #nzTable [nzData]="tableData" nzShowSizeChanger [nzFrontPagination]="false" +<nz-layout> + <div class="top-num"> + <app-top-card + *ngFor="let item of serviceNunber" + [serviceDomain]="item.serviceDomain" + [successNum]="item.Success" + [failedNum]="item.failed" + [inProgressNum]="item.InProgress" + [serviceDetailName]="item.detailName"> + </app-top-card> + </div> + <div class="list" id="services-list" [ngClass]="{'listdisplay':listDisplay === true}"> + <nz-table #nzTable [nzData]="tableData" nzShowSizeChanger [nzFrontPagination]="false" [nzShowQuickJumper]="true" [nzPageSizeOptions]="[5,10,15,20]" [nzTotal]='total' [(nzPageSize)]="pageSize" - [(nzPageIndex)]='pageIndex' [nzLoading]="loading" [nzSize]="'middle'" [nzScroll]="{ y: '58vh' }" + [(nzPageIndex)]='pageIndex' [nzLoading]="loading" [nzSize]="'middle'" (nzPageIndexChange)="searchData()" (nzPageSizeChange)="searchData(true)"> <thead> <tr> @@ -153,31 +90,30 @@ <td>{{data["service-instance-name"] || data.nsName}}</td> <td>{{data["service-instance-id"] || data.nsInstanceId}}</td> <td> - <p - [ngClass]="{'e2eColor':data.serviceDomain=='E2E Service','nsColor':data.serviceDomain=='Network Service','ccvpnColor':data.serviceDomain=='CCVPN','sotnColor':data.serviceDomain=='SOTN','voLTEColor':data.serviceDomain=='voLTE type'}"> + <p class="usecase"> {{data.serviceDomain}} </p> </td> <td> - <span [ngClass]="{'active':data.statusClass=='2001','closed':data.statusClass=='Closed','onboarding':data.statusClass=='Onboarding', - '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' " style="margin-left: 10px"> + <span [ngClass]="{'active':data.statusClass==='2001','closed':data.statusClass==='Closed','onboarding':data.statusClass==='Onboarding', + '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"> <img src="assets/images/wancheng-icon.png" alt="Available"> </span> - <span *ngIf="data.tips == 'Unavailable' " style="margin-left: 10px"> + <span *ngIf="data.tips === 'Unavailable' " class="marginLeft10"> <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" [nzShowInfo]="false" nzStatus="active"></nz-progress> </td> <td> - <i [ngClass]="{'cannotclick':data.status == 'In Progress'||(data.status=='Failed' && data.operationType=='1001')||(data.status=='Failed' && data.operationType=='1002')}" + <i [ngClass]="{'cannotclick':data.status === 'In Progress'||(data.status=='Failed' && data.operationType=='1001')||(data.status==='Failed' && data.operationType=='1002')}" class="anticon anticon-bars" (click)="serviceDetail(data,1)"></i> - <i [ngClass]="{'cannotclick':data.status == 'In Progress'}" class="anticon anticon-delete" + <i [ngClass]="{'cannotclick':data.status === 'In Progress'}" class="anticon anticon-delete" (click)="deleteModel(data)"></i> - <i [ngClass]="{'cannotclick':data.status == 'In Progress'}" class="anticon anticon-ellipsis" + <i [ngClass]="{'cannotclick':data.status === 'In Progress'}" class="anticon anticon-ellipsis" (click)="iconMoreShow(data,tableData)" style="transform: rotate(90deg);"></i> <ul *ngIf="data.iconMore==true " class="icon-more"> @@ -218,255 +154,50 @@ </tbody> </nz-table> - <nz-modal nzWidth="428" [nzVisible]="scaleModelVisible" nzTitle=" {{'i18nTextDefine_Scale' | translate}} " - (nzOnCancel)="scaleCancel()" (nzOnOk)="scaleOk(templatescalestarting,templateScaleSuccessFaild)" - nzClassName="scaleModel" nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} " - nzOkText=" {{'i18nTextDefine_modelOk' | translate}} "> - <h3><span style="color: red">* </span> {{"i18nTextDefine_SureScale" | translate}} </h3> - <div class="question"> - <h4> {{"i18nTextDefine_InstanceID" | translate}} :</h4> - <div class="scaleModelContent" style="width: 100%">{{ thisService["service-instance-id"] || - thisService["nsInstanceId"] || - thisService["vnfInstanceId"]}} - </div> - </div> - <div *ngFor="let item of e2e_nsData" style="margin-top: 20px"> - <h3>{{ item.netWorkServiceName }}</h3> - <div class="e2eScaleContent"> - <span class="e2eScaleLable"> {{"i18nTextDefine_ScaleType" | translate}} :</span> - <nz-select style="width: 165px;" [(ngModel)]="item.scaleType"> - <nz-option nzValue="SCALE_NS" nzLabel="SCALE_NS"></nz-option> - <nz-option nzValue="SCALE_VNF" nzLabel="SCALE_VNF"></nz-option> - </nz-select> - </div> - <div class="e2eScaleContent"> - <span class="e2eScaleLable"> {{"i18nTextDefine_AspectId" | translate}} :</span> - <input style="width: 165px;" nz-input [(ngModel)]="item.aspectId" placeholder="string"> - </div> - <div class="e2eScaleContent"> - <span class="e2eScaleLable"> {{"i18nTextDefine_Number_Of_Steps" | translate}} :</span> - <nz-input-number style="width: 165px;" [(ngModel)]="item.numberOfSteps" [nzMin]="1" [nzMax]="100" - nzPrecision=0 [nzStep]="1" nzPlaceHolder="number"></nz-input-number> - </div> - <div class="e2eScaleContent"> - <span class="e2eScaleLable"> {{"i18nTextDefine_ScalingDirection" | translate}} :</span> - <nz-select style="width: 165px;" nzPlaceHolder="Chose" [(ngModel)]="item.scalingDirection"> - <nz-option nzValue="SCALE_IN" nzLabel="SCALE_IN"></nz-option> - <nz-option nzValue="SCALE_OUT" nzLabel="SCALE_OUT"></nz-option> - </nz-select> - </div> - </div> - - <ng-template #templatescalestarting> - <div class="ant-notification-notice-content"> - <div class="ant-notification-notice-with-icon"> - <span class="ant-notification-notice-icon"> - <img src="assets/images/execute-inproess.png" alt="instance temination is starting"> - </span> - <div class="ant-notification-notice-message">E2E - {{"i18nTextDefine_InstanceTeminationStarting" | translate}} - </div> - <div class="ant-notification-notice-description"> - <div class="notificationlist"> - <p> {{"i18nTextDefine_InstanceName" | translate}} :</p> - <span>{{ thisService["service-instance-name"] || - thisService["nsInstanceName"] }} - </span> - </div> - <div class="notificationlist"> - <p> {{"i18nTextDefine_Customer" | translate}} :</p> - <span>{{ customerSelected.name }}</span> - </div> - <div class="notificationlist"> - <p> {{"i18nTextDefine_UseCase" | translate}} :</p> - <span>{{ thisService["serviceDomain"] }}</span> - </div> - </div> - <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> - </div> - </div> - </ng-template> - </nz-modal> - - <nz-modal nzWidth="428" [(nzVisible)]="deleteModelVisible" nzTitle=" {{'i18nTextDefine_delete' | translate}} " - (nzOnCancel)="deleteCancel()" (nzOnOk)="deleteOk(templatedeletestarting,templateDeleteSuccessFaild)" - nzClassName="{{thisService['serviceDomain'] == 'Network Service'?'nsdeleteModel':'deleteModel'}}" - nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} " - nzOkText=" {{'i18nTextDefine_modelOk' | translate}} "> - <h3><span style="color: red">* </span> {{"i18nTextDefine_SureDelete" | translate}} </h3> - <div class="question"> - <h4> {{"i18nTextDefine_InstanceName" | translate}} :</h4> - <div class="deleteModelContent">{{ thisService["service-instance-name"] || - thisService["nsInstanceName"] }} - </div> - </div> - <div class="question"> - <h4> {{"i18nTextDefine_InstanceID" | translate}} :</h4> - <div class="deleteModelContent">{{ thisService["service-instance-id"] || - thisService["nsInstanceId"] }} - </div> - </div> - <div *ngIf="thisService['serviceDomain'] == 'Network Service'"> - <div class="question"> - <h4> {{"i18nTextDefine_terminationType" | translate}} :</h4> - <nz-select style="width: 306px;" [(ngModel)]="terminationType"> - <nz-option nzValue="graceful" nzLabel=" {{'i18nTextDefine_graceful' | translate}} "></nz-option> - <nz-option nzValue="forceful" nzLabel=" {{'i18nTextDefine_forceful' | translate}} "></nz-option> - </nz-select> - </div> - <div class="question"> - <h4 *ngIf="terminationType=='graceful'"> {{"i18nTextDefine_gracefulTerminationTimeout" | translate}} - :</h4> - <input *ngIf="terminationType=='graceful'" style="width: 306px;" nz-input - [(ngModel)]="gracefulTerminationTimeout"> - </div> - </div> - - <ng-template #templatedeletestarting> - <div class="ant-notification-notice-content"> - <div class="ant-notification-notice-with-icon"> - <span class="ant-notification-notice-icon"> - <img src="assets/images/execute-inproess.png" alt="instance temination is starting"> - </span> - <div class="ant-notification-notice-message" - *ngIf="thisService['serviceDomain'] == 'CCVPN' || thisService['serviceDomain'] == 'SOTN'"> - {{ thisService['serviceDomain'] }} {{"i18nTextDefine_InstanceTeminationStarting" | - translate}} - </div> - <div class="ant-notification-notice-message" - *ngIf="thisService['serviceDomain'] == 'E2E Service'">E2E - {{"i18nTextDefine_InstanceTeminationStarting" | translate}} - </div> - <div class="ant-notification-notice-message" - *ngIf="thisService['serviceDomain'] == 'Network Service'">NS - {{"i18nTextDefine_InstanceTeminationStarting" | translate}} - </div> - <div class="ant-notification-notice-description"> - <div class="notificationlist"> - <p> {{"i18nTextDefine_InstanceName" | translate}} :</p> - <span>{{ thisService["service-instance-name"] || - thisService["nsInstanceName"] }} - </span> - </div> - <div class="notificationlist"> - <p> {{"i18nTextDefine_Customer" | translate}} :</p> - <span>{{ customerSelected.name }}</span> - </div> - <div class="notificationlist"> - <p> {{"i18nTextDefine_UseCase" | translate}} :</p> - <span>{{ thisService["serviceDomain"] }}</span> - </div> - </div> - <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> - </div> - </div> - </ng-template> - </nz-modal> - - <nz-modal nzWidth="428" [nzVisible]="healModelVisible" nzTitle=" {{'i18nTextDefine_Heal' | translate}} " - (nzOnCancel)="healCancel()" (nzOnOk)="healOk(templatehealstarting,templatehealSuccessFaild)" - nzClassName="healModel" nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} " - nzOkText=" {{'i18nTextDefine_modelOk' | translate}} "> - <h3><span style="color: red">* </span> {{"i18nTextDefine_SureHeal" | translate}} </h3> - <div class="heal-question"> - <p class="heal-label"> {{"i18nTextDefine_InstanceID" | translate}} : </p> - <div class="healModelContent" title="{{ thisService['service-instance-id'] || thisService['nsInstanceId'] || - thisService['vnfInstanceId']}}"> {{ thisService["service-instance-id"] || - thisService["nsInstanceId"] || - thisService["vnfInstanceId"]}} - </div> - </div> - <!-- NS --> - <div *ngIf="thisService['serviceDomain'] == 'Network Service'"> - <div class="question"> - <p class="heal-label"> {{"i18nTextDefine_degreeHealing" | translate}} :</p> - <nz-select style="width: 200px;height:42px;margin-left: 15px;border-radius: 6px" - [(ngModel)]="nsParams.degreeHealing"> - <nz-option nzValue="HEAL_RESTORE" nzLabel="HEAL_RESTORE"></nz-option> - <nz-option nzValue="HEAL_QOS" nzLabel="HEAL_QOS"></nz-option> - <nz-option nzValue="HEAL_RESET" nzLabel="HEAL_RESET"></nz-option> - <nz-option nzValue="PARTIAL_HEALING" nzLabel="PARTIAL_HEALING"></nz-option> - </nz-select> - </div> - <div> - <span style="display:inline-block;"> {{"i18nTextDefine_actionsHealing" | translate}} :</span> - <button nz-button [nzType]="'default'" (click)="addActionsHealing()"><i - class="anticon anticon-plus-circle-o"></i></button> - <br> - <div *ngFor="let item of healActions;let i = index;" style="display:inline-block;"> - <input style="width: 165px;" nz-input [(ngModel)]="item.value"> - <button nz-button [nzType]="'dashed'" (click)="minusActionsHealing(i)"><i - class="anticon anticon-minus-circle-o"></i></button> - - </div> - </div> - <span style="display:inline-block;width:50%;"> {{"i18nTextDefine_healScript" | translate}} :</span> - <input style="width: 165px;" nz-input [(ngModel)]="nsParams.healScript"> - <div> - <span style="display:inline-block;"> {{"i18nTextDefine_additionalParamsforNs" | translate}} :</span> - <button nz-button [nzType]="'default'" (click)="addNsAdditional()"><i - class="anticon anticon-plus-circle-o"></i></button> - <br> - <div *ngFor="let item of nsAdditional;let i = index;"> - Key: <input style="width: 165px;" nz-input [(ngModel)]="item.key"> - Value: <input style="width: 165px;" nz-input [(ngModel)]="item.value"> - <button nz-button [nzType]="'dashed'" (click)="minusNsAdditional(i)"><i - class="anticon anticon-minus-circle-o"></i></button> - </div> - </div> - </div> - <!-- vnf --> - <div *ngIf="thisService['serviceDomain'] == 'vnf'" style="clear: both"> - <div class="heal-question"> - <p class="heal-label"> {{"i18nTextDefine_cause" | translate}} :</p> - <input nz-input [(ngModel)]="vnfParams.cause" class="heal-input"> - </div> - <div class="heal-question"> - <p class="heal-label"> {{"i18nTextDefine_action" | translate}} :</p> - <input nz-input [(ngModel)]="vnfParams.additionalParams.action" class="heal-input"> - </div> - <div class="heal-question"> - <p class="heal-label"> {{"i18nTextDefine_actionvminfo" | translate}}:</p> - <nz-select - style=" float: right;width: 200px;margin-left: 15px;border-radius: 6px;margin-right: 30px" - [(ngModel)]="vmSelected"> - <nz-option *ngFor="let item of vnfVms" [nzValue]="item" [nzLabel]="item.vmName"></nz-option> - </nz-select> - </div> - </div> - - <ng-template #templatehealstarting> - <div class="ant-notification-notice-content"> - <div class="ant-notification-notice-with-icon"> - <span class="ant-notification-notice-icon"> - <img src="assets/images/execute-inproess.png" alt="instance temination is starting"> - </span> - <div class="ant-notification-notice-message">NS - {{"i18nTextDefine_InstanceHealingStarting" | translate}} - </div> - <div class="ant-notification-notice-description"> - <div class="notificationlist"> - <p> {{"i18nTextDefine_InstanceName" | translate}} :</p> - <span>{{ thisService["service-instance-name"] || - thisService["nsInstanceName"] }} - </span> - </div> - <div class="notificationlist"> - <p> {{"i18nTextDefine_Customer" | translate}} :</p> - <span>{{ customerSelected.name }}</span> - </div> - <div class="notificationlist"> - <p> {{"i18nTextDefine_UseCase" | translate}} :</p> - <span>{{ thisService["serviceDomain"] }}</span> - </div> - </div> - <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> - </div> - </div> - </ng-template> - </nz-modal> + <app-delete-model + *ngIf="deleteModalVisible" + [deleteModalVisible]="deleteModalVisible" + [thisService]="thisService" + [terminationType]="terminationType" + [loadingAnimateShow]="loadingAnimateShow" + [gracefulTerminationTimeout]="gracefulTerminationTimeout" + [templateDeleteSuccessFaild]="templateDeleteSuccessFaild" + (cancel)="deleteModalVisible=$event" + (deleteModalOK)="deleteModalOK($event,templateDeleteSuccessFaild)" + > + </app-delete-model> + <app-scale-model + *ngIf="scaleModelVisible" + [scaleModelVisible]="scaleModelVisible" + [thisService]="thisService" + [e2e_nsData]="e2e_nsData" + [customerSelected]="customerSelected" + [serviceTypeSelected]="serviceTypeSelected" + [templatescalestarting]="templatescalestarting" + [templateScaleSuccessFaild]="templateScaleSuccessFaild" + (cancel)="scaleModelVisible=$event" + (scaleModalOK)="scaleModalOK($event,templatescalestarting,templateScaleSuccessFaild)" + > + </app-scale-model> + <app-heal-model + *ngIf="healModelVisible" + [healModelVisible]="healModelVisible" + [thisService]="thisService" + [nsParams]="nsParams" + [healActions]="healActions" + [nsAdditional]="nsAdditional" + [vnfParams]="vnfParams" + [vmSelected]="vmSelected" + [vnfVms]="vnfVms" + [templatehealstarting]="templatehealstarting" + [templatehealSuccessFaild]="templatehealSuccessFaild" + (cancel)="healModelVisible=$event" + (healModalOK)="healModalOK($event,templatehealstarting,templatehealSuccessFaild)" + ></app-heal-model> + <app-notification #notification [isServicesList]="true" [customerSelected]="customerSelected"></app-notification> <!-- add notification--> + <ng-template #templateCreatestarting> <div class="ant-notification-notice-content"> <div class="ant-notification-notice-with-icon"> @@ -474,7 +205,7 @@ <img src="assets/images/execute-inproess.png" alt="instance temination is starting"> </span> <div class="ant-notification-notice-message" - *ngIf="thisCreateService['serviceDomain'] == 'CCVPN' || thisService['serviceDomain'] == 'SOTN'"> + *ngIf="thisCreateService['serviceDomain'] === 'CCVPN' || thisService['serviceDomain'] === 'SOTN'"> {{ thisService['serviceDomain'] }} {{"i18nTextDefine_InstanceCreationStarting" | translate}} </div> @@ -582,6 +313,7 @@ *ngIf="(thisService['serviceDomain'] == 'Network Service') && thisService.status == 'Successful'"> NS {{"i18nTextDefine_InstanceTeminatedSuccessfully" | translate}} </div> + <div class="ant-notification-notice-message" *ngIf="(thisService['serviceDomain'] == 'CCVPN' || thisService['serviceDomain'] == 'SOTN') && thisService.status == 'Failed'"> {{ thisService['serviceDomain'] }} {{"i18nTextDefine_InstanceTeminationFailed" | @@ -615,6 +347,35 @@ </div> </div> </ng-template> + <ng-template #templatescalestarting> + <div class="ant-notification-notice-content"> + <div class="ant-notification-notice-with-icon"> + <span class="ant-notification-notice-icon"> + <img src="assets/images/execute-inproess.png" alt="instance temination is starting"> + </span> + <div class="ant-notification-notice-message">E2E + {{"i18nTextDefine_InstanceTeminationStarting" | translate}} + </div> + <div class="ant-notification-notice-description"> + <div class="notificationlist"> + <p> {{"i18nTextDefine_InstanceName" | translate}} :</p> + <span>{{ thisService["service-instance-name"] || + thisService["nsInstanceName"] }} + </span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_Customer" | translate}} :</p> + <span>{{ customerSelected.name }}</span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_UseCase" | translate}} :</p> + <span>{{ thisService["serviceDomain"] }}</span> + </div> + </div> + <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> + </div> + </div> + </ng-template> <ng-template #templateScaleSuccessFaild> <div class="ant-notification-notice-content"> <div class="ant-notification-notice-with-icon"> @@ -650,6 +411,35 @@ </div> </div> </ng-template> + <ng-template #templatehealstarting> + <div class="ant-notification-notice-content"> + <div class="ant-notification-notice-with-icon"> + <span class="ant-notification-notice-icon"> + <img src="assets/images/execute-inproess.png" alt="instance temination is starting"> + </span> + <div class="ant-notification-notice-message">NS + {{"i18nTextDefine_InstanceHealingStarting" | translate}} + </div> + <div class="ant-notification-notice-description"> + <div class="notificationlist"> + <p> {{"i18nTextDefine_InstanceName" | translate}} :</p> + <span>{{ thisService["service-instance-name"] || + thisService["nsInstanceName"] }} + </span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_Customer" | translate}} :</p> + <span>{{ customerSelected.name }}</span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_UseCase" | translate}} :</p> + <span>{{ thisService["serviceDomain"] }}</span> + </div> + </div> + <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> + </div> + </div> + </ng-template> <ng-template #templatehealSuccessFaild> <div class="ant-notification-notice-content"> <div class="ant-notification-notice-with-icon"> @@ -728,7 +518,7 @@ </div> <div class="detailComponent" *ngIf="detailshow2"> <app-e2e-detail [detailParams]="detailData" (closeDetail)="detailshow2 = false;listDisplay = false;"> - </app-e2e-detail> + </app-e2e-detail> </div> <div class="createComponent" *ngIf="createshow"> <app-ccvpn-creation [createParams]="createData" [ccvpn_temParametersContent]="ccvpn_temParametersContent" diff --git a/usecaseui-portal/src/app/views/services/services-list/services-list.component.less b/usecaseui-portal/src/app/views/services/services-list/services-list.component.less index aeddf257..454e3bc8 100644 --- a/usecaseui-portal/src/app/views/services/services-list/services-list.component.less +++ b/usecaseui-portal/src/app/views/services/services-list/services-list.component.less @@ -207,69 +207,9 @@ nz-layout{ width: 100%; display: flex; justify-content: space-around; - .top-list{ - position: relative; - width:32%; - max-width:400px; - height:170px; - background:url("/assets/images/servicelist-e2e.png") no-repeat; - background-size: 100% 100%; - border-radius:2px; - .round{ - position: absolute; - width: 60px; - height: 60px; - line-height: 60px; - text-align: center; - background:#E0EDFF; - border:2px solid rgba(224,237,255,1); - border-radius: 50%; - font-size:16px; - font-family:ArialMT; - color:#3C4F8C; - transition: .5s; - } - .top-list-text{ - position: absolute; - text-align: right; - line-height: 20px; - right: 12%; - color: #fff; - p{ - height: 28px; - margin-bottom: 0; - padding-left: 5px; - font-size: 14px; - clear: both; - span{ - display: inline-block; - float: right; - font-weight: 500; - text-align: right; - } - span:nth-child(1){ - font-size: 18px; - margin-left: 15px; - } - span:nth-child(2){ - width: 85px; - font-size: 16px; - } - } - p:nth-child(1){ - margin-top: 25px; - } - .service-description{ - - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - color: #3C4F8C; - - } - } + app-top-card{ + width: 32%; } - } } .list { @@ -312,6 +252,9 @@ nz-layout{ font-size: 12px; color: orangered; } + span.marginLeft10{ + margin-left: 10px; + } i.anticon { cursor: pointer; font-size: 18px; @@ -395,7 +338,7 @@ nz-layout{ z-index: 3; } -.e2eColor,.nsColor,.ccvpnColor,.sotnColor,.voLTEColor{ +.usecase{ width:120px; height: 34px; line-height: 34px; @@ -416,18 +359,6 @@ nz-layout{ border-radius:4px; } -.select-list{ - width: 320px; - height: 32px; - line-height: 32px; - margin: 35px auto; -} -.select-list>span{ - text-align: right; - width: 110px!important; - line-height: 32px; -} - .listdisplay{ display: none; }
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/services/services-list/services-list.component.ts b/usecaseui-portal/src/app/views/services/services-list/services-list.component.ts index 72cacc7e..da027028 100644 --- a/usecaseui-portal/src/app/views/services/services-list/services-list.component.ts +++ b/usecaseui-portal/src/app/views/services/services-list/services-list.component.ts @@ -13,8 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Component, OnInit, HostBinding, TemplateRef } from '@angular/core'; -import { MyhttpService } from '../../../core/services/myhttp.service'; +import { Component, OnInit, HostBinding, TemplateRef, ViewChild } from '@angular/core'; +import { ServiceListService } from '../../../core/services/serviceList.service'; import { slideToRight } from '../../../shared/utils/animates'; import { NzModalService } from 'ng-zorro-antd'; import { NzNotificationService } from 'ng-zorro-antd'; @@ -28,10 +28,11 @@ import { Observable } from 'rxjs/Rx'; }) export class ServicesListComponent implements OnInit { @HostBinding('@routerAnimate') routerAnimateState; + @ViewChild('notification') notification1: any; public width:number = document.documentElement.clientWidth; - constructor(private myhttp: MyhttpService, private modalService: NzModalService, private notification: NzNotificationService) { + constructor(private myhttp: ServiceListService, private modalService: NzModalService, private notification: NzNotificationService) { } ngOnInit() { @@ -41,16 +42,19 @@ export class ServicesListComponent implements OnInit { this.width = document.documentElement.clientWidth }); } - + ngOnDestroy() { + clearInterval(this.progressCcvpnOutTimer); + clearInterval(this.progressingCcvpnTimer); + clearInterval(this.progressNsOutTimer); + clearInterval(this.progressingNsTimer); + } // customer servicetype isSol005Interface = false; orchestratorList = []; customerList = []; - customerList2 = []; customerSelected = { name: null, id: null }; customerSelected2 = { name: null, id: null }; serviceTypeList = []; - serviceTypeList2 = []; serviceTypeSelected = { name: '' }; serviceTypeSelected2 = { name: '' }; serviceTypeSelectedName = ""; @@ -60,7 +64,7 @@ export class ServicesListComponent implements OnInit { language = sessionStorage.getItem("DefaultLang"); iconMore = false; loadingAnimateShow = false; - serviceMunber = [ // top: E2E/NS/CCVPN data + serviceNunber = [ // top: E2E/NS/CCVPN data { "serviceDomain": "E2E", "Success": 0, @@ -84,6 +88,11 @@ export class ServicesListComponent implements OnInit { } ]; + progressCcvpnOutTimer :any; // ccvpn��NS progress Timer + progressingCcvpnTimer :any; + progressNsOutTimer :any; + progressingNsTimer :any; + //The icon behind each row of data in the table expands iconMoreShow(data, tableData) { tableData.map((its) => { @@ -104,59 +113,40 @@ export class ServicesListComponent implements OnInit { console.log(this.language, "this.language"); this.myhttp.getAllCustomers() .subscribe((data) => { - this.customerList = data.map((item) => { - return { name: item["subscriber-name"], id: item["global-customer-id"] } - }); - if (this.customerList.length == 0) { - console.log("customerList.length == 0", this.customerList); - return false; + this.customerList = data.map(item => ({ name: item["subscriber-name"], id: item["global-customer-id"] }) ); + if(data.length !== 0){ + this.customerSelected = this.customerList[0]; + this.choseCustomer(); } - this.customerList2 = data.map((item) => { - return { name: item["subscriber-name"], id: item["global-customer-id"] } - }); - if (this.customerList2.length == 0) { - return false; - } - this.customerSelected = this.customerList[0]; - this.choseCustomer(this.customerSelected); }) } getallOrchestrators() { this.myhttp.getAllOrchestrators() .subscribe((data) => { - this.orchestratorList = data.map((item) => { - return { name: item["name"], id: item["name"] } - }); - if (this.orchestratorList.length == 0) { - console.log("orchestratorList.length == 0", this.orchestratorList); - return false; + if(data.length > 0){ + this.orchestratorList = data.map((item) => { + return { name: item["name"], id: item["name"] } + }); + this.orchestratorSelected = this.orchestratorList[0]; } - this.orchestratorSelected = this.orchestratorList[0]; }) } - choseCustomer(item) { - this.customerSelected = item; + choseCustomer(item = this.customerSelected) { + if(this.customerSelected !== item) this.customerSelected = item; this.myhttp.getServiceTypes(this.customerSelected) .subscribe((data) => { - this.serviceTypeList = data.map((item) => { - return { name: item["service-type"] } - }); - - if (this.serviceTypeList.length == 0) { - console.log("serviceTypeList.length == 0", this.serviceTypeList); - return false; + this.serviceTypeList = data.map( item => ({ name: item["service-type"] })); + if(data.length !== 0){ + this.serviceTypeSelected = this.serviceTypeList[0]; + this.choseServiceType(); } - - this.serviceTypeSelected = this.serviceTypeList[0]; - - this.choseServiceType(this.serviceTypeSelected); }) } - choseServiceType(item) { - this.serviceTypeSelected = item; + choseServiceType(item = this.serviceTypeSelected) { + if(this.serviceTypeSelected !== item) this.serviceTypeSelected = item; this.getTableData(); } @@ -164,131 +154,28 @@ export class ServicesListComponent implements OnInit { // Create modal box 2 (dialog box) create ------------------------------- isVisible = false; - customerChange(): void { - this.getServiceType(this.customerSelected2); - } - - getServiceType(customerSelected2) { - this.myhttp.getServiceTypes(customerSelected2) - .subscribe((data) => { - this.serviceTypeList2 = data.map((item) => { - return { name: item["service-type"] } - }); - if (this.serviceTypeList2.length == 0) { - console.log("serviceTypeList.length == 0", this.serviceTypeList2); - return false; - } - this.getAlltemplates(); - }) - } - - serviceTypeChange(): void { - this.serviceTypeSelected2.name = this.serviceTypeSelectedName - } - createModal(): void { this.isVisible = true; - this.getallOrchestrators(); - this.customerSelected2 = this.customerSelected; - this.serviceTypeSelectedName = this.serviceTypeSelected.name; - this.serviceTypeSelected2 = Object.assign({}, this.serviceTypeSelected); - this.getServiceType(this.customerSelected2); - } - - choseTemplateType() { - this.getallOrchestrators(); - this.getAlltemplates(); - } - - templates = []; - template1 = { name: null }; - - getAlltemplates() { - this.myhttp.getAllServiceTemplates(this.templateTypeSelected) - .subscribe((data) => { - this.templates = data; - if (this.templateTypeSelected == "Network Service") { - this.templates = data.filter((d) => { - return typeof d.packageInfo.csarName == "string"; - }).map((item) => { - let cName = item.packageInfo.csarName.split("/").reverse()[0]; - return { name: cName, id: item.csarId, packageInfo: item.packageInfo } - }); - } - this.template1 = this.templates[0]; - }, (err) => { - console.log(err); - }) } - createshow = false; - createshow2 = false; - listDisplay = false; + createshow: boolean = false; + createshow2: boolean = false; + listDisplay: boolean = false; createData: Object = {}; - - handleOk(): void { - if (this.templateTypeSelected == "SOTN" || this.templateTypeSelected == "CCVPN") { - this.createData = { - commonParams: { - customer: this.customerSelected, - serviceType: this.serviceTypeSelected2, - templateType: this.templateTypeSelected - }, template: this.template1 - }; - } else if (this.templateTypeSelected == "E2E Service" || this.templateTypeSelected == "Network Service") { - this.createData = { - commonParams: { - customer: this.customerSelected, - serviceType: this.serviceTypeSelected2, - templateType: this.templateTypeSelected - }, - template: this.template1, - orchestrator: this.orchestratorSelected, - isSol005Interface: this.isSol005Interface - }; - } - this.getTemParameters(); - } - - handleCancel(): void { - this.isVisible = false; - this.loadingAnimateShow = false; - } - - temParametersTips = false; ccvpn_temParametersContent: any; e2e_ns_temParametersContent: any; - getTemParameters() { - let chosedtemplates = this.createData["template"]; - let types = this.createData["commonParams"].templateType; - if (types == "E2E Service") { - types = "e2e"; - } else if (types == "Network Service") { - types = "ns"; + createdModalShow(obj: any): void{ + this.createData = obj.createData; + console.log(obj.createData) + if (obj.templateType === "SOTN" || obj.templateType === "CCVPN") { + this.ccvpn_temParametersContent = obj.data; + this.createshow = true; + } else if (obj.templateType === "E2E Service" || obj.templateType === "Network Service") { + this.e2e_ns_temParametersContent = obj.data; + this.createshow2 = true; } - this.loadingAnimateShow = true; - this.myhttp.getTemplateParameters(types, chosedtemplates) - .subscribe((data) => { - this.loadingAnimateShow = false; - if (data.status == "FAILED") { - this.temParametersTips = true; - this.isVisible = true; - console.log("Template parsing Failed"); - } else { - this.isVisible = false; - this.temParametersTips = false; - if (this.templateTypeSelected == "SOTN" || this.templateTypeSelected == "CCVPN") { - this.ccvpn_temParametersContent = data; - this.createshow = true; - this.listDisplay = true; - } else if (this.templateTypeSelected == "E2E Service" || this.templateTypeSelected == "Network Service") { - this.e2e_ns_temParametersContent = data; - this.createshow2 = true; - this.listDisplay = true; - } - } - }) + this.listDisplay = true; } //tableData @@ -316,7 +203,7 @@ export class ServicesListComponent implements OnInit { } item["iconMore"] = this.iconMore; - if (item["serviceDomain"] == "Network Service") { + if (item["serviceDomain"] === "Network Service") { if (item["vnfInfo"]) { item["childServiceInstances"] = item["vnfInfo"].map((vnf) => { vnf["serviceDomain"] = "vnf"; @@ -334,10 +221,10 @@ export class ServicesListComponent implements OnInit { }; vnfInfo.vnfNsInstanceId = item["nsInstanceId"] || item["service-instance-id"]; vnfInfo.vnfInstanceId = vnf["relationship-data"].find((vnfid) => { - return vnfid["relationship-key"] == "generic-vnf.vnf-id" + return vnfid["relationship-key"] === "generic-vnf.vnf-id" })["relationship-value"]; vnfInfo.vnfInstanceName = vnf["related-to-property"].find((vnfname) => { - return vnfname["property-key"] == "generic-vnf.vnf-name" + return vnfname["property-key"] === "generic-vnf.vnf-name" })["property-value"]; return vnfInfo; }) @@ -347,32 +234,30 @@ export class ServicesListComponent implements OnInit { } // - if (item["operationResult"] == "2001") { //operationResult==2001 + if (item["operationResult"] === "2001") { item["status"] = "Available"; item["tips"] = "Available"; item["statusClass"] = item["operationResult"]; } // 2018.12.13 - else if (item["operationResult"] == "2002") { //operationResult==2002 - if (item["operationType"] == "1001" || item["operationType"] == "1002") { + else if (item["operationResult"] === "2002") { + if (item["operationType"] === "1001" || item["operationType"] === "1002") { // item["status"] = this.accordingState["operationResult"][item["operationResult"]]; item["status"] = this.listSortMasters["operationResults"].find((its) => { - return its["sortCode"] == item["operationResult"] && its["language"] == this.language + return its["sortCode"] === item["operationResult"] && its["language"] === this.language })["sortValue"]; item["tips"] = "Unavailable"; item["statusClass"] = item["operationType"]; - } else if (item["operationType"] != "1001" && item["operationType"] != "1002") { - // item["status"] = this.accordingState["operationResult"][item["operationResult"]]; + } else { item["status"] = this.listSortMasters["operationResults"].find((its) => { - return its["sortCode"] == item["operationResult"] && its["language"] == this.language + return its["sortCode"] === item["operationResult"] && its["language"] === this.language })["sortValue"]; item["tips"] = "Available"; item["statusClass"] = item["operationType"]; } } - else if (item["operationResult"] == "2003") { //operationResult==2003 - // item["status"] = this.accordingState["operationResult"][item["operationResult"]]; + else if (item["operationResult"] === "2003") { item["status"] = this.listSortMasters["operationResults"].find((its) => { return its["sortCode"] == item["operationResult"] && its["language"] == this.language })["sortValue"]; @@ -404,16 +289,11 @@ export class ServicesListComponent implements OnInit { }) } else { let updata = (prodata) => { - item["rate"] = prodata.progress || item["rate"]; + item["rate"] = prodata.progress || 0; + if(item["rate"] > 100) item["status"] = prodata.status; item["tips"] = this.listSortMasters["operationTypes"].find((its) => { - return its["sortCode"] == item["operationType"] && its["language"] == this.language - })["sortValue"] + '\xa0\xa0\xa0' + prodata.progress + "%"; - if (item["rate"] > 100) { - item["status"] = prodata.status; - item["tips"] = this.listSortMasters["operationTypes"].find((its) => { - return its["sortCode"] == item["operationType"] && its["language"] == this.language - })["sortValue"] + '\xa0\xa0\xa0' + item["status"]; - } + return its["sortCode"] === item["operationType"] && its["language"] === this.language + })["sortValue"] + '\xa0\xa0\xa0' + (item["rate"] > 100? item["status"] : prodata.progress + '%'); } let obj = { serviceId: item["service-instance-id"], @@ -433,35 +313,36 @@ export class ServicesListComponent implements OnInit { } return item; }) - this.tableData.map((item, index) => { - if (item.serviceDomain == 'E2E Service') { - if (item.operationResult == 2001) { - this.serviceMunber[0]["Success"] += 1; - } else if (item.operationResult == 2002) { - this.serviceMunber[0]["failed"] += 1; - } else if (item.operationResult == 2003) { - this.serviceMunber[0]["InProgress"] += 1; + this.tableData.forEach( item => { + if (item.serviceDomain === 'E2E Service') { + if (item.operationResult === 2001) { + this.serviceNunber[0]["Success"] += 1; + } else if (item.operationResult === 2002) { + this.serviceNunber[0]["failed"] += 1; + } else if (item.operationResult === 2003) { + this.serviceNunber[0]["InProgress"] += 1; } } - else if (item.serviceDomain == 'Network Service') { - if (item.operationResult == 2001) { - this.serviceMunber[1]["Success"] += 1; - } else if (item.operationResult == 2002) { - this.serviceMunber[1]["failed"] += 1; - } else if (item.operationResult == 2003) { - this.serviceMunber[1]["InProgress"] += 1; + else if (item.serviceDomain === 'Network Service') { + if (item.operationResult === 2001) { + this.serviceNunber[1]["Success"] += 1; + } else if (item.operationResult === 2002) { + this.serviceNunber[1]["failed"] += 1; + } else if (item.operationResult === 2003) { + this.serviceNunber[1]["InProgress"] += 1; } } - else if (item.serviceDomain == 'CCVPN') { - if (item.operationResult == 2001) { - this.serviceMunber[2]["Success"] += 1; - } else if (item.operationResult == 2002) { - this.serviceMunber[2]["failed"] += 1; - } else if (item.operationResult == 2003) { - this.serviceMunber[2]["InProgress"] += 1; + else if (item.serviceDomain === 'CCVPN') { + if (item.operationResult === 2001) { + this.serviceNunber[2]["Success"] += 1; + } else if (item.operationResult === 2002) { + this.serviceNunber[2]["failed"] += 1; + } else if (item.operationResult === 2003) { + this.serviceNunber[2]["InProgress"] += 1; } } }) + console.log(this.tableData) this.loading = false; }, (err) => { console.log(err); @@ -484,43 +365,18 @@ export class ServicesListComponent implements OnInit { customerId: this.customerSelected.id, serviceType: this.serviceTypeSelected.name, serviceId: service["service-instance-id"] - } + }; this.myhttp.getE2e_nsData(paramsObj) .subscribe((data) => { this.e2e_nsData = data; }) } - scaleOk(templatescalestarting, templateScaleSuccessFaild) { - this.scaleModelVisible = false; - let requestBody = { - "service": { - "serviceInstanceName": this.thisService["service-instance-name"], - "serviceType": this.serviceTypeSelected.name, - "globalSubscriberId": this.customerSelected.id, - "resources": this.e2e_nsData.map((item) => { - return { - "resourceInstanceId": item["netWorkServiceId"], - "scaleType": item["scaleType"], - "scaleNsData": { - "scaleNsByStepsData": { - "aspectId": item["aspectId"], - "numberOfSteps": item["numberOfSteps"], - "scalingDirection": item["scalingDirection"] - } - } - } - }) - } - } - this.scaleE2eService(this.thisService, requestBody, templateScaleSuccessFaild); + scaleModalOK(obj: any,templatescalestarting,templateScaleSuccessFaild) :void{ + this.scaleE2eService(this.thisService, obj, templateScaleSuccessFaild); this.scaleNotification(templatescalestarting); } - scaleCancel() { - this.scaleModelVisible = false; - } - scaleNotification(template: TemplateRef<{}>): void { this.notification.template(template); } @@ -552,23 +408,7 @@ export class ServicesListComponent implements OnInit { vmname: "" } } - } - - addActionsHealing() { - this.healActions.push({ value: "" }) - } - - minusActionsHealing(index) { - this.healActions.splice(index, 1); - } - - addNsAdditional() { - this.nsAdditional.push({ key: "", value: "" }) - } - - minusNsAdditional(index) { - this.nsAdditional.splice(index, 1); - } + }; healService(service) { this.thisService = service; @@ -583,30 +423,11 @@ export class ServicesListComponent implements OnInit { } } - healOk(templatehealstarting, templatehealSuccessFaild) { - this.healModelVisible = false; - // nsParams - this.nsParams.actionsHealing = this.healActions.map((item) => { - return item.value - }); - let additional = {}; - this.nsAdditional.forEach((item) => { - additional[item.key] = item.value; - }); - this.nsParams.additionalParamsforNs = JSON.stringify(additional); - // vnfParams - this.vnfParams.additionalParams.actionvminfo.vmid = this.vmSelected["vmId"]; - this.vnfParams.additionalParams.actionvminfo.vmname = this.vmSelected["vmName"]; - - let requestBody = this.thisService["serviceDomain"] == "Network Service" ? { healNsData: this.nsParams } : { healVnfData: this.vnfParams }; - this.healNsVnfService(this.thisService, requestBody, templatehealSuccessFaild); + healModalOK(obj: any,templatehealstarting,templatehealSuccessFaild) :void{ + this.healNsVnfService(this.thisService, obj, templatehealSuccessFaild); this.healNotification(templatehealstarting); } - healCancel() { - this.healModelVisible = false; - } - healNotification(template: TemplateRef<{}>): void { this.notification.template(template); } @@ -628,54 +449,45 @@ export class ServicesListComponent implements OnInit { service["serviceType"] = this.serviceTypeSelected; service.childServiceInstances.forEach((item) => { - if (item.serviceDomain == "SITE") { + if (item.serviceDomain === "SITE") { service.siteSer.push(item); - } else if (item.serviceDomain == "SDWAN") { + } else if (item.serviceDomain === "SDWAN") { service.sdwanSer.push(item); } }) - if (service["serviceDomain"] == 'CCVPN' || service["serviceDomain"] == 'SOTN') { + if (service["serviceDomain"] === 'CCVPN' || service["serviceDomain"] === 'SOTN') { this.detailshow = true; - if (typeNum == 1) { + if (typeNum === 1) { this.upDateShow = false; } else { this.upDateShow = true; } - } else if (service["serviceDomain"] == 'E2E Service' || service["serviceDomain"] == 'Network Service') { + } else if (service["serviceDomain"] === 'E2E Service' || service["serviceDomain"] === 'Network Service') { this.detailshow2 = true; } this.listDisplay = true; this.detailData = service; - console.log(service); } - deleteModelVisible = false; + deleteModalVisible = false; terminationType = "graceful"; gracefulTerminationTimeout = 120; // delete Model show deleteModel(service) { this.thisService = service; - this.deleteModelVisible = true; + this.deleteModalVisible = true; } - deleteOk(templatedeletestarting, templateDeleteSuccessFaild) { - this.deleteModelVisible = false; + deleteModalOK(obj: any,templateDeleteSuccessFaild) :void{ + this.deleteModalVisible = false; this.loadingAnimateShow = true; - if (this.thisService["serviceDomain"] == "Network Service") { - this.deleteNsService(this.thisService, templateDeleteSuccessFaild); + if (this.thisService["serviceDomain"] === "Network Service") { + this.deleteNsService(obj,this.thisService); } else { this.deleteService(this.thisService, templateDeleteSuccessFaild); } - this.deleteNotification(templatedeletestarting); - } - - deleteCancel() { - this.deleteModelVisible = false; - } - - deleteNotification(template: TemplateRef<{}>): void { - this.notification.template(template); + this.notification1.notificationStart(this.thisService['serviceDomain'],'deleteStarting',this.thisService["service-instance-name"] ||this.thisService["nsInstanceName"]) } deleteSuccessNotification(template: TemplateRef<{}>): void { @@ -1011,7 +823,10 @@ export class ServicesListComponent implements OnInit { service.tips = ""; service.statusClass = "1004"; let id = service.nsInstanceId || service["service-instance-id"] || service["vnfNsInstanceId"]; - this.myhttp.healNsService(id, requestBody) + let paramsObj = { + "ns_instance_id":id + }; + this.myhttp.healNsService(paramsObj, requestBody) .subscribe((data) => { if (data.status == "FAILED") { console.log("heal nsvnf service Failed :" + JSON.stringify(data)); @@ -1113,7 +928,7 @@ export class ServicesListComponent implements OnInit { }) } - deleteService(service, templateDeleteSuccessFaild) { + deleteService(service:any, templateDeleteSuccessFaild) { let allprogress = {}; let querypros = []; service.rate = 0; @@ -1190,21 +1005,17 @@ export class ServicesListComponent implements OnInit { }) } - deleteNsService(service, templateDeleteSuccessFaild) { + deleteNsService(obj:any,service:any) { service.rate = 0; service.status = "In Progress"; service.tips = ""; service.statusClass = "1002"; let id = service.nsInstanceId || service["service-instance-id"]; let operationType = "1002"; - let requestBody = { - terminationType: this.terminationType, - gracefulTerminationTimeout: this.gracefulTerminationTimeout - } - this.stopNsService(id, requestBody).then((jobid) => { - if (jobid == "Failed") { + this.stopNsService(id, obj).then((jobid) => { + if (jobid === "Failed") { service.status = "Failed"; - this.deleteSuccessNotification(templateDeleteSuccessFaild); + this.notification1.notificationFailed(service.serviceDomain,'deleteStarting',service["service-instance-name"] ||service["nsInstanceName"]) service.tips = this.listSortMasters["operationTypes"].find((its) => { return its["sortCode"] == service.statusClass && its["language"] == this.language })["sortValue"] + this.listSortMasters["operationResults"].find((its) => { @@ -1213,58 +1024,56 @@ export class ServicesListComponent implements OnInit { return false; } let updata = (prodata) => { - service.rate = prodata.progress; + service.rate = prodata.progress || 0; + if(service['rate'] > 100)service["status"] = prodata.status; service.tips = this.listSortMasters["operationTypes"].find((its) => { return its["sortCode"] == service.statusClass && its["language"] == this.language - })["sortValue"] + '\xa0\xa0\xa0' + service.rate + "%"; - if (service["rate"] > 100) { - service["status"] = prodata.status; - service.tips = this.listSortMasters["operationTypes"].find((its) => { - return its["sortCode"] == service.statusClass && its["language"] == this.language - })["sortValue"] + service["status"]; - } + })["sortValue"] + (service["rate"] > 100? service["status"] : ('\xa0\xa0\xa0' + service.rate + "%")); } - return this.queryNsProgress(jobid, null, updata, operationType); - }).then(() => { - this.myhttp.nsDeleteInstance(id) - .subscribe((data) => { - console.log(data); - service.rate = 100; - service.status = "Successful"; - service.tips = this.listSortMasters["operationTypes"].find((its) => { - return its["sortCode"] == service.statusClass && its["language"] == this.language - })["sortValue"] + this.listSortMasters["operationResults"].find((its) => { - return its["sortCode"] == 2001 && its["language"] == this.language - })["sortValue"]; - this.deleteSuccessNotification(templateDeleteSuccessFaild); - if (data.status == "FAILED") { - console.log("delete ns service Failed :" + JSON.stringify(data)); - service.status = "Failed"; - service.tips = this.listSortMasters["operationTypes"].find((its) => { - return its["sortCode"] == service.statusClass && its["language"] == this.language - })["sortValue"] + this.listSortMasters["operationResults"].find((its) => { - return its["sortCode"] == 2002 && its["language"] == this.language - })["sortValue"]; - this.deleteSuccessNotification(templateDeleteSuccessFaild); - return false; - } - console.log(service, "deleteservice"); - console.log(this.thisService, "thisService"); - let hasUndone = this.tableData.some((item) => { - return item.rate < 100; + this.queryNsProgress(jobid, null, updata, operationType).then(() => { + let paramsObj = { + "ns_instance_id":id + }; + this.myhttp.nsDeleteInstance(paramsObj) + .subscribe((data) => { + if(data.status == "SUCCESS"){ + service.rate = 100; + service.status = "Successful"; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2001 && its["language"] == this.language + })["sortValue"]; + this.notification1.notificationSuccess(service.serviceDomain,'deleteStarting',service["service-instance-name"] ||service["nsInstanceName"]) + }else { + service.status = "Failed"; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2002 && its["language"] == this.language + })["sortValue"]; + this.notification1.notificationFailed(service.serviceDomain,'deleteStarting',service["service-instance-name"] ||service["nsInstanceName"]) + return false; + } + let hasUndone = this.tableData.some((item) => { + return item.rate < 100; + }) + if (!hasUndone) { + setTimeout(() => { + this.getTableData(); + }, 1000) + } }) - if (!hasUndone) { - setTimeout(() => { - this.getTableData(); - }, 1000) - } - }) + }) }) } stopNsService(id, obj) { - let mypromise = new Promise((res, rej) => { - this.myhttp.stopNsService(id, obj) + let paramsObj = { + "ns_instance_id":id + } + return new Promise((res, rej) => { + this.myhttp.stopNsService(paramsObj, obj) .subscribe((data) => { this.loadingAnimateShow = false; if (data.status == "FAILED") { @@ -1275,87 +1084,77 @@ export class ServicesListComponent implements OnInit { res(data.jobId); }) }) - return mypromise; } queryProgress(obj, callback) { - let mypromise = new Promise((res, rej) => { + return new Promise( res => { + let operationTypeObj = {operationType:obj.operationType}; let errorNums = 180; - let requery = () => { - this.myhttp.getProgress(obj) + let requeryCcvpn = () => { + this.myhttp.getProgress(obj,operationTypeObj) .subscribe((data) => { - if (data.status == "FAILED") { + if (data.status === "FAILED") { callback({ progress: 255, status: "Failed" }); - return false; - } - if (data.operationStatus == null || data.operationStatus.progress == undefined) { + }else if (data.operationStatus === null || data.operationStatus.progress === undefined) { errorNums--; - if (errorNums == 0) { + if (errorNums === 0) { callback({ progress: 255, status: "time over" }); return false; } - setTimeout(() => { - requery(); - }, 10000) - return false; - } - if (data.operationStatus.progress > 100) { + this.progressCcvpnOutTimer = setTimeout(()=>{ + requeryCcvpn(); + },10000); + }else if (data.operationStatus.progress > 100) { callback({ progress: 255, status: "time over" }); - return false; - } - if (data.operationStatus.progress < 100) { + }else if (data.operationStatus.progress < 100) { callback(data.operationStatus); - setTimeout(() => { - requery(); - }, 5000) + this.progressingCcvpnTimer = setTimeout(()=>{ + requeryCcvpn(); + },5000); } else { res(data.operationStatus); } }) } - requery(); + requeryCcvpn(); }) - return mypromise; } queryNsProgress(jobid, id, callback, operationType) { - let mypromise = new Promise((res, rej) => { + return new Promise((res, rej) => { let errorNums = 180; - let requery = () => { - this.myhttp.getNsProgress(jobid, id, operationType) + let paramsObj = { + "responseId":0, + "serviceInstanceId":id, + "operationType":operationType + } + let requeryNs = () => { + this.myhttp.getNsProgress(jobid,paramsObj) .subscribe((data) => { if (data.status == "FAILED") { callback({ progress: 255, status: "Failed" }); - return false; - } - if (data.responseDescriptor == null || data.responseDescriptor.progress == undefined) { + }else if (data.responseDescriptor === null || data.responseDescriptor.progress === undefined) { errorNums--; - if (errorNums == 0) { + if (errorNums === 0) { callback({ progress: 255, status: "time over" }); return false; } - setTimeout(() => { - requery(); - }, 10000) - return false; - } - if (data.responseDescriptor.progress > 100 && data.responseDescriptor.status == "error") { + this.progressNsOutTimer = setTimeout(()=>{ + requeryNs(); + },10000); + }else if (data.responseDescriptor.progress > 100 && data.responseDescriptor.status === "error") { callback({ progress: 255, status: data.responseDescriptor.statusDescription }); - return false; - } - if (data.responseDescriptor.progress < 100) { + }else if (data.responseDescriptor.progress < 100) { callback(data.responseDescriptor); - setTimeout(() => { - requery(); - }, 5000) + this.progressingNsTimer = setTimeout(()=>{ + requeryNs(); + },5000); } else { res(data); } }) }; - requery(); + requeryNs(); }); - return mypromise; } - } diff --git a/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.html b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.html new file mode 100644 index 00000000..98e42ae7 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.html @@ -0,0 +1,18 @@ +<div class="top-list"> + <span class="round">{{serviceDomain}}</span> + <div class="top-list-text"> + <p> + <span>{{failedNum}}</span> + <span> {{"i18nTextDefine_Failed" | translate}} </span> + </p> + <p> + <span>{{successNum}}</span> + <span> {{"i18nTextDefine_Success" | translate}} </span> + </p> + <p> + <span>{{inProgressNum}}</span> + <span> {{"i18nTextDefine_InProgress" | translate}} </span> + </p> + <p class="service-description"> {{serviceDetailName | translate}} </p> + </div> +</div>
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.less b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.less new file mode 100644 index 00000000..a235b1e6 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.less @@ -0,0 +1,65 @@ +.top-list{ + position: relative; + width:100%; + max-width:400px; + height:170px; + background:url("/assets/images/servicelist-e2e.png") no-repeat; + background-size: 100% 100%; + border-radius:2px; + .round{ + position: absolute; + width: 60px; + height: 60px; + line-height: 60px; + text-align: center; + background:#E0EDFF; + border:2px solid rgba(224,237,255,1); + border-radius: 50%; + font-size:16px; + font-family:ArialMT; + color:#3C4F8C; + transition: .5s; + top: 42%; + margin-top: -30px; + left: 15%; + } + .top-list-text{ + position: absolute; + text-align: right; + line-height: 20px; + right: 12%; + color: #fff; + p{ + height: 28px; + margin-bottom: 0; + padding-left: 5px; + font-size: 14px; + clear: both; + span{ + display: inline-block; + float: right; + font-weight: 500; + text-align: right; + } + span:nth-child(1){ + font-size: 18px; + margin-left: 15px; + } + span:nth-child(2){ + width: 85px; + font-size: 16px; + } + } + p:nth-child(1){ + margin-top: 25px; + } + .service-description{ + + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + color: #3C4F8C; + + } + } +}
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.spec.ts new file mode 100644 index 00000000..b2d2cbb4 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TopCardComponent } from './top-card.component'; + +describe('TopCardComponent', () => { + let component: TopCardComponent; + let fixture: ComponentFixture<TopCardComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ TopCardComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TopCardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.ts b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.ts new file mode 100644 index 00000000..6004fb8e --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.ts @@ -0,0 +1,19 @@ +import { Component, OnInit, Input } from '@angular/core'; + +@Component({ + selector: 'app-top-card', + templateUrl: './top-card.component.html', + styleUrls: ['./top-card.component.less'] +}) +export class TopCardComponent implements OnInit { + @Input() serviceDomain: string; + @Input() failedNum: number; + @Input() successNum: number; + @Input() inProgressNum: number; + @Input() serviceDetailName: string; + constructor() { } + + ngOnInit() { + } + +} diff --git a/usecaseui-portal/src/app/views/services/services.component.html b/usecaseui-portal/src/app/views/services/services.component.html deleted file mode 100644 index 10142833..00000000 --- a/usecaseui-portal/src/app/views/services/services.component.html +++ /dev/null @@ -1,18 +0,0 @@ -<!-- - 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. ---> -<p> - services works! -</p> diff --git a/usecaseui-portal/src/app/views/services/services.component.ts b/usecaseui-portal/src/app/views/services/services.component.ts deleted file mode 100644 index eec235b4..00000000 --- a/usecaseui-portal/src/app/views/services/services.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-services', - templateUrl: './services.component.html', - styleUrls: ['./services.component.less'] -}) -export class ServicesComponent implements OnInit { - - constructor() { } - - ngOnInit() { - } - -} |