diff options
author | cyuamber <xuranyjy@chinamobile.com> | 2019-08-22 16:55:57 +0800 |
---|---|---|
committer | cyuamber <xuranyjy@chinamobile.com> | 2019-08-22 16:56:09 +0800 |
commit | d0f5347dc16b5aa9fc95eb520fbc9a1c7b672b09 (patch) | |
tree | b3891d8de290d755d7f0f00d35bb77d3b89ad747 /usecaseui-portal/src/app/views/services | |
parent | 56923755c761897cc86ca2457667fcc3e6a0e43f (diff) |
feat: change the project structure and add mock data function
Change-Id: I381845bff5eb37d1fab3eba8cf1ae7838df523b7
Issue-ID: USECASEUI-307
Signed-off-by: cyuamber <xuranyjy@chinamobile.com>
Diffstat (limited to 'usecaseui-portal/src/app/views/services')
14 files changed, 4038 insertions, 0 deletions
diff --git a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.css b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.css new file mode 100644 index 00000000..4e80750c --- /dev/null +++ b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.css @@ -0,0 +1,67 @@ +/* + Copyright (C) 2019 CMCC, Inc. and others. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +.title { + font: 700 18px/18px "思源黑体"; + color: #4c5e70; + margin-bottom: 18px; +} +hr { + border: none; + height: 2px; + background-color: #dce1e7; + margin-bottom: 20px; +} +.list { + background-color: #fff; + border-radius: 5px; + padding: 10px; +} +.list nz-table tbody td span.onboarding { + font-size: 12px; + color: #147dc2; +} +.list nz-table tbody td span.onboarded { + font-size: 14px; + color: #147dc2; +} +.list nz-table tbody td span.updating { + font-size: 12px; + color: blue; +} +.list nz-table tbody td span.deleting { + font-size: 12px; + color: red; +} +.list nz-table tbody td span.invalid { + font-size: 14px; + color: purple; +} +.list nz-table tbody td i.anticon { + cursor: pointer; + font-size: 18px; + padding: 2px; +} +.list nz-table tbody td i.anticon:hover { + color: #147dc2; +} +.list nz-table tbody td .cannotclick { + pointer-events: none; + color: #aaa; + opacity: 0.6; +} +.list nz-table tbody td .fileIcon{ + display: none; +}
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.html b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.html new file mode 100644 index 00000000..70ee81c0 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.html @@ -0,0 +1,333 @@ +<!-- + Copyright (C) 2019 CMCC, Inc. and others. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<nz-tabset [nzTabPosition]="'top'" [nzType]="'card'"> + <nz-tab *ngFor="let tab of tabs" [nzTitle]="tab" (nzClick)="handleTabChange(tab)"> + <!-- nsList --> + <div class="list" *ngIf="tab === 'NS'"> + <!-- <h3 class="title"> Onboard {{tabTitle}} </h3> --> + <div style="width:100%;height: 30%;margin-bottom: 1%"> + <div class="listupload"> + <nz-upload nzType="drag" [(nzFileList)]="fileListNS" [nzBeforeUpload]="beforeUploadNS"> + <p class="ant-upload-drag-icon"> + <i nz-icon type="inbox" class="anticon anticon-inbox"></i> + </p> + <p class="ant-upload-text"> {{"i18nTextDefine_Click_CSAR_File" | translate}} </p> + <p class="ant-upload-hint"></p> + </nz-upload> + <button nz-button [nzLoading]="nsuploading" (click)="onClick(tab)" [disabled]="fileListNS.length == 0" + style="margin-top: 16px;margin-left: 55px;color: #FFFFFF;font-size: 13px;background-color: #3E9BFF;font-family: ArialMT;"> + {{ nsuploading ? 'Uploading' : 'Start Upload' }} + </button> + </div> + <div class="listlin"></div> + <div class="listfile"> + <div style="color: rgba(66,84,143,1);font-family:ArialMT;padding-bottom: 15px;height: 15%"> {{"i18nTextDefine_Uploaded_files" | translate}} </div> + <div class="nouploadfile">{{"i18nTextDefine_Nofileuploading" | translate}}</div> + <div style="height:80%;overflow: auto"> + <div class="listfilebgc" *ngFor="let itemns of nsRightList"> + <div> + <i class="anticon anticon-link"></i> + </div> + <div class="color" [ngClass]="{'progress':itemns.status == true}">{{itemns.name}}</div> + <div class="color" *ngIf="itemns.status"> + <nz-progress [nzPercent]="itemns.progress" [nzShowInfo]="false"></nz-progress> + </div> + <div class="color" *ngIf="!itemns.status"> + <span *ngIf="itemns.success == 0">{{"i18nTextDefine_File_upload_completed" | translate}}</span> + <span *ngIf="itemns.success == 1">{{"i18nTextDefine_File_upload_failed" | translate}}</span> + </div> + <div *ngIf="!itemns.status"> + <i class="anticon anticon-check-circle" *ngIf="itemns.success == 0" style="color:#7BC7F3!important;"></i> + <i class="anticon anticon-exclamation-circle" *ngIf="itemns.success == 1" style="color:#fb5c5c!important;"></i> + </div> + </div> + </div> + </div> + </div> + <nz-spin [nzSpinning]="isSpinning" style="height: 69%"> + <div class="mask" *ngIf="isSpinning"></div> + <nz-table #nzTable [nzData]="nstableData" nzShowSizeChanger [nzFrontPagination]="true" + [nzShowQuickJumper]="true" [nzPageSizeOptions]="[5,10,15,20]" [nzTotal]='total' [(nzPageSize)]="nspageSize" + [(nzPageIndex)]='nspageIndex' [nzLoading]="loading" nzSize="middle"> + <thead (nzSortChange)="sort($event)" nzSingleSort> + <tr> + <th nzWidth="15%"> {{"i18nTextDefine_NO" | translate}} </th> + <th nzWidth="15%" nzShowSort nzSortKey="name"> {{"i18nTextDefine_Name" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_Version" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_OnboardingState" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_OperationalState" | translate}} </th> + <th nzWidth="10%"> {{"i18nTextDefine_UsageState" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_Operationbutton" | translate}} </th> + </tr> + </thead> + <tbody> + <tr *ngFor="let item of nzTable.data; let i = index; "> + <td>{{i+1}}</td> + <!--<td *ngIf="item.uuid">{{item.uuid}}</td>--> + + <td *ngIf="item.nsdName">{{item.nsdName}}</td> + <td *ngIf="item.nsdName === null || item.nsdName === ''"> </td> + <td *ngIf="item.name">{{item.name}}</td> + <td *ngIf="item.name===null || item.name=== ''"> </td> + <td *ngIf="item.nsdVersion">{{item.nsdVersion}}</td> + <td *ngIf="item.nsdVersion === null || item.nsdVersion === ''"> </td> + <td *ngIf="item.version">{{item.version}}</td> + <td *ngIf="item.version === null || item.version === ''"> </td> + <td> + <span *ngIf="item.nsdOnboardingState">{{item.nsdOnboardingState}}</span> + <span *ngIf="item.nsdOnboardingState === null || item.nsdOnboardingState === ''"> </span> + <span *ngIf="item.uuid">{{status}}</span> + + <!-- <span *ngIf="item.uuid" [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', + 'scaling':data.status=='Scaling','healing':data.status=='Healing'}">{{data.status || "Active"}}</span> + <nz-progress *ngIf="item.uuid" *ngIf="data.status == 'Creating' || data.status == 'Deleting' || data.status == 'Scaling' || data.status == 'Healing' " [nzPercent]="data.rate"></nz-progress> --> + </td> + <td>{{item.nsdOperationalState}}</td> + <td>{{item.nsdUsageState}}</td> + <td> + <i [ngClass]="{'cannotclick':onboardData.status == 'onboarding' && i == currentIndex}" + class="anticon anticon-upload upicon" #upload_icon (click)="updataNsService(item.uuid,i,notificationModel)" + *ngIf="item.uuid"></i> + <i class="anticon anticon-delete" nzType="info" (click)="showConfirm(i,item.id,tab,notificationModel)" + *ngIf="item.id"></i> + <!--<span *ngIf="item.id" [ngClass]="{'fileIcon':OnboardFile == 'disNone'}">--> + <!--<span *ngIf="item.id && item.sameid == undefined">--> + <!--<nz-upload [(nzFileList)]="fileList" [nzBeforeUpload]="beforeUpload">--> + <!--<i class="anticon anticon-file" type="upload" (click)="onClickId(item.id,tab)"></i>--> + <!--</nz-upload>--> + <!--<button nz-button [nzLoading]="nsuploading" (click)="onClick(tab)" [disabled]="fileList.length == 0"--> + <!--style="margin-top: 16px" *ngIf="item.id==nsdInfoId">--> + <!--{{ nsuploading ? 'Uploading' : 'Start Upload' }}--> + <!--</button>--> + <!--</span>--> + + </td> + </tr> + </tbody> + </nz-table> + </nz-spin> + <!-- <div style="margin-top:8px;"> + Loading state: + <nz-switch [(ngModel)]="isSpinning"></nz-switch> + </div> --> + + </div> + <!-- VNFList --> + <div class="list" *ngIf="tab === 'VNF'"> + <!-- <h3 class="title"> Onboard {{tabTitle}} </h3> --> + <div style="width:100%;height: 30%;margin-bottom: 1%"> + <div class="listupload"> + <nz-upload nzType="drag" [(nzFileList)]="fileListVNF" [nzBeforeUpload]="beforeUploadVNF"> + <p class="ant-upload-drag-icon"> + <i nz-icon type="inbox" class="anticon anticon-inbox"></i> + </p> + <p class="ant-upload-text">Click or drag CSAR File here</p> + <p class="ant-upload-hint"></p> + </nz-upload> + <button nz-button [nzLoading]="vnfuploading" (click)="onClick(tab)" [disabled]="fileListVNF.length == 0" + style="margin-top: 16px;margin-left: 55px;color: #FFFFFF;font-size: 13px;background-color: #3E9BFF;font-family: ArialMT;"> + {{ vnfuploading ? 'Uploading' : 'Start Upload' }} + </button> + </div> + <div class="listlin"></div> + <div class="listfile"> + <div style="color: rgba(66,84,143,1);font-family:ArialMT;padding-bottom: 15px;height: 15%"> {{"i18nTextDefine_Uploaded_files" | translate}} </div> + <div class="nouploadfile">{{"i18nTextDefine_Nofileuploading" | translate}}</div> + <div style="height:80%;overflow: auto"> + <div class="listfilebgc" *ngFor="let itemns of vnfRightList"> + <div> + <i class="anticon anticon-link"></i> + </div> + <div class="color" [ngClass]="{'progress':itemns.status == true}">{{itemns.name}}</div> + <div class="color" *ngIf="itemns.status"> + <nz-progress [nzPercent]="itemns.progress" [nzShowInfo]="false"></nz-progress> + </div> + <div class="color" *ngIf="!itemns.status"> + <span *ngIf="itemns.success == 0">{{"i18nTextDefine_File_upload_completed" | translate}}</span> + <span *ngIf="itemns.success == 1">{{"i18nTextDefine_File_upload_failed" | translate}}</span> + </div> + <div *ngIf="!itemns.status"> + <i class="anticon anticon-check-circle" *ngIf="itemns.success == 0" style="color:#7BC7F3!important;"></i> + <i class="anticon anticon-exclamation-circle" *ngIf="itemns.success == 1" style="color:#fb5c5c!important;"></i> + </div> + </div> + </div> + </div> + </div> + <nz-spin [nzSpinning]="isSpinning" style="height: 69%"> + <div class="mask" *ngIf="isSpinning"></div> + <nz-table #nzTable [nzData]="vnftableData" nzShowSizeChanger [nzFrontPagination]="true" + [nzShowQuickJumper]="true" [nzPageSizeOptions]="[5,10,15,20]" [nzTotal]='total' [(nzPageSize)]="vnfpageSize" + [(nzPageIndex)]='vnfpageIndex' [nzLoading]="loading" nzSize="middle"> + <thead (nzSortChange)="sort($event)" nzSingleSort> + <tr> + <th nzWidth="15%"> {{"i18nTextDefine_NO" | translate}} </th> + <th nzWidth="15%" nzShowSort nzSortKey="name"> {{"i18nTextDefine_Name" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_Version" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_OnboardingState" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_OperationalState" | translate}} </th> + <th nzWidth="10%"> {{"i18nTextDefine_UsageState" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_Operationbutton" | translate}} </th> + </tr> + </thead> + <tbody> + <tr *ngFor="let item of nzTable.data; let i = index; "> + <td>{{i+1}}</td> + <!--<td *ngIf="item.uuid">{{item.uuid}}</td>--> + <td *ngIf="item.vnfProductName">{{item.vnfProductName}}</td> + <td *ngIf="item.vnfProductName === null || item.vnfProductName === ''"> </td> + <td *ngIf="item.name">{{item.name}}</td> + <td *ngIf="item.vnfdVersion">{{item.vnfdVersion}}</td> + <td *ngIf="item.vnfdVersion === null || item.vnfdVersion === ''"> </td> + <td *ngIf="item.version">{{item.version}}</td> + <td>{{item.onboardingState}}</td> + <td>{{item.operationalState}}</td> + <td>{{item.usageState}}</td> + <td> + <i [ngClass]="{'cannotclick':onboardData.status == 'onboarding' && i == currentIndex}" + class="anticon anticon-upload upicon" #upload_icon (click)="updataVnfService(item.uuid,i,notificationModel)" + *ngIf="item.uuid"></i> + <i class="anticon anticon-delete" nzType="info" (click)="showConfirm(i,item.id,tab,notificationModel)" + *ngIf="item.id"></i> + <!--<span *ngIf="item.id && item.sameid == undefined">--> + <!--<nz-upload [(nzFileList)]="fileList" [nzBeforeUpload]="beforeUpload">--> + <!--<!– <button nz-button> –>--> + <!--<i class="anticon anticon-file" type="upload" (click)="onClickId(item.id,tab)"></i>--> + <!--<!– <span >upload</span> –>--> + <!--<!– </button> –>--> + + <!--</nz-upload>--> + <!--<button nz-button [nzLoading]="nsuploading" (click)="onClick(tab)" [disabled]="fileList.length == 0"--> + <!--style="margin-top: 16px;margin-left: 55px;color: #FFFFFF;font-size: 13px;background-color: #3E9BFF;font-family: ArialMT;"--> + <!--*ngIf="item.id==vnfPkgId">--> + <!--{{ nsuploading ? 'Uploading' : 'Start Upload' }}--> + <!--</button>--> + <!--</span>--> + </td> + </tr> + </tbody> + </nz-table> + </nz-spin> + + </div> + <!-- PNFList --> + <div class="list" *ngIf="tab === 'PNF'"> + <!-- <h3 class="title"> Onboard {{tabTitle}} </h3> --> + <div style="width:100%;height: 30%;margin-bottom: 1%"> + <div class="listupload"> + <nz-upload nzType="drag" [(nzFileList)]="fileListPNF" [nzBeforeUpload]="beforeUploadPNF"> + <p class="ant-upload-drag-icon"> + <i nz-icon type="inbox" class="anticon anticon-inbox"></i> + </p> + <p class="ant-upload-text">Click or drag CSAR File here</p> + <p class="ant-upload-hint"></p> + </nz-upload> + <button nz-button [nzLoading]="pnfuploading" (click)="onClick(tab)" [disabled]="fileListPNF.length == 0" + style="margin-top: 16px;margin-left: 55px;color: #FFFFFF;font-size: 13px;background-color: #3E9BFF;font-family: ArialMT;"> + {{ pnfuploading ? 'Uploading' : 'Start Upload' }} + </button> + </div> + <div class="listlin"></div> + <div class="listfile"> + <div style="color: rgba(66,84,143,1);font-family:ArialMT;padding-bottom: 15px;height: 15%"> {{"i18nTextDefine_Uploaded_files" | translate}} </div> + <div class="nouploadfile">{{"i18nTextDefine_Nofileuploading" | translate}}</div> + <div style="height:80%;overflow: auto"> + <div class="listfilebgc" *ngFor="let itemns of pnfRightList"> + <div> + <i class="anticon anticon-link"></i> + </div> + <div class="color" [ngClass]="{'progress':itemns.status == true}">{{itemns.name}}</div> + <div class="color" *ngIf="itemns.status"> + <nz-progress [nzPercent]="itemns.progress" [nzShowInfo]="false"></nz-progress> + </div> + <div class="color" *ngIf="!itemns.status"> + <span *ngIf="itemns.success == 0">{{"i18nTextDefine_File_upload_completed" | translate}}</span> + <span *ngIf="itemns.success == 1">{{"i18nTextDefine_File_upload_failed" | translate}}</span> + </div> + <div *ngIf="!itemns.status"> + <i class="anticon anticon-check-circle" *ngIf="itemns.success == 0" style="color:#7BC7F3!important;"></i> + <i class="anticon anticon-exclamation-circle" *ngIf="itemns.success == 1" style="color:#fb5c5c!important;"></i> + </div> + </div> + </div> + </div> + </div> + <nz-spin [nzSpinning]="isSpinning" style="height: 69%"> + <div class="mask" *ngIf="isSpinning"></div> + <nz-table #nzTable [nzData]="pnftableData" nzShowSizeChanger [nzFrontPagination]="true" + [nzShowQuickJumper]="true" [nzPageSizeOptions]="[5,10,15,20]" [nzTotal]='total' [(nzPageSize)]="pnfpageSize" + [(nzPageIndex)]='pnfpageIndex' [nzLoading]="loading" nzSize="middle"> + <thead (nzSortChange)="sort($event)" nzSingleSort> + <tr> + <th nzWidth="15%"> {{"i18nTextDefine_NO" | translate}} </th> + <th nzWidth="15%" nzShowSort nzSortKey="name"> {{"i18nTextDefine_Name" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_Version" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_OnboardingState" | translate}} </th> + <th nzWidth="10%"> {{"i18nTextDefine_UsageState" | translate}} </th> + <th nzWidth="15%"> {{"i18nTextDefine_Operationbutton" | translate}} </th> + </tr> + </thead> + <tbody> + <tr *ngFor="let item of nzTable.data; let i = index; "> + <td>{{i+1}}</td> + <td>{{item.pnfdName}}</td> + <td>{{item.pnfdVersion}}</td> + <td>{{item.pnfdOnboardingState}}</td> + <td>{{item.pnfdUsageState}}</td> + <td> + <i class="anticon anticon-delete" nzType="info" (click)="showConfirm(i,item.id,tab,notificationModel)"></i> + <!--<span *ngIf="item.id" [ngClass]="{'fileIcon':OnboardFile == 'disNone'}">--> + <!--<nz-upload [(nzFileList)]="fileList" [nzBeforeUpload]="beforeUpload">--> + <!--<i class="anticon anticon-file" type="upload" (click)="onClickId(item.id,tab)"></i>--> + <!--</nz-upload>--> + <!--<button nz-button [nzLoading]="nsuploading" (click)="onClick(tab)" [disabled]="fileList.length == 0"--> + <!--style="margin-top: 16px;margin-left: 55px;color: #FFFFFF;font-size: 13px;background-color: #3E9BFF;font-family: ArialMT;"--> + <!--*ngIf="item.id==vnfPkgId">--> + <!--{{ nsuploading ? 'Uploading' : 'Start Upload' }}--> + <!--</button>--> + <!--</span>--> + </td> + </tr> + </tbody> + </nz-table> + </nz-spin> + + </div> + </nz-tab> + <!--2019.08.14 add notification--> + <ng-template #notificationModel > + <div class="ant-notification-notice-content"> + <div class="ant-notification-notice-with-icon"> + <span class="ant-notification-notice-icon"> + <img src="{{notificationAttributes.imgPath}}" alt="{{notificationAttributes.status}}"> + </span> + <div class="ant-notification-notice-message"> + {{notificationAttributes.title}} + {{"i18nTextDefine_"+notificationAttributes.action | translate}} {{"i18nTextDefine_"+notificationAttributes.status | translate}} + </div> + <div class="ant-notification-notice-description"> + <div class="notificationlist"> + <p>{{notificationAttributes.title}} id: </p> + <span>{{ notificationAttributes.id }}</span> + </div> + </div> + <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> + </div> + </div> + </ng-template> +</nz-tabset> + diff --git a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.less b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.less new file mode 100644 index 00000000..c31409c9 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.less @@ -0,0 +1,182 @@ +/* + Copyright (C) 2019 CMCC, Inc. and others. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +.title { + font: 700 18px/18px "思源黑体"; + color: #4c5e70; + margin-bottom: 18px; +} +hr { + border: none; + height: 2px; + background-color: #dce1e7; + margin-bottom: 20px; +} +.switch_btn { + position: absolute; + right: 6%; + top: 18px; + border: 1px solid #3fa8eb; + width: 8%; + border-radius: 10px; + margin-bottom: 18px; + span { + display: block; + float: left; + text-align: center; + width: 50%; + color: #3fa8eb; + font-weight: 700; + cursor: pointer; + } + span:first-child { + border-radius: 10px 0 0 10px; + } + span:last-child { + border-radius: 0 10px 10px 0; + } + span.left_b { + border-left: 1px solid #3fa8eb; + } + span.active { + color: #fff; + background: #3fa8eb; + } +} + +.list { + // background-color: #fff; + border-radius: 5px; + // padding: 10px; + .listupload { + width: 22%; + vertical-align: top; + display: inline-block; + margin-left: 13%; + } + .listlin { + vertical-align: top; + display: inline-block; + width: 1%; + margin-left: 10%; + height: 177px; + margin-bottom: 30px; + border-right: 2px solid #EEEEEE; + } + .listfile { + width: 43%; + height: 100%; + vertical-align: top; + display: inline-block; + margin-left: 10%; + .nouploadfile{ + height: 80%; + width: 100%; + text-align: center; + font-size: 22px; + margin-top: 5%; + } + .listfilebgc { + background-color: #fff; + border-bottom: 8px solid #F7F8FC; + } + .listfilebgc { + background-color: #fff; + height: 30px; + border-radius: 2px; + line-height: 2; + color: #42548F; + border-bottom: 4px solid #F7F8FC; + >div { + float: left; + } + :first-child { + width: 6%; + margin-left: 5px; + } + :nth-child(2){ + width:20%; + } + :nth-child(3){ + width: 60%; + text-align: center; + } + :nth-child(4){ + padding-left: 4%; + } + .color { + color:rgba(66,84,143,1); + span{ + color:rgba(66,84,143,0.7); + } + } + .progress{ + color:rgba(66,84,143,0.7); + } + } + } + nz-table { + tbody { + td { + span.onboarding { + font-size: 12px; + color: #147dc2; + } + span.onboarded { + font-size: 14px; + color: #147dc2; + } + span.updating { + font-size: 12px; + color: blue; + } + span.deleting { + font-size: 12px; + color: red; + } + span.invalid { + font-size: 14px; + color: purple; + } + i.anticon { + cursor: pointer; + font-size: 18px; + padding: 2px; + &:hover{ + color: #147dc2; + } + } + .cannotclick { + pointer-events: none; + color: #aaa; + opacity: 0.6; + } + .fileIcon{ + display: none; + } + } + } + } +} +.mask { + top: 0; + left: 0; + position: fixed; + width: 100%; + height: 100%; + opacity: 0.1; + background: black; + z-index: 1049; +}
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.spec.ts b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.spec.ts new file mode 100644 index 00000000..0e49f656 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { OnboardVnfVmComponent } from './onboard-vnf-vm.component'; + +describe('OnboardVnfVmComponent', () => { + let component: OnboardVnfVmComponent; + let fixture: ComponentFixture<OnboardVnfVmComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ OnboardVnfVmComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(OnboardVnfVmComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.ts b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.ts new file mode 100644 index 00000000..4899aed8 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.ts @@ -0,0 +1,668 @@ +/* + Copyright (C) 2019 CMCC, Inc. and others. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +import { HttpClient, HttpRequest, HttpResponse } from '@angular/common/http'; +import { Component, OnInit, HostBinding, TemplateRef } from '@angular/core'; +import { NzNotificationService } from 'ng-zorro-antd'; +// import { MyhttpService } from '../../myhttp.service'; +import { onboardService } from '../../../core/services/onboard.service'; +import { slideToRight } from '../../../animates'; +import { NzMessageService, UploadFile, NzModalRef, NzModalService } from 'ng-zorro-antd'; +import { filter } from 'rxjs/operators'; +import { Title } from '@angular/platform-browser'; + +@Component({ + selector: 'app-onboard-vnf-vm', + templateUrl: './onboard-vnf-vm.component.html', + styleUrls: ['./onboard-vnf-vm.component.less'], + animations: [slideToRight] +}) +export class OnboardVnfVmComponent implements OnInit { + @HostBinding('@routerAnimate') routerAnimateState; + + // delete Modal + confirmModal: NzModalRef; + nsdInfoId = ''; + vnfPkgId = ''; + pnfdInfoId = ''; + tabTitle = "NS"; + nsuploading = false; + vnfuploading = false; + pnfloading = false; + fileList: UploadFile[] = []; + fileListNS: UploadFile[] = []; + fileListVNF: UploadFile[] = []; + fileListPNF: UploadFile[] = []; + // onboard initial value + status = "Onboard Available"; + jobId = ''; + //url + url = { + // line up + ns: '/api/nsd/v1/ns_descriptors/*_*/nsd_content', + vnf: '/api/vnfpkgm/v1/vnf_packages/*_*/package_content', + pnf: '/api/nsd/v1/pnf_descriptors/*_*/pnfd_content' + // line local + //ns: 'https://jsonplaceholder.typicode.com/posts/', + //vnf: 'https://jsonplaceholder.typicode.com/posts/', + //pnf: 'https://jsonplaceholder.typicode.com/posts/', + }; + constructor( + private myhttp: onboardService, + private http: HttpClient, + private msg: NzMessageService, + private titleService: Title, + private modal: NzModalService, + private modalService: NzModalService, + private notification: NzNotificationService + ) { } + //default Call ns data by default + ngOnInit() { + this.getTableData(); + } + + //Tabular data + nstableData: any; + vnftableData: any; + pnftableData: any; + nssdcData: any; + nsvfcData: any; + + vnfsdcData: any; + vnfvfcData: any; + nspageIndex = 1; + nspageSize = 10; + vnfpageIndex = 1; + vnfpageSize = 10; + pnfpageIndex = 1; + pnfpageSize = 10; + total; + nsloading = false; + sortName = null; + sortValue = null; + tabs = ['NS', 'VNF', 'PNF']; + isSpinning = false; + + //2019.08.14 add + notificationAttributes = { + "title": this.tabs[0], + "imgPath": "../../../../assets/images/execute-inproess.png", + "action": "OnboardingState", + "status": "InProgress", + "id": null + }; + notificationModelShow(template: TemplateRef<{}>): void { + this.notification.template(template); + } + notificationSuccess(notificationModel) { + this.notificationAttributes.imgPath = "../../../../assets/images/execute-success.png"; + this.notificationAttributes.status = "Success"; + this.notificationModelShow(notificationModel); + } + notificationFailed(notificationModel) { + this.notificationAttributes.imgPath = "../../../../assets/images/execute-faild.png"; + this.notificationAttributes.status = "Failed"; + this.notificationModelShow(notificationModel); + } + // Handling tab switching request data + handleTabChange(tab) { + this.tabTitle = tab; + switch (tab) { + case 'NS': + this.nstableData = []; + this.getTableData(); + this.fileList = []; //Empty uploaded files when switching + break + case 'VNF': + this.vnftableData = []; + this.getTableVnfData() + this.fileList = []; + break + case 'PNF': + this.pnftableData = []; + this.getTablePnfData() + this.fileList = []; + break + } + } + + + //before put create--Drag and drop files to the page before uploading + requestBody = { + "userDefinedData": { + "additionalProp1": "", + "additionalProp2": "", + "additionalProp3": "" + } + } + + //NS/VNF List add file + beforeUpload = (file: UploadFile): boolean => { + this.fileList.push(file); + return false; + } + + // ns beforeUpload + beforeUploadNS = (file: UploadFile): boolean => { + this.fileListNS.push(file); + this.myhttp.getCreatensData("createNetworkServiceData", this.requestBody)//on-line + // this.myhttp.getCreatensData("creatensDataNS") //local + .subscribe((data) => { + this.nsdInfoId = data["id"]; + }, (err) => { + console.log(err); + }) + return false; + } + + //vnf beforeUpload + beforeUploadVNF = (file: UploadFile): boolean => { + this.fileListVNF.push(file); + this.myhttp.getCreatensData("createVnfData", this.requestBody)//on-line + // this.myhttp.getCreatensData("creatensDataVNF") //local + .subscribe((data) => { + this.vnfPkgId = data["id"]; + }, (err) => { + console.log(err); + }) + return false; + } + + // //pnf eforeUpload + beforeUploadPNF = (file: UploadFile): boolean => { + this.fileListPNF.push(file); + this.myhttp.getCreatensData("createPnfData", this.requestBody) //on-line + // this.myhttp.getCreatensData("creatensDataPNF") //local + .subscribe((data) => { + this.pnfdInfoId = data["id"]; + }, (err) => { + console.log(err); + }) + return false; + } + + //Get list list id + onClickId(id, tab) { + switch (tab) { + case 'NS': + this.nsdInfoId = id; + break + case 'VNF': + this.vnfPkgId = id; + break + case 'PNF': + this.pnfdInfoId = id; + break + } + } + + //Drag and drop and click the upload button + onClick(tab) { + switch (tab) { + case 'NS': + // this.handleUpload('/api/nsd/v1/ns_descriptors/'+this.nsdInfoId+'/nsd_content',tab); + this.handleUpload(this.url.ns.replace("*_*", this.nsdInfoId), tab); + this.getTableData(); + break + case 'VNF': + // this.handleUpload('/api/vnfpkgm/v1/vnf_packages/'+this.vnfPkgId+'/package_content',tab); + this.handleUpload(this.url.vnf.replace("*_*", this.vnfPkgId), tab); + this.getTableVnfData() + break + case 'PNF': + // this.handleUpload('/api/nsd/v1/pnf_descriptors/'+this.pnfdInfoId+'/pnfd_content',tab); + this.handleUpload(this.url.pnf.replace("*_*", this.pnfdInfoId), tab); + this.getTablePnfData(); + break + } + } + + nsRightList = []; + nsNum = 0; + vnfRightList = []; + vnfNum = 0; + pnfRightList = []; + pnfNum = 0; + //put Upload Upload + handleUpload(url, tab): void { + const formData = new FormData(); + // tslint:disable-next-line:no-any + switch (tab) { + case "NS": + this.fileListNS.forEach((file: any) => { + formData.append('file', file); + }); + this.nsuploading = true; + let lastNs = this.fileListNS[this.fileListNS.length - 1]; + let nsfile = { + name: lastNs.name, + uid: lastNs.uid, + progress: 0, + status: true, + success: 0 + }; + this.nsNum += 1; + this.nsRightList.push(nsfile); + let requeryNs = (nsfile) => { + setTimeout(() => { + nsfile.progress += 2; + if (nsfile.progress < 100) { + requeryNs(nsfile) + } else { + nsfile.progress = 100; + nsfile.status = false; + } + }, 100) + }; + requeryNs(nsfile); + break + case "VNF": + this.fileListVNF.forEach((file: any) => { + formData.append('file', file); + }); + this.vnfuploading = true; + let lastVnf = this.fileListVNF[this.fileListVNF.length - 1]; + let vnffile = { + name: lastVnf.name, + uid: lastVnf.uid, + progress: 0, + status: true, + success: 0 + }; + this.vnfNum += 1; + this.vnfRightList.push(vnffile); + let requeryVnf = (vnffile) => { + setTimeout(() => { + vnffile.progress += 2; + if (vnffile.progress < 100) { + requeryVnf(vnffile) + } else { + vnffile.progress = 100; + vnffile.status = false; + } + }, 100) + }; + requeryVnf(vnffile); + break + case "PNF": + this.fileListPNF.forEach((file: any) => { + formData.append('file', file); + }); + this.pnfloading = true; + let lastPnf = this.fileListPNF[this.fileListPNF.length - 1]; + let pnffile = { + name: lastPnf.name, + uid: lastPnf.uid, + progress: 0, + status: true, + success: 0 + }; + this.pnfNum += 1; + this.pnfRightList.push(pnffile); + let requeryPnf = (pnffile) => { + setTimeout(() => { + pnffile.progress += 2; + if (pnffile.progress < 100) { + requeryPnf(pnffile) + } else { + pnffile.progress = 100; + pnffile.status = false; + } + }, 100) + }; + requeryPnf(pnffile); + break + } + // line PUT + const req = new HttpRequest('PUT', url, formData, { + reportProgress: true, + withCredentials: true + }); + //Upload pre-empty array + this.fileList = []; + this.fileListNS = []; + this.fileListVNF = []; + this.fileListPNF = []; + this.http.request(req) + .pipe(filter(e => e instanceof HttpResponse)) + .subscribe( + (event: {}) => { + if (tab == "NS") { + this.nsRightList[this.nsNum - 1].progress = 100; + this.nsRightList[this.nsNum - 1].status = false; + this.nsRightList[this.nsNum - 1].success = 0; + } + if (tab == "VNF") { + this.vnfRightList[this.vnfNum - 1].progress = 100; + this.vnfRightList[this.vnfNum - 1].status = false; + this.vnfRightList[this.vnfNum - 1].success = 0; + } + if (tab == "PNF") { + this.pnfRightList[this.pnfNum - 1].progress = 100; + this.pnfRightList[this.pnfNum - 1].status = false; + this.pnfRightList[this.pnfNum - 1].success = 0; + } + this.changeUploadingSta(tab); + this.msg.success('upload successfully.'); + }, + err => { + if (tab == "NS") { + this.nsRightList[this.nsNum - 1].progress = 100; + this.nsRightList[this.nsNum - 1].status = false; + this.nsRightList[this.nsNum - 1].success = 1; + } + if (tab == "VNF") { + this.vnfRightList[this.vnfNum - 1].progress = 100; + this.vnfRightList[this.vnfNum - 1].status = false; + this.vnfRightList[this.vnfNum - 1].success = 1; + } + if (tab == "PNF") { + this.pnfRightList[this.pnfNum - 1].progress = 100; + this.pnfRightList[this.pnfNum - 1].status = false; + this.pnfRightList[this.pnfNum - 1].success = 1; + } + this.changeUploadingSta(tab); + this.msg.error('upload failed.'); + } + ); + } + + // Control the status of uploading + changeUploadingSta(tab) { + switch (tab) { + case "NS": + this.nsuploading = false; + break + case "VNF": + this.vnfuploading = false; + break + case "PNF": + this.pnfloading = false; + } + } + + //---------------------------------------------------------------------------------------------- + + // Get the NS list + getTableData() { + this.isSpinning = true; + //ns vfc lists + this.myhttp.getOnboardTableData() + .subscribe((data) => { + this.nsvfcData = data; + this.nstableData = this.nsvfcData; + //ns sdc list + this.myhttp.getSDC_NSTableData() + .subscribe((data) => { + this.isSpinning = false; //loading hide + this.nssdcData = data; + this.nsvfcData.map((nsvfc) => { nsvfc.sameid = this.nssdcData.find((nssdc) => { return nsvfc.id == nssdc.uuid }) && nsvfc.id; return nsvfc; }); + let sameData = this.nssdcData.filter((nssdc) => { return !this.nsvfcData.find((nsvfc) => { return nsvfc.id == nssdc.uuid }) }); + this.nstableData = this.nstableData.concat(sameData); + }, (err) => { + console.log(err); + this.isSpinning = false; + }) + }, (err) => { + console.log(err); + this.isSpinning = false; + }) + + } + + // Get the vnf list + getTableVnfData() { + this.isSpinning = true; + //vnf vfc lists + this.myhttp.getOnboardTableVnfData() + .subscribe((data) => { + this.vnfvfcData = data; + this.vnftableData = this.vnfvfcData; + //vnf sdc lists + this.myhttp.getSDC_VNFTableData() + .subscribe((data) => { + this.isSpinning = false; //loading hide + this.vnfsdcData = data; + this.vnfvfcData.map((vnfvfc) => { vnfvfc.sameid = this.vnfsdcData.find((nssdc) => { return vnfvfc.id == nssdc.uuid }) && vnfvfc.id; return vnfvfc; }); + let sameData = this.vnfsdcData.filter((vnfsdc) => { return !this.vnfvfcData.find((vnfvfc) => { return vnfvfc.id == vnfsdc.uuid }) }); + this.vnftableData = this.vnftableData.concat(sameData); + }, (err) => { + console.log(err); + }) + + }, (err) => { + console.log(err); + }) + } + + // Get pnf list + getTablePnfData() { + this.isSpinning = true; + this.myhttp.getOnboardTablePnfData() + .subscribe((data) => { + this.pnftableData = data; + this.isSpinning = false; //loading hide + }, (err) => { + console.log(err); + }) + } + + //----------------------------------------------------------------------------------- + /* onboard */ + //Successful frame + success(tab): void { + const modal = this.modalService.success({ + nzTitle: 'This is an success message', + nzContent: 'Package Onboard Completed.' + }); + switch (tab) { + case "NS": + this.getTableData(); + break + case "VNF": + this.getTableVnfData(); + break + } + } + + //Failure frame + error(): void { + this.modalService.error({ + nzTitle: 'This is an error message', + nzContent: 'Package Onboard Failed!' + }); + } + + //onboard status + onboardData = { + status: "onboard", + progress: 0, + } + currentIndex = 0; + // ns onboard Upload button + updataNsService(id, index, notificationModel) { + this.currentIndex = index; + this.onboardData.status = "onboarding"; //Disabled + this.onboardData.progress = 0; + let requestBody = { + "csarId": id + }; + this.notificationAttributes = { + "title": this.tabs[0], + "imgPath": "../../../../assets/images/execute-inproess.png", + "action": "OnboardingState", + "status": "InProgress", + "id": id + }; + this.notificationModelShow(notificationModel); + this.myhttp.getNsonboard(requestBody) + .subscribe((data) => { + if (data.status == "failed") { + this.onboardData.status = "Failed"; + this.notificationFailed(notificationModel); + this.error(); + return false + } else if (data.status == "success") { + this.success("NS"); + this.onboardData.status = "onboarded"; + this.notificationSuccess(notificationModel); + } + }, (err) => { + console.log(err); + }) + } + + // vnf onboard Upload button + updataVnfService(id, index, notificationModel) { + this.currentIndex = index; + this.onboardData.status = "onboarding"; //Disabled button + this.onboardData.progress = 0; + + + let requestBody = { + "csarId": id + }; + this.notificationAttributes = { + "title": this.tabs[1], + "imgPath": "../../../../assets/images/execute-inproess.png", + "action": "OnboardingState", + "status": "InProgress", + "id": id + }; + this.notificationModelShow(notificationModel); + this.myhttp.getVnfonboard(requestBody) + .subscribe((data) => { + this.jobId = data.jobId; + this.queryProgress(this.jobId, 0, notificationModel); //vnf Need to query progress interface + }, (err) => { + console.log(err); + }) + } + + //Progress Progress inquiry + queryProgress(jobId, responseId, notificationModel) { + let mypromise = new Promise((res) => { + this.myhttp.getProgress(jobId, responseId) + .subscribe((data) => { + if (data.responseDescriptor == null || data.responseDescriptor == "null" || data.responseDescriptor.progress == undefined || data.responseDescriptor.progress == null) { + this.onboardData.status = "onboarding"; + setTimeout(() => { + this.queryProgress(this.jobId, 0, notificationModel); + }, 10000) + return false + } + if (data.responseDescriptor.progress > 100) { + this.onboardData.status = "Failed"; + this.notificationFailed(notificationModel); + this.error(); + return false + } + if (data.responseDescriptor.progress < 100) { + this.onboardData.status = "onboarding"; + setTimeout(() => { + this.queryProgress(this.jobId, 0, notificationModel); + }, 5000) + } else if (data.responseDescriptor.progress == 100) { + res(data); + this.success("VNF"); + this.onboardData.status = "onboarded"; + this.notificationSuccess(notificationModel); + } + return false + }) + }) + return mypromise; + } + + //-------------------------------------------------------------------------------- + /* delete button */ + showConfirm(index, pkgid, tab, notificationModel): void { + this.notificationAttributes = { + "title": this.tabs[0], + "imgPath": "../../../../assets/images/execute-inproess.png", + "action": "OnboardingState", + "status": "InProgress", + "id": pkgid + }; + this.confirmModal = this.modal.confirm({ + nzTitle: 'Do you Want to delete these items?', + nzContent: 'Do you Want to delete these items?', + nzOkText: 'Yes', + nzCancelText: 'No', + nzOnOk: () => new Promise((resolve, reject) => { + switch (tab) { + case 'NS': + this.notificationAttributes.title = this.tabs[0]; + this.notificationModelShow(notificationModel); + this.deleteNsService(index, pkgid, notificationModel); + setTimeout(Math.random() > 0.5 ? resolve : reject, 2000); + break + case 'VNF': + this.notificationAttributes.title = this.tabs[1]; + this.notificationModelShow(notificationModel); + this.deleteVnfService(index, pkgid, notificationModel); + setTimeout(Math.random() > 0.5 ? resolve : reject, 2000); + break + case 'PNF': + this.notificationAttributes.title = this.tabs[2]; + this.notificationModelShow(notificationModel); + this.deletePnfService(index, pkgid, notificationModel); + setTimeout(Math.random() > 0.5 ? resolve : reject, 2000); + break + } + }).catch(() => console.log('Oops errors!')) + }); + } + + //delete nsItem + deleteNsService(index, pkgid, notificationModel) { + this.myhttp.deleteNsIdData(pkgid) + .subscribe((data) => { + this.notificationSuccess(notificationModel); + //refresh list after successful deletion + this.getTableData(); + }, (err) => { + console.log(err); + this.notificationFailed(notificationModel); + }) + } + + //delete vnfItem + deleteVnfService(index, pkgid, notificationModel) { + this.myhttp.deleteVnfIdData(pkgid) + .subscribe((data) => { + this.notificationSuccess(notificationModel); + //refresh list after successful deletion + this.getTableVnfData() + }, (err) => { + console.log(err); + this.notificationFailed(notificationModel); + }) + } + + //delete PnfItem + deletePnfService(index, pkgid, notificationModel) { + this.myhttp.deletePnfIdData(pkgid) + .subscribe((data) => { + //refresh list after successful deletion + this.notificationSuccess(notificationModel); + this.getTablePnfData() + }, (err) => { + console.log(err); + this.notificationFailed(notificationModel); + }) + } + +} diff --git a/usecaseui-portal/src/app/views/services/services-list/services-list.component.css b/usecaseui-portal/src/app/views/services/services-list/services-list.component.css new file mode 100644 index 00000000..0a7f92eb --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/services-list.component.css @@ -0,0 +1,145 @@ +/* + Copyright (C) 2019 CMCC, Inc. and others. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +.title { + font: 700 18px/18px "思源黑体"; + color: #4c5e70; + margin-bottom: 18px; +} +hr { + border: none; + height: 2px; + background-color: #dce1e7; + margin-bottom: 20px; +} +.action { + margin-bottom: 20px; +} +.action span { + display: inline-block; + font: 700 14px "Arial"; + color: #4c5e70; +} +.action nz-dropdown { + vertical-align: middle; +} +.action nz-dropdown :hover { + border-color: #147dc2; +} +.action nz-dropdown button { + width: 165px; + height: 30px; + background-color: #eceff4; + text-align: left; + border-color: #9fa9ab; +} +.action nz-dropdown button span { + font-weight: 400; + display: inline-block; + width: 120px; + overflow: hidden; + text-overflow: ellipsis; + padding-top: 2px; +} +.action nz-dropdown button i { + position: absolute; + top: 10px; + right: 10px; +} +.action .create { + float: right; + height: 30px; + padding: 0 10px; +} +.action .create span { + color: #fff; + font-weight: 400; +} +.list { + background-color: #fff; + border-radius: 5px; + padding: 10px; +} +.list nz-table tbody td span.active { + font-size: 14px; + color: #147dc2; +} +.list nz-table tbody td span.closed { + font-size: 14px; + color: red; +} +.list nz-table tbody td span.onboarding { + font-size: 12px; + color: #147dc2; +} +.list nz-table tbody td span.updating { + font-size: 12px; + color: blue; +} +.list nz-table tbody td span.deleting { + font-size: 12px; + color: red; +} +.list nz-table tbody td span.creating { + font-size: 12px; + color: green; +} +.list nz-table tbody td span.scaling { + font-size: 12px; + color: purple; +} +.list nz-table tbody td span.healing { + font-size: 12px; + color: orangered; +} +.list nz-table tbody td i.anticon { + cursor: pointer; + font-size: 18px; + padding: 2px; +} +.list nz-table tbody td i.anticon:hover { + color: #147dc2; +} +.list nz-table tbody td .cannotclick { + pointer-events: none; + color: #aaa; + opacity: 0.6; +} +.list nz-table tbody tr.childtr td { + font-size: 12px; + color: #147dc2; +} +.detailComponent { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100vh; + background-color: #f3f3f3; + overflow-y: auto; + padding: 20px 32px; + z-index: 3; +} +.createComponent { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100vh; + background-color: #f3f3f3; + overflow-y: auto; + padding: 20px 32px; + z-index: 3; +} diff --git a/usecaseui-portal/src/app/views/services/services-list/services-list.component.html b/usecaseui-portal/src/app/views/services/services-list/services-list.component.html new file mode 100644 index 00000000..6f6d8f74 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/services-list.component.html @@ -0,0 +1,745 @@ +<!-- + Copyright (C) 2019 CMCC, Inc. and others. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<div class="action ant-tabs-bar"> + + <span><i style="margin-right: 10px"><img src="assets/images/customer.png" alt=""></i> + {{"i18nTextDefine_Customer" | translate}} : </span> + <nz-dropdown [nzTrigger]="'click'" [nzPlacement]="'bottomLeft'"> + <button nz-button nz-dropdown><span>{{customerSelected.name}}</span> <i class="anticon anticon-down"></i> + </button> + <ul nz-menu style="min-height:40px;max-height: 200px; overflow: auto;"> + <li nz-menu-item (click)="choseCustomer(item)" *ngFor="let item of customerList"> + <a title="{{item.name}}" + style="max-width: 165px; overflow: hidden; text-overflow: ellipsis;">{{item.name}}</a> + </li> + </ul> + </nz-dropdown> + + <span style="margin-left:40px"><i style="margin-right: 10px"><img src="assets/images/service-type.png" alt=""></i> + {{"i18nTextDefine_ServiceType" | translate}} : </span> + <nz-dropdown [nzTrigger]="'click'" [nzPlacement]="'bottomLeft'"> + <button nz-button nz-dropdown><span>{{serviceTypeSelected.name}}</span> <i class="anticon anticon-down"></i> + </button> + <ul nz-menu style="min-height:40px;max-height: 200px; overflow: auto;"> + <li nz-menu-item (click)="choseServiceType(item)" *ngFor="let item of serviceTypeList"> + <a title="{{item.name}}" + style="max-width: 165px; overflow: hidden; text-overflow: ellipsis;">{{item.name}}</a> + </li> + </ul> + </nz-dropdown> + + <button class="create" nz-button [nzType]="'primary'" (click)="createModal()"><i class="anticon anticon-plus" + style="transform: scale(1.5);line-height: 15px;margin-right: 5px;"></i><span> + {{"i18nTextDefine_Create" | translate}} </span> + </button> + <nz-modal nzWidth="428" [(nzVisible)]="isVisible" nzTitle=" {{'i18nTextDefine_ServiceCreation' | translate}} " + (nzOnCancel)="handleCancel()" (nzOnOk)="handleOk()" nzClassName="serviceCreationModel" + nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} " nzOkText=" {{'i18nTextDefine_modelOk' | translate}} "> + <div class="select-list"> + <span style="display:inline-block;"> {{"i18nTextDefine_Customer" | translate}} : </span> + <nz-select style="width: 176px;float: right;" [(ngModel)]="customerSelected2.name" nzAllowClear + (ngModelChange)="customerChange()"> + <nz-option *ngFor="let item of customerList2" [nzValue]="item.name" [nzLabel]="item.name"></nz-option> + </nz-select> + </div> + <div class="select-list"> + <span style="display:inline-block;"> {{"i18nTextDefine_ServiceType" | translate}} : </span> + <nz-select style="width: 176px;float: right;" [(ngModel)]="serviceTypeSelectedName" nzAllowClear + (ngModelChange)="serviceTypeChange()"> + <nz-option *ngFor="let item of serviceTypeList2" [nzValue]="item.name" [nzLabel]="item.name"> + </nz-option> + </nz-select> + </div> + <div class="select-list"> + <span style="display:inline-block;"> {{"i18nTextDefine_UseCase" | translate}} : </span> + <nz-select style="width: 176px;float: right;" [(ngModel)]="templateTypeSelected" nzAllowClear + (ngModelChange)="choseTemplateType()"> + <!-- <nz-option *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> + </div> + + <div class="select-list"> + <span style="display:inline-block;width:70px;"> {{"i18nTextDefine_Template" | translate}} : </span> + <nz-select style="width: 176px;float: right;" [(ngModel)]="template1" nzAllowClear> + <nz-option *ngFor="let item of templates" [nzValue]="item" [nzLabel]="item.name"></nz-option> + </nz-select> + </div> + <div *ngIf="templateTypeSelected == 'E2E Service'"> + <div class="select-list"> + <span style="display:inline-block;width:70px;"> {{"i18nTextDefine_Orchestrator" | translate}} : </span> + <nz-select style="width: 176px;float: right;" [(ngModel)]="orchestratorSelected" nzAllowClear> + <nz-option *ngFor="let item of orchestratorList" [nzValue]="item" [nzLabel]="item.name"></nz-option> + </nz-select> + </div> + </div> + <div *ngIf="templateTypeSelected == 'E2E Service'"> + <div class="check-box" style="margin:30px; height: 50px"> + <input class="check-box-style" style="zoom: 1.8; width: 70px" type="checkbox" + [(ngModel)]="isSol005Interface" value="true" nzAllowClear> + <label class="label" style="font-size: 20px; color: rgb(60,79,140,0.5)">Sol005</label> + </div> + </div> + <div class="select-list" style="color: red;margin-left: 66px;" *ngIf="temParametersTips"> + {{"i18nTextDefine_Templateparsingfailed" | translate}} + </div> + </nz-modal> +</div> +<nz-layout style=" padding: 20px 32px; "> + <ul class="top-num"> + <li *ngFor="let item of serviceMunber" class="top-list"> + <span class="round">{{item.serviceDomain}}</span> + <div class="top-list-text"> + <p> + <span>{{item.failed}}</span> + <span> {{"i18nTextDefine_Failed" | translate}} </span> + </p> + <p> + <span>{{item.Success}}</span> + <span> {{"i18nTextDefine_Success" | translate}} </span> + </p> + <p> + <span>{{item.InProgress}}</span> + <span> {{"i18nTextDefine_InProgress" | translate}} </span> + </p> + </div> + <p class="service-description"> {{item.detailName | translate}} </p> + </li> + </ul> + <div class="list" id="services-list" [ngClass]="{'listdisplay':listDisplay == true}"> + <nz-table *ngIf="1" #nzTable [nzData]="tableData" nzShowSizeChanger [nzFrontPagination]="false" + [nzShowQuickJumper]="true" [nzPageSizeOptions]="[5,10,15,20]" [nzTotal]='total' [(nzPageSize)]="pageSize" + [(nzPageIndex)]='pageIndex' [nzLoading]="loading" [nzSize]="'middle'" [nzScroll]="{ y: '58vh' }" + (nzPageIndexChange)="searchData()" (nzPageSizeChange)="searchData(true)"> + <thead> + <tr> + <th nzWidth="5%"> {{"i18nTextDefine_NO" | translate}}</th> + <th nzWidth="5%"></th> + <th nzWidth="20%"> {{"i18nTextDefine_Name" | translate}}</th> + <th nzWidth="20%"> {{"i18nTextDefine_InstanceID" | translate}}</th> + <th nzWidth="15%"> {{"i18nTextDefine_UseCase" | translate}}</th> + <th nzWidth="20%"> {{"i18nTextDefine_Status" | translate}}</th> + <th nzWidth="15%"> {{"i18nTextDefine_Action" | translate}}</th> + </tr> + </thead> + <tbody> + <ng-template ngFor let-data [ngForOf]="nzTable.data" let-i="index"> + <tr> + <td>{{pageSize*(pageIndex-1) + i+1}}</td> + <td [nzShowExpand]="data.childServiceInstances[0]" [(nzExpand)]="data.expand"></td> + <td>{{data["service-instance-name"] || data.nsName}}</td> + <td>{{data["service-instance-id"] || data.nsInstanceId}}</td> + <td> + <p + [ngClass]="{'e2eColor':data.serviceDomain=='E2E Service','nsColor':data.serviceDomain=='Network Service','ccvpnColor':data.serviceDomain=='CCVPN','sotnColor':data.serviceDomain=='SOTN','voLTEColor':data.serviceDomain=='voLTE type'}"> + {{data.serviceDomain}} + </p> + </td> + <td> + <span [ngClass]="{'active':data.statusClass=='2001','closed':data.statusClass=='Closed','onboarding':data.statusClass=='Onboarding', + 'updating':data.statusClass=='Updating','deleting':data.statusClass=='1002','creating':data.statusClass=='1001', + 'scaling':data.statusClass=='1003','healing':data.statusClass=='1004'}" + *ngIf="data.tips != 'Available' && data.tips != 'Unavailable'">{{data.tips}}</span> + <span *ngIf="data.tips == 'Available' " style="margin-left: 10px"> + <img src="assets/images/wancheng-icon.png" alt="Available"> + </span> + <span *ngIf="data.tips == 'Unavailable' " style="margin-left: 10px"> + <img src="assets/images/shibai-icon.png" alt="Unavailable"> + </span> + <nz-progress *ngIf="data.status == 'In Progress'" [nzPercent]="data.rate" + [nzShowInfo]="false" nzStatus="active"></nz-progress> + </td> + <td> + <i [ngClass]="{'cannotclick':data.status == 'In Progress'||(data.status=='Failed' && data.operationType=='1001')||(data.status=='Failed' && data.operationType=='1002')}" + class="anticon anticon-bars" (click)="serviceDetail(data,1)"></i> + <i [ngClass]="{'cannotclick':data.status == 'In Progress'}" class="anticon anticon-delete" + (click)="deleteModel(data)"></i> + <i [ngClass]="{'cannotclick':data.status == 'In Progress'}" class="anticon anticon-ellipsis" + (click)="iconMoreShow(data,tableData)" style="transform: rotate(90deg);"></i> + + <ul *ngIf="data.iconMore==true " class="icon-more"> + <li (click)="scaleService(data)" + [ngClass]="{'cannotclick':data.serviceDomain!='E2E Service' || data.status == 'In Progress'||(data.status=='Failed' && data.operationType=='1001')||(data.status=='Failed' && data.operationType=='1002')}"> + <i class="anticon anticon-scale"></i> + <span> {{"i18nTextDefine_Scale" | translate}} </span> + </li> + <li (click)="serviceDetail(data,2)" + [ngClass]="{'cannotclick':data.serviceDomain!='CCVPN' || data.status == 'In Progress'||(data.status=='Failed' && data.operationType=='1001')||(data.status=='Failed' && data.operationType=='1002')}"> + <i class="anticon anticon-update"></i> + <span> {{"i18nTextDefine_Update" | translate}} </span> + </li> + </ul> + <!-- <i *ngIf="data.serviceDomain=='E2E Service'||data.serviceDomain=='Network Service' " class="anticon anticon-cloud-upload-o" (click)="updataService(data)"></i> --> + <!-- <i [ngClass]="{'cannotclick':data.status == 'processing'||data.status=='Deleting'||data.status=='Creating'||data.status=='Healing'}" + *ngIf="data.serviceDomain=='Network Service' " class="anticon anticon-reload" (click)="healService(data)"></i> --> + </td> + </tr> + <tr class="childtr" [nzExpand]="data.expand" *ngFor="let item of data.childServiceInstances"> + <td></td> + <td></td> + <td>{{item["service-instance-id"] || item.nsInstanceId || item.vnfInstanceId}}</td> + <td>{{item["service-instance-name"] || item.nsName || item.vnfInstanceName}}</td> + <td> + <p + [ngClass]="{'vnfColor':item.serviceDomain=='vnf','siteColor':item.serviceDomain=='SITE','SDWANColor':item.serviceDomain=='SDWAN'}"> + {{item.serviceDomain}} + </p> + </td> + <td> + <span [ngClass]="{'healing':data.statusClass=='1004'}">{{item.tips}}</span> + <nz-progress *ngIf=" item.status == 'In Progress' " [nzPercent]="item.rate"></nz-progress> + </td> + <td> + <i [ngClass]="{'cannotclick':data.serviceDomain!='Network Service' || data.status == 'In Progress'||(data.status=='Failed' && data.operationType=='1001')||(data.status=='Failed' && data.operationType=='1002')}" + class="anticon anticon-reload" (click)="healService(item)"></i> + </td> + </tr> + </ng-template> + </tbody> + </nz-table> + + <nz-modal nzWidth="428" [nzVisible]="scaleModelVisible" nzTitle=" {{'i18nTextDefine_Scale' | translate}} " + (nzOnCancel)="scaleCancel()" (nzOnOk)="scaleOk(templatescalestarting,templateScaleSuccessFaild)" + nzClassName="scaleModel" nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} " + nzOkText=" {{'i18nTextDefine_modelOk' | translate}} "> + <h3><span style="color: red">* </span> {{"i18nTextDefine_SureScale" | translate}} </h3> + <div class="question"> + <h4> {{"i18nTextDefine_InstanceID" | translate}} :</h4> + <div class="scaleModelContent" style="width: 100%">{{ thisService["service-instance-id"] || + thisService["nsInstanceId"] || + thisService["vnfInstanceId"]}} + </div> + </div> + <div *ngFor="let item of e2e_nsData" style="margin-top: 20px"> + <h3>{{ item.netWorkServiceName }}</h3> + <div class="e2eScaleContent"> + <span class="e2eScaleLable"> {{"i18nTextDefine_ScaleType" | translate}} :</span> + <nz-select style="width: 165px;" [(ngModel)]="item.scaleType"> + <nz-option nzValue="SCALE_NS" nzLabel="SCALE_NS"></nz-option> + <nz-option nzValue="SCALE_VNF" nzLabel="SCALE_VNF"></nz-option> + </nz-select> + </div> + <div class="e2eScaleContent"> + <span class="e2eScaleLable"> {{"i18nTextDefine_AspectId" | translate}} :</span> + <input style="width: 165px;" nz-input [(ngModel)]="item.aspectId" placeholder="string"> + </div> + <div class="e2eScaleContent"> + <span class="e2eScaleLable"> {{"i18nTextDefine_Number_Of_Steps" | translate}} :</span> + <nz-input-number style="width: 165px;" [(ngModel)]="item.numberOfSteps" [nzMin]="1" [nzMax]="100" + nzPrecision=0 [nzStep]="1" nzPlaceHolder="number"></nz-input-number> + </div> + <div class="e2eScaleContent"> + <span class="e2eScaleLable"> {{"i18nTextDefine_ScalingDirection" | translate}} :</span> + <nz-select style="width: 165px;" nzPlaceHolder="Chose" [(ngModel)]="item.scalingDirection"> + <nz-option nzValue="SCALE_IN" nzLabel="SCALE_IN"></nz-option> + <nz-option nzValue="SCALE_OUT" nzLabel="SCALE_OUT"></nz-option> + </nz-select> + </div> + </div> + + <ng-template #templatescalestarting> + <div class="ant-notification-notice-content"> + <div class="ant-notification-notice-with-icon"> + <span class="ant-notification-notice-icon"> + <img src="assets/images/execute-inproess.png" alt="instance temination is starting"> + </span> + <div class="ant-notification-notice-message">E2E + {{"i18nTextDefine_InstanceTeminationStarting" | translate}} + </div> + <div class="ant-notification-notice-description"> + <div class="notificationlist"> + <p> {{"i18nTextDefine_InstanceName" | translate}} :</p> + <span>{{ thisService["service-instance-name"] || + thisService["nsInstanceName"] }} + </span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_Customer" | translate}} :</p> + <span>{{ customerSelected.name }}</span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_UseCase" | translate}} :</p> + <span>{{ thisService["serviceDomain"] }}</span> + </div> + </div> + <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> + </div> + </div> + </ng-template> + </nz-modal> + + <nz-modal nzWidth="428" [(nzVisible)]="deleteModelVisible" nzTitle=" {{'i18nTextDefine_delete' | translate}} " + (nzOnCancel)="deleteCancel()" (nzOnOk)="deleteOk(templatedeletestarting,templateDeleteSuccessFaild)" + nzClassName="{{thisService['serviceDomain'] == 'Network Service'?'nsdeleteModel':'deleteModel'}}" + nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} " + nzOkText=" {{'i18nTextDefine_modelOk' | translate}} "> + <h3><span style="color: red">* </span> {{"i18nTextDefine_SureDelete" | translate}} </h3> + <div class="question"> + <h4> {{"i18nTextDefine_InstanceName" | translate}} :</h4> + <div class="deleteModelContent">{{ thisService["service-instance-name"] || + thisService["nsInstanceName"] }} + </div> + </div> + <div class="question"> + <h4> {{"i18nTextDefine_InstanceID" | translate}} :</h4> + <div class="deleteModelContent">{{ thisService["service-instance-id"] || + thisService["nsInstanceId"] }} + </div> + </div> + <div *ngIf="thisService['serviceDomain'] == 'Network Service'"> + <div class="question"> + <h4> {{"i18nTextDefine_terminationType" | translate}} :</h4> + <nz-select style="width: 306px;" [(ngModel)]="terminationType"> + <nz-option nzValue="graceful" nzLabel=" {{'i18nTextDefine_graceful' | translate}} "></nz-option> + <nz-option nzValue="forceful" nzLabel=" {{'i18nTextDefine_forceful' | translate}} "></nz-option> + </nz-select> + </div> + <div class="question"> + <h4 *ngIf="terminationType=='graceful'"> {{"i18nTextDefine_gracefulTerminationTimeout" | translate}} + :</h4> + <input *ngIf="terminationType=='graceful'" style="width: 306px;" nz-input + [(ngModel)]="gracefulTerminationTimeout"> + </div> + </div> + + <ng-template #templatedeletestarting> + <div class="ant-notification-notice-content"> + <div class="ant-notification-notice-with-icon"> + <span class="ant-notification-notice-icon"> + <img src="assets/images/execute-inproess.png" alt="instance temination is starting"> + </span> + <div class="ant-notification-notice-message" + *ngIf="thisService['serviceDomain'] == 'CCVPN' || thisService['serviceDomain'] == 'SOTN'"> + {{ thisService['serviceDomain'] }} {{"i18nTextDefine_InstanceTeminationStarting" | + translate}} + </div> + <div class="ant-notification-notice-message" + *ngIf="thisService['serviceDomain'] == 'E2E Service'">E2E + {{"i18nTextDefine_InstanceTeminationStarting" | translate}} + </div> + <div class="ant-notification-notice-message" + *ngIf="thisService['serviceDomain'] == 'Network Service'">NS + {{"i18nTextDefine_InstanceTeminationStarting" | translate}} + </div> + <div class="ant-notification-notice-description"> + <div class="notificationlist"> + <p> {{"i18nTextDefine_InstanceName" | translate}} :</p> + <span>{{ thisService["service-instance-name"] || + thisService["nsInstanceName"] }} + </span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_Customer" | translate}} :</p> + <span>{{ customerSelected.name }}</span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_UseCase" | translate}} :</p> + <span>{{ thisService["serviceDomain"] }}</span> + </div> + </div> + <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> + </div> + </div> + </ng-template> + </nz-modal> + + <nz-modal nzWidth="428" [nzVisible]="healModelVisible" nzTitle=" {{'i18nTextDefine_Heal' | translate}} " + (nzOnCancel)="healCancel()" (nzOnOk)="healOk(templatehealstarting,templatehealSuccessFaild)" + nzClassName="healModel" nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} " + nzOkText=" {{'i18nTextDefine_modelOk' | translate}} "> + <h3><span style="color: red">* </span> {{"i18nTextDefine_SureHeal" | translate}} </h3> + <div class="heal-question"> + <p class="heal-label"> {{"i18nTextDefine_InstanceID" | translate}} : </p> + <div class="healModelContent" title="{{ thisService['service-instance-id'] || thisService['nsInstanceId'] || + thisService['vnfInstanceId']}}"> {{ thisService["service-instance-id"] || + thisService["nsInstanceId"] || + thisService["vnfInstanceId"]}} + </div> + </div> + <!-- NS --> + <div *ngIf="thisService['serviceDomain'] == 'Network Service'"> + <div class="question"> + <p class="heal-label"> {{"i18nTextDefine_degreeHealing" | translate}} :</p> + <nz-select style="width: 200px;height:42px;margin-left: 15px;border-radius: 6px" + [(ngModel)]="nsParams.degreeHealing"> + <nz-option nzValue="HEAL_RESTORE" nzLabel="HEAL_RESTORE"></nz-option> + <nz-option nzValue="HEAL_QOS" nzLabel="HEAL_QOS"></nz-option> + <nz-option nzValue="HEAL_RESET" nzLabel="HEAL_RESET"></nz-option> + <nz-option nzValue="PARTIAL_HEALING" nzLabel="PARTIAL_HEALING"></nz-option> + </nz-select> + </div> + <div> + <span style="display:inline-block;"> {{"i18nTextDefine_actionsHealing" | translate}} :</span> + <button nz-button [nzType]="'default'" (click)="addActionsHealing()"><i + class="anticon anticon-plus-circle-o"></i></button> + <br> + <div *ngFor="let item of healActions;let i = index;" style="display:inline-block;"> + <input style="width: 165px;" nz-input [(ngModel)]="item.value"> + <button nz-button [nzType]="'dashed'" (click)="minusActionsHealing(i)"><i + class="anticon anticon-minus-circle-o"></i></button> + + </div> + </div> + <span style="display:inline-block;width:50%;"> {{"i18nTextDefine_healScript" | translate}} :</span> + <input style="width: 165px;" nz-input [(ngModel)]="nsParams.healScript"> + <div> + <span style="display:inline-block;"> {{"i18nTextDefine_additionalParamsforNs" | translate}} :</span> + <button nz-button [nzType]="'default'" (click)="addNsAdditional()"><i + class="anticon anticon-plus-circle-o"></i></button> + <br> + <div *ngFor="let item of nsAdditional;let i = index;"> + Key: <input style="width: 165px;" nz-input [(ngModel)]="item.key"> + Value: <input style="width: 165px;" nz-input [(ngModel)]="item.value"> + <button nz-button [nzType]="'dashed'" (click)="minusNsAdditional(i)"><i + class="anticon anticon-minus-circle-o"></i></button> + </div> + </div> + </div> + <!-- vnf --> + <div *ngIf="thisService['serviceDomain'] == 'vnf'" style="clear: both"> + <div class="heal-question"> + <p class="heal-label"> {{"i18nTextDefine_cause" | translate}} :</p> + <input nz-input [(ngModel)]="vnfParams.cause" class="heal-input"> + </div> + <div class="heal-question"> + <p class="heal-label"> {{"i18nTextDefine_action" | translate}} :</p> + <input nz-input [(ngModel)]="vnfParams.additionalParams.action" class="heal-input"> + </div> + <div class="heal-question"> + <p class="heal-label"> {{"i18nTextDefine_actionvminfo" | translate}}:</p> + <nz-select + style=" float: right;width: 200px;margin-left: 15px;border-radius: 6px;margin-right: 30px" + [(ngModel)]="vmSelected"> + <nz-option *ngFor="let item of vnfVms" [nzValue]="item" [nzLabel]="item.vmName"></nz-option> + </nz-select> + </div> + </div> + + <ng-template #templatehealstarting> + <div class="ant-notification-notice-content"> + <div class="ant-notification-notice-with-icon"> + <span class="ant-notification-notice-icon"> + <img src="assets/images/execute-inproess.png" alt="instance temination is starting"> + </span> + <div class="ant-notification-notice-message">NS + {{"i18nTextDefine_InstanceHealingStarting" | translate}} + </div> + <div class="ant-notification-notice-description"> + <div class="notificationlist"> + <p> {{"i18nTextDefine_InstanceName" | translate}} :</p> + <span>{{ thisService["service-instance-name"] || + thisService["nsInstanceName"] }} + </span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_Customer" | translate}} :</p> + <span>{{ customerSelected.name }}</span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_UseCase" | translate}} :</p> + <span>{{ thisService["serviceDomain"] }}</span> + </div> + </div> + <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> + </div> + </div> + </ng-template> + </nz-modal> + + <!-- add notification--> + <ng-template #templateCreatestarting> + <div class="ant-notification-notice-content"> + <div class="ant-notification-notice-with-icon"> + <span class="ant-notification-notice-icon"> + <img src="assets/images/execute-inproess.png" alt="instance temination is starting"> + </span> + <div class="ant-notification-notice-message" + *ngIf="thisCreateService['serviceDomain'] == 'CCVPN' || thisService['serviceDomain'] == 'SOTN'"> + {{ thisService['serviceDomain'] }} {{"i18nTextDefine_InstanceCreationStarting" | + translate}} + </div> + <div class="ant-notification-notice-message" + *ngIf="thisCreateService['serviceDomain'] == 'E2E Service'">E2E + {{"i18nTextDefine_InstanceCreationStarting" | translate}} + </div> + <div class="ant-notification-notice-message" + *ngIf="thisCreateService['serviceDomain'] == 'Network Service'">NS + {{"i18nTextDefine_InstanceCreationStarting" | translate}} + </div> + <div class="ant-notification-notice-description"> + <div class="notificationlist"> + <p> {{"i18nTextDefine_InstanceName" | translate}} :</p> + <span>{{ thisCreateService["service-instance-name"] }} + </span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_Customer" | translate}} :</p> + <span>{{ customerSelected2.name }}</span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_UseCase" | translate}} :</p> + <span>{{ thisCreateService['serviceDomain'] }}</span> + </div> + </div> + <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> + </div> + </div> + </ng-template> + <ng-template #templateCreateSuccessFaild> + <div class="ant-notification-notice-content"> + <div class="ant-notification-notice-with-icon"> + <span class="ant-notification-notice-icon"> + <img src="assets/images/execute-success.png" alt="instance temination is starting" + *ngIf="thisCreateService.status == 'Successful'"> + <img src="assets/images/execute-faild.png" alt="instance temination is starting" + *ngIf="thisCreateService.status == 'Failed'"> + </span> + <div class="ant-notification-notice-message" + *ngIf="(thisCreateService['serviceDomain'] == 'CCVPN' || thisCreateService['serviceDomain'] == 'SOTN') && thisCreateService.status == 'Successful'"> + {{ thisCreateService['serviceDomain'] }} {{"i18nTextDefine_InstanceCreatedSuccessfully" | + translate}} + </div> + <div class="ant-notification-notice-message" + *ngIf="(thisCreateService['serviceDomain'] == 'E2E Service') && thisCreateService.status == 'Successful'"> + E2E {{"i18nTextDefine_InstanceCreatedSuccessfully" | translate}} + </div> + <div class="ant-notification-notice-message" + *ngIf="(thisCreateService['serviceDomain'] == 'Network Service') && thisCreateService.status == 'Successful'"> + NS {{"i18nTextDefine_InstanceCreatedSuccessfully" | translate}} + </div> + <div class="ant-notification-notice-message" + *ngIf="(thisCreateService['serviceDomain'] == 'CCVPN' || thisCreateService['serviceDomain'] == 'SOTN') && thisCreateService.status == 'Failed'"> + {{ thisCreateService['serviceDomain'] }} {{"i18nTextDefine_InstanceCreationFailed" | + translate}} + </div> + <div class="ant-notification-notice-message" + *ngIf="(thisCreateService['serviceDomain'] == 'E2E Service') && thisCreateService.status == 'Failed'"> + E2E {{"i18nTextDefine_InstanceCreationFailed" | translate}} + </div> + <div class="ant-notification-notice-message" + *ngIf="(thisCreateService['serviceDomain'] == 'Network Service') && thisCreateService.status == 'Failed'"> + NS {{"i18nTextDefine_InstanceCreationFailed" | translate}} + </div> + <div class="ant-notification-notice-description"> + <div class="notificationlist"> + <p> {{"i18nTextDefine_InstanceName" | translate}} :</p> + <span>{{ thisCreateService["service-instance-name"] || + thisCreateService["nsInstanceName"] }} + </span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_Customer" | translate}} :</p> + <span>{{ customerSelected2.name }}</span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_UseCase" | translate}} :</p> + <span>{{ thisCreateService["serviceDomain"] }}</span> + </div> + </div> + <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> + </div> + </div> + </ng-template> + <ng-template #templateDeleteSuccessFaild> + <div class="ant-notification-notice-content"> + <div class="ant-notification-notice-with-icon"> + <span class="ant-notification-notice-icon"> + <img src="assets/images/execute-success.png" alt="instance temination is starting" + *ngIf="thisService.status == 'Successful'"> + <img src="assets/images/execute-faild.png" alt="instance temination is starting" + *ngIf="thisService.status == 'Failed'"> + </span> + <div class="ant-notification-notice-message" + *ngIf="(thisService['serviceDomain'] == 'CCVPN' || thisService['serviceDomain'] == 'SOTN') && thisService.status == 'Successful'"> + {{ thisService['serviceDomain'] }} {{"i18nTextDefine_InstanceTeminatedSuccessfully" | + translate}} + </div> + <div class="ant-notification-notice-message" + *ngIf="(thisService['serviceDomain'] == 'E2E Service') && thisService.status == 'Successful'"> + E2E {{"i18nTextDefine_InstanceTeminatedSuccessfully" | translate}} + </div> + <div class="ant-notification-notice-message" + *ngIf="(thisService['serviceDomain'] == 'Network Service') && thisService.status == 'Successful'"> + NS {{"i18nTextDefine_InstanceTeminatedSuccessfully" | translate}} + </div> + <div class="ant-notification-notice-message" + *ngIf="(thisService['serviceDomain'] == 'CCVPN' || thisService['serviceDomain'] == 'SOTN') && thisService.status == 'Failed'"> + {{ thisService['serviceDomain'] }} {{"i18nTextDefine_InstanceTeminationFailed" | + translate}} + </div> + <div class="ant-notification-notice-message" + *ngIf="(thisService['serviceDomain'] == 'E2E Service') && thisService.status == 'Failed'">E2E + {{"i18nTextDefine_InstanceTeminationFailed" | translate}} + </div> + <div class="ant-notification-notice-message" + *ngIf="(thisService['serviceDomain'] == 'Network Service') && thisService.status == 'Failed'"> + NS {{"i18nTextDefine_InstanceTeminationFailed" | translate}} + </div> + <div class="ant-notification-notice-description"> + <div class="notificationlist"> + <p> {{"i18nTextDefine_InstanceName" | translate}} :</p> + <span>{{ thisService["service-instance-name"] || + thisService["nsInstanceName"] }} + </span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_Customer" | translate}} :</p> + <span>{{ customerSelected.name }}</span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_UseCase" | translate}} :</p> + <span>{{ thisService["serviceDomain"] }}</span> + </div> + </div> + <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> + </div> + </div> + </ng-template> + <ng-template #templateScaleSuccessFaild> + <div class="ant-notification-notice-content"> + <div class="ant-notification-notice-with-icon"> + <span class="ant-notification-notice-icon"> + <img src="assets/images/execute-success.png" alt="instance temination is starting" + *ngIf="thisService.status == 'Successful'"> + <img src="assets/images/execute-faild.png" alt="instance temination is starting" + *ngIf="thisService.status == 'Failed'"> + </span> + <div class="ant-notification-notice-message" *ngIf="thisService.status == 'Successful'">E2E + {{"i18nTextDefine_InstanceScaledSuccessfully" | translate}} + </div> + <div class="ant-notification-notice-message" *ngIf="thisService.status == 'Failed'">E2E + {{"i18nTextDefine_InstanceScaleFailed" | translate}} + </div> + <div class="ant-notification-notice-description"> + <div class="notificationlist"> + <p> {{"i18nTextDefine_InstanceName" | translate}} :</p> + <span>{{ thisService["service-instance-name"] || + thisService["nsInstanceName"] }} + </span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_Customer" | translate}} :</p> + <span>{{ customerSelected.name }}</span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_UseCase" | translate}} :</p> + <span>{{ thisService["serviceDomain"] }}</span> + </div> + </div> + <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> + </div> + </div> + </ng-template> + <ng-template #templatehealSuccessFaild> + <div class="ant-notification-notice-content"> + <div class="ant-notification-notice-with-icon"> + <span class="ant-notification-notice-icon"> + <img src="assets/images/execute-success.png" alt="instance temination is starting" + *ngIf="thisService.status == 'Successful'"> + <img src="assets/images/execute-faild.png" alt="instance temination is starting" + *ngIf="thisService.status == 'Failed'"> + </span> + <div class="ant-notification-notice-message" *ngIf="thisService.status == 'Successful'">NS + {{"i18nTextDefine_InstanceHealedSuccessfully" | translate}} + </div> + <div class="ant-notification-notice-message" *ngIf="thisService.status == 'Failed'">NS + {{"i18nTextDefine_InstanceHealingFailed" | translate}} + </div> + <div class="ant-notification-notice-description"> + <div class="notificationlist"> + <p> {{"i18nTextDefine_InstanceName" | translate}} :</p> + <span>{{ thisService["service-instance-name"] || + thisService["nsInstanceName"] }} + </span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_Customer" | translate}} :</p> + <span>{{ customerSelected.name }}</span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_UseCase" | translate}} :</p> + <span>{{ thisService["serviceDomain"] }}</span> + </div> + </div> + <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> + </div> + </div> + </ng-template> + <ng-template #templateUpdateSuccessFaild> + <div class="ant-notification-notice-content"> + <div class="ant-notification-notice-with-icon"> + <span class="ant-notification-notice-icon"> + <img src="assets/images/execute-success.png" alt="instance temination is starting" + *ngIf="thisService.status == 'Successful'"> + <img src="assets/images/execute-faild.png" alt="instance temination is starting" + *ngIf="thisService.status == 'Failed'"> + </span> + <div class="ant-notification-notice-message" *ngIf="thisService.status == 'Successful'">CCVPN + {{"i18nTextDefine_InstanceUpdatedSuccessfully" | translate}} + </div> + <div class="ant-notification-notice-message" *ngIf="thisService.status == 'Failed'">CCVPN + {{"i18nTextDefine_InstanceUpdateFailed" | translate}} + </div> + <div class="ant-notification-notice-description"> + <div class="notificationlist"> + <p> {{"i18nTextDefine_InstanceName" | translate}} :</p> + <span>{{ thisService["service-instance-name"] || + thisService["nsInstanceName"] }} + </span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_Customer" | translate}} :</p> + <span>{{ customerSelected.name }}</span> + </div> + <div class="notificationlist"> + <p> {{"i18nTextDefine_UseCase" | translate}} :</p> + <span>{{ thisService["serviceDomain"] }}</span> + </div> + </div> + <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div> + </div> + </div> + </ng-template> + </div> + <div class="detailComponent" *ngIf="detailshow"> + <app-ccvpn-detail [detailParams]="detailData" [upDateShow]="upDateShow" + (closeUpdate)="closeCCVPNUpdate($event,templateUpdateSuccessFaild)" + (closeDetail)="detailshow = false;listDisplay = false;"></app-ccvpn-detail> + </div> + <div class="detailComponent" *ngIf="detailshow2"> + <app-e2e-detail [detailParams]="detailData" (closeDetail)="detailshow2 = false;listDisplay = false;"> + </app-e2e-detail> + </div> + <div class="createComponent" *ngIf="createshow"> + <app-ccvpn-creation [createParams]="createData" [ccvpn_temParametersContent]="ccvpn_temParametersContent" + (closeCreate)="closeCreate($event,templateCreatestarting,templateCreateSuccessFaild)"> + </app-ccvpn-creation> + </div> + <div class="createComponent" *ngIf="createshow2"> + <app-e2e-creation [createParams]="createData" [e2e_ns_temParametersContent]="e2e_ns_temParametersContent" + (nsCloseCreate)="nsCloseCreate($event,templateCreatestarting,templateCreateSuccessFaild)" + (e2eCloseCreate)="e2eCloseCreate($event,templateCreatestarting,templateCreateSuccessFaild)"> + </app-e2e-creation> + </div> + <!--</div>--> +</nz-layout> +<div class="loading" *ngIf="loadingAnimateShow"> + <img src="assets/images/loading-animate2.gif" alt="loading"> + <p>Please wating……</p> +</div>
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/services/services-list/services-list.component.less b/usecaseui-portal/src/app/views/services/services-list/services-list.component.less new file mode 100644 index 00000000..392d1b3a --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/services-list.component.less @@ -0,0 +1,380 @@ +/* + Copyright (C) 2019 CMCC, Inc. and others. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +.title { + font: 700 18px/18px "思源黑体"; + color: #4c5e70; + margin-bottom: 18px; +} +hr { + border: none; + height: 2px; + background-color: #dce1e7; + margin-bottom: 20px; +} +.ant-tabs-bar{ + margin-bottom: 0!important; +} +.mask{ + width: 100%; + height: 100%; + position: absolute; + z-index: 999; + background: rgba(0, 0, 0, 0.65); + top:0; +} +.loading{ + width: 100%; + height: 100%; + position: fixed; + top: 0; + margin-top: -50px; + margin-left: -50px; + z-index: 1001; + text-align: center; + background: transparent; + p{ + color: #0DA9E2; + text-align: center; + position: absolute; + width: 300px; + height: 30px; + line-height: 30px; + top: 71%; + left: 36%; + margin-top: -150px; + margin-left: -150px; + } + img{ + width: 300px; + height: 300px; + position: absolute; + top: 50%; + left: 36%; + margin-top: -150px; + margin-left: -150px; + } +} +.action { + margin-bottom: 15px; + padding: 28px; + background: #ffffff; + position: relative; + span { + display: inline-block; + font: 700 14px "Arial"; + color: #3C4F8C; + margin-right: 5px; + } + nz-dropdown { + vertical-align: middle; + background-color:#ffffff; + :hover{ + border-color: #48C6EF; + } + button { + width: 165px; + height: 42px; + background-color:#ffffff; + text-align: left; + border-color: #EEEEEE; + span { + font-weight: 400; + color: #3C4F8C; + display: inline-block; + width: 120px; + overflow: hidden; + text-overflow: ellipsis; + padding-top: 2px; + } + i { + position: absolute; + top: 10px; + right: 10px; + } + } + } + //The style in the drop-down box is in style.less, and the drop-down box is extra temporary generated in the body. + .create { + position: absolute; + right: 3%; + top:50%; + width:116px; + height:42px; + background:#0DA9E2; + border-radius:6px; + margin-top: -15px; + span { + color: #fff; + font-weight: 400; + font-size: 18px; + } + .anticon-plus-circle-o{ + font-size: 18px; + } + } + .create.ant-btn.ant-btn-primary{ + border: none; + } + .create:hover{ + background:#09C6E2; + } + +} +.top-num{ + overflow: auto; + width: 100%; +} +.top-list{ + position: relative; + width:29%; + height:170px; + margin: 10px 1%; + float: left; + background:url("../../../../assets/images/servicelist-e2e.png") no-repeat; + background-size: 100% 100%; + border-radius:2px; +} +.top-num .top-list:nth-child(2){ + background:url("../../../../assets/images/servicelist-e2e.png") no-repeat; + background-size: 100% 100%; +} +.top-num .top-list:nth-child(3){ + background:url("../../../../assets/images/servicelist-e2e.png") no-repeat; + background-size: 100% 100%; +} +.top-num .top-list:nth-child(4){ + background:url("../../../../assets/images/servicelist-sotn.png") no-repeat; + background-size: 100% 100%; +} +.top-list .round{ + position: absolute; + width: 60px; + height: 60px; + line-height: 60px; + text-align: center; + top:45%; + left: 50px; + margin-top: -30px; + background:#E0EDFF; + border:2px solid rgba(224,237,255,1); + border-radius: 50%; + font-size:16px; + font-family:ArialMT; + color:#3C4F8C; +} +.top-list { + .top-list-text { + position: absolute; + text-align: right; + height: 40px; + line-height: 20px; + right: 50px; + color: #fff; + p { + font-size: 14px; + width: 250px; + margin: 15px 0 0 0; + height: 13px; + clear: both; + span { + display: inline-block; + font-weight: 500; + text-align: right; + float: right; + } + span:nth-child(1) { + font-size: 18px; + width: 40px; + min-width: 40px; + } + span:nth-child(2) { + width: 85px; + font-size: 16px; + } + } + p:nth-child(1) { + margin-top: 25px; + } + } + .service-description{ + font-size: 14px; + width: 250px; + height: 13px; + position: absolute; + bottom: 30px; + left: 50px; + color: #3C4F8C; + } +} +.list { + background-color: #fff; + border-radius: 5px; + padding: 10px; + nz-table { + tbody { + td { + position: relative; + span.active { + font-size: 14px; + color: #147dc2; + } + span.closed { + font-size: 14px; + color: red; + } + span.onboarding{ + font-size: 12px; + color: #147dc2; + } + span.updating{ + font-size: 12px; + color: blue; + } + span.deleting { + font-size: 12px; + color: red; + } + span.creating { + font-size: 12px; + color: green; + } + span.scaling { + font-size: 12px; + color: purple; + } + span.healing { + font-size: 12px; + color: orangered; + } + i.anticon { + cursor: pointer; + font-size: 18px; + padding: 2px; + &:hover{ + color: #147dc2; + } + } + .cannotclick { + pointer-events: none; + color: #aaa; + opacity: 0.6; + } + .icon-more{ + position: absolute; + width: 115px; + height: 90px; + top:50px; + padding:15px 0 0 15px; + background: #ffffff; + z-index: 2; + border-radius: 5px; + box-shadow: 0px 10px 15px 2px rgba(247, 247, 247, 0.5); + li{ + margin-bottom:10px; + line-height: 20px; + text-align: left; + cursor: pointer; + .anticon{ + width: 18px; + height: 18px; + background: url("../../../../assets/images/scale.png") no-repeat; + } + .anticon.anticon-update{ + background: url("../../../../assets/images/update.png") no-repeat; + } + span{ + margin-left: 5px; + } + } + li:hover{ + color: #0DA9E2; + .anticon{ + background: url("../../../../assets/images/scale-active.png") no-repeat; + } + .anticon.anticon-update{ + background: url("../../../../assets/images/update-active.png") no-repeat; + } + } + } + } + tr.childtr { + td { + font-size: 12px; + color: #147dc2; + } + } + } + } +} + + +.detailComponent { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100vh; + background-color: #f3f3f3; + overflow-y: auto; + z-index: 3; +} +.createComponent { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100vh; + background-color: #F7F8FC; + overflow-y: auto; + z-index: 3; +} + +.e2eColor,.nsColor,.ccvpnColor,.sotnColor,.voLTEColor{ + width:120px; + height: 34px; + line-height: 34px; + margin-bottom: 0!important; + text-align: center; + background:rgba(158, 158, 158, 0.38); + border-radius:4px +} + +.vnfColor,.siteColor,.SDWANColor{ + color:rgba(60,79,140,0.5); + width:120px; + height: 34px; + line-height: 34px; + margin-bottom: 0!important; + text-align: center; + background:rgba(238,238,238,1); + border-radius:4px; +} + +.select-list{ + width: 320px; + height: 32px; + line-height: 32px; + margin: 35px auto; +} +.select-list>span{ + text-align: right; + width: 110px!important; + line-height: 32px; +} + +.listdisplay{ + display: none; +}
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/services/services-list/services-list.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/services-list.component.spec.ts new file mode 100644 index 00000000..61440dc3 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/services-list.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ServicesListComponent } from './services-list.component'; + +describe('ServicesListComponent', () => { + let component: ServicesListComponent; + let fixture: ComponentFixture<ServicesListComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ServicesListComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ServicesListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/usecaseui-portal/src/app/views/services/services-list/services-list.component.ts b/usecaseui-portal/src/app/views/services/services-list/services-list.component.ts new file mode 100644 index 00000000..c15e9f11 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services-list/services-list.component.ts @@ -0,0 +1,1410 @@ +/* + Copyright (C) 2019 CMCC, Inc. and others. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +import { Component, OnInit, HostBinding, TemplateRef } from '@angular/core'; +import { MyhttpService } from '../../../core/services/myhttp.service'; +import { slideToRight } from '../../../animates'; +import { NzModalService } from 'ng-zorro-antd'; +import { NzNotificationService } from 'ng-zorro-antd'; + +@Component({ + selector: 'app-services-list', + templateUrl: './services-list.component.html', + styleUrls: ['./services-list.component.less'], + animations: [slideToRight] +}) +export class ServicesListComponent implements OnInit { + @HostBinding('@routerAnimate') routerAnimateState; + + constructor(private myhttp: MyhttpService, private modalService: NzModalService, private notification: NzNotificationService) { + } + + ngOnInit() { + this.getallCustomers(); + } + + // customer servicetype + isSol005Interface = false; + orchestratorList = []; + customerList = []; + customerList2 = []; + customerSelected = { name: null, id: null }; + customerSelected2 = { name: null, id: null }; + serviceTypeList = []; + serviceTypeList2 = []; + serviceTypeSelected = { name: '' }; + serviceTypeSelected2 = { name: '' }; + serviceTypeSelectedName = ""; + templateTypeSelected = "CCVPN"; + orchestratorSelected = { name: null, id: null }; + listSortMasters = JSON.parse(sessionStorage.getItem('listSortMasters')); + language = sessionStorage.getItem("DefaultLang"); + iconMore = false; + loadingAnimateShow = false; + serviceMunber = [ // top: E2E/NS/CCVPN data + { + "serviceDomain": "E2E", + "Success": 0, + "failed": 0, + "InProgress": 0, + "detailName": "i18nTextDefine_End_To_End_Service" + }, + { + "serviceDomain": "NS", + "Success": 0, + "failed": 0, + "InProgress": 0, + "detailName": "i18nTextDefine_Network_Service" + }, + { + "serviceDomain": "CCVPN", + "Success": 0, + "failed": 0, + "InProgress": 0, + "detailName": "i18nTextDefine_Cross_Domain_and_Cross_Layer_VPN" + } + ]; + + //The icon behind each row of data in the table expands + iconMoreShow(data, tableData) { + tableData.map((its) => { + if (its["service-instance-id"] == data["service-instance-id"]) { + if (its["iconMore"] == false) { + data.iconMore = true; + } else if (its["iconMore"] == true) { + data.iconMore = false; + } + } else { + its["iconMore"] = false; + } + }) + } + + //Get all the customers + getallCustomers() { + console.log(this.language, "this.language"); + this.myhttp.getAllCustomers() + .subscribe((data) => { + this.customerList = data.map((item) => { + return { name: item["subscriber-name"], id: item["global-customer-id"] } + }); + if (this.customerList.length == 0) { + console.log("customerList.length == 0", this.customerList); + return false; + } + this.customerList2 = data.map((item) => { + return { name: item["subscriber-name"], id: item["global-customer-id"] } + }); + if (this.customerList2.length == 0) { + return false; + } + this.customerSelected = this.customerList[0]; + this.choseCustomer(this.customerSelected); + }) + } + + getallOrchestrators() { + this.myhttp.getAllOrchestrators() + .subscribe((data) => { + this.orchestratorList = data.map((item) => { + return { name: item["name"], id: item["name"] } + }); + if (this.orchestratorList.length == 0) { + console.log("orchestratorList.length == 0", this.orchestratorList); + return false; + } + this.orchestratorSelected = this.orchestratorList[0]; + }) + } + + choseCustomer(item) { + this.customerSelected = item; + this.myhttp.getServiceTypes(this.customerSelected) + .subscribe((data) => { + this.serviceTypeList = data.map((item) => { + return { name: item["service-type"] } + }); + + if (this.serviceTypeList.length == 0) { + console.log("serviceTypeList.length == 0", this.serviceTypeList); + return false; + } + + this.serviceTypeSelected = this.serviceTypeList[0]; + + this.choseServiceType(this.serviceTypeSelected); + }) + } + + choseServiceType(item) { + this.serviceTypeSelected = item; + this.getTableData(); + } + + + // Create modal box 2 (dialog box) create ------------------------------- + isVisible = false; + + customerChange(): void { + this.getServiceType(this.customerSelected2); + } + + getServiceType(customerSelected2) { + this.myhttp.getServiceTypes(customerSelected2) + .subscribe((data) => { + this.serviceTypeList2 = data.map((item) => { + return { name: item["service-type"] } + }); + if (this.serviceTypeList2.length == 0) { + console.log("serviceTypeList.length == 0", this.serviceTypeList2); + return false; + } + this.getAlltemplates(); + }) + } + + serviceTypeChange(): void { + this.serviceTypeSelected2.name = this.serviceTypeSelectedName + } + + createModal(): void { + this.isVisible = true; + this.getallOrchestrators(); + this.customerSelected2 = this.customerSelected; + this.serviceTypeSelectedName = this.serviceTypeSelected.name; + this.serviceTypeSelected2 = Object.assign({}, this.serviceTypeSelected); + this.getServiceType(this.customerSelected2); + } + + choseTemplateType() { + this.getallOrchestrators(); + this.getAlltemplates(); + } + + templates = []; + template1 = { name: null }; + + getAlltemplates() { + this.myhttp.getAllServiceTemplates(this.templateTypeSelected) + .subscribe((data) => { + this.templates = data; + if (this.templateTypeSelected == "Network Service") { + this.templates = data.filter((d) => { + return typeof d.packageInfo.csarName == "string"; + }).map((item) => { + let cName = item.packageInfo.csarName.split("/").reverse()[0]; + return { name: cName, id: item.csarId, packageInfo: item.packageInfo } + }); + } + this.template1 = this.templates[0]; + }, (err) => { + console.log(err); + }) + } + + createshow = false; + createshow2 = false; + listDisplay = false; + createData: Object = {}; + + handleOk(): void { + if (this.templateTypeSelected == "SOTN" || this.templateTypeSelected == "CCVPN") { + this.createData = { + commonParams: { + customer: this.customerSelected, + serviceType: this.serviceTypeSelected2, + templateType: this.templateTypeSelected + }, template: this.template1 + }; + } else if (this.templateTypeSelected == "E2E Service" || this.templateTypeSelected == "Network Service") { + this.createData = { + commonParams: { + customer: this.customerSelected, + serviceType: this.serviceTypeSelected2, + templateType: this.templateTypeSelected + }, + template: this.template1, + orchestrator: this.orchestratorSelected, + isSol005Interface: this.isSol005Interface + }; + } + this.getTemParameters(); + } + + handleCancel(): void { + this.isVisible = false; + this.loadingAnimateShow = false; + } + + temParametersTips = false; + ccvpn_temParametersContent: any; + e2e_ns_temParametersContent: any; + + getTemParameters() { + let chosedtemplates = this.createData["template"]; + let types = this.createData["commonParams"].templateType; + if (types == "E2E Service") { + types = "e2e"; + } else if (types == "Network Service") { + types = "ns"; + } + this.loadingAnimateShow = true; + this.myhttp.getTemplateParameters(types, chosedtemplates) + .subscribe((data) => { + this.loadingAnimateShow = false; + if (data.status == "FAILED") { + this.temParametersTips = true; + this.isVisible = true; + console.log("Template parsing Failed"); + } else { + this.isVisible = false; + this.temParametersTips = false; + if (this.templateTypeSelected == "SOTN" || this.templateTypeSelected == "CCVPN") { + this.ccvpn_temParametersContent = data; + this.createshow = true; + this.listDisplay = true; + } else if (this.templateTypeSelected == "E2E Service" || this.templateTypeSelected == "Network Service") { + this.e2e_ns_temParametersContent = data; + this.createshow2 = true; + this.listDisplay = true; + } + } + }) + } + + //tableData + tableData = []; + pageIndex = 1; + pageSize = 10; + total = 100; + loading = false; + + getTableData() { + this.loading = true; + // Query parameter: customer serviceType Current page number, number of pages per page + let paramsObj = { + customerId: this.customerSelected.id, + serviceType: this.serviceTypeSelected.name, + currentPage: this.pageIndex, + pageSize: this.pageSize + } + this.myhttp.getServicesTableData(paramsObj) + .subscribe((data) => { + this.total = data.body.total; + this.tableData = data.body.tableList.map((item) => { + if (typeof item == "string") { + item = JSON.parse(item); + } + + item["iconMore"] = this.iconMore; + if (item["serviceDomain"] == "Network Service") { + if (item["vnfInfo"]) { + item["childServiceInstances"] = item["vnfInfo"].map((vnf) => { + vnf["serviceDomain"] = "vnf"; + return vnf; + }); + } else if (item["relationship-list"] && item["relationship-list"]["relationship"]) { + item["childServiceInstances"] = item["relationship-list"]["relationship"].filter((relate) => { + return relate["related-to"] == "generic-vnf"; + }).map((vnf) => { + let vnfInfo = { + vnfNsInstanceId: "", + vnfInstanceId: "", + vnfInstanceName: "", + serviceDomain: "vnf" + }; + vnfInfo.vnfNsInstanceId = item["nsInstanceId"] || item["service-instance-id"]; + vnfInfo.vnfInstanceId = vnf["relationship-data"].find((vnfid) => { + return vnfid["relationship-key"] == "generic-vnf.vnf-id" + })["relationship-value"]; + vnfInfo.vnfInstanceName = vnf["related-to-property"].find((vnfname) => { + return vnfname["property-key"] == "generic-vnf.vnf-name" + })["property-value"]; + return vnfInfo; + }) + } + } else { + item["childServiceInstances"] = []; + } + + // + if (item["operationResult"] == "2001") { //operationResult==2001 + item["status"] = "Available"; + item["tips"] = "Available"; + item["statusClass"] = item["operationResult"]; + } + // 2018.12.13 + else if (item["operationResult"] == "2002") { //operationResult==2002 + if (item["operationType"] == "1001" || item["operationType"] == "1002") { + // item["status"] = this.accordingState["operationResult"][item["operationResult"]]; + item["status"] = this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == item["operationResult"] && its["language"] == this.language + })["sortValue"]; + item["tips"] = "Unavailable"; + item["statusClass"] = item["operationType"]; + } else if (item["operationType"] != "1001" && item["operationType"] != "1002") { + // item["status"] = this.accordingState["operationResult"][item["operationResult"]]; + item["status"] = this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == item["operationResult"] && its["language"] == this.language + })["sortValue"]; + item["tips"] = "Available"; + item["statusClass"] = item["operationType"]; + } + + } + else if (item["operationResult"] == "2003") { //operationResult==2003 + // item["status"] = this.accordingState["operationResult"][item["operationResult"]]; + item["status"] = this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == item["operationResult"] && its["language"] == this.language + })["sortValue"]; + item["statusClass"] = item["operationType"]; + if (item["serviceDomain"] == "Network Service") { + let updata = (prodata) => { + item["rate"] = prodata.progress; + item["tips"] = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == item["operationType"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + prodata.progress + "%"; + if (item["rate"] > 100) { + item["status"] = prodata.status; + item["tips"] = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == item["operationType"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + item["status"]; + } + } + let id = item["nsInstanceId"] || item["service-instance-id"]; + let jobid = item["jobId"] || item["operationId"]; + let operationType = item["operationType"]; + this.queryNsProgress(jobid, id, updata, operationType).then(() => { + item["rate"] = 100; + item["status"] = this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2001 && its["language"] == this.language + })["sortValue"]; + item["tips"] = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == item["operationType"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + item["status"]; + }) + } else { + let updata = (prodata) => { + item["rate"] = prodata.progress || item["rate"]; + item["tips"] = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == item["operationType"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + prodata.progress + "%"; + if (item["rate"] > 100) { + item["status"] = prodata.status; + item["tips"] = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == item["operationType"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + item["status"]; + } + } + let obj = { + serviceId: item["service-instance-id"], + operationId: item["operationId"], + operationType: item["operationType"] + } + this.queryProgress(obj, updata).then(() => { + item["rate"] = 100; + item["status"] = this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2001 && its["language"] == this.language + })["sortValue"]; + item["tips"] = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == item["operationType"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + item["status"]; + }) + } + } + return item; + }) + this.tableData.map((item, index) => { + if (item.serviceDomain == 'E2E Service') { + if (item.operationResult == 2001) { + this.serviceMunber[0]["Success"] += 1; + } else if (item.operationResult == 2002) { + this.serviceMunber[0]["failed"] += 1; + } else if (item.operationResult == 2003) { + this.serviceMunber[0]["InProgress"] += 1; + } + } + else if (item.serviceDomain == 'Network Service') { + if (item.operationResult == 2001) { + this.serviceMunber[1]["Success"] += 1; + } else if (item.operationResult == 2002) { + this.serviceMunber[1]["failed"] += 1; + } else if (item.operationResult == 2003) { + this.serviceMunber[1]["InProgress"] += 1; + } + } + else if (item.serviceDomain == 'CCVPN') { + if (item.operationResult == 2001) { + this.serviceMunber[2]["Success"] += 1; + } else if (item.operationResult == 2002) { + this.serviceMunber[2]["failed"] += 1; + } else if (item.operationResult == 2003) { + this.serviceMunber[2]["InProgress"] += 1; + } + } + }) + this.loading = false; + }, (err) => { + console.log(err); + this.loading = false; + }) + } + + searchData(reset: boolean = false) { + this.getTableData(); + } + + thisService = {}; //The current service of the operation + e2e_nsData: Object[]; + scaleModelVisible = false; + + scaleService(service) { + this.thisService = service; + this.scaleModelVisible = true; + let paramsObj = { + customerId: this.customerSelected.id, + serviceType: this.serviceTypeSelected.name, + serviceId: service["service-instance-id"] + } + this.myhttp.getE2e_nsData(paramsObj) + .subscribe((data) => { + this.e2e_nsData = data; + }) + } + + scaleOk(templatescalestarting, templateScaleSuccessFaild) { + this.scaleModelVisible = false; + let requestBody = { + "service": { + "serviceInstanceName": this.thisService["service-instance-name"], + "serviceType": this.serviceTypeSelected.name, + "globalSubscriberId": this.customerSelected.id, + "resources": this.e2e_nsData.map((item) => { + return { + "resourceInstanceId": item["netWorkServiceId"], + "scaleType": item["scaleType"], + "scaleNsData": { + "scaleNsByStepsData": { + "aspectId": item["aspectId"], + "numberOfSteps": item["numberOfSteps"], + "scalingDirection": item["scalingDirection"] + } + } + } + }) + } + } + this.scaleE2eService(this.thisService, requestBody, templateScaleSuccessFaild); + this.scaleNotification(templatescalestarting); + } + + scaleCancel() { + this.scaleModelVisible = false; + } + + scaleNotification(template: TemplateRef<{}>): void { + this.notification.template(template); + } + + scaleSuccessNotification(template: TemplateRef<{}>): void { + this.notification.template(template); + } + + //heal + healModelVisible = false; + healActions = []; + nsAdditional = []; + nsParams = { + degreeHealing: "HEAL_RESTORE", + actionsHealing: [], + healScript: "", + additionalParamsforNs: "" + } + vnfVms = []; + vmSelected = {}; + vnfParams = { + vnfInstanceId: "", + cause: "", + additionalParams: { + action: "", + actionvminfo: { + vmid: "", + vduid: "", + vmname: "" + } + } + } + + addActionsHealing() { + this.healActions.push({ value: "" }) + } + + minusActionsHealing(index) { + this.healActions.splice(index, 1); + } + + addNsAdditional() { + this.nsAdditional.push({ key: "", value: "" }) + } + + minusNsAdditional(index) { + this.nsAdditional.splice(index, 1); + } + + healService(service) { + this.thisService = service; + this.healModelVisible = true; + if (service.serviceDomain == "vnf") { + this.vnfParams.vnfInstanceId = service.vnfInstanceId; + this.myhttp.getVnfInfo(service.vnfInstanceId) + .subscribe((data) => { + this.vnfVms = data.vnfVms; + this.vmSelected = this.vnfVms[0]; + }) + } + } + + healOk(templatehealstarting, templatehealSuccessFaild) { + this.healModelVisible = false; + // nsParams + this.nsParams.actionsHealing = this.healActions.map((item) => { + return item.value + }); + let additional = {}; + this.nsAdditional.forEach((item) => { + additional[item.key] = item.value; + }); + this.nsParams.additionalParamsforNs = JSON.stringify(additional); + // vnfParams + this.vnfParams.additionalParams.actionvminfo.vmid = this.vmSelected["vmId"]; + this.vnfParams.additionalParams.actionvminfo.vmname = this.vmSelected["vmName"]; + + let requestBody = this.thisService["serviceDomain"] == "Network Service" ? { healNsData: this.nsParams } : { healVnfData: this.vnfParams }; + this.healNsVnfService(this.thisService, requestBody, templatehealSuccessFaild); + this.healNotification(templatehealstarting); + } + + healCancel() { + this.healModelVisible = false; + } + + healNotification(template: TemplateRef<{}>): void { + this.notification.template(template); + } + + healSuccessNotification(template: TemplateRef<{}>): void { + this.notification.template(template); + } + + // show detail + detailshow = false; + detailshow2 = false; + upDateShow = false; + detailData: Object; + + serviceDetail(service, typeNum) { + service["siteSer"] = []; + service["sdwanSer"] = []; + service["customer"] = this.customerSelected; + service["serviceType"] = this.serviceTypeSelected; + + service.childServiceInstances.forEach((item) => { + if (item.serviceDomain == "SITE") { + service.siteSer.push(item); + } else if (item.serviceDomain == "SDWAN") { + service.sdwanSer.push(item); + } + }) + if (service["serviceDomain"] == 'CCVPN' || service["serviceDomain"] == 'SOTN') { + this.detailshow = true; + if (typeNum == 1) { + this.upDateShow = false; + } else { + this.upDateShow = true; + } + } else if (service["serviceDomain"] == 'E2E Service' || service["serviceDomain"] == 'Network Service') { + this.detailshow2 = true; + } + this.listDisplay = true; + this.detailData = service; + console.log(service); + } + + deleteModelVisible = false; + terminationType = "graceful"; + gracefulTerminationTimeout = 120; + + // delete Model show + deleteModel(service) { + this.thisService = service; + this.deleteModelVisible = true; + } + + deleteOk(templatedeletestarting, templateDeleteSuccessFaild) { + this.deleteModelVisible = false; + this.loadingAnimateShow = true; + if (this.thisService["serviceDomain"] == "Network Service") { + this.deleteNsService(this.thisService, templateDeleteSuccessFaild); + } else { + this.deleteService(this.thisService, templateDeleteSuccessFaild); + } + this.deleteNotification(templatedeletestarting); + } + + deleteCancel() { + this.deleteModelVisible = false; + } + + deleteNotification(template: TemplateRef<{}>): void { + this.notification.template(template); + } + + deleteSuccessNotification(template: TemplateRef<{}>): void { + this.notification.template(template); + } + + createNotification(template: TemplateRef<{}>): void { + this.notification.template(template); + } + + createSuccessNotification(template: TemplateRef<{}>): void { + this.notification.template(template); + } + + //ccvpn sotn createservice + parentServiceInstanceId = ""; + thisCreateService = {}; + + closeCreate(obj, templateCreatestarting, templateCreateSuccessFaild) { + if (!obj) { + this.createshow = false; //close + this.listDisplay = false; //close + return false; + } + this.createshow = false; + this.listDisplay = false; + this.loadingAnimateShow = true; + console.log(obj); + let newData; //Newly created service data for the main table + + let createParams = "?customerId=" + this.customerSelected2.id + + "&serviceType=" + this.serviceTypeSelected2.name + + "&serviceDomain=" + this.templateTypeSelected; + this.createService(obj, createParams, templateCreatestarting, templateCreateSuccessFaild).then((data) => { + console.log(data); + this.loadingAnimateShow = false; + newData = { //Newly created service data in the main form + 'service-instance-id': data["serviceId"], + 'service-instance-name': obj.service.name, + serviceDomain: this.templateTypeSelected, + childServiceInstances: [], + status: "In Progress", + rate: 0, + statusClass: 1001, + tips: "" + }; + this.thisCreateService = newData; + this.tableData = [newData, ...this.tableData]; + this.createNotification(templateCreatestarting); + let updata = (prodata) => { + newData.rate = prodata.progress; + newData.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == newData["statusClass"] && its["language"] == this.language + })["sortValue"] + newData.rate + "%"; + if (newData["rate"] > 100) { + newData["status"] = prodata.status; + newData.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == newData["statusClass"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + newData["status"]; + } + }; + let queryParams = { serviceId: data["serviceId"], operationId: data["operationId"], operationType: "1001" }; + return this.queryProgress(queryParams, updata); + }).then((data) => { + console.log(data); + newData.rate = 100; + newData.status = "Successful"; + this.createSuccessNotification(templateCreateSuccessFaild); + newData.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == newData["statusClass"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2001 && its["language"] == this.language + })["sortValue"]; + let hasUndone = this.tableData.some((item) => { + return item.rate < 100; + }); + if (!hasUndone) { + setTimeout(() => { + this.getTableData(); + }, 1000) + } + }) + } + + e2eCloseCreate(obj, templateCreatestarting, templateCreateSuccessFaild) { + if (!obj) { + this.createshow2 = false; // + this.listDisplay = false; // + return false; + } + this.createshow2 = false; // + this.listDisplay = false; // + this.loadingAnimateShow = true; + console.log(obj); + let newData; // + let createParams = "?customerId=" + this.customerSelected.id + + "&serviceType=" + this.serviceTypeSelected2.name + + "&serviceDomain=" + this.templateTypeSelected + + "&parentServiceInstanceId=" + + "&uuid=" + obj.service.serviceUuid + + "&invariantUuuid=" + obj.service.serviceInvariantUuid; + this.createService(obj, createParams, templateCreatestarting, templateCreateSuccessFaild).then((data) => { + console.log(data); + this.loadingAnimateShow = false; + newData = { // + 'service-instance-id': data["serviceId"], + 'service-instance-name': obj.service.name, + serviceDomain: this.templateTypeSelected, + childServiceInstances: [], + status: "In Progress", + statusClass: 1001, + rate: 0, + tips: "" + } + this.thisCreateService = newData; + this.tableData = [newData, ...this.tableData]; + this.createNotification(templateCreatestarting); + let updata = (prodata) => { + newData.rate = prodata.progress; + newData.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == newData["statusClass"] && its["language"] == this.language + })["sortValue"] + newData.rate + "%"; + if (newData["rate"] > 100) { + newData["status"] = prodata.status; + newData.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == newData["statusClass"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + newData["status"]; + } + } + let queryParams = { serviceId: data["serviceId"], operationId: data["operationId"], operationType: "1001" }; + return this.queryProgress(queryParams, updata); + }).then((data) => { + console.log(data); + newData.rate = 100; + newData.status = "Successful"; + this.createSuccessNotification(templateCreateSuccessFaild); + newData.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == newData["statusClass"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2001 && its["language"] == this.language + })["sortValue"]; + let hasUndone = this.tableData.some((item) => { + return item.rate < 100; + }) + if (!hasUndone) { + setTimeout(() => { + this.getTableData(); + }, 1000) + } + }) + + } + + nsCloseCreate(obj, templateCreatestarting, templateCreateSuccessFaild) { + if (!obj) { + this.createshow2 = false; // + this.listDisplay = false; // + return false; + } + this.createshow2 = false; // + this.listDisplay = false; // + this.loadingAnimateShow = true; + console.log(obj); + let newData; // + // step1 + this.myhttp.nsCreateInstance(obj.step1) + .subscribe((data) => { + // console.log(data); + this.loadingAnimateShow = false; + newData = { // + 'service-instance-id': data.nsInstanceId, + 'service-instance-name': obj.step1.nsName, + serviceDomain: this.templateTypeSelected, + childServiceInstances: [], + status: "In Progress", + statusClass: 1001, + rate: 0, + tips: "" + } + this.thisCreateService = newData; + this.tableData = [newData, ...this.tableData]; + this.createNotification(templateCreatestarting); + if (data.status == "FAILED") { + console.log("create ns service Failed :" + JSON.stringify(data)); + newData.status = "Failed"; + this.createSuccessNotification(templateCreateSuccessFaild); + return false; + } + let createParams = "?ns_instance_id=" + data.nsInstanceId + + "&customerId=" + this.customerSelected2.id + + "&serviceType=" + this.serviceTypeSelected2.name + + "&serviceDomain=" + this.templateTypeSelected + + "&parentServiceInstanceId="; + // step2 + this.createNsService(createParams, obj.step2).then((jobid) => { + if (jobid == "Failed") { + newData.status = "Failed"; + console.log(jobid, "ns two jobid") + this.thisCreateService = newData; + console.log(this.thisCreateService) + this.createSuccessNotification(templateCreateSuccessFaild); + newData.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == newData["statusClass"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2002 && its["language"] == this.language + })["sortValue"]; + return false; + } + let operationType = "1001"; + let updata = (prodata) => { + newData.rate = prodata.progress; + newData.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == newData["statusClass"] && its["language"] == this.language + })["sortValue"] + newData.rate + "%"; + if (newData["rate"] > 100) { + newData["status"] = prodata.status; + newData.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == newData["statusClass"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + newData["status"]; + } + } + + return this.queryNsProgress(jobid, newData["service-instance-id"], updata, operationType); + }).then((data) => { + console.log(data); + newData.rate = 100; + newData.status = "Successful"; + this.thisCreateService = newData; + console.log(this.thisCreateService) + this.createSuccessNotification(templateCreateSuccessFaild); + newData.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == newData["statusClass"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2001 && its["language"] == this.language + })["sortValue"]; + let hasUndone = this.tableData.some((item) => { + return item.rate < 100; + }) + if (!hasUndone) { + setTimeout(() => { + this.getTableData(); + }, 1000) + } + }) + }) + } + + createService(requestBody, createParams, templateCreatestarting, templateCreateSuccessFaild) { + let mypromise = new Promise((res, rej) => { + this.myhttp.createInstance(requestBody, createParams) + .subscribe((data) => { + if (data.status == "FAILED") { + this.loadingAnimateShow = false; + res("Failed"); + console.log("create e2e service Failed :" + JSON.stringify(data)); + return false; + } + res(data.service); + }) + }) + return mypromise; + } + + createNsService(id, obj) { + let mypromise = new Promise((res, rej) => { + this.myhttp.nsCreateInstance2(id, obj) + .subscribe((data) => { + if (data.status == "FAILED") { + this.loadingAnimateShow = false; + console.log("instantiate ns service Failed :" + JSON.stringify(data)); + res("Failed"); + return false; + } + res(data.jobId); + }) + }) + return mypromise; + } + + scaleE2eService(service, requestBody, templateScaleSuccessFaild) { + let id = service["service-instance-id"]; + service.rate = 0; + service.status = "In Progress"; + service.statusClass = "1003"; + service.tips = ""; + this.myhttp.scaleE2eService(id, requestBody) + .subscribe((data) => { + if (data.status == "FAILED") { + console.log("scale E2e service Failed :" + JSON.stringify(data)); + service.status = "Failed"; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2002 && its["language"] == this.language + })["sortValue"]; + this.scaleSuccessNotification(templateScaleSuccessFaild); + return false; + } + let obj = { + serviceId: id, + operationId: data.operationId, + operationType: "1003" + } + let updata = (prodata) => { + service.rate = prodata.progress; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + service["rate"] + "%"; + if (service["rate"] > 100) { + service["status"] = prodata.status; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service["statusClass"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + service["status"]; + } + } + this.queryProgress(obj, updata).then(() => { + service.rate = 100; + service.status = "Successful"; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service["statusClass"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2001 && its["language"] == this.language + })["sortValue"]; + this.scaleSuccessNotification(templateScaleSuccessFaild); + }) + }) + } + + healNsVnfService(service, requestBody, templatehealSuccessFaild) { + console.log(service); + service.rate = 0; + service.status = "In Progress"; + service.tips = ""; + service.statusClass = "1004"; + let id = service.nsInstanceId || service["service-instance-id"] || service["vnfNsInstanceId"]; + this.myhttp.healNsService(id, requestBody) + .subscribe((data) => { + if (data.status == "FAILED") { + console.log("heal nsvnf service Failed :" + JSON.stringify(data)); + service.status = "Failed"; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2002 && its["language"] == this.language + })["sortValue"]; + this.healSuccessNotification(templatehealSuccessFaild); + return false; + } + let jobid = data.jobId; + let operationType = "1004"; + let updata = (prodata) => { + service.rate = prodata.progress; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + service.rate + "%"; + console.log(service.rate) + if (service["rate"] > 100) { + service["status"] = prodata.status; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + service["status"]; + } + } + this.queryNsProgress(jobid, null, updata, operationType).then((data1) => { + console.log(data1); + service.rate = 100; + service.status = "Successful"; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2001 && its["language"] == this.language + })["sortValue"]; + this.healSuccessNotification(templatehealSuccessFaild); + }); + }) + } + + updateCcvpnNotification(template: TemplateRef<{}>): void { + this.notification.template(template); + } + + updateCcvpnSuccessNotification(template: TemplateRef<{}>): void { + this.notification.template(template); + } + + closeCCVPNUpdate(obj, templateUpdateSuccessFaild) { + console.log(obj); + this.detailshow = false; + this.listDisplay = false; + this.upDateShow = false; + this.detailData["rate"] = 0; + this.detailData["status"] = "In Progress"; + this.detailData['tips'] = ""; + this.detailData["statusClass"] = "1005"; + let id = this.detailData["service-instance-id"]; + this.myhttp.updateccvpn(id, obj) + .subscribe((data) => { + if (data.status == "FAILED") { + console.log("scale E2e service Failed :" + JSON.stringify(data)); + this.detailData["status"] = "Failed"; + this.detailData["tips"] = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == this.detailData["statusClass"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2002 && its["language"] == this.language + })["sortValue"]; + this.updateCcvpnSuccessNotification(templateUpdateSuccessFaild); + return false; + } + let obj = { + serviceId: id, + operationId: data.operationId + } + let updata = (prodata) => { + this.detailData["rate"] = prodata.progress; + this.detailData["tips"] = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == this.detailData["statusClass"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + this.detailData["rate"] + "%"; + if (this.detailData["rate"] > 100) { + this.detailData["status"] = prodata.status; + this.detailData["tips"] = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == this.detailData["statusClass"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + this.detailData["status"]; + } + }; + this.queryProgress(obj, updata).then(() => { + this.detailData["rate"] = 100; + this.detailData["status"] = "Successful"; + this.detailData["tips"] = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == this.detailData["statusClass"] && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2001 && its["language"] == this.language + })["sortValue"]; + this.updateCcvpnSuccessNotification(templateUpdateSuccessFaild); + }) + }) + } + + deleteService(service, templateDeleteSuccessFaild) { + let allprogress = {}; // + let querypros = []; // + service.rate = 0; + service.status = "In Progress"; + service.tips = ""; + service.statusClass = "1002"; + 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, + serviceInstanceId: item["service-instance-id"] + } + return new Promise((res, rej) => { + this.myhttp.deleteInstance(params) + .subscribe((data) => { + this.loadingAnimateShow = false; + if (data.status == "FAILED") { + console.log("delete service Failed :" + JSON.stringify(data)); + service.status = "Failed"; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2002 && its["language"] == this.language + })["sortValue"]; + return false; + } + let obj = { + serviceId: params.serviceInstanceId, + operationId: data.operationId, + operationType: "1002" + } + let updata = (prodata) => { + allprogress[prodata.operationId] = prodata.progress; + let average = ((arr) => { + return eval(arr.join("+")) / arr.length + })(Object.values(allprogress)); + service["rate"] = average; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + service["rate"] + "%"; + if (service["rate"] > 100) { + service["status"] = prodata.status; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + service["status"]; + } + }; + querypros.push(this.queryProgress(obj, updata)); + res(); + }) + }) + }); + Promise.all(deletePros).then(() => { + Promise.all(querypros).then((data) => { + console.log(data); + service.rate = 100; + service.status = "Successful"; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2001 && its["language"] == this.language + })["sortValue"]; + this.deleteSuccessNotification(templateDeleteSuccessFaild); + let hasUndone = this.tableData.some((item) => { + return item.rate < 100; + }) + if (!hasUndone) { + setTimeout(() => { + this.getTableData(); + }, 1000) + } + }) + }) + } + + deleteNsService(service, templateDeleteSuccessFaild) { + service.rate = 0; + service.status = "In Progress"; + service.tips = ""; + service.statusClass = "1002"; + let id = service.nsInstanceId || service["service-instance-id"]; + let operationType = "1002"; + let requestBody = { + terminationType: this.terminationType, + gracefulTerminationTimeout: this.gracefulTerminationTimeout + } + this.stopNsService(id, requestBody).then((jobid) => { + if (jobid == "Failed") { + service.status = "Failed"; + this.deleteSuccessNotification(templateDeleteSuccessFaild); + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2002 && its["language"] == this.language + })["sortValue"]; + return false; + } + let updata = (prodata) => { + service.rate = prodata.progress; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + '\xa0\xa0\xa0' + service.rate + "%"; + if (service["rate"] > 100) { + service["status"] = prodata.status; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + service["status"]; + } + } + return this.queryNsProgress(jobid, null, updata, operationType); + }).then(() => { + this.myhttp.nsDeleteInstance(id) + .subscribe((data) => { + console.log(data); + service.rate = 100; + service.status = "Successful"; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2001 && its["language"] == this.language + })["sortValue"]; + this.deleteSuccessNotification(templateDeleteSuccessFaild); + if (data.status == "FAILED") { + console.log("delete ns service Failed :" + JSON.stringify(data)); + service.status = "Failed"; + service.tips = this.listSortMasters["operationTypes"].find((its) => { + return its["sortCode"] == service.statusClass && its["language"] == this.language + })["sortValue"] + this.listSortMasters["operationResults"].find((its) => { + return its["sortCode"] == 2002 && its["language"] == this.language + })["sortValue"]; + this.deleteSuccessNotification(templateDeleteSuccessFaild); + return false; + } + console.log(service, "deleteservice"); + console.log(this.thisService, "thisService"); + let hasUndone = this.tableData.some((item) => { + return item.rate < 100; + }) + if (!hasUndone) { + setTimeout(() => { + this.getTableData(); + }, 1000) + } + }) + }) + } + + stopNsService(id, obj) { + let mypromise = new Promise((res, rej) => { + this.myhttp.stopNsService(id, obj) + .subscribe((data) => { + this.loadingAnimateShow = false; + if (data.status == "FAILED") { + console.log("stop ns service Failed :" + JSON.stringify(data)); + res("Failed"); + return false; + } + res(data.jobId); + }) + }) + return mypromise; + } + + queryProgress(obj, callback) { + let mypromise = new Promise((res, rej) => { + // let data = { + // operationStatus:{ + // "operationId": "XXXXXX", + // "operation": "create|delete|update|scale", + // "result": "finished|error|processing", + // "reason": "", + // "userId": "", + // "operationContent": "Be creating pop.", + // "progress": 0, + // "operateAt": "", + // "finishedAt": "" + // } + // } + let errorNums = 180; + let requery = () => { + this.myhttp.getProgress(obj) + .subscribe((data) => { + if (data.status == "FAILED") { + callback({ progress: 255, status: "Failed" }); + return false; + } + if (data.operationStatus == null || data.operationStatus.progress == undefined) { + // console.log(data); + errorNums--; + if (errorNums == 0) { + callback({ progress: 255, status: "time over" }); + return false; + } + setTimeout(() => { + requery(); + }, 10000) + return false; + } + if (data.operationStatus.progress > 100) { + callback({ progress: 255, status: "time over" }); + return false; + } + if (data.operationStatus.progress < 100) { + callback(data.operationStatus); + setTimeout(() => { + requery(); + }, 5000) + } else { + res(data.operationStatus); + } + }) + // setTimeout(()=>{ + // console.log(data.operationStatus.progress) + // data.operationStatus.progress++; + // if(data.operationStatus.progress<100){ + // callback(data.operationStatus); + // requery() + // }else{ + // callback(data.operationStatus); + // res(data.operationStatus) + // } + // },100) + } + requery(); + }) + return mypromise; + } + + queryNsProgress(jobid, id, callback, operationType) { + 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 errorNums = 180; + let requery = () => { + this.myhttp.getNsProgress(jobid, id, operationType) + .subscribe((data) => { + if (data.status == "FAILED") { + callback({ progress: 255, status: "Failed" }); + return false; + } + if (data.responseDescriptor == null || data.responseDescriptor.progress == undefined) { + // console.log(data); + errorNums--; + if (errorNums == 0) { + callback({ progress: 255, status: "time over" }); + return false; + } + setTimeout(() => { + requery(); + }, 10000) + return false; + } + if (data.responseDescriptor.progress > 100 && data.responseDescriptor.status == "error") { + callback({ progress: 255, status: data.responseDescriptor.statusDescription }); + return false; + } + if (data.responseDescriptor.progress < 100) { + callback(data.responseDescriptor); + setTimeout(() => { + requery(); + }, 5000) + } else { + res(data); + } + }) + // setTimeout(()=>{ + // console.log(data.responseDescriptor.progress) + // data.responseDescriptor.progress++; + // if(data.responseDescriptor.progress<100){ + // callback(data.responseDescriptor); + // requery() + // }else{ + // callback(data); + // res(data) + // } + // },100) + }; + requery(); + }); + return mypromise; + } + +} diff --git a/usecaseui-portal/src/app/views/services/services.component.html b/usecaseui-portal/src/app/views/services/services.component.html new file mode 100644 index 00000000..10142833 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services.component.html @@ -0,0 +1,18 @@ +<!-- + Copyright (C) 2019 CMCC, Inc. and others. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<p> + services works! +</p> diff --git a/usecaseui-portal/src/app/views/services/services.component.less b/usecaseui-portal/src/app/views/services/services.component.less new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services.component.less diff --git a/usecaseui-portal/src/app/views/services/services.component.spec.ts b/usecaseui-portal/src/app/views/services/services.component.spec.ts new file mode 100644 index 00000000..2e76b9f9 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ServicesComponent } from './services.component'; + +describe('ServicesComponent', () => { + let component: ServicesComponent; + let fixture: ComponentFixture<ServicesComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ServicesComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ServicesComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/usecaseui-portal/src/app/views/services/services.component.ts b/usecaseui-portal/src/app/views/services/services.component.ts new file mode 100644 index 00000000..eec235b4 --- /dev/null +++ b/usecaseui-portal/src/app/views/services/services.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-services', + templateUrl: './services.component.html', + styleUrls: ['./services.component.less'] +}) +export class ServicesComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} |