feat: initial Proof of Concept UI (#1)
* initial dashboard layout * add node status card * add accounting section, pull peer data * add file functionality with bee-js, first iteration of accounts page * Add balances and chequebook table * add blockie / identicon for addresses * add basic settlements table * implement theme overrides * cleanup logging * Add troubleshooting block * add initial dark theme support, add copy to clipboard, QR code support * show active element on sidebar * remove duplicate status page and make status page index * Update package.json Co-authored-by: Vojtech Simetka <vojtech@simetka.cz> * Update public/index.html Co-authored-by: Vojtech Simetka <vojtech@simetka.cz> * Update src/pages/accounting/AccountCard.tsx Co-authored-by: Vojtech Simetka <vojtech@simetka.cz> * change bee api client to use beeJS library * add initial setup workflow * breakout ethereum address component, define initial setup workflow * add types to responses, add additional node troubleshooting info to workflow * make setup steps nonlinear and interactive * make host endpoint dynamic on setup * split out api calls into custom hooks, add component loading indicators * add depost / withdrawl functionality, show transactions in BZZ * add multiOS code support troubleshooting, check for balance in chequebook on setup * add ability to change apis in settings page * show file loading status * Style active sidebar item * reload on theme change * modify troubleshooting verbage, add cashout functionality and details, * facilitate file upload with beeJS * update readme to show UI samples * remove nnPeersWatermark from peers page * split node steps into separate components, make status page visible at anytime * minor UI/UX enhancements * format accounting page * remove WIP wallet connection code * Update src/components/CashoutModal.tsx Co-authored-by: Vojtech Simetka <vojtech@simetka.cz> * use bigint for deposits/withdrawls * revise status card * clean up unused imports and variables * add api status to sidebar * obfuscate pages with troubleshooting component when apis not connected * add localhost OS detection for troubleshooting code * cleanup extra logos * monospace BZZ in tables * hide troubleshooting page while loading API status * Remove ability to remove peers * add null types to API responses Co-authored-by: Vojtech Simetka <vojtech@simetka.cz>
This commit is contained in:
@@ -0,0 +1,334 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import type { NodeAddresses, ChequebookAddressResponse, ChequebookBalanceResponse, BalanceResponse,
|
||||
LastChequesResponse, AllSettlements, LastCashoutActionResponse } from '@ethersphere/bee-js'
|
||||
|
||||
import { beeDebugApi, beeApi } from '../services/bee';
|
||||
|
||||
export const useApiHealth = () => {
|
||||
const [health, setHealth] = useState('')
|
||||
const [isLoadingHealth, setLoading] = useState<boolean>(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
beeApi.status.health()
|
||||
.then(res => {
|
||||
setHealth(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return { health, isLoadingHealth, error } ;
|
||||
}
|
||||
|
||||
interface NodeHealth {
|
||||
status: string,
|
||||
version: string
|
||||
}
|
||||
|
||||
export const useDebugApiHealth = () => {
|
||||
const [nodeHealth, setNodeHealth] = useState<NodeHealth | null>(null)
|
||||
const [isLoadingNodeHealth, setLoading] = useState<boolean>(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
beeDebugApi.status.nodeHealth()
|
||||
.then(res => {
|
||||
setNodeHealth(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return { nodeHealth, isLoadingNodeHealth, error } ;
|
||||
}
|
||||
|
||||
interface NodeReadiness {
|
||||
status: string,
|
||||
version: string
|
||||
}
|
||||
|
||||
export const useApiReadiness = () => {
|
||||
const [nodeReadiness, setNodeReadiness] = useState<NodeReadiness | null>(null)
|
||||
const [isLoadingNodeReadiness, setLoading] = useState<boolean>(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
beeDebugApi.status.nodeReadiness()
|
||||
.then(res => {
|
||||
setNodeReadiness(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return { nodeReadiness, isLoadingNodeReadiness, error } ;
|
||||
}
|
||||
|
||||
export const useApiNodeAddresses = () => {
|
||||
const [nodeAddresses, setNodeAddresses] = useState<NodeAddresses | null>(null)
|
||||
const [isLoadingNodeAddresses, setLoading] = useState<boolean>(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
beeDebugApi.connectivity.addresses()
|
||||
.then(res => {
|
||||
setNodeAddresses(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return { nodeAddresses, isLoadingNodeAddresses, error } ;
|
||||
}
|
||||
|
||||
export const useApiNodeTopology = () => {
|
||||
const [nodeTopology, setNodeTopology] = useState({ baseAddr: '', bins: [""], connected: 0, depth: 0, nnLowWatermark: 0, population: 0, timestamp: ''})
|
||||
const [isLoadingNodeTopology, setLoading] = useState<boolean>(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
beeDebugApi.connectivity.topology()
|
||||
.then(res => {
|
||||
setNodeTopology(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return { nodeTopology, isLoadingNodeTopology, error } ;
|
||||
}
|
||||
|
||||
export const useApiChequebookAddress = () => {
|
||||
const [chequebookAddress, setChequebookAddress] = useState<ChequebookAddressResponse | null>(null)
|
||||
const [isLoadingChequebookAddress, setLoading] = useState<boolean>(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
beeDebugApi.chequebook.address()
|
||||
.then(res => {
|
||||
setChequebookAddress(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return { chequebookAddress, isLoadingChequebookAddress, error };
|
||||
}
|
||||
|
||||
export const useApiNodePeers = () => {
|
||||
const [nodePeers, setNodePeers] = useState({ peers: [{ address: '-'}]})
|
||||
const [isLoadingNodePeers, setLoading] = useState<boolean>(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
beeDebugApi.connectivity.listPeers()
|
||||
.then(res => {
|
||||
setNodePeers(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return { nodePeers, isLoadingNodePeers, error };
|
||||
}
|
||||
|
||||
export const useApiChequebookBalance = () => {
|
||||
const [chequebookBalance, setChequebookBalance] = useState<ChequebookBalanceResponse | null>(null)
|
||||
const [isLoadingChequebookBalance, setLoading] = useState<boolean>(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
beeDebugApi.chequebook.balance()
|
||||
.then(res => {
|
||||
setChequebookBalance(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return { chequebookBalance, isLoadingChequebookBalance, error };
|
||||
}
|
||||
|
||||
export const useApiPeerBalances = () => {
|
||||
const [peerBalances, setPeerBalances] = useState<BalanceResponse | null>(null)
|
||||
const [isLoadingPeerBalances, setLoading] = useState<boolean>(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
beeDebugApi.balance.balances()
|
||||
.then(res => {
|
||||
setPeerBalances(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return { peerBalances, isLoadingPeerBalances, error };
|
||||
}
|
||||
|
||||
export const useApiPeerCheques = () => {
|
||||
const [peerCheques, setPeerCheques] = useState<LastChequesResponse | null>(null)
|
||||
const [isLoadingPeerCheques, setLoading] = useState<boolean>(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
beeDebugApi.chequebook.getLastCheques()
|
||||
.then(res => {
|
||||
setPeerCheques(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return { peerCheques, isLoadingPeerCheques, error };
|
||||
}
|
||||
|
||||
export const useApiPeerLastCheque = (peerId: string) => {
|
||||
const [peerCheque, setPeerCheque] = useState({ peer: '-', chequebook: "",
|
||||
cumulativePayout: 0,
|
||||
beneficiary: "",
|
||||
transactionHash: "",
|
||||
result: {
|
||||
recipient: "",
|
||||
lastPayout: 0,
|
||||
bounced: false
|
||||
}}
|
||||
)
|
||||
const [isLoadingPeerCheque, setLoading] = useState<boolean>(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
beeDebugApi.chequebook.getPeerLastCheques(peerId)
|
||||
.then(res => {
|
||||
setPeerCheque(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return { peerCheque, isLoadingPeerCheque, error };
|
||||
}
|
||||
|
||||
export const useApiSettlements = () => {
|
||||
const [settlements, setSettlements] = useState<AllSettlements | null>(null)
|
||||
const [isLoadingSettlements, setLoading] = useState<boolean>(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
beeDebugApi.settlements.getSettlements()
|
||||
.then(res => {
|
||||
setSettlements(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return { settlements, isLoadingSettlements, error };
|
||||
}
|
||||
|
||||
|
||||
export const useApiPingPeer = (peerId: string) => {
|
||||
const [peerRTP, setPeerRTP] = useState<string>('')
|
||||
const [isPingingPeer, setPingingPeer] = useState<boolean>(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setPingingPeer(true)
|
||||
beeDebugApi.connectivity.ping(peerId)
|
||||
.then(res => {
|
||||
setPeerRTP(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error)
|
||||
})
|
||||
.finally(() => {
|
||||
setPingingPeer(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return { peerRTP, isPingingPeer, error };
|
||||
}
|
||||
|
||||
export const useApiPeerLastCashout = (peerId: string) => {
|
||||
const [peerCashout, setPeerCashout] = useState<LastCashoutActionResponse | null>(null)
|
||||
const [isLoadingPeerCashout, setLoading] = useState<boolean>(false)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
beeDebugApi.chequebook.getPeerLastCashout(peerId)
|
||||
.then(res => {
|
||||
setPeerCashout(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return { peerCashout, isLoadingPeerCashout, error };
|
||||
}
|
||||
Reference in New Issue
Block a user