From 624c0d6fd370dcf9179c11871c3bbbd6ad102ee4 Mon Sep 17 00:00:00 2001 From: shats Date: Wed, 4 Mar 2026 23:32:33 +0700 Subject: [PATCH] feat(route-optimizer): add country and interface name display in route optimization UI --- backend/routes/routeOptimizerRoutes.js | 4 ++++ frontend/src/RouteOptimizerPage.jsx | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/backend/routes/routeOptimizerRoutes.js b/backend/routes/routeOptimizerRoutes.js index ac882f8..b94caf2 100644 --- a/backend/routes/routeOptimizerRoutes.js +++ b/backend/routes/routeOptimizerRoutes.js @@ -114,6 +114,7 @@ function compactServer(server) { ip: server?.ip || null, dns: server?.dns || null, type: server?.type || null, + country: server?.country || null, label: server?.dns || server?.ip || server?.id || 'unknown', }; } @@ -482,6 +483,7 @@ function buildRecursiveGatewayOptionsForJumphost({ recursiveGatewayId: rgw.id || null, recursiveDescription: rgw.description || '', tunnelGatewayIp: best.physicalGatewayIp, + interfaceName: best.candidate.interfaceName || null, distance: best.distance, exit: best.candidate.exit, baseScore: best.candidate.score, @@ -574,6 +576,7 @@ function buildCommunityOptimization({ current: currentCandidate ? { gateway: currentCandidate.recursiveGateway || currentCandidate.gatewayIpForJumphost || null, tunnelGateway: currentCandidate.tunnelGatewayIp || currentCandidate.gatewayIpForJumphost || null, + interfaceName: currentCandidate.interfaceName || null, distance: currentCandidate.distance != null ? currentCandidate.distance : null, exit: currentCandidate.exit, score: currentCandidate.score, @@ -584,6 +587,7 @@ function buildCommunityOptimization({ recommended: recommendedCandidate ? { gateway: recommendedCandidate.recursiveGateway || recommendedCandidate.gatewayIpForJumphost || null, tunnelGateway: recommendedCandidate.tunnelGatewayIp || recommendedCandidate.gatewayIpForJumphost || null, + interfaceName: recommendedCandidate.interfaceName || null, distance: recommendedCandidate.distance != null ? recommendedCandidate.distance : null, exit: recommendedCandidate.exit, score: recommendedCandidate.score, diff --git a/frontend/src/RouteOptimizerPage.jsx b/frontend/src/RouteOptimizerPage.jsx index db4e2b2..84a9104 100644 --- a/frontend/src/RouteOptimizerPage.jsx +++ b/frontend/src/RouteOptimizerPage.jsx @@ -8,6 +8,7 @@ import { } from '@tabler/icons-react'; import api from './lib/api.js'; import PageHeader from './components/PageHeader.jsx'; +import { countryToFlag } from './utils/serverUtils.js'; function MetricBadge({ label, value, tone = 'secondary' }) { return ( @@ -237,6 +238,12 @@ export default function RouteOptimizerPage() { {r.current.distance != null ? ` (dist ${r.current.distance})` : ''} )} + {(r.current?.interfaceName || r.current?.exit?.country) && ( +
+ {r.current?.exit?.country ? `${countryToFlag(r.current.exit.country)} ` : ''} + {r.current?.interfaceName ? `iface: ${r.current.interfaceName}` : ''} +
+ )}
{r.recommended?.gateway || '—'}
@@ -246,6 +253,12 @@ export default function RouteOptimizerPage() { {r.recommended.distance != null ? ` (dist ${r.recommended.distance})` : ''} )} + {(r.recommended?.interfaceName || r.recommended?.exit?.country) && ( +
+ {r.recommended?.exit?.country ? `${countryToFlag(r.recommended.exit.country)} ` : ''} + {r.recommended?.interfaceName ? `iface: ${r.recommended.interfaceName}` : ''} +
+ )} {fmtProb(r.current?.probabilityOptimal)} / {fmtProb(r.recommended?.probabilityOptimal)}