summaryrefslogtreecommitdiffstats
path: root/src/generic-components/input
diff options
context:
space:
mode:
Diffstat (limited to 'src/generic-components/input')
-rw-r--r--src/generic-components/input/validation/ValidationButtons.jsx66
-rw-r--r--src/generic-components/input/validation/ValidationForm.jsx170
-rw-r--r--src/generic-components/input/validation/ValidationInput.jsx351
-rw-r--r--src/generic-components/input/validation/ValidationTab.jsx141
-rw-r--r--src/generic-components/input/validation/ValidationTabs.jsx102
5 files changed, 0 insertions, 830 deletions
diff --git a/src/generic-components/input/validation/ValidationButtons.jsx b/src/generic-components/input/validation/ValidationButtons.jsx
deleted file mode 100644
index 1568a57..0000000
--- a/src/generic-components/input/validation/ValidationButtons.jsx
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017 Amdocs
- * ================================================================================
- * 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=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
- */
-/**
- * Holds the buttons for save/reset for forms.
- * Used by the ValidationForm that changes the state of the buttons according
- * to its own state.
- *
- * properties:
- * labledButtons - whether or not to use labeled buttons or icons only
- */
-import React from 'react';
-import i18n from 'utils/i18n/i18n.js';
-import Button from 'react-bootstrap/lib/Button.js';
-import FontAwesome from 'react-fontawesome';
-
-class ValidationButtons extends React.Component {
-
- static propTypes = {
- labledButtons: React.PropTypes.bool.isRequired,
- isReadOnlyMode: React.PropTypes.bool
- };
-
- state = {
- isValid: this.props.formValid
- };
-
- render() {
- var submitBtn = this.props.labledButtons ? i18n('Save') :
- <FontAwesome className='check' name='check'/>;
- var closeBtn = this.props.labledButtons ? i18n('Cancel') :
- <FontAwesome className='close' name='close'/>;
- return (
- <div className='validation-buttons'>
- {!this.props.isReadOnlyMode ?
- <div>
- <Button bsStyle='primary' ref='submitbutton' type='submit'
- disabled={!this.state.isValid}>{submitBtn}</Button>
- <Button type='reset'>{closeBtn}</Button>
- </div>
- : <Button type='reset'>{i18n('Close')}</Button>
- }
- </div>
- );
- }
-}
-export default ValidationButtons;
diff --git a/src/generic-components/input/validation/ValidationForm.jsx b/src/generic-components/input/validation/ValidationForm.jsx
deleted file mode 100644
index af4001e..0000000
--- a/src/generic-components/input/validation/ValidationForm.jsx
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017 Amdocs
- * ================================================================================
- * 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=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
- */
-/**
- * ValidationForm should be used in order to have a form that handles it's
- * internal validation state. All ValidationInputs inside the form are checked
- * for validity and the styling and submit buttons are updated accordingly.
- *
- * The properties that ahould be given to the form:
- * labledButtons - whether or not use icons only as the form default buttons or
- * use buttons with labels onSubmit - function for click on the submit button
- * onReset - function for click on the reset button
- */
-import React from 'react';
-import ValidationButtons from './ValidationButtons.jsx';
-
-class ValidationForm extends React.Component {
-
- static childContextTypes = {
- validationParent: React.PropTypes.any,
- isReadOnlyMode: React.PropTypes.bool
- };
-
- static defaultProps = {
- hasButtons: true,
- onSubmit: null,
- onReset: null,
- labledButtons: true,
- onValidChange: null,
- isValid: true
- };
-
- static propTypes = {
- isValid: React.PropTypes.bool,
- hasButtons: React.PropTypes.bool,
- onSubmit: React.PropTypes.func,
- onReset: React.PropTypes.func,
- labledButtons: React.PropTypes.bool,
- onValidChange: React.PropTypes.func
- };
-
- state = {
- isValid: this.props.isValid
- };
-
- constructor(props) {
- super(props);
- this.validationComponents = [];
- }
-
- render() {
- var buttons = (this.props.hasButtons) ?
- <ValidationButtons labledButtons={this.props.labledButtons}
- ref='buttons'
- isReadOnlyMode={this.props.isReadOnlyMode}/>
- : null;
- return (
- <form {...this.props} onSubmit={event => this.handleFormSubmit(event)}>
- <div className='validation-form-content'>{this.props.children}</div>
- {buttons}
- </form>
- );
- }
-
- handleFormSubmit(event) {
- event.preventDefault();
- let isFormValid = true;
- this.validationComponents.forEach(validationComponent => {
- const isInputValid = validationComponent.validate().isValid;
- isFormValid = isInputValid && isFormValid;
- });
- if (isFormValid && this.props.onSubmit) {
- this.props.onSubmit(event);
- } else if (!isFormValid) {
- this.setState({isValid: false});
- }
- };
-
- componentDidUpdate(prevProps, prevState) {
- // only handling this programatically if the validation of the form is done
- // outside of the view (example with a form that is dependent on the state
- // of other forms)
- if (prevProps.isValid !== this.props.isValid) {
- if (this.props.hasButtons) {
- this.refs.buttons.setState({isValid: this.state.isValid});
- }
- } else if (this.state.isValid !== prevState.isValid) {
- if (this.props.hasButtons) {
- this.refs.buttons.setState({isValid: this.state.isValid});
- }
- // callback in case form is part of bigger picture in view
- if (this.props.onValidChange) {
- this.props.onValidChange(this.state.isValid);
- }
- }
- }
-
- componentDidMount() {
- if (this.props.hasButtons) {
- this.refs.buttons.setState({isValid: this.state.isValid});
- }
- }
-
-
- getChildContext() {
- return {
- validationParent: this,
- isReadOnlyMode: this.props.isReadOnlyMode
- };
- }
-
-
- /***
- * Used by ValidationInput in order to let the (parent) form know
- * the valid state. If there is a change in the state of the form,
- * the buttons will be updated.
- *
- * @param validationComponent
- * @param isValid
- */
- childValidStateChanged(validationComponent, isValid) {
- if (isValid !== this.state.isValid) {
- let oldState = this.state.isValid;
- let newState = isValid &&
- this.validationComponents.filter(
- otherValidationComponent => validationComponent !==
- otherValidationComponent).every(otherValidationComponent => {
- return otherValidationComponent.isValid();
- });
-
- if (oldState !== newState) {
- this.setState({isValid: newState});
- }
- }
- }
-
- register(validationComponent) {
- this.validationComponents.push(validationComponent);
- }
-
- unregister(validationComponent) {
- this.childValidStateChanged(validationComponent, true);
- this.validationComponents =
- this.validationComponents.filter(
- otherValidationComponent => validationComponent !==
- otherValidationComponent);
- }
-}
-
-
-export default ValidationForm;
diff --git a/src/generic-components/input/validation/ValidationInput.jsx b/src/generic-components/input/validation/ValidationInput.jsx
deleted file mode 100644
index 7c3c2a8..0000000
--- a/src/generic-components/input/validation/ValidationInput.jsx
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017 Amdocs
- * ================================================================================
- * 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=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
- */
-/**
- * Used for inputs on a validation form.
- * All properties will be passed on to the input element.
- *
- * The following properties can be set for OOB validations and callbacks:
- - required: Boolean: Should be set to true if the input must have a value
- - numeric: Boolean : Should be set to true id the input should be an integer
- - onChange : Function : Will be called to validate the value if the default validations are not sufficient, should return a boolean value
- indicating whether the value is valid
- - didUpdateCallback :Function: Will be called after the state has been updated and the component has rerendered. This can be used if
- there are dependencies between inputs in a form.
- *
- * The following properties of the state can be set to determine
- * the state of the input from outside components:
- - isValid : Boolean - whether the value is valid
- - value : value for the input field,
- - disabled : Boolean,
- - required : Boolean - whether the input value must be filled out.
- */
-import React from 'react';
-import ReactDOM from 'react-dom';
-import Validator from 'validator';
-import Input from 'react-bootstrap/lib/Input.js';
-import Overlay from 'react-bootstrap/lib/Overlay.js';
-import Tooltip from 'react-bootstrap/lib/Tooltip.js';
-import isEqual from 'lodash/lang/isEqual.js';
-import i18n from 'utils/i18n/i18n.js';
-
-import InputOptions from '../inputOptions/InputOptions.jsx';
-
-const globalValidationFunctions = {
- required: value => value !== '',
- maxLength: (value, length) => Validator.isLength(value, {max: length}),
- minLength: (value, length) => Validator.isLength(value, {min: length}),
- pattern: (value, pattern) => Validator.matches(value, pattern),
- numeric: value => Validator.isNumeric(value),
- maxValue: (value, maxValue) => value < maxValue,
- alphanumeric: value => Validator.isAlphanumeric(value),
- alphanumericWithSpaces: value => Validator.isAlphanumeric(
- value.replace(/ /g, '')),
- validateName: value => Validator.isAlphanumeric(
- value.replace(/\s|\.|\_|\-/g, ''), 'en-US'),
- validateVendorName: value => Validator.isAlphanumeric(
- value.replace(/[\x7F-\xFF]|\s/g, ''), 'en-US'),
- freeEnglishText: value => Validator.isAlphanumeric(
- value.replace(/\s|\.|\_|\-|\,|\(|\)|\?/g, ''), 'en-US'),
- email: value => Validator.isEmail(value),
- ip: value => Validator.isIP(value),
- url: value => Validator.isURL(value)
-};
-
-const globalValidationMessagingFunctions = {
- required: () => i18n('Field is required'),
- maxLength: (value, maxLength) => i18n(
- 'Field value has exceeded it\'s limit, {maxLength}. current length: {length}',
- {
- length: value.length,
- maxLength
- }),
- minLength: (value, minLength) => i18n(
- 'Field value should contain at least {minLength} characters.', {minLength}),
- pattern: (value, pattern) => i18n(
- 'Field value should match the pattern: {pattern}.', {pattern}),
- numeric: () => i18n('Field value should contain numbers only.'),
- maxValue: (value, maxValue) => i18n(
- 'Field value should be less then: {maxValue}.', {maxValue}),
- alphanumeric: () => i18n(
- 'Field value should contain letters or digits only.'),
- alphanumericWithSpaces: () => i18n(
- 'Field value should contain letters, digits or spaces only.'),
- validateName: ()=> i18n(
- 'Field value should contain English letters, digits , spaces, underscores, dashes and dots only.'),
- validateVendorName: ()=> i18n(
- 'Field value should contain English letters digits and spaces only.'),
- freeEnglishText: ()=> i18n(
- 'Field value should contain English letters, digits , spaces, underscores, dashes and dots only.'),
- email: () => i18n('Field value should be a valid email address.'),
- ip: () => i18n('Field value should be a valid ip address.'),
- url: () => i18n('Field value should be a valid url address.'),
- general: () => i18n('Field value is invalid.')
-};
-
-class ValidationInput extends React.Component {
-
- static contextTypes = {
- validationParent: React.PropTypes.any,
- isReadOnlyMode: React.PropTypes.bool
- };
-
- static defaultProps = {
- onChange: null,
- disabled: null,
- didUpdateCallback: null,
- validations: {},
- value: ''
- };
-
- static propTypes = {
- onChange: React.PropTypes.func,
- disabled: React.PropTypes.bool,
- didUpdateCallback: React.PropTypes.func,
- validations: React.PropTypes.object
- };
-
-
- state = {
- isValid: true,
- style: null,
- value: this.props.value,
- error: {},
- previousErrorMessage: '',
- wasInvalid: false
- };
-
- componentWillReceiveProps({value: nextValue, validations: nextValidaions}) {
- if (this.state.wasInvalid) {
- const {validations, value} = this.props;
- if (value !== nextValue || !isEqual(validations, nextValidaions)) {
- this.validate(nextValue, nextValidaions);
- }
- } else if (this.props.value !== nextValue) {
- this.setState({value: nextValue});
- }
- }
-
- render() {
- let {isMultiSelect, onOtherChange, type} = this.props;
-
- let groupClasses = this.props.groupClassName || '';
- if (this.props.validations.required) {
- groupClasses += ' required';
- }
- let isReadOnlyMode = this.context.isReadOnlyMode;
-
- return (
- <div className='validation-input-wrapper'>
- {
- !isMultiSelect && !onOtherChange && type !== 'select'
- && <Input
- {...this.props}
- groupClassName={groupClasses}
- ref={'_myInput'}
- value={this.state.value}
- disabled={isReadOnlyMode || Boolean(this.props.disabled)}
- bsStyle={this.state.style}
- onChange={() => this.changedInput()}
- onBlur={() => this.blurInput()}>
- {this.props.children}
- </Input>
- }
- {
- (isMultiSelect || onOtherChange || type === 'select')
- && <InputOptions onInputChange={() => this.changedInput()}
- onBlur={() => this.blurInput()}
- hasError={!this.state.isValid}
- ref={'_myInput'} {...this.props} />
- }
- {this.renderOverlay()}
- </div>
- );
- }
-
- renderOverlay() {
- let position = 'right';
- if (this.props.type === 'text'
- || this.props.type === 'email'
- || this.props.type === 'number'
- || this.props.type === 'password'
-
- ) {
- position = 'bottom';
- }
-
- let validationMessage = this.state.error.message ||
- this.state.previousErrorMessage;
- return (
- <Overlay
- show={!this.state.isValid}
- placement={position}
- target={() => {let target = ReactDOM.findDOMNode(this.refs._myInput); return target.offsetParent ? target : undefined;}}
- container={this}>
- <Tooltip
- id={`error-${validationMessage.replace(' ','-')}`}
- className='validation-error-message'>
- {validationMessage}
- </Tooltip>
- </Overlay>
- );
- }
-
- componentDidMount() {
- if (this.context.validationParent) {
- this.context.validationParent.register(this);
- }
- }
-
- componentDidUpdate(prevProps, prevState) {
- if (this.context.validationParent) {
- if (prevState.isValid !== this.state.isValid) {
- this.context.validationParent.childValidStateChanged(this,
- this.state.isValid);
- }
- }
- if (this.props.didUpdateCallback) {
- this.props.didUpdateCallback();
- }
-
- }
-
- componentWillUnmount() {
- if (this.context.validationParent) {
- this.context.validationParent.unregister(this);
- }
- }
-
- /***
- * Adding same method as the actual input component
- * @returns {*}
- */
- getValue() {
- if (this.props.type === 'checkbox') {
- return this.refs._myInput.getChecked();
- }
- return this.refs._myInput.getValue();
- }
-
- resetValue() {
- this.setState({value: this.props.value});
- }
-
-
- /***
- * internal method that validated the value. includes callback to the
- * onChange method
- * @param value
- * @param validations - map containing validation id and the limitation
- * describing the validation.
- * @returns {object}
- */
- validateValue = (value, validations) => {
- let {customValidationFunction} = validations;
- let error = {};
- let isValid = true;
- for (let validation in validations) {
- if ('customValidationFunction' !== validation) {
- if (validations[validation]) {
- if (!globalValidationFunctions[validation](value,
- validations[validation])) {
- error.id = validation;
- error.message =
- globalValidationMessagingFunctions[validation](value,
- validations[validation]);
- isValid = false;
- break;
- }
- }
- } else {
- let customValidationResult = customValidationFunction(value);
-
- if (customValidationResult !== true) {
- error.id = 'custom';
- isValid = false;
- if (typeof customValidationResult === 'string') {//custom validation error message supplied.
- error.message = customValidationResult;
- } else {
- error.message = globalValidationMessagingFunctions.general();
- }
- break;
- }
-
-
- }
- }
-
- return {
- isValid,
- error
- };
- };
-
- /***
- * Internal method that handles the change event of the input. validates and
- * updates the state.
- */
- changedInput() {
-
- let {isValid, error} = this.state.wasInvalid ? this.validate() : this.state;
- let onChange = this.props.onChange;
- if (onChange) {
- onChange(this.getValue(), isValid, error);
- }
- };
-
- blurInput() {
- if (!this.state.wasInvalid) {
- this.setState({wasInvalid: true});
- }
-
- let {isValid, error} = !this.state.wasInvalid
- ? this.validate()
- : this.state;
- let onBlur = this.props.onBlur;
- if (onBlur) {
- onBlur(this.getValue(), isValid, error);
- }
- };
-
- validate(value = this.getValue(), validations = this.props.validations) {
- let validationStatus = this.validateValue(value, validations);
- let {isValid, error} = validationStatus;
- let _style = isValid ? null : 'error';
- this.setState({
- isValid,
- error,
- value,
- previousErrorMessage: this.state.error.message || '',
- style: _style,
- wasInvalid: !isValid || this.state.wasInvalid
- });
-
- return validationStatus;
- }
-
- isValid() {
- return this.state.isValid;
- }
-
-}
-export default ValidationInput;
diff --git a/src/generic-components/input/validation/ValidationTab.jsx b/src/generic-components/input/validation/ValidationTab.jsx
deleted file mode 100644
index 385d585..0000000
--- a/src/generic-components/input/validation/ValidationTab.jsx
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017 Amdocs
- * ================================================================================
- * 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=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
- */
-import React from 'react';
-import Tab from 'react-bootstrap/lib/Tab.js';
-
-export default
-class ValidationTab extends React.Component {
-
- static propTypes = {
- children: React.PropTypes.node,
- eventKey: React.PropTypes.any.isRequired,
- onValidationStateChange: React.PropTypes.func //This property is assigned
- // dynamically via
- // React.cloneElement. lookup
- // ValidationTabs.jsx.
- // therefore it cannot be
- // stated as required!
- };
-
- constructor(props) {
- super(props);
- this.validationComponents = [];
- }
-
- static childContextTypes = {
- validationParent: React.PropTypes.any
- };
-
- static contextTypes = {
- validationParent: React.PropTypes.any
- };
-
- getChildContext() {
- return {validationParent: this};
- }
-
- state = {
- isValid: true,
- notifyParent: false
- };
-
- componentDidMount() {
- let validationParent = this.context.validationParent;
- if (validationParent) {
- validationParent.register(this);
- }
- }
-
- componentWillUnmount() {
- let validationParent = this.context.validationParent;
- if (validationParent) {
- validationParent.unregister(this);
- }
- }
-
- register(validationComponent) {
- this.validationComponents.push(validationComponent);
- }
-
- unregister(validationComponent) {
- this.childValidStateChanged(validationComponent, true);
- this.validationComponents =
- this.validationComponents.filter(
- otherValidationComponent => validationComponent !==
- otherValidationComponent);
- }
-
- notifyValidStateChangedToParent(isValid) {
-
- let validationParent = this.context.validationParent;
- if (validationParent) {
- validationParent.childValidStateChanged(this, isValid);
- }
- }
-
- childValidStateChanged(validationComponent, isValid) {
-
- const currentValidState = this.state.isValid;
- if (isValid !== currentValidState) {
- let filteredValidationComponents = this.validationComponents.filter(
- otherValidationComponent => validationComponent !==
- otherValidationComponent);
- let newValidState = isValid &&
- filteredValidationComponents.every(otherValidationComponent => {
- return otherValidationComponent.isValid();
- });
- this.setState({isValid: newValidState, notifyParent: true});
- }
- }
-
- validate() {
- let isValid = true;
- this.validationComponents.forEach(validationComponent => {
- const isValidationComponentValid = validationComponent.validate().isValid;
- isValid = isValidationComponentValid && isValid;
- });
- this.setState({isValid, notifyParent: false});
- return {isValid};
- }
-
- componentDidUpdate(prevProps, prevState) {
- if (prevState.isValid !== this.state.isValid) {
- if (this.state.notifyParent) {
- this.notifyValidStateChangedToParent(this.state.isValid);
- }
- this.props.onValidationStateChange(this.props.eventKey,
- this.state.isValid);
- }
- }
-
- isValid() {
- return this.state.isValid;
- }
-
- render() {
- let {children, ...tabProps} = this.props;
- return (
- <Tab {...tabProps}>{children}</Tab>
- );
- }
-}
diff --git a/src/generic-components/input/validation/ValidationTabs.jsx b/src/generic-components/input/validation/ValidationTabs.jsx
deleted file mode 100644
index 64dd365..0000000
--- a/src/generic-components/input/validation/ValidationTabs.jsx
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017 Amdocs
- * ================================================================================
- * 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=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
- */
-import React from 'react';
-import ReactDOM from 'react-dom';
-import Tabs from 'react-bootstrap/lib/Tabs.js';
-import Overlay from 'react-bootstrap/lib/Overlay.js';
-import Tooltip from 'react-bootstrap/lib/Tooltip.js';
-
-import i18n from 'utils/i18n/i18n.js';
-
-export default
-class ValidationTab extends React.Component {
-
- static propTypes = {
- children: React.PropTypes.node
- };
-
- state = {
- invalidTabs: []
- };
-
- cloneTab(element) {
- const {invalidTabs} = this.state;
- return React.cloneElement(
- element,
- {
- key: element.props.eventKey,
- tabClassName: invalidTabs.indexOf(element.props.eventKey) > -1
- ? 'invalid-tab'
- : 'valid-tab',
- onValidationStateChange: (
- eventKey, isValid) => this.validTabStateChanged(eventKey, isValid)
- }
- );
- }
-
- validTabStateChanged(eventKey, isValid) {
- let {invalidTabs} = this.state;
- let invalidTabIndex = invalidTabs.indexOf(eventKey);
- if (isValid && invalidTabIndex > -1) {
- this.setState({
- invalidTabs: invalidTabs.filter(
- otherEventKey => eventKey !== otherEventKey)
- });
- } else if (!isValid && invalidTabIndex === -1) {
- this.setState({invalidTabs: [...invalidTabs, eventKey]});
- }
- }
-
- showTabsError() {
- const {invalidTabs} = this.state;
- return invalidTabs.length >
- 0 &&
- (invalidTabs.length > 1 || invalidTabs[0] !== this.props.activeKey);
- }
-
- render() {
- return (
- <div>
- <Tabs {...this.props} ref='tabsList'>
- {this.props.children.map(element => this.cloneTab(element))}
- </Tabs>
- <Overlay
- animation={false}
- show={this.showTabsError()}
- placement='bottom'
- target={() => {
- let target = ReactDOM.findDOMNode(this.refs.tabsList).querySelector('ul > li.invalid-tab:not(.active):nth-of-type(n)');
- return target && target.offsetParent ? target : undefined;
- }
- }
- container={this}>
- <Tooltip
- id='error-some-tabs-contain-errors'
- className='validation-error-message'>
- {i18n('One or more tabs are invalid')}
- </Tooltip>
- </Overlay>
- </div>
- );
- }
-}