Fixed metrics display.

This commit is contained in:
Mike Cao 2023-03-31 05:55:28 -07:00
parent 2172dddd1c
commit 9dd35b3766
20 changed files with 345 additions and 808 deletions

View File

@ -1,27 +1,32 @@
import { Icon, Icons } from 'react-basics';
import classNames from 'classnames';
import Link from 'next/link';
import { safeDecodeURI } from 'next-basics';
import usePageQuery from 'hooks/usePageQuery';
import { Icon, Icons } from 'react-basics';
import useMessages from 'hooks/useMessages';
import styles from './FilterLink.module.css';
export default function FilterLink({ id, value, label, externalUrl }) {
const { formatMessage, labels } = useMessages();
const { resolveUrl, query } = usePageQuery();
const active = query[id] !== undefined;
const selected = query[id] === value;
return (
<div className={styles.row}>
<Link
href={resolveUrl({ [id]: value })}
className={classNames(styles.label, {
[styles.inactive]: active && !selected,
[styles.active]: active && selected,
})}
replace
>
{safeDecodeURI(label || value)}
</Link>
{!value && <span className={styles.empty}>{label || formatMessage(labels.unknown)}</span>}
{value && (
<Link
href={resolveUrl({ [id]: value })}
className={classNames(styles.label, {
[styles.inactive]: active && !selected,
[styles.active]: active && selected,
})}
replace
>
{safeDecodeURI(label || value)}
</Link>
)}
{externalUrl && (
<a className={styles.link} href={externalUrl} target="_blank" rel="noreferrer noopener">
<Icon className={styles.icon}>

View File

@ -30,3 +30,7 @@
.icon {
cursor: pointer;
}
.empty {
color: var(--base400);
}

View File

@ -1,6 +1,7 @@
.tag {
padding: 2px 4px;
border: 1px solid var(--base300);
padding: 4px 6px;
border-radius: 4px;
margin-right: 10px;
color: var(--primary400);
background: var(--blue100);
}

View File

@ -113,6 +113,8 @@ export const labels = defineMessages({
mobile: { id: 'label.mobile', defaultMessage: 'Mobile' },
toggleCharts: { id: 'label.toggle-charts', defaultMessage: 'Toggle charts' },
editDashboard: { id: 'label.edit-dashboard', defaultMessage: 'Edit dashboard' },
title: { id: 'label.title', defaultMessage: 'Title' },
url: { id: 'label.url', defaultMessage: 'URL' },
});
export const messages = defineMessages({

View File

@ -13,11 +13,7 @@ export default function CountriesTable({ websiteId, onDataLoad, ...props }) {
function renderLink({ x: code }) {
return (
<div className={locale}>
<FilterLink
id="country"
value={code}
label={countryNames[code] ?? formatMessage(labels.unknown)}
/>
<FilterLink id="country" value={countryNames[code] && code} label={countryNames[code]} />
</div>
);
}

View File

@ -9,7 +9,7 @@ export default function DevicesTable({ websiteId, ...props }) {
return (
<FilterLink
id="device"
value={device}
value={labels[device] && device}
label={formatMessage(labels[device] || labels.unknown)}
/>
);

View File

@ -1,27 +1,24 @@
import MetricsTable from './MetricsTable';
import { percentFilter } from 'lib/filters';
import { FormattedMessage } from 'react-intl';
import useLanguageNames from 'hooks/useLanguageNames';
import useLocale from 'hooks/useLocale';
import useMessages from 'hooks/useMessages';
export default function LanguagesTable({ websiteId, onDataLoad, ...props }) {
const { formatMessage, labels } = useMessages();
const { locale } = useLocale();
const languageNames = useLanguageNames(locale);
function renderLabel({ x }) {
return (
<div className={locale}>
{languageNames[x] ?? <FormattedMessage id="label.unknown" defaultMessage="Unknown" />}{' '}
</div>
);
}
const renderLabel = ({ x }) => {
return <div className={locale}>{languageNames[x?.split('-')[0]] ?? x}</div>;
};
return (
<MetricsTable
{...props}
title={<FormattedMessage id="metrics.languages" defaultMessage="Languages" />}
title={formatMessage(labels.languages)}
type="language"
metric={<FormattedMessage id="metrics.visitors" defaultMessage="Visitors" />}
metric={formatMessage(labels.visitors)}
websiteId={websiteId}
onDataLoad={data => onDataLoad?.(percentFilter(data))}
renderLabel={renderLabel}

View File

@ -1,19 +1,42 @@
import FilterLink from 'components/common/FilterLink';
import FilterButtons from 'components/common/FilterButtons';
import MetricsTable from './MetricsTable';
import useMessages from 'hooks/useMessages';
import usePageQuery from 'hooks/usePageQuery';
export default function PagesTable({ websiteId, ...props }) {
export default function PagesTable({ websiteId, showFilters, ...props }) {
const {
router,
resolveUrl,
query: { view },
} = usePageQuery();
const { formatMessage, labels } = useMessages();
const renderLink = ({ x: url }) => {
return <FilterLink id="url" value={url} />;
const handleSelect = key => {
router.push(resolveUrl({ view: key }), null, { shallow: true });
};
const buttons = [
{
label: formatMessage(labels.url),
key: 'url',
},
{
label: formatMessage(labels.title),
key: 'title',
},
];
const renderLink = ({ x }) => {
return <FilterLink id={view} value={x || `(${formatMessage(labels.none)})`} />;
};
return (
<>
{showFilters && <FilterButtons items={buttons} selectedKey={view} onSelect={handleSelect} />}
<MetricsTable
title={formatMessage(labels.pages)}
type="url"
type={view}
metric={formatMessage(labels.views)}
websiteId={websiteId}
renderLabel={renderLink}

View File

@ -6,10 +6,13 @@ export default function ReferrersTable({ websiteId, ...props }) {
const { formatMessage, labels } = useMessages();
const renderLink = ({ w: link, x: referrer }) => {
return referrer ? (
<FilterLink id="referrer" value={referrer} externalUrl={link} />
) : (
`(${formatMessage(labels.none)})`
return (
<FilterLink
id="referrer"
value={referrer}
externalUrl={link}
label={!referrer && `(${formatMessage(labels.none)})`}
/>
);
};

View File

@ -21,7 +21,7 @@ import useMessages from 'hooks/useMessages';
export default function WebsiteChart({
websiteId,
title,
name,
domain,
stickyHeader = false,
showChart = true,
@ -33,7 +33,7 @@ export default function WebsiteChart({
const { startDate, endDate, unit, value, modified } = dateRange;
const [timezone] = useTimezone();
const {
query: { url, referrer, os, browser, device, country },
query: { url, referrer, os, browser, device, country, title },
} = usePageQuery();
const { get, useQuery } = useApi();
const { ref, isSticky } = useSticky({ enabled: stickyHeader });
@ -68,7 +68,7 @@ export default function WebsiteChart({
return (
<>
<WebsiteHeader websiteId={websiteId} title={title} domain={domain}>
<WebsiteHeader websiteId={websiteId} name={name} domain={domain}>
{showDetailsButton && (
<Link href={`/websites/${websiteId}`}>
<Button variant="primary">
@ -80,7 +80,10 @@ export default function WebsiteChart({
</Link>
)}
</WebsiteHeader>
<FilterTags websiteId={websiteId} params={{ url, referrer, os, browser, device, country }} />
<FilterTags
websiteId={websiteId}
params={{ url, referrer, os, browser, device, country, title }}
/>
<Row
ref={ref}
className={classNames(styles.header, {

View File

@ -3,12 +3,12 @@ import Favicon from 'components/common/Favicon';
import ActiveUsers from './ActiveUsers';
import styles from './WebsiteHeader.module.css';
export default function WebsiteHeader({ websiteId, title, domain, children }) {
export default function WebsiteHeader({ websiteId, name, domain, children }) {
return (
<Row className={styles.header} justifyContent="center">
<Column className={styles.title} variant="two">
<Column className={styles.name} variant="two">
<Favicon domain={domain} />
<Text>{title}</Text>
<Text>{name}</Text>
</Column>
<Column className={styles.body} variant="two">
<ActiveUsers websiteId={websiteId} />

View File

@ -2,7 +2,7 @@
height: 100px;
}
.title {
.name {
display: flex;
flex-direction: row;
align-items: center;

View File

@ -122,7 +122,7 @@ export default function TestConsole() {
<Column>
<WebsiteChart
websiteId={website.id}
title={website.name}
name={website.name}
domain={website.domain}
showLink
/>

View File

@ -22,7 +22,7 @@ export default function WebsiteChartList({ websites, showCharts, limit }) {
<div key={id} className={styles.website}>
<WebsiteChart
websiteId={id}
title={name}
name={name}
domain={domain}
showChart={showCharts}
showDetailsButton={true}

View File

@ -29,7 +29,7 @@ export default function WebsiteDetails({ websiteId }) {
<Page loading={isLoading} error={error}>
<WebsiteChart
websiteId={websiteId}
title={data?.name}
name={data?.name}
domain={data?.domain}
onDataLoad={handleDataLoad}
showLink={false}

View File

@ -1,4 +1,4 @@
import { Menu, Item, Icon, Button, Flexbox, Text } from 'react-basics';
import { Icon, Button, Flexbox, Text } from 'react-basics';
import Link from 'next/link';
import { GridRow, GridColumn } from 'components/layout/Grid';
import BrowsersTable from 'components/metrics/BrowsersTable';
@ -19,6 +19,7 @@ import styles from './WebsiteMenuView.module.css';
const views = {
url: PagesTable,
title: PagesTable,
referrer: ReferrersTable,
browser: BrowsersTable,
os: OSTable,

View File

@ -1,6 +1,5 @@
import { useState } from 'react';
import { GridRow, GridColumn } from 'components/layout/Grid';
//import { Row as GridRow, Column as GridColumn } from 'react-basics';
import PagesTable from 'components/metrics/PagesTable';
import ReferrersTable from 'components/metrics/ReferrersTable';
import BrowsersTable from 'components/metrics/BrowsersTable';

View File

@ -17,7 +17,7 @@ const sessionColumns = [
'subdivision2',
'city',
];
const pageviewColumns = ['url', 'referrer', 'query', 'pageTitle'];
const pageviewColumns = ['url', 'referrer', 'query', 'title'];
function getTable(type) {
if (type === 'event') {
@ -45,6 +45,8 @@ function getColumn(type) {
return 'event_name';
case 'query':
return 'url_query';
case 'title':
return 'page_title';
}
return type;
@ -57,7 +59,7 @@ export interface WebsiteMetricsRequestQuery {
endAt: number;
url: string;
referrer: string;
pageTitle: string;
title: string;
os: string;
browser: string;
device: string;
@ -81,7 +83,7 @@ export default async (
endAt,
url,
referrer,
pageTitle,
title,
os,
browser,
device,
@ -154,7 +156,7 @@ export default async (
domain,
url: type !== 'url' && table !== 'event' ? url : undefined,
referrer: type !== 'referrer' && table !== 'event' ? referrer : FILTER_IGNORED,
pageTitle: type !== 'pageTitle' && table !== 'event' ? pageTitle : undefined,
title: type !== 'title' && table !== 'event' ? title : undefined,
os: type !== 'os' ? os : undefined,
browser: type !== 'browser' ? browser : undefined,
device: type !== 'device' ? device : undefined,

View File

@ -116,10 +116,9 @@
!(e.ctrlKey || e.shiftKey || e.metaKey || (e.button && e.button === 1))
) {
e.preventDefault();
track(eventName, { data: eventData }).then(() => {
return track(eventName, { data: eventData }).then(() => {
location.href = href;
});
return;
}
}

1006
yarn.lock

File diff suppressed because it is too large Load Diff