feat: initial Proof of Concept UI (#1)

* initial dashboard layout

* add node status card

* add accounting section, pull peer data

* add file functionality with bee-js,  first iteration of accounts page

* Add balances and chequebook table

* add blockie / identicon for addresses

* add basic settlements table

* implement theme overrides

* cleanup logging

* Add troubleshooting block

* add initial dark theme support, add copy to clipboard, QR code support

* show active element on sidebar

* remove duplicate status page and make status page index

* Update package.json

Co-authored-by: Vojtech Simetka <vojtech@simetka.cz>

* Update public/index.html

Co-authored-by: Vojtech Simetka <vojtech@simetka.cz>

* Update src/pages/accounting/AccountCard.tsx

Co-authored-by: Vojtech Simetka <vojtech@simetka.cz>

* change bee api client to use beeJS library

* add initial setup workflow

* breakout ethereum address component, define initial setup workflow

* add types to responses, add additional node troubleshooting info to workflow

* make setup steps nonlinear and interactive

* make host endpoint dynamic on setup

* split out api calls into custom hooks, add component loading indicators

* add depost / withdrawl functionality, show transactions in BZZ

* add multiOS code support troubleshooting, check for balance in chequebook on setup

* add ability to change apis in settings page

* show file loading status

* Style active sidebar item

* reload on theme change

* modify troubleshooting verbage, add cashout functionality and details,

* facilitate file upload with beeJS

* update readme to show UI samples

* remove nnPeersWatermark from peers page

* split node steps into separate components, make status page visible at anytime

* minor UI/UX enhancements

* format accounting page

* remove WIP wallet connection code

* Update src/components/CashoutModal.tsx

Co-authored-by: Vojtech Simetka <vojtech@simetka.cz>

* use bigint for deposits/withdrawls

* revise status card

* clean up unused imports and variables

* add api status to sidebar

* obfuscate pages with troubleshooting component when apis not connected

* add localhost OS detection for troubleshooting code

* cleanup extra logos

* monospace BZZ in tables

* hide troubleshooting page while loading API status

* Remove ability to remove peers

* add null types to API responses

Co-authored-by: Vojtech Simetka <vojtech@simetka.cz>
This commit is contained in:
matmertz25
2021-03-12 12:01:56 -05:00
committed by GitHub
parent f4ce271479
commit 34d2dfda5a
60 changed files with 6155 additions and 364 deletions
+185
View File
@@ -0,0 +1,185 @@
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 NodeConnectionCheck from './SetupSteps/NodeConnectionCheck';
import VersionCheck from './SetupSteps/VersionCheck';
import EthereumConnectionCheck from './SetupSteps/EthereumConnectionCheck';
import ChequebookDeployFund from './SetupSteps/ChequebookDeployFund';
import PeerConnection from './SetupSteps/PeerConnection';
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
width: '100%',
},
button: {
marginTop: theme.spacing(1),
marginRight: theme.spacing(1),
},
actionsContainer: {
margin: theme.spacing(2),
},
resetContainer: {
padding: theme.spacing(5),
},
}),
);
function getSteps() {
return [
'Node Connection Check',
'Version Check',
'Connect to Ethereum Blockchain',
'Deploy and Fund Chequebook',
'Connect to Peers',
];
}
function getStepContent(step: number, props: any) {
switch (step) {
case 0:
return <NodeConnectionCheck {...props} />;
case 1:
return <VersionCheck {...props} />;
case 2:
return <EthereumConnectionCheck {...props} />;
case 3:
return <ChequebookDeployFund {...props} />;
default:
return <PeerConnection {...props} />;
}
}
export default function NodeSetupWorkflow(props: any) {
const classes = useStyles();
const [activeStep, setActiveStep] = useState(0);
const [completed, setCompleted] = useState<{ [k: number]: boolean }>({});
const steps = getSteps();
const evaluateNodeStatus = () => {
if (props.nodeHealth?.status === 'ok' && props.nodeApiHealth) {
handleComplete(0)
setActiveStep(1)
}
if (props.beeRelease && props.beeRelease.name === `v${props.nodeHealth?.version?.split('-')[0]}`) {
handleComplete(1)
setActiveStep(2)
}
if (props.nodeAddresses?.ethereum) {
handleComplete(2)
setActiveStep(3)
}
if (props.chequebookAddress?.chequebookaddress && props.chequebookBalance.totalBalance > 0) {
handleComplete(3)
setActiveStep(4)
}
if (props.nodeTopology.connected && props.nodeTopology.connected > 0) {
handleComplete(4)
setActiveStep(5)
}
}
useEffect(() => {
evaluateNodeStatus()
}, [])
useEffect(() => {
evaluateNodeStatus()
}, [props])
const handleNext = () => {
setActiveStep((prevActiveStep) => prevActiveStep + 1);
};
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};
const handleSetupComplete = () => {
props.setStatusChecksVisible(false)
};
const handleComplete = (index: number) => {
const newCompleted = completed;
newCompleted[index] = true;
setCompleted(newCompleted);
};
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>
</Typography>
<Stepper nonLinear activeStep={activeStep} orientation="vertical">
{steps.map((label, index) => (
<Step key={label}>
<StepLabel
onClick={() => setActiveStep(index === activeStep ? 5 : 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 ? 5 : index)} style={{justifyContent:'space-between'}}>
<div style={{display:'flex'}}>
<div style={{marginTop:'5px'}}>{label}</div>
<div style={{marginLeft:'12px'}}>{index === activeStep ? <ExpandLessSharp /> : <ExpandMoreSharp />}</div>
</div>
</StepButton>
</StepLabel>
<StepContent>
<Typography>{getStepContent(index, props)}</Typography>
<div className={classes.actionsContainer}>
<div>
<Button
disabled={activeStep === 0}
onClick={handleBack}
className={classes.button}
>
Back
</Button>
<Button
variant="contained"
color="primary"
onClick={handleNext}
className={classes.button}
>
Next
</Button>
</div>
</div>
</StepContent>
</Step>
))}
</Stepper>
{Object.values(completed).filter(value => value).length === 5 ? (
<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}
>
Back
</Button>
<Button onClick={handleSetupComplete} variant="contained" color="primary" className={classes.button}>
Complete
</Button>
</Paper>
) : null}
</div>
);
}