Extend badge color settings to cover integration types too
Settings → DNS Badges only let you customize DNS provider badge colors. Expand it into a general Badges page with a second section for the six integration types (Tailscale, Proxmox, Synology, Semaphore, Gitea, Dockhand), applied to the type badge in the Manage integrations table. - New integrationColors key on AppSettings, stored/merged the same way as providerColors via the existing settingsStore. - New GET /api/settings/integration-colors — non-secret, any signed-in user, mirroring /provider-colors — so the badge color can be read without needing admin access to the full settings payload. - Renamed DnsBadgeSettings.tsx -> BadgeSettings.tsx (route /settings/dns-badges -> /settings/badges, sub-nav label "DNS Badges" -> "Badges") with both color sections saved together. Verified end-to-end against the real dev server: PUT persists integration colors independently of provider colors, the public integration-colors endpoint reflects updates immediately, and the change is audit-logged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7fed1dbfa4
commit
ad6783b6a1
9 files changed
+175
-100
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useState, type CSSProperties } from "react";
|
||||
import {
|
||||
api,
|
||||
type CurrentUser,
|
||||
@@ -130,6 +130,12 @@ const TYPE_LABELS: Record<IntegrationType, string> = {
|
||||
dockhand: "Dockhand",
|
||||
};
|
||||
|
||||
function typeBadgeStyle(colors: Record<string, string>, type: IntegrationType): CSSProperties {
|
||||
const color = colors[type];
|
||||
if (!color) return {};
|
||||
return { backgroundColor: `${color}22`, color, border: `1px solid ${color}55` };
|
||||
}
|
||||
|
||||
export default function Integrations({ user }: { user: CurrentUser }) {
|
||||
const isAdmin = user.role === "admin";
|
||||
const canEdit = user.role === "admin" || user.role === "operator";
|
||||
@@ -139,6 +145,11 @@ export default function Integrations({ user }: { user: CurrentUser }) {
|
||||
const [editingIntegration, setEditingIntegration] = useState<IntegrationSummary | null>(null);
|
||||
const [selectedId, setSelectedId] = useState<number | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [integrationColors, setIntegrationColors] = useState<Record<string, string>>({});
|
||||
|
||||
useEffect(() => {
|
||||
api.settings.integrationColors().then((res) => setIntegrationColors(res.integrationColors)).catch(() => {});
|
||||
}, []);
|
||||
|
||||
const [tailscaleData, setTailscaleData] = useState<TailscaleDevicesResponse | null>(null);
|
||||
const [tailscaleError, setTailscaleError] = useState<string | null>(null);
|
||||
@@ -418,7 +429,11 @@ export default function Integrations({ user }: { user: CurrentUser }) {
|
||||
{integrations?.map((i) => (
|
||||
<tr key={i.id}>
|
||||
<td>{i.name}</td>
|
||||
<td>{TYPE_LABELS[i.type]}</td>
|
||||
<td>
|
||||
<span className="badge" style={typeBadgeStyle(integrationColors, i.type)}>
|
||||
{TYPE_LABELS[i.type]}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
className={`badge ${i.enabled ? "bg-green-lt text-green" : "bg-secondary-lt text-secondary"} border-0`}
|
||||
|
||||
Reference in new issue
Block a user