mirror of
https://github.com/umami-software/umami.git
synced 2025-12-06 01:18:00 +01:00
fix visitDuration calculation and conditionally show bounce/visitDuration on session columns
Some checks failed
Node.js CI / build (postgresql, 18.18) (push) Has been cancelled
Some checks failed
Node.js CI / build (postgresql, 18.18) (push) Has been cancelled
This commit is contained in:
parent
6c832bd0db
commit
f06ef6fbc9
4 changed files with 28 additions and 106 deletions
|
|
@ -59,7 +59,7 @@ export function Breakdown({ websiteId, selectedFields = [], startDate, endDate }
|
|||
</DataColumn>
|
||||
<DataColumn id="visitDuration" label={formatMessage(labels.visitDuration)} align="end">
|
||||
{row => {
|
||||
const n = (row?.['totaltime'] / row?.['visits']) * 100;
|
||||
const n = row?.['totaltime'] / row?.['visits'];
|
||||
return `${+n < 0 ? '-' : ''}${formatShortTime(Math.abs(~~n), ['m', 's'], ' ')}`;
|
||||
}}
|
||||
</DataColumn>
|
||||
|
|
|
|||
|
|
@ -1,42 +0,0 @@
|
|||
import { FilterLink } from '@/components/common/FilterLink';
|
||||
import { useCountryNames } from '@/components/hooks';
|
||||
import { useLocale, useMessages, useFormat } from '@/components/hooks';
|
||||
import { MetricsTable, MetricsTableProps } from './MetricsTable';
|
||||
import { TypeIcon } from '@/components/common/TypeIcon';
|
||||
import { MetricsExpandedTable } from '@/components/metrics/MetricsExpandedTable';
|
||||
|
||||
export interface CountriesTableProps extends MetricsTableProps {
|
||||
isExpanded?: boolean;
|
||||
}
|
||||
|
||||
export function CountriesTable({ isExpanded, ...props }: CountriesTableProps) {
|
||||
const { locale } = useLocale();
|
||||
const { countryNames } = useCountryNames(locale);
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { formatCountry } = useFormat();
|
||||
|
||||
const renderLabel = ({ label: code }) => {
|
||||
return (
|
||||
<FilterLink
|
||||
type="country"
|
||||
value={(countryNames[code] && code) || code}
|
||||
label={formatCountry(code)}
|
||||
>
|
||||
<TypeIcon type="country" value={code} />
|
||||
</FilterLink>
|
||||
);
|
||||
};
|
||||
|
||||
const Component = isExpanded ? MetricsExpandedTable : MetricsTable;
|
||||
|
||||
return (
|
||||
<Component
|
||||
{...props}
|
||||
title={formatMessage(labels.countries)}
|
||||
type="country"
|
||||
metric={formatMessage(labels.visitors)}
|
||||
renderLabel={renderLabel}
|
||||
searchFormattedValues={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
import { useMessages } from '@/components/hooks';
|
||||
import { formatShortTime } from '@/lib/format';
|
||||
import { DataColumn, DataTable } from '@umami/react-zen';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export interface ListExpandedTableProps {
|
||||
data?: any[];
|
||||
title?: string;
|
||||
renderLabel?: (row: any, index: number) => ReactNode;
|
||||
}
|
||||
|
||||
export function ListExpandedTable({ data = [], title, renderLabel }: ListExpandedTableProps) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
||||
return (
|
||||
<DataTable data={data}>
|
||||
<DataColumn id="label" label={title} align="start">
|
||||
{row =>
|
||||
renderLabel
|
||||
? renderLabel({ x: row?.['name'], country: row?.['country'] }, Number(row.id))
|
||||
: (row?.['name'] ?? formatMessage(labels.unknown))
|
||||
}
|
||||
</DataColumn>
|
||||
<DataColumn id="visitors" label={formatMessage(labels.visitors)} align="end">
|
||||
{row => row?.['visitors']?.toLocaleString()}
|
||||
</DataColumn>
|
||||
<DataColumn id="visits" label={formatMessage(labels.visits)} align="end">
|
||||
{row => row?.['visits']?.toLocaleString()}
|
||||
</DataColumn>
|
||||
<DataColumn id="pageviews" label={formatMessage(labels.views)} align="end">
|
||||
{row => row?.['pageviews']?.toLocaleString()}
|
||||
</DataColumn>
|
||||
<DataColumn id="bounceRate" label={formatMessage(labels.bounceRate)} align="end">
|
||||
{row => {
|
||||
const n = (Math.min(row?.['visits'], row?.['bounces']) / row?.['visits']) * 100;
|
||||
return Math.round(+n) + '%';
|
||||
}}
|
||||
</DataColumn>
|
||||
<DataColumn id="visitDuration" label={formatMessage(labels.visitDuration)} align="end">
|
||||
{row => {
|
||||
const n = (row?.['totaltime'] / row?.['visits']) * 100;
|
||||
return `${+n < 0 ? '-' : ''}${formatShortTime(Math.abs(~~n), ['m', 's'], ' ')}`;
|
||||
}}
|
||||
</DataColumn>
|
||||
</DataTable>
|
||||
);
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import { Close } from '@/components/icons';
|
|||
import { DownloadButton } from '@/components/input/DownloadButton';
|
||||
import { formatShortTime } from '@/lib/format';
|
||||
import { MetricLabel } from '@/components/metrics/MetricLabel';
|
||||
import { SESSION_COLUMNS } from '@/lib/constants';
|
||||
|
||||
export interface MetricsExpandedTableProps {
|
||||
websiteId: string;
|
||||
|
|
@ -34,6 +35,7 @@ export function MetricsExpandedTable({
|
|||
const [search, setSearch] = useState('');
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const isType = ['browser', 'country', 'device', 'os'].includes(type);
|
||||
const showBounceDuration = SESSION_COLUMNS.includes(type);
|
||||
|
||||
const { data, isLoading, isFetching, error } = useWebsiteExpandedMetricsQuery(websiteId, {
|
||||
type,
|
||||
|
|
@ -85,22 +87,31 @@ export function MetricsExpandedTable({
|
|||
<DataColumn id="pageviews" label={formatMessage(labels.views)} align="end">
|
||||
{row => row?.['pageviews']?.toLocaleString()}
|
||||
</DataColumn>
|
||||
<DataColumn id="bounceRate" label={formatMessage(labels.bounceRate)} align="end">
|
||||
{row => {
|
||||
const n = (Math.min(row?.['visits'], row?.['bounces']) / row?.['visits']) * 100;
|
||||
return Math.round(+n) + '%';
|
||||
}}
|
||||
</DataColumn>
|
||||
<DataColumn
|
||||
id="visitDuration"
|
||||
label={formatMessage(labels.visitDuration)}
|
||||
align="end"
|
||||
>
|
||||
{row => {
|
||||
const n = (row?.['totaltime'] / row?.['visits']) * 100;
|
||||
return `${+n < 0 ? '-' : ''}${formatShortTime(Math.abs(~~n), ['m', 's'], ' ')}`;
|
||||
}}
|
||||
</DataColumn>
|
||||
{showBounceDuration && [
|
||||
<DataColumn
|
||||
key="bounceRate"
|
||||
id="bounceRate"
|
||||
label={formatMessage(labels.bounceRate)}
|
||||
align="end"
|
||||
>
|
||||
{row => {
|
||||
const n = (Math.min(row?.['visits'], row?.['bounces']) / row?.['visits']) * 100;
|
||||
return Math.round(+n) + '%';
|
||||
}}
|
||||
</DataColumn>,
|
||||
|
||||
<DataColumn
|
||||
key="visitDuration"
|
||||
id="visitDuration"
|
||||
label={formatMessage(labels.visitDuration)}
|
||||
align="end"
|
||||
>
|
||||
{row => {
|
||||
const n = row?.['totaltime'] / row?.['visits'];
|
||||
return `${+n < 0 ? '-' : ''}${formatShortTime(Math.abs(~~n), ['m', 's'], ' ')}`;
|
||||
}}
|
||||
</DataColumn>,
|
||||
]}
|
||||
</DataTable>
|
||||
)}
|
||||
</Column>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue