feat: status page redesign (#214)
* feat: initial rewrite without status indicators * feat: status icon as a component and add to the node setup * feat: added input list item component * feat: improved the topology status info * fix: disabled state of the buttons * chore: removed unused components * chore: remove debug console log * fix: deposit modal helper text
This commit is contained in:
@@ -1,50 +0,0 @@
|
|||||||
import React, { ReactElement, useState } from 'react'
|
|
||||||
import { TextField, Button } from '@material-ui/core'
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
defaultHost?: string
|
|
||||||
setHost: (host: string) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function ConnectToHost(props: Props): ReactElement {
|
|
||||||
const [hostInputVisible, toggleHostInputVisibility] = useState(false)
|
|
||||||
const [host, setHost] = useState('')
|
|
||||||
|
|
||||||
const handleNewHostConnection = () => {
|
|
||||||
if (host) {
|
|
||||||
props.setHost(host)
|
|
||||||
toggleHostInputVisibility(!hostInputVisible)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{hostInputVisible ? (
|
|
||||||
<div style={{ display: 'flex' }}>
|
|
||||||
<TextField
|
|
||||||
defaultValue={props.defaultHost}
|
|
||||||
label="Enter host"
|
|
||||||
variant="outlined"
|
|
||||||
size="small"
|
|
||||||
onChange={e => setHost(e.target.value)}
|
|
||||||
style={{ marginRight: '15px', minWidth: '300px' }}
|
|
||||||
/>
|
|
||||||
<Button onClick={() => handleNewHostConnection()} size="small" variant="outlined">
|
|
||||||
Connect
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
style={{ marginLeft: '7px' }}
|
|
||||||
onClick={() => toggleHostInputVisibility(!hostInputVisible)}
|
|
||||||
size="small"
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<Button onClick={() => toggleHostInputVisibility(!hostInputVisible)} size="small" variant="outlined">
|
|
||||||
Change host
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
import { ReactElement } from 'react'
|
|
||||||
|
|
||||||
import { createStyles, makeStyles } from '@material-ui/core/styles'
|
|
||||||
import { Card, CardContent, Typography } from '@material-ui/core/'
|
|
||||||
|
|
||||||
import EthereumAddress from '../components/EthereumAddress'
|
|
||||||
|
|
||||||
import type { ChequebookAddressResponse, NodeAddresses } from '@ethersphere/bee-js'
|
|
||||||
|
|
||||||
const useStyles = makeStyles(() =>
|
|
||||||
createStyles({
|
|
||||||
root: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'space-around',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
},
|
|
||||||
details: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
},
|
|
||||||
content: {
|
|
||||||
flex: '1 0 auto',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
nodeAddresses: NodeAddresses | null
|
|
||||||
chequebookAddress: ChequebookAddressResponse | null
|
|
||||||
}
|
|
||||||
|
|
||||||
function EthereumAddressCard(props: Props): ReactElement {
|
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card className={classes.root}>
|
|
||||||
<div className={classes.details}>
|
|
||||||
<CardContent className={classes.content}>
|
|
||||||
<Typography variant="subtitle1" gutterBottom>
|
|
||||||
Ethereum Address
|
|
||||||
</Typography>
|
|
||||||
<EthereumAddress address={props.nodeAddresses?.ethereum} />
|
|
||||||
</CardContent>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={classes.details}>
|
|
||||||
<CardContent className={classes.content}>
|
|
||||||
<Typography variant="subtitle1" gutterBottom>
|
|
||||||
Chequebook Contract Address
|
|
||||||
</Typography>
|
|
||||||
<EthereumAddress address={props.chequebookAddress?.chequebookAddress} />
|
|
||||||
</CardContent>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default EthereumAddressCard
|
|
||||||
@@ -24,7 +24,7 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
)
|
)
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
label?: string
|
label?: ReactNode
|
||||||
value?: ReactNode
|
value?: ReactNode
|
||||||
tooltip?: string
|
tooltip?: string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
import { ReactElement, useState } from 'react'
|
||||||
|
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'
|
||||||
|
import Collapse from '@material-ui/core/Collapse'
|
||||||
|
import { ListItem, Typography, Grid, IconButton, InputBase, Button } from '@material-ui/core'
|
||||||
|
import { Edit, Minus, RotateCcw, Check } from 'react-feather'
|
||||||
|
|
||||||
|
import ExpandableListItemActions from './ExpandableListItemActions'
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
|
createStyles({
|
||||||
|
header: {
|
||||||
|
backgroundColor: theme.palette.background.paper,
|
||||||
|
marginBottom: theme.spacing(0.25),
|
||||||
|
borderLeft: `${theme.spacing(0.25)}px solid rgba(0,0,0,0)`,
|
||||||
|
wordBreak: 'break-word',
|
||||||
|
},
|
||||||
|
headerOpen: {
|
||||||
|
borderLeft: `${theme.spacing(0.25)}px solid ${theme.palette.primary.main}`,
|
||||||
|
},
|
||||||
|
copyValue: {
|
||||||
|
cursor: 'pointer',
|
||||||
|
padding: theme.spacing(1),
|
||||||
|
borderRadius: 0,
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: '#fcf2e8',
|
||||||
|
color: theme.palette.primary.main,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
marginTop: theme.spacing(1),
|
||||||
|
marginBottom: theme.spacing(1),
|
||||||
|
},
|
||||||
|
keyMargin: {
|
||||||
|
marginRight: theme.spacing(1),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
label: string
|
||||||
|
value: string
|
||||||
|
onConfirm: (value: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ExpandableListItemKey({ label, value, onConfirm }: Props): ReactElement | null {
|
||||||
|
const classes = useStyles()
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
|
const [inputValue, setInputValue] = useState(value)
|
||||||
|
const toggleOpen = () => setOpen(!open)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ListItem className={`${classes.header} ${open ? classes.headerOpen : ''}`}>
|
||||||
|
<Grid container direction="column" justifyContent="space-between" alignItems="stretch">
|
||||||
|
<Grid container direction="row" justifyContent="space-between" alignItems="center">
|
||||||
|
{label && <Typography variant="body1">{label}</Typography>}
|
||||||
|
<Typography variant="body2">
|
||||||
|
<div>
|
||||||
|
{!open && value}
|
||||||
|
<IconButton size="small" className={classes.copyValue}>
|
||||||
|
{open ? (
|
||||||
|
<Minus onClick={toggleOpen} strokeWidth={1} />
|
||||||
|
) : (
|
||||||
|
<Edit onClick={toggleOpen} strokeWidth={1} />
|
||||||
|
)}
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||||
|
<InputBase
|
||||||
|
value={inputValue}
|
||||||
|
onChange={e => setInputValue(e.target.value)}
|
||||||
|
fullWidth
|
||||||
|
className={classes.content}
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
</Collapse>
|
||||||
|
</Grid>
|
||||||
|
</ListItem>
|
||||||
|
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||||
|
<ExpandableListItemActions>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
disabled={inputValue === value}
|
||||||
|
startIcon={<Check size="1rem" />}
|
||||||
|
onClick={() => onConfirm(inputValue)}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
disabled={inputValue === value}
|
||||||
|
startIcon={<RotateCcw size="1rem" />}
|
||||||
|
onClick={() => setInputValue(value)}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</ExpandableListItemActions>
|
||||||
|
</Collapse>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { ReactElement, ReactNode } from 'react'
|
||||||
|
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'
|
||||||
|
import { Typography } from '@material-ui/core'
|
||||||
|
import ListItem from '@material-ui/core/ListItem'
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
|
createStyles({
|
||||||
|
header: {
|
||||||
|
backgroundColor: '#F7F7F7',
|
||||||
|
marginBottom: theme.spacing(0.25),
|
||||||
|
},
|
||||||
|
typography: {
|
||||||
|
color: '#242424',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children?: ReactNode | ReactNode[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ExpandableListItemNote({ children }: Props): ReactElement | null {
|
||||||
|
const classes = useStyles()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ListItem className={classes.header}>
|
||||||
|
<Typography variant="body1" className={classes.typography}>
|
||||||
|
{children}
|
||||||
|
</Typography>
|
||||||
|
</ListItem>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import { ArrowRight } from 'react-feather'
|
|||||||
import { createStyles, Theme, makeStyles } from '@material-ui/core/styles'
|
import { createStyles, Theme, makeStyles } from '@material-ui/core/styles'
|
||||||
import { ListItemText, ListItemIcon, ListItem, Typography } from '@material-ui/core'
|
import { ListItemText, ListItemIcon, ListItem, Typography } from '@material-ui/core'
|
||||||
import { Context } from '../providers/Bee'
|
import { Context } from '../providers/Bee'
|
||||||
|
import StatusIcon from './StatusIcon'
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
@@ -50,7 +51,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function SideBarItem({ path }: Props): ReactElement {
|
export default function SideBarItem({ path }: Props): ReactElement {
|
||||||
const { status } = useContext(Context)
|
const { status, isLoading } = useContext(Context)
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const isSelected = Boolean(matchPath(location.pathname, { path, exact: true }))
|
const isSelected = Boolean(matchPath(location.pathname, { path, exact: true }))
|
||||||
@@ -62,17 +63,8 @@ export default function SideBarItem({ path }: Props): ReactElement {
|
|||||||
selected={isSelected}
|
selected={isSelected}
|
||||||
disableRipple
|
disableRipple
|
||||||
>
|
>
|
||||||
<ListItemIcon>
|
<ListItemIcon style={{ marginLeft: '30px' }}>
|
||||||
<span
|
<StatusIcon isOk={status.all} isLoading={isLoading} />
|
||||||
style={{
|
|
||||||
backgroundColor: status.all ? '#1de600' : '#ff3a52',
|
|
||||||
height: '14px',
|
|
||||||
width: '14px',
|
|
||||||
borderRadius: '50%',
|
|
||||||
display: 'inline-block',
|
|
||||||
marginLeft: 30,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={<Typography className={classes.smallerText}>{`Node ${status.all ? 'OK' : 'Error'}`}</Typography>}
|
primary={<Typography className={classes.smallerText}>{`Node ${status.all ? 'OK' : 'Error'}`}</Typography>}
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
import { Card, CardContent, Typography } from '@material-ui/core/'
|
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
|
||||||
import { Skeleton } from '@material-ui/lab'
|
|
||||||
import type { ReactElement } from 'react'
|
|
||||||
import { Title } from './Title'
|
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
|
||||||
root: {
|
|
||||||
minWidth: 275,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
label: string
|
|
||||||
statistic?: string
|
|
||||||
loading?: boolean
|
|
||||||
tooltip?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function StatCard({ loading, label, statistic, tooltip }: Props): ReactElement {
|
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card className={classes.root}>
|
|
||||||
<CardContent>
|
|
||||||
{loading && (
|
|
||||||
<>
|
|
||||||
<Skeleton width={180} height={25} animation="wave" />
|
|
||||||
<Skeleton width={180} height={35} animation="wave" />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{!loading && (
|
|
||||||
<>
|
|
||||||
<Title label={label} tooltip={tooltip} />
|
|
||||||
<Typography variant="h5" component="h2">
|
|
||||||
{statistic}
|
|
||||||
</Typography>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import type { ReactElement } from 'react'
|
||||||
|
import { CircularProgress } from '@material-ui/core'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
isOk: boolean
|
||||||
|
isLoading?: boolean
|
||||||
|
size?: number | string
|
||||||
|
className?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function StatusIcon({ isOk, size, className, isLoading }: Props): ReactElement {
|
||||||
|
const s = size || '1rem'
|
||||||
|
|
||||||
|
if (isLoading) return <CircularProgress size={s} className={className} />
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={className}
|
||||||
|
style={{
|
||||||
|
backgroundColor: isOk ? '#1de600' : '#ff3a52',
|
||||||
|
height: s,
|
||||||
|
width: s,
|
||||||
|
borderRadius: '50%',
|
||||||
|
display: 'inline-block',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
import { Grid, Tooltip, Typography } from '@material-ui/core/'
|
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
|
||||||
import { Info } from '@material-ui/icons'
|
|
||||||
import type { ReactElement } from 'react'
|
|
||||||
|
|
||||||
interface TitleProps {
|
|
||||||
label: string
|
|
||||||
tooltip?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
|
||||||
title: {
|
|
||||||
fontSize: 16,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
export function Title({ label, tooltip }: TitleProps): ReactElement {
|
|
||||||
const classes = useStyles()
|
|
||||||
|
|
||||||
if (!tooltip) {
|
|
||||||
return (
|
|
||||||
<Typography className={classes.title} color="textSecondary" gutterBottom>
|
|
||||||
{label}
|
|
||||||
</Typography>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// span is needed as Tooltip expects a non-functional element!
|
|
||||||
return (
|
|
||||||
<Tooltip title={tooltip}>
|
|
||||||
<span>
|
|
||||||
<Grid container direction="row" justify="space-between">
|
|
||||||
<Typography className={classes.title} color="textSecondary" gutterBottom>
|
|
||||||
{label}
|
|
||||||
</Typography>
|
|
||||||
<Info />
|
|
||||||
</Grid>
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import type { Topology } from '@ethersphere/bee-js'
|
import type { Topology } from '@ethersphere/bee-js'
|
||||||
import type { ReactElement } from 'react'
|
import type { ReactElement } from 'react'
|
||||||
import { pickThreshold, ThresholdValues } from '../utils/threshold'
|
import { pickThreshold, ThresholdValues } from '../utils/threshold'
|
||||||
import ExpandableList from './ExpandableList'
|
|
||||||
import ExpandableListItem from './ExpandableListItem'
|
import ExpandableListItem from './ExpandableListItem'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -20,7 +19,7 @@ const TopologyStats = (props: Props): ReactElement => {
|
|||||||
const percentageText = Math.round((actualTotalScore / maximumTotalScore) * 100) + '%'
|
const percentageText = Math.round((actualTotalScore / maximumTotalScore) * 100) + '%'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ExpandableList label="Connectivity" defaultOpen>
|
<>
|
||||||
<ExpandableListItem label="Overall Health Indicator" value={percentageText} />
|
<ExpandableListItem label="Overall Health Indicator" value={percentageText} />
|
||||||
<ExpandableListItem
|
<ExpandableListItem
|
||||||
label="Connected Peers"
|
label="Connected Peers"
|
||||||
@@ -37,7 +36,7 @@ const TopologyStats = (props: Props): ReactElement => {
|
|||||||
value={props.topology?.depth.toString()}
|
value={props.topology?.depth.toString()}
|
||||||
tooltip={thresholds.depth.explanation}
|
tooltip={thresholds.depth.explanation}
|
||||||
/>
|
/>
|
||||||
</ExpandableList>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default function DepositModal(): ReactElement {
|
|||||||
<WithdrawDepositModal
|
<WithdrawDepositModal
|
||||||
successMessage="Successful deposit."
|
successMessage="Successful deposit."
|
||||||
errorMessage="Error with depositing"
|
errorMessage="Error with depositing"
|
||||||
dialogMessage="Specify the amount of BZZ you would like to withdraw from your node."
|
dialogMessage="Specify the amount of BZZ you would like to deposit to your node."
|
||||||
label="Deposit"
|
label="Deposit"
|
||||||
icon={<Download size="1rem" />}
|
icon={<Download size="1rem" />}
|
||||||
min={new BigNumber(0)}
|
min={new BigNumber(0)}
|
||||||
|
|||||||
@@ -56,7 +56,9 @@ export default function Status(): ReactElement {
|
|||||||
<ExpandableListItemKey label="Ethereum address" value={nodeAddresses?.ethereum || ''} />
|
<ExpandableListItemKey label="Ethereum address" value={nodeAddresses?.ethereum || ''} />
|
||||||
<ExpandableListItemKey label="Chequebook contract address" value={chequebookAddress?.chequebookAddress || ''} />
|
<ExpandableListItemKey label="Chequebook contract address" value={chequebookAddress?.chequebookAddress || ''} />
|
||||||
</ExpandableList>
|
</ExpandableList>
|
||||||
<TopologyStats topology={topology} />
|
<ExpandableList label="Connectivity" defaultOpen>
|
||||||
|
<TopologyStats topology={topology} />
|
||||||
|
</ExpandableList>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,48 @@
|
|||||||
import { Typography } from '@material-ui/core/'
|
import { useContext } from 'react'
|
||||||
import EthereumAddress from '../../../components/EthereumAddress'
|
|
||||||
import DepositModal from '../../../containers/DepositModal'
|
import DepositModal from '../../../containers/DepositModal'
|
||||||
import type { ReactElement } from 'react'
|
import type { ReactElement } from 'react'
|
||||||
|
import ExpandableList from '../../../components/ExpandableList'
|
||||||
|
import ExpandableListItemKey from '../../../components/ExpandableListItemKey'
|
||||||
|
import ExpandableListItemActions from '../../../components/ExpandableListItemActions'
|
||||||
|
import ExpandableListItemNote from '../../../components/ExpandableListItemNote'
|
||||||
|
import StatusIcon from '../../../components/StatusIcon'
|
||||||
|
import { Context } from '../../../providers/Bee'
|
||||||
|
|
||||||
interface Props extends StatusHookCommon {
|
const ChequebookDeployFund = (): ReactElement | null => {
|
||||||
chequebookAddress?: string
|
const { status, isLoading, chequebookAddress } = useContext(Context)
|
||||||
}
|
const isOk = status.chequebook
|
||||||
|
|
||||||
const ChequebookDeployFund = ({ chequebookAddress, isOk }: Props): ReactElement | null => {
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<ExpandableList
|
||||||
<p style={{ marginBottom: '20px', display: 'flex' }}>{chequebookAddress && <DepositModal />}</p>
|
label={
|
||||||
<div style={{ marginBottom: '10px' }}>
|
<>
|
||||||
{!isOk && (
|
<StatusIcon isOk={isOk} isLoading={isLoading} /> Chequebook Deployment & Funding
|
||||||
<div>
|
</>
|
||||||
<span>
|
}
|
||||||
Your chequebook is either not deployed or funded. To run the node you will need xDAI and xBZZ on the xDai
|
>
|
||||||
network. You may need to aquire BZZ (e.g. <a href="https://bzz.exchange/">bzz.exchange</a>) and bridge it
|
<ExpandableListItemNote>
|
||||||
to the xDai network through the <a href="https://omni.xdaichain.com/bridge">omni bridge</a>. To pay the
|
{isOk ? (
|
||||||
transaction fees, you will also need xDAI token. You can purchase DAI on the network and bridge it to xDai
|
'Your chequebook is deployed and funded'
|
||||||
network through the <a href="https://bridge.xdaichain.com/">xDai Bridge</a>. See the{' '}
|
) : (
|
||||||
<a href="https://www.xdaichain.com/#xdai-stable-chain">official xDai website</a> for more information.
|
<>
|
||||||
</span>
|
Your chequebook is either not deployed or funded. To run the node you will need xDAI and xBZZ on the xDai
|
||||||
</div>
|
network. You may need to aquire BZZ (e.g. <a href="https://bzz.exchange/">bzz.exchange</a>) and bridge it to
|
||||||
|
the xDai network through the <a href="https://omni.xdaichain.com/bridge">omni bridge</a>. To pay the
|
||||||
|
transaction fees, you will also need xDAI token. You can purchase DAI on the network and bridge it to xDai
|
||||||
|
network through the <a href="https://bridge.xdaichain.com/">xDai Bridge</a>. See the{' '}
|
||||||
|
<a href="https://www.xdaichain.com/#xdai-stable-chain">official xDai website</a> for more information.
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</ExpandableListItemNote>
|
||||||
<Typography variant="subtitle1" gutterBottom>
|
{chequebookAddress && (
|
||||||
Chequebook Address
|
<>
|
||||||
</Typography>
|
<ExpandableListItemKey label="Chequebook Address" value={chequebookAddress.chequebookAddress} />
|
||||||
<EthereumAddress address={chequebookAddress} />
|
<ExpandableListItemActions>
|
||||||
</div>
|
<DepositModal />
|
||||||
|
</ExpandableListItemActions>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</ExpandableList>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,99 +1,87 @@
|
|||||||
import { ReactElement, useContext } from 'react'
|
import { ReactElement, useContext } from 'react'
|
||||||
import { Typography, Accordion, AccordionSummary, AccordionDetails } from '@material-ui/core/'
|
|
||||||
import MuiAlert from '@material-ui/lab/Alert'
|
import MuiAlert from '@material-ui/lab/Alert'
|
||||||
import { ExpandMoreSharp } from '@material-ui/icons/'
|
|
||||||
|
|
||||||
import ConnectToHost from '../../../components/ConnectToHost'
|
|
||||||
import CodeBlockTabs from '../../../components/CodeBlockTabs'
|
import CodeBlockTabs from '../../../components/CodeBlockTabs'
|
||||||
|
import ExpandableList from '../../../components/ExpandableList'
|
||||||
|
import ExpandableListItem from '../../../components/ExpandableListItem'
|
||||||
|
import ExpandableListItemInput from '../../../components/ExpandableListItemInput'
|
||||||
|
import ExpandableListItemNote from '../../../components/ExpandableListItemNote'
|
||||||
|
import StatusIcon from '../../../components/StatusIcon'
|
||||||
import { Context as SettingsContext } from '../../../providers/Settings'
|
import { Context as SettingsContext } from '../../../providers/Settings'
|
||||||
|
import { Context } from '../../../providers/Bee'
|
||||||
|
|
||||||
type Props = StatusHookCommon
|
export default function NodeConnectionCheck(): ReactElement | null {
|
||||||
|
const { status, isLoading } = useContext(Context)
|
||||||
export default function NodeConnectionCheck({ isOk }: Props): ReactElement | null {
|
|
||||||
const { setDebugApiUrl, apiDebugUrl } = useContext(SettingsContext)
|
const { setDebugApiUrl, apiDebugUrl } = useContext(SettingsContext)
|
||||||
|
const isOk = status.debugApiConnection
|
||||||
const changeDebugApiUrl = (
|
|
||||||
<div style={{ display: 'flex', marginTop: '25px', marginBottom: '25px' }}>
|
|
||||||
<span style={{ marginRight: '15px' }}>
|
|
||||||
Debug API (<Typography variant="button">{apiDebugUrl}</Typography>)
|
|
||||||
</span>
|
|
||||||
<ConnectToHost
|
|
||||||
setHost={(host: string) => {
|
|
||||||
console.log(host) // eslint-disable-line
|
|
||||||
setDebugApiUrl(host)
|
|
||||||
}}
|
|
||||||
defaultHost={apiDebugUrl}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
if (isOk) {
|
|
||||||
return changeDebugApiUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<ExpandableList
|
||||||
{changeDebugApiUrl}
|
label={
|
||||||
|
<>
|
||||||
|
<StatusIcon isOk={isOk} isLoading={isLoading} /> Connection to Bee Debug API
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ExpandableListItemNote>
|
||||||
|
{isOk
|
||||||
|
? 'The connection to the Bee nodes deug API has been successful'
|
||||||
|
: 'We cannot connect to your nodes debug API. Please check the following to troubleshoot your issue.'}
|
||||||
|
</ExpandableListItemNote>
|
||||||
|
<ExpandableListItemInput label="Bee Debug API" value={apiDebugUrl} onConfirm={setDebugApiUrl} />
|
||||||
|
|
||||||
<div>
|
{!isOk && (
|
||||||
<Typography component="div" variant="body2" gutterBottom style={{ margin: '15px' }}>
|
<ExpandableList level={1} label="Troubleshoot">
|
||||||
We cannot connect to your nodes debug API at <Typography variant="button">{apiDebugUrl}</Typography>. Please
|
<ExpandableListItem
|
||||||
check the following to troubleshoot your issue.
|
label={
|
||||||
<Accordion style={{ marginTop: '20px' }}>
|
<ol>
|
||||||
<AccordionSummary expandIcon={<ExpandMoreSharp />} aria-controls="panel1a-content" id="panel1a-header">
|
<li>Check the status of your node by running the below command to see if your node is running.</li>
|
||||||
<Typography>Troubleshoot</Typography>
|
<CodeBlockTabs showLineNumbers linux={`sudo systemctl status bee`} mac={`brew services list`} />
|
||||||
</AccordionSummary>
|
<li>
|
||||||
<AccordionDetails>
|
If your node is running, check your firewall settings to make sure that port 1635 (or your custom
|
||||||
<Typography component="div">
|
specified port) is bound to localhost. If your node is not running try executing the below command to
|
||||||
<ol>
|
start your bee node
|
||||||
<li>Check the status of your node by running the below command to see if your node is running.</li>
|
</li>
|
||||||
<CodeBlockTabs showLineNumbers linux={`sudo systemctl status bee`} mac={`brew services list`} />
|
<MuiAlert
|
||||||
<li>
|
style={{ marginTop: '10px', marginBottom: '10px' }}
|
||||||
If your node is running, check your firewall settings to make sure that port 1635 (or your custom
|
elevation={6}
|
||||||
specified port) is bound to localhost. If your node is not running try executing the below command
|
variant="filled"
|
||||||
to start your bee node
|
severity="error"
|
||||||
</li>
|
>
|
||||||
<MuiAlert
|
Your debug node API should never be completely open to the internet. If you want to connect remotely,
|
||||||
style={{ marginTop: '10px', marginBottom: '10px' }}
|
make sure your firewall settings are set to only allow specific trusted IP addresses and block all
|
||||||
elevation={6}
|
other ports. A simple google search for "what is my ip" will show you your computers public
|
||||||
variant="filled"
|
IP address to allow.
|
||||||
severity="error"
|
</MuiAlert>
|
||||||
>
|
<CodeBlockTabs
|
||||||
Your debug node API should never be completely open to the internet. If you want to connect
|
showLineNumbers
|
||||||
remotely, make sure your firewall settings are set to only allow specific trusted IP addresses and
|
linux={`sudo systemctl start bee`}
|
||||||
block all other ports. A simple google search for "what is my ip" will show you your
|
mac={`brew services start swarm-bee`}
|
||||||
computers public IP address to allow.
|
/>
|
||||||
</MuiAlert>
|
<li>Run the commands to validate your node is running and see the log output.</li>
|
||||||
<CodeBlockTabs
|
<CodeBlockTabs
|
||||||
showLineNumbers
|
showLineNumbers
|
||||||
linux={`sudo systemctl start bee`}
|
linux={`sudo systemctl status bee \njournalctl --lines=100 --follow --unit bee`}
|
||||||
mac={`brew services start swarm-bee`}
|
mac={`brew services list \ntail -f /usr/local/var/log/swarm-bee/bee.log`}
|
||||||
/>
|
/>
|
||||||
<li>Run the commands to validate your node is running and see the log output.</li>
|
<li>
|
||||||
<CodeBlockTabs
|
Lastly, check your nodes configuration settings to validate the debug API is enabled and the Cross
|
||||||
showLineNumbers
|
Origin Resource Sharing (CORS) setting is configured to allow your host. Config parameter{' '}
|
||||||
linux={`sudo systemctl status bee \njournalctl --lines=100 --follow --unit bee`}
|
<strong>debug-api-enable</strong> must be set to <strong>true</strong> and{' '}
|
||||||
mac={`brew services list \ntail -f /usr/local/var/log/swarm-bee/bee.log`}
|
<strong>cors-allowed-origins</strong> must be set to your host domain or IP (you can also use the
|
||||||
/>
|
wildcard <code>{"cors-allowed-origins: ['*']"}</code>). If edits are made to the configuration run the
|
||||||
<li>
|
restart command below for changes to take effect.
|
||||||
Lastly, check your nodes configuration settings to validate the debug API is enabled and the Cross
|
</li>
|
||||||
Origin Resource Sharing (CORS) setting is configured to allow your host. Config parameter{' '}
|
<CodeBlockTabs
|
||||||
<strong>debug-api-enable</strong> must be set to <strong>true</strong> and{' '}
|
showLineNumbers
|
||||||
<strong>cors-allowed-origins</strong> must be set to your host domain or IP (you can also use the
|
linux={`sudo vi /etc/bee/bee.yaml\nsudo systemctl restart bee`}
|
||||||
wildcard <code>{"cors-allowed-origins: ['*']"}</code>). If edits are made to the configuration run
|
mac={`sudo vi /usr/local/etc/swarm-bee/bee.yaml \nbrew services restart swarm-bee`}
|
||||||
the restart command below for changes to take effect.
|
/>
|
||||||
</li>
|
</ol>
|
||||||
<CodeBlockTabs
|
}
|
||||||
showLineNumbers
|
/>
|
||||||
linux={`sudo vi /etc/bee/bee.yaml\nsudo systemctl restart bee`}
|
</ExpandableList>
|
||||||
mac={`sudo vi /usr/local/etc/swarm-bee/bee.yaml \nbrew services restart swarm-bee`}
|
)}
|
||||||
/>
|
</ExpandableList>
|
||||||
</ol>
|
|
||||||
</Typography>
|
|
||||||
</AccordionDetails>
|
|
||||||
</Accordion>
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,42 @@
|
|||||||
import type { ReactElement } from 'react'
|
import { ReactElement, useContext } from 'react'
|
||||||
import { Typography } from '@material-ui/core/'
|
import ExpandableList from '../../../components/ExpandableList'
|
||||||
import EthereumAddress from '../../../components/EthereumAddress'
|
import ExpandableListItemKey from '../../../components/ExpandableListItemKey'
|
||||||
|
import ExpandableListItemNote from '../../../components/ExpandableListItemNote'
|
||||||
|
import StatusIcon from '../../../components/StatusIcon'
|
||||||
|
import { Context } from '../../../providers/Bee'
|
||||||
|
|
||||||
type Props = StatusEthereumConnectionHook
|
export default function EthereumConnectionCheck(): ReactElement | null {
|
||||||
|
const { status, isLoading, nodeAddresses } = useContext(Context)
|
||||||
export default function EthereumConnectionCheck({ isOk, nodeAddresses }: Props): ReactElement | null {
|
const isOk = status.blockchainConnection
|
||||||
if (isOk) {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Typography variant="subtitle1" gutterBottom>
|
|
||||||
Node Address
|
|
||||||
</Typography>
|
|
||||||
<EthereumAddress address={nodeAddresses?.ethereum} />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<p>
|
<ExpandableList
|
||||||
Your Bee node must have access to the xDai blockchain, so that it can interact and deploy your chequebook
|
label={
|
||||||
contract. You can run{' '}
|
<>
|
||||||
<a href="https://www.xdaichain.com/" rel="noreferrer" target="_blank">
|
<StatusIcon isOk={isOk} isLoading={isLoading} /> Connection to Blockchain
|
||||||
your own xDai node
|
</>
|
||||||
</a>
|
}
|
||||||
, or use a provider instead - we recommend{' '}
|
>
|
||||||
<a href="https://getblock.io/" rel="noreferrer" target="_blank">
|
<ExpandableListItemNote>
|
||||||
Getblock
|
{isOk ? (
|
||||||
</a>
|
'Your node is connected to the xDai blockchain'
|
||||||
. By default, Bee expects a local node at http://localhost:8545. To use a provider instead, simply change the{' '}
|
) : (
|
||||||
<strong>swap-endpoint</strong> in your configuration file.
|
<>
|
||||||
</p>
|
Your Bee node must have access to the xDai blockchain, so that it can interact and deploy your chequebook
|
||||||
|
contract. You can run{' '}
|
||||||
|
<a href="https://www.xdaichain.com/" rel="noreferrer" target="_blank">
|
||||||
|
your own xDai node
|
||||||
|
</a>
|
||||||
|
, or use a provider instead - we recommend{' '}
|
||||||
|
<a href="https://getblock.io/" rel="noreferrer" target="_blank">
|
||||||
|
Getblock
|
||||||
|
</a>
|
||||||
|
. By default, Bee expects a local node at http://localhost:8545. To use a provider instead, simply change
|
||||||
|
the <strong>swap-endpoint</strong> in your configuration file.
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</ExpandableListItemNote>
|
||||||
|
{nodeAddresses?.ethereum && <ExpandableListItemKey label="Ethereum Address" value={nodeAddresses?.ethereum} />}
|
||||||
|
</ExpandableList>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,61 +1,61 @@
|
|||||||
import { ReactElement, useContext } from 'react'
|
import { ReactElement, useContext } from 'react'
|
||||||
import { Typography, Accordion, AccordionSummary, AccordionDetails } from '@material-ui/core/'
|
|
||||||
import { ExpandMoreSharp } from '@material-ui/icons/'
|
|
||||||
|
|
||||||
import ConnectToHost from '../../../components/ConnectToHost'
|
|
||||||
import CodeBlockTabs from '../../../components/CodeBlockTabs'
|
import CodeBlockTabs from '../../../components/CodeBlockTabs'
|
||||||
import { Context as SettingsContext } from '../../../providers/Settings'
|
import { Context as SettingsContext } from '../../../providers/Settings'
|
||||||
|
import ExpandableList from '../../../components/ExpandableList'
|
||||||
|
import ExpandableListItem from '../../../components/ExpandableListItem'
|
||||||
|
import ExpandableListItemNote from '../../../components/ExpandableListItemNote'
|
||||||
|
import ExpandableListItemInput from '../../../components/ExpandableListItemInput'
|
||||||
|
import StatusIcon from '../../../components/StatusIcon'
|
||||||
|
import { Context } from '../../../providers/Bee'
|
||||||
|
|
||||||
type Props = StatusHookCommon
|
export default function NodeConnectionCheck(): ReactElement | null {
|
||||||
|
|
||||||
export default function NodeConnectionCheck({ isOk }: Props): ReactElement | null {
|
|
||||||
const { setApiUrl, apiUrl } = useContext(SettingsContext)
|
const { setApiUrl, apiUrl } = useContext(SettingsContext)
|
||||||
|
const { status, isLoading } = useContext(Context)
|
||||||
|
const isOk = status.apiConnection
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<ExpandableList
|
||||||
<div style={{ display: 'flex', marginBottom: '25px' }}>
|
label={
|
||||||
<span style={{ marginRight: '15px' }}>
|
<>
|
||||||
Node API (<Typography variant="button">{apiUrl}</Typography>)
|
<StatusIcon isOk={isOk} isLoading={isLoading} /> Connection to Bee API
|
||||||
</span>
|
</>
|
||||||
<ConnectToHost setHost={setApiUrl} defaultHost={apiUrl} />
|
}
|
||||||
</div>
|
>
|
||||||
<div>
|
<ExpandableListItemNote>
|
||||||
{!isOk && (
|
{isOk
|
||||||
<Typography component="div" variant="body2" gutterBottom style={{ margin: '15px' }}>
|
? 'The connection to the Bee nodes API has been successful'
|
||||||
We cannot connect to your nodes API at <Typography variant="button">{apiUrl}</Typography>. Please check the
|
: 'Could not connect to your Bee nodes API. Please check the troubleshoot below on how you may resolve it.'}
|
||||||
following to troubleshoot your issue.
|
</ExpandableListItemNote>
|
||||||
<Accordion style={{ marginTop: '20px' }}>
|
<ExpandableListItemInput label="Bee API" value={apiUrl} onConfirm={setApiUrl} />
|
||||||
<AccordionSummary expandIcon={<ExpandMoreSharp />} aria-controls="panel1a-content" id="panel1a-header">
|
{!isOk && (
|
||||||
<Typography>Troubleshoot</Typography>
|
<ExpandableList level={1} label="Troubleshoot">
|
||||||
</AccordionSummary>
|
<ExpandableListItem
|
||||||
<AccordionDetails>
|
label={
|
||||||
<Typography component="div">
|
<ol>
|
||||||
<ol>
|
<li>Check the status of your node by running the below command to see if your node is running.</li>
|
||||||
<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 list`} />
|
||||||
<CodeBlockTabs showLineNumbers linux={`sudo systemctl status bee`} mac={`brew services list`} />
|
<li>
|
||||||
<li>
|
If your node is running, check your firewall settings to make sure that port 1633 (or your custom
|
||||||
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
|
||||||
specified port) is exposed to the internet. If your node is not running try executing the below
|
command to start your bee node
|
||||||
command to start your bee node
|
</li>
|
||||||
</li>
|
<CodeBlockTabs
|
||||||
<CodeBlockTabs
|
showLineNumbers
|
||||||
showLineNumbers
|
linux={`sudo systemctl start bee`}
|
||||||
linux={`sudo systemctl start bee`}
|
mac={`brew services start swarm-bee`}
|
||||||
mac={`brew services start swarm-bee`}
|
/>
|
||||||
/>
|
<li>Run the commands to validate your node is running and see the log output.</li>
|
||||||
<li>Run the commands to validate your node is running and see the log output.</li>
|
<CodeBlockTabs
|
||||||
<CodeBlockTabs
|
showLineNumbers
|
||||||
showLineNumbers
|
linux={`sudo systemctl status bee \njournalctl --lines=100 --follow --unit bee`}
|
||||||
linux={`sudo systemctl status bee \njournalctl --lines=100 --follow --unit bee`}
|
mac={`brew services list \ntail -f /usr/local/var/log/swarm-bee/bee.log`}
|
||||||
mac={`brew services list \ntail -f /usr/local/var/log/swarm-bee/bee.log`}
|
/>
|
||||||
/>
|
</ol>
|
||||||
</ol>
|
}
|
||||||
</Typography>
|
/>
|
||||||
</AccordionDetails>
|
</ExpandableList>
|
||||||
</Accordion>
|
)}
|
||||||
</Typography>
|
</ExpandableList>
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +1,29 @@
|
|||||||
import type { ReactElement } from 'react'
|
import { ReactElement, useContext } from 'react'
|
||||||
import { Typography } from '@material-ui/core/'
|
import ExpandableList from '../../../components/ExpandableList'
|
||||||
|
import ExpandableListItemNote from '../../../components/ExpandableListItemNote'
|
||||||
|
import TopologyStats from '../../../components/TopologyStats'
|
||||||
|
import StatusIcon from '../../../components/StatusIcon'
|
||||||
|
import { Context } from '../../../providers/Bee'
|
||||||
|
|
||||||
type Props = StatusTopologyHook
|
export default function PeerConnection(): ReactElement | null {
|
||||||
|
const { status, isLoading, topology } = useContext(Context)
|
||||||
export default function PeerConnection({ isOk, topology }: Props): ReactElement | null {
|
const isOk = status.topology
|
||||||
const peers = (
|
|
||||||
<div style={{ display: 'flex', marginTop: '15px' }}>
|
|
||||||
<div style={{ marginRight: '30px' }}>
|
|
||||||
<Typography component="div" variant="subtitle1" gutterBottom color="textSecondary">
|
|
||||||
<span>Connected Peers</span>
|
|
||||||
</Typography>
|
|
||||||
<Typography component="h2" variant="h5">
|
|
||||||
{topology?.connected ? topology.connected : '-'}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Typography component="div" variant="subtitle1" gutterBottom color="textSecondary">
|
|
||||||
<span>Discovered Nodes</span>
|
|
||||||
</Typography>
|
|
||||||
<Typography component="h2" variant="h5">
|
|
||||||
{topology?.population ? topology.population : '-'}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
if (isOk) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<span>You are connected to peers!</span>
|
|
||||||
{peers}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<ExpandableList
|
||||||
<span>Your node is not connected to any peers</span>
|
label={
|
||||||
{peers}
|
<>
|
||||||
</>
|
<StatusIcon isOk={isOk} isLoading={isLoading} /> Connection to Peers
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ExpandableListItemNote>
|
||||||
|
{isOk
|
||||||
|
? 'You are connected to other Bee nodes'
|
||||||
|
: 'Your node is not connected to any peers. Please wait a bit if you just started the node, otherwise review your configuration file.'}
|
||||||
|
</ExpandableListItemNote>
|
||||||
|
|
||||||
|
<TopologyStats topology={topology} />
|
||||||
|
</ExpandableList>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,60 +1,47 @@
|
|||||||
import type { ReactElement } from 'react'
|
import { ReactElement, useContext } from 'react'
|
||||||
import { Typography } from '@material-ui/core/'
|
|
||||||
import CodeBlockTabs from '../../../components/CodeBlockTabs'
|
import CodeBlockTabs from '../../../components/CodeBlockTabs'
|
||||||
|
import ExpandableList from '../../../components/ExpandableList'
|
||||||
|
import ExpandableListItem from '../../../components/ExpandableListItem'
|
||||||
|
import ExpandableListItemNote from '../../../components/ExpandableListItemNote'
|
||||||
|
import StatusIcon from '../../../components/StatusIcon'
|
||||||
|
import { Context } from '../../../providers/Bee'
|
||||||
|
|
||||||
type Props = StatusNodeVersionHook
|
export default function VersionCheck(): ReactElement | null {
|
||||||
|
const { status, isLoading, latestUserVersion, latestPublishedVersion, latestBeeVersionUrl } = useContext(Context)
|
||||||
|
const isOk = status.version
|
||||||
|
|
||||||
export default function VersionCheck({ isOk, userVersion, latestVersion, latestUrl }: Props): ReactElement | null {
|
|
||||||
const version = (
|
|
||||||
<div style={{ display: 'flex' }}>
|
|
||||||
<div style={{ marginRight: '30px' }}>
|
|
||||||
<p>
|
|
||||||
<span>User Version</span>
|
|
||||||
</p>
|
|
||||||
<Typography component="h5" variant="h5">
|
|
||||||
<span>{userVersion}</span>
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
<span>Latest Version</span>
|
|
||||||
</p>
|
|
||||||
<Typography component="h5" variant="h5">
|
|
||||||
<span>{latestVersion}</span>
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
// Running latest bee version
|
|
||||||
if (isOk) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<span>You are running the latest version of Bee</span>
|
|
||||||
{version}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Old version or not connected to bee debug API
|
|
||||||
return (
|
return (
|
||||||
<>
|
<ExpandableList
|
||||||
<span>
|
label={
|
||||||
Your Bee version is out of date. Please update to the{' '}
|
<>
|
||||||
<a href={latestUrl} rel="noreferrer" target="_blank">
|
<StatusIcon isOk={isOk} isLoading={isLoading} /> Bee Version
|
||||||
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">
|
<ExpandableListItemNote>
|
||||||
Docs
|
{isOk ? (
|
||||||
</a>
|
'You are running the latest version of Bee.'
|
||||||
</span>
|
) : (
|
||||||
<CodeBlockTabs
|
<>
|
||||||
showLineNumbers
|
Your Bee version is out of date. Please update to the{' '}
|
||||||
linux={`bee version\nwget https://github.com/ethersphere/bee/releases/download/${latestVersion}/bee_${latestVersion}_amd64.deb\nsudo dpkg -i bee_${latestVersion}_amd64.deb`}
|
<a href={latestBeeVersionUrl} rel="noreferrer" target="_blank">
|
||||||
mac={`bee version\nbrew tap ethersphere/tap\nbrew install swarm-bee\nbrew services start swarm-bee`}
|
latest
|
||||||
/>
|
</a>{' '}
|
||||||
{version}
|
before continuing. Rerun the installation script below to upgrade. For more information please see the{' '}
|
||||||
</>
|
<a href="https://docs.ethswarm.org/docs/installation/manual#upgrading-bee" rel="noreferrer" target="_blank">
|
||||||
|
Docs
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
<CodeBlockTabs
|
||||||
|
showLineNumbers
|
||||||
|
linux={`bee version\nwget https://github.com/ethersphere/bee/releases/download/${latestPublishedVersion}/bee_${latestPublishedVersion}_amd64.deb\nsudo dpkg -i bee_${latestPublishedVersion}_amd64.deb`}
|
||||||
|
mac={`bee version\nbrew tap ethersphere/tap\nbrew install swarm-bee\nbrew services start swarm-bee`}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</ExpandableListItemNote>
|
||||||
|
<ExpandableListItem label="Your Version" value={latestUserVersion || '-'} />
|
||||||
|
<ExpandableListItem label="Latest Version" value={latestPublishedVersion || '-'} />
|
||||||
|
</ExpandableList>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-140
@@ -1,7 +1,4 @@
|
|||||||
import { ReactElement, useState, useContext } from 'react'
|
import type { ReactElement } 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, ExpandLessSharp, ExpandMoreSharp, Autorenew } from '@material-ui/icons/'
|
|
||||||
|
|
||||||
import DebugConnectionCheck from './SetupSteps/DebugConnectionCheck'
|
import DebugConnectionCheck from './SetupSteps/DebugConnectionCheck'
|
||||||
import NodeConnectionCheck from './SetupSteps/NodeConnectionCheck'
|
import NodeConnectionCheck from './SetupSteps/NodeConnectionCheck'
|
||||||
@@ -9,144 +6,16 @@ import VersionCheck from './SetupSteps/VersionCheck'
|
|||||||
import EthereumConnectionCheck from './SetupSteps/EthereumConnectionCheck'
|
import EthereumConnectionCheck from './SetupSteps/EthereumConnectionCheck'
|
||||||
import ChequebookDeployFund from './SetupSteps/ChequebookDeployFund'
|
import ChequebookDeployFund from './SetupSteps/ChequebookDeployFund'
|
||||||
import PeerConnection from './SetupSteps/PeerConnection'
|
import PeerConnection from './SetupSteps/PeerConnection'
|
||||||
import { Context } from '../../providers/Bee'
|
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
|
||||||
createStyles({
|
|
||||||
root: {
|
|
||||||
padding: theme.spacing(2),
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
button: {
|
|
||||||
marginTop: theme.spacing(1),
|
|
||||||
marginRight: theme.spacing(1),
|
|
||||||
},
|
|
||||||
actionsContainer: {
|
|
||||||
margin: theme.spacing(2),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
interface Step {
|
|
||||||
label: string
|
|
||||||
isOk: boolean
|
|
||||||
component: ReactElement
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function NodeSetupWorkflow(): 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: status.debugApiConnection,
|
|
||||||
component: <DebugConnectionCheck isOk={status.debugApiConnection} />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Running latest Bee version',
|
|
||||||
isOk: status.version,
|
|
||||||
component: (
|
|
||||||
<VersionCheck
|
|
||||||
isOk={status.version}
|
|
||||||
isLatestBeeVersion={isLatestBeeVersion}
|
|
||||||
userVersion={latestUserVersion}
|
|
||||||
latestVersion={latestPublishedVersion}
|
|
||||||
latestUrl={latestBeeVersionUrl}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Connected to xDai Blockchain',
|
|
||||||
isOk: status.blockchainConnection,
|
|
||||||
component: <EthereumConnectionCheck isOk={status.blockchainConnection} nodeAddresses={nodeAddresses} />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Deployed and Funded Chequebook',
|
|
||||||
isOk: status.chequebook,
|
|
||||||
component: (
|
|
||||||
<ChequebookDeployFund chequebookAddress={chequebookAddress?.chequebookAddress} isOk={status.chequebook} />
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Connected to Node API',
|
|
||||||
isOk: status.apiConnection,
|
|
||||||
component: <NodeConnectionCheck isOk={status.apiConnection} />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Connected to Peers',
|
|
||||||
isOk: status.topology,
|
|
||||||
component: <PeerConnection isOk={status.topology} topology={topology} />,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const handleNext = () => {
|
|
||||||
setActiveStep(prevActiveStep => prevActiveStep + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleBack = () => {
|
|
||||||
setActiveStep(prevActiveStep => prevActiveStep - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper className={classes.root}>
|
<div>
|
||||||
<Typography variant="h5" gutterBottom>
|
<DebugConnectionCheck />
|
||||||
Node Setup
|
<VersionCheck />
|
||||||
</Typography>
|
<EthereumConnectionCheck />
|
||||||
<Stepper nonLinear activeStep={activeStep} orientation="vertical">
|
<ChequebookDeployFund />
|
||||||
{steps.map(({ label, isOk, component }, index) => (
|
<NodeConnectionCheck />
|
||||||
<Step key={label}>
|
<PeerConnection />
|
||||||
<StepLabel
|
</div>
|
||||||
onClick={() => setActiveStep(index === activeStep ? steps.length : index)}
|
|
||||||
StepIconComponent={() => {
|
|
||||||
if (isLoading) return <Autorenew style={{ height: '25px', cursor: 'pointer' }} />
|
|
||||||
|
|
||||||
if (isOk) return <CheckCircle style={{ color: '#32c48d', height: '25px', cursor: 'pointer' }} />
|
|
||||||
|
|
||||||
return <Error style={{ color: '#c9201f', height: '25px', cursor: 'pointer' }} />
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<StepButton
|
|
||||||
disabled={isLoading}
|
|
||||||
onClick={() => setActiveStep(index === activeStep ? steps.length : 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 component="div">{component}</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}>
|
|
||||||
{index < steps.length - 1 ? 'Next' : 'Finish'}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</StepContent>
|
|
||||||
</Step>
|
|
||||||
))}
|
|
||||||
</Stepper>
|
|
||||||
</Paper>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,9 @@ const componentsOverrides = (theme: Theme) => ({
|
|||||||
backgroundColor: theme.palette.primary.main,
|
backgroundColor: theme.palette.primary.main,
|
||||||
color: 'white',
|
color: 'white',
|
||||||
},
|
},
|
||||||
|
'&:disabled': {
|
||||||
|
backgroundColor: 'white',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MuiTab: {
|
MuiTab: {
|
||||||
|
|||||||
Reference in New Issue
Block a user