Fix open state in combobox (#2797)

* Fix open state in combobox

* Improve filter suggestions when using the `contains` filter

* Support contains filter type for utm filter group

* Remove console.log
This commit is contained in:
Uku Taht 2023-03-28 21:06:37 +03:00 committed by GitHub
parent 66be99b38a
commit 70f1c6538d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 19 additions and 12 deletions

View File

@ -1,6 +1,7 @@
{
"env": {
"browser": true
"browser": true,
"es6": true
},
"extends": ["eslint:recommended",
"plugin:react/recommended",

View File

@ -99,6 +99,7 @@ export default function PlausibleCombobox(props) {
function fetchOptions(query) {
setLoading(true)
setOpen(true)
return props.fetchOptions(query).then((loadedOptions) => {
setLoading(false)
@ -119,7 +120,6 @@ export default function PlausibleCombobox(props) {
if (!isOpen) {
fetchOptions(input)
searchRef.current.focus()
setOpen(true)
} else {
setInput('')
setOpen(false)
@ -186,11 +186,16 @@ export default function PlausibleCombobox(props) {
Loading options...
</div>
)}
{ noMatchesFound && (
{ noMatchesFound && !props.freeChoice && (
<div className="relative cursor-default select-none py-2 px-4 text-gray-700 dark:text-gray-300">
No matches found in the current dashboard. Try selecting a different time range or searching for something different
</div>
)}
{ noMatchesFound && props.freeChoice && (
<div className="relative cursor-default select-none py-2 px-4 text-gray-700 dark:text-gray-300">
Start typing to apply filter
</div>
)}
{ matchesFound && (
visibleOptions.map((option, i) => {
const text = option.freeChoice ? `Filter by '${option.label}'` : option.label

View File

@ -35,10 +35,6 @@ function getFormState(filterGroup, query) {
}, {})
}
function supportsContains(filterName) {
return ['page', 'entry_page', 'exit_page'].includes(filterName)
}
function supportsIsNot(filterName) {
return !['goal', 'prop_key'].includes(filterName)
}
@ -122,6 +118,8 @@ class FilterModal extends React.Component {
fetchOptions(filter) {
return (input) => {
const { query, formState } = this.state
if (formState[filter].type === FILTER_TYPES.contains) {return Promise.resolve([])}
const formFilters = Object.fromEntries(
Object.entries(formState).map(([filter, {type, clauses}]) => [filter, toFilterQuery(type, clauses)])
)
@ -147,6 +145,8 @@ class FilterModal extends React.Component {
return filterVal
} else if (filterVal.startsWith('!')) {
return filterVal
} else if (filterVal.startsWith('~')) {
return null
} else {
return '!' + filterVal
}
@ -178,9 +178,12 @@ class FilterModal extends React.Component {
this.props.history.replace({ pathname: siteBasePath(this.props.site), search: queryString.toString() })
}
isFreeChoice() {
return ['page', 'utm'].includes(this.state.selectedFilterGroup)
}
renderSearchBox(filter) {
const freeChoice = this.state.selectedFilterGroup === 'page'
return <Combobox fetchOptions={this.fetchOptions(filter)} freeChoice={freeChoice} values={this.state.formState[filter].clauses} onChange={this.onChange(filter)} placeholder={`Select ${withIndefiniteArticle(formattedFilters[filter])}`} />
return <Combobox fetchOptions={this.fetchOptions(filter)} freeChoice={this.isFreeChoice()} values={this.state.formState[filter].clauses} onChange={this.onChange(filter)} placeholder={`Select ${withIndefiniteArticle(formattedFilters[filter])}`} />
}
renderFilterInputs() {
@ -228,7 +231,7 @@ class FilterModal extends React.Component {
<div className="py-1">
{this.renderTypeItem(filterName, FILTER_TYPES.is, true)}
{this.renderTypeItem(filterName, FILTER_TYPES.isNot, supportsIsNot(filterName))}
{this.renderTypeItem(filterName, FILTER_TYPES.contains, supportsContains(filterName))}
{this.renderTypeItem(filterName, FILTER_TYPES.contains, this.isFreeChoice())}
</div>
</Menu.Items>
</Transition>

View File

@ -31,8 +31,6 @@ try {
NON_ESCAPED_PIPE_REGEX = '|'
}
console.log(NON_ESCAPED_PIPE_REGEX)
const ESCAPED_PIPE = '\\|'
function escapeFilterValue(value) {