tianji/src/client/components/monitor/MonitorInfo.tsx

320 lines
8.7 KiB
TypeScript
Raw Normal View History

import { Button, Card, Dropdown, Popconfirm, Space, Spin, Modal } from 'antd';
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';
import { MonitorHealthBar } from './MonitorHealthBar';
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';
import { MonitorEventList } from './MonitorEventList';
2023-10-28 16:01:11 +08:00
import { useEvent } from '../../hooks/useEvent';
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;
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,
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,
});
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 () => {
Modal.confirm({
2024-02-12 00:10:38 +08:00
title: t('Warning'),
content: t('Did you sure delete this monitor?'),
okButtonProps: {
danger: true,
},
onOk: async () => {
await deleteMutation.mutateAsync({
workspaceId,
monitorId,
});
await trpcUtils.monitor.all.refetch();
2023-12-09 00:39:36 +08:00
navigate('/monitor', {
replace: true,
});
},
});
2023-12-09 00:39:36 +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?'),
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?'
),
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 (
<div className="w-full h-full overflow-auto">
<Spin spinning={isLoading}>
2023-10-28 16:01:11 +08:00
<Space className="w-full" direction="vertical">
<div className="flex justify-between">
<Space direction="vertical">
2023-10-28 16:01:11 +08:00
<div className="text-2xl flex items-center gap-2">
<span>{monitorInfo.name}</span>
{monitorInfo.active === false && (
<div className="bg-red-500 rounded-full px-2 py-0.5 text-white text-xs">
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
<div>
<ColorTag label={monitorInfo.type} />
<span>
{getMonitorLink(monitorInfo as any as MonitorInfoType)}
</span>
</div>
</Space>
2023-12-21 01:30:48 +08:00
<div className="text-black dark:text-gray-200 text-opacity-75">
2024-02-12 00:10:38 +08:00
{t('Monitored for {{dayNum}} days', {
dayNum: dayjs().diff(dayjs(monitorInfo.createdAt), 'days'),
})}
</div>
</div>
2023-10-10 00:09:39 +08:00
2023-10-28 16:01:11 +08:00
<div className="flex gap-2">
<Button
type="primary"
onClick={() => {
navigate(`/monitor/${monitorInfo.id}/edit`);
}}
>
2024-02-12 00:10:38 +08:00
{t('Edit')}
</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),
},
{
type: 'divider',
},
{
key: 'delete',
2024-02-12 00:10:38 +08:00
label: t('Delete'),
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}
monitorName={monitorInfo.name}
2024-01-06 22:08:10 +08:00
/>
</Modal>
</div>
2023-10-10 00:09:39 +08:00
<Card>
<MonitorHealthBar
2023-12-16 00:33:36 +08:00
workspaceId={workspaceId}
monitorId={monitorId}
monitorType={monitorInfo.type}
count={40}
size="large"
showCurrentStatus={true}
onBeatsItemUpdate={(items) => {
setCurrentResponse(last(items)?.value ?? 0);
}}
/>
</Card>
2023-10-19 23:22:39 +08:00
<Card>
<MonitorDataMetrics
monitorId={monitorId}
monitorType={monitorInfo.type}
currectResponse={currectResponse}
/>
</Card>
<Card>
<MonitorDataChart monitorId={monitorId} />
</Card>
<div className="text-right">
<Dropdown
trigger={['click']}
menu={{
items: [
{
key: 'events',
2024-02-12 00:10:38 +08:00
label: t('Events'),
onClick: handleClearEvents,
},
{
key: 'heartbeats',
2024-02-12 00:10:38 +08:00
label: t('Heartbeats'),
onClick: handleClearData,
},
],
}}
>
<Button icon={<DeleteOutlined />} danger={true}>
2024-02-12 00:10:38 +08:00
{t('Clear Data')}
</Button>
</Dropdown>
</div>
<MonitorEventList monitorId={monitorId} />
</Space>
</Spin>
</div>
2023-10-10 00:09:39 +08:00
);
});
MonitorInfo.displayName = 'MonitorInfo';