mirror of
https://github.com/plausible/analytics.git
synced 2024-12-22 17:11:36 +03:00
8ac166b447
* extract add_exit_rate function * Change internal API metric names for /entry-pages & /exit-pages * `unique_entrances` -> `visitors`, * `total_entrances` -> `visits`, * `unique_exits` -> `visitors`, * `total_exits` -> `visits`, This is just a consistency improvement - the `visitors` metric always means one thing and there's no need to call it different for entry pages internally. This commit does not change any noticable behavior. The UI labels are kept the same and the column headers in the CSV export will also remain the same. * Change internal API metric names for /conversions * `unique_conversions` -> `visitors`, * `total_conversions` -> `events`, * return revenue metrics from /custom-prop-values (backend) * be more explicit about which metric is plotted with Bar * validate that ListReport input metrics actually exist in the API response * display revenue metrics in the dashboard Properties section * limit the number of columns shown on mobile * add revenue metrics to Properties > Details * review suggestions * define hiddenOnMobile per metric instead of keeping the first 3 * rewrite if-else block --------- Co-authored-by: Vini Brasil <vini@hey.com>
72 lines
2.5 KiB
JavaScript
72 lines
2.5 KiB
JavaScript
import React, { useCallback, useState } from "react";
|
|
import ListReport 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";
|
|
|
|
export default function Properties(props) {
|
|
const { site, query } = props
|
|
const propKeyStorageName = `prop_key__${site.domain}`
|
|
const [propKey, setPropKey] = useState(defaultPropKey())
|
|
|
|
function defaultPropKey() {
|
|
const stored = storage.getItem(propKeyStorageName)
|
|
if (stored) { return stored }
|
|
return null
|
|
}
|
|
|
|
function fetchProps() {
|
|
return api.get(url.apiPath(site, `/custom-prop-values/${encodeURIComponent(propKey)}`), query)
|
|
}
|
|
|
|
const fetchPropKeyOptions = useCallback(() => {
|
|
return (input) => {
|
|
return api.get(url.apiPath(site, "/suggestions/prop_key"), query, { q: input.trim() })
|
|
}
|
|
}, [query])
|
|
|
|
function onPropKeySelect() {
|
|
return (selectedOptions) => {
|
|
const newPropKey = selectedOptions.length === 0 ? null : selectedOptions[0].value
|
|
|
|
if (newPropKey) { storage.setItem(propKeyStorageName, newPropKey) }
|
|
setPropKey(newPropKey)
|
|
}
|
|
}
|
|
|
|
function renderBreakdown() {
|
|
return (
|
|
<ListReport
|
|
fetchData={fetchProps}
|
|
getFilterFor={getFilterFor}
|
|
keyLabel={propKey}
|
|
metrics={[
|
|
{name: 'visitors', label: 'Visitors', plot: true},
|
|
{name: 'events', label: 'Events', hiddenOnMobile: true},
|
|
query.filters.goal ? CR_METRIC : PERCENTAGE_METRIC,
|
|
{name: 'total_revenue', label: 'Revenue', hiddenOnMobile: true},
|
|
{name: 'average_revenue', label: 'Average', hiddenOnMobile: true}
|
|
]}
|
|
detailsLink={url.sitePath(site, `/custom-prop-values/${propKey}`)}
|
|
query={query}
|
|
color="bg-red-50"
|
|
colMinWidth={90}
|
|
/>
|
|
)
|
|
}
|
|
|
|
const getFilterFor = (listItem) => { return {'props': JSON.stringify({[propKey]: listItem['name']})} }
|
|
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'
|
|
|
|
return (
|
|
<div className="w-full mt-4">
|
|
<div className="w-56">
|
|
<Combobox boxClass={boxClass} fetchOptions={fetchPropKeyOptions()} singleOption={true} values={comboboxValues} onSelect={onPropKeySelect()} placeholder={'Select a property'} />
|
|
</div>
|
|
{ propKey && renderBreakdown() }
|
|
</div>
|
|
)
|
|
} |