ADD storage information to node

This commit is contained in:
Shaun Orssaud 2024-01-01 16:34:23 +09:00
parent a05e2472fa
commit d6cc20fefa
9 changed files with 255 additions and 83 deletions

View File

@ -8,4 +8,4 @@ services:
ports: ports:
- "3000:80" - "3000:80"
environment: environment:
- codex_url=${codex_url:-http://kubernetes.docker.internal:31264} - codex_url=${codex_url:-http://kubernetes.docker.internal:30003}

View File

@ -5,6 +5,7 @@ import DataPage from "./pages/data/DataPage";
import DebugPage from "./pages/debug/DebugPage"; import DebugPage from "./pages/debug/DebugPage";
import SettingsPage from "./pages/settings/SettingsPage"; import SettingsPage from "./pages/settings/SettingsPage";
import MarketplacePage from "./pages/marketplace/Marketplace"; import MarketplacePage from "./pages/marketplace/Marketplace";
import NodeInfoPage from "./pages/node/NodePage";
function PlacehoderPage(props: { name: string }) { function PlacehoderPage(props: { name: string }) {
return ( return (
@ -29,7 +30,7 @@ export default function App() {
<Route path="/settings" element={<SettingsPage />} /> <Route path="/settings" element={<SettingsPage />} />
<Route path="/marketplace" element={<MarketplacePage/>}/> <Route path="/marketplace" element={<MarketplacePage/>}/>
<Route path="/" element={<DataPage />} /> <Route path="/" element={<DataPage />} />
<Route path="/node" element={PlacehoderPage({ name: "Node" })} /> <Route path="/node" element={<NodeInfoPage/>} />
<Route path="/debug" element={DebugPage()} /> <Route path="/debug" element={DebugPage()} />
</Routes> </Routes>

View File

@ -0,0 +1,147 @@
import React from "react";
import styled from "styled-components";
import { DebugNodeInfoModel } from "../../data/models/DebugNodeInfoModel";
import DropDownList from "../layout/dropDownList/DropDownList";
function NodeInfoItemComponent(props: {
data: DebugNodeInfoModel | undefined;
}) {
return (
(props.data && (
<NodeInfoItemComponentWrapper>
<div id="info-row">
<p>
<span>Adresses: </span>
{props.data.addrs.join(", ")}
</p>
<p>
<span>Codex Version: </span>
{`${props.data.codex.version} (${props.data.codex.revision})`}
</p>
</div>
<div id="info-row">
<p>
<span>ID: </span>
{props.data.id}
</p>
</div>
<div id="info-row">
<p>
<span>SPR: </span>
{props.data.spr}
</p>
</div>
<div>
<h3>Local Node</h3>
<div id="info-row">
<p>
<span>Address: </span>
{props.data.table.localNode.address}
</p>
<p>
<span>Node ID: </span>
{props.data.table.localNode.nodeId}
</p>
</div>
<div id="info-row">
<p>
<span>Peer ID: </span>
{props.data.table.localNode.peerId}
</p>
<p>
<span>Seen: </span>
{`${props.data.table.localNode.seen
.toString()[0]
.toUpperCase()}${props.data.table.localNode.seen
.toString()
.slice(1)}`}
</p>
</div>
</div>
<DropDownList title="Nodes">
{props.data.table.nodes.map((node, index) => (
<div key={index}>
<h3>Node {index + 1}</h3>
<div id="info-row">
<p>
<span>Address: </span>
{node.address}
</p>
<p>
<span>Node ID: </span>
{node.nodeId}
</p>
</div>
<div id="info-row">
<p>
<span>Peer ID: </span>
{node.peerId}
</p>
<p>
<span>Seen: </span>
{`${node.seen.toString()[0].toUpperCase()}${node.seen
.toString()
.slice(1)}`}
</p>
</div>
</div>
))}
</DropDownList>
<DropDownList title="Record">
<div id="info-row">
<p>
<span>Record: </span>
{props.data.table.localNode.record}
</p>
</div>
</DropDownList>
</NodeInfoItemComponentWrapper>
)) || <></>
);
}
export default NodeInfoItemComponent;
const NodeInfoItemComponentWrapper = styled.div`
background-color: #1e1e1e;
border-radius: 8px;
padding: 10px;
width: 100%;
#info-row {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 8px;
margin: 5px;
}
h3 {
padding: 8px;
margin: 5px;
font-style: italic;
}
div p:nth-child(1) {
text-align: start;
}
div p:nth-child(2) {
text-align: end;
}
p {
flex: 1;
font-size: 1rem;
text-align: start;
word-break: break-all;
}
p span {
font-weight: bold;
}
#cid {
flex: 2;
}
`;

View File

@ -1,104 +1,38 @@
import React from "react"; import React from "react";
import styled from "styled-components"; import styled from "styled-components";
import { DebugNodeInfoModel } from "../../data/models/DebugNodeInfoModel"; import { NodeInfoModel } from "../../data/models/NodeInfoModel";
import DropDownList from "../layout/dropDownList/DropDownList"; import DropDownList from "../layout/dropDownList/DropDownList";
function NodeInfoItemComponent(props: { function NodeInfoItemComponent(props: {
data: DebugNodeInfoModel | undefined; data: NodeInfoModel | undefined;
}) { }) {
return ( return (
(props.data && ( (props.data && (
<NodeInfoItemComponentWrapper> <NodeInfoItemComponentWrapper>
<div id="info-row"> <div id="info-row">
<p> <p>
<span>Adresses: </span> <span>TotalBlocks: </span>
{props.data.addrs.join(", ")} {props.data.totalBlocks}
</p>
<p>
<span>Codex Version: </span>
{`${props.data.codex.version} (${props.data.codex.revision})`}
</p> </p>
</div> </div>
<div id="info-row"> <div id="info-row">
<p> <p>
<span>ID: </span> <span>QuotaMaxBytes: </span>
{props.data.id} {props.data.quotaMaxBytes}
</p>
<p>
<span>Repo: </span>
{props.data.repo}
</p> </p>
</div> </div>
<div id="info-row"> <div id="info-row">
<p> <p>
<span>SPR: </span> <span>QuotaUsedBytes: </span>
{props.data.spr} {props.data.quotaUsedBytes}
</p> </p>
</div> </div>
<div> <div id="info-row">
<h3>Local Node</h3> <p>
<div id="info-row"> <span>QuotaReservedBytes: </span>
<p> {props.data.quotaReservedBytes}
<span>Address: </span> </p>
{props.data.table.localNode.address}
</p>
<p>
<span>Node ID: </span>
{props.data.table.localNode.nodeId}
</p>
</div>
<div id="info-row">
<p>
<span>Peer ID: </span>
{props.data.table.localNode.peerId}
</p>
<p>
<span>Seen: </span>
{`${props.data.table.localNode.seen
.toString()[0]
.toUpperCase()}${props.data.table.localNode.seen
.toString()
.slice(1)}`}
</p>
</div>
</div> </div>
<DropDownList title="Nodes">
{props.data.table.nodes.map((node, index) => (
<div key={index}>
<h3>Node {index + 1}</h3>
<div id="info-row">
<p>
<span>Address: </span>
{node.address}
</p>
<p>
<span>Node ID: </span>
{node.nodeId}
</p>
</div>
<div id="info-row">
<p>
<span>Peer ID: </span>
{node.peerId}
</p>
<p>
<span>Seen: </span>
{`${node.seen.toString()[0].toUpperCase()}${node.seen
.toString()
.slice(1)}`}
</p>
</div>
</div>
))}
</DropDownList>
<DropDownList title="Record">
<div id="info-row">
<p>
<span>Record: </span>
{props.data.table.localNode.record}
</p>
</div>
</DropDownList>
</NodeInfoItemComponentWrapper> </NodeInfoItemComponentWrapper>
)) || <></> )) || <></>
); );

View File

@ -4,6 +4,7 @@ type AvailabilityModel = {
duration: string; duration: string;
minPrice: string; minPrice: string;
maxCollateral: string; maxCollateral: string;
expiry: string;
}; };
export default AvailabilityModel; export default AvailabilityModel;

View File

@ -0,0 +1,12 @@
export interface NodeInfoModel {
totalBlocks: number;
quotaMaxBytes: number;
quotaUsedBytes: number;
quotaReservedBytes: number;
}
export class Convert {
public static toNodeInfoModel(json: string): NodeInfoModel {
return JSON.parse(json);
}
}

View File

@ -5,7 +5,7 @@ import {
Convert, Convert,
DebugNodeInfoModel, DebugNodeInfoModel,
} from "../../data/models/DebugNodeInfoModel"; } from "../../data/models/DebugNodeInfoModel";
import NodeInfoItemComponent from "../../components/nodeInfoItem/NodeInfoItemComponent"; import NodeInfoItemComponent from "../../components/debugInfoItem/debugInfoItem";
import Header from "../../components/layout/partials/Header"; import Header from "../../components/layout/partials/Header";
import { useDexyStore } from "../../store"; import { useDexyStore } from "../../store";

View File

@ -10,6 +10,7 @@ function OfferStorage() {
const [duration, setDuration,] = useState("file"); const [duration, setDuration,] = useState("file");
const [minPrice, setMinPrice,] = useState("file"); const [minPrice, setMinPrice,] = useState("file");
const [maxCollateral, setMaxCollateral,] = useState("file"); const [maxCollateral, setMaxCollateral,] = useState("file");
const [expiry, setExpiry,] = useState("file");
function upload(cid: string) { function upload(cid: string) {
@ -27,7 +28,8 @@ function OfferStorage() {
size: size, size: size,
duration: duration, duration: duration,
minPrice: minPrice, minPrice: minPrice,
maxCollateral: maxCollateral maxCollateral: maxCollateral,
expiry: expiry
}) })
} }
) )
@ -75,6 +77,12 @@ function OfferStorage() {
placeholder="MaxCollateral" placeholder="MaxCollateral"
onChange={(e) => setMaxCollateral(e.target.value)} onChange={(e) => setMaxCollateral(e.target.value)}
/> />
<div id="divider"></div>
<input
type="text"
placeholder="Expiry"
onChange={(e) => setExpiry(e.target.value)}
/>
<button onClick={() => upload(ftdCid)}>Download</button> <button onClick={() => upload(ftdCid)}>Download</button>
</OfferStorageWrapper> </OfferStorageWrapper>
); );

View File

@ -0,0 +1,69 @@
import axios from "axios";
import React, { useEffect } from "react";
import styled from "styled-components";
import {
Convert,
NodeInfoModel,
} from "../../data/models/NodeInfoModel";
import NodeInfoItemComponent from "../../components/nodeInfoItem/NodeInfoItemComponent";
import Header from "../../components/layout/partials/Header";
import { useDexyStore } from "../../store";
function NodeInfoPage() {
const { nodeInfo } = useDexyStore();
const [statusInfo, setStatusInfo] = React.useState<
NodeInfoModel | undefined
>();
useEffect(() => {
axios
.get(
`/api/codex/v1/space`,
{
headers:
(nodeInfo.auth && {
Authorization:
(nodeInfo.auth && "Basic " + btoa(nodeInfo.auth)) || "",
}) ||
{},
}
)
.then((response) => {
setStatusInfo(
Convert.toNodeInfoModel(JSON.stringify(response.data))
);
});
}, [nodeInfo]);
console.log(statusInfo);
return (
<NodeInfoPageWrapper>
<Header title="Node Info" />
<main>{statusInfo && <NodeInfoItemComponent data={statusInfo!!} />}</main>
</NodeInfoPageWrapper>
);
}
export default NodeInfoPage;
const NodeInfoPageWrapper = styled.div`
flex: 1;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
overflow-y: scroll;
main {
margin-top: auto;
margin-bottom: auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 16px;
}
.scroll {
}
`;