forked from pterodactyl/panel
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathActivityLogEntry.tsx
More file actions
90 lines (85 loc) · 4.18 KB
/
ActivityLogEntry.tsx
File metadata and controls
90 lines (85 loc) · 4.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import React from 'react';
import { UserIcon } from '@heroicons/react/outline';
import { Link } from 'react-router-dom';
import Tooltip from '@/components/elements/tooltip/Tooltip';
import Translate from '@/components/elements/Translate';
import { format, formatDistanceToNowStrict } from 'date-fns';
import { ActivityLog } from '@definitions/user';
import { useLocation } from 'react-router';
import ActivityLogMetaButton from '@/components/elements/activity/ActivityLogMetaButton';
import { TerminalIcon } from '@heroicons/react/solid';
import classNames from 'classnames';
import style from './style.module.css';
interface Props {
activity: ActivityLog;
children?: React.ReactNode;
}
export default ({ activity, children }: Props) => {
const location = useLocation();
const actor = activity.relationships.actor;
const queryTo = (params: Record<string, string>): string => {
const current = new URLSearchParams(location.search);
Object.keys(params).forEach(key => current.set(key, params[key]));
return current.toString();
};
return (
<div className={'grid grid-cols-10 py-4 border-b-2 border-gray-800 last:rounded-b last:border-0 group'}>
<div className={'hidden sm:flex sm:col-span-1 items-center justify-center select-none'}>
<div className={'flex items-center w-8 h-8 rounded-full bg-gray-600 overflow-hidden'}>
{actor ?
<img src={actor.image} alt={'User avatar'}/>
:
<UserIcon className={'w-5 h-5 mx-auto'}/>
}
</div>
</div>
<div className={'col-span-10 sm:col-span-9 flex'}>
<div className={'flex-1 px-4 sm:px-0'}>
<div className={'flex items-center text-gray-50'}>
<Tooltip placement={'top'} content={actor?.email || 'System User'}>
<span>{actor?.username || 'System'}</span>
</Tooltip>
<span className={'text-gray-400'}> — </span>
<Link
to={`?${queryTo({ event: activity.event })}`}
className={'transition-colors duration-75 active:text-cyan-400 hover:text-cyan-400'}
>
{activity.event}
</Link>
<div className={classNames(style.icons, 'group-hover:text-gray-300')}>
{activity.isApi &&
<Tooltip placement={'top'} content={'Performed using API Key'}>
<span><TerminalIcon/></span>
</Tooltip>
}
{children}
</div>
</div>
<p className={'mt-1 text-sm break-words line-clamp-2 pr-4'}>
<Translate ns={'activity'} values={activity.properties}>
{activity.event.replace(':', '.')}
</Translate>
</p>
<div className={'mt-1 flex items-center text-sm'}>
<Link
to={`?${queryTo({ ip: activity.ip })}`}
className={'transition-colors duration-75 active:text-cyan-400 hover:text-cyan-400'}
>
{activity.ip}
</Link>
<span className={'text-gray-400'}> | </span>
<Tooltip
placement={'right'}
content={format(activity.timestamp, 'MMM do, yyyy h:mma')}
>
<span>
{formatDistanceToNowStrict(activity.timestamp, { addSuffix: true })}
</span>
</Tooltip>
</div>
</div>
{activity.hasAdditionalMetadata && <ActivityLogMetaButton meta={activity.properties}/>}
</div>
</div>
);
};