2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
22 import * as _ from "lodash";
24 PROPERTY_TYPES, ModalsHandler, ValidationUtils, PROPERTY_VALUE_CONSTRAINTS, FormState, PROPERTY_DATA} from "app/utils";
25 import {DataTypesService} from "app/services";
26 import {PropertyModel, DataTypesMap, Component, GroupInstance, PolicyInstance, PropertyBEModel} from "app/models";
27 import {ComponentInstance} from "../../../../models/componentsInstances/componentInstance";
28 import { ComponentInstanceServiceNg2 } from "app/ng2/services/component-instance-services/component-instance.service";
30 export interface IEditPropertyModel {
31 property:PropertyModel;
33 simpleTypes:Array<string>;
36 interface IPropertyFormViewModelScope extends ng.IScope {
38 editForm:ng.IFormController;
39 footerButtons:Array<any>;
43 validationPattern:RegExp;
44 propertyNameValidationPattern:RegExp;
45 commentValidationPattern:RegExp;
46 editPropertyModel:IEditPropertyModel;
47 modalInstanceProperty:ng.ui.bootstrap.IModalServiceInstance;
48 currentPropertyIndex:number;
49 isLastProperty:boolean;
51 nonPrimitiveTypes:Array<string>;
52 dataTypes:DataTypesMap;
53 isTypeDataType:boolean;
55 isPropertyValueOwner:boolean;
56 isVnfConfiguration:boolean;
58 validateJson(json:string):boolean;
59 save(doNotCloseModal?:boolean):void;
60 getValidationPattern(type:string):RegExp;
61 validateIntRange(value:string):boolean;
64 onSchemaTypeChange():void;
65 onTypeChange(resetSchema:boolean):void;
67 delete(property:PropertyModel):void;
70 isSimpleType(typeName:string):boolean;
71 getDefaultValue():any;
74 export class PropertyFormViewModel {
78 'Sdc.Services.DataTypesService',
82 'PropertyNameValidationPattern',
83 'CommentValidationPattern',
90 'isPropertyValueOwner',
93 'ComponentInstanceServiceNg2'
96 private formState:FormState;
98 constructor(private $scope:IPropertyFormViewModelScope,
99 private DataTypesService:DataTypesService,
100 private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance,
101 private property:PropertyModel,
102 private ValidationPattern:RegExp,
103 private PropertyNameValidationPattern:RegExp,
104 private CommentValidationPattern:RegExp,
105 private ValidationUtils:ValidationUtils,
106 private component:Component,
107 private $filter:ng.IFilterService,
108 private ModalsHandler:ModalsHandler,
109 private filteredProperties:Array<PropertyModel>,
110 private $timeout:ng.ITimeoutService,
111 private isPropertyValueOwner:boolean,
112 private propertyOwnerType:string,
113 private propertyOwnerId:string,
114 private ComponentInstanceServiceNg2: ComponentInstanceServiceNg2) {
116 this.formState = angular.isDefined(property.name) ? FormState.UPDATE : FormState.CREATE;
120 private initResource = ():void => {
121 this.$scope.editPropertyModel.property = new PropertyModel(this.property);
122 this.$scope.editPropertyModel.property.type = this.property.type ? this.property.type : null;
123 this.$scope.editPropertyModel.property.value = this.$scope.editPropertyModel.property.value || this.$scope.editPropertyModel.property.defaultValue;
125 this.initAddOnLabels();
128 //init property add-ons labels that show up at the left side of the input.
129 private initAddOnLabels = () => {
130 if (this.$scope.editPropertyModel.property.name == 'network_role' && this.$scope.isService) {
131 //the server sends back the normalized name. Remove it (to prevent interference with validation) and set the addon label to the component name directly.
132 //Note: this cant be done in properties.ts because we dont have access to the component
133 if (this.$scope.editPropertyModel.property.value) {
134 let splitProp = this.$scope.editPropertyModel.property.value.split(new RegExp(this.component.normalizedName + '.', "gi"));
135 this.$scope.editPropertyModel.property.value = splitProp.pop();
137 this.$scope.editPropertyModel.property.addOn = this.component.name;
141 private initEditPropertyModel = ():void => {
142 this.$scope.editPropertyModel = {
144 types: PROPERTY_DATA.TYPES,
145 simpleTypes: PROPERTY_DATA.SIMPLE_TYPES
151 private initForNotSimpleType = ():void => {
152 let property = this.$scope.editPropertyModel.property;
153 this.$scope.isTypeDataType = this.DataTypesService.isDataTypeForPropertyType(this.$scope.editPropertyModel.property);
154 if (property.type && this.$scope.editPropertyModel.simpleTypes.indexOf(property.type) == -1) {
155 if (!(property.value || property.defaultValue)) {
156 switch (property.type) {
157 case PROPERTY_TYPES.MAP:
158 this.$scope.myValue = {'': null};
160 case PROPERTY_TYPES.LIST:
161 this.$scope.myValue = [];
164 this.$scope.myValue = {};
167 this.$scope.myValue = JSON.parse(property.value || property.defaultValue);
172 private setMaxLength = ():void => {
173 switch (this.$scope.editPropertyModel.property.type) {
174 case PROPERTY_TYPES.MAP:
175 case PROPERTY_TYPES.LIST:
176 this.$scope.maxLength = this.$scope.editPropertyModel.property.schema.property.type == PROPERTY_TYPES.JSON ?
177 PROPERTY_VALUE_CONSTRAINTS.JSON_MAX_LENGTH :
178 PROPERTY_VALUE_CONSTRAINTS.MAX_LENGTH;
180 case PROPERTY_TYPES.JSON:
181 this.$scope.maxLength = PROPERTY_VALUE_CONSTRAINTS.JSON_MAX_LENGTH;
184 this.$scope.maxLength =PROPERTY_VALUE_CONSTRAINTS.MAX_LENGTH;
189 private initScope = ():void => {
192 this.$scope.forms = {};
193 this.$scope.validationPattern = this.ValidationPattern;
194 this.$scope.propertyNameValidationPattern = this.PropertyNameValidationPattern;
195 this.$scope.commentValidationPattern = this.CommentValidationPattern;
196 this.$scope.isLoading = false;
197 this.$scope.isNew = (this.formState === FormState.CREATE);
198 this.$scope.isService = this.component.isService();
199 this.$scope.modalInstanceProperty = this.$uibModalInstance;
200 this.$scope.currentPropertyIndex = _.findIndex(this.filteredProperties, i=> i.name == this.property.name);
201 this.$scope.isLastProperty = this.$scope.currentPropertyIndex == (this.filteredProperties.length - 1);
202 this.$scope.dataTypes = this.DataTypesService.getAllDataTypes();
203 this.$scope.isPropertyValueOwner = this.isPropertyValueOwner;
204 this.$scope.propertyOwnerType = this.propertyOwnerType;
205 this.initEditPropertyModel();
207 //check if property of VnfConfiguration
208 this.$scope.isVnfConfiguration = false;
209 if(this.propertyOwnerType == "component" && angular.isArray(this.component.componentInstances)) {
211 var componentPropertyOwner:ComponentInstance = this.component.componentInstances.find((ci:ComponentInstance) => {
212 return ci.uniqueId === this.property.resourceInstanceUniqueId;
214 if (componentPropertyOwner && componentPropertyOwner.componentName === 'vnfConfiguration') {
215 this.$scope.isVnfConfiguration = true;
219 this.$scope.nonPrimitiveTypes = _.filter(Object.keys(this.$scope.dataTypes), (type:string)=> {
220 return this.$scope.editPropertyModel.types.indexOf(type) == -1;
222 this.initForNotSimpleType();
225 this.$scope.validateJson = (json:string):boolean => {
229 return this.ValidationUtils.validateJson(json);
234 this.$scope.save = (doNotCloseModal?:boolean):void => {
235 let property:PropertyModel = this.$scope.editPropertyModel.property;
236 this.$scope.editPropertyModel.property.description = this.ValidationUtils.stripAndSanitize(this.$scope.editPropertyModel.property.description);
237 //if read only - or no changes made - just closes the modal
238 //need to check for property.value changes manually to detect if map properties deleted
239 if ((this.$scope.editPropertyModel.property.readonly && !this.$scope.isPropertyValueOwner)
240 || (!this.$scope.forms.editForm.$dirty && angular.equals(JSON.stringify(this.$scope.myValue), this.$scope.editPropertyModel.property.value))) {
241 this.$uibModalInstance.close();
245 this.$scope.isLoading = true;
247 let onPropertyFaild = (response):void => {
248 console.info('onFaild', response);
249 this.$scope.isLoading = false;
252 let onPropertySuccess = (propertyFromBE:PropertyModel):void => {
253 console.info('onPropertyResourceSuccess : ', propertyFromBE);
254 this.$scope.isLoading = false;
255 this.filteredProperties[this.$scope.currentPropertyIndex] = propertyFromBE;
256 if (!doNotCloseModal) {
257 this.$uibModalInstance.close(propertyFromBE);
259 this.$scope.forms.editForm.$setPristine();
260 this.$scope.editPropertyModel.property = new PropertyModel();
264 //Not clean, but doing this as a temporary fix until we update the property right panel modals
265 if(this.propertyOwnerType == "group"){
266 this.ComponentInstanceServiceNg2.updateComponentGroupInstanceProperties(this.component, this.propertyOwnerId, [property])
267 .subscribe((propertiesFromBE) => { onPropertySuccess(<PropertyModel>propertiesFromBE[0])}, error => onPropertyFaild);
268 } else if(this.propertyOwnerType == "policy"){
269 this.ComponentInstanceServiceNg2.updateComponentPolicyInstanceProperties(this.component, this.propertyOwnerId, [property])
270 .subscribe((propertiesFromBE) => { onPropertySuccess(<PropertyModel>propertiesFromBE[0])}, error => onPropertyFaild);
272 //in case we have uniqueId we call update method
273 if (this.$scope.isPropertyValueOwner) {
274 if (!this.$scope.editPropertyModel.property.simpleType && !this.$scope.isSimpleType(property.type)) {
275 let myValueString:string = JSON.stringify(this.$scope.myValue);
276 property.value = myValueString;
278 this.component.updateInstanceProperties(property.resourceInstanceUniqueId, [property]).then((propertiesFromBE) => onPropertySuccess(propertiesFromBE[0]), onPropertyFaild);
280 if (!this.$scope.editPropertyModel.property.simpleType && !this.$scope.isSimpleType(property.type)) {
281 let myValueString:string = JSON.stringify(this.$scope.myValue);
282 property.defaultValue = myValueString;
284 this.$scope.editPropertyModel.property.defaultValue = this.$scope.editPropertyModel.property.value;
286 this.component.addOrUpdateProperty(property).then(onPropertySuccess, onPropertyFaild);
291 this.$scope.getPrev = ():void=> {
292 this.property = this.filteredProperties[--this.$scope.currentPropertyIndex];
294 this.initForNotSimpleType();
295 this.$scope.isLastProperty = false;
298 this.$scope.getNext = ():void=> {
299 this.property = this.filteredProperties[++this.$scope.currentPropertyIndex];
301 this.initForNotSimpleType();
302 this.$scope.isLastProperty = this.$scope.currentPropertyIndex == (this.filteredProperties.length - 1);
305 this.$scope.isSimpleType = (typeName:string):boolean=> {
306 return typeName && this.$scope.editPropertyModel.simpleTypes.indexOf(typeName) != -1;
309 this.$scope.showSchema = ():boolean => {
310 return [PROPERTY_TYPES.LIST, PROPERTY_TYPES.MAP].indexOf(this.$scope.editPropertyModel.property.type) > -1;
313 this.$scope.getValidationPattern = (type:string):RegExp => {
314 return this.ValidationUtils.getValidationPattern(type);
317 this.$scope.validateIntRange = (value:string):boolean => {
318 return !value || this.ValidationUtils.validateIntRange(value);
321 this.$scope.close = ():void => {
322 this.$uibModalInstance.close();
325 // put default value when instance value is empty
326 this.$scope.onValueChange = ():void => {
327 if (!this.$scope.editPropertyModel.property.value) {
328 if (this.$scope.isPropertyValueOwner) {
329 this.$scope.editPropertyModel.property.value = this.$scope.editPropertyModel.property.defaultValue;
334 // Add the done button at the footer.
335 this.$scope.footerButtons = [
336 {'name': 'Save', 'css': 'blue', 'callback': this.$scope.save},
337 {'name': 'Cancel', 'css': 'grey', 'callback': this.$scope.close}
340 this.$scope.$watch("forms.editForm.$invalid", (newVal, oldVal) => {
341 this.$scope.footerButtons[0].disabled = this.$scope.forms.editForm.$invalid;
344 this.$scope.getDefaultValue = ():any => {
345 return this.$scope.isPropertyValueOwner ? this.$scope.editPropertyModel.property.defaultValue : null;
348 this.$scope.onTypeChange = ():void => {
349 this.$scope.editPropertyModel.property.value = '';
350 this.$scope.editPropertyModel.property.defaultValue = '';
352 this.initForNotSimpleType();
355 this.$scope.onSchemaTypeChange = ():void => {
356 if (this.$scope.editPropertyModel.property.type == PROPERTY_TYPES.MAP) {
357 this.$scope.myValue = {'': null};
358 } else if (this.$scope.editPropertyModel.property.type == PROPERTY_TYPES.LIST) {
359 this.$scope.myValue = [];
364 this.$scope.delete = (property:PropertyModel):void => {
365 let onOk = ():void => {
366 this.component.deleteProperty(property.uniqueId).then(
370 let title:string = this.$filter('translate')("PROPERTY_VIEW_DELETE_MODAL_TITLE");
371 let message:string = this.$filter('translate')("PROPERTY_VIEW_DELETE_MODAL_TEXT", "{'name': '" + property.name + "'}");
372 this.ModalsHandler.openConfirmationModal(title, message, false).then(onOk);