style: add eslint configuration and fixed linter issues (#35)
* style: add eslint configuration as per bee-js * chore: add `plugin:react/reocommended` in `.eslintrc` Co-authored-by: nugaon <50576770+nugaon@users.noreply.github.com> * chore: add `consistent` to `array-bracket-newline` as per review * style: after automatic fixes with `npm run lint` * style: fixed all linter errors * refactor: fixed all linter warnings * chore: added missing new line at end of `.prettierrc` file Co-authored-by: nugaon <50576770+nugaon@users.noreply.github.com>
This commit is contained in:
@@ -1,17 +1,17 @@
|
||||
import React from 'react'
|
||||
import { ReactElement } from 'react'
|
||||
|
||||
import { Theme, createStyles, makeStyles } from '@material-ui/core/styles';
|
||||
import { Card, CardContent, Typography, Grid } from '@material-ui/core/';
|
||||
import { Skeleton } from '@material-ui/lab';
|
||||
import WithdrawlModal from '../../components/WithdrawlModal';
|
||||
import DepositModal from '../../components/DepositModal';
|
||||
import CashoutModal from '../../components/CashoutModal';
|
||||
import { createStyles, makeStyles } from '@material-ui/core/styles'
|
||||
import { Card, CardContent, Typography, Grid } from '@material-ui/core/'
|
||||
import { Skeleton } from '@material-ui/lab'
|
||||
import WithdrawlModal from '../../components/WithdrawlModal'
|
||||
import DepositModal from '../../components/DepositModal'
|
||||
import CashoutModal from '../../components/CashoutModal'
|
||||
|
||||
import { ConvertBalanceToBZZ } from '../../utils/common';
|
||||
import { ConvertBalanceToBZZ } from '../../utils/common'
|
||||
|
||||
import type { ChequebookAddressResponse } from '@ethersphere/bee-js';
|
||||
import type { AllSettlements, ChequebookAddressResponse } from '@ethersphere/bee-js'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
const useStyles = makeStyles(() =>
|
||||
createStyles({
|
||||
root: {
|
||||
display: 'flex',
|
||||
@@ -20,93 +20,107 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
display: 'flex',
|
||||
},
|
||||
address: {
|
||||
color: 'grey',
|
||||
fontWeight: 400,
|
||||
},
|
||||
color: 'grey',
|
||||
fontWeight: 400,
|
||||
},
|
||||
content: {
|
||||
flexGrow: 1,
|
||||
flexGrow: 1,
|
||||
},
|
||||
status: {
|
||||
color: '#fff',
|
||||
backgroundColor: '#76a9fa',
|
||||
}
|
||||
color: '#fff',
|
||||
backgroundColor: '#76a9fa',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
)
|
||||
|
||||
interface ChequebookBalance {
|
||||
totalBalance: number,
|
||||
availableBalance: number
|
||||
totalBalance: number
|
||||
availableBalance: number
|
||||
}
|
||||
|
||||
interface IProps{
|
||||
chequebookAddress: ChequebookAddressResponse | null,
|
||||
isLoadingChequebookAddress: boolean,
|
||||
chequebookBalance: ChequebookBalance | null,
|
||||
isLoadingChequebookBalance: boolean,
|
||||
settlements: any,
|
||||
isLoadingSettlements: boolean,
|
||||
interface Props {
|
||||
chequebookAddress: ChequebookAddressResponse | null
|
||||
isLoadingChequebookAddress: boolean
|
||||
chequebookBalance: ChequebookBalance | null
|
||||
isLoadingChequebookBalance: boolean
|
||||
settlements: AllSettlements | null
|
||||
isLoadingSettlements: boolean
|
||||
}
|
||||
|
||||
function AccountCard(props: Props): ReactElement {
|
||||
const classes = useStyles()
|
||||
|
||||
function AccountCard(props: IProps) {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{justifyContent: 'space-between', display: 'flex'}}>
|
||||
<h2 style={{ marginTop: '0px' }}>Accounting</h2>
|
||||
<div style={{display:'flex'}}>
|
||||
<WithdrawlModal />
|
||||
<DepositModal />
|
||||
<CashoutModal />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Card className={classes.root}>
|
||||
{ !props.isLoadingChequebookBalance && !props.isLoadingSettlements && props.chequebookBalance ?
|
||||
<div className={classes.details}>
|
||||
<CardContent className={classes.content}>
|
||||
<Grid container spacing={5}>
|
||||
<Grid item>
|
||||
<Typography component="h2" variant="h6" color="primary" gutterBottom>
|
||||
Total Balance
|
||||
</Typography>
|
||||
<Typography component="p" variant="h5">
|
||||
{ConvertBalanceToBZZ(props.chequebookBalance.totalBalance)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography component="h2" variant="h6" color="primary" gutterBottom>
|
||||
Available Balance
|
||||
</Typography>
|
||||
<Typography component="p" variant="h5">
|
||||
{ConvertBalanceToBZZ(props.chequebookBalance.availableBalance)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography component="h2" variant="h6" color="primary" gutterBottom>
|
||||
Total Sent / Received
|
||||
</Typography>
|
||||
<Typography component="div" variant="h5" >
|
||||
<span style={{marginRight:'7px'}}>{ConvertBalanceToBZZ(props.settlements.totalsent)} / {ConvertBalanceToBZZ(props.settlements.totalreceived)}</span>
|
||||
<span style={{ color: props.settlements.totalsent > props.settlements.totalreceived ? '#c9201f' : '#32c48d' }}>({ConvertBalanceToBZZ(props.settlements.totalsent - props.settlements.totalreceived)})</span>
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</CardContent>
|
||||
</div>
|
||||
:
|
||||
<div className={classes.details}>
|
||||
<Skeleton width={180} height={110} animation="wave" style={{ marginLeft: '12px', marginRight: '12px'}} />
|
||||
<Skeleton width={180} height={110} animation="wave" style={{ marginLeft: '12px', marginRight: '12px'}} />
|
||||
<Skeleton width={180} height={110} animation="wave" style={{ marginLeft: '12px', marginRight: '12px'}} />
|
||||
<Skeleton width={180} height={110} animation="wave" />
|
||||
</div>
|
||||
}
|
||||
</Card>
|
||||
return (
|
||||
<div>
|
||||
<div style={{ justifyContent: 'space-between', display: 'flex' }}>
|
||||
<h2 style={{ marginTop: '0px' }}>Accounting</h2>
|
||||
<div style={{ display: 'flex' }}>
|
||||
<WithdrawlModal />
|
||||
<DepositModal />
|
||||
<CashoutModal />
|
||||
</div>
|
||||
)
|
||||
</div>
|
||||
|
||||
<Card className={classes.root}>
|
||||
{!props.isLoadingChequebookBalance && !props.isLoadingSettlements && props.chequebookBalance ? (
|
||||
<div className={classes.details}>
|
||||
<CardContent className={classes.content}>
|
||||
<Grid container spacing={5}>
|
||||
<Grid item>
|
||||
<Typography component="h2" variant="h6" color="primary" gutterBottom>
|
||||
Total Balance
|
||||
</Typography>
|
||||
<Typography component="p" variant="h5">
|
||||
{ConvertBalanceToBZZ(props.chequebookBalance.totalBalance)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography component="h2" variant="h6" color="primary" gutterBottom>
|
||||
Available Balance
|
||||
</Typography>
|
||||
<Typography component="p" variant="h5">
|
||||
{ConvertBalanceToBZZ(props.chequebookBalance.availableBalance)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography component="h2" variant="h6" color="primary" gutterBottom>
|
||||
Total Sent / Received
|
||||
</Typography>
|
||||
<Typography component="div" variant="h5">
|
||||
<span style={{ marginRight: '7px' }}>
|
||||
{ConvertBalanceToBZZ(props.settlements?.totalsent || 0)} /{' '}
|
||||
{ConvertBalanceToBZZ(props.settlements?.totalreceived || 0)}
|
||||
</span>
|
||||
<span
|
||||
style={{
|
||||
color:
|
||||
props.settlements && props.settlements?.totalsent > props.settlements?.totalreceived
|
||||
? '#c9201f'
|
||||
: '#32c48d',
|
||||
}}
|
||||
>
|
||||
(
|
||||
{ConvertBalanceToBZZ(
|
||||
(props.settlements && props.settlements?.totalsent - props.settlements?.totalreceived) || 0,
|
||||
)}
|
||||
)
|
||||
</span>
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</CardContent>
|
||||
</div>
|
||||
) : (
|
||||
<div className={classes.details}>
|
||||
<Skeleton width={180} height={110} animation="wave" style={{ marginLeft: '12px', marginRight: '12px' }} />
|
||||
<Skeleton width={180} height={110} animation="wave" style={{ marginLeft: '12px', marginRight: '12px' }} />
|
||||
<Skeleton width={180} height={110} animation="wave" style={{ marginLeft: '12px', marginRight: '12px' }} />
|
||||
<Skeleton width={180} height={110} animation="wave" />
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AccountCard;
|
||||
export default AccountCard
|
||||
|
||||
@@ -1,64 +1,80 @@
|
||||
import React from 'react';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { Table, TableBody, TableCell, TableContainer, TableRow, TableHead, Paper, Container, CircularProgress } from '@material-ui/core';
|
||||
import type { ReactElement } from 'react'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableRow,
|
||||
TableHead,
|
||||
Paper,
|
||||
Container,
|
||||
CircularProgress,
|
||||
} from '@material-ui/core'
|
||||
|
||||
import { ConvertBalanceToBZZ } from '../../utils/common';
|
||||
import { ConvertBalanceToBZZ } from '../../utils/common'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
table: {
|
||||
minWidth: 650,
|
||||
},
|
||||
});
|
||||
table: {
|
||||
minWidth: 650,
|
||||
},
|
||||
})
|
||||
|
||||
interface PeerBalance {
|
||||
balance: number,
|
||||
peer: string,
|
||||
balance: number
|
||||
peer: string
|
||||
}
|
||||
|
||||
interface PeerBalances {
|
||||
balances: Array<PeerBalance>
|
||||
balances: Array<PeerBalance>
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
peerBalances: PeerBalances | null,
|
||||
loading?: boolean,
|
||||
}
|
||||
|
||||
function BalancesTable(props: IProps) {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{props.loading ?
|
||||
<Container style={{textAlign:'center', padding:'50px'}}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
:
|
||||
<TableContainer component={Paper}>
|
||||
<Table className={classes.table} size="small" aria-label="simple table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Peer</TableCell>
|
||||
<TableCell style={{textAlign:'right'}}>Balance (BZZ)</TableCell>
|
||||
<TableCell align="right"></TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{props.peerBalances?.balances.map((peerBalance: PeerBalance, idx: number) => (
|
||||
<TableRow key={peerBalance.peer}>
|
||||
<TableCell>{peerBalance.peer}</TableCell>
|
||||
<TableCell style={{ color: ConvertBalanceToBZZ(peerBalance.balance) > 0 ? '#32c48d' : '#c9201f', textAlign:'right', fontFamily: 'monospace, monospace' }}>
|
||||
{ConvertBalanceToBZZ(peerBalance.balance).toFixed(7).toLocaleString() }
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>}
|
||||
</div>
|
||||
)
|
||||
interface Props {
|
||||
peerBalances: PeerBalances | null
|
||||
loading?: boolean
|
||||
}
|
||||
|
||||
export default BalancesTable;
|
||||
function BalancesTable(props: Props): ReactElement {
|
||||
const classes = useStyles()
|
||||
|
||||
return (
|
||||
<div>
|
||||
{props.loading ? (
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
) : (
|
||||
<TableContainer component={Paper}>
|
||||
<Table className={classes.table} size="small" aria-label="simple table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Peer</TableCell>
|
||||
<TableCell style={{ textAlign: 'right' }}>Balance (BZZ)</TableCell>
|
||||
<TableCell align="right"></TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{props.peerBalances?.balances.map((peerBalance: PeerBalance) => (
|
||||
<TableRow key={peerBalance.peer}>
|
||||
<TableCell>{peerBalance.peer}</TableCell>
|
||||
<TableCell
|
||||
style={{
|
||||
color: ConvertBalanceToBZZ(peerBalance.balance) > 0 ? '#32c48d' : '#c9201f',
|
||||
textAlign: 'right',
|
||||
fontFamily: 'monospace, monospace',
|
||||
}}
|
||||
>
|
||||
{ConvertBalanceToBZZ(peerBalance.balance).toFixed(7).toLocaleString()}
|
||||
</TableCell>
|
||||
<TableCell align="right"></TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default BalancesTable
|
||||
|
||||
@@ -1,113 +1,125 @@
|
||||
import React from 'react';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { Table, TableBody, TableCell, TableContainer, TableRow, TableHead, Paper, Container, CircularProgress } from '@material-ui/core';
|
||||
import React, { ReactElement } from 'react'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableRow,
|
||||
TableHead,
|
||||
Paper,
|
||||
Container,
|
||||
CircularProgress,
|
||||
} from '@material-ui/core'
|
||||
|
||||
import { ConvertBalanceToBZZ } from '../../utils/common';
|
||||
import EthereumAddress from '../../components/EthereumAddress';
|
||||
import ClipboardCopy from '../../components/ClipboardCopy';
|
||||
import PeerDetailDrawer from './PeerDetailDrawer';
|
||||
import { ConvertBalanceToBZZ } from '../../utils/common'
|
||||
import EthereumAddress from '../../components/EthereumAddress'
|
||||
import ClipboardCopy from '../../components/ClipboardCopy'
|
||||
import PeerDetailDrawer from './PeerDetailDrawer'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
table: {
|
||||
minWidth: 650,
|
||||
},
|
||||
});
|
||||
table: {
|
||||
minWidth: 650,
|
||||
},
|
||||
})
|
||||
|
||||
interface ChequeEvent {
|
||||
beneficiary: string,
|
||||
chequebook: string,
|
||||
payout: number,
|
||||
beneficiary: string
|
||||
chequebook: string
|
||||
payout: number
|
||||
}
|
||||
|
||||
interface PeerCheque {
|
||||
lastreceived?: ChequeEvent,
|
||||
lastsent?: ChequeEvent,
|
||||
peer: string,
|
||||
lastreceived?: ChequeEvent
|
||||
lastsent?: ChequeEvent
|
||||
peer: string
|
||||
}
|
||||
|
||||
interface PeerCheques {
|
||||
lastcheques: Array<PeerCheque>
|
||||
lastcheques: Array<PeerCheque>
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
peerCheques: PeerCheques | null,
|
||||
loading?: boolean,
|
||||
interface Props {
|
||||
peerCheques: PeerCheques | null
|
||||
loading?: boolean
|
||||
}
|
||||
|
||||
function ChequebookTable(props: IProps) {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
function ChequebookTable(props: Props): ReactElement {
|
||||
const classes = useStyles()
|
||||
|
||||
return (
|
||||
<div>
|
||||
{props.loading ? (
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
) : (
|
||||
<div>
|
||||
{props.loading ?
|
||||
<Container style={{textAlign:'center', padding:'50px'}}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
:
|
||||
<div>
|
||||
<TableContainer component={Paper}>
|
||||
<Table className={classes.table} size="small" aria-label="simple table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Peer</TableCell>
|
||||
<TableCell>Last Received</TableCell>
|
||||
<TableCell>Last Sent</TableCell>
|
||||
<TableCell align="right"></TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{props.peerCheques?.lastcheques.map((peerCheque: PeerCheque, idx: number) => (
|
||||
<TableRow key={peerCheque.peer}>
|
||||
<TableCell>
|
||||
<div style={{display:'flex'}}>
|
||||
<small>
|
||||
<PeerDetailDrawer
|
||||
peerId={peerCheque.peer}
|
||||
/>
|
||||
</small>
|
||||
<ClipboardCopy value={peerCheque.peer} />
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell style={{maxWidth:'320px'}}>
|
||||
<p style={{marginBottom: '0px', fontFamily: 'monospace, monospace', display:'flex'}}>
|
||||
<span style={{whiteSpace: 'nowrap', marginRight:'12px', paddingTop:'3px'}}>
|
||||
{peerCheque.lastreceived?.payout ?
|
||||
`${ConvertBalanceToBZZ(peerCheque.lastreceived?.payout).toFixed(7).toLocaleString()} from`
|
||||
: '-'}
|
||||
</span>
|
||||
{peerCheque.lastreceived ?
|
||||
<EthereumAddress
|
||||
hideBlockie
|
||||
truncate
|
||||
network='goerli'
|
||||
address={peerCheque.lastreceived.beneficiary}
|
||||
/> : null}
|
||||
</p>
|
||||
</TableCell>
|
||||
<TableCell style={{maxWidth:'320px'}}>
|
||||
<p style={{marginBottom: '0px', fontFamily: 'monospace, monospace', display:'flex'}}>
|
||||
<span style={{whiteSpace: 'nowrap', marginRight:'12px', paddingTop:'3px'}}>
|
||||
{peerCheque.lastsent?.payout ? `${ConvertBalanceToBZZ(peerCheque.lastsent?.payout).toFixed(7).toLocaleString()} to` : '-'}
|
||||
</span>
|
||||
{peerCheque.lastsent ?
|
||||
<EthereumAddress
|
||||
hideBlockie
|
||||
truncate
|
||||
network='goerli'
|
||||
address={peerCheque.lastsent.beneficiary}
|
||||
/> : null}
|
||||
</p>
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</div>}
|
||||
<TableContainer component={Paper}>
|
||||
<Table className={classes.table} size="small" aria-label="simple table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Peer</TableCell>
|
||||
<TableCell>Last Received</TableCell>
|
||||
<TableCell>Last Sent</TableCell>
|
||||
<TableCell align="right"></TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{props.peerCheques?.lastcheques.map((peerCheque: PeerCheque) => (
|
||||
<TableRow key={peerCheque.peer}>
|
||||
<TableCell>
|
||||
<div style={{ display: 'flex' }}>
|
||||
<small>
|
||||
<PeerDetailDrawer peerId={peerCheque.peer} />
|
||||
</small>
|
||||
<ClipboardCopy value={peerCheque.peer} />
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell style={{ maxWidth: '320px' }}>
|
||||
<p style={{ marginBottom: '0px', fontFamily: 'monospace, monospace', display: 'flex' }}>
|
||||
<span style={{ whiteSpace: 'nowrap', marginRight: '12px', paddingTop: '3px' }}>
|
||||
{peerCheque.lastreceived?.payout
|
||||
? `${ConvertBalanceToBZZ(peerCheque.lastreceived?.payout).toFixed(7).toLocaleString()} from`
|
||||
: '-'}
|
||||
</span>
|
||||
{peerCheque.lastreceived ? (
|
||||
<EthereumAddress
|
||||
hideBlockie
|
||||
truncate
|
||||
network="goerli"
|
||||
address={peerCheque.lastreceived.beneficiary}
|
||||
/>
|
||||
) : null}
|
||||
</p>
|
||||
</TableCell>
|
||||
<TableCell style={{ maxWidth: '320px' }}>
|
||||
<p style={{ marginBottom: '0px', fontFamily: 'monospace, monospace', display: 'flex' }}>
|
||||
<span style={{ whiteSpace: 'nowrap', marginRight: '12px', paddingTop: '3px' }}>
|
||||
{peerCheque.lastsent?.payout
|
||||
? `${ConvertBalanceToBZZ(peerCheque.lastsent?.payout).toFixed(7).toLocaleString()} to`
|
||||
: '-'}
|
||||
</span>
|
||||
{peerCheque.lastsent ? (
|
||||
<EthereumAddress
|
||||
hideBlockie
|
||||
truncate
|
||||
network="goerli"
|
||||
address={peerCheque.lastsent.beneficiary}
|
||||
/>
|
||||
) : null}
|
||||
</p>
|
||||
</TableCell>
|
||||
<TableCell align="right"></TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ChequebookTable;
|
||||
export default ChequebookTable
|
||||
|
||||
@@ -1,188 +1,170 @@
|
||||
import React, { useState } from 'react'
|
||||
import { Paper, Container, Drawer, Button, Typography, CircularProgress, Grid } from '@material-ui/core';
|
||||
import ClipboardCopy from '../../components/ClipboardCopy';
|
||||
import { beeDebugApi } from '../../services/bee';
|
||||
import EthereumAddress from '../../components/EthereumAddress';
|
||||
import { ConvertBalanceToBZZ } from '../../utils/common';
|
||||
import React, { ReactElement, useState } from 'react'
|
||||
import { Paper, Container, Drawer, Button, Typography, CircularProgress, Grid } from '@material-ui/core'
|
||||
import ClipboardCopy from '../../components/ClipboardCopy'
|
||||
import { beeDebugApi } from '../../services/bee'
|
||||
import EthereumAddress from '../../components/EthereumAddress'
|
||||
import { ConvertBalanceToBZZ } from '../../utils/common'
|
||||
import { LastCashoutActionResponse, LastChequesForPeerResponse } from '@ethersphere/bee-js'
|
||||
|
||||
function truncStringPortion(str: string, firstCharCount=10, endCharCount=10) {
|
||||
var convertedStr="";
|
||||
convertedStr+=str.substring(0, firstCharCount);
|
||||
convertedStr += ".".repeat(3);
|
||||
convertedStr+=str.substring(str.length-endCharCount, str.length);
|
||||
return convertedStr;
|
||||
function truncStringPortion(str: string, firstCharCount = 10, endCharCount = 10) {
|
||||
let convertedStr = ''
|
||||
convertedStr += str.substring(0, firstCharCount)
|
||||
convertedStr += '.'.repeat(3)
|
||||
convertedStr += str.substring(str.length - endCharCount, str.length)
|
||||
|
||||
return convertedStr
|
||||
}
|
||||
|
||||
export default function Index(props: any) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [peerCashout, setPeerCashout] = useState({ "peer": "",
|
||||
"chequebook": "",
|
||||
"cumulativePayout": 0,
|
||||
"beneficiary": "",
|
||||
"transactionHash": "",
|
||||
"result": {
|
||||
"recipient": "",
|
||||
"lastPayout": 0,
|
||||
"bounced": false
|
||||
}});
|
||||
interface Props {
|
||||
peerId: string
|
||||
}
|
||||
|
||||
const [peerCheque, setPeerCheque] = useState({
|
||||
lastreceived: { beneficiary: "", payout: 0, chequebook: "" },
|
||||
lastsent: { beneficiary: "", payout: 0, chequebook: "" },
|
||||
peer: ""
|
||||
})
|
||||
export default function Index(props: Props): ReactElement {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [peerCashout, setPeerCashout] = useState<LastCashoutActionResponse | null>(null)
|
||||
const [peerCheque, setPeerCheque] = useState<LastChequesForPeerResponse | null>(null)
|
||||
|
||||
const [isLoadingPeerCheque, setIsLoadingPeerCheque] = useState<boolean>(false)
|
||||
const [isLoadingPeerCashout, setIsLoadingPeerCashout] = useState<boolean>(false);
|
||||
const [isLoadingPeerCheque, setIsLoadingPeerCheque] = useState<boolean>(false)
|
||||
const [isLoadingPeerCashout, setIsLoadingPeerCashout] = useState<boolean>(false)
|
||||
|
||||
const handleClickOpen = (peerId: string) => {
|
||||
setIsLoadingPeerCashout(true)
|
||||
beeDebugApi.chequebook
|
||||
.getPeerLastCashout(peerId)
|
||||
.then(res => {
|
||||
setPeerCashout(res)
|
||||
})
|
||||
.catch(() => {
|
||||
// FIXME: handle the error
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoadingPeerCashout(false)
|
||||
})
|
||||
|
||||
const handleClickOpen = (peerId: string) => {
|
||||
setIsLoadingPeerCashout(true)
|
||||
beeDebugApi.chequebook.getPeerLastCashout(peerId)
|
||||
.then(res => {
|
||||
setPeerCashout(res)
|
||||
})
|
||||
.catch(error => {
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoadingPeerCashout(false)
|
||||
})
|
||||
setIsLoadingPeerCheque(true)
|
||||
beeDebugApi.chequebook
|
||||
.getPeerLastCheques(peerId)
|
||||
.then(res => {
|
||||
setPeerCheque(res)
|
||||
})
|
||||
.catch(() => {
|
||||
// FIXME: handle the error
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoadingPeerCheque(false)
|
||||
})
|
||||
|
||||
setIsLoadingPeerCheque(true)
|
||||
beeDebugApi.chequebook.getPeerLastCheques(peerId)
|
||||
.then(res => {
|
||||
setPeerCheque(res)
|
||||
})
|
||||
.catch(error => {
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoadingPeerCheque(false)
|
||||
})
|
||||
setOpen(true)
|
||||
}
|
||||
|
||||
setOpen(true);
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button color="primary" onClick={() => handleClickOpen(props.peerId)}>{truncStringPortion(props.peerId)}</Button>
|
||||
<Drawer anchor={'right'} open={open} onClose={handleClose}>
|
||||
<div style={{padding:'20px'}}>
|
||||
<Typography variant="h5" gutterBottom style={{display:'flex'}}>
|
||||
<span>Peer: { truncStringPortion(props.peerId) }</span>
|
||||
<ClipboardCopy value={props.peerId} />
|
||||
</Typography>
|
||||
<Paper>
|
||||
{ isLoadingPeerCashout || isLoadingPeerCheque ?
|
||||
<Container style={{textAlign:'center', padding:'50px'}}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
:
|
||||
<div style={{textAlign:'left', padding:'10px'}}>
|
||||
<h3>Last Cheque</h3>
|
||||
<Grid container spacing={1}>
|
||||
<Grid key={1} item xs={12} sm={12} xl={6}>
|
||||
<h5>Last Sent</h5>
|
||||
<p>
|
||||
Payout:
|
||||
<span style={{marginBottom: '0px', fontFamily: 'monospace, monospace'}}> {
|
||||
peerCheque.lastsent?.payout ? ConvertBalanceToBZZ(peerCheque.lastsent?.payout) : '-'
|
||||
}</span>
|
||||
</p>
|
||||
<p>Beneficiary:
|
||||
<EthereumAddress
|
||||
network={'goerli'}
|
||||
hideBlockie
|
||||
address={peerCheque.lastsent?.beneficiary}
|
||||
/>
|
||||
</p>
|
||||
<p>Chequebook:
|
||||
<EthereumAddress
|
||||
network={'goerli'}
|
||||
hideBlockie
|
||||
address={peerCheque.lastsent?.chequebook}
|
||||
/>
|
||||
</p>
|
||||
</Grid>
|
||||
<Grid key={1} item xs={12} sm={12} xl={6}>
|
||||
<h5>Last Received</h5>
|
||||
<p>
|
||||
Payout:
|
||||
<span style={{marginBottom: '0px', fontFamily: 'monospace, monospace'}}> {
|
||||
peerCheque.lastreceived?.payout ? ConvertBalanceToBZZ(peerCheque.lastreceived?.payout) : '-'}</span>
|
||||
</p>
|
||||
<p>Beneficiary:
|
||||
<EthereumAddress
|
||||
network={'goerli'}
|
||||
hideBlockie
|
||||
address={peerCheque.lastreceived?.beneficiary}
|
||||
/>
|
||||
</p>
|
||||
<p>Chequebook:
|
||||
<EthereumAddress
|
||||
network={'goerli'}
|
||||
hideBlockie
|
||||
address={peerCheque.lastreceived?.chequebook}
|
||||
/>
|
||||
</p>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<h3>Last Cashout</h3>
|
||||
{peerCashout.cumulativePayout > 0 ?
|
||||
<div>
|
||||
<p>
|
||||
Cumulative Payout:
|
||||
<span style={{marginBottom: '0px', fontFamily: 'monospace, monospace'}}>
|
||||
{peerCashout.cumulativePayout ? ConvertBalanceToBZZ(peerCashout.cumulativePayout) : '-'}
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
Last Payout:
|
||||
<span style={{marginBottom: '0px', fontFamily: 'monospace, monospace'}}> {
|
||||
peerCashout.result.lastPayout ? ConvertBalanceToBZZ(peerCashout.result.lastPayout) : '-'
|
||||
}</span>
|
||||
<span> {peerCashout.result.bounced ? 'Bounced' : ''}</span>
|
||||
</p>
|
||||
<p>Beneficiary:
|
||||
<EthereumAddress
|
||||
network={'goerli'}
|
||||
hideBlockie
|
||||
address={peerCashout.beneficiary}
|
||||
/>
|
||||
</p>
|
||||
<p>Chequebook:
|
||||
<EthereumAddress
|
||||
network={'goerli'}
|
||||
hideBlockie
|
||||
address={peerCashout.chequebook}
|
||||
/>
|
||||
</p>
|
||||
<p>Recipient:
|
||||
<EthereumAddress
|
||||
network={'goerli'}
|
||||
hideBlockie
|
||||
address={peerCashout.result.recipient}
|
||||
/>
|
||||
</p>
|
||||
<p>Transaction:
|
||||
<EthereumAddress
|
||||
transaction
|
||||
network={'goerli'}
|
||||
hideBlockie
|
||||
address={peerCashout.transactionHash}
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
: 'None'}
|
||||
</div>
|
||||
}
|
||||
</Paper>
|
||||
</div>
|
||||
</Drawer>
|
||||
return (
|
||||
<div>
|
||||
<Button color="primary" onClick={() => handleClickOpen(props.peerId)}>
|
||||
{truncStringPortion(props.peerId)}
|
||||
</Button>
|
||||
<Drawer anchor={'right'} open={open} onClose={handleClose}>
|
||||
<div style={{ padding: '20px' }}>
|
||||
<Typography variant="h5" gutterBottom style={{ display: 'flex' }}>
|
||||
<span>Peer: {truncStringPortion(props.peerId)}</span>
|
||||
<ClipboardCopy value={props.peerId} />
|
||||
</Typography>
|
||||
<Paper>
|
||||
{isLoadingPeerCashout || isLoadingPeerCheque ? (
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
) : (
|
||||
<div style={{ textAlign: 'left', padding: '10px' }}>
|
||||
<h3>Last Cheque</h3>
|
||||
<Grid container spacing={1}>
|
||||
<Grid key={1} item xs={12} sm={12} xl={6}>
|
||||
<h5>Last Sent</h5>
|
||||
<p>
|
||||
Payout:
|
||||
<span style={{ marginBottom: '0px', fontFamily: 'monospace, monospace' }}>
|
||||
{' '}
|
||||
{peerCheque?.lastsent?.payout ? ConvertBalanceToBZZ(peerCheque?.lastsent?.payout) : '-'}
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
Beneficiary:
|
||||
<EthereumAddress network={'goerli'} hideBlockie address={peerCheque?.lastsent?.beneficiary} />
|
||||
</p>
|
||||
<p>
|
||||
Chequebook:
|
||||
<EthereumAddress network={'goerli'} hideBlockie address={peerCheque?.lastsent?.chequebook} />
|
||||
</p>
|
||||
</Grid>
|
||||
<Grid key={1} item xs={12} sm={12} xl={6}>
|
||||
<h5>Last Received</h5>
|
||||
<p>
|
||||
Payout:
|
||||
<span style={{ marginBottom: '0px', fontFamily: 'monospace, monospace' }}>
|
||||
{' '}
|
||||
{peerCheque?.lastreceived?.payout ? ConvertBalanceToBZZ(peerCheque?.lastreceived?.payout) : '-'}
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
Beneficiary:
|
||||
<EthereumAddress network={'goerli'} hideBlockie address={peerCheque?.lastreceived?.beneficiary} />
|
||||
</p>
|
||||
<p>
|
||||
Chequebook:
|
||||
<EthereumAddress network={'goerli'} hideBlockie address={peerCheque?.lastreceived?.chequebook} />
|
||||
</p>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<h3>Last Cashout</h3>
|
||||
{peerCashout && peerCashout?.cumulativePayout > 0 ? (
|
||||
<div>
|
||||
<p>
|
||||
Cumulative Payout:
|
||||
<span style={{ marginBottom: '0px', fontFamily: 'monospace, monospace' }}>
|
||||
{peerCashout?.cumulativePayout ? ConvertBalanceToBZZ(peerCashout?.cumulativePayout) : '-'}
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
Last Payout:
|
||||
<span style={{ marginBottom: '0px', fontFamily: 'monospace, monospace' }}>
|
||||
{' '}
|
||||
{peerCashout?.result.lastPayout ? ConvertBalanceToBZZ(peerCashout?.result.lastPayout) : '-'}
|
||||
</span>
|
||||
<span> {peerCashout?.result.bounced ? 'Bounced' : ''}</span>
|
||||
</p>
|
||||
<p>
|
||||
Beneficiary:
|
||||
<EthereumAddress network={'goerli'} hideBlockie address={peerCashout?.beneficiary} />
|
||||
</p>
|
||||
<p>
|
||||
Chequebook:
|
||||
<EthereumAddress network={'goerli'} hideBlockie address={peerCashout?.chequebook} />
|
||||
</p>
|
||||
<p>
|
||||
Recipient:
|
||||
<EthereumAddress network={'goerli'} hideBlockie address={peerCashout?.result.recipient} />
|
||||
</p>
|
||||
<p>
|
||||
Transaction:
|
||||
<EthereumAddress
|
||||
transaction
|
||||
network={'goerli'}
|
||||
hideBlockie
|
||||
address={peerCashout?.transactionHash}
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
'None'
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Paper>
|
||||
</div>
|
||||
)
|
||||
</Drawer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,59 +1,69 @@
|
||||
import React from 'react';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { Table, TableBody, TableCell, TableContainer, TableRow, TableHead, Paper, Container, CircularProgress } from '@material-ui/core';
|
||||
import { ReactElement } from 'react'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableRow,
|
||||
TableHead,
|
||||
Paper,
|
||||
Container,
|
||||
CircularProgress,
|
||||
} from '@material-ui/core'
|
||||
|
||||
import { ConvertBalanceToBZZ } from '../../utils/common';
|
||||
import { ConvertBalanceToBZZ } from '../../utils/common'
|
||||
|
||||
import type { AllSettlements, Settlements } from '@ethersphere/bee-js'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
table: {
|
||||
minWidth: 650,
|
||||
},
|
||||
});
|
||||
table: {
|
||||
minWidth: 650,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
interface IProps {
|
||||
nodeSettlements: AllSettlements | null,
|
||||
loading?: boolean,
|
||||
}
|
||||
|
||||
function SettlementsTable(props: IProps) {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{props.loading ?
|
||||
<Container style={{textAlign:'center', padding:'50px'}}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
:
|
||||
<TableContainer component={Paper}>
|
||||
<Table className={classes.table} size="small" aria-label="simple table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Peer</TableCell>
|
||||
<TableCell>Received (BZZ)</TableCell>
|
||||
<TableCell>Sent (BZZ)</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{props.nodeSettlements?.settlements.map((item: Settlements, idx: number) => (
|
||||
<TableRow key={item.peer}>
|
||||
<TableCell>{item.peer}</TableCell>
|
||||
<TableCell style={{ fontFamily: 'monospace, monospace'}}>
|
||||
{item.received > 0 ? ConvertBalanceToBZZ(item.received).toFixed(7).toLocaleString() : item.received}
|
||||
</TableCell>
|
||||
<TableCell style={{ fontFamily: 'monospace, monospace'}}>
|
||||
{item.sent > 0 ? ConvertBalanceToBZZ(item.sent).toFixed(7).toLocaleString() : item.sent}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>}
|
||||
</div>
|
||||
)
|
||||
interface Props {
|
||||
nodeSettlements: AllSettlements | null
|
||||
loading?: boolean
|
||||
}
|
||||
|
||||
export default SettlementsTable;
|
||||
function SettlementsTable(props: Props): ReactElement {
|
||||
const classes = useStyles()
|
||||
|
||||
return (
|
||||
<div>
|
||||
{props.loading ? (
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
) : (
|
||||
<TableContainer component={Paper}>
|
||||
<Table className={classes.table} size="small" aria-label="simple table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Peer</TableCell>
|
||||
<TableCell>Received (BZZ)</TableCell>
|
||||
<TableCell>Sent (BZZ)</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{props.nodeSettlements?.settlements.map((item: Settlements) => (
|
||||
<TableRow key={item.peer}>
|
||||
<TableCell>{item.peer}</TableCell>
|
||||
<TableCell style={{ fontFamily: 'monospace, monospace' }}>
|
||||
{item.received > 0 ? ConvertBalanceToBZZ(item.received).toFixed(7).toLocaleString() : item.received}
|
||||
</TableCell>
|
||||
<TableCell style={{ fontFamily: 'monospace, monospace' }}>
|
||||
{item.sent > 0 ? ConvertBalanceToBZZ(item.sent).toFixed(7).toLocaleString() : item.sent}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SettlementsTable
|
||||
|
||||
+141
-139
@@ -1,166 +1,168 @@
|
||||
import React from 'react';
|
||||
import { withStyles, Theme, createStyles } from '@material-ui/core/styles';
|
||||
import { Tabs, Tab, Box, Typography, Container, CircularProgress } from '@material-ui/core';
|
||||
import { ReactElement, useState, ChangeEvent, ReactChild } from 'react'
|
||||
import { withStyles, Theme, createStyles } from '@material-ui/core/styles'
|
||||
import { Tabs, Tab, Box, Typography, Container, CircularProgress } from '@material-ui/core'
|
||||
|
||||
import AccountCard from '../accounting/AccountCard';
|
||||
import BalancesTable from './BalancesTable';
|
||||
import ChequebookTable from './ChequebookTable';
|
||||
import SettlementsTable from './SettlementsTable';
|
||||
import EthereumAddressCard from '../../components/EthereumAddressCard';
|
||||
import TroubleshootConnectionCard from '../../components/TroubleshootConnectionCard';
|
||||
import AccountCard from '../accounting/AccountCard'
|
||||
import BalancesTable from './BalancesTable'
|
||||
import ChequebookTable from './ChequebookTable'
|
||||
import SettlementsTable from './SettlementsTable'
|
||||
import EthereumAddressCard from '../../components/EthereumAddressCard'
|
||||
import TroubleshootConnectionCard from '../../components/TroubleshootConnectionCard'
|
||||
|
||||
import { useApiNodeAddresses, useApiChequebookAddress, useApiChequebookBalance, useApiPeerBalances, useApiPeerCheques, useApiSettlements } from '../../hooks/apiHooks';
|
||||
import {
|
||||
useApiNodeAddresses,
|
||||
useApiChequebookAddress,
|
||||
useApiChequebookBalance,
|
||||
useApiPeerBalances,
|
||||
useApiPeerCheques,
|
||||
useApiSettlements,
|
||||
useApiHealth,
|
||||
useDebugApiHealth,
|
||||
} from '../../hooks/apiHooks'
|
||||
|
||||
interface TabPanelProps {
|
||||
children?: React.ReactNode;
|
||||
index: any;
|
||||
value: any;
|
||||
children?: ReactChild
|
||||
index: number
|
||||
value: number
|
||||
}
|
||||
|
||||
|
||||
function a11yProps(index: any) {
|
||||
return {
|
||||
id: `simple-tab-${index}`,
|
||||
'aria-controls': `simple-tabpanel-${index}`,
|
||||
};
|
||||
function a11yProps(index: number) {
|
||||
return {
|
||||
id: `simple-tab-${index}`,
|
||||
'aria-controls': `simple-tabpanel-${index}`,
|
||||
}
|
||||
}
|
||||
|
||||
export default function Accounting(props: any) {
|
||||
const [value, setValue] = React.useState(0);
|
||||
export default function Accounting(): ReactElement {
|
||||
const [value, setValue] = useState(0)
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
|
||||
setValue(newValue);
|
||||
};
|
||||
const handleChange = (event: ChangeEvent<unknown>, newValue: number) => {
|
||||
setValue(newValue)
|
||||
}
|
||||
|
||||
const { chequebookAddress, isLoadingChequebookAddress } = useApiChequebookAddress()
|
||||
const { chequebookBalance, isLoadingChequebookBalance } = useApiChequebookBalance()
|
||||
const { peerBalances, isLoadingPeerBalances } = useApiPeerBalances()
|
||||
const { nodeAddresses, isLoadingNodeAddresses } = useApiNodeAddresses()
|
||||
const { chequebookAddress, isLoadingChequebookAddress } = useApiChequebookAddress()
|
||||
const { chequebookBalance, isLoadingChequebookBalance } = useApiChequebookBalance()
|
||||
const { peerBalances, isLoadingPeerBalances } = useApiPeerBalances()
|
||||
const { nodeAddresses, isLoadingNodeAddresses } = useApiNodeAddresses()
|
||||
const { health, isLoadingHealth } = useApiHealth()
|
||||
const { nodeHealth, isLoadingNodeHealth } = useDebugApiHealth()
|
||||
|
||||
const { peerCheques, isLoadingPeerCheques } = useApiPeerCheques()
|
||||
const { settlements, isLoadingSettlements } = useApiSettlements()
|
||||
const { peerCheques, isLoadingPeerCheques } = useApiPeerCheques()
|
||||
const { settlements, isLoadingSettlements } = useApiSettlements()
|
||||
|
||||
function TabPanel(props: TabPanelProps) {
|
||||
const { children, value, index, ...other } = props
|
||||
|
||||
function TabPanel(props: TabPanelProps) {
|
||||
const { children, value, index, ...other } = props;
|
||||
|
||||
return (
|
||||
<div
|
||||
role="tabpanel"
|
||||
hidden={value !== index}
|
||||
id={`simple-tabpanel-${index}`}
|
||||
aria-labelledby={`simple-tab-${index}`}
|
||||
{...other}
|
||||
>
|
||||
{value === index && (
|
||||
<Box style={{ marginTop: '20px' }}>
|
||||
<Typography component="div">{children}</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const AntTabs = withStyles({
|
||||
root: {
|
||||
borderBottom: '1px solid #e8e8e8',
|
||||
},
|
||||
indicator: {
|
||||
backgroundColor: '#3f51b5',
|
||||
},
|
||||
})(Tabs);
|
||||
|
||||
interface StyledTabProps {
|
||||
label: string;
|
||||
}
|
||||
|
||||
const AntTab = withStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
root: {
|
||||
textTransform: 'none',
|
||||
minWidth: 72,
|
||||
backgroundColor: 'transparent',
|
||||
fontWeight: theme.typography.fontWeightRegular,
|
||||
marginRight: theme.spacing(4),
|
||||
fontFamily: [
|
||||
'-apple-system',
|
||||
'BlinkMacSystemFont',
|
||||
'"Segoe UI"',
|
||||
'Roboto',
|
||||
'"Helvetica Neue"',
|
||||
'Arial',
|
||||
'sans-serif',
|
||||
'"Apple Color Emoji"',
|
||||
'"Segoe UI Emoji"',
|
||||
'"Segoe UI Symbol"',
|
||||
].join(','),
|
||||
'&:hover': {
|
||||
color: '#3f51b5',
|
||||
opacity: 1,
|
||||
},
|
||||
'&$selected': {
|
||||
color: '#3f51b5',
|
||||
fontWeight: theme.typography.fontWeightMedium,
|
||||
},
|
||||
'&:focus': {
|
||||
color: '#3f51b5',
|
||||
},
|
||||
},
|
||||
selected: {},
|
||||
}),
|
||||
)((props: StyledTabProps) => <Tab disableRipple {...props} />);
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
{props.nodeHealth?.status === 'ok' && props.health ?
|
||||
<div
|
||||
role="tabpanel"
|
||||
hidden={value !== index}
|
||||
id={`simple-tabpanel-${index}`}
|
||||
aria-labelledby={`simple-tab-${index}`}
|
||||
{...other}
|
||||
>
|
||||
{value === index && (
|
||||
<Box style={{ marginTop: '20px' }}>
|
||||
<Typography component="div">{children}</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const AntTabs = withStyles({
|
||||
root: {
|
||||
borderBottom: '1px solid #e8e8e8',
|
||||
},
|
||||
indicator: {
|
||||
backgroundColor: '#3f51b5',
|
||||
},
|
||||
})(Tabs)
|
||||
|
||||
interface StyledTabProps {
|
||||
label: string
|
||||
}
|
||||
|
||||
const AntTab = withStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
root: {
|
||||
textTransform: 'none',
|
||||
minWidth: 72,
|
||||
backgroundColor: 'transparent',
|
||||
fontWeight: theme.typography.fontWeightRegular,
|
||||
marginRight: theme.spacing(4),
|
||||
fontFamily: [
|
||||
'-apple-system',
|
||||
'BlinkMacSystemFont',
|
||||
'"Segoe UI"',
|
||||
'Roboto',
|
||||
'"Helvetica Neue"',
|
||||
'Arial',
|
||||
'sans-serif',
|
||||
'"Apple Color Emoji"',
|
||||
'"Segoe UI Emoji"',
|
||||
'"Segoe UI Symbol"',
|
||||
].join(','),
|
||||
'&:hover': {
|
||||
color: '#3f51b5',
|
||||
opacity: 1,
|
||||
},
|
||||
'&$selected': {
|
||||
color: '#3f51b5',
|
||||
fontWeight: theme.typography.fontWeightMedium,
|
||||
},
|
||||
'&:focus': {
|
||||
color: '#3f51b5',
|
||||
},
|
||||
},
|
||||
selected: {},
|
||||
}),
|
||||
)((props: StyledTabProps) => <Tab disableRipple {...props} />)
|
||||
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
// FIXME: this should be broken up
|
||||
/* eslint-disable no-nested-ternary */
|
||||
nodeHealth?.status === 'ok' && health ? (
|
||||
<div>
|
||||
<AccountCard
|
||||
chequebookAddress={chequebookAddress}
|
||||
isLoadingChequebookAddress={isLoadingChequebookAddress}
|
||||
chequebookBalance={chequebookBalance}
|
||||
isLoadingChequebookBalance={isLoadingChequebookBalance}
|
||||
settlements={settlements}
|
||||
isLoadingSettlements={isLoadingSettlements}
|
||||
chequebookAddress={chequebookAddress}
|
||||
isLoadingChequebookAddress={isLoadingChequebookAddress}
|
||||
chequebookBalance={chequebookBalance}
|
||||
isLoadingChequebookBalance={isLoadingChequebookBalance}
|
||||
settlements={settlements}
|
||||
isLoadingSettlements={isLoadingSettlements}
|
||||
/>
|
||||
<EthereumAddressCard
|
||||
nodeAddresses={nodeAddresses}
|
||||
isLoadingNodeAddresses={isLoadingNodeAddresses}
|
||||
chequebookAddress={chequebookAddress}
|
||||
isLoadingChequebookAddress={isLoadingChequebookAddress}
|
||||
<EthereumAddressCard
|
||||
nodeAddresses={nodeAddresses}
|
||||
isLoadingNodeAddresses={isLoadingNodeAddresses}
|
||||
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)} />
|
||||
<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}
|
||||
/>
|
||||
<BalancesTable peerBalances={peerBalances} loading={isLoadingPeerBalances} />
|
||||
</TabPanel>
|
||||
<TabPanel value={value} index={1}>
|
||||
<ChequebookTable
|
||||
peerCheques={peerCheques}
|
||||
loading={isLoadingPeerCheques}
|
||||
/>
|
||||
<ChequebookTable peerCheques={peerCheques} loading={isLoadingPeerCheques} />
|
||||
</TabPanel>
|
||||
<TabPanel value={value} index={2}>
|
||||
<SettlementsTable
|
||||
nodeSettlements={settlements}
|
||||
loading={isLoadingSettlements}
|
||||
/>
|
||||
<SettlementsTable nodeSettlements={settlements} loading={isLoadingSettlements} />
|
||||
</TabPanel>
|
||||
</div>
|
||||
:
|
||||
props.isLoadingHealth || props.isLoadingNodeHealth ?
|
||||
<Container style={{textAlign:'center', padding:'50px'}}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
:
|
||||
<TroubleshootConnectionCard />
|
||||
}
|
||||
</div>
|
||||
)
|
||||
</div>
|
||||
) : isLoadingHealth || isLoadingNodeHealth ? (
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
) : (
|
||||
<TroubleshootConnectionCard />
|
||||
) /* eslint-enable no-nested-ternary */
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
+128
-117
@@ -1,14 +1,15 @@
|
||||
import React, { useState } from 'react';
|
||||
import { beeApi } from '../../services/bee';
|
||||
import { ReactElement, useState } from 'react'
|
||||
import { beeApi } from '../../services/bee'
|
||||
|
||||
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles';
|
||||
import { Paper, InputBase, IconButton, Button, Container, CircularProgress } from '@material-ui/core';
|
||||
import { Search } from '@material-ui/icons';
|
||||
import {DropzoneArea} from 'material-ui-dropzone'
|
||||
import ClipboardCopy from '../../components/ClipboardCopy';
|
||||
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'
|
||||
import { Paper, InputBase, IconButton, Button, Container, CircularProgress } from '@material-ui/core'
|
||||
import { Search } from '@material-ui/icons'
|
||||
import { DropzoneArea } from 'material-ui-dropzone'
|
||||
import ClipboardCopy from '../../components/ClipboardCopy'
|
||||
|
||||
import TroubleshootConnectionCard from '../../components/TroubleshootConnectionCard';
|
||||
import { Data, FileData } from '@ethersphere/bee-js';
|
||||
import TroubleshootConnectionCard from '../../components/TroubleshootConnectionCard'
|
||||
import { Data, FileData } from '@ethersphere/bee-js'
|
||||
import { useApiHealth, useDebugApiHealth } from '../../hooks/apiHooks'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -30,128 +31,138 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
margin: 4,
|
||||
},
|
||||
}),
|
||||
);
|
||||
)
|
||||
|
||||
export default function Files(props: any) {
|
||||
const classes = useStyles();
|
||||
export default function Files(): ReactElement {
|
||||
const classes = useStyles()
|
||||
|
||||
const [inputMode, setInputMode] = useState<'browse' | 'upload'>('browse');
|
||||
const [searchInput, setSearchInput] = useState('');
|
||||
const [searchResult, setSearchResult] = useState<FileData<Data> | null>(null);
|
||||
const [loadingSearch, setLoadingSearch] = useState(false);
|
||||
const [inputMode, setInputMode] = useState<'browse' | 'upload'>('browse')
|
||||
const [searchInput, setSearchInput] = useState('')
|
||||
const [searchResult, setSearchResult] = useState<FileData<Data> | null>(null)
|
||||
const [loadingSearch, setLoadingSearch] = useState(false)
|
||||
const { health, isLoadingHealth } = useApiHealth()
|
||||
const { nodeHealth, isLoadingNodeHealth } = useDebugApiHealth()
|
||||
|
||||
const [files, setFiles] = useState<File[]>([]);
|
||||
const [uploadReference, setUploadReference] = useState('');
|
||||
const [uploadingFile, setUploadingFile] = useState(false);
|
||||
const [files, setFiles] = useState<File[]>([])
|
||||
const [uploadReference, setUploadReference] = useState('')
|
||||
const [uploadingFile, setUploadingFile] = useState(false)
|
||||
|
||||
const getFile = () => {
|
||||
setLoadingSearch(true)
|
||||
beeApi.files.downloadFile(searchInput)
|
||||
.then(res => {
|
||||
setSearchResult(res)
|
||||
|
||||
const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
|
||||
const link = document.createElement('a');
|
||||
link.href = downloadUrl;
|
||||
link.setAttribute('download', 'file.zip'); //any other extension
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
link.remove();
|
||||
})
|
||||
.catch(error => {
|
||||
})
|
||||
.finally(() => {
|
||||
setLoadingSearch(false)
|
||||
})
|
||||
const getFile = () => {
|
||||
setLoadingSearch(true)
|
||||
beeApi.files
|
||||
.downloadFile(searchInput)
|
||||
.then(res => {
|
||||
setSearchResult(res)
|
||||
|
||||
const downloadUrl = window.URL.createObjectURL(new Blob([res.data]))
|
||||
const link = document.createElement('a')
|
||||
link.href = downloadUrl
|
||||
link.setAttribute('download', 'file.zip') //any other extension
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
link.remove()
|
||||
})
|
||||
.catch(() => {
|
||||
// FIXME: handle the error
|
||||
})
|
||||
.finally(() => {
|
||||
setLoadingSearch(false)
|
||||
})
|
||||
}
|
||||
|
||||
const uploadFile = () => {
|
||||
setUploadingFile(true)
|
||||
beeApi.files
|
||||
.uploadFile(files[0])
|
||||
.then(hash => {
|
||||
setUploadReference(hash)
|
||||
setFiles([])
|
||||
})
|
||||
.catch(() => {
|
||||
// FIXME: handle the error
|
||||
})
|
||||
.finally(() => {
|
||||
setUploadingFile(false)
|
||||
})
|
||||
}
|
||||
|
||||
const handleChange = (files?: File[]) => {
|
||||
if (files) {
|
||||
setFiles(files)
|
||||
}
|
||||
}
|
||||
|
||||
const uploadFile = () => {
|
||||
setUploadingFile(true)
|
||||
beeApi.files.uploadFile(files[0])
|
||||
.then(hash => {
|
||||
setUploadReference(hash)
|
||||
setFiles([])
|
||||
})
|
||||
.catch(error => {
|
||||
})
|
||||
.finally(() => {
|
||||
setUploadingFile(false)
|
||||
})
|
||||
}
|
||||
|
||||
const handleChange = (files: any) => {
|
||||
if (files) {
|
||||
setFiles(files)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{props.nodeHealth?.status === 'ok' && props.health ?
|
||||
<Container maxWidth="sm">
|
||||
<div style={{marginBottom: '7px'}}>
|
||||
<Button color="primary" style={{marginRight: '7px'}} onClick={() => setInputMode('browse')}>Browse</Button>
|
||||
<Button color="primary" onClick={() => setInputMode('upload')}>Upload</Button>
|
||||
</div>
|
||||
{inputMode === 'browse' ?
|
||||
<Paper component="form" className={classes.root}>
|
||||
<InputBase
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
// FIXME: this should be broken up
|
||||
/* eslint-disable no-nested-ternary */
|
||||
nodeHealth?.status === 'ok' && health ? (
|
||||
<Container maxWidth="sm">
|
||||
<div style={{ marginBottom: '7px' }}>
|
||||
<Button color="primary" style={{ marginRight: '7px' }} onClick={() => setInputMode('browse')}>
|
||||
Browse
|
||||
</Button>
|
||||
<Button color="primary" onClick={() => setInputMode('upload')}>
|
||||
Upload
|
||||
</Button>
|
||||
</div>
|
||||
{inputMode === 'browse' ? (
|
||||
<Paper component="form" className={classes.root}>
|
||||
<InputBase
|
||||
className={classes.input}
|
||||
placeholder="Enter hash e.g. 0773a91efd6547c754fc1d95fb1c62c7d1b47f959c2caa685dfec8736da95c1c"
|
||||
inputProps={{ 'aria-label': 'search swarm nodes' }}
|
||||
onChange={(e) => setSearchInput(e.target.value)}
|
||||
/>
|
||||
<IconButton onClick={() => getFile()} className={classes.iconButton} aria-label="search">
|
||||
<Search />
|
||||
</IconButton>
|
||||
onChange={e => setSearchInput(e.target.value)}
|
||||
/>
|
||||
<IconButton onClick={() => getFile()} className={classes.iconButton} aria-label="search">
|
||||
<Search />
|
||||
</IconButton>
|
||||
</Paper>
|
||||
:
|
||||
) : (
|
||||
<div>
|
||||
{uploadingFile ?
|
||||
<Container style={{textAlign:'center', padding:'50px'}}>
|
||||
{uploadingFile ? (
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
:
|
||||
<div>
|
||||
{uploadReference ?
|
||||
<Paper component="form" className={classes.root} style={{marginBottom:'15px', display: 'flex'}}>
|
||||
<span>{uploadReference}</span>
|
||||
<ClipboardCopy
|
||||
value={uploadReference}
|
||||
/>
|
||||
</Paper>
|
||||
:
|
||||
null
|
||||
}
|
||||
<DropzoneArea
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<div style={{marginTop:'15px'}}>
|
||||
<Button onClick={() => uploadFile()} className={classes.iconButton}>
|
||||
</Container>
|
||||
) : (
|
||||
<div>
|
||||
{uploadReference ? (
|
||||
<Paper
|
||||
component="form"
|
||||
className={classes.root}
|
||||
style={{ marginBottom: '15px', display: 'flex' }}
|
||||
>
|
||||
<span>{uploadReference}</span>
|
||||
<ClipboardCopy value={uploadReference} />
|
||||
</Paper>
|
||||
) : null}
|
||||
<DropzoneArea onChange={handleChange} />
|
||||
<div style={{ marginTop: '15px' }}>
|
||||
<Button onClick={() => uploadFile()} className={classes.iconButton}>
|
||||
Upload
|
||||
</Button>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>}
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
{loadingSearch ?
|
||||
<Container style={{textAlign:'center', padding:'50px'}}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
:
|
||||
<div style={{padding:'20px'}} >
|
||||
{searchResult}
|
||||
</div>
|
||||
}
|
||||
</Container>
|
||||
:
|
||||
props.isLoadingHealth || props.isLoadingNodeHealth ?
|
||||
<Container style={{textAlign:'center', padding:'50px'}}>
|
||||
)}
|
||||
{loadingSearch ? (
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
:
|
||||
<TroubleshootConnectionCard
|
||||
/>}
|
||||
</div>
|
||||
)
|
||||
</Container>
|
||||
) : (
|
||||
<div style={{ padding: '20px' }}>{searchResult}</div>
|
||||
)}
|
||||
</Container>
|
||||
) : isLoadingHealth || isLoadingNodeHealth ? (
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
) : (
|
||||
<TroubleshootConnectionCard />
|
||||
) /* eslint-enable no-nested-ternary */
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,92 +1,113 @@
|
||||
import React, { useState } from 'react';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { Table, TableBody, TableCell, TableContainer, TableRow, TableHead, Button, Paper, Tooltip, Container, CircularProgress } from '@material-ui/core';
|
||||
import { Autorenew } from '@material-ui/icons';
|
||||
import React, { ReactElement, useState } from 'react'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableRow,
|
||||
TableHead,
|
||||
Button,
|
||||
Paper,
|
||||
Tooltip,
|
||||
Container,
|
||||
CircularProgress,
|
||||
} from '@material-ui/core'
|
||||
import { Autorenew } from '@material-ui/icons'
|
||||
|
||||
import { beeDebugApi } from '../../services/bee';
|
||||
import type { Peer } from '@ethersphere/bee-js';
|
||||
import { beeDebugApi } from '../../services/bee'
|
||||
import type { Peer } from '@ethersphere/bee-js'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
table: {
|
||||
minWidth: 650,
|
||||
},
|
||||
});
|
||||
table: {
|
||||
minWidth: 650,
|
||||
},
|
||||
})
|
||||
|
||||
interface Props {
|
||||
peers: Peer[] | null
|
||||
isLoading: boolean
|
||||
error: Error | null
|
||||
peers: Peer[] | null
|
||||
isLoading: boolean
|
||||
error: Error | null
|
||||
}
|
||||
|
||||
|
||||
function PeerTable(props: Props) {
|
||||
const classes = useStyles();
|
||||
function PeerTable(props: Props): ReactElement {
|
||||
const classes = useStyles()
|
||||
|
||||
const [peerLatency, setPeerLatency] = useState([{ peerId: '', rtt: '', loading: false }]);
|
||||
const [peerLatency, setPeerLatency] = useState([{ peerId: '', rtt: '', loading: false }])
|
||||
|
||||
const PingPeer = async (peerId: string) => {
|
||||
|
||||
setPeerLatency([...peerLatency, { peerId: peerId, rtt: '', loading: true }])
|
||||
beeDebugApi.connectivity.ping(peerId)
|
||||
.then(res => {
|
||||
setPeerLatency([...peerLatency, { peerId: peerId, rtt: res.rtt, loading: false }])
|
||||
})
|
||||
.catch(error => {
|
||||
setPeerLatency([...peerLatency, { peerId: peerId, rtt: 'error', loading: false }])
|
||||
})
|
||||
}
|
||||
|
||||
if (props.isLoading) {
|
||||
return (
|
||||
<Container style={{textAlign:'center', padding:'50px'}}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
if (props.error || props.peers === null) {
|
||||
return (
|
||||
<Container style={{textAlign:'center', padding:'50px'}}>
|
||||
<p>Failed to load peers</p>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
const PingPeer = (peerId: string) => {
|
||||
setPeerLatency([...peerLatency, { peerId: peerId, rtt: '', loading: true }])
|
||||
beeDebugApi.connectivity
|
||||
.ping(peerId)
|
||||
.then(res => {
|
||||
setPeerLatency([...peerLatency, { peerId: peerId, rtt: res.rtt, loading: false }])
|
||||
})
|
||||
.catch(() => {
|
||||
setPeerLatency([...peerLatency, { peerId: peerId, rtt: 'error', loading: false }])
|
||||
})
|
||||
}
|
||||
|
||||
if (props.isLoading) {
|
||||
return (
|
||||
<div>
|
||||
<TableContainer component={Paper}>
|
||||
<Table className={classes.table} aria-label="simple table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Index</TableCell>
|
||||
<TableCell>Peer Id</TableCell>
|
||||
<TableCell align="right">Actions</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{props.peers.map((peer: any, idx: number) => (
|
||||
<TableRow key={peer.address}>
|
||||
<TableCell component="th" scope="row">
|
||||
{idx + 1}
|
||||
</TableCell>
|
||||
<TableCell>{peer.address}</TableCell>
|
||||
<TableCell align="right">
|
||||
<Tooltip title="Ping node">
|
||||
<Button color="primary" onClick={() => PingPeer(peer.address)} >
|
||||
{peerLatency.find(item => item.peerId === peer.address) ?
|
||||
peerLatency.filter(item => item.peerId === peer.address)[0].loading ? <CircularProgress size={20} /> :
|
||||
peerLatency.filter(item => item.peerId === peer.address)[0].rtt :
|
||||
<Autorenew />}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</div>
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
if (props.error || props.peers === null) {
|
||||
return (
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<p>Failed to load peers</p>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<TableContainer component={Paper}>
|
||||
<Table className={classes.table} aria-label="simple table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Index</TableCell>
|
||||
<TableCell>Peer Id</TableCell>
|
||||
<TableCell align="right">Actions</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{props.peers.map((peer: Peer, idx: number) => (
|
||||
<TableRow key={peer.address}>
|
||||
<TableCell component="th" scope="row">
|
||||
{idx + 1}
|
||||
</TableCell>
|
||||
<TableCell>{peer.address}</TableCell>
|
||||
<TableCell align="right">
|
||||
<Tooltip title="Ping node">
|
||||
<Button color="primary" onClick={() => PingPeer(peer.address)}>
|
||||
{
|
||||
// FIXME: this should be broken up
|
||||
/* eslint-disable no-nested-ternary */
|
||||
peerLatency.find(item => item.peerId === peer.address) ? (
|
||||
peerLatency.filter(item => item.peerId === peer.address)[0].loading ? (
|
||||
<CircularProgress size={20} />
|
||||
) : (
|
||||
peerLatency.filter(item => item.peerId === peer.address)[0].rtt
|
||||
)
|
||||
) : (
|
||||
<Autorenew />
|
||||
)
|
||||
/* eslint-enable no-nested-ternary */
|
||||
}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PeerTable
|
||||
|
||||
+26
-25
@@ -1,31 +1,32 @@
|
||||
import { Container, CircularProgress } from '@material-ui/core/';
|
||||
import PeerTable from './PeerTable';
|
||||
import TroubleshootConnectionCard from '../../components/TroubleshootConnectionCard';
|
||||
import { Container, CircularProgress } from '@material-ui/core/'
|
||||
import PeerTable from './PeerTable'
|
||||
import TroubleshootConnectionCard from '../../components/TroubleshootConnectionCard'
|
||||
|
||||
import { useApiNodeTopology, useApiNodePeers, useDebugApiHealth } from '../../hooks/apiHooks';
|
||||
import TopologyStats from '../../components/TopologyStats';
|
||||
import { useApiNodeTopology, useApiNodePeers, useDebugApiHealth } from '../../hooks/apiHooks'
|
||||
import TopologyStats from '../../components/TopologyStats'
|
||||
import { ReactElement } from 'react'
|
||||
|
||||
export default function Peers() {
|
||||
const topology = useApiNodeTopology()
|
||||
const debugHealth = useDebugApiHealth()
|
||||
const peers = useApiNodePeers()
|
||||
|
||||
if (debugHealth.isLoadingNodeHealth) {
|
||||
return (
|
||||
<Container style={{textAlign:'center', padding:'50px'}}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
if (debugHealth.error) {
|
||||
return <TroubleshootConnectionCard />
|
||||
}
|
||||
export default function Peers(): ReactElement {
|
||||
const topology = useApiNodeTopology()
|
||||
const debugHealth = useDebugApiHealth()
|
||||
const peers = useApiNodePeers()
|
||||
|
||||
if (debugHealth.isLoadingNodeHealth) {
|
||||
return (
|
||||
<>
|
||||
<TopologyStats {...topology} />
|
||||
<PeerTable {...peers} />
|
||||
</>
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
if (debugHealth.error) {
|
||||
return <TroubleshootConnectionCard />
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<TopologyStats {...topology} />
|
||||
<PeerTable {...peers} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,77 +1,86 @@
|
||||
import React, { useState } from 'react'
|
||||
import { Paper, Container, TextField, Typography, Button } from '@material-ui/core';
|
||||
import React, { ReactElement, useState } from 'react'
|
||||
import { Paper, Container, TextField, Typography, Button } from '@material-ui/core'
|
||||
|
||||
export default function Settings() {
|
||||
export default function Settings(): ReactElement {
|
||||
const [refreshVisibility, toggleRefreshVisibility] = useState(false)
|
||||
const [host, setHost] = useState('')
|
||||
const [debugHost, setDebugHost] = useState('')
|
||||
|
||||
const [refreshVisibility, toggleRefreshVisibility] = useState(false)
|
||||
const [host, setHost] = useState('')
|
||||
const [debugHost, setDebugHost] = useState('')
|
||||
|
||||
const handleNewHostConnection = () => {
|
||||
if (host) {
|
||||
sessionStorage.setItem('api_host', host)
|
||||
}
|
||||
if (debugHost) {
|
||||
sessionStorage.setItem('debug_api_host', debugHost)
|
||||
}
|
||||
if (host || debugHost) {
|
||||
toggleRefreshVisibility(!refreshVisibility)
|
||||
window.location.reload();
|
||||
}
|
||||
const handleNewHostConnection = () => {
|
||||
if (host) {
|
||||
sessionStorage.setItem('api_host', host)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Container>
|
||||
<Typography variant="h4" gutterBottom>
|
||||
Settings
|
||||
</Typography>
|
||||
<Paper>
|
||||
<TextField
|
||||
id="filled-full-width"
|
||||
label="API Endpoint"
|
||||
style={{ margin: 0 }}
|
||||
placeholder="ex: 127.0.0.0.1:1633"
|
||||
helperText="Enter node host override / port"
|
||||
fullWidth
|
||||
defaultValue={sessionStorage.getItem('api_host') ? sessionStorage.getItem('api_host') : process.env.REACT_APP_BEE_HOST}
|
||||
margin="normal"
|
||||
InputLabelProps={{
|
||||
shrink: true,
|
||||
}}
|
||||
onChange={(e) => {
|
||||
setHost(e.target.value)
|
||||
toggleRefreshVisibility(true)
|
||||
}}
|
||||
variant="filled"
|
||||
/>
|
||||
</Paper>
|
||||
<Paper style={{marginTop:'20px'}}>
|
||||
<TextField
|
||||
id="filled-full-width"
|
||||
label="Debug API Endpoint"
|
||||
style={{ margin: 0 }}
|
||||
placeholder="ex: 127.0.0.0.1:1635"
|
||||
helperText="Enter node debug host override / port"
|
||||
fullWidth
|
||||
defaultValue={sessionStorage.getItem('debug_api_host') ? sessionStorage.getItem('debug_api_host') : process.env.REACT_APP_BEE_DEBUG_HOST}
|
||||
onChange={(e) => {
|
||||
setDebugHost(e.target.value)
|
||||
toggleRefreshVisibility(true)
|
||||
}}
|
||||
margin="normal"
|
||||
InputLabelProps={{
|
||||
shrink: true,
|
||||
}}
|
||||
variant="filled"
|
||||
/>
|
||||
</Paper>
|
||||
{refreshVisibility ?
|
||||
<div style={{marginTop:'20px'}}>
|
||||
<Button variant='outlined' color='primary' onClick={() => handleNewHostConnection()}>Save</Button>
|
||||
</div>
|
||||
: null}
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
if (debugHost) {
|
||||
sessionStorage.setItem('debug_api_host', debugHost)
|
||||
}
|
||||
|
||||
if (host || debugHost) {
|
||||
toggleRefreshVisibility(!refreshVisibility)
|
||||
window.location.reload()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Container>
|
||||
<Typography variant="h4" gutterBottom>
|
||||
Settings
|
||||
</Typography>
|
||||
<Paper>
|
||||
<TextField
|
||||
id="filled-full-width"
|
||||
label="API Endpoint"
|
||||
style={{ margin: 0 }}
|
||||
placeholder="ex: 127.0.0.0.1:1633"
|
||||
helperText="Enter node host override / port"
|
||||
fullWidth
|
||||
defaultValue={
|
||||
sessionStorage.getItem('api_host') ? sessionStorage.getItem('api_host') : process.env.REACT_APP_BEE_HOST
|
||||
}
|
||||
margin="normal"
|
||||
InputLabelProps={{
|
||||
shrink: true,
|
||||
}}
|
||||
onChange={e => {
|
||||
setHost(e.target.value)
|
||||
toggleRefreshVisibility(true)
|
||||
}}
|
||||
variant="filled"
|
||||
/>
|
||||
</Paper>
|
||||
<Paper style={{ marginTop: '20px' }}>
|
||||
<TextField
|
||||
id="filled-full-width"
|
||||
label="Debug API Endpoint"
|
||||
style={{ margin: 0 }}
|
||||
placeholder="ex: 127.0.0.0.1:1635"
|
||||
helperText="Enter node debug host override / port"
|
||||
fullWidth
|
||||
defaultValue={
|
||||
sessionStorage.getItem('debug_api_host')
|
||||
? sessionStorage.getItem('debug_api_host')
|
||||
: process.env.REACT_APP_BEE_DEBUG_HOST
|
||||
}
|
||||
onChange={e => {
|
||||
setDebugHost(e.target.value)
|
||||
toggleRefreshVisibility(true)
|
||||
}}
|
||||
margin="normal"
|
||||
InputLabelProps={{
|
||||
shrink: true,
|
||||
}}
|
||||
variant="filled"
|
||||
/>
|
||||
</Paper>
|
||||
{refreshVisibility ? (
|
||||
<div style={{ marginTop: '20px' }}>
|
||||
<Button variant="outlined" color="primary" onClick={() => handleNewHostConnection()}>
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
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 DebugConnectionCheck from './SetupSteps/DebugConnectionCheck';
|
||||
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';
|
||||
import { ReactElement, 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 DebugConnectionCheck from './SetupSteps/DebugConnectionCheck'
|
||||
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'
|
||||
import type {
|
||||
ChequebookAddressResponse,
|
||||
ChequebookBalanceResponse,
|
||||
Health,
|
||||
NodeAddresses,
|
||||
Topology,
|
||||
} from '@ethersphere/bee-js'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -27,50 +33,100 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
padding: theme.spacing(5),
|
||||
},
|
||||
}),
|
||||
);
|
||||
)
|
||||
|
||||
function getSteps() {
|
||||
return [
|
||||
'Debug Connection Check',
|
||||
'Version Check',
|
||||
'Version Check',
|
||||
'Connect to Ethereum Blockchain',
|
||||
'Deploy and Fund Chequebook',
|
||||
'Node Connection Check',
|
||||
'Node Connection Check',
|
||||
'Connect to Peers',
|
||||
];
|
||||
]
|
||||
}
|
||||
interface Props {
|
||||
nodeHealth: Health | null
|
||||
nodeApiHealth: boolean
|
||||
nodeAddresses: NodeAddresses | null
|
||||
chequebookAddress: ChequebookAddressResponse | null
|
||||
chequebookBalance: ChequebookBalanceResponse | null
|
||||
beeRelease: LatestBeeRelease | null
|
||||
nodeTopology: Topology | null
|
||||
isLoadingBeeRelease: boolean
|
||||
isLoadingNodeHealth: boolean
|
||||
isLoadingNodeAddresses: boolean
|
||||
isLoadingNodeTopology: boolean
|
||||
isLoadingHealth: boolean
|
||||
isLoadingChequebookAddress: boolean
|
||||
isLoadingChequebookBalance: boolean
|
||||
setStatusChecksVisible: (value: boolean) => void
|
||||
apiHost: string
|
||||
debugApiHost: string
|
||||
}
|
||||
|
||||
function getStepContent(step: number, props: any) {
|
||||
|
||||
function getStepContent(step: number, props: Props) {
|
||||
const {
|
||||
nodeHealth,
|
||||
debugApiHost,
|
||||
beeRelease,
|
||||
isLoadingBeeRelease,
|
||||
nodeAddresses,
|
||||
isLoadingNodeAddresses,
|
||||
isLoadingChequebookBalance,
|
||||
chequebookAddress,
|
||||
chequebookBalance,
|
||||
isLoadingChequebookAddress,
|
||||
nodeApiHealth,
|
||||
apiHost,
|
||||
isLoadingNodeTopology,
|
||||
nodeTopology,
|
||||
} = props
|
||||
switch (step) {
|
||||
case 0:
|
||||
return <DebugConnectionCheck {...props} />;
|
||||
return <DebugConnectionCheck nodeHealth={nodeHealth} debugApiHost={debugApiHost} />
|
||||
case 1:
|
||||
return <VersionCheck {...props} />;
|
||||
return <VersionCheck nodeHealth={nodeHealth} beeRelease={beeRelease} isLoadingBeeRelease={isLoadingBeeRelease} />
|
||||
case 2:
|
||||
return <EthereumConnectionCheck {...props} />;
|
||||
return <EthereumConnectionCheck nodeAddresses={nodeAddresses} isLoadingNodeAddresses={isLoadingNodeAddresses} />
|
||||
case 3:
|
||||
return <ChequebookDeployFund {...props} />;
|
||||
return (
|
||||
<ChequebookDeployFund
|
||||
chequebookAddress={chequebookAddress}
|
||||
chequebookBalance={chequebookBalance}
|
||||
isLoadingChequebookAddress={isLoadingChequebookAddress}
|
||||
isLoadingChequebookBalance={isLoadingChequebookBalance}
|
||||
/>
|
||||
)
|
||||
case 4:
|
||||
return <NodeConnectionCheck {...props} />;
|
||||
return <NodeConnectionCheck nodeApiHealth={nodeApiHealth} apiHost={apiHost} />
|
||||
default:
|
||||
return <PeerConnection {...props} />;
|
||||
return <PeerConnection nodeTopology={nodeTopology} isLoadingNodeTopology={isLoadingNodeTopology} />
|
||||
}
|
||||
}
|
||||
|
||||
export default function NodeSetupWorkflow(props: any) {
|
||||
const {nodeHealth, nodeApiHealth, nodeAddresses, chequebookAddress, chequebookBalance, beeRelease, nodeTopology, setStatusChecksVisible} = props
|
||||
const classes = useStyles();
|
||||
const [activeStep, setActiveStep] = useState(0);
|
||||
const [completed, setCompleted] = useState<{ [k: number]: boolean }>({});
|
||||
const steps = getSteps();
|
||||
export default function NodeSetupWorkflow(props: Props): ReactElement {
|
||||
const {
|
||||
nodeHealth,
|
||||
nodeApiHealth,
|
||||
nodeAddresses,
|
||||
chequebookAddress,
|
||||
chequebookBalance,
|
||||
beeRelease,
|
||||
nodeTopology,
|
||||
setStatusChecksVisible,
|
||||
} = props
|
||||
const classes = useStyles()
|
||||
const [activeStep, setActiveStep] = useState(0)
|
||||
const [completed, setCompleted] = useState<{ [k: number]: boolean }>({})
|
||||
const steps = getSteps()
|
||||
|
||||
useEffect(() => {
|
||||
const handleComplete = (index: number) => {
|
||||
const newCompleted = completed;
|
||||
newCompleted[index] = true;
|
||||
setCompleted(newCompleted);
|
||||
};
|
||||
const newCompleted = completed
|
||||
newCompleted[index] = true
|
||||
setCompleted(newCompleted)
|
||||
}
|
||||
|
||||
const evaluateNodeStatus = () => {
|
||||
if (nodeHealth?.status === 'ok') {
|
||||
@@ -88,7 +144,7 @@ export default function NodeSetupWorkflow(props: any) {
|
||||
setActiveStep(3)
|
||||
}
|
||||
|
||||
if (chequebookAddress?.chequebookaddress && chequebookBalance.totalBalance > 0) {
|
||||
if (chequebookAddress?.chequebookaddress && chequebookBalance && chequebookBalance.totalBalance > 0) {
|
||||
handleComplete(3)
|
||||
setActiveStep(4)
|
||||
}
|
||||
@@ -104,45 +160,62 @@ export default function NodeSetupWorkflow(props: any) {
|
||||
}
|
||||
}
|
||||
evaluateNodeStatus()
|
||||
}, [nodeHealth, nodeApiHealth, nodeAddresses, chequebookAddress, beeRelease, chequebookBalance, nodeTopology, completed])
|
||||
}, [
|
||||
nodeHealth,
|
||||
nodeApiHealth,
|
||||
nodeAddresses,
|
||||
chequebookAddress,
|
||||
beeRelease,
|
||||
chequebookBalance,
|
||||
nodeTopology,
|
||||
completed,
|
||||
])
|
||||
|
||||
const handleNext = () => {
|
||||
setActiveStep((prevActiveStep) => prevActiveStep + 1);
|
||||
};
|
||||
setActiveStep(prevActiveStep => prevActiveStep + 1)
|
||||
}
|
||||
|
||||
const handleBack = () => {
|
||||
setActiveStep((prevActiveStep) => prevActiveStep - 1);
|
||||
};
|
||||
setActiveStep(prevActiveStep => prevActiveStep - 1)
|
||||
}
|
||||
|
||||
const handleSetupComplete = () => {
|
||||
setStatusChecksVisible(false)
|
||||
};
|
||||
}
|
||||
|
||||
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 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 ? 6 : index)}
|
||||
StepIconComponent={() => {
|
||||
if(completed[index])
|
||||
return <CheckCircle style={{color:'#32c48d', height: '25px', cursor:'pointer'}} />
|
||||
else {
|
||||
return <Error style={{color:'#c9201f', height: '25px', cursor:'pointer'}} />
|
||||
}
|
||||
}}
|
||||
<StepLabel
|
||||
onClick={() => setActiveStep(index === activeStep ? 6 : 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 ? 6 : index)} style={{justifyContent:'space-between'}}>
|
||||
<div style={{display:'flex'}}>
|
||||
<div style={{marginTop:'5px'}}>{label}</div>
|
||||
<div style={{marginLeft:'12px'}}>{index === activeStep ? <ExpandLessSharp /> : <ExpandMoreSharp />}</div>
|
||||
<StepButton
|
||||
onClick={() => setActiveStep(index === activeStep ? 6 : 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>
|
||||
@@ -150,20 +223,11 @@ export default function NodeSetupWorkflow(props: any) {
|
||||
<Typography component="div">{getStepContent(index, props)}</Typography>
|
||||
<div className={classes.actionsContainer}>
|
||||
<div>
|
||||
<Button
|
||||
disabled={activeStep === 0}
|
||||
onClick={handleBack}
|
||||
className={classes.button}
|
||||
>
|
||||
<Button disabled={activeStep === 0} onClick={handleBack} className={classes.button}>
|
||||
Back
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleNext}
|
||||
className={classes.button}
|
||||
>
|
||||
Next
|
||||
<Button variant="contained" color="primary" onClick={handleNext} className={classes.button}>
|
||||
Next
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -174,10 +238,7 @@ export default function NodeSetupWorkflow(props: any) {
|
||||
{Object.values(completed).filter(value => value).length === 6 ? (
|
||||
<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}
|
||||
>
|
||||
<Button onClick={handleBack} className={classes.button}>
|
||||
Back
|
||||
</Button>
|
||||
<Button onClick={handleSetupComplete} variant="contained" color="primary" className={classes.button}>
|
||||
@@ -186,5 +247,5 @@ export default function NodeSetupWorkflow(props: any) {
|
||||
</Paper>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,44 +1,57 @@
|
||||
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';
|
||||
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'
|
||||
import type { ChequebookAddressResponse, ChequebookBalanceResponse } from '@ethersphere/bee-js'
|
||||
import type { ReactElement } from 'react'
|
||||
|
||||
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 <Typography variant='button'>https://bzz.ethswarm.org/?transaction=buy&amount=10&slippage=30&receiver=[ENTER_ADDRESS_HERE]</Typography> to get BZZ</span>
|
||||
<CodeBlockTabs
|
||||
showLineNumbers
|
||||
linux={`bee-get-addr`}
|
||||
mac={`bee-get-addr`}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<Typography variant="subtitle1" gutterBottom>Chequebook Address</Typography>
|
||||
<EthereumAddress
|
||||
address={props.chequebookAddress?.chequebookaddress}
|
||||
network={'goerli'}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
interface Props {
|
||||
chequebookAddress: ChequebookAddressResponse | null
|
||||
chequebookBalance: ChequebookBalanceResponse | null
|
||||
isLoadingChequebookAddress: boolean
|
||||
isLoadingChequebookBalance: boolean
|
||||
}
|
||||
|
||||
const ChequebookDeployFund = (props: Props): ReactElement => (
|
||||
<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' }}>
|
||||
{
|
||||
// FIXME: this should be broken up
|
||||
/* eslint-disable no-nested-ternary */
|
||||
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.isLoadingChequebookAddress || 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{' '}
|
||||
<Typography variant="button">
|
||||
https://bzz.ethswarm.org/?transaction=buy&amount=10&slippage=30&receiver=[ENTER_ADDRESS_HERE]
|
||||
</Typography>{' '}
|
||||
to get BZZ
|
||||
</span>
|
||||
<CodeBlockTabs showLineNumbers linux={`bee-get-addr`} mac={`bee-get-addr`} />
|
||||
</div>
|
||||
)
|
||||
/* eslint-enable no-nested-ternary */
|
||||
}
|
||||
</div>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
Chequebook Address
|
||||
</Typography>
|
||||
<EthereumAddress address={props.chequebookAddress?.chequebookaddress} network={'goerli'} />
|
||||
</div>
|
||||
)
|
||||
|
||||
export default ChequebookDeployFund
|
||||
|
||||
@@ -1,76 +1,101 @@
|
||||
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 type { ReactElement } 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 ConnectToHost from '../../../components/ConnectToHost'
|
||||
import CodeBlockTabs from '../../../components/CodeBlockTabs'
|
||||
import type { Health } from '@ethersphere/bee-js'
|
||||
|
||||
export default function NodeConnectionCheck(props: any) {
|
||||
return (
|
||||
interface Props {
|
||||
nodeHealth: Health | null
|
||||
debugApiHost: string
|
||||
}
|
||||
|
||||
export default function NodeConnectionCheck(props: Props): ReactElement {
|
||||
return (
|
||||
<div>
|
||||
<p>Connect to Bee Node Debug API</p>
|
||||
<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 (<Typography variant="button">{props.debugApiHost}</Typography>)
|
||||
</span>
|
||||
<ConnectToHost hostName={'debug_api_host'} defaultHost={props.debugApiHost} />
|
||||
</div>
|
||||
<div>
|
||||
<p>Connect to Bee Node Debug API</p>
|
||||
<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 (<Typography variant="button">{props.debugApiHost}</Typography>)</span>
|
||||
<ConnectToHost hostName={'debug_api_host'} defaultHost={props.debugApiHost} />
|
||||
</div>
|
||||
<div>
|
||||
{ props.nodeHealth?.status !== 'ok' ?
|
||||
<Typography component="div" variant="body2" gutterBottom style={{margin: '15px'}}>
|
||||
We cannot connect to your nodes debug API at <Typography variant="button">{props.debugApiHost}</Typography>. 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 component="div">
|
||||
{props.nodeHealth?.status !== 'ok' ? (
|
||||
<Typography component="div" variant="body2" gutterBottom style={{ margin: '15px' }}>
|
||||
We cannot connect to your nodes debug API at{' '}
|
||||
<Typography variant="button">{props.debugApiHost}</Typography>. 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 component="div">
|
||||
<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 status swarm-bee`}
|
||||
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.
|
||||
<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`}
|
||||
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`}
|
||||
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>
|
||||
<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`}
|
||||
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>
|
||||
</Typography>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</Typography>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,37 +1,56 @@
|
||||
import React from 'react';
|
||||
import { Typography } from '@material-ui/core/';
|
||||
import { CheckCircle, Warning } from '@material-ui/icons/';
|
||||
import EthereumAddress from '../../../components/EthereumAddress';
|
||||
import type { ReactElement } from 'react'
|
||||
import { Typography } from '@material-ui/core/'
|
||||
import { CheckCircle, Warning } from '@material-ui/icons/'
|
||||
import EthereumAddress from '../../../components/EthereumAddress'
|
||||
import type { NodeAddresses } from '@ethersphere/bee-js'
|
||||
|
||||
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>Node Address</Typography>
|
||||
<EthereumAddress
|
||||
address={props.nodeAddresses?.ethereum}
|
||||
network={'goerli'}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
interface Props {
|
||||
nodeAddresses: NodeAddresses | null
|
||||
isLoadingNodeAddresses: boolean
|
||||
}
|
||||
|
||||
export default function EthereumConnectionCheck(props: Props): ReactElement {
|
||||
return (
|
||||
<div>
|
||||
<p>Connect to the ethereum blockchain.</p>
|
||||
<div style={{ marginBottom: '10px' }}>
|
||||
{
|
||||
// FIXME: this should be broken up
|
||||
/* eslint-disable no-nested-ternary */
|
||||
props.nodeAddresses?.ethereum ? (
|
||||
<div>
|
||||
<CheckCircle style={{ color: '#32c48d', marginRight: '7px', height: '18px' }} />
|
||||
<span>Your connected to the Ethereum network</span>
|
||||
</div>
|
||||
) : props.isLoadingNodeAddresses ? 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>
|
||||
) /* eslint-enable no-nested-ternary */
|
||||
}
|
||||
</div>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
Node Address
|
||||
</Typography>
|
||||
<EthereumAddress address={props.nodeAddresses?.ethereum} network={'goerli'} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,64 +1,71 @@
|
||||
import React from 'react'
|
||||
import { Typography, Accordion, AccordionSummary, AccordionDetails } from '@material-ui/core/';
|
||||
import { CheckCircle, Error, ExpandMoreSharp } from '@material-ui/icons/';
|
||||
import React, { ReactElement } from 'react'
|
||||
import { Typography, Accordion, AccordionSummary, AccordionDetails } from '@material-ui/core/'
|
||||
import { CheckCircle, Error, ExpandMoreSharp } from '@material-ui/icons/'
|
||||
|
||||
import ConnectToHost from '../../../components/ConnectToHost';
|
||||
import ConnectToHost from '../../../components/ConnectToHost'
|
||||
import CodeBlockTabs from '../../../components/CodeBlockTabs'
|
||||
|
||||
export default function NodeConnectionCheck(props: any) {
|
||||
return (
|
||||
<div>
|
||||
<p>Connect to Bee Node API</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 (<Typography variant="button">{props.apiHost}</Typography>)</span>
|
||||
<ConnectToHost hostName='api_host' defaultHost={props.apiHost} />
|
||||
</div>
|
||||
<div>
|
||||
{ !props.nodeApiHealth ?
|
||||
<Typography component="div" variant="body2" gutterBottom style={{margin: '15px'}}>
|
||||
We cannot connect to your nodes API at <Typography variant="button">{props.apiHost}</Typography>. 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 component="div">
|
||||
<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>
|
||||
)
|
||||
interface Props {
|
||||
nodeApiHealth: boolean
|
||||
apiHost: string
|
||||
}
|
||||
|
||||
export default function NodeConnectionCheck(props: Props): ReactElement {
|
||||
return (
|
||||
<div>
|
||||
<p>Connect to Bee Node API</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 (<Typography variant="button">{props.apiHost}</Typography>)
|
||||
</span>
|
||||
<ConnectToHost hostName="api_host" defaultHost={props.apiHost} />
|
||||
</div>
|
||||
<div>
|
||||
{!props.nodeApiHealth ? (
|
||||
<Typography component="div" variant="body2" gutterBottom style={{ margin: '15px' }}>
|
||||
We cannot connect to your nodes API at <Typography variant="button">{props.apiHost}</Typography>. 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 component="div">
|
||||
<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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,45 +1,53 @@
|
||||
import React from 'react';
|
||||
import { Typography } from '@material-ui/core/';
|
||||
import { CheckCircle, Warning } from '@material-ui/icons/';
|
||||
import React, { ReactElement } from 'react'
|
||||
import { Typography } from '@material-ui/core/'
|
||||
import { CheckCircle, Warning } from '@material-ui/icons/'
|
||||
import { Topology } from '@ethersphere/bee-js'
|
||||
|
||||
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 component="div" variant="subtitle1" gutterBottom color="textSecondary">
|
||||
<span>Connected Peers</span>
|
||||
</Typography>
|
||||
<Typography component="h2" variant="h5">
|
||||
{ props.nodeTopology.connected }
|
||||
</Typography>
|
||||
</div>
|
||||
<div>
|
||||
<Typography component="div" variant="subtitle1" gutterBottom color="textSecondary">
|
||||
<span>Discovered Nodes</span>
|
||||
</Typography>
|
||||
<Typography component="h2" variant="h5">
|
||||
{ props.nodeTopology.population }
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
interface Props {
|
||||
nodeTopology: Topology | null
|
||||
isLoadingNodeTopology: boolean
|
||||
}
|
||||
|
||||
export default function PeerConnection(props: Props): ReactElement {
|
||||
return (
|
||||
<div>
|
||||
<p>Connect to Peers</p>
|
||||
<div style={{ marginBottom: '10px' }}>
|
||||
html_url
|
||||
{
|
||||
// FIXME: this should be broken up
|
||||
/* eslint-disable no-nested-ternary */
|
||||
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.isLoadingNodeTopology ? null : (
|
||||
<div>
|
||||
<Warning style={{ color: '#ff9800', marginRight: '7px', height: '18px' }} />
|
||||
<span>Your node is not connected to any peers</span>
|
||||
</div>
|
||||
) /* eslint-enable no-nested-ternary */
|
||||
}
|
||||
</div>
|
||||
<div style={{ display: 'flex' }}>
|
||||
<div style={{ marginRight: '30px' }}>
|
||||
<Typography component="div" variant="subtitle1" gutterBottom color="textSecondary">
|
||||
<span>Connected Peers</span>
|
||||
</Typography>
|
||||
<Typography component="h2" variant="h5">
|
||||
{props.nodeTopology?.connected}
|
||||
</Typography>
|
||||
</div>
|
||||
<div>
|
||||
<Typography component="div" variant="subtitle1" gutterBottom color="textSecondary">
|
||||
<span>Discovered Nodes</span>
|
||||
</Typography>
|
||||
<Typography component="h2" variant="h5">
|
||||
{props.nodeTopology?.population}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,45 +1,81 @@
|
||||
import React from 'react';
|
||||
import { Typography } from '@material-ui/core/';
|
||||
import { CheckCircle, Warning } from '@material-ui/icons/';
|
||||
import CodeBlockTabs from '../../../components/CodeBlockTabs';
|
||||
import React, { ReactElement } from 'react'
|
||||
import { Typography } from '@material-ui/core/'
|
||||
import { CheckCircle, Warning } from '@material-ui/icons/'
|
||||
import CodeBlockTabs from '../../../components/CodeBlockTabs'
|
||||
import { Health } from '@ethersphere/bee-js'
|
||||
|
||||
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>
|
||||
)
|
||||
interface Props {
|
||||
beeRelease: LatestBeeRelease | null
|
||||
isLoadingBeeRelease: boolean
|
||||
nodeHealth: Health | null
|
||||
}
|
||||
|
||||
export default function VersionCheck(props: Props): ReactElement {
|
||||
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>
|
||||
{
|
||||
// FIXME: this should be broken up
|
||||
/* eslint-disable no-nested-ternary */
|
||||
props.beeRelease && props.beeRelease.name === `v${props.nodeHealth?.version?.split('-')[0]}` ? (
|
||||
<div>
|
||||
<CheckCircle style={{ color: '#32c48d', marginRight: '7px', height: '18px' }} />
|
||||
<span>Your running the latest version of Bee</span>
|
||||
</div>
|
||||
) : props.isLoadingBeeRelease ? 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.nodeHealth?.version?.split('-')[0]}_amd64.deb\nsudo dpkg -i bee_${
|
||||
props.nodeHealth?.version?.split('-')[0]
|
||||
}_amd64.deb`}
|
||||
mac={`bee version\nbrew tap ethersphere/tap\nbrew install swarm-bee\nbrew services start swarm-bee`}
|
||||
/>
|
||||
</div>
|
||||
) /* eslint-enable no-nested-ternary */
|
||||
}
|
||||
<div style={{ display: 'flex' }}>
|
||||
<div style={{ marginRight: '30px' }}>
|
||||
<p>
|
||||
<span>Current Version</span>
|
||||
</p>
|
||||
<Typography component="h5" variant="h5">
|
||||
<span>{props.nodeHealth?.version ? ` v${props.nodeHealth?.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>
|
||||
)
|
||||
}
|
||||
|
||||
+126
-114
@@ -1,13 +1,13 @@
|
||||
import React, { useState } from 'react'
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ReactElement, 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';
|
||||
import type { Health, NodeAddresses, Topology } from '@ethersphere/bee-js';
|
||||
import { 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'
|
||||
import type { Health, NodeAddresses, Topology } from '@ethersphere/bee-js'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
const useStyles = makeStyles(() =>
|
||||
createStyles({
|
||||
root: {
|
||||
display: 'flex',
|
||||
@@ -22,120 +22,132 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
flex: '1 0 auto',
|
||||
},
|
||||
status: {
|
||||
color: '#2145a0',
|
||||
backgroundColor: '#e1effe',
|
||||
}
|
||||
color: '#2145a0',
|
||||
backgroundColor: '#e1effe',
|
||||
},
|
||||
}),
|
||||
);
|
||||
)
|
||||
|
||||
interface IProps{
|
||||
nodeHealth: Health,
|
||||
loadingNodeHealth: boolean,
|
||||
beeRelease: any,
|
||||
loadingBeeRelease: boolean,
|
||||
nodeAddresses: NodeAddresses,
|
||||
nodeTopology: Topology,
|
||||
loadingNodeTopology: boolean,
|
||||
setStatusChecksVisible: any,
|
||||
interface Props {
|
||||
nodeHealth: Health | null
|
||||
loadingNodeHealth: boolean
|
||||
beeRelease: LatestBeeRelease | null
|
||||
loadingBeeRelease: boolean
|
||||
nodeAddresses: NodeAddresses
|
||||
nodeTopology: Topology
|
||||
loadingNodeTopology: boolean
|
||||
setStatusChecksVisible: (value: boolean) => void
|
||||
}
|
||||
|
||||
function StatusCard(props: IProps) {
|
||||
const classes = useStyles();
|
||||
function StatusCard(props: Props): ReactElement {
|
||||
const classes = useStyles()
|
||||
|
||||
const [underlayAddressesVisible, setUnderlayAddresessVisible] = useState<Boolean>(false)
|
||||
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>
|
||||
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 component="div" variant="subtitle2" gutterBottom>
|
||||
<span>AGENT: </span>
|
||||
<a href="https://github.com/ethersphere/bee" rel="noreferrer" target="_blank">
|
||||
Bee
|
||||
</a>
|
||||
<span>{props.nodeHealth?.version ? ` v${props.nodeHealth.version}` : '-'}</span>
|
||||
{
|
||||
// FIXME: this should be broken up
|
||||
/* eslint-disable no-nested-ternary */
|
||||
props.beeRelease && props.beeRelease.name === `v${props.nodeHealth?.version?.split('-')[0]}` ? (
|
||||
<Chip
|
||||
style={{ marginLeft: '7px', color: '#2145a0' }}
|
||||
size="small"
|
||||
label="latest"
|
||||
className={classes.status}
|
||||
/>
|
||||
) : props.loadingBeeRelease ? (
|
||||
''
|
||||
) : (
|
||||
<Typography variant="button">update</Typography>
|
||||
)
|
||||
/* eslint-enable no-nested-ternary */
|
||||
}
|
||||
</Typography>
|
||||
<Typography component="div" variant="subtitle2" gutterBottom>
|
||||
<span>PUBLIC KEY: </span>
|
||||
<span>{props.nodeAddresses.public_key ? props.nodeAddresses.public_key : '-'}</span>
|
||||
</Typography>
|
||||
<Typography component="div" variant="subtitle2" gutterBottom>
|
||||
<span>PSS PUBLIC KEY: </span>
|
||||
<span>{props.nodeAddresses.pss_public_key ? props.nodeAddresses.pss_public_key : '-'}</span>
|
||||
</Typography>
|
||||
<Typography component="div" variant="subtitle2" gutterBottom>
|
||||
<Typography component="div" style={{ marginTop: '20px' }}>
|
||||
<span>OVERLAY ADDRESS (PEER ID): </span>
|
||||
<span>{props.nodeAddresses.overlay ? props.nodeAddresses.overlay : '-'}</span>
|
||||
</Typography>
|
||||
<Typography component="div" 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>
|
||||
<Typography component="div" variant="subtitle2" gutterBottom>
|
||||
<span>AGENT: </span>
|
||||
<a href='https://github.com/ethersphere/bee' rel='noreferrer' target='_blank'>Bee</a>
|
||||
<span>{props.nodeHealth?.version ? ` v${props.nodeHealth.version}` : '-'}</span>
|
||||
{props.beeRelease && props.beeRelease.name === `v${props.nodeHealth?.version?.split('-')[0]}` ?
|
||||
<Chip
|
||||
style={{ marginLeft: '7px', color: '#2145a0' }}
|
||||
size="small"
|
||||
label='latest'
|
||||
className={classes.status}
|
||||
/>
|
||||
:
|
||||
props.loadingBeeRelease ?
|
||||
''
|
||||
:
|
||||
<Typography variant="button">update</Typography>
|
||||
}
|
||||
</Typography>
|
||||
<Typography component="div" variant="subtitle2" gutterBottom>
|
||||
<span>PUBLIC KEY: </span>
|
||||
<span>{ props.nodeAddresses.public_key ? props.nodeAddresses.public_key : '-' }</span>
|
||||
</Typography>
|
||||
<Typography component="div" variant="subtitle2" gutterBottom>
|
||||
<span>PSS PUBLIC KEY: </span>
|
||||
<span>{ props.nodeAddresses.pss_public_key ? props.nodeAddresses.pss_public_key : '-' }</span>
|
||||
</Typography>
|
||||
<Typography component="div" variant="subtitle2" gutterBottom>
|
||||
<Typography component="div" style={{marginTop:'20px'}}>
|
||||
<span>OVERLAY ADDRESS (PEER ID): </span>
|
||||
<span>{ props.nodeAddresses.overlay ? props.nodeAddresses.overlay : '-' }</span>
|
||||
</Typography>
|
||||
<Typography component="div" 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>
|
||||
{props.nodeAddresses.underlay
|
||||
? props.nodeAddresses.underlay.map(item => <li key={item}>{item}</li>)
|
||||
: '-'}
|
||||
</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>
|
||||
)
|
||||
) : 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
|
||||
|
||||
+128
-120
@@ -1,135 +1,143 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import axios from 'axios';
|
||||
import { Container, CircularProgress } from '@material-ui/core';
|
||||
import { useState, useEffect, ReactElement } 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, useApiNodeAddresses, useApiChequebookAddress, useApiNodeTopology, useApiChequebookBalance } from '../../hooks/apiHooks';
|
||||
import NodeSetupWorkflow from './NodeSetupWorkflow'
|
||||
import StatusCard from './StatusCard'
|
||||
import EthereumAddressCard from '../../components/EthereumAddressCard'
|
||||
import {
|
||||
useApiHealth,
|
||||
useDebugApiHealth,
|
||||
useApiNodeAddresses,
|
||||
useApiChequebookAddress,
|
||||
useApiNodeTopology,
|
||||
useApiChequebookBalance,
|
||||
} from '../../hooks/apiHooks'
|
||||
|
||||
export default function Status() {
|
||||
const [beeRelease, setBeeRelease] = useState({ name: ''});
|
||||
const [isLoadingBeeRelease, setIsLoadingBeeRelease] = useState<boolean>(false);
|
||||
export default function Status(): ReactElement {
|
||||
const [beeRelease, setBeeRelease] = useState<LatestBeeRelease | null>(null)
|
||||
const [isLoadingBeeRelease, setIsLoadingBeeRelease] = useState<boolean>(false)
|
||||
|
||||
const [apiHost, setApiHost] = useState('');
|
||||
const [debugApiHost, setDebugApiHost] = useState('');
|
||||
const [apiHost, setApiHost] = useState('')
|
||||
const [debugApiHost, setDebugApiHost] = useState('')
|
||||
|
||||
const [statusChecksVisible, setStatusChecksVisible] = useState<boolean>(false);
|
||||
const [statusChecksVisible, setStatusChecksVisible] = useState<boolean>(false)
|
||||
|
||||
const { health, isLoadingHealth } = useApiHealth()
|
||||
const { nodeHealth, isLoadingNodeHealth } = useDebugApiHealth()
|
||||
const { nodeAddresses, isLoadingNodeAddresses } = useApiNodeAddresses()
|
||||
const { chequebookAddress, isLoadingChequebookAddress } = useApiChequebookAddress()
|
||||
const { topology: nodeTopology, isLoading: isLoadingNodeTopology } = useApiNodeTopology()
|
||||
const { chequebookBalance, isLoadingChequebookBalance } = useApiChequebookBalance()
|
||||
const { health, isLoadingHealth } = useApiHealth()
|
||||
const { nodeHealth, isLoadingNodeHealth } = useDebugApiHealth()
|
||||
const { nodeAddresses, isLoadingNodeAddresses } = useApiNodeAddresses()
|
||||
const { chequebookAddress, isLoadingChequebookAddress } = useApiChequebookAddress()
|
||||
const { topology: nodeTopology, isLoading: isLoadingNodeTopology } = useApiNodeTopology()
|
||||
const { chequebookBalance, isLoadingChequebookBalance } = useApiChequebookBalance()
|
||||
|
||||
const fetchLatestBeeRelease = () => {
|
||||
setIsLoadingBeeRelease(true)
|
||||
axios
|
||||
.get(`${process.env.REACT_APP_BEE_GITHUB_REPO_URL}/releases/latest`)
|
||||
.then(res => {
|
||||
setBeeRelease(res.data)
|
||||
})
|
||||
.catch(() => {
|
||||
// FIXME: should do something about the error
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoadingBeeRelease(false)
|
||||
})
|
||||
}
|
||||
|
||||
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 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)
|
||||
}
|
||||
|
||||
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()
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
fetchApiHost()
|
||||
fetchDebugApiHost()
|
||||
fetchLatestBeeRelease()
|
||||
}, []);
|
||||
|
||||
return (
|
||||
// FIXME: this should be broken up
|
||||
/* eslint-disable no-nested-ternary */
|
||||
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>
|
||||
{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}
|
||||
beeRelease={beeRelease}
|
||||
loadingBeeRelease={isLoadingBeeRelease}
|
||||
nodeAddresses={nodeAddresses}
|
||||
loadingNodeTopology={isLoadingNodeTopology}
|
||||
nodeTopology={nodeTopology}
|
||||
setStatusChecksVisible={setStatusChecksVisible}
|
||||
/>
|
||||
<EthereumAddressCard
|
||||
nodeAddresses={nodeAddresses}
|
||||
isLoadingNodeAddresses={isLoadingNodeAddresses}
|
||||
chequebookAddress={chequebookAddress}
|
||||
isLoadingChequebookAddress={isLoadingChequebookAddress}
|
||||
/>
|
||||
</div>
|
||||
:
|
||||
( isLoadingNodeHealth || isLoadingHealth || isLoadingChequebookAddress ||
|
||||
isLoadingNodeTopology || isLoadingBeeRelease || isLoadingNodeAddresses || isLoadingBeeRelease || isLoadingChequebookBalance
|
||||
)
|
||||
?
|
||||
<Container style={{textAlign:'center', padding:'50px'}}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
:
|
||||
<NodeSetupWorkflow
|
||||
beeRelease={beeRelease}
|
||||
isLoadingBeeRelease={isLoadingBeeRelease}
|
||||
|
||||
nodeHealth={nodeHealth}
|
||||
isLoadingNodeHealth={isLoadingNodeHealth}
|
||||
|
||||
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}
|
||||
/>
|
||||
}
|
||||
<StatusCard
|
||||
nodeHealth={nodeHealth}
|
||||
loadingNodeHealth={isLoadingNodeHealth}
|
||||
beeRelease={beeRelease}
|
||||
loadingBeeRelease={isLoadingBeeRelease}
|
||||
nodeAddresses={nodeAddresses}
|
||||
loadingNodeTopology={isLoadingNodeTopology}
|
||||
nodeTopology={nodeTopology}
|
||||
setStatusChecksVisible={setStatusChecksVisible}
|
||||
/>
|
||||
<EthereumAddressCard
|
||||
nodeAddresses={nodeAddresses}
|
||||
isLoadingNodeAddresses={isLoadingNodeAddresses}
|
||||
chequebookAddress={chequebookAddress}
|
||||
isLoadingChequebookAddress={isLoadingChequebookAddress}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
) : isLoadingNodeHealth ||
|
||||
isLoadingHealth ||
|
||||
isLoadingChequebookAddress ||
|
||||
isLoadingNodeTopology ||
|
||||
isLoadingBeeRelease ||
|
||||
isLoadingNodeAddresses ||
|
||||
isLoadingBeeRelease ||
|
||||
isLoadingChequebookBalance ? (
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
) : (
|
||||
<NodeSetupWorkflow
|
||||
beeRelease={beeRelease}
|
||||
isLoadingBeeRelease={isLoadingBeeRelease}
|
||||
nodeHealth={nodeHealth}
|
||||
isLoadingNodeHealth={isLoadingNodeHealth}
|
||||
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>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user