feat: bee provider caching the state of the app and refreshing periodically (#172)
* feat: bee provider caching the state of the app and refreshing periodically * chore: added error handling
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { ReactElement, useEffect, useState } from 'react'
|
||||
import { ReactElement, useEffect, useState, useContext } 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, Autorenew } from '@material-ui/icons/'
|
||||
@@ -9,7 +9,7 @@ import VersionCheck from './SetupSteps/VersionCheck'
|
||||
import EthereumConnectionCheck from './SetupSteps/EthereumConnectionCheck'
|
||||
import ChequebookDeployFund from './SetupSteps/ChequebookDeployFund'
|
||||
import PeerConnection from './SetupSteps/PeerConnection'
|
||||
import { StatusChequebookHook } from '../../hooks/status'
|
||||
import { Context } from '../../providers/Bee'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -30,66 +30,65 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
interface Step {
|
||||
label: string
|
||||
isOk: boolean
|
||||
isLoading: boolean
|
||||
component: ReactElement
|
||||
}
|
||||
|
||||
interface Props {
|
||||
nodeVersion: StatusNodeVersionHook
|
||||
ethereumConnection: StatusEthereumConnectionHook
|
||||
debugApiConnection: StatusHookCommon
|
||||
apiConnection: StatusHookCommon
|
||||
topology: StatusTopologyHook
|
||||
chequebook: StatusChequebookHook
|
||||
}
|
||||
|
||||
export default function NodeSetupWorkflow({
|
||||
nodeVersion,
|
||||
ethereumConnection,
|
||||
debugApiConnection,
|
||||
apiConnection,
|
||||
topology,
|
||||
chequebook,
|
||||
}: Props): ReactElement {
|
||||
export default function NodeSetupWorkflow(): ReactElement {
|
||||
const classes = useStyles()
|
||||
const [activeStep, setActiveStep] = useState(-1)
|
||||
|
||||
const {
|
||||
status,
|
||||
isLoading,
|
||||
latestUserVersion,
|
||||
latestPublishedVersion,
|
||||
isLatestBeeVersion,
|
||||
latestBeeVersionUrl,
|
||||
topology,
|
||||
nodeAddresses,
|
||||
chequebookAddress,
|
||||
} = useContext(Context)
|
||||
|
||||
const steps: Step[] = [
|
||||
{
|
||||
label: 'Connected to Node DebugAPI',
|
||||
isOk: debugApiConnection.isOk,
|
||||
isLoading: debugApiConnection.isLoading,
|
||||
component: <DebugConnectionCheck {...debugApiConnection} />,
|
||||
isOk: status.debugApiConnection,
|
||||
component: <DebugConnectionCheck isOk={status.debugApiConnection} />,
|
||||
},
|
||||
{
|
||||
label: 'Running latest Bee version',
|
||||
isOk: nodeVersion.isOk,
|
||||
isLoading: nodeVersion.isLoading,
|
||||
component: <VersionCheck {...nodeVersion} />,
|
||||
isOk: status.version,
|
||||
component: (
|
||||
<VersionCheck
|
||||
isOk={status.version}
|
||||
isLatestBeeVersion={isLatestBeeVersion}
|
||||
userVersion={latestUserVersion}
|
||||
latestVersion={latestPublishedVersion}
|
||||
latestUrl={latestBeeVersionUrl}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: 'Connected to Ethereum Blockchain',
|
||||
isOk: ethereumConnection.isOk,
|
||||
isLoading: ethereumConnection.isLoading,
|
||||
component: <EthereumConnectionCheck {...ethereumConnection} />,
|
||||
label: 'Connected to xDai Blockchain',
|
||||
isOk: status.blockchainConnection,
|
||||
component: <EthereumConnectionCheck isOk={status.blockchainConnection} nodeAddresses={nodeAddresses} />,
|
||||
},
|
||||
{
|
||||
label: 'Deployed and Funded Chequebook',
|
||||
isOk: chequebook.isOk,
|
||||
isLoading: chequebook.isLoading,
|
||||
component: <ChequebookDeployFund ethereumAddress={ethereumConnection.nodeAddresses?.ethereum} {...chequebook} />,
|
||||
isOk: status.chequebook,
|
||||
component: (
|
||||
<ChequebookDeployFund chequebookAddress={chequebookAddress?.chequebookAddress} isOk={status.chequebook} />
|
||||
),
|
||||
},
|
||||
{
|
||||
label: 'Connected to Node API',
|
||||
isOk: apiConnection.isOk,
|
||||
isLoading: apiConnection.isLoading,
|
||||
component: <NodeConnectionCheck {...apiConnection} />,
|
||||
isOk: status.apiConnection,
|
||||
component: <NodeConnectionCheck isOk={status.apiConnection} />,
|
||||
},
|
||||
{
|
||||
label: 'Connected to Peers',
|
||||
isOk: topology.isOk,
|
||||
isLoading: topology.isLoading,
|
||||
component: <PeerConnection {...topology} />,
|
||||
isOk: status.topology,
|
||||
component: <PeerConnection isOk={status.topology} topology={topology} />,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -98,7 +97,7 @@ export default function NodeSetupWorkflow({
|
||||
if (activeStep >= 0 && activeStep < steps.length) return
|
||||
|
||||
// If any step is not fully loaded yet return
|
||||
if (!steps.every(step => !step.isLoading)) return
|
||||
if (!isLoading) return
|
||||
|
||||
// Select first step that is not OK
|
||||
// This is deliberately a for loop (and not forEach) so that we can terminate the useEffect from within the cycle
|
||||
@@ -131,10 +130,9 @@ export default function NodeSetupWorkflow({
|
||||
</span>
|
||||
</Typography>
|
||||
<Stepper nonLinear activeStep={activeStep} orientation="vertical">
|
||||
{steps.map(({ label, isOk, component, isLoading }, index) => (
|
||||
{steps.map(({ label, isOk, component }, index) => (
|
||||
<Step key={label}>
|
||||
<StepLabel
|
||||
disabled={isLoading}
|
||||
onClick={() => setActiveStep(index === activeStep ? steps.length : index)}
|
||||
StepIconComponent={() => {
|
||||
if (isLoading) return <Autorenew style={{ height: '25px', cursor: 'pointer' }} />
|
||||
|
||||
@@ -2,22 +2,17 @@ import { Typography } from '@material-ui/core/'
|
||||
import EthereumAddress from '../../../components/EthereumAddress'
|
||||
import DepositModal from '../../../containers/DepositModal'
|
||||
import type { ReactElement } from 'react'
|
||||
import type { StatusChequebookHook } from '../../../hooks/status'
|
||||
|
||||
interface Props extends StatusChequebookHook {
|
||||
ethereumAddress?: string
|
||||
interface Props extends StatusHookCommon {
|
||||
chequebookAddress?: string
|
||||
}
|
||||
|
||||
const ChequebookDeployFund = ({ isLoading, chequebookAddress, chequebookBalance }: Props): ReactElement | null => {
|
||||
if (isLoading) return null
|
||||
|
||||
const ChequebookDeployFund = ({ chequebookAddress, isOk }: Props): ReactElement | null => {
|
||||
return (
|
||||
<div>
|
||||
<p style={{ marginBottom: '20px', display: 'flex' }}>
|
||||
{chequebookAddress?.chequebookAddress && <DepositModal />}
|
||||
</p>
|
||||
<p style={{ marginBottom: '20px', display: 'flex' }}>{chequebookAddress && <DepositModal />}</p>
|
||||
<div style={{ marginBottom: '10px' }}>
|
||||
{!(chequebookAddress?.chequebookAddress && chequebookBalance?.totalBalance.toBigNumber.isGreaterThan(0)) && (
|
||||
{!isOk && (
|
||||
<div>
|
||||
<span>
|
||||
Your chequebook is either not deployed or funded. To run the node you will need xDAI and xBZZ on the xDai
|
||||
@@ -33,7 +28,7 @@ const ChequebookDeployFund = ({ isLoading, chequebookAddress, chequebookBalance
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
Chequebook Address
|
||||
</Typography>
|
||||
<EthereumAddress address={chequebookAddress?.chequebookAddress} />
|
||||
<EthereumAddress address={chequebookAddress} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,9 +9,7 @@ import { debugApiHost } from '../../../constants'
|
||||
|
||||
type Props = StatusHookCommon
|
||||
|
||||
export default function NodeConnectionCheck({ isLoading, isOk }: Props): ReactElement | null {
|
||||
if (isLoading) return null
|
||||
|
||||
export default function NodeConnectionCheck({ isOk }: Props): ReactElement | null {
|
||||
const changeDebugApiUrl = (
|
||||
<div style={{ display: 'flex', marginTop: '25px', marginBottom: '25px' }}>
|
||||
<span style={{ marginRight: '15px' }}>
|
||||
|
||||
@@ -4,9 +4,7 @@ import EthereumAddress from '../../../components/EthereumAddress'
|
||||
|
||||
type Props = StatusEthereumConnectionHook
|
||||
|
||||
export default function EthereumConnectionCheck({ isLoading, isOk, nodeAddresses }: Props): ReactElement | null {
|
||||
if (isLoading) return null
|
||||
|
||||
export default function EthereumConnectionCheck({ isOk, nodeAddresses }: Props): ReactElement | null {
|
||||
if (isOk) {
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -8,9 +8,7 @@ import { apiHost } from '../../../constants'
|
||||
|
||||
type Props = StatusHookCommon
|
||||
|
||||
export default function NodeConnectionCheck({ isLoading, isOk }: Props): ReactElement | null {
|
||||
if (isLoading) return null
|
||||
|
||||
export default function NodeConnectionCheck({ isOk }: Props): ReactElement | null {
|
||||
return (
|
||||
<div>
|
||||
<div style={{ display: 'flex', marginBottom: '25px' }}>
|
||||
|
||||
@@ -3,9 +3,7 @@ import { Typography } from '@material-ui/core/'
|
||||
|
||||
type Props = StatusTopologyHook
|
||||
|
||||
export default function PeerConnection({ isLoading, isOk, topology }: Props): ReactElement | null {
|
||||
if (isLoading) return null
|
||||
|
||||
export default function PeerConnection({ isOk, topology }: Props): ReactElement | null {
|
||||
const peers = (
|
||||
<div style={{ display: 'flex', marginTop: '15px' }}>
|
||||
<div style={{ marginRight: '30px' }}>
|
||||
|
||||
@@ -4,15 +4,7 @@ import CodeBlockTabs from '../../../components/CodeBlockTabs'
|
||||
|
||||
type Props = StatusNodeVersionHook
|
||||
|
||||
export default function VersionCheck({
|
||||
isLoading,
|
||||
isOk,
|
||||
userVersion,
|
||||
latestVersion,
|
||||
latestUrl,
|
||||
}: Props): ReactElement | null {
|
||||
if (isLoading) return null
|
||||
|
||||
export default function VersionCheck({ isOk, userVersion, latestVersion, latestUrl }: Props): ReactElement | null {
|
||||
const version = (
|
||||
<div style={{ display: 'flex' }}>
|
||||
<div style={{ marginRight: '30px' }}>
|
||||
|
||||
+20
-48
@@ -1,18 +1,10 @@
|
||||
import { ReactElement } from 'react'
|
||||
import { Container, CircularProgress } from '@material-ui/core'
|
||||
import { ReactElement, useContext } from 'react'
|
||||
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'
|
||||
|
||||
import NodeSetupWorkflow from './NodeSetupWorkflow'
|
||||
import StatusCard from './StatusCard'
|
||||
import EthereumAddressCard from '../../components/EthereumAddressCard'
|
||||
import {
|
||||
useStatusEthereumConnection,
|
||||
useStatusNodeVersion,
|
||||
useStatusDebugConnection,
|
||||
useStatusConnection,
|
||||
useStatusTopology,
|
||||
useStatusChequebook,
|
||||
} from '../../hooks/status'
|
||||
import { Context } from '../../providers/Bee'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -27,50 +19,30 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
export default function Status(): ReactElement {
|
||||
const classes = useStyles()
|
||||
|
||||
const nodeVersion = useStatusNodeVersion()
|
||||
const ethereumConnection = useStatusEthereumConnection()
|
||||
const debugApiConnection = useStatusDebugConnection()
|
||||
const apiConnection = useStatusConnection()
|
||||
const topology = useStatusTopology()
|
||||
const chequebook = useStatusChequebook()
|
||||
|
||||
const checks = [nodeVersion, ethereumConnection, debugApiConnection, apiConnection, topology, chequebook]
|
||||
|
||||
// If any check data are still loading
|
||||
if (!checks.every(c => !c.isLoading)) {
|
||||
return (
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
const {
|
||||
status,
|
||||
latestUserVersion,
|
||||
isLatestBeeVersion,
|
||||
latestBeeVersionUrl,
|
||||
topology,
|
||||
nodeAddresses,
|
||||
chequebookAddress,
|
||||
} = useContext(Context)
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<StatusCard
|
||||
userBeeVersion={nodeVersion.userVersion}
|
||||
isLatestBeeVersion={nodeVersion.isLatestBeeVersion}
|
||||
isOk={checks.every(c => c.isOk)}
|
||||
nodeTopology={topology.topology}
|
||||
latestUrl={nodeVersion.latestUrl}
|
||||
nodeAddresses={ethereumConnection.nodeAddresses}
|
||||
userBeeVersion={latestUserVersion}
|
||||
isLatestBeeVersion={isLatestBeeVersion}
|
||||
isOk={status.all}
|
||||
nodeTopology={topology}
|
||||
latestUrl={latestBeeVersionUrl}
|
||||
nodeAddresses={nodeAddresses}
|
||||
/>
|
||||
{ethereumConnection.nodeAddresses && chequebook.chequebookAddress && (
|
||||
<EthereumAddressCard
|
||||
nodeAddresses={ethereumConnection.nodeAddresses}
|
||||
isLoadingNodeAddresses={ethereumConnection.isLoading}
|
||||
chequebookAddress={chequebook.chequebookAddress}
|
||||
isLoadingChequebookAddress={chequebook.isLoading}
|
||||
/>
|
||||
{nodeAddresses && chequebookAddress && (
|
||||
<EthereumAddressCard nodeAddresses={nodeAddresses} chequebookAddress={chequebookAddress} />
|
||||
)}
|
||||
<NodeSetupWorkflow
|
||||
nodeVersion={nodeVersion}
|
||||
ethereumConnection={ethereumConnection}
|
||||
debugApiConnection={debugApiConnection}
|
||||
apiConnection={apiConnection}
|
||||
topology={topology}
|
||||
chequebook={chequebook}
|
||||
/>
|
||||
<NodeSetupWorkflow />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user