diff --git a/.env.example b/.env.example index fd5148d..15c54b6 100644 --- a/.env.example +++ b/.env.example @@ -27,12 +27,6 @@ LinuxDo_CLIENT_SECRET= RESEND_API_KEY= RESEND_FROM_EMAIL="wrdo " -# Open Signup -NEXT_PUBLIC_OPEN_SIGNUP=1 - -# Enable subdomain apply, default is false(0). If set to 1, will enable subdomain apply -NEXT_PUBLIC_ENABLE_SUBDOMAIN_APPLY=0 - # Google Analytics NEXT_PUBLIC_GOOGLE_ID= diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml index 0f3147d..5a61bc1 100644 --- a/.github/workflows/docker-build-push.yml +++ b/.github/workflows/docker-build-push.yml @@ -4,8 +4,6 @@ on: push: branches: - main - - fix/docker - - i18n tags: - "v*.*.*" pull_request: diff --git a/README-zh.md b/README-zh.md index a088bca..bdfdc2d 100644 --- a/README-zh.md +++ b/README-zh.md @@ -73,7 +73,7 @@ WR.DO 是一个一站式网络工具平台,集成短链服务、临时邮箱 ### 使用 Vercel 部署 -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/oiov/wr.do.git&project-name=wrdo&env=DATABASE_URL&env=AUTH_SECRET&env=RESEND_API_KEY&env=NEXT_PUBLIC_EMAIL_R2_DOMAIN&env=NEXT_PUBLIC_OPEN_SIGNUP&env=GITHUB_TOKEN) +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/oiov/wr.do.git&project-name=wrdo&env=DATABASE_URL&env=AUTH_SECRET&env=RESEND_API_KEY&env=NEXT_PUBLIC_EMAIL_R2_DOMAIN&env=GITHUB_TOKEN) 记得填写必要的环境变量。 diff --git a/README.md b/README.md index f0f0603..5aa1f53 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ See step by step installation tutorial at [Quick Start for Developer](https://wr ### Deploy with Vercel -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/oiov/wr.do.git&project-name=wrdo&env=DATABASE_URL&env=AUTH_SECRET&env=RESEND_API_KEY&env=NEXT_PUBLIC_EMAIL_R2_DOMAIN&env=NEXT_PUBLIC_OPEN_SIGNUP&env=GITHUB_TOKEN) +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/oiov/wr.do.git&project-name=wrdo&env=DATABASE_URL&env=AUTH_SECRET&env=RESEND_API_KEY&env=NEXT_PUBLIC_EMAIL_R2_DOMAIN&env=GITHUB_TOKEN) Remember to fill in the necessary environment variables. diff --git a/app/(marketing)/layout.tsx b/app/(marketing)/layout.tsx index fb42356..671de1d 100644 --- a/app/(marketing)/layout.tsx +++ b/app/(marketing)/layout.tsx @@ -1,5 +1,6 @@ import { NavMobile } from "@/components/layout/mobile-nav"; import { NavBar } from "@/components/layout/navbar"; +import { Notification } from "@/components/layout/notification"; import { SiteFooter } from "@/components/layout/site-footer"; interface MarketingLayoutProps { @@ -11,6 +12,7 @@ export default function MarketingLayout({ children }: MarketingLayoutProps) {
+
{children}
diff --git a/app/(protected)/admin/page.tsx b/app/(protected)/admin/page.tsx index 338ec8f..1a7371d 100644 --- a/app/(protected)/admin/page.tsx +++ b/app/(protected)/admin/page.tsx @@ -1,6 +1,5 @@ import { Suspense } from "react"; import { redirect } from "next/navigation"; -import { useTranslations } from "next-intl"; import { getUserRecordCount } from "@/lib/dto/cloudflare-dns-record"; import { diff --git a/app/(protected)/admin/records/page.tsx b/app/(protected)/admin/records/page.tsx index 60a0f51..e9a61d3 100644 --- a/app/(protected)/admin/records/page.tsx +++ b/app/(protected)/admin/records/page.tsx @@ -7,7 +7,7 @@ import { DashboardHeader } from "@/components/dashboard/header"; import UserRecordsList from "../../dashboard/records/record-list"; export const metadata = constructMetadata({ - title: "DNS Records - WR.DO", + title: "DNS Records", description: "List and manage records.", }); diff --git a/app/(protected)/admin/system/app-configs.tsx b/app/(protected)/admin/system/app-configs.tsx new file mode 100644 index 0000000..eec27b0 --- /dev/null +++ b/app/(protected)/admin/system/app-configs.tsx @@ -0,0 +1,141 @@ +"use client"; + +import { useEffect, useState, useTransition } from "react"; +import { useTranslations } from "next-intl"; +import { toast } from "sonner"; +import useSWR from "swr"; + +import { fetcher } from "@/lib/utils"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { Skeleton } from "@/components/ui/skeleton"; +import { Switch } from "@/components/ui/switch"; +import { Textarea } from "@/components/ui/textarea"; +import { Icons } from "@/components/shared/icons"; +import { SkeletonSection } from "@/components/shared/section-skeleton"; + +export default function AppConfigs({}: {}) { + const [isPending, startTransition] = useTransition(); + + const { data: configs, isLoading } = useSWR>( + "/api/admin/configs", + fetcher, + ); + const [notification, setNotification] = useState(""); + + const t = useTranslations("Setting"); + + useEffect(() => { + if (!isLoading && configs?.system_notification) { + setNotification(configs.system_notification); + } + }, [configs, isLoading]); + + const handleChange = (value: any, key: string, type: string) => { + startTransition(async () => { + const res = await fetch("/api/admin/configs", { + method: "POST", + body: JSON.stringify({ key, value, type }), + }); + if (res.ok) { + toast.success("Updated!"); + } else { + toast.error("Failed!", { + description: await res.text(), + }); + } + }); + }; + + if (isLoading) { + return ( + <> + + + + ); + } + + return ( + + + {t("App Configs")} + + +
+
+
+

{t("User Registration")}

+

+ {t("Allow users to sign up")} +

+
+ {configs && ( + + handleChange(v, "enable_user_registration", "BOOLEAN") + } + /> + )} +
+
+
+

{t("Subdomain Apply Mode")}

+

+ {t( + "Enable subdomain apply mode, each submission requires administrator review", + )} +

+
+ {configs && ( + + handleChange(v, "enable_subdomain_apply", "BOOLEAN") + } + /> + )} +
+
+
+

{t("Notification")}

+

+ {t( + "Set system notification, this will be displayed in the header", + )} +

+
+ {configs && ( +
+