mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 12:47:13 +01:00
New page and referrer url filters.
This commit is contained in:
parent
1d977875be
commit
cf8ed13d1f
11 changed files with 133 additions and 50 deletions
|
|
@ -1,7 +1,6 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import WebsiteChart from 'components/metrics/WebsiteChart';
|
||||
import MetricsTable from 'components/metrics/MetricsTable';
|
||||
import WorldMap from 'components/common/WorldMap';
|
||||
import Page from 'components/layout/Page';
|
||||
import WebsiteHeader from 'components/metrics/WebsiteHeader';
|
||||
|
|
@ -53,6 +52,17 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' })
|
|||
},
|
||||
];
|
||||
|
||||
const tableProps = {
|
||||
websiteId,
|
||||
startDate,
|
||||
endDate,
|
||||
limit: 10,
|
||||
onExpand: handleExpand,
|
||||
websiteDomain: data?.domain,
|
||||
};
|
||||
|
||||
const DetailsComponent = expand?.component;
|
||||
|
||||
async function loadData() {
|
||||
setData(await get(`/api/website/${websiteId}`));
|
||||
}
|
||||
|
|
@ -73,10 +83,6 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' })
|
|||
setExpand(menuOptions.find(e => e.value === value));
|
||||
}
|
||||
|
||||
function getMetricLabel(type) {
|
||||
return type === 'url' || type === 'referrer' ? 'Views' : 'Visitors';
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (websiteId) {
|
||||
loadData();
|
||||
|
|
@ -87,15 +93,6 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' })
|
|||
return null;
|
||||
}
|
||||
|
||||
const tableProps = {
|
||||
websiteId,
|
||||
startDate,
|
||||
endDate,
|
||||
limit: 10,
|
||||
onExpand: handleExpand,
|
||||
websiteDomain: data?.domain,
|
||||
};
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<div className="row">
|
||||
|
|
@ -149,7 +146,7 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' })
|
|||
selectedOption={expand.value}
|
||||
onMenuSelect={handleMenuSelect}
|
||||
>
|
||||
{expand.component({ ...tableProps, limit: false })}
|
||||
<DetailsComponent {...tableProps} limit={false} />
|
||||
</MenuLayout>
|
||||
)}
|
||||
</Page>
|
||||
|
|
|
|||
29
components/common/ButtonGroup.js
Normal file
29
components/common/ButtonGroup.js
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import Button from './Button';
|
||||
import styles from './ButtonGroup.module.css';
|
||||
|
||||
export default function ButtonGroup({
|
||||
items = [],
|
||||
selectedItem,
|
||||
className,
|
||||
size,
|
||||
icon,
|
||||
onClick = () => {},
|
||||
}) {
|
||||
return (
|
||||
<div className={classNames(styles.group, className)}>
|
||||
{items.map(item => (
|
||||
<Button
|
||||
key={item}
|
||||
className={classNames(styles.button, { [styles.selected]: selectedItem === item })}
|
||||
size={size}
|
||||
icon={icon}
|
||||
onClick={() => onClick(item)}
|
||||
>
|
||||
{item}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
25
components/common/ButtonGroup.module.css
Normal file
25
components/common/ButtonGroup.module.css
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
.group {
|
||||
display: inline-flex;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--gray400);
|
||||
}
|
||||
|
||||
.group .button {
|
||||
border-radius: 0;
|
||||
background: var(--gray50);
|
||||
border-left: 1px solid var(--gray400);
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.group .button:first-child {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.group .button + .button {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.selected {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ export default function Header() {
|
|||
<div className="col-12 col-md-6">
|
||||
<div className={styles.title}>
|
||||
<Icon icon={<Logo />} size="large" className={styles.logo} />
|
||||
{user ? <Link href="/">umami</Link> : 'umami'}
|
||||
<Link href={user ? '/' : 'https://umami.is'}>umami</Link>
|
||||
</div>
|
||||
</div>
|
||||
{user && (
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export default function MetricsTable({
|
|||
return items;
|
||||
}
|
||||
return [];
|
||||
}, [data]);
|
||||
}, [data, dataFilter, filterOptions]);
|
||||
|
||||
async function loadData() {
|
||||
const data = await get(`/api/website/${websiteId}/rankings`, {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import MetricsTable from './MetricsTable';
|
||||
import { urlFilter } from 'lib/filters';
|
||||
import ButtonGroup from '../common/ButtonGroup';
|
||||
|
||||
export default function PagesTable({
|
||||
websiteId,
|
||||
|
|
@ -10,19 +11,32 @@ export default function PagesTable({
|
|||
limit,
|
||||
onExpand,
|
||||
}) {
|
||||
const [filter, setFilter] = useState('Combined');
|
||||
|
||||
return (
|
||||
<MetricsTable
|
||||
title="Pages"
|
||||
type="url"
|
||||
metric="Views"
|
||||
headerComponent={null}
|
||||
headerComponent={limit ? null : <FilterButtons selected={filter} onClick={setFilter} />}
|
||||
websiteId={websiteId}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
limit={limit}
|
||||
dataFilter={urlFilter}
|
||||
filterOptions={{ domain: websiteDomain }}
|
||||
filterOptions={{ domain: websiteDomain, raw: filter === 'Raw' }}
|
||||
onExpand={onExpand}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const FilterButtons = ({ selected, onClick }) => {
|
||||
return (
|
||||
<ButtonGroup
|
||||
size="xsmall"
|
||||
items={['Combined', 'Raw']}
|
||||
selectedItem={selected}
|
||||
onClick={onClick}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,31 +1,28 @@
|
|||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import Button from '../common/Button';
|
||||
import ButtonGroup from 'components/common/ButtonGroup';
|
||||
import { getDateRange } from 'lib/date';
|
||||
import styles from './QuickButtons.module.css';
|
||||
|
||||
const options = {
|
||||
'24hour': '24h',
|
||||
'7day': '7d',
|
||||
'30day': '30d',
|
||||
'24h': '24hour',
|
||||
'7d': '7day',
|
||||
'30d': '30day',
|
||||
};
|
||||
|
||||
export default function QuickButtons({ value, onChange }) {
|
||||
const selectedItem = Object.keys(options).find(key => options[key] === value);
|
||||
|
||||
function handleClick(value) {
|
||||
onChange(getDateRange(value));
|
||||
onChange(getDateRange(options[value]));
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.buttons}>
|
||||
{Object.keys(options).map(key => (
|
||||
<Button
|
||||
key={key}
|
||||
className={classNames(styles.button, { [styles.active]: value === key })}
|
||||
onClick={() => handleClick(key)}
|
||||
>
|
||||
{options[key]}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<ButtonGroup
|
||||
size="xsmall"
|
||||
className={styles.buttons}
|
||||
items={Object.keys(options)}
|
||||
selectedItem={selectedItem}
|
||||
onClick={handleClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import MetricsTable from './MetricsTable';
|
||||
import { refFilter } from 'lib/filters';
|
||||
import ButtonGroup from '../common/ButtonGroup';
|
||||
|
||||
export default function Referrers({
|
||||
websiteId,
|
||||
|
|
@ -10,19 +11,36 @@ export default function Referrers({
|
|||
limit,
|
||||
onExpand = () => {},
|
||||
}) {
|
||||
const [filter, setFilter] = useState('Combined');
|
||||
|
||||
return (
|
||||
<MetricsTable
|
||||
title="Referrers"
|
||||
type="referrer"
|
||||
metric="Views"
|
||||
headerComponent={null}
|
||||
headerComponent={limit ? null : <FilterButtons selected={filter} onClick={setFilter} />}
|
||||
websiteId={websiteId}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
limit={limit}
|
||||
dataFilter={refFilter}
|
||||
filterOptions={{ domain: websiteDomain }}
|
||||
filterOptions={{
|
||||
domain: websiteDomain,
|
||||
domainOnly: filter === 'Domain only',
|
||||
raw: filter === 'Raw',
|
||||
}}
|
||||
onExpand={onExpand}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const FilterButtons = ({ selected, onClick }) => {
|
||||
return (
|
||||
<ButtonGroup
|
||||
size="xsmall"
|
||||
items={['Domain only', 'Combined', 'Raw']}
|
||||
selectedItem={selected}
|
||||
onClick={onClick}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue