diff options
Diffstat (limited to 'usecaseui-portal/src/app')
16 files changed, 2001 insertions, 1083 deletions
diff --git a/usecaseui-portal/src/app/app.module.ts b/usecaseui-portal/src/app/app.module.ts index 8582a6fc..7f77bd81 100644 --- a/usecaseui-portal/src/app/app.module.ts +++ b/usecaseui-portal/src/app/app.module.ts @@ -37,6 +37,7 @@ import { CcvpnCreationComponent } from './ccvpn-creation/ccvpn-creation.componen import { DetailsComponent } from './components/details/details.component'; import { GraphiclistComponent } from './components/graphiclist/graphiclist.component'; +import { E2eCreationComponent } from './components/e2e-creation/e2e-creation.component'; import { BarComponent } from './components/charts/bar/bar.component'; import { LineComponent } from './components/charts/line/line.component'; @@ -73,6 +74,7 @@ import { PerformanceDetailsComponent } from './components/performance-details/pe LineComponent, BarComponent, GraphiclistComponent, + E2eCreationComponent, CcvpnNetworkComponent, CcvpnDetailComponent, diff --git a/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.css b/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.css index 710bd104..02c3d4c6 100644 --- a/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.css +++ b/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.css @@ -135,4 +135,22 @@ hr { background-color: #aaa; border-radius: 5px; box-shadow: 0px 0px 20px #000; +} +#togo{ + width: 600px; + height:400px; + border:1px solid #ccc; + user-select: none; +} +#togo text{ + font-size:10px; + fill:#1A2C3F; + text-anchor: middle; +} + +#togo .link{ + stroke:#FFC000; +} +#togo .node-title{ + font-size: 14px; }
\ No newline at end of file diff --git a/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.html b/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.html index 33d56eb9..cd3e2067 100644 --- a/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.html +++ b/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.html @@ -16,321 +16,178 @@ <h3 class="title"> Services List </h3> <hr> <div class="model"> - <!-- 详情数据 --> + <button class="back" nz-button (click)="goback()"><span><i class="anticon anticon-rollback"></i></span></button> <div class="detaildata fl"> - <h3 class="title">{{detailParams.sotnvpnSer['service-instance-name']}} Instance Detail</h3> - <div class="sotnvpn clearfix"> - <h3>SOTN VPN Info</h3> + <h3 class="title">{{detailParams['service-instance-name']}} Instance Detail</h3> + <div class="sotnvpn clearfix"> + <h3>SOTN VPN Info</h3> + <ul> + <li><span>Name:</span> {{sotnVpnInfo.name}}</li> + <li><span>Description:</span> {{sotnVpnInfo.description}} </li> + <li><span>Start Time:</span> {{sotnVpnInfo.startTime}}</li> + <li><span>End Time:</span> {{sotnVpnInfo.endTime}} </li> + <li><span>COS:</span> {{sotnVpnInfo.COS}}</li> + <li><span>Reroute Enable:</span> {{sotnVpnInfo.reroute}} </li> + <li><span>Service Level Specification:</span> {{sotnVpnInfo.SLS}}</li> + <li><span>DualLink:</span> {{sotnVpnInfo.dualLink}} </li> + <li><span>CIR:</span> {{sotnVpnInfo.CIR}}</li> + <li><span>EIR:</span> {{sotnVpnInfo.EIR}} </li> + <li><span>CBS:</span> {{sotnVpnInfo.CBS}}</li> + <li><span>EBS:</span> {{sotnVpnInfo.EBS}} </li> + <li><span>Color Aware:</span> {{sotnVpnInfo.colorAware}}</li> + <li><span>Coupling Flag:</span> {{sotnVpnInfo.couplingFlag}} </li> + </ul> + </div> + + <div class="site"> + <h3>Site List</h3> + <nz-table #nzTable [nzData]="siteList" + [nzShowPagination]="false" + nzSize="small"> + <thead> + <tr> + <th nzWidth="10%"> NO. </th> + <th nzWidth="15%"> Name </th> + <th nzWidth="20%"> Description </th> + <th nzWidth="15%"> Post Code </th> + <th nzWidth="15%"> Address </th> + <th nzWidth="15%"> VLAN </th> + <th nzWidth="10%"> Action </th> + </tr> + </thead> + <tbody> + + <tr *ngFor="let item of nzTable.data; let i = index; "> + <td>{{i+1}}</td> + <td>{{item.baseNames.name}}</td> + <td>{{item.baseNames.description}}</td> + <td>{{item.baseNames.postcode}}</td> + <td>{{item.baseNames.address}}</td> + <td>{{item.baseNames.vlan}}</td> + <td (click)="showSiteDetail(item)"> <a href="javascript:;">Detail</a> </td> + </tr> + + </tbody> + </nz-table> + <div class="siteDetail" *ngIf="siteDetail"> + <h3>Site_Enterprise Service <span class="closeDetail fr" (click)="siteDetail=false">X</span></h3> <ul> - <li><span>Name:</span> {{sotnVpnInfo.name}}</li> - <li><span>Description:</span> {{sotnVpnInfo.description}} </li> - <li><span>Start Time:</span> {{sotnVpnInfo.startTime}}</li> - <li><span>End Time:</span> {{sotnVpnInfo.endTime}} </li> - <li><span>COS:</span> {{sotnVpnInfo.COS}}</li> - <li><span>Reroute Enable:</span> {{sotnVpnInfo.reroute}} </li> - <li><span>Service Level Specification:</span> {{sotnVpnInfo.SLS}}</li> - <li><span>DualLink:</span> {{sotnVpnInfo.dualLink}} </li> - <li><span>CIR:</span> {{sotnVpnInfo.CIR}}</li> - <li><span>EIR:</span> {{sotnVpnInfo.EIR}} </li> - <li><span>CBS:</span> {{sotnVpnInfo.CBS}}</li> - <li><span>EBS:</span> {{sotnVpnInfo.EBS}} </li> - <li><span>Color Aware:</span> {{sotnVpnInfo.colorAware}}</li> - <li><span>Coupling Flag:</span> {{sotnVpnInfo.couplingFlag}} </li> + <li><span>Name:</span> {{ siteDetailData.baseNames.name}}</li> + <li><span>Description:</span> {{ siteDetailData.baseNames.description }} </li> + <li *ngIf="detailParams.serviceDomain == 'CCVPN'"><span>Type:</span> {{ siteDetailData.baseNames.type }} </li> + <li *ngIf="detailParams.serviceDomain == 'CCVPN'"><span>Role:</span> {{ siteDetailData.baseNames.role }} </li> + <li><span>PostCode:</span> {{ siteDetailData.baseNames.postcode }} </li> + <li><span>VLAN:</span> {{ siteDetailData.baseNames.vlan }}</li> + <li><span>Address:</span> {{ siteDetailData.baseNames.address }}</li> + <li><span>ClientSignal:</span> {{ siteDetailData.baseNames.clientSignal }}</li> + <li><span>ControlPoint:</span> {{ siteDetailData.baseNames.controlPoint }}</li> + <li><span>Emails:</span> {{ siteDetailData.baseNames.emails }}</li> + <li><span>GroupName:</span> {{ siteDetailData.baseNames.groupName }}</li> + <li><span>GroupRole:</span> {{ siteDetailData.baseNames.groupRole }}</li> + <li><span>Latitude:</span> {{ siteDetailData.baseNames.latitude }}</li> + <li><span>Longitude:</span> {{ siteDetailData.baseNames.longitude }}</li> + <li><span>SotnVpnName:</span> {{ siteDetailData.baseNames.sotnVpnName }}</li> </ul> - </div> - - <div class="site"> - <h3>Site List</h3> - <nz-table #nzTable [nzData]="siteList" - [nzShowPagination]="false" - nzSize="small"> - <thead> + <div *ngIf="detailParams.serviceDomain == 'CCVPN'"> + <h3>CPE</h3> + <ul> + <li><span>Name:</span> {{siteDetailData.cpeNames.device_name}}</li> + <li><span>Version:</span> {{ siteDetailData.cpeNames.device_version }} </li> + <li><span>ESN:</span> {{ siteDetailData.cpeNames.device_esn }} </li> + <li><span>Class:</span> {{ siteDetailData.cpeNames.device_class }} </li> + <li><span>System IP:</span> {{ siteDetailData.cpeNames.device_systemIp }} </li> + <li><span>Vendor:</span> {{ siteDetailData.cpeNames.device_vendor }}</li> + <li><span>Type:</span> {{ siteDetailData.cpeNames.device_type }}</li> + </ul> + <h3>WAN Port</h3> + <nz-table #nzTable [nzData]="siteDetailData.wanportNames" + [nzShowPagination]="false" + nzSize="small"> + <thead> <tr> <th nzWidth="10%"> NO. </th> <th nzWidth="15%"> Name </th> <th nzWidth="20%"> Description </th> - <th nzWidth="15%"> Post Code </th> - <th nzWidth="15%"> Address </th> - <th nzWidth="15%"> VLAN </th> + <th nzWidth="15%"> PortType </th> + <th nzWidth="15%"> PortNumber </th> + <th nzWidth="15%"> IPAddress </th> <th nzWidth="10%"> 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.baseNames.name}}</td> - <td>{{item.baseNames.description}}</td> - <td>{{item.baseNames.postcode}}</td> - <td>{{item.baseNames.address}}</td> - <td>{{item.baseNames.vlan}}</td> - <td (click)="showSiteDetail(item)"> <a href="javascript:;">Detail</a> </td> - </tr> - <!-- </ng-template> --> - </tbody> - </nz-table> - <div class="siteDetail" *ngIf="siteDetail"> - <h3>Site_Enterprise Service <span class="closeDetail fr" (click)="siteDetail=false">X</span></h3> - <ul> - <li><span>Name:</span> {{ siteDetailData.baseNames.name}}</li> - <li><span>Description:</span> {{ siteDetailData.baseNames.description }} </li> - <li *ngIf="detailParams.sotnvpnSer.Type == 'CCVPN'"><span>Type:</span> {{ siteDetailData.baseNames.type }} </li> - <li *ngIf="detailParams.sotnvpnSer.Type == 'CCVPN'"><span>Role:</span> {{ siteDetailData.baseNames.role }} </li> - <li><span>PostCode:</span> {{ siteDetailData.baseNames.postcode }} </li> - <li><span>VLAN:</span> {{ siteDetailData.baseNames.vlan }}</li> - <li><span>Address:</span> {{ siteDetailData.baseNames.address }}</li> - <li><span>ClientSignal:</span> {{ siteDetailData.baseNames.clientSignal }}</li> - <li><span>ControlPoint:</span> {{ siteDetailData.baseNames.controlPoint }}</li> - <li><span>Emails:</span> {{ siteDetailData.baseNames.emails }}</li> - <li><span>GroupName:</span> {{ siteDetailData.baseNames.groupName }}</li> - <li><span>GroupRole:</span> {{ siteDetailData.baseNames.groupRole }}</li> - <li><span>Latitude:</span> {{ siteDetailData.baseNames.latitude }}</li> - <li><span>Longitude:</span> {{ siteDetailData.baseNames.longitude }}</li> - <li><span>SotnVpnName:</span> {{ siteDetailData.baseNames.sotnVpnName }}</li> - </ul> - <div *ngIf="detailParams.sotnvpnSer.Type == 'CCVPN'"> - <h3>CPE</h3> - <ul> - <li><span>Name:</span> {{siteDetailData.cpeNames.device_name}}</li> - <li><span>Version:</span> {{ siteDetailData.cpeNames.device_version }} </li> - <li><span>ESN:</span> {{ siteDetailData.cpeNames.device_esn }} </li> - <li><span>Class:</span> {{ siteDetailData.cpeNames.device_class }} </li> - <li><span>System IP:</span> {{ siteDetailData.cpeNames.device_systemIp }} </li> - <li><span>Vendor:</span> {{ siteDetailData.cpeNames.device_vendor }}</li> - <li><span>Type:</span> {{ siteDetailData.cpeNames.device_type }}</li> - </ul> - <h3>WAN Port</h3> - <nz-table #nzTable [nzData]="siteDetailData.wanportNames" - [nzShowPagination]="false" - nzSize="small"> - <thead> - <tr> - <th nzWidth="10%"> NO. </th> - <th nzWidth="15%"> Name </th> - <th nzWidth="20%"> Description </th> - <th nzWidth="15%"> PortType </th> - <th nzWidth="15%"> PortNumber </th> - <th nzWidth="15%"> IPAddress </th> - <th nzWidth="10%"> 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.sitewanport_name}}</td> - <td>{{item.sitewanport_description}}</td> - <td>{{item.sitewanport_portType}}</td> - <td>{{item.sitewanport_portNumber}}</td> - <td>{{item.sitewanport_ipAddress}}</td> - <td (click)="showWanportDetail(item)"> <a href="javascript:;">Detail</a> </td> - </tr> - <!-- </ng-template> --> - </tbody> - </nz-table> - <nz-modal [(nzVisible)]="wanPortModal" [nzTitle]="modalTitle" [nzContent]="modalContent" [nzFooter]="modalFooter" (nzOnCancel)="handleCancel()"> - <ng-template #modalTitle> - WAN Port Detail - </ng-template> + </thead> + <tbody> + + <tr *ngFor="let item of nzTable.data; let i = index; "> + <td>{{i+1}}</td> + <td>{{item.sitewanport_name}}</td> + <td>{{item.sitewanport_description}}</td> + <td>{{item.sitewanport_portType}}</td> + <td>{{item.sitewanport_portNumber}}</td> + <td>{{item.sitewanport_ipAddress}}</td> + <td (click)="showWanportDetail(item)"> <a href="javascript:;">Detail</a> </td> + </tr> + + </tbody> + </nz-table> + <nz-modal [(nzVisible)]="wanPortModal" [nzTitle]="modalTitle" [nzContent]="modalContent" [nzFooter]="modalFooter" (nzOnCancel)="handleCancel()"> + <ng-template #modalTitle> + WAN Port Detail + </ng-template> - <ng-template #modalContent> - <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Name </span> {{wanPortDetail.sitewanport_name}}</p> - <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Description: </span> {{wanPortDetail.sitewanport_description}} </p> - <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Port Type: </span> {{wanPortDetail.sitewanport_portType}} </p> - <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Port Number: </span> {{wanPortDetail.sitewanport_portNumber}} </p> - <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Ip Address: </span> {{wanPortDetail.sitewanport_ipAddress}} </p> - <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Provider IP Address: </span> {{wanPortDetail.sitewanport_providerIpAddress}} </p> - <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Transport Nerwork: </span> {{wanPortDetail.sitewanport_transportNetworkName}} </p> - <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Input Bandwidth: </span> {{wanPortDetail.sitewanport_inputBandwidth}} </p> - <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Output Bandwidth: </span> {{wanPortDetail.sitewanport_outputBandwidth}} </p> - </ng-template> + <ng-template #modalContent> + <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Name </span> {{wanPortDetail.sitewanport_name}}</p> + <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Description: </span> {{wanPortDetail.sitewanport_description}} </p> + <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Port Type: </span> {{wanPortDetail.sitewanport_portType}} </p> + <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Port Number: </span> {{wanPortDetail.sitewanport_portNumber}} </p> + <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Ip Address: </span> {{wanPortDetail.sitewanport_ipAddress}} </p> + <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Provider IP Address: </span> {{wanPortDetail.sitewanport_providerIpAddress}} </p> + <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Transport Nerwork: </span> {{wanPortDetail.sitewanport_transportNetworkName}} </p> + <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Input Bandwidth: </span> {{wanPortDetail.sitewanport_inputBandwidth}} </p> + <p> <span style="color:#3fa8eb;font:700 14px 'Arial';display:inline-block;width:200px;"> Output Bandwidth: </span> {{wanPortDetail.sitewanport_outputBandwidth}} </p> + </ng-template> - <ng-template #modalFooter> - <!-- <button nz-button nzType="primary" (click)="handleOk()" [nzLoading]="isConfirmLoading">Custom Submit</button> --> - </ng-template> - </nz-modal> - </div> + <ng-template #modalFooter> + </ng-template> + </nz-modal> </div> - </div> - <div class="sitegroup" *ngIf="detailParams.sotnvpnSer.Type == 'CCVPN'"> - <h3>Site_Group List</h3> - <nz-table #nzTable [nzData]="siteGroupList" - [nzLoading]="loading" - [nzShowPagination]="false" - nzSize="small"> - <thead> - <tr> - <th nzWidth="10%"> NO. </th> - <th nzWidth="20%"> Group Name </th> - <th nzWidth="20%"> Topology </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.topology}}</td> - </tr> - <!-- </ng-template> --> - </tbody> - </nz-table> </div> + </div> + + <div class="sitegroup" *ngIf="detailParams.serviceDomain == 'CCVPN'"> + <h3>Site_Group List</h3> + <nz-table #nzTable [nzData]="siteGroupList" + [nzLoading]="loading" + [nzShowPagination]="false" + nzSize="small"> + <thead> + <tr> + <th nzWidth="10%"> NO. </th> + <th nzWidth="20%"> Group Name </th> + <th nzWidth="20%"> Topology </th> + </tr> + </thead> + <tbody> + + <tr *ngFor="let item of nzTable.data; let i = index; "> + <td>{{i+1}}</td> + <td>{{item.name}}</td> + <td>{{item.topology}}</td> + </tr> + + </tbody> + </nz-table> + </div> </div> - <!-- 图 --> + <div class="chart fr"> - <div id="detailChart"> - <!-- <svg width="100%" height="100%"> - <line *ngFor="let item of lines" [attr.x1]="item.x1" [attr.y1]="item.y1" [attr.x2]="item.x2" [attr.y2]="item.y2" style="stroke:#3fa8eb;stroke-width:2"/> - <image xlink:href="./assets/images/cloud-county.png" - class="cloudcounty" - (click)="toggleClick()" - (mouseover)="hoverShowcould()" - (mouseout)="hoverHidecould()" - x="175" y="175" height="50px" width="50px"/> - <image *ngFor="let item of siteImage" - xlink:href="./assets/images/cloud-city.png" - [attr.x]="item.x" [attr.y]="item.y" height="50px" width="50px"/> - </svg> - <div class="couldDetail" *ngIf="hoverShow || clickShow"> + <div id="detailChart"> + <svg id="togo"> - </div> --> - <svg width="100%" height="100%" style="position: relative"> - <!--背景大图--> - <image xlink:href="./assets/images/bigcloud.png" - class="backgroundcloud" - width="100%" - style="position: absolute;z-index:-1"> - </image> - <!--tp,site,domain之间的连线--> - <line *ngFor="let item of detailLines" [attr.x1]="item.x1" [attr.y1]="item.y1" [attr.x2]="item.x2" [attr.y2]="item.y2" style="stroke:#FFC000; stroke-width:2"></line> - <line *ngIf="detailSites" x1="45%" y1="30%" x2="75%" y2="20%" style="stroke:#FFC000; stroke-width:2"></line> - <!--本地domain--> - <g class="clouds"> - <image xlink:href="./assets/images/domain.png" - id="domain1" - width="20%" - x="10%" y="10%" - ></image> - <text dx="12%" dy="16%" style="font-size: 14px; fill:#666;width: 20px;"> - {{vpns[0].domain}} - </text> - </g> - <g *ngIf="vpns[1]" class="clouds"> - <image xlink:href="./assets/images/domain.png" - id="domain2" - width="20%" - x="40%" y="13%" - ></image> - <text dx="43%" dy="19%" style="font-size: 14px; fill: #666;width: 20px;"> - {{vpns[1].domain}} - </text> - </g> - <!--domain1下连接的tp--> - <g class="clouds"> - <image xlink:href="./assets/images/tp.png" - class="tp" - id="tp1" - height="16" width="20" - x="15%" y="25%" - ></image> - <text dx="18%" dy="27%" style="font-size: 14px; fill: #666;width: 20px;"> - {{vpns[0].sitetpname}} - </text> - </g> - <g class="clouds"> - <image xlink:href="./assets/images/tp.png" - class="tp" - id="tp2" - height="16" width="20" - x="30%" y="10%" - ></image> - <text dx="30%" dy="6%" style="font-size: 14px; fill: #666;width: 20px;"> - {{vpns[0].othertpname}} - </text> - </g> - <!--domain2下连接的tp--> - <g *ngIf="vpns[1]" class="clouds"> - <image xlink:href="./assets/images/tp.png" - class="tp" - id="tp3" - height="16" width="20" - x="40%" y="10%" - ></image> - <text dx="40%" dy="9%" style="font-size: 14px; fill: #666;width: 20px;"> - {{vpns[1].othertpname}} - </text> - </g> - <g *ngIf="vpns[1]" class="clouds"> - <image xlink:href="./assets/images/tp.png" - class="tp" - id="tp4" - height="16" width="20" - x="43%" y="28%" - ></image> - <text dx="46%" dy="30%" style="font-size: 14px; fill: #666;width: 20px;"> - {{vpns[1].sitetpname}} - </text> - </g> - <!--外部云--> - <g class="clouds"> - <image xlink:href="./assets/images/out-domain.png" - id="extent-cloud" - height="70.8" width="120" - x="66%" y="12%" - ></image> - <text dx="68%" dy="18%" style="font-size: 14px; fill: #666;width: 20px;"> - SP Partent Network - </text> - </g> - <!--本地的2个site--> - <g class="clouds"> - <image xlink:href="./assets/images/site.png" - id="site1" - height="59" width="100" - x="0%" y="48%" - ></image> - <text dx="2%" dy="53%" style="font-size: 14px; fill: #666;width: 20px;"> - {{localSite[0]["service-instance-name"]}} - </text> - </g> - <g *ngIf="!detailSites" class="clouds"> - <image xlink:href="./assets/images/site.png" - id="site2" - height="59" width="100" - x="25%" y="48%" - ></image> - <text dx="26%" dy="54%" style="font-size: 14px; fill: #666;width: 20px;"> - {{localSite[1]["service-instance-name"]}} - </text> - </g> - <!--外部的2个site--> - <g *ngIf="!detailSites" class="clouds"> - <image xlink:href="./assets/images/site.png" - id="site3" - height="59" width="100" - x="50%" y="48%" - ></image> - <text dx="52%" dy="54%" style="font-size: 14px; fill: #666;width: 20px;"> - {{outerSite[1]["service-instance-name"]}} - </text> - </g> - <g class="clouds"> - <image xlink:href="./assets/images/site.png" - id="site4" - height="59" width="100" - x="75%" y="48%" - ></image> - <text dx="80%" dy="54%" style="font-size: 14px; fill: #666;width: 20px;"> - {{outerSite[0]["service-instance-name"]}} - </text> - </g> - </svg> - </div> + </svg> + </div> </div> </div> diff --git a/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.spec.ts b/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.spec.ts index dc5d34d9..b8afc9c3 100644 --- a/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.spec.ts +++ b/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.spec.ts @@ -1,3 +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. +*/ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { CcvpnDetailComponent } from './ccvpn-detail.component'; diff --git a/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.ts b/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.ts index c9d60ef8..6f30253d 100644 --- a/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.ts +++ b/usecaseui-portal/src/app/ccvpn-detail/ccvpn-detail.component.ts @@ -3,366 +3,830 @@ import { MyhttpService } from '../myhttp.service'; import * as d3 from 'd3'; @Component({ - selector: 'app-ccvpn-detail', - templateUrl: './ccvpn-detail.component.html', - styleUrls: ['./ccvpn-detail.component.css'] + selector: 'app-ccvpn-detail', + templateUrl: './ccvpn-detail.component.html', + styleUrls: ['./ccvpn-detail.component.css'] }) export class CcvpnDetailComponent implements OnInit { - constructor(private myhttp:MyhttpService) { } - - ngOnInit() { - // this.getDetails(); - this.dataInit(); - this.drawImages(); - } - - @Input() detailParams; - @Input() namesTranslate; - @Output() closeDetail = new EventEmitter(); - - sotnVpnInfo:any; - siteList=[]; - siteGroupList=[]; - dataInit(){ - // 循环真实参数,对比名字转换配置文件,将真实参数名字改成通用名字 - this.sotnVpnInfo = JSON.parse(this.detailParams.sotnvpnSer['input-parameters']).service.parameters.requestInputs; - for(let key in this.sotnVpnInfo){ - for(let key2 in this.namesTranslate.sotnNameTranslate){ - let partnames = this.namesTranslate.sotnNameTranslate[key2].split("_"); - if(key.startsWith(partnames[0])&&key.endsWith(partnames[1])){ - this.sotnVpnInfo[key2] = this.sotnVpnInfo[key]; - break; - } - } + constructor(private myhttp:MyhttpService) { } + + ngOnInit() { + // this.getDetails(); + this.dataInit(); + this.drawImages(); } - this.siteList = this.detailParams.siteSer.map((item)=>{ - return JSON.parse(item['input-parameters']).service.parameters.requestInputs; - }) - this.siteList.forEach((oneSite,idex)=>{ - oneSite["baseNames"]={};oneSite["cpeNames"]={};oneSite["wanportNames"]=[]; - for(let key in oneSite){ - let hasfind = false; - if(key == "baseNames" || key == "cpeNames" || key == "wanportNames"){ continue }; - for(let key2 in this.namesTranslate.siteNameTranslate.baseNames){ - if(key.endsWith(this.namesTranslate.siteNameTranslate.baseNames[key2])){ - oneSite["baseNames"][key2] = oneSite[key]; - hasfind = true; - break; - } - } - if(hasfind){ continue }; - for(let key3 in this.namesTranslate.siteNameTranslate.cpeNames){ - if(key.endsWith(this.namesTranslate.siteNameTranslate.cpeNames[key3])){ - oneSite["cpeNames"][key3] = oneSite[key]; - hasfind = true; - break; - } + @Input() detailParams; + @Input() namesTranslate; + @Output() closeDetail = new EventEmitter(); + + sotnVpnInfo:any; + siteList=[]; + siteGroupList=[]; + dataInit(){ + console.log(this.detailParams); + + this.sotnVpnInfo = JSON.parse(this.detailParams['input-parameters']).service.parameters.requestInputs; + for(let key in this.sotnVpnInfo){ + for(let key2 in this.namesTranslate.sotnNameTranslate){ + let partnames = this.namesTranslate.sotnNameTranslate[key2].split("_"); + if(key.startsWith(partnames[0])&&key.endsWith(partnames[1])){ + this.sotnVpnInfo[key2] = this.sotnVpnInfo[key]; + break; + } + } } - if(hasfind){ continue }; - let wanportStartName = key.split("_")[0]; - // 先分组,后面再变换名字 - let theItem = oneSite["wanportNames"].find((item,index)=>{ - if(item){ - return Object.keys(item)[0].startsWith(wanportStartName) - } + + this.siteList = this.detailParams.siteSer.map((item)=>{ + return JSON.parse(item['input-parameters']).service.parameters.requestInputs; }) - theItem?theItem[key]=oneSite[key]:oneSite["wanportNames"].push({[key]:oneSite[key]}) - } - let wanportTs = Object.values(this.namesTranslate.siteNameTranslate.wanportNames); - oneSite["wanportNames"].forEach((item)=>{ - for(let key in item){ - let newName = wanportTs.find((name)=>{ - return key.endsWith(name); - }) - newName?item[newName]=item[key]:null; - } - }) - - }) - - this.siteGroupList = this.detailParams.sdwanSer.map((item)=>{ - return JSON.parse(item['input-parameters']).service.parameters.requestInputs; - }) - this.siteGroupList.forEach((oneSiteGroup)=>{ - for(let key in oneSiteGroup){ - for(let key2 in this.namesTranslate.siteGroupNameTranslate){ - let partnames = this.namesTranslate.siteGroupNameTranslate[key2].split("_"); - if(key.startsWith(partnames[0])&&key.endsWith(partnames[1])){ - oneSiteGroup[key2] = oneSiteGroup[key]; - break; - } - } - } - }) - console.log(this.siteList) - this.drawImage(this.siteList); - } - - // site详情 - siteDetailData={baseNames:{},cpeNames:{},wanportNames:[]}; - siteDetail = false; - showSiteDetail(item){ - this.siteDetail = true; - this.siteDetailData = item; - } - - wanPortModal = false; - wanPortDetail = {}; - showWanportDetail(item){ - this.wanPortModal = true; - this.wanPortDetail = item; - } - handleCancel(){ - this.wanPortModal = false; - } - - // sitegroup详情 - - // site节点图形描绘 - // site分类,根据site查tp pnf --> allotted-resource - localSite = [];//本地site - outerSite = [];//外部site - - getSiteAResource(){ - return new Promise((res,rej)=>{ - this.detailParams.siteSer.forEach((site)=>{ - site["relationship-list"]["relationship"].find((item)=>{return item["related-to"]=="site-resource"})?this.localSite.push(site):this.outerSite.push(site); - }) - - if(this.localSite[0]["service-instance-name"].startsWith("Dc")){ - this.localSite.reverse(); - } - - if(this.outerSite[0]["service-instance-name"].startsWith("Dc")){ - this.outerSite.reverse(); - } - - // 本地site获取tp pnf - this.localSite.forEach((site)=>{ - let obj = { - customerId: this.detailParams.customer.id, - serviceType: this.detailParams.serviceType, - serviceId: site["service-instance-id"] - } - this.myhttp.getAllottedResource(obj) - .subscribe((data)=>{ - // console.log(data); - let resource = data["allotted-resource"].find((item)=>{ return item["allotted-resource-name"]=="sotn ar"}); - // console.log(resource); - let tps_pnfs = resource["relationship-list"]["relationship"].find((item)=>{ return item["related-to"]=="p-interface"})["relationship-data"]; - // console.log(tps_pnfs); - // site.pnfname = tps_pnfs.find((item)=>{return item["relationship-key"]=="pnf.pnf-name"})["relationship-value"]; - site.tpsitename = tps_pnfs.find((item)=>{return item["relationship-key"]=="p-interface.interface-name"})["relationship-value"]; - // // 通过pnfname获取domain(network-resource); - // this.myhttp.getPnfDetail(site.pnfname) - // .subscribe((data2)=>{ - // // console.log(data2); - // let networkRelation = data2["relationship-list"]["relationship"].find((item)=>{ return item["related-to"]=="network-resource"})["relationship-data"]; - // site.domain = networkRelation.find((item)=>{return item["relationship-key"]=="network-resource.network-id"})["relationship-value"]; - // res("sites-domain"); - // }) - res("sites-domain"); - }) - }) - }) - } - //通过sotn 查vpn-id --> tp pnf --> allotted-resource - relation = {sotn:{ - name:"sotn1", - vpns:[ - { - name:"vpn1", - domain:"domain1", - site:"site1", - tps:[ - {name:"tp1",lineto:"site1"}, - {name:"tp2",lineto:"domain1"} - ] - }, - { - name:"vpn2", - domain:"domain2", - site:"site2", - tps:[ - {name:"tp3",lineto:"site2"}, - {name:"tp4",lineto:"domain2"} - ] - } - ] - }}; - - vpns = [{name: "", tps: [], domain: "", sitetpname: "", othertpname: ""}]; - getSotnAresource(){ - return new Promise((res,rej)=>{ - let connectivityId = this.detailParams.sotnvpnSer["relationship-list"]["relationship"] - .find((item)=>{return item["related-to"]=="connectivity"})["relationship-data"] - .find((item2)=>{return item2["relationship-key"]=="connectivity.connectivity-id"})["relationship-value"]; - this.myhttp.getSotnConnectivity(connectivityId) - .subscribe((data)=>{ - // console.log(data); //默认一个connectivityId只能查到一个connectivity - let vpns = data.connectivity[0]["relationship-list"]["relationship"] - .filter((item)=>{ return item["related-to"]=="vpn-binding"}) - .map((item2)=>{return item2["relationship-data"].find((item3)=>{return item3["relationship-key"]=="vpn-binding.vpn-id"})["relationship-value"]}); - console.log(vpns); - this.detailParams.sotnvpnSer.vpns = vpns.map((item)=>{return {name:item}}); - this.detailParams.sotnvpnSer.vpns.forEach((vpn,index)=>{ - this.myhttp.getVpnBinding(vpn.name) - .subscribe((data2)=>{ - // console.log(data2); //默认一个vpnid只能查到一个vpnbinding - let tps_pnfs = data2["vpn-binding"][0]["relationship-list"]["relationship"] - .filter((item)=>{ return item["related-to"]=="p-interface"}) - .map((item2)=>{return item2["relationship-data"]}); - let pnfname = tps_pnfs.map((item)=>{return item.find((item2)=>{return item2["relationship-key"]=="pnf.pnf-name"})["relationship-value"]}); - let tpnames = tps_pnfs.map((item)=>{return item.find((item2)=>{return item2["relationship-key"]=="p-interface.interface-name"})["relationship-value"]}); - // console.log(pnfname) - // console.log(tpnames) - vpn.tps = tpnames; - // let thissite = this.localSite.find((item)=>{return item.pnfname == pnfname[0]}); //查找site上pnfname相同的项,即同domain - // console.log(thissite); - // thissite.tpsotnname = tpsotnnames.find((item)=>{return item!=thissite.tpsitename}); - // 通过pnfname获取domain(network-resource); - this.myhttp.getPnfDetail(pnfname[0]) - .subscribe((data2)=>{ - // console.log(data2); - let networkRelation = data2["relationship-list"]["relationship"].find((item)=>{ return item["related-to"]=="network-resource"})["relationship-data"]; - vpn.domain = networkRelation.find((item)=>{return item["relationship-key"]=="network-resource.network-id"})["relationship-value"]; - if(this.localSite[index]){ - vpn.sitetpname = this.localSite.find((site)=>{return tpnames.includes(site.tpsitename)}).tpsitename; - console.log(tpnames) - console.log(vpn.sitetpname) - vpn.othertpname = tpnames.find((name)=>{return name != vpn.sitetpname}); - }else{ - vpn.sitetpname = this.localSite[0].tpsitename; - vpn.othertpname = tpnames.find((name)=>{return name != vpn.sitetpname}); + this.siteList.forEach((oneSite,idex)=>{ + oneSite["baseNames"]={};oneSite["cpeNames"]={};oneSite["wanportNames"]=[]; + for(let key in oneSite){ + let hasfind = false; + if(key == "baseNames" || key == "cpeNames" || key == "wanportNames"){ continue }; + for(let key2 in this.namesTranslate.siteNameTranslate.baseNames){ + if(key.endsWith(this.namesTranslate.siteNameTranslate.baseNames[key2])){ + oneSite["baseNames"][key2] = oneSite[key]; + hasfind = true; + break; + } + } + if(hasfind){ continue }; + for(let key3 in this.namesTranslate.siteNameTranslate.cpeNames){ + if(key.endsWith(this.namesTranslate.siteNameTranslate.cpeNames[key3])){ + oneSite["cpeNames"][key3] = oneSite[key]; + hasfind = true; + break; + } + } + if(hasfind){ continue }; + let wanportStartName = key.split("_")[0]; + + let theItem = oneSite["wanportNames"].find((item,index)=>{ + if(item){ + return Object.keys(item)[0].startsWith(wanportStartName) } + }) + theItem?theItem[key]=oneSite[key]:oneSite["wanportNames"].push({[key]:oneSite[key]}) + } + let wanportTs = Object.values(this.namesTranslate.siteNameTranslate.wanportNames); + oneSite["wanportNames"].forEach((item)=>{ + for(let key in item){ + let newName = wanportTs.find((name)=>{ + return key.endsWith(name); + }) + newName?item[newName]=item[key]:null; + } + }) + + }) - this.vpns = this.detailParams.sotnvpnSer.vpns; - res("sotn-domain"); - // console.log(vpn); - }) - - }) - }) + this.siteGroupList = this.detailParams.sdwanSer.map((item)=>{ + return JSON.parse(item['input-parameters']).service.parameters.requestInputs; }) - }) - } - - drawImages(){ - - this.getSiteAResource().then((data)=>{ - console.log(data); - return this.getSotnAresource() - }).then((data)=>{ - console.log(data); - console.log(this.localSite); - this.detailSites = this.detailParams.sotnvpnSer.Type == "CCVPN"?false:true; - this.detailParams.sotnvpnSer.Type == "CCVPN"?null:this.detailLines.length = this.detailLines.length-3; - // 当只有一个vpn的时候 - if(this.detailParams.sotnvpnSer.Type == "CCVPN" && this.vpns.length == 1){ - let line = { - "x1":"32%","y1":"12%","x2":"32%","y2":"50%"//t2--site2 当本地云只有一朵的时候,tp2与本地site2相连 - } - this.detailLines.length = this.detailLines.length-6; - this.detailLines.push(line); - // 当本地site有两个的时候 - if(this.localSite.length==2){ - let line = { - "x1":"40%","y1":"52%","x2":"52%","y2":"52%"//site2--site3 - } - this.detailLines.push(line); + this.siteGroupList.forEach((oneSiteGroup)=>{ + for(let key in oneSiteGroup){ + for(let key2 in this.namesTranslate.siteGroupNameTranslate){ + let partnames = this.namesTranslate.siteGroupNameTranslate[key2].split("_"); + if(key.startsWith(partnames[0])&&key.endsWith(partnames[1])){ + oneSiteGroup[key2] = oneSiteGroup[key]; + break; + } + } + } + }) + } + + + siteDetailData={baseNames:{},cpeNames:{},wanportNames:[]}; + siteDetail = false; + showSiteDetail(item){ + this.siteDetail = true; + this.siteDetailData = item; + } + + wanPortModal = false; + wanPortDetail = {}; + showWanportDetail(item){ + this.wanPortModal = true; + this.wanPortDetail = item; + } + handleCancel(){ + this.wanPortModal = false; + } + + + + + + localSite = []; + outerSite = []; + + getSiteAResource(){ + return new Promise((res,rej)=>{ + this.detailParams.siteSer.forEach((site)=>{ + site["relationship-list"]["relationship"].find((item)=>{return item["related-to"]=="site-resource"})?this.localSite.push(site):this.outerSite.push(site); + }); + + if(this.localSite[0] && this.localSite[0]["service-instance-name"].startsWith("Dc")){ + this.localSite.reverse(); + } + + if(this.outerSite[0] && this.outerSite[0]["service-instance-name"].startsWith("Dc")){ + this.outerSite.reverse(); + } + console.log(this.localSite); + console.log(this.outerSite); + + this.localSite.forEach((site)=>{ + let obj = { + customerId: this.detailParams.customer.id, + serviceType: this.detailParams.serviceType, + serviceId: site["service-instance-id"] + }; + this.myhttp.getAllottedResource(obj) + .subscribe((data)=>{ + let resource = data["allotted-resource"].find((item)=>{ return item["allotted-resource-name"]=="sotn ar"}); + let tps_pnfs = resource["relationship-list"]["relationship"].find((item)=>{ return item["related-to"]=="p-interface"})["relationship-data"]; + site.tpsitename = tps_pnfs.find((item)=>{return item["relationship-key"]=="p-interface.interface-name"})["relationship-value"]; + res("sites-domain"); + }) + }) + }) + } + + + vpns = [{ + name:"", + domain: "", + tp1: "", + tp2: "", + tps:[], + site: [], + type: "domain", + start:false, + end:false + }]; + cloudDomain={ + cloud: "Partent Network", + site: [], + type: "cloud" + }; + d3Data={ + dates:[], + linkss:[] + }; + svg=d3.select("#togo"); + scale=1; + width=600; + height=600; + container; + nodes; + lineGroup; + + getSotnAresource(){ + return new Promise((res,rej)=>{ + let connectivityId = this.detailParams["relationship-list"]["relationship"] + .find((item)=>{return item["related-to"]=="connectivity"})["relationship-data"] + .find((item2)=>{return item2["relationship-key"]=="connectivity.connectivity-id"})["relationship-value"]; + this.myhttp.getSotnConnectivity(connectivityId) + .subscribe((data)=>{ + + let vpns = data.connectivity[0]["relationship-list"]["relationship"] + .filter((item)=>{ return item["related-to"]=="vpn-binding"}) + .map((item2)=>{return item2["relationship-data"].find((item3)=>{return item3["relationship-key"]=="vpn-binding.vpn-id"})["relationship-value"]}); + console.log(vpns); + this.detailParams.vpns = vpns.map((item)=>{return { + name:item, + domain: "", + tp1: "", + tp2: "", + tps:[], + site: [], + type: "domain", + start:false, + end:false + }}); + this.detailParams.vpns.forEach((vpn,index)=>{ + this.myhttp.getVpnBinding(vpn.name) + .subscribe((data2)=>{ + + let tps_pnfs = data2["vpn-binding"][0]["relationship-list"]["relationship"] + .filter((item)=>{ return item["related-to"]=="p-interface"}) + .map((item2)=>{return item2["relationship-data"]}); + let pnfname = tps_pnfs.map((item)=>{return item.find((item2)=>{return item2["relationship-key"]=="pnf.pnf-name"})["relationship-value"]}); + let tpnames = tps_pnfs.map((item)=>{return item.find((item2)=>{return item2["relationship-key"]=="p-interface.interface-name"})["relationship-value"]}); + + vpn.tps = tpnames; + this.myhttp.getPnfDetail(pnfname[0]) + .subscribe((data2)=>{ + + let networkRelation = data2["relationship-list"]["relationship"].find((item)=>{ return item["related-to"]=="network-resource"})["relationship-data"]; + vpn.domain = networkRelation.find((item)=>{return item["relationship-key"]=="network-resource.network-id"})["relationship-value"]; + console.log(this.localSite) + for(let i=0;i<this.localSite.length;i++){ + for(let a=0;a<this.detailParams.vpns.length;a++){ + let tps=this.detailParams.vpns[a].tps; + if(i==0){ + if(tps.indexOf(this.localSite[i]["tpsitename"])>-1){ + this.detailParams.vpns[a].site=[]; + let index=tps.indexOf(this.localSite[i]["tpsitename"]); + let tp1=tps.slice(index,1)[0]; + let tp2=tps.find((name)=>{return name != tp1}); + this.detailParams.vpns[a].tp1=tp1; + this.detailParams.vpns[a].tp2=tp2; + this.detailParams.vpns[a].site.push(this.localSite[i]["service-instance-name"]); + this.detailParams.vpns[a].start=true; + let first=this.detailParams.vpns.splice(a,1)[0]; + console.log(first) + this.detailParams.vpns.unshift(first); + console.log(this.detailParams.vpns) + }else { + this.detailParams.vpns[a].tp1=tps[0]; + this.detailParams.vpns[a].tp2=tps[1]; + } + + } else if(i==1){ + if(tps.indexOf(this.localSite[i]["tpsitename"])>-1){ + let thisDomain=this.detailParams.vpns[a].domain; + if(thisDomain==this.detailParams.vpns[0].domain){ + console.log(this.detailParams.vpns[0]); + console.log(this.localSite[i]["service-instance-name"]); + this.detailParams.vpns[0].site.push(this.localSite[i]["service-instance-name"]) + console.log(this.detailParams.vpns[0]) + }else { + this.detailParams.vpns[a].site=[]; + let index=tps.indexOf(this.localSite[i]["tpsitename"]); + let tp2=tps.slice(index,1)[0]; + let tp1=tps.find((name)=>{return name != tp2}); + this.detailParams.vpns[a].tp1=tp1; + this.detailParams.vpns[a].tp2=tp2; + console.log("有多个domain,2个site"); + this.detailParams.vpns[a].site.push(this.localSite[i]["service-instance-name"]); + this.detailParams.vpns[a].start=false; + this.detailParams.vpns[a].end=true; + let last=this.detailParams.vpns.splice(a,1)[0]; + console.log(last); + this.detailParams.vpns.push(last); + } + + } + } + + } + } + for(let b=0;b<this.outerSite.length;b++){ + this.cloudDomain.site.push(this.outerSite[b]["service-instance-name"]); + } + this.detailParams.vpns.push(this.cloudDomain); + console.log(this.detailParams.vpns); + this.vpns = this.detailParams.vpns; + console.log(this.vpns); + res(this.detailParams.vpns); + }) + + }) + }) + }) + }) + } + + drawImages(){ + this.getSiteAResource().then((data)=>{ + console.log(data); + return this.getSotnAresource(); + }).then((data)=>{ + console.log(data); + this.detailParams.vpns.forEach((item)=>{ + if(item.type == "domain" && item.site.length == 0){ + this.d3Data.dates.push( + { + name: item.domain, + type: 'domain' + },{ + name: item.tp1, + type: 'tp' + + },{ + name: item.tp2, + type: 'tp' + }); + this.d3Data.linkss.push({ + source: item.domain, + target: item.domain + },{ + source: item.domain, + target: item.tp1 + },{ + source: item.domain, + target: item.tp2 + }) + }; + if (item.type == "domain" && item.site.length == 1) { + this.d3Data.dates.push({ + name: item.domain, + type: 'domain' + }, { + name: item.tp1, + type: 'tp' + }, { + name: item.tp2, + type: 'tp' + }); + this.d3Data.linkss.push({ + source: item.domain, + target: item.domain + }, { + source: item.domain, + target: item.tp1 + }, { + source: item.domain, + target: item.tp2 + }); + if (item.start == true && item.end == false) { + this.d3Data.dates.push( + { + name: item.site[0], + type: 'site' + }); + this.d3Data.linkss.push({ + source: item.tp1, + target: item.site[0] + }) + } + if (item.start == false && item.end == true) { + this.d3Data.dates.push( + { + name: item.site[0], + type: 'site' + }); + this.d3Data.linkss.push({ + source: item.tp2, + target: item.site[0] + }) + } + + }else if (item.type == "domain" && item.site.length == 2) { + this.d3Data.dates.push({ + name: item.domain, + type: 'domain' + }, { + name: item.tp1, + type: 'tp' + }, { + name: item.tp2, + type: 'tp' + }, + { + name: item.site[0], + type: 'site' + }, + { + name: item.site[1], + type: 'site' + }); + this.d3Data.linkss.push({ + source: item.domain, + target: item.domain + }, { + source: item.domain, + target: item.tp1 + }, { + source: item.domain, + target: item.tp2 + }, { + source: item.tp1, + target: item.site[0] + }, { + source: item.tp2, + target: item.site[1] + }); + }else if (item.type == "cloud" && item.site.length == 1) { + this.d3Data.dates.push({ + name: item.cloud, + type: 'cloud' + }, + { + name: item.site[0], + type: 'site' + }); + this.d3Data.linkss.push({ + source: item.cloud, + target: item.cloud + }, { + source: item.cloud, + target: item.site[0] + }) + } + else if (item.type == "cloud" && item.site.length == 2) { + this.d3Data.dates.push({ + name: item.cloud, + type: 'cloud', + source: item.cloud, + target: item.cloud + }, + { + name: item.site[0], + type: 'site', + source: item.cloud, + target: item.site[0] + }, + { + name: item.site[1], + type: 'site', + source: item.cloud, + target: item.site[1] + }); + this.d3Data.linkss.push({ + source: item.cloud, + target: item.cloud + }, { + source: item.cloud, + target: item.site[0] + }, { + source: item.cloud, + target: item.site[1] + }) + } + + + }); + + var siteNum = 0; + + for (var b = 0; b < this.d3Data.dates.length; b++) { + if (this.d3Data.dates[b].type == "site") { + siteNum++; + } + } + + if (this.detailParams.vpns.length == 2) { + var source = this.detailParams.vpns.find((item) => {return item["type"] == "domain"}).site[1]; + var target = this.detailParams.vpns.find((item) => {return item["type"] == "cloud"}).site[0]; + this.d3Data.linkss.push({ + source: source, + target: target + }) + } else if (this.detailParams.vpns.length > 2) { + if (siteNum == 2) { + for (var c = 0; c < this.detailParams.vpns.length - 1; c++) { + if (c + 1 == this.detailParams.vpns.length - 1) { + var sourcess = this.detailParams.vpns[c].tp2, + targetss = this.detailParams.vpns.find((item)=> {return item["type"] == "cloud";}).cloud; + this.d3Data.linkss.push({ + source: sourcess, + target: targetss + }); + break; + } + var sources = this.detailParams.vpns[c].tp2, + targets = this.detailParams.vpns[c + 1].tp1; + this.d3Data.linkss.push({ + source: sources, + target: targets + }) + } + } else if (siteNum == 4) { + for (var c = 0; c < this.detailParams.vpns.length - 1; c++) { + if (c + 1 == this.detailParams.vpns.length - 1) { + break; + } + var sources = this.detailParams.vpns[c].tp2, + targets = this.detailParams.vpns[c + 1].tp1; + this.d3Data.linkss.push({ + source: sources, + target: targets + }) + } + } + } + setTimeout(this.render(),0) + }); + } + + + + clickShow = false; + hoverShow = false; + toggleClick(){ + this.clickShow = !this.clickShow; + } + hoverShowcould(){ + this.hoverShow = true; + } + hoverHidecould(){ + this.hoverShow = false; + } + + + + goback(){ + this.closeDetail.emit(); + } + + + render() { + console.log("dadada"); + console.log(this.d3Data); + console.log(this.detailParams.vpns); + this.scale = 1; + + this.svg .attr('width', this.width) + .attr('height', this.height); + this.container = this.svg.append('g') + .attr('transform', 'scale(' + this.scale + ')'); + + this.initPosition(); + this.initLink(); + this.initNode(); + } + + + initPosition() { + let origin = [this.width / 6, this.height / 7]; + var data=this.d3Data.dates; + let points = this.getVertices(origin, Math.min(this.width, this.height) * 0.3,data.length,this.detailParams.vpns); + + this.d3Data.dates.forEach((item,i)=>{ + item.x = points[i].x; + item.y = points[i].y; + }) + } + + + getVertices(origin, r, n,data) { + if (typeof n !== 'number') return; + var ox = origin[0]; + var oy = origin[1]; + var i = 0; + var points = []; + var tempAngle =180, + reduce=50, + add=100; + for(let a=0;a<this.detailParams.vpns.length;a++){ + if(this.detailParams.vpns[a].type=="domain"){ + if(this.detailParams.vpns[a].site.length == 0){ + tempAngle =180*i; + points.push({ + x: ox +tempAngle, + y: oy + },{ + x: ox +tempAngle-reduce, + y: oy+add + },{ + x: ox +tempAngle+reduce, + y: oy+add + }); + i++; + }else if((this.detailParams.vpns[a].site.length == 1)){ + tempAngle =180*i; + points.push({ + x: ox +tempAngle, + y: oy + },{ + x: ox +tempAngle-reduce, + y: oy+add + },{ + x: ox +tempAngle+reduce, + y: oy+add + },{ + x: ox +tempAngle-1.5*reduce, + y: oy+2*add + }); + i++; + } else if((this.detailParams.vpns[a].site.length == 2)){ + tempAngle =350*i; + reduce=70; + points.push({ + x: ox +tempAngle, + y: oy + },{ + x: ox +tempAngle-reduce, + y: oy+add + },{ + x: ox +tempAngle+reduce, + y: oy+add + },{ + x: ox +tempAngle-1.5*reduce, + y: oy+2*add + } + ,{ + x: ox +tempAngle+reduce, + y: oy+2*add + }); + i++; + } + + }else if((this.detailParams.vpns[a].type=="cloud")){ + if((this.detailParams.vpns[a].site.length ==1)){ + tempAngle =180*i; + points.push({ + x: ox +tempAngle, + y: oy + },{ + x: ox +tempAngle+1.5*reduce, + y: oy+2*add + }); + i++; + } else if((this.detailParams.vpns[a].site.length == 2)){ + if((this.detailParams.vpns.length>2)){ + tempAngle =180*i; + }else{ + tempAngle =400*i; + } + points.push({ + x: ox +tempAngle, + y: oy + },{ + x: ox +tempAngle-1.5*reduce, + y: oy+2*add + } + ,{ + x: ox +tempAngle+1.5*reduce, + y: oy+2*add + }); + i++; + } + + } + } + + return points; + } + + + initLink() { + this.drawLinkLine(); + } + + + initNode() { + var self = this; + + this.nodes = this.container.selectAll(".node") + .data(this.d3Data.dates) + .enter() + .append("g") + .attr("transform", function (d) { + return "translate(" + d.x + "," + d.y + ")"; + }) + .attr('class', 'node') + .style("cursor","pointer") + .call(d3.behavior.drag() + .on("drag", function (d) { + self.onDrag(this, d) + }) + ); + + + this.drawNodeSymbol(); + + this.drawNodeTitle(); + } + + + + drawNodeSymbol() { + var imgmap = { + 'domain': '../../assets/images/domain.png', + 'tp': '../../assets/images/tp.png', + 'site': '../../assets/images/site.png', + 'cloud': '../../assets/images/out-domain.png' + }; + + + this.nodes.append('image') + .attr('width', function (d) { + let width = "15%"; + switch (d.type) { + case 'domain': + width ="15%"; + break; + case 'tp': + width ="4%"; + break; + case 'site': + width ="10%"; + break; + case 'cloud': + width ="15%"; + break; + default: + break; + } + return width; + }) + .attr('height', function (d) { + let height = "15%"; + switch (d.type) { + case 'domain': + height ="15%"; + break; + case 'tp': + height ="4%"; + break; + case 'site': + height ="10%"; + break; + case 'cloud': + height ="15%"; + break; + default: + break; + } + return height; + }) + .attr('xlink:href', function (d) { + return imgmap[d.type]; + }) + .attr('x',function () { + return -this.getBBox().width/2 + }) + .attr('y',function () { + return -this.getBBox().height/2 + }); + } + + + + drawNodeTitle() { + + this.nodes.append("text") + .attr('class','node-title') + .text(function (d) { + return d.name; + }) + .attr("dx",function (d) { + var x=0; + if(d.type=="tp"){ + x=20; + }else { + x=0; + } + return x; + }) + .attr("dy",function (d) { + var y=0; + if(d.type=="tp"){ + y=25; + }else { + y=0; + } + return y; + }); + } + + + drawLinkLine() { + let data = this.d3Data.dates; + if (this.lineGroup) { + this.lineGroup.selectAll('.link') + .attr('d', link => genLinkPath(link)) + } else { + this.lineGroup = this.container.append('g'); + this.lineGroup.selectAll('.link') + .data(this.d3Data.linkss) + .enter() + .append('path') + .attr('class', 'link') + .attr('d',function (link) { + return genLinkPath(link) + }) + } - // 当外部site有两个的时候 - if(this.outerSite.length==2){ - let line = { - "x1":"75%","y1":"20%","x2":"60%","y2":"50%"//out-domain--site3 - } - this.detailLines.push(line); + function genLinkPath(d) { + let sx = data.find(function(item){ + return item["name"]==d.source; + }).x; + let sy = data.find(function(item){ + return item["name"]==d.source; + }).y; + let tx =data.find(function(item){ + return item["name"]==d.target; + }).x; + let ty =data.find(function(item){ + return item["name"]==d.target; + }).y; + return 'M' + sx + ',' + sy + ' L' + tx + ',' + ty; } - } - }) - // let allnodes = [this.getSiteAResource(),this.getSotnAresource()]; - // Promise.all(allnodes).then((data)=>{ - // console.log(data) - // console.log(this.localSite); - - - // }) - } - - detailSites=false; - detailLines=[ //详情拓扑图连线的坐标 - { - "x1":"5%","y1":"50%","x2":"17%","y2":"25%"//site1--tp1 - }, - { - "x1":"22%","y1":"20%","x2":"17%","y2":"25%"//tp1--domian1 } - , - { - "x1":"26%","y1":"15%","x2":"30%","y2":"12%"//domian1--tp2 - }, - - { - "x1":"80%","y1":"20%","x2":"85%","y2":"50%"//out-domain--site4 - }, - - { - "x1":"50%","y1":"22%","x2":"45%","y2":"28%"//tp4--domian2 - }, - { - "x1":"40%","y1":"11%","x2":"50%","y2":"15%"//domian2--tp3 - }, - { - "x1":"32%","y1":"11%","x2":"41%","y2":"11%"//tp2--tp3 - }, - - { - "x1":"45%","y1":"30%","x2":"35%","y2":"50%"//site2--tp4 - }, - { - "x1":"75%","y1":"20%","x2":"60%","y2":"50%"//out-domain--site3 - }, - { - "x1":"40%","y1":"52%","x2":"52%","y2":"52%"//site2--site3 + + + + update(d) { + this.drawLinkLine(); } - ]; - lines=[]; - siteImage=[]; - drawImage(sitelist){ - let cx = 200; - let cy = 200; - let r = 150; - let startAngle = -210 * (Math.PI/180); - let step = sitelist.length > 1 ? 120/(sitelist.length-1) * (Math.PI/180) : 1; - - this.lines = sitelist.map((item,index)=>{ - let x = cx + Math.cos(startAngle - step*index)*r; - let y = cy + Math.sin(startAngle - step*index)*r; - return {img:"line",x1:cx,y1:cy,x2:x,y2:y} - }) - this.siteImage = this.lines.map((item)=>{ - return {img:"site",x:item.x2 - 25,y:item.y2 - 25} - }) - console.log(this.siteImage,this.lines) - } - clickShow = false; - hoverShow = false; - toggleClick(){ - this.clickShow = !this.clickShow; - } - hoverShowcould(){ - this.hoverShow = true; - } - hoverHidecould(){ - this.hoverShow = false; - } - - - - goback(){ - this.closeDetail.emit(); - } + + + onDrag(ele, d) { + d.x = d3.event.x; + d.y = d3.event.y; + d3.select(ele) + .attr('transform', "translate(" + d3.event.x + "," + d3.event.y + ")"); + this.update(d); + } + } diff --git a/usecaseui-portal/src/app/components/e2e-creation/e2e-creation.component.css b/usecaseui-portal/src/app/components/e2e-creation/e2e-creation.component.css new file mode 100644 index 00000000..f1d359f0 --- /dev/null +++ b/usecaseui-portal/src/app/components/e2e-creation/e2e-creation.component.css @@ -0,0 +1,77 @@ +/* + 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: 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/components/e2e-creation/e2e-creation.component.html b/usecaseui-portal/src/app/components/e2e-creation/e2e-creation.component.html new file mode 100644 index 00000000..0ada7dd1 --- /dev/null +++ b/usecaseui-portal/src/app/components/e2e-creation/e2e-creation.component.html @@ -0,0 +1,123 @@ +<!-- + 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="model"> + <!-- 创建数据 --> + <button class="back" nz-button (click)="goback()"><span><i class="anticon anticon-rollback"></i></span></button> + <div class="creation fl"> + <div *ngIf="createParams.commonParams.templateType=='E2E Service'" class="baseparms clearfix"> + <h3>Base</h3> + <ul> + <li><span>Name*</span> <input nz-input [(ngModel)]="service.name"></li> + <li><span>Description*</span> <input nz-input [(ngModel)]="service.description"></li> + </ul> + <br> + <h3>Template Parameters</h3> + <h4>template Inputs</h4> + <ul> + <li *ngFor="let parameter of templateParameters.inputs; let i = index;"> + <span *ngIf="parameter.type !== 'vf_location' && parameter.type !== 'sdn_controller'">{{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'" style="width: 165px;" [(ngModel)]="parameter.value" nzAllowClear > + <nz-option *ngFor="let vim of vimInfos" [nzValue]="vim" [nzLabel]="vim.name"></nz-option> + </nz-select> + <!-- <nz-select *ngIf="parameter.type === 'sdn_controller'" style="width: 165px;" [(ngModel)]="parameter.value" nzAllowClear > + <nz-option *ngFor="let control of sdnControllers" [nzValue]="control" [nzLabel]="control.name"></nz-option> + </nz-select> --> + </li> + </ul> + <h4>nestedTemplate Inputs</h4> + <div *ngFor="let template of templateParameters.nestedTemplates;"> + <h4 style="font:400 14px 'Arial';color:#aaa;">templateName: {{template.name}}</h4> + <ul> + <li *ngFor="let input of template.inputs; let i = index;"> + <span *ngIf="input.type !== 'vf_location' && input.type !== 'sdn_controller'" > {{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'" style="width: 165px;" [(ngModel)]="input.value" nzAllowClear > + <nz-option *ngFor="let vim of vimInfos" [nzValue]="vim" [nzLabel]="vim.name"></nz-option> + </nz-select> + <!-- <nz-select *ngIf="input.type === 'sdn_controller'" style="width: 165px;" [(ngModel)]="input.value" nzAllowClear > + <nz-option *ngFor="let control of sdnControllers" [nzValue]="control" [nzLabel]="control.name"></nz-option> + </nz-select> --> + </li> + </ul> + </div> + + </div> + + <div *ngIf="createParams.commonParams.templateType=='Network Service'" class="baseparms clearfix"> + <h3>Base</h3> + <ul> + <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> + <h3>Template Parameters</h3> + <h4>template Inputs</h4> + <ul> + <li *ngFor="let parameter of nsTemplateParameters.inputs2; let i = index;"> + <span *ngIf="parameter.type !== 'vf_location' && parameter.type !== 'sdn_controller'">{{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'" style="width: 165px;" [(ngModel)]="parameter.value" nzAllowClear > + <nz-option *ngFor="let vim of vimInfos" [nzValue]="vim" [nzLabel]="vim.name"></nz-option> + </nz-select> + <!-- <nz-select *ngIf="parameter.type === 'sdn_controller'" style="width: 165px;" [(ngModel)]="parameter.value" nzAllowClear > + <nz-option *ngFor="let control of sdnControllers" [nzValue]="control" [nzLabel]="control.name"></nz-option> + </nz-select> --> + </li> + </ul> + + <h4>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 style="width: 165px;" [(ngModel)]="vnf.value" nzAllowClear > + <nz-option *ngFor="let vim of vimInfos" [nzValue]="vim" [nzLabel]="vim.name"></nz-option> + </nz-select> + </li> + </ul> + + </div> + <button class="submit" nz-button [nzType]="'primary'" (click)="submit()"><span>Create</span></button> + </div> + + <!-- 图 --> + <div class="chart fr"> + Create Service + <div id="createChart"> + <svg width="100%" height="100%"> + + <image xlink:href="./assets/images/cloud-site.png" + x="25%" y="30%" width="50%"/> + + </svg> + + </div> + </div> + +</div> + diff --git a/usecaseui-portal/src/app/components/e2e-creation/e2e-creation.component.less b/usecaseui-portal/src/app/components/e2e-creation/e2e-creation.component.less new file mode 100644 index 00000000..b8c41877 --- /dev/null +++ b/usecaseui-portal/src/app/components/e2e-creation/e2e-creation.component.less @@ -0,0 +1,80 @@ +/* + 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: 10px; +} +.model { + background-color: #fff; + height: 90%; + overflow-y: auto; + .back { + position: absolute; + top: 10px; + right: 20px; + } + .creation{ + position: relative; + width: 60%; + height: 100%; + overflow-y: auto; + border-radius: 5px; + padding: 20px; + .baseparms { + h3 { + color: #3fa8eb; + font: 700 16px "Arial"; + } + h4 { + font: 700 16px "Arial"; + } + ul li { + // display: inline-block; + margin: 3px 0; + span { + display: inline-block; + width: 40%; + font: 700 14px "Arial"; + vertical-align: middle; + overflow: hidden; + text-overflow: ellipsis; + text-align: right; + } + input { + width: 165px; + } + } + } + .submit { + position: absolute; + top: 10px; + right: 20px; + } + } + .chart { + width: 40%; + padding: 10px; + height: 100%; + border-left: 10px solid #f3f3f3; + } +} diff --git a/usecaseui-portal/src/app/components/e2e-creation/e2e-creation.component.spec.ts b/usecaseui-portal/src/app/components/e2e-creation/e2e-creation.component.spec.ts new file mode 100644 index 00000000..de00c43f --- /dev/null +++ b/usecaseui-portal/src/app/components/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/components/e2e-creation/e2e-creation.component.ts b/usecaseui-portal/src/app/components/e2e-creation/e2e-creation.component.ts new file mode 100644 index 00000000..f478c699 --- /dev/null +++ b/usecaseui-portal/src/app/components/e2e-creation/e2e-creation.component.ts @@ -0,0 +1,212 @@ +/* + 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. +*/ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { MyhttpService } from '../../myhttp.service'; + +@Component({ + selector: 'app-e2e-creation', + templateUrl: './e2e-creation.component.html', + styleUrls: ['./e2e-creation.component.less'] +}) +export class E2eCreationComponent implements OnInit { + + constructor( private myhttp:MyhttpService ) { } + + ngOnInit() { + this.getTemParameters(); + this.getVimInfo(); + this.getSdnControllers(); + console.log(this.createParams); + } + + @Output() e2eCloseCreate = new EventEmitter(); + @Output() nsCloseCreate = new EventEmitter(); + @Input() createParams; + + + // e2e serviceTemplateParameters + templateParameters = { + invariantUUID: "", + uuid: "", + name: "", + type: "", + version: "", + description: "", + category: "", + subcategory: "", + customizationUuid: "", + inputs:[], + nestedTemplates:[] + }; + // ns serviceTemplateParameters + nsTemplateParameters = { + inputs:{}, + inputs2:[], + vnfs:[] + } + getTemParameters(){ //获取模板参数 + let type = this.createParams.commonParams.templateType == "E2E Service" ? "e2e" : "ns"; + this.myhttp.getTemplateParameters(type,this.createParams.template) + .subscribe((data)=>{ + 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"}); + }) + }else if(type == "ns"){ + this.nsTemplateParameters = data; + 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}) + } + console.log(this.nsTemplateParameters); + } + + + }) + } + 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: "", + 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((item)=>{ + this.service.parameters.requestInputs[item.name] = item.value == undefined ? item.defaultValue : item.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:{ + vimId:input.value.id + } + } + nsService.parameters.locationConstraints.push(location); + } + }) + this.service.parameters.resources.push(nsService); + }) + + this.e2eCloseCreate.emit(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.vnf_id, + locationConstraints: { + vimid: vnf.value.id, + accessinfo: { + tenant: "" + }, + accessInfo: { + tenant: "" + } + } + } + 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(); + } + +} diff --git a/usecaseui-portal/src/app/myhttp.service.ts b/usecaseui-portal/src/app/myhttp.service.ts index 8b872e64..958bc741 100644 --- a/usecaseui-portal/src/app/myhttp.service.ts +++ b/usecaseui-portal/src/app/myhttp.service.ts @@ -21,15 +21,19 @@ export class MyhttpService { // customers:this.baseUrl + "/customers.json?", // serviceType:this.baseUrl + "/serviceTypes.json?*_*", // servicesCategory:this.baseUrl + "/configuration_files/servicesCategory.json?", - // serviceInstanceList:this.baseUrl + "/instanceTableData4.json?", + // serviceInstanceList:this.baseUrl + "/instanceTableData.json?", // serviceTemplates:this.baseUrl + "/serviceTemplates2.json?", - // templateCategory:this.baseUrl + "/configuration_files/templateCategory.json?", // templateParameters:this.baseUrl + "/*_*" + "ServiceTemplateParameters.json?", + // vimInfo:this.baseUrl + "/vimInfo.json?", + // sdnControllers:this.baseUrl + "/sdnControllers.json?", // addressData: this.baseUrl + "/siteAddressData.json?", - // createService:this.baseUrl + "/createService.json?", + // createService:this.baseUrl + "/createService.json", + // ns_createService: this.baseUrl + "/createNsService.json?", + // ns_createService2: this.baseUrl + "/createNsService2.json", // inputNamesTransform: this.baseUrl + "/configuration_files/inputNamesTranslate.json?", // deleteService: this.baseUrl + "/deleteService.json?", // progress:this.baseUrl + "/progress.json?", + // nsProgress:this.baseUrl + "nsProgress.json?", // allottedResource:this.baseUrl + "/allotted-resources2.json?", // pnfDetail:this.baseUrl + "/pnfdetail-domain.json?", @@ -54,13 +58,18 @@ export class MyhttpService { servicesCategory: "./assets/json/configuration_files/servicesCategory.json", serviceInstanceList:this.baseUrl + '/uui-sotn/getServiceInstanceList', serviceTemplates:this.baseUrl + "/uui-lcm/service-templates", - templateCategory: "./assets/json/configuration_files/templateCategory.json", templateParameters:this.baseUrl + "/uui-lcm/service-templates/" + "*_*" +"?toscaModelPath=", + nstemplateParameters:this.baseUrl + "/uui-lcm/fetchNsTemplateData", + vimInfo:this.baseUrl + "/uui-lcm/locations/", + sdnControllers:this.baseUrl + "/uui-lcm/sdnc-controllers/", addressData: this.baseUrl + "/uui-sotn/getOssInvenory", createService:this.baseUrl + "/uui-lcm/services", + ns_createService: this.baseUrl + "/uui-lcm/createNetworkServiceInstance", + ns_createService2: this.baseUrl + "/uui-lcm/instantiateNetworkServiceInstance", inputNamesTransform: "./assets/json/configuration_files/inputNamesTranslate.json?", deleteService: this.baseUrl + "/uui-lcm/services/", progress:this.baseUrl + "/uui-lcm/services/" + "*_*" + "/operations/", + nsProgress:this.baseUrl + "/uui-lcm/jobs/getNsLcmJobStatus/"+ "*_*" + "?responseId=", allottedResource:this.baseUrl + "/uui-sotn/getAllottedResources", pnfDetail:this.baseUrl + "/uui-sotn/getPnfInfo/", @@ -98,44 +107,11 @@ export class MyhttpService { - - - testObservable(){ - let myObservable = new Observable((observer)=>{ - observer.next(1); - observer.next((n)=>{ - console.log(3+n); - }) - setTimeout(()=>{ - observer.next(66666) - },100) - observer.next(()=>{ - setTimeout((n)=>{ - console.log("9999---" + n); - },10) - }) - // observer.error(2); - // observer.complete(); - }); - - myObservable.subscribe((e)=>{ - if(typeof e == "function"){ - e(5) - } - console.log(e); - },(err)=>{ - console.log(err); - },()=>{ - console.log(555); - }) - } - //--------------------------------------------------------------------------------- // Get all customers getAllCustomers(){ return this.http.get<any>(this.url.customers); - // return this.http.jsonp<Object[]>('http://127.0.0.1:5500/customers.json',"callback");// } // Get relevant serviceType @@ -144,9 +120,9 @@ export class MyhttpService { return this.http.get<any>(url); } // Get service classification information, local configuration file - getServicesCategory(){ - return this.http.get<any>(this.url.servicesCategory); - } + // getServicesCategory(){ + // return this.http.get<any>(this.url.servicesCategory); + // } // list Tabular data getInstanceTableData(paramsObj){ let params = new HttpParams({fromObject:paramsObj}); @@ -160,18 +136,27 @@ export class MyhttpService { // } // Get all template types - getAllServiceTemplates(){ + getAllServiceTemplates(type){ + if(type=="Network Service"){ + let nsUrl = this.url.serviceTemplates.replace("service-templates","listNsTemplates").replace("serviceTemplates2","serviceTemplates-ns"); + console.log(nsUrl); + return this.http.get<any>(nsUrl); + } return this.http.get<any>(this.url.serviceTemplates); } - // Get template classification information, local configuration file - getTemplateCategory(){ - return this.http.get<any>(this.url.servicesCategory); - } + //Get template input parameters getTemplateParameters(type,template){ - let url = this.url.templateParameters.replace("*_*",type) + template.toscaModelURL; //本地模拟 - // let url = this.url.templateParameters.replace("*_*",template.uuid) + template.toscaModelURL; + // let url = this.url.templateParameters.replace("*_*",type) + template.toscaModelURL; //Local simulation + if(type == "ns"){ + let body = { + csarId:template.id, + inputs:"" + } + return this.http.post<any>(this.url.nstemplateParameters,body); + } + let url = this.url.templateParameters.replace("*_*",template.uuid) + template.toscaModelURL; return this.http.get<any>(url); } // siteAddress address @@ -179,10 +164,25 @@ export class MyhttpService { return this.http.get<any>(this.url.addressData); } + getVimInfo() { + return this.http.get<any>(this.url.vimInfo); + }; + getSdnControllers(){ + return this.http.get<any>(this.url.sdnControllers); + } + // Create interface - createInstance(requestBody){ - return this.http.get<any>(this.url.createService); //本地模拟 - // return this.http.post<any>(this.url.createService,requestBody); + createInstance(requestBody,createParams){ + // return this.http.get<any>(this.url.createService + createParams); //Local simulation + return this.http.post<any>(this.url.createService,requestBody); + } + nsCreateInstance(requestBody){ + // return this.http.get<any>(this.url.ns_createService); //Local simulation + return this.http.post<any>(this.url.ns_createService,requestBody); + } + nsCreateInstance2(params,requestBody){ + // return this.http.get<any>(this.url.ns_createService2 + params); //Local simulation + return this.http.post<any>(this.url.ns_createService + params,requestBody); } // Input parameter name conversion @@ -203,8 +203,8 @@ export class MyhttpService { 'serviceType': obj.serviceType } }; - return this.http.get<any>(this.url.deleteService); //Local simulation - // return this.http.delete<any>(this.url.deleteService + obj.serviceInstanceId, httpOptions); + // return this.http.get<any>(this.url.deleteService); //Local simulation + return this.http.delete<any>(this.url.deleteService + obj.serviceInstanceId, httpOptions); } // Query progress interface @@ -212,6 +212,10 @@ export class MyhttpService { let url = this.url.progress.replace("*_*",obj.serviceId) + obj.operationId; return this.http.get<any>(url); } + getNsProgress(jobid,responseId){ + let url = this.url.nsProgress.replace("*_*",jobid) + responseId; + return this.http.get<any>(url); + } // Get allotted-resource to get tp and pnf values getAllottedResource(obj){ diff --git a/usecaseui-portal/src/app/networkHttpservice.service1.ts b/usecaseui-portal/src/app/networkHttpservice.service1.ts deleted file mode 100644 index edb4df7c..00000000 --- a/usecaseui-portal/src/app/networkHttpservice.service1.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { Injectable } from '@angular/core'; -import { HttpClient, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http'; - - -@Injectable() -export class networkHttpservice { - - constructor(private http:HttpClient) { } - - // baseUrl = "./assets/json/";//本地环境 - // url={ - // "getNetworkD3Data":this.baseUrl + "netWorkD3Data.json", - // "getLogicalLinksData":this.baseUrl + "LogicalLinksData.json", - // "getPInterfacesData1":this.baseUrl + "netWorkD3Data.json", - // "getPInterfacesData2":this.baseUrl + "p_interfaces1.json", - // "createLink":this.baseUrl + "status.json", - // "querySpecificLinkInfo":this.baseUrl + "specific_link _nfo.json", - // "queryCloudUrl":this.baseUrl + "url.json", - // "createNetwrok":this.baseUrl + "status.json", - // "createPnf":this.baseUrl + "status.json", - // "createTp":this.baseUrl + "status.json", - // "createCloudLink":this.baseUrl + "status.json", - // "createCloudUrl":this.baseUrl + "status.json", - // "deleteLink":this.baseUrl + "status.json", - // }; - // baseUrl = "http://10.73.242.244:8082/uui-sotn/";//线上环境 - // baseUrl = "http://172.19.44.223/api/usecaseui-server/v1/uui-sotn/";//线上环境 - baseUrl = "/api/usecaseui-server/v1/uui-sotn/";//线上环境 - url={ - "getNetworkD3Data":this.baseUrl + "getNetWorkResources", - "getLogicalLinksData":this.baseUrl + "getLogicalLinks", - "getPInterfacesData1":this.baseUrl + "getPinterfaceByPnfName/", - "getPInterfacesData2":this.baseUrl + "getPinterfaceByPnfName/", - "createLink":this.baseUrl + "createLink/", - "querySpecificLinkInfo":this.baseUrl + "getSpecificLogicalLink/", - "queryCloudUrl":this.baseUrl + "getHostUrl/", - "createNetwrok":this.baseUrl + "createTopoNetwork/", - "createPnf":this.baseUrl + "createPnf/", - "createTp":this.baseUrl + "pnf/", - "createCloudLink":this.baseUrl + "createLink/", - "createCloudUrl":this.baseUrl + "createHostUrl/", - "deleteLink":this.baseUrl + "deleteLink/", - }; - //d3数据 - getNetworkD3Data(){ - return this.http.get<any>(this.url["getNetworkD3Data"]); - } - //初始化连线 logical-links - getLogicalLinksData(){ - return this.http.get<any>(this.url["getLogicalLinksData"]); - } - //查询指定的node对应的tp数据 - getPInterfacesData1(paramsObj){ - return this.http.get<any>(this.url['getPInterfacesData1']+paramsObj["pnfName"]); - } - getPInterfacesData2(paramsObj){ - return this.http.get<any>(this.url["getPInterfacesData2"]+paramsObj["pnfName"]); - } - //创建连线接口 - createLink(paramsObj){ - return this.http.put<any>(this.url["createLink"]+paramsObj["link-name"],paramsObj); - } - //查询指定的单个连接线 接口 - querySpecificLinkInfo(paramsObj){ - return this.http.get<any>(this.url["querySpecificLinkInfo"]+paramsObj["link-name"]); - } - //查询 外部云host this.url地址 接口 - queryCloudUrl(aaiId){ - return this.http.get<any>(this.url["queryCloudUrl"]+aaiId); - } - //创建外部云newwork接口 - createNetwrok(paramsObj){ - return this.http.put<any>(this.url["createNetwrok"]+paramsObj["network-id"],paramsObj); - } - //创建外部云pnf接口 - createPnf(paramsObj){ - return this.http.put<any>(this.url["createPnf"]+paramsObj["pnf-name"],paramsObj); - } - //创建外部云Tp接口 - createTp(paramsObj,cloudNodeName){ - let str=cloudNodeName+"/p-interfaces/p-interface/"+paramsObj["interface-name"]+"/createTerminationPoint"; - return this.http.put<any>(this.url["createTp"]+str,paramsObj); - } - //创建外部云link接口 - createCloudLink(paramsObj){ - return this.http.put<any>(this.url["createCloudLink"]+paramsObj["link-name"],paramsObj); - } - //创建外部云host url接口 - createCloudUrl(paramsObj){ - return this.http.put<any>(this.url["createCloudUrl"]+paramsObj["aai-id"],paramsObj); - } - //删除连线 - deleteLink(paramsObj){ - let str=paramsObj["logical-link"]+"/"+paramsObj["resource-version"]; - return this.http.delete<any>((this.url["deleteLink"]+str)); - } -} 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 index eaf8fddb..63426fd9 100644 --- a/usecaseui-portal/src/app/services/services-list/services-list.component.css +++ b/usecaseui-portal/src/app/services/services-list/services-list.component.css @@ -108,6 +108,31 @@ hr { font-size: 12px; color: #147dc2; } +.list nz-table.table2 tr td { + padding: 10px 8px; +} +.list nz-table.table2 tr td span.action { + color: #3fa8eb; + cursor: pointer; + padding: 5px; +} +.list nz-table.table2 tr td span.cannotclick { + pointer-events: none; + color: #aaa; + opacity: 0.6; +} +.list nz-table.table2 tr td span.deleting { + color: red; + font-size: 12px; + display: block; + height: 12px; +} +.list nz-table.table2 tr td span.creating { + color: #3fa8eb; + font-size: 12px; + display: block; + height: 12px; +} .detailComponent { position: absolute; left: 0; 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 index e0866524..c18d294a 100644 --- a/usecaseui-portal/src/app/services/services-list/services-list.component.html +++ b/usecaseui-portal/src/app/services/services-list/services-list.component.html @@ -39,34 +39,40 @@ <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-option nzValue="E2E Service" nzLabel="E2E Service"></nz-option> + <nz-option nzValue="Network Service" nzLabel="Network Service"></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> + <div *ngIf="templateTypeSelected == 'SOTN'||templateTypeSelected == 'CCVPN'"> + <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 > + <br><br> + <span style="display:inline-block;width:70px;"> 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> + </div> + + <div *ngIf="templateTypeSelected == 'E2E Service'||templateTypeSelected == 'Network Service'"> + <span style="display:inline-block;width:70px;">TEMPLATE: </span> + <nz-select style="width: 165px;" [(ngModel)]="template4" nzAllowClear > <nz-option *ngFor="let item of templates" [nzValue]="item" [nzLabel]="item.name"></nz-option> </nz-select> </div> @@ -101,76 +107,40 @@ <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>{{pageSize*(pageIndex-1) + i+1}}</td> + <td [nzShowExpand]="data.childServiceInstances[0]" [(nzExpand)]="data.expand"></td> + <td>{{data["service-instance-id"] || data.nsInstanceId}}</td> + <td>{{data["service-instance-name"] || data.nsName}}</td> + <td>{{data.serviceDomain}}</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> + 'updating':data.status=='Updating','deleting':data.status=='Deleting','creating':data.status=='Creating'}">{{data.status || "Active"}}</span> + <nz-progress *ngIf="data.status == 'Creating' || data.status == 'Deleting' || data.status == 'Updating' " [nzPercent]="data.rate"></nz-progress> + <!-- <nz-progress *ngIf="item.sotnvpnSer.status=='creating' || item.sotnvpnSer.status=='deleting'" [nzPercent]="item.sotnvpnSer.rate"></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> + <i *ngIf="data.serviceDomain=='E2E Service'||data.serviceDomain=='Network Service' " class="anticon anticon-setting" (click)="scaleService(data)"></i> + <!-- <i *ngIf="data.serviceDomain=='E2E Service'||data.serviceDomain=='Network Service' " class="anticon anticon-cloud-upload-o" (click)="updataService(data)"></i> --> + <i *ngIf="data.serviceDomain=='Network Service' " class="anticon anticon-pause" (click)="stopService(data)"></i> + <i *ngIf="data.serviceDomain=='Network Service' " class="anticon anticon-reload" (click)="restartService(data)"></i> + <i *ngIf="data.serviceDomain=='SOTN'||data.serviceDomain=='CCVPN' " class="anticon anticon-ellipsis" (click)="serviceDetail(data)"></i> + <i class="anticon anticon-delete" (click)="deleteService(data)"></i> + <!-- <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> - <tr class="childtr" [nzExpand]="data.expand" *ngFor="let item of data.children"> + <tr class="childtr" [nzExpand]="data.expand" *ngFor="let item of data.childServiceInstances"> <td></td> <td></td> - <td>{{item.serviceId}}</td> - <td>{{item.name}}</td> - <td colspan="3">{{item.type}}</td> + <td>{{data["service-instance-id"] || data.nsInstanceId}}</td> + <td>{{data["service-instance-name"] || data.nsName}}</td> + <td colspan="3">{{item.serviceDomain}}</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"> @@ -183,3 +153,10 @@ (closeCreate)="closeCreate($event)"> </app-ccvpn-creation> </div> +<div class="createComponent" *ngIf="createshow2"> + <app-e2e-creation + [createParams]="createData" + (nsCloseCreate)="nsCloseCreate($event)" + (e2eCloseCreate)="e2eCloseCreate($event)"> + </app-e2e-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 index 7e8ff80e..8f83cc9d 100644 --- a/usecaseui-portal/src/app/services/services-list/services-list.component.less +++ b/usecaseui-portal/src/app/services/services-list/services-list.component.less @@ -1,3 +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. +*/ .title { font: 700 18px/18px "思源黑体"; color: #4c5e70; @@ -103,6 +118,32 @@ hr { } } +.list nz-table.table2 tr td { + padding: 10px 8px; +} +.list nz-table.table2 tr td span.action { + color: #3fa8eb; + cursor: pointer; + padding: 5px; +} +.list nz-table.table2 tr td span.cannotclick { + pointer-events: none; + color: #aaa; + opacity: 0.6; +} +.list nz-table.table2 tr td span.deleting { + color: red; + font-size: 12px; + display: block; + height: 12px; +} +.list nz-table.table2 tr td span.creating { + color: #3fa8eb; + font-size: 12px; + display: block; + height: 12px; +} + .detailComponent { position: absolute; left: 0; 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 index d893070d..9ea28d4b 100644 --- a/usecaseui-portal/src/app/services/services-list/services-list.component.ts +++ b/usecaseui-portal/src/app/services/services-list/services-list.component.ts @@ -1,3 +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. +*/ import { Component, OnInit, HostBinding } from '@angular/core'; import { MyhttpService } from '../../myhttp.service'; import { slideToRight } from '../../animates'; @@ -13,18 +28,18 @@ export class ServicesListComponent implements OnInit { @HostBinding('@routerAnimate') routerAnimateState; constructor(private myhttp: MyhttpService, private modalService: NzModalService) { } + ngOnInit() { this.getallCustomers(); - this.getTemplateSubTypes(); this.inputNamests(); } - // 筛选框(下拉框)customer servicetype + // customer servicetype customerList = []; customerSelected = {name:null,id:null}; serviceTypeList = []; - serviceTypeSelected = {name:null,id:null}; + serviceTypeSelected = {name:null}; - // 获取所有customer + // getallCustomers(){ this.myhttp.getAllCustomers() .subscribe((data)=>{ @@ -50,108 +65,71 @@ export class ServicesListComponent implements OnInit { this.getTableData(); } - // 模态框(对话框) create + + // Create modal box 2 (dialog box) 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();//分类 + this.getAlltemplates(); } - // 模板 - templates = []; templates1;templates2;templates3; + // + templates = []; 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") - }) - } + template4={name:null}; - getAlltemplates(){ //获取所有模板类型 - this.myhttp.getAllServiceTemplates() + getAlltemplates(){ // + this.myhttp.getAllServiceTemplates(this.templateTypeSelected) .subscribe((data)=>{ console.log(data) this.templates = data; - this.template1 = data[0]; - this.template2 = data[1]; - this.template3 = data[2]; - // this.filterTemplates();//分类 + if(this.templateTypeSelected=="Network Service"){ + this.templates = data.map((item)=>{return {name:item.packageInfo.csarName,id:item.csarId,packageInfo:item.packageInfo}}); + } + this.template1 = this.templates[0]; + this.template2 = this.templates[1]; + this.template3 = this.templates[2]; + this.template4 = this.templates[0]; + },(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; + createshow2 = false; createData:Object={}; - handleOk2(): void { + handleOk(): 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.isVisible = false; + + if(this.templateTypeSelected=="SOTN"||this.templateTypeSelected=="CCVPN"){ + 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; + }else if(this.templateTypeSelected=="E2E Service"||this.templateTypeSelected=="Network Service"){ + this.createData = {commonParams:{customer:this.customerSelected, serviceType:this.serviceTypeSelected, templateType:this.templateTypeSelected},template:this.template4}; + this.createshow2 = true; + } - this.createData = this.templateTypeSelected == "SOTN" ? data1 : data2; - this.createshow = true; } - // handleCancel(): void { - // console.log('Button cancel clicked!'); - // this.isVisible2 = false; - // } + handleCancel(): void { + console.log('Button cancel clicked!'); + this.isVisible = false; + } - //表格数据 + //tableData tableData = []; pageIndex = 1; pageSize = 10; @@ -160,10 +138,10 @@ export class ServicesListComponent implements OnInit { sortName = null; sortValue = null; getTableData(){ - // 查询参数: customer serviceType 当前页码,每页条数,排序方式 + // params: customer serviceType pageIndex,pageSize,sortName let paramsObj = { - customer:this.customerSelected, - serviceType:this.serviceTypeSelected, + customer:this.customerSelected.id, + serviceType:this.serviceTypeSelected.name, pageIndex:this.pageIndex, pageSize:this.pageSize, serviceIdSort:this.sortValue @@ -194,119 +172,54 @@ export class ServicesListComponent implements OnInit { 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); + stopService(data){ - console.log(this.tableData2) - },(err)=>{ - console.log(err); - }) } + restartService(data){ - // 显示详情 + } + // detailshow = false; detailData:Object; - showDetail(service){ + serviceDetail(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; + + service.childServiceInstances.forEach((item)=>{ + if(item.serviceDomain=="SITE"){ + service.siteSer.push(item); + }else if(item.serviceDomain=="SDWAN"){ + service.sdwanSer.push(item); } }) this.detailshow = true; this.detailData = service; console.log(service); } - // 删除 确认模态框 - deleteInstace(service){ - // 创建确认框 + // deleteService(){ + // console.log("deleteService!"); + // } + + + // + deleteService(service){ this.modalService.confirm({ nzTitle : 'Are you sure delete this instance?', - nzContent : `Instance ID: <b class="deleteModelContent"> ${service.sotnvpnSer["service-instance-id"]}</b>`, + nzContent : `Instance ID: <b class="deleteModelContent"> ${service["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 allprogress = {}; // + let querypros = []; // + service.rate = 0; + service.status = "Deleting"; + + service["childServiceInstances"].push({"service-instance-id":service["service-instance-id"]}) + + let deletePros = service["childServiceInstances"].map((item)=>{ let params = { globalSubscriberId:this.customerSelected.id, serviceType:this.serviceTypeSelected, @@ -319,7 +232,7 @@ export class ServicesListComponent implements OnInit { let updata = (prodata)=>{ allprogress[prodata.operationId] = prodata.progress; let average = ((arr)=>{return eval(arr.join("+"))/arr.length})(Object.values(allprogress)); - service.sotnvpnSer["rate"]=average; + service["rate"]=average; } querypros.push(this.queryProgress(obj,updata)); res(); @@ -330,11 +243,16 @@ export class ServicesListComponent implements OnInit { Promise.all(deletePros).then(()=>{ Promise.all(querypros).then((data)=>{ console.log(data); - service.sotnvpnSer.rate = 100; - service.sotnvpnSer.status = "deleted"; - setTimeout(()=>{ - this.getTableData(); - },1000) + service.rate = 100; + service.status = "completed"; + let hasUndone = this.tableData.some((item)=>{ + return item.rate < 100; + }) + if(!hasUndone){ + setTimeout(()=>{ + this.getTableData(); + },1000) + } }) }) @@ -344,35 +262,34 @@ export class ServicesListComponent implements OnInit { }); } - + //ccvpn sotn createservice + parentServiceInstanceId=""; closeCreate(obj){ if(!obj){ - this.createshow = false; //关闭创建窗口 + this.createshow = false; //close return false; } - this.createshow = 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)=>{ + let newData; //Newly created service data for the main table + let stageNum = 0; //Different stages of progress, used to add up subsequent service progress; + + let createParams = "?customerId="+this.customerSelected.id + + "&serviceType="+this.serviceTypeSelected.name + + "&serviceDomain="+this.templateTypeSelected + + "&parentServiceInstanceId="; + this.createService(obj.vpnbody,createParams).then((data)=>{ console.log(data) - newData = { //主表格中新创建的服务数据 + this.parentServiceInstanceId = data["serviceId"]; //------------updata parentServiceInstanceId + newData = { // 'service-instance-id':data["serviceId"], 'service-instance-name':obj.vpnbody.service.name, - description:obj.vpnbody.service.description, - status:"creating", + serviceDomain:this.templateTypeSelected, + childServiceInstances:[], + status:"Creating", rate:0, } - this.tableData2 = [{sotnvpnSer:newData},...this.tableData2]; + this.tableData = [newData,...this.tableData]; let updata = (prodata)=>{ newData.rate = Math.floor(prodata.progress/3); } @@ -380,11 +297,17 @@ export class ServicesListComponent implements OnInit { 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)=>{ + stageNum = newData.rate; //Phase progress value update; + let allprogress = {}; // + let querypros = []; //All the query + // Additional parameters + let createParams = "?customerId="+this.customerSelected.id + + "&serviceType="+this.serviceTypeSelected.name + + "&serviceDomain="+"SDWAN" + + "&parentServiceInstanceId="+this.parentServiceInstanceId; + + let createPros = obj.groupbody.map((group)=>{ // + return this.createService(group,createParams).then((data)=>{ console.log(data); let updata = (prodata)=>{ allprogress[prodata.operationId] = prodata.progress; @@ -397,7 +320,7 @@ export class ServicesListComponent implements OnInit { }) return new Promise((res)=>{ - Promise.all(createPros).then(()=>{ //所有创建好之后querypros中查询进度才全都添加完毕 + Promise.all(createPros).then(()=>{ //All queries in querypros are added only once created Promise.all(querypros).then((data)=>{ console.log(data); res("site--begin"); @@ -406,11 +329,16 @@ export class ServicesListComponent implements OnInit { }) }).then((data)=>{ console.log(data); - stageNum = newData.rate; //阶段进度值更新; + stageNum = newData.rate; //Phase progress value update; let allprogress = {}; - let querypros = []; //所有查询 - let createPros = obj.sitebody.map((group)=>{ //所有创建 - return this.createService(group).then((data)=>{ + let querypros = []; //All the query + // Additional parameters + let createParams = "?customerId="+this.customerSelected.id + + "&serviceType="+this.serviceTypeSelected.name + + "&serviceDomain="+"SITE" + + "&parentServiceInstanceId="+this.parentServiceInstanceId; + let createPros = obj.sitebody.map((group)=>{ + return this.createService(group,createParams).then((data)=>{ console.log(data); let updata = (prodata)=>{ allprogress[prodata.operationId] = prodata.progress; @@ -422,23 +350,125 @@ export class ServicesListComponent implements OnInit { }) }) console.log(createPros); - Promise.all(createPros).then(()=>{ //所有创建好之后querypros中查询进度才全都添加完毕 + Promise.all(createPros).then(()=>{ // Promise.all(querypros).then((data)=>{ console.log(data); newData.rate = 100; newData.status = "completed"; - setTimeout(()=>{ - this.getTableData(); - },1000) + let hasUndone = this.tableData.some((item)=>{ + return item.rate < 100; + }) + if(!hasUndone){ + setTimeout(()=>{ + this.getTableData(); + },1000) + } }) }) }) } - createService(params){ + e2eCloseCreate(obj){ + if(!obj){ + this.createshow2 = false; // + return false; + } + this.createshow2 = false; // + console.log(obj); + let newData; // + let createParams = "?customerId="+this.customerSelected.id + + "&serviceType="+this.serviceTypeSelected.name + + "&serviceDomain="+this.templateTypeSelected + + "&parentServiceInstanceId="; + this.createService(obj,createParams).then((data)=>{ + console.log(data); + newData = { // + 'service-instance-id':data["serviceId"], + 'service-instance-name':obj.name, + serviceDomain:this.templateTypeSelected, + childServiceInstances:[], + status:"Creating", + rate:0, + } + + this.tableData = [newData,...this.tableData]; + let updata = (prodata)=>{ + newData.rate = prodata.progress; + } + let queryParams = {serviceId:data["serviceId"],operationId:data["operationId"]}; + return this.queryProgress(queryParams,updata); + }).then((data)=>{ + console.log(data); + newData.rate = 100; + newData.status = "completed"; + let hasUndone = this.tableData.some((item)=>{ + return item.rate < 100; + }) + if(!hasUndone){ + setTimeout(()=>{ + this.getTableData(); + },1000) + } + }) + + } + + nsCloseCreate(obj){ + if(!obj){ + this.createshow2 = false; // + return false; + } + this.createshow2 = false; // + console.log(obj); + let newData; // + // step1 + this.myhttp.nsCreateInstance(obj.step1) + .subscribe((data)=>{ + console.log(data); + newData = { // + 'service-instance-id':data.nsInstanceId, + 'service-instance-name':obj.step1.nsName, + serviceDomain:this.templateTypeSelected, + childServiceInstances:[], + status:"Creating", + rate:0, + } + this.tableData = [newData,...this.tableData]; + let createParams = "?ns_instance_id=" + data.nsInstanceId + + "&customerId="+this.customerSelected.id + + "&serviceType="+this.serviceTypeSelected.name + + "&serviceDomain="+"SITE" + + "&parentServiceInstanceId="+this.parentServiceInstanceId; + // step2 + this.createNsService(createParams,obj.step2).then((jobid)=>{ + + let updata = (prodata)=>{ + newData.rate = prodata.responseDescriptor.progress; + } + + return this.queryNsProgress(jobid,updata); + }).then((data)=>{ + console.log(data); + newData.rate = 100; + newData.status = "completed"; + let hasUndone = this.tableData.some((item)=>{ + return item.rate < 100; + }) + if(!hasUndone){ + setTimeout(()=>{ + this.getTableData(); + },1000) + } + }) + + + }) + } + + createService(requestBody,createParams){ let mypromise = new Promise((res,rej)=>{ - this.myhttp.createInstance(params) + this.myhttp.createInstance(requestBody,createParams) .subscribe((data)=>{ res(data.service); @@ -446,6 +476,15 @@ export class ServicesListComponent implements OnInit { }) return mypromise; } + createNsService(id,obj){ + let mypromise = new Promise((res,rej)=>{ + this.myhttp.nsCreateInstance2(id,obj) + .subscribe((data)=>{ + res(data.jobId); + }) + }) + return mypromise; + } queryProgress(obj,callback){ let mypromise = new Promise((res,rej)=>{ @@ -497,9 +536,65 @@ export class ServicesListComponent implements OnInit { }) return mypromise; } + queryNsProgress(jobid,callback){ + let mypromise = new Promise((res,rej)=>{ + // let data = { + // "jobId": "string", + // "responseDescriptor": { + // "status": "string", + // "progress": 0, + // "statusDescription": "string", + // "errorCode": "string", + // "responseId": "string", + // "responseHistoryList": [ + // { + // "status": "string", + // "progress": "string", + // "statusDescription": "string", + // "errorCode": "string", + // "responseId": "string" + // } + // ] + // } + // } + let requery = (responseId)=>{ + this.myhttp.getNsProgress(jobid,responseId) + .subscribe((data)=>{ + if(data.responseDescriptor.progress==undefined){ + console.log(data); + setTimeout(()=>{ + requery(data.responseDescriptor.responseId); + },5000) + return false; + } + if(data.responseDescriptor.progress < 100){ + callback(data); + setTimeout(()=>{ + requery(data.responseDescriptor.responseId); + },5000) + }else { + res(data); + } + }) + // setTimeout(()=>{ + // console.log(data.responseDescriptor.progress) + // data.responseDescriptor.progress++; + // if(data.responseDescriptor.progress<100){ + // callback(data); + // requery(data.responseDescriptor.responseId) + // }else{ + // callback(data); + // res(data) + // } + // },100) + } + requery(0); + }) + return mypromise; + } - // 名字转换参数匹配 --> 传给子组件用 + // --> namesTranslate:Object; inputNamests(){ this.myhttp.inputNamesTransform() |