typescript fixes, replayer close error, show page toggle fix.
This commit is contained in:
1 parent
10dced1049
commit
f3ce0e64ca
15 files changed
+67
-28
No files matched your search
@@ -23,7 +23,7 @@ export function TestConsolePage({ websiteId }: { websiteId: string }) {
|
||||
test: 'test-data',
|
||||
boolean: true,
|
||||
booleanError: 'true',
|
||||
time: new Date(),
|
||||
time: new Date().toISOString(),
|
||||
user: `user${Math.round(Math.random() * 10)}`,
|
||||
number: 1,
|
||||
number2: Math.random() * 100,
|
||||
@@ -87,7 +87,7 @@ export function TestConsolePage({ websiteId }: { websiteId: string }) {
|
||||
test: 'test-data',
|
||||
boolean: true,
|
||||
booleanError: 'true',
|
||||
time: new Date(),
|
||||
time: new Date().toISOString(),
|
||||
time2: new Date().toISOString(),
|
||||
nested: {
|
||||
test: 'test-data',
|
||||
|
||||
@@ -10,7 +10,6 @@ export function LinkEditButton({ linkId }: { linkId: string }) {
|
||||
return (
|
||||
<LinkButton
|
||||
href={renderUrl(`/links/${linkId}/edit`, false)}
|
||||
title={t(labels.edit)}
|
||||
aria-label={t(labels.edit)}
|
||||
variant="quiet"
|
||||
>
|
||||
|
||||
@@ -10,7 +10,6 @@ export function PixelEditButton({ pixelId }: { pixelId: string }) {
|
||||
return (
|
||||
<LinkButton
|
||||
href={renderUrl(`/pixels/${pixelId}/edit`, false)}
|
||||
title={t(labels.edit)}
|
||||
aria-label={t(labels.edit)}
|
||||
variant="quiet"
|
||||
>
|
||||
|
||||
@@ -269,8 +269,8 @@ function ClickHeatmapView({
|
||||
const hasSnapshot = Boolean(snapshot);
|
||||
|
||||
useEffect(() => {
|
||||
setSnapshotReady(!(showPage && hasSnapshot));
|
||||
}, [hasSnapshot, showPage, snapshot?.id]);
|
||||
setSnapshotReady(!hasSnapshot);
|
||||
}, [hasSnapshot, snapshot?.id]);
|
||||
const overlayGutter = Math.max(48, Math.round((viewport?.width ?? 1920) * 0.04));
|
||||
const maxPointX = visible.reduce((max, point) => Math.max(max, point.pageX), 0);
|
||||
const maxPointY = visible.reduce((max, point) => Math.max(max, point.pageY), 0);
|
||||
@@ -425,8 +425,8 @@ function ScrollHeatmapView({
|
||||
const hasSnapshot = Boolean(snapshot);
|
||||
|
||||
useEffect(() => {
|
||||
setSnapshotReady(!(showPage && hasSnapshot));
|
||||
}, [hasSnapshot, showPage, snapshot?.id]);
|
||||
setSnapshotReady(!hasSnapshot);
|
||||
}, [hasSnapshot, snapshot?.id]);
|
||||
const {
|
||||
buckets = [],
|
||||
totalSessions = 0,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import thenby from 'thenby';
|
||||
import { firstBy } from 'thenby';
|
||||
import { useMessages, useWebsite } from '@/components/hooks';
|
||||
import { ListTable } from '@/components/metrics/ListTable';
|
||||
import { percentFilter } from '@/lib/filters';
|
||||
@@ -26,7 +26,7 @@ export function RealtimePaths({ data }: { data: any }) {
|
||||
y: urls[key],
|
||||
};
|
||||
})
|
||||
.sort(thenby.firstBy('y', -1))
|
||||
.sort(firstBy('y', -1))
|
||||
.slice(0, limit),
|
||||
);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import thenby from 'thenby';
|
||||
import { useMessages, useWebsite } from '@/components/hooks';
|
||||
import { ListTable } from '@/components/metrics/ListTable';
|
||||
import { percentFilter } from '@/lib/filters';
|
||||
import { firstBy } from 'thenby';
|
||||
|
||||
export function RealtimeReferrers({ data }: { data: any }) {
|
||||
const website = useWebsite();
|
||||
@@ -26,7 +26,7 @@ export function RealtimeReferrers({ data }: { data: any }) {
|
||||
y: referrers[key],
|
||||
};
|
||||
})
|
||||
.sort(thenby.firstBy('y', -1))
|
||||
.sort(firstBy('y', -1))
|
||||
.slice(0, limit),
|
||||
);
|
||||
|
||||
|
||||
@@ -8,6 +8,21 @@ import 'rrweb-player/dist/style.css';
|
||||
|
||||
const DEFAULT_REPLAY_ASPECT_RATIO = 9 / 16;
|
||||
|
||||
function destroyReplayPlayer(player: { $destroy?: () => void } | null) {
|
||||
if (!player) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
player.$destroy?.();
|
||||
} catch (error) {
|
||||
// rrweb-player alpha teardown can throw after it loses its inner replayer instance.
|
||||
if (!(error instanceof TypeError) || !error.message.includes('pause is not a function')) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function ReplayPlayer({ events }: { events: any[] }) {
|
||||
const playerRootRef = useRef<HTMLDivElement>(null);
|
||||
const playerRef = useRef<any>(null);
|
||||
@@ -34,7 +49,7 @@ export function ReplayPlayer({ events }: { events: any[] }) {
|
||||
setPlayerError(false);
|
||||
|
||||
if (playerRef.current) {
|
||||
playerRef.current.$destroy?.();
|
||||
destroyReplayPlayer(playerRef.current);
|
||||
playerRef.current = null;
|
||||
}
|
||||
|
||||
@@ -89,7 +104,7 @@ export function ReplayPlayer({ events }: { events: any[] }) {
|
||||
cancelled = true;
|
||||
|
||||
if (playerRef.current) {
|
||||
playerRef.current.$destroy?.();
|
||||
destroyReplayPlayer(playerRef.current);
|
||||
playerRef.current = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ vi.mock('@/lib/response', () => ({
|
||||
ok: () => new Response(null, { status: 200 }),
|
||||
}));
|
||||
|
||||
const redisMock = redis as {
|
||||
const redisMock = redis as unknown as {
|
||||
enabled: boolean;
|
||||
client: {
|
||||
del: ReturnType<typeof vi.fn>;
|
||||
|
||||
@@ -32,7 +32,7 @@ export function CopyButton({ value, label = 'Copy' }: { value: string; label?: s
|
||||
};
|
||||
|
||||
return (
|
||||
<Button variant="quiet" onPress={handleCopy} title={label} aria-label={label}>
|
||||
<Button variant="quiet" onPress={handleCopy} aria-label={label}>
|
||||
<Icon size="sm">{copied ? <Check /> : <Copy />}</Icon>
|
||||
</Button>
|
||||
);
|
||||
|
||||
@@ -3,9 +3,9 @@ import type { ErrorInfo, ReactNode } from 'react';
|
||||
import { ErrorBoundary as Boundary } from 'react-error-boundary';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
|
||||
const logError = (error: Error, info: ErrorInfo) => {
|
||||
const logError = (error: unknown, info: ErrorInfo) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error, info.componentStack);
|
||||
console.error(error instanceof Error ? error : new Error(String(error)), info.componentStack);
|
||||
};
|
||||
|
||||
export function ErrorBoundary({ children }: { children: ReactNode }) {
|
||||
|
||||
@@ -23,15 +23,14 @@ export function FilterLink({ type, value, label, externalUrl, icon }: FilterLink
|
||||
<Row
|
||||
alignItems="center"
|
||||
gap
|
||||
fontWeight={active && selected ? 'bold' : undefined}
|
||||
color={active && !selected ? 'muted' : undefined}
|
||||
onMouseOver={() => setShowLink(true)}
|
||||
onMouseOut={() => setShowLink(false)}
|
||||
>
|
||||
{icon}
|
||||
{!value && `(${label || t(labels.unknown)})`}
|
||||
{!value && <Text weight={active && selected ? 'bold' : undefined}>({label || t(labels.unknown)})</Text>}
|
||||
{value && (
|
||||
<Text title={label || value} truncate>
|
||||
<Text title={label || value} truncate weight={active && selected ? 'bold' : undefined}>
|
||||
<Link href={updateParams({ [type]: `eq.${value}` })} replace>
|
||||
{label || value}
|
||||
</Link>
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ export const KAFKA = 'kafka';
|
||||
export const KAFKA_PRODUCER = 'kafka-producer';
|
||||
|
||||
// Fixes issue with converting bigint values
|
||||
BigInt.prototype.toJSON = function () {
|
||||
(BigInt.prototype as unknown as { toJSON(): number }).toJSON = function () {
|
||||
return Number(this);
|
||||
};
|
||||
|
||||
|
||||
+5
-1
@@ -4,6 +4,10 @@ import type { Filter, Operator, PropertyFilter, QueryFilters, QueryOptions } fro
|
||||
const VALID_OPERATORS: Operator[] = Object.values(OPERATORS);
|
||||
const VALID_EVENT_DATA_TYPES = Object.values(DATA_TYPE);
|
||||
|
||||
function isValidEventDataType(value: number): value is (typeof VALID_EVENT_DATA_TYPES)[number] {
|
||||
return VALID_EVENT_DATA_TYPES.includes(value as (typeof VALID_EVENT_DATA_TYPES)[number]);
|
||||
}
|
||||
|
||||
function resolveOperator(value?: string): Operator | undefined {
|
||||
if (!value) {
|
||||
return undefined;
|
||||
@@ -126,7 +130,7 @@ export function parsePropertyFilters(
|
||||
|
||||
if (
|
||||
!operator ||
|
||||
(explicitDataType !== undefined && !VALID_EVENT_DATA_TYPES.includes(explicitDataType))
|
||||
(explicitDataType !== undefined && !isValidEventDataType(explicitDataType))
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
+4
-2
@@ -8,9 +8,11 @@ import {
|
||||
type ReactNode,
|
||||
} from 'react';
|
||||
|
||||
type ReactElementWithChildren = ReactElement<{ children?: ReactNode }>;
|
||||
|
||||
export function getFragmentChildren(children: ReactNode) {
|
||||
return (children as ReactElement)?.type === Fragment
|
||||
? (children as ReactElement).props.children
|
||||
return (children as ReactElementWithChildren)?.type === Fragment
|
||||
? (children as ReactElementWithChildren).props.children
|
||||
: children;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+24
-3
@@ -66,7 +66,7 @@ export type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
|
||||
* - Objects have a max of 50 properties. Arrays are considered 1 property.
|
||||
*/
|
||||
export interface EventData {
|
||||
[key: string]: number | string | EventData | number[] | string[] | EventData[];
|
||||
[key: string]: boolean | number | string | EventData | boolean[] | number[] | string[] | EventData[];
|
||||
}
|
||||
|
||||
export type EventProperties = {
|
||||
@@ -146,8 +146,29 @@ export type UmamiTracker = {
|
||||
*/
|
||||
(eventFunction: CustomEventFunction): Promise<string>;
|
||||
};
|
||||
identify: {
|
||||
/**
|
||||
* Identify a visitor with optional associated data.
|
||||
*
|
||||
* @example ```
|
||||
* umami.identify('user-123', { plan: 'pro' });
|
||||
* ```
|
||||
*/
|
||||
(id: string, data?: EventData): Promise<string>;
|
||||
|
||||
/**
|
||||
* Associate data with the current visitor without setting an identity string.
|
||||
*
|
||||
* @example ```
|
||||
* umami.identify({ plan: 'pro' });
|
||||
* ```
|
||||
*/
|
||||
(data: EventData): Promise<string>;
|
||||
};
|
||||
};
|
||||
|
||||
export interface Window {
|
||||
umami: UmamiTracker;
|
||||
declare global {
|
||||
interface Window {
|
||||
umami: UmamiTracker;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user