Skip to content

Commit

Permalink
feat: reviewed and simplified the node status check (#63)
Browse files Browse the repository at this point in the history
* refactor: status page nested ternary logic

* refactor: move the fetch latest bee release to a hook

* refactor: solved node status rerendering, improved performance and clarity

* refactor: step components now use unified hooks interface

* style: removed component margins, layout should be handled by pages
  • Loading branch information
vojtechsimetka committed Apr 9, 2021
1 parent 5608b91 commit 9e4e58f
Show file tree
Hide file tree
Showing 14 changed files with 656 additions and 764 deletions.
74 changes: 35 additions & 39 deletions src/components/EthereumAddressCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ const useStyles = makeStyles(() =>
createStyles({
root: {
display: 'flex',
marginTop: '20px',
alignItems: 'center',
justifyContent: 'space-around',
flexWrap: 'wrap',
},
details: {
display: 'flex',
Expand All @@ -21,10 +23,6 @@ const useStyles = makeStyles(() =>
content: {
flex: '1 0 auto',
},
status: {
color: '#fff',
backgroundColor: '#76a9fa',
},
}),
)

Expand All @@ -39,40 +37,38 @@ function EthereumAddressCard(props: Props): ReactElement {
const classes = useStyles()

return (
<div>
<Card className={classes.root}>
{props.isLoadingNodeAddresses ? (
<div style={{ padding: '16px' }}>
<Skeleton width={300} height={30} animation="wave" />
<Skeleton width={300} height={50} animation="wave" />
</div>
) : (
<div className={classes.details}>
<CardContent className={classes.content}>
<Typography variant="subtitle1" gutterBottom>
Ethereum Address
</Typography>
<EthereumAddress address={props.nodeAddresses?.ethereum} network={'goerli'} />
</CardContent>
</div>
)}
{props.isLoadingChequebookAddress ? (
<div style={{ padding: '16px' }}>
<Skeleton width={300} height={30} animation="wave" />
<Skeleton width={300} height={50} animation="wave" />
</div>
) : (
<div className={classes.details}>
<CardContent className={classes.content}>
<Typography variant="subtitle1" gutterBottom>
Chequebook Contract Address
</Typography>
<EthereumAddress address={props.chequebookAddress?.chequebookaddress} network={'goerli'} />
</CardContent>
</div>
)}
</Card>
</div>
<Card className={classes.root}>
{props.isLoadingNodeAddresses ? (
<div style={{ padding: '16px' }}>
<Skeleton width={300} height={30} animation="wave" />
<Skeleton width={300} height={50} animation="wave" />
</div>
) : (
<div className={classes.details}>
<CardContent className={classes.content}>
<Typography variant="subtitle1" gutterBottom>
Ethereum Address
</Typography>
<EthereumAddress address={props.nodeAddresses?.ethereum} network={'goerli'} />
</CardContent>
</div>
)}
{props.isLoadingChequebookAddress ? (
<div style={{ padding: '16px' }}>
<Skeleton width={300} height={30} animation="wave" />
<Skeleton width={300} height={50} animation="wave" />
</div>
) : (
<div className={classes.details}>
<CardContent className={classes.content}>
<Typography variant="subtitle1" gutterBottom>
Chequebook Contract Address
</Typography>
<EthereumAddress address={props.chequebookAddress?.chequebookaddress} network={'goerli'} />
</CardContent>
</div>
)}
</Card>
)
}

Expand Down
29 changes: 29 additions & 0 deletions src/hooks/apiHooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from '@ethersphere/bee-js'

import { beeDebugApi, beeApi } from '../services/bee'
import axios from 'axios'

export interface HealthHook {
health: boolean
Expand Down Expand Up @@ -361,3 +362,31 @@ export const useApiPeerLastCashout = (peerId: string): PeerLastCashoutHook => {

return { peerCashout, isLoadingPeerCashout, error }
}

export interface LatestBeeReleaseHook {
latestBeeRelease: LatestBeeRelease | null
isLoadingLatestBeeRelease: boolean
error: Error | null
}

export const useLatestBeeRelease = (): LatestBeeReleaseHook => {
const [latestBeeRelease, setLatestBeeRelease] = useState<LatestBeeRelease | null>(null)
const [isLoadingLatestBeeRelease, setLoading] = useState<boolean>(false)
const [error, setError] = useState<Error | null>(null)

useEffect(() => {
axios
.get(`${process.env.REACT_APP_BEE_GITHUB_REPO_URL}/releases/latest`)
.then(res => {
setLatestBeeRelease(res.data)
})
.catch((error: Error) => {
setError(error)
})
.finally(() => {
setLoading(false)
})
}, [])

return { latestBeeRelease, isLoadingLatestBeeRelease, error }
}
73 changes: 73 additions & 0 deletions src/hooks/status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {
useApiChequebookAddress,
useApiChequebookBalance,
useApiHealth,
useApiNodeAddresses,
useApiNodeTopology,
useDebugApiHealth,
useLatestBeeRelease,
} from './apiHooks'

export const useStatusNodeVersion = (): StatusNodeVersionHook => {
const { latestBeeRelease, isLoadingLatestBeeRelease } = useLatestBeeRelease()
const { nodeHealth, isLoadingNodeHealth } = useDebugApiHealth()

return {
isLoading: isLoadingNodeHealth || isLoadingLatestBeeRelease,
isOk: Boolean(latestBeeRelease && latestBeeRelease.name === `v${nodeHealth?.version?.split('-')[0]}`),
userVersion: nodeHealth?.version?.split('-')[0] || '-',
latestVersion: latestBeeRelease?.name.substring(1) || '-',
latestUrl: latestBeeRelease?.html_url || 'https://github.com/ethersphere/bee/releases/latest',
}
}

export const useStatusEthereumConnection = (): StatusEthereumConnectionHook => {
const { isLoadingNodeAddresses, nodeAddresses } = useApiNodeAddresses()

return {
isLoading: isLoadingNodeAddresses,
isOk: Boolean(nodeAddresses?.ethereum),
nodeAddresses,
}
}

export const useStatusDebugConnection = (): StatusHookCommon => {
const { isLoadingNodeHealth, nodeHealth } = useDebugApiHealth()

return {
isLoading: isLoadingNodeHealth,
isOk: Boolean(nodeHealth?.status === 'ok'),
}
}

export const useStatusConnection = (): StatusHookCommon => {
const { isLoadingHealth, health } = useApiHealth()

return {
isLoading: isLoadingHealth,
isOk: health,
}
}

export const useStatusTopology = (): StatusTopologyHook => {
const { topology, isLoading } = useApiNodeTopology()

return {
isLoading,
isOk: Boolean(topology?.connected && topology?.connected > 0),
topology,
}
}

export const useStatusChequebook = (): StatusChequebookHook => {
const { chequebookAddress, isLoadingChequebookAddress } = useApiChequebookAddress()
const { chequebookBalance, isLoadingChequebookBalance } = useApiChequebookBalance()

return {
isLoading: isLoadingChequebookAddress || isLoadingChequebookBalance,
isOk:
Boolean(chequebookAddress?.chequebookaddress) && chequebookBalance !== null && chequebookBalance.totalBalance > 0,
chequebookBalance,
chequebookAddress,
}
}
46 changes: 29 additions & 17 deletions src/pages/accounting/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ReactElement, useState, ChangeEvent, ReactChild } from 'react'
import { withStyles, Theme, createStyles } from '@material-ui/core/styles'
import { withStyles, Theme, createStyles, makeStyles } from '@material-ui/core/styles'
import { Tabs, Tab, Box, Typography, Container, CircularProgress } from '@material-ui/core'

import AccountCard from '../accounting/AccountCard'
Expand Down Expand Up @@ -33,8 +33,19 @@ function a11yProps(index: number) {
}
}

const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
width: '100%',
display: 'grid',
rowGap: theme.spacing(3),
},
}),
)

export default function Accounting(): ReactElement {
const [value, setValue] = useState(0)
const classes = useStyles()

const handleChange = (event: ChangeEvent<unknown>, newValue: number) => {
setValue(newValue)
Expand Down Expand Up @@ -115,7 +126,6 @@ export default function Accounting(): ReactElement {
color: '#3f51b5',
},
},
selected: {},
}),
)((props: StyledTabProps) => <Tab disableRipple {...props} />)

Expand All @@ -125,7 +135,7 @@ export default function Accounting(): ReactElement {
// FIXME: this should be broken up
/* eslint-disable no-nested-ternary */
nodeHealth?.status === 'ok' && health ? (
<div>
<div className={classes.root}>
<AccountCard
chequebookAddress={chequebookAddress}
isLoadingChequebookAddress={isLoadingChequebookAddress}
Expand All @@ -140,20 +150,22 @@ export default function Accounting(): ReactElement {
chequebookAddress={chequebookAddress}
isLoadingChequebookAddress={isLoadingChequebookAddress}
/>
<AntTabs style={{ marginTop: '12px' }} value={value} onChange={handleChange} aria-label="ant example">
<AntTab label="Balances" {...a11yProps(0)} />
<AntTab label="Chequebook" {...a11yProps(1)} />
<AntTab label="Settlements" {...a11yProps(2)} />
</AntTabs>
<TabPanel value={value} index={0}>
<BalancesTable peerBalances={peerBalances} loading={isLoadingPeerBalances} />
</TabPanel>
<TabPanel value={value} index={1}>
<ChequebookTable peerCheques={peerCheques} loading={isLoadingPeerCheques} />
</TabPanel>
<TabPanel value={value} index={2}>
<SettlementsTable nodeSettlements={settlements} loading={isLoadingSettlements} />
</TabPanel>
<div>
<AntTabs style={{ marginTop: '12px' }} value={value} onChange={handleChange} aria-label="ant example">
<AntTab label="Balances" {...a11yProps(0)} />
<AntTab label="Chequebook" {...a11yProps(1)} />
<AntTab label="Settlements" {...a11yProps(2)} />
</AntTabs>
<TabPanel value={value} index={0}>
<BalancesTable peerBalances={peerBalances} loading={isLoadingPeerBalances} />
</TabPanel>
<TabPanel value={value} index={1}>
<ChequebookTable peerCheques={peerCheques} loading={isLoadingPeerCheques} />
</TabPanel>
<TabPanel value={value} index={2}>
<SettlementsTable nodeSettlements={settlements} loading={isLoadingSettlements} />
</TabPanel>
</div>
</div>
) : isLoadingHealth || isLoadingNodeHealth ? (
<Container style={{ textAlign: 'center', padding: '50px' }}>
Expand Down
Loading

0 comments on commit 9e4e58f

Please sign in to comment.