feat: troubleshooting component (#204)
* feat: troubleshooting component and general layout improvements * style: background color, links and button * chore: disable ripples and rounded corners on buttons * fix: spacing on the troubleshooting card
This commit is contained in:
@@ -44,6 +44,8 @@ const navBarItems = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const drawerWidth = 300
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
root: {
|
root: {
|
||||||
@@ -52,6 +54,14 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
paddingTop: theme.spacing(8),
|
paddingTop: theme.spacing(8),
|
||||||
paddingBottom: theme.spacing(8),
|
paddingBottom: theme.spacing(8),
|
||||||
},
|
},
|
||||||
|
drawer: {
|
||||||
|
width: drawerWidth,
|
||||||
|
flexShrink: 0,
|
||||||
|
},
|
||||||
|
drawerPaper: {
|
||||||
|
width: drawerWidth,
|
||||||
|
backgroundColor: '#212121',
|
||||||
|
},
|
||||||
logo: {
|
logo: {
|
||||||
marginLeft: theme.spacing(8),
|
marginLeft: theme.spacing(8),
|
||||||
marginRight: theme.spacing(8),
|
marginRight: theme.spacing(8),
|
||||||
@@ -86,7 +96,7 @@ export default function SideBar(): ReactElement {
|
|||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Drawer variant="permanent">
|
<Drawer className={classes.drawer} variant="permanent" anchor="left" classes={{ paper: classes.drawerPaper }}>
|
||||||
<Grid container direction="column" justifyContent="space-between" className={classes.root}>
|
<Grid container direction="column" justifyContent="space-between" className={classes.root}>
|
||||||
<Grid className={classes.logo}>
|
<Grid className={classes.logo}>
|
||||||
<Link to={ROUTES.INFO}>
|
<Link to={ROUTES.INFO}>
|
||||||
|
|||||||
@@ -40,25 +40,23 @@ const Indicator = ({ thresholds }: Props): ReactElement => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Metrics = ({ topology, thresholds }: Props): ReactElement => (
|
const Metrics = ({ topology, thresholds }: Props): ReactElement => (
|
||||||
<Grid style={{ marginBottom: '20px', flexGrow: 1 }}>
|
<Grid container spacing={3} style={{ marginBottom: '20px' }}>
|
||||||
<Grid container spacing={3}>
|
<Grid key={1} item xs={12} sm={12} md={6} lg={4} xl={4}>
|
||||||
<Grid key={1} item xs={12} sm={12} md={6} lg={4} xl={4}>
|
<StatCard
|
||||||
<StatCard
|
label="Connected Peers"
|
||||||
label="Connected Peers"
|
statistic={topology?.connected.toString()}
|
||||||
statistic={topology?.connected.toString()}
|
tooltip={thresholds.connectedPeers.explanation}
|
||||||
tooltip={thresholds.connectedPeers.explanation}
|
/>
|
||||||
/>
|
</Grid>
|
||||||
</Grid>
|
<Grid key={2} item xs={12} sm={12} md={6} lg={4} xl={4}>
|
||||||
<Grid key={2} item xs={12} sm={12} md={6} lg={4} xl={4}>
|
<StatCard
|
||||||
<StatCard
|
label="Population"
|
||||||
label="Population"
|
statistic={topology?.population.toString()}
|
||||||
statistic={topology?.population.toString()}
|
tooltip={thresholds.population.explanation}
|
||||||
tooltip={thresholds.population.explanation}
|
/>
|
||||||
/>
|
</Grid>
|
||||||
</Grid>
|
<Grid key={3} item xs={12} sm={12} md={6} lg={4} xl={4}>
|
||||||
<Grid key={3} item xs={12} sm={12} md={6} lg={4} xl={4}>
|
<StatCard label="Depth" statistic={topology?.depth.toString()} tooltip={thresholds.depth.explanation} />
|
||||||
<StatCard label="Depth" statistic={topology?.depth.toString()} tooltip={thresholds.depth.explanation} />
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,48 +1,65 @@
|
|||||||
import type { ReactElement } from 'react'
|
import type { ReactElement } from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
|
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
|
||||||
import { Card, CardContent, Typography } from '@material-ui/core/'
|
import { Button, Grid, Typography, Link as MuiLink } from '@material-ui/core/'
|
||||||
import { ROUTES } from '../routes'
|
import { ROUTES } from '../routes'
|
||||||
|
import { Activity } from 'react-feather'
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
root: {
|
createStyles({
|
||||||
flexGrow: 1,
|
root: {
|
||||||
marginTop: '20px',
|
height: '100%',
|
||||||
},
|
},
|
||||||
title: {
|
content: {
|
||||||
textAlign: 'center',
|
maxWidth: 500,
|
||||||
fontSize: 26,
|
marginBottom: theme.spacing(4),
|
||||||
},
|
'&:last-child': {
|
||||||
})
|
marginBottom: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
height: '1rem',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
export default function TroubleshootConnectionCard(): ReactElement {
|
export default function TroubleshootConnectionCard(): ReactElement {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className={classes.root}>
|
<Grid container direction="column" justifyContent="center" alignItems="center" className={classes.root}>
|
||||||
<CardContent>
|
<Grid item className={classes.content}>
|
||||||
<Typography className={classes.title} gutterBottom>
|
<Typography variant="h1" align="center">
|
||||||
Looks like your node is not connected
|
Uh oh, it looks like your node is not connected.
|
||||||
</Typography>
|
</Typography>
|
||||||
<div style={{ marginBottom: '20px', textAlign: 'center' }}>
|
</Grid>
|
||||||
<strong>
|
<Grid item className={classes.content}>
|
||||||
<Link to={ROUTES.STATUS}>Click to run status checks</Link> on your nodes connection or check out the{' '}
|
<Typography align="center">
|
||||||
<a href={process.env.REACT_APP_BEE_DOCS_HOST} target="_blank" rel="noreferrer">
|
Please check your node status to fix the problem. You can also check out the{' '}
|
||||||
Swarm Bee Docs
|
<MuiLink href={process.env.REACT_APP_BEE_DOCS_HOST} target="_blank" rel="noreferrer">
|
||||||
</a>
|
Swarm Bee Docs
|
||||||
</strong>
|
</MuiLink>{' '}
|
||||||
</div>
|
or ask for support on the{' '}
|
||||||
|
<MuiLink href={process.env.REACT_APP_BEE_DISCORD_HOST} target="_blank" rel="noreferrer">
|
||||||
<div style={{ marginBottom: '20px', textAlign: 'center' }}>
|
Ethereum Swarm Discord
|
||||||
<p style={{ marginTop: '50px' }}>
|
</MuiLink>
|
||||||
Still not working? Drop us a message on the Ethereum Swarm{' '}
|
.
|
||||||
<a href={process.env.REACT_APP_BEE_DISCORD_HOST} target="_blank" rel="noreferrer">
|
</Typography>
|
||||||
Discord
|
</Grid>
|
||||||
</a>
|
<Grid item className={classes.content}>
|
||||||
</p>
|
<Typography align="center">
|
||||||
</div>
|
<Button
|
||||||
</CardContent>
|
component={Link}
|
||||||
</Card>
|
variant="contained"
|
||||||
|
size="large"
|
||||||
|
startIcon={<Activity className={classes.icon} />}
|
||||||
|
to={ROUTES.STATUS}
|
||||||
|
>
|
||||||
|
Check node status
|
||||||
|
</Button>
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-17
@@ -12,11 +12,8 @@ import { Context } from '../providers/Bee'
|
|||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
content: {
|
content: {
|
||||||
marginLeft: 300,
|
|
||||||
flexGrow: 1,
|
|
||||||
backgroundColor: theme.palette.background.default,
|
backgroundColor: theme.palette.background.default,
|
||||||
padding: theme.spacing(3),
|
minHeight: '100vh',
|
||||||
paddingBottom: '65px',
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@@ -31,20 +28,22 @@ const Dashboard = (props: Props): ReactElement => {
|
|||||||
const { isLoading } = useContext(Context)
|
const { isLoading } = useContext(Context)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div style={{ display: 'flex' }}>
|
||||||
<SideBar />
|
<SideBar />
|
||||||
<ErrorBoundary>
|
<Container className={classes.content}>
|
||||||
<main className={classes.content}>
|
<ErrorBoundary>
|
||||||
<AlertVersion />
|
<>
|
||||||
{isLoading ? (
|
<AlertVersion />
|
||||||
<Container style={{ textAlign: 'center', padding: '50px' }}>
|
{isLoading ? (
|
||||||
<CircularProgress />
|
<div style={{ textAlign: 'center', width: '100%' }}>
|
||||||
</Container>
|
<CircularProgress />
|
||||||
) : (
|
</div>
|
||||||
props.children
|
) : (
|
||||||
)}
|
props.children
|
||||||
</main>
|
)}
|
||||||
</ErrorBoundary>
|
</>
|
||||||
|
</ErrorBoundary>
|
||||||
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,36 +59,34 @@ function PeerTable(props: Props): ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<TableContainer component={Paper}>
|
||||||
<TableContainer component={Paper}>
|
<Table className={classes.table}>
|
||||||
<Table className={classes.table}>
|
<TableHead>
|
||||||
<TableHead>
|
<TableRow>
|
||||||
<TableRow>
|
<TableCell>Index</TableCell>
|
||||||
<TableCell>Index</TableCell>
|
<TableCell>Peer Id</TableCell>
|
||||||
<TableCell>Peer Id</TableCell>
|
<TableCell align="right">Actions</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)}>
|
||||||
|
{getPingState(peerLatency, peer)}
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
))}
|
||||||
<TableBody>
|
</TableBody>
|
||||||
{props.peers?.map((peer: Peer, idx: number) => (
|
</Table>
|
||||||
<TableRow key={peer.address}>
|
</TableContainer>
|
||||||
<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)}>
|
|
||||||
{getPingState(peerLatency, peer)}
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</TableContainer>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { ReactElement, useState, useContext } from 'react'
|
import { ReactElement, useState, useContext } from 'react'
|
||||||
import { Paper, Container, TextField, Typography, Button } from '@material-ui/core'
|
import { Paper, TextField, Typography, Button } from '@material-ui/core'
|
||||||
import { Context as SettingsContext } from '../../providers/Settings'
|
import { Context as SettingsContext } from '../../providers/Settings'
|
||||||
|
|
||||||
export default function Settings(): ReactElement {
|
export default function Settings(): ReactElement {
|
||||||
@@ -16,55 +16,53 @@ export default function Settings(): ReactElement {
|
|||||||
const touched = host !== apiUrl || debugHost !== apiDebugUrl
|
const touched = host !== apiUrl || debugHost !== apiDebugUrl
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<Container>
|
<Typography variant="h4" gutterBottom>
|
||||||
<Typography variant="h4" gutterBottom>
|
Settings
|
||||||
Settings
|
</Typography>
|
||||||
</Typography>
|
<Paper>
|
||||||
<Paper>
|
<TextField
|
||||||
<TextField
|
label="API Endpoint"
|
||||||
label="API Endpoint"
|
style={{ margin: 0 }}
|
||||||
style={{ margin: 0 }}
|
placeholder="ex: 127.0.0.0.1:1633"
|
||||||
placeholder="ex: 127.0.0.0.1:1633"
|
helperText="Enter node host override / port"
|
||||||
helperText="Enter node host override / port"
|
fullWidth
|
||||||
fullWidth
|
defaultValue={apiUrl}
|
||||||
defaultValue={apiUrl}
|
margin="normal"
|
||||||
margin="normal"
|
InputLabelProps={{
|
||||||
InputLabelProps={{
|
shrink: true,
|
||||||
shrink: true,
|
}}
|
||||||
}}
|
onChange={e => {
|
||||||
onChange={e => {
|
setHost(e.target.value)
|
||||||
setHost(e.target.value)
|
}}
|
||||||
}}
|
variant="filled"
|
||||||
variant="filled"
|
/>
|
||||||
/>
|
</Paper>
|
||||||
</Paper>
|
<Paper style={{ marginTop: '20px' }}>
|
||||||
<Paper style={{ marginTop: '20px' }}>
|
<TextField
|
||||||
<TextField
|
label="Debug API Endpoint"
|
||||||
label="Debug API Endpoint"
|
style={{ margin: 0 }}
|
||||||
style={{ margin: 0 }}
|
placeholder="ex: 127.0.0.0.1:1635"
|
||||||
placeholder="ex: 127.0.0.0.1:1635"
|
helperText="Enter node debug host override / port"
|
||||||
helperText="Enter node debug host override / port"
|
fullWidth
|
||||||
fullWidth
|
defaultValue={apiDebugUrl}
|
||||||
defaultValue={apiDebugUrl}
|
onChange={e => {
|
||||||
onChange={e => {
|
setDebugHost(e.target.value)
|
||||||
setDebugHost(e.target.value)
|
}}
|
||||||
}}
|
margin="normal"
|
||||||
margin="normal"
|
InputLabelProps={{
|
||||||
InputLabelProps={{
|
shrink: true,
|
||||||
shrink: true,
|
}}
|
||||||
}}
|
variant="filled"
|
||||||
variant="filled"
|
/>
|
||||||
/>
|
</Paper>
|
||||||
</Paper>
|
{touched ? (
|
||||||
{touched ? (
|
<div style={{ marginTop: '20px' }}>
|
||||||
<div style={{ marginTop: '20px' }}>
|
<Button variant="outlined" color="primary" onClick={submit}>
|
||||||
<Button variant="outlined" color="primary" onClick={submit}>
|
Save
|
||||||
Save
|
</Button>
|
||||||
</Button>
|
</div>
|
||||||
</div>
|
) : null}
|
||||||
) : null}
|
</>
|
||||||
</Container>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+57
-5
@@ -9,10 +9,55 @@ declare module '@material-ui/core/styles/createPalette' {
|
|||||||
|
|
||||||
// Overwriting default components styles
|
// Overwriting default components styles
|
||||||
const componentsOverrides = (theme: Theme) => ({
|
const componentsOverrides = (theme: Theme) => ({
|
||||||
MuiDrawer: {
|
MuiContainer: {
|
||||||
paper: {
|
root: { padding: theme.spacing(8) },
|
||||||
width: 300,
|
maxWidthXs: { padding: theme.spacing(8) },
|
||||||
backgroundColor: '#212121',
|
maxWidthSm: { padding: theme.spacing(8) },
|
||||||
|
maxWidthMd: { padding: theme.spacing(8) },
|
||||||
|
maxWidthLg: { padding: theme.spacing(8) },
|
||||||
|
maxWidthXl: { padding: theme.spacing(8) },
|
||||||
|
},
|
||||||
|
MuiButton: {
|
||||||
|
textSizeLarge: {
|
||||||
|
padding: theme.spacing(2),
|
||||||
|
},
|
||||||
|
containedSizeLarge: {
|
||||||
|
padding: theme.spacing(2),
|
||||||
|
boxShadow: 'none',
|
||||||
|
borderRadius: 0,
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
color: 'white',
|
||||||
|
boxShadow: 'none',
|
||||||
|
// https://github.com/mui-org/material-ui/issues/22543
|
||||||
|
'@media (hover: none)': {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
color: 'white',
|
||||||
|
boxShadow: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
contained: {
|
||||||
|
backgroundColor: 'white',
|
||||||
|
boxShadow: 'none',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
color: 'white',
|
||||||
|
// https://github.com/mui-org/material-ui/issues/22543
|
||||||
|
'@media (hover: none)': {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
color: 'white',
|
||||||
|
boxShadow: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'&:focus': {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
|
'&:active': {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MuiTab: {
|
MuiTab: {
|
||||||
@@ -59,13 +104,16 @@ const propsOverrides = {
|
|||||||
MuiTab: {
|
MuiTab: {
|
||||||
disableRipple: true,
|
disableRipple: true,
|
||||||
},
|
},
|
||||||
|
MuiButtonBase: {
|
||||||
|
disableRipple: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const theme = createMuiTheme({
|
export const theme = createMuiTheme({
|
||||||
palette: {
|
palette: {
|
||||||
type: 'light',
|
type: 'light',
|
||||||
background: {
|
background: {
|
||||||
default: '#fafafa',
|
default: '#efefef',
|
||||||
},
|
},
|
||||||
primary: {
|
primary: {
|
||||||
light: orange.A200,
|
light: orange.A200,
|
||||||
@@ -78,6 +126,10 @@ export const theme = createMuiTheme({
|
|||||||
},
|
},
|
||||||
typography: {
|
typography: {
|
||||||
fontFamily: ['Work Sans', 'Montserrat', 'Nunito', 'Roboto', '"Helvetica Neue"', 'Arial', 'sans-serif'].join(','),
|
fontFamily: ['Work Sans', 'Montserrat', 'Nunito', 'Roboto', '"Helvetica Neue"', 'Arial', 'sans-serif'].join(','),
|
||||||
|
h1: {
|
||||||
|
fontSize: '1.3rem',
|
||||||
|
fontWeight: 500,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user