From f40b63e4941529d7c11115dfdec7bc7a00216839 Mon Sep 17 00:00:00 2001 From: Milan Patel Date: Sun, 18 Jun 2023 02:20:58 +0530 Subject: [PATCH 1/4] Add autocomplete for filter field selector - add strict prop to autocomplete to set value from suggestion only - add inner popover logic to detect inner popover click - add containerStyle to style input container - add suggestionsItemStyle to style suggestion list items --- .../Autocomplete/Autocomplete.react.js | 37 ++++++++++++++--- .../BrowserFilter/FilterRow.react.js | 41 ++++++++++++++++--- src/components/Popover/Popover.react.js | 8 ++++ .../SuggestionsList/SuggestionsList.react.js | 9 ++-- 4 files changed, 81 insertions(+), 14 deletions(-) diff --git a/src/components/Autocomplete/Autocomplete.react.js b/src/components/Autocomplete/Autocomplete.react.js index 785f61656b..24afa65dea 100644 --- a/src/components/Autocomplete/Autocomplete.react.js +++ b/src/components/Autocomplete/Autocomplete.react.js @@ -23,6 +23,7 @@ export default class Autocomplete extends Component { this.onBlur = this.onBlur.bind(this); this.onClick = this.onClick.bind(this); + this.onMouseDown = this.onMouseDown.bind(this); this.onChange = this.onChange.bind(this); this.onKeyDown = this.onKeyDown.bind(this); this.onInputClick = this.onInputClick.bind(this); @@ -46,10 +47,11 @@ export default class Autocomplete extends Component { }; this.state = { + valueFromSuggestion: props.strict ? props.value ?? props.suggestions[0] : "", activeSuggestion: 0, filteredSuggestions: [], showSuggestions: false, - userInput: '', + userInput: props.strict ? props.value ?? props.suggestions[0] : "", label: props.label, position: null }; @@ -60,6 +62,7 @@ export default class Autocomplete extends Component { this.fieldRef.current.addEventListener('scroll', this.handleScroll); this.recalculatePosition(); this._ignoreBlur = false; + this._suggestionClicked = false; } componentWillUnmount() { @@ -120,11 +123,12 @@ export default class Autocomplete extends Component { error: undefined }); - this.props.onChange && this.props.onChange(userInput); + if (!this.props.strict) this.props.onChange && this.props.onChange(userInput); } onClick(e) { const userInput = e.currentTarget.innerText; + if (this.props.strict) this.props.onChange && this.props.onChange(userInput); const label = this.props.label || this.props.buildLabel(userInput); this.inputRef.current.focus(); @@ -144,15 +148,33 @@ export default class Autocomplete extends Component { ); } + onMouseDown(e) { + this._suggestionClicked = true; + this.props.onMouseDown && this.props.onMouseDown(e); + } + onFocus(e) { if (!this._ignoreBlur && !this.state.showSuggestions) { this._ignoreBlur = true; } - + if(this.props.strict) e.target.select(); this.activate(e); } onBlur(e) { + if (this.props.strict) { + if (!this._suggestionClicked) { + if (!this.props.suggestions.includes(this.state.userInput)) { + this.setState({ userInput: this.state.valueFromSuggestion }); + this.props.onChange && + this.props.onChange(this.state.valueFromSuggestion); + } else { + this.setState({ valueFromSuggestion: this.state.userInput }); + this.props.onChange && this.props.onChange(this.state.userInput); + } + } + this._suggestionClicked = false; + } this.props.onBlur && this.props.onBlur(e); } @@ -279,9 +301,10 @@ export default class Autocomplete extends Component { onChange, onClick, onBlur, + onMouseDown, onFocus, onKeyDown, - props: { suggestionsStyle, inputStyle, placeholder, error }, + props: {suggestionsStyle, suggestionsItemStyle, inputStyle, containerStyle, placeholder, error }, state: { activeSuggestion, filteredSuggestions, @@ -314,19 +337,21 @@ export default class Autocomplete extends Component { onExternalClick={onExternalClick} suggestions={filteredSuggestions} suggestionsStyle={suggestionsStyle} + suggestionsItemStyle={suggestionsItemStyle} activeSuggestion={activeSuggestion} onClick={onClick} + onMouseDown={onMouseDown} /> ); } return ( -
+
- + suggestions={fields} + onChange={onChangeField} + buildSuggestions={(input) => fields.filter((s) => s.startsWith(input))} + buildLabel={() => ''} + />
    {suggestions.map((suggestion, index) => { @@ -57,7 +60,7 @@ export default class Suggestion extends React.Component { className = styles.active; } return ( -
  • +
  • {suggestion}
  • ); From 676e8923876b8da356d876f1d8cd2e3f6b4465ee Mon Sep 17 00:00:00 2001 From: Milan Patel Date: Sun, 18 Jun 2023 02:33:35 +0530 Subject: [PATCH 2/4] fix linting issue --- .../Autocomplete/Autocomplete.react.js | 4 +- .../BrowserFilter/FilterRow.react.js | 38 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/components/Autocomplete/Autocomplete.react.js b/src/components/Autocomplete/Autocomplete.react.js index 24afa65dea..6e0647baae 100644 --- a/src/components/Autocomplete/Autocomplete.react.js +++ b/src/components/Autocomplete/Autocomplete.react.js @@ -47,11 +47,11 @@ export default class Autocomplete extends Component { }; this.state = { - valueFromSuggestion: props.strict ? props.value ?? props.suggestions[0] : "", + valueFromSuggestion: props.strict ? props.value ?? props.suggestions[0] : '', activeSuggestion: 0, filteredSuggestions: [], showSuggestions: false, - userInput: props.strict ? props.value ?? props.suggestions[0] : "", + userInput: props.strict ? props.value ?? props.suggestions[0] : '', label: props.label, position: null }; diff --git a/src/components/BrowserFilter/FilterRow.react.js b/src/components/BrowserFilter/FilterRow.react.js index a29dc19292..5a87c03044 100644 --- a/src/components/BrowserFilter/FilterRow.react.js +++ b/src/components/BrowserFilter/FilterRow.react.js @@ -99,31 +99,31 @@ let FilterRow = ({
    Date: Sun, 18 Jun 2023 13:50:37 +0530 Subject: [PATCH 3/4] make search criteria broader for autocomplete --- src/components/BrowserFilter/FilterRow.react.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/components/BrowserFilter/FilterRow.react.js b/src/components/BrowserFilter/FilterRow.react.js index 5a87c03044..4eb40c5eea 100644 --- a/src/components/BrowserFilter/FilterRow.react.js +++ b/src/components/BrowserFilter/FilterRow.react.js @@ -95,6 +95,20 @@ let FilterRow = ({ } }, []) + // This will add https://github.com/parse-community/parse-dashboard/pull/2463#issuecomment-1595918018 + const buildSuggestions = (input) => { + const lowerCaseInput = input.toLowerCase(); + return fields.filter((field) => { + let inputIndex = 0; + for (let i = 0; i < field.length; i++) { + if (field[i].toLowerCase() === lowerCaseInput[inputIndex]) { + inputIndex++; + } + } + return inputIndex === lowerCaseInput.length; + }); + }; + return (
    fields.filter((s) => s.startsWith(input))} + buildSuggestions={buildSuggestions} buildLabel={() => ''} /> Date: Tue, 20 Jun 2023 01:13:21 +0530 Subject: [PATCH 4/4] refactor filter logic to regex for autocomplete --- src/components/BrowserFilter/FilterRow.react.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/components/BrowserFilter/FilterRow.react.js b/src/components/BrowserFilter/FilterRow.react.js index 4eb40c5eea..eed8c281b2 100644 --- a/src/components/BrowserFilter/FilterRow.react.js +++ b/src/components/BrowserFilter/FilterRow.react.js @@ -95,18 +95,9 @@ let FilterRow = ({ } }, []) - // This will add https://github.com/parse-community/parse-dashboard/pull/2463#issuecomment-1595918018 const buildSuggestions = (input) => { - const lowerCaseInput = input.toLowerCase(); - return fields.filter((field) => { - let inputIndex = 0; - for (let i = 0; i < field.length; i++) { - if (field[i].toLowerCase() === lowerCaseInput[inputIndex]) { - inputIndex++; - } - } - return inputIndex === lowerCaseInput.length; - }); + const regex = new RegExp(input.split('').join('.*?'), 'i'); + return fields.filter(f => regex.test(f)); }; return (