Other option for license agreement term 85/12185/1
authorilanap <ilanap@amdocs.com>
Wed, 13 Sep 2017 11:41:21 +0000 (14:41 +0300)
committerilanap <ilanap@amdocs.com>
Wed, 13 Sep 2017 12:00:13 +0000 (15:00 +0300)
Issue-Id: SDC-290

Change-Id: Ifeae84fd96175b656814e8b70bc67789f57ef78e
Signed-off-by: ilanap <ilanap@amdocs.com>
openecomp-ui/src/nfvo-components/input/inputOptions/InputOptions.jsx [deleted file]
openecomp-ui/src/nfvo-utils/Validator.js
openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.jsx
openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorReducer.js

diff --git a/openecomp-ui/src/nfvo-components/input/inputOptions/InputOptions.jsx b/openecomp-ui/src/nfvo-components/input/inputOptions/InputOptions.jsx
deleted file mode 100644 (file)
index e8aadc4..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/*!
- * 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.
- */
-import React from 'react';
-import i18n from 'nfvo-utils/i18n/i18n.js';
-import classNames from 'classnames';
-import Select from 'nfvo-components/input/SelectInput.jsx';
-
-export const other = {OTHER: 'Other'};
-
-class InputOptions extends React.Component {
-
-       static propTypes = {
-               values: React.PropTypes.arrayOf(React.PropTypes.shape({
-                       enum: React.PropTypes.string,
-                       title: React.PropTypes.string
-               })),
-               isEnabledOther: React.PropTypes.bool,
-               label: React.PropTypes.string,
-               selectedValue: React.PropTypes.string,
-               multiSelectedEnum: React.PropTypes.oneOfType([
-                       React.PropTypes.string,
-                       React.PropTypes.array
-               ]),
-               selectedEnum: React.PropTypes.string,
-               otherValue: React.PropTypes.string,
-               onEnumChange: React.PropTypes.func,
-               onOtherChange: React.PropTypes.func,
-               onBlur: React.PropTypes.func,
-               isRequired: React.PropTypes.bool,
-               isMultiSelect: React.PropTypes.bool,
-               hasError: React.PropTypes.bool,
-               disabled: React.PropTypes.bool
-       };
-
-
-       static contextTypes = {
-               isReadOnlyMode: React.PropTypes.bool
-       };
-
-       state = {
-               otherInputDisabled: !this.props.otherValue
-       };
-
-       oldProps = {
-               selectedEnum: '',
-               otherValue: '',
-               multiSelectedEnum: []
-       };
-
-       render() {
-               let {label, isRequired, values, otherValue, onOtherChange, isMultiSelect, onBlur, multiSelectedEnum, selectedEnum, hasError, validations, children} = this.props;
-               const dataTestId = this.props['data-test-id'] ? {'data-test-id': this.props['data-test-id']} : {};
-               let currentMultiSelectedEnum = [];
-               let currentSelectedEnum = '';
-               let {otherInputDisabled} = this.state;
-               if (isMultiSelect) {
-                       currentMultiSelectedEnum = multiSelectedEnum;
-                       if(!otherInputDisabled) {
-                               currentSelectedEnum = multiSelectedEnum ? multiSelectedEnum.toString() : undefined;
-                       }
-               }
-               else if(selectedEnum){
-                       currentSelectedEnum = selectedEnum;
-               }
-               if (!onBlur) {
-                       onBlur = () => {};
-               }
-
-               let isReadOnlyMode = this.context.isReadOnlyMode;
-
-               return(
-                       <div className={classNames('form-group', {'required' : (validations && validations.required) || isRequired, 'has-error' : hasError})}>
-                               {label && <label className='control-label'>{label}</label>}
-                               {isMultiSelect && otherInputDisabled ?
-                                       <Select
-                                               {...dataTestId}
-                                               ref='_myInput'
-                                               value={currentMultiSelectedEnum}
-                                               className='options-input'
-                                               clearable={false}
-                                               required={isRequired}
-                                               disabled={isReadOnlyMode || Boolean(this.props.disabled)}
-                                               onBlur={() => onBlur()}
-                                               onMultiSelectChanged={value => this.multiSelectEnumChanged(value)}
-                                               options={this.renderMultiSelectOptions(values)}
-                                               multi/> :
-                                       <div className={classNames('input-options',{'has-error' : hasError})}>
-                                               <select
-                                                       {...dataTestId}
-                                                       ref={'_myInput'}
-                                                       label={label}
-                                                       className='form-control input-options-select'
-                                                       value={currentSelectedEnum}
-                                                       style={{'width' : otherInputDisabled ? '100%' : '100px'}}
-                                                       onBlur={() => onBlur()}
-                                                       disabled={isReadOnlyMode || Boolean(this.props.disabled)}
-                                                       onChange={ value => this.enumChanged(value)}
-                                                       type='select'>
-                                                       {children || (values && values.length && values.map((val, index) => this.renderOptions(val, index)))}
-                                                       {onOtherChange && <option key='other' value={other.OTHER}>{i18n(other.OTHER)}</option>}
-                                               </select>
-
-                                               {!otherInputDisabled && <div className='input-options-separator'/>}
-                                               <input
-                                                       className='form-control input-options-other'
-                                                       placeholder={i18n('other')}
-                                                       ref='_otherValue'
-                                                       style={{'display' : otherInputDisabled ? 'none' : 'block'}}
-                                                       disabled={isReadOnlyMode || Boolean(this.props.disabled)}
-                                                       value={otherValue || ''}
-                                                       onBlur={() => onBlur()}
-                                                       onChange={() => this.changedOtherInput()}/>
-                                       </div>
-                               }
-                       </div>
-               );
-       }
-
-       renderOptions(val, index){
-               return (
-                       <option key={index} value={val.enum}>{val.title}</option>
-               );
-       }
-
-
-       renderMultiSelectOptions(values) {
-               let {onOtherChange} = this.props;
-               let optionsList = [];
-               if (onOtherChange) {
-                       optionsList = values.map(option => {
-                               return {
-                                       label: option.title,
-                                       value: option.enum,
-                               };
-                       }).concat([{
-                               label: i18n(other.OTHER),
-                               value: i18n(other.OTHER),
-                       }]);
-               }
-               else {
-                       optionsList = values.map(option => {
-                               return {
-                                       label: option.title,
-                                       value: option.enum,
-                               };
-                       });
-               }
-               if (optionsList.length > 0 && optionsList[0].value === '') {
-                       optionsList.shift();
-               }
-               return optionsList;
-       }
-
-       getValue() {
-               let res = '';
-               let {isMultiSelect} = this.props;
-               let {otherInputDisabled} = this.state;
-
-               if (otherInputDisabled) {
-                       res = isMultiSelect ? this.refs._myInput.getValue() : this.refs._myInput.value;
-               } else {
-                       res = this.refs._otherValue.value;
-               }
-               return res;
-       }
-
-       enumChanged() {
-               let enumValue = this.refs._myInput.value;
-               let {onEnumChange, onOtherChange, isMultiSelect, onChange} = this.props;
-               this.setState({
-                       otherInputDisabled: !Boolean(onOtherChange) || enumValue !== other.OTHER
-               });
-
-               let value = isMultiSelect ? [enumValue] : enumValue;
-               if (onEnumChange) {
-                       onEnumChange(value);
-               }
-               if (onChange) {
-                       onChange(value);
-               }
-       }
-
-       multiSelectEnumChanged(enumValue) {
-               let {onEnumChange, onOtherChange} = this.props;
-               let selectedValues = enumValue.map(enumVal => {
-                       return enumVal.value;
-               });
-
-               if (this.state.otherInputDisabled === false) {
-                       selectedValues.shift();
-               }
-               else if (selectedValues.includes(i18n(other.OTHER))) {
-                       selectedValues = [i18n(other.OTHER)];
-               }
-
-               this.setState({
-                       otherInputDisabled: !Boolean(onOtherChange) || !selectedValues.includes(i18n(other.OTHER))
-               });
-               onEnumChange(selectedValues);
-       }
-
-       changedOtherInput() {
-               let {onOtherChange} = this.props;
-               onOtherChange(this.refs._otherValue.value);
-       }
-
-       componentDidUpdate() {
-               let {otherValue, selectedEnum, onInputChange, multiSelectedEnum} = this.props;
-               if (this.oldProps.otherValue !== otherValue
-                       || this.oldProps.selectedEnum !== selectedEnum
-                       || this.oldProps.multiSelectedEnum !== multiSelectedEnum) {
-                       this.oldProps = {
-                               otherValue,
-                               selectedEnum,
-                               multiSelectedEnum
-                       };
-                       onInputChange();
-               }
-       }
-
-       static getTitleByName(values, name) {
-               for (let key of Object.keys(values)) {
-                       let option = values[key].find(option => option.enum === name);
-                       if (option) {
-                               return option.title;
-                       }
-               }
-               return name;
-       }
-
-}
-
-export default InputOptions;
index 1df82a2..3f6a00e 100644 (file)
@@ -46,7 +46,25 @@ class Validator {
                        email: value => ValidatorJS.isEmail(value),
                        ip: value => ValidatorJS.isIP(value),
                        url: value => ValidatorJS.isURL(value),
-                       alphanumericWithUnderscores: value => ValidatorJS.isAlphanumeric(value.replace(/_/g, ''))
+                       alphanumericWithUnderscores: value => ValidatorJS.isAlphanumeric(value.replace(/_/g, '')),
+                       requiredChoiceWithOther: (value, otherValue) => {
+                               let chosen = value.choice;
+                               // if we have an empty multiple select we have a problem since it's required
+                               let validationFunc = this.globalValidationFunctions['required'];
+                               if (value.choices) {
+                                       if (value.choices.length === 0) {
+                                               return  false;
+                                       } else {
+                                               // continuing validation with the first chosen value in case we have the 'Other' field
+                                               chosen = value.choices[0];
+                                       }
+                               }
+                               if (chosen !== otherValue) {
+                                       return validationFunc(chosen, true);
+                               } else { // when 'Other' was chosen, validate other value
+                                       return validationFunc(value.other, true);
+                               }
+                       }
                };
        }
 
@@ -54,6 +72,7 @@ class Validator {
                return {
                        required: () => i18n('Field is required'),
                        requiredChooseOption: () => i18n('Field should have one of these options'),
+                       requiredChoiceWithOther: () => i18n('Field is required'),
                        maxLength: (value, maxLength) => i18n('Field value has exceeded it\'s limit, {maxLength}. current length: {length}', {
                                length: value.length,
                                maxLength
index 2276984..49f1e3d 100644 (file)
@@ -16,7 +16,7 @@
 import {actionTypes} from './PlainDataReducerConstants.js';
 import Validator from 'nfvo-utils/Validator.js';
 import forOwn from 'lodash/forOwn.js';
-import {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
+import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
 
 function updateDataAndValidateReducer(state = {}, action) {
        let genericFieldInfoCopy;
index 5be1405..9cff279 100644 (file)
@@ -14,6 +14,7 @@
  * permissions and limitations under the License.
  */
 import {actionTypes, defaultState, LA_EDITOR_FORM, enums as LicenseAgreementEnums} from './LicenseAgreementConstants.js';
+import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
 
 export default (state = {}, action) => {
        switch (action.type) {
@@ -38,7 +39,7 @@ export default (state = {}, action) => {
                                        'licenseTerm' : {
                                                isValid: true,
                                                errorText: '',
-                                               validations: [{type: 'required', data: true}],
+                                               validations: [{type: 'required', data: true}, {type: 'requiredChoiceWithOther', data: optionInputOther.OTHER}],
                                                tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL
                                        },
                                        'name' : {
index a15e5da..0b41868 100644 (file)
@@ -21,9 +21,11 @@ import {TabsForm as Form} from 'nfvo-components/input/validation/Form.jsx';
 import Tabs from 'nfvo-components/input/validation/Tabs.jsx';
 import Tab from 'sdc-ui/lib/react/Tab.js';
 import Input from 'nfvo-components/input/validation/Input.jsx';
+import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx';
 import DualListboxView from 'nfvo-components/input/dualListbox/DualListboxView.jsx';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import Validator from 'nfvo-utils/Validator.js';
+import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
 
 import {enums as LicenseAgreementEnums, optionsInputValues as LicenseAgreementOptionsInputValues, LA_EDITOR_FORM} from './LicenseAgreementConstants.js';
 
@@ -43,7 +45,7 @@ const LicenseAgreementPropType = React.PropTypes.shape({
 });
 
 
-const GeneralTabContent = ({data, genericFieldInfo, onDataChanged, validateName, validateLTChoice}) => {
+const GeneralTabContent = ({data, genericFieldInfo, onDataChanged, validateName}) => {
        let {name, description, requirementsAndConstrains, licenseTerm} = data;
        return (
                <GridSection>
@@ -67,24 +69,22 @@ const GeneralTabContent = ({data, genericFieldInfo, onDataChanged, validateName,
                                        data-test-id='create-la-requirements-constants'
                                        name='license-agreement-requirements-and-constraints'
                                        type='textarea'/>
-                               <Input
+                               <InputOptions
+                                       onInputChange={()=>{}}
+                                       isMultiSelect={false}
+                                       onEnumChange={licenseTerm => onDataChanged({licenseTerm:{choice: licenseTerm, other: ''}},
+                                               LA_EDITOR_FORM)}
+                                       onOtherChange={licenseTerm => onDataChanged({licenseTerm:{choice: optionInputOther.OTHER,
+                                               other: licenseTerm}}, LA_EDITOR_FORM)}
                                        label={i18n('License Term')}
-                                       type='select'
-                                       value={licenseTerm && licenseTerm.choice}
+                                       data-test-id='create-la-license-term'
                                        isRequired={true}
-                                       onChange={e => {
-                                               const selectedIndex = e.target.selectedIndex;
-                                               const licenseTerm = e.target.options[selectedIndex].value;
-                                               onDataChanged({licenseTerm:{choice: licenseTerm, other: ''}}, LA_EDITOR_FORM, { licenseTerm: validateLTChoice });
-                                       }}
+                                       type='select'
+                                       selectedEnum={licenseTerm && licenseTerm.choice}
+                                       otherValue={licenseTerm && licenseTerm.other}
+                                       values={LicenseAgreementOptionsInputValues.LICENSE_MODEL_TYPE}
                                        isValid={genericFieldInfo.licenseTerm.isValid}
-                                       errorText={genericFieldInfo.licenseTerm.errorText}
-                                       className='input-options-select'
-                                       groupClassName='bootstrap-input-options'
-                                       data-test-id='create-la-license-term' >
-                                       {LicenseAgreementOptionsInputValues.LICENSE_MODEL_TYPE.map(mtype =>
-                                               <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
-                               </Input>
+                                       errorText={genericFieldInfo.licenseTerm.errorText} />
                        </GridItem>
                        <GridItem colSpan={2} stretch>
                                <Input
@@ -151,7 +151,7 @@ class LicenseAgreementEditorView extends React.Component {
                                                        data-test-id='general-tab'
                                                        title={i18n('General')}>
                                                                <fieldset disabled={isReadOnlyMode}>
-                                                                       <GeneralTabContent data={data} genericFieldInfo={genericFieldInfo} onDataChanged={onDataChanged} validateLTChoice={(value)=>this.validateLTChoice(value)}
+                                                                       <GeneralTabContent data={data} genericFieldInfo={genericFieldInfo} onDataChanged={onDataChanged}
                                                                                   validateName={(value)=>this.validateName(value)}/>
                                                                </fieldset>
                                                </Tab>
@@ -181,12 +181,6 @@ class LicenseAgreementEditorView extends React.Component {
                this.props.onSubmit({licenseAgreement, previousLicenseAgreement});
        }
 
-       validateLTChoice(value) {
-               if (!value.choice) {
-                       return {isValid: false, errorText: i18n('Field is required')};
-               }
-               return {isValid: true, errorText: ''};
-       }
 
        validateName(value) {
                const {data: {id}, LANames} = this.props;
index 5c4e50d..d4b7e5c 100644 (file)
@@ -7,7 +7,7 @@ import GridItem from 'nfvo-components/grid/GridItem.jsx';
 import {LIMITS_FORM_NAME, selectValues} from './LimitEditorConstants.js';
 import Button from 'sdc-ui/lib/react/Button.js';
 import Validator from 'nfvo-utils/Validator.js';
-import {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
+import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
 import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx';
 
 const LimitPropType = React.PropTypes.shape({
@@ -96,9 +96,9 @@ class LimitEditor extends React.Component {
                                                                isMultiSelect={false}
                                                                isRequired={true}
                                                                onEnumChange={metric => onDataChanged({metric:{choice: metric, other: ''}},
-                                                                       LIMITS_FORM_NAME, {metric: this.validateChoiceWithOther})}
+                                                                       LIMITS_FORM_NAME)}
                                                                onOtherChange={metric => onDataChanged({metric:{choice: optionInputOther.OTHER,
-                                                                       other: metric}}, LIMITS_FORM_NAME, {metric: this.validateChoiceWithOther})}
+                                                                       other: metric}}, LIMITS_FORM_NAME)}
                                                                label={i18n('Metric')}
                                                                data-test-id='limit-editor-metric'
                                                                type='select'
@@ -196,23 +196,6 @@ class LimitEditor extends React.Component {
                {isValid: false, errorText: i18n('Limit by the name \'' + value + '\' already exists. Limit name must be unique')};
        }
 
-       validateChoiceWithOther(value) {
-               let chosen = value.choice;
-               // if we have an empty multiple select we have a problem since it's required
-               if (value.choices) {
-                       if (value.choices.length === 0) {
-                               return  Validator.validate('field', '', [{type: 'required', data: true}]);
-                       } else {
-                               // continuing validation with the first chosen value in case we have the 'Other' field
-                               chosen = value.choices[0];
-                       }
-               }
-               if (chosen !== optionInputOther.OTHER) {
-                       return  Validator.validate('field', chosen, [{type: 'required', data: true}]);
-               } else { // when 'Other' was chosen, validate other value
-                       return  Validator.validate('field', value.other, [{type: 'required', data: true}]);
-               }
-       }
 
        submit() {
                if (!this.props.formReady) {
index de9e7c8..99d94a0 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 import {actionTypes, LIMITS_FORM_NAME, defaultState} from './LimitEditorConstants.js';
+import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
 
 export default (state = {}, action) => {
        switch (action.type) {
@@ -38,7 +39,7 @@ export default (state = {}, action) => {
                                        'metric' : {
                                                isValid: true,
                                                errorText: '',
-                                               validations: []
+                                               validations: [{type: 'required', data: true}, {type: 'requiredChoiceWithOther', data: optionInputOther.OTHER}]
                                        },
                                        'value' : {
                                                isValid: true,