merge from ecomp a88f0072 - Modern UI
Issue-ID: VID-378
Change-Id: Ibcb23dd27f550cf32ce2fe0239f0f496ae014ff6
Signed-off-by: Ittay Stern <ittay.stern@att.com>
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.html b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.html
new file mode 100644
index 0000000..f02ed62
--- /dev/null
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.html
@@ -0,0 +1,78 @@
+<div class="drawing-board-header">
+ <div class="left-header">
+ <span class="vid-logo-small"></span>
+ <span class="icon-back">
+ <svg-icon
+ (click)="closePage()"
+ [testId]="'backBtn'"
+ [size]="'large'"
+ [name]="'navigation-arrow-back'">
+ </svg-icon>
+ </span>
+
+ <div class="header-col middleDetails" style="padding-top: 5px;padding-left: 13px;line-height: 100%;" *ngIf="isServiceFailed">
+ <custom-popover class="failed-popover-wrap" [value]= "serviceStatusMessage" [placement]="'bottom'" [popoverType]="'error'">
+ <span [attr.data-tests-id]="'service-failed-msg'" class="failed-msg labelPosition" >Failed</span>
+ </custom-popover>
+ </div>
+ <div class="header-col middleDetails" style="padding-top: 0px;padding-left: 13px;line-height: 100%;padding-right: 50px;">
+ <span [attr.data-tests-id]="'serviceInstance'" class="service-instance-label labelPosition">Service instance:</span>
+ <span [attr.data-tests-id]="'serviceName'" [ngClass]="{'deleted' : isDeleted}" class="service-instance-name">{{serviceName}}</span>
+ </div>
+ <div class="header-col middleDetails notShowOnCreateMode"
+ style="padding-top: 0px;padding-left: 13px;line-height: 100%;">
+ <span [attr.data-tests-id]="'orchStatusLabel'" class="service-instance-label labelPosition">Orch Status:</span>
+ <span [attr.data-tests-id]="'orchStatusValue'" class="orch-status-value">{{serviceOrchStatus}}</span>
+ </div>
+ <div class="quantity-container header-col middleDetails"
+ style="padding-top: 0px;padding-left: 13px;line-height: 100%;"
+ tooltip="Number of services to instantiate including all their objects as defined below">
+ <span [attr.data-tests-id]="'quantityLabel'" class="quantity-instance-label labelPosition">Scale Times:</span>
+ <span [attr.data-tests-id]="'servicesQuantity'" class="scale-value"
+ style="font-family: OpenSans-Semibold;font-size: 13px;"> {{numServicesToDeploy}} </span>
+ </div>
+
+ <span [attr.data-tests-id]="'serviceStatus'" class="status" tooltip="{{status}}"></span>
+ <span [attr.data-tests-id]="'isViewOnly-status-test'" class="service-instance-label purple">{{getModeName()}}</span>
+ </div>
+
+
+ <div class="right-header">
+ <span class="menu-container notShowOnViewMode notShowOnRetryMode">
+ <span [attr.data-tests-id]="'openMenuBtn'" class="icon-browse" (click)="onContextMenu($event)"></span>
+ <context-menu>
+ <ng-template *ngIf="drawingBoardHeaderService?.showEditService(mode, serviceModelId)" contextMenuItem (execute)="editService()">
+ <div [attr.data-tests-id]="'context-menu-header-edit-item'">
+ <span class="icon-edit"></span>Edit</div>
+ </ng-template>
+ <ng-template *ngIf="mode === 'EDIT'" contextMenuItem
+ (execute)="isDeleted=!isDeleted; drawingBoardHeaderService.deleteService(serviceModelId,isDeleted)">
+ <div [attr.data-tests-id]="'context-menu-header-delete-item'"><span class="icon-trash"></span>{{isDeleted ? 'Undo delete': 'Delete'}}</div>
+ </ng-template>
+ <ng-template *ngIf="mode !== 'CREATE'" contextMenuItem
+ (execute)="drawingBoardHeaderService.showAuditInfo(serviceModelId)">
+ <div [attr.data-tests-id]="'context-menu-header-audit-item'" style="float: left;margin-top: 8px;">
+ <svg-icon
+ [ngClass]="'eye-o'"
+ class="eye-o"
+ [size]="'small'"
+ [name]="'eye-o'">
+ </svg-icon></div>
+ <div style="padding-left: 12px;">Show Audit Info</div>
+ </ng-template>
+ </context-menu>
+ </span>
+ <button [disabled]="drawingBoardHeaderService?.deployShouldBeDisabled(serviceModelId, mode)"
+ *ngIf="mode !== 'VIEW' && mode !== 'RETRY'; else viewEditButton"
+ [attr.data-tests-id]="'deployBtn'"
+ (click)="deployService()"
+ class="deploy-btn">{{drawingBoardHeaderService?.getModeButton(mode)}}</button>
+ <ng-template #viewEditButton>
+ <button [disabled]="!isPermitted()"
+ [attr.data-tests-id]="'editBtn'"
+ (click)="editViewEdit()"
+ class="deploy-btn">{{drawingBoardHeaderService?.getButtonText(mode)}}
+ </button>
+ </ng-template>
+ </div>
+</div>
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.scss b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.scss
new file mode 100644
index 0000000..1242f94
--- /dev/null
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.scss
@@ -0,0 +1,176 @@
+.drawing-board-header {
+ height: 60px;
+ font-family: OpenSans-Regular;
+ display: flex;
+ justify-content: space-between;
+ font-size: 14px;
+ box-shadow: 2px 2px 6px #D2D2D2;
+ color: #191919;
+ z-index: 1;
+ position: relative;
+ [class^="icon-"] {
+ height: 60px;
+ width: 60px;
+ display: flex;
+ align-items: center;
+ text-align: center;
+ color: #5A5A5A;
+ cursor: pointer;
+ &:before {
+ font-size: 18px;
+ width: 100%;
+ }
+ &:hover:before {
+ color: #009FDB;
+ }
+ }
+ .left-header {
+ display: flex;
+ align-items: center;
+ .icon-back {
+ justify-content: center;
+ border-right: 1px solid #EAEAEA;
+ }
+ .vid-logo-small{
+ background: url('../../../../assets/img/vid-logo.jpg') no-repeat;
+ width: 60px;
+ height: 60px;
+ }
+ .status{
+ background: url('../../../../assets/img/indesign.svg') no-repeat center;
+ width: 24px;
+ height: 24px;
+ margin-left: 20px;
+ }
+ .header-col {
+ border-right: 1px solid #d2d2d2;
+ padding-right: 15px;
+ margin-left: 15px;
+ span{
+ display: block;
+ }
+ &:after{
+ content: "";
+ background: #D2D2D2;
+ height: 35px;
+ width: 1px;
+ }
+ }
+ .service-instance-label {
+ font-family: OpenSans-Semibold;
+ font-size: 13px;
+ color: #5A5A5A;
+ }
+ .quantity-instance-label {
+ font-family: OpenSans-Regular;
+ font-size: 13px;
+ color: #5A5A5A;
+ }
+
+ .labelPosition {
+ margin-top: 4px;
+ margin-bottom: 6px;
+ font-size: 12px;
+ }
+ .service-instance-name {
+ font-family: OpenSans-Semibold;
+ color: #191919;
+ background-color: white;
+ font-size: 14px;
+ &.deleted{
+ text-decoration: line-through;
+ }
+ }
+ .orch-status-value {
+ font-family: OpenSans-Regular;
+ font-size: 14px;
+ color: #191919;
+ }
+ .scale-value {
+ font-family: OpenSans-Regular;
+ font-size: 14px;
+ color: #191919;
+ }
+ .status {
+ font-family: OpenSans-Semibold;
+ line-height: 14px;
+ font-size: 14px;
+ text-align: center;
+ width: 30px;
+ margin-left: 13px;
+ margin-right: 3px;
+ }
+
+ .purple {
+ color: #9063CD;
+ }
+
+ .middleDetails {
+ border-right: 1px solid #EAEAEA;
+ margin-left: 0;
+ height: 45px;
+ }
+ }
+ .right-header {
+ display: flex;
+ align-items: center;
+ .quantity-container {
+ .quantity-label {
+ padding-left: 10px;
+ font-family: OpenSans-Semibold;
+ font-size: 12px;
+ }
+ .quantity {
+ padding: 5px 10px 5px 0;
+ font-family: OpenSans-Semibold;
+ font-size: 18px;
+ }
+ }
+ .scale-container {
+ .scale-label {
+ padding-left: 10px;
+ font-family: OpenSans-Semibold;
+ font-size: 12px;
+ }
+ .scale {
+ padding: 5px 10px 5px 0;
+ font-family: OpenSans-Semibold;
+ font-size: 18px;
+ }
+ }
+ [class^="icon-"] {
+ border-left: 1px solid #EAEAEA;
+ }
+ .menu-container {
+ height: 100%;
+ display: flex;
+ background: none;
+ border: none;
+ padding: 0;
+ outline: none;
+ justify-content: center;
+ flex-direction: column;
+ text-align: center;
+ cursor: pointer;
+ }
+ .icon-browse:before {
+ content: '\e924';
+ display: inline-block;
+ font-size: 24px;
+ }
+ .deploy-btn {
+ color: #FFFFFF ;
+ background: #009fdb;
+ width: 128px;
+ height: 100%;
+ border: none;
+ &[disabled] {
+ cursor: not-allowed;
+ opacity: .65;
+ color: #99d6ec;
+ }
+ }
+ }
+ }
+
+
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.ts
new file mode 100644
index 0000000..6e43915
--- /dev/null
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.ts
@@ -0,0 +1,187 @@
+import {Component, ViewChild} from '@angular/core';
+import {ContextMenuComponent, ContextMenuService} from 'ngx-contextmenu';
+import {DialogService} from 'ng2-bootstrap-modal';
+import {MsoService} from '../../../shared/services/msoService/mso.service'
+import * as _ from 'lodash';
+import {ActivatedRoute} from '@angular/router';
+import {ServiceInstance} from "../../../shared/models/serviceInstance";
+import {OwningEntity} from "../../../shared/models/owningEntity";
+import {MessageBoxData} from "../../../shared/components/messageBox/messageBox.data";
+import {NgRedux} from "@angular-redux/store";
+import {AppState} from "../../../shared/store/reducers";
+import {IframeService} from "../../../shared/utils/iframe.service";
+import {
+ GenericFormPopupComponent,
+ PopupType
+} from "../../../shared/components/genericFormPopup/generic-form-popup.component";
+import {ServicePopupService} from "../../../shared/components/genericFormPopup/genericFormServices/service/service.popup.service";
+import {SdcUiCommon} from "onap-ui-angular";
+import {DrawingBoardModes} from "../drawing-board.modes";
+import {DrawingBoardHeaderService} from "./drawing-board-header.service";
+import {ServiceInstanceActions} from "../../../shared/models/serviceInstanceActions";
+import {DrawingBoardPermissions} from "../../guards/servicePlanningGuard/drawingBoardGuard";
+import {MessageBoxService} from "../../../shared/components/messageBox/messageBox.service";
+
+@Component({
+ selector: 'drawing-board-header',
+ providers: [MsoService],
+ templateUrl: './drawing-board-header.component.html',
+ styleUrls: ['./drawing-board-header.component.scss']
+})
+
+export class DrawingBoardHeader {
+ serviceName: string;
+ numServicesToDeploy: number;
+ status: string = 'Designing a new service';
+ serviceModelId: string;
+ jobId: string;
+ parentElementClassName = 'content';
+ mode : DrawingBoardModes = DrawingBoardModes.CREATE;
+ serviceOrchStatus: string;
+ isDeleted: boolean = false;
+ store : NgRedux<AppState>;
+ drawingBoardPermissions : DrawingBoardPermissions;
+ drawingBoardHeaderService : DrawingBoardHeaderService;
+ isServiceFailed: boolean;
+ serviceStatusMessage: string;
+ constructor(private _contextMenuService: ContextMenuService, private dialogService: DialogService,
+ private _iframeService : IframeService,
+ private route: ActivatedRoute, private msoService: MsoService,
+ private _servicePopupService : ServicePopupService,
+ private _drawingBoardHeaderService : DrawingBoardHeaderService,
+ private _store: NgRedux<AppState>,
+ private _drawingBoardPermissions : DrawingBoardPermissions) {
+ this.store = _store;
+ this.drawingBoardPermissions = _drawingBoardPermissions;
+ this.drawingBoardHeaderService = _drawingBoardHeaderService;
+ this.mode = (!_.isNil(this.route.routeConfig.path) && this.route.routeConfig.path !== "") ? this.route.routeConfig.path as DrawingBoardModes : DrawingBoardModes.CREATE;
+ this.route
+ .queryParams
+ .subscribe((params) => {
+ this.serviceModelId = params['serviceModelId'];
+ this.jobId = params['jobId'];
+ if (_.has(this.store.getState().service.serviceHierarchy, this.serviceModelId)) {
+ this.setValuesFromStore();
+ this.store.subscribe(() => {
+ this.setValuesFromStore();
+ });
+ }
+ });
+ }
+
+
+ @ViewChild(ContextMenuComponent) public contextMenu: ContextMenuComponent;
+
+ editViewEdit(): void {
+ window.parent.location.assign(this._drawingBoardHeaderService.generateOldViewEditPath());
+ }
+
+ isPermitted() : boolean {
+ return this.drawingBoardPermissions.isEditPermitted;
+}
+
+ getModeName():string {
+ switch (this.mode) {
+ case DrawingBoardModes.CREATE:
+ return 'IN DESIGN';
+ case DrawingBoardModes.VIEW:
+ case DrawingBoardModes.RETRY:
+ return 'VIEW ONLY';
+ case DrawingBoardModes.EDIT:
+ case DrawingBoardModes.RETRY_EDIT:
+ return 'IN EDITING';
+ default:
+ return 'IN DESIGN';
+ }
+
+ }
+ public onContextMenu($event: MouseEvent, item: any): void {
+ this._contextMenuService.show.next({
+ contextMenu: this.contextMenu,
+ event: $event,
+ item: item,
+ });
+ $event.preventDefault();
+ $event.stopPropagation();
+ }
+
+ private setValuesFromStore() {
+ if(!_.isNil(this.store.getState().service.serviceInstance) && !_.isNil(this.store.getState().service.serviceInstance[this.serviceModelId])){
+ const serviceInstance = this.store.getState().service.serviceInstance[this.serviceModelId];
+ this.numServicesToDeploy = serviceInstance.bulkSize;
+ this.serviceName = serviceInstance.instanceName || '<Automatically Assigned>';
+ this.serviceOrchStatus = serviceInstance.orchStatus || "";
+ this.isServiceFailed = serviceInstance.isFailed;
+ this.serviceStatusMessage = serviceInstance.statusMessage;
+ }
+ }
+
+ public editService(): void {
+ this._iframeService.addClassOpenModal(this.parentElementClassName);
+ this.dialogService.addDialog(GenericFormPopupComponent, {
+ type: PopupType.SERVICE,
+ uuidData: <any>{
+ type : PopupType.SERVICE,
+ isMacro : this.store.getState().service.serviceHierarchy[this.serviceModelId].service.instantiationType === 'Macro',
+ serviceId: this.serviceModelId,
+ popupService: this._servicePopupService
+ },
+ isUpdateMode: true
+ });
+ }
+
+ extractOwningEntityNameAccordingtoId(id:String): string {
+ let owningEntityName;
+ _.forEach(this.store.getState().service.categoryParameters.owningEntityList,(owningEntity: OwningEntity) => {
+ if (owningEntity.id === id) {
+ owningEntityName = owningEntity.name;
+
+ }});
+ return owningEntityName;
+ }
+
+ extractServiceFields(): any {
+ let instanceFields : ServiceInstance;
+ instanceFields = this.store.getState().service.serviceInstance[this.serviceModelId];
+ if (instanceFields.action === ServiceInstanceActions.Create) {
+ instanceFields.subscriberName = this.store.getState().service.subscribers.find(sub => sub.id === instanceFields.globalSubscriberId).name;
+ instanceFields.owningEntityName = this.extractOwningEntityNameAccordingtoId(instanceFields.owningEntityId);
+ }
+ return _.omit(instanceFields,'optionalGroupMembersMap');
+ }
+
+
+ public deployService(): void {
+ let instanceFields = this.extractServiceFields();
+ if (this.mode !== DrawingBoardModes.RETRY_EDIT) {
+ instanceFields.rollbackOnFailure = instanceFields.rollbackOnFailure === 'true';
+ this.msoService.submitMsoTask(instanceFields).subscribe((result) => {
+ window.parent.postMessage("navigateToInstantiationStatus", '*');
+ });
+ } else {
+ this.msoService.retryBulkMsoTask(this.jobId, instanceFields).subscribe((result) => {
+ window.parent.postMessage("navigateToInstantiationStatus", '*');
+ });
+ }
+ }
+
+ closePage() {
+ let messageBoxData : MessageBoxData = new MessageBoxData(
+ "Delete Instantiation", // modal title
+ "You are about to stop the instantiation process of this service. \nAll data will be lost. Are you sure you want to stop?",
+ SdcUiCommon.ModalType.warning,
+ SdcUiCommon.ModalSize.medium,
+ [
+ {text:"Stop Instantiation", size:"large", callback: this.navigate.bind(this), closeModal:true},
+ {text:"Cancel", size:"medium", closeModal:true}
+ ]);
+
+ MessageBoxService.openModal.next(messageBoxData);
+ }
+
+
+
+ navigate(){
+ window.parent.postMessage("navigateTo", "*");
+ }
+}
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.spec.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.spec.ts
new file mode 100644
index 0000000..bcf6753
--- /dev/null
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.spec.ts
@@ -0,0 +1,184 @@
+import {getTestBed, TestBed} from '@angular/core/testing';
+import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
+import {DefaultDataGeneratorService} from "../../../shared/services/defaultDataServiceGenerator/default.data.generator.service";
+import {MockNgRedux, NgReduxTestingModule} from "@angular-redux/store/testing";
+import {DrawingBoardHeaderService} from "./drawing-board-header.service";
+import {ActivatedRoute} from '@angular/router';
+import {ServiceInstanceActions} from "../../../shared/models/serviceInstanceActions";
+import {AppState} from "../../../shared/store/reducers";
+import {NgRedux} from "@angular-redux/store";
+import {addServiceAction} from "../../../shared/storeUtil/utils/service/service.actions";
+import {ErrorMsgService} from "../../../shared/components/error-msg/error-msg.service";
+import {DrawingBoardModes} from "../drawing-board.modes";
+import each from "jest-each";
+
+class MockAppStore<T>{
+ getState() {
+ return {
+ service : {
+ serviceInstance : {
+ "serviceInstanceId" : {
+ action: 'None'
+ }
+ }
+ }
+ }
+ }
+}
+
+describe('Generate path to old View/Edit ', () => {
+ let injector;
+ let service: DrawingBoardHeaderService;
+ let httpMock: HttpTestingController;
+ let store : NgRedux<AppState>;
+
+ beforeAll(done => (async () => {
+ TestBed.configureTestingModule({
+ imports: [HttpClientTestingModule, NgReduxTestingModule],
+ providers: [
+ DrawingBoardHeaderService,
+ DefaultDataGeneratorService,
+ MockNgRedux,
+ ErrorMsgService,
+ {
+ provide: ActivatedRoute,
+ useValue: {
+ snapshot : {
+ queryParams:{
+ 'subscriberId' : 'subscriberId',
+ 'subscriberName' : 'subscriberName',
+ 'serviceType' : 'serviceType',
+ 'serviceInstanceId' : 'serviceInstanceId'
+ }
+ }
+ },
+ }]
+ });
+ await TestBed.compileComponents();
+
+ injector = getTestBed();
+ service = injector.get(DrawingBoardHeaderService);
+ httpMock = injector.get(HttpTestingController);
+ store = injector.get(NgRedux);
+
+ })().then(done).catch(done.fail));
+
+
+ test('should generate url to old view/edit ', () => {
+ const query: string = 'subscriberId=subscriberId&subscriberName=subscriberName&serviceType=serviceType&serviceInstanceId=serviceInstanceId';
+ const path = '../../serviceModels.htm#/instantiate?' + query;
+ let result = service.generateOldViewEditPath();
+ expect(result).toEqual(path);
+ });
+
+ test('should call update action for Delete',()=>{
+
+ jest.spyOn(store, 'dispatch');
+ service.deleteService("serviceInstanceId", true);
+ expect(store.dispatch).toHaveBeenCalledWith(addServiceAction("serviceInstanceId", ServiceInstanceActions.Delete));
+ });
+
+ test('should call update action for undo delete',()=>{
+ jest.spyOn(store, 'dispatch');
+ service.deleteService("serviceInstanceId", false);
+ expect(store.dispatch).toHaveBeenCalledWith(addServiceAction("serviceInstanceId", ServiceInstanceActions.None));
+ });
+
+ test('deployShouldBeDisabled with validationCounter greater then 0',()=>{
+ jest.spyOn(store, 'getState').mockReturnValue({
+ service: {
+ serviceInstance : {
+ 'serviceInstanceId' : {
+ validationCounter : 1
+ }
+ }
+ }
+ });
+ let result = service.deployShouldBeDisabled("serviceInstanceId");
+ expect(result).toBeTruthy();
+ });
+
+ test('deployShouldBeDisabled with validationCounter is 0 and not dirty',()=>{
+ jest.spyOn(store, 'getState').mockReturnValue({
+ service: {
+ serviceInstance : {
+ 'serviceInstanceId' : {
+ validationCounter : 0,
+ isDirty : false
+ }
+ }
+ }
+ });
+ let result = service.deployShouldBeDisabled("serviceInstanceId");
+ expect(result).toBeFalsy();
+ });
+
+ test('deployShouldBeDisabled with validationCounter is 0 and dirty',()=>{
+ jest.spyOn(store, 'getState').mockReturnValue({
+ service: {
+ serviceInstance : {
+ 'serviceInstanceId' : {
+ validationCounter : 0,
+ action : 'None',
+ isDirty : true
+ }
+ }
+ }
+ });
+ let result = service.deployShouldBeDisabled("serviceInstanceId");
+ expect(result).not.toBeTruthy();
+ });
+
+ test('deployShouldBeDisabled with validationCounter is 0 and not and action is None and dirty',()=>{
+ jest.spyOn(store, 'getState').mockReturnValue({
+ service: {
+ serviceInstance : {
+ 'serviceInstanceId' : {
+ validationCounter : 0,
+ action : ServiceInstanceActions.None,
+ isDirty : true
+ }
+ }
+ }
+ });
+ let result = service.deployShouldBeDisabled("serviceInstanceId");
+ expect(result).not.toBeTruthy();
+ });
+
+
+ test('getModeButton',()=>{
+ let result : string = service.getModeButton("EDIT");
+ expect(result).toEqual('UPDATE');
+
+ result = service.getModeButton("");
+ expect(result).toEqual('DEPLOY');
+
+ result = service.getModeButton("RETRY_EDIT");
+ expect(result).toEqual('REDEPLOY');
+ });
+ test('getButtonText',()=>{
+ expect(service.getButtonText("VIEW")).toEqual('EDIT');
+ expect(service.getButtonText("RETRY")).toEqual('REDEPLOY');
+
+ });
+ const showEditServiceDataProvider = [
+ ['Create action CREATE mode', DrawingBoardModes.CREATE ,ServiceInstanceActions.Create, true],
+ ['Create action RETRY_EDIT mode',DrawingBoardModes.RETRY_EDIT, ServiceInstanceActions.Create, true],
+ ['Create action EDIT mode',DrawingBoardModes.EDIT, ServiceInstanceActions.Create, true],
+ ['Create action RETRY mode',DrawingBoardModes.RETRY, ServiceInstanceActions.Create, false],
+ ['None action EDIT mode',DrawingBoardModes.EDIT, ServiceInstanceActions.None, false],
+ ['None action RETRY_EDIT mode', DrawingBoardModes.RETRY_EDIT, ServiceInstanceActions.None, false]];
+ each(showEditServiceDataProvider).test('showEditService service with %s', (description, mode, action, enabled) => {
+ jest.spyOn(store, 'getState').mockReturnValue({
+ service: {
+ serviceInstance : {
+ 'serviceInstanceId' : {
+ action : action
+ }
+ }
+ }
+ });
+ expect(service.showEditService(mode, 'serviceInstanceId')).toBe(enabled);
+
+ });
+});
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.ts
new file mode 100644
index 0000000..946c5ca
--- /dev/null
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.ts
@@ -0,0 +1,86 @@
+import {Injectable} from "@angular/core";
+import {ActivatedRoute} from "@angular/router";
+import {addServiceAction} from "../../../shared/storeUtil/utils/service/service.actions";
+import {ServiceInstanceActions} from "../../../shared/models/serviceInstanceActions";
+import {AppState} from "../../../shared/store/reducers";
+import {DrawingBoardTreeComponent} from "../drawing-board-tree/drawing-board-tree.component";
+import {AuditInfoModalComponent} from "../../../shared/components/auditInfoModal/auditInfoModal.component";
+import {ServiceModel} from "../../../shared/models/serviceModel";
+import {NgRedux} from "@angular-redux/store";
+import * as _ from 'lodash';
+import {ErrorMsgService} from "../../../shared/components/error-msg/error-msg.service";
+import {DrawingBoardModes} from "../drawing-board.modes";
+import {ServiceInstance} from "../../../shared/models/serviceInstance";
+
+@Injectable()
+export class DrawingBoardHeaderService{
+
+ constructor(private route: ActivatedRoute, private store: NgRedux<AppState>, private errorMsgService: ErrorMsgService){}
+ generateOldViewEditPath(): string{
+ let query: string =
+ `subscriberId=${this.route.snapshot.queryParams['subscriberId']}&` +
+ `subscriberName=${this.route.snapshot.queryParams['subscriberName']}&` +
+ `serviceType=${this.route.snapshot.queryParams['serviceType']}&` +
+ `serviceInstanceId=${this.route.snapshot.queryParams['serviceInstanceId']}`;
+ return '../../serviceModels.htm#/instantiate?' + query;
+ }
+
+ deleteService(serviceModelId: string, isDeleted: boolean ) {
+ if(isDeleted){
+ this.store.dispatch(addServiceAction(serviceModelId, ServiceInstanceActions.Delete));
+ DrawingBoardTreeComponent.triggerDeleteActionService.next(serviceModelId);
+ } else{
+ this.store.dispatch(addServiceAction(serviceModelId, ServiceInstanceActions.None));
+ DrawingBoardTreeComponent.triggerUndoDeleteActionService.next(serviceModelId);
+ }
+ }
+
+ showAuditInfo(serviceModelId) : void {
+ let instance: ServiceInstance = this.store.getState().service.serviceInstance[serviceModelId];
+ let model = new ServiceModel(this.store.getState().service.serviceHierarchy[serviceModelId]);
+ AuditInfoModalComponent.openInstanceAuditInfoModal.next({instanceId : serviceModelId , type : 'SERVICE', model : model , instance : instance, trackById: instance.trackById});
+ }
+
+
+ /*************************************************
+ should return true if deploy should be disabled
+ *************************************************/
+ deployShouldBeDisabled(serviceInstanceId: string, mode : string) : boolean {
+ const serviceInstance = this.store.getState().service.serviceInstance[serviceInstanceId];
+ if(!_.isNil(serviceInstance)){
+ const validationCounter = serviceInstance.validationCounter;
+ if (!_.isNil(this.errorMsgService.errorMsgObject)&& mode !== DrawingBoardModes.RETRY_EDIT) return true;
+ if(validationCounter > 0) return true;
+ if(serviceInstance.action !== ServiceInstanceActions.None) return false;
+ if(mode === DrawingBoardModes.RETRY_EDIT) return false;
+ return !serviceInstance.isDirty;
+ }
+ return true;
+ }
+
+ getModeButton(mode : string) : string {
+ switch (mode) {
+ case DrawingBoardModes.EDIT:
+ return 'UPDATE';
+ case DrawingBoardModes.RETRY_EDIT:
+ return 'REDEPLOY';
+ default: return 'DEPLOY';
+ }
+ }
+ getButtonText(mode : DrawingBoardModes) : string {
+ switch (mode) {
+ case DrawingBoardModes.EDIT:
+ case DrawingBoardModes.VIEW:
+ return 'EDIT';
+ case DrawingBoardModes.RETRY_EDIT:
+ case DrawingBoardModes.RETRY:
+ return 'REDEPLOY';
+ }
+ }
+
+ showEditService(mode: DrawingBoardModes, serviceModelId: string): boolean{
+ const serviceInstance = this.store.getState().service.serviceInstance;
+ return mode === DrawingBoardModes.CREATE || ((mode === DrawingBoardModes.RETRY_EDIT || mode === DrawingBoardModes.EDIT)&&
+ !_.isNil(serviceInstance) && !_.isNil(serviceInstance[serviceModelId])&& serviceInstance[serviceModelId].action === ServiceInstanceActions.Create);
+ }
+}
diff --git a/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/tmp_instansiate_request.ts b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/tmp_instansiate_request.ts
new file mode 100644
index 0000000..d57e020
--- /dev/null
+++ b/vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/tmp_instansiate_request.ts
@@ -0,0 +1,52 @@
+export default
+ {
+ "modelInfo": {
+ "modelType": "service",
+ "modelInvariantId": "5d48acb5-097d-4982-aeb2-f4a3bd87d31b",
+ "modelVersionId": "3c40d244-808e-42ca-b09a-256d83d19d0a",
+ "modelName": "MOW AVPN vMX BV vPE 1 Service",
+ "modelVersion": "10.0"
+ },
+ "owningEntityId": "038d99af-0427-42c2-9d15-971b99b9b489",
+ "owningEntityName": "JULIO ERICKSON",
+ "projectName": "{some project name}",
+ "globalSubscriberId": "{some subscriber id}",
+ "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb",
+ "instanceName": "vPE_Service",
+ "subscriptionServiceType": "VMX",
+ "lcpCloudRegionId": "mdt1",
+ "tenantId": "88a6ca3ee0394ade9403f075db23167e",
+ "vnfs": [
+ {
+ "modelInfo": {
+ "modelName": "2016-73_MOW-AVPN-vPE-BV-L",
+ "modelVersionId": "7f40c192-f63c-463e-ba94-286933b895f8",
+ "modelCustomizationName": "2016-73_MOW-AVPN-vPE-BV-L 0",
+ "modelCustomizationId": "ab153b6e-c364-44c0-bef6-1f2982117f04"
+ },
+ "lcpCloudRegionId": "mdt1",
+ "tenantId": "88a6ca3ee0394ade9403f075db23167e",
+ "platformName": "test",
+ "productFamilyId": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb",
+ "instanceName": "vmxnjr001",
+ "instanceParams": [],
+ "vfModules": [
+ {
+ "modelInfo": {
+ "modelType": "vfModule",
+ "modelName": "201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0",
+ "modelVersionId": "4c75f813-fa91-45a4-89d0-790ff5f1ae79",
+ "modelCustomizationId": "a25e8e8c-58b8-4eec-810c-97dcc1f5cb7f"
+ },
+ "instanceName": "vmxnjr001_AVPN_base_vPE_BV_base_001",
+ "instanceParams": [
+ {
+ "vmx_int_net_len": "24"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+