WA-232 Displaying safe's token in settings route

This commit is contained in:
apanizo 2018-07-10 16:48:20 +02:00
parent 0b5d14c8f2
commit 3afefea0a7
10 changed files with 63 additions and 35 deletions

View File

@ -11,6 +11,11 @@ const Safe = Loadable({
loading: Loader,
})
const Settings = Loadable({
loader: () => import('./tokens/container'),
loading: Loader,
})
const SafeList = Loadable({
loader: () => import('./safeList/container'),
loading: Loader,
@ -22,6 +27,9 @@ const Open = Loadable({
})
const SAFE_ADDRESS = `${SAFELIST_ADDRESS}/:${SAFE_PARAM_ADDRESS}`
const SAFE_SETTINGS = `${SAFE_ADDRESS}/settings`
export const settingsUrlFrom = (safeAddress: string) => `${SAFELIST_ADDRESS}/${safeAddress}/settings`
const Routes = () => (
<Switch>
@ -30,6 +38,7 @@ const Routes = () => (
<Route exact path={OPEN_ADDRESS} component={Open} />
<Route exact path={SAFELIST_ADDRESS} component={SafeList} />
<Route exact path={SAFE_ADDRESS} component={Safe} />
<Route exact path={SAFE_SETTINGS} component={Settings} />
</Switch>
)

View File

@ -1,7 +1,9 @@
// @flow
import * as React from 'react'
import classNames from 'classnames'
import Link from '~/components/layout/Link'
import AccountBalance from '@material-ui/icons/AccountBalance'
import Settings from '@material-ui/icons/Settings'
import Avatar from '@material-ui/core/Avatar'
import Collapse from '@material-ui/core/Collapse'
import IconButton from '@material-ui/core/IconButton'
@ -18,8 +20,10 @@ import Button from '~/components/layout/Button'
import openHoc, { type Open } from '~/components/hoc/OpenHoc'
import { type WithStyles } from '~/theme/mui'
import { type Token } from '~/routes/tokens/store/model/token'
import { settingsUrlFrom } from '~/routes'
type Props = Open & WithStyles & {
safeAddress: string,
tokens: Map<string, Token>,
onMoveFunds: (token: Token) => void,
}
@ -33,9 +37,10 @@ const styles = {
export const MOVE_FUNDS_BUTTON_TEXT = 'Move'
const BalanceComponent = openHoc(({
open, toggle, tokens, classes, onMoveFunds,
open, toggle, tokens, classes, onMoveFunds, safeAddress,
}: Props) => {
const hasBalances = tokens.count() > 0
const settingsUrl = settingsUrlFrom(safeAddress)
return (
<React.Fragment>
@ -44,6 +49,11 @@ const BalanceComponent = openHoc(({
<AccountBalance />
</Avatar>
<ListItemText primary="Balance" secondary="List of different token balances" />
<ListItemIcon>
<IconButton to={settingsUrl} component={Link} className={classes.button} aria-label="Delete">
<Settings />
</IconButton>
</ListItemIcon>
<ListItemIcon>
{open
? <IconButton disableRipple><ExpandLess /></IconButton>

View File

@ -110,12 +110,13 @@ class GnoSafe extends React.PureComponent<SafeProps, State> {
const { safe, tokens, userAddress } = this.props
const { component } = this.state
const ethBalance = getEthBalanceFrom(tokens)
const address = safe.get('address')
return (
<Row grow>
<Col sm={12} top="xs" md={5} margin="xl" overflow>
<List style={listStyle}>
<BalanceInfo tokens={tokens} onMoveFunds={this.onMoveTokens} />
<BalanceInfo tokens={tokens} onMoveFunds={this.onMoveTokens} safeAddress={address} />
<Owners
owners={safe.owners}
onAddOwner={this.onAddOwner}
@ -123,7 +124,7 @@ class GnoSafe extends React.PureComponent<SafeProps, State> {
onRemoveOwner={this.onRemoveOwner}
/>
<Confirmations confirmations={safe.get('threshold')} onEditThreshold={this.onEditThreshold} />
<Address address={safe.get('address')} />
<Address address={address} />
<DailyLimit balance={ethBalance} dailyLimit={safe.get('dailyLimit')} onWithdraw={this.onWithdraw} onEditDailyLimit={this.onEditDailyLimit} />
<MultisigTx onSeeTxs={this.onListTransactions} />
</List>

View File

@ -10,6 +10,7 @@ import { type Token } from '~/routes/tokens/store/model/token'
import { createTransaction } from '~/wallets/createTransactions'
import { EMPTY_DATA } from '~/wallets/ethTransactions'
import { toNative } from '~/wallets/tokens'
import { isEther } from '~/utils/tokens'
import actions, { type Actions } from './actions'
import selector, { type SelectorProps } from './selector'
import SendTokenForm, { TKN_DESTINATION_PARAM, TKN_VALUE_PARAM } from './SendTokenForm'
@ -31,8 +32,6 @@ type State = {
export const SEE_TXS_BUTTON_TEXT = 'VISIT TXS'
const isEther = (symbol: string) => symbol === 'ETH'
const getTransferData = async (tokenAddress: string, to: string, amount: BigNumber) => {
const StandardToken = await getStandardTokenContract()
const myToken = await StandardToken.at(tokenAddress)

View File

@ -1,5 +1,5 @@
// @flow
import * as MuiList from '@material-ui/core/List'
import MuiList from '@material-ui/core/List'
import * as React from 'react'
import Block from '~/components/layout/Block'
import Col from '~/components/layout/Col'
@ -24,6 +24,7 @@ type State = {
const listStyle = {
width: '100%',
paddingBottom: 0,
}
class TokenLayout extends React.PureComponent<TokenProps, State> {
@ -64,6 +65,7 @@ class TokenLayout extends React.PureComponent<TokenProps, State> {
<Col sm={12} top="xs" md={5} margin="xl" overflow>
<MuiList style={listStyle}>
{tokens.map((token: Token) => (<TokenComponent
key={token.get('symbol')}
token={token}
onDisableToken={this.onDisableToken}
onEnableToken={this.onEnableToken}

View File

@ -3,12 +3,12 @@ import * as React from 'react'
import { type Token } from '~/routes/tokens/store/model/token'
import { withStyles } from '@material-ui/core/styles'
import Block from '~/components/layout/Block'
import Bold from '~/components/layout/Bold'
import Checkbox from '@material-ui/core/Checkbox'
import Card from '@material-ui/core/Card'
import CardContent from '@material-ui/core/CardContent'
import CardMedia from '@material-ui/core/CardMedia'
import Typography from '@material-ui/core/Typography'
import { isEther } from '~/utils/tokens'
// import Delete from '@material-ui/icons/Delete'
// import IconButton from '@material-ui/core/IconButton'
import { type WithStyles } from '~/theme/mui'
@ -24,7 +24,7 @@ type State = {
checked: boolean,
}
const styles = theme => ({
const styles = () => ({
card: {
display: 'flex',
},
@ -36,18 +36,9 @@ const styles = theme => ({
flex: '1 0 auto',
},
cover: {
width: 45,
height: 45,
},
controls: {
display: 'flex',
alignItems: 'center',
paddingLeft: theme.spacing.unit,
paddingBottom: theme.spacing.unit,
},
playIcon: {
height: 38,
width: 38,
width: 150,
margin: 10,
backgroundSize: '50%',
},
})
@ -60,14 +51,15 @@ class TokenComponent extends React.Component<Props, State> {
handleChange = (e: SyntheticInputEvent<HTMLInputElement>) => {
const { checked } = e.target
const callback = checked ? this.props.onDisableToken : this.props.onDisableToken
this.setState(() => ({ checked: e.target.checked }), () => callback(this.props.token))
const callback = checked ? this.props.onEnableToken : this.props.onDisableToken
this.setState(() => ({ checked }), () => callback(this.props.token))
}
render() {
const { classes, token } = this.props
const name = token.get('name')
const symbol = token.get('symbol')
const disabled = isEther(symbol)
return (
<Card className={classes.card}>
@ -75,25 +67,23 @@ class TokenComponent extends React.Component<Props, State> {
<CardContent className={classes.content}>
<Typography variant="headline">{name}</Typography>
<Typography variant="subheading" color="textSecondary">
{symbol}
</Typography>
</CardContent>
<Block className={classes.controls}>
<Bold>
{symbol}
</Bold>
<Checkbox
disabled={disabled}
checked={this.state.checked}
onChange={this.handleChange}
color="primary"
/>
{symbol}
</Typography>
</CardContent>
</Block>
{/*
<Block className={classes.controls}>
<IconButton aria-label="Delete" onClick={this.onRemoveClick}>
<Delete />
</IconButton>
</Block>
*/}
</Block>
</Block>
<CardMedia
className={classes.cover}
image={token.get('logoUrl')}

View File

@ -1,6 +1,7 @@
// @flow
import enableToken from '~/routes/tokens/store/actions/enableToken'
import disableToken from '~/routes/tokens/store/actions/disableToken'
import { fetchTokens } from '~/routes/tokens/store/actions/fetchTokens'
export type Actions = {
enableToken: typeof enableToken,
@ -10,4 +11,5 @@ export type Actions = {
export default {
enableToken,
disableToken,
fetchTokens,
}

View File

@ -3,12 +3,24 @@ import * as React from 'react'
import { connect } from 'react-redux'
import Page from '~/components/layout/Page'
import Layout from '~/routes/tokens/component/Layout'
import { fetchTokens } from '~/routes/tokens/store/actions/fetchTokens'
import selector, { type SelectorProps } from './selector'
import actions, { type Actions } from './actions'
type Props = Actions & SelectorProps
type Props = Actions & SelectorProps & {
safeAddress: string,
fetchTokens: typeof fetchTokens,
}
class TokensView extends React.PureComponent<Props> {
componentDidUpdate() {
const { safeAddress } = this.props
if (this.props.tokens.count() === 0) {
this.props.fetchTokens(safeAddress)
}
}
render() {
const {
tokens, addresses, safe, disableToken, enableToken,

View File

@ -3,7 +3,7 @@ import { List } from 'immutable'
import { createStructuredSelector } from 'reselect'
import { tokenListSelector, tokenAddressesSelector } from '~/routes/tokens/store/selectors'
import { type Safe } from '~/routes/safe/store/model/safe'
import { safeSelector } from '~/routes/safe/store/selectors'
import { safeSelector, safeParamAddressSelector } from '~/routes/safe/store/selectors'
import { type Token } from '~/routes/tokens/store/model/token'
export type SelectorProps = {
@ -14,6 +14,7 @@ export type SelectorProps = {
export default createStructuredSelector({
safe: safeSelector,
safeAddress: safeParamAddressSelector,
tokens: tokenListSelector,
addresses: tokenAddressesSelector,
})

2
src/utils/tokens.js Normal file
View File

@ -0,0 +1,2 @@
// @flow
export const isEther = (symbol: string) => symbol === 'ETH'