WA-232 Displaying safe's token in settings route
This commit is contained in:
parent
0b5d14c8f2
commit
3afefea0a7
|
@ -11,6 +11,11 @@ const Safe = Loadable({
|
||||||
loading: Loader,
|
loading: Loader,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const Settings = Loadable({
|
||||||
|
loader: () => import('./tokens/container'),
|
||||||
|
loading: Loader,
|
||||||
|
})
|
||||||
|
|
||||||
const SafeList = Loadable({
|
const SafeList = Loadable({
|
||||||
loader: () => import('./safeList/container'),
|
loader: () => import('./safeList/container'),
|
||||||
loading: Loader,
|
loading: Loader,
|
||||||
|
@ -22,6 +27,9 @@ const Open = Loadable({
|
||||||
})
|
})
|
||||||
|
|
||||||
const SAFE_ADDRESS = `${SAFELIST_ADDRESS}/:${SAFE_PARAM_ADDRESS}`
|
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 = () => (
|
const Routes = () => (
|
||||||
<Switch>
|
<Switch>
|
||||||
|
@ -30,6 +38,7 @@ const Routes = () => (
|
||||||
<Route exact path={OPEN_ADDRESS} component={Open} />
|
<Route exact path={OPEN_ADDRESS} component={Open} />
|
||||||
<Route exact path={SAFELIST_ADDRESS} component={SafeList} />
|
<Route exact path={SAFELIST_ADDRESS} component={SafeList} />
|
||||||
<Route exact path={SAFE_ADDRESS} component={Safe} />
|
<Route exact path={SAFE_ADDRESS} component={Safe} />
|
||||||
|
<Route exact path={SAFE_SETTINGS} component={Settings} />
|
||||||
</Switch>
|
</Switch>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
import Link from '~/components/layout/Link'
|
||||||
import AccountBalance from '@material-ui/icons/AccountBalance'
|
import AccountBalance from '@material-ui/icons/AccountBalance'
|
||||||
|
import Settings from '@material-ui/icons/Settings'
|
||||||
import Avatar from '@material-ui/core/Avatar'
|
import Avatar from '@material-ui/core/Avatar'
|
||||||
import Collapse from '@material-ui/core/Collapse'
|
import Collapse from '@material-ui/core/Collapse'
|
||||||
import IconButton from '@material-ui/core/IconButton'
|
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 openHoc, { type Open } from '~/components/hoc/OpenHoc'
|
||||||
import { type WithStyles } from '~/theme/mui'
|
import { type WithStyles } from '~/theme/mui'
|
||||||
import { type Token } from '~/routes/tokens/store/model/token'
|
import { type Token } from '~/routes/tokens/store/model/token'
|
||||||
|
import { settingsUrlFrom } from '~/routes'
|
||||||
|
|
||||||
type Props = Open & WithStyles & {
|
type Props = Open & WithStyles & {
|
||||||
|
safeAddress: string,
|
||||||
tokens: Map<string, Token>,
|
tokens: Map<string, Token>,
|
||||||
onMoveFunds: (token: Token) => void,
|
onMoveFunds: (token: Token) => void,
|
||||||
}
|
}
|
||||||
|
@ -33,9 +37,10 @@ const styles = {
|
||||||
export const MOVE_FUNDS_BUTTON_TEXT = 'Move'
|
export const MOVE_FUNDS_BUTTON_TEXT = 'Move'
|
||||||
|
|
||||||
const BalanceComponent = openHoc(({
|
const BalanceComponent = openHoc(({
|
||||||
open, toggle, tokens, classes, onMoveFunds,
|
open, toggle, tokens, classes, onMoveFunds, safeAddress,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const hasBalances = tokens.count() > 0
|
const hasBalances = tokens.count() > 0
|
||||||
|
const settingsUrl = settingsUrlFrom(safeAddress)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
@ -44,6 +49,11 @@ const BalanceComponent = openHoc(({
|
||||||
<AccountBalance />
|
<AccountBalance />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<ListItemText primary="Balance" secondary="List of different token balances" />
|
<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>
|
<ListItemIcon>
|
||||||
{open
|
{open
|
||||||
? <IconButton disableRipple><ExpandLess /></IconButton>
|
? <IconButton disableRipple><ExpandLess /></IconButton>
|
||||||
|
|
|
@ -110,12 +110,13 @@ class GnoSafe extends React.PureComponent<SafeProps, State> {
|
||||||
const { safe, tokens, userAddress } = this.props
|
const { safe, tokens, userAddress } = this.props
|
||||||
const { component } = this.state
|
const { component } = this.state
|
||||||
const ethBalance = getEthBalanceFrom(tokens)
|
const ethBalance = getEthBalanceFrom(tokens)
|
||||||
|
const address = safe.get('address')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row grow>
|
<Row grow>
|
||||||
<Col sm={12} top="xs" md={5} margin="xl" overflow>
|
<Col sm={12} top="xs" md={5} margin="xl" overflow>
|
||||||
<List style={listStyle}>
|
<List style={listStyle}>
|
||||||
<BalanceInfo tokens={tokens} onMoveFunds={this.onMoveTokens} />
|
<BalanceInfo tokens={tokens} onMoveFunds={this.onMoveTokens} safeAddress={address} />
|
||||||
<Owners
|
<Owners
|
||||||
owners={safe.owners}
|
owners={safe.owners}
|
||||||
onAddOwner={this.onAddOwner}
|
onAddOwner={this.onAddOwner}
|
||||||
|
@ -123,7 +124,7 @@ class GnoSafe extends React.PureComponent<SafeProps, State> {
|
||||||
onRemoveOwner={this.onRemoveOwner}
|
onRemoveOwner={this.onRemoveOwner}
|
||||||
/>
|
/>
|
||||||
<Confirmations confirmations={safe.get('threshold')} onEditThreshold={this.onEditThreshold} />
|
<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} />
|
<DailyLimit balance={ethBalance} dailyLimit={safe.get('dailyLimit')} onWithdraw={this.onWithdraw} onEditDailyLimit={this.onEditDailyLimit} />
|
||||||
<MultisigTx onSeeTxs={this.onListTransactions} />
|
<MultisigTx onSeeTxs={this.onListTransactions} />
|
||||||
</List>
|
</List>
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { type Token } from '~/routes/tokens/store/model/token'
|
||||||
import { createTransaction } from '~/wallets/createTransactions'
|
import { createTransaction } from '~/wallets/createTransactions'
|
||||||
import { EMPTY_DATA } from '~/wallets/ethTransactions'
|
import { EMPTY_DATA } from '~/wallets/ethTransactions'
|
||||||
import { toNative } from '~/wallets/tokens'
|
import { toNative } from '~/wallets/tokens'
|
||||||
|
import { isEther } from '~/utils/tokens'
|
||||||
import actions, { type Actions } from './actions'
|
import actions, { type Actions } from './actions'
|
||||||
import selector, { type SelectorProps } from './selector'
|
import selector, { type SelectorProps } from './selector'
|
||||||
import SendTokenForm, { TKN_DESTINATION_PARAM, TKN_VALUE_PARAM } from './SendTokenForm'
|
import SendTokenForm, { TKN_DESTINATION_PARAM, TKN_VALUE_PARAM } from './SendTokenForm'
|
||||||
|
@ -31,8 +32,6 @@ type State = {
|
||||||
|
|
||||||
export const SEE_TXS_BUTTON_TEXT = 'VISIT TXS'
|
export const SEE_TXS_BUTTON_TEXT = 'VISIT TXS'
|
||||||
|
|
||||||
const isEther = (symbol: string) => symbol === 'ETH'
|
|
||||||
|
|
||||||
const getTransferData = async (tokenAddress: string, to: string, amount: BigNumber) => {
|
const getTransferData = async (tokenAddress: string, to: string, amount: BigNumber) => {
|
||||||
const StandardToken = await getStandardTokenContract()
|
const StandardToken = await getStandardTokenContract()
|
||||||
const myToken = await StandardToken.at(tokenAddress)
|
const myToken = await StandardToken.at(tokenAddress)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as MuiList from '@material-ui/core/List'
|
import MuiList from '@material-ui/core/List'
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import Block from '~/components/layout/Block'
|
import Block from '~/components/layout/Block'
|
||||||
import Col from '~/components/layout/Col'
|
import Col from '~/components/layout/Col'
|
||||||
|
@ -24,6 +24,7 @@ type State = {
|
||||||
|
|
||||||
const listStyle = {
|
const listStyle = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
paddingBottom: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
class TokenLayout extends React.PureComponent<TokenProps, State> {
|
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>
|
<Col sm={12} top="xs" md={5} margin="xl" overflow>
|
||||||
<MuiList style={listStyle}>
|
<MuiList style={listStyle}>
|
||||||
{tokens.map((token: Token) => (<TokenComponent
|
{tokens.map((token: Token) => (<TokenComponent
|
||||||
|
key={token.get('symbol')}
|
||||||
token={token}
|
token={token}
|
||||||
onDisableToken={this.onDisableToken}
|
onDisableToken={this.onDisableToken}
|
||||||
onEnableToken={this.onEnableToken}
|
onEnableToken={this.onEnableToken}
|
||||||
|
|
|
@ -3,12 +3,12 @@ import * as React from 'react'
|
||||||
import { type Token } from '~/routes/tokens/store/model/token'
|
import { type Token } from '~/routes/tokens/store/model/token'
|
||||||
import { withStyles } from '@material-ui/core/styles'
|
import { withStyles } from '@material-ui/core/styles'
|
||||||
import Block from '~/components/layout/Block'
|
import Block from '~/components/layout/Block'
|
||||||
import Bold from '~/components/layout/Bold'
|
|
||||||
import Checkbox from '@material-ui/core/Checkbox'
|
import Checkbox from '@material-ui/core/Checkbox'
|
||||||
import Card from '@material-ui/core/Card'
|
import Card from '@material-ui/core/Card'
|
||||||
import CardContent from '@material-ui/core/CardContent'
|
import CardContent from '@material-ui/core/CardContent'
|
||||||
import CardMedia from '@material-ui/core/CardMedia'
|
import CardMedia from '@material-ui/core/CardMedia'
|
||||||
import Typography from '@material-ui/core/Typography'
|
import Typography from '@material-ui/core/Typography'
|
||||||
|
import { isEther } from '~/utils/tokens'
|
||||||
// import Delete from '@material-ui/icons/Delete'
|
// import Delete from '@material-ui/icons/Delete'
|
||||||
// import IconButton from '@material-ui/core/IconButton'
|
// import IconButton from '@material-ui/core/IconButton'
|
||||||
import { type WithStyles } from '~/theme/mui'
|
import { type WithStyles } from '~/theme/mui'
|
||||||
|
@ -24,7 +24,7 @@ type State = {
|
||||||
checked: boolean,
|
checked: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = theme => ({
|
const styles = () => ({
|
||||||
card: {
|
card: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
},
|
},
|
||||||
|
@ -36,18 +36,9 @@ const styles = theme => ({
|
||||||
flex: '1 0 auto',
|
flex: '1 0 auto',
|
||||||
},
|
},
|
||||||
cover: {
|
cover: {
|
||||||
width: 45,
|
width: 150,
|
||||||
height: 45,
|
margin: 10,
|
||||||
},
|
backgroundSize: '50%',
|
||||||
controls: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
paddingLeft: theme.spacing.unit,
|
|
||||||
paddingBottom: theme.spacing.unit,
|
|
||||||
},
|
|
||||||
playIcon: {
|
|
||||||
height: 38,
|
|
||||||
width: 38,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -60,14 +51,15 @@ class TokenComponent extends React.Component<Props, State> {
|
||||||
|
|
||||||
handleChange = (e: SyntheticInputEvent<HTMLInputElement>) => {
|
handleChange = (e: SyntheticInputEvent<HTMLInputElement>) => {
|
||||||
const { checked } = e.target
|
const { checked } = e.target
|
||||||
const callback = checked ? this.props.onDisableToken : this.props.onDisableToken
|
const callback = checked ? this.props.onEnableToken : this.props.onDisableToken
|
||||||
this.setState(() => ({ checked: e.target.checked }), () => callback(this.props.token))
|
this.setState(() => ({ checked }), () => callback(this.props.token))
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { classes, token } = this.props
|
const { classes, token } = this.props
|
||||||
const name = token.get('name')
|
const name = token.get('name')
|
||||||
const symbol = token.get('symbol')
|
const symbol = token.get('symbol')
|
||||||
|
const disabled = isEther(symbol)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className={classes.card}>
|
<Card className={classes.card}>
|
||||||
|
@ -75,25 +67,23 @@ class TokenComponent extends React.Component<Props, State> {
|
||||||
<CardContent className={classes.content}>
|
<CardContent className={classes.content}>
|
||||||
<Typography variant="headline">{name}</Typography>
|
<Typography variant="headline">{name}</Typography>
|
||||||
<Typography variant="subheading" color="textSecondary">
|
<Typography variant="subheading" color="textSecondary">
|
||||||
|
<Checkbox
|
||||||
|
disabled={disabled}
|
||||||
|
checked={this.state.checked}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
{symbol}
|
{symbol}
|
||||||
</Typography>
|
</Typography>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
</Block>
|
||||||
|
{/*
|
||||||
<Block className={classes.controls}>
|
<Block className={classes.controls}>
|
||||||
<Bold>
|
|
||||||
{symbol}
|
|
||||||
</Bold>
|
|
||||||
<Checkbox
|
|
||||||
checked={this.state.checked}
|
|
||||||
onChange={this.handleChange}
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
{/*
|
|
||||||
<IconButton aria-label="Delete" onClick={this.onRemoveClick}>
|
<IconButton aria-label="Delete" onClick={this.onRemoveClick}>
|
||||||
<Delete />
|
<Delete />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
*/}
|
|
||||||
</Block>
|
</Block>
|
||||||
</Block>
|
*/}
|
||||||
<CardMedia
|
<CardMedia
|
||||||
className={classes.cover}
|
className={classes.cover}
|
||||||
image={token.get('logoUrl')}
|
image={token.get('logoUrl')}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import enableToken from '~/routes/tokens/store/actions/enableToken'
|
import enableToken from '~/routes/tokens/store/actions/enableToken'
|
||||||
import disableToken from '~/routes/tokens/store/actions/disableToken'
|
import disableToken from '~/routes/tokens/store/actions/disableToken'
|
||||||
|
import { fetchTokens } from '~/routes/tokens/store/actions/fetchTokens'
|
||||||
|
|
||||||
export type Actions = {
|
export type Actions = {
|
||||||
enableToken: typeof enableToken,
|
enableToken: typeof enableToken,
|
||||||
|
@ -10,4 +11,5 @@ export type Actions = {
|
||||||
export default {
|
export default {
|
||||||
enableToken,
|
enableToken,
|
||||||
disableToken,
|
disableToken,
|
||||||
|
fetchTokens,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,24 @@ import * as React from 'react'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import Page from '~/components/layout/Page'
|
import Page from '~/components/layout/Page'
|
||||||
import Layout from '~/routes/tokens/component/Layout'
|
import Layout from '~/routes/tokens/component/Layout'
|
||||||
|
import { fetchTokens } from '~/routes/tokens/store/actions/fetchTokens'
|
||||||
import selector, { type SelectorProps } from './selector'
|
import selector, { type SelectorProps } from './selector'
|
||||||
import actions, { type Actions } from './actions'
|
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> {
|
class TokensView extends React.PureComponent<Props> {
|
||||||
|
componentDidUpdate() {
|
||||||
|
const { safeAddress } = this.props
|
||||||
|
|
||||||
|
if (this.props.tokens.count() === 0) {
|
||||||
|
this.props.fetchTokens(safeAddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
tokens, addresses, safe, disableToken, enableToken,
|
tokens, addresses, safe, disableToken, enableToken,
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { List } from 'immutable'
|
||||||
import { createStructuredSelector } from 'reselect'
|
import { createStructuredSelector } from 'reselect'
|
||||||
import { tokenListSelector, tokenAddressesSelector } from '~/routes/tokens/store/selectors'
|
import { tokenListSelector, tokenAddressesSelector } from '~/routes/tokens/store/selectors'
|
||||||
import { type Safe } from '~/routes/safe/store/model/safe'
|
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'
|
import { type Token } from '~/routes/tokens/store/model/token'
|
||||||
|
|
||||||
export type SelectorProps = {
|
export type SelectorProps = {
|
||||||
|
@ -14,6 +14,7 @@ export type SelectorProps = {
|
||||||
|
|
||||||
export default createStructuredSelector({
|
export default createStructuredSelector({
|
||||||
safe: safeSelector,
|
safe: safeSelector,
|
||||||
|
safeAddress: safeParamAddressSelector,
|
||||||
tokens: tokenListSelector,
|
tokens: tokenListSelector,
|
||||||
addresses: tokenAddressesSelector,
|
addresses: tokenAddressesSelector,
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
// @flow
|
||||||
|
export const isEther = (symbol: string) => symbol === 'ETH'
|
Loading…
Reference in New Issue