mirror of
https://github.com/logos-storage/logos-storage-marketplace-ui.git
synced 2026-01-05 23:13:08 +00:00
Improve the worldmap display
This commit is contained in:
parent
29ceaea8c5
commit
b33c79788d
125
package-lock.json
generated
125
package-lock.json
generated
@ -15,6 +15,7 @@
|
||||
"@sentry/react": "^8.31.0",
|
||||
"@tanstack/react-query": "^5.51.15",
|
||||
"@tanstack/react-router": "^1.58.7",
|
||||
"dotted-map": "^2.2.3",
|
||||
"idb-keyval": "^6.2.1",
|
||||
"lucide-react": "^0.445.0",
|
||||
"react": "^18.3.1",
|
||||
@ -39,47 +40,6 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"../storybook": {
|
||||
"name": "@codex-storage/marketplace-ui-components",
|
||||
"version": "0.0.16",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lucide-react": "^0.441.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@chromatic-com/storybook": "^2.0.2",
|
||||
"@storybook/addon-essentials": "^8.2.9",
|
||||
"@storybook/addon-interactions": "^8.2.9",
|
||||
"@storybook/addon-links": "^8.2.9",
|
||||
"@storybook/addon-onboarding": "^8.2.9",
|
||||
"@storybook/blocks": "^8.2.9",
|
||||
"@storybook/react": "^8.2.9",
|
||||
"@storybook/react-vite": "^8.2.9",
|
||||
"@storybook/test": "^8.2.9",
|
||||
"@typescript-eslint/eslint-plugin": "^8.6.0",
|
||||
"@typescript-eslint/parser": "^8.0.0",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-react-refresh": "^0.4.7",
|
||||
"glob": "^9.3.5",
|
||||
"prettier": "^3.3.3",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"storybook": "^8.2.9",
|
||||
"typescript": "5.5.2",
|
||||
"vite-plugin-dts": "^4.0.3",
|
||||
"vite-plugin-lib-inject-css": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@codex-storage/sdk-js": "^0.0.6",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@ampproject/remapping": {
|
||||
"version": "2.3.0",
|
||||
"dev": true,
|
||||
@ -383,8 +343,28 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codex-storage/marketplace-ui-components": {
|
||||
"resolved": "../storybook",
|
||||
"link": true
|
||||
"version": "0.0.16",
|
||||
"resolved": "https://registry.npmjs.org/@codex-storage/marketplace-ui-components/-/marketplace-ui-components-0.0.16.tgz",
|
||||
"integrity": "sha512-49RQB/ld3EIZrFr/1GL7NB/cEI7TjnHRIBD3LJqZ2/ml+0gj//Mep85yV9Df1owiE2yyFh76bAeC8rUTo9cA/g==",
|
||||
"dependencies": {
|
||||
"lucide-react": "^0.441.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@codex-storage/sdk-js": "^0.0.6",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@codex-storage/marketplace-ui-components/node_modules/lucide-react": {
|
||||
"version": "0.441.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.441.0.tgz",
|
||||
"integrity": "sha512-0vfExYtvSDhkC2lqg0zYVW1Uu9GsI4knuV9GP9by5z0Xhc4Zi5RejTxfz9LsjRmCyWVzHCJvxGKZWcRyvQCWVg==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@codex-storage/sdk-js": {
|
||||
"version": "0.0.7",
|
||||
@ -1595,6 +1575,37 @@
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@turf/boolean-point-in-polygon": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-6.5.0.tgz",
|
||||
"integrity": "sha512-DtSuVFB26SI+hj0SjrvXowGTUCHlgevPAIsukssW6BG5MlNSBQAo70wpICBNJL6RjukXg8d2eXaAWuD/CqL00A==",
|
||||
"dependencies": {
|
||||
"@turf/helpers": "^6.5.0",
|
||||
"@turf/invariant": "^6.5.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/turf"
|
||||
}
|
||||
},
|
||||
"node_modules/@turf/helpers": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-6.5.0.tgz",
|
||||
"integrity": "sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw==",
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/turf"
|
||||
}
|
||||
},
|
||||
"node_modules/@turf/invariant": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-6.5.0.tgz",
|
||||
"integrity": "sha512-Wv8PRNCtPD31UVbdJE/KVAWKe7l6US+lJItRR/HOEW3eh+U/JwRCSUl/KZ7bmjM/C+zLNoreM2TU6OoLACs4eg==",
|
||||
"dependencies": {
|
||||
"@turf/helpers": "^6.5.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/turf"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/babel__core": {
|
||||
"version": "7.20.5",
|
||||
"dev": true,
|
||||
@ -2190,6 +2201,15 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dotted-map": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/dotted-map/-/dotted-map-2.2.3.tgz",
|
||||
"integrity": "sha512-8hyOOHHLLVCcCisM3yb9hqp+3bJ7TSMcr1SfrUw8Wxp5UMqih35jIvUyagweCooJbz/EH1nC9GGuPysh7+YlAg==",
|
||||
"dependencies": {
|
||||
"@turf/boolean-point-in-polygon": "^6.0.1",
|
||||
"proj4": "^2.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.2.0",
|
||||
"dev": true,
|
||||
@ -2899,6 +2919,11 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/mgrs": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mgrs/-/mgrs-1.0.0.tgz",
|
||||
"integrity": "sha512-awNbTOqCxK1DBGjalK3xqWIstBZgN6fxsMSiXLs9/spqWkF2pAhb2rrYCFSsr1/tT7PhcDGjZndG8SWYn0byYA=="
|
||||
},
|
||||
"node_modules/micromatch": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||
@ -3119,6 +3144,15 @@
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/proj4": {
|
||||
"version": "2.12.1",
|
||||
"resolved": "https://registry.npmjs.org/proj4/-/proj4-2.12.1.tgz",
|
||||
"integrity": "sha512-vmhP3hmstjXjzFwg8QXJwpoj4n7GVrXk3ZW3DzNK/Ur4cuwXq7ZiMXaWYvLYLQbX8n4MXgbwTr4lthOUZltBpA==",
|
||||
"dependencies": {
|
||||
"mgrs": "1.0.0",
|
||||
"wkt-parser": "^1.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"dev": true,
|
||||
@ -4019,6 +4053,11 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/wkt-parser": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.3.3.tgz",
|
||||
"integrity": "sha512-ZnV3yH8/k58ZPACOXeiHaMuXIiaTk1t0hSUVisbO0t4RjA5wPpUytcxeyiN2h+LZRrmuHIh/1UlrR9e7DHDvTw=="
|
||||
},
|
||||
"node_modules/word-wrap": {
|
||||
"version": "1.2.5",
|
||||
"dev": true,
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
"@sentry/react": "^8.31.0",
|
||||
"@tanstack/react-query": "^5.51.15",
|
||||
"@tanstack/react-router": "^1.58.7",
|
||||
"dotted-map": "^2.2.3",
|
||||
"idb-keyval": "^6.2.1",
|
||||
"lucide-react": "^0.445.0",
|
||||
"react": "^18.3.1",
|
||||
@ -55,4 +56,4 @@
|
||||
"author": "Codex team",
|
||||
"readme": "README.md",
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
5
src/components/Peers/PeerCountryCell.css
Normal file
5
src/components/Peers/PeerCountryCell.css
Normal file
@ -0,0 +1,5 @@
|
||||
.peerCountry {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
@ -1,7 +1,8 @@
|
||||
import { Cell } from "@codex-storage/marketplace-ui-components";
|
||||
import { useEffect, useState } from "react";
|
||||
import { PeerPin } from "./types";
|
||||
import { countriesCoordinates } from "./countries";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import "./PeerCountryCell.css";
|
||||
|
||||
export type Props = {
|
||||
address: string;
|
||||
@ -17,34 +18,56 @@ const getFlagEmoji = (countryCode: string) => {
|
||||
};
|
||||
|
||||
export function PeerCountryCell({ address, onPinAdd }: Props) {
|
||||
const [country, setCountry] = useState("");
|
||||
const { data } = useQuery({
|
||||
queryFn: () => {
|
||||
const [ip] = address.split(":");
|
||||
|
||||
useEffect(() => {
|
||||
const [ip] = address.split(":");
|
||||
return fetch(import.meta.env.VITE_GEO_IP_URL + "/" + ip)
|
||||
.then((res) => res.json())
|
||||
.then((json) => {
|
||||
const coordinate = countriesCoordinates.find(
|
||||
(c) => c.iso === json.country
|
||||
);
|
||||
|
||||
console.info(ip);
|
||||
if (coordinate) {
|
||||
onPinAdd({
|
||||
lat: parseFloat(coordinate.lat),
|
||||
lng: parseFloat(coordinate.lng),
|
||||
});
|
||||
}
|
||||
|
||||
fetch("https://api.country.is/" + ip)
|
||||
.then((res) => res.json())
|
||||
.then((json) => {
|
||||
setCountry(json.country);
|
||||
return coordinate;
|
||||
});
|
||||
},
|
||||
queryKey: [address],
|
||||
|
||||
const coordinate = countriesCoordinates.find(
|
||||
(c) => c.iso === json.country
|
||||
);
|
||||
// Enable only when the address exists
|
||||
enabled: !!address,
|
||||
|
||||
if (coordinate) {
|
||||
onPinAdd({
|
||||
lat: parseFloat(coordinate.lat),
|
||||
lng: parseFloat(coordinate.lng),
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [address]);
|
||||
// No need to retry because if the connection to the node
|
||||
// is back again, all the queries will be invalidated.
|
||||
retry: false,
|
||||
|
||||
// We can cache the data at Infinity because the relation between
|
||||
// country and ip is fixed
|
||||
staleTime: Infinity,
|
||||
|
||||
// Don't expect something new when coming back to the UI
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
|
||||
return (
|
||||
<Cell>
|
||||
{getFlagEmoji(country)} {address}
|
||||
<div className="peerCountry">
|
||||
{data ? (
|
||||
<>
|
||||
<span> {!!data && getFlagEmoji(data.iso)}</span>
|
||||
<span>{data?.name}</span>
|
||||
</>
|
||||
) : (
|
||||
<span>{address}</span>
|
||||
)}
|
||||
</div>
|
||||
</Cell>
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,41 @@
|
||||
.peers-map,
|
||||
.peers-table {
|
||||
.peers-map {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.peers-table {
|
||||
margin-top: 1rem;
|
||||
width: 100%;
|
||||
width: calc(100% - 4rem);
|
||||
max-width: calc(1000px - 4rem);
|
||||
}
|
||||
|
||||
.peers {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 4rem;
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
.peers circle[fill="#d6ff79"] {
|
||||
/* fill: yellow; */
|
||||
animation: dash 3s linear infinite;
|
||||
stroke: white;
|
||||
stroke-width: 0.6px;
|
||||
stroke-dasharray: 0.3;
|
||||
}
|
||||
|
||||
@keyframes dash {
|
||||
from {
|
||||
stroke-dashoffset: 2;
|
||||
}
|
||||
to {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
@keyframes circleAn {
|
||||
to {
|
||||
/* stroke-dashoffset: 100px; */
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ export const Route = createFileRoute("/dashboard/peers")({
|
||||
map.addPin({
|
||||
lat: pin.lat,
|
||||
lng: pin.lng,
|
||||
svgOptions: { color: "#d6ff79", radius: 0.4 * quantity },
|
||||
svgOptions: { color: "#d6ff79", radius: 0.8 * quantity },
|
||||
})
|
||||
);
|
||||
|
||||
@ -85,14 +85,18 @@ export const Route = createFileRoute("/dashboard/peers")({
|
||||
)) || [];
|
||||
|
||||
return (
|
||||
<>
|
||||
<img
|
||||
<div className="peers">
|
||||
{/* <img
|
||||
src={`data:image/svg+xml;utf8,${encodeURIComponent(svgMap)}`}
|
||||
className="peers-map"
|
||||
/>
|
||||
/> */}
|
||||
|
||||
<div
|
||||
className="peers-map"
|
||||
dangerouslySetInnerHTML={{ __html: svgMap }}></div>
|
||||
|
||||
<Table headers={headers} rows={rows} className="peers-table" />
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user