mirror of
https://github.com/umami-software/umami.git
synced 2026-02-14 01:25:37 +01:00
Merge branch 'dev' into feat/thumbnail-team-memory
This commit is contained in:
commit
f5d6d0ebaf
577 changed files with 2413 additions and 3645 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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 }> }) {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 }) {
|
||||
|
|
|
|||
|
|
@ -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 = [],
|
||||
|
|
|
|||
|
|
@ -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 }> }) {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 }> }) {
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 }> }) {
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@
|
|||
|
||||
.start:before,
|
||||
.end:before {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
border-radius: 100%;
|
||||
border: 3px solid var(--journey-line-color);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 }> }) {
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 }> }) {
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 }> }) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 }> }) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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' });
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 }> }) {
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 }> }) {
|
||||
|
|
|
|||
|
|
@ -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('');
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 }> }) {
|
||||
|
|
|
|||
|
|
@ -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 ({
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 }) {
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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' });
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 }> }) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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('');
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue