Merge branch 'dev' into feat/thumbnail-team-memory

This commit is contained in:
Mike Cao 2025-12-01 10:43:48 -08:00 committed by GitHub
commit f5d6d0ebaf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
577 changed files with 2413 additions and 3645 deletions

View file

@ -1,8 +1,8 @@
import { useMessages, useModified } from '@/components/hooks';
import { useToast } from '@umami/react-zen';
import { useMessages, useModified } from '@/components/hooks';
import { Plus } from '@/components/icons';
import { WebsiteAddForm } from './WebsiteAddForm';
import { DialogButton } from '@/components/input/DialogButton';
import { WebsiteAddForm } from './WebsiteAddForm';
export function WebsiteAddButton({ teamId, onSave }: { teamId: string; onSave?: () => void }) {
const { formatMessage, labels, messages } = useMessages();

View file

@ -1,7 +1,6 @@
import { Form, FormField, FormSubmitButton, Row, TextField, Button } from '@umami/react-zen';
import { useUpdateQuery } from '@/components/hooks';
import { Button, Form, FormField, FormSubmitButton, Row, TextField } from '@umami/react-zen';
import { useMessages, useUpdateQuery } from '@/components/hooks';
import { DOMAIN_REGEX } from '@/lib/constants';
import { useMessages } from '@/components/hooks';
export function WebsiteAddForm({
teamId,

View file

@ -1,8 +1,8 @@
'use client';
import { createContext, ReactNode } from 'react';
import { Loading } from '@umami/react-zen';
import { Website } from '@/generated/prisma/client';
import { createContext, type ReactNode } from 'react';
import { useWebsiteQuery } from '@/components/hooks/queries/useWebsiteQuery';
import type { Website } from '@/generated/prisma/client';
export const WebsiteContext = createContext<Website>(null);

View file

@ -1,9 +1,9 @@
import Link from 'next/link';
import { WebsitesTable } from './WebsitesTable';
import { DataGrid } from '@/components/common/DataGrid';
import { useLoginQuery, useNavigation, useUserWebsitesQuery } from '@/components/hooks';
import { Favicon } from '@/index';
import { Icon, Row } from '@umami/react-zen';
import { WebsitesTable } from './WebsitesTable';
export function WebsitesDataTable({
userId,

View file

@ -1,6 +1,6 @@
import { PageHeader } from '@/components/common/PageHeader';
import { useMessages, useNavigation } from '@/components/hooks';
import { WebsiteAddButton } from './WebsiteAddButton';
import { PageHeader } from '@/components/common/PageHeader';
export interface WebsitesHeaderProps {
allowCreate?: boolean;

View file

@ -1,11 +1,11 @@
'use client';
import { WebsitesDataTable } from './WebsitesDataTable';
import { WebsiteAddButton } from './WebsiteAddButton';
import { useMessages, useNavigation } from '@/components/hooks';
import { Column } from '@umami/react-zen';
import { PageBody } from '@/components/common/PageBody';
import { PageHeader } from '@/components/common/PageHeader';
import { Panel } from '@/components/common/Panel';
import { PageBody } from '@/components/common/PageBody';
import { useMessages, useNavigation } from '@/components/hooks';
import { WebsiteAddButton } from './WebsiteAddButton';
import { WebsitesDataTable } from './WebsitesDataTable';
export function WebsitesPage() {
const { teamId } = useNavigation();

View file

@ -1,5 +1,5 @@
import { ReactNode } from 'react';
import { Icon, DataTable, DataColumn, DataTableProps } from '@umami/react-zen';
import { DataColumn, DataTable, type DataTableProps, Icon } from '@umami/react-zen';
import type { ReactNode } from 'react';
import { LinkButton } from '@/components/common/LinkButton';
import { useMessages, useNavigation } from '@/components/hooks';
import { SquarePen } from '@/components/icons';

View file

@ -1,13 +1,13 @@
import { Grid, Column } from '@umami/react-zen';
import { useMessages, useResultQuery } from '@/components/hooks';
import { Panel } from '@/components/common/Panel';
import { Column, Grid } from '@umami/react-zen';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { Panel } from '@/components/common/Panel';
import { SectionHeader } from '@/components/common/SectionHeader';
import { useMessages, useResultQuery } from '@/components/hooks';
import { ListTable } from '@/components/metrics/ListTable';
import { MetricCard } from '@/components/metrics/MetricCard';
import { MetricsBar } from '@/components/metrics/MetricsBar';
import { SectionHeader } from '@/components/common/SectionHeader';
import { formatLongNumber } from '@/lib/format';
import { percentFilter } from '@/lib/filters';
import { formatLongNumber } from '@/lib/format';
export interface AttributionProps {
websiteId: string;
@ -97,34 +97,28 @@ export function Attribution({
<SectionHeader title={formatMessage(labels.sources)} />
<Grid columns={{ xs: '1fr', md: '1fr 1fr' }} gap>
<Panel>
<AttributionTable data={data?.['referrer']} title={formatMessage(labels.referrer)} />
<AttributionTable data={data?.referrer} title={formatMessage(labels.referrer)} />
</Panel>
<Panel>
<AttributionTable data={data?.['paidAds']} title={formatMessage(labels.paidAds)} />
<AttributionTable data={data?.paidAds} title={formatMessage(labels.paidAds)} />
</Panel>
</Grid>
<SectionHeader title="UTM" />
<Grid columns={{ xs: '1fr', md: '1fr 1fr' }} gap>
<Panel>
<AttributionTable data={data?.['utm_source']} title={formatMessage(labels.sources)} />
<AttributionTable data={data?.utm_source} title={formatMessage(labels.sources)} />
</Panel>
<Panel>
<AttributionTable data={data?.['utm_medium']} title={formatMessage(labels.medium)} />
<AttributionTable data={data?.utm_medium} title={formatMessage(labels.medium)} />
</Panel>
<Panel>
<AttributionTable
data={data?.['utm_cmapaign']}
title={formatMessage(labels.campaigns)}
/>
<AttributionTable data={data?.utm_cmapaign} title={formatMessage(labels.campaigns)} />
</Panel>
<Panel>
<AttributionTable
data={data?.['utm_content']}
title={formatMessage(labels.content)}
/>
<AttributionTable data={data?.utm_content} title={formatMessage(labels.content)} />
</Panel>
<Panel>
<AttributionTable data={data?.['utm_term']} title={formatMessage(labels.terms)} />
<AttributionTable data={data?.utm_term} title={formatMessage(labels.terms)} />
</Panel>
</Grid>
</Column>

View file

@ -1,9 +1,9 @@
'use client';
import { Column, Grid, ListItem, SearchField, Select } from '@umami/react-zen';
import { useState } from 'react';
import { Column, Grid, Select, ListItem, SearchField } from '@umami/react-zen';
import { Attribution } from './Attribution';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { useDateRange, useMessages } from '@/components/hooks';
import { Attribution } from './Attribution';
export function AttributionPage({ websiteId }: { websiteId: string }) {
const [model, setModel] = useState('first-click');

View file

@ -1,4 +1,4 @@
import { Metadata } from 'next';
import type { Metadata } from 'next';
import { AttributionPage } from './AttributionPage';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {

View file

@ -1,6 +1,6 @@
import { Text, DataTable, DataColumn, Column } from '@umami/react-zen';
import { useMessages, useResultQuery, useFormat, useFields } from '@/components/hooks';
import { Column, DataColumn, DataTable, Text } from '@umami/react-zen';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { useFields, useFormat, useMessages, useResultQuery } from '@/components/hooks';
import { formatShortTime } from '@/lib/format';
export interface BreakdownProps {
@ -54,13 +54,13 @@ export function Breakdown({ websiteId, selectedFields = [], startDate, endDate }
align="end"
width="120px"
>
{row => row?.['visitors']?.toLocaleString()}
{row => row?.visitors?.toLocaleString()}
</DataColumn>
<DataColumn id="visits" label={formatMessage(labels.visits)} align="end" width="120px">
{row => row?.['visits']?.toLocaleString()}
{row => row?.visits?.toLocaleString()}
</DataColumn>
<DataColumn id="views" label={formatMessage(labels.views)} align="end" width="120px">
{row => row?.['views']?.toLocaleString()}
{row => row?.views?.toLocaleString()}
</DataColumn>
<DataColumn
id="bounceRate"
@ -69,8 +69,8 @@ export function Breakdown({ websiteId, selectedFields = [], startDate, endDate }
width="120px"
>
{row => {
const n = (Math.min(row?.['visits'], row?.['bounces']) / row?.['visits']) * 100;
return Math.round(+n) + '%';
const n = (Math.min(row?.visits, row?.bounces) / row?.visits) * 100;
return `${Math.round(+n)}%`;
}}
</DataColumn>
<DataColumn
@ -80,7 +80,7 @@ export function Breakdown({ websiteId, selectedFields = [], startDate, endDate }
width="120px"
>
{row => {
const n = row?.['totaltime'] / row?.['visits'];
const n = row?.totaltime / row?.visits;
return `${+n < 0 ? '-' : ''}${formatShortTime(Math.abs(~~n), ['m', 's'], ' ')}`;
}}
</DataColumn>

View file

@ -1,12 +1,12 @@
'use client';
import { Column, Row } from '@umami/react-zen';
import { useState } from 'react';
import { FieldSelectForm } from '@/app/(main)/websites/[websiteId]/(reports)/breakdown/FieldSelectForm';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { Panel } from '@/components/common/Panel';
import { useDateRange, useMessages } from '@/components/hooks';
import { ListCheck } from '@/components/icons';
import { DialogButton } from '@/components/input/DialogButton';
import { Column, Row } from '@umami/react-zen';
import { useState } from 'react';
import { Breakdown } from './Breakdown';
export function BreakdownPage({ websiteId }: { websiteId: string }) {

View file

@ -1,6 +1,6 @@
import { Column, List, ListItem, Grid, Button } from '@umami/react-zen';
import { useFields, useMessages } from '@/components/hooks';
import { Button, Column, Grid, List, ListItem } from '@umami/react-zen';
import { useState } from 'react';
import { useFields, useMessages } from '@/components/hooks';
export function FieldSelectForm({
selectedFields = [],

View file

@ -1,4 +1,4 @@
import { Metadata } from 'next';
import type { Metadata } from 'next';
import { BreakdownPage } from './BreakdownPage';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {

View file

@ -1,11 +1,11 @@
import { Grid, Column, Row, Text, Icon, ProgressBar, Dialog, Box } from '@umami/react-zen';
import { useMessages, useResultQuery } from '@/components/hooks';
import { Box, Column, Dialog, Grid, Icon, ProgressBar, Row, Text } from '@umami/react-zen';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { useMessages, useResultQuery } from '@/components/hooks';
import { File, User } from '@/components/icons';
import { Lightning } from '@/components/svg';
import { formatLongNumber } from '@/lib/format';
import { ReportEditButton } from '@/components/input/ReportEditButton';
import { ChangeLabel } from '@/components/metrics/ChangeLabel';
import { Lightning } from '@/components/svg';
import { formatLongNumber } from '@/lib/format';
import { FunnelEditForm } from './FunnelEditForm';
type FunnelResult = {

View file

@ -1,7 +1,7 @@
import { Button, DialogTrigger, Dialog, Icon, Text, Modal } from '@umami/react-zen';
import { Button, Dialog, DialogTrigger, Icon, Modal, Text } from '@umami/react-zen';
import { useMessages } from '@/components/hooks';
import { FunnelEditForm } from './FunnelEditForm';
import { Plus } from '@/components/icons';
import { FunnelEditForm } from './FunnelEditForm';
export function FunnelAddButton({ websiteId }: { websiteId: string }) {
const { formatMessage, labels } = useMessages();

View file

@ -1,20 +1,20 @@
import {
Button,
Column,
Form,
FormButtons,
FormField,
FormFieldArray,
TextField,
Grid,
FormButtons,
FormSubmitButton,
Button,
Text,
Grid,
Icon,
Row,
Loading,
Column,
Row,
Text,
TextField,
} from '@umami/react-zen';
import { useMessages, useReportQuery, useUpdateQuery } from '@/components/hooks';
import { X, Plus } from '@/components/icons';
import { Plus, X } from '@/components/icons';
import { ActionSelect } from '@/components/input/ActionSelect';
import { LookupField } from '@/components/input/LookupField';

View file

@ -1,12 +1,12 @@
'use client';
import { Grid, Column } from '@umami/react-zen';
import { SectionHeader } from '@/components/common/SectionHeader';
import { Funnel } from './Funnel';
import { FunnelAddButton } from './FunnelAddButton';
import { Column, Grid } from '@umami/react-zen';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { useDateRange, useReportsQuery } from '@/components/hooks';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { Panel } from '@/components/common/Panel';
import { SectionHeader } from '@/components/common/SectionHeader';
import { useDateRange, useReportsQuery } from '@/components/hooks';
import { Funnel } from './Funnel';
import { FunnelAddButton } from './FunnelAddButton';
export function FunnelsPage({ websiteId }: { websiteId: string }) {
const { data, isLoading, error } = useReportsQuery({ websiteId, type: 'funnel' });
@ -23,7 +23,7 @@ export function FunnelsPage({ websiteId }: { websiteId: string }) {
<LoadingPanel data={data} isLoading={isLoading} error={error}>
{data && (
<Grid gap>
{data['data']?.map((report: any) => (
{data.data?.map((report: any) => (
<Panel key={report.id}>
<Funnel {...report} startDate={startDate} endDate={endDate} />
</Panel>

View file

@ -1,4 +1,4 @@
import { Metadata } from 'next';
import type { Metadata } from 'next';
import { FunnelsPage } from './FunnelsPage';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {

View file

@ -1,9 +1,9 @@
import { Grid, Row, Column, Text, Icon, ProgressBar, Dialog } from '@umami/react-zen';
import { ReportEditButton } from '@/components/input/ReportEditButton';
import { Column, Dialog, Grid, Icon, ProgressBar, Row, Text } from '@umami/react-zen';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { useMessages, useResultQuery } from '@/components/hooks';
import { File, User } from '@/components/icons';
import { ReportEditButton } from '@/components/input/ReportEditButton';
import { Lightning } from '@/components/svg';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { formatLongNumber } from '@/lib/format';
import { GoalEditForm } from './GoalEditForm';

View file

@ -1,7 +1,7 @@
import { Button, DialogTrigger, Dialog, Icon, Text, Modal } from '@umami/react-zen';
import { Button, Dialog, DialogTrigger, Icon, Modal, Text } from '@umami/react-zen';
import { useMessages } from '@/components/hooks';
import { GoalEditForm } from './GoalEditForm';
import { Plus } from '@/components/icons';
import { GoalEditForm } from './GoalEditForm';
export function GoalAddButton({ websiteId }: { websiteId: string }) {
const { formatMessage, labels } = useMessages();

View file

@ -1,18 +1,18 @@
import {
Form,
FormField,
TextField,
Grid,
FormButtons,
FormSubmitButton,
Button,
Loading,
Column,
Form,
FormButtons,
FormField,
FormSubmitButton,
Grid,
Label,
Loading,
TextField,
} from '@umami/react-zen';
import { useMessages, useReportQuery, useUpdateQuery } from '@/components/hooks';
import { LookupField } from '@/components/input/LookupField';
import { ActionSelect } from '@/components/input/ActionSelect';
import { LookupField } from '@/components/input/LookupField';
export function GoalEditForm({
id,

View file

@ -1,12 +1,12 @@
'use client';
import { Grid, Column } from '@umami/react-zen';
import { SectionHeader } from '@/components/common/SectionHeader';
import { Goal } from './Goal';
import { GoalAddButton } from './GoalAddButton';
import { Column, Grid } from '@umami/react-zen';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { useDateRange, useReportsQuery } from '@/components/hooks';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { Panel } from '@/components/common/Panel';
import { SectionHeader } from '@/components/common/SectionHeader';
import { useDateRange, useReportsQuery } from '@/components/hooks';
import { Goal } from './Goal';
import { GoalAddButton } from './GoalAddButton';
export function GoalsPage({ websiteId }: { websiteId: string }) {
const { data, isLoading, error } = useReportsQuery({ websiteId, type: 'goal' });
@ -23,7 +23,7 @@ export function GoalsPage({ websiteId }: { websiteId: string }) {
<LoadingPanel data={data} isLoading={isLoading} error={error}>
{data && (
<Grid columns={{ xs: '1fr', md: '1fr 1fr' }} gap>
{data['data'].map((report: any) => (
{data.data.map((report: any) => (
<Panel key={report.id}>
<Goal {...report} startDate={startDate} endDate={endDate} />
</Panel>

View file

@ -1,4 +1,4 @@
import { Metadata } from 'next';
import type { Metadata } from 'next';
import { GoalsPage } from './GoalsPage';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {

View file

@ -208,7 +208,7 @@
.start:before,
.end:before {
content: '';
content: "";
position: absolute;
border-radius: 100%;
border: 3px solid var(--journey-line-color);

View file

@ -1,13 +1,13 @@
import { useMemo, useState } from 'react';
import { TooltipTrigger, Tooltip, Focusable, Icon, Text, Row, Column } from '@umami/react-zen';
import { firstBy } from 'thenby';
import { Column, Focusable, Icon, Row, Text, Tooltip, TooltipTrigger } from '@umami/react-zen';
import classNames from 'classnames';
import { useMemo, useState } from 'react';
import { firstBy } from 'thenby';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { useEscapeKey, useMessages, useResultQuery } from '@/components/hooks';
import { File } from '@/components/icons';
import { Lightning } from '@/components/svg';
import { objectToArray } from '@/lib/data';
import { formatLongNumber } from '@/lib/format';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import styles from './Journey.module.css';
const NODE_HEIGHT = 60;

View file

@ -1,10 +1,10 @@
'use client';
import { Column, Grid, ListItem, SearchField, Select } from '@umami/react-zen';
import { useState } from 'react';
import { ListItem, Select, Column, Grid, SearchField } from '@umami/react-zen';
import { useDateRange, useMessages } from '@/components/hooks';
import { Panel } from '@/components/common/Panel';
import { Journey } from './Journey';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { Panel } from '@/components/common/Panel';
import { useDateRange, useMessages } from '@/components/hooks';
import { Journey } from './Journey';
const JOURNEY_STEPS = [2, 3, 4, 5, 6, 7];
const DEFAULT_STEP = 3;

View file

@ -1,4 +1,4 @@
import { Metadata } from 'next';
import type { Metadata } from 'next';
import { JourneysPage } from './JourneysPage';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {

View file

@ -1,11 +1,11 @@
import { ReactNode } from 'react';
import { Grid, Row, Column, Text, Icon } from '@umami/react-zen';
import { Column, Grid, Icon, Row, Text } from '@umami/react-zen';
import type { ReactNode } from 'react';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { Panel } from '@/components/common/Panel';
import { useLocale, useMessages, useResultQuery } from '@/components/hooks';
import { Users } from '@/components/icons';
import { useMessages, useLocale, useResultQuery } from '@/components/hooks';
import { formatDate } from '@/lib/date';
import { formatLongNumber } from '@/lib/format';
import { Panel } from '@/components/common/Panel';
import { LoadingPanel } from '@/components/common/LoadingPanel';
const DAYS = [1, 2, 3, 4, 5, 6, 7, 14, 21, 28];

View file

@ -1,9 +1,9 @@
'use client';
import { Column } from '@umami/react-zen';
import { Retention } from './Retention';
import { endOfMonth, startOfMonth } from 'date-fns';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { useDateRange } from '@/components/hooks';
import { endOfMonth, startOfMonth } from 'date-fns';
import { Retention } from './Retention';
export function RetentionPage({ websiteId }: { websiteId: string }) {
const {

View file

@ -1,4 +1,4 @@
import { Metadata } from 'next';
import type { Metadata } from 'next';
import { RetentionPage } from './RetentionPage';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {

View file

@ -1,3 +1,7 @@
import { Column, Grid, Row, Text } from '@umami/react-zen';
import classNames from 'classnames';
import { colord } from 'colord';
import { useCallback, useMemo, useState } from 'react';
import { BarChart } from '@/components/charts/BarChart';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { Panel } from '@/components/common/Panel';
@ -11,10 +15,6 @@ import { renderDateLabels } from '@/lib/charts';
import { CHART_COLORS } from '@/lib/constants';
import { generateTimeSeries } from '@/lib/date';
import { formatLongCurrency, formatLongNumber } from '@/lib/format';
import { Column, Grid, Row, Text } from '@umami/react-zen';
import classNames from 'classnames';
import { colord } from 'colord';
import { useCallback, useMemo, useState } from 'react';
export interface RevenueProps {
websiteId: string;
@ -137,7 +137,7 @@ export function Revenue({ websiteId, startDate, endDate, unit }: RevenueProps) {
metric={formatMessage(labels.revenue)}
data={data?.country.map(({ name, value }: { name: string; value: number }) => ({
label: name,
count: value,
count: Number(value),
percent: (value / data?.total.sum) * 100,
}))}
currency={currency}

View file

@ -1,8 +1,8 @@
'use client';
import { Column } from '@umami/react-zen';
import { Revenue } from './Revenue';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { useDateRange } from '@/components/hooks';
import { Revenue } from './Revenue';
export function RevenuePage({ websiteId }: { websiteId: string }) {
const {

View file

@ -1,4 +1,4 @@
import { Metadata } from 'next';
import type { Metadata } from 'next';
import { RevenuePage } from './RevenuePage';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {

View file

@ -1,10 +1,10 @@
import { Column, Grid, Heading, Text } from '@umami/react-zen';
import { PieChart } from '@/components/charts/PieChart';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { Panel } from '@/components/common/Panel';
import { useMessages, useResultQuery } from '@/components/hooks';
import { ListTable } from '@/components/metrics/ListTable';
import { CHART_COLORS, UTM_PARAMS } from '@/lib/constants';
import { Column, Grid, Heading, Text } from '@umami/react-zen';
export interface UTMProps {
websiteId: string;

View file

@ -1,8 +1,8 @@
'use client';
import { Column } from '@umami/react-zen';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { useDateRange } from '@/components/hooks';
import { UTM } from './UTM';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
export function UTMPage({ websiteId }: { websiteId: string }) {
const {

View file

@ -1,4 +1,4 @@
import { Metadata } from 'next';
import type { Metadata } from 'next';
import { UTMPage } from './UTMPage';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {

View file

@ -1,6 +1,6 @@
import { Dialog, Modal } from '@umami/react-zen';
import { WebsiteExpandedView } from '@/app/(main)/websites/[websiteId]/WebsiteExpandedView';
import { useNavigation, useMobile } from '@/components/hooks';
import { useMobile, useNavigation } from '@/components/hooks';
export function ExpandedViewModal({
websiteId,

View file

@ -1,8 +1,8 @@
import { useMemo } from 'react';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { useDateRange, useTimezone } from '@/components/hooks';
import { useWebsitePageviewsQuery } from '@/components/hooks/queries/useWebsitePageviewsQuery';
import { PageviewsChart } from '@/components/metrics/PageviewsChart';
import { useMemo } from 'react';
export function WebsiteChart({
websiteId,
@ -28,7 +28,7 @@ export function WebsiteChart({
};
if (compare) {
result['compare'] = {
result.compare = {
pageviews: result.pageviews.map(({ x }, i) => ({
x,
y: compare.pageviews[i]?.y,

View file

@ -1,9 +1,9 @@
import { Column, Row, Grid } from '@umami/react-zen';
import { WebsiteFilterButton } from '@/components/input/WebsiteFilterButton';
import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter';
import { Column, Grid, Row } from '@umami/react-zen';
import { ExportButton } from '@/components/input/ExportButton';
import { FilterBar } from '@/components/input/FilterBar';
import { MonthFilter } from '@/components/input/MonthFilter';
import { ExportButton } from '@/components/input/ExportButton';
import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter';
import { WebsiteFilterButton } from '@/components/input/WebsiteFilterButton';
export function WebsiteControls({
websiteId,

View file

@ -1,24 +1,24 @@
import { useMessages, useNavigation } from '@/components/hooks';
import { SideMenu } from '@/components/common/SideMenu';
import { useMessages, useNavigation } from '@/components/hooks';
import {
LogOut,
LogIn,
Search,
Type,
SquareSlash,
Share2,
Megaphone,
AppWindow,
Cpu,
Earth,
Globe,
Landmark,
MapPin,
AppWindow,
Laptop,
Languages,
Laptop,
LogIn,
LogOut,
MapPin,
Megaphone,
Monitor,
Cpu,
Network,
Search,
Share2,
SquareSlash,
Tag,
Type,
} from '@/components/icons';
import { Lightning } from '@/components/svg';

View file

@ -1,8 +1,8 @@
import { Grid, Column, Row } from '@umami/react-zen';
import { useMessages, useNavigation } from '@/components/hooks';
import { MetricsExpandedTable } from '@/components/metrics/MetricsExpandedTable';
import { Column, Grid, Row } from '@umami/react-zen';
import { WebsiteExpandedMenu } from '@/app/(main)/websites/[websiteId]/WebsiteExpandedMenu';
import { useMessages, useNavigation } from '@/components/hooks';
import { MobileMenuButton } from '@/components/input/MobileMenuButton';
import { MetricsExpandedTable } from '@/components/metrics/MetricsExpandedTable';
export function WebsiteExpandedView({
websiteId,

View file

@ -1,12 +1,12 @@
import { Icon, Text, Row } from '@umami/react-zen';
import { PageHeader } from '@/components/common/PageHeader';
import { Share, Edit } from '@/components/icons';
import { Favicon } from '@/components/common/Favicon';
import { ActiveUsers } from '@/components/metrics/ActiveUsers';
import { Icon, Row, Text } from '@umami/react-zen';
import { WebsiteShareForm } from '@/app/(main)/websites/[websiteId]/settings/WebsiteShareForm';
import { useMessages, useNavigation, useWebsite } from '@/components/hooks';
import { Favicon } from '@/components/common/Favicon';
import { LinkButton } from '@/components/common/LinkButton';
import { PageHeader } from '@/components/common/PageHeader';
import { useMessages, useNavigation, useWebsite } from '@/components/hooks';
import { Edit, Share } from '@/components/icons';
import { DialogButton } from '@/components/input/DialogButton';
import { ActiveUsers } from '@/components/metrics/ActiveUsers';
export function WebsiteHeader({ showActions }: { showActions?: boolean }) {
const website = useWebsite();

View file

@ -1,6 +1,6 @@
'use client';
import { ReactNode } from 'react';
import { Column, Grid } from '@umami/react-zen';
import type { ReactNode } from 'react';
import { WebsiteProvider } from '@/app/(main)/websites/WebsiteProvider';
import { PageBody } from '@/components/common/PageBody';
import { WebsiteHeader } from './WebsiteHeader';

View file

@ -9,8 +9,8 @@ import {
Text,
} from '@umami/react-zen';
import { Fragment } from 'react';
import { More, Share, Edit } from '@/components/icons';
import { useMessages, useNavigation } from '@/components/hooks';
import { Edit, More, Share } from '@/components/icons';
export function WebsiteMenu({ websiteId }: { websiteId: string }) {
const { formatMessage, labels } = useMessages();

View file

@ -1,9 +1,9 @@
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { useDateRange, useMessages } from '@/components/hooks';
import { useWebsiteStatsQuery } from '@/components/hooks/queries/useWebsiteStatsQuery';
import { MetricCard } from '@/components/metrics/MetricCard';
import { MetricsBar } from '@/components/metrics/MetricsBar';
import { formatShortTime, formatLongNumber } from '@/lib/format';
import { useWebsiteStatsQuery } from '@/components/hooks/queries/useWebsiteStatsQuery';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { formatLongNumber, formatShortTime } from '@/lib/format';
export function WebsiteMetricsBar({
websiteId,
@ -45,7 +45,7 @@ export function WebsiteMetricsBar({
change:
(Math.min(visits, bounces) / visits) * 100 -
(Math.min(comparison.visits, comparison.bounces) / comparison.visits) * 100,
formatValue: n => Math.round(+n) + '%',
formatValue: n => `${Math.round(+n)}%`,
reverseColors: true,
},
{

View file

@ -1,18 +1,18 @@
import { Text, Column } from '@umami/react-zen';
import { Column, Text } from '@umami/react-zen';
import { SideMenu } from '@/components/common/SideMenu';
import { useMessages, useNavigation } from '@/components/hooks';
import {
Eye,
User,
AlignEndHorizontal,
ChartPie,
Clock,
Eye,
Sheet,
Tag,
ChartPie,
User,
UserPlus,
AlignEndHorizontal,
} from '@/components/icons';
import { Lightning, Path, Money, Target, Funnel, Magnet, Network } from '@/components/svg';
import { useMessages, useNavigation } from '@/components/hooks';
import { SideMenu } from '@/components/common/SideMenu';
import { WebsiteSelect } from '@/components/input/WebsiteSelect';
import { Funnel, Lightning, Magnet, Money, Network, Path, Target } from '@/components/svg';
export function WebsiteNav({
websiteId,

View file

@ -1,11 +1,11 @@
'use client';
import { Column } from '@umami/react-zen';
import { ExpandedViewModal } from '@/app/(main)/websites/[websiteId]/ExpandedViewModal';
import { Panel } from '@/components/common/Panel';
import { WebsiteChart } from './WebsiteChart';
import { WebsiteControls } from './WebsiteControls';
import { WebsiteMetricsBar } from './WebsiteMetricsBar';
import { WebsitePanels } from './WebsitePanels';
import { WebsiteControls } from './WebsiteControls';
import { ExpandedViewModal } from '@/app/(main)/websites/[websiteId]/ExpandedViewModal';
export function WebsitePage({ websiteId }: { websiteId: string }) {
return (

View file

@ -1,3 +1,4 @@
import { Grid, Heading, Row, Tab, TabList, TabPanel, Tabs } from '@umami/react-zen';
import { GridRow } from '@/components/common/GridRow';
import { Panel } from '@/components/common/Panel';
import { useMessages, useNavigation } from '@/components/hooks';
@ -5,7 +6,6 @@ import { EventsChart } from '@/components/metrics/EventsChart';
import { MetricsTable } from '@/components/metrics/MetricsTable';
import { WeeklyTraffic } from '@/components/metrics/WeeklyTraffic';
import { WorldMap } from '@/components/metrics/WorldMap';
import { Grid, Heading, Row, Tab, TabList, TabPanel, Tabs } from '@umami/react-zen';
export function WebsitePanels({ websiteId }: { websiteId: string }) {
const { formatMessage, labels } = useMessages();

View file

@ -1,6 +1,6 @@
import { Tabs, TabList, Tab, Icon, Text, Row } from '@umami/react-zen';
import { Icon, Row, Tab, TabList, Tabs, Text } from '@umami/react-zen';
import { useMessages, useNavigation, useWebsite } from '@/components/hooks';
import { Clock, Eye, User, ChartPie } from '@/components/icons';
import { ChartPie, Clock, Eye, User } from '@/components/icons';
import { Lightning } from '@/components/svg';
export function WebsiteTabs() {

View file

@ -1,8 +1,8 @@
import { Trash } from '@/components/icons';
import { messages } from '@/components/messages';
import { useDeleteQuery, useMessages } from '@/components/hooks';
import { ConfirmationForm } from '@/components/common/ConfirmationForm';
import { useDeleteQuery, useMessages } from '@/components/hooks';
import { Trash } from '@/components/icons';
import { DialogButton } from '@/components/input/DialogButton';
import { messages } from '@/components/messages';
export function CohortDeleteButton({
cohortId,

View file

@ -1,8 +1,8 @@
import { Edit } from '@/components/icons';
import { CohortEditForm } from '@/app/(main)/websites/[websiteId]/cohorts/CohortEditForm';
import { useMessages } from '@/components/hooks';
import { Filter } from '@/lib/types';
import { Edit } from '@/components/icons';
import { DialogButton } from '@/components/input/DialogButton';
import type { Filter } from '@/lib/types';
export function CohortEditButton({
cohortId,

View file

@ -1,20 +1,20 @@
import {
Button,
Column,
Form,
FormButtons,
FormField,
FormSubmitButton,
TextField,
Grid,
Label,
Loading,
Column,
Grid,
TextField,
} from '@umami/react-zen';
import { useMessages, useUpdateQuery, useWebsiteCohortQuery } from '@/components/hooks';
import { ActionSelect } from '@/components/input/ActionSelect';
import { DateFilter } from '@/components/input/DateFilter';
import { FieldFilters } from '@/components/input/FieldFilters';
import { LookupField } from '@/components/input/LookupField';
import { ActionSelect } from '@/components/input/ActionSelect';
export function CohortEditForm({
cohortId,

View file

@ -1,7 +1,7 @@
import { CohortAddButton } from './CohortAddButton';
import { useWebsiteCohortsQuery } from '@/components/hooks';
import { CohortsTable } from './CohortsTable';
import { DataGrid } from '@/components/common/DataGrid';
import { useWebsiteCohortsQuery } from '@/components/hooks';
import { CohortAddButton } from './CohortAddButton';
import { CohortsTable } from './CohortsTable';
export function CohortsDataTable({ websiteId }: { websiteId?: string }) {
const query = useWebsiteCohortsQuery(websiteId, { type: 'cohort' });

View file

@ -1,8 +1,8 @@
'use client';
import { Column } from '@umami/react-zen';
import { CohortsDataTable } from './CohortsDataTable';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { Panel } from '@/components/common/Panel';
import { CohortsDataTable } from './CohortsDataTable';
export function CohortsPage({ websiteId }) {
return (

View file

@ -1,10 +1,10 @@
import { DataTable, DataColumn, Row, DataTableProps } from '@umami/react-zen';
import { useMessages, useNavigation } from '@/components/hooks';
import { DateDistance } from '@/components/common/DateDistance';
import { filtersObjectToArray } from '@/lib/params';
import { CohortEditButton } from '@/app/(main)/websites/[websiteId]/cohorts/CohortEditButton';
import { CohortDeleteButton } from '@/app/(main)/websites/[websiteId]/cohorts/CohortDeleteButton';
import { DataColumn, DataTable, type DataTableProps, Row } from '@umami/react-zen';
import Link from 'next/link';
import { CohortDeleteButton } from '@/app/(main)/websites/[websiteId]/cohorts/CohortDeleteButton';
import { CohortEditButton } from '@/app/(main)/websites/[websiteId]/cohorts/CohortEditButton';
import { DateDistance } from '@/components/common/DateDistance';
import { useMessages, useNavigation } from '@/components/hooks';
import { filtersObjectToArray } from '@/lib/params';
export function CohortsTable(props: DataTableProps) {
const { formatMessage, labels } = useMessages();

View file

@ -1,4 +1,4 @@
import { Metadata } from 'next';
import type { Metadata } from 'next';
import { CohortsPage } from './CohortsPage';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {

View file

@ -1,10 +1,10 @@
'use client';
import { Column } from '@umami/react-zen';
import { CompareTables } from './CompareTables';
import { WebsiteChart } from '@/app/(main)/websites/[websiteId]/WebsiteChart';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { WebsiteMetricsBar } from '@/app/(main)/websites/[websiteId]/WebsiteMetricsBar';
import { Panel } from '@/components/common/Panel';
import { WebsiteChart } from '@/app/(main)/websites/[websiteId]/WebsiteChart';
import { CompareTables } from './CompareTables';
export function ComparePage({ websiteId }: { websiteId: string }) {
return (

View file

@ -1,11 +1,11 @@
import { Column, Grid, Heading, ListItem, Row, Select } from '@umami/react-zen';
import { useState } from 'react';
import { DateDisplay } from '@/components/common/DateDisplay';
import { Panel } from '@/components/common/Panel';
import { useDateRange, useMessages, useNavigation } from '@/components/hooks';
import { ChangeLabel } from '@/components/metrics/ChangeLabel';
import { MetricsTable } from '@/components/metrics/MetricsTable';
import { formatNumber } from '@/lib/format';
import { Column, Grid, Heading, ListItem, Row, Select } from '@umami/react-zen';
import { useState } from 'react';
export function CompareTables({ websiteId }: { websiteId: string }) {
const [data, setData] = useState([]);
@ -106,7 +106,7 @@ export function CompareTables({ websiteId }: { websiteId: string }) {
const change = Math.abs(((count - prev) / prev) * 100);
return (
!isNaN(change) && (
!Number.isNaN(change) && (
<Row alignItems="center" marginRight="3">
<ChangeLabel value={value}>{formatNumber(change)}%</ChangeLabel>
</Row>

View file

@ -1,4 +1,4 @@
import { Metadata } from 'next';
import type { Metadata } from 'next';
import { ComparePage } from './ComparePage';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {

View file

@ -1,14 +1,14 @@
import { Column, Grid, ListItem, Select } from '@umami/react-zen';
import { useMemo, useState } from 'react';
import { Select, ListItem, Grid, Column } from '@umami/react-zen';
import { PieChart } from '@/components/charts/PieChart';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import {
useEventDataPropertiesQuery,
useEventDataValuesQuery,
useMessages,
} from '@/components/hooks';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { PieChart } from '@/components/charts/PieChart';
import { CHART_COLORS } from '@/lib/constants';
import { ListTable } from '@/components/metrics/ListTable';
import { CHART_COLORS } from '@/lib/constants';
export function EventProperties({ websiteId }: { websiteId: string }) {
const [propertyName, setPropertyName] = useState('');

View file

@ -1,9 +1,8 @@
import { useState } from 'react';
import { useMessages, useWebsiteEventsQuery } from '@/components/hooks';
import { EventsTable } from './EventsTable';
import { type ReactNode, useState } from 'react';
import { DataGrid } from '@/components/common/DataGrid';
import { ReactNode } from 'react';
import { useMessages, useWebsiteEventsQuery } from '@/components/hooks';
import { FilterButtons } from '@/components/input/FilterButtons';
import { EventsTable } from './EventsTable';
export function EventsDataTable({
websiteId,

View file

@ -1,9 +1,9 @@
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { useMessages } from '@/components/hooks';
import { useWebsiteSessionStatsQuery } from '@/components/hooks/queries/useWebsiteSessionStatsQuery';
import { MetricCard } from '@/components/metrics/MetricCard';
import { MetricsBar } from '@/components/metrics/MetricsBar';
import { formatLongNumber } from '@/lib/format';
import { LoadingPanel } from '@/components/common/LoadingPanel';
export function EventsMetricsBar({ websiteId }: { websiteId: string }) {
const { formatMessage, labels } = useMessages();

View file

@ -1,15 +1,15 @@
'use client';
import { TabList, Tab, Tabs, TabPanel, Column } from '@umami/react-zen';
import { MetricsTable } from '@/components/metrics/MetricsTable';
import { useState, Key } from 'react';
import { EventsDataTable } from './EventsDataTable';
import { Panel } from '@/components/common/Panel';
import { EventsChart } from '@/components/metrics/EventsChart';
import { useMessages } from '@/components/hooks';
import { EventProperties } from './EventProperties';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { getItem, setItem } from '@/lib/storage';
import { Column, Tab, TabList, TabPanel, Tabs } from '@umami/react-zen';
import { type Key, useState } from 'react';
import { SessionModal } from '@/app/(main)/websites/[websiteId]/sessions/SessionModal';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { Panel } from '@/components/common/Panel';
import { useMessages } from '@/components/hooks';
import { EventsChart } from '@/components/metrics/EventsChart';
import { MetricsTable } from '@/components/metrics/MetricsTable';
import { getItem, setItem } from '@/lib/storage';
import { EventProperties } from './EventProperties';
import { EventsDataTable } from './EventsDataTable';
const KEY_NAME = 'umami.events.tab';

View file

@ -1,24 +1,24 @@
import {
DataTable,
DataColumn,
Row,
Text,
DataTableProps,
IconLabel,
Button,
DataColumn,
DataTable,
type DataTableProps,
Dialog,
DialogTrigger,
Icon,
IconLabel,
Popover,
Row,
Text,
} from '@umami/react-zen';
import { useFormat, useMessages, useNavigation } from '@/components/hooks';
import { Avatar } from '@/components/common/Avatar';
import Link from 'next/link';
import { Eye, FileText } from '@/components/icons';
import { Lightning } from '@/components/svg';
import { Avatar } from '@/components/common/Avatar';
import { DateDistance } from '@/components/common/DateDistance';
import { TypeIcon } from '@/components/common/TypeIcon';
import { useFormat, useMessages, useNavigation } from '@/components/hooks';
import { Eye, FileText } from '@/components/icons';
import { EventData } from '@/components/metrics/EventData';
import { Lightning } from '@/components/svg';
export function EventsTable(props: DataTableProps) {
const { formatMessage, labels } = useMessages();

View file

@ -1,4 +1,4 @@
import { Metadata } from 'next';
import type { Metadata } from 'next';
import { EventsPage } from './EventsPage';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {

View file

@ -1,4 +1,4 @@
import { Metadata } from 'next';
import type { Metadata } from 'next';
import { WebsiteLayout } from '@/app/(main)/websites/[websiteId]/WebsiteLayout';
export default async function ({

View file

@ -1,5 +1,5 @@
import type { Metadata } from 'next';
import { WebsitePage } from './WebsitePage';
import { Metadata } from 'next';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {
const { websiteId } = await params;

View file

@ -1,8 +1,8 @@
import { useCallback } from 'react';
import { IconLabel } from '@umami/react-zen';
import { ListTable } from '@/components/metrics/ListTable';
import { useLocale, useCountryNames, useMessages } from '@/components/hooks';
import { useCallback } from 'react';
import { TypeIcon } from '@/components/common/TypeIcon';
import { useCountryNames, useLocale, useMessages } from '@/components/hooks';
import { ListTable } from '@/components/metrics/ListTable';
export function RealtimeCountries({ data }) {
const { formatMessage, labels } = useMessages();

View file

@ -1,5 +1,5 @@
import { MetricCard } from '@/components/metrics/MetricCard';
import { useMessages } from '@/components/hooks';
import { MetricCard } from '@/components/metrics/MetricCard';
import { MetricsBar } from '@/components/metrics/MetricsBar';
export function RealtimeHeader({ data }: { data: any }) {

View file

@ -1,10 +1,11 @@
import { Column, Heading, IconLabel, Row, SearchField, Text } from '@umami/react-zen';
import Link from 'next/link';
import { useMemo, useState } from 'react';
import { FixedSizeList } from 'react-window';
import { SearchField, Text, Column, Row, IconLabel, Heading } from '@umami/react-zen';
import Link from 'next/link';
import { SessionModal } from '@/app/(main)/websites/[websiteId]/sessions/SessionModal';
import { useFormat } from '@/components//hooks/useFormat';
import { Avatar } from '@/components/common/Avatar';
import { Empty } from '@/components/common/Empty';
import { FilterButtons } from '@/components/input/FilterButtons';
import {
useCountryNames,
useLocale,
@ -15,10 +16,9 @@ import {
useWebsite,
} from '@/components/hooks';
import { Eye, User } from '@/components/icons';
import { FilterButtons } from '@/components/input/FilterButtons';
import { Lightning } from '@/components/svg';
import { BROWSERS, OS_NAMES } from '@/lib/constants';
import { SessionModal } from '@/app/(main)/websites/[websiteId]/sessions/SessionModal';
import { Avatar } from '@/components/common/Avatar';
const TYPE_ALL = 'all';
const TYPE_PAGEVIEW = 'pageview';

View file

@ -1,18 +1,18 @@
'use client';
import { firstBy } from 'thenby';
import { Grid } from '@umami/react-zen';
import { firstBy } from 'thenby';
import { GridRow } from '@/components/common/GridRow';
import { PageBody } from '@/components/common/PageBody';
import { Panel } from '@/components/common/Panel';
import { useMobile, useRealtimeQuery } from '@/components/hooks';
import { RealtimeChart } from '@/components/metrics/RealtimeChart';
import { WorldMap } from '@/components/metrics/WorldMap';
import { useMobile, useRealtimeQuery } from '@/components/hooks';
import { RealtimeLog } from './RealtimeLog';
import { percentFilter } from '@/lib/filters';
import { RealtimeCountries } from './RealtimeCountries';
import { RealtimeHeader } from './RealtimeHeader';
import { RealtimeLog } from './RealtimeLog';
import { RealtimePaths } from './RealtimePaths';
import { RealtimeReferrers } from './RealtimeReferrers';
import { RealtimeCountries } from './RealtimeCountries';
import { percentFilter } from '@/lib/filters';
export function RealtimePage({ websiteId }: { websiteId: string }) {
const { data, isLoading, error } = useRealtimeQuery(websiteId);

View file

@ -1,7 +1,7 @@
import thenby from 'thenby';
import { percentFilter } from '@/lib/filters';
import { ListTable } from '@/components/metrics/ListTable';
import { useMessages, useWebsite } from '@/components/hooks';
import { ListTable } from '@/components/metrics/ListTable';
import { percentFilter } from '@/lib/filters';
export function RealtimePaths({ data }: { data: any }) {
const website = useWebsite();

View file

@ -1,7 +1,7 @@
import thenby from 'thenby';
import { percentFilter } from '@/lib/filters';
import { ListTable } from '@/components/metrics/ListTable';
import { useMessages, useWebsite } from '@/components/hooks';
import { ListTable } from '@/components/metrics/ListTable';
import { percentFilter } from '@/lib/filters';
export function RealtimeReferrers({ data }: { data: any }) {
const website = useWebsite();

View file

@ -1,5 +1,5 @@
import type { Metadata } from 'next';
import { RealtimePage } from './RealtimePage';
import { Metadata } from 'next';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {
const { websiteId } = await params;

View file

@ -1,7 +1,7 @@
import { useMessages } from '@/components/hooks';
import { Plus } from '@/components/icons';
import { SegmentEditForm } from './SegmentEditForm';
import { DialogButton } from '@/components/input/DialogButton';
import { SegmentEditForm } from './SegmentEditForm';
export function SegmentAddButton({ websiteId }: { websiteId: string }) {
const { formatMessage, labels } = useMessages();

View file

@ -1,8 +1,8 @@
import { Trash } from '@/components/icons';
import { ConfirmationForm } from '@/components/common/ConfirmationForm';
import { messages } from '@/components/messages';
import { useDeleteQuery, useMessages } from '@/components/hooks';
import { Trash } from '@/components/icons';
import { DialogButton } from '@/components/input/DialogButton';
import { messages } from '@/components/messages';
export function SegmentDeleteButton({
segmentId,

View file

@ -1,8 +1,8 @@
import { Edit } from '@/components/icons';
import { useMessages } from '@/components/hooks';
import { SegmentEditForm } from './SegmentEditForm';
import { Filter } from '@/lib/types';
import { Edit } from '@/components/icons';
import { DialogButton } from '@/components/input/DialogButton';
import type { Filter } from '@/lib/types';
import { SegmentEditForm } from './SegmentEditForm';
export function SegmentEditButton({
segmentId,

View file

@ -4,12 +4,12 @@ import {
FormButtons,
FormField,
FormSubmitButton,
TextField,
Loading,
Label,
Loading,
TextField,
} from '@umami/react-zen';
import { FieldFilters } from '@/components/input/FieldFilters';
import { useMessages, useUpdateQuery, useWebsiteSegmentQuery } from '@/components/hooks';
import { FieldFilters } from '@/components/input/FieldFilters';
import { messages } from '@/components/messages';
export function SegmentEditForm({

View file

@ -1,7 +1,7 @@
import { SegmentAddButton } from './SegmentAddButton';
import { useWebsiteSegmentsQuery } from '@/components/hooks';
import { SegmentsTable } from './SegmentsTable';
import { DataGrid } from '@/components/common/DataGrid';
import { useWebsiteSegmentsQuery } from '@/components/hooks';
import { SegmentAddButton } from './SegmentAddButton';
import { SegmentsTable } from './SegmentsTable';
export function SegmentsDataTable({ websiteId }: { websiteId?: string }) {
const query = useWebsiteSegmentsQuery(websiteId, { type: 'segment' });

View file

@ -1,8 +1,8 @@
'use client';
import { Column } from '@umami/react-zen';
import { SegmentsDataTable } from './SegmentsDataTable';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { Panel } from '@/components/common/Panel';
import { SegmentsDataTable } from './SegmentsDataTable';
export function SegmentsPage({ websiteId }) {
return (

View file

@ -1,9 +1,9 @@
import { DataTable, DataColumn, Row, DataTableProps } from '@umami/react-zen';
import { useMessages, useNavigation } from '@/components/hooks';
import { DateDistance } from '@/components/common/DateDistance';
import { SegmentEditButton } from '@/app/(main)/websites/[websiteId]/segments/SegmentEditButton';
import { SegmentDeleteButton } from '@/app/(main)/websites/[websiteId]/segments/SegmentDeleteButton';
import { DataColumn, DataTable, type DataTableProps, Row } from '@umami/react-zen';
import Link from 'next/link';
import { SegmentDeleteButton } from '@/app/(main)/websites/[websiteId]/segments/SegmentDeleteButton';
import { SegmentEditButton } from '@/app/(main)/websites/[websiteId]/segments/SegmentEditButton';
import { DateDistance } from '@/components/common/DateDistance';
import { useMessages, useNavigation } from '@/components/hooks';
export function SegmentsTable(props: DataTableProps) {
const { formatMessage, labels } = useMessages();

View file

@ -1,4 +1,4 @@
import { Metadata } from 'next';
import type { Metadata } from 'next';
import { SegmentsPage } from './SegmentsPage';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {

View file

@ -1,21 +1,21 @@
import { isSameDay } from 'date-fns';
import {
Icon,
StatusLight,
Column,
Row,
Heading,
Text,
Button,
DialogTrigger,
Popover,
Column,
Dialog,
DialogTrigger,
Heading,
Icon,
Popover,
Row,
StatusLight,
Text,
} from '@umami/react-zen';
import { isSameDay } from 'date-fns';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { Eye, FileText } from '@/components/icons';
import { Lightning } from '@/components/svg';
import { useMessages, useMobile, useSessionActivityQuery, useTimezone } from '@/components/hooks';
import { Eye, FileText } from '@/components/icons';
import { EventData } from '@/components/metrics/EventData';
import { Lightning } from '@/components/svg';
export function SessionActivity({
websiteId,

View file

@ -1,8 +1,8 @@
import { Text, Column, Row, Label, Box } from '@umami/react-zen';
import { useSessionDataQuery } from '@/components/hooks';
import { Box, Column, Label, Row, Text } from '@umami/react-zen';
import { Empty } from '@/components/common/Empty';
import { DATA_TYPES } from '@/lib/constants';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { useSessionDataQuery } from '@/components/hooks';
import { DATA_TYPES } from '@/lib/constants';
export function SessionData({ websiteId, sessionId }: { websiteId: string; sessionId: string }) {
const { data, isLoading, error } = useSessionDataQuery(websiteId, sessionId);

View file

@ -1,9 +1,9 @@
import { ReactNode } from 'react';
import { Icon, Grid, Column, Row, Label } from '@umami/react-zen';
import { useFormat, useLocale, useMessages, useRegionNames } from '@/components/hooks';
import { TypeIcon } from '@/components/common/TypeIcon';
import { KeyRound, Calendar, MapPin, Landmark } from '@/components/icons';
import { Column, Grid, Icon, Label, Row } from '@umami/react-zen';
import type { ReactNode } from 'react';
import { DateDistance } from '@/components/common/DateDistance';
import { TypeIcon } from '@/components/common/TypeIcon';
import { useFormat, useLocale, useMessages, useRegionNames } from '@/components/hooks';
import { Calendar, KeyRound, Landmark, MapPin } from '@/components/icons';
export function SessionInfo({ data }) {
const { locale } = useLocale();

View file

@ -1,4 +1,4 @@
import { Dialog, Modal, ModalProps, Column } from '@umami/react-zen';
import { Column, Dialog, Modal, type ModalProps } from '@umami/react-zen';
import { SessionProfile } from '@/app/(main)/websites/[websiteId]/sessions/SessionProfile';
import { useNavigation } from '@/components/hooks';

View file

@ -1,14 +1,15 @@
import {
TextField,
Row,
Column,
Tabs,
TabList,
Tab,
TabPanel,
Button,
Column,
Icon,
Row,
Tab,
TabList,
TabPanel,
Tabs,
TextField,
} from '@umami/react-zen';
import { X } from 'lucide-react';
import { Avatar } from '@/components/common/Avatar';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { useMessages, useWebsiteSessionQuery } from '@/components/hooks';
@ -16,7 +17,6 @@ import { SessionActivity } from './SessionActivity';
import { SessionData } from './SessionData';
import { SessionInfo } from './SessionInfo';
import { SessionStats } from './SessionStats';
import { X } from 'lucide-react';
export function SessionProfile({
websiteId,

View file

@ -1,14 +1,14 @@
import { Column, Grid, ListItem, Select } from '@umami/react-zen';
import { useMemo, useState } from 'react';
import { Select, ListItem, Grid, Column } from '@umami/react-zen';
import { PieChart } from '@/components/charts/PieChart';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import {
useMessages,
useSessionDataPropertiesQuery,
useSessionDataValuesQuery,
} from '@/components/hooks';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { PieChart } from '@/components/charts/PieChart';
import { CHART_COLORS } from '@/lib/constants';
import { ListTable } from '@/components/metrics/ListTable';
import { CHART_COLORS } from '@/lib/constants';
export function SessionProperties({ websiteId }: { websiteId: string }) {
const [propertyName, setPropertyName] = useState('');

View file

@ -1,6 +1,6 @@
import { DataGrid } from '@/components/common/DataGrid';
import { useWebsiteSessionsQuery } from '@/components/hooks';
import { SessionsTable } from './SessionsTable';
import { DataGrid } from '@/components/common/DataGrid';
export function SessionsDataTable({ websiteId }: { websiteId?: string; teamId?: string }) {
const queryResult = useWebsiteSessionsQuery(websiteId);

View file

@ -1,9 +1,9 @@
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { useMessages } from '@/components/hooks';
import { useWebsiteSessionStatsQuery } from '@/components/hooks/queries/useWebsiteSessionStatsQuery';
import { MetricCard } from '@/components/metrics/MetricCard';
import { MetricsBar } from '@/components/metrics/MetricsBar';
import { formatLongNumber } from '@/lib/format';
import { LoadingPanel } from '@/components/common/LoadingPanel';
export function SessionsMetricsBar({ websiteId }: { websiteId: string }) {
const { formatMessage, labels } = useMessages();

View file

@ -1,13 +1,13 @@
'use client';
import { Key, useState } from 'react';
import { TabList, Tab, Tabs, TabPanel, Column } from '@umami/react-zen';
import { SessionsDataTable } from './SessionsDataTable';
import { SessionProperties } from './SessionProperties';
import { useMessages } from '@/components/hooks';
import { Panel } from '@/components/common/Panel';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { getItem, setItem } from '@/lib/storage';
import { Column, Tab, TabList, TabPanel, Tabs } from '@umami/react-zen';
import { type Key, useState } from 'react';
import { SessionModal } from '@/app/(main)/websites/[websiteId]/sessions/SessionModal';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { Panel } from '@/components/common/Panel';
import { useMessages } from '@/components/hooks';
import { getItem, setItem } from '@/lib/storage';
import { SessionProperties } from './SessionProperties';
import { SessionsDataTable } from './SessionsDataTable';
const KEY_NAME = 'umami.sessions.tab';

View file

@ -1,9 +1,9 @@
import { DataColumn, DataTable, type DataTableProps } from '@umami/react-zen';
import Link from 'next/link';
import { DataColumn, DataTable, DataTableProps } from '@umami/react-zen';
import { useFormat, useMessages, useNavigation } from '@/components/hooks';
import { Avatar } from '@/components/common/Avatar';
import { TypeIcon } from '@/components/common/TypeIcon';
import { DateDistance } from '@/components/common/DateDistance';
import { TypeIcon } from '@/components/common/TypeIcon';
import { useFormat, useMessages, useNavigation } from '@/components/hooks';
export function SessionsTable(props: DataTableProps) {
const { formatMessage, labels } = useMessages();

View file

@ -1,5 +1,5 @@
import type { Metadata } from 'next';
import { SessionsPage } from './SessionsPage';
import { Metadata } from 'next';
export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {
const { websiteId } = await params;

View file

@ -1,16 +1,16 @@
import { Button, Modal, DialogTrigger, Dialog, Column } from '@umami/react-zen';
import { Button, Column, Dialog, DialogTrigger, Modal } from '@umami/react-zen';
import { ActionForm } from '@/components/common/ActionForm';
import {
useLoginQuery,
useMessages,
useModified,
useUserTeamsQuery,
useNavigation,
useUserTeamsQuery,
} from '@/components/hooks';
import { ROLES } from '@/lib/constants';
import { WebsiteDeleteForm } from './WebsiteDeleteForm';
import { WebsiteResetForm } from './WebsiteResetForm';
import { WebsiteTransferForm } from './WebsiteTransferForm';
import { ActionForm } from '@/components/common/ActionForm';
import { ROLES } from '@/lib/constants';
export function WebsiteData({ websiteId, onSave }: { websiteId: string; onSave?: () => void }) {
const { formatMessage, labels, messages } = useMessages();

View file

@ -1,5 +1,5 @@
import { useDeleteQuery, useMessages } from '@/components/hooks';
import { TypeConfirmationForm } from '@/components/common/TypeConfirmationForm';
import { useDeleteQuery, useMessages } from '@/components/hooks';
const CONFIRM_VALUE = 'DELETE';

View file

@ -1,4 +1,4 @@
import { FormSubmitButton, Form, FormField, FormButtons, TextField } from '@umami/react-zen';
import { Form, FormButtons, FormField, FormSubmitButton, TextField } from '@umami/react-zen';
import { useMessages, useUpdateQuery, useWebsite } from '@/components/hooks';
import { DOMAIN_REGEX } from '@/lib/constants';

View file

@ -1,5 +1,5 @@
import { useMessages, useUpdateQuery } from '@/components/hooks';
import { TypeConfirmationForm } from '@/components/common/TypeConfirmationForm';
import { useMessages, useUpdateQuery } from '@/components/hooks';
const CONFIRM_VALUE = 'RESET';

View file

@ -1,10 +1,10 @@
import { Column } from '@umami/react-zen';
import { Panel } from '@/components/common/Panel';
import { useWebsite } from '@/components/hooks';
import { WebsiteShareForm } from './WebsiteShareForm';
import { WebsiteTrackingCode } from './WebsiteTrackingCode';
import { WebsiteData } from './WebsiteData';
import { WebsiteEditForm } from './WebsiteEditForm';
import { Panel } from '@/components/common/Panel';
import { WebsiteShareForm } from './WebsiteShareForm';
import { WebsiteTrackingCode } from './WebsiteTrackingCode';
export function WebsiteSettings({ websiteId }: { websiteId: string; openExternal?: boolean }) {
const website = useWebsite();

View file

@ -1,8 +1,8 @@
import { IconLabel, Row } from '@umami/react-zen';
import Link from 'next/link';
import { PageHeader } from '@/components/common/PageHeader';
import { Globe, ArrowLeft } from '@/components/icons';
import { useMessages, useNavigation, useWebsite } from '@/components/hooks';
import { IconLabel, Row } from '@umami/react-zen';
import { ArrowLeft, Globe } from '@/components/icons';
export function WebsiteSettingsHeader() {
const website = useWebsite();

Some files were not shown because too many files have changed in this diff Show more