mirror of
https://github.com/Buriburizaem0n/nezha-dash-v1.git
synced 2026-09-19 17:50:13 +00:00
refactor: optimize ServerDetail loading and update MapTooltip positioning logic
This commit is contained in:
+7
-25
@@ -8,7 +8,6 @@ import { DashCommand } from "./components/DashCommand";
|
|||||||
import ErrorBoundary from "./components/ErrorBoundary";
|
import ErrorBoundary from "./components/ErrorBoundary";
|
||||||
import Footer from "./components/Footer";
|
import Footer from "./components/Footer";
|
||||||
import Header, { RefreshToast } from "./components/Header";
|
import Header, { RefreshToast } from "./components/Header";
|
||||||
import { Skeleton } from "./components/ui/skeleton";
|
|
||||||
import { useBackground } from "./hooks/use-background";
|
import { useBackground } from "./hooks/use-background";
|
||||||
import { useTheme } from "./hooks/use-theme";
|
import { useTheme } from "./hooks/use-theme";
|
||||||
import { InjectContext } from "./lib/inject";
|
import { InjectContext } from "./lib/inject";
|
||||||
@@ -18,29 +17,8 @@ import ErrorPage from "./pages/ErrorPage";
|
|||||||
import Server from "./pages/Server";
|
import Server from "./pages/Server";
|
||||||
|
|
||||||
const NotFound = lazy(() => import("./pages/NotFound"));
|
const NotFound = lazy(() => import("./pages/NotFound"));
|
||||||
const ServerDetail = lazy(() => import("./pages/ServerDetail"));
|
const loadServerDetail = () => import("./pages/ServerDetail");
|
||||||
|
const ServerDetail = lazy(loadServerDetail);
|
||||||
function ServerDetailRouteFallback() {
|
|
||||||
return (
|
|
||||||
<div className="mx-auto w-full max-w-5xl px-0 flex flex-col gap-4">
|
|
||||||
<div>
|
|
||||||
<div className="flex flex-none items-center gap-0.5 text-xl">
|
|
||||||
<Skeleton className="h-5 w-5 rounded-[5px] bg-muted-foreground/10 animate-none" />
|
|
||||||
<Skeleton className="h-[20px] w-24 rounded-[5px] bg-muted-foreground/10 animate-none" />
|
|
||||||
</div>
|
|
||||||
<Skeleton className="flex flex-wrap gap-2 h-[81px] w-1/2 mt-3 rounded-[5px] bg-muted-foreground/10 animate-none" />
|
|
||||||
</div>
|
|
||||||
<section className="grid md:grid-cols-2 lg:grid-cols-3 grid-cols-1 gap-3">
|
|
||||||
<Skeleton className="h-[182px] w-full rounded-[5px] bg-muted-foreground/10 animate-none" />
|
|
||||||
<Skeleton className="h-[182px] w-full rounded-[5px] bg-muted-foreground/10 animate-none" />
|
|
||||||
<Skeleton className="h-[182px] w-full rounded-[5px] bg-muted-foreground/10 animate-none" />
|
|
||||||
<Skeleton className="h-[182px] w-full rounded-[5px] bg-muted-foreground/10 animate-none" />
|
|
||||||
<Skeleton className="h-[182px] w-full rounded-[5px] bg-muted-foreground/10 animate-none" />
|
|
||||||
<Skeleton className="h-[182px] w-full rounded-[5px] bg-muted-foreground/10 animate-none" />
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Route checker component
|
// Route checker component
|
||||||
const RouteChecker: React.FC = () => {
|
const RouteChecker: React.FC = () => {
|
||||||
@@ -59,6 +37,10 @@ const MainApp: React.FC = () => {
|
|||||||
const [isCustomCodeInjected, setIsCustomCodeInjected] = useState(false);
|
const [isCustomCodeInjected, setIsCustomCodeInjected] = useState(false);
|
||||||
const { backgroundImage: customBackgroundImage } = useBackground();
|
const { backgroundImage: customBackgroundImage } = useBackground();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadServerDetail();
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (settingData?.data?.config?.custom_code) {
|
if (settingData?.data?.config?.custom_code) {
|
||||||
InjectContext(settingData?.data?.config?.custom_code);
|
InjectContext(settingData?.data?.config?.custom_code);
|
||||||
@@ -137,7 +119,7 @@ const MainApp: React.FC = () => {
|
|||||||
<Route
|
<Route
|
||||||
path="/server/:id"
|
path="/server/:id"
|
||||||
element={
|
element={
|
||||||
<Suspense fallback={<ServerDetailRouteFallback />}>
|
<Suspense fallback={null}>
|
||||||
<ServerDetail />
|
<ServerDetail />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,14 +11,22 @@ const MapTooltip = memo(function MapTooltip() {
|
|||||||
|
|
||||||
if (!tooltipData) return null;
|
if (!tooltipData) return null;
|
||||||
|
|
||||||
|
const verticalPlacement =
|
||||||
|
tooltipData.centroid[1] < 120
|
||||||
|
? "translate(20%, 8px)"
|
||||||
|
: tooltipData.centroid[1] > 380
|
||||||
|
? "translate(20%, calc(-100% - 8px))"
|
||||||
|
: "translate(20%, -50%)";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="tooltip-animate absolute hidden lg:block bg-white dark:bg-neutral-800 px-2 py-1 rounded shadow-lg text-sm dark:border dark:border-neutral-700 z-50"
|
className="tooltip-animate absolute hidden lg:block bg-white dark:bg-neutral-800 px-2 py-1 rounded shadow-lg text-sm dark:border dark:border-neutral-700 z-50"
|
||||||
|
data-testid="map-tooltip"
|
||||||
key={tooltipData.country}
|
key={tooltipData.country}
|
||||||
style={{
|
style={{
|
||||||
left: tooltipData.centroid[0],
|
left: tooltipData.centroid[0],
|
||||||
top: tooltipData.centroid[1],
|
top: tooltipData.centroid[1],
|
||||||
transform: "translate(20%, -50%)",
|
transform: verticalPlacement,
|
||||||
}}
|
}}
|
||||||
onMouseEnter={(e) => {
|
onMouseEnter={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|||||||
@@ -161,6 +161,9 @@ describe("MapTooltip", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(await screen.findByText("Mainland China")).toBeInTheDocument();
|
expect(await screen.findByText("Mainland China")).toBeInTheDocument();
|
||||||
|
expect(screen.getByTestId("map-tooltip")).toHaveStyle({
|
||||||
|
transform: "translate(20%, 8px)",
|
||||||
|
});
|
||||||
expect(screen.getByText("2 map.Servers")).toBeInTheDocument();
|
expect(screen.getByText("2 map.Servers")).toBeInTheDocument();
|
||||||
await user.click(screen.getByRole("button", { name: /edge-2/ }));
|
await user.click(screen.getByRole("button", { name: /edge-2/ }));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user