aboutsummaryrefslogtreecommitdiffstats
path: root/vid-webpack-master/src/app/components/service-popup/service-instance-details
diff options
context:
space:
mode:
authorSonsino, Ofir (os0695) <os0695@intl.att.com>2018-07-10 15:57:37 +0300
committerSonsino, Ofir (os0695) <os0695@intl.att.com>2018-07-10 15:57:37 +0300
commitff76b5ed0aa91d5fdf9dc4f95e8b20f91ed9d072 (patch)
treeaae42404a93fdffdd16ff050eaa28129959f7577 /vid-webpack-master/src/app/components/service-popup/service-instance-details
parentc72d565bb58226b20625b2bce5f0019046bee649 (diff)
New Angular UI from 1806
Change-Id: I39c160db0e0a6ec2e587ccf007ee1b23c6a08666 Issue-ID: VID-208 Signed-off-by: Sonsino, Ofir (os0695) <os0695@intl.att.com>
Diffstat (limited to 'vid-webpack-master/src/app/components/service-popup/service-instance-details')
-rw-r--r--vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.component.ts238
-rw-r--r--vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.html168
-rw-r--r--vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.scss64
-rw-r--r--vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.service.spec.ts26
-rw-r--r--vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.service.ts22
-rw-r--r--vid-webpack-master/src/app/components/service-popup/service-instance-details/servicePopupDataModel.ts32
6 files changed, 550 insertions, 0 deletions
diff --git a/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.component.ts b/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.component.ts
new file mode 100644
index 000000000..b6a2e3967
--- /dev/null
+++ b/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.component.ts
@@ -0,0 +1,238 @@
+import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild} from '@angular/core';
+import {FormControl, FormGroup, Validators} from "@angular/forms";
+import {ServicePopupDataModel} from './servicePopupDataModel';
+import {AaiService} from '../../../services/aaiService/aai.service';
+import {updateServiceInstance} from "../../../service.actions";
+import * as _ from 'lodash';
+import {ServiceModel} from "../../../shared/models/serviceModel";
+import {ModelInfo} from "../../../shared/models/modelInfo";
+import {loadProductFamiliesAction} from "../../../services/aaiService/aai.actions";
+import {Observable} from "rxjs/Observable";
+import {SelectOptionInterface} from "../../../shared/models/selectOption";
+import {NgRedux, select} from "@angular-redux/store";
+import {AppState} from "../../../store/reducers";
+import {isNullOrUndefined} from 'util';
+import {ServiceInstanceDetailsService} from './service-instance-details.service';
+import {NumbersLettersUnderscoreValidator} from '../../../shared/components/validators/numbersLettersUnderscore/numbersLettersUnderscore.validator';
+import {DefaultDataGeneratorService} from '../../../shared/services/defaultDataServiceGenerator/default.data.generator.service';
+
+
+@Component({
+ selector: 'service-instance-details',
+ templateUrl: 'service-instance-details.html',
+ styleUrls: ['service-instance-details.scss'],
+ providers: [AaiService]
+})
+
+export class ServiceInstanceDetailsComponent implements OnInit, OnChanges {
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes["serviceInstance"] !== undefined && changes["serviceInstance"].currentValue !== changes["serviceInstance"].previousValue && changes["serviceInstance"].currentValue !== null) {
+ this.oldServiceInstance = Object.assign({}, this.serviceInstance);
+ }
+ }
+ _serviceModel: ServiceModel;
+ @Input () serviceInstance: any;
+ @Input () dynamicInputs;
+ @Input () servicesQty: number;
+ @Input ()
+ set serviceModel(serviceModel: ServiceModel) {
+ this._serviceModel = serviceModel;
+ this.updateFormGroupControlsWithServiceModel(serviceModel);
+ }
+ @ViewChild('serviceForm') serviceForm: 'ServiceForm';
+ @Output() closePopup : EventEmitter<any> = new EventEmitter<any>();
+ @Output() onDataChanged: EventEmitter<any> = new EventEmitter<any>();
+ oldServiceInstance = {};
+
+ //todo: implement Epics and use @select to fetch the rest of the form's data as done with productFamilies.
+ //that way we can loose the updateFormData function and the subscription to store in the constructor.
+ @select(['service','productFamilies'])
+ readonly productFamilies : Observable<SelectOptionInterface[]>;
+ serviceDetails:any = {
+
+ };
+ servicePopupDataModel: ServicePopupDataModel = new ServicePopupDataModel();
+ serviceInstanceDetailsFormGroup: FormGroup;
+ serviceInstanceDetailsService : ServiceInstanceDetailsService;
+
+ constructor(private _aaiService: AaiService, private store: NgRedux<AppState>, private _serviceInstanceDetailsService : ServiceInstanceDetailsService, private _defaultDataGeneratorService : DefaultDataGeneratorService) {
+ this.store.subscribe(() => {this.updateFormData()});
+ this.serviceInstanceDetailsService = this._serviceInstanceDetailsService;
+ this.serviceInstanceDetailsFormGroup = this.createFormGroup();
+
+ this.serviceInstanceDetailsFormGroup.valueChanges.subscribe(()=> {
+ this.onDataChanged.next();
+ })
+ }
+
+ ngOnInit() {
+ this.subscribeToFormChanges();
+ this._aaiService.getSubscribers().subscribe();
+ this._aaiService.getCategoryParameters(null).subscribe();
+ this._aaiService.getAicZones().subscribe();
+ this.store.dispatch(loadProductFamiliesAction());
+ }
+
+
+ createFormGroup(): FormGroup {
+ const formGroup = new FormGroup({
+ globalSubscriberId: new FormControl(
+ Validators.compose([Validators.required])
+ ),
+ productFamilyId: new FormControl(),
+ subscriptionServiceType: new FormControl({value: null, disabled: true}, Validators.compose([Validators.required])),
+ lcpCloudRegionId: new FormControl({value: null, disabled: true}, Validators.compose([Validators.required])),
+ tenantId: new FormControl({value: null, disabled: true}, Validators.compose([Validators.required])),
+ aicZoneId: new FormControl(),
+ projectName: new FormControl(),
+ owningEntityId: new FormControl(Validators.compose([Validators.required])),
+ rollbackOnFailure: new FormControl(null, Validators.required),
+ });
+
+ return formGroup;
+ }
+
+ updateFormGroupControlsWithServiceModel(serviceModel: ServiceModel) {
+ this.serviceInstanceDetailsFormGroup.markAsUntouched();
+
+ if (serviceModel) {
+ this.serviceDetails.isUserProvidedNaming = serviceModel.isUserProvidedNaming;
+ if (serviceModel.isUserProvidedNaming) {
+ this.serviceInstanceDetailsFormGroup.addControl('instanceName', new FormControl('', Validators.compose([Validators.required, NumbersLettersUnderscoreValidator.valid])))
+ }else{
+ this.serviceInstanceDetailsFormGroup.removeControl('instanceName');
+ }
+
+ if (serviceModel.isMultiStepDesign) {
+ this.serviceInstanceDetailsFormGroup.addControl('pause', new FormControl(true));
+ }else{
+ this.serviceInstanceDetailsFormGroup.removeControl('pause');
+ }
+ }
+ }
+
+ updateFormData() {
+ let service = this.store.getState().service;
+ this.servicePopupDataModel.subscribers = service.subscribers;
+ this.servicePopupDataModel.serviceTypes = service.serviceTypes[this.servicePopupDataModel.globalCustomerId];
+ this.servicePopupDataModel.lcpRegions = service.lcpRegionsAndTenants.lcpRegionList;
+ if (this.serviceInstance) {
+ this.servicePopupDataModel.tenants = service.lcpRegionsAndTenants.lcpRegionsTenantsMap[this.serviceInstance.lcpCloudRegionId];
+ }
+ this.servicePopupDataModel.aicZones = service.aicZones;
+ this.servicePopupDataModel.owningEntities = _.get(service.categoryParameters, 'owningEntityList');
+ this.servicePopupDataModel.projects = _.get(service.categoryParameters, 'projectList');
+ this.onDataChanged.next();
+ }
+
+ subscribeToFormChanges(): void {
+ this.serviceInstanceDetailsFormGroup.get('globalSubscriberId').valueChanges.subscribe(val => {
+ this.updateServiceTypes(val);
+ this.setDisabledState(val, 'subscriptionServiceType');
+
+ });
+ this.serviceInstanceDetailsFormGroup.get('subscriptionServiceType').valueChanges.subscribe(val => {
+ this.getTenants(val);
+ this.setDisabledState(val, 'lcpCloudRegionId');
+
+ });
+ this.serviceInstanceDetailsFormGroup.get('lcpCloudRegionId').valueChanges.subscribe(val => {
+ this.setDisabledState(val, 'tenantId');
+ this.updateTenantList(val);
+
+ });
+
+ this.serviceInstanceDetailsFormGroup.get('tenantId').valueChanges.subscribe(val => {
+ this.serviceDetails.tenantName = this.getNameFromListById(this.servicePopupDataModel.tenants, val);
+ this.onDataChanged.next();
+ });
+
+ this.serviceInstanceDetailsFormGroup.get('aicZoneId').valueChanges.subscribe(val => {
+ this.serviceDetails.aicZoneName = this.getNameFromListById(this.servicePopupDataModel.aicZones, val);
+ this.onDataChanged.next();
+ });
+ }
+
+ getNameFromListById(list, id:string ) {
+ if(list && id) {
+ let filterItem = list.filter(item => {
+ return item.id == id;
+ })
+ return filterItem && filterItem[0].name;
+ }
+ return null;
+ }
+
+ setDisabledState(val, field: string): void {
+ if(val) {
+ this.serviceInstanceDetailsFormGroup.controls[field].enable();
+ } else {
+ this.serviceInstanceDetailsFormGroup.controls[field].disable();
+ }
+ }
+
+ isShowingNotificationArea(): boolean {
+ return this.servicesQty > 1;
+ }
+
+ updateServiceTypes(subscriberId) {
+ if (subscriberId) {
+ this.servicePopupDataModel.globalCustomerId = subscriberId;
+ this._aaiService.getServiceTypes(subscriberId).subscribe(() => {
+ this.updateFormData();
+ this.onDataChanged.next();
+ }, (error) => {
+
+ });
+ }
+ }
+
+ updateTenantList(cloudRegionId) {
+ this.servicePopupDataModel.tenants = this.store.getState().service.lcpRegionsAndTenants.lcpRegionsTenantsMap[cloudRegionId];
+ this.onDataChanged.next();
+ }
+
+ getTenants(serviceType) {
+ if (serviceType) {
+ this._aaiService.getLcpRegionsAndTenants(this.servicePopupDataModel.globalCustomerId, serviceType).subscribe(()=>{
+ this.onDataChanged.next();
+ });
+ }
+ }
+
+ onSubmit(formValues): void {
+ formValues.bulkSize = this.servicesQty;
+ let dynamicFields: { [dynamicField: string] : string; };
+ dynamicFields = {};
+ this.dynamicInputs.map(function (x) {
+ let dynamicField: string = x.id;
+ dynamicFields[dynamicField] = formValues[dynamicField];
+ delete formValues[dynamicField];
+ });
+ formValues.instanceParams = [];
+ formValues.instanceParams.push(dynamicFields);
+ formValues.modelInfo = new ModelInfo(this._serviceModel);
+ Object.assign(formValues, this.serviceDetails);
+ this.store.dispatch(updateServiceInstance(formValues, this._serviceModel.uuid));
+ if (this.store.getState().global.flags['FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD']){
+ this._defaultDataGeneratorService.updateReduxOnFirstSet(this._serviceModel.uuid,formValues);
+ }
+ window.parent.postMessage( {
+ eventId: 'submitIframe',
+ data: {
+ serviceModelId: this._serviceModel.uuid
+ }
+ }, "*");
+ this.closePopup.emit(this._serviceModel.uuid);
+ }
+
+ hasApiError(controlName : string, data : Array<any>){
+ if(!isNullOrUndefined(this.servicePopupDataModel) && !isNullOrUndefined(data)){
+ if(!this.serviceInstanceDetailsFormGroup.controls[controlName].disabled && data.length === 0){
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.html b/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.html
new file mode 100644
index 000000000..3d632bd89
--- /dev/null
+++ b/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.html
@@ -0,0 +1,168 @@
+
+<div id="service-instance-details">
+ <form id="serviceForm" #serviceForm="ngForm" (ngSubmit)="onSubmit(serviceForm.value)" [formGroup]="serviceInstanceDetailsFormGroup">
+ <!--We can't use [hidden] since bootstrap.css label has display: inline-block. -->
+ <!--see https://stackoverflow.com/questions/34650410/angular-2-hidden-does-not-seem-to-be-working-->
+ <label id="notification-area" *ngIf="isShowingNotificationArea()">Data entered will apply to all service instances</label>
+
+ <div class="details-item" *ngIf="serviceInstanceDetailsFormGroup.get('instanceName')">
+ <label class="required">Instance name:</label>
+ <input patternInput
+ pattern="^[a-zA-Z0-9_]*$"
+ [attr.data-tests-id]="'instanceName'"
+ id="instance-name"
+ name="instance-name"
+ [ngClass]="{'error-style' :(serviceInstance?.instanceName != '' && serviceInstanceDetailsFormGroup.controls['instanceName']?.touched && serviceInstanceDetailsFormGroup.controls['instanceName']?.errors?.pattern !== null)}"
+ [formControlName]="'instanceName'"
+ class="form-control input-text"
+ placeholder="Type Instance Name"
+ type="text"
+ [(ngModel)]="serviceInstance.instanceName" required>
+ <form-control-error
+ *ngIf="serviceInstance?.instanceName != '' && serviceInstanceDetailsFormGroup.controls['instanceName']?.touched && serviceInstanceDetailsFormGroup.controls['instanceName']?.errors?.pattern !== null"
+ [message]="'Instance name may include only alphanumeric characters and underscore.'"></form-control-error>
+
+ </div>
+
+ <div class="details-item">
+ <label class="required">Subscriber name:</label>
+ <select class="subscriber form-control input-text" id="subscriber-name-select" data-tests-id="subscriberName"
+ name="subscriber-name-select" [formControlName]="'globalSubscriberId'"
+ [ngClass]="{'error-style' :serviceInstanceDetailsService.hasApiError('globalSubscriberId',servicePopupDataModel?.subscribers, serviceInstanceDetailsFormGroup)}"
+ [(ngModel)]="serviceInstance.globalSubscriberId"
+ required>
+ <option [value]="undefined" disabled>Select Subscriber Name</option>
+ <option class="subscriberNameOption" *ngFor="let subscriber of servicePopupDataModel.subscribers"
+ [value]="subscriber.id" [disabled]="!subscriber.isPermitted">{{subscriber.name}}</option>
+ </select>
+ <form-control-error *ngIf="serviceInstanceDetailsService.hasApiError('globalSubscriberId',servicePopupDataModel?.subscribers, serviceInstanceDetailsFormGroup)" [message]="'No results for this request. Please change criteria.'"></form-control-error>
+
+ </div>
+
+ <div class="details-item">
+ <label class="required">Service type:</label>
+ <select class="form-control input-text"
+ [(ngModel)]="serviceInstance.subscriptionServiceType"
+ [formControlName]="'subscriptionServiceType'"
+ [ngClass]="{'error-style' :serviceInstanceDetailsService.hasApiError('subscriptionServiceType',servicePopupDataModel?.serviceTypes, serviceInstanceDetailsFormGroup)}"
+ data-tests-id="serviceType" id="service-type-select"
+ name="service-type" required>
+ <option [value]="undefined" disabled>Select Service Type</option>
+ <option *ngFor="let serviceType of servicePopupDataModel.serviceTypes" class="serviceTypeOption" [value]="serviceType.name" [disabled]="!serviceType.isPermitted">{{serviceType.name}}</option>
+ </select>
+ <form-control-error *ngIf="serviceInstanceDetailsService.hasApiError('subscriptionServiceType',servicePopupDataModel?.serviceTypes, serviceInstanceDetailsFormGroup)" [message]="'No results for this request. Please change criteria.'"></form-control-error>
+ </div>
+
+ <div class="details-item">
+ <label class="required">Product family:</label>
+ <select class="form-control input-text"
+ data-tests-id="productFamily"
+ id="product-family-select"
+ [ngClass]="{'error-style' :serviceInstanceDetailsService.hasApiError('productFamilyId',productFamilies, serviceInstanceDetailsFormGroup)}"
+ [formControlName]="'productFamilyId'"
+ [(ngModel)]="serviceInstance.productFamilyId"
+ name="product-family-select" required>
+ <option [value]="undefined" disabled>Select Product Family</option>
+ <option *ngFor="let productFamily of productFamilies | async" [value]="productFamily.id"
+ [disabled]="!productFamily.isPermitted">{{productFamily.name}}</option>
+ </select>
+ <form-control-error *ngIf="serviceInstanceDetailsService.hasApiError('productFamilyId',productFamilies, serviceInstanceDetailsFormGroup)" [message]="'No results for this request. Please change criteria.'"></form-control-error>
+ </div>
+
+ <div class="details-item">
+ <label class="required">LCP region:</label>
+ <select
+ class="form-control input-text"
+ [formControlName]="'lcpCloudRegionId'"
+ [(ngModel)]="serviceInstance.lcpCloudRegionId"
+ [ngClass]="{'error-style ' : serviceInstanceDetailsService.hasApiError('lcpCloudRegionId', servicePopupDataModel?.lcpRegions, serviceInstanceDetailsFormGroup)}"
+ name="lcpRegion"
+ id="lcpRegion-select"
+ data-tests-id="lcpRegion"
+ required>
+ <option [value]="undefined" disabled>Select LCP Region</option>
+ <option *ngFor="let lcpRegion of servicePopupDataModel.lcpRegions" [value]="lcpRegion.id" [disabled]="!lcpRegion.isPermitted" class="lcpRegionOption">{{lcpRegion.id}}</option>
+ </select>
+ <form-control-error *ngIf="serviceInstanceDetailsService.hasApiError('lcpCloudRegionId', servicePopupDataModel?.lcpRegions, serviceInstanceDetailsFormGroup)" [message]="'No results for this request. Please change criteria.'"></form-control-error>
+ </div>
+
+ <div class="details-item">
+ <label class="required">Tenant:</label>
+ <select class="form-control input-text"
+ [formControlName]="'tenantId'"
+ [(ngModel)]="serviceInstance.tenantId"
+ name="tenant" id="tenant-select"
+ [ngClass]="{'error-style ' : serviceInstanceDetailsService.hasApiError('tenantId',servicePopupDataModel?.tenants ,serviceInstanceDetailsFormGroup)}"
+ data-tests-id="tenant" required>
+ <option [value]="undefined" disabled>Select Tenant</option>
+ <option *ngFor="let tenant of servicePopupDataModel.tenants" [value]="tenant.id" [disabled]="!tenant.isPermitted">{{tenant.name}}</option>
+ </select>
+ <form-control-error *ngIf="serviceInstanceDetailsService.hasApiError('tenantId',servicePopupDataModel?.tenants ,serviceInstanceDetailsFormGroup)" [message]="'No results for this request. Please change criteria.'"></form-control-error>
+ </div>
+
+ <div class="details-item">
+ <label>AIC Zone:</label>
+ <select
+ class="form-control input-text"
+ name="aicZone" id="aicZone-select"
+ data-tests-id="aic_zone"
+ [formControlName]="'aicZoneId'"
+ [ngClass]="{'error-style ' : servicePopupDataModel?.aicZones?.length == 0 && serviceInstanceDetailsFormGroup.controls['aicZoneId'].disabled == false}"
+ [(ngModel)]="serviceInstance.aicZoneId" >
+ <option [value]="undefined" disabled>Select AIC Zone</option>
+ <option class="aicZoneOption" *ngFor="let aicZone of servicePopupDataModel.aicZones" [value]="aicZone.id">{{aicZone.name}}</option>
+ </select>
+ <form-control-error *ngIf="serviceInstanceDetailsService.hasApiError('aicZoneId',servicePopupDataModel?.aicZones ,serviceInstanceDetailsFormGroup)" [message]="'No results for this request. Please change criteria.'"></form-control-error>
+
+ </div>
+
+ <div class="details-item">
+ <label>Project:</label>
+ <select
+ [attr.data-tests-id]="'project'"
+ class="form-control input-text"
+ [ngClass]="{'error-style ' : servicePopupDataModel?.projects?.length == 0 && serviceInstanceDetailsFormGroup.controls['projectName'].disabled == false}"
+ name="project" id="project"
+ [formControlName]="'projectName'"
+ [(ngModel)]="serviceInstance.projectName" >
+ <option [value]="undefined" disabled>Select Project</option>
+ <option *ngFor="let project of servicePopupDataModel.projects" [value]="project.id">{{project.name}}</option>
+ </select>
+ <form-control-error *ngIf="serviceInstanceDetailsService.hasApiError('projectName',servicePopupDataModel?.projects ,serviceInstanceDetailsFormGroup)" [message]="'No results for this request. Please change criteria.'"></form-control-error>
+
+ </div>
+
+ <div class="details-item">
+ <label class="required">Owning entity:</label>
+ <select [attr.data-tests-id]="'owningEntity'"
+ class="form-control input-text"
+ [formControlName]="'owningEntityId'"
+ [(ngModel)]="serviceInstance.owningEntityId"
+ name="owningEntity" id="owningEntity"
+ [ngClass]="{'error-style ' : servicePopupDataModel?.owningEntities?.length == 0 && serviceInstanceDetailsFormGroup.controls['owningEntityId'].disabled == false}"
+ required>
+ <option [value]="undefined" disabled>Select Owning Entity</option>
+ <option *ngFor="let owningEntity of servicePopupDataModel.owningEntities" [value]="owningEntity.id">{{owningEntity.name}}</option>
+ </select>
+ <form-control-error *ngIf="serviceInstanceDetailsService.hasApiError('owningEntityId',servicePopupDataModel?.owningEntities ,serviceInstanceDetailsFormGroup)" [message]="'No results for this request. Please change criteria.'"></form-control-error>
+ </div>
+ <div class="details-item">
+ <label class="required">Rollback On Failure:</label>
+ <select [attr.data-tests-id]="'rollback'"
+ [ngClass]="{'error-style' :serviceInstanceDetailsService.hasApiError('rollbackOnFailure',servicePopupDataModel?.rollbackOnFailure, serviceInstanceDetailsFormGroup)}"
+ class="form-control input-text"
+ [(ngModel)]="serviceInstance.rollbackOnFailure"
+ [formControlName]="'rollbackOnFailure'" name="rollbackOnFailure" id="rollbackOnFailure">
+ <option *ngFor="let option of servicePopupDataModel.rollbackOnFailure" [value]="option.id">{{option.name}}</option>
+ </select>
+ <form-control-error *ngIf="serviceInstanceDetailsService.hasApiError('rollbackOnFailure',servicePopupDataModel?.rollbackOnFailure, serviceInstanceDetailsFormGroup)" [message]="'No results for this request. Please change criteria.'"></form-control-error>
+ </div>
+ <div class="details-item" *ngIf="serviceInstanceDetailsFormGroup.get('pause')">
+ <input #pause id="pause" [formControlName]="'pause'" [(ngModel)]="serviceInstance.pause" type="checkbox" name="pause" data-toggle="toggle">
+ <label class="checkbox-label" for="pause">Pause on pause points:</label>
+ </div>
+
+
+ <dynamic-inputs *ngIf="dynamicInputs != undefined && dynamicInputs.length>0" [group]="serviceInstanceDetailsFormGroup" [list]="dynamicInputs"></dynamic-inputs>
+ </form>
+</div>
diff --git a/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.scss b/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.scss
new file mode 100644
index 000000000..928343d43
--- /dev/null
+++ b/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.scss
@@ -0,0 +1,64 @@
+#service-instance-details {
+ position: relative;
+
+ #notification-area {
+ color: #959595;
+ font-size: 12px;
+ position: absolute;
+ top: 3px;
+ left: 30px;
+ }
+
+ height: 100%;
+ overflow: auto;
+ padding: 30px;
+
+ /deep/ {
+ .form-control {
+ border-radius: 2px;
+ box-shadow: none;
+ border-color: #D2D2D2;
+ }
+
+ label {
+ font-family: OpenSans-Semibold;
+ font-size: 12px;
+ }
+
+ select {
+ @extend .form-control;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ background: url('../../../../assets/img/chevron.svg') 0 0 no-repeat;
+ background-size: 24px;
+ background-position-x: right;
+ background-position-y: center;
+ font-family: OpenSans-Italic;
+ font-size: 14px;
+ color: #959595;
+ height: 38px;
+ }
+
+ input:not([type='checkbox']) {
+ @extend .form-control;
+ height: 38px;
+ }
+
+ .form-control[disabled], fieldset[disabled] .form-control {
+ opacity: 0.5;
+ }
+ .input-text {
+ border: 1px solid #D2D2D2;
+ border-radius: 2px;
+ }
+
+ .details-item {
+ margin-bottom: 20px;
+ }
+ }
+
+ .checkbox-label {
+ font-family: OpenSans-Regular;
+ }
+}
diff --git a/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.service.spec.ts b/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.service.spec.ts
new file mode 100644
index 000000000..605653bd0
--- /dev/null
+++ b/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.service.spec.ts
@@ -0,0 +1,26 @@
+import { getTestBed, TestBed } from '@angular/core/testing';
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { ServiceInstanceDetailsService } from './service-instance-details.service';
+import { NgRedux } from '@angular-redux/store';
+
+export class MockAppStore<T> {}
+
+describe('Service instance details service', () => {
+ let injector;
+ let service: ServiceInstanceDetailsService;
+ let httpMock: HttpTestingController;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [HttpClientTestingModule],
+ providers: [ServiceInstanceDetailsService,
+ {provide: NgRedux, useClass: MockAppStore}]
+ });
+
+ injector = getTestBed();
+ service = injector.get(ServiceInstanceDetailsService);
+ httpMock = injector.get(HttpTestingController);
+ });
+});
+
+
diff --git a/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.service.ts b/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.service.ts
new file mode 100644
index 000000000..99b390d2f
--- /dev/null
+++ b/vid-webpack-master/src/app/components/service-popup/service-instance-details/service-instance-details.service.ts
@@ -0,0 +1,22 @@
+import { Injectable } from '@angular/core';
+import { isNullOrUndefined } from 'util';
+import { FormGroup } from '@angular/forms';
+import * as _ from 'lodash';
+import { createVFModuleInstance, updateVFModuleInstance, updateVNFInstance } from '../../../service.actions';
+import { NgRedux } from '@angular-redux/store';
+import { AppState } from '../../../store/reducers';
+
+@Injectable()
+export class ServiceInstanceDetailsService {
+ static controlsFieldsStatus = {};
+
+ constructor(private store: NgRedux<AppState>) { }
+ hasApiError(controlName: string, data: Array<any>, serviceInstanceDetailsFormGroup: FormGroup) {
+ if (!isNullOrUndefined(data)) {
+ if (!serviceInstanceDetailsFormGroup.controls[controlName].disabled && data.length === 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/vid-webpack-master/src/app/components/service-popup/service-instance-details/servicePopupDataModel.ts b/vid-webpack-master/src/app/components/service-popup/service-instance-details/servicePopupDataModel.ts
new file mode 100644
index 000000000..c7894e2cd
--- /dev/null
+++ b/vid-webpack-master/src/app/components/service-popup/service-instance-details/servicePopupDataModel.ts
@@ -0,0 +1,32 @@
+import {SelectOption, SelectOptionInterface} from "../../../shared/models/selectOption";
+
+export class ServicePopupDataModel {
+ subscribers: SelectOptionInterface[];
+ serviceTypes: SelectOptionInterface[];
+ aicZones: SelectOptionInterface[];
+ lcpRegions: SelectOptionInterface[];
+ productFamilies: SelectOptionInterface[];
+ lcpRegionsTenantsMap: object;
+ tenants: SelectOptionInterface[];
+ projects: SelectOptionInterface[];
+ owningEntities: SelectOptionInterface[];
+ globalCustomerId: string;
+ rollbackOnFailure: SelectOptionInterface[];
+
+
+ constructor(){
+ this.subscribers = null;
+ this.serviceTypes = null;
+ this.aicZones = null;
+ this.lcpRegions = null;
+ this.lcpRegionsTenantsMap = {};
+ this.tenants = null;
+ this.productFamilies = null;
+ this.projects = null;
+ this.owningEntities = null;
+ this.rollbackOnFailure = [
+ new SelectOption({id: 'true', name: 'Rollback'}),
+ new SelectOption({id: 'false', name: 'Don\'t Rollback'})
+ ];
+ }
+}