2023-12-30 01:02:57 +08:00
|
|
|
import { Button, Card, Dropdown, Popconfirm, Space, Spin, Modal } from 'antd';
|
2023-11-15 22:09:10 +08:00
|
|
|
import dayjs from 'dayjs';
|
|
|
|
import React, { useState } from 'react';
|
2023-10-28 16:01:11 +08:00
|
|
|
import {
|
|
|
|
defaultErrorHandler,
|
|
|
|
defaultSuccessHandler,
|
|
|
|
trpc,
|
|
|
|
} from '../../api/trpc';
|
2023-10-10 00:09:39 +08:00
|
|
|
import { useCurrentWorkspaceId } from '../../store/user';
|
|
|
|
import { Loading } from '../Loading';
|
2023-12-05 20:07:36 +08:00
|
|
|
import { getMonitorLink } from './provider';
|
2023-10-10 00:09:39 +08:00
|
|
|
import { NotFoundTip } from '../NotFoundTip';
|
|
|
|
import { MonitorInfo as MonitorInfoType } from '../../../types';
|
2023-10-10 19:47:05 +08:00
|
|
|
import { MonitorHealthBar } from './MonitorHealthBar';
|
2023-11-15 22:09:10 +08:00
|
|
|
import { last } from 'lodash-es';
|
2023-10-15 00:51:03 +08:00
|
|
|
import { ColorTag } from '../ColorTag';
|
2023-10-19 23:22:39 +08:00
|
|
|
import { useNavigate } from 'react-router';
|
2023-10-25 00:29:47 +08:00
|
|
|
import { MonitorEventList } from './MonitorEventList';
|
2023-10-28 16:01:11 +08:00
|
|
|
import { useEvent } from '../../hooks/useEvent';
|
2023-11-15 22:09:10 +08:00
|
|
|
import { MonitorDataMetrics } from './MonitorDataMetrics';
|
|
|
|
import { MonitorDataChart } from './MonitorDataChart';
|
2024-01-06 22:08:10 +08:00
|
|
|
import { DeleteOutlined, MoreOutlined } from '@ant-design/icons';
|
|
|
|
import { MonitorBadgeView } from './MonitorBadgeView';
|
2024-02-12 00:10:38 +08:00
|
|
|
import { useTranslation } from '@i18next-toolkit/react';
|
2023-10-10 00:09:39 +08:00
|
|
|
|
|
|
|
interface MonitorInfoProps {
|
|
|
|
monitorId: string;
|
|
|
|
}
|
|
|
|
export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
|
2024-02-12 00:10:38 +08:00
|
|
|
const { t } = useTranslation();
|
2023-10-10 00:09:39 +08:00
|
|
|
const workspaceId = useCurrentWorkspaceId();
|
|
|
|
const { monitorId } = props;
|
2023-10-13 00:55:41 +08:00
|
|
|
const [currectResponse, setCurrentResponse] = useState(0);
|
2023-10-19 23:22:39 +08:00
|
|
|
const navigate = useNavigate();
|
2024-01-06 22:08:10 +08:00
|
|
|
const [showBadge, setShowBadge] = useState(false);
|
2023-10-10 00:09:39 +08:00
|
|
|
|
2023-10-19 23:22:39 +08:00
|
|
|
const {
|
|
|
|
data: monitorInfo,
|
|
|
|
isInitialLoading,
|
|
|
|
isLoading,
|
|
|
|
} = trpc.monitor.get.useQuery({
|
2023-10-10 00:09:39 +08:00
|
|
|
workspaceId,
|
2023-10-25 00:17:18 +08:00
|
|
|
monitorId,
|
2023-10-10 00:09:39 +08:00
|
|
|
});
|
2023-10-28 16:01:11 +08:00
|
|
|
const changeActiveMutation = trpc.monitor.changeActive.useMutation({
|
|
|
|
onSuccess: defaultSuccessHandler,
|
|
|
|
onError: defaultErrorHandler,
|
|
|
|
});
|
2023-12-09 00:39:36 +08:00
|
|
|
const deleteMutation = trpc.monitor.delete.useMutation({
|
|
|
|
onSuccess: defaultSuccessHandler,
|
|
|
|
onError: defaultErrorHandler,
|
|
|
|
});
|
2023-12-30 01:02:57 +08:00
|
|
|
const clearEventsMutation = trpc.monitor.clearEvents.useMutation({
|
|
|
|
onSuccess: defaultSuccessHandler,
|
|
|
|
onError: defaultErrorHandler,
|
|
|
|
});
|
|
|
|
const clearDataMutation = trpc.monitor.clearData.useMutation({
|
|
|
|
onSuccess: defaultSuccessHandler,
|
|
|
|
onError: defaultErrorHandler,
|
|
|
|
});
|
2023-10-28 16:01:11 +08:00
|
|
|
|
|
|
|
const trpcUtils = trpc.useContext();
|
|
|
|
|
|
|
|
const handleStart = useEvent(async () => {
|
|
|
|
await changeActiveMutation.mutateAsync({
|
|
|
|
workspaceId,
|
|
|
|
monitorId,
|
|
|
|
active: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
trpcUtils.monitor.get.refetch({
|
|
|
|
workspaceId,
|
|
|
|
monitorId,
|
|
|
|
});
|
|
|
|
trpcUtils.monitor.events.refetch({
|
|
|
|
workspaceId,
|
|
|
|
monitorId,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
const handleStop = useEvent(async () => {
|
|
|
|
await changeActiveMutation.mutateAsync({
|
|
|
|
workspaceId,
|
|
|
|
monitorId,
|
|
|
|
active: false,
|
|
|
|
});
|
|
|
|
|
|
|
|
trpcUtils.monitor.get.refetch({
|
|
|
|
workspaceId,
|
|
|
|
monitorId,
|
|
|
|
});
|
|
|
|
trpcUtils.monitor.events.refetch({
|
|
|
|
workspaceId,
|
|
|
|
monitorId,
|
|
|
|
});
|
|
|
|
});
|
2023-10-10 00:09:39 +08:00
|
|
|
|
2023-12-09 00:39:36 +08:00
|
|
|
const handleDelete = useEvent(async () => {
|
2024-02-08 15:56:21 +08:00
|
|
|
Modal.confirm({
|
2024-02-12 00:10:38 +08:00
|
|
|
title: t('Warning'),
|
|
|
|
content: t('Did you sure delete this monitor?'),
|
2024-02-08 15:56:21 +08:00
|
|
|
okButtonProps: {
|
|
|
|
danger: true,
|
|
|
|
},
|
|
|
|
onOk: async () => {
|
|
|
|
await deleteMutation.mutateAsync({
|
|
|
|
workspaceId,
|
|
|
|
monitorId,
|
|
|
|
});
|
|
|
|
await trpcUtils.monitor.all.refetch();
|
2023-12-09 00:39:36 +08:00
|
|
|
|
2024-02-08 15:56:21 +08:00
|
|
|
navigate('/monitor', {
|
|
|
|
replace: true,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
});
|
2023-12-09 00:39:36 +08:00
|
|
|
});
|
|
|
|
|
2023-12-30 01:02:57 +08:00
|
|
|
const handleClearEvents = useEvent(() => {
|
|
|
|
Modal.confirm({
|
2024-02-12 00:10:38 +08:00
|
|
|
title: t('Warning'),
|
|
|
|
content: t('Are you sure want to delete all events for this monitor?'),
|
2023-12-30 01:02:57 +08:00
|
|
|
okButtonProps: {
|
|
|
|
danger: true,
|
|
|
|
},
|
|
|
|
onOk: async () => {
|
|
|
|
await clearEventsMutation.mutateAsync({
|
|
|
|
workspaceId,
|
|
|
|
monitorId,
|
|
|
|
});
|
|
|
|
trpcUtils.monitor.events.refetch({
|
|
|
|
workspaceId,
|
|
|
|
monitorId,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
const handleClearData = useEvent(() => {
|
|
|
|
Modal.confirm({
|
2024-02-12 00:10:38 +08:00
|
|
|
title: t('Warning'),
|
|
|
|
content: t(
|
|
|
|
'Are you sure want to delete all heartbeats for this monitor?'
|
|
|
|
),
|
2023-12-30 01:02:57 +08:00
|
|
|
okButtonProps: {
|
|
|
|
danger: true,
|
|
|
|
},
|
|
|
|
onOk: async () => {
|
|
|
|
await clearDataMutation.mutateAsync({
|
|
|
|
workspaceId,
|
|
|
|
monitorId,
|
|
|
|
});
|
|
|
|
trpcUtils.monitor.data.reset();
|
|
|
|
trpcUtils.monitor.recentData.reset();
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2023-10-19 23:22:39 +08:00
|
|
|
if (isInitialLoading) {
|
2023-10-10 00:09:39 +08:00
|
|
|
return <Loading />;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!monitorInfo) {
|
|
|
|
return <NotFoundTip />;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
2024-03-23 00:45:21 +08:00
|
|
|
<div className="h-full w-full overflow-auto">
|
2023-10-25 00:29:47 +08:00
|
|
|
<Spin spinning={isLoading}>
|
2023-10-28 16:01:11 +08:00
|
|
|
<Space className="w-full" direction="vertical">
|
2023-10-25 00:29:47 +08:00
|
|
|
<div className="flex justify-between">
|
|
|
|
<Space direction="vertical">
|
2024-03-23 00:45:21 +08:00
|
|
|
<div className="flex items-center gap-2 text-2xl">
|
2023-10-28 16:01:11 +08:00
|
|
|
<span>{monitorInfo.name}</span>
|
|
|
|
{monitorInfo.active === false && (
|
2024-03-23 00:45:21 +08:00
|
|
|
<div className="rounded-full bg-red-500 px-2 py-0.5 text-xs text-white">
|
2024-02-12 00:10:38 +08:00
|
|
|
{t('Stopped')}
|
2023-10-28 16:01:11 +08:00
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</div>
|
2023-10-10 00:09:39 +08:00
|
|
|
|
2023-10-25 00:29:47 +08:00
|
|
|
<div>
|
|
|
|
<ColorTag label={monitorInfo.type} />
|
|
|
|
<span>
|
|
|
|
{getMonitorLink(monitorInfo as any as MonitorInfoType)}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
</Space>
|
|
|
|
|
2024-03-23 00:45:21 +08:00
|
|
|
<div className="text-black text-opacity-75 dark:text-gray-200">
|
2024-02-12 00:10:38 +08:00
|
|
|
{t('Monitored for {{dayNum}} days', {
|
|
|
|
dayNum: dayjs().diff(dayjs(monitorInfo.createdAt), 'days'),
|
|
|
|
})}
|
2023-10-10 19:47:05 +08:00
|
|
|
</div>
|
2023-10-25 00:29:47 +08:00
|
|
|
</div>
|
2023-10-10 00:09:39 +08:00
|
|
|
|
2023-10-28 16:01:11 +08:00
|
|
|
<div className="flex gap-2">
|
2023-10-25 00:29:47 +08:00
|
|
|
<Button
|
|
|
|
type="primary"
|
|
|
|
onClick={() => {
|
|
|
|
navigate(`/monitor/${monitorInfo.id}/edit`);
|
|
|
|
}}
|
|
|
|
>
|
2024-02-12 00:10:38 +08:00
|
|
|
{t('Edit')}
|
2023-10-25 00:29:47 +08:00
|
|
|
</Button>
|
2023-10-28 16:01:11 +08:00
|
|
|
|
|
|
|
{monitorInfo.active ? (
|
|
|
|
<Button
|
|
|
|
loading={changeActiveMutation.isLoading}
|
|
|
|
onClick={handleStop}
|
|
|
|
>
|
2024-02-12 00:10:38 +08:00
|
|
|
{t('Stop')}
|
2023-10-28 16:01:11 +08:00
|
|
|
</Button>
|
|
|
|
) : (
|
|
|
|
<Button
|
|
|
|
loading={changeActiveMutation.isLoading}
|
|
|
|
onClick={handleStart}
|
|
|
|
>
|
2024-02-12 00:10:38 +08:00
|
|
|
{t('Start')}
|
2023-10-28 16:01:11 +08:00
|
|
|
</Button>
|
|
|
|
)}
|
2023-12-09 00:39:36 +08:00
|
|
|
|
2024-01-06 22:08:10 +08:00
|
|
|
<Dropdown
|
|
|
|
trigger={['click']}
|
|
|
|
placement="bottomRight"
|
|
|
|
menu={{
|
|
|
|
items: [
|
|
|
|
{
|
|
|
|
key: 'badge',
|
2024-02-12 00:10:38 +08:00
|
|
|
label: t('Show Badge'),
|
2024-01-06 22:08:10 +08:00
|
|
|
onClick: () => setShowBadge(true),
|
|
|
|
},
|
2024-02-08 15:56:21 +08:00
|
|
|
{
|
|
|
|
type: 'divider',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
key: 'delete',
|
2024-02-12 00:10:38 +08:00
|
|
|
label: t('Delete'),
|
2024-02-08 15:56:21 +08:00
|
|
|
danger: true,
|
|
|
|
onClick: handleDelete,
|
|
|
|
},
|
2024-01-06 22:08:10 +08:00
|
|
|
],
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<Button icon={<MoreOutlined />} />
|
|
|
|
</Dropdown>
|
|
|
|
|
|
|
|
<Modal
|
|
|
|
open={showBadge}
|
|
|
|
onCancel={() => setShowBadge(false)}
|
|
|
|
onOk={() => setShowBadge(false)}
|
|
|
|
destroyOnClose={true}
|
|
|
|
centered={true}
|
|
|
|
>
|
|
|
|
<MonitorBadgeView
|
|
|
|
workspaceId={workspaceId}
|
|
|
|
monitorId={monitorId}
|
2024-01-31 01:43:02 +08:00
|
|
|
monitorName={monitorInfo.name}
|
2024-01-06 22:08:10 +08:00
|
|
|
/>
|
|
|
|
</Modal>
|
2023-10-10 19:47:05 +08:00
|
|
|
</div>
|
2023-10-10 00:09:39 +08:00
|
|
|
|
2023-10-25 00:29:47 +08:00
|
|
|
<Card>
|
|
|
|
<MonitorHealthBar
|
2023-12-16 00:33:36 +08:00
|
|
|
workspaceId={workspaceId}
|
2023-10-25 00:29:47 +08:00
|
|
|
monitorId={monitorId}
|
2024-01-13 02:43:38 +08:00
|
|
|
monitorType={monitorInfo.type}
|
2023-10-25 00:29:47 +08:00
|
|
|
count={40}
|
|
|
|
size="large"
|
|
|
|
showCurrentStatus={true}
|
|
|
|
onBeatsItemUpdate={(items) => {
|
|
|
|
setCurrentResponse(last(items)?.value ?? 0);
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</Card>
|
2023-10-19 23:22:39 +08:00
|
|
|
|
2023-10-25 00:29:47 +08:00
|
|
|
<Card>
|
|
|
|
<MonitorDataMetrics
|
|
|
|
monitorId={monitorId}
|
|
|
|
monitorType={monitorInfo.type}
|
|
|
|
currectResponse={currectResponse}
|
|
|
|
/>
|
|
|
|
</Card>
|
2023-10-13 00:55:41 +08:00
|
|
|
|
2023-10-25 00:29:47 +08:00
|
|
|
<Card>
|
|
|
|
<MonitorDataChart monitorId={monitorId} />
|
|
|
|
</Card>
|
2023-10-10 19:47:05 +08:00
|
|
|
|
2023-12-30 01:02:57 +08:00
|
|
|
<div className="text-right">
|
|
|
|
<Dropdown
|
|
|
|
trigger={['click']}
|
|
|
|
menu={{
|
|
|
|
items: [
|
|
|
|
{
|
|
|
|
key: 'events',
|
2024-02-12 00:10:38 +08:00
|
|
|
label: t('Events'),
|
2023-12-30 01:02:57 +08:00
|
|
|
onClick: handleClearEvents,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
key: 'heartbeats',
|
2024-02-12 00:10:38 +08:00
|
|
|
label: t('Heartbeats'),
|
2023-12-30 01:02:57 +08:00
|
|
|
onClick: handleClearData,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<Button icon={<DeleteOutlined />} danger={true}>
|
2024-02-12 00:10:38 +08:00
|
|
|
{t('Clear Data')}
|
2023-12-30 01:02:57 +08:00
|
|
|
</Button>
|
|
|
|
</Dropdown>
|
|
|
|
</div>
|
|
|
|
|
2023-10-25 00:29:47 +08:00
|
|
|
<MonitorEventList monitorId={monitorId} />
|
|
|
|
</Space>
|
|
|
|
</Spin>
|
|
|
|
</div>
|
2023-10-10 00:09:39 +08:00
|
|
|
);
|
|
|
|
});
|
|
|
|
MonitorInfo.displayName = 'MonitorInfo';
|