mirror of
https://github.com/umami-software/umami.git
synced 2026-02-13 17:15:37 +01:00
Merge 5413ce5d61 into a3733b0424
This commit is contained in:
commit
f31567a60c
4 changed files with 43 additions and 10 deletions
|
|
@ -13,6 +13,7 @@ import { X } from 'lucide-react';
|
||||||
import { Avatar } from '@/components/common/Avatar';
|
import { Avatar } from '@/components/common/Avatar';
|
||||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||||
import { useMessages, useWebsiteSessionQuery } from '@/components/hooks';
|
import { useMessages, useWebsiteSessionQuery } from '@/components/hooks';
|
||||||
|
import { isLikelyBot } from '@/lib/botDetection';
|
||||||
import { SessionActivity } from './SessionActivity';
|
import { SessionActivity } from './SessionActivity';
|
||||||
import { SessionData } from './SessionData';
|
import { SessionData } from './SessionData';
|
||||||
import { SessionInfo } from './SessionInfo';
|
import { SessionInfo } from './SessionInfo';
|
||||||
|
|
@ -51,7 +52,7 @@ export function SessionProfile({
|
||||||
)}
|
)}
|
||||||
<Column gap="6">
|
<Column gap="6">
|
||||||
<Row justifyContent="center" alignItems="center" gap="6">
|
<Row justifyContent="center" alignItems="center" gap="6">
|
||||||
<Avatar seed={data?.id} size={128} />
|
<Avatar seed={data?.id} size={128} isBot={isLikelyBot(data)} />
|
||||||
<Column width="360px">
|
<Column width="360px">
|
||||||
<TextField label="ID" value={data?.id} allowCopy />
|
<TextField label="ID" value={data?.id} allowCopy />
|
||||||
</Column>
|
</Column>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { Avatar } from '@/components/common/Avatar';
|
||||||
import { DateDistance } from '@/components/common/DateDistance';
|
import { DateDistance } from '@/components/common/DateDistance';
|
||||||
import { TypeIcon } from '@/components/common/TypeIcon';
|
import { TypeIcon } from '@/components/common/TypeIcon';
|
||||||
import { useFormat, useMessages, useNavigation } from '@/components/hooks';
|
import { useFormat, useMessages, useNavigation } from '@/components/hooks';
|
||||||
|
import { isLikelyBot } from '@/lib/botDetection';
|
||||||
|
|
||||||
export function SessionsTable(props: DataTableProps) {
|
export function SessionsTable(props: DataTableProps) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
@ -15,7 +16,7 @@ export function SessionsTable(props: DataTableProps) {
|
||||||
<DataColumn id="id" label={formatMessage(labels.session)} width="100px">
|
<DataColumn id="id" label={formatMessage(labels.session)} width="100px">
|
||||||
{(row: any) => (
|
{(row: any) => (
|
||||||
<Link href={updateParams({ session: row.id })}>
|
<Link href={updateParams({ session: row.id })}>
|
||||||
<Avatar seed={row.id} size={32} />
|
<Avatar seed={row.id} size={32} isBot={isLikelyBot(row)} />
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</DataColumn>
|
</DataColumn>
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,27 @@
|
||||||
import { lorelei } from '@dicebear/collection';
|
import { bottts, lorelei } from '@dicebear/collection';
|
||||||
import { createAvatar } from '@dicebear/core';
|
import { createAvatar, type Style } from '@dicebear/core';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { getColor, getPastel } from '@/lib/colors';
|
import { getColor, getPastel } from '@/lib/colors';
|
||||||
|
|
||||||
const lib = lorelei;
|
export function Avatar({
|
||||||
|
seed,
|
||||||
export function Avatar({ seed, size = 128, ...props }: { seed: string; size?: number }) {
|
size = 128,
|
||||||
|
isBot = false,
|
||||||
|
}: {
|
||||||
|
seed: string;
|
||||||
|
size?: number;
|
||||||
|
isBot?: boolean;
|
||||||
|
}) {
|
||||||
const backgroundColor = getPastel(getColor(seed), 4);
|
const backgroundColor = getPastel(getColor(seed), 4);
|
||||||
|
const style = (isBot ? bottts : lorelei) as Style<object>;
|
||||||
|
|
||||||
const avatar = useMemo(() => {
|
const avatar = useMemo(() => {
|
||||||
return createAvatar(lib, {
|
return createAvatar(style, {
|
||||||
...props,
|
|
||||||
seed,
|
seed,
|
||||||
size,
|
size,
|
||||||
backgroundColor: [backgroundColor],
|
backgroundColor: [backgroundColor],
|
||||||
}).toDataUri();
|
}).toDataUri();
|
||||||
}, []);
|
}, [seed, isBot]);
|
||||||
|
|
||||||
return <img src={avatar} alt="Avatar" style={{ borderRadius: '100%', width: size }} />;
|
return <img src={avatar} alt="Avatar" style={{ borderRadius: '100%', width: size }} />;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
25
src/lib/botDetection.ts
Normal file
25
src/lib/botDetection.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
const BOT_CITIES = [
|
||||||
|
'Council Bluffs',
|
||||||
|
'North Richland Hills',
|
||||||
|
'Santa Clara',
|
||||||
|
'Ashburn',
|
||||||
|
'The Dalles',
|
||||||
|
'Boardman',
|
||||||
|
'Quincy',
|
||||||
|
];
|
||||||
|
|
||||||
|
export function isLikelyBot(session: {
|
||||||
|
city?: string;
|
||||||
|
firstAt?: string | Date;
|
||||||
|
lastAt?: string | Date;
|
||||||
|
}): boolean {
|
||||||
|
const cityMatch =
|
||||||
|
session.city && BOT_CITIES.some(botCity => session.city?.toLowerCase() === botCity.toLowerCase());
|
||||||
|
|
||||||
|
const zeroDuration =
|
||||||
|
session.firstAt &&
|
||||||
|
session.lastAt &&
|
||||||
|
new Date(session.firstAt).getTime() === new Date(session.lastAt).getTime();
|
||||||
|
|
||||||
|
return !!(cityMatch && zeroDuration);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue