Updated reports components.

This commit is contained in:
Mike Cao
2025-03-26 21:54:23 -07:00
parent f5bc3dc6c2
commit 0f6cdf8b80
95 changed files with 580 additions and 698 deletions

View File

@@ -1,4 +1,4 @@
import { PageHeader } from '@/components/layout/PageHeader';
import { PageHeader } from '@/components/common/PageHeader';
import { Icon, Icons, Text } from '@umami/react-zen';
import { useLoginQuery, useMessages, useNavigation } from '@/components/hooks';
import { LinkButton } from '@/components/common/LinkButton';

View File

@@ -4,7 +4,7 @@ import { useMessages, useLoginQuery, useNavigation } from '@/components/hooks';
import { REPORT_TYPES } from '@/lib/constants';
import { ReportDeleteButton } from './ReportDeleteButton';
export function ReportsTable({ data = [], showDomain }: { data: any[]; showDomain?: boolean }) {
export function ReportsTable({ data = [] }: { data: any[]; showDomain?: boolean }) {
const { formatMessage, labels } = useMessages();
const { user } = useLoginQuery();
const { renderTeamUrl } = useNavigation();
@@ -20,11 +20,6 @@ export function ReportsTable({ data = [], showDomain }: { data: any[]; showDomai
);
}}
</DataColumn>
{showDomain && (
<DataColumn id="domain" label={formatMessage(labels.domain)}>
{(row: any) => row?.website?.domain}
</DataColumn>
)}
<DataColumn id="action" label="" align="end">
{(row: any) => {
const { id, name, userId, website } = row;

View File

@@ -1,3 +0,0 @@
.dropdown div {
max-height: 300px;
}

View File

@@ -1,11 +1,9 @@
import { useContext } from 'react';
import { Column, Label } from '@umami/react-zen';
import { useReport } from '@/components/hooks';
import { parseDateRange } from '@/lib/date';
import { DateFilter } from '@/components/input/DateFilter';
import { WebsiteSelect } from '@/components/input/WebsiteSelect';
import { useMessages, useNavigation, useWebsiteQuery } from '@/components/hooks';
import { ReportContext } from './Report';
import styles from './BaseParameters.module.css';
export interface BaseParametersProps {
showWebsiteSelect?: boolean;
@@ -20,7 +18,7 @@ export function BaseParameters({
showDateSelect = true,
allowDateSelect = true,
}: BaseParametersProps) {
const { report, updateReport } = useContext(ReportContext);
const { report, updateReport } = useReport();
const { formatMessage, labels } = useMessages();
const { teamId } = useNavigation();
const { parameters } = report || {};
@@ -50,7 +48,7 @@ export function BaseParameters({
</Column>
)}
{showDateSelect && (
<Column className={styles.dropdown}>
<Column>
<Label>{formatMessage(labels.dateRange)}</Label>
{allowDateSelect && (
<DateFilter

View File

@@ -1,7 +1,6 @@
import { useState } from 'react';
import { createPortal } from 'react-dom';
import { REPORT_PARAMETERS } from '@/lib/constants';
import { PopupForm } from './PopupForm';
import { FieldSelectForm } from './FieldSelectForm';
export function FieldAddForm({
@@ -39,9 +38,7 @@ export function FieldAddForm({
};
return createPortal(
<PopupForm>
{!selected && <FieldSelectForm fields={fields} onSelect={handleSelect} />}
</PopupForm>,
!selected && <FieldSelectForm fields={fields} onSelect={handleSelect} />,
document.body,
);
}

View File

@@ -1,13 +1,11 @@
import { useFields, useMessages } from '@/components/hooks';
import { useFields, useMessages, useReport } from '@/components/hooks';
import { Icons } from '@/components/icons';
import { useContext } from 'react';
import { Button, Row, Label, Icon, Popover, MenuTrigger } from '@umami/react-zen';
import { Button, Row, Label, Icon, Popover, MenuTrigger, Column } from '@umami/react-zen';
import { FieldSelectForm } from '../[reportId]/FieldSelectForm';
import { ParameterList } from '../[reportId]/ParameterList';
import { ReportContext } from './Report';
export function FieldParameters() {
const { report, updateReport } = useContext(ReportContext);
const { report, updateReport } = useReport();
const { formatMessage, labels } = useMessages();
const { parameters } = report || {};
const { fields } = parameters || {};
@@ -26,12 +24,12 @@ export function FieldParameters() {
const AddButton = () => {
return (
<MenuTrigger>
<Button size="sm">
<Icon>
<Button variant="quiet">
<Icon size="sm">
<Icons.Plus />
</Icon>
</Button>
<Popover placement="start">
<Popover placement="right top">
<FieldSelectForm
fields={fieldOptions.filter(({ name }) => !fields.find(f => f.name === name))}
onSelect={handleAdd}
@@ -43,8 +41,11 @@ export function FieldParameters() {
};
return (
<Row>
<Label>{formatMessage(labels.fields)}</Label>
<Column gap="3">
<Row justifyContent="space-between">
<Label>{formatMessage(labels.fields)}</Label>
<AddButton />
</Row>
<ParameterList>
{fields.map(({ name }) => {
return (
@@ -54,7 +55,6 @@ export function FieldParameters() {
);
})}
</ParameterList>
<AddButton />
</Row>
</Column>
);
}

View File

@@ -1,6 +1,5 @@
import { List, ListItem, Label, Column } from '@umami/react-zen';
import { Menu, MenuItem, Text, MenuSection } from '@umami/react-zen';
import { useMessages } from '@/components/hooks';
import styles from './FieldSelectForm.module.css';
import { Key } from 'react';
export interface FieldSelectFormProps {
@@ -13,18 +12,17 @@ export function FieldSelectForm({ fields = [], onSelect, showType = true }: Fiel
const { formatMessage, labels } = useMessages();
return (
<Column>
<Label>{formatMessage(labels.fields)}</Label>
<List onSelectionChange={key => onSelect(fields[key as any])}>
<Menu onSelectionChange={key => onSelect(fields[key as any])}>
<MenuSection title={formatMessage(labels.fields)}>
{fields.map(({ name, label, type }: any, index: Key) => {
return (
<ListItem key={index} className={styles.item}>
<div>{label || name}</div>
{showType && type && <div className={styles.type}>{type}</div>}
</ListItem>
<MenuItem key={index}>
<Text>{label || name}</Text>
{showType && type && <Text color="muted">{type}</Text>}
</MenuItem>
);
})}
</List>
</Column>
</MenuSection>
</Menu>
);
}

View File

@@ -1,17 +1,23 @@
import { useContext } from 'react';
import { useMessages, useFormat, useFilters, useFields } from '@/components/hooks';
import { useMessages, useFormat, useFilters, useFields, useReport } from '@/components/hooks';
import { Icons } from '@/components/icons';
import { Button, Row, Label, Icon, Popover, MenuTrigger } from '@umami/react-zen';
import {
Button,
Row,
Column,
Label,
Icon,
Popover,
MenuTrigger,
Focusable,
Text,
} from '@umami/react-zen';
import { FilterSelectForm } from '../[reportId]/FilterSelectForm';
import { ParameterList } from '../[reportId]/ParameterList';
import { PopupForm } from '../[reportId]/PopupForm';
import { ReportContext } from './Report';
import { FieldFilterEditForm } from '../[reportId]/FieldFilterEditForm';
import { isSearchOperator } from '@/lib/params';
import styles from './FilterParameters.module.css';
export function FilterParameters() {
const { report, updateReport } = useContext(ReportContext);
const { report, updateReport } = useReport();
const { formatMessage, labels } = useMessages();
const { formatValue } = useFormat();
const { parameters } = report || {};
@@ -45,28 +51,26 @@ export function FilterParameters() {
const AddButton = () => {
return (
<MenuTrigger>
<Button size="sm">
<Icon>
<Button variant="quiet">
<Icon size="sm">
<Icons.Plus />
</Icon>
</Button>
<Popover placement="bottom start">
<PopupForm>
<FilterSelectForm
websiteId={websiteId}
fields={fields.filter(({ name }) => !filters.find(f => f.name === name))}
startDate={dateRange?.startDate}
endDate={dateRange?.endDate}
onChange={handleAdd}
/>
</PopupForm>
<Popover placement="right top">
<FilterSelectForm
websiteId={websiteId}
fields={fields.filter(({ name }) => !filters.find(f => f.name === name))}
startDate={dateRange?.startDate}
endDate={dateRange?.endDate}
onChange={handleAdd}
/>
</Popover>
</MenuTrigger>
);
};
return (
<>
<Column gap="3">
<Row justifyContent="space-between">
<Label>{formatMessage(labels.filters)}</Label>
<AddButton />
@@ -94,7 +98,7 @@ export function FilterParameters() {
},
)}
</ParameterList>
</>
</Column>
);
}
@@ -113,12 +117,16 @@ const FilterParameter = ({
return (
<MenuTrigger>
<div className={styles.item}>
<div className={styles.label}>{label}</div>
<div className={styles.op}>{operatorLabels[operator]}</div>
<div className={styles.value}>{value}</div>
</div>
<Popover className={styles.edit} placement="right top">
<Focusable>
<Row gap="3" alignItems="center">
<Text>{label}</Text>
<Text size="2" transform="uppercase">
{operatorLabels[operator]}
</Text>
<Text weight="bold">{value}</Text>
</Row>
</Focusable>
<Popover placement="right top">
{(close: any) => (
<FieldFilterEditForm
websiteId={websiteId}

View File

@@ -1,10 +1,8 @@
import { ReactNode } from 'react';
import { Icon } from '@umami/react-zen';
import { Icon, Row, Text, Button, Column } from '@umami/react-zen';
import { Icons } from '@/components/icons';
import { Empty } from '@/components/common/Empty';
import { useMessages } from '@/components/hooks';
import styles from './ParameterList.module.css';
import classNames from 'classnames';
export interface ParameterListProps {
children?: ReactNode;
@@ -14,34 +12,43 @@ export function ParameterList({ children }: ParameterListProps) {
const { formatMessage, labels } = useMessages();
return (
<div className={styles.list}>
<Column>
{!children && <Empty message={formatMessage(labels.none)} />}
{children}
</div>
</Column>
);
}
const Item = ({
children,
className,
icon,
onClick,
onRemove,
children,
}: {
children?: ReactNode;
className?: string;
icon?: ReactNode;
onClick?: () => void;
onRemove?: () => void;
children?: ReactNode;
}) => {
return (
<div className={classNames(styles.item, className)} onClick={onClick}>
{icon && <Icon className={styles.icon}>{icon}</Icon>}
<div className={styles.value}>{children}</div>
<Icon className={styles.close} onClick={onRemove}>
<Icons.Close />
</Icon>
</div>
<Row
gap="3"
alignItems="center"
justifyContent="space-between"
onClick={onClick}
backgroundColor="2"
border
borderRadius="2"
paddingLeft="3"
>
{icon && <Icon>{icon}</Icon>}
<Text>{children}</Text>
<Button onPress={onRemove} variant="quiet">
<Icon>
<Icons.Close />
</Icon>
</Button>
</Row>
);
};

View File

@@ -1,9 +0,0 @@
.form {
background: var(--base50);
min-width: 300px;
padding: 20px;
border: 1px solid var(--base400);
border-radius: var(--border-radius);
box-shadow: 0 0 0 5px rgba(0, 0, 0, 0.1);
z-index: 1000;
}

View File

@@ -1,23 +0,0 @@
import { CSSProperties, ReactNode } from 'react';
import classNames from 'classnames';
import styles from './PopupForm.module.css';
export function PopupForm({
className,
style,
children,
}: {
className?: string;
style?: CSSProperties;
children: ReactNode;
}) {
return (
<div
className={classNames(styles.form, className)}
style={style}
onClick={e => e.stopPropagation()}
>
{children}
</div>
);
}

View File

@@ -1,8 +1,6 @@
import { createContext, ReactNode } from 'react';
import { Loading } from '@umami/react-zen';
import classNames from 'classnames';
import { Loading, Grid } from '@umami/react-zen';
import { useReportQuery } from '@/components/hooks';
import styles from './Report.module.css';
export const ReportContext = createContext(null);
@@ -10,12 +8,10 @@ export function Report({
reportId,
defaultParameters,
children,
className,
}: {
reportId: string;
defaultParameters: { type: string; parameters: { [key: string]: any } };
children: ReactNode;
className?: string;
}) {
const report = useReportQuery(reportId, defaultParameters);
@@ -25,7 +21,9 @@ export function Report({
return (
<ReportContext.Provider value={report}>
<div className={classNames(styles.container, className)}>{children}</div>
<Grid rows="auto 1fr" columns="auto 1fr" gap="6">
{children}
</Grid>
</ReportContext.Provider>
);
}

View File

@@ -1,13 +1,12 @@
import { useContext } from 'react';
import { ReportContext } from './Report';
import styles from './ReportBody.module.css';
import { Panel } from '@/components/common/Panel';
import { useReport } from '@/components/hooks';
export function ReportBody({ children }) {
const { report } = useContext(ReportContext);
const { report } = useReport();
if (!report) {
return null;
}
return <div className={styles.body}>{children}</div>;
return <Panel>{children}</Panel>;
}

View File

@@ -1,36 +0,0 @@
.header {
display: grid;
grid-template-columns: 1fr min-content;
align-items: center;
grid-row: 1 / 2;
grid-column: 1 / 3;
margin: 20px 0 40px 0;
}
.title {
display: flex;
flex-direction: row;
align-items: center;
font-size: 24px;
font-weight: 700;
gap: 20px;
height: 60px;
}
.type {
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
color: var(--base600);
}
.description {
color: var(--font-color300);
max-width: 500px;
height: 30px;
}
.actions {
display: flex;
align-items: center;
}

View File

@@ -1,13 +1,18 @@
import { useContext } from 'react';
import { Icon, LoadingButton, InlineEditField, useToast } from '@umami/react-zen';
import { useMessages, useApi, useNavigation } from '@/components/hooks';
import { ReportContext } from './Report';
import styles from './ReportHeader.module.css';
import {
Row,
Column,
Text,
Heading,
Icon,
LoadingButton,
InlineEditField,
useToast,
} from '@umami/react-zen';
import { useMessages, useApi, useNavigation, useReport } from '@/components/hooks';
import { REPORT_TYPES } from '@/lib/constants';
import { Breadcrumb } from '@/components/common/Breadcrumb';
export function ReportHeader({ icon }) {
const { report, updateReport } = useContext(ReportContext);
const { report, updateReport } = useReport();
const { formatMessage, labels, messages } = useMessages();
const { toast } = useToast();
const { router, renderTeamUrl } = useNavigation();
@@ -54,41 +59,33 @@ export function ReportHeader({ icon }) {
}
return (
<div className={styles.header}>
<div>
<div className={styles.type}>
<Breadcrumb
data={[
{ label: formatMessage(labels.reports), url: renderTeamUrl('/reports') },
{
label: formatMessage(
labels[Object.keys(REPORT_TYPES).find(key => REPORT_TYPES[key] === report?.type)],
),
},
]}
/>
</div>
<div className={styles.title}>
<Icon size="lg">{icon}</Icon>
<InlineEditField
key={name}
name="name"
value={name}
placeholder={defaultName}
onCommit={handleNameChange}
/>
</div>
<div className={styles.description}>
<InlineEditField
key={description}
name="description"
value={description}
placeholder={`+ ${formatMessage(labels.addDescription)}`}
onCommit={handleDescriptionChange}
/>
</div>
</div>
<div className={styles.actions}>
<Column marginY="6" gap="3" gridColumn="1 / 3">
<Row gap="3" alignItems="center">
<Icon size="sm">{icon}</Icon>
<Text transform="uppercase" weight="bold">
{formatMessage(
labels[Object.keys(REPORT_TYPES).find(key => REPORT_TYPES[key] === report?.type)],
)}
</Text>
</Row>
<Row justifyContent="space-between" alignItems="center">
<Row gap="6">
<Column gap="3">
<Row gap="3" alignItems="center">
<InlineEditField key={name} name="name" value={name} onCommit={handleNameChange}>
<Heading>{name}</Heading>
</InlineEditField>
</Row>
<InlineEditField
key={description}
name="description"
value={description}
onCommit={handleDescriptionChange}
>
<Text>{description || `+ ${formatMessage(labels.addDescription)}`}</Text>
</InlineEditField>
</Column>
</Row>
<LoadingButton
variant="primary"
isLoading={isCreating || isUpdating}
@@ -97,7 +94,7 @@ export function ReportHeader({ icon }) {
>
{formatMessage(labels.save)}
</LoadingButton>
</div>
</div>
</Row>
</Column>
);
}

View File

@@ -1,25 +1,26 @@
import { useContext, useState } from 'react';
import { Icon, Icons } from '@umami/react-zen';
import classNames from 'classnames';
import { ReportContext } from './Report';
import styles from './ReportMenu.module.css';
import { useState } from 'react';
import { Button, Column, Icon, Row } from '@umami/react-zen';
import { Icons } from '@/components/icons';
import { useReport } from '@/components/hooks';
export function ReportMenu({ children }) {
const [collapsed, setCollapsed] = useState(false);
const { report } = useContext(ReportContext);
const { report } = useReport();
if (!report) {
return null;
}
return (
<div className={classNames(styles.menu, collapsed && styles.collapsed)}>
<div className={styles.button} onClick={() => setCollapsed(!collapsed)}>
<Icon rotate={collapsed ? -90 : 90}>
<Icons.Chevron />
</Icon>
</div>
<Column>
<Row alignItems="center" justifyContent="flex-end">
<Button variant="quiet" onPress={() => setCollapsed(!collapsed)}>
<Icon>
<Icons.PanelLeft />
</Icon>
</Button>
</Row>
{!collapsed && children}
</div>
</Column>
);
}

View File

@@ -1,7 +1,7 @@
import { Icon, Text, Row, Column, Grid } from '@umami/react-zen';
import { useMessages, useNavigation } from '@/components/hooks';
import { Icons } from '@/components/icons';
import { PageHeader } from '@/components/layout/PageHeader';
import { PageHeader } from '@/components/common/PageHeader';
import { LinkButton } from '@/components/common/LinkButton';
export function ReportTemplates({ showHeader = true }: { showHeader?: boolean }) {
@@ -71,7 +71,7 @@ function ReportItem({ title, description, url, icon }) {
const { formatMessage, labels } = useMessages();
return (
<Column gap="6" padding="6" borderSize="1" borderRadius="3" justifyContent="space-between">
<Column gap="6" padding="6" border borderRadius="3" justifyContent="space-between">
<Row gap="3" alignItems="center">
<Icon size="md">{icon}</Icon>
<Text size="5" weight="bold">

View File

@@ -1,4 +1,3 @@
import { useContext } from 'react';
import {
Form,
FormField,
@@ -10,9 +9,8 @@ import {
} from '@umami/react-zen';
import { Empty } from '@/components/common/Empty';
import { Icons } from '@/components/icons';
import { useApi, useMessages } from '@/components/hooks';
import { useApi, useMessages, useReport } from '@/components/hooks';
import { DATA_TYPES, REPORT_PARAMETERS } from '@/lib/constants';
import { ReportContext } from '../[reportId]/Report';
import { FieldAddForm } from '../[reportId]/FieldAddForm';
import { ParameterList } from '../[reportId]/ParameterList';
import { BaseParameters } from '../[reportId]/BaseParameters';
@@ -35,7 +33,7 @@ function useFields(websiteId, startDate, endDate) {
}
export function EventDataParameters() {
const { report, runReport, updateReport, isRunning } = useContext(ReportContext);
const { report, runReport, updateReport, isRunning } = useReport();
const { formatMessage, labels, messages } = useMessages();
const { id, parameters } = report || {};
const { websiteId, dateRange, fields, filters, groups } = parameters || {};

View File

@@ -1,10 +1,8 @@
import { useContext } from 'react';
import { DataTable, DataColumn } from '@umami/react-zen';
import { useMessages } from '@/components/hooks';
import { ReportContext } from '../[reportId]/Report';
import { useMessages, useReport } from '@/components/hooks';
export function EventDataTable() {
const { report } = useContext(ReportContext);
const { report } = useReport();
const { formatMessage, labels } = useMessages();
return (

View File

@@ -1,7 +1,5 @@
import { useContext } from 'react';
import classNames from 'classnames';
import { useMessages } from '@/components/hooks';
import { ReportContext } from '../[reportId]/Report';
import { useMessages, useReport } from '@/components/hooks';
import { formatLongNumber } from '@/lib/format';
import styles from './FunnelChart.module.css';
@@ -11,7 +9,7 @@ export interface FunnelChartProps {
}
export function FunnelChart({ className }: FunnelChartProps) {
const { report } = useContext(ReportContext);
const { report } = useReport();
const { formatMessage, labels } = useMessages();
const { data } = report || {};

View File

@@ -1,5 +1,4 @@
import { useContext } from 'react';
import { useMessages } from '@/components/hooks';
import { useMessages, useReport } from '@/components/hooks';
import {
Icon,
Form,
@@ -13,14 +12,12 @@ import {
} from '@umami/react-zen';
import { Icons } from '@/components/icons';
import { FunnelStepAddForm } from './FunnelStepAddForm';
import { ReportContext } from '../[reportId]/Report';
import { BaseParameters } from '../[reportId]/BaseParameters';
import { ParameterList } from '../[reportId]/ParameterList';
import { PopupForm } from '../[reportId]/PopupForm';
import styles from './FunnelParameters.module.css';
export function FunnelParameters() {
const { report, runReport, updateReport, isRunning } = useContext(ReportContext);
const { report, runReport, updateReport, isRunning } = useReport();
const { formatMessage, labels } = useMessages();
const { id, parameters } = report || {};
@@ -66,9 +63,7 @@ export function FunnelParameters() {
</Icon>
</Button>
<Popover placement="start">
<PopupForm>
<FunnelStepAddForm onChange={handleAddStep} />
</PopupForm>
<FunnelStepAddForm onChange={handleAddStep} />
</Popover>
</DialogTrigger>
);
@@ -90,7 +85,6 @@ export function FunnelParameters() {
return (
<DialogTrigger key={index}>
<ParameterList.Item
className={styles.item}
icon={step.type === 'url' ? <Icons.Eye /> : <Icons.Bolt />}
onRemove={() => handleRemoveStep(index)}
>
@@ -100,13 +94,11 @@ export function FunnelParameters() {
</ParameterList.Item>
<Popover placement="start">
{({ close }: any) => (
<PopupForm>
<FunnelStepAddForm
type={step.type}
value={step.value}
onChange={handleUpdateStep.bind(null, close, index)}
/>
</PopupForm>
<FunnelStepAddForm
type={step.type}
value={step.value}
onChange={handleUpdateStep.bind(null, close, index)}
/>
)}
</Popover>
</DialogTrigger>

View File

@@ -1,12 +1,10 @@
import { useContext } from 'react';
import classNames from 'classnames';
import { useMessages } from '@/components/hooks';
import { ReportContext } from '../[reportId]/Report';
import { useMessages, useReport } from '@/components/hooks';
import { formatLongNumber } from '@/lib/format';
import styles from './GoalsChart.module.css';
export function GoalsChart({ className }: { className?: string; isLoading?: boolean }) {
const { report } = useContext(ReportContext);
const { report } = useReport();
const { formatMessage, labels } = useMessages();
const { data } = report || {};

View File

@@ -1,7 +1,6 @@
import { useMessages } from '@/components/hooks';
import { useMessages, useReport } from '@/components/hooks';
import { Icons } from '@/components/icons';
import { formatNumber } from '@/lib/format';
import { useContext } from 'react';
import {
Button,
Form,
@@ -15,12 +14,11 @@ import {
} from '@umami/react-zen';
import { BaseParameters } from '../[reportId]/BaseParameters';
import { ParameterList } from '../[reportId]/ParameterList';
import { ReportContext } from '../[reportId]/Report';
import { GoalsAddForm } from './GoalsAddForm';
import styles from './GoalsParameters.module.css';
export function GoalsParameters() {
const { report, runReport, updateReport, isRunning } = useContext(ReportContext);
const { report, runReport, updateReport, isRunning } = useReport();
const { formatMessage, labels } = useMessages();
const { id, parameters } = report || {};
@@ -76,7 +74,7 @@ export function GoalsParameters() {
<Form values={parameters} onSubmit={handleSubmit} preventSubmit={true}>
<BaseParameters allowWebsiteSelect={!id} />
<AddGoalsButton />
<FormField label={formatMessage(labels.goals)}>
<FormField name="goal" label={formatMessage(labels.goals)}>
<ParameterList>
{goals.map(
(

View File

@@ -1,13 +1,11 @@
import { useMessages } from '@/components/hooks';
import { useContext } from 'react';
import { useMessages, useReport } from '@/components/hooks';
import { Form, FormButtons, FormSubmitButton } from '@umami/react-zen';
import { BaseParameters } from '../[reportId]/BaseParameters';
import { ReportContext } from '../[reportId]/Report';
import { FieldParameters } from '../[reportId]/FieldParameters';
import { FilterParameters } from '../[reportId]/FilterParameters';
export function InsightsParameters() {
const { report, runReport, isRunning } = useContext(ReportContext);
const { report, runReport, isRunning } = useReport();
const { formatMessage, labels } = useMessages();
const { id, parameters } = report || {};
const { websiteId, dateRange, fields, filters } = parameters || {};
@@ -20,7 +18,7 @@ export function InsightsParameters() {
};
return (
<Form values={parameters} onSubmit={handleSubmit}>
<Form values={parameters} onSubmit={handleSubmit} gap="6">
<BaseParameters allowWebsiteSelect={!id} />
{parametersSelected && <FieldParameters />}
{parametersSelected && <FilterParameters />}

View File

@@ -1,13 +1,12 @@
import { useContext, useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import { DataTable, DataColumn } from '@umami/react-zen';
import { useFormat, useMessages } from '@/components/hooks';
import { ReportContext } from '../[reportId]/Report';
import { useFormat, useMessages, useReport } from '@/components/hooks';
import { EmptyPlaceholder } from '@/components/common/EmptyPlaceholder';
import { formatShortTime } from '@/lib/format';
export function InsightsTable() {
const [fields, setFields] = useState([]);
const { report } = useContext(ReportContext);
const { report } = useReport();
const { formatMessage, labels } = useMessages();
const { formatValue } = useFormat();

View File

@@ -1,5 +1,4 @@
import { useContext } from 'react';
import { useMessages } from '@/components/hooks';
import { useMessages, useReport } from '@/components/hooks';
import {
Select,
Form,
@@ -9,11 +8,10 @@ import {
FormSubmitButton,
TextField,
} from '@umami/react-zen';
import { ReportContext } from '../[reportId]/Report';
import { BaseParameters } from '../[reportId]/BaseParameters';
export function JourneyParameters() {
const { report, runReport, isRunning } = useContext(ReportContext);
const { report, runReport, isRunning } = useReport();
const { formatMessage, labels } = useMessages();
const { id, parameters } = report || {};

View File

@@ -1,10 +1,9 @@
import { useContext, useMemo, useState } from 'react';
import { useMemo, useState } from 'react';
import { TooltipTrigger, Tooltip, Focusable } from '@umami/react-zen';
import { firstBy } from 'thenby';
import classNames from 'classnames';
import { useEscapeKey, useMessages } from '@/components/hooks';
import { useEscapeKey, useMessages, useReport } from '@/components/hooks';
import { objectToArray } from '@/lib/data';
import { ReportContext } from '../[reportId]/Report';
import styles from './JourneyView.module.css';
import { formatLongNumber } from '@/lib/format';
@@ -15,7 +14,7 @@ const LINE_WIDTH = 3;
export function JourneyView() {
const [selectedNode, setSelectedNode] = useState(null);
const [activeNode, setActiveNode] = useState(null);
const { report } = useContext(ReportContext);
const { report } = useReport();
const { data, parameters } = report || {};
const { formatMessage, labels } = useMessages();

View File

@@ -1,12 +1,9 @@
import { useContext } from 'react';
import { useMessages } from '@/components/hooks';
import { useMessages, useReport } from '@/components/hooks';
import { Form, FormButtons, FormSubmitButton } from '@umami/react-zen';
import { ReportContext } from '../[reportId]/Report';
import { BaseParameters } from '../[reportId]/BaseParameters';
import { parseDateRange } from '@/lib/date';
export function RetentionParameters() {
const { report, runReport, isRunning, updateReport } = useContext(ReportContext);
const { report, runReport, isRunning } = useReport();
const { formatMessage, labels } = useMessages();
const { id, parameters } = report || {};

View File

@@ -1,8 +1,6 @@
import { useContext } from 'react';
import classNames from 'classnames';
import { ReportContext } from '../[reportId]/Report';
import { EmptyPlaceholder } from '@/components/common/EmptyPlaceholder';
import { useMessages, useLocale } from '@/components/hooks';
import { useMessages, useLocale, useReport } from '@/components/hooks';
import { formatDate } from '@/lib/date';
import styles from './RetentionTable.module.css';
@@ -11,7 +9,7 @@ const DAYS = [1, 2, 3, 4, 5, 6, 7, 14, 21, 28];
export function RetentionTable({ days = DAYS }) {
const { formatMessage, labels } = useMessages();
const { locale } = useLocale();
const { report } = useContext(ReportContext);
const { report } = useReport();
const { data } = report || {};
if (!data) {

View File

@@ -1,12 +1,10 @@
import { useMessages } from '@/components/hooks';
import { useMessages, useReport } from '@/components/hooks';
import { useRevenueValuesQuery } from '@/components/hooks/queries/useRevenueValuesQuery';
import { useContext } from 'react';
import { Select, Form, FormButtons, FormField, ListItem, FormSubmitButton } from '@umami/react-zen';
import { BaseParameters } from '../[reportId]/BaseParameters';
import { ReportContext } from '../[reportId]/Report';
export function RevenueParameters() {
const { report, runReport, isRunning } = useContext(ReportContext);
const { report, runReport, isRunning } = useReport();
const { formatMessage, labels } = useMessages();
const { id, parameters } = report || {};
const { websiteId, dateRange } = parameters || {};

View File

@@ -1,12 +1,10 @@
import { EmptyPlaceholder } from '@/components/common/EmptyPlaceholder';
import { useMessages } from '@/components/hooks';
import { useContext } from 'react';
import { useMessages, useReport } from '@/components/hooks';
import { DataColumn, DataTable } from '@umami/react-zen';
import { ReportContext } from '../[reportId]/Report';
import { formatLongCurrency } from '@/lib/format';
export function RevenueTable() {
const { report } = useContext(ReportContext);
const { report } = useReport();
const { formatMessage, labels } = useMessages();
const { data } = report || {};

View File

@@ -3,16 +3,15 @@ import { colord } from 'colord';
import { BarChart } from '@/components/charts/BarChart';
import { PieChart } from '@/components/charts/PieChart';
import { TypeIcon } from '@/components/common/TypeIcon';
import { useCountryNames, useLocale, useMessages } from '@/components/hooks';
import { GridRow } from '@/components/layout/GridRow';
import { useCountryNames, useLocale, useMessages, useReport } from '@/components/hooks';
import { GridRow } from '@/components/common/GridRow';
import { ListTable } from '@/components/metrics/ListTable';
import { MetricCard } from '@/components/metrics/MetricCard';
import { MetricsBar } from '@/components/metrics/MetricsBar';
import { renderDateLabels } from '@/lib/charts';
import { CHART_COLORS } from '@/lib/constants';
import { formatLongCurrency, formatLongNumber } from '@/lib/format';
import { useCallback, useContext, useMemo } from 'react';
import { ReportContext } from '../[reportId]/Report';
import { useCallback, useMemo } from 'react';
import { RevenueTable } from './RevenueTable';
import styles from './RevenueView.module.css';
@@ -24,7 +23,7 @@ export function RevenueView({ isLoading }: RevenueViewProps) {
const { formatMessage, labels } = useMessages();
const { locale } = useLocale();
const { countryNames } = useCountryNames(locale);
const { report } = useContext(ReportContext);
const { report } = useReport();
const {
data,
parameters: { dateRange, currency },

View File

@@ -1,11 +1,9 @@
import { useContext } from 'react';
import { useMessages } from '@/components/hooks';
import { useMessages, useReport } from '@/components/hooks';
import { Form, FormButtons, FormSubmitButton } from '@umami/react-zen';
import { ReportContext } from '../[reportId]/Report';
import { BaseParameters } from '../[reportId]/BaseParameters';
export function UTMParameters() {
const { report, runReport, isRunning } = useContext(ReportContext);
const { report, runReport, isRunning } = useReport();
const { formatMessage, labels } = useMessages();
const { id, parameters } = report || {};

View File

@@ -1,7 +1,6 @@
import { useContext } from 'react';
import { firstBy } from 'thenby';
import { ReportContext } from '../[reportId]/Report';
import { CHART_COLORS, UTM_PARAMS } from '@/lib/constants';
import { useReport } from '@/components/hooks';
import { PieChart } from '@/components/charts/PieChart';
import { ListTable } from '@/components/metrics/ListTable';
import styles from './UTMView.module.css';
@@ -17,7 +16,7 @@ function toArray(data: { [key: string]: number } = {}) {
export function UTMView() {
const { formatMessage, labels } = useMessages();
const { report } = useContext(ReportContext);
const { report } = useReport();
const { data } = report || {};
if (!data) {