feat(traffic-flow): enhance country handling in flow analytics
Docker images / prepare-release (push) Successful in 9s
Docker images / backend-test (push) Successful in 2m19s
Docker images / frontend-image (push) Successful in 3m26s
Docker images / updater-image (push) Successful in 47s
Docker images / backend-image (push) Successful in 2m23s
Docker images / notify-webhook (push) Skipped
Docker images / publish-release (push) Successful in 10s
Docker images / prepare-release (push) Successful in 9s
Docker images / backend-test (push) Successful in 2m19s
Docker images / frontend-image (push) Successful in 3m26s
Docker images / updater-image (push) Successful in 47s
Docker images / backend-image (push) Successful in 2m23s
Docker images / notify-webhook (push) Skipped
Docker images / publish-release (push) Successful in 10s
- Introduced country-specific handling in traffic flow analytics, including new mappings for country nodes and edges. - Added mock data for countries and their respective service paths to improve visualization in the Network Map. - Updated the `countryName` function to utilize `Intl.DisplayNames` for better localization of country names. - Enhanced tests to validate country handling and ensure accurate representation in flow analytics. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
+29
-2
@@ -20,9 +20,29 @@ const COUNTRY_NAMES: Record<string, string> = {
|
||||
HK: "Гонконг",
|
||||
}
|
||||
|
||||
/** Country name in Russian (fallback to code) */
|
||||
let regionNames: Intl.DisplayNames | null | undefined
|
||||
|
||||
function regionDisplayName(iso: string): string | undefined {
|
||||
try {
|
||||
if (regionNames === undefined) {
|
||||
regionNames = typeof Intl !== "undefined" && "DisplayNames" in Intl
|
||||
? new Intl.DisplayNames(["ru"], { type: "region" })
|
||||
: null
|
||||
}
|
||||
return regionNames?.of(iso) ?? undefined
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
/** Country name in Russian (fallback to ISO code) */
|
||||
export function countryName(code: string): string {
|
||||
return COUNTRY_NAMES[code.toUpperCase()] ?? code
|
||||
const iso = code.toUpperCase()
|
||||
if (!iso) return code
|
||||
if (COUNTRY_NAMES[iso]) return COUNTRY_NAMES[iso]
|
||||
const intl = regionDisplayName(iso)
|
||||
if (intl && intl !== iso) return intl
|
||||
return iso
|
||||
}
|
||||
|
||||
interface FlagProps {
|
||||
@@ -39,6 +59,13 @@ function nearestCdnSize(px: number): number {
|
||||
return CDN_SIZES.find(s => s >= px) ?? CDN_SIZES[CDN_SIZES.length - 1]
|
||||
}
|
||||
|
||||
/** CDN URL for SVG `<image href>` (flagcdn widths only). */
|
||||
export function flagCdnUrl(code: string, size = 40): string | null {
|
||||
const lower = code.toLowerCase()
|
||||
if (!/^[a-z]{2}$/.test(lower)) return null
|
||||
return `https://flagcdn.com/w${nearestCdnSize(size)}/${lower}.png`
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a flag <img> for a given ISO 3166-1 alpha-2 country code.
|
||||
* Source: https://flagcdn.com — free CDN, no API key needed.
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
"use client"
|
||||
|
||||
import { flagCdnUrl } from "@/components/flag"
|
||||
|
||||
export function CountryFlagSvg({ iso, size = 22 }: { iso: string; size?: number }) {
|
||||
const url = flagCdnUrl(iso, size)
|
||||
if (!url) return null
|
||||
const h = Math.round(size * 0.75)
|
||||
return (
|
||||
<image
|
||||
href={url}
|
||||
width={size}
|
||||
height={h}
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
/>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user