mirror of
https://github.com/hamster1963/nezha-dash.git
synced 2025-04-24 21:10:45 +08:00
Merge branch 'main' into cloudflare
This commit is contained in:
commit
768fbd6c8e
7
.eslintrc.json
Normal file
7
.eslintrc.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": ["next/core-web-vitals", "next/typescript"],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@next/next/no-img-element": "off"
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
|
||||
import NetworkChartLoading from "@/app/(main)/ClientComponents/NetworkChartLoading";
|
||||
import { NezhaAPIMonitor, ServerMonitorChart } from "@/app/types/nezha-api";
|
||||
import { BackIcon } from "@/components/Icon";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@ -21,9 +20,7 @@ import {
|
||||
import getEnv from "@/lib/env-entry";
|
||||
import { formatTime, nezhaFetcher } from "@/lib/utils";
|
||||
import { formatRelativeTime } from "@/lib/utils";
|
||||
import { useLocale } from "next-intl";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useRouter } from "next/navigation";
|
||||
import * as React from "react";
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts";
|
||||
|
@ -8,7 +8,7 @@ import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import getEnv from "@/lib/env-entry";
|
||||
import { cn, formatBytes, nezhaFetcher } from "@/lib/utils";
|
||||
import { useLocale, useTranslations } from "next-intl";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import useSWR from "swr";
|
||||
@ -51,7 +51,6 @@ export default function ServerDetailClient({
|
||||
nezhaFetcher,
|
||||
);
|
||||
const fallbackData = allFallbackData?.result?.find(
|
||||
// @ts-ignore
|
||||
(item) => item.id === server_id,
|
||||
);
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { BackIcon } from "@/components/Icon";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { useLocale } from "next-intl";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
export function ServerDetailChartLoading() {
|
||||
|
@ -5,12 +5,12 @@ import ServerDetailChartClient from "@/app/(main)/ClientComponents/ServerDetailC
|
||||
import ServerDetailClient from "@/app/(main)/ClientComponents/ServerDetailClient";
|
||||
import TabSwitch from "@/components/TabSwitch";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { useState } from "react";
|
||||
import { use, useState } from "react";
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
export default function Page({ params }: { params: { id: string } }) {
|
||||
|
||||
export default function Page(props: { params: Promise<{ id: string }> }) {
|
||||
const params = use(props.params);
|
||||
const tabs = ["Detail", "Network"];
|
||||
const [currentTab, setCurrentTab] = useState(tabs[0]);
|
||||
return (
|
||||
|
@ -61,8 +61,8 @@ function Header() {
|
||||
}
|
||||
|
||||
// https://github.com/streamich/react-use/blob/master/src/useInterval.ts
|
||||
const useInterval = (callback: Function, delay?: number | null) => {
|
||||
const savedCallback = useRef<Function>(() => {});
|
||||
const useInterval = (callback: () => void, delay: number | null) => {
|
||||
const savedCallback = useRef<() => void>(() => {});
|
||||
useEffect(() => {
|
||||
savedCallback.current = callback;
|
||||
});
|
||||
|
@ -2,14 +2,21 @@ import { auth } from "@/auth";
|
||||
import getEnv from "@/lib/env-entry";
|
||||
import { GetServerDetail } from "@/lib/serverFetch";
|
||||
import { redirect } from "next/navigation";
|
||||
import { NextResponse } from "next/server";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const GET = auth(async function GET(req) {
|
||||
if (!req.auth && getEnv("SitePassword")) {
|
||||
interface ResError extends Error {
|
||||
statusCode: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const session = await auth();
|
||||
|
||||
if (!session && getEnv("SitePassword")) {
|
||||
redirect("/");
|
||||
}
|
||||
|
||||
@ -35,11 +42,10 @@ export const GET = auth(async function GET(req) {
|
||||
const detailData = await GetServerDetail({ server_id: serverIdNum });
|
||||
return NextResponse.json(detailData, { status: 200 });
|
||||
} catch (error) {
|
||||
console.error("Error in GET handler:", error);
|
||||
// @ts-ignore
|
||||
const statusCode = error.statusCode || 500;
|
||||
// @ts-ignore
|
||||
const message = error.message || "Internal Server Error";
|
||||
const err = error as ResError;
|
||||
console.error("Error in GET handler:", err);
|
||||
const statusCode = err.statusCode || 500;
|
||||
const message = err.message || "Internal Server Error";
|
||||
return NextResponse.json({ error: message }, { status: statusCode });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -2,14 +2,21 @@ import { auth } from "@/auth";
|
||||
import getEnv from "@/lib/env-entry";
|
||||
import { GetServerMonitor } from "@/lib/serverFetch";
|
||||
import { redirect } from "next/navigation";
|
||||
import { NextResponse } from "next/server";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
export const runtime = "edge";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const GET = auth(async function GET(req) {
|
||||
if (!req.auth && getEnv("SitePassword")) {
|
||||
interface ResError extends Error {
|
||||
statusCode: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const session = await auth();
|
||||
|
||||
if (!session && getEnv("SitePassword")) {
|
||||
redirect("/");
|
||||
}
|
||||
|
||||
@ -36,11 +43,10 @@ export const GET = auth(async function GET(req) {
|
||||
});
|
||||
return NextResponse.json(monitorData, { status: 200 });
|
||||
} catch (error) {
|
||||
console.error("Error in GET handler:", error);
|
||||
// @ts-ignore
|
||||
const statusCode = error.statusCode || 500;
|
||||
// @ts-ignore
|
||||
const message = error.message || "Internal Server Error";
|
||||
const err = error as ResError;
|
||||
console.error("Error in GET handler:", err);
|
||||
const statusCode = err.statusCode || 500;
|
||||
const message = err.message || "Internal Server Error";
|
||||
return NextResponse.json({ error: message }, { status: statusCode });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -10,8 +10,15 @@ export const runtime = "edge";
|
||||
|
||||
|
||||
|
||||
export const GET = auth(async function GET(req) {
|
||||
if (!req.auth && getEnv("SitePassword")) {
|
||||
interface ResError extends Error {
|
||||
statusCode: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
const session = await auth();
|
||||
|
||||
if (!session && getEnv("SitePassword")) {
|
||||
redirect("/");
|
||||
}
|
||||
|
||||
@ -19,11 +26,10 @@ export const GET = auth(async function GET(req) {
|
||||
const data = await GetNezhaData();
|
||||
return NextResponse.json(data, { status: 200 });
|
||||
} catch (error) {
|
||||
console.error("Error in GET handler:", error);
|
||||
// @ts-ignore
|
||||
const statusCode = error.statusCode || 500;
|
||||
// @ts-ignore
|
||||
const message = error.message || "Internal Server Error";
|
||||
const err = error as ResError;
|
||||
console.error("Error in GET handler:", err);
|
||||
const statusCode = err.statusCode || 500;
|
||||
const message = err.message || "Internal Server Error";
|
||||
return NextResponse.json({ error: message }, { status: statusCode });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
} from "@/components/ui/popover";
|
||||
import getEnv from "@/lib/env-entry";
|
||||
import { cn, formatBytes, formatNezhaInfo } from "@/lib/utils";
|
||||
import { useLocale, useTranslations } from "next-intl";
|
||||
import { useTranslations } from "next-intl";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
@ -21,7 +21,7 @@ export default function ServerCard({
|
||||
}) {
|
||||
const t = useTranslations("ServerCard");
|
||||
const router = useRouter();
|
||||
const { id, name, country_code, online, cpu, up, down, mem, stg, ...props } =
|
||||
const { id, name, country_code, online, cpu, up, down, mem, stg } =
|
||||
formatNezhaInfo(serverInfo);
|
||||
|
||||
const showFlag = getEnv("NEXT_PUBLIC_ShowFlag") === "true";
|
||||
|
@ -3,7 +3,7 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { motion } from "framer-motion";
|
||||
import { useTranslations } from "next-intl";
|
||||
import React, { createRef, useEffect, useRef, useState } from "react";
|
||||
import React, { createRef, useEffect, useRef } from "react";
|
||||
|
||||
export default function Switch({
|
||||
allTag,
|
||||
@ -23,7 +23,7 @@ export default function Switch({
|
||||
if (savedTag && allTag.includes(savedTag)) {
|
||||
onTagChange(savedTag);
|
||||
}
|
||||
}, [allTag]);
|
||||
}, [allTag, onTagChange]);
|
||||
|
||||
useEffect(() => {
|
||||
const container = scrollRef.current;
|
||||
@ -53,7 +53,7 @@ export default function Switch({
|
||||
inline: "center",
|
||||
});
|
||||
}
|
||||
}, [nowTag]);
|
||||
}, [nowTag, allTag]);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -8,7 +8,7 @@ import * as RechartsPrimitive from "recharts";
|
||||
const THEMES = { light: "", dark: ".dark" } as const;
|
||||
|
||||
export type ChartConfig = {
|
||||
[k in string]: {
|
||||
[k: string]: {
|
||||
label?: React.ReactNode;
|
||||
icon?: React.ComponentType;
|
||||
} & (
|
||||
@ -68,7 +68,7 @@ ChartContainer.displayName = "Chart";
|
||||
|
||||
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
|
||||
const colorConfig = Object.entries(config).filter(
|
||||
([_, config]) => config.theme || config.color,
|
||||
([, config]) => config.theme || config.color,
|
||||
);
|
||||
|
||||
if (!colorConfig.length) {
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import * as React from "react";
|
||||
|
||||
export interface InputProps
|
||||
extends React.InputHTMLAttributes<HTMLInputElement> {}
|
||||
export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;
|
||||
|
||||
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
({ className, type, ...props }, ref) => {
|
||||
|
@ -6,9 +6,12 @@ import { cookies } from "next/headers";
|
||||
const COOKIE_NAME = "NEXT_LOCALE";
|
||||
|
||||
export async function getUserLocale() {
|
||||
return cookies().get(COOKIE_NAME)?.value || (getEnv("DefaultLocale") ?? "en");
|
||||
return (
|
||||
(await cookies()).get(COOKIE_NAME)?.value ||
|
||||
(getEnv("DefaultLocale") ?? "en")
|
||||
);
|
||||
}
|
||||
|
||||
export async function setUserLocale(locale: string) {
|
||||
cookies().set(COOKIE_NAME, locale);
|
||||
(await cookies()).set(COOKIE_NAME, locale);
|
||||
}
|
||||
|
@ -76,9 +76,9 @@ export const nezhaFetcher = async (url: string) => {
|
||||
|
||||
if (!res.ok) {
|
||||
const error = new Error("An error occurred while fetching the data.");
|
||||
// @ts-ignore
|
||||
// @ts-expect-error - res.json() returns a Promise<any>
|
||||
error.info = await res.json();
|
||||
// @ts-ignore
|
||||
// @ts-expect-error - res.status is a number
|
||||
error.status = res.status;
|
||||
throw error;
|
||||
}
|
||||
|
39
package.json
39
package.json
@ -22,46 +22,53 @@
|
||||
"@radix-ui/react-tooltip": "^1.1.3",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/luxon": "^3.4.2",
|
||||
"@typescript-eslint/eslint-plugin": "^8.10.0",
|
||||
"caniuse-lite": "^1.0.30001669",
|
||||
"@typescript-eslint/eslint-plugin": "^8.12.2",
|
||||
"caniuse-lite": "^1.0.30001674",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"country-flag-icons": "^1.5.13",
|
||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||
"flag-icons": "^7.2.3",
|
||||
"framer-motion": "^11.11.9",
|
||||
"framer-motion": "^12.0.0-alpha.1",
|
||||
"lucide-react": "^0.451.0",
|
||||
"luxon": "^3.5.0",
|
||||
"next": "^14.2.15",
|
||||
"next": "15.0.2",
|
||||
"next-auth": "^5.0.0-beta.25",
|
||||
"next-intl": "^3.21.1",
|
||||
"next-intl": "^3.23.5",
|
||||
"next-runtime-env": "^3.2.2",
|
||||
"next-themes": "^0.3.0",
|
||||
"react": "^18.3.1",
|
||||
"react": "19.0.0-rc-02c0e824-20241028",
|
||||
"react-device-detect": "^2.2.3",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-dom": "19.0.0-rc-02c0e824-20241028",
|
||||
"react-intersection-observer": "^9.13.1",
|
||||
"react-wrap-balancer": "^1.1.1",
|
||||
"recharts": "2.12.7",
|
||||
"recharts": "2.13.1",
|
||||
"sharp": "^0.33.5",
|
||||
"swr": "^2.2.6-beta.4",
|
||||
"tailwind-merge": "^2.5.4",
|
||||
"tailwindcss-animate": "^1.0.7"
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"typescript-eslint": "^8.12.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint-plugin-turbo": "^2.2.1",
|
||||
"eslint-plugin-turbo": "^2.2.3",
|
||||
"eslint-plugin-unused-imports": "^4.1.4",
|
||||
"@next/bundle-analyzer": "^14.2.15",
|
||||
"@types/node": "^22.7.7",
|
||||
"@types/react": "^18.3.11",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@next/bundle-analyzer": "15.0.2",
|
||||
"@types/node": "^22.8.4",
|
||||
"@types/react": "npm:types-react@19.0.0-rc.1",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"eslint": "^9.13.0",
|
||||
"eslint-config-next": "^14.2.15",
|
||||
"eslint-config-next": "15.0.2",
|
||||
"postcss": "^8.4.47",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-tailwindcss": "^0.6.8",
|
||||
"tailwindcss": "^3.4.14",
|
||||
"typescript": "^5.6.3"
|
||||
}
|
||||
},
|
||||
"overrides": {
|
||||
"@types/react": "npm:types-react@19.0.0-rc.1",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
|
||||
"react-is": "^19.0.0-rc-69d4b800-20241021"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "HomeDash",
|
||||
"short_name": "HomeDash PWA App",
|
||||
"name": "NezhaDash PWA App",
|
||||
"short_name": "NezhaDash",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
|
Loading…
Reference in New Issue
Block a user