From 2c9358a92c68a28c3ea307c9036f4721c7f0ca7e Mon Sep 17 00:00:00 2001 From: ilanap Date: Wed, 13 Sep 2017 14:41:21 +0300 Subject: Other option for license agreement term Issue-Id: SDC-290 Change-Id: Ifeae84fd96175b656814e8b70bc67789f57ef78e Signed-off-by: ilanap --- .../input/inputOptions/InputOptions.jsx | 246 --------------------- openecomp-ui/src/nfvo-utils/Validator.js | 21 +- .../sdc-app/common/reducers/PlainDataReducer.js | 2 +- .../LicenseAgreementEditorReducer.js | 3 +- .../LicenseAgreementEditorView.jsx | 40 ++-- .../onboarding/licenseModel/limits/LimitEditor.jsx | 23 +- .../licenseModel/limits/LimitEditorReducer.js | 3 +- 7 files changed, 45 insertions(+), 293 deletions(-) delete mode 100644 openecomp-ui/src/nfvo-components/input/inputOptions/InputOptions.jsx (limited to 'openecomp-ui') 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 e8aadc4357..0000000000 --- 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( -
- {label && } - {isMultiSelect && otherInputDisabled ? - 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 && } - - - {!otherInputDisabled &&
} - onBlur()} - onChange={() => this.changedOtherInput()}/> -
- } -
- ); - } - - renderOptions(val, index){ - return ( - - ); - } - - - 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 1df82a2ada..3f6a00e289 100644 --- a/openecomp-ui/src/nfvo-utils/Validator.js +++ b/openecomp-ui/src/nfvo-utils/Validator.js @@ -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 diff --git a/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js b/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js index 2276984f7a..49f1e3d415 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 5be140550a..9cff2792ff 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 @@ 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' : { 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 a15e5daa4e..0b418686fd 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 {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 ( @@ -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'/> - {}} + 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 => - )} - + errorText={genericFieldInfo.licenseTerm.errorText} />
- this.validateLTChoice(value)} + this.validateName(value)}/>
@@ -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; 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 5c4e50d673..d4b7e5c898 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 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) { 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 de9e7c8c38..99d94a09cc 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 @@ export default (state = {}, action) => { 'metric' : { isValid: true, errorText: '', - validations: [] + validations: [{type: 'required', data: true}, {type: 'requiredChoiceWithOther', data: optionInputOther.OTHER}] }, 'value' : { isValid: true, -- cgit 1.2.3-korg