refactor: remove primaryColor from whitelabeling settings and related components for cleaner configuration

This commit is contained in:
Mauricio Siu
2026-03-10 02:03:34 -06:00
parent 2e03cf3d48
commit 985c9102da
10 changed files with 10 additions and 90 deletions

View File

@@ -53,7 +53,6 @@ const baseSettings: WebServerSettings = {
appDescription: null,
logoUrl: null,
faviconUrl: null,
primaryColor: null,
customCss: null,
loginLogoUrl: null,
supportUrl: null,

View File

@@ -12,14 +12,12 @@ interface WhitelabelingPreviewProps {
config: {
appName?: string;
logoUrl?: string;
primaryColor?: string;
footerText?: string;
};
}
export function WhitelabelingPreview({ config }: WhitelabelingPreviewProps) {
const appName = config.appName || "Dokploy";
const primaryColor = config.primaryColor || "hsl(var(--primary))";
return (
<Card className="bg-transparent">
@@ -40,10 +38,7 @@ export function WhitelabelingPreview({ config }: WhitelabelingPreviewProps) {
className="size-8 rounded-sm object-contain"
/>
) : (
<div
className="size-8 rounded-sm flex items-center justify-center text-white font-bold text-sm"
style={{ backgroundColor: primaryColor }}
>
<div className="size-8 rounded-sm flex items-center justify-center bg-primary text-primary-foreground font-bold text-sm">
{appName.charAt(0).toUpperCase()}
</div>
)}
@@ -53,17 +48,11 @@ export function WhitelabelingPreview({ config }: WhitelabelingPreviewProps) {
{/* Simulated content area */}
<div className="p-4 bg-background">
<div className="flex items-center gap-2 mb-3">
<div
className="h-2 w-16 rounded-full"
style={{ backgroundColor: primaryColor }}
/>
<div className="h-2 w-16 rounded-full bg-primary" />
<div className="h-2 w-24 rounded-full bg-muted" />
</div>
<div className="flex gap-2">
<div
className="px-3 py-1.5 rounded-md text-xs text-white font-medium"
style={{ backgroundColor: primaryColor }}
>
<div className="px-3 py-1.5 rounded-md text-xs bg-primary text-primary-foreground font-medium">
Button
</div>
<div className="px-3 py-1.5 rounded-md text-xs border font-medium">

View File

@@ -18,76 +18,14 @@ export function WhitelabelingProvider() {
{config.faviconUrl && <link rel="icon" href={config.faviconUrl} />}
</Head>
{(config.customCss || config.primaryColor) && (
{config.customCss && (
<style
id="whitelabeling-styles"
dangerouslySetInnerHTML={{
__html: [
config.primaryColor
? `:root { --primary: ${hexToHSL(config.primaryColor)}; }`
: "",
config.customCss || "",
]
.filter(Boolean)
.join("\n"),
__html: config.customCss,
}}
/>
)}
</>
);
}
/**
* Converts a hex color string to HSL values (without the hsl() wrapper)
* matching the format used by shadcn/ui CSS variables (e.g., "262 83% 58%")
*/
function hexToHSL(hex: string): string {
// Remove # prefix if present
const cleanHex = hex.replace(/^#/, "");
if (
!/^[0-9a-fA-F]{6}$/.test(cleanHex) &&
!/^[0-9a-fA-F]{3}$/.test(cleanHex)
) {
return hex; // Return as-is if not a valid hex color (might be HSL already)
}
let r: number;
let g: number;
let b: number;
if (cleanHex.length === 3) {
r = Number.parseInt(cleanHex[0]! + cleanHex[0], 16);
g = Number.parseInt(cleanHex[1]! + cleanHex[1], 16);
b = Number.parseInt(cleanHex[2]! + cleanHex[2], 16);
} else {
r = Number.parseInt(cleanHex.slice(0, 2), 16);
g = Number.parseInt(cleanHex.slice(2, 4), 16);
b = Number.parseInt(cleanHex.slice(4, 6), 16);
}
r /= 255;
g /= 255;
b /= 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const l = (max + min) / 2;
let h = 0;
let s = 0;
if (max !== min) {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
if (max === r) {
h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
} else if (max === g) {
h = ((b - r) / d + 2) / 6;
} else {
h = ((r - g) / d + 4) / 6;
}
}
return `${Math.round(h * 360)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
}

View File

@@ -228,7 +228,6 @@ export function WhitelabelingSettings() {
appDescription: values.appDescription || null,
logoUrl: values.logoUrl || null,
faviconUrl: values.faviconUrl || null,
primaryColor: null,
customCss: values.customCss || null,
loginLogoUrl: values.loginLogoUrl || null,
supportUrl: values.supportUrl || null,

View File

@@ -1 +0,0 @@
ALTER TABLE "webServerSettings" ADD COLUMN "whitelabelingConfig" jsonb DEFAULT '{"appName":null,"appDescription":null,"logoUrl":null,"faviconUrl":null,"primaryColor":null,"customCss":null,"loginLogoUrl":null,"supportUrl":null,"docsUrl":null,"errorPageTitle":null,"errorPageDescription":null,"metaTitle":null,"footerText":null}'::jsonb;

View File

@@ -0,0 +1 @@
ALTER TABLE "webServerSettings" ADD COLUMN "whitelabelingConfig" jsonb DEFAULT '{"appName":null,"appDescription":null,"logoUrl":null,"faviconUrl":null,"customCss":null,"loginLogoUrl":null,"supportUrl":null,"docsUrl":null,"errorPageTitle":null,"errorPageDescription":null,"metaTitle":null,"footerText":null}'::jsonb;

View File

@@ -1,5 +1,5 @@
{
"id": "cec2dc6b-f0db-4064-bc17-7f79ed1b8638",
"id": "a293a443-ceaf-418e-8e34-ff46e183995f",
"prevId": "2e0aba0b-93fc-4bfe-a975-1c5d45354753",
"version": "7",
"dialect": "postgresql",
@@ -7179,7 +7179,7 @@
"type": "jsonb",
"primaryKey": false,
"notNull": false,
"default": "'{\"appName\":null,\"appDescription\":null,\"logoUrl\":null,\"faviconUrl\":null,\"primaryColor\":null,\"customCss\":null,\"loginLogoUrl\":null,\"supportUrl\":null,\"docsUrl\":null,\"errorPageTitle\":null,\"errorPageDescription\":null,\"metaTitle\":null,\"footerText\":null}'::jsonb"
"default": "'{\"appName\":null,\"appDescription\":null,\"logoUrl\":null,\"faviconUrl\":null,\"customCss\":null,\"loginLogoUrl\":null,\"supportUrl\":null,\"docsUrl\":null,\"errorPageTitle\":null,\"errorPageDescription\":null,\"metaTitle\":null,\"footerText\":null}'::jsonb"
},
"cleanupCacheApplications": {
"name": "cleanupCacheApplications",

View File

@@ -1041,8 +1041,8 @@
{
"idx": 148,
"version": "7",
"when": 1773124119746,
"tag": "0148_cold_kitty_pryde",
"when": 1773129798212,
"tag": "0148_futuristic_bullseye",
"breakpoints": true
}
]

View File

@@ -66,7 +66,6 @@ export const whitelabelingRouter = createTRPCRouter({
appDescription: null,
logoUrl: null,
faviconUrl: null,
primaryColor: null,
customCss: null,
loginLogoUrl: null,
supportUrl: null,
@@ -97,7 +96,6 @@ export const whitelabelingRouter = createTRPCRouter({
logoUrl: config.logoUrl,
loginLogoUrl: config.loginLogoUrl,
faviconUrl: config.faviconUrl,
primaryColor: config.primaryColor,
customCss: config.customCss,
metaTitle: config.metaTitle,
errorPageTitle: config.errorPageTitle,

View File

@@ -73,7 +73,6 @@ export const webServerSettings = pgTable("webServerSettings", {
appDescription: string | null;
logoUrl: string | null;
faviconUrl: string | null;
primaryColor: string | null;
customCss: string | null;
loginLogoUrl: string | null;
supportUrl: string | null;
@@ -88,7 +87,6 @@ export const webServerSettings = pgTable("webServerSettings", {
appDescription: null,
logoUrl: null,
faviconUrl: null,
primaryColor: null,
customCss: null,
loginLogoUrl: null,
supportUrl: null,
@@ -199,7 +197,6 @@ export const whitelabelingConfigSchema = z.object({
appDescription: z.string().nullable(),
logoUrl: safeUrl,
faviconUrl: safeUrl,
primaryColor: z.string().nullable(),
customCss: z.string().nullable(),
loginLogoUrl: safeUrl,
supportUrl: safeUrl,