aboutsummaryrefslogtreecommitdiffstats
path: root/vid-webpack-master/src/app/instantiationStatus
diff options
context:
space:
mode:
Diffstat (limited to 'vid-webpack-master/src/app/instantiationStatus')
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.module.ts9
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.routing.ts19
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.html84
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.scss159
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.service.ts0
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.ts83
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html60
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts118
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts136
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts251
-rw-r--r--vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts170
11 files changed, 585 insertions, 504 deletions
diff --git a/vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.module.ts b/vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.module.ts
index 01db0f187..6d14b149d 100644
--- a/vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.module.ts
+++ b/vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.module.ts
@@ -1,33 +1,30 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-import { InputsModule } from '../modules/inputs.module';
import { DataTableModule } from 'angular2-datatable';
import { BootstrapModalModule } from 'ng2-bootstrap-modal';
import { TooltipModule } from 'ngx-tooltip';
import { InstantiationStatusComponent } from './instantiationStatus.component';
import { InstantiationStatusComponentService } from './instantiationStatus.component.service';
import { SharedModule } from '../shared/shared.module';
-import { AngularSvgIconModule } from 'angular-svg-icon';
import { ContextMenuModule, ContextMenuService } from 'ngx-contextmenu';
import {ModalModule, PopoverModule} from 'ngx-bootstrap';
-import {AuditInfoModalComponent} from "./auditInfoModal/auditInfoModal.component";
+import {SdcUiComponentsModule} from "onap-ui-angular";
@NgModule({
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
+ SdcUiComponentsModule,
BootstrapModalModule,
DataTableModule,
TooltipModule,
ModalModule,
- InputsModule,
- AngularSvgIconModule,
ContextMenuModule,
SharedModule.forRoot(),
PopoverModule.forRoot()],
- declarations: [InstantiationStatusComponent, AuditInfoModalComponent],
+ declarations: [InstantiationStatusComponent, ],
providers: [InstantiationStatusComponentService, ContextMenuService]
})
export class InstantiationStatusModule { }
diff --git a/vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.routing.ts b/vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.routing.ts
new file mode 100644
index 000000000..6991eefef
--- /dev/null
+++ b/vid-webpack-master/src/app/instantiationStatus/InstantiationStatus.routing.ts
@@ -0,0 +1,19 @@
+import {Route} from "@angular/router";
+import {FlagsResolve} from "../shared/resolvers/flag/flag.resolver";
+import {InstantiationStatusComponent} from "./instantiationStatus.component";
+
+export const InstantiationStatusRoutes: Route[] = [
+ {
+ path: 'instantiationStatus',
+ children: [
+ {
+ path: '',
+ component: InstantiationStatusComponent,
+ resolve: {
+ flags: FlagsResolve
+ },
+ }
+ ]
+ }
+];
+
diff --git a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.html b/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.html
deleted file mode 100644
index 9386af347..000000000
--- a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<div class="modal fade" bsModal #auditInfoModal="bs-modal" [config]="{backdrop: 'static'}"
- tabindex="-1" role="dialog" aria-labelledby="dialog-static-name">
- <div id="audit-info-modal" class="">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" (click)="onCancelClick()">&times;</button>
- <span [attr.data-tests-id]="'audit-info-title'" class="modal-title">{{title}}</span>
- </div>
- <div class="modal-body row">
- <div class="col-md-4 left-panel">
- <div id="service-model-name" class="row">SERVICE MODEL: {{serviceModelName}}</div>
- <div class="row service-model">
- <model-information [modelInformationItems]="modelInfoItems"></model-information>
- </div>
- </div>
- <div class="col-md-8 right-panel">
- <div class="row"><span class="table-title">VID status</span></div>
- <div class="row">
- <table id="service-instantiation-audit-info-vid" class="table table-bordered">
- <thead class="thead-dark">
- <tr class="row">
- <th class="col-md-4" scope="col">Status</th>
- <th class="col-md-4" scope="col">Status time</th>
- <th class="col-md-4" scope="col">Final</th>
- </tr>
- </thead>
- <tbody>
- <tr class="row" *ngFor="let data of vidInfoData">
- <td class="col-md-4" id="vidJobStatus" [attr.data-tests-id]="'vidJobStatus'">
- <custom-ellipsis [id]="data?.jobStatus" [value]="data?.jobStatus | capitalizeAndFormat"></custom-ellipsis>
- </td>
- <td class="col-md-4" id="vidStatusTime">
- <custom-ellipsis [id]="data?.vidCreated"
- [value]="data?.createdDate | date:'MMM dd, yyyy HH:mm'"></custom-ellipsis>
- </td>
- <td class="col-md-4" id="vidFinalStatus">
- <custom-ellipsis [id]="data?.final"
- [value]="data?.final ? 'Yes' : 'No'"></custom-ellipsis>
- </td>
- </tr>
- </tbody>
- </table>
- <div class="no-result" *ngIf="!isLoading && vidInfoData?.length == 0">There is no data.</div>
- </div>
-
- <div class="row"><span class="table-title">MSO status</span></div>
- <table id="service-instantiation-audit-info-mso" class="table table-bordered">
- <thead class="thead-dark row">
- <tr class="row">
- <th class="col-md-3" scope="col">Request ID</th>
- <th class="col-md-3" scope="col">Status</th>
- <th class="col-md-3" scope="col">Status time</th>
- <th class="col-md-3" scope="col">Additional info</th>
- </tr>
- </thead>
- <tbody>
- <tr class="row" *ngFor="let data of msoInfoData">
- <td class="col-md-3" id="msoRequestId">
- <custom-ellipsis [id]="data?.requestId" [value]="data?.requestId"></custom-ellipsis>
- </td>
- <td class="col-md-3" id="msoJobStatus">
- <custom-ellipsis [id]="data?.jobStatus" [value]="data?.jobStatus | capitalizeAndFormat"></custom-ellipsis>
- </td>
- <td class="col-md-3" id="msoStatusTime">
- <custom-ellipsis [id]="data?.vidCreated"
- [value]="data?.createdDate | date:'MMM dd, yyyy HH:mm'"></custom-ellipsis>
- </td>
- <td class="col-md-3" id="msoAdditionalInfo">
- <custom-ellipsis [id]="data?.additionalInfo" [value]="data?.additionalInfo"></custom-ellipsis>
- </td>
- </tr>
- </tbody>
- </table>
- <div class="no-result" *ngIf="!isLoading && msoInfoData?.length == 0">There is no data.</div>
- </div>
- </div>
- <div class="modal-footer row">
- <button id="cancelButton" type="button" class="btn btn-default cancel" (click)="onCancelClick()">
- Close
- </button>
- </div>
- </div>
- </div>
-</div>
diff --git a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.scss b/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.scss
deleted file mode 100644
index 27b271496..000000000
--- a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.scss
+++ /dev/null
@@ -1,159 +0,0 @@
-.templatebody.modal-open{
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 1040;
- background-color: #000;
- opacity: 0.5;
-}
-.modal{
-
- #audit-info-modal {
-
- .modal-content{
- border-radius: 0px;
- border: none;
- .modal-header{
- background: #009FDB;
- font-size: 24px;
- color: #ffffff;
- .close{
- font-size: 32px;
- font-weight: 200;
- color: #ffffff;
- text-shadow: none;
- filter: none;
- opacity: 1;
- &:hover{
- color: #d2d2d2;
- }
- }
- .modal-title{
-
- }
- }
- .modal-body{
- padding: 0px;
- margin: 0px;
- display: flex;
- .left-panel{
- background: #f2f2f2;
- border-right: 1px solid #D2D2D2;
- padding-right: 0px;
- .row:first-child{
- border-bottom: 1px solid #D2D2D2;
- height: 50px;
- font-size: 12px;
- line-height: 50px;
- padding-left: 30px;
- font-weight: 700;
- margin-right: 0px;
- }
- .service-model{
- padding-left: 30px;
- padding-top: 15px;
- }
- }
- .right-panel{
- padding: 30px 30px 15px 30px;
- .row{
- margin: 0px;
- }
- .table-title{
- font-size: 12px;
- text-transform: uppercase;
- font-weight: bold;
- }
- .no-result{
- margin-bottom: 20px;
- text-align: center;
- border: 1px solid #d2d2d2;
- padding: 20px;
- margin-top: -23px;
- }
-
- .table-bordered{
- width: 100%;
- margin-top: 10px;
- font-family: OpenSans-Semibold;
- font-size: 12px;
- overflow-x: auto;
- display: block;
- color: #5A5A5A;
-
- thead {
- position: sticky;
- top: 0;
- z-index: 100;
- display: block;
- background: rgb(242, 242, 242);
- border-bottom: 1px solid #d2d2d2;
- tr {
- display: flex;
- th {
- flex-grow: 1;
- border-right: 1px solid #d2d2d2;
- &:last-child{
- border-right: none;
- }
- }
- }
- }
-
- tbody {
- border: none !important;
- max-height: 152px;
- display: block;
-
- tr {
- display: flex;
- border-bottom: 1px solid #d2d2d2;
- &:last-child{
- border-bottom: none;
- }
- td {
- border: none;
- border-right: 1px solid #d2d2d2;
- &:last-child{
- border-right: none;
- }
- }
- }
- }
-
- th {
- background: #f2f2f2;
- font-family: OpenSans-Semibold;
- color: #000000;
- font-weight: bold;
- border: none;
- }
-
- tr.odd {
- background-color: rgb(242, 242, 242);
- }
-
- tr:hover {
- background: #e1e1e1;
- }
- }
- }
- }
- .modal-footer{
- margin: 0px;
- .cancel{
- width: 120px;
- height: 36px;
- background: #009fdb;
- border-radius: 2px;
- font-family: OpenSans-Regular;
- font-size: 14px;
- color: #ffffff;
- line-height: 16px;
- }
- }
- }
- }
-}
diff --git a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.service.ts b/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.service.ts
deleted file mode 100644
index e69de29bb..000000000
--- a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.service.ts
+++ /dev/null
diff --git a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.ts b/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.ts
deleted file mode 100644
index 1cff97f5b..000000000
--- a/vid-webpack-master/src/app/instantiationStatus/auditInfoModal/auditInfoModal.component.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import {Component, ViewChild} from '@angular/core';
-import {Subject} from 'rxjs/Subject';
-import {ModalDirective} from 'ngx-bootstrap'
-import {Constants} from '../../shared/utils/constants';
-import {ModelInformationItem} from '../../shared/components/model-information/model-information.component';
-import {ServiceModel} from '../../shared/models/serviceModel';
-import {ServiceInfoService} from '../../shared/server/serviceInfo/serviceInfo.service';
-import {ServiceInfoModel} from '../../shared/server/serviceInfo/serviceInfo.model';
-import {AuditStatus} from '../../shared/server/serviceInfo/AuditStatus.model';
-import {IframeService} from "../../shared/utils/iframe.service";
-
-@Component({
- selector: 'audit-info-modal',
- templateUrl: './auditInfoModal.component.html',
- styleUrls: ['./auditInfoModal.component.scss']
-})
-export class AuditInfoModalComponent {
- static openModal: Subject<ServiceInfoModel> = new Subject<ServiceInfoModel>();
- @ViewChild('auditInfoModal') public auditInfoModal: ModalDirective;
- title: string = Constants.AuditInfoModal.TITLE;
- modelInfoItems: Array<ModelInformationItem> = [];
- serviceModel: ServiceModel;
- serviceModelName: string;
- vidInfoData: Array<AuditStatus> = [];
- msoInfoData: Array<AuditStatus> = [];
- parentElementClassName = 'content';
- isLoading = true;
-
- constructor(private _serviceInfoService: ServiceInfoService, private _iframeService : IframeService) {
- AuditInfoModalComponent.openModal.subscribe((jobData: ServiceInfoModel) => {
- this.initializeProperties();
- if (jobData) {
- this.openAuditInfoModal(jobData);
- _iframeService.addClassOpenModal(this.parentElementClassName);
- this.serviceModelName = jobData.serviceModelName ? jobData.serviceModelName : '';
- this.auditInfoModal.show();
- } else {
- _iframeService.removeClassCloseModal(this.parentElementClassName);
- this.auditInfoModal.hide();
- }
- })
- }
-
- initializeProperties() : void {
- this.modelInfoItems = null;
- this.vidInfoData = [];
- this.msoInfoData = [];
- this.isLoading = true;
- }
-
- openAuditInfoModal(jobData: ServiceInfoModel): void {
- this.modelInfoItems = this.createModelInformationItems(jobData);
- this.initAuditInfoData(jobData['jobId']);
- this.auditInfoModal.show();
- }
-
- initAuditInfoData(jobId: string) {
- this._serviceInfoService.getJobAuditStatus(jobId)
- .subscribe((res: Array<Array<AuditStatus>>) => {
- this.vidInfoData = res[0];
- this.msoInfoData = res[1];
- this.isLoading = false;
- });
- }
-
- createModelInformationItems(serviceModel: ServiceInfoModel): Array<ModelInformationItem> {
- return [
- new ModelInformationItem('Subscriber name', 'subscriberName', [serviceModel.subscriberName]),
- new ModelInformationItem('Service type', 'serviceType', [serviceModel.serviceType]),
- new ModelInformationItem('Service model version', 'serviceModelVersion', [serviceModel.serviceModelVersion]),
- new ModelInformationItem('Service instance name', 'serviceInstanceName', [serviceModel.serviceInstanceName], '', true),
- new ModelInformationItem('Service instance ID', 'serviceInstanceId', [serviceModel.serviceInstanceId]),
- new ModelInformationItem('Requestor User ID', 'userId', [serviceModel.userId]),
- ];
- }
-
- onCancelClick() {
- this._iframeService.removeClassCloseModal(this.parentElementClassName);
- this.initializeProperties();
- this.auditInfoModal.hide();
- }
-}
-
diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html
index e0641d03b..212981aaf 100644
--- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html
+++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html
@@ -3,7 +3,7 @@
<div>
<div class="row" style="margin-left: 0;">
<div>
- <span class="title">Instantiation Status</span>
+ <span class="title" [attr.data-tests-id]="'instantiation-status-title'">Instantiation Status</span>
<span class="icon-info"
triggers="mouseenter:mouseleave"
popover="This table presents all the instantiation requests you made that are waiting, during or finished instantiating. You may see others requests by removing the Show only my requests checkmark."
@@ -24,6 +24,7 @@
<thead class="thead-dark">
<tr>
<th scope="col" class="smallTd">User ID</th>
+ <th scope="col" class="smallTd">Action</th>
<th scope="col" class="normal">Model Name</th>
<th scope="col" class="normal">Instance Name</th>
<th scope="col" class="smallTd">Model version</th>
@@ -40,8 +41,9 @@
</tr>
</thead>
<tbody >
- <tr *ngFor="let data of serviceInfoData; let i = index" [ngClass]="{'odd' : data.serviceIndex%2 == 1}" [id]="data.jobId" (mouseenter)="currentJobId = data?.jobId">
+ <tr *ngFor="let data of serviceInfoData; trackBy: trackByFn; let i = index" [ngClass]="{'odd' : data.serviceIndex%2 == 1}" [id]="data.jobId">
<td class="smallTd" id="userId"><custom-ellipsis [id]="data.userId" [value]="data.userId"></custom-ellipsis></td>
+ <td class="smallTd" id="action"><custom-ellipsis [id]="data.action" [value]="data.action | capitalizeAndFormat"></custom-ellipsis></td>
<td class="normal" id="serviceModelName"><custom-ellipsis [id]="data.serviceModelName" [value]="data.serviceModelName"></custom-ellipsis></td>
<td class="normal" id="serviceInstanceName"><custom-ellipsis [id]="data.serviceInstanceName" [value]="data.serviceInstanceName"></custom-ellipsis></td>
<td class="smallTd" id="serviceModelVersion"><custom-ellipsis [id]="data.serviceModelVersion" [value]="data.serviceModelVersion"></custom-ellipsis></td>
@@ -55,37 +57,32 @@
<td class="smallTd" id="pause"><custom-ellipsis [id]="data.pause" [value]="data.pause"></custom-ellipsis></td>
<td class="mediumTd" id="created"><custom-ellipsis [id]="data.created" [value]="data.created | date:'MMM. dd, yyyy HH:mm'"></custom-ellipsis></td>
<td class="last" id="jobStatus" [ngClass]="data.jobStatus">
- <custom-popover [value]="data.serviceStatus.tooltip" style="float: left;">
- <svg-icon id="jobStatusIcon-{{i}}" (click)="auditInfo(data)" svg-directive [fill]="data.serviceStatus.color" [widthViewBox]="27" [heightViewBox]="27"
- src="./assets/img/{{data.serviceStatus.iconClassName}}.svg"></svg-icon>
+ <custom-popover [value]="data.serviceStatus.tooltip" [popoverType]="data?.serviceStatus?.color" style="float: left;">
+ <svg-icon
+ id="jobStatusIcon-{{i}}"
+ (click)="auditInfo(data)"
+ [mode]="data.serviceStatus.color"
+ [size]="'large'"
+ [name]="data.serviceStatus.iconClassName">
+ </svg-icon>
+
</custom-popover>
- <div class="menu-div" (click)="onContextMenu($event, data); currentJobId = data.jobId">
+ <div class="menu-div" (click)="onContextMenu($event, data)">
<span class="icon-menu"></span>
- <context-menu>
- <ng-template contextMenuItem (execute)="open($event?.item)" [enabled]="isOpenVisible">
- <div [attr.data-tests-id]="'context-menu-open'">
- <span class="context-menu-icon"><i class="fa fa-external-link" aria-hidden="true"></i></span>
- Open
- </div>
- </ng-template>
- <ng-template contextMenuItem (execute)="auditInfo($event?.item)">
- <div [attr.data-tests-id]="'context-menu-audit-info'">
- <span class="context-menu-icon audit-icon"><i class="fa fa-info-circle" aria-hidden="true"></i></span>
- Audit info
- </div>
- </ng-template>
- <ng-template contextMenuItem let-item (execute)="deleteItem($event?.item)" [enabled]="isDeleteEnabled">
- <div [attr.data-tests-id]="'context-menu-delete'">
- <span class="context-menu-icon"><i class="fa fa-trash-o" aria-hidden="true"></i></span>
- Delete
- </div>
- </ng-template>
- <ng-template contextMenuItem let-item (execute)="hideItem($event?.item)" [enabled]="isHideEnabled">
- <div [attr.data-tests-id]="'context-menu-hide'">
- <span class="context-menu-icon"><i class="fa fa-eye-slash" aria-hidden="true"></i></span>
- Hide request
- </div>
- </ng-template>
+ <context-menu>
+ <ng-template *ngFor="let action of contextMenuActions" contextMenuItem let-item
+ [visible]="action.visible"
+ [enabled]="action.enabled"
+ (execute)="action.click($event.item)">
+ <div [attr.data-tests-id]="action.dataTestId"
+ [tooltip]="action?.tooltip"
+ [tooltipDisabled]="!action.tooltip">
+ <span class="context-menu-icon">
+ <i class="fa {{action.className}}" aria-hidden="true"></i>
+ </span>
+ {{action.name}}
+ </div>
+ </ng-template>
</context-menu>
</div>
</td>
@@ -93,7 +90,6 @@
</tbody>
</table>
</div>
- <audit-info-modal></audit-info-modal>
</div>
diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts
index c9f434e99..4848d8e99 100644
--- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts
+++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts
@@ -1,5 +1,6 @@
import {getTestBed, TestBed} from '@angular/core/testing';
import {
+ COMPLETED_WITH_ERRORS,
INPROGRESS,
InstantiationStatusComponentService,
PAUSE,
@@ -10,24 +11,64 @@ import {
X_O
} from './instantiationStatus.component.service';
import {ServiceInfoModel} from '../shared/server/serviceInfo/serviceInfo.model';
-import { Observable } from 'rxjs/Rx';
+import {AaiService} from "../shared/services/aaiService/aai.service";
+import {MsoService} from "../shared/services/msoService/mso.service";
+import {NgRedux} from "@angular-redux/store";
+import {HttpClientTestingModule} from "@angular/common/http/testing";
+import {FeatureFlagsService} from "../shared/services/featureFlag/feature-flags.service";
+import {DrawingBoardModes} from "../drawingBoard/service-planning/drawing-board.modes";
+import {RouterTestingModule} from "@angular/router/testing";
+import {of} from "rxjs";
+import {UrlTree} from "@angular/router";
+class MockAppStore<T> {
+
+ getState() {
+ return {
+ global: {
+ flags: {
+ 'FLAG_1902_NEW_VIEW_EDIT': true,
+
+ }
+ }
+ }
+ }
+
+ dispatch() {
+
+ }
+}
describe('Instantiation Status Service', () => {
let injector;
+ let aaiService: AaiService;
+ let msoService: MsoService;
let service: InstantiationStatusComponentService;
- beforeEach(() => {
+
+ beforeAll(done => (async () => {
TestBed.configureTestingModule({
- imports: [],
- providers: [InstantiationStatusComponentService]
+ imports: [
+ HttpClientTestingModule,
+ RouterTestingModule,
+ ],
+ providers: [
+ InstantiationStatusComponentService,
+ AaiService,
+ MsoService,
+ FeatureFlagsService,
+ {provide: NgRedux, useClass: MockAppStore}]
});
+ await TestBed.compileComponents();
injector = getTestBed();
+ aaiService = injector.get(AaiService);
+ msoService = injector.get(MsoService);
service = injector.get(InstantiationStatusComponentService);
- });
- it('generateServiceInfoDataMapping should return mapping of arrays', (done: DoneFn) => {
- let data : Array<ServiceInfoModel> = generateServiceInfoData();
+ })().then(done).catch(done.fail));
+
+ test('generateServiceInfoDataMapping should return mapping of arrays', () => {
+ let data : ServiceInfoModel[] = generateServiceInfoData();
let result = service.generateServiceInfoDataMapping(data);
expect(result['1']).toBeDefined();
@@ -37,53 +78,81 @@ describe('Instantiation Status Service', () => {
expect(result['1'].length).toEqual(2);
expect(result['2'].length).toEqual(2);
expect(result['3'].length).toEqual(1);
- done();
});
- it('generateServiceInfoDataMapping if array is empty should return empty object', (done: DoneFn) => {
+ test('generateServiceInfoDataMapping if array is empty should return empty object', () => {
let result = service.generateServiceInfoDataMapping([]);
expect(result['1']).not.toBeDefined();
expect(result['2']).not.toBeDefined();
expect(result['3']).not.toBeDefined();
- done();
});
- it('convertObjectToArray', (done: DoneFn) => {
+ test('convertObjectToArray', () => {
- spyOn(service, 'convertObjectToArray').and.returnValue(
- Observable.of([])
+ jest.spyOn(service, 'convertObjectToArray').mockReturnValue(
+ of([])
);
- let data : Array<ServiceInfoModel> = generateServiceInfoData();
+ let data : ServiceInfoModel[] = generateServiceInfoData();
service.convertObjectToArray(data).subscribe((result) => {
expect(result).toBeDefined();
- done();
});
});
- it('getStatusTooltip should return status popover', (done: DoneFn) => {
+ test('click on "Open" button should open new view edit' , ()=>{
+ const item = {
+ serviceModelId : 'serviceModelId',
+ serviceInstanceId : 'serviceInstanceId',
+ serviceType : 'serviceType',
+ subscriberId : 'subscriberId'
+ };
+ let params:UrlTree = service.getNewViewEditUrlTree(item, DrawingBoardModes.VIEW);
+ expect(params.toString().startsWith('/servicePlanning/VIEW')).toBeTruthy();
+ expect(params.queryParams).toEqual(
+ {
+ serviceModelId: item.serviceModelId,
+ serviceInstanceId: item.serviceInstanceId,
+ serviceType : item.serviceType,
+ subscriberId : item.subscriberId
+ });
+ });
+
+ test('build the View Edit url' , ()=>{
+ const item = {
+ serviceModelId : '28aeb8f6-5620-4148-8bfb-a5fb406f0309',
+ };
+ let serviceModelUrl: string = '/servicePlanning/EDIT?serviceModelId=28aeb8f6-5620-4148-8bfb-a5fb406f0309';
+ let suffix:string = '../../serviceModels.htm#';
+ let tree:UrlTree = service.getNewViewEditUrlTree(item, DrawingBoardModes.EDIT);
+ let result = service.getViewEditUrl(tree);
+ expect (suffix + serviceModelUrl).toEqual(result);
+ });
+
+ test('getStatusTooltip should return status popover', () => {
let result : ServiceStatus = service.getStatus('pending');
- expect(result.tooltip).toEqual('Pending: The service will automatically be sent for instantiation as soon as possible.');
+ expect(result.tooltip).toEqual('Pending: The action required will be sent as soon as possible.');
result = service.getStatus('IN_PROGRESS');
- expect(result.tooltip).toEqual('In-progress: the service is in process of instantiation.');
+ expect(result.tooltip).toEqual('In-progress: the service is in process of the action required.');
result = service.getStatus('PAUSED');
expect(result.tooltip).toEqual('Paused: Service has paused and waiting for your action.\n Select actions from the menu to the right.');
result = service.getStatus('FAILED');
- expect(result.tooltip).toEqual('Failed: Service instantiation has failed, load the service to see the error returned.');
+ expect(result.tooltip).toEqual('Failed: All planned actions have failed.');
result = service.getStatus('COMPLETED');
- expect(result.tooltip).toEqual('Completed successfully: Service is successfully instantiated.');
+ expect(result.tooltip).toEqual('Completed successfully: Service is successfully instantiated, updated or deleted.');
result = service.getStatus('STOPPED');
expect(result.tooltip).toEqual('Stopped: Due to previous failure, will not be instantiated.');
- done();
+
+ result = service.getStatus('COMPLETED_WITH_ERRORS');
+ expect(result.tooltip).toEqual('Completed with errors: some of the planned actions where successfully committed while other have not.\n Open the service to check it out.');
});
- it('getStatusTooltip should return correct icon per job status', (done: DoneFn) => {
+ test('getStatusTooltip should return correct icon per job status', () => {
let result : ServiceStatus = service.getStatus('pending');
expect(result.iconClassName).toEqual(PENDING);
@@ -101,9 +170,10 @@ describe('Instantiation Status Service', () => {
result = service.getStatus('STOPPED');
expect(result.iconClassName).toEqual(STOPED);
- done();
- });
+ result = service.getStatus('COMPLETED_WITH_ERRORS');
+ expect(result.iconClassName).toEqual(COMPLETED_WITH_ERRORS);
+ });
function generateServiceInfoData(){
return JSON.parse(JSON.stringify([
diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts
index 293397cc9..0e4451ca8 100644
--- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts
+++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts
@@ -1,23 +1,38 @@
import {Injectable} from '@angular/core';
import {ServiceInfoModel, ServiceInfoUiModel} from '../shared/server/serviceInfo/serviceInfo.model';
-import {isNullOrUndefined} from "util";
-import { Observable } from 'rxjs/Observable';
-import 'rxjs/observable/of';
-
+import * as _ from 'lodash';
+import {Observable} from 'rxjs/Observable';
+import {NgRedux} from "@angular-redux/store";
+import {AppState} from "../shared/store/reducers";
+import {AaiService} from "../shared/services/aaiService/aai.service";
+import {ServiceModel} from "../shared/models/serviceModel";
+import {FeatureFlagsService, Features} from "../shared/services/featureFlag/feature-flags.service";
+import {DrawingBoardModes} from "../drawingBoard/service-planning/drawing-board.modes";
+import {updateDrawingBoardStatus} from "../shared/storeUtil/utils/global/global.actions";
+import {Router, UrlTree} from "@angular/router";
+import {of} from "rxjs";
+import {MsoService} from "../shared/services/msoService/mso.service";
export let PENDING : string = "pending";
-export let INPROGRESS : string = "inprogress";
+export let INPROGRESS : string = "in_progress";
export let PAUSE : string = "pause";
-export let X_O : string = "X_o";
-export let SUCCESS_CIRCLE : string = "success+Circle";
-export let STOPED : string = "stoped";
+export let X_O : string = "x-circle-o";
+export let SUCCESS_CIRCLE : string = "success-circle-o";
+export let STOPED : string = "stop";
+export let COMPLETED_WITH_ERRORS : string = "success_with_warning";
@Injectable()
export class InstantiationStatusComponentService {
- generateServiceInfoDataMapping(arr: Array<ServiceInfoModel>) : { [serviceInstanceId: string]: Array<ServiceInfoModel>}{
- let serviceInfoData: { [serviceInstanceId: string]: Array<ServiceInfoModel>; } = {};
+ constructor( private _aaiService: AaiService,
+ private _msoService: MsoService,
+ private _router : Router,
+ private _store: NgRedux<AppState>) {
+ }
+
+ generateServiceInfoDataMapping(arr: ServiceInfoModel[]) : { [serviceInstanceId: string]: ServiceInfoModel[]}{
+ let serviceInfoData: { [serviceInstanceId: string]: ServiceInfoModel[]; } = {};
for(let item of arr){
- if(isNullOrUndefined(serviceInfoData[item.templateId])){
+ if(_.isNil(serviceInfoData[item.templateId])){
serviceInfoData[item.templateId] = [item];
}else {
serviceInfoData[item.templateId].push(item);
@@ -26,7 +41,7 @@ export class InstantiationStatusComponentService {
return serviceInfoData;
}
- convertObjectToArray(arr: Array<ServiceInfoModel>) : Observable<Array<ServiceInfoUiModel>>{
+ convertObjectToArray(arr: ServiceInfoModel[]) : Observable<ServiceInfoUiModel[]>{
const obj = this.generateServiceInfoDataMapping(arr);
let index:number = 0;
let result = [];
@@ -40,25 +55,108 @@ export class InstantiationStatusComponentService {
}
console.log(result);
- return Observable.of(result);
+ return of(result);
+ }
+
+ isDrawingBoardViewEdit(serviceModel: ServiceModel): boolean {
+ if (!_.isNil(serviceModel.vidNotions) && !_.isNil(serviceModel.vidNotions.viewEditUI)
+ && serviceModel.vidNotions.viewEditUI !== 'legacy'){
+ return true;
+ }
+ return false;
+ }
+
+ open(item: ServiceInfoModel): void {
+ if (FeatureFlagsService.getFlagState(Features.FLAG_1902_VNF_GROUPING, this._store)) {
+ this._aaiService.getServiceModelById(item['serviceModelId']).subscribe((result)=>{
+ const serviceModel = new ServiceModel(result);
+
+ if (this.isDrawingBoardViewEdit(serviceModel)) {
+ this.navigateToNewViewEdit(item, DrawingBoardModes.EDIT);
+ return;
+ }
+
+ this.navigateToNewViewOnlyOrOldEditView(item);
+
+ });
+ }
+
+ /*this else is here only to save time in case we don't need to retrieve service model
+ it can be removed once it service model is always needed, and it doesn't save time*/
+ else {
+ this.navigateToNewViewOnlyOrOldEditView(item);
+ }
+ }
+
+ navigateToNewViewOnlyOrOldEditView(item: ServiceInfoModel) {
+ if (FeatureFlagsService.getFlagState(Features.FLAG_1902_NEW_VIEW_EDIT, this._store)) {
+ this.navigateToNewViewEdit(item, DrawingBoardModes.VIEW);
+ }
+ else {
+ this.navigateToOldViewEdit(item);
+ }
+ }
+
+ navigateToOldViewEdit(item: ServiceInfoModel) {
+ let query =
+ `subscriberId=${item.subscriberId}&` +
+ `subscriberName=${item.subscriberName}&` +
+ `serviceType=${item.serviceType}&` +
+ `serviceInstanceId=${item.serviceInstanceId}`;
+
+ this._store.dispatch(updateDrawingBoardStatus(DrawingBoardModes.OLD_VIEW_EDIT));
+ window.parent.location.assign('../../serviceModels.htm#/instantiate?' + query);
+ }
+
+ navigateToNewViewEdit(item: ServiceInfoModel, mode: DrawingBoardModes): void{
+ this._store.dispatch(updateDrawingBoardStatus(mode));
+ const viewEditUrlTree:UrlTree = this.getNewViewEditUrlTree(item, mode);
+ this._router.navigateByUrl(viewEditUrlTree);
+ window.parent.location.assign(this.getViewEditUrl(viewEditUrlTree));
+ }
+
+ getNewViewEditUrlTree(item: ServiceInfoModel, mode: DrawingBoardModes): UrlTree {
+ return this._router.createUrlTree(
+ ['/servicePlanning/' + mode],
+ {
+ queryParams:
+ {
+ serviceModelId: item.serviceModelId,
+ serviceInstanceId: item.serviceInstanceId,
+ serviceType : item.serviceType,
+ subscriberId : item.subscriberId,
+ jobId: item.jobId
+ }
+ });
+ }
+
+ getViewEditUrl(viewEditUrlTree:UrlTree): string {
+ return '../../serviceModels.htm#' + viewEditUrlTree.toString();
+
}
getStatus(status : string) : ServiceStatus {
switch(status.toUpperCase()) {
case 'PENDING' :
- return new ServiceStatus(PENDING, '#009FDB', 'Pending: The service will automatically be sent for instantiation as soon as possible.');
+ return new ServiceStatus(PENDING, 'primary', 'Pending: The action required will be sent as soon as possible.');
case 'IN_PROGRESS' :
- return new ServiceStatus(INPROGRESS, '#009FDB', 'In-progress: the service is in process of instantiation.');
+ return new ServiceStatus(INPROGRESS, 'primary', 'In-progress: the service is in process of the action required.');
case 'PAUSED' :
- return new ServiceStatus(PAUSE, '#009FDB', 'Paused: Service has paused and waiting for your action.\n Select actions from the menu to the right.');
+ return new ServiceStatus(PAUSE, 'primary', 'Paused: Service has paused and waiting for your action.\n Select actions from the menu to the right.');
case 'FAILED' :
- return new ServiceStatus(X_O, '#D02B2B', 'Failed: Service instantiation has failed, load the service to see the error returned.');
+ return new ServiceStatus(X_O, 'error', 'Failed: All planned actions have failed.');
case 'COMPLETED' :
- return new ServiceStatus(SUCCESS_CIRCLE, '#53AD15', 'Completed successfully: Service is successfully instantiated.');
+ return new ServiceStatus(SUCCESS_CIRCLE, 'success', 'Completed successfully: Service is successfully instantiated, updated or deleted.');
case 'STOPPED' :
- return new ServiceStatus(STOPED, '#D02B2B', 'Stopped: Due to previous failure, will not be instantiated.');
+ return new ServiceStatus(STOPED, 'error', 'Stopped: Due to previous failure, will not be instantiated.');
+ case 'COMPLETED_WITH_ERRORS' :
+ return new ServiceStatus(COMPLETED_WITH_ERRORS, 'success', 'Completed with errors: some of the planned actions where successfully committed while other have not.\n Open the service to check it out.');
}
}
+
+ retry(item: ServiceInfoModel): void {
+ this.navigateToNewViewEdit(item, DrawingBoardModes.RETRY_EDIT);
+ }
}
diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts
index 00b6a9945..53dfcc1f2 100644
--- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts
+++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.spec.ts
@@ -1,88 +1,227 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import {ComponentFixture, TestBed} from '@angular/core/testing';
import {InstantiationStatusComponent} from './instantiationStatus.component';
import {ServiceInfoService} from '../shared/server/serviceInfo/serviceInfo.service';
import {InstantiationStatusComponentService} from './instantiationStatus.component.service';
-import { ContextMenuModule, ContextMenuService } from 'ngx-contextmenu';
+import {ContextMenuModule, ContextMenuService} from 'ngx-contextmenu';
import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
-import { HttpClientTestingModule } from '@angular/common/http/testing';
-import { ScrollToModule } from '@nicky-lenaers/ngx-scroll-to';
-import { ConfigurationService } from '../services/configuration.service';
-import { LogService } from '../shared/utils/log/log.service';
+import {HttpClientTestingModule} from '@angular/common/http/testing';
+import {ScrollToModule} from '@nicky-lenaers/ngx-scroll-to';
+import {ConfigurationService} from '../shared/services/configuration.service';
+import {LogService} from '../shared/utils/log/log.service';
+import {NgRedux} from '@angular-redux/store';
+import {RouterTestingModule} from '@angular/router/testing';
+import {CapitalizeAndFormatPipe} from "../shared/pipes/capitalize/capitalize-and-format.pipe";
+import {AaiService} from "../shared/services/aaiService/aai.service";
+import {MsoService} from "../shared/services/msoService/mso.service";
+import {FeatureFlagsService} from "../shared/services/featureFlag/feature-flags.service";
+import {JobStatus, ServiceAction} from "../shared/models/serviceInstanceActions";
+import each from 'jest-each';
+import {ServiceInfoModel} from "../shared/server/serviceInfo/serviceInfo.model";
+import { TooltipModule } from 'ngx-tooltip';
+
+class MockAppStore<T> {
+
+ getState() {
+ return {
+ global: {
+ flags: {
+ 'FLAG_1902_NEW_VIEW_EDIT': true
+ }
+ }
+ }
+ }
+
+ dispatch() {
+
+ }
+}
describe('Instantiation Status Component', () => {
let component: InstantiationStatusComponent;
let fixture: ComponentFixture<InstantiationStatusComponent>;
- let enableDeleteItems = [
- { jobStatus:"PENDING" },
- { jobStatus:"STOPPED" }];
- let disableDeleteItems = [
- { jobStatus:"COMPLETED" },
- { jobStatus:"FAILED" },
- {jobStatus:"IN_PROGRESS"},
- {jobStatus:"UnknownOne"}];
-
+let item = new ServiceInfoModel();
+ beforeAll(done => (async () => {
- beforeEach(async(() => {
TestBed.configureTestingModule({
- imports: [HttpClientTestingModule, ContextMenuModule, ScrollToModule.forRoot()],
- providers: [ServiceInfoService, InstantiationStatusComponentService, ContextMenuService, ConfigurationService, LogService],
- declarations: [InstantiationStatusComponent],
+ imports: [
+ HttpClientTestingModule,
+ ContextMenuModule,
+ ScrollToModule.forRoot(),
+ RouterTestingModule,
+ TooltipModule
+ ],
+ providers: [
+ ServiceInfoService,
+ InstantiationStatusComponentService,
+ AaiService,
+ MsoService,
+ ContextMenuService,
+ FeatureFlagsService,
+ ConfigurationService,
+ LogService,
+ {provide: NgRedux, useClass: MockAppStore}
+ ],
+ declarations: [InstantiationStatusComponent, CapitalizeAndFormatPipe],
schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
- }).compileComponents();
- }));
+ });
+ await TestBed.compileComponents();
- beforeEach(() => {
fixture = TestBed.createComponent(InstantiationStatusComponent);
component = fixture.componentInstance;
fixture.detectChanges();
- });
+ })().then(done).catch(done.fail));
+
- it('component should initialize basic parameters', (done: DoneFn) => {
+ test('component should initialize basic parameters', () => {
component.TIMER_TIME_IN_SECONDS = 2;
expect(component.TIMER_TIME_IN_SECONDS).toEqual(2);
expect(component.dataIsReady).toBeFalsy();
expect(component.lastUpdatedDate).toBeNull();
- done();
});
- it('component constructor should call activateInterval and ngOnInit', (done: DoneFn) => {
+ test('component constructor should call activateInterval and ngOnInit', () => {
component.refreshData();
expect(component.dataIsReady).toBeFalsy();
- done();
});
- it('stopped and pending status isDeleteEnabled button should be enabled, not allowed delete statuses isDeleteEnabled button should be disabled', (done: DoneFn) => {
- enableDeleteItems.forEach((item) => {
- let isDeleteEnabled: boolean = component.isDeleteEnabled(item);
- expect(isDeleteEnabled).toBeTruthy();
- });
+ const enableDeleteItemsDataProvider = [
+ ['INSTANTIATE action PENDING job status',JobStatus.PENDING , ServiceAction.INSTANTIATE],
+ ['DELETE action PENDING job status',JobStatus.PENDING , ServiceAction.DELETE],
+ ['UPDATE action PENDING job status',JobStatus.PENDING , ServiceAction.UPDATE],
+ ['INSTANTIATE action STOPPED job status',JobStatus.STOPPED , ServiceAction.INSTANTIATE]];
+ each(enableDeleteItemsDataProvider).test('delete item should enable for %s', (desc, jobStatus, action ) => {
+ item.action=action;
+ item.jobStatus=jobStatus;
+ let isDeleteEnabled: boolean = component.isDeleteEnabled(item);
+ expect(isDeleteEnabled).toBeTruthy();
+ });
- disableDeleteItems.forEach((item) => {
- let isDeleteEnabled: boolean = component.isDeleteEnabled(item);
- expect(isDeleteEnabled).toBeFalsy();
- });
- done();
+ const disableDeleteItemsDataProvider = [
+ [ 'INSTANTIATE action COMPLETED job status', JobStatus.COMPLETED , ServiceAction.INSTANTIATE],
+ [ 'INSTANTIATE action FAILED job status', JobStatus.FAILED , ServiceAction.INSTANTIATE],
+ [ 'INSTANTIATE action IN_PROGRESS job status', JobStatus.IN_PROGRESS, ServiceAction.INSTANTIATE],
+ [ 'INSTANTIATE action COMPLETED_WITH_ERRORS job status', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.INSTANTIATE],
+ [ 'DELETE action IN_PROGRESS job status', JobStatus.IN_PROGRESS, ServiceAction.DELETE],
+ [ 'DELETE action COMPLETED_WITH_ERRORS job status',JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.DELETE],
+ [ 'UPDATE action IN_PROGRESS job status', JobStatus.IN_PROGRESS, ServiceAction.UPDATE],
+ [ 'UPDATE action COMPLETED_WITH_ERRORS job status', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.UPDATE],
+ [ 'INSTANTIATE action UNKNOWN job status', "UNKNOWN", ServiceAction.INSTANTIATE]];
+ each(disableDeleteItemsDataProvider).test('delete item should disable for %s', (desc,jobStatus, action ) => {
+ item.action=action;
+ item.jobStatus=jobStatus;
+ let isDeleteEnabled: boolean = component.isDeleteEnabled(item);
+ expect(isDeleteEnabled).toBeFalsy();
});
- it('[COMPLETED, FAILED, STOPPED] status isHideEnable button should be enabled, [IN_PROGRESS, PAUSE, PENDING] status isHideEnable button should be disabled', (done: DoneFn) => {
- const enableHideItems = [
- { jobStatus:"COMPLETED" },
- { jobStatus:"FAILED" },
- { jobStatus:"STOPPED" }];
- enableHideItems.forEach((item) => {
- let isDeleteEnabled: boolean = component.isHideEnabled(item);
- expect(isDeleteEnabled).toBeTruthy();
- });
+ const enableHideItemsDataProvider = [
+ ['instantiate action job status COMPLETED',JobStatus.COMPLETED, ServiceAction.INSTANTIATE ],
+ ['instantiate action job status FAILED',JobStatus.FAILED, ServiceAction.INSTANTIATE ],
+ ['instantiate action job status STOPPED', JobStatus.STOPPED, ServiceAction.INSTANTIATE ],
+ ['instantiate action job status COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.INSTANTIATE ],
+ ['delete action job status COMPLETED', JobStatus.COMPLETED, ServiceAction.DELETE ],
+ ['delete action job status FAILED', JobStatus.FAILED, ServiceAction.DELETE ],
+ ['delete action job status STOPPED',JobStatus.STOPPED, ServiceAction.DELETE ],
+ ['delete action job status COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.DELETE ],
+ ['update action job status COMPLETED', JobStatus.COMPLETED, ServiceAction.UPDATE ],
+ ['update action job status FAILED',JobStatus.FAILED, ServiceAction.UPDATE ],
+ ['update action job status STOPPED', JobStatus.STOPPED, ServiceAction.UPDATE ],
+ ['update action job status COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.UPDATE ]];
+ each(enableHideItemsDataProvider).test('hide item should be enabled for %s', (desc, jobStatus, action ) => {
+ item.action=action;
+ item.jobStatus=jobStatus;
+ let isHideEnabled: boolean = component.isHideEnabled(item);
+ expect(isHideEnabled).toBeTruthy();
+ });
- const disableHideItems = [
- { jobStatus:"IN_PROGRESS" },
- { jobStatus:"PAUSE" },
- { jobStatus:"PENDING" },
- { jobStatus:"NOT_MATTER"}];
- disableHideItems.forEach((item) => {
- let isDeleteEnabled: boolean = component.isHideEnabled(item);
- expect(isDeleteEnabled).toBeFalsy();
- });
- done();
+ const disableHideItemsDataProvider = [
+ ['action instantiate job status IN_PROGRESS',JobStatus.IN_PROGRESS , ServiceAction.INSTANTIATE],
+ ['action instantiate job status PAUSE',JobStatus.PAUSE, ServiceAction.INSTANTIATE],
+ ['action instantiate job status PENDING', JobStatus.PENDING, ServiceAction.INSTANTIATE ],
+ ['action instantiate job status UNKNOWN', "UNKNOWN", ServiceAction.INSTANTIATE],
+ ['update instantiate job status IN_PROGRESS', JobStatus.IN_PROGRESS , ServiceAction.UPDATE],
+ ['update instantiate job status PAUSE', JobStatus.PAUSE, ServiceAction.UPDATE],
+ ['update instantiate job status PENDING', JobStatus.PENDING, ServiceAction.UPDATE ],
+ ['update instantiate job status UNKNOWN',"UNKNOWN", ServiceAction.UPDATE],
+ ['delete instantiate job status IN_PROGRESS',JobStatus.IN_PROGRESS , ServiceAction.DELETE],
+ ['delete instantiate job status PAUSE', JobStatus.PAUSE, ServiceAction.DELETE],
+ ['delete instantiate job status PENDING', JobStatus.PENDING, ServiceAction.DELETE ],
+ ['delete instantiate job status UNKNOWN', "UNKNOWN", ServiceAction.DELETE]];
+ each(disableHideItemsDataProvider).test('hide item should disable for %s', (desc, jobStatus, action ) => {
+ item.action=action;
+ item.jobStatus=jobStatus;
+ let isHideEnabled: boolean = component.isHideEnabled(item);
+ expect(isHideEnabled).toBeFalsy();
+ });
+
+ const enableAuditItemsDataProvider = [
+ ['instantiate action UNKNOWN job status', "UNKNOWN", ServiceAction.INSTANTIATE ],
+ ['delete action JobStatus IN_PROGRESS', JobStatus.IN_PROGRESS, ServiceAction.DELETE ],
+ ['delete action JobStatus PAUSE', JobStatus.PAUSE, ServiceAction.DELETE ],
+ ['delete action JobStatus FAILED', JobStatus.FAILED, ServiceAction.DELETE ],
+ ['delete action JobStatus COMPLETED', JobStatus.COMPLETED, ServiceAction.DELETE ],
+ ['delete action JobStatus COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.DELETE ],
+ ['update action JobStatus IN_PROGRESS', JobStatus.IN_PROGRESS, ServiceAction.UPDATE ],
+ ['update action JobStatus PAUSE', JobStatus.PAUSE, ServiceAction.UPDATE ],
+ ['update action JobStatus COMPLETED', JobStatus.COMPLETED, ServiceAction.UPDATE ],
+ ['update action JobStatus FAILED', JobStatus.FAILED, ServiceAction.UPDATE ],
+ ['update action JobStatus COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.UPDATE ]];
+
+ each(enableAuditItemsDataProvider).test('audit item should be enabled for %s', (desc, jobStatus, action ) => {
+ item.action=action;
+ item.jobStatus=jobStatus;
+ const isAuditEnabled: boolean = component.isAuditInfoEnabled(item);
+ expect(isAuditEnabled).toBeTruthy();
+ });
+
+ const disableAuditItemsDataProvider = [
+ ['Job status STOPPED action update', JobStatus.STOPPED, ServiceAction.UPDATE ],
+ ['Job status PENDING action update', JobStatus.PENDING, ServiceAction.UPDATE ],
+ ['Job status UNKNOWN action update', "UNKNOWN", ServiceAction.UPDATE],
+ ['Job status STOPPED action delete',JobStatus.STOPPED, ServiceAction.DELETE],
+ ['Job status PENDING action delete', JobStatus.PENDING, ServiceAction.DELETE ],
+ ['Job status UNKNOWN action delete', "UNKNOWN", ServiceAction.DELETE]];
+ each(disableAuditItemsDataProvider).test('audit item should be disabled for %s', (desc, jobStatus, action ) => {
+ item.action=action;
+ item.jobStatus=jobStatus;
+ let isAuditEnabled: boolean = component.isAuditInfoEnabled(item);
+ expect(isAuditEnabled).toBeFalsy();
+ });
+
+ const enableOpenItemsDataProvider = [
+ ['action instantiate job status PAUSE', JobStatus.PAUSE, ServiceAction.INSTANTIATE ],
+ ['action instantiate job status COMPLETED', JobStatus.COMPLETED, ServiceAction.INSTANTIATE ],
+ ['action instantiate job status COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.INSTANTIATE ],
+ ['action delete job status PENDING', JobStatus.PENDING, ServiceAction.DELETE ],
+ ['action delete job status FAILED', JobStatus.FAILED, ServiceAction.DELETE ],
+ ['action delete job status COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.DELETE ],
+ ['action update job status PENDING', JobStatus.PENDING, ServiceAction.UPDATE ],
+ ['action update job status PAUSE', JobStatus.PAUSE, ServiceAction.UPDATE ],
+ ['action update job status COMPLETED', JobStatus.COMPLETED, ServiceAction.UPDATE ],
+ ['action update job status FAILED', JobStatus.FAILED, ServiceAction.UPDATE ],
+ ['action update job status COMPLETED_WITH_ERRORS', JobStatus.COMPLETED_WITH_ERRORS, ServiceAction.UPDATE ]];
+ each(enableOpenItemsDataProvider).test('open item should be enabled for %s', (desc, jobStatus, action ) => {
+ item.action=action;
+ item.jobStatus=jobStatus;
+ let isOpenEnabled: boolean = component.isOpenEnabled(item);
+ expect(isOpenEnabled).toBeTruthy();
});
+
+ const disableOpenItemsDataProvider = [
+ ['action instantiate job status STOPPED', JobStatus.STOPPED, ServiceAction.INSTANTIATE],
+ ['action instantiate job status FAILED', JobStatus.FAILED, ServiceAction.INSTANTIATE],
+ ['action instantiate job status UNKNOWN', "UNKNOWN", ServiceAction.INSTANTIATE],
+ ['action update job status STOPPED', JobStatus.STOPPED, ServiceAction.UPDATE ],
+ ['action update job status IN_PROGRESS', JobStatus.IN_PROGRESS, ServiceAction.UPDATE ],
+ ['action update job status UNKNOWN', "UNKNOWN", ServiceAction.UPDATE],
+ ['action delete job status COMPLETED', JobStatus.COMPLETED, ServiceAction.DELETE],
+ ['action delete job status PAUSE', JobStatus.PAUSE, ServiceAction.DELETE],
+ ['action delete job status IN_PROGRESS', JobStatus.IN_PROGRESS, ServiceAction.DELETE ],
+ ['action delete job status UNKNOWN',"UNKNOWN", ServiceAction.DELETE]];
+ each(disableOpenItemsDataProvider).test('open item should be disabled for %s', (desc, jobStatus, action ) => {
+ item.action=action;
+ item.jobStatus=jobStatus;
+ let isOpenEnabled: boolean = component.isOpenEnabled(item);
+ expect(isOpenEnabled).toBeFalsy();
+ });
+
});
diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts
index ed45ce43c..f3f651960 100644
--- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts
+++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts
@@ -1,40 +1,97 @@
-import {AfterViewChecked, Component, ViewChild} from '@angular/core';
+import {Component, ViewChild} from '@angular/core';
import {ServiceInfoService} from '../shared/server/serviceInfo/serviceInfo.service';
import {ServiceInfoModel} from '../shared/server/serviceInfo/serviceInfo.model';
import {InstantiationStatusComponentService} from './instantiationStatus.component.service';
import {ContextMenuComponent, ContextMenuService} from 'ngx-contextmenu';
-import {AuditInfoModalComponent} from "./auditInfoModal/auditInfoModal.component";
+import {AuditInfoModalComponent} from "../shared/components/auditInfoModal/auditInfoModal.component";
import * as _ from 'lodash';
import {ScrollToConfigOptions, ScrollToService} from '@nicky-lenaers/ngx-scroll-to';
-import {ConfigurationService} from "../services/configuration.service";
+import {ConfigurationService} from "../shared/services/configuration.service";
import {LogService} from '../shared/utils/log/log.service';
-
+import {AppState} from "../shared/store/reducers";
+import {NgRedux} from '@angular-redux/store';
+import {JobStatus, ServiceAction} from "../shared/models/serviceInstanceActions";
+import {DrawingBoardModes} from "../drawingBoard/service-planning/drawing-board.modes";
+
+export interface MenuAction{
+ name: string;
+ dataTestId: string;
+ className: string;
+ tooltip?: string;
+ click(item: ServiceInfoModel): void;
+ enabled (item?: ServiceInfoModel): boolean;
+ visible (item?: ServiceInfoModel): boolean;
+}
@Component({
selector : 'instantiation-status',
templateUrl : './instantiationStatus.component.html',
styleUrls : ['./instantiationStatus.component.scss']
})
-export class InstantiationStatusComponent implements AfterViewChecked{
-
+export class InstantiationStatusComponent {
TIMER_TIME_IN_SECONDS : number = 0;
timer = null;
dataIsReady : boolean = false;
scroll : boolean = false;
lastUpdatedDate: Date = null;
- currentJobId: string = null;
instantiationStatusComponentService: InstantiationStatusComponentService;
configurationService : ConfigurationService;
- serviceInfoData: Array<ServiceInfoModel> = null;
+ serviceInfoData: ServiceInfoModel[] = null;
@ViewChild(ContextMenuComponent) public contextMenu: ContextMenuComponent;
+ public contextMenuActions: Array<MenuAction> = [
+ {
+ name: "Redeploy",
+ dataTestId: "context-menu-retry",
+ className: "fa-repeat",
+ click: (item: ServiceInfoModel) => this.retryItem(item),
+ enabled: () => true,
+ visible: (item: ServiceInfoModel) => item.isRetryEnabled,
+ },
+ {
+ name: "Open",
+ dataTestId: "context-menu-open",
+ className: "fa-external-link",
+ click: (item: ServiceInfoModel) => this.instantiationStatusComponentService.open(item),
+ enabled: (item: ServiceInfoModel) => this.isOpenEnabled(item),
+ visible: () => true,
+ },
+ {
+ name: "Audit info",
+ dataTestId: "context-menu-audit-info",
+ className: "fa-info-circle",
+ click: (item: ServiceInfoModel) => this.auditInfo(item),
+ enabled: (item: ServiceInfoModel) => this.isAuditInfoEnabled(item),
+ visible: () => true,
+ },
+ {
+ name: "Delete",
+ dataTestId: "context-menu-remove",
+ className: "fa-trash-o",
+ click: (item: ServiceInfoModel) => this.deleteItem(item),
+ enabled: (item: ServiceInfoModel) => this.isDeleteEnabled(item),
+ visible: () => true,
+ },
+ {
+ name: "Hide request",
+ dataTestId: "context-menu-hide",
+ className: "fa-eye-slash",
+ tooltip: "Hide this service from this table",
+ click: (item: ServiceInfoModel) => this.hideItem(item),
+ enabled: (item: ServiceInfoModel) => this.isHideEnabled(item),
+ visible: () => true,
+ }
+ ];
+
+ flags: any;
constructor(private _serviceInfoService: ServiceInfoService,
private _instantiationStatusComponentService : InstantiationStatusComponentService,
private _contextMenuService: ContextMenuService,
private _configurationService : ConfigurationService,
private _scrollToService: ScrollToService,
- private _logService : LogService) {
+ private _logService : LogService,
+ private _store: NgRedux<AppState>) {
this.instantiationStatusComponentService = _instantiationStatusComponentService;
this.configurationService = this._configurationService;
this.configurationService.getConfiguration("refreshTimeInstantiationDashboard").subscribe(response => {
@@ -58,61 +115,73 @@ export class InstantiationStatusComponent implements AfterViewChecked{
refreshData(): void {
this.dataIsReady = false;
- this._serviceInfoService.getServicesJobInfo(true)
- .subscribe((res: Array<ServiceInfoModel>) => {
+ this._serviceInfoService.getServicesJobInfo(true, this.lastUpdatedDate === null)
+ .subscribe((res: ServiceInfoModel[]) => {
this._instantiationStatusComponentService.convertObjectToArray(res).subscribe((res) => {
this._logService.info('refresh instantiation status table', res);
this.dataIsReady = true;
this.lastUpdatedDate = new Date();
if (!_.isEqual(this.serviceInfoData, res)) {
this.serviceInfoData = res;
- this.scroll = true;
+ this.scrollToElement(this.findFirstVisibleJob());
}
});
})
}
- ngAfterViewChecked(){
- if (this.scroll) {
- this.scrollToElement();
- this.scroll = false;
- }
+ trackByFn(index: number, item: ServiceInfoModel){
+ return _.isNil(item) ? null : item.jobId;
}
-
-
- isDeleteEnabled(item):boolean {
- return _.includes(['PENDING', 'STOPPED'], item.jobStatus);
- }
-
- deleteItem(item): void {
+ deleteItem(item: ServiceInfoModel): void {
this._serviceInfoService.deleteJob(item.jobId).subscribe(() => {
this.refreshData();
});
}
- hideItem(item): void {
+ hideItem(item: ServiceInfoModel): void {
this._serviceInfoService.hideJob(item.jobId).subscribe(() => {
this.refreshData();
});
}
+
+ retryItem(item: ServiceInfoModel) : void {
+ if (item.isRetryEnabled) {
+ this._instantiationStatusComponentService.retry(item);
+ }
+ }
auditInfo(jobData : ServiceInfoModel): void {
AuditInfoModalComponent.openModal.next(jobData);
+ }
+ isOpenEnabled(item: ServiceInfoModel):boolean {
+ switch(item.action) {
+ case ServiceAction.DELETE:
+ return _.includes([ JobStatus.PENDING, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.FAILED], item.jobStatus);
+ case ServiceAction.UPDATE:
+ return _.includes([JobStatus.PENDING, JobStatus.PAUSE, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.COMPLETED, JobStatus.FAILED], item.jobStatus);
+ default:
+ return _.includes([JobStatus.COMPLETED, JobStatus.PAUSE, JobStatus.COMPLETED_WITH_ERRORS], item.jobStatus);
+ }
}
- isOpenVisible(item):boolean {
- return _.includes(['COMPLETED', 'PAUSE'], item.jobStatus);
+ isAuditInfoEnabled(item: ServiceInfoModel): boolean {
+ if(item.action === ServiceAction.DELETE || item.action=== ServiceAction.UPDATE) {
+ return _.includes([JobStatus.FAILED, JobStatus.IN_PROGRESS, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.PAUSE, JobStatus.COMPLETED], item.jobStatus);
+ }
+ return true;// ServiceAction.INSTANTIATE
}
- open(item): void {
- let query =
- `subscriberId=${item['subscriberName']}&` +
- `serviceType=${item['serviceType']}&` +
- `serviceInstanceId=${item['serviceInstanceId']}`;
+ isDeleteEnabled(item: ServiceInfoModel):boolean {
+ if( item.action === ServiceAction.DELETE || item.action === ServiceAction.UPDATE){
+ return _.includes([JobStatus.PENDING], item.jobStatus);
+ }
+ return _.includes([JobStatus.PENDING, JobStatus.STOPPED], item.jobStatus);
+ }
- window.parent.location.assign('../../serviceModels.htm#/instantiate?' + query);
+ isHideEnabled(item: ServiceInfoModel):boolean {
+ return _.includes([JobStatus.COMPLETED, JobStatus.FAILED, JobStatus.STOPPED, JobStatus.COMPLETED_WITH_ERRORS], item.jobStatus);
}
public onContextMenu($event: MouseEvent, item: any): void {
@@ -129,17 +198,36 @@ export class InstantiationStatusComponent implements AfterViewChecked{
return './' + imageName + '.svg';
}
- isHideEnabled(item: any):boolean {
- return _.includes(['COMPLETED', 'FAILED', 'STOPPED'], item.jobStatus);
+ private getHeaderHeaderClientRect(): ClientRect {
+ const element = document.querySelector("#instantiation-status thead") as HTMLElement;
+ return element.getBoundingClientRect();
}
- scrollToElement() {
- if(this.currentJobId){
+
+ findFirstVisibleJob(): HTMLElement {
+ const elements : any = document.querySelectorAll('#instantiation-status tr');
+ const headerRect = this.getHeaderHeaderClientRect();
+ if (headerRect) {
+ const topEdge = headerRect.bottom;
+ for (let i = 0; i < elements.length; i++) {
+ if (elements[i].getBoundingClientRect().top >= topEdge)
+ return elements[i];
+ }
+ }
+ return null;
+ }
+
+ scrollToElement(currentJob: HTMLElement) {
+ if (currentJob) {
const config: ScrollToConfigOptions = {
- target: this.currentJobId,
- duration: 50,
- offset: -35 //header height
+ target: currentJob,
+ duration: 0,
+ offset: -1 * (this.getHeaderHeaderClientRect().height + 2),
};
- this._scrollToService.scrollTo(config);
+
+ // wait after render
+ setTimeout(() => {
+ this._scrollToService.scrollTo(config);
+ }, 0)
}
}
}