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,98 +1,92 @@
|
||||
import React from 'react';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Input from '@material-ui/core/Input';
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import DialogActions from '@material-ui/core/DialogActions';
|
||||
import DialogContent from '@material-ui/core/DialogContent';
|
||||
import DialogContentText from '@material-ui/core/DialogContentText';
|
||||
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||
import { Snackbar, Container, CircularProgress } from '@material-ui/core';
|
||||
import { ReactElement, useState } from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Input from '@material-ui/core/Input'
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import DialogActions from '@material-ui/core/DialogActions'
|
||||
import DialogContent from '@material-ui/core/DialogContent'
|
||||
import DialogContentText from '@material-ui/core/DialogContentText'
|
||||
import DialogTitle from '@material-ui/core/DialogTitle'
|
||||
import { Snackbar, Container, CircularProgress } from '@material-ui/core'
|
||||
|
||||
import { beeDebugApi } from '../services/bee';
|
||||
import { beeDebugApi } from '../services/bee'
|
||||
|
||||
import EthereumAddress from './EthereumAddress';
|
||||
import EthereumAddress from './EthereumAddress'
|
||||
|
||||
export default function DepositModal() {
|
||||
const [open, setOpen] = React.useState<boolean>(false);
|
||||
const [peerId, setPeerId] = React.useState('');
|
||||
const [loadingCashout, setLoadingCashout] = React.useState<boolean>(false);
|
||||
const [showToast, setToastVisibility] = React.useState<boolean>(false);
|
||||
const [toastContent, setToastContent] = React.useState<JSX.Element | null>(null);
|
||||
export default function DepositModal(): ReactElement {
|
||||
const [open, setOpen] = useState<boolean>(false)
|
||||
const [peerId, setPeerId] = useState('')
|
||||
const [loadingCashout, setLoadingCashout] = useState<boolean>(false)
|
||||
const [showToast, setToastVisibility] = useState<boolean>(false)
|
||||
const [toastContent, setToastContent] = useState<JSX.Element | null>(null)
|
||||
|
||||
const handleClickOpen = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
setOpen(true)
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
const handleCashout = () => {
|
||||
if (peerId) {
|
||||
setLoadingCashout(true)
|
||||
beeDebugApi.chequebook.peerCashout(peerId)
|
||||
setLoadingCashout(true)
|
||||
beeDebugApi.chequebook
|
||||
.peerCashout(peerId)
|
||||
.then(res => {
|
||||
setOpen(false);
|
||||
handleToast(<span>Successfully cashed out cheque. Transaction
|
||||
<EthereumAddress
|
||||
hideBlockie
|
||||
transaction
|
||||
address={res.transactionHash}
|
||||
network={'goerli'}
|
||||
/>
|
||||
</span>)
|
||||
setOpen(false)
|
||||
handleToast(
|
||||
<span>
|
||||
Successfully cashed out cheque. Transaction
|
||||
<EthereumAddress hideBlockie transaction address={res.transactionHash} network={'goerli'} />
|
||||
</span>,
|
||||
)
|
||||
})
|
||||
.catch(error => {
|
||||
.catch(() => {
|
||||
// FIXME: handle errors more gracefully
|
||||
handleToast(<span>Error with cashout</span>)
|
||||
})
|
||||
.finally(() => {
|
||||
setLoadingCashout(false)
|
||||
})
|
||||
} else {
|
||||
handleToast(<span>Peer Id invalid</span>)
|
||||
handleToast(<span>Peer Id invalid</span>)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleToast = (text: JSX.Element) => {
|
||||
setToastContent(text)
|
||||
setToastVisibility(true);
|
||||
setTimeout(
|
||||
() => setToastVisibility(false),
|
||||
7000
|
||||
);
|
||||
};
|
||||
setToastVisibility(true)
|
||||
setTimeout(() => setToastVisibility(false), 7000)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button variant="contained" color="primary" onClick={handleClickOpen} style={{marginLeft:'7px'}}>
|
||||
<Button variant="contained" color="primary" onClick={handleClickOpen} style={{ marginLeft: '7px' }}>
|
||||
Cashout
|
||||
</Button>
|
||||
<Snackbar
|
||||
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
|
||||
open={showToast}
|
||||
message={toastContent}
|
||||
/>
|
||||
<Snackbar anchorOrigin={{ vertical: 'top', horizontal: 'center' }} open={showToast} message={toastContent} />
|
||||
<Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title">
|
||||
<DialogTitle id="form-dialog-title">Cashout Cheque</DialogTitle>
|
||||
{loadingCashout ?
|
||||
<Container style={{textAlign:'center', padding:'50px'}}>
|
||||
<CircularProgress />
|
||||
{loadingCashout ? (
|
||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<CircularProgress />
|
||||
</Container>
|
||||
:
|
||||
<DialogContent>
|
||||
<DialogContentText style={{marginTop: '20px'}}>
|
||||
Specify the peer Id of the peer you would like to cashout.
|
||||
</DialogContentText>
|
||||
<Input
|
||||
autoFocus
|
||||
margin="dense"
|
||||
id="peerId"
|
||||
type="text"
|
||||
placeholder='Peer Id'
|
||||
fullWidth
|
||||
onChange={(e) => setPeerId(e.target.value)}
|
||||
/>
|
||||
</DialogContent>}
|
||||
) : (
|
||||
<DialogContent>
|
||||
<DialogContentText style={{ marginTop: '20px' }}>
|
||||
Specify the peer Id of the peer you would like to cashout.
|
||||
</DialogContentText>
|
||||
<Input
|
||||
autoFocus
|
||||
margin="dense"
|
||||
id="peerId"
|
||||
type="text"
|
||||
placeholder="Peer Id"
|
||||
fullWidth
|
||||
onChange={e => setPeerId(e.target.value)}
|
||||
/>
|
||||
</DialogContent>
|
||||
)}
|
||||
<DialogActions>
|
||||
<Button onClick={handleClose} color="primary">
|
||||
Cancel
|
||||
@@ -103,5 +97,5 @@ export default function DepositModal() {
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,37 +1,28 @@
|
||||
import React from 'react';
|
||||
import { IconButton, Snackbar } from '@material-ui/core';
|
||||
import {CopyToClipboard} from 'react-copy-to-clipboard';
|
||||
import { Clipboard } from 'react-feather';
|
||||
import { ReactElement, useState } from 'react'
|
||||
import { IconButton, Snackbar } from '@material-ui/core'
|
||||
import { CopyToClipboard } from 'react-copy-to-clipboard'
|
||||
import { Clipboard } from 'react-feather'
|
||||
|
||||
interface IProps {
|
||||
value: string,
|
||||
interface Props {
|
||||
value: string
|
||||
}
|
||||
|
||||
export default function ClipboardCopy(props: IProps) {
|
||||
const [copied, setCopied] = React.useState(false);
|
||||
|
||||
const handleCopy = () => {
|
||||
setCopied(true);
|
||||
setTimeout(
|
||||
() => setCopied(false),
|
||||
3000
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div style={{marginRight:'3px', marginLeft:'3px'}}>
|
||||
<Snackbar
|
||||
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
|
||||
open={copied}
|
||||
message="Copied"
|
||||
/>
|
||||
<IconButton color="primary" size='small' onClick={handleCopy}>
|
||||
<CopyToClipboard text={props.value}
|
||||
>
|
||||
<Clipboard style={{height:'20px'}}/>
|
||||
</CopyToClipboard>
|
||||
</IconButton>
|
||||
</div>
|
||||
);
|
||||
export default function ClipboardCopy(props: Props): ReactElement {
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const handleCopy = () => {
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 3000)
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ marginRight: '3px', marginLeft: '3px' }}>
|
||||
<Snackbar anchorOrigin={{ vertical: 'top', horizontal: 'center' }} open={copied} message="Copied" />
|
||||
<IconButton color="primary" size="small" onClick={handleCopy}>
|
||||
<CopyToClipboard text={props.value}>
|
||||
<Clipboard style={{ height: '20px' }} />
|
||||
</CopyToClipboard>
|
||||
</IconButton>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import SyntaxHighlighter from 'react-syntax-highlighter';
|
||||
import type { ReactElement } from 'react'
|
||||
import SyntaxHighlighter from 'react-syntax-highlighter'
|
||||
|
||||
interface IProps {
|
||||
code: string,
|
||||
language: string,
|
||||
showLineNumbers?: boolean,
|
||||
interface Props {
|
||||
code: string
|
||||
language: string
|
||||
showLineNumbers?: boolean
|
||||
}
|
||||
|
||||
const CodeBlock = (props: IProps) => {
|
||||
const CodeBlock = (props: Props): ReactElement => {
|
||||
return (
|
||||
<div style={{textAlign:'left'}}>
|
||||
<SyntaxHighlighter
|
||||
language={props.language}
|
||||
showLineNumbers={props.showLineNumbers}
|
||||
>
|
||||
<div style={{ textAlign: 'left' }}>
|
||||
<SyntaxHighlighter language={props.language} showLineNumbers={props.showLineNumbers}>
|
||||
{props.code}
|
||||
</SyntaxHighlighter>
|
||||
</SyntaxHighlighter>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default CodeBlock;
|
||||
export default CodeBlock
|
||||
|
||||
+129
-140
@@ -1,158 +1,147 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { withStyles, Theme, createStyles } from '@material-ui/core/styles';
|
||||
import { Tabs, Tab, Box, Typography } from '@material-ui/core';
|
||||
import CodeBlock from './CodeBlock';
|
||||
import React, { ReactElement, useEffect } from 'react'
|
||||
import { withStyles, Theme, createStyles } from '@material-ui/core/styles'
|
||||
import { Tabs, Tab, Box, Typography } from '@material-ui/core'
|
||||
import CodeBlock from './CodeBlock'
|
||||
|
||||
interface TabPanelProps {
|
||||
children?: React.ReactNode;
|
||||
index: any;
|
||||
value: any;
|
||||
children?: React.ReactNode
|
||||
index: number
|
||||
value: number
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
linux: string;
|
||||
mac: string;
|
||||
showLineNumbers?: boolean
|
||||
interface Props {
|
||||
linux: string
|
||||
mac: string
|
||||
showLineNumbers?: boolean
|
||||
}
|
||||
|
||||
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}`,
|
||||
}
|
||||
}
|
||||
|
||||
function getOS() {
|
||||
var userAgent = window.navigator.userAgent,
|
||||
platform = window.navigator.platform,
|
||||
macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'],
|
||||
windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE'],
|
||||
iosPlatforms = ['iPhone', 'iPad', 'iPod'],
|
||||
os = null;
|
||||
const userAgent = window.navigator.userAgent
|
||||
const platform = window.navigator.platform
|
||||
const macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K']
|
||||
const windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE']
|
||||
const iosPlatforms = ['iPhone', 'iPad', 'iPod']
|
||||
|
||||
if (macosPlatforms.indexOf(platform) !== -1) {
|
||||
os = 'macOS';
|
||||
} else if (iosPlatforms.indexOf(platform) !== -1) {
|
||||
os = 'iOS';
|
||||
} else if (windowsPlatforms.indexOf(platform) !== -1) {
|
||||
os = 'windows';
|
||||
} else if (/Android/.test(userAgent)) {
|
||||
os = 'android';
|
||||
} else if (!os && /Linux/.test(platform)) {
|
||||
os = 'linux';
|
||||
if (macosPlatforms.includes(platform)) return 'macOS'
|
||||
|
||||
if (iosPlatforms.includes(platform)) return 'iOS'
|
||||
|
||||
if (windowsPlatforms.includes(platform)) return 'windows'
|
||||
|
||||
if (/Android/.test(userAgent)) return 'android'
|
||||
|
||||
if (/Linux/.test(platform)) return 'linux'
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export default function CodeBlockTabs(props: Props): ReactElement {
|
||||
const [value, setValue] = React.useState(0)
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<unknown>, newValue: number) => {
|
||||
setValue(newValue)
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
useEffect(() => {
|
||||
const os = getOS()
|
||||
|
||||
export default function CodeBlockTabs(props: IProps) {
|
||||
const [value, setValue] = React.useState(0);
|
||||
if (os === 'windows') {
|
||||
setValue(0)
|
||||
} else if (os === 'linux') {
|
||||
setValue(0)
|
||||
} else if (os === 'macOS') {
|
||||
setValue(1)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let os = getOS()
|
||||
if(os === 'windows') {
|
||||
setValue(0)
|
||||
} else if (os === 'linux') {
|
||||
setValue(0)
|
||||
} else if (os === 'macOS') {
|
||||
setValue(1)
|
||||
}
|
||||
|
||||
}, [])
|
||||
|
||||
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: '-12px' }}>
|
||||
<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} />);
|
||||
function TabPanel(props: TabPanelProps) {
|
||||
const { children, value, index, ...other } = props
|
||||
|
||||
return (
|
||||
<div>
|
||||
<AntTabs style={{ marginTop: '12px' }} value={value} onChange={handleChange} aria-label="ant example">
|
||||
<AntTab label="Linux" {...a11yProps(0)} />
|
||||
<AntTab label="MacOS" {...a11yProps(1)} />
|
||||
</AntTabs>
|
||||
<TabPanel value={value} index={0}>
|
||||
<CodeBlock
|
||||
showLineNumbers={props.showLineNumbers}
|
||||
language='bash'
|
||||
code={props.linux}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel value={value} index={1}>
|
||||
<CodeBlock
|
||||
showLineNumbers={props.showLineNumbers}
|
||||
language='bash'
|
||||
code={props.mac}
|
||||
/>
|
||||
</TabPanel>
|
||||
</div>
|
||||
<div
|
||||
role="tabpanel"
|
||||
hidden={value !== index}
|
||||
id={`simple-tabpanel-${index}`}
|
||||
aria-labelledby={`simple-tab-${index}`}
|
||||
{...other}
|
||||
>
|
||||
{value === index && (
|
||||
<Box style={{ marginTop: '-12px' }}>
|
||||
<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>
|
||||
<AntTabs style={{ marginTop: '12px' }} value={value} onChange={handleChange} aria-label="ant example">
|
||||
<AntTab label="Linux" {...a11yProps(0)} />
|
||||
<AntTab label="MacOS" {...a11yProps(1)} />
|
||||
</AntTabs>
|
||||
<TabPanel value={value} index={0}>
|
||||
<CodeBlock showLineNumbers={props.showLineNumbers} language="bash" code={props.linux} />
|
||||
</TabPanel>
|
||||
<TabPanel value={value} index={1}>
|
||||
<CodeBlock showLineNumbers={props.showLineNumbers} language="bash" code={props.mac} />
|
||||
</TabPanel>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,48 +1,62 @@
|
||||
import React, { useState } from 'react';
|
||||
import { TextField, Button, CircularProgress, Container } from '@material-ui/core';
|
||||
import React, { ReactElement, useState } from 'react'
|
||||
import { TextField, Button, CircularProgress, Container } from '@material-ui/core'
|
||||
|
||||
interface IProps {
|
||||
defaultHost?: string,
|
||||
hostName: string,
|
||||
interface Props {
|
||||
defaultHost?: string
|
||||
hostName: string
|
||||
}
|
||||
|
||||
export default function ConnectToHost(props: IProps) {
|
||||
const [hostInputVisible, toggleHostInputVisibility] = useState(false)
|
||||
const [connectingToHost, setConnectingToHost] = useState(false)
|
||||
const [host, setHost] = useState('')
|
||||
export default function ConnectToHost(props: Props): ReactElement {
|
||||
const [hostInputVisible, toggleHostInputVisibility] = useState(false)
|
||||
const [connectingToHost, setConnectingToHost] = useState(false)
|
||||
const [host, setHost] = useState('')
|
||||
|
||||
const handleNewHostConnection = () => {
|
||||
if (host) {
|
||||
setConnectingToHost(true)
|
||||
sessionStorage.setItem(props.hostName, host)
|
||||
toggleHostInputVisibility(!hostInputVisible)
|
||||
window.location.reload();
|
||||
}
|
||||
const handleNewHostConnection = () => {
|
||||
if (host) {
|
||||
setConnectingToHost(true)
|
||||
sessionStorage.setItem(props.hostName, host)
|
||||
toggleHostInputVisibility(!hostInputVisible)
|
||||
window.location.reload()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{hostInputVisible ?
|
||||
<div style={{display:'flex'}}>
|
||||
<TextField
|
||||
defaultValue={props.defaultHost}
|
||||
label="Enter host"
|
||||
variant="outlined"
|
||||
size='small'
|
||||
onChange={(e) => setHost(e.target.value)}
|
||||
style={{marginRight:'15px', minWidth:'300px'}}
|
||||
/>
|
||||
<Button onClick={() => handleNewHostConnection()} size='small' variant="outlined">Connect</Button>
|
||||
<Button style={{marginLeft:'7px'}} onClick={() => toggleHostInputVisibility(!hostInputVisible)} size='small'>Cancel</Button>
|
||||
</div>
|
||||
:
|
||||
connectingToHost ?
|
||||
<Container style={{textAlign:'center', padding:'0px'}}>
|
||||
<CircularProgress size={20} />
|
||||
</Container>
|
||||
:
|
||||
<Button onClick={() => toggleHostInputVisibility(!hostInputVisible)} size='small' variant="outlined">Change host</Button>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
// FIXME: this should be broken up
|
||||
/* eslint-disable no-nested-ternary */
|
||||
hostInputVisible ? (
|
||||
<div style={{ display: 'flex' }}>
|
||||
<TextField
|
||||
defaultValue={props.defaultHost}
|
||||
label="Enter host"
|
||||
variant="outlined"
|
||||
size="small"
|
||||
onChange={e => setHost(e.target.value)}
|
||||
style={{ marginRight: '15px', minWidth: '300px' }}
|
||||
/>
|
||||
<Button onClick={() => handleNewHostConnection()} size="small" variant="outlined">
|
||||
Connect
|
||||
</Button>
|
||||
<Button
|
||||
style={{ marginLeft: '7px' }}
|
||||
onClick={() => toggleHostInputVisibility(!hostInputVisible)}
|
||||
size="small"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
) : connectingToHost ? (
|
||||
<Container style={{ textAlign: 'center', padding: '0px' }}>
|
||||
<CircularProgress size={20} />
|
||||
</Container>
|
||||
) : (
|
||||
<Button onClick={() => toggleHostInputVisibility(!hostInputVisible)} size="small" variant="outlined">
|
||||
Change host
|
||||
</Button>
|
||||
)
|
||||
/* eslint-enable no-nested-ternary */
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,77 +1,69 @@
|
||||
import React from 'react';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Input from '@material-ui/core/Input';
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import DialogActions from '@material-ui/core/DialogActions';
|
||||
import DialogContent from '@material-ui/core/DialogContent';
|
||||
import DialogContentText from '@material-ui/core/DialogContentText';
|
||||
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||
import { Snackbar } from '@material-ui/core';
|
||||
import React, { ReactElement } from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Input from '@material-ui/core/Input'
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import DialogActions from '@material-ui/core/DialogActions'
|
||||
import DialogContent from '@material-ui/core/DialogContent'
|
||||
import DialogContentText from '@material-ui/core/DialogContentText'
|
||||
import DialogTitle from '@material-ui/core/DialogTitle'
|
||||
import { Snackbar } from '@material-ui/core'
|
||||
|
||||
import { beeDebugApi } from '../services/bee';
|
||||
import { beeDebugApi } from '../services/bee'
|
||||
|
||||
export default function DepositModal() {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const [amount, setAmount] = React.useState(BigInt(0));
|
||||
const [showToast, setToastVisibility] = React.useState(false);
|
||||
const [toastContent, setToastContent] = React.useState('');
|
||||
export default function DepositModal(): ReactElement {
|
||||
const [open, setOpen] = React.useState(false)
|
||||
const [amount, setAmount] = React.useState(BigInt(0))
|
||||
const [showToast, setToastVisibility] = React.useState(false)
|
||||
const [toastContent, setToastContent] = React.useState('')
|
||||
|
||||
const handleClickOpen = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
setOpen(true)
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
const handleWithdraw = () => {
|
||||
if (amount > 0) {
|
||||
beeDebugApi.chequebook.deposit(amount)
|
||||
beeDebugApi.chequebook
|
||||
.deposit(amount)
|
||||
.then(res => {
|
||||
setOpen(false);
|
||||
handleToast(`Successful Deposit. Transaction ${res.transactionHash}`)
|
||||
setOpen(false)
|
||||
handleToast(`Successful Deposit. Transaction ${res.transactionHash}`)
|
||||
})
|
||||
.catch(error => {
|
||||
handleToast('Error with Deposit')
|
||||
.catch(() => {
|
||||
handleToast('Error with Deposit')
|
||||
})
|
||||
} else {
|
||||
handleToast('Must be amount of greater than 0')
|
||||
handleToast('Must be amount of greater than 0')
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleToast = (text: string) => {
|
||||
setToastContent(text)
|
||||
setToastVisibility(true);
|
||||
setTimeout(
|
||||
() => setToastVisibility(false),
|
||||
7000
|
||||
);
|
||||
};
|
||||
setToastVisibility(true)
|
||||
setTimeout(() => setToastVisibility(false), 7000)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button variant="outlined" color="primary" onClick={handleClickOpen} style={{marginLeft:'7px'}}>
|
||||
<Button variant="outlined" color="primary" onClick={handleClickOpen} style={{ marginLeft: '7px' }}>
|
||||
Deposit
|
||||
</Button>
|
||||
<Snackbar
|
||||
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
|
||||
open={showToast}
|
||||
message={toastContent}
|
||||
/>
|
||||
<Snackbar anchorOrigin={{ vertical: 'top', horizontal: 'center' }} open={showToast} message={toastContent} />
|
||||
<Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title">
|
||||
<DialogTitle id="form-dialog-title">Deposit Funds</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
Specify the amount you would like to deposit to your node.
|
||||
</DialogContentText>
|
||||
<DialogContentText>Specify the amount you would like to deposit to your node.</DialogContentText>
|
||||
<Input
|
||||
autoFocus
|
||||
margin="dense"
|
||||
id="name"
|
||||
type="number"
|
||||
placeholder='Amount'
|
||||
placeholder="Amount"
|
||||
fullWidth
|
||||
onChange={(e) => setAmount(BigInt(e.target.value))}
|
||||
onChange={e => setAmount(BigInt(e.target.value))}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
@@ -84,5 +76,5 @@ export default function DepositModal() {
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,54 +1,57 @@
|
||||
import React from 'react';
|
||||
import { Typography } from '@material-ui/core/'
|
||||
import QRCodeModal from './QRCodeModal'
|
||||
import ClipboardCopy from './ClipboardCopy'
|
||||
|
||||
import { Typography } from '@material-ui/core/';
|
||||
import QRCodeModal from './QRCodeModal';
|
||||
import ClipboardCopy from './ClipboardCopy';
|
||||
import Identicon from 'react-identicons'
|
||||
import { ReactElement } from 'react'
|
||||
|
||||
// @ts-ignore
|
||||
import Identicon from 'react-identicons';
|
||||
|
||||
interface IProps {
|
||||
address: string | undefined,
|
||||
network?: string,
|
||||
hideBlockie?: boolean,
|
||||
transaction?: boolean,
|
||||
truncate?: boolean,
|
||||
interface Props {
|
||||
address: string | undefined
|
||||
network?: string
|
||||
hideBlockie?: boolean
|
||||
transaction?: boolean
|
||||
truncate?: boolean
|
||||
}
|
||||
|
||||
export default function EthereumAddress(props: IProps) {
|
||||
return (
|
||||
<Typography component="div" variant="subtitle1">
|
||||
{props.address ?
|
||||
<div style={{display:'flex'}}>
|
||||
{props.hideBlockie ?
|
||||
null
|
||||
:
|
||||
<div style={{paddingTop:'5px', marginRight: '10px', }}>
|
||||
<Identicon size='20' string={props.address} />
|
||||
</div>}
|
||||
<div>
|
||||
<a
|
||||
style={props.truncate ?
|
||||
{ marginRight:'7px', maxWidth:'200px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', display:'block'}
|
||||
:
|
||||
{ marginRight:'7px'}
|
||||
}
|
||||
href={`https://${props.network}.${process.env.REACT_APP_ETHERSCAN_HOST}/${props.transaction ? 'tx' : 'address' }/${props.address}`}
|
||||
target='_blank'
|
||||
rel="noreferrer"
|
||||
>
|
||||
{ props.address }
|
||||
</a>
|
||||
</div>
|
||||
<QRCodeModal
|
||||
value={ props.address }
|
||||
label={'Ethereum Address'}
|
||||
/>
|
||||
<ClipboardCopy
|
||||
value={ props.address }
|
||||
/>
|
||||
export default function EthereumAddress(props: Props): ReactElement {
|
||||
return (
|
||||
<Typography component="div" variant="subtitle1">
|
||||
{props.address ? (
|
||||
<div style={{ display: 'flex' }}>
|
||||
{props.hideBlockie ? null : (
|
||||
<div style={{ paddingTop: '5px', marginRight: '10px' }}>
|
||||
<Identicon size={20} string={props.address} />
|
||||
</div>
|
||||
: '-' }
|
||||
</Typography>
|
||||
)
|
||||
)}
|
||||
<div>
|
||||
<a
|
||||
style={
|
||||
props.truncate
|
||||
? {
|
||||
marginRight: '7px',
|
||||
maxWidth: '200px',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
display: 'block',
|
||||
}
|
||||
: { marginRight: '7px' }
|
||||
}
|
||||
href={`https://${props.network}.${process.env.REACT_APP_ETHERSCAN_HOST}/${
|
||||
props.transaction ? 'tx' : 'address'
|
||||
}/${props.address}`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{props.address}
|
||||
</a>
|
||||
</div>
|
||||
<QRCodeModal value={props.address} label={'Ethereum Address'} />
|
||||
<ClipboardCopy value={props.address} />
|
||||
</div>
|
||||
) : (
|
||||
'-'
|
||||
)}
|
||||
</Typography>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import React from 'react'
|
||||
import React, { ReactElement } from 'react'
|
||||
|
||||
import { Theme, createStyles, makeStyles } from '@material-ui/core/styles';
|
||||
import { Card, CardContent, Typography } from '@material-ui/core/';
|
||||
import { createStyles, makeStyles } from '@material-ui/core/styles'
|
||||
import { Card, CardContent, Typography } from '@material-ui/core/'
|
||||
|
||||
import EthereumAddress from '../components/EthereumAddress';
|
||||
import { Skeleton } from '@material-ui/lab';
|
||||
import EthereumAddress from '../components/EthereumAddress'
|
||||
import { Skeleton } from '@material-ui/lab'
|
||||
|
||||
import type { ChequebookAddressResponse, NodeAddresses } from '@ethersphere/bee-js';
|
||||
import type { ChequebookAddressResponse, NodeAddresses } from '@ethersphere/bee-js'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
const useStyles = makeStyles(() =>
|
||||
createStyles({
|
||||
root: {
|
||||
display: 'flex',
|
||||
@@ -22,58 +22,58 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
flex: '1 0 auto',
|
||||
},
|
||||
status: {
|
||||
color: '#fff',
|
||||
backgroundColor: '#76a9fa',
|
||||
}
|
||||
color: '#fff',
|
||||
backgroundColor: '#76a9fa',
|
||||
},
|
||||
}),
|
||||
);
|
||||
)
|
||||
|
||||
interface IProps{
|
||||
nodeAddresses: NodeAddresses | null,
|
||||
isLoadingNodeAddresses: boolean,
|
||||
chequebookAddress: ChequebookAddressResponse | null,
|
||||
isLoadingChequebookAddress: boolean,
|
||||
interface Props {
|
||||
nodeAddresses: NodeAddresses | null
|
||||
isLoadingNodeAddresses: boolean
|
||||
chequebookAddress: ChequebookAddressResponse | null
|
||||
isLoadingChequebookAddress: boolean
|
||||
}
|
||||
|
||||
function EthereumAddressCard(props: IProps) {
|
||||
const classes = useStyles();
|
||||
function EthereumAddressCard(props: Props): ReactElement {
|
||||
const classes = useStyles()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Card className={classes.root}>
|
||||
{props.isLoadingNodeAddresses ?
|
||||
<div style={{padding: '16px'}}>
|
||||
<Skeleton width={300} height={30} animation="wave" />
|
||||
<Skeleton width={300} height={50} animation="wave" />
|
||||
</div>
|
||||
:
|
||||
<div className={classes.details}>
|
||||
<CardContent className={classes.content}>
|
||||
<Typography variant="subtitle1" gutterBottom>Ethereum Address</Typography>
|
||||
<EthereumAddress
|
||||
address={props.nodeAddresses?.ethereum}
|
||||
network={'goerli'}
|
||||
/>
|
||||
</CardContent>
|
||||
</div>}
|
||||
{props.isLoadingChequebookAddress ?
|
||||
<div style={{padding: '16px'}}>
|
||||
<Skeleton width={300} height={30} animation="wave" />
|
||||
<Skeleton width={300} height={50} animation="wave" />
|
||||
</div>
|
||||
:
|
||||
<div className={classes.details}>
|
||||
<CardContent className={classes.content}>
|
||||
<Typography variant="subtitle1" gutterBottom>Chequebook Contract Address</Typography>
|
||||
<EthereumAddress
|
||||
address={props.chequebookAddress?.chequebookaddress}
|
||||
network={'goerli'}
|
||||
/>
|
||||
</CardContent>
|
||||
</div>}
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<div>
|
||||
<Card className={classes.root}>
|
||||
{props.isLoadingNodeAddresses ? (
|
||||
<div style={{ padding: '16px' }}>
|
||||
<Skeleton width={300} height={30} animation="wave" />
|
||||
<Skeleton width={300} height={50} animation="wave" />
|
||||
</div>
|
||||
) : (
|
||||
<div className={classes.details}>
|
||||
<CardContent className={classes.content}>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
Ethereum Address
|
||||
</Typography>
|
||||
<EthereumAddress address={props.nodeAddresses?.ethereum} network={'goerli'} />
|
||||
</CardContent>
|
||||
</div>
|
||||
)}
|
||||
{props.isLoadingChequebookAddress ? (
|
||||
<div style={{ padding: '16px' }}>
|
||||
<Skeleton width={300} height={30} animation="wave" />
|
||||
<Skeleton width={300} height={50} animation="wave" />
|
||||
</div>
|
||||
) : (
|
||||
<div className={classes.details}>
|
||||
<CardContent className={classes.content}>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
Chequebook Contract Address
|
||||
</Typography>
|
||||
<EthereumAddress address={props.chequebookAddress?.chequebookaddress} network={'goerli'} />
|
||||
</CardContent>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default EthereumAddressCard
|
||||
|
||||
+20
-28
@@ -1,30 +1,31 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useState, ReactElement } from 'react'
|
||||
|
||||
import { createStyles, Theme, makeStyles } from '@material-ui/core/styles';
|
||||
import { Toolbar, Chip, IconButton } from '@material-ui/core/';
|
||||
import { createStyles, makeStyles } from '@material-ui/core/styles'
|
||||
import { Toolbar, Chip, IconButton } from '@material-ui/core/'
|
||||
|
||||
import { Sun, Moon } from 'react-feather';
|
||||
import { Sun, Moon } from 'react-feather'
|
||||
|
||||
const drawerWidth = 240;
|
||||
const drawerWidth = 240
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
const useStyles = makeStyles(() =>
|
||||
createStyles({
|
||||
appBar: {
|
||||
width: `calc(100% - ${drawerWidth}px)`,
|
||||
marginLeft: drawerWidth,
|
||||
},
|
||||
network: {
|
||||
|
||||
}
|
||||
network: {},
|
||||
}),
|
||||
);
|
||||
)
|
||||
interface Props {
|
||||
themeMode: string
|
||||
}
|
||||
|
||||
|
||||
export default function SideBar(props: any) {
|
||||
const [darkMode, toggleDarkMode] = useState(false);
|
||||
export default function SideBar(props: Props): ReactElement {
|
||||
const [darkMode, toggleDarkMode] = useState(false)
|
||||
|
||||
const switchTheme = () => {
|
||||
let theme = localStorage.getItem('theme')
|
||||
const theme = localStorage.getItem('theme')
|
||||
|
||||
if (theme) {
|
||||
localStorage.setItem('theme', theme === 'light' ? 'dark' : 'light')
|
||||
} else {
|
||||
@@ -35,26 +36,17 @@ export default function SideBar(props: any) {
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
const classes = useStyles();
|
||||
const classes = useStyles()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{ display: 'fixed' }} className={classes.appBar}>
|
||||
<Toolbar style={{ display: 'flex' }}>
|
||||
<Chip
|
||||
style={{ marginLeft: '7px' }}
|
||||
size="small"
|
||||
label='Goerli'
|
||||
className={classes.network}
|
||||
/>
|
||||
<Chip style={{ marginLeft: '7px' }} size="small" label="Goerli" className={classes.network} />
|
||||
<div style={{ width: '100%' }}>
|
||||
<div style={{ float: 'right' }} >
|
||||
<div style={{ float: 'right' }}>
|
||||
<IconButton style={{ marginRight: '10px' }} aria-label="dark-mode" onClick={() => switchTheme()}>
|
||||
{props.themeMode === 'dark' ?
|
||||
<Moon />
|
||||
:
|
||||
<Sun />
|
||||
}
|
||||
{props.themeMode === 'dark' ? <Moon /> : <Sun />}
|
||||
</IconButton>
|
||||
{/* <Chip
|
||||
label="Connect Wallet"
|
||||
@@ -65,5 +57,5 @@ export default function SideBar(props: any) {
|
||||
</Toolbar>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
import React,{ useState } from 'react';
|
||||
import QRCode from 'qrcode.react';
|
||||
import { IconButton, Dialog, DialogTitle } from '@material-ui/core';
|
||||
import { FilterCenterFocusSharp } from '@material-ui/icons';
|
||||
import { ReactElement, useState } from 'react'
|
||||
import QRCode from 'qrcode.react'
|
||||
import { IconButton, Dialog, DialogTitle } from '@material-ui/core'
|
||||
import { FilterCenterFocusSharp } from '@material-ui/icons'
|
||||
|
||||
interface IProps {
|
||||
value: string,
|
||||
label: string,
|
||||
interface Props {
|
||||
value: string
|
||||
label: string
|
||||
}
|
||||
|
||||
export default function QRCodeModal(props: IProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleOpen = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<IconButton color="primary" size='small' onClick={handleOpen}>
|
||||
<FilterCenterFocusSharp/>
|
||||
</IconButton>
|
||||
<Dialog onClose={handleClose} aria-labelledby="simple-dialog-title" open={open}>
|
||||
<div style={{padding: '30px', textAlign: 'center'}}>
|
||||
<DialogTitle id="simple-dialog-title">{ props.label }</DialogTitle>
|
||||
<QRCode
|
||||
value={props.value}
|
||||
size={150}
|
||||
bgColor={"#ffffff"}
|
||||
fgColor={"#000000"}
|
||||
level={"L"}
|
||||
includeMargin={false}
|
||||
renderAs={"svg"}
|
||||
/>
|
||||
</div>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
export default function QRCodeModal(props: Props): ReactElement {
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
const handleOpen = () => {
|
||||
setOpen(true)
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<IconButton color="primary" size="small" onClick={handleOpen}>
|
||||
<FilterCenterFocusSharp />
|
||||
</IconButton>
|
||||
<Dialog onClose={handleClose} aria-labelledby="simple-dialog-title" open={open}>
|
||||
<div style={{ padding: '30px', textAlign: 'center' }}>
|
||||
<DialogTitle id="simple-dialog-title">{props.label}</DialogTitle>
|
||||
<QRCode
|
||||
value={props.value}
|
||||
size={150}
|
||||
bgColor={'#ffffff'}
|
||||
fgColor={'#000000'}
|
||||
level={'L'}
|
||||
includeMargin={false}
|
||||
renderAs={'svg'}
|
||||
/>
|
||||
</div>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles';
|
||||
import { Paper, InputBase, IconButton } from '@material-ui/core';
|
||||
import { Search } from '@material-ui/icons';
|
||||
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'
|
||||
import { Paper, InputBase, IconButton } from '@material-ui/core'
|
||||
import { Search } from '@material-ui/icons'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -24,27 +24,23 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
margin: 4,
|
||||
},
|
||||
}),
|
||||
);
|
||||
)
|
||||
|
||||
interface IProps {
|
||||
export default function SearchBar() {
|
||||
const classes = useStyles()
|
||||
|
||||
}
|
||||
|
||||
export default function SearchBar(props: IProps) {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Paper component="form" className={classes.root}>
|
||||
<InputBase
|
||||
className={classes.input}
|
||||
placeholder="Enter hash e.g. 0773a91efd6547c754fc1d95fb1c62c7d1b47f959c2caa685dfec8736da95c1c"
|
||||
inputProps={{ 'aria-label': 'search google maps' }}
|
||||
/>
|
||||
<IconButton type="submit" className={classes.iconButton} aria-label="search">
|
||||
<Search />
|
||||
</IconButton>
|
||||
</Paper>
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<div>
|
||||
<Paper component="form" className={classes.root}>
|
||||
<InputBase
|
||||
className={classes.input}
|
||||
placeholder="Enter hash e.g. 0773a91efd6547c754fc1d95fb1c62c7d1b47f959c2caa685dfec8736da95c1c"
|
||||
inputProps={{ 'aria-label': 'search google maps' }}
|
||||
/>
|
||||
<IconButton type="submit" className={classes.iconButton} aria-label="search">
|
||||
<Search />
|
||||
</IconButton>
|
||||
</Paper>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
+75
-53
@@ -1,46 +1,47 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ReactElement } from 'react'
|
||||
import { Link, RouteComponentProps } from 'react-router-dom'
|
||||
|
||||
import { createStyles, Theme, makeStyles } from '@material-ui/core/styles';
|
||||
import { ListItemText, ListItemIcon, ListItem, Divider, List, Drawer, Link as MUILink } from '@material-ui/core';
|
||||
import { OpenInNewSharp } from '@material-ui/icons';
|
||||
import { Activity, FileText, DollarSign, Share2, Settings } from 'react-feather';
|
||||
import { createStyles, Theme, makeStyles } from '@material-ui/core/styles'
|
||||
import { ListItemText, ListItemIcon, ListItem, Divider, List, Drawer, Link as MUILink } from '@material-ui/core'
|
||||
import { OpenInNewSharp } from '@material-ui/icons'
|
||||
import { Activity, FileText, DollarSign, Share2, Settings } from 'react-feather'
|
||||
|
||||
import SwarmLogoOrange from '../assets/swarm-logo-orange.svg'
|
||||
import { Health } from '@ethersphere/bee-js'
|
||||
|
||||
const drawerWidth = 240;
|
||||
const drawerWidth = 240
|
||||
|
||||
const navBarItems = [
|
||||
{
|
||||
'label': 'Status',
|
||||
'id': 'status',
|
||||
'path': '/',
|
||||
'icon': 'activity'
|
||||
label: 'Status',
|
||||
id: 'status',
|
||||
path: '/',
|
||||
icon: Activity,
|
||||
},
|
||||
{
|
||||
'label': 'Files',
|
||||
'id': 'files',
|
||||
'path': '/files/',
|
||||
'icon': 'file-text'
|
||||
label: 'Files',
|
||||
id: 'files',
|
||||
path: '/files/',
|
||||
icon: FileText,
|
||||
},
|
||||
{
|
||||
'label': 'Accounting',
|
||||
'id': 'accounting',
|
||||
'path': '/accounting/',
|
||||
'icon': 'dollar-sign'
|
||||
label: 'Accounting',
|
||||
id: 'accounting',
|
||||
path: '/accounting/',
|
||||
icon: DollarSign,
|
||||
},
|
||||
{
|
||||
'label': 'Peers',
|
||||
'id': 'peers',
|
||||
'path': '/peers/',
|
||||
'icon': 'share-2'
|
||||
label: 'Peers',
|
||||
id: 'peers',
|
||||
path: '/peers/',
|
||||
icon: Share2,
|
||||
},
|
||||
{
|
||||
'label': 'Settings',
|
||||
'id': 'settings',
|
||||
'path': '/settings/',
|
||||
'icon': 'settings'
|
||||
}
|
||||
label: 'Settings',
|
||||
id: 'settings',
|
||||
path: '/settings/',
|
||||
icon: Settings,
|
||||
},
|
||||
]
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
@@ -68,29 +69,20 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
},
|
||||
activeSideBarItem: {
|
||||
borderLeft: '4px solid #dd7700',
|
||||
backgroundColor: 'inherit !important'
|
||||
backgroundColor: 'inherit !important',
|
||||
},
|
||||
toolbar: theme.mixins.toolbar,
|
||||
}),
|
||||
);
|
||||
)
|
||||
|
||||
const getIcon = (iconPath: string) => {
|
||||
switch (iconPath) {
|
||||
case 'activity':
|
||||
return <Activity style={{ height: '20px' }} />
|
||||
case 'file-text':
|
||||
return <FileText style={{ height: '20px' }} />
|
||||
case 'dollar-sign':
|
||||
return <DollarSign style={{ height: '20px' }} />
|
||||
case 'share-2':
|
||||
return <Share2 style={{ height: '20px' }} />
|
||||
case 'settings':
|
||||
return <Settings style={{ height: '20px' }} />
|
||||
}
|
||||
interface Props extends RouteComponentProps {
|
||||
themeMode: string
|
||||
health: boolean
|
||||
nodeHealth: Health | null
|
||||
}
|
||||
|
||||
export default function SideBar(props: any) {
|
||||
const classes = useStyles();
|
||||
export default function SideBar(props: Props): ReactElement {
|
||||
const classes = useStyles()
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
@@ -103,18 +95,30 @@ export default function SideBar(props: any) {
|
||||
anchor="left"
|
||||
>
|
||||
<div className={classes.toolbar} style={{ textAlign: 'left', marginLeft: 20 }}>
|
||||
<Link to='/'>
|
||||
<img alt='swarm' className={classes.logo} src={props.themeMode === 'light' ? SwarmLogoOrange : SwarmLogoOrange} style={{ maxHeight: '30px', alignItems: 'center' }} />
|
||||
<Link to="/">
|
||||
<img
|
||||
alt="swarm"
|
||||
className={classes.logo}
|
||||
src={props.themeMode === 'light' ? SwarmLogoOrange : SwarmLogoOrange}
|
||||
style={{ maxHeight: '30px', alignItems: 'center' }}
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
<List>
|
||||
{navBarItems.map(item => (
|
||||
<Link to={item.path} key={item.id} style={{ color: 'inherit', textDecoration: 'none' }}>
|
||||
<ListItem button selected={props.location.pathname === item.path} className={props.location.pathname === item.path ? classes.activeSideBarItem : ''}>
|
||||
<ListItem
|
||||
button
|
||||
selected={props.location.pathname === item.path}
|
||||
className={props.location.pathname === item.path ? classes.activeSideBarItem : ''}
|
||||
>
|
||||
<ListItemIcon className={props.location.pathname === item.path ? classes.activeSideBar : ''}>
|
||||
{getIcon(item.icon)}
|
||||
<item.icon style={{ height: '20px' }} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={item.label} className={props.location.pathname === item.path ? classes.activeSideBar : ''} />
|
||||
<ListItemText
|
||||
primary={item.label}
|
||||
className={props.location.pathname === item.path ? classes.activeSideBar : ''}
|
||||
/>
|
||||
</ListItem>
|
||||
</Link>
|
||||
))}
|
||||
@@ -131,16 +135,34 @@ export default function SideBar(props: any) {
|
||||
<div style={{ position: 'fixed', bottom: 0, width: 'inherit', padding: '10px' }}>
|
||||
<ListItem>
|
||||
<div style={{ marginRight: '30px' }}>
|
||||
<div style={{ backgroundColor: props.health ? '#32c48d' : '#c9201f', marginRight: '7px', height: '10px', width: '10px', borderRadius: '50%', display: 'inline-block' }} />
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: props.health ? '#32c48d' : '#c9201f',
|
||||
marginRight: '7px',
|
||||
height: '10px',
|
||||
width: '10px',
|
||||
borderRadius: '50%',
|
||||
display: 'inline-block',
|
||||
}}
|
||||
/>
|
||||
<span>API</span>
|
||||
</div>
|
||||
<div>
|
||||
<div style={{ backgroundColor: props.nodeHealth?.status === 'ok' ? '#32c48d' : '#c9201f', marginRight: '7px', height: '10px', width: '10px', borderRadius: '50%', display: 'inline-block' }} />
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: props.nodeHealth?.status === 'ok' ? '#32c48d' : '#c9201f',
|
||||
marginRight: '7px',
|
||||
height: '10px',
|
||||
width: '10px',
|
||||
borderRadius: '50%',
|
||||
display: 'inline-block',
|
||||
}}
|
||||
/>
|
||||
<span>Debug API</span>
|
||||
</div>
|
||||
</ListItem>
|
||||
</div>
|
||||
</Drawer>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
+42
-45
@@ -1,53 +1,50 @@
|
||||
import React from 'react'
|
||||
import type { ReactElement } from 'react'
|
||||
|
||||
import { makeStyles, } from '@material-ui/core/styles';
|
||||
import { Card, CardContent, Typography } from '@material-ui/core/';
|
||||
import { Skeleton } from '@material-ui/lab';
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import { Card, CardContent, Typography } from '@material-ui/core/'
|
||||
import { Skeleton } from '@material-ui/lab'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
root: {
|
||||
minWidth: 275,
|
||||
},
|
||||
title: {
|
||||
fontSize: 16,
|
||||
},
|
||||
pos: {
|
||||
marginBottom: 12,
|
||||
},
|
||||
});
|
||||
root: {
|
||||
minWidth: 275,
|
||||
},
|
||||
title: {
|
||||
fontSize: 16,
|
||||
},
|
||||
pos: {
|
||||
marginBottom: 12,
|
||||
},
|
||||
})
|
||||
|
||||
interface IProps {
|
||||
label: string
|
||||
statistic?: string
|
||||
loading?: boolean
|
||||
interface Props {
|
||||
label: string
|
||||
statistic?: string
|
||||
loading?: boolean
|
||||
}
|
||||
|
||||
export default function StatCard({loading, label, statistic}: IProps) {
|
||||
const classes = useStyles();
|
||||
export default function StatCard({ loading, label, statistic }: Props): ReactElement {
|
||||
const classes = useStyles()
|
||||
|
||||
|
||||
return (
|
||||
<Card className={classes.root}>
|
||||
<CardContent>
|
||||
{loading && (
|
||||
<>
|
||||
<Skeleton width={180} height={25} animation="wave" />
|
||||
<Skeleton width={180} height={35} animation="wave" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
{!loading && (
|
||||
<>
|
||||
<Typography className={classes.title} color="textSecondary" gutterBottom>
|
||||
{label}
|
||||
</Typography>
|
||||
<Typography variant="h5" component="h2">
|
||||
{statistic}
|
||||
</Typography>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
return (
|
||||
<Card className={classes.root}>
|
||||
<CardContent>
|
||||
{loading && (
|
||||
<>
|
||||
<Skeleton width={180} height={25} animation="wave" />
|
||||
<Skeleton width={180} height={35} animation="wave" />
|
||||
</>
|
||||
)}
|
||||
{!loading && (
|
||||
<>
|
||||
<Typography className={classes.title} color="textSecondary" gutterBottom>
|
||||
{label}
|
||||
</Typography>
|
||||
<Typography variant="h5" component="h2">
|
||||
{statistic}
|
||||
</Typography>
|
||||
</>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,39 +1,28 @@
|
||||
import type { Topology } from '@ethersphere/bee-js';
|
||||
import { Grid } from '@material-ui/core/';
|
||||
import StatCard from './StatCard';
|
||||
import type { Topology } from '@ethersphere/bee-js'
|
||||
import { Grid } from '@material-ui/core/'
|
||||
import type { ReactElement } from 'react'
|
||||
import StatCard from './StatCard'
|
||||
|
||||
interface Props {
|
||||
isLoading: boolean
|
||||
topology: Topology | null
|
||||
error: Error | null // FIXME: should display error
|
||||
isLoading: boolean
|
||||
topology: Topology | null
|
||||
error: Error | null // FIXME: should display error
|
||||
}
|
||||
|
||||
const TopologyStats = ({isLoading, topology, error}: Props) => (
|
||||
<Grid style={{ marginBottom: '20px', flexGrow: 1 }}>
|
||||
<Grid container spacing={3}>
|
||||
<Grid key={1} item xs={12} sm={12} md={6} lg={4} xl={4}>
|
||||
<StatCard
|
||||
label='Connected Peers'
|
||||
statistic={topology?.connected.toString()}
|
||||
loading={isLoading}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid key={2} item xs={12} sm={12} md={6} lg={4} xl={4}>
|
||||
<StatCard
|
||||
label='Population'
|
||||
statistic={topology?.population.toString()}
|
||||
loading={isLoading}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid key={3} item xs={12} sm={12} md={6} lg={4} xl={4}>
|
||||
<StatCard
|
||||
label='Depth'
|
||||
statistic={topology?.depth.toString()}
|
||||
loading={isLoading}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
const TopologyStats = ({ isLoading, topology }: Props): ReactElement => (
|
||||
<Grid style={{ marginBottom: '20px', flexGrow: 1 }}>
|
||||
<Grid container spacing={3}>
|
||||
<Grid key={1} item xs={12} sm={12} md={6} lg={4} xl={4}>
|
||||
<StatCard label="Connected Peers" statistic={topology?.connected.toString()} loading={isLoading} />
|
||||
</Grid>
|
||||
<Grid key={2} item xs={12} sm={12} md={6} lg={4} xl={4}>
|
||||
<StatCard label="Population" statistic={topology?.population.toString()} loading={isLoading} />
|
||||
</Grid>
|
||||
<Grid key={3} item xs={12} sm={12} md={6} lg={4} xl={4}>
|
||||
<StatCard label="Depth" statistic={topology?.depth.toString()} loading={isLoading} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
|
||||
export default TopologyStats
|
||||
|
||||
@@ -1,39 +1,47 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import type { ReactElement } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import { makeStyles, } from '@material-ui/core/styles';
|
||||
import { Card, CardContent, Typography } from '@material-ui/core/';
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import { Card, CardContent, Typography } from '@material-ui/core/'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
root: {
|
||||
flexGrow: 1,
|
||||
marginTop: '20px'
|
||||
},
|
||||
title: {
|
||||
textAlign:'center',
|
||||
fontSize: 26,
|
||||
},
|
||||
});
|
||||
root: {
|
||||
flexGrow: 1,
|
||||
marginTop: '20px',
|
||||
},
|
||||
title: {
|
||||
textAlign: 'center',
|
||||
fontSize: 26,
|
||||
},
|
||||
})
|
||||
|
||||
export default function TroubleshootConnectionCard(): ReactElement {
|
||||
const classes = useStyles()
|
||||
|
||||
export default function TroubleshootConnectionCard() {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<Card className={classes.root}>
|
||||
<CardContent>
|
||||
<Typography className={classes.title} gutterBottom>
|
||||
Looks like your node is not connected
|
||||
</Typography>
|
||||
<div style={{ marginBottom: '20px', textAlign: 'center' }}>
|
||||
<strong>
|
||||
<Link to="/">Click to run status checks</Link> on your nodes connection or check out the{' '}
|
||||
<a href={process.env.REACT_APP_BEE_DOCS_HOST} target="_blank" rel="noreferrer">
|
||||
Swarm Bee Docs
|
||||
</a>
|
||||
</strong>
|
||||
</div>
|
||||
|
||||
return (
|
||||
<Card className={classes.root}>
|
||||
<CardContent>
|
||||
<Typography className={classes.title} gutterBottom>
|
||||
Looks like your node is not connected
|
||||
</Typography>
|
||||
<div style={{marginBottom:'20px', textAlign:'center'}}>
|
||||
<strong><Link to='/' >Click to run status checks</Link> on your nodes connection or check out the <a href={process.env.REACT_APP_BEE_DOCS_HOST} target='_blank' rel="noreferrer">Swarm Bee Docs</a></strong>
|
||||
</div>
|
||||
|
||||
<div style={{marginBottom:'20px', textAlign:'center'}}>
|
||||
<p style={{marginTop:'50px'}}>Still not working? Drop us a message on the Ethereum Swarm <a href={process.env.REACT_APP_BEE_DISCORD_HOST} target='_blank' rel="noreferrer">Discord</a></p>
|
||||
</div>
|
||||
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
<div style={{ marginBottom: '20px', textAlign: 'center' }}>
|
||||
<p style={{ marginTop: '50px' }}>
|
||||
Still not working? Drop us a message on the Ethereum Swarm{' '}
|
||||
<a href={process.env.REACT_APP_BEE_DISCORD_HOST} target="_blank" rel="noreferrer">
|
||||
Discord
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,77 +1,70 @@
|
||||
import React from 'react';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Input from '@material-ui/core/Input';
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import DialogActions from '@material-ui/core/DialogActions';
|
||||
import DialogContent from '@material-ui/core/DialogContent';
|
||||
import DialogContentText from '@material-ui/core/DialogContentText';
|
||||
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||
import { Snackbar } from '@material-ui/core';
|
||||
import { ReactElement, useState } from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Input from '@material-ui/core/Input'
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import DialogActions from '@material-ui/core/DialogActions'
|
||||
import DialogContent from '@material-ui/core/DialogContent'
|
||||
import DialogContentText from '@material-ui/core/DialogContentText'
|
||||
import DialogTitle from '@material-ui/core/DialogTitle'
|
||||
import { Snackbar } from '@material-ui/core'
|
||||
|
||||
import { beeDebugApi } from '../services/bee';
|
||||
import { beeDebugApi } from '../services/bee'
|
||||
|
||||
export default function WithdrawlModal() {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const [amount, setAmount] = React.useState(BigInt(0));
|
||||
const [showToast, setToastVisibility] = React.useState(false);
|
||||
const [toastContent, setToastContent] = React.useState('');
|
||||
export default function WithdrawlModal(): ReactElement {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [amount, setAmount] = useState(BigInt(0))
|
||||
const [showToast, setToastVisibility] = useState(false)
|
||||
const [toastContent, setToastContent] = useState('')
|
||||
|
||||
const handleClickOpen = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
setOpen(true)
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
const handleWithdraw = () => {
|
||||
if (amount > 0) {
|
||||
beeDebugApi.chequebook.withdraw(amount)
|
||||
beeDebugApi.chequebook
|
||||
.withdraw(amount)
|
||||
.then(res => {
|
||||
setOpen(false);
|
||||
handleToast(`Successful withdrawl. Transaction ${res.transactionHash}`)
|
||||
setOpen(false)
|
||||
handleToast(`Successful withdrawl. Transaction ${res.transactionHash}`)
|
||||
})
|
||||
.catch(error => {
|
||||
handleToast('Error with withdrawl')
|
||||
.catch(() => {
|
||||
// FIXME: should probably detail the error
|
||||
handleToast('Error with withdrawing')
|
||||
})
|
||||
} else {
|
||||
handleToast('Must be amount of greater than 0')
|
||||
handleToast('Must be amount of greater than 0')
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleToast = (text: string) => {
|
||||
setToastContent(text)
|
||||
setToastVisibility(true);
|
||||
setTimeout(
|
||||
() => setToastVisibility(false),
|
||||
7000
|
||||
);
|
||||
};
|
||||
setToastVisibility(true)
|
||||
setTimeout(() => setToastVisibility(false), 7000)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button variant="outlined" color="primary" onClick={handleClickOpen}>
|
||||
Withdraw
|
||||
</Button>
|
||||
<Snackbar
|
||||
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
|
||||
open={showToast}
|
||||
message={toastContent}
|
||||
/>
|
||||
<Snackbar anchorOrigin={{ vertical: 'top', horizontal: 'center' }} open={showToast} message={toastContent} />
|
||||
<Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title">
|
||||
<DialogTitle id="form-dialog-title">Withdraw Funds</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
Specify the amount you would like to withdraw from your node.
|
||||
</DialogContentText>
|
||||
<DialogContentText>Specify the amount you would like to withdraw from your node.</DialogContentText>
|
||||
<Input
|
||||
autoFocus
|
||||
margin="dense"
|
||||
id="name"
|
||||
type="number"
|
||||
placeholder='Amount'
|
||||
placeholder="Amount"
|
||||
fullWidth
|
||||
onChange={(e) => setAmount(BigInt(e.target.value))}
|
||||
onChange={e => setAmount(BigInt(e.target.value))}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
@@ -84,5 +77,5 @@ export default function WithdrawlModal() {
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user