diff options
author | Michael Lando <ml636r@att.com> | 2017-02-19 10:28:42 +0200 |
---|---|---|
committer | Michael Lando <ml636r@att.com> | 2017-02-19 10:51:01 +0200 |
commit | 451a3400b76511393c62a444f588a4ed15f4a549 (patch) | |
tree | e4f5873a863d1d3e55618eab48b83262f874719d /catalog-ui/app/scripts/view-models/wizard/property-form | |
parent | 5abfe4e1fb5fae4bbd5fbc340519f52075aff3ff (diff) |
Initial OpenECOMP SDC commit
Change-Id: I0924d5a6ae9cdc161ae17c68d3689a30d10f407b
Signed-off-by: Michael Lando <ml636r@att.com>
Diffstat (limited to 'catalog-ui/app/scripts/view-models/wizard/property-form')
4 files changed, 553 insertions, 0 deletions
diff --git a/catalog-ui/app/scripts/view-models/wizard/property-form/property-form-view-model-tests.ts b/catalog-ui/app/scripts/view-models/wizard/property-form/property-form-view-model-tests.ts new file mode 100644 index 0000000000..3f390841ca --- /dev/null +++ b/catalog-ui/app/scripts/view-models/wizard/property-form/property-form-view-model-tests.ts @@ -0,0 +1,163 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +/// <reference path="../../../references"/> + +describe("property form View Model ", () => { + + let $controllerMock:ng.IControllerService; + let $qMock:ng.IQService; + let $httpBackendMock:ng.IHttpBackendService; + let $scopeMock:Sdc.ViewModels.Wizard.IPropertyFormViewModelScope; + let $stateMock:ng.ui.IStateService; + let $stateParams:any; + let component = { + "uniqueId": "ece818e0-fd59-477a-baf6-e27461a7ce23", + "uuid": "8db823c2-6a9c-4636-8676-f5e713270dd7", + "contactId": "uf2345", + "category": "Network Layer 2-3/Router", + "creationDate": 1447235352429, + "description": "u", + "highestVersion": true, + "icon": "network", + "lastUpdateDate": 1447235370064, + "lastUpdaterUserId": "cs0008", + "lastUpdaterFullName": "Carlos Santana", + "lifecycleState": "NOT_CERTIFIED_CHECKOUT", + "name": "u", + "version": "0.1", + "type": 1, + "tags": [ + "u" + ], + "vendorName": "u", + "vendorRelease": "u", + "systemName": "U", + "$$hashKey": "object:34" + }; + + + beforeEach(angular.mock.module('sdcApp')); + + beforeEach(angular.mock.inject((_$controller_:ng.IControllerService, + _$httpBackend_:ng.IHttpBackendService, + _$rootScope_, + _$q_:ng.IQService, + _$state_:ng.ui.IStateService, + _$stateParams_:any) => { + + $controllerMock = _$controller_; + $httpBackendMock = _$httpBackend_ + $scopeMock = _$rootScope_.$new(); + $qMock = _$q_; + $stateMock = _$state_; + $stateParams = _$stateParams_; + + + //handle all http request thet not relevant to the tests + $httpBackendMock.expectGET(/.*languages\/en_US.json.*/).respond(200, JSON.stringify({})); + // $httpBackendMock.expectGET(/.*resources\/certified\/abstract.*/).respond(200, JSON.stringify({})); + $httpBackendMock.expectGET(/.*rest\/version.*/).respond(200, JSON.stringify({})); + $httpBackendMock.expectGET(/.*configuration\/ui.*/).respond(200, JSON.stringify({})); + $httpBackendMock.expectGET(/.*user\/authorize.*/).respond(200, JSON.stringify({})); + $httpBackendMock.expectGET(/.*categories\/services.*/).respond(200, JSON.stringify({})); + $httpBackendMock.expectGET(/.*categories\/resources.*/).respond(200, JSON.stringify({})); + $httpBackendMock.expectGET(/.*categories\/products.*/).respond(200, JSON.stringify({})); + $httpBackendMock.expectGET('http://feHost:8181/sdc1/feProxy/rest/version').respond(200, JSON.stringify({})); + + /** + * Mock the service + * @type {any} + */ + //getAllEntitiesDefered = $qMock.defer(); + //getAllEntitiesDefered.resolve(getAllEntitiesResponseMock); + //entityServiceMock = jasmine.createSpyObj('entityServiceMock', ['getAllComponents']); + //entityServiceMock.getAllComponents.and.returnValue(getAllEntitiesDefered.promise); + + // $stateParams['show'] = ''; + + /** + * Need to inject into the controller only the objects that we want to MOCK + * those that we need to change theirs behaviors + */ + $controllerMock(Sdc.ViewModels.Wizard.PropertyFormViewModel, { + '$scope': $scopeMock, + 'property': new Sdc.Models.PropertyModel(), + 'component': component, + }); + + })); + + describe("when Controller 'PropertyFormViewModel' created", () => { + + it('should have a regexp per each type', () => { + $scopeMock.$apply(); + expect(Object.keys($scopeMock.listRegex).length).toBe($scopeMock.editPropertyModel["simpleTypes"].length); + }); + + it('should have equal regexps for map and list', () => { + $scopeMock.$apply(); + expect(Object.keys($scopeMock.listRegex).length).toBe(Object.keys($scopeMock.mapRegex).length); + }); + + }); + + /*describe("when Controller 'DashboardViewModel' created", () => { + + it('should generate all entities', () => { + $scopeMock.$apply(); + expect($scopeMock.components.length).toBe(getAllEntitiesResponseMock.length); + }); + + + it('should show tutorial page ', () => { + $stateParams.show = 'tutorial'; + + $controllerMock(Sdc.ViewModels.DashboardViewModel, { + '$scope': $scopeMock, + '$stateParams': $stateParams, + 'Sdc.Services.EntityService': entityServiceMock, + //to complete injects + }); + + $scopeMock.$apply(); + expect($scopeMock.isFirstTime).toBeTruthy(); + expect($scopeMock.showTutorial).toBeTruthy(); + }); + + }); + + + describe("when function 'entitiesCount' invoked", () => { + + beforeEach(() => { + $controllerMock(Sdc.ViewModels.DashboardViewModel, { + '$scope': $scopeMock, + 'Sdc.Services.EntityService': entityServiceMock, + }); + $scopeMock.$apply(); + }); + + it('should return entities count per folder', () => { + + }); + + + });*/ +}); diff --git a/catalog-ui/app/scripts/view-models/wizard/property-form/property-form-view-model.ts b/catalog-ui/app/scripts/view-models/wizard/property-form/property-form-view-model.ts new file mode 100644 index 0000000000..5cb0ef1ddd --- /dev/null +++ b/catalog-ui/app/scripts/view-models/wizard/property-form/property-form-view-model.ts @@ -0,0 +1,250 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +/// <reference path="../../../references"/> + +module Sdc.ViewModels.Wizard { + 'use strict'; + + export interface IEditPropertyModel{ + property: Models.PropertyModel; + types: Array<string>; + simpleTypes: Array<string>; + sources: Array<string>; + } + + export interface IPropertyFormViewModelScope extends ng.IScope{ + + $$childTail: any; + editForm:ng.IFormController; + forms:any; + footerButtons: Array<any>; + isNew: boolean; + isLoading: boolean; + validationPattern: RegExp; + propertyNameValidationPattern: RegExp; + integerValidationPattern: RegExp; + floatValidationPattern: RegExp; + commentValidationPattern: RegExp; + listRegex: Sdc.Utils.IMapRegex; + mapRegex: Sdc.Utils.IMapRegex; + editPropertyModel: IEditPropertyModel; + modalInstanceProperty: ng.ui.bootstrap.IModalServiceInstance; + save(doNotCloseModal?: boolean): void; + saveAndAnother(): void; + getValidation(): RegExp; + validateIntRange(value:string):boolean; + close(): void; + onValueChange(): void; + onTypeChange(resetSchema:boolean): void; + showSchema(): boolean; + getValidationTranslate():string; + validateUniqueKeys(viewValue:string):boolean; + } + + export class PropertyFormViewModel{ + + private originalValue: string; + + static '$inject' = [ + '$scope', + '$modalInstance', + 'property', + 'ValidationPattern', + 'PropertyNameValidationPattern', + 'IntegerNoLeadingZeroValidationPattern', + 'FloatValidationPattern', + 'CommentValidationPattern', + 'ValidationUtils', + 'component' + ]; + + private formState: Utils.Constants.FormState; + private entityId: string; + private resourceInstanceUniqueId: string; + private readonly: boolean; + + constructor( + private $scope:IPropertyFormViewModelScope, + private $modalInstance: ng.ui.bootstrap.IModalServiceInstance, + private property : Models.PropertyModel, + private ValidationPattern : RegExp, + private PropertyNameValidationPattern: RegExp, + private IntegerNoLeadingZeroValidationPattern : RegExp, + private FloatValidationPattern : RegExp, + private CommentValidationPattern: RegExp, + private ValidationUtils: Sdc.Utils.ValidationUtils, + private component:Models.Components.Component + ){ + this.entityId = this.component.uniqueId; + this.formState = angular.isDefined(property.name) ? Utils.Constants.FormState.UPDATE : Utils.Constants.FormState.CREATE; + this.initScope(); + } + + + private initResource = (): void => { + this.$scope.editPropertyModel.property = new Sdc.Models.PropertyModel(this.property); + this.originalValue = this.property.defaultValue; + if(this.$scope.editPropertyModel.types.indexOf(this.property.type) === -1 && !this.$scope.isNew){ + this.property.type = "string"; + } + }; + + private initEditPropertyModel = (): void => { + this.$scope.editPropertyModel = { + property: null, + types: ['integer', 'string', 'float', 'boolean', 'list', 'map'], + simpleTypes: ['integer', 'string', 'float', 'boolean'], + sources: ['A&AI', 'Order', 'Runtime'] + }; + + this.initResource(); + }; + + private initScope = (): void => { + + this.$scope.modalInstanceProperty = this.$modalInstance; + //scope properties + this.$scope.validationPattern = this.ValidationPattern; + this.$scope.propertyNameValidationPattern = this.PropertyNameValidationPattern; + this.$scope.integerValidationPattern = this.IntegerNoLeadingZeroValidationPattern; + this.$scope.floatValidationPattern = this.FloatValidationPattern; + this.$scope.commentValidationPattern = this.CommentValidationPattern; + + //map & list validation patterns + this.$scope.listRegex = this.ValidationUtils.getPropertyListPatterns(); + this.$scope.mapRegex = this.ValidationUtils.getPropertyMapPatterns(); + + this.$scope.isLoading = false; + this.$scope.isNew = (this.formState === Utils.Constants.FormState.CREATE); + this.initEditPropertyModel(); + + //scope methods + this.$scope.save = (): void => { + this.$scope.editPropertyModel.property.description = this.ValidationUtils.stripAndSanitize(this.$scope.editPropertyModel.property.description); + this.$scope.isLoading = true; + + let onFailed = (response) => { + console.info('onFaild',response); + this.$scope.isLoading = false; + this.$scope.editPropertyModel.property.readonly = this.readonly; + this.$scope.editPropertyModel.property.resourceInstanceUniqueId = this.resourceInstanceUniqueId; + }; + + let onSuccess = (property: Models.PropertyModel): void => { + console.info('property added : ',property); + this.$scope.isLoading = false; + property.resourceInstanceUniqueId = this.resourceInstanceUniqueId; + property.readonly = (property.parentUniqueId !== this.component.uniqueId) /*|| this.component.isService()*/; + + this.$modalInstance.close(); + }; + + this.resourceInstanceUniqueId = this.$scope.editPropertyModel.property.resourceInstanceUniqueId; + this.readonly = this.$scope.editPropertyModel.property.readonly; + this.$scope.editPropertyModel.property.defaultValue = this.$scope.editPropertyModel.property.defaultValue ? this.$scope.editPropertyModel.property.defaultValue:null; + + this.component.addOrUpdateProperty(this.$scope.editPropertyModel.property).then(onSuccess, onFailed); + }; + + this.$scope.saveAndAnother = (): void => { + this.$scope.save(); + }; + + this.$scope.showSchema = () :boolean => { + return ['list', 'map'].indexOf(this.$scope.editPropertyModel.property.type) > -1; + }; + + this.$scope.getValidationTranslate = () : string => { + let result = "PROPERTY_EDIT_PATTERN"; + if (this.$scope.showSchema()) { + + result = "PROPERTY_EDIT_" + this.$scope.editPropertyModel.property.type.toUpperCase(); + + if(this.$scope.editPropertyModel.property.schema.property.type === 'string') { + result += "_STRING"; + } else { + result += "_GENERIC"; + } + } + + return result; + }; + + this.$scope.getValidation = () : RegExp => { + let type = this.$scope.editPropertyModel.property.type; + switch (type){ + case 'integer': + return this.$scope.integerValidationPattern; + case 'float': + return this.$scope.floatValidationPattern; + case 'list': + return this.$scope.listRegex[this.$scope.editPropertyModel.property.schema.property.type]; + case 'map': + return this.$scope.mapRegex[this.$scope.editPropertyModel.property.schema.property.type]; + default : + return null; + } + }; + + this.$scope.validateUniqueKeys = (viewValue:string) : boolean => { + if(this.$scope.editPropertyModel.property.type === 'map') { + return this.ValidationUtils.validateUniqueKeys(viewValue); + } + else { + return true; //always valid if not a map + } + }; + + this.$scope.validateIntRange = (value:string):boolean => { + return !value || this.ValidationUtils.validateIntRange(value); + }; + + this.$scope.close = (): void => { + this.$modalInstance.close(); + }; + + this.$scope.onValueChange = (): void => { + if(!this.$scope.editPropertyModel.property.defaultValue && this.$scope.editPropertyModel.property.required) { + this.$scope.editPropertyModel.property.defaultValue = this.originalValue; + } + }; + + this.$scope.onTypeChange = (resetSchema:boolean): void => { + this.$scope.editPropertyModel.property.defaultValue = ''; + if (resetSchema) { + this.$scope.editPropertyModel.property.schema.property.type = ''; + } + }; + + //new form layout for import asset + this.$scope.forms = {}; + this.$scope.footerButtons = [ + {'name': this.$scope.isNew ? 'Add' : 'Update', 'css':'blue', 'callback': this.$scope.save}, + {'name':'Cancel', 'css':'grey', 'callback': this.$scope.close} + ]; + + this.$scope.$watch('forms.editForm.$invalid', () => { + this.$scope.footerButtons[0].disabled = this.$scope.forms.editForm.$invalid; + }); + + } + + } +} diff --git a/catalog-ui/app/scripts/view-models/wizard/property-form/property-form.html b/catalog-ui/app/scripts/view-models/wizard/property-form/property-form.html new file mode 100644 index 0000000000..be237112a4 --- /dev/null +++ b/catalog-ui/app/scripts/view-models/wizard/property-form/property-form.html @@ -0,0 +1,133 @@ +<sdc-modal modal="modalInstanceProperty" type="classic" class="sdc-add-property" buttons="footerButtons" header="{{isNew ? 'Add' : 'Update' }} Property" show-close-button="true"> + + <form novalidate class="w-sdc-form two-columns" name="forms.editForm" > + + <div class="w-sdc-form-columns-wrapper"> + + <div class="w-sdc-form-column"> + + <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.propertyName.$dirty && forms.editForm.propertyName.$invalid)}"> + <label class="i-sdc-form-label" ng-class="{'required': !isService}">Name</label> + <input class="i-sdc-form-input" + data-ng-maxlength="50" + data-ng-disabled="!isNew || editPropertyModel.property.readonly" + maxlength="50" + data-ng-model="editPropertyModel.property.name" + type="text" + name="propertyName" + data-ng-pattern="propertyNameValidationPattern" + data-required + data-ng-model-options="{ debounce: 200 }" + data-tests-id="propertyName" + autofocus /> + + <div class="input-error" data-ng-show="forms.editForm.propertyName.$dirty && forms.editForm.propertyName.$invalid"> + <span ng-show="forms.editForm.propertyName.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Property name' }"></span> + <span ng-show="forms.editForm.propertyName.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '128' }"></span> + <span ng-show="forms.editForm.propertyName.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span> + </div> + </div> + + + <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.schemaType.$dirty && forms.editForm.schemaType.$invalid)}" + data-ng-if="showSchema()"> + <label class="i-sdc-form-label required">Entry Schema</label> + <select class="i-sdc-form-select" + data-required + name="schemaType" + data-tests-id="schemaType" + data-ng-change="onTypeChange(false)" + data-ng-model="editPropertyModel.property.schema.property.type" + data-ng-options="type for type in editPropertyModel.simpleTypes"> + <option value="">Choose Schema Type</option> + </select> + + <div class="input-error" data-ng-show="forms.editForm.schemaType.$dirty && forms.editForm.schemaType.$invalid"> + <span ng-show="forms.editForm.schemaType.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Entry schema' }"></span> + </div> + </div> + + + <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.value.$dirty && forms.editForm.value.$invalid)}"> + <label class="i-sdc-form-label">Default Value</label> + <input class="i-sdc-form-input" + ng-if="!(editPropertyModel.property.type == 'boolean')" + data-ng-maxlength="100" + data-ng-disableddddddd="editPropertyModel.property.readonly && !isService && !isPropertyValueOwner()" + maxlength="100" + data-ng-model="editPropertyModel.property.defaultValue" + type="text" + name="value" + data-custom-validation="" data-validation-func="validateUniqueKeys" + data-ng-pattern="getValidation()" + data-ng-model-options="{ debounce: 200 }" + data-ng-change="!forms.editForm.value.$error.pattern && ('integer'==editPropertyModel.property.type && forms.editForm.value.$setValidity('pattern', validateIntRange(editPropertyModel.property.defaultValue)) || onValueChange())" + data-tests-id="defaultValue" + autofocus /> + <select class="i-sdc-form-select" + ng-if="editPropertyModel.property.type == 'boolean'" + data-ng-disabled="editPropertyModel.property.readonly && !isPropertyValueOwner()" + name="value" + data-ng-change="onValueChange()" + data-ng-model="editPropertyModel.property.defaultValue"> + <option value=""></option> + <option value="true">true</option> + <option value="false">false</option> + </select> + + <div class="input-error" data-ng-show="forms.editForm.value.$dirty && forms.editForm.value.$invalid"> + <span ng-show="forms.editForm.value.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Property' }"></span> + <span ng-show="forms.editForm.value.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '100' }"></span> + <span ng-show="forms.editForm.value.$error.pattern" translate="{{getValidationTranslate()}}"></span> + <span ng-show="forms.editForm.value.$error.customValidation" translate="PROPERTY_EDIT_MAP_UNIQUE_KEYS"></span> + </div> + </div> + + </div> + + <div class="w-sdc-form-column"> + + <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.type.$dirty && forms.editForm.type.$invalid)}"> + <label class="i-sdc-form-label" ng-class="{'required': !isService}">Type</label> + <select class="i-sdc-form-select" + data-required + data-ng-disableddddddd="editPropertyModel.property.readonly" + data-tests-id="propertyType" + name="type" + data-ng-change="onTypeChange(true)" + data-ng-model="editPropertyModel.property.type" + data-ng-options="type for type in editPropertyModel.types"> + <option value="">Choose Type</option> + </select> + + <div class="input-error" data-ng-show="forms.editForm.type.$dirty && forms.editForm.type.$invalid"> + <span ng-show="forms.editForm.type.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Type' }"></span> + </div> + </div> + + <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm.description.$dirty && forms.editForm.description.$invalid)}"> + <label class="i-sdc-form-label">Description</label> + <textarea class="i-sdc-form-textarea" + data-ng-maxlength="256" + data-ng-disableddddddd="editPropertyModel.property.readonly" + maxlength="256" + data-ng-pattern="commentValidationPattern" + name="description" + data-ng-model="editPropertyModel.property.description" + data-ng-model-options="{ debounce: 200 }" + data-tests-id="description" + ></textarea> + + <div class="input-error" data-ng-show="forms.editForm.description.$dirty && forms.editForm.description.$invalid"> + <span ng-show="forms.editForm.description.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '256' }"></span> + <span ng-show="forms.editForm.description.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span> + <span ng-show="forms.editForm.description.$error.required" translate="VALIDATION_ERROR_REQUIRED" translate-values="{'field': 'Description' }"></span> + </div> + </div> + + </div> + + </div> + </form> + +</sdc-modal> diff --git a/catalog-ui/app/scripts/view-models/wizard/property-form/property-form.less b/catalog-ui/app/scripts/view-models/wizard/property-form/property-form.less new file mode 100644 index 0000000000..52b8564fdb --- /dev/null +++ b/catalog-ui/app/scripts/view-models/wizard/property-form/property-form.less @@ -0,0 +1,7 @@ +.sdc-add-property{ + + .w-sdc-form { + + } + +} |