diff options
author | zhangab <zhanganbing@chinamobile.com> | 2018-10-23 11:32:03 +0800 |
---|---|---|
committer | zhangab <zhanganbing@chinamobile.com> | 2018-10-23 11:32:05 +0800 |
commit | de9d2e95b43991fccee342ebed03b006f6fed844 (patch) | |
tree | 0667c51a30fd3fed71fec797136d8adefc7d7baf /usecaseui-portal/src/app/services | |
parent | 101e5e37f4ece60af8d08020c7e4bd8f473adce7 (diff) |
Build AngularJs component for usecase-ui
Change-Id: I393f4837fc5f9cbd71448dbf20e1f1781f0656d3
Issue-ID: USECASEUI-154
Signed-off-by: zhangab <zhanganbing@chinamobile.com>
Diffstat (limited to 'usecaseui-portal/src/app/services')
14 files changed, 1294 insertions, 0 deletions
diff --git a/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.css b/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.css new file mode 100644 index 00000000..a1cc6455 --- /dev/null +++ b/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.css @@ -0,0 +1,59 @@ +/* + Copyright (C) 2018 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: 20px; +} +.list { + background-color: #fff; + border-radius: 5px; + padding: 10px; +} +.list nz-table tbody td span.onboarding { + font-size: 12px; + color: #147dc2; +} +.list nz-table tbody td span.onboarded { + font-size: 14px; + color: #147dc2; +} +.list nz-table tbody td span.updating { + font-size: 12px; + color: blue; +} +.list nz-table tbody td span.deleting { + font-size: 12px; + color: red; +} +.list nz-table tbody td span.invalid { + font-size: 14px; + color: purple; +} +.list nz-table tbody td i.anticon { + cursor: pointer; + font-size: 18px; + padding: 2px; +} +.list nz-table tbody td i.anticon:hover { + color: #147dc2; +} diff --git a/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.html b/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.html new file mode 100644 index 00000000..d5286a3a --- /dev/null +++ b/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.html @@ -0,0 +1,61 @@ +<!-- + Copyright (C) 2018 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"> Onboard VNF </h3> +<hr> +<div class="list"> + <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" + (nzPageIndexChange)="searchData()" + (nzPageSizeChange)="searchData(true)"> + <thead (nzSortChange)="sort($event)" nzSingleSort> + <tr> + <th nzWidth="5%">NO</th> + <th nzWidth="20%" nzShowSort nzSortKey="name"> Name </th> + <th nzWidth="20%">Type</th> + <th nzWidth="15%">Version</th> + <th nzWidth="20%">Status</th> + <th nzWidth="15%">Action</th> + </tr> + </thead> + <tbody> + <!-- <ng-template ngFor let-data [ngForOf]="nzTable.data" let-i="index"> --> + <tr *ngFor="let item of nzTable.data; let i = index; "> + <td>{{i+1}}</td> + <td>{{item.name}}</td> + <td>{{item.type}}</td> + <td>{{item.version}}</td> + <td> + <span [ngClass]="{'onboarding':item.status=='Onboarding','onboarded':item.status=='Onboarded', + 'updating':item.status=='Updating','deleting':item.status=='Deleting','invalid':item.status=='Invalid'}">{{item.status}}</span> + <nz-progress *ngIf="item.status!='Onboarded' && item.status!='Invalid'" [nzPercent]="item.progress"></nz-progress> + </td> + <td> + <i class="anticon anticon-cloud-upload-o" (click)="updataService()"></i> + <i class="anticon anticon-delete" (click)="deleteService()"></i> + </td> + </tr> + <!-- </ng-template> --> + </tbody> + </nz-table> +</div>
\ No newline at end of file diff --git a/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.less b/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.less new file mode 100644 index 00000000..ab118737 --- /dev/null +++ b/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.less @@ -0,0 +1,50 @@ +.title { + font: 700 18px/18px "思源黑体"; + color: #4c5e70; + margin-bottom: 18px; +} +hr { + border: none; + height: 2px; + background-color: #dce1e7; + margin-bottom: 20px; +} +.list { + background-color: #fff; + border-radius: 5px; + padding: 10px; + 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; + padding: 2px; + &:hover{ + color: #147dc2; + } + } + } + } + } +}
\ No newline at end of file diff --git a/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.spec.ts b/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.spec.ts new file mode 100644 index 00000000..0e49f656 --- /dev/null +++ b/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { OnboardVnfVmComponent } from './onboard-vnf-vm.component'; + +describe('OnboardVnfVmComponent', () => { + let component: OnboardVnfVmComponent; + let fixture: ComponentFixture<OnboardVnfVmComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ OnboardVnfVmComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(OnboardVnfVmComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.ts b/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.ts new file mode 100644 index 00000000..c42b3ce3 --- /dev/null +++ b/usecaseui-portal/src/app/services/onboard-vnf-vm/onboard-vnf-vm.component.ts @@ -0,0 +1,61 @@ +import { Component, OnInit, HostBinding } from '@angular/core'; +import { MyhttpService } from '../../myhttp.service'; +import { slideToRight } from '../../animates'; + +@Component({ + selector: 'app-onboard-vnf-vm', + templateUrl: './onboard-vnf-vm.component.html', + styleUrls: ['./onboard-vnf-vm.component.less'], + animations: [ slideToRight ] +}) +export class OnboardVnfVmComponent implements OnInit { + @HostBinding('@routerAnimate') routerAnimateState; + constructor(private myhttp: MyhttpService) { } + + ngOnInit() { + this.getTableData(); + } + + + //表格数据 + tableData = []; + pageIndex = 1; + pageSize = 10; + total = 100; + loading = false; + sortName = null; + sortValue = null; + getTableData(){ + // 查询参数: 当前页码,每页条数,排序方式 + let paramsObj = { + pageIndex:this.pageIndex, + pageSize:this.pageSize, + nameSort:this.sortValue + } + this.myhttp.getOnboardTableData(paramsObj) + .subscribe((data)=>{ + console.log(data); + this.total = data.body.total; + this.tableData = data.body.tableList; + },(err)=>{ + console.log(err); + }) + } + sort(sort: { key: string, value: string }): void { + console.log(sort); + this.sortName = sort.key; + this.sortValue = sort.value; + this.getTableData(); + } + searchData(reset:boolean = false){ + console.log(reset) + this.getTableData(); + } + updataService(){ + console.log("updataService!"); + } + deleteService(){ + console.log("deleteService!"); + } + +} diff --git a/usecaseui-portal/src/app/services/services-list/services-list.component.css b/usecaseui-portal/src/app/services/services-list/services-list.component.css new file mode 100644 index 00000000..eaf8fddb --- /dev/null +++ b/usecaseui-portal/src/app/services/services-list/services-list.component.css @@ -0,0 +1,132 @@ +/* + Copyright (C) 2018 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: 20px; +} +.action { + margin-bottom: 20px; +} +.action span { + display: inline-block; + font: 700 14px "Arial"; + color: #4c5e70; +} +.action nz-dropdown { + vertical-align: middle; +} +.action nz-dropdown :hover { + border-color: #147dc2; +} +.action nz-dropdown button { + width: 165px; + height: 30px; + background-color: #eceff4; + text-align: left; + border-color: #9fa9ab; +} +.action nz-dropdown button span { + font-weight: 400; + display: inline-block; + width: 120px; + overflow: hidden; + text-overflow: ellipsis; + padding-top: 2px; +} +.action nz-dropdown button i { + position: absolute; + top: 10px; + right: 10px; +} +.action .create { + float: right; + height: 30px; + padding: 0 10px; +} +.action .create span { + color: #fff; + font-weight: 400; +} +.list { + background-color: #fff; + border-radius: 5px; + padding: 10px; +} +.list nz-table tbody td span.active { + font-size: 14px; + color: #147dc2; +} +.list nz-table tbody td span.closed { + font-size: 14px; + color: red; +} +.list nz-table tbody td span.onboarding { + font-size: 12px; + color: #147dc2; +} +.list nz-table tbody td span.updating { + font-size: 12px; + color: blue; +} +.list nz-table tbody td span.deleting { + font-size: 12px; + color: red; +} +.list nz-table tbody td span.creating { + font-size: 12px; + color: green; +} +.list nz-table tbody td i.anticon { + cursor: pointer; + font-size: 18px; + padding: 2px; +} +.list nz-table tbody td i.anticon:hover { + color: #147dc2; +} +.list nz-table tbody tr.childtr td { + font-size: 12px; + color: #147dc2; +} +.detailComponent { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100vh; + background-color: #f3f3f3; + overflow-y: auto; + padding: 20px 32px; + z-index: 3; +} +.createComponent { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100vh; + background-color: #f3f3f3; + overflow-y: auto; + padding: 20px 32px; + z-index: 3; +} diff --git a/usecaseui-portal/src/app/services/services-list/services-list.component.html b/usecaseui-portal/src/app/services/services-list/services-list.component.html new file mode 100644 index 00000000..e0866524 --- /dev/null +++ b/usecaseui-portal/src/app/services/services-list/services-list.component.html @@ -0,0 +1,185 @@ +<!-- + Copyright (C) 2018 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> +<hr> +<div class="action"> + <span>Customer: </span> + <nz-dropdown [nzTrigger]="'click'" [nzPlacement]="'bottomLeft'"> + <button nz-button nz-dropdown><span>{{customerSelected.name}}</span> <i class="anticon anticon-down"></i></button> + <ul nz-menu style="max-height: 200px; overflow: auto;"> + <li nz-menu-item (click)="choseCustomer(item)" *ngFor="let item of customerList"> + <a title="{{item.name}}" style="max-width: 165px; overflow: hidden; text-overflow: ellipsis;">{{item.name}}</a> + </li> + </ul> + </nz-dropdown> + + + <span>Service Type: </span> + <nz-dropdown [nzTrigger]="'click'" [nzPlacement]="'bottomLeft'"> + <button nz-button nz-dropdown><span>{{serviceTypeSelected.name}}</span> <i class="anticon anticon-down"></i></button> + <ul nz-menu style="max-height: 200px; overflow: auto;"> + <li nz-menu-item (click)="choseServiceType(item)" *ngFor="let item of serviceTypeList"> + <a title="{{item.name}}" style="max-width: 165px; overflow: hidden; text-overflow: ellipsis;">{{item.name}}</a> + </li> + </ul> + </nz-dropdown> + + <button class="create" nz-button [nzType]="'primary'" (click)="showModal()"><i class="anticon anticon-plus-circle-o"></i><span> Create </span></button> + <nz-modal [(nzVisible)]="isVisible" nzTitle="Create" (nzOnCancel)="handleCancel()" (nzOnOk)="handleOk()"> + <p>Content one</p> + <p>Content two</p> + <p>Content three</p> + </nz-modal> + <button class="create" nz-button [nzType]="'primary'" (click)="showModal2()"><i class="anticon anticon-plus-circle-o"></i><span> Create </span></button> + <nz-modal [(nzVisible)]="isVisible2" nzTitle="Create" (nzOnCancel)="handleCancel()" (nzOnOk)="handleOk2()"> + <span style="display:inline-block;width:70px;">Service: </span> + <nz-select style="width: 165px;" [(ngModel)]="templateTypeSelected" nzAllowClear (ngModelChange)="choseTemplateType()"> + <!-- <nz-option *ngFor="let item of templateType" [nzValue]="item" [nzLabel]="item"></nz-option> --> + <nz-option nzValue="SOTN" nzLabel="SOTN"></nz-option> + <nz-option nzValue="CCVPN" nzLabel="CCVPN"></nz-option> + </nz-select> + + <hr> + <span>SOTN VPN: </span> + <nz-select style="width: 165px;" [(ngModel)]="template1" nzAllowClear > + <nz-option *ngFor="let item of templates" [nzValue]="item" [nzLabel]="item.name"></nz-option> + </nz-select> + + <span> SITE: </span> + <nz-select style="width: 165px;" [(ngModel)]="template2" nzAllowClear > + <nz-option *ngFor="let item of templates" [nzValue]="item" [nzLabel]="item.name"></nz-option> + </nz-select> + + <div *ngIf="templateTypeSelected == 'CCVPN'"> + <br> + <span style="display:inline-block;width:70px;">SD-WAN: </span> + <nz-select style="width: 165px;" [(ngModel)]="template3" nzAllowClear > + <nz-option *ngFor="let item of templates" [nzValue]="item" [nzLabel]="item.name"></nz-option> + </nz-select> + </div> + </nz-modal> +</div> +<div class="list"> + <nz-table *ngIf="1" + #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' }" + (nzPageIndexChange)="searchData()" + (nzPageSizeChange)="searchData(true)"> + <thead (nzSortChange)="sort($event)" nzSingleSort> + <tr> + <th nzWidth="5%">NO</th> + <th nzWidth="5%"></th> + <th nzWidth="20%" nzShowSort nzSortKey="name">Service Instance Id</th> + <th nzWidth="20%">Name</th> + <th nzWidth="15%">Type</th> + <th nzWidth="20%">Status</th> + <th nzWidth="15%">Action</th> + </tr> + </thead> + <tbody> + <ng-template ngFor let-data [ngForOf]="nzTable.data" let-i="index"> + <tr> + <td>{{i+1}}</td> + <td [nzShowExpand]="data.children[0]" [(nzExpand)]="data.expand"></td> + <td>{{data.serviceId}}</td> + <td>{{data.name}}</td> + <td>{{data.type}}</td> + <td> + <span [ngClass]="{'active':data.status=='Active','closed':data.status=='Closed','onboarding':data.status=='Onboarding', + 'updating':data.status=='Updating','deleting':data.status=='Deleting','creating':data.status=='Creating'}">{{data.status}}</span> + <nz-progress *ngIf="data.status!='Active' && data.status!='Closed'" [nzPercent]="data.progress"></nz-progress> + </td> + <td> + <i class="anticon anticon-setting" (click)="scaleService()"></i> + <i class="anticon anticon-cloud-upload-o" (click)="updataService()"></i> + <i class="anticon anticon-delete" (click)="deleteService()"></i> + </td> + </tr> + <tr class="childtr" [nzExpand]="data.expand" *ngFor="let item of data.children"> + <td></td> + <td></td> + <td>{{item.serviceId}}</td> + <td>{{item.name}}</td> + <td colspan="3">{{item.type}}</td> + </tr> + </ng-template> + </tbody> + </nz-table> + <nz-table *ngIf="1" + #nzTable2 [nzData]="tableData2" + nzShowSizeChanger + [nzFrontPagination]="true" + [nzShowQuickJumper]="true" + [nzPageSizeOptions]="[5,10,15,20]" + [(nzPageSize)]="pageSize" + [(nzPageIndex)]='pageIndex' + nzSize="middle" + [nzScroll]="{ y: '58vh' }"> + <thead nzSingleSort> + <tr> + <th nzWidth="5%">NO.</th> + <th nzWidth="20%"> Instance ID </th> + <th nzWidth="20%">Instance Name</th> + <!-- <th nzWidth="10%">Type</th> --> + <th nzWidth="25%">Description</th> + <th nzWidth="15%">Status</th> + <th nzWidth="10%">Action</th> + </tr> + </thead> + <tbody> + <!-- <ng-template ngFor let-data [ngForOf]="nzTable2.data" let-i="index"> --> + <tr *ngFor="let item of nzTable2.data; let i = index; "> + <td>{{pageSize*(pageIndex-1) + i+1}}</td> + <td>{{item.sotnvpnSer['service-instance-id']}}</td> + <td>{{item.sotnvpnSer['service-instance-name']}}</td> + <!-- <td>{{item.type}}</td> --> + <td>{{item.sotnvpnSer.description}}</td> + <td> + <span *ngIf="item.sotnvpnSer.status!='creating' && item.sotnvpnSer.status!='deleting'">{{item.sotnvpnSer.status}}</span> + <span *ngIf="item.sotnvpnSer.status=='creating' || item.sotnvpnSer.status=='deleting'" [ngClass]="{'deleting':item.sotnvpnSer.status=='deleting','creating':item.sotnvpnSer.status=='creating'}">{{item.sotnvpnSer.status}}</span> + <nz-progress *ngIf="item.sotnvpnSer.status=='creating' || item.sotnvpnSer.status=='deleting'" [nzPercent]="item.sotnvpnSer.rate"></nz-progress> + </td> + <td> + <span title="detail" class="action" [ngClass]="{'cannotclick':item.sotnvpnSer.status=='deleting'||item.sotnvpnSer.status=='creating'}" + (click)="showDetail(item)"> <i class="anticon anticon-ellipsis"></i> </span> + <span title="delete" class="action" [ngClass]="{'cannotclick':item.sotnvpnSer.status=='deleting'||item.sotnvpnSer.status=='creating'}" + (click)="deleteInstace(item)"> <i class="anticon anticon-delete"></i> </span> + </td> + </tr> + <!-- </ng-template> --> + </tbody> + </nz-table> +</div> + +<div class="detailComponent" *ngIf="detailshow"> + <app-ccvpn-detail [namesTranslate]="namesTranslate" [detailParams]="detailData" (closeDetail)="detailshow = false;"></app-ccvpn-detail> +</div> +<div class="createComponent" *ngIf="createshow"> + <app-ccvpn-creation + [createParams]="createData" + [namesTranslate]="namesTranslate" + (closeCreate)="closeCreate($event)"> + </app-ccvpn-creation> +</div> diff --git a/usecaseui-portal/src/app/services/services-list/services-list.component.less b/usecaseui-portal/src/app/services/services-list/services-list.component.less new file mode 100644 index 00000000..7e8ff80e --- /dev/null +++ b/usecaseui-portal/src/app/services/services-list/services-list.component.less @@ -0,0 +1,127 @@ +.title { + font: 700 18px/18px "思源黑体"; + color: #4c5e70; + margin-bottom: 18px; +} +hr { + border: none; + height: 2px; + background-color: #dce1e7; + margin-bottom: 20px; +} +.action { + margin-bottom: 20px; + span { + display: inline-block; + font: 700 14px "Arial"; + color: #4c5e70; + } + nz-dropdown { + vertical-align: middle; + :hover{ + border-color: #147dc2; + } + button { + width: 165px; + height: 30px; + background-color: #eceff4; + text-align: left; + border-color: #9fa9ab; + span { + font-weight: 400; + display: inline-block; + width: 120px; + overflow: hidden; + text-overflow: ellipsis; + padding-top: 2px; + } + i { + position: absolute; + top: 10px; + right: 10px; + } + } + //下拉框中的样式在style.less中,下拉框是在body中额外临时生成的 + } + .create { + float: right; + height: 30px; + padding: 0 10px; + span { + color: #fff; + font-weight: 400; + } + } +} +.list { + background-color: #fff; + border-radius: 5px; + padding: 10px; + nz-table { + tbody { + td { + span.active { + font-size: 14px; + color: #147dc2; + } + span.closed { + font-size: 14px; + color: red; + } + span.onboarding{ + font-size: 12px; + color: #147dc2; + } + span.updating{ + font-size: 12px; + color: blue; + } + span.deleting { + font-size: 12px; + color: red; + } + span.creating { + font-size: 12px; + color: green; + } + i.anticon { + cursor: pointer; + font-size: 18px; + padding: 2px; + &:hover{ + color: #147dc2; + } + } + } + tr.childtr { + td { + font-size: 12px; + color: #147dc2; + } + } + } + } +} + +.detailComponent { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100vh; + background-color: #f3f3f3; + overflow-y: auto; + padding: 20px 32px; + z-index: 3; +} +.createComponent { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100vh; + background-color: #f3f3f3; + overflow-y: auto; + padding: 20px 32px; + z-index: 3; +} diff --git a/usecaseui-portal/src/app/services/services-list/services-list.component.spec.ts b/usecaseui-portal/src/app/services/services-list/services-list.component.spec.ts new file mode 100644 index 00000000..61440dc3 --- /dev/null +++ b/usecaseui-portal/src/app/services/services-list/services-list.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ServicesListComponent } from './services-list.component'; + +describe('ServicesListComponent', () => { + let component: ServicesListComponent; + let fixture: ComponentFixture<ServicesListComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ServicesListComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ServicesListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/usecaseui-portal/src/app/services/services-list/services-list.component.ts b/usecaseui-portal/src/app/services/services-list/services-list.component.ts new file mode 100644 index 00000000..d893070d --- /dev/null +++ b/usecaseui-portal/src/app/services/services-list/services-list.component.ts @@ -0,0 +1,511 @@ +import { Component, OnInit, HostBinding } from '@angular/core'; +import { MyhttpService } from '../../myhttp.service'; +import { slideToRight } from '../../animates'; +import { NzModalService } from 'ng-zorro-antd'; + +@Component({ + selector: 'app-services-list', + templateUrl: './services-list.component.html', + styleUrls: ['./services-list.component.less'], + animations: [ slideToRight ] +}) +export class ServicesListComponent implements OnInit { + @HostBinding('@routerAnimate') routerAnimateState; + constructor(private myhttp: MyhttpService, private modalService: NzModalService) { } + + ngOnInit() { + this.getallCustomers(); + this.getTemplateSubTypes(); + this.inputNamests(); + } + // 筛选框(下拉框)customer servicetype + customerList = []; + customerSelected = {name:null,id:null}; + serviceTypeList = []; + serviceTypeSelected = {name:null,id:null}; + + // 获取所有customer + getallCustomers(){ + this.myhttp.getAllCustomers() + .subscribe((data)=>{ + this.customerList = data.map((item)=>{return {name:item["subscriber-name"],id:item["global-customer-id"]}}); + this.customerSelected = this.customerList[0]; + this.choseCustomer(this.customerSelected); + // console.log(this.customers) + }) + } + + choseCustomer(item){ + this.customerSelected = item; + this.myhttp.getServiceTypes(this.customerSelected) + .subscribe((data)=>{ + this.serviceTypeList = data.map((item)=>{return {name:item["service-type"]}}); + this.serviceTypeSelected = this.serviceTypeList[0]; + this.choseServiceType(this.serviceTypeSelected); + // console.log(this.listServiceTypes); + }) + } + choseServiceType(item){ + this.serviceTypeSelected = item; + this.getTableData(); + } + + // 模态框(对话框) create + isVisible = false; + showModal(): void { + this.isVisible = true; + } + handleOk(): void { + console.log('Button ok clicked!'); + this.isVisible = false; + } + handleCancel(): void { + console.log('Button cancel clicked!'); + this.isVisible = false; + this.isVisible2 = false; + } + + // 创建模态框2(对话框) create ------------------------------- + isVisible2 = false; + showModal2(): void { + this.isVisible2 = true; + this.templates1 = []; //多次创建会push累积名字,从新置空 + this.templates2 = []; + this.templates3 = []; + this.getAlltemplates(); + } + // 服务 + templateTypeSelected = "SOTN"; + choseTemplateType(){ + // this.filterTemplates();//分类 + } + // 模板 + templates = []; templates1;templates2;templates3; + template1={name:null}; + template2={name:null}; + template3={name:null}; + // 模板分类数据,创建、获取实例分类共用 + templateSubTypes = {}; //子类,sotnvpn、site、sdwan + getTemplateSubTypes(){ + this.myhttp.getServicesCategory() + .subscribe((data)=>{ + this.templateSubTypes = data; + },(err)=>{ + console.log("getTemplateTypes err") + }) + } + + getAlltemplates(){ //获取所有模板类型 + this.myhttp.getAllServiceTemplates() + .subscribe((data)=>{ + console.log(data) + this.templates = data; + this.template1 = data[0]; + this.template2 = data[1]; + this.template3 = data[2]; + // this.filterTemplates();//分类 + },(err)=>{ + + }) + } + // filterTemplates(){ //模板类型分类,本地配置文件 + // this.templates1 = []; + // this.templates2 = []; + // this.templates3 = []; + // this.templates.forEach((item)=>{ + // this.templateSubTypes[this.templateTypeSelected].sotnvpn.find((d)=>{ + // return d["model-invariant-id"] == item.uuid && d["model-version-id"] == item.invariantUUID + // })?this.templates1.push(item):null; + // this.templateSubTypes[this.templateTypeSelected].site.find((d)=>{ + // return d["model-invariant-id"] == item.uuid && d["model-version-id"] == item.invariantUUID + // })?this.templates2.push(item):null; + // if(this.templateTypeSelected=="CCVPN"){ + // this.templateSubTypes[this.templateTypeSelected].sdwan.find((d)=>{ + // return d["model-invariant-id"] == item.uuid && d["model-version-id"] == item.invariantUUID + // })?this.templates3.push(item):null; + // } + // }) + // this.template1 = this.templates1[0]; + // this.template2 = this.templates2[0]; + // if(this.templates3[0]){ + // this.template3 = this.templates3[0]; + // } + // } + + + // 确定、取消 + createshow = false; + createData:Object={}; + handleOk2(): void { + console.log('Button ok clicked!'); + this.isVisible2 = false; + let data1 = {commonParams:{customer:this.customerSelected, serviceType:this.serviceTypeSelected, templateType:"SOTN"},templates:{template1:this.template1,template2:this.template2}}; + let data2 = {commonParams:{customer:this.customerSelected, serviceType:this.serviceTypeSelected, templateType:"CCVPN"},templates:{template1:this.template1,template2:this.template2,template3:this.template3}}; + + this.createData = this.templateTypeSelected == "SOTN" ? data1 : data2; + this.createshow = true; + } + // handleCancel(): void { + // console.log('Button cancel clicked!'); + // this.isVisible2 = false; + // } + + + //表格数据 + tableData = []; + pageIndex = 1; + pageSize = 10; + total = 100; + loading = false; + sortName = null; + sortValue = null; + getTableData(){ + // 查询参数: customer serviceType 当前页码,每页条数,排序方式 + let paramsObj = { + customer:this.customerSelected, + serviceType:this.serviceTypeSelected, + pageIndex:this.pageIndex, + pageSize:this.pageSize, + serviceIdSort:this.sortValue + } + this.myhttp.getServicesTableData(paramsObj) + .subscribe((data)=>{ + console.log(data); + this.total = data.body.total; + this.tableData = data.body.tableList; + },(err)=>{ + console.log(err); + }) + } + sort(sort: { key: string, value: string }): void { + console.log(sort); + this.sortName = sort.key; + this.sortValue = sort.value; + this.getTableData(); + } + searchData(reset:boolean = false){ + console.log(reset) + this.getTableData(); + } + + scaleService(){ + console.log("scaleService!"); + } + updataService(){ + console.log("updataService!"); + } + deleteService(){ + console.log("deleteService!"); + } + + //表格数据 + tableData2 = []; + getTableData2(){ + let params = { + customerId:this.customerSelected.id, + serviceType:this.serviceTypeSelected + } + this.myhttp.getInstanceTableData(params) + .subscribe((data)=>{ + this.pageIndex = 1; + this.tableData2 = []; + console.log(data) + // data.results.forEach((item)=>{ + // item["sotnvpnSer"] = item["service-subscription"]["service-instances"]["service-instance"].find((d)=>{ + // return this.templateSubTypes["SOTN"].sotnvpn.find((m)=>{ + // return d["model-invariant-id"]==m["model-invariant-id"] && d["model-version-id"]==m["model-version-id"] + // })?item["Type"]="SOTN":null || this.templateSubTypes["CCVPN"].sotnvpn.find((m)=>{ + // return d["model-invariant-id"]==m["model-invariant-id"] && d["model-version-id"]==m["model-version-id"] + // })?item["Type"]="CCVPN":null + // }) + + // if(item["sotnvpnSer"]){ + // this.tableData2.push(item); + // } + // }) + + //---------数据结构有问题,模拟只有一组数据情况---------// + data["sotnvpnSer"] = data["service-instance"].find((d)=>{ + return this.templateSubTypes["SOTN"].sotnvpn.find((m)=>{ + return d["model-invariant-id"]==m["model-invariant-id"] && d["model-version-id"]==m["model-version-id"] + })?d["Type"]="SOTN":null || this.templateSubTypes["CCVPN"].sotnvpn.find((m)=>{ + return d["model-invariant-id"]==m["model-invariant-id"] && d["model-version-id"]==m["model-version-id"] + })?d["Type"]="CCVPN":null + }) + let inputParams = JSON.parse(data["sotnvpnSer"]["input-parameters"]).service.parameters.requestInputs; + let descriptionName = Object.keys(inputParams).find((item)=>{ return item.endsWith("_description")}); + data["sotnvpnSer"]["description"] = inputParams[descriptionName]; + data["sotnvpnSer"]["status"] = "Active"; + this.tableData2.push(data); + + console.log(this.tableData2) + },(err)=>{ + console.log(err); + }) + } + + // 显示详情 + detailshow = false; + detailData:Object; + showDetail(service){ + service["siteSer"]=[]; + service["sdwanSer"]=[]; + service["customer"]=this.customerSelected; + service["serviceType"] = this.serviceTypeSelected; + // service["service-subscription"]["service-instances"]["service-instance"].forEach((item)=>{ + // this.templateSubTypes[service.Type].site.find((d)=>{ + // return d["model-invariant-id"] == item["model-invariant-id"] && d["model-version-id"] == item["model-version-id"] + // })?service["siteSer"].push(item):null; + // if(service.Type=="CCVPN"){ + // this.templateSubTypes[service.Type].sdwan.find((d)=>{ + // return d["model-invariant-id"] == item["model-invariant-id"] && d["model-version-id"] == item["model-version-id"] + // })?service["sdwanSer"].push(item):null; + // } + // }) + service["service-instance"].forEach((item)=>{ + this.templateSubTypes[service.sotnvpnSer.Type].site.find((d)=>{ + return d["model-invariant-id"] == item["model-invariant-id"] && d["model-version-id"] == item["model-version-id"] + })?service["siteSer"].push(item):null; + if(service.sotnvpnSer.Type=="CCVPN"){ + this.templateSubTypes[service.sotnvpnSer.Type].sdwan.find((d)=>{ + return d["model-invariant-id"] == item["model-invariant-id"] && d["model-version-id"] == item["model-version-id"] + })?service["sdwanSer"].push(item):null; + } + }) + this.detailshow = true; + this.detailData = service; + console.log(service); + } + // 删除 确认模态框 + deleteInstace(service){ + // 创建确认框 + this.modalService.confirm({ + nzTitle : 'Are you sure delete this instance?', + nzContent : `Instance ID: <b class="deleteModelContent"> ${service.sotnvpnSer["service-instance-id"]}</b>`, + nzOkText : 'Yes', + nzOkType : 'danger', + nzOnOk : () => { + console.log(service); + let allprogress = {}; //所有进度值,以operationId为键 + let querypros = []; //所有查询 + service.sotnvpnSer.rate = 0; + service.sotnvpnSer.status = "deleting"; + // let deletePros = service["service-subscription"]["service-instances"]["service-instance"].map((item)=>{ + // let id = item["service-instance-id"]; + // return new Promise((res,rej)=>{ + // this.myhttp.deleteInstance(id) + // .subscribe((data)=>{ + // let obj = {serviceId:id,operationId:data.operationId} + // let updata = (prodata)=>{ + // allprogress[prodata.operationId] = prodata.progress; + // let average = ((arr)=>{return eval(arr.join("+"))/arr.length})(Object.values(allprogress)); + // service.sotnvpnSer["rate"]=average; + // } + // querypros.push(this.queryProgress(obj,updata)); + // res(); + // }) + // }) + // }) + let deletePros = service["service-instance"].map((item)=>{ + let params = { + globalSubscriberId:this.customerSelected.id, + serviceType:this.serviceTypeSelected, + serviceInstanceId:item["service-instance-id"] + } + return new Promise((res,rej)=>{ + this.myhttp.deleteInstance(params) + .subscribe((data)=>{ + let obj = {serviceId:params.serviceInstanceId,operationId:data.operationId} + let updata = (prodata)=>{ + allprogress[prodata.operationId] = prodata.progress; + let average = ((arr)=>{return eval(arr.join("+"))/arr.length})(Object.values(allprogress)); + service.sotnvpnSer["rate"]=average; + } + querypros.push(this.queryProgress(obj,updata)); + res(); + }) + }) + }) + console.log(deletePros) + Promise.all(deletePros).then(()=>{ + Promise.all(querypros).then((data)=>{ + console.log(data); + service.sotnvpnSer.rate = 100; + service.sotnvpnSer.status = "deleted"; + setTimeout(()=>{ + this.getTableData(); + },1000) + }) + }) + + }, + nzCancelText: 'No', + nzOnCancel : () => console.log('Cancel') + }); + } + + + closeCreate(obj){ + if(!obj){ + this.createshow = false; //关闭创建窗口 + return false; + } + this.createshow = false; //关闭创建窗口 + console.log(obj); + let newData; //主表格中新创建的服务数据 + let stageNum = 0; //不同阶段进度,用于后续服务进度相加; + // -------------------------------------------------------------------------- + // obj.groupbody.map((group)=>{ //所有创建 + // return this.createService(group) + // }) + // obj.sitebody.map((group)=>{ //所有创建 + // console.log(group) + // return this.createService(group) + // }) + // ----------------------------------------------------------------------------- + this.createService(obj.vpnbody).then((data)=>{ + console.log(data) + newData = { //主表格中新创建的服务数据 + 'service-instance-id':data["serviceId"], + 'service-instance-name':obj.vpnbody.service.name, + description:obj.vpnbody.service.description, + status:"creating", + rate:0, + } + this.tableData2 = [{sotnvpnSer:newData},...this.tableData2]; + let updata = (prodata)=>{ + newData.rate = Math.floor(prodata.progress/3); + } + let queryParams = {serviceId:data["serviceId"],operationId:data["operationId"]}; + return this.queryProgress(queryParams,updata); + }).then((data)=>{ + console.log(data); + stageNum = newData.rate; //阶段进度值更新; + let allprogress = {}; //所有进度值,以operationId为键 + let querypros = []; //所有查询 + let createPros = obj.groupbody.map((group)=>{ //所有创建 + return this.createService(group).then((data)=>{ + console.log(data); + let updata = (prodata)=>{ + allprogress[prodata.operationId] = prodata.progress; + let average = ((arr)=>{return eval(arr.join("+"))/arr.length})(Object.values(allprogress)) + newData.rate = Math.floor(average/3) + stageNum; + } + let queryParams = {serviceId:data["serviceId"],operationId:data["operationId"]}; + querypros.push(this.queryProgress(queryParams,updata)) + }) + }) + + return new Promise((res)=>{ + Promise.all(createPros).then(()=>{ //所有创建好之后querypros中查询进度才全都添加完毕 + Promise.all(querypros).then((data)=>{ + console.log(data); + res("site--begin"); + }) + }) + }) + }).then((data)=>{ + console.log(data); + stageNum = newData.rate; //阶段进度值更新; + let allprogress = {}; + let querypros = []; //所有查询 + let createPros = obj.sitebody.map((group)=>{ //所有创建 + return this.createService(group).then((data)=>{ + console.log(data); + let updata = (prodata)=>{ + allprogress[prodata.operationId] = prodata.progress; + let average =((arr)=>{return eval(arr.join("+"))/arr.length})(Object.values(allprogress)) + newData.rate = Math.floor(average/3) + stageNum; + } + let queryParams = {serviceId:data["serviceId"],operationId:data["operationId"]}; + querypros.push(this.queryProgress(queryParams,updata)) + }) + }) + console.log(createPros); + Promise.all(createPros).then(()=>{ //所有创建好之后querypros中查询进度才全都添加完毕 + Promise.all(querypros).then((data)=>{ + console.log(data); + newData.rate = 100; + newData.status = "completed"; + setTimeout(()=>{ + this.getTableData(); + },1000) + }) + }) + }) + + } + + createService(params){ + let mypromise = new Promise((res,rej)=>{ + this.myhttp.createInstance(params) + .subscribe((data)=>{ + + res(data.service); + }) + }) + return mypromise; + } + + queryProgress(obj,callback){ + let mypromise = new Promise((res,rej)=>{ + // let data = { + // operationStatus:{ + // "operationId": "XXXXXX", + // "operation": "create|delete|update|scale", + // "result": "finished|error|processing", + // "reason": "", + // "userId": "", + // "operationContent": "Be creating pop.", + // "progress": 0, + // "operateAt": "", + // "finishedAt": "" + // } + // } + let requery = ()=>{ + this.myhttp.getProgress(obj) + .subscribe((data)=>{ + if(data.operationStatus.progress==undefined){ + console.log(data); + setTimeout(()=>{ + requery(); + },5000) + return false; + } + if(data.operationStatus.progress < 100){ + callback(data.operationStatus); + setTimeout(()=>{ + requery(); + },5000) + }else { + res(data.operationStatus); + } + }) + // setTimeout(()=>{ + // console.log(data.operationStatus.progress) + // data.operationStatus.progress++; + // if(data.operationStatus.progress<100){ + // callback(data.operationStatus); + // requery() + // }else{ + // callback(data.operationStatus); + // res(data.operationStatus) + // } + // },100) + } + requery(); + }) + return mypromise; + } + + + // 名字转换参数匹配 --> 传给子组件用 + namesTranslate:Object; + inputNamests(){ + this.myhttp.inputNamesTransform() + .subscribe((data)=>{ + this.namesTranslate = data; + }) + } + +} diff --git a/usecaseui-portal/src/app/services/services.component.html b/usecaseui-portal/src/app/services/services.component.html new file mode 100644 index 00000000..c4fddfc0 --- /dev/null +++ b/usecaseui-portal/src/app/services/services.component.html @@ -0,0 +1,18 @@ +<!-- + Copyright (C) 2018 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/services/services.component.less b/usecaseui-portal/src/app/services/services.component.less new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/usecaseui-portal/src/app/services/services.component.less diff --git a/usecaseui-portal/src/app/services/services.component.spec.ts b/usecaseui-portal/src/app/services/services.component.spec.ts new file mode 100644 index 00000000..2e76b9f9 --- /dev/null +++ b/usecaseui-portal/src/app/services/services.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ServicesComponent } from './services.component'; + +describe('ServicesComponent', () => { + let component: ServicesComponent; + let fixture: ComponentFixture<ServicesComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ServicesComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ServicesComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/usecaseui-portal/src/app/services/services.component.ts b/usecaseui-portal/src/app/services/services.component.ts new file mode 100644 index 00000000..eec235b4 --- /dev/null +++ b/usecaseui-portal/src/app/services/services.component.ts @@ -0,0 +1,15 @@ +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() { + } + +} |