Merge pull request #22 from gnosis/feature/WA-238-add-daily-limit
WA-238 - Refactor Safe component
This commit is contained in:
commit
92f092c0d1
|
@ -104,7 +104,8 @@
|
||||||
"material-ui-icons": "^1.0.0-beta.35",
|
"material-ui-icons": "^1.0.0-beta.35",
|
||||||
"react-final-form": "^3.1.2",
|
"react-final-form": "^3.1.2",
|
||||||
"react-loadable": "^5.3.1",
|
"react-loadable": "^5.3.1",
|
||||||
"react-router-dom": "^4.2.2"
|
"react-router-dom": "^4.2.2",
|
||||||
|
"recompose": "^0.27.0"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"verbose": true,
|
"verbose": true,
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
// @flow
|
||||||
|
import * as React from 'react'
|
||||||
|
import { ListItemText } from 'material-ui/List'
|
||||||
|
import { withStyles } from 'material-ui/styles'
|
||||||
|
import { type WithStyles } from '~/theme/mui'
|
||||||
|
|
||||||
|
type Props = WithStyles & {
|
||||||
|
primary: string,
|
||||||
|
secondary: string,
|
||||||
|
cut?: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
itemTextSecondary: {
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
overflow: 'hidden',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const GnoListItemText = ({
|
||||||
|
primary, secondary, classes, cut = false,
|
||||||
|
}: Props) => {
|
||||||
|
const cutStyle = cut ? {
|
||||||
|
secondary: classes.itemTextSecondary,
|
||||||
|
} : undefined
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ListItemText
|
||||||
|
classes={cutStyle}
|
||||||
|
inset
|
||||||
|
primary={primary}
|
||||||
|
secondary={secondary}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withStyles(styles)(GnoListItemText)
|
|
@ -0,0 +1,12 @@
|
||||||
|
// @flow
|
||||||
|
import { withStateHandlers } from 'recompose'
|
||||||
|
|
||||||
|
export type Open = {
|
||||||
|
open: boolean,
|
||||||
|
toggle: () => void,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withStateHandlers(
|
||||||
|
() => ({ open: false }),
|
||||||
|
{ toggle: ({ open }) => () => ({ open: !open }) },
|
||||||
|
)
|
|
@ -11,7 +11,7 @@ type Size = 'sm' | 'md' | 'lg' | 'xl'
|
||||||
type Props = {
|
type Props = {
|
||||||
margin?: Size,
|
margin?: Size,
|
||||||
padding?: Size,
|
padding?: Size,
|
||||||
center?: boolean,
|
align?: 'center' | 'right',
|
||||||
children: React$Node,
|
children: React$Node,
|
||||||
className?: string,
|
className?: string,
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,12 @@ type Props = {
|
||||||
class Block extends PureComponent<Props> {
|
class Block extends PureComponent<Props> {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
margin, padding, center, children, className, ...props
|
margin, padding, align, children, className, ...props
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const paddingStyle = padding ? capitalize(padding, 'padding') : undefined
|
const paddingStyle = padding ? capitalize(padding, 'padding') : undefined
|
||||||
return (
|
return (
|
||||||
<div className={cx(className, 'block', margin, paddingStyle, { center })} {...props}>
|
<div className={cx(className, 'block', margin, paddingStyle, align)} {...props}>
|
||||||
{ children }
|
{ children }
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
.block {
|
.block {
|
||||||
display: inline-block;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +36,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.center {
|
.center {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
}
|
}
|
|
@ -16,6 +16,7 @@ type Props = {
|
||||||
around?: 'xs' | 'sm' | 'md' | 'lg',
|
around?: 'xs' | 'sm' | 'md' | 'lg',
|
||||||
between?: 'xs' | 'sm' | 'md' | 'lg',
|
between?: 'xs' | 'sm' | 'md' | 'lg',
|
||||||
margin?: 'sm' | 'md' | 'lg' | 'xl',
|
margin?: 'sm' | 'md' | 'lg' | 'xl',
|
||||||
|
layout?: 'inherit' | 'block',
|
||||||
xs?: number | boolean,
|
xs?: number | boolean,
|
||||||
sm?: number | boolean,
|
sm?: number | boolean,
|
||||||
md?: number | boolean,
|
md?: number | boolean,
|
||||||
|
@ -29,7 +30,7 @@ type Props = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Col = ({
|
const Col = ({
|
||||||
children, margin,
|
children, margin, layout = 'inherit',
|
||||||
xs, sm, md, lg,
|
xs, sm, md, lg,
|
||||||
start, center, end, top, middle, bottom, around, between,
|
start, center, end, top, middle, bottom, around, between,
|
||||||
xsOffset, smOffset, mdOffset, lgOffset,
|
xsOffset, smOffset, mdOffset, lgOffset,
|
||||||
|
@ -54,6 +55,7 @@ const Col = ({
|
||||||
smOffset ? capitalize(smOffset, 'smOffset') : undefined,
|
smOffset ? capitalize(smOffset, 'smOffset') : undefined,
|
||||||
mdOffset ? capitalize(mdOffset, 'mdOffset') : undefined,
|
mdOffset ? capitalize(mdOffset, 'mdOffset') : undefined,
|
||||||
lgOffset ? capitalize(lgOffset, 'lgOffset') : undefined,
|
lgOffset ? capitalize(lgOffset, 'lgOffset') : undefined,
|
||||||
|
layout,
|
||||||
props.className,
|
props.className,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
.col {
|
.col {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
display: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inherit {
|
||||||
|
display: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.marginSm {
|
.marginSm {
|
||||||
|
@ -128,11 +136,11 @@
|
||||||
|
|
||||||
@define-mixin autoWidth $size {
|
@define-mixin autoWidth $size {
|
||||||
.$(size) {
|
.$(size) {
|
||||||
-ms-flex-positive: 1;
|
-ms-flex-positive: 1;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
-ms-flex-preferred-size: 0;
|
-ms-flex-preferred-size: 0;
|
||||||
flex-basis: 0;
|
flex-basis: 0;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
// @flow
|
|
||||||
import * as React from 'react'
|
|
||||||
import Block from '~/components/layout/Block'
|
|
||||||
import Bold from '~/components/layout/Bold'
|
|
||||||
import Col from '~/components/layout/Col'
|
|
||||||
import Paragraph from '~/components/layout/Paragraph'
|
|
||||||
import Row from '~/components/layout/Row'
|
|
||||||
import Table, { TableBody, TableCell, TableHead, TableRow } from '~/components/layout/Table'
|
|
||||||
import { type Safe } from '~/routes/safe/store/model/safe'
|
|
||||||
|
|
||||||
type SafeProps = {
|
|
||||||
safe: Safe,
|
|
||||||
balance: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
const GnoSafe = ({ safe, balance }: SafeProps) => (
|
|
||||||
<React.Fragment>
|
|
||||||
<Row>
|
|
||||||
<Col xs={12}>
|
|
||||||
<Paragraph size="lg">
|
|
||||||
<Bold>{safe.name.toUpperCase()}</Bold>
|
|
||||||
</Paragraph>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Paragraph size="lg">
|
|
||||||
<Bold>Balance</Bold>
|
|
||||||
</Paragraph>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Block>
|
|
||||||
<Paragraph>
|
|
||||||
{balance} - ETH
|
|
||||||
</Paragraph>
|
|
||||||
</Block>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Paragraph size="lg">
|
|
||||||
<Bold>Address</Bold>
|
|
||||||
</Paragraph>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Block>
|
|
||||||
<Paragraph>
|
|
||||||
{safe.address}
|
|
||||||
</Paragraph>
|
|
||||||
</Block>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Paragraph size="lg">
|
|
||||||
<Bold>Number of required confirmations per transaction</Bold>
|
|
||||||
</Paragraph>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Paragraph>
|
|
||||||
{safe.get('confirmations')}
|
|
||||||
</Paragraph>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Paragraph size="lg">
|
|
||||||
<Bold>Owners</Bold>
|
|
||||||
</Paragraph>
|
|
||||||
</Row>
|
|
||||||
<Row margin="lg">
|
|
||||||
<Table size={700}>
|
|
||||||
<TableHead>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell>Name</TableCell>
|
|
||||||
<TableCell>Adress</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
|
||||||
{safe.owners.map(owner => (
|
|
||||||
<TableRow key={safe.address}>
|
|
||||||
<TableCell>{owner.name}</TableCell>
|
|
||||||
<TableCell>{owner.address}</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
<div />
|
|
||||||
</Row>
|
|
||||||
</React.Fragment>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default GnoSafe
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
// @flow
|
||||||
|
import * as React from 'react'
|
||||||
|
import { ListItem } from 'material-ui/List'
|
||||||
|
import Avatar from 'material-ui/Avatar'
|
||||||
|
import Mail from 'material-ui-icons/Mail'
|
||||||
|
import ListItemText from '~/components/List/ListItemText'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
address: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
const Address = ({ address }: Props) => (
|
||||||
|
<ListItem>
|
||||||
|
<Avatar>
|
||||||
|
<Mail />
|
||||||
|
</Avatar>
|
||||||
|
<ListItemText primary="Safe Address" secondary={address} cut />
|
||||||
|
</ListItem>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default Address
|
|
@ -0,0 +1,20 @@
|
||||||
|
// @flow
|
||||||
|
import * as React from 'react'
|
||||||
|
import { ListItem, ListItemText } from 'material-ui/List'
|
||||||
|
import Avatar from 'material-ui/Avatar'
|
||||||
|
import AccountBalance from 'material-ui-icons/AccountBalance'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
balance: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
const Balance = ({ balance }: Props) => (
|
||||||
|
<ListItem>
|
||||||
|
<Avatar>
|
||||||
|
<AccountBalance />
|
||||||
|
</Avatar>
|
||||||
|
<ListItemText primary="Balance" secondary={`${balance} ETH`} />
|
||||||
|
</ListItem>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default Balance
|
|
@ -0,0 +1,25 @@
|
||||||
|
// @flow
|
||||||
|
import * as React from 'react'
|
||||||
|
import { ListItem } from 'material-ui/List'
|
||||||
|
import Avatar from 'material-ui/Avatar'
|
||||||
|
import DoneAll from 'material-ui-icons/DoneAll'
|
||||||
|
import ListItemText from '~/components/List/ListItemText'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
confirmations: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
const Confirmations = ({ confirmations }: Props) => (
|
||||||
|
<ListItem>
|
||||||
|
<Avatar>
|
||||||
|
<DoneAll />
|
||||||
|
</Avatar>
|
||||||
|
<ListItemText
|
||||||
|
primary="Confirmations"
|
||||||
|
secondary={`${confirmations} required confirmations per transaction`}
|
||||||
|
cut
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default Confirmations
|
|
@ -0,0 +1,58 @@
|
||||||
|
// @flow
|
||||||
|
import * as React from 'react'
|
||||||
|
import openHoc, { type Open } from '~/components/hoc/OpenHoc'
|
||||||
|
import { withStyles } from 'material-ui/styles'
|
||||||
|
import Collapse from 'material-ui/transitions/Collapse'
|
||||||
|
import ListItemText from '~/components/List/ListItemText'
|
||||||
|
import List, { ListItem, ListItemIcon } from 'material-ui/List'
|
||||||
|
import Avatar from 'material-ui/Avatar'
|
||||||
|
import Group from 'material-ui-icons/Group'
|
||||||
|
import Person from 'material-ui-icons/Person'
|
||||||
|
import ExpandLess from 'material-ui-icons/ExpandLess'
|
||||||
|
import ExpandMore from 'material-ui-icons/ExpandMore'
|
||||||
|
import { type OwnerProps } from '~/routes/safe/store/model/owner'
|
||||||
|
import { type WithStyles } from '~/theme/mui'
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
nested: {
|
||||||
|
paddingLeft: '40px',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = Open & WithStyles & {
|
||||||
|
owners: List<OwnerProps>,
|
||||||
|
}
|
||||||
|
|
||||||
|
const Owners = openHoc(({
|
||||||
|
open, toggle, owners, classes,
|
||||||
|
}: Props) => (
|
||||||
|
<React.Fragment>
|
||||||
|
<ListItem onClick={toggle}>
|
||||||
|
<Avatar>
|
||||||
|
<Group />
|
||||||
|
</Avatar>
|
||||||
|
<ListItemText primary="Owners" secondary={`${owners.size} owners`} />
|
||||||
|
<ListItemIcon>
|
||||||
|
{open ? <ExpandLess /> : <ExpandMore />}
|
||||||
|
</ListItemIcon>
|
||||||
|
</ListItem>
|
||||||
|
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||||
|
<List component="div" disablePadding>
|
||||||
|
{owners.map(owner => (
|
||||||
|
<ListItem key={owner.address} button className={classes.nested}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<Person />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText
|
||||||
|
cut
|
||||||
|
primary={owner.name}
|
||||||
|
secondary={owner.address}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</Collapse>
|
||||||
|
</React.Fragment>
|
||||||
|
))
|
||||||
|
|
||||||
|
export default withStyles(styles)(Owners)
|
|
@ -0,0 +1,58 @@
|
||||||
|
// @flow
|
||||||
|
import * as React from 'react'
|
||||||
|
import Block from '~/components/layout/Block'
|
||||||
|
import Col from '~/components/layout/Col'
|
||||||
|
import Bold from '~/components/layout/Bold'
|
||||||
|
import Paragraph from '~/components/layout/Paragraph'
|
||||||
|
import Row from '~/components/layout/Row'
|
||||||
|
import { type Safe } from '~/routes/safe/store/model/safe'
|
||||||
|
import List from 'material-ui/List'
|
||||||
|
|
||||||
|
import Address from './Address'
|
||||||
|
import Balance from './Balance'
|
||||||
|
import Owners from './Owners'
|
||||||
|
import Confirmations from './Confirmations'
|
||||||
|
|
||||||
|
type SafeProps = {
|
||||||
|
safe: Safe,
|
||||||
|
balance: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
const listStyle = {
|
||||||
|
width: '100%',
|
||||||
|
}
|
||||||
|
|
||||||
|
class GnoSafe extends React.PureComponent<SafeProps> {
|
||||||
|
render() {
|
||||||
|
const { safe, balance } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row>
|
||||||
|
<Col xs={12} top="xs" sm={4} margin="xl">
|
||||||
|
<List style={listStyle}>
|
||||||
|
<Balance balance={balance} />
|
||||||
|
<Owners owners={safe.owners} />
|
||||||
|
<Confirmations confirmations={safe.get('confirmations')} />
|
||||||
|
<Address address={safe.get('address')} />
|
||||||
|
</List>
|
||||||
|
</Col>
|
||||||
|
<Col xs={12} center="xs" sm={8} margin="xl" layout="block">
|
||||||
|
<Block margin="xl">
|
||||||
|
<Paragraph size="lg" noMargin align="right">
|
||||||
|
<Bold>{safe.name.toUpperCase()}</Bold>
|
||||||
|
</Paragraph>
|
||||||
|
</Block>
|
||||||
|
<Block>
|
||||||
|
Extra info will be placed here
|
||||||
|
</Block>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
<Paragraph size="lg">
|
||||||
|
<Bold>{safe.name.toUpperCase()}</Bold>
|
||||||
|
*/
|
||||||
|
export default GnoSafe
|
|
@ -1,7 +1,12 @@
|
||||||
import red from 'material-ui/colors/red';
|
// @flow
|
||||||
|
import red from 'material-ui/colors/red'
|
||||||
import { createMuiTheme } from 'material-ui/styles'
|
import { createMuiTheme } from 'material-ui/styles'
|
||||||
import { primary, secondary } from './variables'
|
import { primary, secondary } from './variables'
|
||||||
|
|
||||||
|
export type WithStyles = {
|
||||||
|
classes: Object,
|
||||||
|
}
|
||||||
|
|
||||||
const palette = {
|
const palette = {
|
||||||
primary: {
|
primary: {
|
||||||
main: primary,
|
main: primary,
|
||||||
|
@ -18,7 +23,7 @@ const palette = {
|
||||||
// see https://github.com/mui-org/material-ui/blob/v1-beta/src/styles/createMuiTheme.js
|
// see https://github.com/mui-org/material-ui/blob/v1-beta/src/styles/createMuiTheme.js
|
||||||
export default createMuiTheme({
|
export default createMuiTheme({
|
||||||
typography: {
|
typography: {
|
||||||
fontFamily: 'Montserrat,sans-serif'
|
fontFamily: 'Montserrat,sans-serif',
|
||||||
},
|
},
|
||||||
palette,
|
palette,
|
||||||
})
|
})
|
||||||
|
|
15
yarn.lock
15
yarn.lock
|
@ -9249,6 +9249,10 @@ react-lifecycles-compat@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-1.0.2.tgz#551d8b1d156346e5fcf30ffac9b32ce3f78b8850"
|
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-1.0.2.tgz#551d8b1d156346e5fcf30ffac9b32ce3f78b8850"
|
||||||
|
|
||||||
|
react-lifecycles-compat@^3.0.2:
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.2.tgz#7279047275bd727a912e25f734c0559527e84eff"
|
||||||
|
|
||||||
react-loadable@^5.3.1:
|
react-loadable@^5.3.1:
|
||||||
version "5.3.1"
|
version "5.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-loadable/-/react-loadable-5.3.1.tgz#9699e9a08fed49bacd69caaa282034b62a76bcdd"
|
resolved "https://registry.yarnpkg.com/react-loadable/-/react-loadable-5.3.1.tgz#9699e9a08fed49bacd69caaa282034b62a76bcdd"
|
||||||
|
@ -9559,6 +9563,17 @@ recompose@^0.26.0:
|
||||||
hoist-non-react-statics "^2.3.1"
|
hoist-non-react-statics "^2.3.1"
|
||||||
symbol-observable "^1.0.4"
|
symbol-observable "^1.0.4"
|
||||||
|
|
||||||
|
recompose@^0.27.0:
|
||||||
|
version "0.27.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/recompose/-/recompose-0.27.0.tgz#8230ebd651bf1159097006f79083fe224b1501cf"
|
||||||
|
dependencies:
|
||||||
|
babel-runtime "^6.26.0"
|
||||||
|
change-emitter "^0.1.2"
|
||||||
|
fbjs "^0.8.1"
|
||||||
|
hoist-non-react-statics "^2.3.1"
|
||||||
|
react-lifecycles-compat "^3.0.2"
|
||||||
|
symbol-observable "^1.0.4"
|
||||||
|
|
||||||
recursive-readdir@2.2.1:
|
recursive-readdir@2.2.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.1.tgz#90ef231d0778c5ce093c9a48d74e5c5422d13a99"
|
resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.1.tgz#90ef231d0778c5ce093c9a48d74e5c5422d13a99"
|
||||||
|
|
Loading…
Reference in New Issue