Refactor: Separating Header's layout from Provider Information

This commit is contained in:
apanizo 2018-09-03 15:57:31 +02:00
parent 6bcc351fa2
commit 113bc1f4dd
5 changed files with 185 additions and 144 deletions

View File

@ -1,9 +1,6 @@
// @flow // @flow
import * as React from 'react' import * as React from 'react'
import { withStyles } from '@material-ui/core/styles' import { withStyles } from '@material-ui/core/styles'
import ClickAwayListener from '@material-ui/core/ClickAwayListener'
import Grow from '@material-ui/core/Grow'
import Popper from '@material-ui/core/Popper'
import Divider from '~/components/layout/Divider' import Divider from '~/components/layout/Divider'
import openHoc, { type Open } from '~/components/hoc/OpenHoc' import openHoc, { type Open } from '~/components/hoc/OpenHoc'
import Col from '~/components/layout/Col' import Col from '~/components/layout/Col'
@ -11,17 +8,12 @@ import Img from '~/components/layout/Img'
import Row from '~/components/layout/Row' import Row from '~/components/layout/Row'
import Spacer from '~/components/Spacer' import Spacer from '~/components/Spacer'
import { border, sm, md } from '~/theme/variables' import { border, sm, md } from '~/theme/variables'
import Provider from './Provider'
import UserDetails from './UserDetails'
const logo = require('../assets/gnosis-safe-logo.svg') const logo = require('../assets/gnosis-safe-logo.svg')
type Props = Open & { type Props = Open & {
provider: string,
classes: Object, classes: Object,
network: string, children: React$Node,
userAddress: string,
connected: boolean,
} }
const styles = () => ({ const styles = () => ({
@ -37,9 +29,7 @@ const styles = () => ({
}, },
}) })
const Header = openHoc(({ const Header = openHoc(({ classes, children }: Props) => (
open, toggle, provider, network, connected, classes, userAddress,
}: Props) => (
<React.Fragment> <React.Fragment>
<Row className={classes.summary}> <Row className={classes.summary}>
<Col start="xs" middle="xs" className={classes.logo}> <Col start="xs" middle="xs" className={classes.logo}>
@ -48,35 +38,9 @@ const Header = openHoc(({
<Divider /> <Divider />
<Spacer /> <Spacer />
<Divider /> <Divider />
<Provider { children }
provider={provider}
network={network}
userAddress={userAddress}
connected={connected}
open={open}
toggle={toggle}
>
{providerRef => (
<Popper open={open} anchorEl={providerRef.current} placement="bottom-end">
{({ TransitionProps }) => (
<Grow
{...TransitionProps}
>
<ClickAwayListener onClickAway={toggle}>
<UserDetails
provider={provider}
network={network}
userAddress={userAddress}
connected={connected}
/>
</ClickAwayListener>
</Grow>
)}
</Popper>
)}
</Provider>
</Row> </Row>
</React.Fragment> </React.Fragment>
)) ))
export default withStyles(styles)(openHoc(Header)) export default withStyles(styles)(Header)

View File

@ -0,0 +1,109 @@
// @flow
import * as React from 'react'
import { withStyles } from '@material-ui/core/styles'
import IconButton from '@material-ui/core/IconButton'
import ExpandLess from '@material-ui/icons/ExpandLess'
import ExpandMore from '@material-ui/icons/ExpandMore'
import Paragraph from '~/components/layout/Paragraph'
import Col from '~/components/layout/Col'
import Img from '~/components/layout/Img'
import { type Open } from '~/components/hoc/OpenHoc'
import { sm, md } from '~/theme/variables'
import Identicon from '~/components/Identicon'
const connectedLogo = require('../../assets/connected.svg')
type Props = Open & {
provider: string,
network: string,
classes: Object,
userAddress: string,
connected: boolean,
children: Function,
}
const styles = () => ({
root: {
height: '100%',
display: 'flex',
alignItems: 'center',
},
provider: {
padding: `${sm} ${md}`,
alignItems: 'center',
flex: '0 1 auto',
display: 'flex',
cursor: 'pointer',
},
network: {
fontFamily: 'Montserrat, sans-serif',
},
logo: {
top: '10px',
position: 'relative',
right: '13px',
},
account: {
paddingRight: sm,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
},
address: {
letterSpacing: '-0.5px',
},
expand: {
width: '30px',
height: '30px',
},
})
type ProviderRef = { current: null | HTMLDivElement }
class Provider extends React.Component<Props> {
constructor(props: Props) {
super(props)
this.myRef = React.createRef()
}
myRef: ProviderRef
render() {
const {
open, toggle, provider, network, userAddress, connected, children, classes,
} = this.props
const providerText = connected ? `${provider} [${network}]` : 'Not connected'
const cutAddress = connected ? `${userAddress.substring(0, 8)}...${userAddress.substring(36)}` : ''
return (
<React.Fragment>
<div ref={this.myRef} className={classes.root}>
<Col end="sm" middle="xs" className={classes.provider}>
{ connected &&
<React.Fragment>
<Identicon address={userAddress} diameter={30} />
<Img className={classes.logo} src={connectedLogo} height={20} alt="Status connected" />
</React.Fragment>
}
<Col end="sm" middle="xs" layout="column" className={classes.account}>
<Paragraph size="sm" transform="capitalize" className={classes.network} noMargin bold>{providerText}</Paragraph>
<Paragraph size="sm" className={classes.address} noMargin>{cutAddress}</Paragraph>
</Col>
<IconButton
onClick={toggle}
disableRipple
className={classes.expand}
>
{ open ? <ExpandLess /> : <ExpandMore />}
</IconButton>
</Col>
</div>
{ children(this.myRef) }
</React.Fragment>
)
}
}
export default withStyles(styles)(Provider)

View File

@ -1,109 +1,49 @@
// @flow // @flow
import * as React from 'react' import * as React from 'react'
import { withStyles } from '@material-ui/core/styles' import openHoc, { type Open } from '~/components/hoc/OpenHoc'
import IconButton from '@material-ui/core/IconButton' import ClickAwayListener from '@material-ui/core/ClickAwayListener'
import ExpandLess from '@material-ui/icons/ExpandLess' import Grow from '@material-ui/core/Grow'
import ExpandMore from '@material-ui/icons/ExpandMore' import Popper from '@material-ui/core/Popper'
import Paragraph from '~/components/layout/Paragraph' import Connected from './Connected'
import Col from '~/components/layout/Col' import UserDetails from './UserDetails'
import Img from '~/components/layout/Img'
import { type Open } from '~/components/hoc/OpenHoc'
import { sm, md } from '~/theme/variables'
import Identicon from '~/components/Identicon'
const connectedLogo = require('../../assets/connected.svg')
type Props = Open & { type Props = Open & {
provider: string, provider: string,
network: string, network: string,
classes: Object,
userAddress: string, userAddress: string,
connected: boolean, connected: boolean,
children: Function,
} }
const styles = () => ({ const Provider = ({
root: { open, toggle, provider, network, userAddress, connected,
height: '100%', }: Props) => (
display: 'flex', <Connected
alignItems: 'center', provider={provider}
}, network={network}
provider: { userAddress={userAddress}
padding: `${sm} ${md}`, connected={connected}
alignItems: 'center', open={open}
flex: '0 1 auto', toggle={toggle}
display: 'flex',
cursor: 'pointer',
},
network: {
fontFamily: 'Montserrat, sans-serif',
},
logo: {
top: '10px',
position: 'relative',
right: '13px',
},
account: {
paddingRight: sm,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
},
address: {
letterSpacing: '-0.5px',
},
expand: {
width: '30px',
height: '30px',
},
})
type ProviderRef = { current: null | HTMLDivElement }
class Provider extends React.Component<Props> {
constructor(props: Props) {
super(props)
this.myRef = React.createRef()
}
myRef: ProviderRef
render() {
const {
open, toggle, provider, network, userAddress, connected, children, classes,
} = this.props
const providerText = connected ? `${provider} [${network}]` : 'Not connected'
const cutAddress = connected ? `${userAddress.substring(0, 8)}...${userAddress.substring(36)}` : ''
return (
<React.Fragment>
<div ref={this.myRef} className={classes.root}>
<Col end="sm" middle="xs" className={classes.provider}>
{ connected &&
<React.Fragment>
<Identicon address={userAddress} diameter={30} />
<Img className={classes.logo} src={connectedLogo} height={20} alt="Status connected" />
</React.Fragment>
}
<Col end="sm" middle="xs" layout="column" className={classes.account}>
<Paragraph size="sm" transform="capitalize" className={classes.network} noMargin bold>{providerText}</Paragraph>
<Paragraph size="sm" className={classes.address} noMargin>{cutAddress}</Paragraph>
</Col>
<IconButton
onClick={toggle}
disableRipple
className={classes.expand}
> >
{ open ? <ExpandLess /> : <ExpandMore />} {providerRef => (
</IconButton> <Popper open={open} anchorEl={providerRef.current} placement="bottom-end">
</Col> {({ TransitionProps }) => (
</div> <Grow
{ children(this.myRef) } {...TransitionProps}
</React.Fragment> >
) <ClickAwayListener onClickAway={toggle}>
} <UserDetails
} provider={provider}
network={network}
userAddress={userAddress}
connected={connected}
/>
</ClickAwayListener>
</Grow>
)}
</Popper>
)}
</Connected>
)
export default withStyles(styles)(Provider) export default openHoc(Provider)

View File

@ -1,6 +1,8 @@
// @flow // @flow
import * as React from 'react' import * as React from 'react'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { logComponentStack, type Info } from '~/utils/logBoundaries'
import Provider from './component/Provider'
import Layout from './component/Layout' import Layout from './component/Layout'
import actions from './actions' import actions from './actions'
import selector from './selector' import selector from './selector'
@ -13,11 +15,25 @@ type Props = {
connected: boolean, connected: boolean,
} }
class Header extends React.PureComponent<Props> { type State = {
hasError: boolean,
}
class Header extends React.PureComponent<Props, State> {
state = {
hasError: false,
}
componentDidMount() { componentDidMount() {
this.props.fetchProvider() this.props.fetchProvider()
} }
componentDidCatch(error: Error, info: Info) {
this.setState({ hasError: true })
logComponentStack(error, info)
}
reloadWallet = () => { reloadWallet = () => {
this.props.fetchProvider() this.props.fetchProvider()
} }
@ -27,14 +43,26 @@ class Header extends React.PureComponent<Props> {
provider, userAddress, network, connected, provider, userAddress, network, connected,
} = this.props } = this.props
const { hasError } = this.state
// const providerDisconnected = !hasError && !connected
const providerConnected = !hasError && connected
return ( return (
<Layout <Layout
provider={provider}
reloadWallet={this.reloadWallet} reloadWallet={this.reloadWallet}
>
{/* hasError && <ProviderError /> */}
{/* providerDisconnected && <ProviderDisconnected /> */}
{ providerConnected &&
<Provider
provider={provider}
userAddress={userAddress} userAddress={userAddress}
network={network} network={network}
connected={connected} connected={connected}
/> />
}
</Layout>
) )
} }
} }