feat: Show Registered Services on Ingress Proxy page
Replace "Instance Routes" with "Registered Services" on the Central Ingress page. Services are fetched from /api/v1/services and display name, domain, backend, source, reach level, and backend type. Central no longer manages instances directly — it shows services registered by Wild Cloud, Wild Works, and itself. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,12 +4,12 @@ import { Button } from './ui/button';
|
||||
import { Input, Label } from './ui';
|
||||
import { Alert, AlertDescription } from './ui/alert';
|
||||
import { Textarea } from './ui/textarea';
|
||||
import { Network, Loader2, AlertCircle, CheckCircle, Play, RotateCw, Plus, Trash2, X, Check, Activity, ChevronDown, ChevronUp } from 'lucide-react';
|
||||
import { Network, Loader2, AlertCircle, CheckCircle, Play, RotateCw, Plus, Trash2, X, Check, Activity, ChevronDown, ChevronUp, Globe, Server } from 'lucide-react';
|
||||
import { Badge } from './ui/badge';
|
||||
import { useConfig } from '../hooks';
|
||||
import { useHaproxy } from '../hooks/useHaproxy';
|
||||
import { useServices } from '../hooks/useServices';
|
||||
import type { HAProxyCustomRoute } from '../types';
|
||||
import type { HaproxyInstanceRoute } from '../services/api/networking';
|
||||
import { haproxyApi } from '../services/api/networking';
|
||||
|
||||
export function IngressProxyComponent() {
|
||||
@@ -27,6 +27,8 @@ export function IngressProxyComponent() {
|
||||
isRestarting: isHaproxyRestarting,
|
||||
} = useHaproxy();
|
||||
|
||||
const { services, isLoading: isServicesLoading } = useServices();
|
||||
|
||||
const [showAddCustomRoute, setShowAddCustomRoute] = useState(false);
|
||||
const [newCustomRoute, setNewCustomRoute] = useState<HAProxyCustomRoute>({ name: '', port: 0, backend: '' });
|
||||
const [successMessage, setSuccessMessage] = useState<string | null>(null);
|
||||
@@ -133,7 +135,7 @@ export function IngressProxyComponent() {
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle>Instance Routes</CardTitle>
|
||||
<CardTitle>Registered Services</CardTitle>
|
||||
{isHaproxyLoading ? (
|
||||
<Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
|
||||
) : (
|
||||
@@ -145,37 +147,39 @@ export function IngressProxyComponent() {
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{(() => {
|
||||
const routes: HaproxyInstanceRoute[] = haproxyStatus?.routes ?? [];
|
||||
return routes.length > 0 ? (
|
||||
<div className="border rounded-lg divide-y text-sm">
|
||||
{routes.map(r => (
|
||||
<div key={r.name} className="px-3 py-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckCircle className="h-3.5 w-3.5 text-green-500 shrink-0" />
|
||||
<span className="font-mono text-xs">*.{r.domain}</span>
|
||||
</div>
|
||||
<span className="font-mono text-xs text-muted-foreground">{r.backendIP}</span>
|
||||
{isServicesLoading ? (
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<Loader2 className="h-4 w-4 animate-spin" />Loading services...
|
||||
</div>
|
||||
) : services.length > 0 ? (
|
||||
<div className="border rounded-lg divide-y text-sm">
|
||||
{services.map(s => (
|
||||
<div key={s.name} className="px-3 py-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
{s.reach === 'public' ? (
|
||||
<Globe className="h-3.5 w-3.5 text-blue-500 shrink-0" />
|
||||
) : (
|
||||
<Server className="h-3.5 w-3.5 text-green-500 shrink-0" />
|
||||
)}
|
||||
<span className="font-medium">{s.name}</span>
|
||||
<span className="font-mono text-xs text-muted-foreground">{s.domain}</span>
|
||||
</div>
|
||||
{r.extraDomains && r.extraDomains.length > 0 && (
|
||||
<div className="mt-1 ml-5 flex flex-wrap gap-1">
|
||||
{r.extraDomains.map(d => (
|
||||
<span key={d} className="font-mono text-xs text-muted-foreground bg-muted rounded px-1.5 py-0.5">
|
||||
{d}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<span className="font-mono text-xs text-muted-foreground">{s.backend.address}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-xs text-muted-foreground">
|
||||
No instances registered — click Generate & Apply to configure.
|
||||
</p>
|
||||
);
|
||||
})()}
|
||||
<div className="mt-1 ml-5 flex flex-wrap gap-2 text-xs text-muted-foreground">
|
||||
<span>source: <span className="text-foreground">{s.source}</span></span>
|
||||
<span>reach: <span className="text-foreground">{s.reach}</span></span>
|
||||
<span>type: <span className="text-foreground">{s.backend.type}</span></span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-xs text-muted-foreground">
|
||||
No services registered — click Generate & Apply to configure.
|
||||
</p>
|
||||
)}
|
||||
|
||||
{haproxyGenerateData && (
|
||||
<Alert className="border-green-200 bg-green-50 dark:border-green-800 dark:bg-green-950/20">
|
||||
|
||||
Reference in New Issue
Block a user