// Egress — region groups + node table const { Modal, Drawer, Toggle, Seg, RegionPill, StatusDot, LatencyBar, useToast } = window.UI; function PageEgress({ state, dispatch }) { const { pools, regionGroups } = state; const [filter, setFilter] = React.useState("all"); const [search, setSearch] = React.useState(""); const [groupFilter, setGroupFilter] = React.useState(null); const [drawerNode, setDrawerNode] = React.useState(null); const [metaNode, setMetaNode] = React.useState(null); const [addOpen, setAddOpen] = React.useState(false); const toast = useToast(); const realPools = pools.filter(p => p.source === "static" || p.source === "subscription"); const allNodes = realPools.flatMap(p => (p.nodes || []).map(n => ({ ...n, pool: p.name, poolSource: p.source }))); const filtered = allNodes.filter(n => { if (filter === "normal" && n.residential) return false; if (filter === "residential" && !n.residential) return false; if (groupFilter) { const g = n.residential ? `${n.region}-RES` : n.region; if (g !== groupFilter) return false; } if (search) { const q = search.toLowerCase(); if (!n.name.toLowerCase().includes(q) && !n.pool.toLowerCase().includes(q) && !(n.region||"").toLowerCase().includes(q) && !(n.server||"").toLowerCase().includes(q) && !(n.alias||"").toLowerCase().includes(q)) return false; } return true; }); const visibleGroups = regionGroups.filter(g => { if (filter === "normal" && g.residential) return false; if (filter === "residential" && !g.residential) return false; return true; }); return (
Region groups assemble static and subscription nodes by their region code. Templates back up cold regions automatically.
| Node | Pool | Region | Type | Latency | Status | ||
|---|---|---|---|---|---|---|---|
| { e.stopPropagation(); dispatch({type:"toggleNode", id:n.id}); }}>
|
{n.name}
{n.server || "—"}{n.port ? `:${n.port}` : ""}
|
{n.pool}
{n.poolSource}
|
{n.type} |
|
|||
No nodes match your filters. | |||||||