mirror of
https://github.com/plausible/analytics.git
synced 2024-11-23 11:12:15 +03:00
Autoselect prop key (#4253)
* Autoselect propkey on opening properties breakdown * reset propkey when query changes * ignore custom prop filter when selecting a prop key * throttle api requests * Force loading state on combobox when loading propkey * Remove artificial throttling of API requests * Disable combobox when no prop keys are found * drop prop_key and set loading true when query changes * Update changelog --------- Co-authored-by: Robert Joonas <robertjoonas16@gmail.com> Co-authored-by: RobertJoonas <56999674+RobertJoonas@users.noreply.github.com>
This commit is contained in:
parent
486ee68ca8
commit
a7ddc1a141
@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
### Added
|
||||
- Icons for browsers plausible/analytics#4239
|
||||
- Automatic custom property selection in the dashboard Properties report
|
||||
|
||||
### Removed
|
||||
|
||||
|
@ -37,7 +37,7 @@ function optionId(index) {
|
||||
|
||||
export default function PlausibleCombobox(props) {
|
||||
const [options, setOptions] = useState([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [isLoading, setLoading] = useState(false)
|
||||
const [isOpen, setOpen] = useState(false)
|
||||
const [input, setInput] = useState('')
|
||||
const [highlightedIndex, setHighlightedIndex] = useState(0)
|
||||
@ -45,6 +45,8 @@ export default function PlausibleCombobox(props) {
|
||||
const containerRef = useRef(null)
|
||||
const listRef = useRef(null)
|
||||
|
||||
const loading = isLoading || !!props.forceLoading
|
||||
|
||||
const visibleOptions = [...options]
|
||||
if (props.freeChoice && input.length > 0 && options.every(option => option.value !== input)) {
|
||||
visibleOptions.push({value: input, label: input, freeChoice: true})
|
||||
|
@ -1,11 +1,12 @@
|
||||
import React, { useCallback, useState } from "react"
|
||||
import ListReport from "../reports/list";
|
||||
import React, { useCallback, useEffect, useState } from "react"
|
||||
import ListReport, { MIN_HEIGHT } from "../reports/list";
|
||||
import Combobox from '../../components/combobox'
|
||||
import * as api from '../../api'
|
||||
import * as url from '../../util/url'
|
||||
import { CR_METRIC, PERCENTAGE_METRIC } from "../reports/metrics";
|
||||
import * as storage from "../../util/storage";
|
||||
import { getFiltersByKeyPrefix, EVENT_PROPS_PREFIX, getPropertyKeyFromFilterKey, getGoalFilter, FILTER_OPERATIONS, hasGoalFilter } from "../../util/filters"
|
||||
import { EVENT_PROPS_PREFIX, getGoalFilter, FILTER_OPERATIONS, hasGoalFilter } from "../../util/filters"
|
||||
import classNames from "classnames";
|
||||
|
||||
|
||||
export default function Properties(props) {
|
||||
@ -16,7 +17,8 @@ export default function Properties(props) {
|
||||
return `${goal}__prop_key__${site.domain}`
|
||||
}
|
||||
|
||||
const [propKey, setPropKey] = useState(choosePropKey())
|
||||
const [propKey, setPropKey] = useState(null)
|
||||
const [propKeyLoading, setPropKeyLoading] = useState(true)
|
||||
|
||||
function singleGoalFilterApplied() {
|
||||
const goalFilter = getGoalFilter(query)
|
||||
@ -28,15 +30,26 @@ export default function Properties(props) {
|
||||
}
|
||||
}
|
||||
|
||||
function choosePropKey() {
|
||||
const propFilters = getFiltersByKeyPrefix(query, EVENT_PROPS_PREFIX)
|
||||
if (propFilters.length > 0) {
|
||||
const [_operation, filterKey, _clauses] = propFilters[0]
|
||||
return getPropertyKeyFromFilterKey(filterKey)
|
||||
} else {
|
||||
return getPropKeyFromStorage()
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
setPropKeyLoading(true)
|
||||
setPropKey(null)
|
||||
|
||||
fetchPropKeyOptions()("").then((propKeys) => {
|
||||
const propKeyValues = propKeys.map(entry => entry.value)
|
||||
|
||||
if (propKeyValues.length > 0) {
|
||||
const storedPropKey = getPropKeyFromStorage()
|
||||
|
||||
if (propKeyValues.includes(storedPropKey)) {
|
||||
setPropKey(storedPropKey)
|
||||
} else {
|
||||
setPropKey(propKeys[0].value)
|
||||
}
|
||||
}
|
||||
|
||||
setPropKeyLoading(false)
|
||||
})
|
||||
}, [query])
|
||||
|
||||
function getPropKeyFromStorage() {
|
||||
if (singleGoalFilterApplied()) {
|
||||
@ -99,13 +112,19 @@ export default function Properties(props) {
|
||||
filter: ["is", `${EVENT_PROPS_PREFIX}${propKey}`, [listItem.name]]
|
||||
})
|
||||
|
||||
const comboboxDisabled = !propKeyLoading && !propKey
|
||||
const comboboxPlaceholder = comboboxDisabled ? 'No custom properties found' : ''
|
||||
const comboboxValues = propKey ? [{ value: propKey, label: propKey }] : []
|
||||
const boxClass = 'pl-2 pr-8 py-1 bg-transparent dark:text-gray-300 rounded-md shadow-sm border border-gray-300 dark:border-gray-500'
|
||||
const boxClass = classNames('pl-2 pr-8 py-1 bg-transparent dark:text-gray-300 rounded-md shadow-sm border border-gray-300 dark:border-gray-500', {
|
||||
'pointer-events-none': comboboxDisabled
|
||||
})
|
||||
|
||||
const COMBOBOX_HEIGHT = 40
|
||||
|
||||
return (
|
||||
<div className="w-full mt-4">
|
||||
<div>
|
||||
<Combobox boxClass={boxClass} fetchOptions={fetchPropKeyOptions()} singleOption={true} values={comboboxValues} onSelect={onPropKeySelect()} placeholder={'Select a property'} />
|
||||
<div className="w-full mt-4" style={{ minHeight: `${COMBOBOX_HEIGHT + MIN_HEIGHT}px` }}>
|
||||
<div style={{ minHeight: `${COMBOBOX_HEIGHT}px` }}>
|
||||
<Combobox boxClass={boxClass} forceLoading={propKeyLoading} fetchOptions={fetchPropKeyOptions()} singleOption={true} values={comboboxValues} onSelect={onPropKeySelect()} placeholder={comboboxPlaceholder} />
|
||||
</div>
|
||||
{propKey && renderBreakdown()}
|
||||
</div>
|
||||
|
@ -11,7 +11,7 @@ import classNames from 'classnames'
|
||||
import { trimURL, updatedQuery } from '../../util/url'
|
||||
import { cleanLabels, hasGoalFilter, replaceFilterByPrefix } from '../../util/filters'
|
||||
const MAX_ITEMS = 9
|
||||
const MIN_HEIGHT = 380
|
||||
export const MIN_HEIGHT = 380
|
||||
const ROW_HEIGHT = 32
|
||||
const ROW_GAP_HEIGHT = 4
|
||||
const DATA_CONTAINER_HEIGHT = (ROW_HEIGHT + ROW_GAP_HEIGHT) * (MAX_ITEMS - 1) + ROW_HEIGHT
|
||||
|
Loading…
Reference in New Issue
Block a user