mirror of
https://github.com/umami-software/umami.git
synced 2026-02-09 15:17:23 +01:00
Added reports section.
This commit is contained in:
parent
ad918c5bba
commit
a5700d4a25
36 changed files with 422 additions and 43 deletions
33
components/pages/reports/EventDataReport.js
Normal file
33
components/pages/reports/EventDataReport.js
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import { useState } from 'react';
|
||||
import { Form, FormRow, FormInput, TextField } from 'react-basics';
|
||||
import AppLayout from 'components/layout/AppLayout';
|
||||
import Report from './Report';
|
||||
import ReportHeader from './ReportHeader';
|
||||
import useMessages from 'hooks/useMessages';
|
||||
import Nodes from 'assets/nodes.svg';
|
||||
import styles from './reports.module.css';
|
||||
|
||||
export default function EventDataReport({ websiteId, data }) {
|
||||
const [values, setValues] = useState({ query: '' });
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
||||
return (
|
||||
<AppLayout>
|
||||
<Report>
|
||||
<ReportHeader title={formatMessage(labels.eventData)} icon={<Nodes />} />
|
||||
<div className={styles.container}>
|
||||
<div className={styles.menu}>
|
||||
<Form>
|
||||
<FormRow label="Properties">
|
||||
<FormInput name="query">
|
||||
<TextField value={values.query} />
|
||||
</FormInput>
|
||||
</FormRow>
|
||||
</Form>
|
||||
</div>
|
||||
<div className={styles.content}></div>
|
||||
</div>
|
||||
</Report>
|
||||
</AppLayout>
|
||||
);
|
||||
}
|
||||
5
components/pages/reports/Report.js
Normal file
5
components/pages/reports/Report.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import Page from 'components/layout/Page';
|
||||
|
||||
export default function Report({ children, ...props }) {
|
||||
return <Page {...props}>{children}</Page>;
|
||||
}
|
||||
42
components/pages/reports/ReportHeader.js
Normal file
42
components/pages/reports/ReportHeader.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import { useState } from 'react';
|
||||
import { Flexbox, Icon, Text } from 'react-basics';
|
||||
import WebsiteSelect from 'components/input/WebsiteSelect';
|
||||
import PageHeader from 'components/layout/PageHeader';
|
||||
import DateFilter from 'components/input/DateFilter';
|
||||
import { parseDateRange } from 'lib/date';
|
||||
|
||||
export default function ReportHeader({ title, icon }) {
|
||||
const [websiteId, setWebsiteId] = useState();
|
||||
const [dateRange, setDateRange] = useState({});
|
||||
const { value, startDate, endDate } = dateRange;
|
||||
|
||||
const handleSelect = id => {
|
||||
setWebsiteId(id);
|
||||
};
|
||||
|
||||
const handleDateChange = value => setDateRange(parseDateRange(value));
|
||||
|
||||
const Title = () => {
|
||||
return (
|
||||
<>
|
||||
<Icon size="xl">{icon}</Icon>
|
||||
<Text>{title}</Text>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<PageHeader title={<Title />}>
|
||||
<Flexbox gap={20}>
|
||||
<DateFilter
|
||||
value={value}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
onChange={handleDateChange}
|
||||
showAllTime
|
||||
/>
|
||||
<WebsiteSelect websiteId={websiteId} onSelect={handleSelect} />
|
||||
</Flexbox>
|
||||
</PageHeader>
|
||||
);
|
||||
}
|
||||
66
components/pages/reports/ReportsList.js
Normal file
66
components/pages/reports/ReportsList.js
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import Link from 'next/link';
|
||||
import { Button, Icons, Text, Icon } from 'react-basics';
|
||||
import Page from 'components/layout/Page';
|
||||
import PageHeader from 'components/layout/PageHeader';
|
||||
import Funnel from 'assets/funnel.svg';
|
||||
import Nodes from 'assets/nodes.svg';
|
||||
import Lightbulb from 'assets/lightbulb.svg';
|
||||
import styles from './ReportsList.module.css';
|
||||
|
||||
const reports = [
|
||||
{
|
||||
title: 'Event data',
|
||||
description: 'Query your event data.',
|
||||
url: '/reports/event-data',
|
||||
icon: <Nodes />,
|
||||
},
|
||||
{
|
||||
title: 'Funnel',
|
||||
description: 'Understand the conversion and drop-off rate of users.',
|
||||
url: '/reports/funnel',
|
||||
icon: <Funnel />,
|
||||
},
|
||||
{
|
||||
title: 'Insights',
|
||||
description: 'Explore your data by applying segments and filters.',
|
||||
url: '/reports/insights',
|
||||
icon: <Lightbulb />,
|
||||
},
|
||||
];
|
||||
|
||||
function Report({ title, description, url, icon }) {
|
||||
return (
|
||||
<div className={styles.report}>
|
||||
<div className={styles.title}>
|
||||
<Icon size="lg">{icon}</Icon>
|
||||
<Text>{title}</Text>
|
||||
</div>
|
||||
<div className={styles.description}>{description}</div>
|
||||
<div className={styles.buttons}>
|
||||
<Link href={url}>
|
||||
<Button variant="primary">
|
||||
<Icon>
|
||||
<Icons.Plus />
|
||||
</Icon>
|
||||
<Text>Create</Text>
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ReportsList() {
|
||||
return (
|
||||
<Page>
|
||||
<PageHeader title="Reports" />
|
||||
<div className={styles.reports}>
|
||||
{reports.map(({ title, description, url, icon }) => {
|
||||
return (
|
||||
<Report key={title} icon={icon} title={title} description={description} url={url} />
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
32
components/pages/reports/ReportsList.module.css
Normal file
32
components/pages/reports/ReportsList.module.css
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
.reports {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.report {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
padding: 20px;
|
||||
border: 1px solid var(--base500);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
font-size: var(--font-size-lg);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.description {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
14
components/pages/reports/reports.module.css
Normal file
14
components/pages/reports/reports.module.css
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
.container {
|
||||
display: grid;
|
||||
grid-template-rows: 1fr;
|
||||
grid-template-columns: max-content 1fr;
|
||||
}
|
||||
|
||||
.menu {
|
||||
width: 300px;
|
||||
grid-column: 1 / 2;
|
||||
}
|
||||
|
||||
.content {
|
||||
grid-column: 2 / 3;
|
||||
}
|
||||
|
|
@ -9,11 +9,12 @@ export function DateRangeSetting() {
|
|||
const [dateRange, setDateRange] = useDateRange();
|
||||
const { startDate, endDate, value } = dateRange;
|
||||
|
||||
const handleChange = value => setDateRange(value);
|
||||
const handleReset = () => setDateRange(DEFAULT_DATE_RANGE);
|
||||
|
||||
return (
|
||||
<Flexbox gap={10}>
|
||||
<DateFilter value={value} startDate={startDate} endDate={endDate} />
|
||||
<DateFilter value={value} startDate={startDate} endDate={endDate} onChange={handleChange} />
|
||||
<Button onClick={handleReset}>{formatMessage(labels.reset)}</Button>
|
||||
</Flexbox>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue