feat: polish app (#669)
This commit is contained in:
+1
-2
@@ -9,7 +9,6 @@
|
||||
"file-loader",
|
||||
"ts-node",
|
||||
"webpack-cli",
|
||||
"assert",
|
||||
"buffer",
|
||||
"crypto*",
|
||||
"stream*",
|
||||
@@ -17,4 +16,4 @@
|
||||
"open",
|
||||
"base64-inline-loader"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,8 @@
|
||||
**Warning: This project is in alpha state. There might (and most probably will) be changes in the future to its API and
|
||||
working. Also, no guarantees can be made about its stability, efficiency, and security at this stage.**
|
||||
|
||||
This project is intended to be used with \*\*Bee version
|
||||
|
||||
<!-- SUPPORTED_BEE_START -->1.12.0-88c1d236<!-- SUPPORTED_BEE_END -->**. Using it with older or newer Bee versions is
|
||||
|
||||
not recommended and may not work. Stay up to date by joining the [official Discord](https://discord.gg/GU22h2utj6) and
|
||||
by keeping an eye on the [releases tab](https://github.com/ethersphere/bee-dashboard/releases).
|
||||
Stay up to date by joining the [official Discord](https://discord.gg/GU22h2utj6) and by keeping an eye on the
|
||||
[releases tab](https://github.com/ethersphere/bee-dashboard/releases).
|
||||
|
||||

|
||||
|
||||
|
||||
Generated
+203
-366
File diff suppressed because it is too large
Load Diff
+5
-6
@@ -26,14 +26,13 @@
|
||||
"url": "https://github.com/ethersphere/bee-dashboard.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ethersphere/bee-js": "^7.0.3",
|
||||
"@ethersphere/bee-js": "^7.1.0",
|
||||
"@ethersphere/swarm-cid": "^0.1.0",
|
||||
"@material-ui/core": "4.12.3",
|
||||
"@material-ui/icons": "4.11.2",
|
||||
"@material-ui/lab": "4.0.0-alpha.57",
|
||||
"assert": "^2.0.0",
|
||||
"axios": "0.24.0",
|
||||
"bignumber.js": "9.0.1",
|
||||
"axios": "^0.28.1",
|
||||
"bignumber.js": "^9.1.2",
|
||||
"buffer": "^6.0.3",
|
||||
"crypto": "npm:crypto-browserify",
|
||||
"crypto-browserify": "^3.12.0",
|
||||
@@ -42,10 +41,10 @@
|
||||
"file-saver": "^2.0.5",
|
||||
"formik": "2.2.9",
|
||||
"formik-material-ui": "3.0.1",
|
||||
"jszip": "^3.7.1",
|
||||
"jszip": "^3.10.1",
|
||||
"mantaray-js": "^1.0.3",
|
||||
"material-ui-dropzone": "3.5.0",
|
||||
"notistack": "1.0.10",
|
||||
"notistack": "^3.0.1",
|
||||
"opener": "1.5.2",
|
||||
"qrcode.react": "1.0.1",
|
||||
"react": ">= 17.0.2",
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ChainState } from '@ethersphere/bee-js'
|
||||
import { useContext, useEffect, useState } from 'react'
|
||||
import { Context } from '../providers/Settings'
|
||||
import ExpandableListItem from './ExpandableListItem'
|
||||
|
||||
export function ChainSync() {
|
||||
const { beeApi } = useContext(Context)
|
||||
const [chainState, setChainState] = useState<ChainState | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
if (!beeApi) {
|
||||
return
|
||||
}
|
||||
|
||||
beeApi.getChainState().then(setChainState).catch(console.error) // eslint-disable-line
|
||||
}, 3_000)
|
||||
|
||||
return () => clearInterval(interval)
|
||||
})
|
||||
|
||||
return (
|
||||
<ExpandableListItem label="Chain state" value={chainState ? `${chainState.block} / ${chainState.chainTip}` : '-'} />
|
||||
)
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Utils } from '@ethersphere/bee-js'
|
||||
import { Typography } from '@material-ui/core/'
|
||||
import { ReactElement } from 'react'
|
||||
import Identicon from 'react-identicons'
|
||||
import ClipboardCopy from './ClipboardCopy'
|
||||
import QRCodeModal from './QRCodeModal'
|
||||
import { BLOCKCHAIN_EXPLORER_URL } from '../constants'
|
||||
import ClipboardCopy from './ClipboardCopy'
|
||||
import { Flex } from './Flex'
|
||||
import QRCodeModal from './QRCodeModal'
|
||||
|
||||
interface Props {
|
||||
address: string | undefined
|
||||
@@ -16,10 +18,10 @@ export default function EthereumAddress(props: Props): ReactElement {
|
||||
return (
|
||||
<Typography component="div" variant="subtitle1">
|
||||
{props.address ? (
|
||||
<div style={{ display: 'flex' }}>
|
||||
<Flex>
|
||||
{props.hideBlockie ? null : (
|
||||
<div style={{ paddingTop: '5px', marginRight: '10px' }}>
|
||||
<Identicon size={20} string={props.address} />
|
||||
<Identicon size={20} string={Utils.capitalizeAddressERC55(props.address)} />
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
@@ -43,9 +45,9 @@ export default function EthereumAddress(props: Props): ReactElement {
|
||||
{props.address}
|
||||
</a>
|
||||
</div>
|
||||
<QRCodeModal value={props.address} label={'Ethereum Address'} />
|
||||
<ClipboardCopy value={props.address} />
|
||||
</div>
|
||||
<QRCodeModal value={Utils.capitalizeAddressERC55(props.address)} label={'Ethereum Address'} />
|
||||
<ClipboardCopy value={Utils.capitalizeAddressERC55(props.address)} />
|
||||
</Flex>
|
||||
) : (
|
||||
'-'
|
||||
)}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { ReactElement, ReactNode, useState } from 'react'
|
||||
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'
|
||||
import { Collapse, ListItem, ListItemText, Typography } from '@material-ui/core'
|
||||
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
|
||||
import { ExpandLess, ExpandMore } from '@material-ui/icons'
|
||||
import { ReactElement, ReactNode, useState } from 'react'
|
||||
import { Flex } from './Flex'
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -65,14 +66,14 @@ export default function ExpandableList({ children, label, level, defaultOpen, in
|
||||
<div className={`${classes.root} ${rootLevelClass}`}>
|
||||
<ListItem button onClick={handleClick} className={classes.header}>
|
||||
<ListItemText primary={<Typography variant={typographyVariant}>{label}</Typography>} />
|
||||
<div style={{ display: 'flex' }}>
|
||||
<Flex>
|
||||
{!open && (
|
||||
<Typography variant="body2" className={classes.infoText}>
|
||||
{info}
|
||||
</Typography>
|
||||
)}
|
||||
{open ? <ExpandLess /> : <ExpandMore />}
|
||||
</div>
|
||||
</Flex>
|
||||
</ListItem>
|
||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||
<div className={contentLevelClass}>{children}</div>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { ReactNode } from 'react'
|
||||
|
||||
interface Props {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export function Flex({ children }: Props) {
|
||||
return <div style={{ display: 'flex' }}>{children}</div>
|
||||
}
|
||||
@@ -133,7 +133,7 @@ export default function SideBar(): ReactElement {
|
||||
<SideBarItem
|
||||
iconStart={<GithubIcon className={classes.icon} />}
|
||||
iconEnd={<ExternalLinkIcon className={classes.icon} color="#595959" />}
|
||||
label={<span>Github repository</span>}
|
||||
label={<span>GitHub</span>}
|
||||
/>
|
||||
</MUILink>
|
||||
</List>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useSnackbar } from 'notistack'
|
||||
import React, { ReactElement, useContext, useEffect } from 'react'
|
||||
import CloseIcon from 'remixicon-react/CloseCircleLineIcon'
|
||||
import ErrorBoundary from '../components/ErrorBoundary'
|
||||
import { Flex } from '../components/Flex'
|
||||
import SideBar from '../components/SideBar'
|
||||
import { BEE_DESKTOP_LATEST_RELEASE_PAGE } from '../constants'
|
||||
import { useBeeDesktop, useNewBeeDesktopVersion } from '../hooks/apiHooks'
|
||||
@@ -81,13 +82,13 @@ const Dashboard = (props: Props): ReactElement => {
|
||||
)
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex' }}>
|
||||
<Flex>
|
||||
<SideBar />
|
||||
<Container className={classes.content}>
|
||||
{' '}
|
||||
<ErrorBoundary errorReporting={props.errorReporting}>{content}</ErrorBoundary>
|
||||
</Container>
|
||||
</div>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+8
-7
@@ -81,17 +81,18 @@ export class Token {
|
||||
return asString.slice(0, indexOfSignificantDigit + digits)
|
||||
}
|
||||
|
||||
minusBaseUnits(amount: string): Token {
|
||||
minusBaseUnits(amount: string | BigNumber | bigint): Token {
|
||||
const baseUnits = makeBigNumber(amount)
|
||||
|
||||
return new Token(
|
||||
this.toBigNumber.minus(new BigNumber(amount).multipliedBy(new BigNumber(10).pow(this.decimals))),
|
||||
this.toBigNumber.minus(baseUnits.multipliedBy(new BigNumber(10).pow(this.decimals))),
|
||||
this.decimals,
|
||||
)
|
||||
}
|
||||
|
||||
plusBaseUnits(amount: string): Token {
|
||||
return new Token(
|
||||
this.toBigNumber.plus(new BigNumber(amount).multipliedBy(new BigNumber(10).pow(this.decimals))),
|
||||
this.decimals,
|
||||
)
|
||||
plusBaseUnits(amount: string | BigNumber | bigint): Token {
|
||||
const baseUnits = makeBigNumber(amount)
|
||||
|
||||
return new Token(this.toBigNumber.plus(baseUnits.multipliedBy(new BigNumber(10).pow(this.decimals))), this.decimals)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Utils } from '@ethersphere/bee-js'
|
||||
import { Box } from '@material-ui/core'
|
||||
import { ReactElement, useContext } from 'react'
|
||||
import ExpandableList from '../../../components/ExpandableList'
|
||||
@@ -57,7 +58,10 @@ export function AccountChequebook(): ReactElement {
|
||||
</ExpandableList>
|
||||
)}
|
||||
<ExpandableList label="Blockchain" defaultOpen>
|
||||
<ExpandableListItemKey label="Ethereum address" value={nodeAddresses?.ethereum || ''} />
|
||||
<ExpandableListItemKey
|
||||
label="Ethereum address"
|
||||
value={nodeAddresses?.ethereum ? Utils.capitalizeAddressERC55(nodeAddresses.ethereum) : ''}
|
||||
/>
|
||||
<ExpandableListItemKey
|
||||
label="Chequebook contract address"
|
||||
value={chequebookAddress?.chequebookAddress || ''}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BeeModes } from '@ethersphere/bee-js'
|
||||
import { BeeModes, Utils } from '@ethersphere/bee-js'
|
||||
import { Box, Grid, Typography } from '@material-ui/core'
|
||||
import { ReactElement, useContext } from 'react'
|
||||
import { useNavigate } from 'react-router'
|
||||
@@ -26,7 +26,7 @@ export function AccountWallet(): ReactElement {
|
||||
const navigate = useNavigate()
|
||||
|
||||
function onCheckTransactions() {
|
||||
window.open(`https://blockscout.com/xdai/mainnet/address/${nodeAddresses?.ethereum}/transactions`, '_blank')
|
||||
window.open(`https://gnosisscan.io/address/${nodeAddresses?.ethereum}`, '_blank')
|
||||
}
|
||||
|
||||
function onInvite() {
|
||||
@@ -56,7 +56,11 @@ export function AccountWallet(): ReactElement {
|
||||
{balance && nodeAddresses ? (
|
||||
<>
|
||||
<Box mb={0.25}>
|
||||
<ExpandableListItemKey label="Node wallet address" value={nodeAddresses.ethereum} expanded />
|
||||
<ExpandableListItemKey
|
||||
label="Node wallet address"
|
||||
value={Utils.capitalizeAddressERC55(nodeAddresses.ethereum)}
|
||||
expanded
|
||||
/>
|
||||
</Box>
|
||||
<Box mb={0.25}>
|
||||
<ExpandableListItem label="xDAI balance" value={`${balance.dai.toSignificantDigits(4)} xDAI`} />
|
||||
@@ -72,7 +76,7 @@ export function AccountWallet(): ReactElement {
|
||||
)}
|
||||
<ExpandableListItemActions>
|
||||
<SwarmButton onClick={onCheckTransactions} iconType={Link}>
|
||||
Check transactions on Blockscout
|
||||
Check transactions
|
||||
</SwarmButton>
|
||||
{isDesktop && (
|
||||
<SwarmButton onClick={onInvite} iconType={Gift}>
|
||||
|
||||
@@ -17,12 +17,12 @@ export function ChequebookInfoCard() {
|
||||
<Card
|
||||
buttonProps={{
|
||||
iconType: ExchangeFunds,
|
||||
children: 'View chequebook',
|
||||
children: 'Manage chequebook',
|
||||
onClick: () => navigate(ROUTES.ACCOUNT_CHEQUEBOOK),
|
||||
}}
|
||||
icon={<ExchangeFunds />}
|
||||
title={`${chequebookBalance?.availableBalance.toSignificantDigits(4)} xBZZ`}
|
||||
subtitle="Current chequebook balance."
|
||||
subtitle="Network transfer balance."
|
||||
status="ok"
|
||||
/>
|
||||
)
|
||||
@@ -32,7 +32,7 @@ export function ChequebookInfoCard() {
|
||||
<Card
|
||||
buttonProps={{
|
||||
iconType: ExchangeFunds,
|
||||
children: 'View chequebook',
|
||||
children: 'Manage chequebook',
|
||||
onClick: () => navigate(ROUTES.ACCOUNT_CHEQUEBOOK),
|
||||
}}
|
||||
icon={<ExchangeFunds />}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Button } from '@material-ui/core'
|
||||
import { ReactElement, useContext } from 'react'
|
||||
import { ChainSync } from '../../components/ChainSync'
|
||||
import ExpandableListItem from '../../components/ExpandableListItem'
|
||||
import Map from '../../components/Map'
|
||||
import { BEE_DESKTOP_LATEST_RELEASE_PAGE } from '../../constants'
|
||||
@@ -19,11 +20,17 @@ export default function Status(): ReactElement {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'stretch', alignContent: 'stretch' }}>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'stretch',
|
||||
alignContent: 'stretch',
|
||||
gap: '8px',
|
||||
}}
|
||||
>
|
||||
<NodeInfoCard />
|
||||
<div style={{ width: '8px' }}></div>
|
||||
<WalletInfoCard />
|
||||
<div style={{ width: '8px' }}></div>
|
||||
<ChequebookInfoCard />
|
||||
</div>
|
||||
<div style={{ height: '16px' }} />
|
||||
@@ -31,6 +38,9 @@ export default function Status(): ReactElement {
|
||||
<div style={{ height: '2px' }} />
|
||||
<ExpandableListItem label="Connected peers" value={topology?.connected ?? '-'} />
|
||||
<ExpandableListItem label="Population" value={topology?.population ?? '-'} />
|
||||
<ExpandableListItem label="Depth" value={topology?.depth ?? '-'} />
|
||||
<ChainSync />
|
||||
|
||||
<div style={{ height: '16px' }} />
|
||||
{isDesktop && (
|
||||
<ExpandableListItem
|
||||
|
||||
@@ -72,7 +72,7 @@ export function PostageStampAdvancedCreation({ onFinished }: Props): ReactElemen
|
||||
|
||||
return `${secondsToTimeString(
|
||||
convertAmountToSeconds(amount, pricePerBlock),
|
||||
)} (with price of ${pricePerBlock.toFixed(0)} per block)`
|
||||
)} (with price of ${pricePerBlock.toFixed(0)} PLUR per block)`
|
||||
}
|
||||
|
||||
function getPrice(depth: number, amount: bigint): string {
|
||||
|
||||
@@ -67,7 +67,7 @@ export function PostageStampStandardCreation({ onFinished }: Props): ReactElemen
|
||||
|
||||
return `${secondsToTimeString(
|
||||
convertAmountToSeconds(parseInt(amount, 10), pricePerBlock),
|
||||
)} (with price of ${pricePerBlock.toFixed(0)} per block)`
|
||||
)} (with price of ${pricePerBlock.toFixed(0)} PLUR per block)`
|
||||
}
|
||||
|
||||
function getPrice(depth: number, amount: bigint): string {
|
||||
@@ -196,7 +196,7 @@ export function PostageStampStandardCreation({ onFinished }: Props): ReactElemen
|
||||
</Box>
|
||||
<Box display="flex" justifyContent={'right'} mt={0.5}>
|
||||
<Typography style={{ fontSize: '10px', color: 'rgba(0, 0, 0, 0.26)' }}>
|
||||
Current price of 24000 per block
|
||||
Current price of 24000 PLUR per block
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
+1
-2
@@ -31,8 +31,7 @@ export function makeBigNumber(value: BigNumber | bigint | number | string): BigN
|
||||
|
||||
if (typeof value === 'bigint') return new BigNumber(value.toString())
|
||||
|
||||
// FIXME: bee-js still returns some values as numbers and even outside of SAFE INTEGER bounds
|
||||
if (typeof value === 'number' /* && Number.isSafeInteger(value)*/) return new BigNumber(value)
|
||||
if (typeof value === 'number') return new BigNumber(value)
|
||||
|
||||
throw new TypeError(`Not a BigNumber or BigNumber convertible value. Type: ${typeof value} value: ${value}`)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user