mirror of
https://github.com/umami-software/umami.git
synced 2026-02-07 06:07:17 +01:00
Pixel/links development. New validations folder. More refactoring.
This commit is contained in:
parent
88639dfe83
commit
247e14646b
136 changed files with 1395 additions and 516 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { Tooltip, TooltipTrigger, Text, Focusable } from '@umami/react-zen';
|
||||
import { Text } from '@umami/react-zen';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { useLocale, useTimezone } from '@/components/hooks';
|
||||
|
||||
|
|
@ -7,11 +7,8 @@ export function DateDistance({ date }: { date: Date }) {
|
|||
const { dateLocale } = useLocale();
|
||||
|
||||
return (
|
||||
<TooltipTrigger delay={0}>
|
||||
<Focusable>
|
||||
<Text>{formatDistanceToNow(date, { addSuffix: true, locale: dateLocale })}</Text>
|
||||
</Focusable>
|
||||
<Tooltip>{formatTimezoneDate(date.toISOString(), 'PPPpp')}</Tooltip>
|
||||
</TooltipTrigger>
|
||||
<Text title={formatTimezoneDate(date.toISOString(), 'PPPpp')}>
|
||||
{formatDistanceToNow(date, { addSuffix: true, locale: dateLocale })}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
18
src/components/common/ExternalLink.tsx
Normal file
18
src/components/common/ExternalLink.tsx
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import Link from 'next/link';
|
||||
import { Icon, Row, Text } from '@umami/react-zen';
|
||||
import { ExternalLink as LinkIcon } from '@/components/icons';
|
||||
|
||||
export function ExternalLink({ href, children, ...props }: Icon) {
|
||||
return (
|
||||
<Row alignItems="center" overflow="hidden" gap>
|
||||
<Text title={href} truncate>
|
||||
<Link {...props} href={href} target="_blank">
|
||||
{children}
|
||||
</Link>
|
||||
</Text>
|
||||
<Icon size="sm" strokeColor="muted">
|
||||
<LinkIcon />
|
||||
</Icon>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,8 +1,11 @@
|
|||
'use client';
|
||||
|
||||
// Query hooks
|
||||
export * from './queries/useActiveUsersQuery';
|
||||
export * from './queries/useEventDataQuery';
|
||||
export * from './queries/useDeleteQuery';
|
||||
export * from './queries/useEventDataEventsQuery';
|
||||
export * from './queries/useEventDataPropertiesQuery';
|
||||
export * from './queries/useEventDataQuery';
|
||||
export * from './queries/useEventDataValuesQuery';
|
||||
export * from './queries/useLinkQuery';
|
||||
export * from './queries/useLinksQuery';
|
||||
|
|
@ -10,41 +13,51 @@ export * from './queries/useLoginQuery';
|
|||
export * from './queries/usePixelQuery';
|
||||
export * from './queries/usePixelsQuery';
|
||||
export * from './queries/useRealtimeQuery';
|
||||
export * from './queries/useResultQuery';
|
||||
export * from './queries/useReportQuery';
|
||||
export * from './queries/useReportsQuery';
|
||||
export * from './queries/useResultQuery';
|
||||
export * from './queries/useSessionActivityQuery';
|
||||
export * from './queries/useSessionDataQuery';
|
||||
export * from './queries/useSessionDataPropertiesQuery';
|
||||
export * from './queries/useSessionDataQuery';
|
||||
export * from './queries/useSessionDataValuesQuery';
|
||||
export * from './queries/useWebsiteSessionQuery';
|
||||
export * from './queries/useWebsiteSessionsQuery';
|
||||
export * from './queries/useWebsiteSessionsWeeklyQuery';
|
||||
export * from './queries/useShareTokenQuery';
|
||||
export * from './queries/useTeamMembersQuery';
|
||||
export * from './queries/useTeamQuery';
|
||||
export * from './queries/useTeamWebsitesQuery';
|
||||
export * from './queries/useTeamsQuery';
|
||||
export * from './queries/useUpdateQuery';
|
||||
export * from './queries/useUserQuery';
|
||||
export * from './queries/useUserTeamsQuery';
|
||||
export * from './queries/useUserWebsitesQuery';
|
||||
export * from './queries/useTeamWebsitesQuery';
|
||||
export * from './queries/useTeamMembersQuery';
|
||||
export * from './queries/useUserQuery';
|
||||
export * from './queries/useUsersQuery';
|
||||
export * from './queries/useWebsiteCohortQuery';
|
||||
export * from './queries/useWebsiteCohortsQuery';
|
||||
export * from './queries/useWebsiteEventsQuery';
|
||||
export * from './queries/useWebsiteEventsSeriesQuery';
|
||||
export * from './queries/useWebsiteExpandedMetricsQuery';
|
||||
export * from './queries/useWebsiteMetricsQuery';
|
||||
export * from './queries/useWebsitePageviewsQuery';
|
||||
export * from './queries/useWebsiteQuery';
|
||||
export * from './queries/useWebsiteSegmentQuery';
|
||||
export * from './queries/useWebsiteSegmentsQuery';
|
||||
export * from './queries/useWebsitesQuery';
|
||||
export * from './queries/useWebsiteEventsQuery';
|
||||
export * from './queries/useWebsiteEventsSeriesQuery';
|
||||
export * from './queries/useWebsiteMetricsQuery';
|
||||
export * from './queries/useWebsiteExpandedMetricsQuery';
|
||||
export * from './queries/useWebsiteSessionQuery';
|
||||
export * from './queries/useWebsiteSessionStatsQuery';
|
||||
export * from './queries/useWebsiteSessionsQuery';
|
||||
export * from './queries/useWebsiteSessionsWeeklyQuery';
|
||||
export * from './queries/useWebsiteStatsQuery';
|
||||
export * from './queries/useWebsiteValuesQuery';
|
||||
export * from './queries/useWebsitesQuery';
|
||||
|
||||
// Regular hooks
|
||||
export * from './useApi';
|
||||
export * from './useConfig';
|
||||
export * from './useCountryNames';
|
||||
export * from './useDateParameters';
|
||||
export * from './useDateRange';
|
||||
export * from './useDocumentClick';
|
||||
export * from './useEscapeKey';
|
||||
export * from './useFields';
|
||||
export * from './useFilterParameters';
|
||||
export * from './useFilters';
|
||||
export * from './useForceUpdate';
|
||||
export * from './useFormat';
|
||||
|
|
@ -55,6 +68,7 @@ export * from './useMessages';
|
|||
export * from './useModified';
|
||||
export * from './useNavigation';
|
||||
export * from './usePagedQuery';
|
||||
export * from './usePageParameters';
|
||||
export * from './useRegionNames';
|
||||
export * from './useSticky';
|
||||
export * from './useTeam';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useApi } from '../useApi';
|
||||
import { ReactQueryOptions } from '@/lib/types';
|
||||
|
||||
export function useActyiveUsersQuery(websiteId: string, options?: ReactQueryOptions<any>) {
|
||||
export function useActyiveUsersQuery(websiteId: string, options?: ReactQueryOptions) {
|
||||
const { get, useQuery } = useApi();
|
||||
return useQuery<any>({
|
||||
queryKey: ['websites:active', websiteId],
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useFilterParameters } from '../useFilterParameters';
|
|||
import { useDateParameters } from '../useDateParameters';
|
||||
import { ReactQueryOptions } from '@/lib/types';
|
||||
|
||||
export function useEventDataEventsQuery(websiteId: string, options?: ReactQueryOptions<any>) {
|
||||
export function useEventDataEventsQuery(websiteId: string, options?: ReactQueryOptions) {
|
||||
const { get, useQuery } = useApi();
|
||||
const date = useDateParameters(websiteId);
|
||||
const filters = useFilterParameters();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useFilterParameters } from '../useFilterParameters';
|
|||
import { useDateParameters } from '../useDateParameters';
|
||||
import { ReactQueryOptions } from '@/lib/types';
|
||||
|
||||
export function useEventDataPropertiesQuery(websiteId: string, options?: ReactQueryOptions<any>) {
|
||||
export function useEventDataPropertiesQuery(websiteId: string, options?: ReactQueryOptions) {
|
||||
const { get, useQuery } = useApi();
|
||||
const date = useDateParameters(websiteId);
|
||||
const filters = useFilterParameters();
|
||||
|
|
|
|||
|
|
@ -3,11 +3,7 @@ import { useFilterParameters } from '../useFilterParameters';
|
|||
import { useDateParameters } from '../useDateParameters';
|
||||
import { ReactQueryOptions } from '@/lib/types';
|
||||
|
||||
export function useEventDataQuery(
|
||||
websiteId: string,
|
||||
eventId: string,
|
||||
options?: ReactQueryOptions<any>,
|
||||
) {
|
||||
export function useEventDataQuery(websiteId: string, eventId: string, options?: ReactQueryOptions) {
|
||||
const { get, useQuery } = useApi();
|
||||
const date = useDateParameters(websiteId);
|
||||
const params = useFilterParameters();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ export function useEventDataValuesQuery(
|
|||
websiteId: string,
|
||||
eventName: string,
|
||||
propertyName: string,
|
||||
options?: ReactQueryOptions<any>,
|
||||
options?: ReactQueryOptions,
|
||||
) {
|
||||
const { get, useQuery } = useApi();
|
||||
const date = useDateParameters(websiteId);
|
||||
|
|
|
|||
|
|
@ -3,13 +3,15 @@ import { usePagedQuery } from '../usePagedQuery';
|
|||
import { useModified } from '../useModified';
|
||||
import { ReactQueryOptions } from '@/lib/types';
|
||||
|
||||
export function useLinksQuery({ teamId }: { teamId?: string }, options?: ReactQueryOptions<any>) {
|
||||
export function useLinksQuery({ teamId }: { teamId?: string }, options?: ReactQueryOptions) {
|
||||
const { modified } = useModified('links');
|
||||
const { get } = useApi();
|
||||
|
||||
return usePagedQuery({
|
||||
queryKey: ['links', { teamId, modified }],
|
||||
queryFn: async () => get(teamId ? `/teams/${teamId}/links` : '/links'),
|
||||
queryFn: pageParams => {
|
||||
return get(teamId ? `/teams/${teamId}/links` : '/links', pageParams);
|
||||
},
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,17 +3,15 @@ import { usePagedQuery } from '../usePagedQuery';
|
|||
import { useModified } from '../useModified';
|
||||
import { ReactQueryOptions } from '@/lib/types';
|
||||
|
||||
export function usePixelsQuery(
|
||||
{ websiteId, type }: { websiteId: string; type?: string },
|
||||
options?: ReactQueryOptions<any>,
|
||||
) {
|
||||
const { modified } = useModified(`pixels:${type}`);
|
||||
export function usePixelsQuery({ teamId }: { teamId?: string }, options?: ReactQueryOptions) {
|
||||
const { modified } = useModified('pixels');
|
||||
const { get } = useApi();
|
||||
|
||||
return usePagedQuery({
|
||||
queryKey: ['pixels', { websiteId, type, modified }],
|
||||
queryFn: async () => get('/pixels', { websiteId, type }),
|
||||
enabled: !!websiteId && !!type,
|
||||
queryKey: ['pixels', { teamId, modified }],
|
||||
queryFn: pageParams => {
|
||||
return get(teamId ? `/teams/${teamId}/pixels` : '/pixels', pageParams);
|
||||
},
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { ReactQueryOptions } from '@/lib/types';
|
|||
|
||||
export function useReportsQuery(
|
||||
{ websiteId, type }: { websiteId: string; type?: string },
|
||||
options?: ReactQueryOptions<any>,
|
||||
options?: ReactQueryOptions,
|
||||
) {
|
||||
const { modified } = useModified(`reports:${type}`);
|
||||
const { get } = useApi();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useFilterParameters } from '../useFilterParameters';
|
|||
import { useDateParameters } from '../useDateParameters';
|
||||
import { ReactQueryOptions } from '@/lib/types';
|
||||
|
||||
export function useSessionDataPropertiesQuery(websiteId: string, options?: ReactQueryOptions<any>) {
|
||||
export function useSessionDataPropertiesQuery(websiteId: string, options?: ReactQueryOptions) {
|
||||
const { get, useQuery } = useApi();
|
||||
const date = useDateParameters(websiteId);
|
||||
const filters = useFilterParameters();
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { ReactQueryOptions } from '@/lib/types';
|
|||
export function useSessionDataValuesQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
options?: ReactQueryOptions<any>,
|
||||
options?: ReactQueryOptions,
|
||||
) {
|
||||
const { get, useQuery } = useApi();
|
||||
const date = useDateParameters(websiteId);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useModified } from '@/components/hooks';
|
|||
import { keepPreviousData } from '@tanstack/react-query';
|
||||
import { ReactQueryOptions } from '@/lib/types';
|
||||
|
||||
export function useTeamQuery(teamId: string, options?: ReactQueryOptions<any>) {
|
||||
export function useTeamQuery(teamId: string, options?: ReactQueryOptions) {
|
||||
const { get, useQuery } = useApi();
|
||||
const { modified } = useModified(`teams:${teamId}`);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useModified } from '@/components/hooks';
|
|||
import { keepPreviousData } from '@tanstack/react-query';
|
||||
import { ReactQueryOptions } from '@/lib/types';
|
||||
|
||||
export function useUserQuery(userId: string, options?: ReactQueryOptions<any>) {
|
||||
export function useUserQuery(userId: string, options?: ReactQueryOptions) {
|
||||
const { get, useQuery } = useApi();
|
||||
const { modified } = useModified(`user:${userId}`);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { useApi } from '../useApi';
|
||||
import { usePagedQuery } from '../usePagedQuery';
|
||||
import { useLoginQuery } from './useLoginQuery';
|
||||
import { useModified } from '../useModified';
|
||||
import { ReactQueryOptions } from '@/lib/types';
|
||||
|
||||
|
|
@ -10,16 +9,22 @@ export function useUserWebsitesQuery(
|
|||
options?: ReactQueryOptions,
|
||||
) {
|
||||
const { get } = useApi();
|
||||
const { user } = useLoginQuery();
|
||||
const { modified } = useModified(`websites`);
|
||||
|
||||
return usePagedQuery({
|
||||
queryKey: ['websites', { userId, teamId, modified, ...params }],
|
||||
queryFn: pageParams => {
|
||||
return get(teamId ? `/teams/${teamId}/websites` : `/users/${userId || user.id}/websites`, {
|
||||
...pageParams,
|
||||
...params,
|
||||
});
|
||||
return get(
|
||||
teamId
|
||||
? `/teams/${teamId}/websites`
|
||||
: userId
|
||||
? `/users/${userId}/websites`
|
||||
: '/me/websites',
|
||||
{
|
||||
...pageParams,
|
||||
...params,
|
||||
},
|
||||
);
|
||||
},
|
||||
...options,
|
||||
});
|
||||
|
|
|
|||
21
src/components/hooks/queries/useWebsiteCohortQuery.ts
Normal file
21
src/components/hooks/queries/useWebsiteCohortQuery.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { useApi } from '../useApi';
|
||||
import { useModified } from '@/components/hooks';
|
||||
import { keepPreviousData } from '@tanstack/react-query';
|
||||
import { ReactQueryOptions } from '@/lib/types';
|
||||
|
||||
export function useWebsiteCohortQuery(
|
||||
websiteId: string,
|
||||
cohortId: string,
|
||||
options?: ReactQueryOptions,
|
||||
) {
|
||||
const { get, useQuery } = useApi();
|
||||
const { modified } = useModified(`cohorts`);
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['website:cohorts', { websiteId, cohortId, modified }],
|
||||
queryFn: () => get(`/websites/${websiteId}/cohorts/${cohortId}`),
|
||||
enabled: !!(websiteId && cohortId),
|
||||
placeholderData: keepPreviousData,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
25
src/components/hooks/queries/useWebsiteCohortsQuery.ts
Normal file
25
src/components/hooks/queries/useWebsiteCohortsQuery.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { useApi } from '../useApi';
|
||||
import { useModified } from '@/components/hooks';
|
||||
import { keepPreviousData } from '@tanstack/react-query';
|
||||
import { ReactQueryOptions } from '@/lib/types';
|
||||
import { useFilterParameters } from '@/components/hooks/useFilterParameters';
|
||||
|
||||
export function useWebsiteCohortsQuery(
|
||||
websiteId: string,
|
||||
params?: Record<string, string>,
|
||||
options?: ReactQueryOptions,
|
||||
) {
|
||||
const { get, useQuery } = useApi();
|
||||
const { modified } = useModified(`cohorts`);
|
||||
const filters = useFilterParameters();
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['website:cohorts', { websiteId, modified, ...filters, ...params }],
|
||||
queryFn: pageParams => {
|
||||
return get(`/websites/${websiteId}/cohorts`, { ...pageParams, ...filters, ...params });
|
||||
},
|
||||
enabled: !!websiteId,
|
||||
placeholderData: keepPreviousData,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ const EVENT_TYPES = {
|
|||
export function useWebsiteEventsQuery(
|
||||
websiteId: string,
|
||||
params?: Record<string, any>,
|
||||
options?: ReactQueryOptions<any>,
|
||||
options?: ReactQueryOptions,
|
||||
) {
|
||||
const { get } = useApi();
|
||||
const date = useDateParameters(websiteId);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useFilterParameters } from '../useFilterParameters';
|
|||
import { useDateParameters } from '../useDateParameters';
|
||||
import { ReactQueryOptions } from '@/lib/types';
|
||||
|
||||
export function useWebsiteEventsSeriesQuery(websiteId: string, options?: ReactQueryOptions<any>) {
|
||||
export function useWebsiteEventsSeriesQuery(websiteId: string, options?: ReactQueryOptions) {
|
||||
const { get, useQuery } = useApi();
|
||||
const date = useDateParameters(websiteId);
|
||||
const filters = useFilterParameters();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useModified } from '@/components/hooks';
|
|||
import { keepPreviousData } from '@tanstack/react-query';
|
||||
import { ReactQueryOptions } from '@/lib/types';
|
||||
|
||||
export function useWebsiteQuery(websiteId: string, options?: ReactQueryOptions<any>) {
|
||||
export function useWebsiteQuery(websiteId: string, options?: ReactQueryOptions) {
|
||||
const { get, useQuery } = useApi();
|
||||
const { modified } = useModified(`website:${websiteId}`);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { ReactQueryOptions } from '@/lib/types';
|
|||
export function useWebsiteSegmentQuery(
|
||||
websiteId: string,
|
||||
segmentId: string,
|
||||
options?: ReactQueryOptions<any>,
|
||||
options?: ReactQueryOptions,
|
||||
) {
|
||||
const { get, useQuery } = useApi();
|
||||
const { modified } = useModified(`segments`);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { useFilterParameters } from '@/components/hooks/useFilterParameters';
|
|||
export function useWebsiteSegmentsQuery(
|
||||
websiteId: string,
|
||||
params?: Record<string, string>,
|
||||
options?: ReactQueryOptions<any>,
|
||||
options?: ReactQueryOptions,
|
||||
) {
|
||||
const { get, useQuery } = useApi();
|
||||
const { modified } = useModified(`segments`);
|
||||
|
|
|
|||
|
|
@ -1,25 +1,24 @@
|
|||
import { ReactNode } from 'react';
|
||||
import { Button, Icon, Modal, DialogTrigger, TooltipTrigger, Tooltip } from '@umami/react-zen';
|
||||
import { Button, Icon, Modal, Text, DialogTrigger } from '@umami/react-zen';
|
||||
|
||||
export function ActionButton({
|
||||
onClick,
|
||||
icon,
|
||||
tooltip,
|
||||
title,
|
||||
children,
|
||||
}: {
|
||||
onSave?: () => void;
|
||||
icon?: ReactNode;
|
||||
tooltip?: string;
|
||||
children?: React.ReactNode;
|
||||
title?: string;
|
||||
children?: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<DialogTrigger>
|
||||
<TooltipTrigger delay={0}>
|
||||
<Text title={title}>
|
||||
<Button variant="quiet" onPress={onClick}>
|
||||
<Icon>{icon}</Icon>
|
||||
</Button>
|
||||
<Tooltip>{tooltip}</Tooltip>
|
||||
</TooltipTrigger>
|
||||
</Text>
|
||||
<Modal>{children}</Modal>
|
||||
</DialogTrigger>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -352,6 +352,7 @@ export const labels = defineMessages({
|
|||
saveCohort: { id: 'label.save-cohort', defaultMessage: 'Save as cohort' },
|
||||
analysis: { id: 'label.analysis', defaultMessage: 'Analysis' },
|
||||
destinationUrl: { id: 'label.destination-url', defaultMessage: 'Destination URL' },
|
||||
audience: { id: 'label.audience', defaultMessage: 'Audience' },
|
||||
});
|
||||
|
||||
export const messages = defineMessages({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue