Card mode for tables.

This commit is contained in:
Mike Cao 2025-10-13 13:01:01 -07:00
parent df3ae72ab7
commit d9b08d9491
14 changed files with 81 additions and 80 deletions

View file

@ -28,9 +28,9 @@ export function App({ children }) {
}
return (
<Grid columns={{ xs: '1fr', md: 'auto 1fr' }} height="100vh" width="100%" backgroundColor="2">
<Row display={{ xs: 'flex', md: 'none' }} alignItems="center" gap></Row>
<Column display={{ xs: 'none', md: 'flex' }}>
<Grid columns={{ xs: '1fr', lg: 'auto 1fr' }} height="100vh" width="100%" backgroundColor="2">
<Row display={{ xs: 'flex', lg: 'none' }} alignItems="center" gap></Row>
<Column display={{ xs: 'none', lg: 'flex' }}>
<SideNav />
</Column>
<Column alignItems="center" overflowY="auto" overflowX="hidden" position="relative">

View file

@ -1,23 +1,18 @@
import Link from 'next/link';
import { DataTable, DataColumn, Row } from '@umami/react-zen';
import { DataTable, DataColumn, Row, DataTableProps } from '@umami/react-zen';
import { useMessages, useNavigation, useSlug } from '@/components/hooks';
import { Empty } from '@/components/common/Empty';
import { DateDistance } from '@/components/common/DateDistance';
import { ExternalLink } from '@/components/common/ExternalLink';
import { LinkEditButton } from './LinkEditButton';
import { LinkDeleteButton } from './LinkDeleteButton';
export function LinksTable({ data = [] }) {
export function LinksTable(props: DataTableProps) {
const { formatMessage, labels } = useMessages();
const { websiteId, renderUrl } = useNavigation();
const { getSlugUrl } = useSlug('link');
if (data.length === 0) {
return <Empty />;
}
return (
<DataTable data={data}>
<DataTable {...props}>
<DataColumn id="name" label={formatMessage(labels.name)}>
{({ id, name }: any) => {
return <Link href={renderUrl(`/links/${id}`)}>{name}</Link>;

View file

@ -1,23 +1,18 @@
import Link from 'next/link';
import { DataTable, DataColumn, Row } from '@umami/react-zen';
import { DataTable, DataColumn, Row, DataTableProps } from '@umami/react-zen';
import { useMessages, useNavigation, useSlug } from '@/components/hooks';
import { Empty } from '@/components/common/Empty';
import { DateDistance } from '@/components/common/DateDistance';
import { PixelEditButton } from './PixelEditButton';
import { PixelDeleteButton } from './PixelDeleteButton';
import { ExternalLink } from '@/components/common/ExternalLink';
export function PixelsTable({ data = [] }) {
export function PixelsTable(props: DataTableProps) {
const { formatMessage, labels } = useMessages();
const { renderUrl } = useNavigation();
const { getSlugUrl } = useSlug('pixel');
if (data.length === 0) {
return <Empty />;
}
return (
<DataTable data={data}>
<DataTable {...props}>
<DataColumn id="name" label={formatMessage(labels.name)}>
{({ id, name }: any) => {
return <Link href={renderUrl(`/pixels/${id}`)}>{name}</Link>;

View file

@ -1,19 +1,17 @@
import { DataColumn, DataTable } from '@umami/react-zen';
import { DataColumn, DataTable, DataTableProps } from '@umami/react-zen';
import { useMessages } from '@/components/hooks';
import { ROLES } from '@/lib/constants';
import { ReactNode } from 'react';
export function TeamsTable({
data = [],
renderLink,
}: {
data: any[];
export interface TeamsTableProps extends DataTableProps {
renderLink?: (row: any) => ReactNode;
}) {
}
export function TeamsTable({ renderLink, ...props }: TeamsTableProps) {
const { formatMessage, labels } = useMessages();
return (
<DataTable data={data}>
<DataTable {...props}>
<DataColumn id="name" label={formatMessage(labels.name)}>
{renderLink}
</DataColumn>

View file

@ -1,30 +1,22 @@
import { ReactNode } from 'react';
import { Icon, DataTable, DataColumn } from '@umami/react-zen';
import { Icon, DataTable, DataColumn, DataTableProps } from '@umami/react-zen';
import { LinkButton } from '@/components/common/LinkButton';
import { useMessages, useNavigation } from '@/components/hooks';
import { SquarePen } from '@/components/icons';
import { Empty } from '@/components/common/Empty';
export function WebsitesTable({
data = [],
showActions,
renderLink,
}: {
data: Record<string, any>[];
export interface WebsitesTableProps extends DataTableProps {
showActions?: boolean;
allowEdit?: boolean;
allowView?: boolean;
renderLink?: (row: any) => ReactNode;
}) {
}
export function WebsitesTable({ showActions, renderLink, ...props }: WebsitesTableProps) {
const { formatMessage, labels } = useMessages();
const { renderUrl } = useNavigation();
if (data.length === 0) {
return <Empty />;
}
return (
<DataTable data={data}>
<DataTable {...props}>
<DataColumn id="name" label={formatMessage(labels.name)}>
{renderLink}
</DataColumn>

View file

@ -1,6 +1,5 @@
import { DataTable, DataColumn, Icon, Row, Text } from '@umami/react-zen';
import { DataTable, DataColumn, Row, Text, DataTableProps, IconLabel } from '@umami/react-zen';
import { useFormat, useMessages, useNavigation } from '@/components/hooks';
import { Empty } from '@/components/common/Empty';
import { Avatar } from '@/components/common/Avatar';
import Link from 'next/link';
import { Eye } from '@/components/icons';
@ -8,35 +7,44 @@ import { Lightning } from '@/components/svg';
import { DateDistance } from '@/components/common/DateDistance';
import { TypeIcon } from '@/components/common/TypeIcon';
export function EventsTable({ data = [] }) {
export function EventsTable(props: DataTableProps) {
const { formatMessage, labels } = useMessages();
const { updateParams } = useNavigation();
const { formatValue } = useFormat();
if (data.length === 0) {
return <Empty />;
}
return (
<DataTable data={data}>
<DataTable {...props}>
<DataColumn id="event" label={formatMessage(labels.event)} width="2fr">
{(row: any) => {
return (
<Row alignItems="center" gap="2">
<Link href={updateParams({ session: row.sessionId })}>
<Avatar seed={row.sessionId} size={32} />
</Link>
<Icon>{row.eventName ? <Lightning /> : <Eye />}</Icon>
<Text>
{formatMessage(row.eventName ? labels.triggeredEvent : labels.viewedPage)}
</Text>
<Text weight="bold" style={{ maxWidth: '300px' }} truncate>
<Row alignItems="center" wrap="wrap" gap>
<Row>
<IconLabel
icon={row.eventName ? <Lightning /> : <Eye />}
label={formatMessage(row.eventName ? labels.triggeredEvent : labels.viewedPage)}
/>
</Row>
<Text
weight="bold"
style={{ maxWidth: '300px' }}
title={row.eventName || row.urlPath}
truncate
>
{row.eventName || row.urlPath}
</Text>
</Row>
);
}}
</DataColumn>
<DataColumn id="session" label={formatMessage(labels.session)} width="80px">
{(row: any) => {
return (
<Link href={updateParams({ session: row.sessionId })}>
<Avatar seed={row.sessionId} size={32} />
</Link>
);
}}
</DataColumn>
<DataColumn id="location" label={formatMessage(labels.location)}>
{(row: any) => (
<TypeIcon type="country" value={row.country}>

View file

@ -8,7 +8,7 @@ export function SessionsDataTable({ websiteId }: { websiteId?: string; teamId?:
return (
<DataGrid query={queryResult} allowPaging allowSearch>
{({ data }) => {
return <SessionsTable data={data} showDomain={!websiteId} />;
return <SessionsTable data={data} />;
}}
</DataGrid>
);

View file

@ -1,17 +1,17 @@
import Link from 'next/link';
import { DataColumn, DataTable } from '@umami/react-zen';
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';
export function SessionsTable({ data = [] }: { data: any[]; showDomain?: boolean }) {
export function SessionsTable(props: DataTableProps) {
const { formatMessage, labels } = useMessages();
const { formatValue } = useFormat();
const { updateParams } = useNavigation();
return (
<DataTable data={data}>
<DataTable {...props}>
<DataColumn id="id" label={formatMessage(labels.session)} width="100px">
{(row: any) => (
<Link href={updateParams({ session: row.id })}>