diff --git a/explorer-nextjs/app/network-components/nodes/[id]/page.tsx b/explorer-nextjs/app/network-components/nodes/[id]/page.tsx
index 2f92542b3b..95a172d21e 100644
--- a/explorer-nextjs/app/network-components/nodes/[id]/page.tsx
+++ b/explorer-nextjs/app/network-components/nodes/[id]/page.tsx
@@ -1,62 +1,62 @@
-'use client'
+"use client";
-import * as React from 'react'
-import { Alert, AlertTitle, Box, CircularProgress, Grid } from '@mui/material'
-import { useParams } from 'next/navigation'
-import { ColumnsType, DetailTable } from '@/app/components/DetailTable'
-import { ComponentError } from '@/app/components/ComponentError'
-import { ContentCard } from '@/app/components/ContentCard'
-import { UptimeChart } from '@/app/components/UptimeChart'
-import {
- NymNodeContextProvider,
- useNymNodeContext,
-} from '@/app/context/node'
-import { useMainContext } from '@/app/context/main'
-import { Title } from '@/app/components/Title'
+import * as React from "react";
+import { Alert, AlertTitle, Box, CircularProgress, Grid } from "@mui/material";
+import { useParams } from "next/navigation";
+import { ColumnsType, DetailTable } from "@/app/components/DetailTable";
+import { ComponentError } from "@/app/components/ComponentError";
+import { ContentCard } from "@/app/components/ContentCard";
+import { UptimeChart } from "@/app/components/UptimeChart";
+import { NymNodeContextProvider, useNymNodeContext } from "@/app/context/node";
+import { useMainContext } from "@/app/context/main";
+import { Title } from "@/app/components/Title";
import Paper from "@mui/material/Paper";
-import Table from '@mui/material/Table';
-import TableBody from '@mui/material/TableBody';
-import TableCell from '@mui/material/TableCell';
-import TableContainer from '@mui/material/TableContainer';
-import TableRow from '@mui/material/TableRow';
-import {humanReadableCurrencyToString} from "@/app/utils/currency";
-import {DeclaredRole} from "@/app/network-components/nodes/DeclaredRole";
-import {NodeDelegationsTable, VestingDelegationWarning} from "@/app/network-components/nodes/[id]/NodeDelegationsTable";
+import Table from "@mui/material/Table";
+import TableBody from "@mui/material/TableBody";
+import TableCell from "@mui/material/TableCell";
+import TableContainer from "@mui/material/TableContainer";
+import TableRow from "@mui/material/TableRow";
+import { humanReadableCurrencyToString } from "@/app/utils/currency";
+import { DeclaredRole } from "@/app/network-components/nodes/DeclaredRole";
+import {
+ NodeDelegationsTable,
+ VestingDelegationWarning,
+} from "@/app/network-components/nodes/[id]/NodeDelegationsTable";
const columns: ColumnsType[] = [
{
- field: 'identity_key',
- title: 'Identity Key',
- headerAlign: 'left',
+ field: "identity_key",
+ title: "Identity Key",
+ headerAlign: "left",
width: 230,
},
{
- field: 'bond',
- title: 'Bond',
- headerAlign: 'left',
+ field: "bond",
+ title: "Bond",
+ headerAlign: "left",
},
{
- field: 'host',
- title: 'IP',
- headerAlign: 'left',
+ field: "host",
+ title: "IP",
+ headerAlign: "left",
width: 99,
},
{
- field: 'location',
- title: 'Location',
- headerAlign: 'left',
+ field: "location",
+ title: "Location",
+ headerAlign: "left",
},
{
- field: 'owner',
- title: 'Owner',
- headerAlign: 'left',
+ field: "owner",
+ title: "Owner",
+ headerAlign: "left",
},
{
- field: 'version',
- title: 'Version',
- headerAlign: 'left',
+ field: "version",
+ title: "Version",
+ headerAlign: "left",
},
-]
+];
interface NodeEnrichedRowType {
node_id: number;
@@ -71,28 +71,33 @@ interface NodeEnrichedRowType {
function nodeEnrichedToGridRow(node: any): NodeEnrichedRowType {
return {
node_id: node.node_id,
- owner: node.bond_information?.owner || '',
- identity_key: node.bond_information?.node?.identity_key || '',
- location: node.location?.country_name || '',
+ owner: node.bond_information?.owner || "",
+ identity_key: node.bond_information?.node?.identity_key || "",
+ location: node.location?.country_name || "",
bond: node.bond_information?.original_pledge.amount || 0, // TODO: format
- host: node.bond_information?.node?.host || '',
- version: node.description?.build_information?.build_version || '',
+ host: node.bond_information?.node?.host || "",
+ version: node.description?.build_information?.build_version || "",
};
}
-
/**
* Shows nym node details
*/
const PageNymNodeDetailsWithState = ({
selectedNymNode,
}: {
- selectedNymNode?: any
+ selectedNymNode?: any;
}) => {
- const { uptimeHistory } = useNymNodeContext()
- const enrichedData = React.useMemo(() => selectedNymNode ? [nodeEnrichedToGridRow(selectedNymNode)] : [], []);
+ const { uptimeHistory } = useNymNodeContext();
+ const enrichedData = React.useMemo(
+ () => (selectedNymNode ? [nodeEnrichedToGridRow(selectedNymNode)] : []),
+ []
+ );
- const hasVestingContractDelegations = React.useMemo(() => selectedNymNode?.delegations?.filter((d: any) => d.proxy)?.length, [selectedNymNode]);
+ const hasVestingContractDelegations = React.useMemo(
+ () => selectedNymNode?.delegations?.filter((d: any) => d.proxy)?.length,
+ [selectedNymNode]
+ );
return (
@@ -109,81 +114,128 @@ const PageNymNodeDetailsWithState = ({
- {selectedNymNode.rewarding_details &&
-
-
-
-
-
-
- Delegations and Rewards
-
-
-
-
- Operator
-
-
- {humanReadableCurrencyToString({ amount : selectedNymNode.rewarding_details.operator.split('.')[0], denom: "unym" })}
-
-
-
-
-
- {hasVestingContractDelegations ?
-
- Delegates ({selectedNymNode.rewarding_details.unique_delegations} delegates)
- :
- <>Delegates ({selectedNymNode.rewarding_details.unique_delegations} delegates)>
- }
-
-
-
- {humanReadableCurrencyToString({ amount : selectedNymNode.rewarding_details.delegates.split('.')[0], denom: "unym" })}
-
-
-
-
- Profit margin
-
-
- {selectedNymNode.rewarding_details.cost_params.profit_margin_percent * 100}%
-
-
-
-
- Operator costs
-
-
- {humanReadableCurrencyToString(selectedNymNode.rewarding_details.cost_params.interval_operating_cost)}
-
-
-
-
-
- }
+ {selectedNymNode.rewarding_details && (
+
+
+
+
+
+ Delegations and Rewards
+
+
+
+ Operator
+
+
+ {humanReadableCurrencyToString({
+ amount:
+ selectedNymNode.rewarding_details.operator.split(
+ "."
+ )[0],
+ denom: "unym",
+ })}
+
+
+
+
+
+ {hasVestingContractDelegations ? (
+
+ Delegates (
+ {
+ selectedNymNode.rewarding_details
+ .unique_delegations
+ }{" "}
+ delegates)
+
+ ) : (
+ <>
+ Delegates (
+ {
+ selectedNymNode.rewarding_details
+ .unique_delegations
+ }{" "}
+ delegates)
+ >
+ )}
+
+
+
+ {humanReadableCurrencyToString({
+ amount:
+ selectedNymNode.rewarding_details.delegates.split(
+ "."
+ )[0],
+ denom: "unym",
+ })}
+
+
+
+
+ Profit margin
+
+
+ {selectedNymNode.rewarding_details.cost_params
+ .profit_margin_percent * 100}
+ %
+
+
+
+
+ Operator costs
+
+
+ {humanReadableCurrencyToString(
+ selectedNymNode.rewarding_details.cost_params
+ .interval_operating_cost
+ )}
+
+
+
+
+
+
+ )}
- {selectedNymNode.description?.declared_role &&
-
-
-
-
-
- Node roles
-
-
-
-
- Self declared roles
-
-
-
-
-
-
-
-
- }
+ {selectedNymNode.description?.declared_role && (
+
+
+
+
+
+ Node roles
+
+
+ Self declared roles
+
+
+
+
+
+
+
+
+ )}
@@ -205,42 +257,41 @@ const PageNymNodeDetailsWithState = ({
-
+
- )
-}
+ );
+};
/**
* Guard component to handle loading and not found states
*/
const PageNymNodeDetailGuard = () => {
- const [selectedNode, setSelectedNode] = React.useState()
+ const [selectedNode, setSelectedNode] = React.useState();
const [isLoading, setLoading] = React.useState(true);
const [error, setError] = React.useState();
- const { fetchNodeById } = useMainContext()
- const { id } = useParams()
+ const { fetchNodeById } = useMainContext();
+ const { id } = useParams();
React.useEffect(() => {
setSelectedNode(undefined);
setLoading(true);
(async () => {
- if(typeof(id) === "string") {
+ if (typeof id === "string") {
try {
const res = await fetchNodeById(Number.parseInt(id));
setSelectedNode(res);
- } catch(e: any) {
+ } catch (e: any) {
setError(e.message);
- }
- finally {
+ } finally {
setLoading(false);
}
}
})();
- }, [id])
+ }, [id, fetchNodeById]);
if (isLoading) {
- return
+ return ;
}
// loaded, but not found
@@ -248,31 +299,38 @@ const PageNymNodeDetailGuard = () => {
return (
Nym node not found
- Sorry, we could not find a node with id {id || ''}
+ Sorry, we could not find a node with id {id || ""}
- )
+ );
}
- return
-}
+ if (!selectedNode) {
+ return (
+
+ Legacy Node
+ Unable to load details for the selected Nym node.
+
+ );
+ }
+
+ return ;
+};
/**
* Wrapper component that adds the node content based on the `id` in the address URL
*/
const PageNymNodeDetail = () => {
- const { id } = useParams()
+ const { id } = useParams();
- if (!id || typeof id !== 'string') {
- return (
- Oh no! Could not find that node
- )
+ if (!id || typeof id !== "string") {
+ return Oh no! Could not find that node;
}
return (
- )
-}
+ );
+};
-export default PageNymNodeDetail
+export default PageNymNodeDetail;
diff --git a/explorer-nextjs/next.config.mjs b/explorer-nextjs/next.config.mjs
index 4678774e6d..d642290145 100644
--- a/explorer-nextjs/next.config.mjs
+++ b/explorer-nextjs/next.config.mjs
@@ -1,4 +1,14 @@
/** @type {import('next').NextConfig} */
-const nextConfig = {};
+const nextConfig = {
+ async redirects() {
+ return [
+ {
+ source: '/network-components/mixnode/:id', // Match the old URL
+ destination: '/network-components/nodes/:id', // Redirect to the new URL
+ permanent: true,
+ },
+ ];
+ },
+};
export default nextConfig;
diff --git a/explorer-nextjs/tsconfig.json b/explorer-nextjs/tsconfig.json
index 68ef0fdf3b..701d0e6984 100644
--- a/explorer-nextjs/tsconfig.json
+++ b/explorer-nextjs/tsconfig.json
@@ -28,7 +28,8 @@
"../assets/*"
]
},
- "moduleResolution": "node"
+ "moduleResolution": "node",
+ "target": "ES2017"
},
"include": [
"next-env.d.ts",