aboutsummaryrefslogtreecommitdiffstats
path: root/vid-webpack-master/src/app/components/service-popup
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
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')
-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
-rw-r--r--vid-webpack-master/src/app/components/service-popup/service-popup.component.ts144
-rw-r--r--vid-webpack-master/src/app/components/service-popup/service-popup.html52
-rw-r--r--vid-webpack-master/src/app/components/service-popup/service-popup.scss185
-rw-r--r--vid-webpack-master/src/app/components/service-popup/service-popup.service.spec.ts138
-rw-r--r--vid-webpack-master/src/app/components/service-popup/service-popup.service.ts33
11 files changed, 1102 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'})
+ ];
+ }
+}
diff --git a/vid-webpack-master/src/app/components/service-popup/service-popup.component.ts b/vid-webpack-master/src/app/components/service-popup/service-popup.component.ts
new file mode 100644
index 000000000..908ae4adf
--- /dev/null
+++ b/vid-webpack-master/src/app/components/service-popup/service-popup.component.ts
@@ -0,0 +1,144 @@
+import {Component, ViewChild} from '@angular/core';
+import {DialogComponent, DialogService} from 'ng2-bootstrap-modal';
+import {ServiceModel} from '../../shared/models/serviceModel';
+import {Constants} from '../../shared/utils/constants';
+import {ServiceInstanceDetailsComponent} from './service-instance-details/service-instance-details.component';
+import {ActivatedRoute} from "@angular/router";
+import {AaiService} from "../../services/aaiService/aai.service";
+import {Utils} from "../../utils/utils";
+import {ServicePlanningService} from "../../services/service-planning.service";
+import * as _ from 'lodash';
+import {ModelInformationItem} from '../../shared/components/model-information/model-information.component';
+import {deleteServiceInstance} from '../../service.actions';
+
+import {InstancePopup} from "../instance-popup/instance-popup.components";
+import {NgRedux} from "@angular-redux/store";
+import {AppState} from "../../store/reducers";
+import {ServicePopupService} from './service-popup.service';
+import {IframeService} from "../../shared/utils/iframe.service";
+
+export interface ServicePopupModel {
+ serviceModel: ServiceModel
+}
+
+@Component({
+ selector: 'service-popup',
+ templateUrl: 'service-popup.html',
+ styleUrls: ['service-popup.scss'],
+ providers: [AaiService, ServicePopupService]
+})
+
+export class ServicePopupComponent extends DialogComponent<ServicePopupModel, boolean>
+ implements ServicePopupModel, InstancePopup{
+ @ViewChild(ServiceInstanceDetailsComponent) serviceInstanceDetails: ServiceInstanceDetailsComponent;
+
+ serviceModel: ServiceModel;
+ serviceModelId: string;
+ serviceInstance: any = {
+ 'rollbackOnFailure' : 'false'
+ };
+ title: string = Constants.ServicePopup.TITLE;
+ dynamicInputs: any[] = null;
+
+ maxServiceQty:number = 50;
+ minServiceQty:number = 1;
+ servicesQty = 1; //default
+ quantityOptions = this.getQuantityOptions();
+
+ modelInformationItems: Array<ModelInformationItem> = [];
+ hasGeneralApiError : boolean = false;
+ parentElementClassName = 'content';
+
+ constructor(dialogService: DialogService, private route: ActivatedRoute, private _aaiService: AaiService,
+ private _iframeService : IframeService,
+ private _servicePlanningService: ServicePlanningService, private store: NgRedux<AppState>, private _servicePopupService : ServicePopupService) {
+ super(dialogService);
+ this.title = Constants.ServicePopup.TITLE;
+ }
+
+ updateGeneralErrorSection() : void {
+ this.hasGeneralApiError = this._servicePopupService.onControlError(this.serviceInstanceDetails, this.serviceInstanceDetails.serviceInstanceDetailsFormGroup);
+ }
+
+
+ ngOnInit() {
+ this.route
+ .queryParams
+ .subscribe(params => {
+ this.serviceModelId = params['serviceModelId'];
+ if(params['isCreate']=="true") {
+ this.store.dispatch(deleteServiceInstance(this.serviceModelId));
+ }
+ this.updateServiceModelById(this.serviceModelId);
+ this.updateInstanceFromStore();
+ });
+ }
+
+ updateInstanceFromStore() {
+ let serviceInstance;
+ if (_.has(this.store.getState().service.serviceInstance, this.serviceModelId)) {
+ serviceInstance = Object.assign({}, this.store.getState().service.serviceInstance[this.serviceModelId]);
+ }
+
+ this.serviceInstance = serviceInstance ? serviceInstance : this.serviceInstance;
+ this.servicesQty = serviceInstance ? serviceInstance.bulkSize : 1;
+ if (serviceInstance && serviceInstance.instanceParams && serviceInstance.instanceParams[0]) {
+ this.dynamicInputs = this.dynamicInputs.map(function (x) {
+ x.value = (serviceInstance.instanceParams[0][x.id]) ? serviceInstance.instanceParams[0][x.id] : x.value;
+ return x;
+ });
+ }
+ }
+
+ updateServiceModelById(serviceModelId) {
+ this._aaiService.getServiceModelById(serviceModelId).subscribe(
+ value => {
+ const convertedModel = Utils.convertModel(value);
+ this.serviceModel = new ServiceModel(convertedModel);
+ let displayInputs = Object.assign({},convertedModel.service.inputs);
+ this.dynamicInputs = _.isEmpty(displayInputs)? [] : this._servicePlanningService.getArbitraryInputs(displayInputs);
+ this.modelInformationItems = this.createModelInformationItems();
+ },
+ error => {console.log('error is ', error)},
+ () => {console.log('completed')}
+ );
+ }
+
+ createModelInformationItems() : Array<ModelInformationItem> {
+ return [
+ new ModelInformationItem("Model version", "modelVersion", [this.serviceModel.version], "", true),
+ new ModelInformationItem("Description", "description", [this.serviceModel.description]),
+ new ModelInformationItem("Category", "category", [this.serviceModel.category]),
+ new ModelInformationItem("UUID", "uuid", [this.serviceModel.uuid], Constants.ServicePopup.TOOLTIP_UUID, true),
+ new ModelInformationItem("Invariant UUID", "invariantUuid", [this.serviceModel.invariantUuid], Constants.ServicePopup.TOOLTIP_INVARIANT_UUID, true),
+ new ModelInformationItem("Service type", "serviceType", [this.serviceModel.serviceType]),
+ new ModelInformationItem("Service role", "serviceRole", [this.serviceModel.serviceRole])
+ ];
+ }
+
+ onCancelClick() {
+ this._iframeService.removeClassCloseModal(this.parentElementClassName);
+ this.dialogService.removeDialog(this);
+ this.serviceInstance = this.serviceInstanceDetails.oldServiceInstance;
+
+ this._servicePopupService.resetDynamicInputs(this.serviceInstanceDetails, this.dynamicInputs);
+ // Delaying the iframe close in few milliseconds.
+ // This should workaround a problem in Selenium tests' that
+ // blocks after click because the iframe goes out before
+ // the driver understands it was clicked. Similar bug is
+ // described here:
+ // - https://github.com/mozilla/geckodriver/issues/611
+ // - https://bugzilla.mozilla.org/show_bug.cgi?id=1223277
+ setTimeout(() => {
+ window.parent.postMessage("closeIframe", "*");
+ }, 15);
+ }
+
+ getModelName(): string {
+ return (this.serviceModel && this.serviceModel.name) || "";
+ }
+
+ getQuantityOptions(){
+ return _.range(this.minServiceQty, this.maxServiceQty + 1);
+ }
+}
diff --git a/vid-webpack-master/src/app/components/service-popup/service-popup.html b/vid-webpack-master/src/app/components/service-popup/service-popup.html
new file mode 100644
index 000000000..e967daa3b
--- /dev/null
+++ b/vid-webpack-master/src/app/components/service-popup/service-popup.html
@@ -0,0 +1,52 @@
+<div id="service-popup" class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" (click)="onCancelClick()" >&times;</button>
+ <span [attr.data-tests-id]="'create-modal-title'" class="modal-title">{{title}}</span>
+ </div>
+ <div class="modal-body popup-content">
+
+ <div class="header-left">
+ <div>SERVICE MODEL: <span>"{{getModelName()}}"</span></div>
+ </div>
+
+ <div class="header-right">
+ Service Instance Details
+ </div>
+
+ <label class="quantity-label">Qty:</label>
+ <div class="quantity">
+ <select class="quantity-select" [(ngModel)]="servicesQty" name="quantity" id="quantity-select" required>
+ <option *ngFor="let qty of quantityOptions" [value]="qty">{{qty}}</option>
+ </select>
+ </div>
+
+ <div class="service-model">
+
+ <model-information [modelInformationItems]="modelInformationItems"></model-information>
+ </div>
+
+ <div class="service-instance">
+ <service-instance-details [dynamicInputs]="dynamicInputs"
+ [serviceInstance]="serviceInstance"
+ [serviceModel]="serviceModel"
+ [servicesQty]="servicesQty"
+ (onDataChanged)="updateGeneralErrorSection()"
+ (closePopup)="onCancelClick($event)"></service-instance-details>
+ </div>
+
+ </div>
+ <div class="modal-footer row" style="padding: 0">
+ <div class="col-md-6">
+ <div *ngIf="hasGeneralApiError == true">
+ <form-general-error [message]="'Page contains errors. Please see details next to the relevant fields.'"></form-general-error>
+ </div>
+ </div>
+ <div class="col-md-6" style="padding: 15px;padding-right: 35px;">
+ <button [attr.data-tests-id]="'cancelButton'" type="button" class="btn btn-default cancel" (click)="onCancelClick()"><span>Cancel</span></button>
+ <input type="submit" value="Set" form="serviceForm" data-tests-id="service-form-set"
+ class="btn btn-success submit" [disabled]="!serviceInstanceDetails?.serviceForm?.valid">
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/vid-webpack-master/src/app/components/service-popup/service-popup.scss b/vid-webpack-master/src/app/components/service-popup/service-popup.scss
new file mode 100644
index 000000000..aa4552d2f
--- /dev/null
+++ b/vid-webpack-master/src/app/components/service-popup/service-popup.scss
@@ -0,0 +1,185 @@
+$grid-border: 1px #d2d2d2 solid;
+
+#service-popup {
+ color: #191919;
+
+ .left-panel {
+ background: #f2f2f2;
+ border-right: $grid-border;
+ }
+
+ .header-common {
+ height: 100%;
+ align-items: center;
+ display: flex;
+ font-family: OpenSans-Semibold;
+ font-size: 12px;
+ }
+
+ .header-text {
+ padding-left: 30px;
+ @extend .header-common;
+ }
+
+ .header-left {
+ grid-area: header-left;
+ @extend .header-text;
+ @extend .left-panel;
+ border-bottom: $grid-border;
+
+ span {
+ font-family: OpenSans-Regular;
+ font-size: 14px;
+ };
+ }
+
+ .header-right {
+ grid-area: header-right;
+
+ @extend .header-text;
+ border-bottom: $grid-border;
+ }
+
+ .quantity-label {
+ grid-area: quantity-label;
+ @extend .header-common;
+ border-bottom: $grid-border;
+ height: 100%;
+ font-family: OpenSans-Regular;
+ }
+
+ .quantity {
+ grid-area: quantity;
+ border-left: $grid-border;
+ border-bottom: $grid-border;
+ border-top-style: none;
+ font-family: OpenSans-Semibold;
+ text-align: start;
+ text-indent: 10px;
+ }
+
+ .quantity-select {
+ width: 78px;
+ height: 100%;
+ border: 0;
+ background: white;
+ outline: none;
+ -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;
+ }
+ input[type="number"]:hover::-webkit-inner-spin-button {
+ height: 20px;
+ }
+
+ .service-model {
+ grid-area: service-model;
+
+ padding: 30px;
+ overflow: auto;
+ @extend .left-panel;
+ }
+
+ .service-instance {
+ grid-area: service-instance;
+ }
+
+ .popup-content {
+ display: grid;
+ grid-template-columns: 400px auto 30px 93px;
+ grid-template-rows: 50px calc(100vh - 180px);
+ grid-template-areas:
+ "header-left header-right quantity-label quantity"
+ "service-model service-instance service-instance service-instance";
+ padding: 0;
+ }
+}
+
+.modal {
+ background-color: #191919;
+ opacity: 0.8;
+}
+
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 0;
+}
+@media (min-width: 1150px) {
+ .popup-content {
+ grid-template-rows: 30px 680px;
+ }
+}
+
+.modal-content {
+ border-radius: 0;
+ box-shadow: none;
+ border: none;
+}
+
+.modal-footer {
+ .cancel {
+ width: 120px;
+ height: 36px;
+ background: #ffffff;
+ border: 1px solid #009fdb;
+ border-radius: 2px;
+ span {
+ font-family: OpenSans-Regular;
+ font-size: 14px;
+ color: #009fdb;
+ line-height: 16px;
+ }
+ }
+
+ .submit {
+ width: 120px;
+ height: 36px;
+ background: #009fdb;
+ border-radius: 2px;
+ border-color: #009fdb;
+ span {
+ font-family: OpenSans-Regular;
+ font-size: 14px;
+ color: #FFFFFF;
+ line-height: 16px;
+ }
+ }
+}
+
+.modal-header {
+ background-color: #009fdb;
+
+ padding-bottom: 13px;
+ padding-top: 13px;
+ padding-left: 29px;
+ padding-right: 21px;
+
+ .close {
+ font-size: 32px;
+ font-weight: 200;
+ color: #d8d8d8;
+ text-shadow: none;
+ filter: none;
+ opacity: 1;
+ }
+
+ .modal-title {
+ font-family: OpenSans-Regular;
+ font-size: 24px;
+ color: #fff;
+ line-height: 34px;
+ }
+}
+//
+//@media (min-width: 1200px) {
+// .service-model,
+// .service-instance {
+// width: 1050px;
+// margin: 30px auto;
+// }
+//}
diff --git a/vid-webpack-master/src/app/components/service-popup/service-popup.service.spec.ts b/vid-webpack-master/src/app/components/service-popup/service-popup.service.spec.ts
new file mode 100644
index 000000000..cddc6400a
--- /dev/null
+++ b/vid-webpack-master/src/app/components/service-popup/service-popup.service.spec.ts
@@ -0,0 +1,138 @@
+
+import { TestBed, getTestBed} from '@angular/core/testing';
+import {
+ HttpClientTestingModule,
+ HttpTestingController
+} from '@angular/common/http/testing';
+import { ServicePopupService } from './service-popup.service';
+import { FormControl, FormGroup, Validators } from '@angular/forms';
+import { NumbersLettersUnderscoreValidator } from '../../shared/components/validators/numbersLettersUnderscore/numbersLettersUnderscore.validator';
+
+describe('Service Popup Service', () => {
+ let injector;
+ let service: ServicePopupService;
+ let httpMock: HttpTestingController;
+ let form : FormGroup;
+ let servicePopupDataModel;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [HttpClientTestingModule],
+ providers: [ServicePopupService]
+ });
+
+ injector = getTestBed();
+ service = injector.get(ServicePopupService);
+ httpMock = injector.get(HttpTestingController);
+
+ form = generateFormGroup();
+ servicePopupDataModel = generateServicePopupDataModel();
+ });
+
+ describe('#resetDynamicInputs', () => {
+ it('resetDynamicInputs should reset dymanic fields',(done: DoneFn) => {
+ const dynamicInputs = generateDynamicInputs();
+ let serviceForm = generateFormGroup();
+ serviceForm.addControl(dynamicInputs[0].name, new FormControl({value: dynamicInputs[0].value, disabled: false}));
+
+ serviceForm.controls[dynamicInputs[0].name].setValue("diffValue");
+ service.resetDynamicInputs({
+ serviceInstanceDetailsFormGroup : serviceForm,
+ dynamicInputs : dynamicInputs
+ }, dynamicInputs);
+
+ expect(serviceForm.controls[dynamicInputs[0].name].value).toEqual(dynamicInputs[0].value);
+ done();
+ })
+ });
+
+ describe('#onControlError', () => {
+
+ it('should return true if instanceName is illegal', (done: DoneFn) => {
+ form.controls['instanceName'].setValue("illegal - illegal");
+
+ let result : boolean = service.onControlError(<any>servicePopupDataModel, form);
+ expect(result).toBeTruthy();
+ done();
+ });
+
+ it('should return false if instanceName is legal', (done: DoneFn) => {
+
+ form.controls['instanceName'].setValue("legal");
+ let result = service.onControlError(<any>servicePopupDataModel, form);
+ expect(result).toBeFalsy();
+ done();
+ });
+
+ it('should return false if lcpRegions is empty and is disabled', (done: DoneFn) => {
+ servicePopupDataModel.servicePopupDataModel['lcpRegions'] = [];
+ let result = service.onControlError(<any>servicePopupDataModel, form);
+ expect(result).toBeFalsy();
+ done();
+ });
+
+ it('should return true if lcpRegions is empty', (done: DoneFn) => {
+ servicePopupDataModel.servicePopupDataModel['lcpRegions'] = [];
+ form.controls['lcpCloudRegionId'].enable();
+ let result = service.onControlError(<any>servicePopupDataModel, form);
+ expect(result).toBeTruthy();
+ done()
+ });
+ });
+
+
+ function generateDynamicInputs(){
+ return JSON.parse('[{"id":"2017488_adiodvpe0_ASN","type":"string","name":"2017488_adiodvpe0_ASN","value":"AV_vPE","isRequired":true,"description":"AV/PE"}]');
+ }
+
+
+ function generateServicePopupDataModel() {
+ return {
+ "servicePopupDataModel" : JSON.parse('{"subscribers":[{"id":"a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb","name":"Mobility","isPermitted":false},{"id":"a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fc","name":"PACKET CORE","isPermitted":false},{"id":"e433710f-9217-458d-a79d-1c7aff376d89","name":"USP VOICE","isPermitted":true}],"serviceTypes":[{"id":"0","name":"vFlowLogic","isPermitted":false},{"id":"1","name":"VIRTUAL USP","isPermitted":true},{"id":"2","name":"Mobility","isPermitted":false},{"id":"3","name":"vBNG","isPermitted":false},{"id":"4","name":"vVoiceMail","isPermitted":false},{"id":"5","name":"Nimbus","isPermitted":false},{"id":"6","name":"vSEGW","isPermitted":false},{"id":"7","name":"vVM","isPermitted":false},{"id":"8","name":"vOTA","isPermitted":false},{"id":"9","name":"vMME","isPermitted":false},{"id":"10","name":"vMNS","isPermitted":false},{"id":"11","name":"vSCP","isPermitted":false},{"id":"12","name":"VPMS","isPermitted":false},{"id":"13","name":"vMMSC","isPermitted":false},{"id":"14","name":"SSD","isPermitted":false},{"id":"15","name":"vMOG","isPermitted":false},{"id":"16","name":"FIRSTNET","isPermitted":false},{"id":"17","name":"ACTIVE_CHARGE","isPermitted":false},{"id":"18","name":"vHSS","isPermitted":false}],"aicZones":[{"id":"NFT1","name":"NFTJSSSS-NFT1"},{"id":"JAG1","name":"YUDFJULP-JAG1"},{"id":"YYY1","name":"UUUAIAAI-YYY1"},{"id":"BAN1","name":"VSDKYUTP-BAN1"},{"id":"DKJ1","name":"DKJSJDKA-DKJ1"},{"id":"MCS1","name":"ASACMAMS-MCS1"},{"id":"UIO1","name":"uioclli1-UIO1"},{"id":"RAJ1","name":"YGBIJNLQ-RAJ1"},{"id":"OPA1","name":"opaclli1-OPA1"},{"id":"SDE1","name":"ZXCVBNMA-SDE1"},{"id":"VEN2","name":"FGHJUHIL-VEN2"},{"id":"ORL1","name":"ORLDFLMA-ORL1"},{"id":"JAD1","name":"JADECLLI-JAD1"},{"id":"ZXL1","name":"LWLWCANN-ZXL1"},{"id":"CKL1","name":"CLKSKCKK-CKL1"},{"id":"SDF1","name":"sdfclli1-SDF1"},{"id":"RAD1","name":"RADICAL1-RAD1"},{"id":"KIT1","name":"BHYJFGLN-KIT1"},{"id":"REL1","name":"INGERFGT-REL1"},{"id":"JNL1","name":"CJALSDAC-JNL1"},{"id":"OLK1","name":"OLKOLKLS-OLK1"},{"id":"CHI1","name":"CHILLIWE-CHI1"},{"id":"UUU4","name":"UUUAAAUU-UUU4"},{"id":"TUF1","name":"TUFCLLI1-TUF1"},{"id":"KJN1","name":"CKALDKSA-KJN1"},{"id":"SAM1","name":"SNDGCA64-SAN1"},{"id":"SCK1","name":"SCKSCKSK-SCK1"},{"id":"HJH1","name":"AOEEQQQD-HJH1"},{"id":"HGD1","name":"SDFQWHGD-HGD1"},{"id":"KOR1","name":"HYFLNBVT-KOR1"},{"id":"ATL43","name":"AICLOCID-ATL43"},{"id":"ATL54","name":"AICFTAAI-ATL54"},{"id":"ATL66","name":"CLLIAAII-ATL66"},{"id":"VEL1","name":"BNMLKUIK-VEL1"},{"id":"ICC1","name":"SANJITAT-ICC1"},{"id":"MNT11","name":"WSXEFBTH-MNT11"},{"id":"DEF2","name":"WSBHGTYL-DEF2"},{"id":"MAD11","name":"SDFQWGKL-MAD11"},{"id":"OLG1","name":"OLHOLHOL-OLG1"},{"id":"GAR1","name":"NGFVSJKO-GAR1"},{"id":"SAN22","name":"GNVLSCTL-SAN22"},{"id":"HRG1","name":"HRGHRGGS-HRG1"},{"id":"JCS1","name":"JCSJSCJS-JCS1"},{"id":"DHA12","name":"WSXEDECF-DHA12"},{"id":"HJE1","name":"AOEEWWWD-HJE1"},{"id":"NCA1","name":"NCANCANN-NCA1"},{"id":"IOP1","name":"iopclli1-IOP1"},{"id":"RTY1","name":"rtyclli1-RTY1"},{"id":"KAP1","name":"HIOUYTRQ-KAP1"},{"id":"ZEN1","name":"ZENCLLI1-ZEN1"},{"id":"HKA1","name":"JAKHLASS-HKA1"},{"id":"CQK1","name":"CQKSCAKK-CQK1"},{"id":"SAI1","name":"UBEKQLPD-SAI1"},{"id":"ERT1","name":"ertclli1-ERT1"},{"id":"IBB1","name":"PLMKOIJU-IBB1"},{"id":"TIR2","name":"PLKINHYI-TIR2"},{"id":"HSD1","name":"CHASKCDS-HSD1"},{"id":"SLF78","name":"SDCTLFN1-SLF78"},{"id":"SEE78","name":"SDCTEEE4-SEE78"},{"id":"SAN13","name":"TOKYJPFA-SAN13"},{"id":"SAA78","name":"SDCTAAA1-SAA78"},{"id":"LUC1","name":"ATLDFGYC-LUC1"},{"id":"AMD13","name":"MEMATLAN-AMD13"},{"id":"TOR1","name":"TOROONXN-TOR1"},{"id":"QWE1","name":"QWECLLI1-QWE1"},{"id":"ZOG1","name":"ZOGASTRO-ZOG1"},{"id":"CAL33","name":"CALIFORN-CAL33"},{"id":"SHH78","name":"SDIT1HHH-SHH78"},{"id":"DSA1","name":"LKJHGFDS-DSA1"},{"id":"CLG1","name":"CLGRABAD-CLG1"},{"id":"BNA1","name":"BNARAGBK-BNA1"},{"id":"ATL84","name":"CANTTCOC-ATL84"},{"id":"APP1","name":"WBHGTYUI-APP1"},{"id":"RJN1","name":"RJNRBZAW-RJN1"},{"id":"EHH78","name":"SDCSHHH5-EHH78"},{"id":"mac10","name":"PKGTESTF-mac10"},{"id":"SXB78","name":"SDCTGXB1-SXB78"},{"id":"SAX78","name":"SDCTAXG1-SAX78"},{"id":"SYD1","name":"SYDNAUBV-SYD1"},{"id":"TOK1","name":"TOKYJPFA-TOK1"},{"id":"KGM2","name":"KGMTNC20-KGM2"},{"id":"DCC1b","name":"POIUYTGH-DCC1b"},{"id":"SKK78","name":"SDCTKKK1-SKK78"},{"id":"SGG78","name":"SDCTGGG1-SGG78"},{"id":"SJJ78","name":"SDCTJJJ1-SJJ78"},{"id":"SBX78","name":"SDCTBXG1-SBX78"},{"id":"LAG1","name":"LARGIZON-LAG1"},{"id":"IAA1","name":"QAZXSWED-IAA1"},{"id":"POI1","name":"PLMNJKIU-POI1"},{"id":"LAG1a","name":"LARGIZON-LAG1a"},{"id":"PBL1","name":"PBLAPBAI-PBL1"},{"id":"LAG45","name":"LARGIZON-LAG1a"},{"id":"MAR1","name":"MNBVCXZM-MAR1"},{"id":"HST70","name":"HSTNTX70-HST70"},{"id":"DCC1a","name":"POIUYTGH-DCC1a"},{"id":"TOL1","name":"TOLDOH21-TOL1"},{"id":"LON1","name":"LONEENCO-LON1"},{"id":"SJU78","name":"SDIT1JUB-SJU78"},{"id":"STN27","name":"HSTNTX01-STN27"},{"id":"SSW56","name":"ss8126GT-SSW56"},{"id":"SBB78","name":"SDIT1BBB-SBB78"},{"id":"DCC3","name":"POIUYTGH-DCC3"},{"id":"GNV1","name":"GNVLSCTL-GNV1"},{"id":"WAS1","name":"WASHDCSW-WAS1"},{"id":"TOY1","name":"TORYONNZ-TOY1"},{"id":"STT1","name":"STTLWA02-STT1"},{"id":"STG1","name":"STTGGE62-STG1"},{"id":"SLL78","name":"SDCTLLL1-SLL78"},{"id":"SBU78","name":"SDIT1BUB-SBU78"},{"id":"ATL2","name":"ATLNGANW-ATL2"},{"id":"BOT1","name":"BOTHWAKY-BOT1"},{"id":"SNG1","name":"SNGPSIAU-SNG1"},{"id":"NYC1","name":"NYCMNY54-NYC1"},{"id":"LAG1b","name":"LARGIZON-LAG1b"},{"id":"AMD15","name":"AMDFAA01-AMD15"},{"id":"SNA1","name":"SNANTXCA-SNA1"},{"id":"PLT1","name":"PLTNCA60-PLT1"},{"id":"TLP1","name":"TLPNXM18-TLP1"},{"id":"SDD81","name":"SAIT1DD6-SDD81"},{"id":"DCC1","name":"POIUYTGH-DCC1"},{"id":"DCC2","name":"POIUYTGH-DCC2"},{"id":"OKC1","name":"OKCBOK55-OKC1"},{"id":"PAR1","name":"PARSFRCG-PAR1"},{"id":"TES36","name":"ABCEETES-TES36"},{"id":"COM1","name":"PLMKOPIU-COM1"},{"id":"ANI1","name":"ATLNGTRE-ANI1"},{"id":"SDG78","name":"SDIT1BDG-SDG78"},{"id":"mac20","name":"PKGTESTF-mac20"},{"id":"DSF45","name":"DSFBG123-DSF45"},{"id":"HST25","name":"HSTNTX01-HST25"},{"id":"AMD18","name":"AUDIMA01-AMD18"},{"id":"SAA80","name":"SAIT9AA3-SAA80"},{"id":"SSA56","name":"SSIT2AA7-SSA56"},{"id":"SDD82","name":"SAIT1DD9-SDD82"},{"id":"JCV1","name":"JCVLFLBW-JCV1"},{"id":"SUL2","name":"WERTYUJK-SUL2"},{"id":"PUR1","name":"purelyde-PUR1"},{"id":"FDE55","name":"FDERT555-FDE55"},{"id":"SITE","name":"LONEENCO-SITE"},{"id":"ATL1","name":"ATLNGAMA-ATL1"},{"id":"JUL1","name":"ZXCVBNMM-JUL1"},{"id":"TAT34","name":"TESAAISB-TAT34"},{"id":"XCP12","name":"CHKGH123-XCP12"},{"id":"RAI1","name":"poiuytre-RAI1"},{"id":"HPO1","name":"ATLNGAUP-HPO1"},{"id":"KJF12","name":"KJFDH123-KJF12"},{"id":"SCC80","name":"SAIT9CC3-SCC80"},{"id":"SAA12","name":"SAIT9AF8-SAA12"},{"id":"SAA14","name":"SAIT1AA9-SAA14"},{"id":"ATL35","name":"TTESSAAI-ATL35"},{"id":"CWY1","name":"CWYMOWBS-CWY1"},{"id":"ATL76","name":"TELEPAAI-ATL76"},{"id":"DSL12","name":"DSLFK242-DSL12"},{"id":"ATL53","name":"AAIATLTE-ATL53"},{"id":"SAA11","name":"SAIT9AA2-SAA11"},{"id":"ATL62","name":"TESSASCH-ATL62"},{"id":"AUG1","name":"ASDFGHJK-AUG1"},{"id":"POI22","name":"POIUY123-POI22"},{"id":"SAA13","name":"SAIT1AA9-SAA13"},{"id":"BHY17","name":"BHYTFRF3-BHY17"},{"id":"LIS1","name":"HOSTPROF-LIS1"},{"id":"SIP1","name":"ZXCVBNMK-SIP1"},{"id":"ATL99","name":"TEESTAAI-ATL43"},{"id":"ATL64","name":"FORLOAAJ-ATL64"},{"id":"TAT33","name":"TESAAISA-TAT33"},{"id":"RAD10","name":"INDIPUNE-RAD10"},{"id":"RTW5","name":"BHYTFRY4-RTW5"},{"id":"JGS1","name":"KSJKKKKK-JGS1"},{"id":"ATL98","name":"TEESTAAI-ATL43"},{"id":"WAN1","name":"LEIWANGW-WAN1"},{"id":"ATL44","name":"ATLSANAB-ATL44"},{"id":"RTD2","name":"BHYTFRk4-RTD2"},{"id":"NIR1","name":"ORFLMANA-NIR1"},{"id":"ATL75","name":"SANAAIRE-ATL75"},{"id":"NUM1","name":"QWERTYUI-NUM1"},{"id":"MTN32","name":"MDTWNJ21-MTN32"},{"id":"RTZ4","name":"BHYTFRZ6-RTZ4"},{"id":"ATL56","name":"ATLSANAC-ATL56"},{"id":"AMS1","name":"AMSTNLBW-AMS1"},{"id":"RCT1","name":"AMSTERNL-RCT1"},{"id":"JAN1","name":"ORFLMATT-JAN1"},{"id":"ABC14","name":"TESAAISA-ABC14"},{"id":"TAT37","name":"TESAAISD-TAT37"},{"id":"MIC54","name":"MICHIGAN-MIC54"},{"id":"ABC11","name":"ATLSANAI-ABC11"},{"id":"AMF11","name":"AMDOCS01-AMF11"},{"id":"ATL63","name":"ATLSANEW-ATL63"},{"id":"ABC12","name":"ATLSECIA-ABC12"},{"id":"MTN20","name":"MDTWNJ21-MTN20"},{"id":"ABC15","name":"AAITESAN-ABC15"},{"id":"AVT1","name":"AVTRFLHD-AVT1"},{"id":"ATL34","name":"ATLSANAI-ATL34"}],"lcpRegions":[{"id":"AAIAIC25","name":"AAIAIC25","isPermitted":true},{"id":"mtn6","name":"mtn6","isPermitted":true}],"lcpRegionsTenantsMap":{},"tenants":[{"id":"bae71557c5bb4d5aac6743a4e5f1d054","name":"AIN Web Tool-15-D-testgamma","isPermitted":true},{"id":"229bcdc6eaeb4ca59d55221141d01f8e","name":"AIN Web Tool-15-D-STTest2","isPermitted":true},{"id":"1178612d2b394be4834ad77f567c0af2","name":"AIN Web Tool-15-D-SSPtestcustome","isPermitted":true},{"id":"19c5ade915eb461e8af52fb2fd8cd1f2","name":"AIN Web Tool-15-D-UncheckedEcopm","isPermitted":true},{"id":"de007636e25249238447264a988a927b","name":"AIN Web Tool-15-D-dfsdf","isPermitted":true},{"id":"62f29b3613634ca6a3065cbe0e020c44","name":"AIN/SMS-16-D-Multiservices1","isPermitted":true},{"id":"649289e30d3244e0b48098114d63c2aa","name":"AIN Web Tool-15-D-SSPST66","isPermitted":true},{"id":"3f21eeea6c2c486bba31dab816c05a32","name":"AIN Web Tool-15-D-ASSPST47","isPermitted":true},{"id":"f60ce21d3ee6427586cff0d22b03b773","name":"CESAR-100-D-sspjg67246","isPermitted":true},{"id":"8774659e425f479895ae091bb5d46560","name":"CESAR-100-D-sspjg68359","isPermitted":true},{"id":"624eb554b0d147c19ff8885341760481","name":"AINWebTool-15-D-iftach","isPermitted":true},{"id":"214f55f5fc414c678059c383b03e4962","name":"CESAR-100-D-sspjg612401","isPermitted":true},{"id":"c90666c291664841bb98e4d981ff1db5","name":"CESAR-100-D-sspjg621340","isPermitted":true},{"id":"ce5b6bc5c7b348e1bf4b91ac9a174278","name":"sspjg621351cloned","isPermitted":true},{"id":"b386b768a3f24c8e953abbe0b3488c02","name":"AINWebTool-15-D-eteancomp","isPermitted":true},{"id":"dc6c4dbfd225474e9deaadd34968646c","name":"AINWebTool-15-T-SPFET","isPermitted":true},{"id":"02cb5030e9914aa4be120bd9ed1e19eb","name":"AINWebTool-15-X-eeweww","isPermitted":true},{"id":"f2f3830e4c984d45bcd00e1a04158a79","name":"CESAR-100-D-spjg61909","isPermitted":true},{"id":"05b91bd5137f4929878edd965755c06d","name":"CESAR-100-D-sspjg621512cloned","isPermitted":true},{"id":"7002fbe8482d4a989ddf445b1ce336e0","name":"AINWebTool-15-X-vdr","isPermitted":true},{"id":"4008522be43741dcb1f5422022a2aa0b","name":"AINWebTool-15-D-ssasa","isPermitted":true},{"id":"f44e2e96a1b6476abfda2fa407b00169","name":"AINWebTool-15-D-PFNPT","isPermitted":true},{"id":"b69a52bec8a84669a37a1e8b72708be7","name":"AINWebTool-15-X-vdre","isPermitted":true},{"id":"fac7d9fd56154caeb9332202dcf2969f","name":"AINWebTool-15-X-NONPODECOMP","isPermitted":true},{"id":"2d34d8396e194eb49969fd61ffbff961","name":"DN5242-Nov16-T5","isPermitted":true},{"id":"cb42a77ff45b48a8b8deb83bb64acc74","name":"ro-T11","isPermitted":true},{"id":"fa45ca53c80b492fa8be5477cd84fc2b","name":"ro-T112","isPermitted":true},{"id":"4914ab0ab3a743e58f0eefdacc1dde77","name":"DN5242-Nov21-T1","isPermitted":true},{"id":"d0a3e3f2964542259d155a81c41aadc3","name":"test-mtn6-09","isPermitted":true},{"id":"cbb99fe4ada84631b7baf046b6fd2044","name":"DN5242-Nov16-T3","isPermitted":true}],"productFamilies":null,"projects":[{"id":"DFW","name":"DFW"},{"id":"x1","name":"x1"},{"id":"yyy1","name":"yyy1"}],"owningEntities":[{"id":"aaa1","name":"aaa1"},{"id":"d61e6f2d-12fa-4cc2-91df-7c244011d6fc","name":"MetroPacketCore"},{"id":"Wireline","name":"Wireline"}],"globalCustomerId":"e433710f-9217-458d-a79d-1c7aff376d89"}')}
+ }
+
+ function generateFormGroup(){
+ return 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])),
+ instanceName : new FormControl({value: null}, Validators.compose([Validators.required, NumbersLettersUnderscoreValidator.valid]))
+ });
+ }
+
+
+ function generateServiceInstanceDetails(){
+ return {
+ servicePopupDataModel : {
+ "productFamilies" : []
+ },
+ serviceInstanceDetailsFormGroup : {
+ controls : {
+ productFamilyId : {
+ disabled : false
+ }
+ }
+ }
+ }
+ }
+
+ function generateLegalServiceInstance(){
+ return {
+ instanceName : "legalInstanceName"
+ }
+ }
+
+ function generateIllegalServiceInstance(){
+ return {
+ instanceName : "illegalInstanceName"
+ }
+ }
+
+});
diff --git a/vid-webpack-master/src/app/components/service-popup/service-popup.service.ts b/vid-webpack-master/src/app/components/service-popup/service-popup.service.ts
new file mode 100644
index 000000000..f6efd353b
--- /dev/null
+++ b/vid-webpack-master/src/app/components/service-popup/service-popup.service.ts
@@ -0,0 +1,33 @@
+import {Injectable} from '@angular/core';
+import {isNullOrUndefined} from "util";
+import {NumbersLettersUnderscoreValidator} from '../../shared/components/validators/numbersLettersUnderscore/numbersLettersUnderscore.validator';
+import {ServiceInstanceDetailsComponent} from './service-instance-details/service-instance-details.component';
+import {FormGroup} from '@angular/forms';
+import * as _ from "lodash";
+
+@Injectable()
+export class ServicePopupService {
+ onControlError(serviceInstanceDetails : ServiceInstanceDetailsComponent, serviceInstanceDetailsFormGroup : FormGroup) : boolean{
+ if(!isNullOrUndefined(serviceInstanceDetailsFormGroup) && !isNullOrUndefined(serviceInstanceDetailsFormGroup.controls['instanceName']) && NumbersLettersUnderscoreValidator.valid(serviceInstanceDetailsFormGroup.controls['instanceName'].value) && serviceInstanceDetailsFormGroup.controls['instanceName'].value != null && serviceInstanceDetailsFormGroup.controls['instanceName'].value.length > 0){
+ return true;
+ }
+
+ const controlName : Array<string> = ['productFamilyId', 'lcpCloudRegionId', 'tenantId', 'owningEntityId', 'projectName', 'aicZoneId', 'subscriptionServiceType', 'globalSubscriberId', 'rollbackOnFailure'];
+ const selectDataName : Array<string> = ['productFamilies', 'lcpRegions', 'tenants', 'owningEntities', 'projects', 'aicZones', 'serviceTypes', 'subscribers', 'rollbackOnFailure'];
+ for(let i = 0 ; i < controlName.length ; i++){
+ if (!isNullOrUndefined(serviceInstanceDetails.servicePopupDataModel) && !isNullOrUndefined(serviceInstanceDetails.servicePopupDataModel[selectDataName[i]])) {
+ if (!serviceInstanceDetailsFormGroup.controls[controlName[i]].disabled && serviceInstanceDetails.servicePopupDataModel[selectDataName[i]].length === 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ resetDynamicInputs(serviceInstance : any, defaultDynamicInputs : any) : void {
+ for(let dynamicInput of serviceInstance.dynamicInputs){
+ const defaultDymanicInput = _.find(defaultDynamicInputs, {name:dynamicInput.name});
+ serviceInstance.serviceInstanceDetailsFormGroup.controls[dynamicInput.name].setValue(defaultDymanicInput.value);
+ }
+ }
+}