Add TLS Certificates page to Advanced section of web UI

New page at /advanced/certificates showing:
- Overview card with central domain, cert count, Cloudflare token status
- Auto-provision readiness badge (requires CF token + operator email)
- Table of all domains needing TLS with: domain, source, expiry date,
  issuer, and status badges (days left / covered by wildcard / missing)
- Per-domain "Provision" button for missing certs when auto-provision ready
- "Provision" and "Renew All" action buttons
- Guidance alert when prerequisites are missing

Also fixes pre-existing type errors:
- AppSidebar: guard daemon index access when undefined
- DomainsComponent: fix circular type reference in filter state
- DomainTopology: remove unused isWildcard variable
This commit is contained in:
2026-07-14 12:08:43 +00:00
parent a85bfbfe9e
commit 947991da7f
8 changed files with 247 additions and 5 deletions

View File

@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react';
import { NavLink } from 'react-router';
import { Sun, Moon, Monitor, Shield, Lock, ShieldAlert, ShieldBan, Wifi, LayoutDashboard, Globe, Network, ChevronRight, KeyRound } from 'lucide-react';
import { Sun, Moon, Monitor, Shield, Lock, ShieldAlert, ShieldBan, ShieldCheck, Wifi, LayoutDashboard, Globe, Network, ChevronRight, KeyRound } from 'lucide-react';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './ui/collapsible';
import {
Sidebar,
@@ -105,6 +105,7 @@ export function AppSidebar() {
{ to: '/advanced/crowdsec', icon: ShieldAlert, label: 'CrowdSec', daemon: 'crowdsec' as const },
{ to: '/advanced/authelia', icon: KeyRound, label: 'Authelia', daemon: 'authelia' as const },
{ to: '/advanced/ddns', icon: Globe, label: 'DDNS', daemon: undefined },
{ to: '/advanced/certificates', icon: ShieldCheck, label: 'Certificates', daemon: undefined },
];
return (
@@ -203,7 +204,7 @@ export function AppSidebar() {
<SidebarGroupContent>
<SidebarMenu>
{advancedItems.map(({ to, icon: Icon, label, daemon }) => {
const active = centralStatus?.daemons?.[daemon]?.active;
const active = daemon ? centralStatus?.daemons?.[daemon]?.active : undefined;
return (
<SidebarMenuItem key={to}>
<NavLink to={to}>