From 29ceaea8c5c57dc34b9c61967560fa56d2cfaab9 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Thu, 10 Oct 2024 10:34:59 +0200 Subject: [PATCH] Add peers page --- src/components/Peers/PeerCountryCell.tsx | 50 + src/components/Peers/countries.ts | 1312 ++++++++++++++++++++++ src/components/Peers/types.ts | 4 + src/routeTree.gen.ts | 26 + src/routes/dashboard.tsx | 10 + src/routes/dashboard/peers.css | 10 + src/routes/dashboard/peers.tsx | 98 ++ 7 files changed, 1510 insertions(+) create mode 100644 src/components/Peers/PeerCountryCell.tsx create mode 100644 src/components/Peers/countries.ts create mode 100644 src/components/Peers/types.ts create mode 100644 src/routes/dashboard/peers.css create mode 100644 src/routes/dashboard/peers.tsx diff --git a/src/components/Peers/PeerCountryCell.tsx b/src/components/Peers/PeerCountryCell.tsx new file mode 100644 index 0000000..9877c73 --- /dev/null +++ b/src/components/Peers/PeerCountryCell.tsx @@ -0,0 +1,50 @@ +import { Cell } from "@codex-storage/marketplace-ui-components"; +import { useEffect, useState } from "react"; +import { PeerPin } from "./types"; +import { countriesCoordinates } from "./countries"; + +export type Props = { + address: string; + onPinAdd: (pin: PeerPin) => void; +}; + +const getFlagEmoji = (countryCode: string) => { + const codePoints = countryCode + .toUpperCase() + .split("") + .map((char) => 127397 + char.charCodeAt(0)); + return String.fromCodePoint(...codePoints); +}; + +export function PeerCountryCell({ address, onPinAdd }: Props) { + const [country, setCountry] = useState(""); + + useEffect(() => { + const [ip] = address.split(":"); + + console.info(ip); + + fetch("https://api.country.is/" + ip) + .then((res) => res.json()) + .then((json) => { + setCountry(json.country); + + const coordinate = countriesCoordinates.find( + (c) => c.iso === json.country + ); + + if (coordinate) { + onPinAdd({ + lat: parseFloat(coordinate.lat), + lng: parseFloat(coordinate.lng), + }); + } + }); + }, [address]); + + return ( + + {getFlagEmoji(country)} {address} + + ); +} diff --git a/src/components/Peers/countries.ts b/src/components/Peers/countries.ts new file mode 100644 index 0000000..4c8ec26 --- /dev/null +++ b/src/components/Peers/countries.ts @@ -0,0 +1,1312 @@ +export const countriesCoordinates = [ + { + "iso": "AF", + "lat": "33", + "lng": "65" + }, + { + "iso": "AX", + "lat": "60.116667", + "lng": "19.9" + }, + { + "iso": "AL", + "lat": "41", + "lng": "20" + }, + { + "iso": "DZ", + "lat": "28", + "lng": "3" + }, + { + "iso": "AS", + "lat": "-14.3333", + "lng": "-170" + }, + { + "iso": "AD", + "lat": "42.5", + "lng": "1.6" + }, + { + "iso": "AO", + "lat": "-12.5", + "lng": "18.5" + }, + { + "iso": "AI", + "lat": "18.25", + "lng": "-63.1667" + }, + { + "iso": "AQ", + "lat": "-90", + "lng": "0" + }, + { + "iso": "AG", + "lat": "17.05", + "lng": "-61.8" + }, + { + "iso": "AR", + "lat": "-34", + "lng": "-64" + }, + { + "iso": "AM", + "lat": "40", + "lng": "45" + }, + { + "iso": "AW", + "lat": "12.5", + "lng": "-69.9667" + }, + { + "iso": "AU", + "lat": "-27", + "lng": "133" + }, + { + "iso": "AT", + "lat": "47.3333", + "lng": "13.3333" + }, + { + "iso": "AZ", + "lat": "40.5", + "lng": "47.5" + }, + { + "iso": "BS", + "lat": "24.25", + "lng": "-76" + }, + { + "iso": "BH", + "lat": "26", + "lng": "50.55" + }, + { + "iso": "BD", + "lat": "24", + "lng": "90" + }, + { + "iso": "BB", + "lat": "13.1667", + "lng": "-59.5333" + }, + { + "iso": "BY", + "lat": "53", + "lng": "28" + }, + { + "iso": "BE", + "lat": "50.8333", + "lng": "4" + }, + { + "iso": "BZ", + "lat": "17.25", + "lng": "-88.75" + }, + { + "iso": "BJ", + "lat": "9.5", + "lng": "2.25" + }, + { + "iso": "BM", + "lat": "32.3333", + "lng": "-64.75" + }, + { + "iso": "BT", + "lat": "27.5", + "lng": "90.5" + }, + { + "iso": "Plurinational State of", + "lat": "68", + "lng": "-17" + }, + { + "iso": "BO", + "lat": "-17", + "lng": "-65" + }, + { + "iso": "Sint Eustatius and Saba", + "lat": "535", + "lng": "12.183333" + }, + { + "iso": "BA", + "lat": "44", + "lng": "18" + }, + { + "iso": "BW", + "lat": "-22", + "lng": "24" + }, + { + "iso": "BV", + "lat": "-54.4333", + "lng": "3.4" + }, + { + "iso": "BR", + "lat": "-10", + "lng": "-55" + }, + { + "iso": "IO", + "lat": "-6", + "lng": "71.5" + }, + { + "iso": "BN", + "lat": "4.5", + "lng": "114.6667" + }, + { + "iso": "BN", + "lat": "4.5", + "lng": "114.6667" + }, + { + "iso": "BG", + "lat": "43", + "lng": "25" + }, + { + "iso": "BF", + "lat": "13", + "lng": "-2" + }, + { + "iso": "MM", + "lat": "22", + "lng": "98" + }, + { + "iso": "BI", + "lat": "-3.5", + "lng": "30" + }, + { + "iso": "KH", + "lat": "13", + "lng": "105" + }, + { + "iso": "CM", + "lat": "6", + "lng": "12" + }, + { + "iso": "CA", + "lat": "60", + "lng": "-95" + }, + { + "iso": "CV", + "lat": "16", + "lng": "-24" + }, + { + "iso": "KY", + "lat": "19.5", + "lng": "-80.5" + }, + { + "iso": "CF", + "lat": "7", + "lng": "21" + }, + { + "iso": "TD", + "lat": "15", + "lng": "19" + }, + { + "iso": "CL", + "lat": "-30", + "lng": "-71" + }, + { + "iso": "CN", + "lat": "35", + "lng": "105" + }, + { + "iso": "CX", + "lat": "-10.5", + "lng": "105.6667" + }, + { + "iso": "CC", + "lat": "-12.5", + "lng": "96.8333" + }, + { + "iso": "CO", + "lat": "4", + "lng": "-72" + }, + { + "iso": "KM", + "lat": "-12.1667", + "lng": "44.25" + }, + { + "iso": "the Democratic Republic of the", + "lat": "180", + "lng": "0" + }, + { + "iso": "CG", + "lat": "-1", + "lng": "15" + }, + { + "iso": "CK", + "lat": "-21.2333", + "lng": "-159.7667" + }, + { + "iso": "CR", + "lat": "10", + "lng": "-84" + }, + { + "iso": "CI", + "lat": "8", + "lng": "-5" + }, + { + "iso": "HR", + "lat": "45.1667", + "lng": "15.5" + }, + { + "iso": "CU", + "lat": "21.5", + "lng": "-80" + }, + { + "iso": "CW", + "lat": "12.166667", + "lng": "-68.966667" + }, + { + "iso": "CY", + "lat": "35", + "lng": "33" + }, + { + "iso": "CZ", + "lat": "49.75", + "lng": "15.5" + }, + { + "iso": "DK", + "lat": "56", + "lng": "10" + }, + { + "iso": "DJ", + "lat": "11.5", + "lng": "43" + }, + { + "iso": "DM", + "lat": "15.4167", + "lng": "-61.3333" + }, + { + "iso": "DO", + "lat": "19", + "lng": "-70.6667" + }, + { + "iso": "EC", + "lat": "-2", + "lng": "-77.5" + }, + { + "iso": "EG", + "lat": "27", + "lng": "30" + }, + { + "iso": "SV", + "lat": "13.8333", + "lng": "-88.9167" + }, + { + "iso": "GQ", + "lat": "2", + "lng": "10" + }, + { + "iso": "ER", + "lat": "15", + "lng": "39" + }, + { + "iso": "EE", + "lat": "59", + "lng": "26" + }, + { + "iso": "ET", + "lat": "8", + "lng": "38" + }, + { + "iso": "FK", + "lat": "-51.75", + "lng": "-59" + }, + { + "iso": "FO", + "lat": "62", + "lng": "-7" + }, + { + "iso": "FJ", + "lat": "-18", + "lng": "175" + }, + { + "iso": "FI", + "lat": "64", + "lng": "26" + }, + { + "iso": "FR", + "lat": "46", + "lng": "2" + }, + { + "iso": "GF", + "lat": "4", + "lng": "-53" + }, + { + "iso": "PF", + "lat": "-15", + "lng": "-140" + }, + { + "iso": "TF", + "lat": "-43", + "lng": "67" + }, + { + "iso": "GA", + "lat": "-1", + "lng": "11.75" + }, + { + "iso": "GM", + "lat": "13.4667", + "lng": "-16.5667" + }, + { + "iso": "GE", + "lat": "42", + "lng": "43.5" + }, + { + "iso": "DE", + "lat": "51", + "lng": "9" + }, + { + "iso": "GH", + "lat": "8", + "lng": "-2" + }, + { + "iso": "GI", + "lat": "36.1833", + "lng": "-5.3667" + }, + { + "iso": "GR", + "lat": "39", + "lng": "22" + }, + { + "iso": "GL", + "lat": "72", + "lng": "-40" + }, + { + "iso": "GD", + "lat": "12.1167", + "lng": "-61.6667" + }, + { + "iso": "GP", + "lat": "16.25", + "lng": "-61.5833" + }, + { + "iso": "GU", + "lat": "13.4667", + "lng": "144.7833" + }, + { + "iso": "GT", + "lat": "15.5", + "lng": "-90.25" + }, + { + "iso": "GG", + "lat": "49.5", + "lng": "-2.56" + }, + { + "iso": "GW", + "lat": "12", + "lng": "-15" + }, + { + "iso": "GN", + "lat": "11", + "lng": "-10" + }, + { + "iso": "GY", + "lat": "5", + "lng": "-59" + }, + { + "iso": "HT", + "lat": "19", + "lng": "-72.4167" + }, + { + "iso": "HM", + "lat": "-53.1", + "lng": "72.5167" + }, + { + "iso": "VA", + "lat": "41.9", + "lng": "12.45" + }, + { + "iso": "HN", + "lat": "15", + "lng": "-86.5" + }, + { + "iso": "HK", + "lat": "22.25", + "lng": "114.1667" + }, + { + "iso": "HU", + "lat": "47", + "lng": "20" + }, + { + "iso": "IS", + "lat": "65", + "lng": "-18" + }, + { + "iso": "IN", + "lat": "20", + "lng": "77" + }, + { + "iso": "ID", + "lat": "-5", + "lng": "120" + }, + { + "iso": "Islamic Republic of", + "lat": "364", + "lng": "32" + }, + { + "iso": "IQ", + "lat": "33", + "lng": "44" + }, + { + "iso": "IE", + "lat": "53", + "lng": "-8" + }, + { + "iso": "IM", + "lat": "54.23", + "lng": "-4.55" + }, + { + "iso": "IL", + "lat": "31.5", + "lng": "34.75" + }, + { + "iso": "IT", + "lat": "42.8333", + "lng": "12.8333" + }, + { + "iso": "CI", + "lat": "8", + "lng": "-5" + }, + { + "iso": "JM", + "lat": "18.25", + "lng": "-77.5" + }, + { + "iso": "JP", + "lat": "36", + "lng": "138" + }, + { + "iso": "JE", + "lat": "49.21", + "lng": "-2.13" + }, + { + "iso": "JO", + "lat": "31", + "lng": "36" + }, + { + "iso": "KZ", + "lat": "48", + "lng": "68" + }, + { + "iso": "KE", + "lat": "1", + "lng": "38" + }, + { + "iso": "KI", + "lat": "1.4167", + "lng": "173" + }, + { + "iso": "Democratic People's Republic of", + "lat": "408", + "lng": "40" + }, + { + "iso": "Republic of", + "lat": "410", + "lng": "37" + }, + { + "iso": "XK", + "lat": "42.583333", + "lng": "21" + }, + { + "iso": "KW", + "lat": "29.3375", + "lng": "47.6581" + }, + { + "iso": "KG", + "lat": "41", + "lng": "75" + }, + { + "iso": "LA", + "lat": "18", + "lng": "105" + }, + { + "iso": "LV", + "lat": "57", + "lng": "25" + }, + { + "iso": "LB", + "lat": "33.8333", + "lng": "35.8333" + }, + { + "iso": "LS", + "lat": "-29.5", + "lng": "28.5" + }, + { + "iso": "LR", + "lat": "6.5", + "lng": "-9.5" + }, + { + "iso": "LY", + "lat": "25", + "lng": "17" + }, + { + "iso": "LY", + "lat": "25", + "lng": "17" + }, + { + "iso": "LI", + "lat": "47.1667", + "lng": "9.5333" + }, + { + "iso": "LT", + "lat": "56", + "lng": "24" + }, + { + "iso": "LU", + "lat": "49.75", + "lng": "6.1667" + }, + { + "iso": "MO", + "lat": "22.1667", + "lng": "113.55" + }, + { + "iso": "the former Yugoslav Republic of", + "lat": "807", + "lng": "41.8333" + }, + { + "iso": "MG", + "lat": "-20", + "lng": "47" + }, + { + "iso": "MW", + "lat": "-13.5", + "lng": "34" + }, + { + "iso": "MY", + "lat": "2.5", + "lng": "112.5" + }, + { + "iso": "MV", + "lat": "3.25", + "lng": "73" + }, + { + "iso": "ML", + "lat": "17", + "lng": "-4" + }, + { + "iso": "MT", + "lat": "35.8333", + "lng": "14.5833" + }, + { + "iso": "MH", + "lat": "9", + "lng": "168" + }, + { + "iso": "MQ", + "lat": "14.6667", + "lng": "-61" + }, + { + "iso": "MR", + "lat": "20", + "lng": "-12" + }, + { + "iso": "MU", + "lat": "-20.2833", + "lng": "57.55" + }, + { + "iso": "YT", + "lat": "-12.8333", + "lng": "45.1667" + }, + { + "iso": "MX", + "lat": "23", + "lng": "-102" + }, + { + "iso": "Federated States of", + "lat": "583", + "lng": "6.9167" + }, + { + "iso": "Republic of", + "lat": "498", + "lng": "47" + }, + { + "iso": "MC", + "lat": "43.7333", + "lng": "7.4" + }, + { + "iso": "MN", + "lat": "46", + "lng": "105" + }, + { + "iso": "ME", + "lat": "42", + "lng": "19" + }, + { + "iso": "MS", + "lat": "16.75", + "lng": "-62.2" + }, + { + "iso": "MA", + "lat": "32", + "lng": "-5" + }, + { + "iso": "MZ", + "lat": "-18.25", + "lng": "35" + }, + { + "iso": "MM", + "lat": "22", + "lng": "98" + }, + { + "iso": "NA", + "lat": "-22", + "lng": "17" + }, + { + "iso": "NR", + "lat": "-0.5333", + "lng": "166.9167" + }, + { + "iso": "NP", + "lat": "28", + "lng": "84" + }, + { + "iso": "AN", + "lat": "12.25", + "lng": "-68.75" + }, + { + "iso": "NL", + "lat": "52.5", + "lng": "5.75" + }, + { + "iso": "NC", + "lat": "-21.5", + "lng": "165.5" + }, + { + "iso": "NZ", + "lat": "-41", + "lng": "174" + }, + { + "iso": "NI", + "lat": "13", + "lng": "-85" + }, + { + "iso": "NE", + "lat": "16", + "lng": "8" + }, + { + "iso": "NG", + "lat": "10", + "lng": "8" + }, + { + "iso": "NU", + "lat": "-19.0333", + "lng": "-169.8667" + }, + { + "iso": "NF", + "lat": "-29.0333", + "lng": "167.95" + }, + { + "iso": "MP", + "lat": "15.2", + "lng": "145.75" + }, + { + "iso": "NO", + "lat": "62", + "lng": "10" + }, + { + "iso": "OM", + "lat": "21", + "lng": "57" + }, + { + "iso": "PK", + "lat": "30", + "lng": "70" + }, + { + "iso": "PW", + "lat": "7.5", + "lng": "134.5" + }, + { + "iso": "Occupied", + "lat": "275", + "lng": "32" + }, + { + "iso": "PA", + "lat": "9", + "lng": "-80" + }, + { + "iso": "PG", + "lat": "-6", + "lng": "147" + }, + { + "iso": "PY", + "lat": "-23", + "lng": "-58" + }, + { + "iso": "PE", + "lat": "-10", + "lng": "-76" + }, + { + "iso": "PH", + "lat": "13", + "lng": "122" + }, + { + "iso": "PN", + "lat": "-24.7", + "lng": "-127.4" + }, + { + "iso": "PL", + "lat": "52", + "lng": "20" + }, + { + "iso": "PT", + "lat": "39.5", + "lng": "-8" + }, + { + "iso": "PR", + "lat": "18.25", + "lng": "-66.5" + }, + { + "iso": "QA", + "lat": "25.5", + "lng": "51.25" + }, + { + "iso": "RE", + "lat": "-21.1", + "lng": "55.6" + }, + { + "iso": "RO", + "lat": "46", + "lng": "25" + }, + { + "iso": "RU", + "lat": "60", + "lng": "100" + }, + { + "iso": "RU", + "lat": "60", + "lng": "100" + }, + { + "iso": "RW", + "lat": "-2", + "lng": "30" + }, + { + "iso": "BL", + "lat": "17.897728", + "lng": "-62.834244" + }, + { + "iso": "Ascension and Tristan da Cunha", + "lat": "654", + "lng": "-15.9333" + }, + { + "iso": "KN", + "lat": "17.3333", + "lng": "-62.75" + }, + { + "iso": "LC", + "lat": "13.8833", + "lng": "-61.1333" + }, + { + "iso": "MF", + "lat": "18.075278", + "lng": "-63.06" + }, + { + "iso": "PM", + "lat": "46.8333", + "lng": "-56.3333" + }, + { + "iso": "VC", + "lat": "13.25", + "lng": "-61.2" + }, + { + "iso": "VC", + "lat": "13.25", + "lng": "-61.2" + }, + { + "iso": "WS", + "lat": "-13.5833", + "lng": "-172.3333" + }, + { + "iso": "SM", + "lat": "43.7667", + "lng": "12.4167" + }, + { + "iso": "ST", + "lat": "1", + "lng": "7" + }, + { + "iso": "SA", + "lat": "25", + "lng": "45" + }, + { + "iso": "SN", + "lat": "14", + "lng": "-14" + }, + { + "iso": "RS", + "lat": "44", + "lng": "21" + }, + { + "iso": "SC", + "lat": "-4.5833", + "lng": "55.6667" + }, + { + "iso": "SL", + "lat": "8.5", + "lng": "-11.5" + }, + { + "iso": "SG", + "lat": "1.3667", + "lng": "103.8" + }, + { + "iso": "SX", + "lat": "18.033333", + "lng": "-63.05" + }, + { + "iso": "SK", + "lat": "48.6667", + "lng": "19.5" + }, + { + "iso": "SI", + "lat": "46", + "lng": "15" + }, + { + "iso": "SB", + "lat": "-8", + "lng": "159" + }, + { + "iso": "SO", + "lat": "10", + "lng": "49" + }, + { + "iso": "ZA", + "lat": "-29", + "lng": "24" + }, + { + "iso": "GS", + "lat": "-54.5", + "lng": "-37" + }, + { + "iso": "KR", + "lat": "37", + "lng": "127.5" + }, + { + "iso": "SS", + "lat": "8", + "lng": "30" + }, + { + "iso": "ES", + "lat": "40", + "lng": "-4" + }, + { + "iso": "LK", + "lat": "7", + "lng": "81" + }, + { + "iso": "VC", + "lat": "13.25", + "lng": "-61.2" + }, + { + "iso": "SD", + "lat": "15", + "lng": "30" + }, + { + "iso": "SR", + "lat": "4", + "lng": "-56" + }, + { + "iso": "SJ", + "lat": "78", + "lng": "20" + }, + { + "iso": "SZ", + "lat": "-26.5", + "lng": "31.5" + }, + { + "iso": "SE", + "lat": "62", + "lng": "15" + }, + { + "iso": "CH", + "lat": "47", + "lng": "8" + }, + { + "iso": "SY", + "lat": "35", + "lng": "38" + }, + { + "iso": "TW", + "lat": "23.5", + "lng": "121" + }, + { + "iso": "TJ", + "lat": "39", + "lng": "71" + }, + { + "iso": "United Republic of", + "lat": "834", + "lng": "-6" + }, + { + "iso": "TH", + "lat": "15", + "lng": "100" + }, + { + "iso": "TL", + "lat": "-8.55", + "lng": "125.5167" + }, + { + "iso": "TG", + "lat": "8", + "lng": "1.1667" + }, + { + "iso": "TK", + "lat": "-9", + "lng": "-172" + }, + { + "iso": "TO", + "lat": "-20", + "lng": "-175" + }, + { + "iso": "TT", + "lat": "11", + "lng": "-61" + }, + { + "iso": "TN", + "lat": "34", + "lng": "9" + }, + { + "iso": "TR", + "lat": "39", + "lng": "35" + }, + { + "iso": "TM", + "lat": "40", + "lng": "60" + }, + { + "iso": "TC", + "lat": "21.75", + "lng": "-71.5833" + }, + { + "iso": "TV", + "lat": "-8", + "lng": "178" + }, + { + "iso": "UG", + "lat": "1", + "lng": "32" + }, + { + "iso": "UA", + "lat": "49", + "lng": "32" + }, + { + "iso": "AE", + "lat": "24", + "lng": "54" + }, + { + "iso": "GB", + "lat": "54", + "lng": "-2" + }, + { + "iso": "UM", + "lat": "19.2833", + "lng": "166.6" + }, + { + "iso": "US", + "lat": "38", + "lng": "-97" + }, + { + "iso": "UY", + "lat": "-33", + "lng": "-56" + }, + { + "iso": "UZ", + "lat": "41", + "lng": "64" + }, + { + "iso": "VU", + "lat": "-16", + "lng": "167" + }, + { + "iso": "Bolivarian Republic of", + "lat": "862", + "lng": "8" + }, + { + "iso": "VE", + "lat": "8", + "lng": "-66" + }, + { + "iso": "VN", + "lat": "16", + "lng": "106" + }, + { + "iso": "VN", + "lat": "16", + "lng": "106" + }, + { + "iso": "British", + "lat": "92", + "lng": "18.5" + }, + { + "iso": "U.S.", + "lat": "850", + "lng": "18.3333" + }, + { + "iso": "WF", + "lat": "-13.3", + "lng": "-176.2" + }, + { + "iso": "EH", + "lat": "24.5", + "lng": "-13" + }, + { + "iso": "YE", + "lat": "15", + "lng": "48" + }, + { + "iso": "ZM", + "lat": "-15", + "lng": "30" + }, + { + "iso": "ZW", + "lat": "-20", + "lng": "30" + } +] \ No newline at end of file diff --git a/src/components/Peers/types.ts b/src/components/Peers/types.ts new file mode 100644 index 0000000..a3e1bea --- /dev/null +++ b/src/components/Peers/types.ts @@ -0,0 +1,4 @@ +export type PeerPin = { + lat: number; + lng: number; +}; \ No newline at end of file diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts index 2484188..3441411 100644 --- a/src/routeTree.gen.ts +++ b/src/routeTree.gen.ts @@ -17,6 +17,7 @@ import { Route as DashboardIndexImport } from './routes/dashboard/index' import { Route as DashboardSettingsImport } from './routes/dashboard/settings' import { Route as DashboardRequestsImport } from './routes/dashboard/requests' import { Route as DashboardPurchasesImport } from './routes/dashboard/purchases' +import { Route as DashboardPeersImport } from './routes/dashboard/peers' import { Route as DashboardHelpImport } from './routes/dashboard/help' import { Route as DashboardFavoritesImport } from './routes/dashboard/favorites' import { Route as DashboardDisclaimerImport } from './routes/dashboard/disclaimer' @@ -55,6 +56,11 @@ const DashboardPurchasesRoute = DashboardPurchasesImport.update({ getParentRoute: () => DashboardRoute, } as any) +const DashboardPeersRoute = DashboardPeersImport.update({ + path: '/peers', + getParentRoute: () => DashboardRoute, +} as any) + const DashboardHelpRoute = DashboardHelpImport.update({ path: '/help', getParentRoute: () => DashboardRoute, @@ -133,6 +139,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof DashboardHelpImport parentRoute: typeof DashboardImport } + '/dashboard/peers': { + id: '/dashboard/peers' + path: '/peers' + fullPath: '/dashboard/peers' + preLoaderRoute: typeof DashboardPeersImport + parentRoute: typeof DashboardImport + } '/dashboard/purchases': { id: '/dashboard/purchases' path: '/purchases' @@ -172,6 +185,7 @@ interface DashboardRouteChildren { DashboardDisclaimerRoute: typeof DashboardDisclaimerRoute DashboardFavoritesRoute: typeof DashboardFavoritesRoute DashboardHelpRoute: typeof DashboardHelpRoute + DashboardPeersRoute: typeof DashboardPeersRoute DashboardPurchasesRoute: typeof DashboardPurchasesRoute DashboardRequestsRoute: typeof DashboardRequestsRoute DashboardSettingsRoute: typeof DashboardSettingsRoute @@ -184,6 +198,7 @@ const DashboardRouteChildren: DashboardRouteChildren = { DashboardDisclaimerRoute: DashboardDisclaimerRoute, DashboardFavoritesRoute: DashboardFavoritesRoute, DashboardHelpRoute: DashboardHelpRoute, + DashboardPeersRoute: DashboardPeersRoute, DashboardPurchasesRoute: DashboardPurchasesRoute, DashboardRequestsRoute: DashboardRequestsRoute, DashboardSettingsRoute: DashboardSettingsRoute, @@ -202,6 +217,7 @@ export interface FileRoutesByFullPath { '/dashboard/disclaimer': typeof DashboardDisclaimerRoute '/dashboard/favorites': typeof DashboardFavoritesRoute '/dashboard/help': typeof DashboardHelpRoute + '/dashboard/peers': typeof DashboardPeersRoute '/dashboard/purchases': typeof DashboardPurchasesRoute '/dashboard/requests': typeof DashboardRequestsRoute '/dashboard/settings': typeof DashboardSettingsRoute @@ -215,6 +231,7 @@ export interface FileRoutesByTo { '/dashboard/disclaimer': typeof DashboardDisclaimerRoute '/dashboard/favorites': typeof DashboardFavoritesRoute '/dashboard/help': typeof DashboardHelpRoute + '/dashboard/peers': typeof DashboardPeersRoute '/dashboard/purchases': typeof DashboardPurchasesRoute '/dashboard/requests': typeof DashboardRequestsRoute '/dashboard/settings': typeof DashboardSettingsRoute @@ -230,6 +247,7 @@ export interface FileRoutesById { '/dashboard/disclaimer': typeof DashboardDisclaimerRoute '/dashboard/favorites': typeof DashboardFavoritesRoute '/dashboard/help': typeof DashboardHelpRoute + '/dashboard/peers': typeof DashboardPeersRoute '/dashboard/purchases': typeof DashboardPurchasesRoute '/dashboard/requests': typeof DashboardRequestsRoute '/dashboard/settings': typeof DashboardSettingsRoute @@ -246,6 +264,7 @@ export interface FileRouteTypes { | '/dashboard/disclaimer' | '/dashboard/favorites' | '/dashboard/help' + | '/dashboard/peers' | '/dashboard/purchases' | '/dashboard/requests' | '/dashboard/settings' @@ -258,6 +277,7 @@ export interface FileRouteTypes { | '/dashboard/disclaimer' | '/dashboard/favorites' | '/dashboard/help' + | '/dashboard/peers' | '/dashboard/purchases' | '/dashboard/requests' | '/dashboard/settings' @@ -271,6 +291,7 @@ export interface FileRouteTypes { | '/dashboard/disclaimer' | '/dashboard/favorites' | '/dashboard/help' + | '/dashboard/peers' | '/dashboard/purchases' | '/dashboard/requests' | '/dashboard/settings' @@ -315,6 +336,7 @@ export const routeTree = rootRoute "/dashboard/disclaimer", "/dashboard/favorites", "/dashboard/help", + "/dashboard/peers", "/dashboard/purchases", "/dashboard/requests", "/dashboard/settings", @@ -341,6 +363,10 @@ export const routeTree = rootRoute "filePath": "dashboard/help.tsx", "parent": "/dashboard" }, + "/dashboard/peers": { + "filePath": "dashboard/peers.tsx", + "parent": "/dashboard" + }, "/dashboard/purchases": { "filePath": "dashboard/purchases.tsx", "parent": "/dashboard" diff --git a/src/routes/dashboard.tsx b/src/routes/dashboard.tsx index c50f33a..fea649d 100644 --- a/src/routes/dashboard.tsx +++ b/src/routes/dashboard.tsx @@ -12,6 +12,7 @@ import { Settings, HelpCircle, TriangleAlert, + Earth, } from "lucide-react"; import { ICON_SIZE } from "../utils/constants"; import { NodeIndicator } from "../components/NodeIndicator/NodeIndicator"; @@ -87,6 +88,15 @@ const Layout = () => { ), }, + { + type: "menu-item", + Component: (p: MenuItemComponentProps) => ( + + + Peers + + ), + }, { type: "menu-item", Component: (p: MenuItemComponentProps) => ( diff --git a/src/routes/dashboard/peers.css b/src/routes/dashboard/peers.css new file mode 100644 index 0000000..e017a11 --- /dev/null +++ b/src/routes/dashboard/peers.css @@ -0,0 +1,10 @@ +.peers-map, +.peers-table { + max-width: 1000px; + margin: auto; +} + +.peers-table { + margin-top: 1rem; + width: 100%; +} diff --git a/src/routes/dashboard/peers.tsx b/src/routes/dashboard/peers.tsx new file mode 100644 index 0000000..b0f836e --- /dev/null +++ b/src/routes/dashboard/peers.tsx @@ -0,0 +1,98 @@ +import { Cell, Row, Table } from "@codex-storage/marketplace-ui-components"; +import { createFileRoute } from "@tanstack/react-router"; +import { getMapJSON } from "dotted-map"; +import DottedMap from "dotted-map/without-countries"; +import { Promises } from "../../utils/promises"; +import { useQuery } from "@tanstack/react-query"; +import { PeerCountryCell } from "../../components/Peers/PeerCountryCell"; +import { useCallback, useState } from "react"; +import { PeerPin } from "../../components/Peers/types"; +import "./peers.css"; +import { CodexSdk } from "../../sdk/codex"; + +// This function accepts the same arguments as DottedMap in the example above. +const mapJsonString = getMapJSON({ height: 60, grid: "diagonal" }); + +export const Route = createFileRoute("/dashboard/peers")({ + component: () => { + const [pins, setPins] = useState<[PeerPin, number][]>([]); + const { data } = useQuery({ + queryFn: () => + CodexSdk.debug.info().then((s) => Promises.rejectOnError(s)), + queryKey: ["debug"], + + // No need to retry because if the connection to the node + // is back again, all the queries will be invalidated. + retry: false, + + // The client node should be local, so display the cache value while + // making a background request looks good. + staleTime: 0, + + // Refreshing when focus returns can be useful if a user comes back + // to the UI after performing an operation in the terminal. + refetchOnWindowFocus: true, + + // Throw the error to the error boundary + throwOnError: true, + }); + + const onPinAdd = useCallback((pin: PeerPin) => { + setPins((val) => { + const [, quantity = 0] = + val.find(([p]) => p.lat === pin.lat && p.lng == pin.lng) || []; + return [...val, [pin, quantity + 1]]; + }); + }, []); + + // It’s safe to re-create the map at each render, because of the + // pre-computation it’s super fast ⚡️ + const map = new DottedMap({ map: JSON.parse(mapJsonString) }); + + pins.map(([pin, quantity]) => + map.addPin({ + lat: pin.lat, + lng: pin.lng, + svgOptions: { color: "#d6ff79", radius: 0.4 * quantity }, + }) + ); + + const svgMap = map.getSVG({ + radius: 0.42, + color: "#423B38", + shape: "circle", + backgroundColor: "#020300", + }); + + const headers = ["Country", "PeerId", "Active"]; + + const rows = + ((data as any)?.table?.nodes || []).map((node: any) => ( + , + {node.peerId}, + + {node.seen ? ( +
+ ) : ( +
+ )} +
, + ]}>
+ )) || []; + + return ( + <> + + + + + ); + }, +});