summaryrefslogtreecommitdiffstats
path: root/usecaseui-portal/src/app/views/services
diff options
context:
space:
mode:
Diffstat (limited to 'usecaseui-portal/src/app/views/services')
-rw-r--r--usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.html365
-rw-r--r--usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.less232
-rw-r--r--usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.ts662
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.css315
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.html276
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.spec.ts24
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.ts724
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.css359
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.html421
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.spec.ts69
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.ts797
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.html59
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.less59
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.spec.ts26
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.ts144
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.html34
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.less (renamed from usecaseui-portal/src/app/views/services/services.component.less)0
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.spec.ts25
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.ts42
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.css77
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.html139
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.less161
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.spec.ts25
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.ts357
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.html109
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.less142
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.spec.ts25
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.ts246
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.html72
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.less0
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.spec.ts25
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.ts68
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.html40
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.less0
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.spec.ts25
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.ts53
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/services-list.component.html474
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/services-list.component.less81
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/services-list.component.ts575
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.html18
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.less65
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.spec.ts (renamed from usecaseui-portal/src/app/views/services/services.component.spec.ts)12
-rw-r--r--usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.ts19
-rw-r--r--usecaseui-portal/src/app/views/services/services.component.html18
-rw-r--r--usecaseui-portal/src/app/views/services/services.component.ts15
45 files changed, 5744 insertions, 1730 deletions
diff --git a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.html b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.html
index 4f865ff3..c48d68f9 100644
--- a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.html
+++ b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.html
@@ -13,274 +13,111 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<nz-tabset [nzTabPosition]="'top'" [nzType]="'card'">
- <nz-tab *ngFor="let tab of tabs" [nzTitle]="tab" (nzClick)="handleTabChange(tab)">
- <!-- nsList -->
- <div class="list" *ngIf="tab === 'NS'">
- <div style="width:100%;height: 30%;margin-bottom: 1%">
- <div class="listupload">
- <nz-upload nzType="drag" [(nzFileList)]="fileListNS" [nzBeforeUpload]="beforeUploadNS">
- <p class="ant-upload-drag-icon">
- <i nz-icon type="inbox" class="anticon anticon-inbox"></i>
- </p>
- <p class="ant-upload-text"> {{"i18nTextDefine_Click_CSAR_File" | translate}} </p>
- <p class="ant-upload-hint"></p>
- </nz-upload>
- <button nz-button [nzLoading]="nsuploading" (click)="onClick(tab)" [disabled]="fileListNS.length == 0"
- style="margin-top: 16px;margin-left: 55px;color: #FFFFFF;font-size: 13px;background-color: #3E9BFF;font-family: ArialMT;">
- {{ nsuploading ? 'Uploading' : 'Start Upload' }}
- </button>
- </div>
- <div class="listlin"></div>
- <div class="listfile">
- <div style="color: rgba(66,84,143,1);font-family:ArialMT;padding-bottom: 15px;height: 15%"> {{"i18nTextDefine_Uploaded_files" | translate}} </div>
- <div class="nouploadfile">{{"i18nTextDefine_Nofileuploading" | translate}}</div>
- <div style="height:80%;overflow: auto">
- <div class="listfilebgc" *ngFor="let itemns of nsRightList">
- <div>
- <i class="anticon anticon-link"></i>
- </div>
- <div class="color" [ngClass]="{'progress':itemns.status == true}">{{itemns.name}}</div>
- <div class="color" *ngIf="itemns.status">
- <nz-progress [nzPercent]="itemns.progress" [nzShowInfo]="false"></nz-progress>
- </div>
- <div class="color" *ngIf="!itemns.status">
- <span *ngIf="itemns.success == 0">{{"i18nTextDefine_File_upload_completed" | translate}}</span>
- <span *ngIf="itemns.success == 1">{{"i18nTextDefine_File_upload_failed" | translate}}</span>
- </div>
- <div *ngIf="!itemns.status">
- <i class="anticon anticon-check-circle" *ngIf="itemns.success == 0" style="color:#7BC7F3!important;"></i>
- <i class="anticon anticon-exclamation-circle" *ngIf="itemns.success == 1" style="color:#fb5c5c!important;"></i>
- </div>
- </div>
- </div>
- </div>
- </div>
- <nz-spin [nzSpinning]="isSpinning" style="height: 69%">
- <div class="mask" *ngIf="isSpinning"></div>
- <nz-table #nzTable [nzData]="nstableData" nzShowSizeChanger [nzFrontPagination]="true"
- [nzShowQuickJumper]="true" [nzPageSizeOptions]="[5,10,15,20]" [nzTotal]='total' [(nzPageSize)]="nspageSize"
- [(nzPageIndex)]='nspageIndex' [nzLoading]="loading" nzSize="middle">
- <thead (nzSortChange)="sort($event)" nzSingleSort>
- <tr>
- <th nzWidth="15%"> {{"i18nTextDefine_NO" | translate}} </th>
- <th nzWidth="15%" nzShowSort nzSortKey="name"> {{"i18nTextDefine_Name" | translate}} </th>
- <th nzWidth="15%"> {{"i18nTextDefine_Version" | translate}} </th>
- <th nzWidth="15%"> {{"i18nTextDefine_OnboardingState" | translate}} </th>
- <th nzWidth="15%"> {{"i18nTextDefine_OperationalState" | translate}} </th>
- <th nzWidth="10%"> {{"i18nTextDefine_UsageState" | translate}} </th>
- <th nzWidth="15%"> {{"i18nTextDefine_Operationbutton" | translate}} </th>
- </tr>
- </thead>
- <tbody>
- <tr *ngFor="let item of nzTable.data; let i = index; ">
- <td>{{i+1}}</td>
-
- <td *ngIf="item.nsdName">{{item.nsdName}}</td>
- <td *ngIf="item.nsdName === null || item.nsdName === ''">&nbsp;</td>
- <td *ngIf="item.name">{{item.name}}</td>
- <td *ngIf="item.name===null || item.name=== ''">&nbsp;</td>
- <td *ngIf="item.nsdVersion">{{item.nsdVersion}}</td>
- <td *ngIf="item.nsdVersion === null || item.nsdVersion === ''">&nbsp;</td>
- <td *ngIf="item.version">{{item.version}}</td>
- <td *ngIf="item.version === null || item.version === ''">&nbsp;</td>
- <td>
- <span *ngIf="item.nsdOnboardingState">{{item.nsdOnboardingState}}</span>
- <span *ngIf="item.nsdOnboardingState === null || item.nsdOnboardingState === ''">&nbsp;</span>
- <span *ngIf="item.uuid">{{status}}</span>
-
- </td>
- <td>{{item.nsdOperationalState}}</td>
- <td>{{item.nsdUsageState}}</td>
- <td>
- <i [ngClass]="{'cannotclick':onboardData.status == 'onboarding' && i == currentIndex}"
- class="anticon anticon-upload upicon" #upload_icon (click)="updataNsService(item.uuid,i,notificationModel)"
- *ngIf="item.uuid"></i>
- <i class="anticon anticon-delete" nzType="info" (click)="showConfirm(i,item.id,tab,notificationModel)"
- *ngIf="item.id"></i>
-
- </td>
- </tr>
- </tbody>
- </nz-table>
- </nz-spin>
-
- </div>
- <!-- VNFList -->
- <div class="list" *ngIf="tab === 'VNF'">
- <div style="width:100%;height: 30%;margin-bottom: 1%">
- <div class="listupload">
- <nz-upload nzType="drag" [(nzFileList)]="fileListVNF" [nzBeforeUpload]="beforeUploadVNF">
- <p class="ant-upload-drag-icon">
- <i nz-icon type="inbox" class="anticon anticon-inbox"></i>
- </p>
- <p class="ant-upload-text">Click or drag CSAR File here</p>
- <p class="ant-upload-hint"></p>
- </nz-upload>
- <button nz-button [nzLoading]="vnfuploading" (click)="onClick(tab)" [disabled]="fileListVNF.length == 0"
- style="margin-top: 16px;margin-left: 55px;color: #FFFFFF;font-size: 13px;background-color: #3E9BFF;font-family: ArialMT;">
- {{ vnfuploading ? 'Uploading' : 'Start Upload' }}
- </button>
- </div>
- <div class="listlin"></div>
- <div class="listfile">
- <div style="color: rgba(66,84,143,1);font-family:ArialMT;padding-bottom: 15px;height: 15%"> {{"i18nTextDefine_Uploaded_files" | translate}} </div>
- <div class="nouploadfile">{{"i18nTextDefine_Nofileuploading" | translate}}</div>
- <div style="height:80%;overflow: auto">
- <div class="listfilebgc" *ngFor="let itemns of vnfRightList">
- <div>
- <i class="anticon anticon-link"></i>
- </div>
- <div class="color" [ngClass]="{'progress':itemns.status == true}">{{itemns.name}}</div>
- <div class="color" *ngIf="itemns.status">
- <nz-progress [nzPercent]="itemns.progress" [nzShowInfo]="false"></nz-progress>
- </div>
- <div class="color" *ngIf="!itemns.status">
- <span *ngIf="itemns.success == 0">{{"i18nTextDefine_File_upload_completed" | translate}}</span>
- <span *ngIf="itemns.success == 1">{{"i18nTextDefine_File_upload_failed" | translate}}</span>
- </div>
- <div *ngIf="!itemns.status">
- <i class="anticon anticon-check-circle" *ngIf="itemns.success == 0" style="color:#7BC7F3!important;"></i>
- <i class="anticon anticon-exclamation-circle" *ngIf="itemns.success == 1" style="color:#fb5c5c!important;"></i>
- </div>
- </div>
- </div>
- </div>
- </div>
- <nz-spin [nzSpinning]="isSpinning" style="height: 69%">
- <div class="mask" *ngIf="isSpinning"></div>
- <nz-table #nzTable [nzData]="vnftableData" nzShowSizeChanger [nzFrontPagination]="true"
- [nzShowQuickJumper]="true" [nzPageSizeOptions]="[5,10,15,20]" [nzTotal]='total' [(nzPageSize)]="vnfpageSize"
- [(nzPageIndex)]='vnfpageIndex' [nzLoading]="loading" nzSize="middle">
- <thead (nzSortChange)="sort($event)" nzSingleSort>
- <tr>
- <th nzWidth="15%"> {{"i18nTextDefine_NO" | translate}} </th>
- <th nzWidth="15%" nzShowSort nzSortKey="name"> {{"i18nTextDefine_Name" | translate}} </th>
- <th nzWidth="15%"> {{"i18nTextDefine_Version" | translate}} </th>
- <th nzWidth="15%"> {{"i18nTextDefine_OnboardingState" | translate}} </th>
- <th nzWidth="15%"> {{"i18nTextDefine_OperationalState" | translate}} </th>
- <th nzWidth="10%"> {{"i18nTextDefine_UsageState" | translate}} </th>
- <th nzWidth="15%"> {{"i18nTextDefine_Operationbutton" | translate}} </th>
- </tr>
- </thead>
- <tbody>
- <tr *ngFor="let item of nzTable.data; let i = index; ">
- <td>{{i+1}}</td>
- <td *ngIf="item.vnfProductName">{{item.vnfProductName}}</td>
- <td *ngIf="item.vnfProductName === null || item.vnfProductName === ''">&nbsp;</td>
- <td *ngIf="item.name">{{item.name}}</td>
- <td *ngIf="item.vnfdVersion">{{item.vnfdVersion}}</td>
- <td *ngIf="item.vnfdVersion === null || item.vnfdVersion === ''">&nbsp;</td>
- <td *ngIf="item.version">{{item.version}}</td>
- <td>{{item.onboardingState}}</td>
- <td>{{item.operationalState}}</td>
- <td>{{item.usageState}}</td>
- <td>
- <i [ngClass]="{'cannotclick':onboardData.status == 'onboarding' && i == currentIndex}"
- class="anticon anticon-upload upicon" #upload_icon (click)="updataVnfService(item.uuid,i,notificationModel)"
- *ngIf="item.uuid"></i>
- <i class="anticon anticon-delete" nzType="info" (click)="showConfirm(i,item.id,tab,notificationModel)"
- *ngIf="item.id"></i>
- </td>
- </tr>
- </tbody>
- </nz-table>
- </nz-spin>
+<!-- tab -->
+<nz-tabset [nzTabPosition]="'top'" [nzType]="'card'">
+ <nz-tab *ngFor="let tab of tabs" [nzTitle]="tab" (nzClick)="handleTabChange(tab)"></nz-tab>
+</nz-tabset>
+<div class="list">
+ <!-- upload -->
+ <div class="listUploadContainer">
+ <div class="listupload">
+ <nz-upload nzType="drag" [(nzFileList)]="fileList" [nzBeforeUpload]="beforeUpload">
+ <p class="ant-upload-drag-icon">
+ <i nz-icon type="inbox" class="anticon anticon-inbox"></i>
+ </p>
+ <p class="ant-upload-text"> {{"i18nTextDefine_Click_CSAR_File" | translate}} </p>
+ <p class="ant-upload-hint"></p>
+ </nz-upload>
+ <button nz-button [nzLoading]="uploading" (click)="onClick()" [disabled]="fileList.length == 0" class="upload">
+ {{ uploading ? 'Uploading' : 'Start Upload' }}
+ </button>
</div>
- <!-- PNFList -->
- <div class="list" *ngIf="tab === 'PNF'">
- <div style="width:100%;height: 30%;margin-bottom: 1%">
- <div class="listupload">
- <nz-upload nzType="drag" [(nzFileList)]="fileListPNF" [nzBeforeUpload]="beforeUploadPNF">
- <p class="ant-upload-drag-icon">
- <i nz-icon type="inbox" class="anticon anticon-inbox"></i>
- </p>
- <p class="ant-upload-text">Click or drag CSAR File here</p>
- <p class="ant-upload-hint"></p>
- </nz-upload>
- <button nz-button [nzLoading]="pnfuploading" (click)="onClick(tab)" [disabled]="fileListPNF.length == 0"
- style="margin-top: 16px;margin-left: 55px;color: #FFFFFF;font-size: 13px;background-color: #3E9BFF;font-family: ArialMT;">
- {{ pnfuploading ? 'Uploading' : 'Start Upload' }}
- </button>
- </div>
- <div class="listlin"></div>
- <div class="listfile">
- <div style="color: rgba(66,84,143,1);font-family:ArialMT;padding-bottom: 15px;height: 15%"> {{"i18nTextDefine_Uploaded_files" | translate}} </div>
- <div class="nouploadfile">{{"i18nTextDefine_Nofileuploading" | translate}}</div>
- <div style="height:80%;overflow: auto">
- <div class="listfilebgc" *ngFor="let itemns of pnfRightList">
- <div>
- <i class="anticon anticon-link"></i>
- </div>
- <div class="color" [ngClass]="{'progress':itemns.status == true}">{{itemns.name}}</div>
- <div class="color" *ngIf="itemns.status">
- <nz-progress [nzPercent]="itemns.progress" [nzShowInfo]="false"></nz-progress>
- </div>
- <div class="color" *ngIf="!itemns.status">
- <span *ngIf="itemns.success == 0">{{"i18nTextDefine_File_upload_completed" | translate}}</span>
- <span *ngIf="itemns.success == 1">{{"i18nTextDefine_File_upload_failed" | translate}}</span>
- </div>
- <div *ngIf="!itemns.status">
- <i class="anticon anticon-check-circle" *ngIf="itemns.success == 0" style="color:#7BC7F3!important;"></i>
- <i class="anticon anticon-exclamation-circle" *ngIf="itemns.success == 1" style="color:#fb5c5c!important;"></i>
- </div>
- </div>
+ <div class="listlin"></div>
+ <div class="listfile">
+ <div class="listFileTitle"> {{"i18nTextDefine_Uploaded_files" | translate}} </div>
+ <div class="nouploadfile" [style.display]="display">{{"i18nTextDefine_Nofileuploading" | translate}}</div>
+ <div class="listfilebgc" *ngIf="file">
+ <i class="anticon anticon-link icon"></i>
+ <div class="color" [ngClass]="{'progress':file.status}">{{file.name}}</div>
+ <div class="color" *ngIf="file.status">
+ <nz-progress [nzPercent]="file.progress" [nzShowInfo]="false"></nz-progress>
</div>
- </div>
- </div>
- <nz-spin [nzSpinning]="isSpinning" style="height: 69%">
- <div class="mask" *ngIf="isSpinning"></div>
- <nz-table #nzTable [nzData]="pnftableData" nzShowSizeChanger [nzFrontPagination]="true"
- [nzShowQuickJumper]="true" [nzPageSizeOptions]="[5,10,15,20]" [nzTotal]='total' [(nzPageSize)]="pnfpageSize"
- [(nzPageIndex)]='pnfpageIndex' [nzLoading]="loading" nzSize="middle">
- <thead (nzSortChange)="sort($event)" nzSingleSort>
- <tr>
- <th nzWidth="15%"> {{"i18nTextDefine_NO" | translate}} </th>
- <th nzWidth="15%" nzShowSort nzSortKey="name"> {{"i18nTextDefine_Name" | translate}} </th>
- <th nzWidth="15%"> {{"i18nTextDefine_Version" | translate}} </th>
- <th nzWidth="15%"> {{"i18nTextDefine_OnboardingState" | translate}} </th>
- <th nzWidth="10%"> {{"i18nTextDefine_UsageState" | translate}} </th>
- <th nzWidth="15%"> {{"i18nTextDefine_Operationbutton" | translate}} </th>
- </tr>
- </thead>
- <tbody>
- <tr *ngFor="let item of nzTable.data; let i = index; ">
- <td>{{i+1}}</td>
- <td>{{item.pnfdName}}</td>
- <td>{{item.pnfdVersion}}</td>
- <td>{{item.pnfdOnboardingState}}</td>
- <td>{{item.pnfdUsageState}}</td>
- <td>
- <i class="anticon anticon-delete" nzType="info" (click)="showConfirm(i,item.id,tab,notificationModel)"></i>
- </td>
- </tr>
- </tbody>
- </nz-table>
- </nz-spin>
-
- </div>
- </nz-tab>
- <!--2019.08.14 add notification-->
- <ng-template #notificationModel >
- <div class="ant-notification-notice-content">
- <div class="ant-notification-notice-with-icon">
- <span class="ant-notification-notice-icon">
- <img src="{{notificationAttributes.imgPath}}" alt="{{notificationAttributes.status}}">
- </span>
- <div class="ant-notification-notice-message">
- {{notificationAttributes.title}}&nbsp;
- {{"i18nTextDefine_"+notificationAttributes.action | translate}}&nbsp;&nbsp;{{"i18nTextDefine_"+notificationAttributes.status | translate}}
+ <div class="color" *ngIf="!file.status">
+ <span *ngIf="file.success === 0">{{"i18nTextDefine_File_upload_completed" | translate}}</span>
+ <span *ngIf="file.success === 1">{{"i18nTextDefine_File_upload_failed" | translate}}</span>
</div>
- <div class="ant-notification-notice-description">
- <div class="notificationlist">
- <p>{{notificationAttributes.title}} id:&nbsp;</p>
- <span>{{ notificationAttributes.id }}</span>
- </div>
+ <div *ngIf="!file.status">
+ <i class="anticon anticon-check-circle success" *ngIf="file.success === 0"></i>
+ <i class="anticon anticon-exclamation-circle fail" *ngIf="file.success === 1"></i>
</div>
- <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div>
</div>
</div>
- </ng-template>
-</nz-tabset>
-
+ </div>
+ <!-- table -->
+ <nz-spin [nzSpinning]="isSpinning" class="listContainer">
+ <div class="mask" *ngIf="isSpinning"></div>
+ <nz-table #nzTable [nzData]="currentTab === 'NS'? nsTableData: (currentTab === 'VNF'? vnfTableData : pnfTableData)" nzShowSizeChanger [nzFrontPagination]="true"
+ [nzShowQuickJumper]="true" [nzPageSizeOptions]="[5,10,15,20]" [(nzPageSize)]="pageSize"
+ [(nzPageIndex)]='pageIndex' nzSize="middle">
+ <thead>
+ <tr class="theadColor">
+ <th nzWidth="15%"> {{"i18nTextDefine_NO" | translate}} </th>
+ <th nzWidth="15%"> {{"i18nTextDefine_Name" | translate}} </th>
+ <th nzWidth="15%"> {{"i18nTextDefine_Version" | translate}} </th>
+ <th nzWidth="15%"> {{"i18nTextDefine_OnboardingState" | translate}} </th>
+ <th nzWidth="15%" *ngIf="currentTab !== 'PNF'"> {{"i18nTextDefine_OperationalState" | translate}} </th>
+ <th nzWidth="10%"> {{"i18nTextDefine_UsageState" | translate}} </th>
+ <th nzWidth="15%"> {{"i18nTextDefine_Operationbutton" | translate}} </th>
+ </tr>
+ </thead>
+ <tbody *ngIf="currentTab === 'NS'">
+ <tr *ngFor="let item of nzTable.data;let i = index;">
+ <td>{{i+1}}</td>
+ <td>{{item.nsdName || item.name }}</td>
+ <td>{{item.nsdVersion || item.version}}</td>
+ <td>{{item.nsdOnboardingState ? item.nsdOnboardingState : status}}</td>
+ <td>{{item.nsdOperationalState}}</td>
+ <td>{{item.nsdUsageState}}</td>
+ <td>
+ <i [ngClass]="{'cannotclick': isUpdate}"
+ class="anticon anticon-upload upicon" #upload_icon (click)="updataService(item.uuid)"
+ *ngIf="item.uuid"></i>
+ <i class="anticon anticon-delete" (click)="showDeleteConfirm(item.id)"
+ *ngIf="item.id"></i>
+ </td>
+ </tr>
+ </tbody>
+ <tbody *ngIf="currentTab === 'VNF'">
+ <tr *ngFor="let item of nzTable.data;let i = index;">
+ <td>{{i+1}}</td>
+ <td>{{item.vnfProductName || item.name }}</td>
+ <td>{{item.vnfdVersion || item.version}}</td>
+ <td>{{item.onboardingState}}</td>
+ <td>{{item.operationalState}}</td>
+ <td>{{item.usageState}}</td>
+ <td>
+ <i [ngClass]="{'cannotclick': isUpdate}"
+ class="anticon anticon-upload upicon" #upload_icon (click)="updataService(item.uuid)"
+ *ngIf="item.uuid"></i>
+ <i class="anticon anticon-delete" (click)="showDeleteConfirm(item.id)"
+ *ngIf="item.id"></i>
+ </td>
+ </tr>
+ </tbody>
+ <tbody *ngIf="currentTab === 'PNF'" >
+ <tr *ngFor="let item of nzTable.data; let i = index;">
+ <td>{{i+1}}</td>
+ <td>{{item.pnfdName}}</td>
+ <td>{{item.pnfdVersion}}</td>
+ <td>{{item.pnfdOnboardingState}}</td>
+ <td>{{item.pnfdUsageState}}</td>
+ <td>
+ <i class="anticon anticon-delete" (click)="showDeleteConfirm(item.id)"></i>
+ </td>
+ </tr>
+ </tbody>
+ </nz-table>
+ </nz-spin>
+</div>
+<app-notification #notification [isServicesList]="false"></app-notification> \ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.less b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.less
index 5ba479de..f877e1ca 100644
--- a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.less
+++ b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.less
@@ -13,141 +13,112 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
-.title {
- font: 700 18px/18px "思源黑体";
- color: #4c5e70;
- margin-bottom: 18px;
+th{
+ background-color: rgba(241,243,244,.9) !important;
}
-hr {
- border: none;
- height: 2px;
- background-color: #dce1e7;
- margin-bottom: 20px;
-}
-.switch_btn {
- position: absolute;
- right: 6%;
- top: 18px;
- border: 1px solid #3fa8eb;
- width: 8%;
- border-radius: 10px;
- margin-bottom: 18px;
- span {
- display: block;
- float: left;
- text-align: center;
- width: 50%;
- color: #3fa8eb;
- font-weight: 700;
- cursor: pointer;
- }
- span:first-child {
- border-radius: 10px 0 0 10px;
- }
- span:last-child {
- border-radius: 0 10px 10px 0;
- }
- span.left_b {
- border-left: 1px solid #3fa8eb;
- }
- span.active {
- color: #fff;
- background: #3fa8eb;
- }
-}
-
.list {
- border-radius: 5px;
- .listupload {
- width: 22%;
- vertical-align: top;
- display: inline-block;
- margin-left: 13%;
- }
- .listlin {
- vertical-align: top;
- display: inline-block;
- width: 1%;
- margin-left: 10%;
- height: 177px;
- margin-bottom: 30px;
- border-right: 2px solid #EEEEEE;
- }
- .listfile {
- width: 43%;
- height: 100%;
- vertical-align: top;
- display: inline-block;
- margin-left: 10%;
- .nouploadfile{
- height: 80%;
- width: 100%;
- text-align: center;
- font-size: 22px;
- margin-top: 5%;
+ padding: 20px;
+ .listUploadContainer{
+ display: flex;
+ align-items: flex-start;
+ width: 100%;
+ height: 30%;
+ margin-bottom: 1%;
+ .listupload {
+ position: relative;
+ width: 22%;
+ margin-left: 13%;
+ .upload{
+ position: absolute;
+ left: 50%;
+ bottom: -48px;
+ transform: translateX(-50%);
+ color: #FFFFFF;
+ font-size: 13px;
+ background-color: #3E9BFF;
+ font-family: ArialMT;
+ }
}
- .listfilebgc {
- background-color: #fff;
- border-bottom: 8px solid #F7F8FC;
+ .listlin {
+ width: 1%;
+ margin-left: 10%;
+ height: 177px;
+ margin-bottom: 30px;
+ border-right: 2px solid #EEEEEE;
}
- .listfilebgc {
- background-color: #fff;
- height: 30px;
- border-radius: 2px;
- line-height: 2;
- color: #42548F;
- border-bottom: 4px solid #F7F8FC;
- >div {
- float: left;
+ .listfile {
+ width: 43%;
+ height: 100%;
+ margin-left: 10%;
+ .listFileTitle{
+ height: 15%;
+ padding-bottom: 15px;
+ color: rgba(66,84,143,1);
+ font-family: ArialMT;
}
- :first-child {
- width: 6%;
- margin-left: 5px;
- }
- :nth-child(2){
- width:20%;
- }
- :nth-child(3){
- width: 60%;
- text-align: center;
- }
- :nth-child(4){
- padding-left: 4%;
- }
- .color {
- color:rgba(66,84,143,1);
- span{
- color:rgba(66,84,143,0.7);
- }
- }
- .progress{
- color:rgba(66,84,143,0.7);
+ .nouploadfile{
+ height: 80%;
+ width: 100%;
+ text-align: center;
+ font-size: 22px;
+ margin: 5% 0 10px;
}
+ .listfilebgc {
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+ width:100%;
+ height: 80%;
+ padding: 5px;
+ background-color: #fff;
+ border-radius: 2px;
+ color: #42548F;
+ .icon{
+ width: 15px;
+ }
+ :nth-child(3){
+ width: 50%;
+ }
+ :nth-child(4){
+ width: 5%;
+ height:100%;
+ .success{
+ color:#7BC7F3!important;
+ }
+ .fail{
+ color:#fb5c5c!important;
+ }
+ }
+ .color {
+ color:rgba(66,84,143,1);
+ span{
+ color:rgba(66,84,143,0.7);
+ }
+ .progress{
+ color:rgba(66,84,143,0.7);
+ }
+ }
+ }
+
+ }
+
+ }
+ .listContainer{
+ height: 69%;
+ .mask {
+ top: 0;
+ left: 0;
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ opacity: 0.1;
+ background: black;
+ z-index: 1049;
}
}
nz-table {
tbody {
td {
- span.onboarding {
- font-size: 12px;
- color: #147dc2;
- }
- span.onboarded {
- font-size: 14px;
- color: #147dc2;
- }
- span.updating {
- font-size: 12px;
- color: blue;
- }
- span.deleting {
- font-size: 12px;
- color: red;
- }
- span.invalid {
- font-size: 14px;
- color: purple;
- }
i.anticon {
cursor: pointer;
font-size: 18px;
@@ -161,20 +132,7 @@ hr {
color: #aaa;
opacity: 0.6;
}
- .fileIcon{
- display: none;
- }
}
}
}
}
-.mask {
- top: 0;
- left: 0;
- position: fixed;
- width: 100%;
- height: 100%;
- opacity: 0.1;
- background: black;
- z-index: 1049;
-} \ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.ts b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.ts
index 33385e32..3d312c5c 100644
--- a/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.ts
+++ b/usecaseui-portal/src/app/views/services/onboard-vnf-vm/onboard-vnf-vm.component.ts
@@ -14,14 +14,11 @@
limitations under the License.
*/
import { HttpClient, HttpRequest, HttpResponse } from '@angular/common/http';
-import { Component, OnInit, HostBinding, TemplateRef } from '@angular/core';
-import { NzNotificationService } from 'ng-zorro-antd';
-// import { MyhttpService } from '../../myhttp.service';
+import { Component, OnInit, HostBinding, TemplateRef, ViewChild } from '@angular/core';
import { onboardService } from '../../../core/services/onboard.service';
import { slideToRight } from '../../../shared/utils/animates';
import { NzMessageService, UploadFile, NzModalRef, NzModalService } from 'ng-zorro-antd';
import { filter } from 'rxjs/operators';
-import { Title } from '@angular/platform-browser';
@Component({
selector: 'app-onboard-vnf-vm',
@@ -31,114 +28,75 @@ import { Title } from '@angular/platform-browser';
})
export class OnboardVnfVmComponent implements OnInit {
@HostBinding('@routerAnimate') routerAnimateState;
+ @ViewChild('notification') notification: any;
- // delete Modal
- confirmModal: NzModalRef;
- nsdInfoId = '';
- vnfPkgId = '';
- pnfdInfoId = '';
- tabTitle = "NS";
- nsuploading = false;
- vnfuploading = false;
- pnfloading = false;
+ // upload
+ tabs: string[] = ['NS', 'VNF', 'PNF'];
+ currentTab: string = 'NS'
fileList: UploadFile[] = [];
- fileListNS: UploadFile[] = [];
- fileListVNF: UploadFile[] = [];
- fileListPNF: UploadFile[] = [];
- // onboard initial value
- status = "Onboard Available";
- jobId = '';
+ uploading:boolean = false;
+ infoId: string;
+ display: string = 'block';
+
+ // table
+ isSpinning: boolean = false;
+ nsTableData: any[];
+ vnfTableData: any[];
+ pnfTableData: any[];
+ status: string = "Onboard Available";
+ pageIndex: number = 1;
+ pageSize: number = 10;
+
+ // update or delete
+ isUpdate: boolean = false;
+ jobId: string;
+
//url
url = {
- // line up
ns: '/api/nsd/v1/ns_descriptors/*_*/nsd_content',
vnf: '/api/vnfpkgm/v1/vnf_packages/*_*/package_content',
pnf: '/api/nsd/v1/pnf_descriptors/*_*/pnfd_content'
- // line local
- //ns: 'https://jsonplaceholder.typicode.com/posts/',
- //vnf: 'https://jsonplaceholder.typicode.com/posts/',
- //pnf: 'https://jsonplaceholder.typicode.com/posts/',
};
+
+ file: {
+ name: string,
+ uid: string,
+ progress: number,
+ status: boolean,
+ success: number
+ };
+
constructor(
private myhttp: onboardService,
private http: HttpClient,
private msg: NzMessageService,
- private titleService: Title,
- private modal: NzModalService,
- private modalService: NzModalService,
- private notification: NzNotificationService
+ private modalService: NzModalService
) { }
+
//default Call ns data by default
ngOnInit() {
this.getTableData();
}
- //Tabular data
- nstableData: any;
- vnftableData: any;
- pnftableData: any;
- nssdcData: any;
- nsvfcData: any;
-
- vnfsdcData: any;
- vnfvfcData: any;
- nspageIndex = 1;
- nspageSize = 10;
- vnfpageIndex = 1;
- vnfpageSize = 10;
- pnfpageIndex = 1;
- pnfpageSize = 10;
- total;
- nsloading = false;
- sortName = null;
- sortValue = null;
- tabs = ['NS', 'VNF', 'PNF'];
- isSpinning = false;
-
- //2019.08.14 add
- notificationAttributes = {
- "title": this.tabs[0],
- "imgPath": "../../../../assets/images/execute-inproess.png",
- "action": "OnboardingState",
- "status": "InProgress",
- "id": null
- };
- notificationModelShow(template: TemplateRef<{}>): void {
- this.notification.template(template);
- }
- notificationSuccess(notificationModel) {
- this.notificationAttributes.imgPath = "../../../../assets/images/execute-success.png";
- this.notificationAttributes.status = "Success";
- this.notificationModelShow(notificationModel);
- }
- notificationFailed(notificationModel) {
- this.notificationAttributes.imgPath = "../../../../assets/images/execute-faild.png";
- this.notificationAttributes.status = "Failed";
- this.notificationModelShow(notificationModel);
- }
// Handling tab switching request data
- handleTabChange(tab) {
- this.tabTitle = tab;
+ handleTabChange(tab: string): void {
+ this.currentTab = tab;
+ this.fileList = [];
+ this.display = 'block';
+ delete this.file;
switch (tab) {
case 'NS':
- this.nstableData = [];
this.getTableData();
- this.fileList = []; //Empty uploaded files when switching
break
case 'VNF':
- this.vnftableData = [];
this.getTableVnfData()
- this.fileList = [];
break
case 'PNF':
- this.pnftableData = [];
this.getTablePnfData()
- this.fileList = [];
break
}
}
-
//before put create--Drag and drop files to the page before uploading
requestBody = {
"userDefinedData": {
@@ -148,302 +106,128 @@ export class OnboardVnfVmComponent implements OnInit {
}
}
- //NS/VNF List add file
beforeUpload = (file: UploadFile): boolean => {
- this.fileList.push(file);
- return false;
- }
-
- // ns beforeUpload
- beforeUploadNS = (file: UploadFile): boolean => {
- this.fileListNS.push(file);
- this.myhttp.getCreatensData("createNetworkServiceData", this.requestBody)//on-line
- // this.myhttp.getCreatensData("creatensDataNS") //local
- .subscribe((data) => {
- this.nsdInfoId = data["id"];
- }, (err) => {
- console.log(err);
- })
- return false;
- }
-
- //vnf beforeUpload
- beforeUploadVNF = (file: UploadFile): boolean => {
- this.fileListVNF.push(file);
- this.myhttp.getCreatensData("createVnfData", this.requestBody)//on-line
- // this.myhttp.getCreatensData("creatensDataVNF") //local
- .subscribe((data) => {
- this.vnfPkgId = data["id"];
- }, (err) => {
- console.log(err);
- })
- return false;
- }
-
- // //pnf eforeUpload
- beforeUploadPNF = (file: UploadFile): boolean => {
- this.fileListPNF.push(file);
- this.myhttp.getCreatensData("createPnfData", this.requestBody) //on-line
- // this.myhttp.getCreatensData("creatensDataPNF") //local
+ this.fileList.splice(0,1,file);
+ let API: string;
+ if(this.currentTab === 'NS'){
+ API = 'createNetworkServiceData';
+ }else if(this.currentTab === 'VNF'){
+ API = 'createVnfData';
+ }else {
+ API = 'createPnfData';
+ }
+ this.myhttp.getCreatensData(API, this.requestBody)//on-line
.subscribe((data) => {
- this.pnfdInfoId = data["id"];
+ this.infoId = data["id"];
}, (err) => {
console.log(err);
})
return false;
}
- //Get list list id
- onClickId(id, tab) {
- switch (tab) {
- case 'NS':
- this.nsdInfoId = id;
- break
- case 'VNF':
- this.vnfPkgId = id;
- break
- case 'PNF':
- this.pnfdInfoId = id;
- break
- }
- }
-
- //Drag and drop and click the upload button
- onClick(tab) {
- switch (tab) {
- case 'NS':
- // this.handleUpload('/api/nsd/v1/ns_descriptors/'+this.nsdInfoId+'/nsd_content',tab);
- this.handleUpload(this.url.ns.replace("*_*", this.nsdInfoId), tab);
- this.getTableData();
- break
- case 'VNF':
- // this.handleUpload('/api/vnfpkgm/v1/vnf_packages/'+this.vnfPkgId+'/package_content',tab);
- this.handleUpload(this.url.vnf.replace("*_*", this.vnfPkgId), tab);
- this.getTableVnfData()
- break
- case 'PNF':
- // this.handleUpload('/api/nsd/v1/pnf_descriptors/'+this.pnfdInfoId+'/pnfd_content',tab);
- this.handleUpload(this.url.pnf.replace("*_*", this.pnfdInfoId), tab);
- this.getTablePnfData();
- break
- }
+ // Drag and drop and click the upload button
+ onClick(): void {
+ this.display = 'none';
+ let tab = this.currentTab === 'NS' ? 'ns' : (this.currentTab === 'VNF' ? 'vnf' : 'pnf')
+ this.handleUpload(this.url[tab].replace("*_*", this.infoId));
}
- nsRightList = [];
- nsNum = 0;
- vnfRightList = [];
- vnfNum = 0;
- pnfRightList = [];
- pnfNum = 0;
- //put Upload Upload
- handleUpload(url, tab): void {
+ handleUpload(url: string): void {
const formData = new FormData();
// tslint:disable-next-line:no-any
- switch (tab) {
- case "NS":
- this.fileListNS.forEach((file: any) => {
- formData.append('file', file);
- });
- this.nsuploading = true;
- let lastNs = this.fileListNS[this.fileListNS.length - 1];
- let nsfile = {
- name: lastNs.name,
- uid: lastNs.uid,
- progress: 0,
- status: true,
- success: 0
- };
- this.nsNum += 1;
- this.nsRightList.push(nsfile);
- let requeryNs = (nsfile) => {
- setTimeout(() => {
- nsfile.progress += 2;
- if (nsfile.progress < 100) {
- requeryNs(nsfile)
- } else {
- nsfile.progress = 100;
- nsfile.status = false;
- }
- }, 100)
- };
- requeryNs(nsfile);
- break
- case "VNF":
- this.fileListVNF.forEach((file: any) => {
- formData.append('file', file);
- });
- this.vnfuploading = true;
- let lastVnf = this.fileListVNF[this.fileListVNF.length - 1];
- let vnffile = {
- name: lastVnf.name,
- uid: lastVnf.uid,
- progress: 0,
- status: true,
- success: 0
- };
- this.vnfNum += 1;
- this.vnfRightList.push(vnffile);
- let requeryVnf = (vnffile) => {
- setTimeout(() => {
- vnffile.progress += 2;
- if (vnffile.progress < 100) {
- requeryVnf(vnffile)
- } else {
- vnffile.progress = 100;
- vnffile.status = false;
- }
- }, 100)
- };
- requeryVnf(vnffile);
- break
- case "PNF":
- this.fileListPNF.forEach((file: any) => {
- formData.append('file', file);
- });
- this.pnfloading = true;
- let lastPnf = this.fileListPNF[this.fileListPNF.length - 1];
- let pnffile = {
- name: lastPnf.name,
- uid: lastPnf.uid,
- progress: 0,
- status: true,
- success: 0
- };
- this.pnfNum += 1;
- this.pnfRightList.push(pnffile);
- let requeryPnf = (pnffile) => {
- setTimeout(() => {
- pnffile.progress += 2;
- if (pnffile.progress < 100) {
- requeryPnf(pnffile)
- } else {
- pnffile.progress = 100;
- pnffile.status = false;
- }
- }, 100)
- };
- requeryPnf(pnffile);
- break
- }
- // line PUT
+ this.fileList.forEach((file: any) => {
+ formData.set('file', file);
+ });
+ this.uploading = true;
+ this.file = {
+ name: this.fileList[0].name,
+ uid: this.fileList[0].uid,
+ progress: 0,
+ status: true,
+ success: 0
+ };
+ let requery = (file) => {
+ file.progress += 3;
+ setTimeout(() => {
+ if (file.progress < 100) {
+ requery(file)
+ }
+ }, 100)
+ };
+ requery(this.file);
const req = new HttpRequest('PUT', url, formData, {
reportProgress: true,
withCredentials: true
});
//Upload pre-empty array
this.fileList = [];
- this.fileListNS = [];
- this.fileListVNF = [];
- this.fileListPNF = [];
this.http.request(req)
.pipe(filter(e => e instanceof HttpResponse))
.subscribe(
(event: {}) => {
- if (tab == "NS") {
- this.nsRightList[this.nsNum - 1].progress = 100;
- this.nsRightList[this.nsNum - 1].status = false;
- this.nsRightList[this.nsNum - 1].success = 0;
- }
- if (tab == "VNF") {
- this.vnfRightList[this.vnfNum - 1].progress = 100;
- this.vnfRightList[this.vnfNum - 1].status = false;
- this.vnfRightList[this.vnfNum - 1].success = 0;
- }
- if (tab == "PNF") {
- this.pnfRightList[this.pnfNum - 1].progress = 100;
- this.pnfRightList[this.pnfNum - 1].status = false;
- this.pnfRightList[this.pnfNum - 1].success = 0;
- }
- this.changeUploadingSta(tab);
+ this.file.progress = 100;
+ this.file.status = false;
+ this.uploading = false;
this.msg.success('upload successfully.');
+ this.currentTab === 'NS' ? this.getTableData() : (this.currentTab === 'VNF' ? this.getTableVnfData() : this.getTablePnfData());
},
err => {
- if (tab == "NS") {
- this.nsRightList[this.nsNum - 1].progress = 100;
- this.nsRightList[this.nsNum - 1].status = false;
- this.nsRightList[this.nsNum - 1].success = 1;
- }
- if (tab == "VNF") {
- this.vnfRightList[this.vnfNum - 1].progress = 100;
- this.vnfRightList[this.vnfNum - 1].status = false;
- this.vnfRightList[this.vnfNum - 1].success = 1;
- }
- if (tab == "PNF") {
- this.pnfRightList[this.pnfNum - 1].progress = 100;
- this.pnfRightList[this.pnfNum - 1].status = false;
- this.pnfRightList[this.pnfNum - 1].success = 1;
- }
- this.changeUploadingSta(tab);
+ this.file.progress = 100;
+ this.file.status = false;
+ this.file.success = 1;
+ this.uploading = false;
this.msg.error('upload failed.');
}
);
}
- // Control the status of uploading
- changeUploadingSta(tab) {
- switch (tab) {
- case "NS":
- this.nsuploading = false;
- break
- case "VNF":
- this.vnfuploading = false;
- break
- case "PNF":
- this.pnfloading = false;
- }
- }
-
- //----------------------------------------------------------------------------------------------
-
// Get the NS list
- getTableData() {
+ getTableData(): void{
this.isSpinning = true;
//ns vfc lists
this.myhttp.getOnboardTableData()
.subscribe((data) => {
- this.nsvfcData = data;
- this.nstableData = this.nsvfcData;
+ this.nsTableData = data;
//ns sdc list
this.myhttp.getSDC_NSTableData()
.subscribe((data) => {
this.isSpinning = false; //loading hide
- this.nssdcData = data;
- this.nsvfcData.map((nsvfc) => { nsvfc.sameid = this.nssdcData.find((nssdc) => { return nsvfc.id == nssdc.uuid }) && nsvfc.id; return nsvfc; });
- let sameData = this.nssdcData.filter((nssdc) => { return !this.nsvfcData.find((nsvfc) => { return nsvfc.id == nssdc.uuid }) });
- this.nstableData = this.nstableData.concat(sameData);
+ let nsData = data;
+ // this.NSTableData.map((nsvfc) => { nsvfc.sameid = nsData.find((nssdc) => { return nsvfc.id == nssdc.uuid }) && nsvfc.id; return nsvfc; });
+ let sameData = nsData.filter((nssdc) => { return !this.nsTableData.find((nsvfc) => { return nsvfc.id == nssdc.uuid }) });
+ this.nsTableData = this.nsTableData.concat(sameData);
}, (err) => {
- console.log(err);
+ console.error(err);
this.isSpinning = false;
})
}, (err) => {
- console.log(err);
+ console.error(err);
this.isSpinning = false;
})
-
}
// Get the vnf list
- getTableVnfData() {
+ getTableVnfData(): void{
this.isSpinning = true;
//vnf vfc lists
this.myhttp.getOnboardTableVnfData()
.subscribe((data) => {
- this.vnfvfcData = data;
- this.vnftableData = this.vnfvfcData;
+ this.vnfTableData = data;
//vnf sdc lists
this.myhttp.getSDC_VNFTableData()
.subscribe((data) => {
this.isSpinning = false; //loading hide
- this.vnfsdcData = data;
- this.vnfvfcData.map((vnfvfc) => { vnfvfc.sameid = this.vnfsdcData.find((nssdc) => { return vnfvfc.id == nssdc.uuid }) && vnfvfc.id; return vnfvfc; });
- let sameData = this.vnfsdcData.filter((vnfsdc) => { return !this.vnfvfcData.find((vnfvfc) => { return vnfvfc.id == vnfsdc.uuid }) });
- this.vnftableData = this.vnftableData.concat(sameData);
+ let vnfData = data;
+ // this.VNFTableData.map((vnfvfc) => { vnfvfc.sameid = this.vnfData.find((nssdc) => { return vnfvfc.id == nssdc.uuid }) && vnfvfc.id; return vnfvfc; });
+ let sameData = vnfData.filter((vnfsdc) => { return !this.vnfTableData.find((vnfvfc) => { return vnfvfc.id == vnfsdc.uuid }) });
+ this.vnfTableData = this.vnfTableData.concat(sameData);
}, (err) => {
- console.log(err);
+ console.error(err);
+ this.isSpinning = false;
})
-
}, (err) => {
- console.log(err);
+ console.error(err);
+ this.isSpinning = false;
})
}
@@ -452,133 +236,76 @@ export class OnboardVnfVmComponent implements OnInit {
this.isSpinning = true;
this.myhttp.getOnboardTablePnfData()
.subscribe((data) => {
- this.pnftableData = data;
+ this.pnfTableData = data;
this.isSpinning = false; //loading hide
}, (err) => {
- console.log(err);
+ console.error(err);
+ this.isSpinning = false;
})
}
- //-----------------------------------------------------------------------------------
- /* onboard */
- //Successful frame
- success(tab): void {
- const modal = this.modalService.success({
- nzTitle: 'This is an success message',
- nzContent: 'Package Onboard Completed.'
- });
- switch (tab) {
- case "NS":
- this.getTableData();
- break
- case "VNF":
- this.getTableVnfData();
- break
- }
+ // confirm
+ showConfirm(requestBody: object, id: string): void{
+ let API = this.currentTab === 'NS'? 'getNsonboard' : 'getVnfonboard';
+ this.modalService.confirm({
+ nzTitle: '<p>Are you sure you want to do this?</p>',
+ nzOnOk: () => {
+ this.myhttp[API](requestBody)
+ .subscribe((data) => {
+ if (data.status == "success") {
+ if(this.currentTab === 'NS'){
+ this.isUpdate = false;
+ this.notification.notificationSuccess(this.currentTab, "OnboardingState", id);
+ this.getTableData();
+ }else{
+ this.jobId = data.jobId;
+ this.queryProgress(this.jobId, id);
+ this.getTableVnfData();
+ }
+ } else {
+ this.isUpdate = false;
+ this.notification.notificationFailed(this.currentTab, "OnboardingState", id);
+ return false
+ }
+ }, (err) => {
+ console.log(err);
+ })
+ }
+ })
}
- //Failure frame
- error(): void {
- this.modalService.error({
- nzTitle: 'This is an error message',
- nzContent: 'Package Onboard Failed!'
- });
- }
- //onboard status
- onboardData = {
- status: "onboard",
- progress: 0,
- }
- currentIndex = 0;
// ns onboard Upload button
- updataNsService(id, index, notificationModel) {
- this.currentIndex = index;
- this.onboardData.status = "onboarding"; //Disabled
- this.onboardData.progress = 0;
- let requestBody = {
- "csarId": id
- };
- this.notificationAttributes = {
- "title": this.tabs[0],
- "imgPath": "../../../../assets/images/execute-inproess.png",
- "action": "OnboardingState",
- "status": "InProgress",
- "id": id
- };
- this.notificationModelShow(notificationModel);
- this.myhttp.getNsonboard(requestBody)
- .subscribe((data) => {
- if (data.status == "failed") {
- this.onboardData.status = "Failed";
- this.notificationFailed(notificationModel);
- this.error();
- return false
- } else if (data.status == "success") {
- this.success("NS");
- this.onboardData.status = "onboarded";
- this.notificationSuccess(notificationModel);
- }
- }, (err) => {
- console.log(err);
- })
- }
-
- // vnf onboard Upload button
- updataVnfService(id, index, notificationModel) {
- this.currentIndex = index;
- this.onboardData.status = "onboarding"; //Disabled button
- this.onboardData.progress = 0;
-
-
- let requestBody = {
- "csarId": id
- };
- this.notificationAttributes = {
- "title": this.tabs[1],
- "imgPath": "../../../../assets/images/execute-inproess.png",
- "action": "OnboardingState",
- "status": "InProgress",
- "id": id
- };
- this.notificationModelShow(notificationModel);
- this.myhttp.getVnfonboard(requestBody)
- .subscribe((data) => {
- this.jobId = data.jobId;
- this.queryProgress(this.jobId, 0, notificationModel); //vnf Need to query progress interface
- }, (err) => {
- console.log(err);
- })
- }
+ updataService(id: string) {
+ this.isUpdate = true;
+ let requestBody = { "csarId": id };
+ this.showConfirm(requestBody, id)
+ }
//Progress Progress inquiry
- queryProgress(jobId, responseId, notificationModel) {
+ queryProgress(jobId: string, id: string): any{
let mypromise = new Promise((res) => {
- this.myhttp.getProgress(jobId, responseId)
+ this.myhttp.getProgress(jobId, 0)
.subscribe((data) => {
if (data.responseDescriptor == null || data.responseDescriptor == "null" || data.responseDescriptor.progress == undefined || data.responseDescriptor.progress == null) {
- this.onboardData.status = "onboarding";
+ this.isUpdate = true;
setTimeout(() => {
- this.queryProgress(this.jobId, 0, notificationModel);
+ this.queryProgress(this.jobId, id);
}, 10000)
return false
}
if (data.responseDescriptor.progress > 100) {
- this.onboardData.status = "Failed";
- this.notificationFailed(notificationModel);
- this.error();
- return false
- }
- if (data.responseDescriptor.progress < 100) {
- this.onboardData.status = "onboarding";
+ this.isUpdate = false;
+ this.notification.notificationFailed(this.currentTab, 'OnboardingState', id);
+ }else if (data.responseDescriptor.progress < 100) {
+ this.isUpdate = true;
setTimeout(() => {
- this.queryProgress(this.jobId, 0, notificationModel);
+ this.queryProgress(this.jobId, id);
}, 5000)
- } else if (data.responseDescriptor.progress == 100) {
+ } else {
res(data);
- this.success("VNF");
- this.onboardData.status = "onboarded";
- this.notificationSuccess(notificationModel);
+ this.isUpdate = false;
+ this.notification.notificationSuccess(this.currentTab, 'OnboardingState', id);
}
return false
})
@@ -586,83 +313,48 @@ export class OnboardVnfVmComponent implements OnInit {
return mypromise;
}
- //--------------------------------------------------------------------------------
/* delete button */
- showConfirm(index, pkgid, tab, notificationModel): void {
- this.notificationAttributes = {
- "title": this.tabs[0],
- "imgPath": "../../../../assets/images/execute-inproess.png",
- "action": "OnboardingState",
- "status": "InProgress",
- "id": pkgid
- };
- this.confirmModal = this.modal.confirm({
+ showDeleteConfirm(pkgid: string): void {
+ this.modalService.confirm({
nzTitle: 'Do you Want to delete these items?',
nzContent: 'Do you Want to delete these items?',
nzOkText: 'Yes',
nzCancelText: 'No',
- nzOnOk: () => new Promise((resolve, reject) => {
- switch (tab) {
- case 'NS':
- this.notificationAttributes.title = this.tabs[0];
- this.notificationModelShow(notificationModel);
- this.deleteNsService(index, pkgid, notificationModel);
- setTimeout(Math.random() > 0.5 ? resolve : reject, 2000);
- break
- case 'VNF':
- this.notificationAttributes.title = this.tabs[1];
- this.notificationModelShow(notificationModel);
- this.deleteVnfService(index, pkgid, notificationModel);
- setTimeout(Math.random() > 0.5 ? resolve : reject, 2000);
- break
- case 'PNF':
- this.notificationAttributes.title = this.tabs[2];
- this.notificationModelShow(notificationModel);
- this.deletePnfService(index, pkgid, notificationModel);
- setTimeout(Math.random() > 0.5 ? resolve : reject, 2000);
- break
- }
+ nzOnOk: () => new Promise((resolve) => {
+ this.deleteService(pkgid, resolve);
}).catch(() => console.log('Oops errors!'))
});
}
//delete nsItem
- deleteNsService(index, pkgid, notificationModel) {
- this.myhttp.deleteNsIdData(pkgid)
- .subscribe((data) => {
- this.notificationSuccess(notificationModel);
- //refresh list after successful deletion
- this.getTableData();
- }, (err) => {
- console.log(err);
- this.notificationFailed(notificationModel);
- })
- }
-
- //delete vnfItem
- deleteVnfService(index, pkgid, notificationModel) {
- this.myhttp.deleteVnfIdData(pkgid)
- .subscribe((data) => {
- this.notificationSuccess(notificationModel);
- //refresh list after successful deletion
- this.getTableVnfData()
- }, (err) => {
- console.log(err);
- this.notificationFailed(notificationModel);
- })
- }
-
- //delete PnfItem
- deletePnfService(index, pkgid, notificationModel) {
- this.myhttp.deletePnfIdData(pkgid)
+ deleteService(pkgid, resolve) {
+ let API: string;
+ if(this.currentTab === 'NS'){
+ API = 'deleteNsIdData';
+ }else if(this.currentTab === 'VNF'){
+ API = 'deleteVnfIdData';
+ }else{
+ API = 'deletePnfIdData';
+ }
+ this.myhttp[API](pkgid)
.subscribe((data) => {
+ this.notification.notificationSuccess(this.currentTab, 'OnboardingState', pkgid);
+ resolve()
//refresh list after successful deletion
- this.notificationSuccess(notificationModel);
- this.getTablePnfData()
+ switch(this.currentTab){
+ case 'NS':
+ this.getTableData();
+ break
+ case 'VNF':
+ this.getTableVnfData();
+ break
+ case 'PNF':
+ this.getTablePnfData();
+ break
+ }
}, (err) => {
console.log(err);
- this.notificationFailed(notificationModel);
+ this.notification.notificationFailed(this.currentTab, 'OnboardingState', pkgid);
})
}
-
}
diff --git a/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.css b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.css
new file mode 100644
index 00000000..8ea1b621
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.css
@@ -0,0 +1,315 @@
+/*
+ Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+.title {
+ font: 700 18px/18px "思源黑体";
+ color: #4c5e70;
+ margin-bottom: 18px;
+}
+hr {
+ border: none;
+ height: 2px;
+ background-color: #dce1e7;
+ margin-bottom: 10px;
+}
+.model {
+ background-color: #F7F8FC;
+ overflow-y: auto;
+}
+.creation-model{
+ position: relative;
+}
+.top-title{
+ width: 100%;
+ padding: 20px;
+ position: relative;
+ display: inline-block;
+}
+.model .back,.model .back:hover{
+ position: absolute;
+ top: 10px;
+ right: 20px;
+ display: inline-block;
+ width: 35px;
+ height: 35px;
+ background:url("../../../../../assets/images/Return-icon.png") no-repeat!important;
+ background-size: 100%!important;
+ border-radius:4px;
+ color: #D7D7D7;
+ cursor: pointer;
+}
+.model .back:hover{
+ background: url("../../../../../assets/images/Return-icon-active.png")!important;
+ background-size: 100%!important;
+}
+.top-title h3.title {
+ height: 35px;
+ width: 80%;
+ font-size:16px;
+ font-family:ArialMT;
+ color:#3C4F8C;
+ line-height:35px;
+ display: inline-block;
+
+}
+.model .submit{
+ position: absolute;
+ width:90px;
+ height: 35px;
+ top: 10px;
+ right: 85px;
+ color: #fff;
+ font-size: 18px;
+ background:#0DA9E2;
+ border-radius:4px;
+ border: none!important;
+ border-color:rgba(0,0,0,0)!important;
+}
+.model .submit:hover{
+ background:#09C6E2;
+ border: none;
+}
+.model .creation {
+ width: 100%;
+ overflow-y: auto;
+ border-radius: 5px;
+ padding: 15px;
+}
+.model .creation h3 {
+ height: 20px;
+ font: 700 16px/20px "Arial";
+ margin: 5px 0px;
+ color: #000;
+}
+/* SOTN VPN */
+.model .creation .service-title{
+ margin:60px 50px;
+}
+.model .creation .service-title .info-inputs{
+ width:400px;
+ height: 42px;
+ display: inline-block;
+}
+.model .creation .service-title span{
+ height: 42px;
+ line-height: 42px;
+ vertical-align: middle;
+}
+.model .creation .service-title .lable{
+ display: inline-block;
+ font: 700 14px "Arial";
+ color: #3C4F8C;
+ height: 42px;
+ line-height: 42px;
+ vertical-align: middle;
+ margin-left: 5px;
+ margin-right: 10px;
+}
+.model .creation .service-title input {
+ width: 20%;
+ height: 42px;
+ border-radius:4px;
+ outline: none;
+ margin-right: 50px;
+}
+/* Site List */
+/* addsite model */
+.model .sitemodel,.model .sotnnpnmodel{
+ position: absolute;
+ z-index: 1001;
+ left: 50%;
+ top: 50%;
+ background-color: #fff;
+ width:90%;
+ min-width: 725px;
+ border-radius:2px;
+ overflow:auto;
+ transform: translate(-50%, -50%);
+}
+.model .sitemodel h3,.model .sotnnpnmodel h3{
+ width: 96%;
+ height: 40px;
+ line-height: 35px;
+ font-size: 18px;
+ font-weight: 500;
+ margin: 10px auto;
+ color: #06A7E2;
+ border-bottom: 2px solid;
+ border-image: -webkit-linear-gradient(#07A9E1,#30D9C4) 100 100;
+ border-image: -moz-linear-gradient(#07A9E1,#30D9C4) 100 100;
+ border-image: linear-gradient(#07A9E1,#30D9C4) 100 100;
+ border-radius:2px;
+}
+.model .sitemodel .inputs,.model .sotnnpnmodel .inputs {
+ padding: 10px 20px 0;
+}
+.model .sitemodel .inputs ul li,.model .sotnnpnmodel .inputs ul li {
+ display: inline-block;
+ height: 35px;
+ line-height: 35px;
+ width: 24.5%;
+ margin-bottom: 20px;
+}
+.model .sotnnpnmodel .inputs ul li{
+ width: 31%;
+}
+.model .sitemodel .inputs ul li span,.model .sotnnpnmodel .inputs ul li span {
+ display: inline-block;
+ line-height: 35px;
+ font-size: 14px;
+ font-weight: 500;
+ color: #3C4F8C;
+ margin-left: 10px;
+ vertical-align: middle;
+ float: left;
+}
+.model .sitemodel .inputs input,.model .sitemodel .inputs nz-select {
+ width: 42%;
+ float: right;
+ margin-right: 2%;
+}
+.model .sotnnpnmodel .inputs input{
+ width: 42%;
+ float: right;
+ margin-right: 2%;
+}
+.model .sitemodel .action,.model .sotnnpnmodel .action {
+ text-align: center;
+ margin-top: 30px;
+ margin-bottom: 20px;
+ cursor: pointer
+}
+.model .sotnnpnmodel .action{
+ margin-top: 70px;
+}
+.model .sitemodel .action button,.model .sotnnpnmodel .action button{
+ width: 126px;
+ height:40px;
+ background:#EEEEEE;
+ border-radius:2px;
+ border: none!important;
+ color: #9DA7C5;
+ font-size: 16px;
+ margin: 0 15px;
+}
+.model .sitemodel .action button:nth-child(2),.model .sotnnpnmodel .action button:nth-child(2){
+ background: #0DA9E2;
+ color: #fff;
+}
+.model .sitemodel .action button:nth-child(2):hover,.model .sotnnpnmodel .action button:nth-child(2):hover{
+ background:#09C6E2;
+}
+
+.model nz-table tbody td i.anticon:hover {
+ color: #3fa8eb;
+ cursor: pointer;
+}
+
+/* site table */
+.sitemodel h3 button,.sotnnpnmodel h3 button{
+ color: #D7D7D7;
+ width:32px;
+ height:32px;
+ background:#ffffff;
+ border-radius:4px;
+ border:1px solid #D7D7D7;
+}
+.sitemodel h3 button:hover,.sotnnpnmodel h3 button:hover{
+ background:#ffffff;
+ color: #0DA9E2;
+ border:1px solid #0DA9E2;
+}
+.sitemodel h3>button,.sotnnpnmodel h3>button{
+ float: right;
+ width: 30px;
+ height: 30px;
+ margin-right: 15px;
+}
+.model nz-table tbody th{
+ color:rgba(60,79,140,0.5);
+ font-size: 16px;
+}
+.model .site nz-table tbody td i.anticon:hover {
+ color: #3fa8eb;
+ cursor: pointer;
+}
+/* WAN Port */
+
+.mask{
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ z-index: 1000;
+ background: rgba(0, 0, 0, 0.65);
+ top:0;
+}
+
+
+/* chart */
+.model .chart {
+ width: 98%;
+ padding: 10px;
+ margin: 0 auto;
+ color: #06A7E2;
+ font-size: 16px;
+ font-weight: 500;
+ margin-bottom: 30px;
+ background: #EEF9FF;
+ border-radius:4px;
+}
+.model .chart #createChart {
+ width: 100%;
+ height: 220px;
+ margin-top: 20px;
+ position: relative;
+}
+.model .chart #createChart .siteNameP {
+ position: fixed;
+ border: 5px;
+ padding: 3px 5px;
+ color: #fff;
+ background: #999;
+ box-shadow: 0px 0px 20px #000;
+ max-width: 100px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.model .creation .sotnvpn,.model .creation .site{
+ background: #fff;
+ padding: 30px 30px 0 30px;
+}
+.siteWanTab{
+ width: 96%;
+ margin: 0 auto;
+ margin-top: 10px;
+}
+.siteWanTab th{
+ padding: 10px 8px;
+ color: #3C4F8C;
+ font-size: 16px;
+}
+.siteWanTab tr td{
+ padding: 10px 5px;
+}
+.siteWanTab .tr-border{
+ border-bottom: 1px solid #EDEDED;
+}
+.addListBtn{
+ margin-right: 30px;
+ color: #06A7E2;
+ border: none;
+ background: rgba(229,238,252,0.8);
+ cursor: pointer;
+} \ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.html b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.html
new file mode 100644
index 00000000..6a05ff11
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.html
@@ -0,0 +1,276 @@
+<!--
+ 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="model creation-model">
+
+ <div class="top-title">
+ <h3 class="title fl">{{createParams.commonParams.templateType}}
+ {{"i18nTextDefine_InstanceCreation" | translate}} </h3>
+ <div class="fl" style="width: 20%">
+ <button class="submit" nz-button (click)="submit()"><span> {{"i18nTextDefine_Create" | translate}} </span>
+ </button>
+ <button class="back" nz-button (click)="goback()"></button>
+ </div>
+ </div>
+ <!-- chart -->
+ <div class="chart">
+ <span style="padding: 25px;display: inline-block;">
+ {{"i18nTextDefine_InstanceTopology" | translate}}
+ </span>
+ <div id="createChart">
+ <svg width="100%" height="100%">
+ <image id="domain" xlink:href="assets/images/domain1.png" style="width: 15%" x="40%" y="0" />
+ </svg>
+ </div>
+ </div>
+ <!--Template resolution : Three major items-->
+ <div class="creation">
+ <nz-tabset [nzTabPosition]="'top'" [nzShowPagination]=false [nzTabBarGutter]="'2'" [nzTabBarStyle]=tabBarStyle>
+ <nz-tab nzTitle="Service Info">
+ <div class="service-title" style="clear: both">
+ <span style="color: red;">*</span><span class="lable" style="width: 60px">name:</span>
+ <input nz-input [(ngModel)]="this.templateParameters.service['name']" required="required">
+ <span style="color: red;">*</span><span class="lable">description:</span>
+ <input nz-input [(ngModel)]="this.templateParameters.service['description']">
+ </div>
+ </nz-tab>
+ <nz-tab nzTitle="Sdwanvpnresource List">
+ <div class="sotnvpn clearfix">
+ <div style="clear: both;height: 10px">
+ <h3 style="float: left;color: #3C4F8C">sdwanVPN List</h3>
+ <button nz-button (click)="addSotnvpn()" class="addListBtn"
+ style="float: right;margin-right: 10px"><i class="anticon anticon-plus"
+ style="transform: scale(1.2);font-weight: 700"></i> {{"i18nTextDefine_Add" | translate}}
+ </button>
+ </div>
+ <nz-table #sotnVpnTable [nzData]="sotnVpnTableData" [nzShowPagination]="false" nzSize="small">
+ <thead>
+ <tr>
+ <th width="30%"> NO.</th>
+ <th *ngFor="let key of getKeys(this.sotnInfo)">{{key.split("_")[1] || key}}</th>
+ <th width="10%"> Action</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let item of sotnVpnTable.data; let i = index; ">
+ <td>{{i+1}}</td>
+ <td *ngFor="let keys of getKeys(this.sotnInfo);let a = index;">
+ {{item[keys]}}
+ </td>
+ <td>
+ <span class="action" (click)="editSotnVpn(i+1)"><i
+ class="anticon anticon-edit"></i></span>
+ &nbsp;
+ <span class="action" (click)="deleteSotnVpn(i+1)"><i
+ class="anticon anticon-delete"></i></span>
+ </td>
+ </tr>
+ </tbody>
+ </nz-table>
+ </div>
+ </nz-tab>
+ <nz-tab nzTitle="Sdwansiteresource List" nzVirtualScroll>
+ <div class="site">
+ <div style="height: 10px">
+ <h3 style="float: left;color: #3C4F8C">Site List</h3>
+ <button nz-button (click)="addSite()" class="addListBtn"
+ style="float: right;margin-right: 10px"><i class="anticon anticon-plus"
+ style="transform: scale(1.2);font-weight: 700"></i>{{"i18nTextDefine_Add" | translate}}
+ </button>
+ </div>
+ <nz-table #siteTable [nzData]="siteTableData" [nzShowPagination]="false" nzSize="small" nzVirtualScroll [nzScroll]="siteTableWidth">
+ <thead>
+ <tr>
+ <th nzWidth="10%" nzLeft="0px"> NO.</th>
+ <th *ngFor="let key of getKeys(this.siteBaseData)">{{key.split("_")[1] || key}}</th>
+ <th nzWidth="20%" style="text-align: center" nzRight="0px"> Action</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let item of siteTable.data; let i = index; ">
+ <td>{{i+1}}</td>
+ <td *ngFor="let keys of getKeys(this.siteBaseData);let a = index;">
+ {{item[keys]}}
+ </td>
+ <td style="text-align: center">
+ <span class="action" (click)="editSite(i+1)"><i
+ class="anticon anticon-edit"></i></span>
+ &nbsp;
+ <span class="action" (click)="deleteSite(i+1)"><i
+ class="anticon anticon-delete"></i></span>
+ </td>
+ </tr>
+ </tbody>
+ </nz-table>
+ </div>
+ </nz-tab>
+ </nz-tabset>
+ </div>
+ <!-- sotnVpnmodel -->
+ <div class="sotnnpnmodel" *ngIf="sotnVpnModelShow">
+ <h3> {{"i18nTextDefine_Base" | translate}} </h3>
+ <div class="inputs">
+ <ul>
+ <li *ngFor="let item of this.templateParameters.sotnvpn.sdwanvpnresource_list">
+ <span *ngIf="item.required"
+ style="color: red;margin: 0;margin-right: -5px;">*</span><span>{{item.lableShow}}:</span>
+ <input nz-input [(ngModel)]="sotnInfo[item.lable]"
+ title="{{item.description ? item.description:null }}"
+ required="{{item.required==true ? 'required':null}}"></li>
+ </ul>
+ </div>
+ <div>
+ <h3>Sdwansitelan List</h3>
+ <div>
+ <div style="width: 100%;text-align: right">
+ <button nz-button (click)="addSotnSdwansitelan()" class="addListBtn"><i class="anticon anticon-plus"
+ style="transform: scale(1.2);font-weight: 700;"></i>{{"i18nTextDefine_Add" | translate}}
+ </button>
+ </div>
+ <table class="siteWanTab">
+ <thead>
+ <tr>
+ <th width="4%"> NO.</th>
+ <th *ngFor="let key of getKeys(this.sotnSdwansitelanParams)">{{key}}</th>
+ <th width="7%"> Action</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let item of sotnSdwansitelanData; let i = index;"
+ [ngClass]="{'tr-border':item.tabInputShowSdwansitelan ==false}">
+ <td>{{i+1}}</td>
+ <td *ngFor="let key of getKeys(item);let a = index;">
+ <span *ngIf="!tabInputShowSdwansitelan[i]"
+ title="{{this.templateParameters.sotnvpn.sdwansitelan_list[a]['lable']==getKeys(item)[a] ? this.templateParameters.site.sdwansitewan_list[a].description:null}}">{{item[key]}}</span>
+ <input nz-input [(ngModel)]="item[key]" *ngIf="tabInputShowSdwansitelan[i] "
+ title="{{this.templateParameters.sotnvpn.sdwansitelan_list[a]['lable']==getKeys(item)[a] ? this.templateParameters.site.sdwansitewan_list[a].description:null}}"
+ required="{{item.required==true ? 'required':null}}">
+ </td>
+ <td>
+ <span class="action" (click)="editSotnSdwansitelan(i+1,item,sotnSdwansitelanData)"><i
+ class="anticon anticon-edit" style="margin: 0 5px;"></i></span>
+ <span class="action" (click)="deleteSotnSdwansitelan(i+1,item,sotnSdwansitelanData)"><i
+ class="anticon anticon-delete"></i></span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+
+ <div class="action">
+ <button nz-button nzType="primary"
+ (click)="addSotnVpn_cancel()">{{"i18nTextDefine_Cancel" | translate}}</button>
+ <button nz-button nzType="primary" (click)="addSotnVpn_OK()">{{"i18nTextDefine_Add" | translate}}</button>
+ </div>
+ </div>
+ <!-- sitemodel -->
+ <div class="sitemodel" *ngIf="siteModelShow">
+ <h3> {{"i18nTextDefine_Base" | translate}} </h3>
+ <div class="inputs">
+ <ul>
+ <li *ngFor="let item of this.templateParameters.site.sdwansiteresource_list">
+ <span *ngIf="item.required"
+ style="color: red;margin: 0;margin-right: -5px;">*</span><span>{{item.lableShow}}:</span>
+ <input nz-input [(ngModel)]="siteBaseData[item.lable]" title="{{item.description}}"
+ required="{{item.required==true ? 'required':null}}"></li>
+ </ul>
+ </div>
+ <div>
+ <h3>Sdwandevice</h3>
+ <div>
+ <div style="width: 100%;text-align: right">
+ <button nz-button (click)="addSdwanDevice()" class="addListBtn"><i class="anticon anticon-plus"
+ style="transform: scale(1.2);font-weight: 700;"></i>{{"i18nTextDefine_Add" | translate}}
+ </button>
+ </div>
+ <table class="siteWanTab">
+ <thead>
+ <tr>
+ <th width="4%"> NO.</th>
+ <th *ngFor="let key of getKeys(this.siteCpeData)">{{key}}</th>
+ <th width="7%"> Action</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let item of siteSdwanDevice; let i = index;"
+ [ngClass]="{'tr-border':item.tabInputShowDevice ==false}">
+ <td>{{i+1}}</td>
+ <td *ngFor="let key of getKeys(item);let a = index;">
+ <span *ngIf="!tabInputShowDevice[i]"
+ title="{{this.templateParameters.site.sdwandevice_list[a]['lable']==getKeys(item)[a] ? this.templateParameters.site.sdwandevice_list[a].description:null}}">{{item[key]}}</span>
+ <input nz-input [(ngModel)]="item[key]" *ngIf="tabInputShowDevice[i] "
+ title="{{this.templateParameters.site.sdwandevice_list[a]['lable']==getKeys(item)[a] ? this.templateParameters.site.sdwandevice_list[a].description:null}}"
+ required="{{item.required==true ? 'required':null}}">
+ </td>
+ <td>
+ <span class="action" (click)="editDevicePort(i+1,item,siteSdwanDevice)"><i
+ class="anticon anticon-edit" style="margin: 0 5px;"></i></span>
+ <span class="action" (click)="deleteDevicePort(i+1,item,siteSdwanDevice)"><i
+ class="anticon anticon-delete"></i></span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+
+ <h3>Sdwansitewan List</h3>
+ <div>
+ <div style="width: 100%;text-align: right">
+ <button nz-button (click)="addSiteWan()" class="addListBtn"><i class="anticon anticon-plus"
+ style="transform: scale(1.2);font-weight: 700;"></i>{{"i18nTextDefine_Add" | translate}}
+ </button>
+ </div>
+ <nz-table class="siteWanTab" nzVirtualScroll #nzTable [nzData]="siteWanData" [nzScroll]="{ x: '2500px'}">
+ <thead>
+ <tr>
+ <th width="4%" nzLeft="0px"> NO.</th>
+ <th *ngFor="let key of getKeys(this.siteWanParams)">{{key}}</th>
+ <th width="7%" nzRight="0px"> Action</th>
+ </tr>
+ </thead>
+ <tbody>
+ <ng-template ngFor let-item [ngForOf]="nzTable.data" let-i="index">
+ <tr [ngClass]="{'tr-border':item.tabInputShowWanPort ==false}">
+ <td>{{i+1}}</td>
+ <td *ngFor="let key of getKeys(item);let a = index;">
+ <span *ngIf="!tabInputShowWanPort[i]"
+ title="{{this.templateParameters.site.sdwansitewan_list[a]['lable']==getKeys(item)[a] ? this.templateParameters.site.sdwansitewan_list[a].description:null}}">{{item[key]}}</span>
+ <input nz-input [(ngModel)]="item[key]" *ngIf="tabInputShowWanPort[i] "
+ title="{{this.templateParameters.site.sdwansitewan_list[a]['lable']==getKeys(item)[a] ? this.templateParameters.site.sdwansitewan_list[a].description:null}}"
+ required="{{item.required==true ? 'required':null}}">
+ </td>
+ <td>
+ <span class="action" (click)="editWanPort(i+1,item,siteWanData)"><i
+ class="anticon anticon-edit" style="margin: 0 5px;"></i></span>
+ <span class="action" (click)="deleteWanPort(i+1,item,siteWanData)"><i
+ class="anticon anticon-delete"></i></span>
+ </td>
+ </tr>
+ </ng-template>
+ </tbody>
+ </nz-table>
+ </div>
+ </div>
+
+ <div class="action">
+ <button nz-button nzType="primary"
+ (click)="addsite_cancel()">{{"i18nTextDefine_Cancel" | translate}}</button>
+ <button nz-button nzType="primary" (click)="addsite_OK()">{{"i18nTextDefine_Add" | translate}}</button>
+ </div>
+ </div>
+ <div class="mask" *ngIf="siteModelShow || sotnVpnModelShow"></div>
+</div> \ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.spec.ts
new file mode 100644
index 00000000..30402412
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.spec.ts
@@ -0,0 +1,24 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CcvpnCreationComponent } from './ccvpn-creation.component';
+describe('CcvpnCreationComponent', () => {
+ let component: CcvpnCreationComponent;
+ let fixture: ComponentFixture<CcvpnCreationComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ CcvpnCreationComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CcvpnCreationComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.ts b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.ts
new file mode 100644
index 00000000..752fddd6
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-creation/ccvpn-creation.component.ts
@@ -0,0 +1,724 @@
+/*
+ Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
+import * as d3 from 'd3';
+import { ServiceListService } from '../../../../core/services/serviceList.service';
+import {Observable} from "../../../../../../node_modules/rxjs";
+
+@Component({
+ selector: 'app-ccvpn-creation',
+ templateUrl: './ccvpn-creation.component.html',
+ styleUrls: ['./ccvpn-creation.component.css']
+})
+export class CcvpnCreationComponent implements OnInit {
+
+ constructor(private myhttp: ServiceListService) { }
+ @Input() createParams;
+ @Input() ccvpn_temParametersContent;
+ @Output() closeCreate = new EventEmitter();
+
+
+ ngOnInit() {
+ this.getccvpnTemParameters(this.ccvpn_temParametersContent);
+ Observable.fromEvent(window, 'resize').subscribe((event) => {
+ this.siteTableWidth["x"] = document.documentElement.clientWidth > 1400 ?"78%":"961px";
+ });
+ }
+
+ //tabBarStyle
+ tabBarStyle: object = {
+ "height": "58px",
+ "width": "694px",
+ "box-shadow": "none",
+ "margin": "0",
+ "border-radius": "4px 4px 0px 0px"
+ };
+ siteTableWidth: object = {
+ x:""
+ };
+ templateParameters: any = {
+ service: {},
+ sotnvpn: {
+ info: {},
+ sdwanvpnresource_list: [],
+ sdwansitelan_list: []
+ },
+ site: {
+ info: {},
+ sdwansiteresource_list: [],
+ sdwandevice_list: [],
+ sdwansitewan_list: []
+ }
+ };
+
+ bodyTemplateParameter: object = {};
+
+ // SOTN VPN List
+ sotnVpnTableData: any[] = [];
+ sotnInfo: object = {};//sotnmodel The first part of sotnInfo
+ sotnSdwansitelanData: any[] = [];//sotnmodel The second part of the data sdwansitelan Table
+ sotnSdwansitelanParams: object = {};//sdwansitelan Table Detailed parameters of each line of data
+ tabInputShowSdwansitelan: any[] = [];//sdwansitelan Table input&span The status identifier of the label switching display
+ // Site List
+ siteTableData: any[] = [];
+ siteBaseData: object = {}; //sitemodel one sdwansiteresource_list
+ // cpe
+ siteSdwanDevice: any[] = []; //sitemodel SdwanDevice port Table data
+ siteCpeData: object = {}; //sitemodel two sdwandevice_list
+ tabInputShowDevice: any[] = [];//Device port Table input和span The status identifier of the label switching display
+ // Wan Port
+ siteWanData: any[] = []; //sitemodel three wan port Table data
+ siteWanParams: object = {}; //wan port Table Detailed parameters of each line of data
+ tabInputShowWanPort: any[] = [];//wan port Table input和span The status identifier of the label switching display
+ getKeys(item) {
+ return Object.keys(item);
+ }
+
+ getccvpnTemParameters(data) { //Get template parameters
+ if (data.hasOwnProperty("model") && typeof data["model"] == 'string') {
+ data = JSON.parse(data["model"]);
+ }
+ let inputss = data["inputs"];
+ let inputs = {};
+ this.templateParameters.service = {
+ name: data.metadata["name"],
+ description: data.metadata.description,
+ serviceInvariantUuid: data.metadata.invariantUUID,
+ serviceUuid: data.metadata.UUID
+ };
+
+ //Screening separation sotnvpn data
+ Object.keys(inputss).map((items) => {
+ if (items.search("vpn") != -1) {
+ this.bodyTemplateParameter[items] = [];
+ inputss[items].map((item, index) => {
+ if (item["required"] != undefined) {
+ this.templateParameters["sotnvpn"]["sdwanvpnresource_list"].push(item);
+ }
+ if (item["required"] == undefined && Object.keys(item).length == 1 && Object.keys(item)[0].search("site") != -1 && item[Object.keys(item)[0]] instanceof Array === true) {
+ this.templateParameters["sotnvpn"]["sdwansitelan_list"] = item[Object.keys(item)[0]]
+ let sitelanKey = {};
+ sitelanKey[Object.keys(item)[0]] = [];
+ this.bodyTemplateParameter[items].push(sitelanKey);
+ }
+ });
+ }
+ if (items.search("site") != -1) {
+ this.bodyTemplateParameter[items] = [];
+ inputss[items].map((item, index) => {
+ if (item["required"] != undefined) {
+ this.templateParameters["site"]["sdwansiteresource_list"].push(item);
+ }
+ if (item["required"] == undefined && Object.keys(item).length == 1 && Object.keys(item)[0].search("device") != -1 && item[Object.keys(item)[0]] instanceof Array === true) {
+ this.templateParameters["site"]["sdwandevice_list"] = item[Object.keys(item)[0]];
+ let sitelanKey = {};
+ sitelanKey[Object.keys(item)[0]] = [];
+ this.bodyTemplateParameter[items].push(sitelanKey);
+ }
+ if (item["required"] == undefined && Object.keys(item).length == 1 && Object.keys(item)[0].search("site") != -1 && Object.keys(item)[0].search("device") == -1 && item[Object.keys(item)[0]] instanceof Array === true) {
+ this.templateParameters["site"]["sdwansitewan_list"] = item[Object.keys(item)[0]];
+ let sitelanKey = {};
+ sitelanKey[Object.keys(item)[0]] = [];
+ this.bodyTemplateParameter[items].push(sitelanKey);
+ }
+ });
+ }
+ });
+ this.showTemParametersSotnVpn();
+ this.showTemParametersSite();
+ }
+
+ //sotnVpn data, after combining the structure, rendering the template data to the page
+ showTemParametersSotnVpn() {
+ //sotn Data analysis, structure assembly
+ this.templateParameters.sotnvpn.sdwanvpnresource_list.map((item, index) => {
+ let input = {};
+ for (var keys in item) {
+ if (keys != "required" && keys != "type" && keys != "description") {
+ input[keys] = item[keys];
+ item["lable"] = keys;
+ item["lableShow"] = keys.split("_")[1];
+ this.sotnInfo = Object.assign(this.sotnInfo, input);
+ }
+ }
+ });
+
+ this.templateParameters.sotnvpn.sdwansitelan_list.map((item, index) => {
+ let input = {};
+ for (var keys in item) {
+ if (keys != "required" && keys != "type" && keys != "description") {
+ input[keys] = item[keys];
+ item["lable"] = keys;
+ this.sotnSdwansitelanParams = Object.assign(this.sotnSdwansitelanParams, this.sotnSdwansitelanParams, input);
+ }
+ }
+ });
+ this.sotnSdwansitelanData.push(this.sotnSdwansitelanParams);
+ this.sotnSdwansitelanData.map((item, index) => {
+ this.tabInputShowSdwansitelan[index] = true;
+ });
+ }
+
+ //Site data, after combining the structure, rendering the template to the page
+ showTemParametersSite() {
+ //site Data analysis, structure assembly
+ this.templateParameters.site.sdwansiteresource_list.map((item, index) => {
+ let input = {};
+ for (var keys in item) {
+ if (keys != "required" && keys != "type" && keys != "description") {
+ input[keys] = item[keys];
+ item["lable"] = keys;
+ item["lableShow"] = keys.split("_")[1];
+ this.siteBaseData = Object.assign(this.siteBaseData, input);
+ }
+ }
+ });
+
+ this.templateParameters.site.sdwandevice_list.map((item, index) => {
+ let input = {};
+ for (var keys in item) {
+ if (keys != "required" && keys != "type" && keys != "description") {
+ input[keys] = item[keys];
+ item["lable"] = keys;
+ this.siteCpeData = Object.assign(this.siteCpeData, input);
+ }
+ }
+ });
+ this.templateParameters.site.sdwandevice_list.map((item, index) => {
+ if (this.getKeys(item).indexOf("lable") == -1) {
+ this.templateParameters.site.sdwandevice_list.splice(index, 1)
+ }
+ });
+ this.templateParameters.site.sdwansitewan_list.push(
+ {
+ ipMode: "",
+ description: ""
+ },
+ {
+ publicIP: "",
+ description: ""
+ }
+ );
+
+ this.templateParameters.site.sdwansitewan_list.map((item, index) => {
+ let input = {};
+ for (var keys in item) {
+ if (keys != "required" && keys != "type" && keys != "description") {
+ input[keys] = item[keys];
+ item["lable"] = keys;
+ this.siteWanParams = Object.assign(this.siteWanParams, this.siteWanParams, input);
+ }
+ }
+ });
+ this.siteSdwanDevice.push(this.siteCpeData);
+ this.siteWanData.push(this.siteWanParams);
+ this.siteWanData.map((item, index) => {
+ this.tabInputShowDevice[index] = true;
+ });
+ this.siteWanData.map((item, index) => {
+ this.tabInputShowWanPort[index] = true;
+ });
+
+ }
+
+ //add,edit,delete sotnSdwansitelan
+ addSotnSdwansitelan() {
+ if (this.tabInputShowSdwansitelan.indexOf(true) > -1) {//Adding new rows is not allowed when there is a row of data being edited
+ return false;
+ }
+ let addNum = this.sotnSdwansitelanData.length;
+ let inputsData = Object.assign({}, this.sotnSdwansitelanParams);
+ Object.keys(inputsData).forEach((item) => {//Add a new line of empty data
+ if (item != "description") {
+ inputsData[item] = null;
+ }
+ });
+ this.sotnSdwansitelanData[addNum] = inputsData;
+ this.tabInputShowSdwansitelan[addNum] = true;
+ this.sotnSdwansitelanData = [...this.sotnSdwansitelanData]; //Table refresh
+ }
+ editSotnSdwansitelan(num, item, sotnSdwansitelanData) {
+ if (this.tabInputShowSdwansitelan[num - 1] == false) {
+ this.tabInputShowSdwansitelan[num - 1] = true;
+ } else {
+ this.tabInputShowSdwansitelan[num - 1] = false;
+ }
+ }
+ deleteSotnSdwansitelan(num, item, sotnSdwansitelanData) {
+ if (this.sotnSdwansitelanData.length <= 1) {
+ return false;
+ } else {
+
+ }
+ this.sotnSdwansitelanData = this.sotnSdwansitelanData.filter((d, i) => i !== num - 1);
+ }
+
+ //add,edit,delete SdwanDevice
+ addSdwanDevice() {
+ if (this.tabInputShowDevice.indexOf(true) > -1) {//Adding new rows is not allowed when there is a row of data being edited
+ return false;
+ }
+ let addNum = this.siteSdwanDevice.length;
+ let inputsData = Object.assign({}, this.siteCpeData);
+ Object.keys(inputsData).forEach((item) => {//Add a new line of empty data
+ if (item != "description") {
+ inputsData[item] = null;
+ }
+ });
+ this.siteSdwanDevice[addNum] = inputsData;
+ this.tabInputShowDevice[addNum] = true;
+ this.siteSdwanDevice = [...this.siteSdwanDevice]; //Table refresh
+ }
+
+ editDevicePort(num, item, siteSdwanDevice) {
+ if (this.tabInputShowDevice[num - 1] == false) {
+ this.tabInputShowDevice[num - 1] = true;
+ } else {
+ this.tabInputShowDevice[num - 1] = false;
+ }
+ }
+
+ deleteDevicePort(num, item, siteSdwanDevice) {
+ if (this.siteSdwanDevice.length <= 1) {
+ return false;
+ }
+ this.siteSdwanDevice = this.siteSdwanDevice.filter((d, i) => i !== num - 1);
+ }
+
+ //add,edit,delete siteWanPort
+ addSiteWan() {
+ if (this.tabInputShowWanPort.indexOf(true) > -1) {//Adding new rows is not allowed when there is a row of data being edited
+ return false;
+ }
+ let addNum = this.siteWanData.length;
+ let inputsData = Object.assign({}, this.siteWanParams);
+ Object.keys(inputsData).forEach((item) => {//Add a new line of empty data
+ if (item != "description") {
+ inputsData[item] = null;
+ }
+ });
+ this.siteWanData[addNum] = inputsData;
+ this.tabInputShowWanPort[addNum] = true;
+ this.siteWanData = [...this.siteWanData]; //Table refresh
+ }
+ editWanPort(num, item, siteWanData) {
+ if (this.tabInputShowWanPort[num - 1] == false) {
+ this.tabInputShowWanPort[num - 1] = true;
+ } else {
+ this.tabInputShowWanPort[num - 1] = false;
+ }
+ }
+ deleteWanPort(num, item, siteWanData) {
+ if (this.siteWanData.length <= 1) {
+ return false;
+ }
+ this.siteWanData = this.siteWanData.filter((d, i) => i !== num - 1);
+ }
+
+ //siteModel,sotnVpnModel Display sign
+ siteModelShow = false;
+ sotnVpnModelShow = false;
+ addSotnvpn() {
+ this.sotnVpnModelShow = true;
+ this.isEditSotnVpn = 0;
+ }
+ addSite() {
+ this.siteModelShow = true;
+ this.isEditSite = 0;
+ }
+
+ //add sotnVpn model
+ isEditSotnVpn = 0;//Edit serial number, No value, 0 means increase
+ addSotnVpn_OK() {
+ let inputs = {
+ "sdwansitelan_list": []
+ };
+ inputs = Object.assign(inputs, this.sotnInfo);
+ inputs["sdwansitelan_list"] = this.sotnSdwansitelanData.map((item) => {
+ return Object.assign({}, item);
+ });
+ if (this.isEditSotnVpn) {
+ // Edit status does not increase
+ this.sotnVpnTableData[this.isEditSotnVpn - 1] = inputs;
+ this.sotnVpnTableData = [...this.sotnVpnTableData]; //Table refresh
+ } else {
+ this.sotnVpnTableData = [...this.sotnVpnTableData, inputs];
+ }
+ Object.keys(this.sotnInfo).forEach((item) => { //Clear modal box
+ this.sotnInfo[item] = null;
+ });
+ this.sotnSdwansitelanData.forEach((item, index) => {
+ if (index > 0) {
+ this.sotnSdwansitelanData.splice(index, 1);
+ this.tabInputShowSdwansitelan.splice(index, 1);
+ } else {
+ Object.keys(item).forEach((item2) => {
+ item[item2] = null;
+ });
+ this.tabInputShowSdwansitelan[index] = true;
+ }
+
+ });
+ this.sotnVpnModelShow = false;
+ }
+
+ addSotnVpn_cancel() {
+ Object.keys(this.sotnInfo).forEach((item) => { //Clear modal box
+ this.sotnInfo[item] = null;
+ });
+ this.sotnSdwansitelanData.forEach((item, index) => {
+ if (index > 0) {
+ this.sotnSdwansitelanData.splice(index, 1);
+ } else {
+ Object.keys(item).forEach((item2) => {
+ item[item2] = null;
+ });
+ this.tabInputShowSdwansitelan[index] = true;
+ }
+
+ });
+ this.sotnVpnModelShow = false;
+ }
+
+ editSotnVpn(num) {
+ this.sotnVpnModelShow = true;
+ this.isEditSotnVpn = num;
+ Object.keys(this.sotnInfo).forEach((item) => { //Clear modal box
+ this.sotnInfo[item] = this.sotnVpnTableData[num - 1][item];
+ });
+ this.sotnSdwansitelanData = this.sotnVpnTableData[num - 1].sdwansitelan_list.map((item) => {
+ return Object.assign({}, {}, item)
+ });
+ this.sotnSdwansitelanData.forEach((item, index) => {
+ this.tabInputShowSdwansitelan[index] = false;
+ });
+ }
+
+ deleteSotnVpn(num) {
+ this.sotnVpnTableData = this.sotnVpnTableData.filter((d, i) => i !== num - 1);
+ }
+
+ // addsite model
+ isEditSite = 0; //Edit serial number, No value, 0 means increase
+ addsite_OK() {
+ let inputs = {
+ "sdwandevice_list": [],
+ "sdwansitewan_list": []
+ };
+ inputs = Object.assign(inputs, this.siteBaseData);
+ inputs["sdwandevice_list"] = this.siteSdwanDevice.map((item) => {
+ return Object.assign({}, item);
+ });
+ inputs["sdwansitewan_list"] = this.siteWanData.map((item) => {
+ return Object.assign({}, item);
+ });
+ if (this.isEditSite) {
+ // Edit status does not increase
+ this.siteTableData[this.isEditSite - 1] = inputs;
+ this.siteTableData = [...this.siteTableData]; //Table refresh
+ } else {
+ this.siteTableData = [...this.siteTableData, inputs];
+ }
+
+ Object.keys(this.siteBaseData).forEach((item) => { //Clear modal box
+ this.siteBaseData[item] = null;
+ });
+ this.siteSdwanDevice.forEach((item, index) => {
+ if (index > 0) {
+ this.siteSdwanDevice.splice(index, 1);
+ this.tabInputShowDevice.splice(index, 1);
+ } else {
+ Object.keys(item).forEach((item2) => {
+ item[item2] = null;
+ });
+ this.tabInputShowDevice[index] = true;
+ }
+ });
+ this.siteWanData.forEach((item, index) => {
+ if (index > 0) {
+ this.siteWanData.splice(index, 1);
+ this.tabInputShowWanPort.splice(index, 1);
+ } else {
+ Object.keys(item).forEach((item2) => {
+ item[item2] = null;
+ });
+ this.tabInputShowWanPort[index] = true;
+ }
+ });
+ this.drawImage(this.siteTableData);
+ this.siteModelShow = false;
+ }
+
+ addsite_cancel() {
+ Object.keys(this.siteBaseData).forEach((item) => { //Clear modal box
+ this.siteBaseData[item] = null;
+ })
+ this.siteSdwanDevice.forEach((item, index) => {
+ if (index > 0) {
+ this.siteSdwanDevice.splice(index, 1);
+ } else {
+ Object.keys(item).forEach((item2) => {
+ item[item2] = null;
+ });
+ this.tabInputShowDevice[index] = true;
+ }
+
+ });
+ this.siteWanData.forEach((item, index) => {
+ if (index > 0) {
+ this.siteWanData.splice(index, 1);
+ } else {
+ Object.keys(item).forEach((item2) => {
+ item[item2] = null;
+ });
+ this.tabInputShowWanPort[index] = true;
+ }
+
+ });
+ this.siteModelShow = false;
+ }
+
+ editSite(num) { //Edit and modify the selected site information
+ this.siteModelShow = true;
+ this.isEditSite = num;
+ Object.keys(this.siteBaseData).forEach((item) => { //Clear modal box
+ this.siteBaseData[item] = this.siteTableData[num - 1][item];
+ });
+ this.siteSdwanDevice = this.siteTableData[num - 1].sdwandevice_list.map((item) => {
+ return Object.assign({}, item)
+ });
+ this.siteSdwanDevice.forEach((item, index) => {
+ this.tabInputShowDevice[index] = false;
+ });
+ this.siteWanData = this.siteTableData[num - 1].sdwansitewan_list.map((item) => {
+ return Object.assign({}, item)
+ });
+ this.siteWanData.forEach((item, index) => {
+ this.tabInputShowWanPort[index] = false;
+ });
+ }
+
+ deleteSite(num) {
+ this.siteTableData = this.siteTableData.filter((d, i) => i !== num - 1);
+ this.drawImage(this.siteTableData);
+ }
+
+ // Site node graphic depiction
+ lines = [];
+ siteImage = [];
+ tpImage = [];
+ imgmap = {
+ '1': '../../../assets/images/domain1.png',
+ '2': '../../../assets/images/site.png'
+ };
+
+ drawImage(sitelist) {
+ let cx = 550;
+ let cy = 40;
+ let innerx1 = 720; //Left site pattern coordinate position
+ let innery1 = 40;
+ let ox = 950;
+ let oy = 50;
+ let innerx2 = 780;//Right site pattern coordinate position
+ let innery2 = 50;
+ let lateX1 = Math.random() * 30 + 55;
+ let lateX2 = 10;
+ let lateY1 = 15;
+ this.lines = sitelist.map((item, index) => {
+ let step = index + 1;
+ let x = cx;
+ let y = cy;
+ let innerX = innerx1;
+ let innerY = innery1;
+ if (step % 2 != 0) { //Left site pattern coordinate position
+ x = cx;
+ y = cy;
+ innerX = innerx1;
+ innerY = innery1;
+ if (step == 1) {
+ innerX = innerx1;
+ innerY = innery1;
+ } else {
+ x = cx - lateX1 * Math.ceil((step / 2)) >= 0 ? cx - lateX1 * Math.ceil((step / 2)) : -(cx - lateX1 * Math.ceil((step / 2)));
+ y = cy + lateY1 * Math.floor((step / 2));
+ innerX = this.lines[step - 3].innerX - lateX2;
+ innerY = y;
+ }
+ } else { //Right site pattern coordinate position
+ x = ox;
+ y = oy;
+ innerX = innerx2;
+ innerY = innery2;
+ if (step / 2 == 1) {
+ innerX = innerx2;
+ innerY = innery2;
+ } else {
+ x = ox + lateX1 * (step / 2) >= 0 ? ox + lateX1 * (step / 2) : -(ox + lateX1 * (step / 2));
+ y = oy + lateY1 * (step / 2 - 1);
+ innerX = this.lines[step - 3].innerX - lateX2;
+ innerY = y;
+ }
+ }
+ return {
+ img: "line",
+ site: item.sdwandevice_list[0].name,
+ x1: x,
+ y1: y,
+ x2: innerX,
+ y2: innerY,
+ innerX: innerX,
+ innerY: innerY
+ }
+ });
+ this.render(this.imgmap, this.lines);
+ }
+
+ render(imgmap, lines) {
+
+ //enter
+ var svg = d3.select("svg"),
+ _g_lines = svg.selectAll('line.line')
+ .data(lines)
+ .enter()
+ .append('line')
+ .style('stroke', '#3fa8eb'
+ )
+ .style('stroke-width', 2)
+ .attr('class', 'line')
+ .attr("x1", function (d) {
+ return d.x1;
+ })
+ .attr("y1", function (d) {
+ return d.y1;
+ })
+ .attr("x2", function (d) {
+ return d.x2;
+ })
+ .attr("y2", function (d) {
+ return d.y2;
+ }),
+ _g_site = svg.selectAll('g.g-site')
+ .data(lines)
+ .enter()
+ .append('g')
+ .style('cursor', 'pointer')
+ .attr('class', 'g-site');
+ _g_site.append('image')
+ .style("width", "50px")
+ .attr('xlink:href', function (d) {
+ return imgmap[2];
+ })
+ .attr("x", function (d) {
+ return d.x1 - 25;
+ })
+ .attr("y", function (d) {
+ return d.y1 - 25;
+ })
+
+ //quit
+ svg.selectAll("g.g-site")
+ .data(lines)
+ .exit() //Select a picture without bound data
+ .remove();
+ svg.selectAll("line.line")
+ .data(lines)
+ .exit() //Select the connection without binding data
+ .remove();
+
+ }
+
+ modifyJosnKey(json, oddkey, newkey) {
+
+ let val = json[oddkey];
+ delete json[oddkey];
+ json[newkey] = val;
+ }
+
+ // submit createData
+ submit() {
+ let globalCustomerId = this.createParams.commonParams.customer.id;
+ let globalServiceType = this.createParams.commonParams.serviceType.name;
+ let servicebody = {
+ service: {
+ name: this.templateParameters.service["name"],
+ description: this.templateParameters.service["description"],
+ serviceInvariantUuid: this.templateParameters.service["serviceInvariantUuid"],
+ serviceUuid: this.templateParameters.service["serviceUuid"],
+ globalSubscriberId: globalCustomerId, //customer.id
+ serviceType: globalServiceType, //serviceType.value
+ parameters: {
+ locationConstraints: [],
+ resources: [],
+ requestInputs: {}
+ },
+ }
+ };
+ let siteresource = null, sitewan = null, device = null, vpnresource = null, sitelan = null;
+ Object.keys(this.bodyTemplateParameter).map((item, index) => {
+ if (item.search("site") != -1) {
+ siteresource = item;
+ this.bodyTemplateParameter[item].map((items, index) => {
+ if (Object.keys(items)[0].search("site") != -1 && Object.keys(items)[0].search("device") == -1) {
+ sitewan = Object.keys(items)[0]
+ }
+ if (Object.keys(items)[0].search("device") != -1) {
+ device = Object.keys(items)[0]
+ }
+ });
+ }
+ if (item.search("vpn") != -1) {
+ vpnresource = item;
+ this.bodyTemplateParameter[item].map((items, index) => {
+ if (Object.keys(items)[0].search("site") != -1) {
+ sitelan = Object.keys(items)[0]
+ }
+ });
+ }
+ });
+ this.sotnVpnTableData.forEach((item, index) => {
+ Object.keys(item).map((items, index) => {
+ if (items.search("site") != -1 && item[items] instanceof Array === true) {
+ this.modifyJosnKey(item, items, sitelan)
+ }
+ });
+ });
+ this.siteTableData.forEach((item, index) => {
+ Object.keys(item).map((items, index) => {
+ if (items.search("site") != -1 && Object.keys(item)[0].search("device") == -1 && item[items] instanceof Array === true) {
+ this.modifyJosnKey(item, items, sitewan)
+ }
+ if (items.search("device") != -1) {
+ this.modifyJosnKey(item, items, device)
+ }
+ });
+ });
+ Object.keys(this.bodyTemplateParameter).map((item, index) => {
+ if (item.search("site") != -1) {
+ servicebody.service.parameters.requestInputs[item] = [].concat(this.siteTableData);
+ }
+ if (item.search("vpn") != -1) {
+ servicebody.service.parameters.requestInputs[item] = [].concat(this.sotnVpnTableData);
+ }
+ });
+
+ this.closeCreate.emit(servicebody);
+
+ }
+
+ goback() {
+ this.closeCreate.emit();
+ }
+}
diff --git a/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.css b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.css
new file mode 100644
index 00000000..8d005d40
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.css
@@ -0,0 +1,359 @@
+/*
+ Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+.title {
+ font: 700 18px/18px "思源黑体";
+ color: #4c5e70;
+ margin-bottom: 18px;
+}
+hr {
+ border: none;
+ height: 2px;
+ background-color: #dce1e7;
+ margin-bottom: 10px;
+}
+.model {
+ background-color: #F7F8FC;
+ overflow-y: auto;
+}
+.creation-model{
+ position: relative;
+ height: 100%;
+}
+.top-title{
+ width: 100%;
+ padding: 20px;
+ position: relative;
+ display: inline-block;
+}
+.model .submit{
+ position: absolute;
+ width: 90px;
+ height: 35px;
+ top: 10px;
+ right: 85px;
+ color: #fff;
+ font-size: 18px;
+ background: #0DA9E2;
+ border-radius: 4px;
+ border: none!important;
+ border-color: rgba(0,0,0,0)!important;
+}
+.model .back,.model .back:hover{
+ position: absolute;
+ top: 10px;
+ right: 20px;
+ display: inline-block;
+ width: 35px;
+ height: 35px;
+ background:url("../../../../../assets/images/Return-icon.png") no-repeat!important;
+ background-size: 100%!important;
+ border-radius:4px;
+ color: #D7D7D7;
+ cursor: pointer;
+}
+.model .back:hover{
+ background: url("../../../../../assets/images/Return-icon-active.png")!important;
+ background-size: 100%!important;
+}
+.top-title h3.title {
+ height: 35px;
+ width: 80%;
+ font-size:16px;
+ font-family:ArialMT;
+ color:#3C4F8C;
+ line-height:35px;
+ display: inline-block;
+}
+
+
+.model .detaildata {
+ width: 100%;
+ overflow-y: auto;
+ border-radius: 5px;
+ padding: 15px;
+}
+.model .detaildata h3.title {
+ height: 20px;
+ font: 700 20px/20px "Arial";
+ color: #666;
+}
+.model .detaildata h3 {
+ height: 20px;
+ font: 700 16px/20px "Arial";
+ margin: 5px 0;
+ color: #000;
+}
+.model .detaildata .service-title{
+ margin:60px 50px;
+}
+.model .detaildata .service-title .info-inputs{
+ width:400px;
+ height: 42px;
+ display: inline-block;
+}
+.model .detaildata .service-title span{
+ height: 42px;
+ line-height: 42px;
+ vertical-align: middle;
+}
+.model .detaildata .service-title .lable{
+ display: inline-block;
+ width: 100px;
+ font: 700 14px "Arial";
+ color: #3C4F8C;
+ height: 42px;
+ line-height: 42px;
+ vertical-align: middle;
+ margin-left: 5px;
+}
+.model .detaildata .service-title .service-title-input {
+ width: 230px;
+ height: 42px;
+ border-radius:4px;
+ margin-right: 30px;
+ display: inline-block;
+}
+/* SOTN VPN */
+.model .detaildata .sotnvpn ul li {
+ display: inline-block;
+ height: 40px;
+ width: 24.5%;
+ margin-bottom: 40px;
+ float: left;
+}
+.model .detaildata .sotnvpn ul li span {
+ display: inline-block;
+ font-size: 14px;
+ font-weight: 500;
+ color:rgba(60,79,140,0.5);
+ margin-left: 10px;
+ vertical-align: middle;
+ float: left;
+ width: 110px;
+}
+
+.model .sitemodel .inputs ul li span,.model .sotnnpnmodel .inputs ul li span {
+ display: inline-block;
+ line-height: 35px;
+ font-size: 14px;
+ font-weight: 500;
+ color: #3C4F8C;
+ margin-left: 10px;
+ vertical-align: middle;
+ float: left;
+}
+.model .sitemodel .inputs input,.model .sitemodel .inputs nz-select{
+ width: 42%;
+ float: right;
+ margin-right: 2%;
+}
+.model .sotnnpnmodel .inputs input{
+ width: 42%;
+ float: right;
+ margin-right: 2%;
+}
+
+/* addsite model */
+.model .sitemodel,.model .sotnnpnmodel{
+ position: absolute;
+ z-index: 1001;
+ left: 50%;
+ top: 50%;
+ background-color: #fff;
+ width:90%;
+ min-width: 725px;
+ border-radius:2px;
+ overflow:auto;
+ transform: translate(-50%, -50%);
+}
+.model .sitemodel h3,.model .sotnnpnmodel h3{
+ width: 96%;
+ height: 40px;
+ line-height: 35px;
+ font-size: 18px;
+ font-weight: 500;
+ margin: 10px auto;
+ color: #06A7E2;
+ border-bottom: 2px solid;
+ border-image: -webkit-linear-gradient(#07A9E1,#30D9C4) 100 100;
+ border-image: -moz-linear-gradient(#07A9E1,#30D9C4) 100 100;
+ border-image: linear-gradient(#07A9E1,#30D9C4) 100 100;
+ border-radius:2px;
+}
+.model .sitemodel .inputs,.model .sotnnpnmodel .inputs {
+ padding: 10px 20px 0;
+}
+.model .sitemodel .inputs ul li,.model .sotnnpnmodel .inputs ul li {
+ display: inline-block;
+ height: 35px;
+ line-height: 35px;
+ width: 24.5%;
+ margin-bottom: 20px;
+}
+.model .sotnnpnmodel .inputs ul li{
+ width: 31%;
+}
+.model .sitemodel .inputs ul li span,.model .sotnnpnmodel .inputs ul li span {
+ display: inline-block;
+ line-height: 35px;
+ font-size: 14px;
+ font-weight: 500;
+ color: #3C4F8C;
+ margin-left: 10px;
+ vertical-align: middle;
+ float: left;
+}
+.model .sitemodel .inputs input,.model .sitemodel .inputs nz-select{
+ width: 42%;
+ float: right;
+ margin-right: 2%;
+}
+.model .sotnnpnmodel .inputs div{
+ width: 42%;
+ float: right;
+ margin-right: 2%;
+}
+.model .sitemodel .action,.model .sotnnpnmodel .action {
+ text-align: center;
+ margin-top: 30px;
+ margin-bottom: 20px;
+ cursor: pointer
+}
+.model .sotnnpnmodel .action{
+ margin-top: 70px;
+}
+.model .sitemodel .action button,.model .sotnnpnmodel .action button{
+ width: 126px;
+ height:40px;
+ background:#EEEEEE;
+ border-radius:2px;
+ border: none!important;
+ color: #9DA7C5;
+ font-size: 16px;
+ margin: 0 15px;
+}
+.model .sitemodel .action button:nth-child(2),.model .sotnnpnmodel .action button:nth-child(2){
+ background: #0DA9E2;
+ color: #fff;
+}
+.model .sitemodel .action button:nth-child(2):hover,.model .sotnnpnmodel .action button:nth-child(2):hover{
+ background:#09C6E2;
+}
+
+.model nz-table tbody td i.anticon:hover {
+ color: #3fa8eb;
+ cursor: pointer;
+}
+
+/* site table */
+.sitemodel h3 button,.sotnnpnmodel h3 button{
+ color: #D7D7D7;
+ width:32px;
+ height:32px;
+ background:#ffffff;
+ border-radius:4px;
+ border:1px solid #D7D7D7;
+}
+.sitemodel h3 button:hover,.sotnnpnmodel h3 button:hover{
+ background:#ffffff;
+ color: #0DA9E2;
+ border:1px solid #0DA9E2;
+}
+.sitemodel h3>button,.sotnnpnmodel h3>button{
+ float: right;
+ width: 30px;
+ height: 30px;
+ margin-right: 15px;
+}
+
+/* site Detail */
+
+.model .detaildata .site h3 .closeDetail {
+ cursor: pointer;
+ padding: 2px 15px;
+ color: #3fa8eb;
+}
+
+.model .detaildata .sotnvpn,.model .detaildata .site{
+ background: #fff;
+ padding: 30px 30px 0 30px;
+}
+
+.mask{
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ z-index: 1000;
+ background: rgba(0, 0, 0, 0.65);
+ top:0;
+}
+
+/* charts */
+.model .chart {
+ width: 98%;
+ padding: 10px;
+ margin: 0 auto;
+ color: #06A7E2;
+ font-size: 16px;
+ font-weight: 500;
+ margin-bottom: 30px;
+ background: #EEF9FF;
+ border-radius: 4px;
+}
+.model .chart #detailChart {
+ width: 100%;
+ height: 254px;
+ margin-top: 20px;
+ position: relative;
+}
+.model .chart #detailChart .cloudcounty {
+ cursor: pointer;
+}
+
+.model .chart #detailChart .couldDetail {
+ position: absolute;
+ left: 50%;
+ top: 10px;
+ width: 80%;
+ transform: translate(-50%,0);
+ height: 160px;
+ background-color: #aaa;
+ border-radius: 5px;
+ box-shadow: 0px 0px 20px #000;
+}
+.siteWanTab{
+ width: 96%;
+ margin: 0 auto;
+ margin-top: 10px;
+}
+.siteWanTab th{
+ padding: 10px 8px;
+ color: #3C4F8C;
+ font-size: 16px;
+}
+.siteWanTab tr td{
+ padding: 10px 5px;
+}
+.siteWanTab .tr-border{
+ border-bottom: 1px solid #EDEDED;
+}
+.addListBtn{
+ margin-right: 30px;
+ color: #06A7E2;
+ border: none;
+ background: rgba(229,238,252,0.8);
+ cursor: pointer;
+}
diff --git a/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.html b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.html
new file mode 100644
index 00000000..e2b5159e
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.html
@@ -0,0 +1,421 @@
+<!--
+ 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="model creation-model" style="background: #F7F8FC;">
+ <!-- top title -->
+ <div class="top-title">
+ <h3 class="title fl">{{detailParams['service-instance-name']}} Instance Detail</h3>
+ <div class="fl" style="width: 20%">
+ <button class="submit" nz-button (click)="submitUpdate()" *ngIf="upDateShow"><span>
+ {{"i18nTextDefine_Update" | translate}} </span>
+ </button>
+ <button class="back" nz-button (click)="goback()"></button>
+ </div>
+ </div>
+ <!-- chart -->
+ <div class="chart">
+
+ <div id="detailChart">
+ <svg width="100%" height="100%" style="position: relative">
+ <!--local domain-->
+ <g class="clouds" *ngIf="vpns[0].domain!=''">
+ <image xlink:href="assets/images/domain1.png" id="domain1" width="14%" x="17%" y="14%"></image>
+ <text dx="24%" dy="51%" style="font-size: 14px; fill:#ffffff;width: 20px;">
+ {{vpns[0].domain}}
+ </text>
+ </g>
+ <g *ngIf="vpns[1]" class="clouds">
+ <image xlink:href="assets/images/domain1.png" id="domain2" width="14%" x="40%" y="40%"></image>
+ <text dx="43%" dy="19%" style="font-size: 14px; fill: #ffffff;width: 20px;">
+ {{vpns[1].domain}}
+ </text>
+ </g>
+ <!--domain1 tp-->
+ <g class="clouds" *ngIf="vpns[0].sitetpname!=''">
+ <image xlink:href="assets/images/tp.png" class="tp" id="tp1" height="16" width="20" x="21%" y="37%"></image>
+ <text dx="21%" dy="34%" style="font-size: 14px; fill: #666;width: 20px;">
+ {{vpns[0].sitetpname}}
+ </text>
+ </g>
+ <g class="clouds" *ngIf="vpns[0].othertpname!=''">
+ <image xlink:href="assets/images/tp.png" class="tp" id="tp2" height="16" width="20" x="29%" y="52%"></image>
+ <text dx="29%" dy="49%" style="font-size: 14px; fill: #666;width: 20px;">
+ {{vpns[0].othertpname}}
+ </text>
+ </g>
+ <!--domain2 tp-->
+ <g *ngIf="vpns[1]" class="clouds">
+ <image xlink:href="assets/images/tp.png" class="tp" id="tp3" height="16" width="20" x="44%" y="52%"></image>
+ <text dx="44%" dy="49%" style="font-size: 14px; fill: #666;width: 20px;">
+ {{vpns[1].othertpname}}
+ </text>
+ </g>
+ <g *ngIf="vpns[1]" class="clouds">
+ <image xlink:href="assets/images/tp.png" class="tp" id="tp4" height="16" width="20" x="51%" y="78%"></image>
+ <text dx="51%" dy="75%" style="font-size: 14px; fill: #666;width: 20px;">
+ {{vpns[1].sitetpname}}
+ </text>
+ </g>
+ <!--clouds-->
+ <g class="clouds">
+ <image xlink:href="assets/images/cloud-out.png" id="extent-cloud" width="14%" x="70%" y="11%"></image>
+ <text dx="75%" dy="39%" style="font-size: 14px; fill: #666;width: 20px;">
+ SP Partent Network
+ </text>
+ </g>
+ <!--local site-->
+ <g class="clouds" *ngIf="localSite.length>0">
+ <image xlink:href="assets/images/site.png" id="site1" height="59" width="100" x="6%" y="29%"></image>
+ <text dx="8%" dy="26%" style="font-size: 14px; fill: #666;width: 20px;">
+ {{localSite[0] && localSite[0]["service-instance-name"]}}
+ </text>
+ </g>
+ <g *ngIf="!detailSites && localSite.length>0" class="clouds">
+ <image xlink:href="assets/images/site.png" id="site2" height="59" width="100" x="61%" y="70%"
+ *ngIf="this.vpns.length == 2"></image>
+ <text dx="62%" dy="66%" style="font-size: 14px; fill: #666;width: 20px;" *ngIf="this.vpns.length == 2">
+ {{ localSite[1] && localSite[1]["service-instance-name"]}}
+ </text>
+ <image xlink:href="assets/images/site.png" id="site2" height="59" width="100" x="40%" y="44%"
+ *ngIf="this.vpns.length == 1"></image>
+ <text dx="41%" dy="40%" style="font-size: 14px; fill: #666;width: 20px;" *ngIf="this.vpns.length == 1">
+ {{ localSite[1] && localSite[1]["service-instance-name"]}}
+ </text>
+ </g>
+ <!--cloud site-->
+ <g *ngIf="!detailSites && outerSite.length>0" class="clouds">
+ <image xlink:href="assets/images/site.png" id="site3" height="59" width="100" x="89%" y="10%"></image>
+ <text dx="90%" dy="7%" style="font-size: 14px; fill: #666;width: 20px;">
+ {{outerSite[1] && outerSite[1]["service-instance-name"]}}
+ </text>
+ </g>
+ <g class="clouds" *ngIf="outerSite.length>0">
+ <image xlink:href="assets/images/site.png" id="site4" height="59" width="100" x="89%" y="40%"></image>
+ <text dx="90%" dy="37%" style="font-size: 14px; fill: #666;width: 20px;">
+ {{outerSite[0] && outerSite[0]["service-instance-name"]}}
+ </text>
+ </g>
+ <!--tp,site,domain---line -->
+ <line *ngFor="let item of detailLines" [attr.x1]="item.x1" [attr.y1]="item.y1" [attr.x2]="item.x2"
+ [attr.y2]="item.y2" style="stroke:#2F8BF7; stroke-width:2"></line>
+ <line *ngIf="detailSites" x1="45%" y1="30%" x2="75%" y2="20%" style="stroke:#FFC000; stroke-width:2"></line>
+ </svg>
+ </div>
+ </div>
+ <div class="detaildata">
+ <nz-tabset [nzTabPosition]="'top'" [nzShowPagination]=false [nzTabBarGutter]="'2'" [nzTabBarStyle]=tabBarStyle
+ [nzSelectedIndex]="upDateShow == false?0:1">
+ <nz-tab nzTitle="Service Info">
+ <div class="service-title" style="clear: both">
+ <span class="lable" style="width: 60px">name:</span>
+ <div class="service-title-input">{{templateParameters.service["name"]}}</div>
+ <span class="lable">description:</span>
+ <div class="service-title-input">{{templateParameters.service["description"]}}</div>
+ </div>
+ </nz-tab>
+ <nz-tab nzTitle="Sdwanvpnresource List">
+ <div class="sotnvpn clearfix">
+ <div style="clear: both;height: 10px">
+ <h3 style="float: left;color: #3C4F8C">sdwanVPN List</h3>
+ <button nz-button *ngIf="upDateShow" (click)="updateSotnvpn()" class="addListBtn"
+ style="float: right;margin-right: 10px"><i class="anticon anticon-plus"
+ style="transform: scale(1.2);font-weight: 700"></i> {{"i18nTextDefine_Add" | translate}}
+ </button>
+ </div>
+ <nz-table #sotnVpnTable [nzData]="sotnVpnTableData" [nzShowPagination]="false" nzSize="small">
+ <thead>
+ <tr>
+ <th width="30%"> NO.</th>
+ <th width="30%"> Name</th>
+ <th width="30%"> topology</th>
+ <th nzWidth="10%"> Action </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let item of sotnVpnTable.data; let i = index; ">
+ <td>{{i+1}}</td>
+ <td>{{item.sdwanvpn_name}}</td>
+ <td>{{item.sdwanvpn_topology}}</td>
+ <td>
+ <span class="action" (click)="showstonVpnDetail(i+1)"><i class="anticon anticon-bars"></i></span>
+ <span class="action" (click)="editUpdateSotnVpn(i+1)" *ngIf="sotnvpnnum[i]"><i
+ class="anticon anticon-edit"></i></span>
+ &nbsp;
+ <span class="action" (click)="deleteUpdateSotnVpn(i+1)" *ngIf="upDateShow"><i
+ class="anticon anticon-delete"></i></span>
+ </td>
+ </tr>
+ </tbody>
+ </nz-table>
+ </div>
+ </nz-tab>
+ <nz-tab nzTitle="Sdwansiteresource List">
+ <div class="site">
+ <div style="height: 10px">
+ <h3 style="float: left;color: #3C4F8C">Site List</h3>
+ <button nz-button *ngIf="upDateShow" (click)="updateSite()" class="addListBtn"
+ style="float: right;margin-right: 10px"><i class="anticon anticon-plus"
+ style="transform: scale(1.2);font-weight: 700"></i>{{"i18nTextDefine_Add" | translate}}
+ </button>
+ </div>
+ <nz-table #nzTable [nzData]="siteTableData" [nzShowPagination]="false" nzSize="small">
+ <thead>
+ <tr>
+ <th nzWidth="10%"> NO. </th>
+ <th nzWidth="15%"> Name </th>
+ <th nzWidth="20%"> Description </th>
+ <th nzWidth="15%"> Post Code </th>
+ <th nzWidth="15%"> Address </th>
+ <th nzWidth="15%"> VLAN </th>
+ <th nzWidth="10%"> Action </th>
+ </tr>
+ </thead>
+ <tbody>
+
+ <tr *ngFor="let item of nzTable.data; let i = index; ">
+ <td>{{i+1}}</td>
+ <td>{{item.sdwandevice_list[0].name}}</td>
+ <td>{{item.sdwansite_description}}</td>
+ <td>{{item.sdwansite_postcode}}</td>
+ <td>{{item.sdwansite_address}}</td>
+ <td>{{item.sdwansite_emails}}</td>
+ <td>
+ <span class="action" (click)="showSiteDetail(i+1)"><i class="anticon anticon-bars"></i></span>
+ &nbsp;
+ <span class="action" (click)="editUpdateSite(i+1)" *ngIf="sitenum[i]"><i
+ class="anticon anticon-edit"></i></span>
+ &nbsp;
+ <span class="action" (click)="deleteUpdateSite(i+1)" *ngIf="upDateShow"><i
+ class="anticon anticon-delete"></i></span>
+ </td>
+ </tr>
+
+ </tbody>
+ </nz-table>
+ </div>
+ </nz-tab>
+ </nz-tabset>
+ </div>
+ <!-- sotnVpn model -->
+ <div class="sotnnpnmodel" *ngIf="sotnVpnDetailShow">
+ <h3> {{"i18nTextDefine_Base" | translate}} </h3>
+ <div class="inputs">
+ <ul>
+ <li *ngFor="let item of this.templateParameters.sotnvpn.sdwanvpnresource_list">
+ <span>{{item.lableShow}}:</span>
+ <span class="input-info">{{sotnInfo[item.lable]}}</span>
+ </li>
+ </ul>
+ </div>
+ <div>
+ <h3>Sdwansitelan List</h3>
+ <div>
+ <div style="width: 100%;text-align: right">
+ </div>
+ <table class="siteWanTab">
+ <thead>
+ <tr>
+ <th width="4%"> NO.</th>
+ <th *ngFor="let key of getKeys(this.sotnSdwansitelanParams)">{{key}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let item of sotnSdwansitelanData; let i = index;" class="tr-border">
+ <td>{{i+1}}</td>
+ <td *ngFor="let key of getKeys(item);let a = index;">
+ <span *ngIf="key != 'lable' ">{{item[key]}}</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="action">
+ <button nz-button nzType="primary"
+ (click)="detailSotnVpn_cancel()">{{"i18nTextDefine_Cancel" | translate}}</button>
+ </div>
+ </div>
+ <!-- site model -->
+ <div class="sitemodel" *ngIf="siteDetail">
+ <h3> {{"i18nTextDefine_Base" | translate}} </h3>
+ <div class="inputs">
+ <ul>
+ <li *ngFor="let item of this.templateParameters.site.sdwansiteresource_list">
+ <span>{{item.lableShow}}:</span>
+ <span class="input-info">{{siteBaseData[item.lable]}}</span>
+ </li>
+ </ul>
+ </div>
+ <div>
+ <h3>Sdwandevice</h3>
+ <div>
+ <table class="siteWanTab">
+ <thead>
+ <tr>
+ <th width="4%"> NO.</th>
+ <th *ngFor="let key of getKeys(this.siteCpeData)">{{key}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let item of siteSdwanDevice; let i = index;" class="tr-border">
+ <td>{{i+1}}</td>
+ <td *ngFor="let key of getKeys(item);">
+ <span *ngIf="key != 'lable' ">{{item[key]}}</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <h3>Sdwansitewan List</h3>
+ <div>
+ <table class="siteWanTab">
+ <thead>
+ <tr>
+ <th width="4%"> NO.</th>
+ <th *ngFor="let key of getKeys(this.siteWanParams)">{{key}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let item of siteWanData; let i = index;" class="tr-border">
+ <td>{{i+1}}</td>
+ <td *ngFor="let key of getKeys(item);">
+ <span *ngIf="key != 'lable' ">{{item[key]}}</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+
+ <div class="action">
+ <button nz-button nzType="primary" (click)="detailsite_cancel()">{{"i18nTextDefine_Cancel" | translate}}</button>
+ </div>
+ </div>
+ <!-- sotnVpn update model -->
+ <div class="sotnnpnmodel" *ngIf="sotnVpnAddModelShow">
+ <h3> {{"i18nTextDefine_Base" | translate}} </h3>
+ <div class="inputs">
+ <ul>
+ <li *ngFor="let item of this.templateParameters.sotnvpn.sdwanvpnresource_list">
+ <span>{{item.lableShow}}:</span>
+ <input nz-input [(ngModel)]="sotnInfo[item.lable]"></li>
+ </ul>
+ </div>
+ <div>
+ <h3>Sdwansitelan List</h3>
+ <div>
+ <div style="width: 100%;text-align: right">
+ <button nz-button (click)="updateSotnSdwansitelan()" class="addListBtn"><i class="anticon anticon-plus"
+ style="transform: scale(1.2);font-weight: 700;"></i>{{"i18nTextDefine_Add" | translate}}
+ </button>
+ </div>
+ <table class="siteWanTab">
+ <thead>
+ <tr>
+ <th width="4%"> NO.</th>
+ <th *ngFor="let key of getKeys(this.sotnSdwansitelanParams)">{{key}}</th>
+ <th width="7%"> Action</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let item of sotnSdwansitelanData; let i = index;"
+ [ngClass]="{'tr-border':item.tabInputShowSdwansitelan ==false}">
+ <td>{{i+1}}</td>
+ <td *ngFor="let key of getKeys(item);let a = index;">
+ <span *ngIf="!tabInputShowSdwansitelan[i]">{{item[key]}}</span>
+ <input nz-input [(ngModel)]="item[key]" *ngIf="tabInputShowSdwansitelan[i] ">
+ </td>
+ <td>
+ <span class="action" (click)="editUpdateSotnSdwansitelan(i+1,item,sotnSdwansitelanData)"><i
+ class="anticon anticon-edit" style="margin: 0 5px;"></i></span>
+ <span class="action" (click)="deleteUpdateSotnSdwansitelan(i+1,item,sotnSdwansitelanData)"><i
+ class="anticon anticon-delete"></i></span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+
+ <div class="action">
+ <button nz-button nzType="primary"
+ (click)="updateSotnVpn_cancel()">{{"i18nTextDefine_Cancel" | translate}}</button>
+ <button nz-button nzType="primary" (click)="updateSotnVpn_OK()">{{"i18nTextDefine_Add" | translate}}</button>
+ </div>
+ </div>
+ <!-- site update Model -->
+ <div class="sitemodel" *ngIf="siteAddModelShow">
+ <h3> {{"i18nTextDefine_Base" | translate}} </h3>
+ <div class="inputs">
+ <ul>
+ <li *ngFor="let item of this.templateParameters.site.sdwansiteresource_list">
+ <span>{{item.lableShow}}:</span>
+ <input nz-input [(ngModel)]="siteBaseData[item.lable]"></li>
+ </ul>
+ </div>
+ <div>
+ <h3>Sdwandevice</h3>
+ <div class="inputs">
+ <ul>
+ <li *ngFor="let item of this.templateParameters.site.sdwandevice_list">
+ <span>{{item.lable}}:</span>
+ <input nz-input [(ngModel)]="siteCpeData[item.lable]">
+ </li>
+ </ul>
+ </div>
+ <h3>Sdwansitewan List</h3>
+ <div>
+ <div style="width: 100%;text-align: right">
+ <button nz-button (click)="updateSiteWan()" class="addListBtn"><i class="anticon anticon-plus"
+ style="transform: scale(1.2);font-weight: 700;"></i>{{"i18nTextDefine_Add" | translate}}
+ </button>
+ </div>
+ <table class="siteWanTab">
+ <thead>
+ <tr>
+ <th width="4%"> NO.</th>
+ <th *ngFor="let key of getKeys(this.siteWanParams)">{{key}}</th>
+ <th width="7%"> Action</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let item of siteWanData; let i = index;"
+ [ngClass]="{'tr-border':item.tabInputShowWanPort ==false}">
+ <td>{{i+1}}</td>
+ <td *ngFor="let key of getKeys(item);let a = index;">
+ <span *ngIf="!tabInputShowWanPort[i]">{{item[key]}}</span>
+ <input nz-input [(ngModel)]="item[key]" *ngIf="tabInputShowWanPort[i] ">
+ </td>
+ <td>
+ <span class="action" (click)="editUpdateWanPort(i+1,item,siteWanData)"><i class="anticon anticon-edit"
+ style="margin: 0 5px;"></i></span>
+ <span class="action" (click)="deleteUpdateWanPort(i+1,item,siteWanData)"><i
+ class="anticon anticon-delete"></i></span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+
+ <div class="action">
+ <button nz-button nzType="primary" (click)="updatesite_cancel()">{{"i18nTextDefine_Cancel" | translate}}</button>
+ <button nz-button nzType="primary" (click)="updatesite_OK()">{{"i18nTextDefine_Add" | translate}}</button>
+ </div>
+ </div>
+ <div class="mask" *ngIf="sotnVpnDetailShow || siteDetail || sotnVpnAddModelShow || siteAddModelShow"
+ (click)="hiddenModel()"></div>
+</div> \ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.spec.ts
new file mode 100644
index 00000000..b6f3171f
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.spec.ts
@@ -0,0 +1,69 @@
+/*
+ Copyright (C) 2018 CMCC, Inc. and others. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { NgZorroAntdModule } from 'ng-zorro-antd';
+import { HttpClientModule } from '@angular/common/http';
+import { NZ_I18N, en_US } from 'ng-zorro-antd';
+import { TranslateModule, TranslateLoader, TranslateService, TranslateFakeLoader } from '@ngx-translate/core';
+
+import { CcvpnDetailComponent } from './ccvpn-detail.component';
+import { ServiceListService } from '../../core/services/serviceList.service';
+
+describe('CcvpnDetailComponent', () => {
+ let component: CcvpnDetailComponent;
+ let fixture: ComponentFixture<CcvpnDetailComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [CcvpnDetailComponent],
+ imports: [TranslateModule.forRoot({ loader: { provide: TranslateLoader, useClass: TranslateFakeLoader } }),
+ NgZorroAntdModule.forRoot(), HttpClientModule],
+ providers: [ServiceListService, { provide: NZ_I18N, useValue: en_US }]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ let detailshow = false;
+ detailData: Object;
+ let serviceDetail = (service) => {
+ 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);
+ }
+ })
+ this.detailshow = true;
+ this.detailData = service;
+ component.detailParams = this.detailData
+ fixture = TestBed.createComponent(CcvpnDetailComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ };
+
+ it('should create', () => {
+ console.log(component);
+ expect(component).toBeTruthy();
+ });
+ });
+
+});
diff --git a/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.ts b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.ts
new file mode 100644
index 00000000..a253b044
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/ccvpn-detail/ccvpn-detail.component.ts
@@ -0,0 +1,797 @@
+/*
+ Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
+import { ServiceListService } from '../../../../core/services/serviceList.service';
+import * as d3 from 'd3';
+
+@Component({
+ selector: 'app-ccvpn-detail',
+ templateUrl: './ccvpn-detail.component.html',
+ styleUrls: ['./ccvpn-detail.component.css']
+})
+export class CcvpnDetailComponent implements OnInit {
+
+ constructor(private myhttp: ServiceListService) { }
+
+ ngOnInit() {
+ this.dataInit();
+ this.drawImages();
+ }
+
+ @Input() detailParams;
+ @Input() upDateShow;
+ @Output() closeDetail = new EventEmitter();
+ @Output() closeUpdate = new EventEmitter();
+
+ tabBarStyle = {
+ "height": "58px",
+ "width": "694px",
+ "box-shadow": "none",
+ "margin": "0",
+ "border-radius": "4px 4px 0px 0px"
+ };
+ input_parameters: any;
+ templateParameters = {
+ service: {},
+ sotnvpn: {
+ // info: {},
+ sdwanvpnresource_list: [],
+ sdwansitelan_list: []
+ },
+ site: {
+ // info: {},
+ sdwansiteresource_list: [],
+ sdwandevice_list: [],
+ sdwansitewan_list: []
+ }
+ };
+ bodyTemplateParameter = {};
+
+ // SOTN VPN List
+ sotnVpnTableData = [];
+ sotnInfo = {};//sotnmodel The first part of sotnInfo
+ sotnSdwansitelanData = [];//sotnmodel The second part of the data sdwansitelan Table
+ sotnSdwansitelanParams = {};//sdwansitelan Table Detailed parameters of each line of data
+ tabInputShowSdwansitelan = [];//sdwansitelan table input and span
+ // Site List
+ siteTableData = [];
+ siteBaseData = {}; //sitemodel one sdwansiteresource_list
+ // cpe
+ siteSdwanDevice = []; //sitemodel SdwanDevice port Table data
+ siteCpeData = {}; //sitemodel two sdwandevice_list
+ tabInputShowDevice = [];//Device port input and span
+ // Wan Port
+ siteWanData = []; //sitemodel three wan port Table data
+ siteWanParams = {}; //wan port Table Detailed parameters of each line of data
+ tabInputShowWanPort = [];//wan port table input and span
+ sitenum = [];
+ sotnvpnnum = [];
+
+ getKeys(item) {
+ return Object.keys(item);
+ }
+ //tabBarStyle
+ dataInit() {
+ // this.input_parameters = JSON.stringify(this.detailParams['input-parameters'])
+ if (this.detailParams['input-parameters']) {
+ this.input_parameters = JSON.parse(this.detailParams['input-parameters']);
+ } else {
+ return false;
+ }
+ this.templateParameters.service = {
+ name: this.input_parameters.service.name,
+ description: this.input_parameters.service.description,
+ serviceInvariantUuid: this.input_parameters.service["serviceInvariantUuid"],
+ serviceUuid: this.input_parameters.service["serviceUuid"]
+ };
+ let inputs = this.input_parameters.service.parameters.requestInputs;
+
+ Object.keys(inputs).map((items) => {
+ if (items.search("vpn") != -1) {
+ this.bodyTemplateParameter[items] = [];
+ inputs[items].map((item, index) => {
+ this.sotnVpnTableData.push(item);
+ this.sotnvpnnum.push(false);
+ });
+ let sdwanvpnresource_list = inputs[items][0];
+ Object.keys(sdwanvpnresource_list).forEach((its) => {
+ let input = {};
+ if (its.search("site") != -1 && sdwanvpnresource_list[its] instanceof Array === true) {
+ Object.keys(sdwanvpnresource_list[its][0]).forEach((i) => {
+ let input1 = {};
+ input1[i] = sdwanvpnresource_list[its][i];
+ this.templateParameters["sotnvpn"]["sdwansitelan_list"].push(input1);
+ })
+ let sitelanKey = {};
+ sitelanKey[its] = [];
+ this.bodyTemplateParameter[items].push(sitelanKey);
+ }
+ if (its.search("sitelan") == -1 && sdwanvpnresource_list[its] instanceof Array === false) {
+ input[its] = sdwanvpnresource_list[its];
+ this.templateParameters["sotnvpn"]["sdwanvpnresource_list"].push(input);
+ }
+ });
+ }
+ if (items.search("site") != -1) {
+ this.bodyTemplateParameter[items] = [];
+ inputs[items].map((item, index) => {
+ this.siteTableData.push(item);
+ this.sitenum.push(false);
+ });
+ let sdwansiteresource_list = inputs[items][0];
+ Object.keys(sdwansiteresource_list).forEach((its) => {
+ let input2 = {};
+ if (its.search("device") != -1 && sdwansiteresource_list[its] instanceof Array === true) {
+ this.templateParameters["site"]["sdwandevice_list"][0] = sdwansiteresource_list[its][0];
+ let sitelanKey = {};
+ sitelanKey[its] = [];
+ this.bodyTemplateParameter[items].push(sitelanKey);
+ }
+ if (its.search("site") != -1 && its.search("device") == -1 && sdwansiteresource_list[its] instanceof Array === true) {
+ this.templateParameters["site"]["sdwansitewan_list"][0] = sdwansiteresource_list[its][0];
+ let sitelanKey = {};
+ sitelanKey[its] = [];
+ this.bodyTemplateParameter[items].push(sitelanKey);
+ }
+ if (its.search("device") == -1 && sdwansiteresource_list[its] instanceof Array === false) {
+ input2[its] = sdwansiteresource_list[its];
+ this.templateParameters["site"]["sdwansiteresource_list"].push(input2);
+ }
+ });
+
+ }
+ });
+
+ this.showTemParametersSotnVpn();
+ this.showTemParametersSite();
+
+ }
+
+ //sotnVpn data, after combining the structure, rendering the template data to the page
+ showTemParametersSotnVpn() {
+ //sotn Data analysis, structure assembly
+ this.templateParameters.sotnvpn.sdwanvpnresource_list.map((item, index) => {
+ let input = {};
+ for (let keys in item) {
+ if (keys != "required" && keys != "type" && keys != "description") {
+ input[keys] = item[keys];
+ item["lable"] = keys;
+ item["lableShow"] = keys.split("_")[1];
+ this.sotnInfo = Object.assign(this.sotnInfo, input);
+ }
+ }
+ });
+
+ this.templateParameters.sotnvpn.sdwansitelan_list.map((item, index) => {
+ let input = {};
+ for (let keys in item) {
+ if (keys != "required" && keys != "type" && keys != "description") {
+ input[keys] = item[keys];
+ item["lable"] = keys;
+ this.sotnSdwansitelanParams = Object.assign(this.sotnSdwansitelanParams, this.sotnSdwansitelanParams, input);
+ }
+ }
+ });
+ this.sotnSdwansitelanData.push(this.sotnSdwansitelanParams);
+ this.sotnSdwansitelanData.map((item, index) => {
+ this.tabInputShowSdwansitelan[index] = true;
+ });
+ }
+
+ //Site data, after combining the structure, rendering the template to the page
+ showTemParametersSite() {
+ //site Data analysis, structure assembly
+ this.templateParameters.site.sdwansiteresource_list.map((item, index) => {
+ let input = {};
+ for (let keys in item) {
+ if (keys != "required" && keys != "type" && keys != "description") {
+ input[keys] = item[keys];
+ item["lable"] = keys;
+ item["lableShow"] = keys.split("_")[1];
+ this.siteBaseData = Object.assign(this.siteBaseData, input);
+ }
+ }
+ });
+
+ this.templateParameters.site.sdwandevice_list.map((item, index) => {
+ let input = {};
+ for (let keys in item) {
+ if (keys != "required" && keys != "type" && keys != "description") {
+ input[keys] = item[keys];
+ item["lable"] = keys;
+ this.siteCpeData = Object.assign(this.siteCpeData, input);
+ }
+ }
+ });
+ this.templateParameters.site.sdwandevice_list.map((item, index) => {
+ if (this.getKeys(item).indexOf("lable") == -1) {
+ this.templateParameters.site.sdwandevice_list.splice(index, 1)
+ }
+ });
+ this.templateParameters.site.sdwansitewan_list.map((item, index) => {
+ let input = {};
+ for (let keys in item) {
+ if (keys != "required" && keys != "type" && keys != "description") {
+ input[keys] = item[keys];
+ item["lable"] = keys;
+ this.siteWanParams = Object.assign(this.siteWanParams, this.siteWanParams, input);
+ }
+ }
+ });
+ this.siteSdwanDevice.push(this.siteCpeData);
+ this.siteSdwanDevice.map((item, index) => {
+ this.tabInputShowDevice[index] = true;
+ });
+ this.siteWanData.push(this.siteWanParams);
+ this.siteWanData.map((item, index) => {
+ this.tabInputShowWanPort[index] = true;
+ });
+ }
+
+ //sotnVpn detail show
+ sotnVpnDetailShow = false;
+ isEditSotnVpn = 0;
+ showstonVpnDetail(num) {
+ this.sotnVpnDetailShow = true;
+ this.isEditSotnVpn = num;
+ Object.keys(this.sotnInfo).forEach((item) => {
+ this.sotnInfo[item] = this.sotnVpnTableData[num - 1][item];
+ });
+ this.sotnSdwansitelanData = this.sotnVpnTableData[num - 1].sdwansitelan_list.map((item) => {
+ return Object.assign({}, {}, item)
+ });
+ }
+ detailSotnVpn_cancel() {
+ this.sotnVpnDetailShow = false;
+ }
+
+ // site detail show
+ siteDetail = false;
+ isEditSite = 0;
+ showSiteDetail(num) {
+ this.siteDetail = true;
+ this.isEditSite = num;
+ Object.keys(this.siteBaseData).forEach((item) => {
+ this.siteBaseData[item] = this.siteTableData[num - 1][item];
+ });
+ this.siteSdwanDevice = this.siteTableData[num - 1].sdwandevice_list.map((item) => {
+ return Object.assign({}, {}, item)
+ });
+ this.siteWanData = this.siteTableData[num - 1].sdwansitewan_list.map((item) => {
+ return Object.assign({}, {}, item)
+ });
+ }
+ detailsite_cancel() {
+ this.siteDetail = false;
+ }
+ deleteUpdateSite(num) {
+ this.siteTableData = this.siteTableData.filter((d, i) => i !== num - 1);
+ this.sitenum.splice(num - 1, 1);
+ }
+
+ //sotnVpn addModel
+ sotnVpnAddModelShow = false;
+
+ updateSotnVpn_OK() {
+ let inputs = {
+ "sdwansitelan_list": []
+ };
+ inputs = Object.assign(inputs, this.sotnInfo);
+ inputs["sdwansitelan_list"] = this.sotnSdwansitelanData.map((item) => {
+ return Object.assign({}, item);
+ });
+ if (this.isEditSotnVpn) {
+
+ this.sotnVpnTableData[this.isEditSotnVpn - 1] = inputs;
+ this.sotnVpnTableData = [...this.sotnVpnTableData];
+ } else {
+ // this.siteTableData.push(inputs);
+ this.sotnVpnTableData = [...this.sotnVpnTableData, inputs];
+ this.sotnvpnnum = [...this.sotnvpnnum, true];
+ }
+ Object.keys(this.sotnInfo).forEach((item) => {
+ this.sotnInfo[item] = null;
+ });
+ this.sotnSdwansitelanData.forEach((item, index) => {
+ if (index > 0) {
+ this.sotnSdwansitelanData.splice(index, 1);
+ this.tabInputShowSdwansitelan.splice(index, 1);
+ } else {
+ Object.keys(item).forEach((item2) => {
+ item[item2] = null;
+ });
+ this.tabInputShowSdwansitelan[index] = true;
+ }
+
+ });
+ this.sotnVpnAddModelShow = false;
+ }
+
+ updateSotnVpn_cancel() {
+ Object.keys(this.sotnInfo).forEach((item) => {
+ this.sotnInfo[item] = null;
+ });
+ this.sotnSdwansitelanData.forEach((item, index) => {
+ if (index > 0) {
+ this.sotnSdwansitelanData.splice(index, 1);
+ } else {
+ Object.keys(item).forEach((item2) => {
+ item[item2] = null;
+ });
+ this.tabInputShowSdwansitelan[index] = true;
+ }
+
+ });
+ this.sotnVpnAddModelShow = false;
+ }
+
+ editUpdateSotnVpn(num) {
+ this.sotnVpnAddModelShow = true;
+ this.isEditSotnVpn = num;
+ Object.keys(this.sotnInfo).forEach((item) => {
+ this.sotnInfo[item] = this.sotnVpnTableData[num - 1][item];
+ });
+ this.sotnSdwansitelanData = this.sotnVpnTableData[num - 1].sdwansitelan_list.map((item) => {
+ return Object.assign({}, {}, item)
+ });
+ this.sotnSdwansitelanData.forEach((item, index) => {
+ this.tabInputShowSdwansitelan[index] = false;
+ });
+ }
+
+ deleteUpdateSotnVpn(num) {
+ this.sotnVpnTableData = this.sotnVpnTableData.filter((d, i) => i !== num - 1);
+ this.sotnvpnnum.splice(num - 1, 1);
+ }
+ updateSotnSdwansitelan() {
+ if (this.tabInputShowSdwansitelan.indexOf(true) > -1) {
+ return false;
+ }
+ let addNum = this.sotnSdwansitelanData.length;
+ let inputsData = Object.assign({}, this.sotnSdwansitelanParams);
+ Object.keys(inputsData).forEach((item) => {
+ if (item != "description") {
+ inputsData[item] = null;
+ }
+ });
+ this.sotnSdwansitelanData[addNum] = inputsData;
+ this.tabInputShowSdwansitelan[addNum] = true;
+ this.sotnSdwansitelanData = [...this.sotnSdwansitelanData];
+ }
+ editUpdateSotnSdwansitelan(num, item, sotnSdwansitelanData) {
+ if (this.tabInputShowSdwansitelan[num - 1] == false) {
+ this.tabInputShowSdwansitelan[num - 1] = true;
+ } else {
+ this.tabInputShowSdwansitelan[num - 1] = false;
+ }
+ }
+ deleteUpdateSotnSdwansitelan(num, item, sotnSdwansitelanData) {
+ if (this.sotnSdwansitelanData.length <= 1) {
+ return false;
+ } else {
+
+ }
+ this.sotnSdwansitelanData = this.sotnSdwansitelanData.filter((d, i) => i !== num - 1);
+ }
+
+ // site addModel
+ siteAddModelShow = false;
+
+ updateSotnvpn() {
+ this.sotnVpnAddModelShow = true;
+ this.isEditSotnVpn = 0;
+ }
+
+ updateSite() {
+ this.siteAddModelShow = true;
+ this.isEditSite = 0;
+ }
+
+ editUpdateSite(num) {
+ this.siteAddModelShow = true;
+ this.isEditSite = num;
+ Object.keys(this.siteBaseData).forEach((item) => {
+ this.siteBaseData[item] = this.siteTableData[num - 1][item];
+ });
+ this.siteSdwanDevice = this.siteTableData[num - 1].sdwandevice_list.map((item) => {
+ return Object.assign({}, item)
+ });
+ this.siteSdwanDevice.forEach((item, index) => {
+ this.tabInputShowDevice[index] = false;
+ });
+ this.siteWanData = this.siteTableData[num - 1].sdwansitewan_list.map((item) => {
+ return Object.assign({}, item)
+ });
+ this.siteWanData.forEach((item, index) => {
+ this.tabInputShowWanPort[index] = false;
+ });
+ }
+
+ updatesite_cancel() {
+ Object.keys(this.siteBaseData).forEach((item) => {
+ this.siteBaseData[item] = null;
+ })
+ this.siteSdwanDevice.forEach((item, index) => {
+ if (index > 0) {
+ this.siteSdwanDevice.splice(index, 1);
+ } else {
+ Object.keys(item).forEach((item2) => {
+ item[item2] = null;
+ });
+ this.tabInputShowDevice[index] = true;
+ }
+
+ });
+ this.siteWanData.forEach((item, index) => {
+ if (index > 0) {
+ this.siteWanData.splice(index, 1);
+ } else {
+ Object.keys(item).forEach((item2) => {
+ item[item2] = null;
+ });
+ this.tabInputShowWanPort[index] = true;
+ }
+
+ });
+ this.siteAddModelShow = false;
+ }
+
+ updatesite_OK() {
+ let inputs = {
+ "sdwandevice_list": [],
+ "sdwansitewan_list": []
+ };
+ inputs = Object.assign(inputs, this.siteBaseData);
+ inputs["sdwandevice_list"] = this.siteSdwanDevice.map((item) => {
+ return Object.assign({}, item);
+ });
+ inputs["sdwansitewan_list"] = this.siteWanData.map((item) => {
+ return Object.assign({}, item);
+ });
+ if (this.isEditSite) {
+ // Edit status does not increase
+ this.siteTableData[this.isEditSite - 1] = inputs;
+ this.siteTableData = [...this.siteTableData]; //Table refresh
+ } else {
+ // this.siteTableData.push(inputs);
+ this.siteTableData = [...this.siteTableData, inputs];
+ this.sitenum = [...this.sitenum, true];
+ }
+
+ Object.keys(this.siteBaseData).forEach((item) => { //Clear modal box
+ this.siteBaseData[item] = null;
+ });
+ this.siteSdwanDevice.forEach((item, index) => {
+ if (index > 0) {
+ this.siteSdwanDevice.splice(index, 1);
+ this.tabInputShowDevice.splice(index, 1);
+ } else {
+ Object.keys(item).forEach((item2) => {
+ item[item2] = null;
+ });
+ this.tabInputShowDevice[index] = true;
+ }
+
+ });
+ this.siteWanData.forEach((item, index) => {
+ if (index > 0) {
+ this.siteWanData.splice(index, 1);
+ this.tabInputShowWanPort.splice(index, 1);
+ } else {
+ Object.keys(item).forEach((item2) => {
+ item[item2] = null;
+ });
+ this.tabInputShowWanPort[index] = true;
+ }
+
+ });
+ console.log(this.siteTableData);
+ this.siteAddModelShow = false;
+ }
+
+ //add.edit,detele siteWanPort
+ updateSiteWan() {
+ if (this.tabInputShowWanPort.indexOf(true) > -1) {//Adding new rows is not allowed when there is a row of data being edited
+ return false;
+ }
+ let addNum = this.siteWanData.length;
+ let inputsData = Object.assign({}, this.siteWanParams);
+ Object.keys(inputsData).forEach((item) => {//Add a new line of empty data
+ if (item != "description") {
+ inputsData[item] = null;
+ }
+ });
+ this.siteWanData[addNum] = inputsData;
+ this.tabInputShowWanPort[addNum] = true;
+ this.siteWanData = [...this.siteWanData]; //Table refresh
+ }
+
+ editUpdateWanPort(num, item, siteWanData) {
+ if (this.tabInputShowWanPort[num - 1] == false) {
+ this.tabInputShowWanPort[num - 1] = true;
+ } else {
+ this.tabInputShowWanPort[num - 1] = false;
+ }
+ }
+
+ deleteUpdateWanPort(num, item, siteWanData) {
+ if (this.siteWanData.length <= 1) {
+ return false;
+ }
+ this.siteWanData = this.siteWanData.filter((d, i) => i !== num - 1);
+ }
+
+ // site node graphic depiction
+ // site sort,Check tp add pnf according to site --> allotted-resource
+ localSite = [];//local site
+ outerSite = [];//outer site
+
+ getSiteAResource() {
+ return new Promise((res, rej) => {
+ this.detailParams.siteSer.forEach((site) => {
+ site["relationship-list"]["relationship"].find((item) => { return item["related-to"] == "site-resource" }) ? this.localSite.push(site) : this.outerSite.push(site);
+ });
+
+ if (this.localSite[0] && this.localSite[0]["service-instance-name"].startsWith("Dc")) {
+ this.localSite.reverse();
+ }
+
+ if (this.outerSite[0] && this.outerSite[0]["service-instance-name"].startsWith("Dc")) {
+ this.outerSite.reverse();
+ }
+ if (this.localSite.length > 0) {
+ this.detailLines = [].concat(this.detailLiness);
+ this.localSite.forEach((site) => {
+ let obj = {
+ customerId: this.detailParams.customer.id,
+ serviceType: this.detailParams.serviceType,
+ serviceId: site["service-instance-id"]
+ };
+ this.myhttp.getAllottedResource(obj)
+ .subscribe((data) => {
+ let resource = data["allotted-resource"].find((item) => { return item["allotted-resource-name"] == "sotn ar" });
+ let tps_pnfs = resource["relationship-list"]["relationship"].find((item) => { return item["related-to"] == "p-interface" })["relationship-data"];
+ site.tpsitename = tps_pnfs.find((item) => { return item["relationship-key"] == "p-interface.interface-name" })["relationship-value"];
+ res("sites-domain");
+ })
+ })
+ } else {
+ return false;
+ }
+ })
+ }
+
+
+ vpns = [{ name: "", tps: [], domain: "", sitetpname: "", othertpname: "" }];
+
+
+ getSotnAresource() {
+ return new Promise((res, rej) => {
+ let connectivityId = this.detailParams["relationship-list"]["relationship"]
+ .find((item) => {
+ return item["related-to"] == "connectivity"
+ })["relationship-data"]
+ .find((item2) => {
+ return item2["relationship-key"] == "connectivity.connectivity-id"
+ })["relationship-value"];
+ this.myhttp.getSotnConnectivity(connectivityId)
+ .subscribe((data) => {
+ let vpns = data.connectivity[0]["relationship-list"]["relationship"]
+ .filter((item) => {
+ return item["related-to"] == "vpn-binding"
+ })
+ .map((item2) => {
+ return item2["relationship-data"].find((item3) => {
+ return item3["relationship-key"] == "vpn-binding.vpn-id"
+ })["relationship-value"]
+ });
+ this.detailParams.vpns = vpns.map((item) => {
+ return { name: item }
+ });
+ this.detailParams.vpns.forEach((vpn, index) => {
+ this.myhttp.getVpnBinding(vpn.name)
+ .subscribe((data2) => {
+ let tps_pnfs = data2["vpn-binding"][0]["relationship-list"]["relationship"]
+ .filter((item) => {
+ return item["related-to"] == "p-interface"
+ })
+ .map((item2) => {
+ return item2["relationship-data"]
+ });
+ let pnfname = tps_pnfs.map((item) => {
+ return item.find((item2) => {
+ return item2["relationship-key"] == "pnf.pnf-name"
+ })["relationship-value"]
+ });
+ let tpnames = tps_pnfs.map((item) => {
+ return item.find((item2) => {
+ return item2["relationship-key"] == "p-interface.interface-name"
+ })["relationship-value"]
+ });
+ vpn.tps = tpnames;
+ this.myhttp.getPnfDetail(pnfname[0])
+ .subscribe((data2) => {
+ let networkRelation = data2["relationship-list"]["relationship"].find((item) => {
+ return item["related-to"] == "network-resource"
+ })["relationship-data"];
+ vpn.domain = networkRelation.find((item) => {
+ return item["relationship-key"] == "network-resource.network-id"
+ })["relationship-value"];
+ if (this.localSite[index]) {
+ vpn.sitetpname = this.localSite.find((site) => {
+ return tpnames.includes(site.tpsitename)
+ }).tpsitename;
+ vpn.othertpname = tpnames.find((name) => {
+ return name != vpn.sitetpname
+ });
+ } else {
+ vpn.sitetpname = this.localSite[0].tpsitename;
+ vpn.othertpname = tpnames.find((name) => {
+ return name != vpn.sitetpname
+ });
+ }
+ this.vpns = this.detailParams.vpns;
+ res(this.detailParams.vpns)
+ });
+ })
+ })
+ })
+ })
+ }
+
+
+ drawImages() {
+
+ this.getSiteAResource().then((data) => {
+ return this.getSotnAresource()
+ }).then((data) => {
+ this.detailSites = this.detailParams.serviceDomain == "CCVPN" ? false : true;
+ // When there is only one vpn
+ if (this.detailParams.serviceDomain == "CCVPN" && this.vpns.length == 1) {
+ this.detailLines.length = this.detailLines.length - 3;
+ // this.detailLines.push(line);
+ // when local site have 2
+ if (this.localSite.length == 2) {
+ let line = {
+ "x1": "30%", "y1": "55%", "x2": "42%", "y2": "55%"//tp2--tp3
+ };
+ this.detailLines.push(line);
+ }
+ // when cloud site have 2
+ if (this.outerSite.length == 2) {
+ let line = {
+ "x1": "81%", "y1": "21%", "x2": "90%", "y2": "21%"//out-domain--site3
+ };
+ this.detailLines.push(line);
+ }
+ }
+ });
+ let allnodes = [this.getSiteAResource(), this.getSotnAresource()];
+ Promise.all(allnodes).then((data) => {
+ })
+ }
+
+ detailSites = false;
+ detailLines = [];
+ detailLiness = [ //Details of the topology map connection coordinates
+ {
+ "x1": "9%", "y1": "40%", "x2": "21%", "y2": "40%"//site1--tp1
+ },
+
+ {
+ "x1": "83%", "y1": "51%", "x2": "91%", "y2": "51%"//out-domain--site4
+ },
+
+ {
+ "x1": "52%", "y1": "81%", "x2": "63%", "y2": "81%"//site2--tp4
+ },
+ {
+ "x1": "81%", "y1": "21%", "x2": "90%", "y2": "21%"//out-domain--site3
+ },
+ {
+ "x1": "30%", "y1": "55%", "x2": "44%", "y2": "55%"//tp2--tp3
+ }
+ ];
+
+ modifyJosnKey(json, oddkey, newkey) {
+
+ let val = json[oddkey];
+ delete json[oddkey];
+ json[newkey] = val;
+ }
+
+ // ccvpn update
+ submitUpdate() {
+ let globalCustomerId = this.detailParams.customer.id;
+ let globalServiceType = this.detailParams.serviceType.name;
+ let servicebody = {
+ service: {
+ name: this.templateParameters.service["name"],
+ description: this.templateParameters.service["description"],
+ serviceInvariantUuid: this.templateParameters.service["serviceInvariantUuid"],
+ serviceUuid: this.templateParameters.service["serviceUuid"],
+ globalSubscriberId: globalCustomerId, //customer.id
+ serviceType: globalServiceType, //serviceType.value
+ parameters: {
+ locationConstraints: [],
+ resources: [],
+ requestInputs: {
+ sdwanvpnresource_list: [],
+ sdwansiteresource_list: []
+ }
+ }
+ }
+ };
+ let siteresource = null, sitewan = null, device = null, vpnresource = null, sitelan = null;
+ Object.keys(this.bodyTemplateParameter).map((item, index) => {
+ if (item.search("site") != -1) {
+ siteresource = item;
+ this.bodyTemplateParameter[item].map((items, index) => {
+ if (Object.keys(items)[0].search("site") != -1 && Object.keys(items)[0].search("device") == -1) {
+ sitewan = Object.keys(items)[0]
+ }
+ if (Object.keys(items)[0].search("device") != -1) {
+ device = Object.keys(items)[0]
+ }
+ });
+ }
+ if (item.search("vpn") != -1) {
+ vpnresource = item;
+ this.bodyTemplateParameter[item].map((items, index) => {
+ if (Object.keys(items)[0].search("site") != -1) {
+ sitelan = Object.keys(items)[0]
+ }
+ });
+ }
+ });
+ this.sotnVpnTableData.forEach((item, index) => {
+ Object.keys(item).map((items, index) => {
+ if (items.search("site") != -1 && item[items] instanceof Array === true) {
+ this.modifyJosnKey(item, items, sitelan)
+ }
+ });
+ });
+ this.siteTableData.forEach((item, index) => {
+ Object.keys(item).map((items, index) => {
+ if (items.search("site") != -1 && items.search("device") == -1 && item[items] instanceof Array === true) {
+ this.modifyJosnKey(item, items, sitewan)
+ }
+ if (items.search("device") != -1) {
+ this.modifyJosnKey(item, items, device)
+ }
+ });
+ });
+ Object.keys(this.bodyTemplateParameter).map((item, index) => {
+ if (item.search("site") != -1) {
+ servicebody.service.parameters.requestInputs[item] = [].concat(this.siteTableData);
+ }
+ if (item.search("vpn") != -1) {
+ servicebody.service.parameters.requestInputs[item] = [].concat(this.sotnVpnTableData);
+ }
+ });
+ this.closeUpdate.emit(servicebody);
+ }
+
+ goback() {
+ this.closeDetail.emit();
+ }
+
+ hiddenModel() {
+ this.sotnVpnDetailShow = false;
+ this.siteDetail = false;
+ }
+
+}
diff --git a/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.html b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.html
new file mode 100644
index 00000000..e093b3b8
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.html
@@ -0,0 +1,59 @@
+<nz-modal nzWidth="428" [(nzVisible)]="isVisible" nzTitle=" {{'i18nTextDefine_ServiceCreation' | translate}} "
+ (nzOnCancel)="handleCancel()"
+ (nzOnOk)="handleOk()" nzClassName="serviceCreationModel"
+ nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} "
+ nzOkText=" {{'i18nTextDefine_modelOk' | translate}} "
+>
+ <div class="select-list">
+ <span> {{"i18nTextDefine_Customer" | translate}} : </span>
+ <nz-select [(ngModel)]="currentCustomer.name" nzAllowClear
+ (ngModelChange)="customerChange()">
+ <nz-option *ngFor="let item of customerList" [nzValue]="item.name" [nzLabel]="item.name"></nz-option>
+ </nz-select>
+ </div>
+ <div class="select-list">
+ <span> {{"i18nTextDefine_ServiceType" | translate}} : </span>
+ <nz-select [(ngModel)]="currentServiceType.name" nzAllowClear>
+ <nz-option *ngFor="let item of serviceTypes" [nzValue]="item.name" [nzLabel]="item.name">
+ </nz-option>
+ </nz-select>
+ </div>
+ <div class="select-list">
+ <span> {{"i18nTextDefine_UseCase" | translate}} : </span>
+ <nz-select [(ngModel)]="templateTypeSelected" nzAllowClear
+ (ngModelChange)="choseTemplateType()">
+ <nz-option nzValue="SOTN" nzLabel="SOTN"></nz-option>
+ <nz-option nzValue="CCVPN" nzLabel="CCVPN"></nz-option>
+ <nz-option nzValue="E2E Service" nzLabel="E2E Service"></nz-option>
+ <nz-option nzValue="Network Service" nzLabel="Network Service"></nz-option>
+ </nz-select>
+ </div>
+ <div class="select-list">
+ <span> {{"i18nTextDefine_Template" | translate}} : </span>
+ <nz-select [(ngModel)]="currentTemplate" nzAllowClear>
+ <nz-option *ngFor="let item of templates" [nzValue]="item" [nzLabel]="item.name"></nz-option>
+ </nz-select>
+ </div>
+ <div *ngIf="templateTypeSelected === 'E2E Service'">
+ <div class="select-list">
+ <span> {{"i18nTextDefine_Orchestrator" | translate}} : </span>
+ <nz-select [(ngModel)]="orchestratorSelected" nzAllowClear>
+ <nz-option *ngFor="let item of orchestratorList" [nzValue]="item" [nzLabel]="item.name"></nz-option>
+ </nz-select>
+ </div>
+ <div class="checkbox select-list">
+ <span>Sol005 :</span>
+ <input type="checkbox"
+ [(ngModel)]="isSol005Interface" value="true" nzAllowClear>
+
+ </div>
+ </div>
+ <div class="select-list" *ngIf="temParametersTips">
+ {{"i18nTextDefine_Templateparsingfailed" | translate}}
+ </div>
+</nz-modal>
+<div class="loading" *ngIf="loadingAnimateShow">
+ <img src="assets/images/loading-animate2.gif" alt="loading">
+ <p>Please wating……</p>
+</div>
+
diff --git a/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.less b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.less
new file mode 100644
index 00000000..fdee93c8
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.less
@@ -0,0 +1,59 @@
+.select-list{
+ width: 320px;
+ height: 32px;
+ line-height: 32px;
+ margin: 35px auto;
+ .select-list>span{
+ display:inline-block;
+ text-align: right;
+ line-height: 32px;
+ }
+ nz-select{
+ width: 176px;
+ float: right;
+ }
+ &.checkbox{
+ margin: 0 auto;
+ line-height: 32px;
+ input[type="checkbox"]{
+ zoom: 1.3;
+ width: 140px;
+ }
+ }
+}
+::ng-deep nz-modal button.ant-btn {
+ margin-top:20px !important;
+}
+
+.loading{
+ width: 100%;
+ height: 100%;
+ position: fixed;
+ top: 0;
+ margin-top: -50px;
+ margin-left: -50px;
+ z-index: 1001;
+ text-align: center;
+ background: transparent;
+ p{
+ color: #0DA9E2;
+ text-align: center;
+ position: absolute;
+ width: 300px;
+ height: 30px;
+ line-height: 30px;
+ top: 71%;
+ left: 36%;
+ margin-top: -150px;
+ margin-left: -150px;
+ }
+ img{
+ width: 300px;
+ height: 300px;
+ position: absolute;
+ top: 50%;
+ left: 36%;
+ margin-top: -150px;
+ margin-left: -150px;
+ }
+}
diff --git a/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.spec.ts
new file mode 100644
index 00000000..fd57b3a7
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.spec.ts
@@ -0,0 +1,26 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CreateModelComponent } from './create-model.component';
+
+describe('CreateModelComponent', () => {
+ let component: CreateModelComponent;
+ let fixture: ComponentFixture<CreateModelComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ CreateModelComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CreateModelComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
+
diff --git a/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.ts b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.ts
new file mode 100644
index 00000000..f7cce450
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/create-model/create-model.component.ts
@@ -0,0 +1,144 @@
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
+import { ServiceListService } from '../../../../core/services/serviceList.service';
+
+@Component({
+ selector: 'app-create-model',
+ templateUrl: './create-model.component.html',
+ styleUrls: ['./create-model.component.less'],
+})
+export class CreateModelComponent implements OnInit {
+ @Input()isVisible: boolean;
+ @Input()customerList;
+ @Input()serviceTypeList;
+ @Input()customerSelected;
+ @Input()serviceTypeSelected;
+
+ @Output() cancel = new EventEmitter<boolean>();
+ @Output() createdModalShow = new EventEmitter<any>();
+
+ serviceTypes: any[];
+ currentCustomer: any;
+ currentServiceType: any;
+ templateTypeSelected:string = "CCVPN";
+ templates: any[] = [];
+ currentTemplate: object = { name: null };
+ orchestratorList: any[] = [];
+ orchestratorSelected: object = { name: null, id: null };
+ isSol005Interface: boolean = false;
+ temParametersTips: boolean = false;
+ createData: Object = {};
+ loadingAnimateShow: boolean = false;
+
+ constructor( private http: ServiceListService) {}
+
+ ngOnInit() {
+ this.serviceTypes = this.serviceTypeList;
+ this.currentCustomer = JSON.parse(JSON.stringify(this.customerSelected));
+ this.currentServiceType = JSON.parse(JSON.stringify(this.serviceTypeSelected));
+ this.getAlltemplates();
+ }
+
+ getServiceType(): void{
+ this.http.getServiceTypes(this.currentCustomer)
+ .subscribe((data) => {
+ this.serviceTypes = data.map((item) => {
+ return { name: item["service-type"] }
+ });
+ })
+ }
+
+ getAlltemplates() {
+ this.http.getAllServiceTemplates(this.templateTypeSelected)
+ .subscribe((data) => {
+ this.templates = data;
+ if (this.templateTypeSelected == "Network Service") {
+ this.templates = data.filter((d) => {
+ return typeof d.packageInfo.csarName == "string";
+ }).map((item) => {
+ let cName = item.packageInfo.csarName.split("/").reverse()[0];
+ return { name: cName, id: item.csarId, packageInfo: item.packageInfo }
+ });
+ }
+ this.currentTemplate = this.templates[0];
+ }, (err) => {
+ console.log(err);
+ })
+ }
+
+ getallOrchestrators() {
+ this.http.getAllOrchestrators()
+ .subscribe((data) => {
+ if(data.length > 0){
+ this.orchestratorList = data.map((item) => {
+ return { name: item["name"], id: item["name"] }
+ });
+ this.orchestratorSelected = this.orchestratorList[0];
+ }
+ })
+ }
+
+ handleCancel(): void {
+ this.isVisible = false;
+ this.cancel.emit(false);
+ this.loadingAnimateShow = false;
+ }
+
+ customerChange(): void {
+ this.getServiceType();
+ }
+
+ choseTemplateType() {
+ if(this.templateTypeSelected === 'E2E Service'){
+ this.getallOrchestrators();
+ }
+ this.getAlltemplates();
+ }
+
+ handleOk(): void {
+ if (this.templateTypeSelected === "SOTN" || this.templateTypeSelected === "CCVPN") {
+ this.createData = {
+ commonParams: {
+ customer: this.currentCustomer,
+ serviceType: this.currentServiceType,
+ templateType: this.templateTypeSelected
+ },
+ template: this.currentTemplate
+ };
+ } else if (this.templateTypeSelected === "E2E Service" || this.templateTypeSelected === "Network Service") {
+ this.createData = {
+ commonParams: {
+ customer: this.currentCustomer,
+ serviceType: this.currentServiceType,
+ templateType: this.templateTypeSelected
+ },
+ template: this.currentTemplate,
+ orchestrator: this.orchestratorSelected,
+ isSol005Interface: this.isSol005Interface
+ };
+ }
+ this.getTemParameters();
+ }
+
+ getTemParameters() {
+ let chosedtemplates = this.createData["template"];
+ let types = this.createData["commonParams"].templateType;
+ if (types == "E2E Service") {
+ types = "e2e";
+ } else if (types == "Network Service") {
+ types = "ns";
+ }
+ this.loadingAnimateShow = true;
+ this.http.getTemplateParameters(types, chosedtemplates)
+ .subscribe((data) => {
+ this.loadingAnimateShow = false;
+ if (data.status == "FAILED") {
+ this.temParametersTips = true;
+ this.isVisible = true;
+ } else {
+ this.cancel.emit(false);
+ this.temParametersTips = false;
+ this.createdModalShow.emit({templateType: this.templateTypeSelected, data, createData: this.createData})
+ }
+ })
+ }
+} \ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.html b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.html
new file mode 100644
index 00000000..5b516a0f
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.html
@@ -0,0 +1,34 @@
+<nz-modal nzWidth="428" [(nzVisible)]="deleteModalVisible" nzTitle=" {{'i18nTextDefine_delete' | translate}}"
+ (nzOnCancel)="deleteCancel()" (nzOnOk)="deleteOk()"
+ nzClassName="{{thisService['serviceDomain'] == 'Network Service'?'nsdeleteModel':'deleteModel'}}"
+ nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} "
+ nzOkText=" {{'i18nTextDefine_modelOk' | translate}} ">
+ <h3><span style="color: red">*&nbsp;</span> {{"i18nTextDefine_SureDelete" | translate}} </h3>
+ <div class="question">
+ <h4> {{"i18nTextDefine_InstanceName" | translate}} :</h4>
+ <div class="deleteModelContent">{{ thisService["service-instance-name"] ||
+ thisService["nsInstanceName"] }}
+ </div>
+ </div>
+ <div class="question">
+ <h4> {{"i18nTextDefine_InstanceID" | translate}} :</h4>
+ <div class="deleteModelContent">{{ thisService["service-instance-id"] ||
+ thisService["nsInstanceId"] }}
+ </div>
+ </div>
+ <div *ngIf="thisService['serviceDomain'] == 'Network Service'">
+ <div class="question">
+ <h4> {{"i18nTextDefine_terminationType" | translate}} :</h4>
+ <nz-select style="width: 306px;" [(ngModel)]="terminationType">
+ <nz-option nzValue="graceful" nzLabel=" {{'i18nTextDefine_graceful' | translate}} "></nz-option>
+ <nz-option nzValue="forceful" nzLabel=" {{'i18nTextDefine_forceful' | translate}} "></nz-option>
+ </nz-select>
+ </div>
+ <div class="question">
+ <h4 *ngIf="terminationType=='graceful'"> {{"i18nTextDefine_gracefulTerminationTimeout" | translate}}
+ :</h4>
+ <input *ngIf="terminationType=='graceful'" style="width: 306px;" nz-input
+ [(ngModel)]="gracefulTerminationTimeout">
+ </div>
+ </div>
+</nz-modal>
diff --git a/usecaseui-portal/src/app/views/services/services.component.less b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.less
index e69de29b..e69de29b 100644
--- a/usecaseui-portal/src/app/views/services/services.component.less
+++ b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.less
diff --git a/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.spec.ts
new file mode 100644
index 00000000..e5e94c94
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DeleteModelComponent } from './delete-model.component';
+
+describe('DeleteModelComponent', () => {
+ let component: DeleteModelComponent;
+ let fixture: ComponentFixture<DeleteModelComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ DeleteModelComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DeleteModelComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.ts b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.ts
new file mode 100644
index 00000000..f9bf9a9c
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/delete-model/delete-model.component.ts
@@ -0,0 +1,42 @@
+import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
+
+@Component({
+ selector: 'app-delete-model',
+ templateUrl: './delete-model.component.html',
+ styleUrls: ['./delete-model.component.less']
+})
+export class DeleteModelComponent implements OnInit {
+ @Input()deleteModalVisible: boolean;
+ @Input()thisService;
+ @Input()terminationType;
+ @Input()loadingAnimateShow;
+ @Input()templateDeleteSuccessFaild;
+ @Input()gracefulTerminationTimeout;
+
+ @Output() cancel = new EventEmitter<boolean>();
+ @Output() deleteModalOK = new EventEmitter<any>();
+
+ constructor() { }
+
+ ngOnInit() {
+ }
+
+ deleteOk() {
+ this.deleteModalVisible = false;
+ this.loadingAnimateShow = true;
+
+ if (this.thisService["serviceDomain"] === "Network Service") {
+ this.deleteModalOK.emit({
+ terminationType: this.terminationType,
+ gracefulTerminationTimeout: this.gracefulTerminationTimeout
+ })
+ } else {
+ this.deleteModalOK.emit()
+ }
+ }
+ deleteCancel() {
+ this.deleteModalVisible = false;
+ }
+
+
+}
diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.css b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.css
new file mode 100644
index 00000000..5dce6c92
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.css
@@ -0,0 +1,77 @@
+/*
+ Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+.title {
+ font: 700 18px/18px "思源黑体";
+ color: #4c5e70;
+ margin-bottom: 18px;
+}
+hr {
+ border: none;
+ height: 2px;
+ background-color: #dce1e7;
+ margin-bottom: 10px;
+}
+.model {
+ background-color: #fff;
+ height: 90%;
+ overflow-y: auto;
+}
+.model .back {
+ position: absolute;
+ top: 10px;
+ right: 20px;
+}
+.model .creation {
+ position: relative;
+ width: 60%;
+ height: 100%;
+ overflow-y: auto;
+ border-radius: 5px;
+ padding: 20px;
+}
+.model .creation .baseparms h3 {
+ color: #3fa8eb;
+ font: 700 16px "Arial";
+}
+.model .creation .baseparms h4 {
+ font: 700 16px "Arial";
+}
+.model .creation .baseparms ul li {
+ margin: 3px 0;
+}
+.model .creation .baseparms ul li span {
+ display: inline-block;
+ width: 40%;
+ font: 700 14px "Arial";
+ vertical-align: middle;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ text-align: right;
+}
+.model .creation .baseparms ul li input {
+ width: 165px;
+}
+.model .creation .submit {
+ position: absolute;
+ top: 10px;
+ right: 20px;
+}
+.model .chart {
+ width: 40%;
+ padding: 10px;
+ height: 100%;
+ border-left: 10px solid #f3f3f3;
+}
diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.html b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.html
new file mode 100644
index 00000000..da673bf0
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.html
@@ -0,0 +1,139 @@
+<!--
+ Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!--<h3 class="title"> Services List </h3>-->
+<div class="model creation-model">
+ <!-- Create data -->
+ <div class="top-title">
+ <h3 class="title fl">{{createParams.commonParams.templateType}} {{"i18nTextDefine_InstanceCreation" | translate}} </h3>
+ <div class="fl" style="width: 20%">
+ <button class="submit" nz-button (click)="submit()">
+ <span> {{"i18nTextDefine_Create" | translate}} </span>
+ </button>
+ <button class="back" nz-button (click)="goback()"></button>
+ </div>
+ </div>
+ <div class="e2ecreate-content">
+ <div class="creation fl">
+ <div *ngIf="createParams.commonParams.templateType=='E2E Service'" class="baseparms clearfix">
+ <div class="vnf-box">
+ <h3> {{"i18nTextDefine_Base" | translate}} </h3>
+ <ul class="clearfix">
+ <li>
+ <span>Name:</span>
+ <input nz-input [(ngModel)]="service.name">
+ </li>
+ <li>
+ <span>Description:</span>
+ <input nz-input [(ngModel)]="service.description">
+ </li>
+ <li>
+ <span>COS:</span>
+ <input nz-input [(ngModel)]="service.COS">
+ </li>
+ <li>
+ <span>EBS:</span>
+ <input nz-input [(ngModel)]="service.EBS">
+ </li>
+ </ul>
+ </div>
+ <div class="vnf-box" *ngIf="templateParameters.inputs.length>0">
+ <h3>{{"i18nTextDefine_templateInputs" | translate}}</h3>
+ <ul>
+ <li *ngFor="let parameter of templateParameters.inputs; let i = index;">
+ <span *ngIf="parameter.type !== 'vf_location' && parameter.type !== 'sdn_controller'" title="{{parameter.name}}">{{parameter.name}}:</span>
+ <input *ngIf="parameter.type !== 'vf_location' && parameter.type !== 'sdn_controller'" nz-input [(ngModel)]="parameter.value">
+
+ <h5 *ngIf="parameter.type === 'vf_location'" style="padding-left:10px;">id: {{parameter.name}}
+ </h5>
+ <span *ngIf="parameter.type === 'vf_location'"> vf_location: </span>
+ <nz-select *ngIf="parameter.type === 'vf_location'" [(ngModel)]="parameter.value" nzAllowClear>
+ <nz-option *ngFor="let vim of vimInfos" [nzValue]="vim" [nzLabel]="vim.name"></nz-option>
+ </nz-select>
+ </li>
+ </ul>
+ </div>
+ <div class="vnf-box" *ngFor="let template of templateParameters.nestedTemplates;">
+ <h3>{{template.name}}</h3>
+ <ul>
+ <li *ngFor="let input of template.inputs; let i = index;">
+ <span *ngIf="input.type !== 'vf_location' && input.type !== 'sdn_controller'" title="{{input.name}}"> {{input.name}}: </span>
+ <input *ngIf="input.type !== 'vf_location' && input.type !== 'sdn_controller'" nz-input [(ngModel)]="input.value">
+
+ <h5 *ngIf="input.type === 'vf_location'" style="padding-left:10px;">id: {{input.name}}</h5>
+ <span *ngIf="input.type === 'vf_location'"> vf_location: </span>
+ <nz-select *ngIf="input.type === 'vf_location'" [(ngModel)]="input.value" nzAllowClear>
+ <nz-option *ngFor="let vim of vimInfos" [nzValue]="vim" [nzLabel]="vim.name"></nz-option>
+ </nz-select>
+ </li>
+ </ul>
+ </div>
+ </div>
+
+ <div *ngIf="createParams.commonParams.templateType=='Network Service'" class="baseparms clearfix">
+ <div class="vnf-box">
+ <h3> {{"i18nTextDefine_Base" | translate}} </h3>
+ <ul class="clearfix">
+ <li>
+ <span>Name:</span>
+ <input nz-input [(ngModel)]="ns_service.nsName">
+ </li>
+ <li>
+ <span>Description:</span>
+ <input nz-input [(ngModel)]="ns_service.description">
+ </li>
+ </ul>
+ </div>
+ <div class="vnf-box" *ngIf="nsTemplateParameters.inputs2.length>0">
+ <h4>{{"i18nTextDefine_templateInputs" | translate}}</h4>
+ <ul>
+ <li *ngFor="let parameter of nsTemplateParameters.inputs2; let i = index;">
+ <span *ngIf="parameter.type !== 'vf_location' && parameter.type !== 'sdn_controller'" title="{{parameter.name}}">{{parameter.name}}:</span>
+ <input *ngIf="parameter.type !== 'vf_location' && parameter.type !== 'sdn_controller'" nz-input [(ngModel)]="parameter.value">
+
+ <h5 *ngIf="parameter.type === 'vf_location'" style="padding-left:10px;">id: {{parameter.name}}
+ </h5>
+ <span *ngIf="parameter.type === 'vf_location'"> vf_location: </span>
+ <nz-select *ngIf="parameter.type === 'vf_location'" [(ngModel)]="parameter.value" nzAllowClear>
+ <nz-option *ngFor="let vim of vimInfos" [nzValue]="vim" [nzLabel]="vim.name"></nz-option>
+ </nz-select>
+ </li>
+ </ul>
+ </div>
+ <div class="vnf-box">
+ <h4 *ngIf="nsTemplateParameters.vnfs.length>0">vnfs Inputs</h4>
+ <ul>
+ <li *ngFor="let vnf of nsTemplateParameters.vnfs;">
+ <h5 style="padding-left:10px;">id: {{vnf.vnf_id}}</h5>
+ <span> vf_location: </span>
+ <nz-select [(ngModel)]="vnf.value" nzAllowClear>
+ <nz-option *ngFor="let vim of vimInfos" [nzValue]="vim" [nzLabel]="vim.name"></nz-option>
+ </nz-select>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ <div class="dividing-line fl"></div>
+ <!-- chart -->
+ <div class="chart fr">
+ <div id="createChart">
+ <svg width="100%" height="100%">
+ </svg>
+ </div>
+ </div>
+ </div>
+
+</div> \ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.less b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.less
new file mode 100644
index 00000000..3679079e
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.less
@@ -0,0 +1,161 @@
+/*
+ Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+.title {
+ font: 700 18px/18px "思源黑体";
+ color: #4c5e70;
+ margin-bottom: 18px;
+}
+hr {
+ border: none;
+ height: 2px;
+ background-color: #dce1e7;
+ margin-bottom: 10px;
+}
+.model {
+ background-color: #F7F8FC;
+ height: 100%;
+ overflow-y: auto;
+ position: relative;
+ .top-title{
+ width: 100%;
+ padding: 20px;
+ position: relative;
+ display: inline-block;
+ }
+ .submit{
+ position: absolute;
+ width:84px;
+ height: 35px;
+ top: 10px;
+ right: 85px;
+ color: #fff;
+ font-size: 18px;
+ background:linear-gradient(90deg,rgba(99,194,246,1) 0%,rgba(62,155,255,1) 100%) !important;
+ border-radius:4px;
+ border: none!important;
+ border-color:rgba(0,0,0,0)!important;
+ }
+ .submit:hover{
+ background:linear-gradient(90deg, rgb(103, 207, 246) 0%, rgb(69, 175, 255) 100%) !important;
+ border: none;
+ }
+ .back,.back:hover{
+ position: absolute;
+ top: 10px;
+ right: 20px;
+ display: inline-block;
+ width: 35px;
+ height: 35px;
+ background:url("../../../../../assets/images/Return-icon.png") no-repeat!important;
+ background-size: 100%!important;
+ border-radius:4px;
+ color: #D7D7D7;
+ cursor: pointer;
+ }
+ .back:hover{
+ background: url("../../../../../assets/images/Return-icon-active.png")!important;
+ background-size: 100%!important;
+ }
+ .top-title h3.title {
+ height: 35px;
+ width: 80%;
+ font-size:16px;
+ font-family:ArialMT;
+ color:#3C4F8C;
+ line-height:35px;
+ display: inline-block;
+ }
+ .e2ecreate-content{
+ position: relative;
+ width: 98%;
+ height: 100%;
+ margin-left: 30px;
+ box-shadow:0px 10px 15px 2px rgba(222,222,222,0.5);
+ background: #fff;
+ border-radius:2px;
+ }
+ .creation{
+ position: relative;
+ width: 58%;
+ height: 100%;
+ overflow-y: auto;
+ padding: 20px;
+ background: #fff;
+ .baseparms {
+ h3,h4{
+ color: #06A7E2;
+ width: 96%;
+ height: 40px;
+ line-height: 35px;
+ font-size: 18px;
+ font-weight: 500;
+ margin: 10px auto;
+ border-bottom: 2px solid;
+ border-image: -webkit-linear-gradient(#07A9E1,#30D9C4) 100 100;
+ border-image: -moz-linear-gradient(#07A9E1,#30D9C4) 100 100;
+ border-image: linear-gradient(#07A9E1,#30D9C4) 100 100;
+ border-radius:2px;
+ }
+ h4 {
+ font: 700 16px "Arial";
+ margin-left: 25px;
+ }
+ .vnf-box{
+ clear: both;
+ }
+ ul{
+ margin-left: 30px;
+ }
+ ul li {
+ margin: 10px 0;
+ width: 42%;
+ margin-right: 5%;
+ float: left;
+ text-align: left;
+ span {
+ display: inline-block;
+ width: 30%;
+ min-width: 80px;
+ font: 700 14px "Arial";
+ overflow: hidden;
+ text-align: left;
+ word-break: break-all;
+ vertical-align: top;
+ }
+ input,nz-select{
+ width: 49%;
+ margin-left:3%
+ }
+ }
+ }
+ }
+ .dividing-line{
+ width: 0;
+ height: 85%;
+ margin: 4% 0;
+ border-left: 1px #cccccc dashed;
+ }
+ .chart {
+ width: 38%;
+ padding: 10px;
+ height: 95%;
+ margin: 0 auto;
+ #createChart{
+ height: 100%;
+ width: 100%;
+ }
+ }
+}
diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.spec.ts
new file mode 100644
index 00000000..de00c43f
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { E2eCreationComponent } from './e2e-creation.component';
+
+describe('E2eCreationComponent', () => {
+ let component: E2eCreationComponent;
+ let fixture: ComponentFixture<E2eCreationComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ E2eCreationComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(E2eCreationComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.ts b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.ts
new file mode 100644
index 00000000..f1df9636
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/e2e-creation/e2e-creation.component.ts
@@ -0,0 +1,357 @@
+/*
+ Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
+import { ServiceListService } from '../../../../core/services/serviceList.service';
+import * as d3 from 'd3';
+
+@Component({
+ selector: 'app-e2e-creation',
+ templateUrl: './e2e-creation.component.html',
+ styleUrls: ['./e2e-creation.component.less']
+})
+export class E2eCreationComponent implements OnInit {
+
+ constructor(private myhttp: ServiceListService) { }
+
+ ngOnInit() {
+ this.gete2eTemParameters(this.e2e_ns_temParametersContent);
+ this.getVimInfo();
+ this.getSdnControllers();
+ console.log(this.createParams);
+ }
+
+ @Output() e2eCloseCreate = new EventEmitter();
+ @Output() nsCloseCreate = new EventEmitter();
+ @Input() createParams;
+ @Input() e2e_ns_temParametersContent;
+
+
+ // e2e serviceTemplateParameters
+ templateParameters = {
+ invariantUUID: "",
+ uuid: "",
+ name: "",
+ type: "",
+ version: "",
+ description: "",
+ category: "",
+ subcategory: "",
+ customizationUuid: "",
+ inputs: [],
+ nestedTemplates: []
+ };
+ // ns serviceTemplateParameters
+ nsTemplateParameters = {
+ inputs: {},
+ inputs2: [],
+ vnfs: []
+ }
+ roote2e = {
+ "name": "e2e",
+ "type": "e2e",
+ "children": []
+ };
+
+ rootns = {
+ "name": "ns",
+ "type": "ns",
+ "children": []
+ };
+
+ imgmap = {
+ '1': '../../../../assets/images/create-e2e.png',
+ '2': '../../../../assets/images/create-ns.png',
+ '3': '../../../../assets/images/create-vnf.png',
+ };
+ gete2eTemParameters(data) { //Get template parameters
+ let type = this.createParams.commonParams.templateType == "E2E Service" ? "e2e" : "ns";
+ console.log(this.createParams);
+ console.log(data);
+ if (type == "e2e") {
+ this.templateParameters = data;
+ this.templateParameters.nestedTemplates.forEach((item) => {
+ item.inputs = item.inputs.filter((input) => { return input.type !== "sdn_controller" });
+ })
+ this.templateParameters.nestedTemplates.map((item, index) => {
+ let nsIndex = {
+ "name": "ns",
+ "type": "ns",
+ "children": []
+ };
+ nsIndex.children = item.nestedTemplates.map((item, index) => {
+ return {
+ "name": "vnf",
+ "type": "vnf",
+ }
+ });
+ this.roote2e.children.push(nsIndex);
+ });
+ console.log(this.templateParameters);
+ console.log(this.roote2e)
+ } else if (type == "ns") {
+ if (data["model"] != undefined && typeof data["model"] == 'string') {
+ this.nsTemplateParameters = JSON.parse(data["model"]);
+ console.log(data["model"]);
+ } else {
+ this.nsTemplateParameters = data;
+ }
+ console.log(this.nsTemplateParameters);
+ this.nsTemplateParameters["inputs2"] = [];
+ let inputs = this.nsTemplateParameters.inputs;
+ for (let key in inputs) {
+ this.nsTemplateParameters["inputs2"].push({ name: key, type: inputs[key].type, value: inputs[key].value })
+ }
+ this.rootns.children = this.nsTemplateParameters.vnfs.map((item, index) => {
+ return {
+ "name": "vnf",
+ "type": "vnf",
+ }
+ });
+ console.log(this.nsTemplateParameters);
+ }
+
+ this.drawImage(type)
+
+ }
+ vimInfos = [];
+ getVimInfo() {
+ this.myhttp.getVimInfo()
+ .subscribe((data) => {
+ this.vimInfos = data.map((item) => { return { name: item['cloud-owner'], id: item['cloud-region-id'] } });
+ })
+ };
+ sdnControllers = [];
+ getSdnControllers() {
+ this.myhttp.getSdnControllers()
+ .subscribe((data) => {
+ this.sdnControllers = data.map((item) => { return { name: item['thirdparty-sdnc-id'], id: item['thirdparty-sdnc-id'] } });
+ })
+ }
+
+ // e2e requstbody
+ service = {
+ name: "",
+ description: "",
+ COS: "",
+ EBS: "",
+ serviceInvariantUuid: "",
+ serviceUuid: "", // uuid ??
+ globalSubscriberId: "", // "customer.id",
+ serviceType: "", // "serviceType.value",
+ parameters: {
+ locationConstraints: [
+
+ ],
+ resources: [],
+ requestInputs: {},
+ }
+
+ }
+
+ // ns requstbody
+ ns_service = {
+ csarId: "",
+ nsName: "",
+ description: "",
+ context: {
+ globalCustomerId: "",
+ serviceType: ""
+ }
+ }
+ ns_service2 = {
+ locationConstraints: [
+
+ ],
+ additionalParamForNs: {
+ }
+ }
+ submit() {
+ let type = this.createParams.commonParams.templateType == "E2E Service" ? "e2e" : "ns";
+ if (type == "e2e") {
+ this.service.serviceInvariantUuid = this.templateParameters.invariantUUID;
+ this.service.serviceUuid = this.templateParameters.uuid;
+ this.service.globalSubscriberId = this.createParams.commonParams.customer.id;
+ this.service.serviceType = this.createParams.commonParams.serviceType.name;
+
+ this.templateParameters.inputs.forEach((ipnut) => {
+ this.service.parameters.requestInputs[ipnut.name] = ipnut.value == undefined ? ipnut.defaultValue : ipnut.value;
+ })
+
+ this.templateParameters.nestedTemplates.forEach((item) => {
+ let nsService = {
+ resourceName: item.name,
+ resourceInvariantUuid: item.invariantUUID,
+ resourceUuid: item.uuid,
+ resourceCustomizationUuid: item.customizationUuid,
+ parameters: {
+ locationConstraints: [],
+ resources: [],
+ requestInputs: {}
+ }
+ }
+ item.inputs.forEach((input) => {
+ if (input.type == "vf_location") {
+ let location = {
+ vnfProfileId: input.name,
+ locationConstraints: {
+ cloudOwner: input.value.name,
+ cloudRegionId: input.value.id
+ }
+ }
+ nsService.parameters.locationConstraints.push(location);
+ } else {
+ nsService.parameters.requestInputs[input.name] = input.value == undefined ? input.defaultValue : input.value;
+ }
+ })
+ this.service.parameters.resources.push(nsService);
+ })
+ console.log(this.service)
+ this.service.parameters.requestInputs['orchestrator'] = this.createParams.orchestrator.name;
+ if (this.createParams.isSol005Interface) {
+ this.service.parameters.requestInputs['isSol005Interface'] = this.createParams.isSol005Interface;
+ }
+ this.e2eCloseCreate.emit({ service: this.service });
+
+ } else if (type == "ns") {
+ //create ns instance
+ this.ns_service.csarId = this.createParams.template.id;
+ this.ns_service.context.globalCustomerId = this.createParams.commonParams.customer.id;
+ this.ns_service.context.serviceType = this.createParams.commonParams.serviceType.name;
+
+ this.nsTemplateParameters.inputs2.forEach((input) => {
+ this.ns_service2.additionalParamForNs[input.name] = input.value == undefined ? input.defaultValue : input.value;
+ })
+ this.nsTemplateParameters.vnfs.forEach((vnf) => {
+ let vnfparams = {
+ vnfProfileId: vnf.properties.id,
+ locationConstraints: {
+ cloudOwner: vnf.value.name,
+ cloudRegionId: vnf.value.id
+ }
+ }
+ this.ns_service2.locationConstraints.push(vnfparams);
+ })
+ console.log(this.ns_service2);
+
+ let requstbody = {
+ step1: this.ns_service,
+ step2: this.ns_service2
+ }
+ this.nsCloseCreate.emit(requstbody);
+ }
+
+ }
+ goback() {
+ this.e2eCloseCreate.emit();
+ }
+
+
+
+ drawImage(type) {
+ if (type == "e2e") {
+ this.render(this.roote2e, this.imgmap)
+ } else if (type == "ns") {
+ this.render(this.rootns, this.imgmap)
+ }
+
+
+ }
+
+ render(data, imgmap) {
+ var width = document.getElementById("createChart").clientWidth,
+ height = document.getElementById("createChart").clientHeight;
+ var cluster = d3.layout.tree()
+ .size([width, height]);
+ var diagonal = d3.svg.diagonal()
+ .projection(function (d) {
+ return [d.x - 18, d.y + 40];
+ });
+ var svg = d3.select("svg");
+
+ //marker
+ var marker =
+ svg.append("marker")
+ .attr("id", "resolved")
+ .attr("markerUnits", "strokeWidth")
+ .attr("markerUnits", "userSpaceOnUse")
+ .attr("viewBox", "0 -5 10 10")
+ .attr("refX", 22)
+ .attr("refY", 0)
+ .attr("markerWidth", 20)
+ .attr("markerHeight", 20)
+ .attr("orient", "auto")
+ .attr("stroke-width", 1)
+ .append("circle")
+ .attr("cx", 5)
+ .attr("cy", 0)
+ .attr("r", 2)
+ .attr("stroke-width", 1)
+ .style("stroke", "#2F8BF7")
+ .attr('fill', 'white');
+ var i = 0;
+ var nodes = cluster.nodes(data).reverse();
+ nodes.forEach(function (d) {
+ d.y = d.depth * 200 + 100;
+
+ });
+
+ var links = cluster.links(nodes);
+
+ var linkEnter = svg.selectAll("path.link")
+ .data(links);
+
+ linkEnter.enter().append("path")
+ .attr("class", "link")
+ .attr("d", diagonal)
+ .style("stroke", "#2F8BF7")
+ .style('stroke-width', '1px')
+ .attr("marker-end", "url(#resolved)")
+ .style("fill", "none")
+ // .style("fill-opacity", 1)
+ .attr("id", function (d, i) {
+ return "mypath" + i;
+ });
+
+ var node = svg.selectAll(".node")
+ .data(nodes)
+ .enter()
+ .append("g")
+ .attr("class", "node")
+ .attr("transform", function (d) {
+ return "translate(" + (d.x + -50) + "," + (d.y) + ")";
+ });
+
+ node.append('image')
+ .attr('xlink:href', function (d) {
+ if (d.type == "e2e") {
+ return imgmap[1];
+ } else if (d.type == "ns") {
+ return imgmap[2];
+ } else if (d.type == "vnf") {
+ return imgmap[3];
+ }
+
+ })
+ .style('width', '12%')
+ .style("cursor", "pointer")
+ .attr("x", 0)
+ .attr("y", 0)
+ .attr("rx", 3);
+
+
+ }
+
+}
diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.html b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.html
new file mode 100644
index 00000000..976a9f6c
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.html
@@ -0,0 +1,109 @@
+<!--
+ Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!--<h3 class="title"> Services List </h3>-->
+<div class="model creation-model">
+
+ <div class="top-title">
+ <h3 class="title fl">{{serviceInstanceName}} Instance Detail</h3>
+ <div class="fl" style="width: 20%">
+ <button class="back" nz-button (click)="goback()"></button>
+ </div>
+ </div>
+ <div class="detaildata fl">
+ <div *ngIf="detailParams.serviceDomain == 'E2E Service'" class="baseparms clearfix">
+ <div class="vnf-box">
+ <h3> {{"i18nTextDefine_Base" | translate}} </h3>
+ <ul class="clearfix">
+ <li>
+ <span style="width:15%">Name:</span>
+ <span class="input-content">{{service.name}}</span>
+ </li>
+ <li>
+ <span style="width:25%">Description:</span>
+ <span class="input-content">{{service.description}}</span>
+ </li>
+ </ul>
+ </div>
+ <div class="vnf-box" *ngIf="getKeys(e2e_requestInputs).length>0">
+ <h3>{{"i18nTextDefine_templateInputs" | translate}}</h3>
+ <ul class="clearfix">
+ <li *ngFor="let key of getKeys(e2e_requestInputs);">
+ <span title="{{key}}">{{key}}:</span>
+ <span class="input-content">{{e2e_requestInputs[key]}}</span>
+ </li>
+ </ul>
+ </div>
+ <div class="vnf-box" *ngFor="let template of e2e_nestedTemplates;">
+ <h3>{{template.name}}</h3>
+ <ul class="clearfix">
+ <li *ngFor="let input of template.vnfs; let i = index;">
+ <span style="width: 26%;min-width: 80px!important"> vf_location: </span>
+ <span class="input-content">{{input["vf_location"]}}</span>
+ </li>
+ </ul>
+ </div>
+ </div>
+
+ <div *ngIf="detailParams.serviceDomain=='Network Service'" class="baseparms clearfix">
+ <div class="vnf-box">
+ <h3> {{"i18nTextDefine_Base" | translate}} </h3>
+ <ul class="clearfix">
+ <li>
+ <span style="width:15%">Name:</span>
+ <span class="input-content">{{ns_service.name}}</span>
+ </li>
+ <li>
+ <span style="width:25%">Description:</span>
+ <span class="input-content">{{ns_service.description}}</span>
+ </li>
+ </ul>
+ </div>
+ <div class="vnf-box" *ngIf="getKeys(ns_requestInputs).length>0">
+ <h4>{{"i18nTextDefine_templateInputs" | translate}}</h4>
+ <ul>
+ <li *ngFor="let key of getKeys(ns_requestInputs);">
+ <span title="{{key}}">{{key}}:</span>
+ <span class="input-content">{{ns_requestInputs[key]}}</span>
+ </li>
+ </ul>
+ </div>
+ <div class="vnf-box" *ngIf="ns_nestedTemplates.length>0">
+ <h4>vnfs Inputs</h4>
+ <ul>
+ <li *ngFor="let vnf of ns_nestedTemplates;">
+ <h5>
+ <span style="width: 26%;min-width: 80px!important"> id: </span>
+ <span class="input-content"> {{vnf.vnfInstanceId}}</span>
+ </h5>
+ <h5>
+ <span style="width: 26%;min-width: 80px!important"> vf_location: </span>
+ <span class="input-content">{{vnf["vnfInstanceName"]}}</span>
+ </h5>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+
+ <!-- chart -->
+ <div class="chart fr">
+ <div id="createChart">
+ <svg width="100%" height="100%">
+ </svg>
+ </div>
+ </div>
+
+</div> \ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.less b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.less
new file mode 100644
index 00000000..ad28a518
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.less
@@ -0,0 +1,142 @@
+/*
+ Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+.title {
+ font: 700 18px/18px "思源黑体";
+ color: #4c5e70;
+ margin-bottom: 18px;
+}
+hr {
+ border: none;
+ height: 2px;
+ background-color: #dce1e7;
+ margin-bottom: 10px;
+}
+.creation-model{
+ position: relative;
+}
+.model {
+ background-color: #F7F8FC;
+ height: 100%;
+ overflow-y: auto;
+ position: relative;
+ .top-title{
+ width: 100%;
+ padding: 20px;
+ position: relative;
+ display: inline-block;
+ }
+ .back,.back:hover{
+ position: absolute;
+ top: 10px;
+ right: 20px;
+ display: inline-block;
+ width: 35px;
+ height: 35px;
+ background:url("../../../../../assets/images/Return-icon.png") no-repeat!important;
+ background-size: 100%!important;
+ border-radius:4px;
+ color: #D7D7D7;
+ cursor: pointer;
+ }
+ .back:hover{
+ background: url("../../../../../assets/images/Return-icon-active.png")!important;
+ background-size: 100%!important;
+ }
+ .top-title h3.title {
+ height: 35px;
+ width: 80%;
+ font-size:16px;
+ font-family:ArialMT;
+ color:#3C4F8C;
+ line-height:35px;
+ display: inline-block;
+ }
+ .detaildata{
+ position: relative;
+ width: 58%;
+ height: 100%;
+ overflow-y: auto;
+ border-radius: 5px;
+ padding: 20px;
+ background: #fff;
+ margin-left: 30px;
+ box-shadow:0px 10px 15px 2px rgba(222,222,222,0.5);
+ .baseparms {
+ h3,h4{
+ color: #06A7E2;
+ width: 96%;
+ height: 40px;
+ line-height: 35px;
+ font-size: 18px;
+ font-weight: 500;
+ margin: 10px auto;
+ border-bottom: 2px solid;
+ border-image: -webkit-linear-gradient(#07A9E1,#30D9C4) 100 100;
+ border-image: -moz-linear-gradient(#07A9E1,#30D9C4) 100 100;
+ border-image: linear-gradient(#07A9E1,#30D9C4) 100 100;
+ border-radius:2px;
+ }
+ h4 {
+ font: 700 16px "Arial";
+ margin-left: 25px;
+ }
+ .vnf-box{
+ clear: both;
+ }
+ ul{
+ margin-left: 30px;
+ }
+ ul li {
+ margin: 10px 0;
+ width: 49%;
+ float: left;
+ text-align: left;
+ color:rgba(60,79,140,1);
+ font-size: 14px;
+ span {
+ display: inline-block;
+ width: 50%;
+ font: 700 14px "Arial";
+ vertical-align: top;
+ overflow: hidden;
+ text-align: left;
+ color:rgba(60,79,140,0.5);
+ word-break: break-all;
+ }
+ span.input-content{
+ width: 42%;
+ color: #3C4F8C;
+ margin-left: 5%;
+ word-break: break-all;
+ vertical-align: top;
+ }
+ }
+ }
+ }
+ .chart {
+ width: 35%;
+ padding: 10px;
+ height: 95%;
+ box-shadow: 0px 10px 35px 10px rgba(222, 222, 222, 0.5);
+ margin-right: 1%;
+ background:linear-gradient(180deg,rgba(183, 230, 247, 1) 0%,rgba(214, 240, 254, 1) 100%);
+ border-radius: 4px;
+ #createChart{
+ height: 100%;
+ width: 100%;
+ }
+ }
+}
diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.spec.ts
new file mode 100644
index 00000000..ad24a477
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { E2eDetailComponent } from './e2e-detail.component';
+
+describe('E2eDetailComponent', () => {
+ let component: E2eDetailComponent;
+ let fixture: ComponentFixture<E2eDetailComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ E2eDetailComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(E2eDetailComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.ts b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.ts
new file mode 100644
index 00000000..50f63b3e
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/e2e-detail/e2e-detail.component.ts
@@ -0,0 +1,246 @@
+/*
+ Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
+import { ServiceListService } from '../../../../core/services/serviceList.service';
+import * as d3 from 'd3';
+
+@Component({
+ selector: 'app-e2e-detail',
+ templateUrl: './e2e-detail.component.html',
+ styleUrls: ['./e2e-detail.component.less']
+})
+export class E2eDetailComponent implements OnInit {
+
+ constructor(private myhttp: ServiceListService) {
+ }
+
+ ngOnInit() {
+ // this.getDetails();
+ this.dataInit();
+ }
+
+ @Input() detailParams;
+
+ @Output() closeDetail = new EventEmitter();
+ serviceInstanceName: any;
+ serviceType: any;
+ input_parameters: any;
+ nsinput_parameters: any;
+
+ // e2e
+ service = {
+ name: "",
+ description: "",
+ };
+ e2e_nestedTemplates = [];
+ e2e_requestInputs: any;
+
+ ns_service = {
+ name: "",
+ description: ""
+ }
+ ns_nestedTemplates = [];
+ ns_requestInputs = {};
+ roote2e = {
+ "name": "e2e",
+ "type": "e2e",
+ "children": []
+ };
+
+ rootns = {
+ "name": "ns",
+ "type": "ns",
+ "children": []
+ };
+
+ imgmap = {
+ '1': '../../../../assets/images/create-e2e.png',
+ '2': '../../../../assets/images/create-ns.png',
+ '3': '../../../../assets/images/create-vnf.png',
+ };
+
+ getKeys(item) {
+ return Object.keys(item);
+ }
+
+ dataInit() {
+ console.log(this.detailParams);
+ this.serviceInstanceName = this.detailParams['service-instance-name'] || this.detailParams["nsName"];
+ if (this.detailParams.serviceDomain == 'E2E Service') {
+ this.input_parameters = JSON.stringify(this.detailParams['input-parameters']);
+ this.input_parameters = JSON.parse(this.input_parameters);
+ console.log(this.input_parameters);
+ this.service = {
+ name: this.input_parameters.service.name,
+ description: this.input_parameters.service.description,
+ };
+ if (this.input_parameters.service.parameters.requestInputs != undefined && Object.keys(this.input_parameters.service.parameters.requestInputs).length > 0) {
+ this.e2e_requestInputs = this.input_parameters.service.parameters.requestInputs;
+ }
+ if (this.input_parameters.service.parameters.resources != undefined && this.input_parameters.service.parameters.resources.length > 0) {
+ this.input_parameters.service.parameters.resources.map((item, i) => {
+ let nestedTemplates = {
+ name: null,
+ vnfs: []
+ };
+ nestedTemplates.name = item.resourceName;
+ item.parameters.locationConstraints.map((its, k) => {
+ nestedTemplates.vnfs.push({
+ "vf_location": its.locationConstraints.cloudOwner
+ })
+ });
+ this.e2e_nestedTemplates.push(nestedTemplates);
+
+ let nsIndex = {
+ "name": "ns",
+ "type": "ns",
+ "children": []
+ };
+ nsIndex.children = item.parameters.locationConstraints.map((itemits, index) => {
+ return {
+ "name": "vnf",
+ "type": "vnf",
+ }
+ });
+ this.roote2e.children.push(nsIndex);
+ });
+ console.log(this.e2e_nestedTemplates);
+ console.log(this.e2e_requestInputs);
+ console.log(this.roote2e)
+ }
+ } else if (this.detailParams.serviceDomain == 'Network Service') {
+ this.ns_service = {
+ name: this.detailParams.name || this.detailParams['service-instance-name'],
+ description: this.detailParams.description || null
+ };
+ if (this.detailParams.requestInputs != undefined && Object.keys(this.detailParams.requestInputs).length > 0) {
+ this.ns_requestInputs = this.detailParams.requestInputs;
+ }
+ this.ns_nestedTemplates = this.detailParams.childServiceInstances;
+ this.rootns.children = this.ns_nestedTemplates.map((item, index) => {
+ return {
+ "name": "vnf",
+ "type": "vnf"
+ }
+ });
+ console.log(this.ns_nestedTemplates);
+ console.log(this.ns_requestInputs);
+ console.log(this.rootns)
+ }
+ this.drawImage(this.detailParams.serviceDomain)
+ }
+
+ goback() {
+ this.closeDetail.emit();
+ }
+
+ drawImage(type) {
+ if (type == "E2E Service") {
+ this.render(this.roote2e, this.imgmap)
+ } else if (type == "Network Service") {
+ this.render(this.rootns, this.imgmap)
+ }
+
+
+ }
+
+ render(data, imgmap) {
+ var width = document.getElementById("createChart").clientWidth,
+ height = document.getElementById("createChart").clientHeight;
+ var cluster = d3.layout.tree()
+ .size([width, height]);
+ var diagonal = d3.svg.diagonal()
+ .projection(function (d) {
+ return [d.x - 18, d.y + 40];
+ });
+ var svg = d3.select("svg");
+
+ //marker
+ var marker =
+ svg.append("marker")
+ .attr("id", "resolved")
+ .attr("markerUnits", "strokeWidth")
+ .attr("markerUnits", "userSpaceOnUse")
+ .attr("viewBox", "0 -5 10 10")
+ .attr("refX", 22)
+ .attr("refY", 0)
+ .attr("markerWidth", 20)
+ .attr("markerHeight", 20)
+ .attr("orient", "auto")
+ .attr("stroke-width", 1)
+ .append("circle")
+ .attr("cx", 5)
+ .attr("cy", 0)
+ .attr("r", 2)
+ .attr("stroke-width", 1)
+ .style("stroke", "#2F8BF7")
+ .attr('fill', 'white');
+ var i = 0;
+ var nodes = cluster.nodes(data).reverse();
+ nodes.forEach(function (d) {
+ d.y = d.depth * 200 + 100;
+
+ });
+
+ var links = cluster.links(nodes);
+
+ var linkEnter = svg.selectAll("path.link")
+ .data(links);
+
+ linkEnter.enter().append("path")
+ .attr("class", "link")
+ .attr("d", diagonal)
+ .style("stroke", "#2F8BF7")
+ .style('stroke-width', '1px')
+ .attr("marker-end", "url(#resolved)")
+ .style("fill", "none")
+ // .style("fill-opacity", 1)
+ .attr("id", function (d, i) {
+ return "mypath" + i;
+ });
+
+ var node = svg.selectAll(".node")
+ .data(nodes)
+ .enter()
+ .append("g")
+ .attr("class", "node")
+ .attr("transform", function (d) {
+ return "translate(" + (d.x + -50) + "," + (d.y) + ")";
+ });
+
+ node.append('image')
+ .attr('xlink:href', function (d) {
+ if (d.type == "e2e") {
+ return imgmap[1];
+ } else if (d.type == "ns") {
+ return imgmap[2];
+ } else if (d.type == "vnf") {
+ return imgmap[3];
+ }
+
+ })
+ .style('width', '12%')
+ .style("cursor", "pointer")
+ .attr("x", 0)
+ .attr("y", 0)
+ .attr("rx", 3);
+
+
+ }
+
+
+}
diff --git a/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.html b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.html
new file mode 100644
index 00000000..0117669f
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.html
@@ -0,0 +1,72 @@
+<nz-modal nzWidth="428" [nzVisible]="healModelVisible" nzTitle=" {{'i18nTextDefine_Heal' | translate}} "
+ (nzOnCancel)="healCancel()" (nzOnOk)="healOk()"
+ nzClassName="healModel" nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} "
+ nzOkText=" {{'i18nTextDefine_modelOk' | translate}} ">
+ <h3><span style="color: red">*&nbsp;</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>
+ &nbsp;
+ </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"> &nbsp;
+ Value: <input style="width: 165px;" nz-input [(ngModel)]="item.value">
+ <button nz-button [nzType]="'dashed'" (click)="minusNsAdditional(i)"><i
+ class="anticon anticon-minus-circle-o"></i></button>
+ </div>
+ </div>
+ </div>
+ <!-- vnf -->
+ <div *ngIf="thisService['serviceDomain'] == 'vnf'" style="clear: both">
+ <div class="heal-question">
+ <p class="heal-label"> {{"i18nTextDefine_cause" | translate}} :</p>
+ <input nz-input [(ngModel)]="vnfParams.cause" class="heal-input">
+ </div>
+ <div class="heal-question">
+ <p class="heal-label"> {{"i18nTextDefine_action" | translate}} :</p>
+ <input nz-input [(ngModel)]="vnfParams.additionalParams.action" class="heal-input">
+ </div>
+ <div class="heal-question">
+ <p class="heal-label"> {{"i18nTextDefine_actionvminfo" | translate}}:</p>
+ <nz-select
+ style=" float: right;width: 200px;margin-left: 15px;border-radius: 6px;margin-right: 30px"
+ [(ngModel)]="vmSelected">
+ <nz-option *ngFor="let item of vnfVms" [nzValue]="item" [nzLabel]="item.vmName"></nz-option>
+ </nz-select>
+ </div>
+ </div>
+</nz-modal> \ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.less b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.less
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.less
diff --git a/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.spec.ts
new file mode 100644
index 00000000..af1c07bd
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { HealModelComponent } from './heal-model.component';
+
+describe('HealModelComponent', () => {
+ let component: HealModelComponent;
+ let fixture: ComponentFixture<HealModelComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ HealModelComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(HealModelComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.ts b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.ts
new file mode 100644
index 00000000..a7ffe663
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/heal-model/heal-model.component.ts
@@ -0,0 +1,68 @@
+import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
+
+@Component({
+ selector: 'app-heal-model',
+ templateUrl: './heal-model.component.html',
+ styleUrls: ['./heal-model.component.less']
+})
+export class HealModelComponent implements OnInit {
+ @Input()healModelVisible: boolean;
+ @Input()thisService;
+ @Input()nsParams;
+ @Input()healActions;
+ @Input()nsAdditional;
+ @Input()vnfParams;
+ @Input()vmSelected;
+ @Input()vnfVms;
+ @Input()templatehealstarting;
+ @Input()templatehealSuccessFaild;
+
+ @Output() cancel = new EventEmitter<boolean>();
+ @Output() healModalOK = new EventEmitter<any>();
+
+ constructor() { }
+
+ ngOnInit() {
+ }
+
+
+ addActionsHealing() {
+ this.healActions.push({ value: "" })
+ }
+
+ minusActionsHealing(index) {
+ this.healActions.splice(index, 1);
+ }
+
+ addNsAdditional() {
+ this.nsAdditional.push({ key: "", value: "" })
+ }
+
+ minusNsAdditional(index) {
+ this.nsAdditional.splice(index, 1);
+ }
+
+ healOk() {
+ this.healModelVisible = false;
+ // nsParams
+ this.nsParams.actionsHealing = this.healActions.map((item) => {
+ return item.value
+ });
+ let additional = {};
+ this.nsAdditional.forEach((item) => {
+ additional[item.key] = item.value;
+ });
+ this.nsParams.additionalParamsforNs = JSON.stringify(additional);
+ // vnfParams
+ this.vnfParams.additionalParams.actionvminfo.vmid = this.vmSelected["vmId"];
+ this.vnfParams.additionalParams.actionvminfo.vmname = this.vmSelected["vmName"];
+
+ let requestBody = this.thisService["serviceDomain"] == "Network Service" ? { healNsData: this.nsParams } : { healVnfData: this.vnfParams };
+ this.healModalOK.emit(requestBody)
+ }
+
+ healCancel() {
+ this.healModelVisible = false;
+ }
+
+}
diff --git a/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.html b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.html
new file mode 100644
index 00000000..cb873149
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.html
@@ -0,0 +1,40 @@
+<nz-modal nzWidth="428" [nzVisible]="scaleModelVisible" nzTitle=" {{'i18nTextDefine_Scale' | translate}} "
+ (nzOnCancel)="scaleCancel()" (nzOnOk)="scaleOk()"
+ nzClassName="scaleModel" nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} "
+ nzOkText=" {{'i18nTextDefine_modelOk' | translate}} ">
+ <h3><span style="color: red">*&nbsp;</span> {{"i18nTextDefine_SureScale" | translate}} </h3>
+ <div class="question">
+ <h4> {{"i18nTextDefine_InstanceID" | translate}} :</h4>
+ <div class="scaleModelContent" style="width: 100%">{{ thisService["service-instance-id"] ||
+ thisService["nsInstanceId"] ||
+ thisService["vnfInstanceId"]}}
+ </div>
+ </div>
+ <div *ngFor="let item of e2e_nsData" style="margin-top: 20px">
+ <h3>{{ item.netWorkServiceName }}</h3>
+ <div class="e2eScaleContent">
+ <span class="e2eScaleLable"> {{"i18nTextDefine_ScaleType" | translate}} :</span>
+ <nz-select style="width: 165px;" [(ngModel)]="item.scaleType">
+ <nz-option nzValue="SCALE_NS" nzLabel="SCALE_NS"></nz-option>
+ <nz-option nzValue="SCALE_VNF" nzLabel="SCALE_VNF"></nz-option>
+ </nz-select>
+ </div>
+ <div class="e2eScaleContent">
+ <span class="e2eScaleLable"> {{"i18nTextDefine_AspectId" | translate}} :</span>
+ <input style="width: 165px;" nz-input [(ngModel)]="item.aspectId" placeholder="string">
+ </div>
+ <div class="e2eScaleContent">
+ <span class="e2eScaleLable"> {{"i18nTextDefine_Number_Of_Steps" | translate}} :</span>
+ <nz-input-number style="width: 165px;" [(ngModel)]="item.numberOfSteps" [nzMin]="1" [nzMax]="100"
+ nzPrecision=0 [nzStep]="1" nzPlaceHolder="number"></nz-input-number>
+ </div>
+ <div class="e2eScaleContent">
+ <span class="e2eScaleLable"> {{"i18nTextDefine_ScalingDirection" | translate}} :</span>
+ <nz-select style="width: 165px;" nzPlaceHolder="Chose" [(ngModel)]="item.scalingDirection">
+ <nz-option nzValue="SCALE_IN" nzLabel="SCALE_IN"></nz-option>
+ <nz-option nzValue="SCALE_OUT" nzLabel="SCALE_OUT"></nz-option>
+ </nz-select>
+ </div>
+ </div>
+
+</nz-modal> \ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.less b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.less
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.less
diff --git a/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.spec.ts
new file mode 100644
index 00000000..5d069ee4
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ScaleModelComponent } from './scale-model.component';
+
+describe('ScaleModelComponent', () => {
+ let component: ScaleModelComponent;
+ let fixture: ComponentFixture<ScaleModelComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ ScaleModelComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ScaleModelComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.ts b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.ts
new file mode 100644
index 00000000..c1b9a86e
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/scale-model/scale-model.component.ts
@@ -0,0 +1,53 @@
+import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
+
+@Component({
+ selector: 'app-scale-model',
+ templateUrl: './scale-model.component.html',
+ styleUrls: ['./scale-model.component.less']
+})
+export class ScaleModelComponent implements OnInit {
+ @Input()scaleModelVisible: boolean;
+ @Input()templatescalestarting;
+ @Input()templateScaleSuccessFaild;
+ @Input()thisService;
+ @Input()e2e_nsData;
+ @Input()customerSelected;
+ @Input()serviceTypeSelected;
+
+ @Output() cancel = new EventEmitter<boolean>();
+ @Output() scaleModalOK = new EventEmitter<any>();
+ constructor() { }
+
+ ngOnInit() {
+ }
+
+ scaleOk() {
+ this.scaleModelVisible = false;
+ let requestBody = {
+ "service": {
+ "serviceInstanceName": this.thisService["service-instance-name"],
+ "serviceType": this.serviceTypeSelected.name,
+ "globalSubscriberId": this.customerSelected.id,
+ "resources": this.e2e_nsData.map((item) => {
+ return {
+ "resourceInstanceId": item["netWorkServiceId"],
+ "scaleType": item["scaleType"],
+ "scaleNsData": {
+ "scaleNsByStepsData": {
+ "aspectId": item["aspectId"],
+ "numberOfSteps": item["numberOfSteps"],
+ "scalingDirection": item["scalingDirection"]
+ }
+ }
+ }
+ })
+ }
+ };
+ this.scaleModalOK.emit(requestBody)
+ }
+
+ scaleCancel() {
+ this.scaleModelVisible = false;
+ }
+
+}
diff --git a/usecaseui-portal/src/app/views/services/services-list/services-list.component.html b/usecaseui-portal/src/app/views/services/services-list/services-list.component.html
index a995b485..216e92df 100644
--- a/usecaseui-portal/src/app/views/services/services-list/services-list.component.html
+++ b/usecaseui-portal/src/app/views/services/services-list/services-list.component.html
@@ -14,7 +14,6 @@
limitations under the License.
-->
<div class="action ant-tabs-bar">
-
<span>
<i class="icon">
<img src="assets/images/customer.png" alt="">
@@ -51,88 +50,26 @@
<i *ngIf="width>1200" class="anticon anticon-plus"></i>
<span> {{"i18nTextDefine_Create" | translate}} </span>
</button>
- <nz-modal nzWidth="428" [(nzVisible)]="isVisible" nzTitle=" {{'i18nTextDefine_ServiceCreation' | translate}} "
- (nzOnCancel)="handleCancel()"
- (nzOnOk)="handleOk()" nzClassName="serviceCreationModel"
- nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} "
- nzOkText=" {{'i18nTextDefine_modelOk' | translate}} ">
- <div class="select-list">
- <span style="display:inline-block;"> {{"i18nTextDefine_Customer" | translate}} : </span>
- <nz-select style="width: 176px;float: right;" [(ngModel)]="customerSelected2.name" nzAllowClear
- (ngModelChange)="customerChange()">
- <nz-option *ngFor="let item of customerList2" [nzValue]="item.name" [nzLabel]="item.name"></nz-option>
- </nz-select>
- </div>
- <div class="select-list">
- <span style="display:inline-block;"> {{"i18nTextDefine_ServiceType" | translate}} : </span>
- <nz-select style="width: 176px;float: right;" [(ngModel)]="serviceTypeSelectedName" nzAllowClear
- (ngModelChange)="serviceTypeChange()">
- <nz-option *ngFor="let item of serviceTypeList2" [nzValue]="item.name" [nzLabel]="item.name">
- </nz-option>
- </nz-select>
- </div>
- <div class="select-list">
- <span style="display:inline-block;"> {{"i18nTextDefine_UseCase" | translate}} : </span>
- <nz-select style="width: 176px;float: right;" [(ngModel)]="templateTypeSelected" nzAllowClear
- (ngModelChange)="choseTemplateType()">
- <nz-option nzValue="SOTN" nzLabel="SOTN"></nz-option>
- <nz-option nzValue="CCVPN" nzLabel="CCVPN"></nz-option>
- <nz-option nzValue="E2E Service" nzLabel="E2E Service"></nz-option>
- <nz-option nzValue="Network Service" nzLabel="Network Service"></nz-option>
- </nz-select>
- </div>
-
- <div class="select-list">
- <span style="display:inline-block;width:70px;"> {{"i18nTextDefine_Template" | translate}} : </span>
- <nz-select style="width: 176px;float: right;" [(ngModel)]="template1" nzAllowClear>
- <nz-option *ngFor="let item of templates" [nzValue]="item" [nzLabel]="item.name"></nz-option>
- </nz-select>
- </div>
- <div *ngIf="templateTypeSelected == 'E2E Service'">
- <div class="select-list">
- <span style="display:inline-block;width:70px;"> {{"i18nTextDefine_Orchestrator" | translate}} : </span>
- <nz-select style="width: 176px;float: right;" [(ngModel)]="orchestratorSelected" nzAllowClear>
- <nz-option *ngFor="let item of orchestratorList" [nzValue]="item" [nzLabel]="item.name"></nz-option>
- </nz-select>
- </div>
- </div>
- <div *ngIf="templateTypeSelected == 'E2E Service'">
- <div class="check-box" style="margin:30px; height: 50px">
- <input class="check-box-style" style="zoom: 1.8; width: 70px" type="checkbox"
- [(ngModel)]="isSol005Interface" value="true" nzAllowClear>
- <label class="label" style="font-size: 20px; color: rgb(60,79,140,0.5)">Sol005</label>
- </div>
- </div>
- <div class="select-list" style="color: red;margin-left: 66px;" *ngIf="temParametersTips">
- {{"i18nTextDefine_Templateparsingfailed" | translate}}
- </div>
- </nz-modal>
+ <app-create-model *ngIf="isVisible" [isVisible]="isVisible" (cancel)="isVisible=$event" (createdModalShow)="createdModalShow($event)"
+ [customerList]="customerList" [serviceTypeList]="serviceTypeList" [customerSelected]="customerSelected" [serviceTypeSelected]="serviceTypeSelected">
+ </app-create-model>
+
</div>
-<nz-layout style=" padding: 20px 32px; ">
- <ul class="top-num">
- <li *ngFor="let item of serviceMunber" class="top-list">
- <span class="round">{{item.serviceDomain}}</span>
- <div class="top-list-text">
- <p>
- <span>{{item.failed}}</span>
- <span> {{"i18nTextDefine_Failed" | translate}} </span>
- </p>
- <p>
- <span>{{item.Success}}</span>
- <span> {{"i18nTextDefine_Success" | translate}} </span>
- </p>
- <p>
- <span>{{item.InProgress}}</span>
- <span> {{"i18nTextDefine_InProgress" | translate}} </span>
- </p>
- <p class="service-description"> {{item.detailName | translate}} </p>
- </div>
- </li>
- </ul>
- <div class="list" id="services-list" [ngClass]="{'listdisplay':listDisplay == true}">
- <nz-table *ngIf="1" #nzTable [nzData]="tableData" nzShowSizeChanger [nzFrontPagination]="false"
+<nz-layout>
+ <div class="top-num">
+ <app-top-card
+ *ngFor="let item of serviceNunber"
+ [serviceDomain]="item.serviceDomain"
+ [successNum]="item.Success"
+ [failedNum]="item.failed"
+ [inProgressNum]="item.InProgress"
+ [serviceDetailName]="item.detailName">
+ </app-top-card>
+ </div>
+ <div class="list" id="services-list" [ngClass]="{'listdisplay':listDisplay === true}">
+ <nz-table #nzTable [nzData]="tableData" nzShowSizeChanger [nzFrontPagination]="false"
[nzShowQuickJumper]="true" [nzPageSizeOptions]="[5,10,15,20]" [nzTotal]='total' [(nzPageSize)]="pageSize"
- [(nzPageIndex)]='pageIndex' [nzLoading]="loading" [nzSize]="'middle'" [nzScroll]="{ y: '58vh' }"
+ [(nzPageIndex)]='pageIndex' [nzLoading]="loading" [nzSize]="'middle'"
(nzPageIndexChange)="searchData()" (nzPageSizeChange)="searchData(true)">
<thead>
<tr>
@@ -153,31 +90,30 @@
<td>{{data["service-instance-name"] || data.nsName}}</td>
<td>{{data["service-instance-id"] || data.nsInstanceId}}</td>
<td>
- <p
- [ngClass]="{'e2eColor':data.serviceDomain=='E2E Service','nsColor':data.serviceDomain=='Network Service','ccvpnColor':data.serviceDomain=='CCVPN','sotnColor':data.serviceDomain=='SOTN','voLTEColor':data.serviceDomain=='voLTE type'}">
+ <p class="usecase">
{{data.serviceDomain}}
</p>
</td>
<td>
- <span [ngClass]="{'active':data.statusClass=='2001','closed':data.statusClass=='Closed','onboarding':data.statusClass=='Onboarding',
- 'updating':data.statusClass=='Updating','deleting':data.statusClass=='1002','creating':data.statusClass=='1001',
- 'scaling':data.statusClass=='1003','healing':data.statusClass=='1004'}"
- *ngIf="data.tips != 'Available' && data.tips != 'Unavailable'">{{data.tips}}</span>
- <span *ngIf="data.tips == 'Available' " style="margin-left: 10px">
+ <span [ngClass]="{'active':data.statusClass==='2001','closed':data.statusClass==='Closed','onboarding':data.statusClass==='Onboarding',
+ 'updating':data.statusClass==='Updating','deleting':data.statusClass==='1002','creating':data.statusClass==='1001',
+ 'scaling':data.statusClass==='1003','healing':data.statusClass==='1004'}"
+ *ngIf="data.tips !== 'Available' && data.tips !== 'Unavailable'">{{data.tips}}</span>
+ <span *ngIf="data.tips === 'Available' " class="marginLeft10">
<img src="assets/images/wancheng-icon.png" alt="Available">
</span>
- <span *ngIf="data.tips == 'Unavailable' " style="margin-left: 10px">
+ <span *ngIf="data.tips === 'Unavailable' " class="marginLeft10">
<img src="assets/images/shibai-icon.png" alt="Unavailable">
</span>
- <nz-progress *ngIf="data.status == 'In Progress'" [nzPercent]="data.rate"
+ <nz-progress *ngIf="data.status === 'In Progress'" [nzPercent]="data.rate"
[nzShowInfo]="false" nzStatus="active"></nz-progress>
</td>
<td>
- <i [ngClass]="{'cannotclick':data.status == 'In Progress'||(data.status=='Failed' && data.operationType=='1001')||(data.status=='Failed' && data.operationType=='1002')}"
+ <i [ngClass]="{'cannotclick':data.status === 'In Progress'||(data.status=='Failed' && data.operationType=='1001')||(data.status==='Failed' && data.operationType=='1002')}"
class="anticon anticon-bars" (click)="serviceDetail(data,1)"></i>
- <i [ngClass]="{'cannotclick':data.status == 'In Progress'}" class="anticon anticon-delete"
+ <i [ngClass]="{'cannotclick':data.status === 'In Progress'}" class="anticon anticon-delete"
(click)="deleteModel(data)"></i>
- <i [ngClass]="{'cannotclick':data.status == 'In Progress'}" class="anticon anticon-ellipsis"
+ <i [ngClass]="{'cannotclick':data.status === 'In Progress'}" class="anticon anticon-ellipsis"
(click)="iconMoreShow(data,tableData)" style="transform: rotate(90deg);"></i>
<ul *ngIf="data.iconMore==true " class="icon-more">
@@ -218,255 +154,50 @@
</tbody>
</nz-table>
- <nz-modal nzWidth="428" [nzVisible]="scaleModelVisible" nzTitle=" {{'i18nTextDefine_Scale' | translate}} "
- (nzOnCancel)="scaleCancel()" (nzOnOk)="scaleOk(templatescalestarting,templateScaleSuccessFaild)"
- nzClassName="scaleModel" nzCancelText=" {{'i18nTextDefine_Cancel' | translate}} "
- nzOkText=" {{'i18nTextDefine_modelOk' | translate}} ">
- <h3><span style="color: red">*&nbsp;</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 &nbsp;
- {{"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">*&nbsp;</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'] }} &nbsp; {{"i18nTextDefine_InstanceTeminationStarting" |
- translate}}
- </div>
- <div class="ant-notification-notice-message"
- *ngIf="thisService['serviceDomain'] == 'E2E Service'">E2E &nbsp;
- {{"i18nTextDefine_InstanceTeminationStarting" | translate}}
- </div>
- <div class="ant-notification-notice-message"
- *ngIf="thisService['serviceDomain'] == 'Network Service'">NS &nbsp;
- {{"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">*&nbsp;</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>
- &nbsp;
- </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"> &nbsp;
- 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 &nbsp;
- {{"i18nTextDefine_InstanceHealingStarting" | translate}}
- </div>
- <div class="ant-notification-notice-description">
- <div class="notificationlist">
- <p> {{"i18nTextDefine_InstanceName" | translate}} :</p>
- <span>{{ thisService["service-instance-name"] ||
- thisService["nsInstanceName"] }}
- </span>
- </div>
- <div class="notificationlist">
- <p> {{"i18nTextDefine_Customer" | translate}} :</p>
- <span>{{ customerSelected.name }}</span>
- </div>
- <div class="notificationlist">
- <p> {{"i18nTextDefine_UseCase" | translate}} :</p>
- <span>{{ thisService["serviceDomain"] }}</span>
- </div>
- </div>
- <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div>
- </div>
- </div>
- </ng-template>
- </nz-modal>
+ <app-delete-model
+ *ngIf="deleteModalVisible"
+ [deleteModalVisible]="deleteModalVisible"
+ [thisService]="thisService"
+ [terminationType]="terminationType"
+ [loadingAnimateShow]="loadingAnimateShow"
+ [gracefulTerminationTimeout]="gracefulTerminationTimeout"
+ [templateDeleteSuccessFaild]="templateDeleteSuccessFaild"
+ (cancel)="deleteModalVisible=$event"
+ (deleteModalOK)="deleteModalOK($event,templateDeleteSuccessFaild)"
+ >
+ </app-delete-model>
+ <app-scale-model
+ *ngIf="scaleModelVisible"
+ [scaleModelVisible]="scaleModelVisible"
+ [thisService]="thisService"
+ [e2e_nsData]="e2e_nsData"
+ [customerSelected]="customerSelected"
+ [serviceTypeSelected]="serviceTypeSelected"
+ [templatescalestarting]="templatescalestarting"
+ [templateScaleSuccessFaild]="templateScaleSuccessFaild"
+ (cancel)="scaleModelVisible=$event"
+ (scaleModalOK)="scaleModalOK($event,templatescalestarting,templateScaleSuccessFaild)"
+ >
+ </app-scale-model>
+ <app-heal-model
+ *ngIf="healModelVisible"
+ [healModelVisible]="healModelVisible"
+ [thisService]="thisService"
+ [nsParams]="nsParams"
+ [healActions]="healActions"
+ [nsAdditional]="nsAdditional"
+ [vnfParams]="vnfParams"
+ [vmSelected]="vmSelected"
+ [vnfVms]="vnfVms"
+ [templatehealstarting]="templatehealstarting"
+ [templatehealSuccessFaild]="templatehealSuccessFaild"
+ (cancel)="healModelVisible=$event"
+ (healModalOK)="healModalOK($event,templatehealstarting,templatehealSuccessFaild)"
+ ></app-heal-model>
+ <app-notification #notification [isServicesList]="true" [customerSelected]="customerSelected"></app-notification>
<!-- add notification-->
+
<ng-template #templateCreatestarting>
<div class="ant-notification-notice-content">
<div class="ant-notification-notice-with-icon">
@@ -474,7 +205,7 @@
<img src="assets/images/execute-inproess.png" alt="instance temination is starting">
</span>
<div class="ant-notification-notice-message"
- *ngIf="thisCreateService['serviceDomain'] == 'CCVPN' || thisService['serviceDomain'] == 'SOTN'">
+ *ngIf="thisCreateService['serviceDomain'] === 'CCVPN' || thisService['serviceDomain'] === 'SOTN'">
{{ thisService['serviceDomain'] }} &nbsp; {{"i18nTextDefine_InstanceCreationStarting" |
translate}}
</div>
@@ -582,6 +313,7 @@
*ngIf="(thisService['serviceDomain'] == 'Network Service') && thisService.status == 'Successful'">
NS &nbsp; {{"i18nTextDefine_InstanceTeminatedSuccessfully" | translate}}
</div>
+
<div class="ant-notification-notice-message"
*ngIf="(thisService['serviceDomain'] == 'CCVPN' || thisService['serviceDomain'] == 'SOTN') && thisService.status == 'Failed'">
{{ thisService['serviceDomain'] }} &nbsp; {{"i18nTextDefine_InstanceTeminationFailed" |
@@ -615,6 +347,35 @@
</div>
</div>
</ng-template>
+ <ng-template #templatescalestarting>
+ <div class="ant-notification-notice-content">
+ <div class="ant-notification-notice-with-icon">
+ <span class="ant-notification-notice-icon">
+ <img src="assets/images/execute-inproess.png" alt="instance temination is starting">
+ </span>
+ <div class="ant-notification-notice-message">E2E &nbsp;
+ {{"i18nTextDefine_InstanceTeminationStarting" | translate}}
+ </div>
+ <div class="ant-notification-notice-description">
+ <div class="notificationlist">
+ <p> {{"i18nTextDefine_InstanceName" | translate}} :</p>
+ <span>{{ thisService["service-instance-name"] ||
+ thisService["nsInstanceName"] }}
+ </span>
+ </div>
+ <div class="notificationlist">
+ <p> {{"i18nTextDefine_Customer" | translate}} :</p>
+ <span>{{ customerSelected.name }}</span>
+ </div>
+ <div class="notificationlist">
+ <p> {{"i18nTextDefine_UseCase" | translate}} :</p>
+ <span>{{ thisService["serviceDomain"] }}</span>
+ </div>
+ </div>
+ <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div>
+ </div>
+ </div>
+ </ng-template>
<ng-template #templateScaleSuccessFaild>
<div class="ant-notification-notice-content">
<div class="ant-notification-notice-with-icon">
@@ -650,6 +411,35 @@
</div>
</div>
</ng-template>
+ <ng-template #templatehealstarting>
+ <div class="ant-notification-notice-content">
+ <div class="ant-notification-notice-with-icon">
+ <span class="ant-notification-notice-icon">
+ <img src="assets/images/execute-inproess.png" alt="instance temination is starting">
+ </span>
+ <div class="ant-notification-notice-message">NS &nbsp;
+ {{"i18nTextDefine_InstanceHealingStarting" | translate}}
+ </div>
+ <div class="ant-notification-notice-description">
+ <div class="notificationlist">
+ <p> {{"i18nTextDefine_InstanceName" | translate}} :</p>
+ <span>{{ thisService["service-instance-name"] ||
+ thisService["nsInstanceName"] }}
+ </span>
+ </div>
+ <div class="notificationlist">
+ <p> {{"i18nTextDefine_Customer" | translate}} :</p>
+ <span>{{ customerSelected.name }}</span>
+ </div>
+ <div class="notificationlist">
+ <p> {{"i18nTextDefine_UseCase" | translate}} :</p>
+ <span>{{ thisService["serviceDomain"] }}</span>
+ </div>
+ </div>
+ <div class="close-icons">{{"i18nTextDefine_Close" | translate}}</div>
+ </div>
+ </div>
+ </ng-template>
<ng-template #templatehealSuccessFaild>
<div class="ant-notification-notice-content">
<div class="ant-notification-notice-with-icon">
@@ -728,7 +518,7 @@
</div>
<div class="detailComponent" *ngIf="detailshow2">
<app-e2e-detail [detailParams]="detailData" (closeDetail)="detailshow2 = false;listDisplay = false;">
- </app-e2e-detail>
+ </app-e2e-detail>
</div>
<div class="createComponent" *ngIf="createshow">
<app-ccvpn-creation [createParams]="createData" [ccvpn_temParametersContent]="ccvpn_temParametersContent"
diff --git a/usecaseui-portal/src/app/views/services/services-list/services-list.component.less b/usecaseui-portal/src/app/views/services/services-list/services-list.component.less
index aeddf257..454e3bc8 100644
--- a/usecaseui-portal/src/app/views/services/services-list/services-list.component.less
+++ b/usecaseui-portal/src/app/views/services/services-list/services-list.component.less
@@ -207,69 +207,9 @@ nz-layout{
width: 100%;
display: flex;
justify-content: space-around;
- .top-list{
- position: relative;
- width:32%;
- max-width:400px;
- height:170px;
- background:url("/assets/images/servicelist-e2e.png") no-repeat;
- background-size: 100% 100%;
- border-radius:2px;
- .round{
- position: absolute;
- width: 60px;
- height: 60px;
- line-height: 60px;
- text-align: center;
- background:#E0EDFF;
- border:2px solid rgba(224,237,255,1);
- border-radius: 50%;
- font-size:16px;
- font-family:ArialMT;
- color:#3C4F8C;
- transition: .5s;
- }
- .top-list-text{
- position: absolute;
- text-align: right;
- line-height: 20px;
- right: 12%;
- color: #fff;
- p{
- height: 28px;
- margin-bottom: 0;
- padding-left: 5px;
- font-size: 14px;
- clear: both;
- span{
- display: inline-block;
- float: right;
- font-weight: 500;
- text-align: right;
- }
- span:nth-child(1){
- font-size: 18px;
- margin-left: 15px;
- }
- span:nth-child(2){
- width: 85px;
- font-size: 16px;
- }
- }
- p:nth-child(1){
- margin-top: 25px;
- }
- .service-description{
-
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- color: #3C4F8C;
-
- }
- }
+ app-top-card{
+ width: 32%;
}
-
}
}
.list {
@@ -312,6 +252,9 @@ nz-layout{
font-size: 12px;
color: orangered;
}
+ span.marginLeft10{
+ margin-left: 10px;
+ }
i.anticon {
cursor: pointer;
font-size: 18px;
@@ -395,7 +338,7 @@ nz-layout{
z-index: 3;
}
-.e2eColor,.nsColor,.ccvpnColor,.sotnColor,.voLTEColor{
+.usecase{
width:120px;
height: 34px;
line-height: 34px;
@@ -416,18 +359,6 @@ nz-layout{
border-radius:4px;
}
-.select-list{
- width: 320px;
- height: 32px;
- line-height: 32px;
- margin: 35px auto;
-}
-.select-list>span{
- text-align: right;
- width: 110px!important;
- line-height: 32px;
-}
-
.listdisplay{
display: none;
} \ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services-list/services-list.component.ts b/usecaseui-portal/src/app/views/services/services-list/services-list.component.ts
index 72cacc7e..da027028 100644
--- a/usecaseui-portal/src/app/views/services/services-list/services-list.component.ts
+++ b/usecaseui-portal/src/app/views/services/services-list/services-list.component.ts
@@ -13,8 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
-import { Component, OnInit, HostBinding, TemplateRef } from '@angular/core';
-import { MyhttpService } from '../../../core/services/myhttp.service';
+import { Component, OnInit, HostBinding, TemplateRef, ViewChild } from '@angular/core';
+import { ServiceListService } from '../../../core/services/serviceList.service';
import { slideToRight } from '../../../shared/utils/animates';
import { NzModalService } from 'ng-zorro-antd';
import { NzNotificationService } from 'ng-zorro-antd';
@@ -28,10 +28,11 @@ import { Observable } from 'rxjs/Rx';
})
export class ServicesListComponent implements OnInit {
@HostBinding('@routerAnimate') routerAnimateState;
+ @ViewChild('notification') notification1: any;
public width:number = document.documentElement.clientWidth;
- constructor(private myhttp: MyhttpService, private modalService: NzModalService, private notification: NzNotificationService) {
+ constructor(private myhttp: ServiceListService, private modalService: NzModalService, private notification: NzNotificationService) {
}
ngOnInit() {
@@ -41,16 +42,19 @@ export class ServicesListComponent implements OnInit {
this.width = document.documentElement.clientWidth
});
}
-
+ ngOnDestroy() {
+ clearInterval(this.progressCcvpnOutTimer);
+ clearInterval(this.progressingCcvpnTimer);
+ clearInterval(this.progressNsOutTimer);
+ clearInterval(this.progressingNsTimer);
+ }
// customer servicetype
isSol005Interface = false;
orchestratorList = [];
customerList = [];
- customerList2 = [];
customerSelected = { name: null, id: null };
customerSelected2 = { name: null, id: null };
serviceTypeList = [];
- serviceTypeList2 = [];
serviceTypeSelected = { name: '' };
serviceTypeSelected2 = { name: '' };
serviceTypeSelectedName = "";
@@ -60,7 +64,7 @@ export class ServicesListComponent implements OnInit {
language = sessionStorage.getItem("DefaultLang");
iconMore = false;
loadingAnimateShow = false;
- serviceMunber = [ // top: E2E/NS/CCVPN data
+ serviceNunber = [ // top: E2E/NS/CCVPN data
{
"serviceDomain": "E2E",
"Success": 0,
@@ -84,6 +88,11 @@ export class ServicesListComponent implements OnInit {
}
];
+ progressCcvpnOutTimer :any; // ccvpn��NS progress Timer
+ progressingCcvpnTimer :any;
+ progressNsOutTimer :any;
+ progressingNsTimer :any;
+
//The icon behind each row of data in the table expands
iconMoreShow(data, tableData) {
tableData.map((its) => {
@@ -104,59 +113,40 @@ export class ServicesListComponent implements OnInit {
console.log(this.language, "this.language");
this.myhttp.getAllCustomers()
.subscribe((data) => {
- this.customerList = data.map((item) => {
- return { name: item["subscriber-name"], id: item["global-customer-id"] }
- });
- if (this.customerList.length == 0) {
- console.log("customerList.length == 0", this.customerList);
- return false;
+ this.customerList = data.map(item => ({ name: item["subscriber-name"], id: item["global-customer-id"] }) );
+ if(data.length !== 0){
+ this.customerSelected = this.customerList[0];
+ this.choseCustomer();
}
- this.customerList2 = data.map((item) => {
- return { name: item["subscriber-name"], id: item["global-customer-id"] }
- });
- if (this.customerList2.length == 0) {
- return false;
- }
- this.customerSelected = this.customerList[0];
- this.choseCustomer(this.customerSelected);
})
}
getallOrchestrators() {
this.myhttp.getAllOrchestrators()
.subscribe((data) => {
- this.orchestratorList = data.map((item) => {
- return { name: item["name"], id: item["name"] }
- });
- if (this.orchestratorList.length == 0) {
- console.log("orchestratorList.length == 0", this.orchestratorList);
- return false;
+ if(data.length > 0){
+ this.orchestratorList = data.map((item) => {
+ return { name: item["name"], id: item["name"] }
+ });
+ this.orchestratorSelected = this.orchestratorList[0];
}
- this.orchestratorSelected = this.orchestratorList[0];
})
}
- choseCustomer(item) {
- this.customerSelected = item;
+ choseCustomer(item = this.customerSelected) {
+ if(this.customerSelected !== item) this.customerSelected = item;
this.myhttp.getServiceTypes(this.customerSelected)
.subscribe((data) => {
- this.serviceTypeList = data.map((item) => {
- return { name: item["service-type"] }
- });
-
- if (this.serviceTypeList.length == 0) {
- console.log("serviceTypeList.length == 0", this.serviceTypeList);
- return false;
+ this.serviceTypeList = data.map( item => ({ name: item["service-type"] }));
+ if(data.length !== 0){
+ this.serviceTypeSelected = this.serviceTypeList[0];
+ this.choseServiceType();
}
-
- this.serviceTypeSelected = this.serviceTypeList[0];
-
- this.choseServiceType(this.serviceTypeSelected);
})
}
- choseServiceType(item) {
- this.serviceTypeSelected = item;
+ choseServiceType(item = this.serviceTypeSelected) {
+ if(this.serviceTypeSelected !== item) this.serviceTypeSelected = item;
this.getTableData();
}
@@ -164,131 +154,28 @@ export class ServicesListComponent implements OnInit {
// Create modal box 2 (dialog box) create -------------------------------
isVisible = false;
- customerChange(): void {
- this.getServiceType(this.customerSelected2);
- }
-
- getServiceType(customerSelected2) {
- this.myhttp.getServiceTypes(customerSelected2)
- .subscribe((data) => {
- this.serviceTypeList2 = data.map((item) => {
- return { name: item["service-type"] }
- });
- if (this.serviceTypeList2.length == 0) {
- console.log("serviceTypeList.length == 0", this.serviceTypeList2);
- return false;
- }
- this.getAlltemplates();
- })
- }
-
- serviceTypeChange(): void {
- this.serviceTypeSelected2.name = this.serviceTypeSelectedName
- }
-
createModal(): void {
this.isVisible = true;
- this.getallOrchestrators();
- this.customerSelected2 = this.customerSelected;
- this.serviceTypeSelectedName = this.serviceTypeSelected.name;
- this.serviceTypeSelected2 = Object.assign({}, this.serviceTypeSelected);
- this.getServiceType(this.customerSelected2);
- }
-
- choseTemplateType() {
- this.getallOrchestrators();
- this.getAlltemplates();
- }
-
- templates = [];
- template1 = { name: null };
-
- getAlltemplates() {
- this.myhttp.getAllServiceTemplates(this.templateTypeSelected)
- .subscribe((data) => {
- this.templates = data;
- if (this.templateTypeSelected == "Network Service") {
- this.templates = data.filter((d) => {
- return typeof d.packageInfo.csarName == "string";
- }).map((item) => {
- let cName = item.packageInfo.csarName.split("/").reverse()[0];
- return { name: cName, id: item.csarId, packageInfo: item.packageInfo }
- });
- }
- this.template1 = this.templates[0];
- }, (err) => {
- console.log(err);
- })
}
- createshow = false;
- createshow2 = false;
- listDisplay = false;
+ createshow: boolean = false;
+ createshow2: boolean = false;
+ listDisplay: boolean = false;
createData: Object = {};
-
- handleOk(): void {
- if (this.templateTypeSelected == "SOTN" || this.templateTypeSelected == "CCVPN") {
- this.createData = {
- commonParams: {
- customer: this.customerSelected,
- serviceType: this.serviceTypeSelected2,
- templateType: this.templateTypeSelected
- }, template: this.template1
- };
- } else if (this.templateTypeSelected == "E2E Service" || this.templateTypeSelected == "Network Service") {
- this.createData = {
- commonParams: {
- customer: this.customerSelected,
- serviceType: this.serviceTypeSelected2,
- templateType: this.templateTypeSelected
- },
- template: this.template1,
- orchestrator: this.orchestratorSelected,
- isSol005Interface: this.isSol005Interface
- };
- }
- this.getTemParameters();
- }
-
- handleCancel(): void {
- this.isVisible = false;
- this.loadingAnimateShow = false;
- }
-
- temParametersTips = false;
ccvpn_temParametersContent: any;
e2e_ns_temParametersContent: any;
- getTemParameters() {
- let chosedtemplates = this.createData["template"];
- let types = this.createData["commonParams"].templateType;
- if (types == "E2E Service") {
- types = "e2e";
- } else if (types == "Network Service") {
- types = "ns";
+ createdModalShow(obj: any): void{
+ this.createData = obj.createData;
+ console.log(obj.createData)
+ if (obj.templateType === "SOTN" || obj.templateType === "CCVPN") {
+ this.ccvpn_temParametersContent = obj.data;
+ this.createshow = true;
+ } else if (obj.templateType === "E2E Service" || obj.templateType === "Network Service") {
+ this.e2e_ns_temParametersContent = obj.data;
+ this.createshow2 = true;
}
- this.loadingAnimateShow = true;
- this.myhttp.getTemplateParameters(types, chosedtemplates)
- .subscribe((data) => {
- this.loadingAnimateShow = false;
- if (data.status == "FAILED") {
- this.temParametersTips = true;
- this.isVisible = true;
- console.log("Template parsing Failed");
- } else {
- this.isVisible = false;
- this.temParametersTips = false;
- if (this.templateTypeSelected == "SOTN" || this.templateTypeSelected == "CCVPN") {
- this.ccvpn_temParametersContent = data;
- this.createshow = true;
- this.listDisplay = true;
- } else if (this.templateTypeSelected == "E2E Service" || this.templateTypeSelected == "Network Service") {
- this.e2e_ns_temParametersContent = data;
- this.createshow2 = true;
- this.listDisplay = true;
- }
- }
- })
+ this.listDisplay = true;
}
//tableData
@@ -316,7 +203,7 @@ export class ServicesListComponent implements OnInit {
}
item["iconMore"] = this.iconMore;
- if (item["serviceDomain"] == "Network Service") {
+ if (item["serviceDomain"] === "Network Service") {
if (item["vnfInfo"]) {
item["childServiceInstances"] = item["vnfInfo"].map((vnf) => {
vnf["serviceDomain"] = "vnf";
@@ -334,10 +221,10 @@ export class ServicesListComponent implements OnInit {
};
vnfInfo.vnfNsInstanceId = item["nsInstanceId"] || item["service-instance-id"];
vnfInfo.vnfInstanceId = vnf["relationship-data"].find((vnfid) => {
- return vnfid["relationship-key"] == "generic-vnf.vnf-id"
+ return vnfid["relationship-key"] === "generic-vnf.vnf-id"
})["relationship-value"];
vnfInfo.vnfInstanceName = vnf["related-to-property"].find((vnfname) => {
- return vnfname["property-key"] == "generic-vnf.vnf-name"
+ return vnfname["property-key"] === "generic-vnf.vnf-name"
})["property-value"];
return vnfInfo;
})
@@ -347,32 +234,30 @@ export class ServicesListComponent implements OnInit {
}
//
- if (item["operationResult"] == "2001") { //operationResult==2001
+ if (item["operationResult"] === "2001") {
item["status"] = "Available";
item["tips"] = "Available";
item["statusClass"] = item["operationResult"];
}
// 2018.12.13
- else if (item["operationResult"] == "2002") { //operationResult==2002
- if (item["operationType"] == "1001" || item["operationType"] == "1002") {
+ else if (item["operationResult"] === "2002") {
+ if (item["operationType"] === "1001" || item["operationType"] === "1002") {
// item["status"] = this.accordingState["operationResult"][item["operationResult"]];
item["status"] = this.listSortMasters["operationResults"].find((its) => {
- return its["sortCode"] == item["operationResult"] && its["language"] == this.language
+ return its["sortCode"] === item["operationResult"] && its["language"] === this.language
})["sortValue"];
item["tips"] = "Unavailable";
item["statusClass"] = item["operationType"];
- } else if (item["operationType"] != "1001" && item["operationType"] != "1002") {
- // item["status"] = this.accordingState["operationResult"][item["operationResult"]];
+ } else {
item["status"] = this.listSortMasters["operationResults"].find((its) => {
- return its["sortCode"] == item["operationResult"] && its["language"] == this.language
+ return its["sortCode"] === item["operationResult"] && its["language"] === this.language
})["sortValue"];
item["tips"] = "Available";
item["statusClass"] = item["operationType"];
}
}
- else if (item["operationResult"] == "2003") { //operationResult==2003
- // item["status"] = this.accordingState["operationResult"][item["operationResult"]];
+ else if (item["operationResult"] === "2003") {
item["status"] = this.listSortMasters["operationResults"].find((its) => {
return its["sortCode"] == item["operationResult"] && its["language"] == this.language
})["sortValue"];
@@ -404,16 +289,11 @@ export class ServicesListComponent implements OnInit {
})
} else {
let updata = (prodata) => {
- item["rate"] = prodata.progress || item["rate"];
+ item["rate"] = prodata.progress || 0;
+ if(item["rate"] > 100) item["status"] = prodata.status;
item["tips"] = this.listSortMasters["operationTypes"].find((its) => {
- return its["sortCode"] == item["operationType"] && its["language"] == this.language
- })["sortValue"] + '\xa0\xa0\xa0' + prodata.progress + "%";
- if (item["rate"] > 100) {
- item["status"] = prodata.status;
- item["tips"] = this.listSortMasters["operationTypes"].find((its) => {
- return its["sortCode"] == item["operationType"] && its["language"] == this.language
- })["sortValue"] + '\xa0\xa0\xa0' + item["status"];
- }
+ return its["sortCode"] === item["operationType"] && its["language"] === this.language
+ })["sortValue"] + '\xa0\xa0\xa0' + (item["rate"] > 100? item["status"] : prodata.progress + '%');
}
let obj = {
serviceId: item["service-instance-id"],
@@ -433,35 +313,36 @@ export class ServicesListComponent implements OnInit {
}
return item;
})
- this.tableData.map((item, index) => {
- if (item.serviceDomain == 'E2E Service') {
- if (item.operationResult == 2001) {
- this.serviceMunber[0]["Success"] += 1;
- } else if (item.operationResult == 2002) {
- this.serviceMunber[0]["failed"] += 1;
- } else if (item.operationResult == 2003) {
- this.serviceMunber[0]["InProgress"] += 1;
+ this.tableData.forEach( item => {
+ if (item.serviceDomain === 'E2E Service') {
+ if (item.operationResult === 2001) {
+ this.serviceNunber[0]["Success"] += 1;
+ } else if (item.operationResult === 2002) {
+ this.serviceNunber[0]["failed"] += 1;
+ } else if (item.operationResult === 2003) {
+ this.serviceNunber[0]["InProgress"] += 1;
}
}
- else if (item.serviceDomain == 'Network Service') {
- if (item.operationResult == 2001) {
- this.serviceMunber[1]["Success"] += 1;
- } else if (item.operationResult == 2002) {
- this.serviceMunber[1]["failed"] += 1;
- } else if (item.operationResult == 2003) {
- this.serviceMunber[1]["InProgress"] += 1;
+ else if (item.serviceDomain === 'Network Service') {
+ if (item.operationResult === 2001) {
+ this.serviceNunber[1]["Success"] += 1;
+ } else if (item.operationResult === 2002) {
+ this.serviceNunber[1]["failed"] += 1;
+ } else if (item.operationResult === 2003) {
+ this.serviceNunber[1]["InProgress"] += 1;
}
}
- else if (item.serviceDomain == 'CCVPN') {
- if (item.operationResult == 2001) {
- this.serviceMunber[2]["Success"] += 1;
- } else if (item.operationResult == 2002) {
- this.serviceMunber[2]["failed"] += 1;
- } else if (item.operationResult == 2003) {
- this.serviceMunber[2]["InProgress"] += 1;
+ else if (item.serviceDomain === 'CCVPN') {
+ if (item.operationResult === 2001) {
+ this.serviceNunber[2]["Success"] += 1;
+ } else if (item.operationResult === 2002) {
+ this.serviceNunber[2]["failed"] += 1;
+ } else if (item.operationResult === 2003) {
+ this.serviceNunber[2]["InProgress"] += 1;
}
}
})
+ console.log(this.tableData)
this.loading = false;
}, (err) => {
console.log(err);
@@ -484,43 +365,18 @@ export class ServicesListComponent implements OnInit {
customerId: this.customerSelected.id,
serviceType: this.serviceTypeSelected.name,
serviceId: service["service-instance-id"]
- }
+ };
this.myhttp.getE2e_nsData(paramsObj)
.subscribe((data) => {
this.e2e_nsData = data;
})
}
- scaleOk(templatescalestarting, templateScaleSuccessFaild) {
- this.scaleModelVisible = false;
- let requestBody = {
- "service": {
- "serviceInstanceName": this.thisService["service-instance-name"],
- "serviceType": this.serviceTypeSelected.name,
- "globalSubscriberId": this.customerSelected.id,
- "resources": this.e2e_nsData.map((item) => {
- return {
- "resourceInstanceId": item["netWorkServiceId"],
- "scaleType": item["scaleType"],
- "scaleNsData": {
- "scaleNsByStepsData": {
- "aspectId": item["aspectId"],
- "numberOfSteps": item["numberOfSteps"],
- "scalingDirection": item["scalingDirection"]
- }
- }
- }
- })
- }
- }
- this.scaleE2eService(this.thisService, requestBody, templateScaleSuccessFaild);
+ scaleModalOK(obj: any,templatescalestarting,templateScaleSuccessFaild) :void{
+ this.scaleE2eService(this.thisService, obj, templateScaleSuccessFaild);
this.scaleNotification(templatescalestarting);
}
- scaleCancel() {
- this.scaleModelVisible = false;
- }
-
scaleNotification(template: TemplateRef<{}>): void {
this.notification.template(template);
}
@@ -552,23 +408,7 @@ export class ServicesListComponent implements OnInit {
vmname: ""
}
}
- }
-
- addActionsHealing() {
- this.healActions.push({ value: "" })
- }
-
- minusActionsHealing(index) {
- this.healActions.splice(index, 1);
- }
-
- addNsAdditional() {
- this.nsAdditional.push({ key: "", value: "" })
- }
-
- minusNsAdditional(index) {
- this.nsAdditional.splice(index, 1);
- }
+ };
healService(service) {
this.thisService = service;
@@ -583,30 +423,11 @@ export class ServicesListComponent implements OnInit {
}
}
- healOk(templatehealstarting, templatehealSuccessFaild) {
- this.healModelVisible = false;
- // nsParams
- this.nsParams.actionsHealing = this.healActions.map((item) => {
- return item.value
- });
- let additional = {};
- this.nsAdditional.forEach((item) => {
- additional[item.key] = item.value;
- });
- this.nsParams.additionalParamsforNs = JSON.stringify(additional);
- // vnfParams
- this.vnfParams.additionalParams.actionvminfo.vmid = this.vmSelected["vmId"];
- this.vnfParams.additionalParams.actionvminfo.vmname = this.vmSelected["vmName"];
-
- let requestBody = this.thisService["serviceDomain"] == "Network Service" ? { healNsData: this.nsParams } : { healVnfData: this.vnfParams };
- this.healNsVnfService(this.thisService, requestBody, templatehealSuccessFaild);
+ healModalOK(obj: any,templatehealstarting,templatehealSuccessFaild) :void{
+ this.healNsVnfService(this.thisService, obj, templatehealSuccessFaild);
this.healNotification(templatehealstarting);
}
- healCancel() {
- this.healModelVisible = false;
- }
-
healNotification(template: TemplateRef<{}>): void {
this.notification.template(template);
}
@@ -628,54 +449,45 @@ export class ServicesListComponent implements OnInit {
service["serviceType"] = this.serviceTypeSelected;
service.childServiceInstances.forEach((item) => {
- if (item.serviceDomain == "SITE") {
+ if (item.serviceDomain === "SITE") {
service.siteSer.push(item);
- } else if (item.serviceDomain == "SDWAN") {
+ } else if (item.serviceDomain === "SDWAN") {
service.sdwanSer.push(item);
}
})
- if (service["serviceDomain"] == 'CCVPN' || service["serviceDomain"] == 'SOTN') {
+ if (service["serviceDomain"] === 'CCVPN' || service["serviceDomain"] === 'SOTN') {
this.detailshow = true;
- if (typeNum == 1) {
+ if (typeNum === 1) {
this.upDateShow = false;
} else {
this.upDateShow = true;
}
- } else if (service["serviceDomain"] == 'E2E Service' || service["serviceDomain"] == 'Network Service') {
+ } else if (service["serviceDomain"] === 'E2E Service' || service["serviceDomain"] === 'Network Service') {
this.detailshow2 = true;
}
this.listDisplay = true;
this.detailData = service;
- console.log(service);
}
- deleteModelVisible = false;
+ deleteModalVisible = false;
terminationType = "graceful";
gracefulTerminationTimeout = 120;
// delete Model show
deleteModel(service) {
this.thisService = service;
- this.deleteModelVisible = true;
+ this.deleteModalVisible = true;
}
- deleteOk(templatedeletestarting, templateDeleteSuccessFaild) {
- this.deleteModelVisible = false;
+ deleteModalOK(obj: any,templateDeleteSuccessFaild) :void{
+ this.deleteModalVisible = false;
this.loadingAnimateShow = true;
- if (this.thisService["serviceDomain"] == "Network Service") {
- this.deleteNsService(this.thisService, templateDeleteSuccessFaild);
+ if (this.thisService["serviceDomain"] === "Network Service") {
+ this.deleteNsService(obj,this.thisService);
} else {
this.deleteService(this.thisService, templateDeleteSuccessFaild);
}
- this.deleteNotification(templatedeletestarting);
- }
-
- deleteCancel() {
- this.deleteModelVisible = false;
- }
-
- deleteNotification(template: TemplateRef<{}>): void {
- this.notification.template(template);
+ this.notification1.notificationStart(this.thisService['serviceDomain'],'deleteStarting',this.thisService["service-instance-name"] ||this.thisService["nsInstanceName"])
}
deleteSuccessNotification(template: TemplateRef<{}>): void {
@@ -1011,7 +823,10 @@ export class ServicesListComponent implements OnInit {
service.tips = "";
service.statusClass = "1004";
let id = service.nsInstanceId || service["service-instance-id"] || service["vnfNsInstanceId"];
- this.myhttp.healNsService(id, requestBody)
+ let paramsObj = {
+ "ns_instance_id":id
+ };
+ this.myhttp.healNsService(paramsObj, requestBody)
.subscribe((data) => {
if (data.status == "FAILED") {
console.log("heal nsvnf service Failed :" + JSON.stringify(data));
@@ -1113,7 +928,7 @@ export class ServicesListComponent implements OnInit {
})
}
- deleteService(service, templateDeleteSuccessFaild) {
+ deleteService(service:any, templateDeleteSuccessFaild) {
let allprogress = {};
let querypros = [];
service.rate = 0;
@@ -1190,21 +1005,17 @@ export class ServicesListComponent implements OnInit {
})
}
- deleteNsService(service, templateDeleteSuccessFaild) {
+ deleteNsService(obj:any,service:any) {
service.rate = 0;
service.status = "In Progress";
service.tips = "";
service.statusClass = "1002";
let id = service.nsInstanceId || service["service-instance-id"];
let operationType = "1002";
- let requestBody = {
- terminationType: this.terminationType,
- gracefulTerminationTimeout: this.gracefulTerminationTimeout
- }
- this.stopNsService(id, requestBody).then((jobid) => {
- if (jobid == "Failed") {
+ this.stopNsService(id, obj).then((jobid) => {
+ if (jobid === "Failed") {
service.status = "Failed";
- this.deleteSuccessNotification(templateDeleteSuccessFaild);
+ this.notification1.notificationFailed(service.serviceDomain,'deleteStarting',service["service-instance-name"] ||service["nsInstanceName"])
service.tips = this.listSortMasters["operationTypes"].find((its) => {
return its["sortCode"] == service.statusClass && its["language"] == this.language
})["sortValue"] + this.listSortMasters["operationResults"].find((its) => {
@@ -1213,58 +1024,56 @@ export class ServicesListComponent implements OnInit {
return false;
}
let updata = (prodata) => {
- service.rate = prodata.progress;
+ service.rate = prodata.progress || 0;
+ if(service['rate'] > 100)service["status"] = prodata.status;
service.tips = this.listSortMasters["operationTypes"].find((its) => {
return its["sortCode"] == service.statusClass && its["language"] == this.language
- })["sortValue"] + '\xa0\xa0\xa0' + service.rate + "%";
- if (service["rate"] > 100) {
- service["status"] = prodata.status;
- service.tips = this.listSortMasters["operationTypes"].find((its) => {
- return its["sortCode"] == service.statusClass && its["language"] == this.language
- })["sortValue"] + service["status"];
- }
+ })["sortValue"] + (service["rate"] > 100? service["status"] : ('\xa0\xa0\xa0' + service.rate + "%"));
}
- return this.queryNsProgress(jobid, null, updata, operationType);
- }).then(() => {
- this.myhttp.nsDeleteInstance(id)
- .subscribe((data) => {
- console.log(data);
- service.rate = 100;
- service.status = "Successful";
- service.tips = this.listSortMasters["operationTypes"].find((its) => {
- return its["sortCode"] == service.statusClass && its["language"] == this.language
- })["sortValue"] + this.listSortMasters["operationResults"].find((its) => {
- return its["sortCode"] == 2001 && its["language"] == this.language
- })["sortValue"];
- this.deleteSuccessNotification(templateDeleteSuccessFaild);
- if (data.status == "FAILED") {
- console.log("delete ns service Failed :" + JSON.stringify(data));
- service.status = "Failed";
- service.tips = this.listSortMasters["operationTypes"].find((its) => {
- return its["sortCode"] == service.statusClass && its["language"] == this.language
- })["sortValue"] + this.listSortMasters["operationResults"].find((its) => {
- return its["sortCode"] == 2002 && its["language"] == this.language
- })["sortValue"];
- this.deleteSuccessNotification(templateDeleteSuccessFaild);
- return false;
- }
- console.log(service, "deleteservice");
- console.log(this.thisService, "thisService");
- let hasUndone = this.tableData.some((item) => {
- return item.rate < 100;
+ this.queryNsProgress(jobid, null, updata, operationType).then(() => {
+ let paramsObj = {
+ "ns_instance_id":id
+ };
+ this.myhttp.nsDeleteInstance(paramsObj)
+ .subscribe((data) => {
+ if(data.status == "SUCCESS"){
+ service.rate = 100;
+ service.status = "Successful";
+ service.tips = this.listSortMasters["operationTypes"].find((its) => {
+ return its["sortCode"] == service.statusClass && its["language"] == this.language
+ })["sortValue"] + this.listSortMasters["operationResults"].find((its) => {
+ return its["sortCode"] == 2001 && its["language"] == this.language
+ })["sortValue"];
+ this.notification1.notificationSuccess(service.serviceDomain,'deleteStarting',service["service-instance-name"] ||service["nsInstanceName"])
+ }else {
+ service.status = "Failed";
+ service.tips = this.listSortMasters["operationTypes"].find((its) => {
+ return its["sortCode"] == service.statusClass && its["language"] == this.language
+ })["sortValue"] + this.listSortMasters["operationResults"].find((its) => {
+ return its["sortCode"] == 2002 && its["language"] == this.language
+ })["sortValue"];
+ this.notification1.notificationFailed(service.serviceDomain,'deleteStarting',service["service-instance-name"] ||service["nsInstanceName"])
+ return false;
+ }
+ let hasUndone = this.tableData.some((item) => {
+ return item.rate < 100;
+ })
+ if (!hasUndone) {
+ setTimeout(() => {
+ this.getTableData();
+ }, 1000)
+ }
})
- if (!hasUndone) {
- setTimeout(() => {
- this.getTableData();
- }, 1000)
- }
- })
+ })
})
}
stopNsService(id, obj) {
- let mypromise = new Promise((res, rej) => {
- this.myhttp.stopNsService(id, obj)
+ let paramsObj = {
+ "ns_instance_id":id
+ }
+ return new Promise((res, rej) => {
+ this.myhttp.stopNsService(paramsObj, obj)
.subscribe((data) => {
this.loadingAnimateShow = false;
if (data.status == "FAILED") {
@@ -1275,87 +1084,77 @@ export class ServicesListComponent implements OnInit {
res(data.jobId);
})
})
- return mypromise;
}
queryProgress(obj, callback) {
- let mypromise = new Promise((res, rej) => {
+ return new Promise( res => {
+ let operationTypeObj = {operationType:obj.operationType};
let errorNums = 180;
- let requery = () => {
- this.myhttp.getProgress(obj)
+ let requeryCcvpn = () => {
+ this.myhttp.getProgress(obj,operationTypeObj)
.subscribe((data) => {
- if (data.status == "FAILED") {
+ if (data.status === "FAILED") {
callback({ progress: 255, status: "Failed" });
- return false;
- }
- if (data.operationStatus == null || data.operationStatus.progress == undefined) {
+ }else if (data.operationStatus === null || data.operationStatus.progress === undefined) {
errorNums--;
- if (errorNums == 0) {
+ if (errorNums === 0) {
callback({ progress: 255, status: "time over" });
return false;
}
- setTimeout(() => {
- requery();
- }, 10000)
- return false;
- }
- if (data.operationStatus.progress > 100) {
+ this.progressCcvpnOutTimer = setTimeout(()=>{
+ requeryCcvpn();
+ },10000);
+ }else if (data.operationStatus.progress > 100) {
callback({ progress: 255, status: "time over" });
- return false;
- }
- if (data.operationStatus.progress < 100) {
+ }else if (data.operationStatus.progress < 100) {
callback(data.operationStatus);
- setTimeout(() => {
- requery();
- }, 5000)
+ this.progressingCcvpnTimer = setTimeout(()=>{
+ requeryCcvpn();
+ },5000);
} else {
res(data.operationStatus);
}
})
}
- requery();
+ requeryCcvpn();
})
- return mypromise;
}
queryNsProgress(jobid, id, callback, operationType) {
- let mypromise = new Promise((res, rej) => {
+ return new Promise((res, rej) => {
let errorNums = 180;
- let requery = () => {
- this.myhttp.getNsProgress(jobid, id, operationType)
+ let paramsObj = {
+ "responseId":0,
+ "serviceInstanceId":id,
+ "operationType":operationType
+ }
+ let requeryNs = () => {
+ this.myhttp.getNsProgress(jobid,paramsObj)
.subscribe((data) => {
if (data.status == "FAILED") {
callback({ progress: 255, status: "Failed" });
- return false;
- }
- if (data.responseDescriptor == null || data.responseDescriptor.progress == undefined) {
+ }else if (data.responseDescriptor === null || data.responseDescriptor.progress === undefined) {
errorNums--;
- if (errorNums == 0) {
+ if (errorNums === 0) {
callback({ progress: 255, status: "time over" });
return false;
}
- setTimeout(() => {
- requery();
- }, 10000)
- return false;
- }
- if (data.responseDescriptor.progress > 100 && data.responseDescriptor.status == "error") {
+ this.progressNsOutTimer = setTimeout(()=>{
+ requeryNs();
+ },10000);
+ }else if (data.responseDescriptor.progress > 100 && data.responseDescriptor.status === "error") {
callback({ progress: 255, status: data.responseDescriptor.statusDescription });
- return false;
- }
- if (data.responseDescriptor.progress < 100) {
+ }else if (data.responseDescriptor.progress < 100) {
callback(data.responseDescriptor);
- setTimeout(() => {
- requery();
- }, 5000)
+ this.progressingNsTimer = setTimeout(()=>{
+ requeryNs();
+ },5000);
} else {
res(data);
}
})
};
- requery();
+ requeryNs();
});
- return mypromise;
}
-
}
diff --git a/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.html b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.html
new file mode 100644
index 00000000..98e42ae7
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.html
@@ -0,0 +1,18 @@
+<div class="top-list">
+ <span class="round">{{serviceDomain}}</span>
+ <div class="top-list-text">
+ <p>
+ <span>{{failedNum}}</span>
+ <span> {{"i18nTextDefine_Failed" | translate}} </span>
+ </p>
+ <p>
+ <span>{{successNum}}</span>
+ <span> {{"i18nTextDefine_Success" | translate}} </span>
+ </p>
+ <p>
+ <span>{{inProgressNum}}</span>
+ <span> {{"i18nTextDefine_InProgress" | translate}} </span>
+ </p>
+ <p class="service-description"> {{serviceDetailName | translate}} </p>
+ </div>
+</div> \ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.less b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.less
new file mode 100644
index 00000000..a235b1e6
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.less
@@ -0,0 +1,65 @@
+.top-list{
+ position: relative;
+ width:100%;
+ max-width:400px;
+ height:170px;
+ background:url("/assets/images/servicelist-e2e.png") no-repeat;
+ background-size: 100% 100%;
+ border-radius:2px;
+ .round{
+ position: absolute;
+ width: 60px;
+ height: 60px;
+ line-height: 60px;
+ text-align: center;
+ background:#E0EDFF;
+ border:2px solid rgba(224,237,255,1);
+ border-radius: 50%;
+ font-size:16px;
+ font-family:ArialMT;
+ color:#3C4F8C;
+ transition: .5s;
+ top: 42%;
+ margin-top: -30px;
+ left: 15%;
+ }
+ .top-list-text{
+ position: absolute;
+ text-align: right;
+ line-height: 20px;
+ right: 12%;
+ color: #fff;
+ p{
+ height: 28px;
+ margin-bottom: 0;
+ padding-left: 5px;
+ font-size: 14px;
+ clear: both;
+ span{
+ display: inline-block;
+ float: right;
+ font-weight: 500;
+ text-align: right;
+ }
+ span:nth-child(1){
+ font-size: 18px;
+ margin-left: 15px;
+ }
+ span:nth-child(2){
+ width: 85px;
+ font-size: 16px;
+ }
+ }
+ p:nth-child(1){
+ margin-top: 25px;
+ }
+ .service-description{
+
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ color: #3C4F8C;
+
+ }
+ }
+} \ No newline at end of file
diff --git a/usecaseui-portal/src/app/views/services/services.component.spec.ts b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.spec.ts
index 2e76b9f9..b2d2cbb4 100644
--- a/usecaseui-portal/src/app/views/services/services.component.spec.ts
+++ b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.spec.ts
@@ -1,20 +1,20 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-import { ServicesComponent } from './services.component';
+import { TopCardComponent } from './top-card.component';
-describe('ServicesComponent', () => {
- let component: ServicesComponent;
- let fixture: ComponentFixture<ServicesComponent>;
+describe('TopCardComponent', () => {
+ let component: TopCardComponent;
+ let fixture: ComponentFixture<TopCardComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
- declarations: [ ServicesComponent ]
+ declarations: [ TopCardComponent ]
})
.compileComponents();
}));
beforeEach(() => {
- fixture = TestBed.createComponent(ServicesComponent);
+ fixture = TestBed.createComponent(TopCardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
diff --git a/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.ts b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.ts
new file mode 100644
index 00000000..6004fb8e
--- /dev/null
+++ b/usecaseui-portal/src/app/views/services/services-list/top-card/top-card.component.ts
@@ -0,0 +1,19 @@
+import { Component, OnInit, Input } from '@angular/core';
+
+@Component({
+ selector: 'app-top-card',
+ templateUrl: './top-card.component.html',
+ styleUrls: ['./top-card.component.less']
+})
+export class TopCardComponent implements OnInit {
+ @Input() serviceDomain: string;
+ @Input() failedNum: number;
+ @Input() successNum: number;
+ @Input() inProgressNum: number;
+ @Input() serviceDetailName: string;
+ constructor() { }
+
+ ngOnInit() {
+ }
+
+}
diff --git a/usecaseui-portal/src/app/views/services/services.component.html b/usecaseui-portal/src/app/views/services/services.component.html
deleted file mode 100644
index 10142833..00000000
--- a/usecaseui-portal/src/app/views/services/services.component.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!--
- Copyright (C) 2019 CMCC, Inc. and others. All rights reserved.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<p>
- services works!
-</p>
diff --git a/usecaseui-portal/src/app/views/services/services.component.ts b/usecaseui-portal/src/app/views/services/services.component.ts
deleted file mode 100644
index eec235b4..00000000
--- a/usecaseui-portal/src/app/views/services/services.component.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-
-@Component({
- selector: 'app-services',
- templateUrl: './services.component.html',
- styleUrls: ['./services.component.less']
-})
-export class ServicesComponent implements OnInit {
-
- constructor() { }
-
- ngOnInit() {
- }
-
-}