Updated components build.

This commit is contained in:
Mike Cao 2025-09-01 15:59:06 -07:00
parent 5f27ba149b
commit 56af91950a
53 changed files with 942 additions and 333 deletions

View file

@ -1,8 +1,9 @@
import { createContext, ReactNode } from 'react';
import { Loading } from '@umami/react-zen';
import { useUserQuery } from '@/components/hooks';
import { User } from '@/generated/prisma/client';
import { useUserQuery } from '@/components/hooks/queries/useUserQuery';
export const UserContext = createContext(null);
export const UserContext = createContext<User>(null);
export function UserProvider({ userId, children }: { userId: string; children: ReactNode }) {
const { data: user, isFetching, isLoading } = useUserQuery(userId);

View file

@ -14,7 +14,7 @@ import {
import { useConfig, useLinkQuery } from '@/components/hooks';
import { useMessages } from '@/components/hooks';
import { Refresh } from '@/components/icons';
import { getRandomChars } from '@/lib/crypto';
import { getRandomChars } from '@/lib/generate';
import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery';
import { LINKS_URL } from '@/lib/constants';
import { isValidUrl } from '@/lib/url';

View file

@ -1,9 +1,10 @@
'use client';
import { createContext, ReactNode } from 'react';
import { useLinkQuery } from '@/components/hooks';
import { Loading } from '@umami/react-zen';
import { Link } from '@/generated/prisma/client';
import { useLinkQuery } from '@/components/hooks/queries/useLinkQuery';
export const LinkContext = createContext(null);
export const LinkContext = createContext<Link>(null);
export function LinkProvider({ linkId, children }: { linkId?: string; children: ReactNode }) {
const { data: link, isLoading, isFetching } = useLinkQuery(linkId);

View file

@ -13,7 +13,7 @@ import {
import { useConfig, usePixelQuery } from '@/components/hooks';
import { useMessages } from '@/components/hooks';
import { Refresh } from '@/components/icons';
import { getRandomChars } from '@/lib/crypto';
import { getRandomChars } from '@/lib/generate';
import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery';
import { useEffect, useState } from 'react';
import { PIXELS_URL } from '@/lib/constants';

View file

@ -1,9 +1,10 @@
'use client';
import { createContext, ReactNode } from 'react';
import { usePixelQuery } from '@/components/hooks';
import { Loading } from '@umami/react-zen';
import { Pixel } from '@/generated/prisma/client';
import { usePixelQuery } from '@/components/hooks/queries/usePixelQuery';
export const PixelContext = createContext(null);
export const PixelContext = createContext<Pixel>(null);
export function PixelProvider({ pixelId, children }: { pixelId?: string; children: ReactNode }) {
const { data: pixel, isLoading, isFetching } = usePixelQuery(pixelId);

View file

@ -41,9 +41,9 @@ export function SettingsLayout({ children }: { children: ReactNode }) {
},
];
const selectedKey =
items.flatMap(e => e.items)?.find(({ path }) => path && pathname.includes(path))?.id ||
'overview';
const selectedKey = items
.flatMap(e => e.items)
.find(({ path }) => path && pathname.endsWith(path.split('?')[0]))?.id;
return (
<Grid columns="auto 1fr" width="100%" height="100%">

View file

@ -2,10 +2,6 @@ import { Metadata } from 'next';
import { SettingsLayout } from './SettingsLayout';
export default function ({ children }) {
if (process.env.cloudMode) {
return null;
}
return <SettingsLayout>{children}</SettingsLayout>;
}

View file

@ -32,7 +32,7 @@ export function TeamLeaveForm({
<ConfirmationForm
buttonLabel={formatMessage(labels.leave)}
message={formatMessage(messages.confirmLeave, {
target: <b key={messages.confirmLeave.id}>{teamName}</b>,
target: teamName,
})}
onConfirm={handleConfirm}
onClose={onClose}

View file

@ -1,9 +1,10 @@
'use client';
import { createContext, ReactNode } from 'react';
import { useTeamQuery } from '@/components/hooks';
import { Loading } from '@umami/react-zen';
import { useTeamQuery } from '@/components/hooks/queries/useTeamQuery';
import { Team } from '@/generated/prisma/client';
export const TeamContext = createContext(null);
export const TeamContext = createContext<Team>(null);
export function TeamProvider({ teamId, children }: { teamId?: string; children: ReactNode }) {
const { data: team, isLoading, isFetching } = useTeamQuery(teamId);

View file

@ -6,7 +6,7 @@ import {
TextField,
Button,
} from '@umami/react-zen';
import { getRandomChars } from '@/lib/crypto';
import { getRandomChars } from '@/lib/generate';
import { useMessages, useTeam, useUpdateQuery } from '@/components/hooks';
const generateId = () => `team_${getRandomChars(16)}`;

View file

@ -13,7 +13,7 @@ import { PageHeader } from '@/components/common/PageHeader';
import { Panel } from '@/components/common/Panel';
export function TeamSettings({ teamId }: { teamId: string }) {
const team = useTeam();
const team: any = useTeam();
const { formatMessage, labels } = useMessages();
const { user } = useLoginQuery();
const { query, pathname } = useNavigation();

View file

@ -1,8 +1,19 @@
import { DataColumn, DataTable } from '@umami/react-zen';
import { DataColumn, DataTable, Row } from '@umami/react-zen';
import { useMessages } from '@/components/hooks';
import Link from 'next/link';
import { ROLES } from '@/lib/constants';
import { TeamMemberEditButton } from '@/app/(main)/teams/[teamId]/TeamMemberEditButton';
import { TeamMemberRemoveButton } from '@/app/(main)/teams/[teamId]/TeamMemberRemoveButton';
export function TeamWebsitesTable({ teamId, data = [] }: { teamId: string; data: any[] }) {
export function TeamWebsitesTable({
teamId,
data = [],
allowEdit,
}: {
teamId: string;
data: any[];
allowEdit: boolean;
}) {
const { formatMessage, labels } = useMessages();
return (
@ -14,6 +25,26 @@ export function TeamWebsitesTable({ teamId, data = [] }: { teamId: string; data:
<DataColumn id="createdBy" label={formatMessage(labels.createdBy)}>
{(row: any) => row?.createUser?.username}
</DataColumn>
{allowEdit && (
<DataColumn id="action" align="end">
{(row: any) => {
if (row?.role === ROLES.teamOwner) {
return null;
}
return (
<Row alignItems="center">
<TeamMemberEditButton teamId={teamId} userId={row?.user?.id} role={row?.role} />
<TeamMemberRemoveButton
teamId={teamId}
userId={row?.user?.id}
userName={row?.user?.username}
/>
</Row>
);
}}
</DataColumn>
)}
</DataTable>
);
}

View file

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

View file

@ -143,12 +143,12 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
},
];
const selectedKey =
items.flatMap(e => e.items).find(({ path }) => path && pathname.endsWith(path.split('?')[0]))
?.id || 'overview';
const selectedKey = items
.flatMap(e => e.items)
.find(({ path }) => path && pathname.endsWith(path.split('?')[0]))?.id;
return (
<SideMenu items={items} selectedKey={selectedKey} allowMinimize={false}>
<SideMenu items={items} selectedKey={selectedKey} allowMinimize={false} muteItems={false}>
<WebsiteSelect websiteId={websiteId} teamId={teamId} />
</SideMenu>
);

View file

@ -1,5 +1,5 @@
import { useMemo, useState } from 'react';
import { Select, ListItem, Grid } from '@umami/react-zen';
import { Select, ListItem, Grid, Column } from '@umami/react-zen';
import {
useEventDataPropertiesQuery,
useEventDataValuesQuery,
@ -33,40 +33,41 @@ export function EventProperties({ websiteId }: { websiteId: string }) {
isFetching={isFetching}
error={error}
minHeight="300px"
gap="6"
>
{data && (
<Grid columns="repeat(auto-fill, minmax(300px, 1fr))" marginBottom="3" gap>
<Select
label={formatMessage(labels.event)}
value={eventName}
onChange={setEventName}
placeholder=""
>
{events?.map(p => (
<ListItem key={p} id={p}>
{p}
</ListItem>
))}
</Select>
<Select
label={formatMessage(labels.property)}
value={propertyName}
onChange={setPropertyName}
isDisabled={!eventName}
placeholder=""
>
{properties?.map(p => (
<ListItem key={p} id={p}>
{p}
</ListItem>
))}
</Select>
</Grid>
)}
{eventName && propertyName && (
<EventValues websiteId={websiteId} eventName={eventName} propertyName={propertyName} />
)}
<Column gap="6">
{data && (
<Grid columns="repeat(auto-fill, minmax(300px, 1fr))" marginBottom="3" gap>
<Select
label={formatMessage(labels.event)}
value={eventName}
onChange={setEventName}
placeholder=""
>
{events?.map(p => (
<ListItem key={p} id={p}>
{p}
</ListItem>
))}
</Select>
<Select
label={formatMessage(labels.property)}
value={propertyName}
onChange={setPropertyName}
isDisabled={!eventName}
placeholder=""
>
{properties?.map(p => (
<ListItem key={p} id={p}>
{p}
</ListItem>
))}
</Select>
</Grid>
)}
{eventName && propertyName && (
<EventValues websiteId={websiteId} eventName={eventName} propertyName={propertyName} />
)}
</Column>
</LoadingPanel>
);
}

View file

@ -10,7 +10,7 @@ import {
Row,
} from '@umami/react-zen';
import { useState } from 'react';
import { getRandomChars } from '@/lib/crypto';
import { getRandomChars } from '@/lib/generate';
import { useMessages, useUpdateQuery } from '@/components/hooks';
const generateId = () => getRandomChars(16);

View file

@ -39,7 +39,7 @@ const schema = z.object({
url: urlOrPathParam.optional(),
name: z.string().max(50).optional(),
tag: z.string().max(50).optional(),
ip: z.string().ip().optional(),
ip: z.string().optional(),
userAgent: z.string().optional(),
timestamp: z.coerce.number().int().optional(),
id: z.string().optional(),

View file

@ -1,5 +1,5 @@
import { z } from 'zod';
import { getRandomChars } from '@/lib/crypto';
import { getRandomChars } from '@/lib/generate';
import { unauthorized, json } from '@/lib/response';
import { canCreateTeam } from '@/validations';
import { uuid } from '@/lib/crypto';