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:
matmertz25
2021-03-12 12:01:56 -05:00
committed by GitHub
parent f4ce271479
commit 34d2dfda5a
60 changed files with 6155 additions and 364 deletions
+185
View File
@@ -0,0 +1,185 @@
import React, { useEffect, useState } from 'react';
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles';
import { Typography, Paper, Button, Step, StepLabel, StepContent, Stepper, StepButton } from '@material-ui/core/';
import { CheckCircle, Error, Sync, ExpandLessSharp, ExpandMoreSharp } from '@material-ui/icons/';
import NodeConnectionCheck from './SetupSteps/NodeConnectionCheck';
import VersionCheck from './SetupSteps/VersionCheck';
import EthereumConnectionCheck from './SetupSteps/EthereumConnectionCheck';
import ChequebookDeployFund from './SetupSteps/ChequebookDeployFund';
import PeerConnection from './SetupSteps/PeerConnection';
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
width: '100%',
},
button: {
marginTop: theme.spacing(1),
marginRight: theme.spacing(1),
},
actionsContainer: {
margin: theme.spacing(2),
},
resetContainer: {
padding: theme.spacing(5),
},
}),
);
function getSteps() {
return [
'Node Connection Check',
'Version Check',
'Connect to Ethereum Blockchain',
'Deploy and Fund Chequebook',
'Connect to Peers',
];
}
function getStepContent(step: number, props: any) {
switch (step) {
case 0:
return <NodeConnectionCheck {...props} />;
case 1:
return <VersionCheck {...props} />;
case 2:
return <EthereumConnectionCheck {...props} />;
case 3:
return <ChequebookDeployFund {...props} />;
default:
return <PeerConnection {...props} />;
}
}
export default function NodeSetupWorkflow(props: any) {
const classes = useStyles();
const [activeStep, setActiveStep] = useState(0);
const [completed, setCompleted] = useState<{ [k: number]: boolean }>({});
const steps = getSteps();
const evaluateNodeStatus = () => {
if (props.nodeHealth?.status === 'ok' && props.nodeApiHealth) {
handleComplete(0)
setActiveStep(1)
}
if (props.beeRelease && props.beeRelease.name === `v${props.nodeHealth?.version?.split('-')[0]}`) {
handleComplete(1)
setActiveStep(2)
}
if (props.nodeAddresses?.ethereum) {
handleComplete(2)
setActiveStep(3)
}
if (props.chequebookAddress?.chequebookaddress && props.chequebookBalance.totalBalance > 0) {
handleComplete(3)
setActiveStep(4)
}
if (props.nodeTopology.connected && props.nodeTopology.connected > 0) {
handleComplete(4)
setActiveStep(5)
}
}
useEffect(() => {
evaluateNodeStatus()
}, [])
useEffect(() => {
evaluateNodeStatus()
}, [props])
const handleNext = () => {
setActiveStep((prevActiveStep) => prevActiveStep + 1);
};
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};
const handleSetupComplete = () => {
props.setStatusChecksVisible(false)
};
const handleComplete = (index: number) => {
const newCompleted = completed;
newCompleted[index] = true;
setCompleted(newCompleted);
};
return (
<div className={classes.root}>
<Typography variant="h4" gutterBottom>
Node Setup
<span style={{marginLeft:'25px'}}>
<Button variant='outlined' size='small' onClick={() => window.location.reload()}><Sync/><span style={{marginLeft:'7px'}}>Refresh Checks</span></Button>
</span>
</Typography>
<Stepper nonLinear activeStep={activeStep} orientation="vertical">
{steps.map((label, index) => (
<Step key={label}>
<StepLabel
onClick={() => setActiveStep(index === activeStep ? 5 : index)}
StepIconComponent={() => {
if(completed[index])
return <CheckCircle style={{color:'#32c48d', height: '25px', cursor:'pointer'}} />
else {
return <Error style={{color:'#c9201f', height: '25px', cursor:'pointer'}} />
}
}}
>
<StepButton onClick={() => setActiveStep(index === activeStep ? 5 : index)} style={{justifyContent:'space-between'}}>
<div style={{display:'flex'}}>
<div style={{marginTop:'5px'}}>{label}</div>
<div style={{marginLeft:'12px'}}>{index === activeStep ? <ExpandLessSharp /> : <ExpandMoreSharp />}</div>
</div>
</StepButton>
</StepLabel>
<StepContent>
<Typography>{getStepContent(index, props)}</Typography>
<div className={classes.actionsContainer}>
<div>
<Button
disabled={activeStep === 0}
onClick={handleBack}
className={classes.button}
>
Back
</Button>
<Button
variant="contained"
color="primary"
onClick={handleNext}
className={classes.button}
>
Next
</Button>
</div>
</div>
</StepContent>
</Step>
))}
</Stepper>
{Object.values(completed).filter(value => value).length === 5 ? (
<Paper square elevation={0} className={classes.resetContainer}>
<Typography>Bee setup complete! Welcome to the swarm and the internet of decentralized storage</Typography>
<Button
onClick={handleBack}
className={classes.button}
>
Back
</Button>
<Button onClick={handleSetupComplete} variant="contained" color="primary" className={classes.button}>
Complete
</Button>
</Paper>
) : null}
</div>
);
}
@@ -0,0 +1,47 @@
import React from 'react';
import { Typography } from '@material-ui/core/';
import { CheckCircle, Warning } from '@material-ui/icons/';
import EthereumAddress from '../../../components/EthereumAddress';
import DepositModal from '../../../components/DepositModal';
import CodeBlockTabs from '../../../components/CodeBlockTabs';
export default function ChequebookDeployFund(props: any) {
return (
<div>
<p style={{marginBottom:'20px', display:'flex'}}>
<span style={{ marginRight:'40px'}} >Deploy chequebook and fund with BZZ</span>
{props.chequebookAddress?.chequebookaddress ?
<DepositModal />
: null }
</p>
<div style={{ marginBottom:'10px' }}>
{props.chequebookAddress?.chequebookaddress && props.chequebookBalance && props.chequebookBalance?.totalBalance > 0 ?
<div>
<CheckCircle style={{color:'#32c48d', marginRight: '7px', height: '18px'}} />
<span>Your chequebook is deployed and funded!</span>
</div>
:
props.loadingChequebookAddress || props.isLoadingChequebookBalance ?
null
:
<div>
<Warning style={{color:'#ff9800', marginRight: '7px', height: '18px'}} />
<span>Your chequebook is either not deployed or funded. Run the below commands to get your address and deposit ETH. Then visit the BZZaar here <a href='#'>https://bzz.ethswarm.org/?transaction=buy&amount=10&slippage=30&receiver=[ENTER_ADDRESS_HERE]</a> to get BZZ</span>
<CodeBlockTabs
showLineNumbers
linux={`bee-get-addr`}
mac={`bee-get-addr`}
/>
</div>
}
</div>
<Typography variant="subtitle1" gutterBottom>
<span>Chequebook Address</span>
</Typography>
<EthereumAddress
address={props.chequebookAddress?.chequebookaddress}
network={'goerli'}
/>
</div>
)
}
@@ -0,0 +1,39 @@
import React from 'react';
import { Typography } from '@material-ui/core/';
import { CheckCircle, Warning } from '@material-ui/icons/';
import EthereumAddress from '../../../components/EthereumAddress';
export default function EthereumConnectionCheck(props: any) {
return (
<div>
<p>Connect to the ethereum blockchain.</p>
<div style={{ marginBottom:'10px' }}>
{props.nodeAddresses?.ethereum ?
<div>
<CheckCircle style={{color:'#32c48d', marginRight: '7px', height: '18px'}} />
<span>Your connected to the Ethereum network</span>
</div>
:
props.loadingNodeAddresses ?
null
:
<div>
<Warning style={{color:'#ff9800', marginRight: '7px', height: '18px'}} />
<span>Your not connected to the Ethereum network. </span>
<p>Your Bee node must have access to the Ethereum blockchain, so that it can interact and deploy your chequebook contract. You can run <a href='https://github.com/goerli/testnet' rel='noreferrer' target='_blank'>your own Goerli node</a>, or use a provider such as <a href='https://rpc.slock.it/goerli' rel='noreferrer' target='_blank'>rpc.slock.it/goerli</a> or <a href='https://infura.io/' rel='noreferrer' target='_blank'>Infura</a>.
By default, Bee expects a local Goerli node at http://localhost:8545. To use a provider instead, simply change your <strong>--swap-endpoint</strong> in your configuration file.
</p>
</div>
}
</div>
<Typography variant="subtitle1" gutterBottom>
<span>Node Address</span>
</Typography>
<EthereumAddress
address={props.nodeAddresses?.ethereum}
network={'goerli'}
/>
</div>
)
}
@@ -0,0 +1,126 @@
import React from 'react'
import { Typography, Accordion, AccordionSummary, AccordionDetails } from '@material-ui/core/';
import MuiAlert from '@material-ui/lab/Alert';
import { CheckCircle, Error, ExpandMoreSharp } from '@material-ui/icons/';
import ConnectToHost from '../../../components/ConnectToHost';
import CodeBlockTabs from '../../../components/CodeBlockTabs'
export default function NodeConnectionCheck(props: any) {
return (
<div>
<p>Connect to Bee Node APIs</p>
<div style={{display:'flex', marginBottom: '25px'}}>
{ props.nodeApiHealth ?
<CheckCircle style={{color:'#32c48d', marginRight: '7px', height: '18px'}} />
:
<Error style={{color:'#c9201f', marginRight: '7px', height: '18px'}} />
}
<span style={{marginRight:'15px'}}>Node API (<a href='#'>{props.apiHost}</a>)</span>
<ConnectToHost hostName='api_host' defaultHost={props.apiHost} />
</div>
<div>
{ !props.nodeApiHealth ?
<Typography variant="body2" gutterBottom style={{margin: '15px'}}>
We cannot connect to your nodes API at <a href='#'>{props.apiHost}</a>. Please check the following to troubleshoot your issue.
<Accordion style={{marginTop:'20px'}}>
<AccordionSummary
expandIcon={<ExpandMoreSharp />}
aria-controls="panel1a-content"
id="panel1a-header"
>
<Typography>Troubleshoot</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
<ol>
<li>Check the status of your node by running the below command to see if your node is running.</li>
<CodeBlockTabs
showLineNumbers
linux={`sudo systemctl status bee`}
mac={`brew services status swarm-bee`}
/>
<li>If your node is running, check your firewall settings to make sure that port 1633 (or your custom specified port) is exposed to the internet. If your node is not running try executing the below command to start your bee node</li>
<CodeBlockTabs
showLineNumbers
linux={`sudo systemctl start bee`}
mac={`brew services start swarm-bee`}
/>
<li>Run the commands to validate your node is running and see the log output.</li>
<CodeBlockTabs
showLineNumbers
linux={`sudo systemctl status bee \njournalctl --lines=100 --follow --unit bee`}
mac={`brew services status swarm-bee \ntail -f /usr/local/var/log/swarm-bee/bee.log`}
/>
</ol>
</Typography>
</AccordionDetails>
</Accordion>
</Typography>
:
null}
</div>
<div>
<div style={{display:'flex', marginBottom: '25px'}}>
{ props.nodeHealth?.status === 'ok' ?
<CheckCircle style={{color:'#32c48d', marginRight: '7px', height: '18px'}} />
:
<Error style={{color:'#c9201f', marginRight: '7px', height: '18px'}} />
}
<span style={{marginRight:'15px'}}>Debug API (<a href='#'>{props.debugApiHost}</a>)</span>
<ConnectToHost hostName={'debug_api_host'} defaultHost={props.debugApiHost} />
</div>
<div>
{ props.nodeHealth?.status !== 'ok' ?
<Typography variant="body2" gutterBottom style={{margin: '15px'}}>
We cannot connect to your nodes debug API at <a href='#'>{props.debugApiHost}</a>. Please check the following to troubleshoot your issue.
<Accordion style={{marginTop:'20px'}}>
<AccordionSummary
expandIcon={<ExpandMoreSharp />}
aria-controls="panel1a-content"
id="panel1a-header"
>
<Typography>Troubleshoot</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
<ol>
<li>Check the status of your node by running the below command to see if your node is running.</li>
<CodeBlockTabs
showLineNumbers
linux={`sudo systemctl status bee`}
mac={`brew services status swarm-bee`}
/>
<li>If your node is running, check your firewall settings to make sure that port 1635 (or your custom specified port) is bound to localhost. If your node is not running try executing the below command to start your bee node</li>
<MuiAlert style={{marginTop:'10px', marginBottom:'10px'}} elevation={6} variant="filled" severity="error">
Your debug node API should never be completely open to the internet. If you want to connect remotely, make sure your firewall settings are set to only allow specific trusted IP addresses and block all other ports. A simple google search for "what is my ip" will show you your computers public IP address to allow.
</MuiAlert>
<CodeBlockTabs
showLineNumbers
linux={`sudo systemctl start bee`}
mac={`brew services start swarm-bee`}
/>
<li>Run the commands to validate your node is running and see the log output.</li>
<CodeBlockTabs
showLineNumbers
linux={`sudo systemctl status bee \njournalctl --lines=100 --follow --unit bee`}
mac={`brew services status swarm-bee \ntail -f /usr/local/var/log/swarm-bee/bee.log`}
/>
<li>Lastly, check your nodes configuration settings to validate the debug API is enabled and the Cross Origin Resource Sharing (CORS) setting is configured to allow your host. Config parameter <strong>debug-api-enable</strong> must be set to <strong>true</strong> and <strong>cors-allowed-origins</strong> must be set to your host domain or IP. If edits are made to the configuration run the restart command below for changes to take effect.</li>
<CodeBlockTabs
showLineNumbers
linux={`sudo vi /etc/bee/bee.yaml\nsudo systemctl restart bee`}
mac={`sudo vi /etc/bee/bee.yaml \nbrew services restart swarm-bee`}
/>
</ol>
</Typography>
</AccordionDetails>
</Accordion>
</Typography>
:
null}
</div>
</div>
</div>
)
}
@@ -0,0 +1,45 @@
import React from 'react';
import { Typography } from '@material-ui/core/';
import { CheckCircle, Warning } from '@material-ui/icons/';
export default function PeerConnection(props: any) {
return (
<div>
<p>Connect to Peers</p>
<div style={{ marginBottom:'10px' }}>
{props.nodeTopology.connected && props.nodeTopology.connected > 0 ?
<div>
<CheckCircle style={{color:'#32c48d', marginRight: '7px', height: '18px'}} />
<span>Your connected to {props.nodeTopology.connected} peers!</span>
</div>
:
props.loadingNodeTopology ?
null
:
<div>
<Warning style={{color:'#ff9800', marginRight: '7px', height: '18px'}} />
<span>Your node is not connected to any peers</span>
</div>
}
</div>
<div style={{display:'flex'}}>
<div style={{marginRight:'30px'}}>
<Typography variant="subtitle1" gutterBottom color="textSecondary">
<span>Connected Peers</span>
</Typography>
<Typography variant="h5" component="h2">
{ props.nodeTopology.connected }
</Typography>
</div>
<div>
<Typography variant="subtitle1" gutterBottom color="textSecondary">
<span>Discovered Nodes</span>
</Typography>
<Typography variant="h5" component="h2">
{ props.nodeTopology.population }
</Typography>
</div>
</div>
</div>
)
}
@@ -0,0 +1,45 @@
import React from 'react';
import { Typography } from '@material-ui/core/';
import { CheckCircle, Warning } from '@material-ui/icons/';
import CodeBlockTabs from '../../../components/CodeBlockTabs';
export default function VersionCheck(props: any) {
return (
<div>
<p>Check to make sure the latest version of <a href='https://github.com/ethersphere/bee' rel='noreferrer' target='_blank'>Bee</a> is running</p>
{props.beeRelease && props.beeRelease.name === `v${props.nodeReadiness?.version?.split('-')[0]}` ?
<div>
<CheckCircle style={{color:'#32c48d', marginRight: '7px', height: '18px'}} />
<span>Your running the latest version of Bee</span>
</div>
:
props.loadingBeeRelease ?
null
:
<div>
<Warning style={{color:'#ff9800', marginRight: '7px', height: '18px'}} />
<span>Your Bee version is out of date. Please update to the <a href={props.beeRelease.html_url} rel='noreferrer' target='_blank'>latest</a> before continuing. Rerun the installation script below to upgrade. Reference the docs for help with updating. <a href='https://docs.ethswarm.org/docs/installation/manual#upgrading-bee' rel='noreferrer' target='_blank'>Docs</a></span>
<CodeBlockTabs
showLineNumbers
linux={`bee version\nwget https://github.com/ethersphere/bee/releases/download/${props.beeRelease.name}/bee_${props.nodeReadiness?.version?.split('-')[0]}_amd64.deb\nsudo dpkg -i bee_${props.nodeReadiness?.version?.split('-')[0]}_amd64.deb`}
mac={`bee version\nbrew tap ethersphere/tap\nbrew install swarm-bee\nbrew services start swarm-bee`}
/>
</div>
}
<div style={{display:'flex'}}>
<div style={{marginRight:'30px'}}>
<p><span>Current Version</span></p>
<Typography component="h5" variant="h5">
<span>{props.nodeReadiness?.version ? ` v${props.nodeReadiness?.version?.split('-')[0]}` : '-'}</span>
</Typography>
</div>
<div>
<p><span>Latest Version</span></p>
<Typography component="h5" variant="h5">
<span>{props.beeRelease && props.beeRelease.name ? props.beeRelease.name : '-'}</span>
</Typography>
</div>
</div>
</div>
)
}
+172
View File
@@ -0,0 +1,172 @@
import React, { useState } from 'react'
import { Link } from 'react-router-dom';
import { Theme, createStyles, makeStyles } from '@material-ui/core/styles';
import { Card, CardContent, Typography, Chip, Button } from '@material-ui/core/';
import { CheckCircle, Error, ArrowRight, ArrowDropUp } from '@material-ui/icons/';
import { Skeleton } from '@material-ui/lab';
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
display: 'flex',
},
details: {
display: 'flex',
flex: '1 0 auto',
flexDirection: 'column',
},
content: {
flex: '1 0 auto',
},
status: {
color: '#2145a0',
backgroundColor: '#e1effe',
}
}),
);
interface NodeHealth {
status?: string,
version?: string
}
interface NodeReadiness {
status?: string,
version?: string
}
interface NodeAddresses {
overlay: string,
underlay: string[],
ethereum: string,
public_key: string,
pss_public_key: string
}
interface NodeTopology {
baseAddr: string,
bins: string[],
connected: number,
depth: number,
nnLowWatermark: number,
population: number,
timestamp: string,
}
interface IProps{
nodeHealth: NodeHealth,
loadingNodeHealth: boolean,
nodeReadiness: NodeReadiness | null,
loadingNodeReadiness: boolean,
beeRelease: any,
loadingBeeRelease: boolean,
nodeAddresses: NodeAddresses,
nodeTopology: NodeTopology,
loadingNodeTopology: boolean,
setStatusChecksVisible: any,
}
function StatusCard(props: IProps) {
const classes = useStyles();
const [underlayAddressesVisible, setUnderlayAddresessVisible] = useState<Boolean>(false)
return (
<div>
<Card className={classes.root}>
{ !props.loadingNodeHealth && props.nodeHealth ?
<div className={classes.details}>
<CardContent className={classes.content}>
<Typography component="h5" variant="h5" style={{display:'flex', justifyContent:'space-between'}}>
{ props.nodeHealth.status === 'ok' ?
<div>
<CheckCircle style={{color:'#32c48d', marginRight: '7px'}} />
<span>Connected to Bee Node</span>
</div>
:
<div>
<Error style={{color:'#c9201f', marginRight: '7px'}} />
<span>Could not connect to Bee Node</span>
</div>
}
<Button variant='outlined' color='primary' size='small' style={{marginLeft:'12px'}} onClick={() => props.setStatusChecksVisible(true)}>View Status Checks</Button>
</Typography>
<div style={{marginBottom: '20px' }}>
<span style={{marginRight:'20px'}}>Discovered Nodes: { props.nodeTopology.population }</span>
<span style={{marginRight:'20px'}}>
<span>Connected Peers: </span>
<Link to='/peers/'>
{ props.nodeTopology.connected }
</Link>
</span>
</div>
<div>
<Typography variant="subtitle2" gutterBottom>
<span>AGENT: </span>
<a href='https://github.com/ethersphere/bee' rel='noreferrer' target='_blank'>Bee</a>
<span>{props.nodeReadiness?.version ? ` v${props.nodeReadiness.version}` : '-'}</span>
{props.beeRelease && props.beeRelease.name === `v${props.nodeReadiness?.version?.split('-')[0]}` ?
<Chip
style={{ marginLeft: '7px', color: '#2145a0' }}
size="small"
label='latest'
className={classes.status}
/>
:
props.loadingBeeRelease ?
''
:
<a href='#'>update</a>
}
</Typography>
<Typography variant="subtitle2" gutterBottom>
<span>PUBLIC KEY: </span>
<span>{ props.nodeAddresses.public_key ? props.nodeAddresses.public_key : '-' }</span>
</Typography>
<Typography variant="subtitle2" gutterBottom>
<span>PSS PUBLIC KEY: </span>
<span>{ props.nodeAddresses.pss_public_key ? props.nodeAddresses.pss_public_key : '-' }</span>
</Typography>
<Typography variant="subtitle2" gutterBottom>
<Typography style={{marginTop:'20px'}}>
<span>OVERLAY ADDRESS (PEER ID): </span>
<span>{ props.nodeAddresses.overlay ? props.nodeAddresses.overlay : '-' }</span>
</Typography>
<Typography onClick={() => setUnderlayAddresessVisible(!underlayAddressesVisible)}>
<Button color="primary" style={{padding: 0, marginTop:'6px'}}>
{ underlayAddressesVisible ?
<ArrowDropUp style={{fontSize:'12px'}} /> :
<ArrowRight style={{fontSize:'12px'}} />
}
<span>Underlay Addresses</span>
</Button>
</Typography>
{underlayAddressesVisible ?
<div>
{ props.nodeAddresses.underlay ?
props.nodeAddresses.underlay.map(item => (<li>{item}</li>))
: '-' }
</div>
: null}
</Typography>
</div>
</CardContent>
</div>
:
<div style={{padding: '16px'}}>
<Skeleton width={650} height={32} animation="wave" />
<Skeleton width={650} height={24} animation="wave" />
<Skeleton width={650} height={24} animation="wave" />
</div>
}
</Card>
</div>
)
}
export default StatusCard
+141
View File
@@ -0,0 +1,141 @@
import React, { useState, useEffect } from 'react'
import axios from 'axios';
import { Container, CircularProgress } from '@material-ui/core';
import NodeSetupWorkflow from './NodeSetupWorkflow';
import StatusCard from './StatusCard';
import EthereumAddressCard from '../../components/EthereumAddressCard';
import { useApiHealth, useDebugApiHealth, useApiReadiness, useApiNodeAddresses, useApiChequebookAddress, useApiNodeTopology, useApiChequebookBalance } from '../../hooks/apiHooks';
export default function Status() {
const [beeRelease, setBeeRelease] = useState({ name: ''});
const [isLoadingBeeRelease, setIsLoadingBeeRelease] = useState<boolean>(false);
const [apiHost, setApiHost] = useState('');
const [debugApiHost, setDebugApiHost] = useState('');
const [statusChecksVisible, setStatusChecksVisible] = useState<boolean>(false);
const { health, isLoadingHealth } = useApiHealth()
const { nodeHealth, isLoadingNodeHealth } = useDebugApiHealth()
const { nodeReadiness, isLoadingNodeReadiness } = useApiReadiness()
const { nodeAddresses, isLoadingNodeAddresses } = useApiNodeAddresses()
const { chequebookAddress, isLoadingChequebookAddress } = useApiChequebookAddress()
const { nodeTopology, isLoadingNodeTopology } = useApiNodeTopology()
const { chequebookBalance, isLoadingChequebookBalance } = useApiChequebookBalance()
const fetchLatestBeeRelease = async () => {
setIsLoadingBeeRelease(true)
axios.get(`${process.env.REACT_APP_BEE_GITHUB_REPO_URL}/releases/latest`)
.then(res => {
setBeeRelease(res.data)
})
.catch(error => {
console.log(error)
})
.finally(() => {
setIsLoadingBeeRelease(false)
})
}
const fetchApiHost = () => {
let apiHost
if (sessionStorage.getItem('api_host')) {
apiHost = String(sessionStorage.getItem('api_host') || '')
} else {
apiHost = String(process.env.REACT_APP_BEE_HOST)
}
setApiHost(apiHost)
}
const fetchDebugApiHost = () => {
let debugApiHost
if (sessionStorage.getItem('debug_api_host')) {
debugApiHost = String(sessionStorage.getItem('debug_api_host') || '')
} else {
debugApiHost = String(process.env.REACT_APP_BEE_DEBUG_HOST)
}
setDebugApiHost(debugApiHost)
}
useEffect(() => {
fetchApiHost()
fetchDebugApiHost()
fetchLatestBeeRelease()
}, []);
return (
<div>
{nodeHealth?.status === 'ok' &&
health &&
beeRelease &&
beeRelease.name === `v${nodeHealth?.version?.split('-')[0]}` &&
nodeAddresses?.ethereum &&
chequebookAddress?.chequebookaddress && chequebookBalance && chequebookBalance?.totalBalance > 0 &&
nodeTopology.connected && nodeTopology.connected > 0 &&
!statusChecksVisible ?
<div>
<StatusCard
nodeHealth={nodeHealth}
loadingNodeHealth={isLoadingNodeHealth}
nodeReadiness={nodeReadiness}
loadingNodeReadiness={isLoadingNodeReadiness}
beeRelease={beeRelease}
loadingBeeRelease={isLoadingBeeRelease}
nodeAddresses={nodeAddresses}
loadingNodeTopology={isLoadingNodeTopology}
nodeTopology={nodeTopology}
setStatusChecksVisible={setStatusChecksVisible}
/>
<EthereumAddressCard
nodeAddresses={nodeAddresses}
isLoadingNodeAddresses={isLoadingNodeAddresses}
chequebookAddress={chequebookAddress}
isLoadingChequebookAddress={isLoadingChequebookAddress}
/>
</div>
:
( isLoadingNodeHealth || isLoadingHealth || isLoadingNodeReadiness || isLoadingChequebookAddress ||
isLoadingNodeTopology || isLoadingBeeRelease || isLoadingNodeAddresses || isLoadingBeeRelease || isLoadingChequebookBalance
)
?
<Container style={{textAlign:'center', padding:'50px'}}>
<CircularProgress />
</Container>
:
<NodeSetupWorkflow
beeRelease={beeRelease}
isLoadingBeeRelease={isLoadingBeeRelease}
nodeHealth={nodeHealth}
isLoadingNodeHealth={isLoadingNodeHealth}
nodeReadiness={nodeReadiness}
isLoadingNodeReadiness={isLoadingNodeReadiness}
nodeAddresses={nodeAddresses}
isLoadingNodeAddresses={isLoadingNodeAddresses}
nodeTopology={nodeTopology}
isLoadingNodeTopology={isLoadingNodeTopology}
nodeApiHealth={health}
isLoadingHealth={isLoadingHealth}
chequebookAddress={chequebookAddress}
isLoadingChequebookAddress={isLoadingChequebookAddress}
chequebookBalance={chequebookBalance}
isLoadingChequebookBalance={isLoadingChequebookBalance}
apiHost={apiHost}
debugApiHost={debugApiHost}
setStatusChecksVisible={setStatusChecksVisible}
/>
}
</div>
)
}