Other option for license agreement term
Issue-Id: SDC-290
Change-Id: Ifeae84fd96175b656814e8b70bc67789f57ef78e
Signed-off-by: ilanap <ilanap@amdocs.com>
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
index e8aadc4..0000000
--- a/openecomp-ui/src/nfvo-components/input/inputOptions/InputOptions.jsx
+++ /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;
diff --git a/openecomp-ui/src/nfvo-utils/Validator.js b/openecomp-ui/src/nfvo-utils/Validator.js
index 1df82a2..3f6a00e 100644
--- a/openecomp-ui/src/nfvo-utils/Validator.js
+++ b/openecomp-ui/src/nfvo-utils/Validator.js
@@ -46,7 +46,25 @@
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 @@
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
diff --git a/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js b/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js
index 2276984..49f1e3d 100644
--- a/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js
+++ b/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js
@@ -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;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js
index 5be1405..9cff279 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js
@@ -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 @@
'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' : {
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx
index a15e5da..0b41868 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx
@@ -21,9 +21,11 @@
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 GeneralTabContent = ({data, genericFieldInfo, onDataChanged, validateName, validateLTChoice}) => {
+const GeneralTabContent = ({data, genericFieldInfo, onDataChanged, validateName}) => {
let {name, description, requirementsAndConstrains, licenseTerm} = data;
return (
<GridSection>
@@ -67,24 +69,22 @@
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 @@
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 @@
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;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.jsx
index 5c4e50d..d4b7e5c 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.jsx
@@ -7,7 +7,7 @@
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 @@
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 @@
{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) {
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorReducer.js
index de9e7c8..99d94a0 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorReducer.js
@@ -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 @@
'metric' : {
isValid: true,
errorText: '',
- validations: []
+ validations: [{type: 'required', data: true}, {type: 'requiredChoiceWithOther', data: optionInputOther.OTHER}]
},
'value' : {
isValid: true,