From 05095d06251d19eba1d812b522e8e6e052ad8a29 Mon Sep 17 00:00:00 2001 From: ahmedGaber93 Date: Tue, 3 Oct 2023 00:36:39 +0200 Subject: [PATCH 1/8] OptionsSelector display max length error with counter when exceeded --- src/CONST.ts | 2 ++ .../OptionsSelector/BaseOptionsSelector.js | 30 ++++++++++++++++--- .../optionsSelectorPropTypes.js | 3 +- src/languages/en.ts | 1 + 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 0a262d868de9..8b3fc56b33e3 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -2684,6 +2684,8 @@ const CONST = { HIDDEN_MARGIN_VERTICAL: 0, HIDDEN_BORDER_BOTTOM_WIDTH: 0, }, + SEARCH_MAX_LENGTH: 500, + ERROR_EXCEED_RANGE: 20, } as const; export default CONST; diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index aa02701b1c98..bf1d678d1f4e 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -53,6 +53,7 @@ class BaseOptionsSelector extends Component { this.scrollToIndex = this.scrollToIndex.bind(this); this.selectRow = this.selectRow.bind(this); this.selectFocusedOption = this.selectFocusedOption.bind(this); + this.updateSearchValue = this.updateSearchValue.bind(this); this.relatedTarget = null; const allOptions = this.flattenSections(); @@ -62,6 +63,8 @@ class BaseOptionsSelector extends Component { allOptions, focusedIndex, shouldDisableRowSelection: false, + errorMessage: "", + searchValue: this.props.value, }; } @@ -165,6 +168,24 @@ class BaseOptionsSelector extends Component { return defaultIndex; } + updateSearchValue(value){ + if (value.length > this.props.maxLength) { + this.setState({ + searchValue: value, + errorMessage: this.props.translate("common.error.characterLimitExceedCounter", {length: value.length, limit: this.props.maxLength}), + }); + return; + } + + this.setState({ + searchValue: value, + errorMessage: "", + }); + + this.props.onChangeText(value); + } + + subscribeToKeyboardShortcut() { const enterConfig = CONST.KEYBOARD_SHORTCUTS.ENTER; this.unsubscribeEnter = KeyboardShortcut.subscribe( @@ -346,14 +367,15 @@ class BaseOptionsSelector extends Component { const textInput = ( (this.textInput = el)} - value={this.props.value} + value={this.state.searchValue} label={this.props.textInputLabel} accessibilityLabel={this.props.textInputLabel} accessibilityRole={CONST.ACCESSIBILITY_ROLE.TEXT} - onChangeText={this.props.onChangeText} + onChangeText={this.updateSearchValue} + errorText={this.state.errorMessage} onSubmitEditing={this.selectFocusedOption} placeholder={this.props.placeholderText} - maxLength={this.props.maxLength} + maxLength={this.props.maxLength + CONST.ERROR_EXCEED_RANGE} keyboardType={this.props.keyboardType} onBlur={(e) => { if (!this.props.shouldFocusOnSelectRow) { @@ -379,7 +401,7 @@ class BaseOptionsSelector extends Component { multipleOptionSelectorButtonText={this.props.multipleOptionSelectorButtonText} onAddToSelection={this.props.onAddToSelection} hideSectionHeaders={this.props.hideSectionHeaders} - headerMessage={this.props.headerMessage} + headerMessage={this.state.errorMessage ? "" : this.props.headerMessage} boldStyle={this.props.boldStyle} showTitleTooltip={this.props.showTitleTooltip} isDisabled={this.props.isDisabled} diff --git a/src/components/OptionsSelector/optionsSelectorPropTypes.js b/src/components/OptionsSelector/optionsSelectorPropTypes.js index ca336c324673..91462c9092e4 100644 --- a/src/components/OptionsSelector/optionsSelectorPropTypes.js +++ b/src/components/OptionsSelector/optionsSelectorPropTypes.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import optionPropTypes from '../optionPropTypes'; import styles from '../../styles/styles'; +import CONST from "../../CONST" const propTypes = { /** Callback to fire when a row is tapped */ @@ -154,7 +155,7 @@ const defaultProps = { isDisabled: false, shouldHaveOptionSeparator: false, initiallyFocusedOptionKey: undefined, - maxLength: undefined, + maxLength: CONST.SEARCH_MAX_LENGTH, shouldShowTextInput: true, onChangeText: () => {}, shouldUseStyleForChildren: true, diff --git a/src/languages/en.ts b/src/languages/en.ts index abba4cfd71a3..36328f01f44a 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -190,6 +190,7 @@ export default { phoneNumber: `Please enter a valid phone number, with the country code (e.g. ${CONST.EXAMPLE_PHONE_NUMBER})`, fieldRequired: 'This field is required.', characterLimit: ({limit}: CharacterLimitParams) => `Exceeds the maximum length of ${limit} characters`, + characterLimitExceedCounter: ({length, limit}) => `Characters limit exceeded(${length}/${limit})`, dateInvalid: 'Please select a valid date', invalidCharacter: 'Invalid character', enterMerchant: 'Enter a merchant name', From 40354e16b3dc7f5338f163113558e895d6203b5e Mon Sep 17 00:00:00 2001 From: ahmedGaber93 Date: Tue, 3 Oct 2023 15:13:48 +0200 Subject: [PATCH 2/8] update translations --- src/languages/en.ts | 2 +- src/languages/es.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index edaf7aa9fc48..ac4c5b63a192 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -192,7 +192,7 @@ export default { phoneNumber: `Please enter a valid phone number, with the country code (e.g. ${CONST.EXAMPLE_PHONE_NUMBER})`, fieldRequired: 'This field is required.', characterLimit: ({limit}: CharacterLimitParams) => `Exceeds the maximum length of ${limit} characters`, - characterLimitExceedCounter: ({length, limit}) => `Characters limit exceeded(${length}/${limit})`, + characterLimitExceedCounter: ({length, limit}) => `Characters limit exceeded (${length}/${limit})`, dateInvalid: 'Please select a valid date', invalidCharacter: 'Invalid character', enterMerchant: 'Enter a merchant name', diff --git a/src/languages/es.ts b/src/languages/es.ts index fa97556d8096..30ed6a6e523e 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -182,6 +182,7 @@ export default { phoneNumber: `Introduce un teléfono válido, incluyendo el código del país (p. ej. ${CONST.EXAMPLE_PHONE_NUMBER})`, fieldRequired: 'Este campo es obligatorio.', characterLimit: ({limit}: CharacterLimitParams) => `Supera el límite de ${limit} caracteres`, + characterLimitExceedCounter: ({length, limit}) => `Se superó el límite de caracteres (${length}/${limit})`, dateInvalid: 'Por favor, selecciona una fecha válida', invalidCharacter: 'Carácter invalido', enterMerchant: 'Introduce un comerciante', From 7728993847b0dc61f794c18e83a99f8601066f65 Mon Sep 17 00:00:00 2001 From: ahmedGaber93 Date: Tue, 3 Oct 2023 15:15:25 +0200 Subject: [PATCH 3/8] prettier --- src/components/OptionsSelector/BaseOptionsSelector.js | 11 +++++------ .../OptionsSelector/optionsSelectorPropTypes.js | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index a71ef0b7b381..e766eeb5d154 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -64,7 +64,7 @@ class BaseOptionsSelector extends Component { allOptions, focusedIndex, shouldDisableRowSelection: false, - errorMessage: "", + errorMessage: '', searchValue: this.props.value, }; } @@ -169,24 +169,23 @@ class BaseOptionsSelector extends Component { return defaultIndex; } - updateSearchValue(value){ + updateSearchValue(value) { if (value.length > this.props.maxLength) { this.setState({ searchValue: value, - errorMessage: this.props.translate("common.error.characterLimitExceedCounter", {length: value.length, limit: this.props.maxLength}), + errorMessage: this.props.translate('common.error.characterLimitExceedCounter', {length: value.length, limit: this.props.maxLength}), }); return; } this.setState({ searchValue: value, - errorMessage: "", + errorMessage: '', }); this.props.onChangeText(value); } - subscribeToKeyboardShortcut() { const enterConfig = CONST.KEYBOARD_SHORTCUTS.ENTER; this.unsubscribeEnter = KeyboardShortcut.subscribe( @@ -416,7 +415,7 @@ class BaseOptionsSelector extends Component { multipleOptionSelectorButtonText={this.props.multipleOptionSelectorButtonText} onAddToSelection={this.addToSelection} hideSectionHeaders={this.props.hideSectionHeaders} - headerMessage={this.state.errorMessage ? "" : this.props.headerMessage} + headerMessage={this.state.errorMessage ? '' : this.props.headerMessage} boldStyle={this.props.boldStyle} showTitleTooltip={this.props.showTitleTooltip} isDisabled={this.props.isDisabled} diff --git a/src/components/OptionsSelector/optionsSelectorPropTypes.js b/src/components/OptionsSelector/optionsSelectorPropTypes.js index 91462c9092e4..53815a1c0907 100644 --- a/src/components/OptionsSelector/optionsSelectorPropTypes.js +++ b/src/components/OptionsSelector/optionsSelectorPropTypes.js @@ -1,7 +1,7 @@ import PropTypes from 'prop-types'; import optionPropTypes from '../optionPropTypes'; import styles from '../../styles/styles'; -import CONST from "../../CONST" +import CONST from '../../CONST'; const propTypes = { /** Callback to fire when a row is tapped */ From fde11f999af4fb6351392ceb7d023ec2cd547898 Mon Sep 17 00:00:00 2001 From: ahmedGaber93 Date: Thu, 5 Oct 2023 08:15:36 +0200 Subject: [PATCH 4/8] OptionsSelector display max length error with counter when exceeded --- .../OptionsSelector/BaseOptionsSelector.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index e766eeb5d154..9c0aca289808 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -65,7 +65,6 @@ class BaseOptionsSelector extends Component { focusedIndex, shouldDisableRowSelection: false, errorMessage: '', - searchValue: this.props.value, }; } @@ -172,17 +171,12 @@ class BaseOptionsSelector extends Component { updateSearchValue(value) { if (value.length > this.props.maxLength) { this.setState({ - searchValue: value, errorMessage: this.props.translate('common.error.characterLimitExceedCounter', {length: value.length, limit: this.props.maxLength}), }); - return; + } else if (value.length <= this.props.maxLength && this.state.errorMessage) { + this.setState({errorMessage: ''}); } - this.setState({ - searchValue: value, - errorMessage: '', - }); - this.props.onChangeText(value); } @@ -381,7 +375,7 @@ class BaseOptionsSelector extends Component { const textInput = ( (this.textInput = el)} - value={this.state.searchValue} + value={this.props.value} label={this.props.textInputLabel} accessibilityLabel={this.props.textInputLabel} accessibilityRole={CONST.ACCESSIBILITY_ROLE.TEXT} From afc7d691b2b24734e29c51748ddb6aff0f832f34 Mon Sep 17 00:00:00 2001 From: ahmedGaber93 Date: Thu, 5 Oct 2023 15:23:05 +0200 Subject: [PATCH 5/8] OptionsSelector display max length error with counter when exceeded --- src/components/OptionsSelector/BaseOptionsSelector.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index 9c0aca289808..994c73050a56 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -169,13 +169,9 @@ class BaseOptionsSelector extends Component { } updateSearchValue(value) { - if (value.length > this.props.maxLength) { - this.setState({ - errorMessage: this.props.translate('common.error.characterLimitExceedCounter', {length: value.length, limit: this.props.maxLength}), - }); - } else if (value.length <= this.props.maxLength && this.state.errorMessage) { - this.setState({errorMessage: ''}); - } + this.setState({ + errorMessage: value.length > this.props.maxLength ? this.props.translate('common.error.characterLimitExceedCounter', {length: value.length, limit: this.props.maxLength}) : '', + }); this.props.onChangeText(value); } From 9b98e98b0ab6bf458d2d98174348265f143da68e Mon Sep 17 00:00:00 2001 From: ahmedGaber93 Date: Fri, 6 Oct 2023 15:53:52 +0200 Subject: [PATCH 6/8] update en.ts file --- src/languages/en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index ac4c5b63a192..1b2e82ebf9cb 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -192,7 +192,7 @@ export default { phoneNumber: `Please enter a valid phone number, with the country code (e.g. ${CONST.EXAMPLE_PHONE_NUMBER})`, fieldRequired: 'This field is required.', characterLimit: ({limit}: CharacterLimitParams) => `Exceeds the maximum length of ${limit} characters`, - characterLimitExceedCounter: ({length, limit}) => `Characters limit exceeded (${length}/${limit})`, + characterLimitExceedCounter: ({length, limit}) => `Character limit exceeded (${length}/${limit})`, dateInvalid: 'Please select a valid date', invalidCharacter: 'Invalid character', enterMerchant: 'Enter a merchant name', From 0c00e23bc2663da4bff3bd15fe5f6287ece1906f Mon Sep 17 00:00:00 2001 From: ahmedGaber93 Date: Tue, 10 Oct 2023 18:08:16 +0200 Subject: [PATCH 7/8] add comment for CONST.ERROR_EXCEED_RANGE --- src/CONST.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CONST.ts b/src/CONST.ts index 73f93cd39233..cffe3f3c68aa 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -2738,6 +2738,10 @@ const CONST = { MISSING_TRANSLATION: 'MISSING TRANSLATION', SEARCH_MAX_LENGTH: 500, + + /** + * The count of characters we'll allow the user to type after reaching SEARCH_MAX_LENGTH in an input. + */ ERROR_EXCEED_RANGE: 20, } as const; From d5e39c203e4001c1585300980e44e0c9c27c142d Mon Sep 17 00:00:00 2001 From: ahmedGaber93 Date: Wed, 11 Oct 2023 11:44:15 +0200 Subject: [PATCH 8/8] rename CONST.ERROR_EXCEED_RANGE --- src/CONST.ts | 2 +- src/components/OptionsSelector/BaseOptionsSelector.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index c3ab64e85e42..491136863f6c 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -2741,7 +2741,7 @@ const CONST = { /** * The count of characters we'll allow the user to type after reaching SEARCH_MAX_LENGTH in an input. */ - ERROR_EXCEED_RANGE: 20, + ADDITIONAL_ALLOWED_CHARACTERS: 20, } as const; export default CONST; diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index b9745d81d78b..64896162fb07 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -380,7 +380,7 @@ class BaseOptionsSelector extends Component { errorText={this.state.errorMessage} onSubmitEditing={this.selectFocusedOption} placeholder={this.props.placeholderText} - maxLength={this.props.maxLength + CONST.ERROR_EXCEED_RANGE} + maxLength={this.props.maxLength + CONST.ADDITIONAL_ALLOWED_CHARACTERS} keyboardType={this.props.keyboardType} onBlur={(e) => { if (!this.props.shouldFocusOnSelectRow) {