From 5428f74f0905e8ee1b6073c5aad53da1ab81120b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Czeyir=20=C4=B0smail=20Bahtiyar?= <76667836+uzeyirrr@users.noreply.github.com> Date: Wed, 28 Jan 2026 11:08:54 +0300 Subject: [PATCH 1/2] whitelabel --- .../dashboard/settings/whitelabel-form.tsx | 218 ++++++++++++++++++ .../components/layouts/onboarding-layout.tsx | 16 +- apps/dokploy/components/layouts/side.tsx | 10 + .../pages/dashboard/settings/whitelabel.tsx | 78 +++++++ apps/dokploy/pages/index.tsx | 36 ++- apps/dokploy/public/locales/en/settings.json | 14 +- apps/dokploy/public/locales/tr/settings.json | 14 +- apps/dokploy/server/api/routers/settings.ts | 19 ++ .../src/db/schema/web-server-settings.ts | 7 + 9 files changed, 395 insertions(+), 17 deletions(-) create mode 100644 apps/dokploy/components/dashboard/settings/whitelabel-form.tsx create mode 100644 apps/dokploy/pages/dashboard/settings/whitelabel.tsx diff --git a/apps/dokploy/components/dashboard/settings/whitelabel-form.tsx b/apps/dokploy/components/dashboard/settings/whitelabel-form.tsx new file mode 100644 index 0000000000..42183d612e --- /dev/null +++ b/apps/dokploy/components/dashboard/settings/whitelabel-form.tsx @@ -0,0 +1,218 @@ +"use client"; + +import { ImageIcon, Loader2 } from "lucide-react"; +import { useTranslation } from "next-i18next"; +import { useEffect } from "react"; +import { useForm } from "react-hook-form"; +import { toast } from "sonner"; +import { z } from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { AlertBlock } from "@/components/shared/alert-block"; +import { Button } from "@/components/ui/button"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { api } from "@/utils/api"; + +const whitelabelSchema = z.object({ + whitelabelLogoUrl: z.string().url("Geçerli bir URL girin").optional().nullable(), + whitelabelBrandName: z.string().optional().nullable(), + whitelabelTagline: z.string().optional().nullable(), +}); + +type WhitelabelForm = z.infer; + +export const WhitelabelForm = () => { + const { data: isCloud } = api.settings.isCloud.useQuery(); + const { data: settings, refetch, isLoading } = api.settings.getWebServerSettings.useQuery(undefined, { + enabled: !isCloud, + }); + const { mutateAsync, isError, error, isLoading: isUpdating } = api.settings.updateWhitelabel.useMutation(); + const { t } = useTranslation("settings"); + + const form = useForm({ + resolver: zodResolver(whitelabelSchema), + defaultValues: { + whitelabelLogoUrl: null, + whitelabelBrandName: null, + whitelabelTagline: null, + }, + }); + + useEffect(() => { + if (settings) { + form.reset({ + whitelabelLogoUrl: settings.whitelabelLogoUrl || null, + whitelabelBrandName: settings.whitelabelBrandName || null, + whitelabelTagline: settings.whitelabelTagline || null, + }); + } + }, [settings, form]); + + const onSubmit = async (data: WhitelabelForm) => { + try { + await mutateAsync({ + whitelabelLogoUrl: data.whitelabelLogoUrl || null, + whitelabelBrandName: data.whitelabelBrandName || null, + whitelabelTagline: data.whitelabelTagline || null, + }); + toast.success(t("settings.whitelabel.success")); + await refetch(); + } catch (error) { + toast.error(t("settings.whitelabel.error")); + } + }; + + if (isCloud) { + return ( +
+ +
+ + + + {t("settings.whitelabel.title")} + + + {t("settings.whitelabel.description")} + + + + + Whitelabel özelliği sadece self-hosted kurulumlarda kullanılabilir. + + +
+
+
+ ); + } + + return ( +
+ +
+ + + + {t("settings.whitelabel.title")} + + + {t("settings.whitelabel.description")} + + + + + {isError && {error?.message}} + {isLoading ? ( +
+ {t("settings.common.loading")} + +
+ ) : ( +
+ + ( + + + {t("settings.whitelabel.logoUrl")} + + + + + + {t("settings.whitelabel.logoUrlDescription")} + + + + )} + /> + + ( + + + {t("settings.whitelabel.brandName")} + + + + + + {t("settings.whitelabel.brandNameDescription")} + + + + )} + /> + + ( + + + {t("settings.whitelabel.tagline")} + + + + + + {t("settings.whitelabel.taglineDescription")} + + + + )} + /> + +
+ +
+ + + )} +
+
+
+
+ ); +}; diff --git a/apps/dokploy/components/layouts/onboarding-layout.tsx b/apps/dokploy/components/layouts/onboarding-layout.tsx index fff5413e06..96c1b57389 100644 --- a/apps/dokploy/components/layouts/onboarding-layout.tsx +++ b/apps/dokploy/components/layouts/onboarding-layout.tsx @@ -4,11 +4,20 @@ import { cn } from "@/lib/utils"; import { GithubIcon } from "../icons/data-tools-icons"; import { Logo } from "../shared/logo"; import { Button } from "../ui/button"; +import { api } from "@/utils/api"; interface Props { children: React.ReactNode; } export const OnboardingLayout = ({ children }: Props) => { + const { data: settings } = api.settings.getWebServerSettings.useQuery(undefined, { + refetchOnWindowFocus: false, + }); + + const brandName = settings?.whitelabelBrandName || "Dokploy"; + const tagline = settings?.whitelabelTagline || "The Open Source alternative to Netlify, Vercel, Heroku."; + const logoUrl = settings?.whitelabelLogoUrl; + return (
@@ -17,14 +26,13 @@ export const OnboardingLayout = ({ children }: Props) => { href="https://dokploy.com" className="relative z-20 flex items-center text-lg font-medium gap-4 text-primary" > - - Dokploy + + {brandName}

- “The Open Source alternative to Netlify, Vercel, - Heroku.” + “{tagline}”

diff --git a/apps/dokploy/components/layouts/side.tsx b/apps/dokploy/components/layouts/side.tsx index d256a51196..20c5c92876 100644 --- a/apps/dokploy/components/layouts/side.tsx +++ b/apps/dokploy/components/layouts/side.tsx @@ -18,6 +18,7 @@ import { Forward, GalleryVerticalEnd, GitBranch, + ImageIcon, KeyRound, Loader2, type LucideIcon, @@ -396,6 +397,15 @@ const MENU: Menu = { // Only enabled for admins in cloud environments isEnabled: ({ auth, isCloud }) => !!(auth?.role === "owner" && isCloud), }, + { + isSingle: true, + title: "Whitelabel", + url: "/dashboard/settings/whitelabel", + icon: ImageIcon, + // Only enabled for admins in non-cloud environments + isEnabled: ({ auth, isCloud }) => + !!((auth?.role === "owner" || auth?.role === "admin") && !isCloud), + }, ], help: [ diff --git a/apps/dokploy/pages/dashboard/settings/whitelabel.tsx b/apps/dokploy/pages/dashboard/settings/whitelabel.tsx new file mode 100644 index 0000000000..f34581a0e9 --- /dev/null +++ b/apps/dokploy/pages/dashboard/settings/whitelabel.tsx @@ -0,0 +1,78 @@ +import { createServerSideHelpers } from "@trpc/react-query/server"; +import type { GetServerSidePropsContext } from "next"; +import type { ReactElement } from "react"; +import superjson from "superjson"; +import { WhitelabelForm } from "@/components/dashboard/settings/whitelabel-form"; +import { DashboardLayout } from "@/components/layouts/dashboard-layout"; +import { appRouter } from "@/server/api/root"; +import { validateRequest } from "@dokploy/server/lib/auth"; +import { getLocale, serverSideTranslations } from "@/utils/i18n"; +import { IS_CLOUD } from "@dokploy/server"; + +const Page = () => { + return ( +
+ +
+ ); +}; + +export default Page; + +Page.getLayout = (page: ReactElement) => { + return {page}; +}; + +export async function getServerSideProps( + ctx: GetServerSidePropsContext, +) { + const { req, res } = ctx; + const locale = await getLocale(req.cookies); + + if (IS_CLOUD) { + return { + redirect: { + permanent: true, + destination: "/dashboard/projects", + }, + }; + } + + const { user, session } = await validateRequest(ctx.req); + if (!user) { + return { + redirect: { + permanent: true, + destination: "/", + }, + }; + } + if (user.role === "member") { + return { + redirect: { + permanent: true, + destination: "/dashboard/settings/profile", + }, + }; + } + + const helpers = createServerSideHelpers({ + router: appRouter, + ctx: { + req: req as any, + res: res as any, + db: null as any, + session: session as any, + user: user as any, + }, + transformer: superjson, + }); + await helpers.settings.getWebServerSettings.prefetch(); + + return { + props: { + trpcState: helpers.dehydrate(), + ...(await serverSideTranslations(locale, ["settings"])), + }, + }; +}; diff --git a/apps/dokploy/pages/index.tsx b/apps/dokploy/pages/index.tsx index 8127b41fd6..ee3934aa61 100644 --- a/apps/dokploy/pages/index.tsx +++ b/apps/dokploy/pages/index.tsx @@ -37,6 +37,7 @@ import { } from "@/components/ui/input-otp"; import { Label } from "@/components/ui/label"; import { authClient } from "@/lib/auth-client"; +import { api } from "@/utils/api"; const LoginSchema = z.object({ email: z.string().email(), @@ -52,6 +53,29 @@ type LoginForm = z.infer; interface Props { IS_CLOUD: boolean; } + +const LoginHeader = () => { + const { data: settings } = api.settings.getWebServerSettings.useQuery(undefined, { + refetchOnWindowFocus: false, + }); + + const logoUrl = settings?.whitelabelLogoUrl; + + return ( +
+

+
+ + Sign in +
+

+

+ Enter your email and password to sign in +

+
+ ); +}; + export default function Home({ IS_CLOUD }: Props) { const router = useRouter(); const [isLoginLoading, setIsLoginLoading] = useState(false); @@ -202,17 +226,7 @@ export default function Home({ IS_CLOUD }: Props) { }; return ( <> -
-

-
- - Sign in -
-

-

- Enter your email and password to sign in -

-
+ {error && ( {error} diff --git a/apps/dokploy/public/locales/en/settings.json b/apps/dokploy/public/locales/en/settings.json index 699a456e70..4fb19c4ea7 100644 --- a/apps/dokploy/public/locales/en/settings.json +++ b/apps/dokploy/public/locales/en/settings.json @@ -54,5 +54,17 @@ "settings.terminal.connectionSettings": "Connection settings", "settings.terminal.ipAddress": "IP Address", "settings.terminal.port": "Port", - "settings.terminal.username": "Username" + "settings.terminal.username": "Username", + + "settings.whitelabel.title": "Whitelabel", + "settings.whitelabel.description": "Customize the login page with your logo and branding.", + "settings.whitelabel.logoUrl": "Logo URL", + "settings.whitelabel.logoUrlDescription": "Enter the URL of your logo image", + "settings.whitelabel.brandName": "Brand Name", + "settings.whitelabel.brandNameDescription": "Your company or product name", + "settings.whitelabel.tagline": "Tagline", + "settings.whitelabel.taglineDescription": "A short description or slogan", + "settings.whitelabel.success": "Whitelabel settings updated successfully", + "settings.whitelabel.error": "Failed to update whitelabel settings", + "settings.common.loading": "Loading..." } diff --git a/apps/dokploy/public/locales/tr/settings.json b/apps/dokploy/public/locales/tr/settings.json index 47a6629f5e..ca073e40dd 100644 --- a/apps/dokploy/public/locales/tr/settings.json +++ b/apps/dokploy/public/locales/tr/settings.json @@ -40,5 +40,17 @@ "settings.appearance.themes.dark": "Koyu", "settings.appearance.themes.system": "Sistem", "settings.appearance.language": "Dil", - "settings.appearance.languageDescription": "Kontrol paneli için bir dil seçin" + "settings.appearance.languageDescription": "Kontrol paneli için bir dil seçin", + + "settings.whitelabel.title": "Whitelabel", + "settings.whitelabel.description": "Giriş sayfasını logonuz ve markanızla özelleştirin.", + "settings.whitelabel.logoUrl": "Logo URL", + "settings.whitelabel.logoUrlDescription": "Logo görselinizin URL'sini girin", + "settings.whitelabel.brandName": "Marka Adı", + "settings.whitelabel.brandNameDescription": "Şirket veya ürün adınız", + "settings.whitelabel.tagline": "Slogan", + "settings.whitelabel.taglineDescription": "Kısa bir açıklama veya slogan", + "settings.whitelabel.success": "Whitelabel ayarları başarıyla güncellendi", + "settings.whitelabel.error": "Whitelabel ayarları güncellenemedi", + "settings.common.loading": "Yükleniyor..." } diff --git a/apps/dokploy/server/api/routers/settings.ts b/apps/dokploy/server/api/routers/settings.ts index c9d21e515d..0b130f2d02 100644 --- a/apps/dokploy/server/api/routers/settings.ts +++ b/apps/dokploy/server/api/routers/settings.ts @@ -907,4 +907,23 @@ export const settingsRouter = createTRPCRouter({ const ips = process.env.DOKPLOY_CLOUD_IPS?.split(","); return ips; }), + updateWhitelabel: adminProcedure + .input( + z.object({ + whitelabelLogoUrl: z.string().url().optional().nullable(), + whitelabelBrandName: z.string().optional().nullable(), + whitelabelTagline: z.string().optional().nullable(), + }), + ) + .mutation(async ({ input }) => { + if (IS_CLOUD) { + return true; + } + await updateWebServerSettings({ + whitelabelLogoUrl: input.whitelabelLogoUrl, + whitelabelBrandName: input.whitelabelBrandName, + whitelabelTagline: input.whitelabelTagline, + }); + return true; + }), }); diff --git a/packages/server/src/db/schema/web-server-settings.ts b/packages/server/src/db/schema/web-server-settings.ts index fe5cc5ad1e..17ed0d2388 100644 --- a/packages/server/src/db/schema/web-server-settings.ts +++ b/packages/server/src/db/schema/web-server-settings.ts @@ -76,6 +76,10 @@ export const webServerSettings = pgTable("webServerSettings", { cleanupCacheOnCompose: boolean("cleanupCacheOnCompose") .notNull() .default(false), + // Whitelabel Configuration + whitelabelLogoUrl: text("whitelabelLogoUrl"), + whitelabelBrandName: text("whitelabelBrandName"), + whitelabelTagline: text("whitelabelTagline"), createdAt: timestamp("created_at").defaultNow(), updatedAt: timestamp("updated_at").notNull().defaultNow(), }); @@ -125,6 +129,9 @@ export const apiUpdateWebServerSettings = createSchema.partial().extend({ cleanupCacheApplications: z.boolean().optional(), cleanupCacheOnPreviews: z.boolean().optional(), cleanupCacheOnCompose: z.boolean().optional(), + whitelabelLogoUrl: z.string().url().optional().nullable(), + whitelabelBrandName: z.string().optional().nullable(), + whitelabelTagline: z.string().optional().nullable(), }); export const apiAssignDomain = z From 84af0096755a322e7bab89510f74e98862556ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Czeyir=20=C4=B0smail=20Bahtiyar?= <76667836+uzeyirrr@users.noreply.github.com> Date: Thu, 29 Jan 2026 18:01:45 +0300 Subject: [PATCH 2/2] changes --- .../dashboard/settings/whitelabel-form.tsx | 90 +++++++++++-------- .../components/layouts/onboarding-layout.tsx | 32 ++++--- apps/dokploy/components/shared/logo.tsx | 35 +++++++- .../drizzle/0137_add_whitelabel_fields.sql | 4 + apps/dokploy/pages/_app.tsx | 18 +++- apps/dokploy/pages/index.tsx | 54 ++++++++--- apps/dokploy/public/locales/de/settings.json | 21 ++++- apps/dokploy/public/locales/en/settings.json | 9 +- apps/dokploy/public/locales/es/settings.json | 21 ++++- apps/dokploy/public/locales/fa/settings.json | 21 ++++- apps/dokploy/public/locales/fr/settings.json | 21 ++++- apps/dokploy/public/locales/it/settings.json | 21 ++++- apps/dokploy/public/locales/ja/settings.json | 21 ++++- apps/dokploy/public/locales/ko/settings.json | 21 ++++- apps/dokploy/public/locales/pl/settings.json | 21 ++++- .../public/locales/pt-br/settings.json | 21 ++++- apps/dokploy/public/locales/ru/settings.json | 21 ++++- apps/dokploy/public/locales/tr/settings.json | 9 +- .../public/locales/zh-Hans/settings.json | 21 ++++- .../public/locales/zh-Hant/settings.json | 21 ++++- apps/dokploy/server/api/routers/settings.ts | 11 +++ 21 files changed, 439 insertions(+), 75 deletions(-) create mode 100644 apps/dokploy/drizzle/0137_add_whitelabel_fields.sql diff --git a/apps/dokploy/components/dashboard/settings/whitelabel-form.tsx b/apps/dokploy/components/dashboard/settings/whitelabel-form.tsx index 42183d612e..e056876c8e 100644 --- a/apps/dokploy/components/dashboard/settings/whitelabel-form.tsx +++ b/apps/dokploy/components/dashboard/settings/whitelabel-form.tsx @@ -28,22 +28,57 @@ import { import { Input } from "@/components/ui/input"; import { api } from "@/utils/api"; -const whitelabelSchema = z.object({ - whitelabelLogoUrl: z.string().url("Geçerli bir URL girin").optional().nullable(), - whitelabelBrandName: z.string().optional().nullable(), - whitelabelTagline: z.string().optional().nullable(), -}); - -type WhitelabelForm = z.infer; +type WhitelabelForm = { + whitelabelLogoUrl: string | null; + whitelabelBrandName: string | null; + whitelabelTagline: string | null; +}; export const WhitelabelForm = () => { - const { data: isCloud } = api.settings.isCloud.useQuery(); - const { data: settings, refetch, isLoading } = api.settings.getWebServerSettings.useQuery(undefined, { - enabled: !isCloud, - }); + const { data: settings, refetch, isLoading } = api.settings.getWebServerSettings.useQuery(); const { mutateAsync, isError, error, isLoading: isUpdating } = api.settings.updateWhitelabel.useMutation(); const { t } = useTranslation("settings"); + const whitelabelSchema = z.object({ + whitelabelLogoUrl: z + .string() + .optional() + .nullable() + .refine( + (url) => { + if (!url || url.trim() === "") return true; + try { + const parsedUrl = new URL(url); + return parsedUrl.protocol === "https:"; + } catch { + return false; + } + }, + (url) => { + if (!url || url.trim() === "") return true; + try { + new URL(url); + return t("settings.whitelabel.validation.httpsRequired"); + } catch { + return t("settings.whitelabel.validation.invalidUrl"); + } + }, + ) + .transform((val) => (val && val.trim() !== "" ? val.trim() : null)), + whitelabelBrandName: z + .string() + .max(100, t("settings.whitelabel.validation.maxLength", { max: 100 })) + .optional() + .nullable() + .transform((val) => (val && val.trim() !== "" ? val.trim() : null)), + whitelabelTagline: z + .string() + .max(200, t("settings.whitelabel.validation.maxLength", { max: 200 })) + .optional() + .nullable() + .transform((val) => (val && val.trim() !== "" ? val.trim() : null)), + }); + const form = useForm({ resolver: zodResolver(whitelabelSchema), defaultValues: { @@ -77,30 +112,6 @@ export const WhitelabelForm = () => { } }; - if (isCloud) { - return ( -
- -
- - - - {t("settings.whitelabel.title")} - - - {t("settings.whitelabel.description")} - - - - - Whitelabel özelliği sadece self-hosted kurulumlarda kullanılabilir. - - -
-
-
- ); - } return (
@@ -139,9 +150,10 @@ export const WhitelabelForm = () => { @@ -162,9 +174,10 @@ export const WhitelabelForm = () => { @@ -185,9 +198,10 @@ export const WhitelabelForm = () => { diff --git a/apps/dokploy/components/layouts/onboarding-layout.tsx b/apps/dokploy/components/layouts/onboarding-layout.tsx index 96c1b57389..7329f7a073 100644 --- a/apps/dokploy/components/layouts/onboarding-layout.tsx +++ b/apps/dokploy/components/layouts/onboarding-layout.tsx @@ -4,19 +4,24 @@ import { cn } from "@/lib/utils"; import { GithubIcon } from "../icons/data-tools-icons"; import { Logo } from "../shared/logo"; import { Button } from "../ui/button"; -import { api } from "@/utils/api"; interface Props { children: React.ReactNode; + whitelabelLogoUrl?: string | null; + whitelabelBrandName?: string | null; + whitelabelTagline?: string | null; } -export const OnboardingLayout = ({ children }: Props) => { - const { data: settings } = api.settings.getWebServerSettings.useQuery(undefined, { - refetchOnWindowFocus: false, - }); - const brandName = settings?.whitelabelBrandName || "Dokploy"; - const tagline = settings?.whitelabelTagline || "The Open Source alternative to Netlify, Vercel, Heroku."; - const logoUrl = settings?.whitelabelLogoUrl; +export const OnboardingLayout = ({ + children, + whitelabelLogoUrl, + whitelabelBrandName, + whitelabelTagline, +}: Props) => { + const brandName = whitelabelBrandName || "Dokploy"; + const tagline = + whitelabelTagline || + "The Open Source alternative to Netlify, Vercel, Heroku."; return (
@@ -26,8 +31,15 @@ export const OnboardingLayout = ({ children }: Props) => { href="https://dokploy.com" className="relative z-20 flex items-center text-lg font-medium gap-4 text-primary" > - - {brandName} + +
+ {brandName} + {whitelabelBrandName && ( + + powered by Dokploy + + )} +
diff --git a/apps/dokploy/components/shared/logo.tsx b/apps/dokploy/components/shared/logo.tsx index a1c3acb7e1..8b79d1ecd6 100644 --- a/apps/dokploy/components/shared/logo.tsx +++ b/apps/dokploy/components/shared/logo.tsx @@ -6,7 +6,40 @@ interface Props { } export const Logo = ({ className = "size-14", logoUrl }: Props) => { - if (logoUrl) { + if (logoUrl && logoUrl.trim() !== "") { + // Validate URL to prevent XSS + try { + const url = new URL(logoUrl); + if (url.protocol !== "https:") { + // Fallback to default logo if not HTTPS + return ( + + + + ); + } + } catch { + // Invalid URL, fallback to default + return ( + + + + ); + } return ( = NextPage & { - getLayout?: (page: ReactElement) => ReactNode; + getLayout?: ( + page: ReactElement, + whitelabelProps?: { + whitelabelLogoUrl?: string | null; + whitelabelBrandName?: string | null; + whitelabelTagline?: string | null; + }, + ) => ReactNode; theme?: string; }; @@ -29,6 +36,13 @@ const MyApp = ({ pageProps: { ...pageProps }, }: AppPropsWithLayout) => { const getLayout = Component.getLayout ?? ((page) => page); + + // Extract whitelabel props for OnboardingLayout + const whitelabelProps = { + whitelabelLogoUrl: pageProps.whitelabelLogoUrl, + whitelabelBrandName: pageProps.whitelabelBrandName, + whitelabelTagline: pageProps.whitelabelTagline, + }; return ( <> @@ -52,7 +66,7 @@ const MyApp = ({ - {getLayout()} + {getLayout(, whitelabelProps)} ); diff --git a/apps/dokploy/pages/index.tsx b/apps/dokploy/pages/index.tsx index ee3934aa61..a3dd451d55 100644 --- a/apps/dokploy/pages/index.tsx +++ b/apps/dokploy/pages/index.tsx @@ -1,5 +1,6 @@ import { IS_CLOUD, isAdminPresent } from "@dokploy/server"; import { validateRequest } from "@dokploy/server/lib/auth"; +import { getWebServerSettings } from "@dokploy/server"; import { zodResolver } from "@hookform/resolvers/zod"; import { REGEXP_ONLY_DIGITS } from "input-otp"; import type { GetServerSidePropsContext } from "next"; @@ -54,13 +55,11 @@ interface Props { IS_CLOUD: boolean; } -const LoginHeader = () => { - const { data: settings } = api.settings.getWebServerSettings.useQuery(undefined, { - refetchOnWindowFocus: false, - }); - - const logoUrl = settings?.whitelabelLogoUrl; +interface LoginHeaderProps { + logoUrl?: string | null; +} +const LoginHeader = ({ logoUrl }: LoginHeaderProps) => { return (

@@ -76,7 +75,19 @@ const LoginHeader = () => { ); }; -export default function Home({ IS_CLOUD }: Props) { +interface HomeProps { + IS_CLOUD: boolean; + whitelabelLogoUrl?: string | null; + whitelabelBrandName?: string | null; + whitelabelTagline?: string | null; +} + +export default function Home({ + IS_CLOUD, + whitelabelLogoUrl, + whitelabelBrandName, + whitelabelTagline, +}: HomeProps) { const router = useRouter(); const [isLoginLoading, setIsLoginLoading] = useState(false); const [isTwoFactorLoading, setIsTwoFactorLoading] = useState(false); @@ -226,7 +237,7 @@ export default function Home({ IS_CLOUD }: Props) { }; return ( <> - + {error && ( {error} @@ -478,8 +489,23 @@ export default function Home({ IS_CLOUD }: Props) { ); } -Home.getLayout = (page: ReactElement) => { - return {page}; +Home.getLayout = ( + page: ReactElement, + whitelabelProps?: { + whitelabelLogoUrl?: string | null; + whitelabelBrandName?: string | null; + whitelabelTagline?: string | null; + }, +) => { + return ( + + {page} + + ); }; export async function getServerSideProps(context: GetServerSidePropsContext) { if (IS_CLOUD) { @@ -523,9 +549,17 @@ export async function getServerSideProps(context: GetServerSidePropsContext) { }; } + const whitelabelSettings = !IS_CLOUD + ? await getWebServerSettings() + : null; + return { props: { hasAdmin, + IS_CLOUD, + whitelabelLogoUrl: whitelabelSettings?.whitelabelLogoUrl || null, + whitelabelBrandName: whitelabelSettings?.whitelabelBrandName || null, + whitelabelTagline: whitelabelSettings?.whitelabelTagline || null, }, }; } diff --git a/apps/dokploy/public/locales/de/settings.json b/apps/dokploy/public/locales/de/settings.json index e2ba062365..88c7da3edb 100644 --- a/apps/dokploy/public/locales/de/settings.json +++ b/apps/dokploy/public/locales/de/settings.json @@ -40,5 +40,24 @@ "settings.appearance.themes.dark": "Dunkel", "settings.appearance.themes.system": "System", "settings.appearance.language": "Sprache", - "settings.appearance.languageDescription": "Wähl eine Sprache für dein Dashboard aus" + "settings.appearance.languageDescription": "Wähl eine Sprache für dein Dashboard aus", + + "settings.whitelabel.title": "Whitelabel", + "settings.whitelabel.description": "Passe die Anmeldeseite mit deinem Logo und deiner Marke an.", + "settings.whitelabel.logoUrl": "Logo-URL", + "settings.whitelabel.logoUrlDescription": "Gib die URL deines Logo-Bildes ein (nur HTTPS)", + "settings.whitelabel.logoUrlPlaceholder": "https://example.com/logo.png", + "settings.whitelabel.brandName": "Markenname", + "settings.whitelabel.brandNameDescription": "Der Name deines Unternehmens oder Produkts", + "settings.whitelabel.brandNamePlaceholder": "Firmenname", + "settings.whitelabel.tagline": "Slogan", + "settings.whitelabel.taglineDescription": "Eine kurze Beschreibung oder ein Slogan", + "settings.whitelabel.taglinePlaceholder": "Dein Slogan", + "settings.whitelabel.success": "Whitelabel-Einstellungen erfolgreich aktualisiert", + "settings.whitelabel.error": "Fehler beim Aktualisieren der Whitelabel-Einstellungen", + "settings.whitelabel.cloudOnly": "Die Whitelabel-Funktion ist nur für Self-Hosted-Installationen verfügbar.", + "settings.whitelabel.validation.invalidUrl": "Bitte gib eine gültige URL ein", + "settings.whitelabel.validation.httpsRequired": "Die Logo-URL muss das HTTPS-Protokoll verwenden", + "settings.whitelabel.validation.maxLength": "Maximal {max} Zeichen erlaubt", + "settings.common.loading": "Lädt..." } diff --git a/apps/dokploy/public/locales/en/settings.json b/apps/dokploy/public/locales/en/settings.json index 4fb19c4ea7..d11d26efa0 100644 --- a/apps/dokploy/public/locales/en/settings.json +++ b/apps/dokploy/public/locales/en/settings.json @@ -59,12 +59,19 @@ "settings.whitelabel.title": "Whitelabel", "settings.whitelabel.description": "Customize the login page with your logo and branding.", "settings.whitelabel.logoUrl": "Logo URL", - "settings.whitelabel.logoUrlDescription": "Enter the URL of your logo image", + "settings.whitelabel.logoUrlDescription": "Enter the URL of your logo image (HTTPS only)", + "settings.whitelabel.logoUrlPlaceholder": "https://example.com/logo.png", "settings.whitelabel.brandName": "Brand Name", "settings.whitelabel.brandNameDescription": "Your company or product name", + "settings.whitelabel.brandNamePlaceholder": "Company Name", "settings.whitelabel.tagline": "Tagline", "settings.whitelabel.taglineDescription": "A short description or slogan", + "settings.whitelabel.taglinePlaceholder": "Your tagline", "settings.whitelabel.success": "Whitelabel settings updated successfully", "settings.whitelabel.error": "Failed to update whitelabel settings", + "settings.whitelabel.cloudOnly": "Whitelabel feature is only available for self-hosted installations.", + "settings.whitelabel.validation.invalidUrl": "Please enter a valid URL", + "settings.whitelabel.validation.httpsRequired": "Logo URL must use HTTPS protocol", + "settings.whitelabel.validation.maxLength": "Maximum {max} characters allowed", "settings.common.loading": "Loading..." } diff --git a/apps/dokploy/public/locales/es/settings.json b/apps/dokploy/public/locales/es/settings.json index 90a41cd05c..22c0cae8a8 100644 --- a/apps/dokploy/public/locales/es/settings.json +++ b/apps/dokploy/public/locales/es/settings.json @@ -48,5 +48,24 @@ "settings.appearance.themes.dark": "Oscuro", "settings.appearance.themes.system": "Sistema", "settings.appearance.language": "Idioma", - "settings.appearance.languageDescription": "Selecciona un idioma para tu panel" + "settings.appearance.languageDescription": "Selecciona un idioma para tu panel", + + "settings.whitelabel.title": "Whitelabel", + "settings.whitelabel.description": "Personaliza la página de inicio de sesión con tu logo y marca.", + "settings.whitelabel.logoUrl": "URL del Logo", + "settings.whitelabel.logoUrlDescription": "Ingresa la URL de la imagen de tu logo (solo HTTPS)", + "settings.whitelabel.logoUrlPlaceholder": "https://example.com/logo.png", + "settings.whitelabel.brandName": "Nombre de la Marca", + "settings.whitelabel.brandNameDescription": "El nombre de tu empresa o producto", + "settings.whitelabel.brandNamePlaceholder": "Nombre de la Empresa", + "settings.whitelabel.tagline": "Eslogan", + "settings.whitelabel.taglineDescription": "Una breve descripción o eslogan", + "settings.whitelabel.taglinePlaceholder": "Tu eslogan", + "settings.whitelabel.success": "Configuración de whitelabel actualizada correctamente", + "settings.whitelabel.error": "Error al actualizar la configuración de whitelabel", + "settings.whitelabel.cloudOnly": "La función de whitelabel solo está disponible para instalaciones self-hosted.", + "settings.whitelabel.validation.invalidUrl": "Por favor ingresa una URL válida", + "settings.whitelabel.validation.httpsRequired": "La URL del logo debe usar el protocolo HTTPS", + "settings.whitelabel.validation.maxLength": "Se permiten máximo {max} caracteres", + "settings.common.loading": "Cargando..." } diff --git a/apps/dokploy/public/locales/fa/settings.json b/apps/dokploy/public/locales/fa/settings.json index f28aaa27c5..91f51680ee 100644 --- a/apps/dokploy/public/locales/fa/settings.json +++ b/apps/dokploy/public/locales/fa/settings.json @@ -40,5 +40,24 @@ "settings.appearance.themes.dark": "تاریک", "settings.appearance.themes.system": "سیستم", "settings.appearance.language": "زبان", - "settings.appearance.languageDescription": "یک زبان برای داشبورد خود انتخاب کنید" + "settings.appearance.languageDescription": "یک زبان برای داشبورد خود انتخاب کنید", + + "settings.whitelabel.title": "Whitelabel", + "settings.whitelabel.description": "صفحه ورود را با لوگو و برند خود سفارشی کنید.", + "settings.whitelabel.logoUrl": "URL لوگو", + "settings.whitelabel.logoUrlDescription": "URL تصویر لوگوی خود را وارد کنید (فقط HTTPS)", + "settings.whitelabel.logoUrlPlaceholder": "https://example.com/logo.png", + "settings.whitelabel.brandName": "نام برند", + "settings.whitelabel.brandNameDescription": "نام شرکت یا محصول شما", + "settings.whitelabel.brandNamePlaceholder": "نام شرکت", + "settings.whitelabel.tagline": "شعار", + "settings.whitelabel.taglineDescription": "توضیحات کوتاه یا شعار", + "settings.whitelabel.taglinePlaceholder": "شعار شما", + "settings.whitelabel.success": "تنظیمات whitelabel با موفقیت به‌روزرسانی شد", + "settings.whitelabel.error": "به‌روزرسانی تنظیمات whitelabel ناموفق بود", + "settings.whitelabel.cloudOnly": "قابلیت whitelabel فقط برای نصب‌های self-hosted در دسترس است.", + "settings.whitelabel.validation.invalidUrl": "لطفاً یک URL معتبر وارد کنید", + "settings.whitelabel.validation.httpsRequired": "URL لوگو باید از پروتکل HTTPS استفاده کند", + "settings.whitelabel.validation.maxLength": "حداکثر {max} کاراکتر مجاز است", + "settings.common.loading": "در حال بارگذاری..." } diff --git a/apps/dokploy/public/locales/fr/settings.json b/apps/dokploy/public/locales/fr/settings.json index 8901cf1fc4..c0a32734a7 100644 --- a/apps/dokploy/public/locales/fr/settings.json +++ b/apps/dokploy/public/locales/fr/settings.json @@ -40,5 +40,24 @@ "settings.appearance.themes.dark": "Sombre", "settings.appearance.themes.system": "Système", "settings.appearance.language": "Langue", - "settings.appearance.languageDescription": "Sélectionner une langue pour votre dashboard" + "settings.appearance.languageDescription": "Sélectionner une langue pour votre dashboard", + + "settings.whitelabel.title": "Whitelabel", + "settings.whitelabel.description": "Personnalisez la page de connexion avec votre logo et votre marque.", + "settings.whitelabel.logoUrl": "URL du Logo", + "settings.whitelabel.logoUrlDescription": "Entrez l'URL de l'image de votre logo (HTTPS uniquement)", + "settings.whitelabel.logoUrlPlaceholder": "https://example.com/logo.png", + "settings.whitelabel.brandName": "Nom de la Marque", + "settings.whitelabel.brandNameDescription": "Le nom de votre entreprise ou produit", + "settings.whitelabel.brandNamePlaceholder": "Nom de l'Entreprise", + "settings.whitelabel.tagline": "Slogan", + "settings.whitelabel.taglineDescription": "Une courte description ou slogan", + "settings.whitelabel.taglinePlaceholder": "Votre slogan", + "settings.whitelabel.success": "Paramètres whitelabel mis à jour avec succès", + "settings.whitelabel.error": "Échec de la mise à jour des paramètres whitelabel", + "settings.whitelabel.cloudOnly": "La fonctionnalité whitelabel n'est disponible que pour les installations self-hosted.", + "settings.whitelabel.validation.invalidUrl": "Veuillez entrer une URL valide", + "settings.whitelabel.validation.httpsRequired": "L'URL du logo doit utiliser le protocole HTTPS", + "settings.whitelabel.validation.maxLength": "Maximum {max} caractères autorisés", + "settings.common.loading": "Chargement..." } diff --git a/apps/dokploy/public/locales/it/settings.json b/apps/dokploy/public/locales/it/settings.json index 6280e44ebc..56b99390fa 100644 --- a/apps/dokploy/public/locales/it/settings.json +++ b/apps/dokploy/public/locales/it/settings.json @@ -40,5 +40,24 @@ "settings.appearance.themes.dark": "Scuro", "settings.appearance.themes.system": "Sistema", "settings.appearance.language": "Lingua", - "settings.appearance.languageDescription": "Seleziona una lingua per la tua dashboard" + "settings.appearance.languageDescription": "Seleziona una lingua per la tua dashboard", + + "settings.whitelabel.title": "Whitelabel", + "settings.whitelabel.description": "Personalizza la pagina di accesso con il tuo logo e il tuo brand.", + "settings.whitelabel.logoUrl": "URL Logo", + "settings.whitelabel.logoUrlDescription": "Inserisci l'URL dell'immagine del tuo logo (solo HTTPS)", + "settings.whitelabel.logoUrlPlaceholder": "https://example.com/logo.png", + "settings.whitelabel.brandName": "Nome del Brand", + "settings.whitelabel.brandNameDescription": "Il nome della tua azienda o prodotto", + "settings.whitelabel.brandNamePlaceholder": "Nome Azienda", + "settings.whitelabel.tagline": "Slogan", + "settings.whitelabel.taglineDescription": "Una breve descrizione o slogan", + "settings.whitelabel.taglinePlaceholder": "Il tuo slogan", + "settings.whitelabel.success": "Impostazioni whitelabel aggiornate con successo", + "settings.whitelabel.error": "Errore nell'aggiornamento delle impostazioni whitelabel", + "settings.whitelabel.cloudOnly": "La funzionalità whitelabel è disponibile solo per installazioni self-hosted.", + "settings.whitelabel.validation.invalidUrl": "Inserisci un URL valido", + "settings.whitelabel.validation.httpsRequired": "L'URL del logo deve utilizzare il protocollo HTTPS", + "settings.whitelabel.validation.maxLength": "Massimo {max} caratteri consentiti", + "settings.common.loading": "Caricamento..." } diff --git a/apps/dokploy/public/locales/ja/settings.json b/apps/dokploy/public/locales/ja/settings.json index 757586b730..7e3e75d11f 100644 --- a/apps/dokploy/public/locales/ja/settings.json +++ b/apps/dokploy/public/locales/ja/settings.json @@ -40,5 +40,24 @@ "settings.appearance.themes.dark": "ダーク", "settings.appearance.themes.system": "システム", "settings.appearance.language": "言語", - "settings.appearance.languageDescription": "ダッシュボードの言語を選択してください" + "settings.appearance.languageDescription": "ダッシュボードの言語を選択してください", + + "settings.whitelabel.title": "Whitelabel", + "settings.whitelabel.description": "ロゴとブランディングでログインページをカスタマイズします。", + "settings.whitelabel.logoUrl": "ロゴURL", + "settings.whitelabel.logoUrlDescription": "ロゴ画像のURLを入力してください(HTTPSのみ)", + "settings.whitelabel.logoUrlPlaceholder": "https://example.com/logo.png", + "settings.whitelabel.brandName": "ブランド名", + "settings.whitelabel.brandNameDescription": "会社または製品名", + "settings.whitelabel.brandNamePlaceholder": "会社名", + "settings.whitelabel.tagline": "タグライン", + "settings.whitelabel.taglineDescription": "短い説明またはスローガン", + "settings.whitelabel.taglinePlaceholder": "あなたのタグライン", + "settings.whitelabel.success": "Whitelabel設定が正常に更新されました", + "settings.whitelabel.error": "Whitelabel設定の更新に失敗しました", + "settings.whitelabel.cloudOnly": "Whitelabel機能はセルフホスト型インストールでのみ利用可能です。", + "settings.whitelabel.validation.invalidUrl": "有効なURLを入力してください", + "settings.whitelabel.validation.httpsRequired": "ロゴURLはHTTPSプロトコルを使用する必要があります", + "settings.whitelabel.validation.maxLength": "最大{max}文字まで許可されています", + "settings.common.loading": "読み込み中..." } diff --git a/apps/dokploy/public/locales/ko/settings.json b/apps/dokploy/public/locales/ko/settings.json index db877ee6a9..7e34f2ded8 100644 --- a/apps/dokploy/public/locales/ko/settings.json +++ b/apps/dokploy/public/locales/ko/settings.json @@ -40,5 +40,24 @@ "settings.appearance.themes.dark": "다크", "settings.appearance.themes.system": "시스템", "settings.appearance.language": "언어", - "settings.appearance.languageDescription": "대시보드에서 사용할 언어 선택" + "settings.appearance.languageDescription": "대시보드에서 사용할 언어 선택", + + "settings.whitelabel.title": "Whitelabel", + "settings.whitelabel.description": "로고와 브랜딩으로 로그인 페이지를 사용자 정의합니다.", + "settings.whitelabel.logoUrl": "로고 URL", + "settings.whitelabel.logoUrlDescription": "로고 이미지의 URL을 입력하세요 (HTTPS만)", + "settings.whitelabel.logoUrlPlaceholder": "https://example.com/logo.png", + "settings.whitelabel.brandName": "브랜드 이름", + "settings.whitelabel.brandNameDescription": "회사 또는 제품 이름", + "settings.whitelabel.brandNamePlaceholder": "회사 이름", + "settings.whitelabel.tagline": "태그라인", + "settings.whitelabel.taglineDescription": "짧은 설명 또는 슬로건", + "settings.whitelabel.taglinePlaceholder": "태그라인", + "settings.whitelabel.success": "Whitelabel 설정이 성공적으로 업데이트되었습니다", + "settings.whitelabel.error": "Whitelabel 설정 업데이트 실패", + "settings.whitelabel.cloudOnly": "Whitelabel 기능은 셀프 호스팅 설치에서만 사용할 수 있습니다.", + "settings.whitelabel.validation.invalidUrl": "유효한 URL을 입력하세요", + "settings.whitelabel.validation.httpsRequired": "로고 URL은 HTTPS 프로토콜을 사용해야 합니다", + "settings.whitelabel.validation.maxLength": "최대 {max}자까지 허용됩니다", + "settings.common.loading": "로딩 중..." } diff --git a/apps/dokploy/public/locales/pl/settings.json b/apps/dokploy/public/locales/pl/settings.json index 9899fc13e6..78b6b3aadf 100644 --- a/apps/dokploy/public/locales/pl/settings.json +++ b/apps/dokploy/public/locales/pl/settings.json @@ -54,5 +54,24 @@ "settings.terminal.connectionSettings": "Ustawienia połączenia", "settings.terminal.ipAddress": "Adres IP", "settings.terminal.port": "Port", - "settings.terminal.username": "Nazwa użytkownika" + "settings.terminal.username": "Nazwa użytkownika", + + "settings.whitelabel.title": "Whitelabel", + "settings.whitelabel.description": "Dostosuj stronę logowania za pomocą logo i marki.", + "settings.whitelabel.logoUrl": "URL Logo", + "settings.whitelabel.logoUrlDescription": "Wprowadź URL obrazu logo (tylko HTTPS)", + "settings.whitelabel.logoUrlPlaceholder": "https://example.com/logo.png", + "settings.whitelabel.brandName": "Nazwa Marki", + "settings.whitelabel.brandNameDescription": "Nazwa Twojej firmy lub produktu", + "settings.whitelabel.brandNamePlaceholder": "Nazwa Firmy", + "settings.whitelabel.tagline": "Slogan", + "settings.whitelabel.taglineDescription": "Krótki opis lub slogan", + "settings.whitelabel.taglinePlaceholder": "Twój slogan", + "settings.whitelabel.success": "Ustawienia whitelabel zostały pomyślnie zaktualizowane", + "settings.whitelabel.error": "Nie udało się zaktualizować ustawień whitelabel", + "settings.whitelabel.cloudOnly": "Funkcja whitelabel jest dostępna tylko dla instalacji self-hosted.", + "settings.whitelabel.validation.invalidUrl": "Proszę wprowadzić prawidłowy URL", + "settings.whitelabel.validation.httpsRequired": "URL logo musi używać protokołu HTTPS", + "settings.whitelabel.validation.maxLength": "Dozwolone maksymalnie {max} znaków", + "settings.common.loading": "Ładowanie..." } diff --git a/apps/dokploy/public/locales/pt-br/settings.json b/apps/dokploy/public/locales/pt-br/settings.json index f4d90a2f80..c9a39e8bdd 100644 --- a/apps/dokploy/public/locales/pt-br/settings.json +++ b/apps/dokploy/public/locales/pt-br/settings.json @@ -40,5 +40,24 @@ "settings.appearance.themes.dark": "Escuro", "settings.appearance.themes.system": "Automático", "settings.appearance.language": "Linguagem", - "settings.appearance.languageDescription": "Selecione o idioma do dashboard" + "settings.appearance.languageDescription": "Selecione o idioma do dashboard", + + "settings.whitelabel.title": "Whitelabel", + "settings.whitelabel.description": "Personalize a página de login com seu logo e marca.", + "settings.whitelabel.logoUrl": "URL do Logo", + "settings.whitelabel.logoUrlDescription": "Digite a URL da imagem do seu logo (apenas HTTPS)", + "settings.whitelabel.logoUrlPlaceholder": "https://example.com/logo.png", + "settings.whitelabel.brandName": "Nome da Marca", + "settings.whitelabel.brandNameDescription": "O nome da sua empresa ou produto", + "settings.whitelabel.brandNamePlaceholder": "Nome da Empresa", + "settings.whitelabel.tagline": "Slogan", + "settings.whitelabel.taglineDescription": "Uma breve descrição ou slogan", + "settings.whitelabel.taglinePlaceholder": "Seu slogan", + "settings.whitelabel.success": "Configurações de whitelabel atualizadas com sucesso", + "settings.whitelabel.error": "Falha ao atualizar as configurações de whitelabel", + "settings.whitelabel.cloudOnly": "A funcionalidade whitelabel está disponível apenas para instalações self-hosted.", + "settings.whitelabel.validation.invalidUrl": "Por favor, insira uma URL válida", + "settings.whitelabel.validation.httpsRequired": "A URL do logo deve usar o protocolo HTTPS", + "settings.whitelabel.validation.maxLength": "Máximo de {max} caracteres permitidos", + "settings.common.loading": "Carregando..." } diff --git a/apps/dokploy/public/locales/ru/settings.json b/apps/dokploy/public/locales/ru/settings.json index 0d87ed1597..fc68736965 100644 --- a/apps/dokploy/public/locales/ru/settings.json +++ b/apps/dokploy/public/locales/ru/settings.json @@ -54,5 +54,24 @@ "settings.terminal.connectionSettings": "Настройки подключения", "settings.terminal.ipAddress": "IP адрес", "settings.terminal.port": "Порт", - "settings.terminal.username": "Имя пользователя" + "settings.terminal.username": "Имя пользователя", + + "settings.whitelabel.title": "Whitelabel", + "settings.whitelabel.description": "Настройте страницу входа с вашим логотипом и брендингом.", + "settings.whitelabel.logoUrl": "URL логотипа", + "settings.whitelabel.logoUrlDescription": "Введите URL изображения вашего логотипа (только HTTPS)", + "settings.whitelabel.logoUrlPlaceholder": "https://example.com/logo.png", + "settings.whitelabel.brandName": "Название бренда", + "settings.whitelabel.brandNameDescription": "Название вашей компании или продукта", + "settings.whitelabel.brandNamePlaceholder": "Название компании", + "settings.whitelabel.tagline": "Слоган", + "settings.whitelabel.taglineDescription": "Краткое описание или слоган", + "settings.whitelabel.taglinePlaceholder": "Ваш слоган", + "settings.whitelabel.success": "Настройки whitelabel успешно обновлены", + "settings.whitelabel.error": "Не удалось обновить настройки whitelabel", + "settings.whitelabel.cloudOnly": "Функция whitelabel доступна только для self-hosted установок.", + "settings.whitelabel.validation.invalidUrl": "Пожалуйста, введите действительный URL", + "settings.whitelabel.validation.httpsRequired": "URL логотипа должен использовать протокол HTTPS", + "settings.whitelabel.validation.maxLength": "Разрешено максимум {max} символов", + "settings.common.loading": "Загрузка..." } diff --git a/apps/dokploy/public/locales/tr/settings.json b/apps/dokploy/public/locales/tr/settings.json index ca073e40dd..db47ffba52 100644 --- a/apps/dokploy/public/locales/tr/settings.json +++ b/apps/dokploy/public/locales/tr/settings.json @@ -45,12 +45,19 @@ "settings.whitelabel.title": "Whitelabel", "settings.whitelabel.description": "Giriş sayfasını logonuz ve markanızla özelleştirin.", "settings.whitelabel.logoUrl": "Logo URL", - "settings.whitelabel.logoUrlDescription": "Logo görselinizin URL'sini girin", + "settings.whitelabel.logoUrlDescription": "Logo görselinizin URL'sini girin (sadece HTTPS)", + "settings.whitelabel.logoUrlPlaceholder": "https://example.com/logo.png", "settings.whitelabel.brandName": "Marka Adı", "settings.whitelabel.brandNameDescription": "Şirket veya ürün adınız", + "settings.whitelabel.brandNamePlaceholder": "Şirket Adı", "settings.whitelabel.tagline": "Slogan", "settings.whitelabel.taglineDescription": "Kısa bir açıklama veya slogan", + "settings.whitelabel.taglinePlaceholder": "Sloganınız", "settings.whitelabel.success": "Whitelabel ayarları başarıyla güncellendi", "settings.whitelabel.error": "Whitelabel ayarları güncellenemedi", + "settings.whitelabel.cloudOnly": "Whitelabel özelliği sadece self-hosted kurulumlarda kullanılabilir.", + "settings.whitelabel.validation.invalidUrl": "Geçerli bir URL girin", + "settings.whitelabel.validation.httpsRequired": "Logo URL HTTPS protokolü kullanmalıdır", + "settings.whitelabel.validation.maxLength": "Maksimum {max} karakter izin verilir", "settings.common.loading": "Yükleniyor..." } diff --git a/apps/dokploy/public/locales/zh-Hans/settings.json b/apps/dokploy/public/locales/zh-Hans/settings.json index d70676d6a4..ca05908fe0 100644 --- a/apps/dokploy/public/locales/zh-Hans/settings.json +++ b/apps/dokploy/public/locales/zh-Hans/settings.json @@ -63,5 +63,24 @@ "settings.backups": "备份", "settings.logs": "日志", "settings.updates": "更新", - "settings.network": "网络" + "settings.network": "网络", + + "settings.whitelabel.title": "白标", + "settings.whitelabel.description": "使用您的徽标和品牌自定义登录页面。", + "settings.whitelabel.logoUrl": "徽标 URL", + "settings.whitelabel.logoUrlDescription": "输入您的徽标图片 URL(仅 HTTPS)", + "settings.whitelabel.logoUrlPlaceholder": "https://example.com/logo.png", + "settings.whitelabel.brandName": "品牌名称", + "settings.whitelabel.brandNameDescription": "您的公司或产品名称", + "settings.whitelabel.brandNamePlaceholder": "公司名称", + "settings.whitelabel.tagline": "标语", + "settings.whitelabel.taglineDescription": "简短的描述或标语", + "settings.whitelabel.taglinePlaceholder": "您的标语", + "settings.whitelabel.success": "白标设置已成功更新", + "settings.whitelabel.error": "更新白标设置失败", + "settings.whitelabel.cloudOnly": "白标功能仅适用于自托管安装。", + "settings.whitelabel.validation.invalidUrl": "请输入有效的 URL", + "settings.whitelabel.validation.httpsRequired": "徽标 URL 必须使用 HTTPS 协议", + "settings.whitelabel.validation.maxLength": "最多允许 {max} 个字符", + "settings.common.loading": "加载中..." } diff --git a/apps/dokploy/public/locales/zh-Hant/settings.json b/apps/dokploy/public/locales/zh-Hant/settings.json index 9d69003772..93af82a806 100644 --- a/apps/dokploy/public/locales/zh-Hant/settings.json +++ b/apps/dokploy/public/locales/zh-Hant/settings.json @@ -54,5 +54,24 @@ "settings.terminal.connectionSettings": "終端機設定", "settings.terminal.ipAddress": "IP 位址", "settings.terminal.port": "埠", - "settings.terminal.username": "使用者名稱" + "settings.terminal.username": "使用者名稱", + + "settings.whitelabel.title": "白標", + "settings.whitelabel.description": "使用您的徽標和品牌自訂登入頁面。", + "settings.whitelabel.logoUrl": "徽標 URL", + "settings.whitelabel.logoUrlDescription": "輸入您的徽標圖片 URL(僅 HTTPS)", + "settings.whitelabel.logoUrlPlaceholder": "https://example.com/logo.png", + "settings.whitelabel.brandName": "品牌名稱", + "settings.whitelabel.brandNameDescription": "您的公司或產品名稱", + "settings.whitelabel.brandNamePlaceholder": "公司名稱", + "settings.whitelabel.tagline": "標語", + "settings.whitelabel.taglineDescription": "簡短的描述或標語", + "settings.whitelabel.taglinePlaceholder": "您的標語", + "settings.whitelabel.success": "白標設定已成功更新", + "settings.whitelabel.error": "更新白標設定失敗", + "settings.whitelabel.cloudOnly": "白標功能僅適用於自託管安裝。", + "settings.whitelabel.validation.invalidUrl": "請輸入有效的 URL", + "settings.whitelabel.validation.httpsRequired": "徽標 URL 必須使用 HTTPS 協議", + "settings.whitelabel.validation.maxLength": "最多允許 {max} 個字元", + "settings.common.loading": "載入中..." } diff --git a/apps/dokploy/server/api/routers/settings.ts b/apps/dokploy/server/api/routers/settings.ts index 0b130f2d02..8f01d969ad 100644 --- a/apps/dokploy/server/api/routers/settings.ts +++ b/apps/dokploy/server/api/routers/settings.ts @@ -740,6 +740,17 @@ export const settingsRouter = createTRPCRouter({ isCloud: publicProcedure.query(async () => { return IS_CLOUD; }), + getWhitelabelSettings: publicProcedure.query(async () => { + if (IS_CLOUD) { + return null; + } + const settings = await getWebServerSettings(); + return { + whitelabelLogoUrl: settings?.whitelabelLogoUrl || null, + whitelabelBrandName: settings?.whitelabelBrandName || null, + whitelabelTagline: settings?.whitelabelTagline || null, + }; + }), isUserSubscribed: protectedProcedure.query(async ({ ctx }) => { const haveServers = await db.query.server.findMany({ where: eq(server.organizationId, ctx.session?.activeOrganizationId || ""),