mirror of
https://github.com/Buriburizaem0n/nezha-dash-v1.git
synced 2026-09-21 02:30:15 +00:00
feat: refactor DashCommand to use useMemo for shortcuts and server commands
feat: optimize GlobalMap component with useMemo for country data processing feat: enhance ServerCard and ServerCardInline components with memoization feat: improve ServiceTracker component by processing service data with useMemo feat: add VirtualServerList component for efficient rendering of server lists refactor: update Servers page to utilize VirtualServerList for better performance test: add tests for DashCommand and GlobalMap components, including virtualization checks
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { ExclamationTriangleIcon } from "@heroicons/react/20/solid";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useMemo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { fetchService } from "@/lib/nezha-api";
|
||||
import type { NezhaServer, ServiceData } from "@/types/nezha-api";
|
||||
@@ -8,6 +9,32 @@ import { CycleTransferStatsCard } from "./CycleTransferStats";
|
||||
import { Loader } from "./loading/Loader";
|
||||
import ServiceTrackerClient from "./ServiceTrackerClient";
|
||||
|
||||
function processServiceData(serviceData: ServiceData) {
|
||||
const days = serviceData.up.map((up, index) => {
|
||||
const totalChecks = up + serviceData.down[index];
|
||||
const dailyUptime = totalChecks > 0 ? (up / totalChecks) * 100 : 0;
|
||||
return {
|
||||
completed: up > serviceData.down[index],
|
||||
date: new Date(Date.now() - (29 - index) * 24 * 60 * 60 * 1000),
|
||||
uptime: dailyUptime,
|
||||
delay: serviceData.delay[index] || 0,
|
||||
};
|
||||
});
|
||||
|
||||
const totalUp = serviceData.up.reduce((a, b) => a + b, 0);
|
||||
const totalChecks =
|
||||
serviceData.up.reduce((a, b) => a + b, 0) +
|
||||
serviceData.down.reduce((a, b) => a + b, 0);
|
||||
const uptime = totalChecks > 0 ? (totalUp / totalChecks) * 100 : 0;
|
||||
|
||||
const avgDelay =
|
||||
serviceData.delay.length > 0
|
||||
? serviceData.delay.reduce((a, b) => a + b, 0) / serviceData.delay.length
|
||||
: 0;
|
||||
|
||||
return { days, uptime, avgDelay };
|
||||
}
|
||||
|
||||
export function ServiceTracker({ serverList }: { serverList: NezhaServer[] }) {
|
||||
const { t } = useTranslation();
|
||||
const { data: serviceData, isLoading } = useQuery({
|
||||
@@ -18,32 +45,15 @@ export function ServiceTracker({ serverList }: { serverList: NezhaServer[] }) {
|
||||
refetchInterval: 10000,
|
||||
});
|
||||
|
||||
const processServiceData = (serviceData: ServiceData) => {
|
||||
const days = serviceData.up.map((up, index) => {
|
||||
const totalChecks = up + serviceData.down[index];
|
||||
const dailyUptime = totalChecks > 0 ? (up / totalChecks) * 100 : 0;
|
||||
return {
|
||||
completed: up > serviceData.down[index],
|
||||
date: new Date(Date.now() - (29 - index) * 24 * 60 * 60 * 1000),
|
||||
uptime: dailyUptime,
|
||||
delay: serviceData.delay[index] || 0,
|
||||
};
|
||||
});
|
||||
|
||||
const totalUp = serviceData.up.reduce((a, b) => a + b, 0);
|
||||
const totalChecks =
|
||||
serviceData.up.reduce((a, b) => a + b, 0) +
|
||||
serviceData.down.reduce((a, b) => a + b, 0);
|
||||
const uptime = totalChecks > 0 ? (totalUp / totalChecks) * 100 : 0;
|
||||
|
||||
const avgDelay =
|
||||
serviceData.delay.length > 0
|
||||
? serviceData.delay.reduce((a, b) => a + b, 0) /
|
||||
serviceData.delay.length
|
||||
: 0;
|
||||
|
||||
return { days, uptime, avgDelay };
|
||||
};
|
||||
const serviceSummaries = useMemo(() => {
|
||||
return Object.entries(serviceData?.data?.services ?? {}).map(
|
||||
([name, data]) => ({
|
||||
...processServiceData(data),
|
||||
name,
|
||||
title: data.service_name,
|
||||
}),
|
||||
);
|
||||
}, [serviceData?.data?.services]);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
@@ -76,23 +86,19 @@ export function ServiceTracker({ serverList }: { serverList: NezhaServer[] }) {
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{serviceData.data.services &&
|
||||
Object.keys(serviceData.data.services).length > 0 && (
|
||||
<section className="grid grid-cols-1 md:grid-cols-2 mt-4 gap-2 md:gap-4">
|
||||
{Object.entries(serviceData.data.services).map(([name, data]) => {
|
||||
const { days, uptime, avgDelay } = processServiceData(data);
|
||||
return (
|
||||
<ServiceTrackerClient
|
||||
key={name}
|
||||
days={days}
|
||||
title={data.service_name}
|
||||
uptime={uptime}
|
||||
avgDelay={avgDelay}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
)}
|
||||
{serviceSummaries.length > 0 && (
|
||||
<section className="grid grid-cols-1 md:grid-cols-2 mt-4 gap-2 md:gap-4">
|
||||
{serviceSummaries.map(({ avgDelay, days, name, title, uptime }) => (
|
||||
<ServiceTrackerClient
|
||||
key={name}
|
||||
days={days}
|
||||
title={title}
|
||||
uptime={uptime}
|
||||
avgDelay={avgDelay}
|
||||
/>
|
||||
))}
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user