refactor(route-optimizer): enhance layout and structure of optimized routes table in RouteOptimizerPage component
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m53s

This commit is contained in:
2026-03-05 14:26:16 +07:00
parent 31ce1ae02a
commit 1dcdc0e6c2
+80 -74
View File
@@ -320,80 +320,86 @@ export default function RouteOptimizerPage() {
</div> </div>
<div className="mt-4"> <div className="mt-4">
<h3 className="mb-3">Оптимизированные маршруты Home -&gt; JumpHost -&gt; Exit по BGP community</h3> <div className="card">
<div className="text-muted small mb-3"> <div className="card-header">
Таблица показывает лучший полный маршрут для каждой community с учетом рекомендованного <h3 className="card-title mb-0">Оптимизированные маршруты Home -&gt; JumpHost -&gt; Exit по BGP community</h3>
gateway на Jumphost. </div>
</div> <div className="card-body">
<div className="table-responsive mb-4"> <div className="text-muted small mb-3">
<table className="table table-vcenter card-table align-middle" style={OPT_TABLE_STYLE}> Таблица показывает лучший полный маршрут для каждой community с учетом рекомендованного
<OptimizerColgroup /> gateway на Jumphost.
<thead> </div>
<tr> <div className="table-responsive mb-0">
<th>Community</th> <table className="table table-vcenter card-table align-middle" style={OPT_TABLE_STYLE}>
<th>Маршрут (Home -&gt; JumpHost -&gt; Exit)</th> <OptimizerColgroup />
<th>Сегменты</th> <thead>
<th>Gateway / Действие</th> <tr>
<th>Вероятность</th> <th>Community</th>
</tr> <th>Маршрут (Home -&gt; JumpHost -&gt; Exit)</th>
</thead> <th>Сегменты</th>
<tbody> <th>Gateway / Действие</th>
{communityFullRoutes.length === 0 ? ( <th>Вероятность</th>
<tr> </tr>
<td colSpan={5} className="text-muted">Недостаточно данных для построения полных маршрутов по community.</td> </thead>
</tr> <tbody>
) : communityFullRoutes.map((r, idx) => ( {communityFullRoutes.length === 0 ? (
<tr key={`${r.community}-${routeNodeKey(r.home)}-${routeNodeKey(r.jumphost)}-${routeNodeKey(r.exit)}-${idx}`}> <tr>
<td className="text-break"> <td colSpan={5} className="text-muted">Недостаточно данных для построения полных маршрутов по community.</td>
<div className="fw-semibold">{r.community}</div> </tr>
{(r.communityInfo?.name || r.communityInfo?.description) && ( ) : communityFullRoutes.map((r, idx) => (
<div className="small text-muted">{r.communityInfo?.name || r.communityInfo?.description}</div> <tr key={`${r.community}-${routeNodeKey(r.home)}-${routeNodeKey(r.jumphost)}-${routeNodeKey(r.exit)}-${idx}`}>
)} <td className="text-break">
</td> <div className="fw-semibold">{r.community}</div>
<td className="small text-break"> {(r.communityInfo?.name || r.communityInfo?.description) && (
<span className="fw-semibold">{r.home?.label || r.home?.dns || r.home?.ip || 'home'}</span> <div className="small text-muted">{r.communityInfo?.name || r.communityInfo?.description}</div>
<span className="text-muted"> </span> )}
<span className="fw-semibold">{r.jumphost?.label || r.jumphost?.dns || r.jumphost?.ip || 'jumphost'}</span> </td>
<span className="text-muted"> </span> <td className="small text-break">
<span className="fw-semibold">{r.exit?.label || r.exit?.dns || r.exit?.ip || 'exit'}</span> <span className="fw-semibold">{r.home?.label || r.home?.dns || r.home?.ip || 'home'}</span>
</td> <span className="text-muted"> </span>
<td className="small text-break"> <span className="fw-semibold">{r.jumphost?.label || r.jumphost?.dns || r.jumphost?.ip || 'jumphost'}</span>
<div> <span className="text-muted"> </span>
HJ: ping {r.homeToJumphost?.pingMs ?? '—'} ms, {fmtSpeed( <span className="fw-semibold">{r.exit?.label || r.exit?.dns || r.exit?.ip || 'exit'}</span>
r.homeToJumphost?.speedDownloadMbps, </td>
r.homeToJumphost?.speedUploadMbps, <td className="small text-break">
r.homeToJumphost?.speedMbps <div>
)} HJ: ping {r.homeToJumphost?.pingMs ?? '—'} ms, {fmtSpeed(
</div> r.homeToJumphost?.speedDownloadMbps,
<div className="text-muted"> r.homeToJumphost?.speedUploadMbps,
JE: ping {r.jumphostToExit?.pingMs ?? '—'} ms, {fmtSpeed( r.homeToJumphost?.speedMbps
r.jumphostToExit?.speedDownloadMbps, )}
r.jumphostToExit?.speedUploadMbps, </div>
r.jumphostToExit?.speedMbps <div className="text-muted">
)} JE: ping {r.jumphostToExit?.pingMs ?? '—'} ms, {fmtSpeed(
</div> r.jumphostToExit?.speedDownloadMbps,
</td> r.jumphostToExit?.speedUploadMbps,
<td className="small text-break"> r.jumphostToExit?.speedMbps
<div>{r.recommendedGateway || '—'}</div> )}
{r.tunnelGateway && <div className="text-muted">{'->'} {r.tunnelGateway}</div>} </div>
<div className="mt-1"> </td>
{r.pinnedBySettings ? ( <td className="small text-break">
<span className="badge bg-blue-lt text-blue">pin</span> <div>{r.recommendedGateway || '—'}</div>
) : r.shouldSwitch ? ( {r.tunnelGateway && <div className="text-muted">{'->'} {r.tunnelGateway}</div>}
<span className="badge bg-orange-lt text-orange">switch</span> <div className="mt-1">
) : ( {r.pinnedBySettings ? (
<span className="badge bg-green-lt text-green">ok</span> <span className="badge bg-blue-lt text-blue">pin</span>
)} ) : r.shouldSwitch ? (
</div> <span className="badge bg-orange-lt text-orange">switch</span>
</td> ) : (
<td className="small"> <span className="badge bg-green-lt text-green">ok</span>
<div>{fmtProb(r.fullRouteProbability)}</div> )}
<div className="text-muted">score {r.fullRouteScore} / conf {r.fullRouteConfidence ?? '—'}</div> </div>
</td> </td>
</tr> <td className="small">
))} <div>{fmtProb(r.fullRouteProbability)}</div>
</tbody> <div className="text-muted">score {r.fullRouteScore} / conf {r.fullRouteConfidence ?? '—'}</div>
</table> </td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div> </div>
</div> </div>