feat(v2): add monitor health bar in list
This commit is contained in:
parent
d97c671913
commit
539f24244a
@ -88,7 +88,7 @@ export const CommonList: React.FC<CommonListProps> = React.memo((props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-muted-foreground line-clamp-2 text-xs">
|
<div className="text-muted-foreground line-clamp-2 w-full text-xs">
|
||||||
{item.content}
|
{item.content}
|
||||||
</div>
|
</div>
|
||||||
{Array.isArray(item.tags) && item.tags.length > 0 ? (
|
{Array.isArray(item.tags) && item.tags.length > 0 ? (
|
||||||
|
@ -8,6 +8,7 @@ import { useWatch } from '../../hooks/useWatch';
|
|||||||
import { getMonitorProvider, getProviderDisplay } from './provider';
|
import { getMonitorProvider, getProviderDisplay } from './provider';
|
||||||
import { MonitorProvider } from './provider/types';
|
import { MonitorProvider } from './provider/types';
|
||||||
import { useTranslation } from '@i18next-toolkit/react';
|
import { useTranslation } from '@i18next-toolkit/react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
|
||||||
interface MonitorHealthBarProps {
|
interface MonitorHealthBarProps {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
@ -16,6 +17,7 @@ interface MonitorHealthBarProps {
|
|||||||
count?: number;
|
count?: number;
|
||||||
size?: HealthBarProps['size'];
|
size?: HealthBarProps['size'];
|
||||||
showCurrentStatus?: boolean;
|
showCurrentStatus?: boolean;
|
||||||
|
showPercent?: boolean;
|
||||||
onBeatsItemUpdate?: (
|
onBeatsItemUpdate?: (
|
||||||
items: ({ value: number; createdAt: string | Date } | null)[]
|
items: ({ value: number; createdAt: string | Date } | null)[]
|
||||||
) => void;
|
) => void;
|
||||||
@ -26,9 +28,10 @@ export const MonitorHealthBar: React.FC<MonitorHealthBarProps> = React.memo(
|
|||||||
const {
|
const {
|
||||||
workspaceId,
|
workspaceId,
|
||||||
monitorId,
|
monitorId,
|
||||||
size,
|
size = 'small',
|
||||||
count = 20,
|
count = 20,
|
||||||
showCurrentStatus = false,
|
showCurrentStatus = false,
|
||||||
|
showPercent = false,
|
||||||
} = props;
|
} = props;
|
||||||
const { data: recent = [] } = trpc.monitor.recentData.useQuery({
|
const { data: recent = [] } = trpc.monitor.recentData.useQuery({
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -82,26 +85,78 @@ export const MonitorHealthBar: React.FC<MonitorHealthBarProps> = React.memo(
|
|||||||
});
|
});
|
||||||
}, [items, provider]);
|
}, [items, provider]);
|
||||||
|
|
||||||
|
const upPercent = useMemo(() => {
|
||||||
|
let up = 0;
|
||||||
|
beats.forEach((b) => {
|
||||||
|
if (!b) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b.status === 'health') {
|
||||||
|
up++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return parseFloat(((up / beats.length) * 100).toFixed(1));
|
||||||
|
}, [beats]);
|
||||||
|
|
||||||
useWatch([items], () => {
|
useWatch([items], () => {
|
||||||
props.onBeatsItemUpdate?.(items);
|
props.onBeatsItemUpdate?.(items);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center">
|
||||||
<HealthBar size={size} beats={beats} />
|
{showPercent && (
|
||||||
|
<span
|
||||||
|
className={clsx(
|
||||||
|
'mr-2 inline-block min-w-[62px] rounded-full p-0.5 text-center text-white',
|
||||||
|
upPercent === 100 ? 'bg-green-400' : 'bg-amber-400',
|
||||||
|
{
|
||||||
|
'min-w-[50px] text-sm': size === 'small',
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{upPercent}%
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="flex-1">
|
||||||
|
<HealthBar size={size} beats={beats} />
|
||||||
|
</div>
|
||||||
|
|
||||||
{showCurrentStatus && (
|
{showCurrentStatus && (
|
||||||
<>
|
<>
|
||||||
{last(beats)?.status === 'health' ? (
|
{last(beats)?.status === 'health' ? (
|
||||||
<div className="rounded-full bg-green-500 px-4 py-1 text-lg font-bold text-white">
|
<div
|
||||||
|
className={clsx(
|
||||||
|
'rounded-full bg-green-500 px-4 py-1 text-lg font-bold text-white',
|
||||||
|
{
|
||||||
|
'text-sm': size === 'small',
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
>
|
||||||
{t('UP')}
|
{t('UP')}
|
||||||
</div>
|
</div>
|
||||||
) : last(beats)?.status === 'error' ? (
|
) : last(beats)?.status === 'error' ? (
|
||||||
<div className="rounded-full bg-red-600 px-4 py-1 text-lg font-bold text-white">
|
<div
|
||||||
|
className={clsx(
|
||||||
|
'rounded-full bg-red-600 px-4 py-1 text-lg font-bold text-white',
|
||||||
|
{
|
||||||
|
'text-sm': size === 'small',
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
>
|
||||||
{t('DOWN')}
|
{t('DOWN')}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="rounded-full bg-gray-400 px-4 py-1 text-lg font-bold text-white">
|
<div
|
||||||
|
className={clsx(
|
||||||
|
'rounded-full bg-gray-400 px-4 py-1 text-lg font-bold text-white',
|
||||||
|
{
|
||||||
|
'text-sm': size === 'small',
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
>
|
||||||
{t('NONE')}
|
{t('NONE')}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -85,6 +85,7 @@ export const MonitorListItem: React.FC<{
|
|||||||
{upPercent}%
|
{upPercent}%
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex-1 pl-2">
|
<div className="flex-1 pl-2">
|
||||||
<div className="text-base">{monitorName}</div>
|
<div className="text-base">{monitorName}</div>
|
||||||
{/* <div>
|
{/* <div>
|
||||||
|
@ -2,6 +2,7 @@ import { trpc } from '@/api/trpc';
|
|||||||
import { CommonHeader } from '@/components/CommonHeader';
|
import { CommonHeader } from '@/components/CommonHeader';
|
||||||
import { CommonList } from '@/components/CommonList';
|
import { CommonList } from '@/components/CommonList';
|
||||||
import { CommonWrapper } from '@/components/CommonWrapper';
|
import { CommonWrapper } from '@/components/CommonWrapper';
|
||||||
|
import { MonitorHealthBar } from '@/components/monitor/MonitorHealthBar';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { useDataReady } from '@/hooks/useDataReady';
|
import { useDataReady } from '@/hooks/useDataReady';
|
||||||
import { useEvent } from '@/hooks/useEvent';
|
import { useEvent } from '@/hooks/useEvent';
|
||||||
@ -35,6 +36,14 @@ function MonitorComponent() {
|
|||||||
const items = data.map((item) => ({
|
const items = data.map((item) => ({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
title: item.name,
|
title: item.name,
|
||||||
|
content: (
|
||||||
|
<MonitorHealthBar
|
||||||
|
workspaceId={workspaceId}
|
||||||
|
monitorId={item.id}
|
||||||
|
showPercent={true}
|
||||||
|
showCurrentStatus={true}
|
||||||
|
/>
|
||||||
|
),
|
||||||
tags: [item.type],
|
tags: [item.type],
|
||||||
href: `/monitor/${item.id}`,
|
href: `/monitor/${item.id}`,
|
||||||
}));
|
}));
|
||||||
|
Loading…
Reference in New Issue
Block a user