Build the Settings module: notification channels, event toggles, DNS badge colors
The Settings page was a "coming soon" placeholder. Port Sloth Manager's settings feature set: Gotify/ntfy/SMTP/webhook notification channels (each with its own test-send button), per-event toggles (DNS record added/updated/deleted, a daily secret-expiry digest with configurable time/timezone), and per-provider DNS badge color customization. Settings persist in the existing `settings` key/value table via a new settingsStore service; a notify service fans a message out to every enabled channel. DNS record add/update/delete now fire notifications, and a node-schedule job re-arms itself whenever the notification settings change. Removed the now-superseded GOTIFY_URL/GOTIFY_TOKEN env vars in favor of in-app configuration. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3a53a86ce0
commit
3255314402
16 files changed
+1272
-23
No files matched your search
+17
-2
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useState, type CSSProperties } from "react";
|
||||
import {
|
||||
api,
|
||||
type CurrentUser,
|
||||
@@ -21,6 +21,12 @@ const PROVIDER_LABELS: Record<DnsProviderType, string> = {
|
||||
|
||||
const emptyRecordForm: DnsRecordInput = { type: "A", name: "", content: "", ttl: 3600, priority: undefined, proxied: undefined };
|
||||
|
||||
function providerBadgeStyle(colors: Record<string, string>, providerType: DnsProviderType): CSSProperties {
|
||||
const color = colors[providerType];
|
||||
if (!color) return {};
|
||||
return { backgroundColor: `${color}22`, color, border: `1px solid ${color}55` };
|
||||
}
|
||||
|
||||
export default function Dns({ user }: { user: CurrentUser }) {
|
||||
const isAdmin = user.role === "admin";
|
||||
const canEdit = user.role === "admin" || user.role === "operator";
|
||||
@@ -29,6 +35,11 @@ export default function Dns({ user }: { user: CurrentUser }) {
|
||||
const [managingProviders, setManagingProviders] = useState(false);
|
||||
const [selectedProviderId, setSelectedProviderId] = useState<number | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [providerColors, setProviderColors] = useState<Record<string, string>>({});
|
||||
|
||||
useEffect(() => {
|
||||
api.settings.providerColors().then((res) => setProviderColors(res.providerColors)).catch(() => {});
|
||||
}, []);
|
||||
|
||||
const [zones, setZones] = useState<DnsZone[] | null>(null);
|
||||
const [zonesError, setZonesError] = useState<string | null>(null);
|
||||
@@ -212,7 +223,11 @@ export default function Dns({ user }: { user: CurrentUser }) {
|
||||
{providers?.map((p) => (
|
||||
<tr key={p.id}>
|
||||
<td>{p.name}</td>
|
||||
<td>{PROVIDER_LABELS[p.providerType]}</td>
|
||||
<td>
|
||||
<span className="badge" style={providerBadgeStyle(providerColors, p.providerType)}>
|
||||
{PROVIDER_LABELS[p.providerType]}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
className={`badge ${p.enabled ? "bg-green-lt text-green" : "bg-secondary-lt text-secondary"} border-0`}
|
||||
|
||||
Reference in new issue
Block a user