Merge pull request #22 from gnosis/feature/WA-238-add-daily-limit

WA-238 - Refactor Safe component
This commit is contained in:
Adolfo Panizo 2018-04-27 15:26:12 +02:00 committed by GitHub
commit 92f092c0d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 286 additions and 104 deletions

View File

@ -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,

View File

@ -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)

View File

@ -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 }) },
)

View File

@ -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>
) )

View File

@ -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;
} }

View File

@ -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,
) )

View File

@ -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%;
} }
} }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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,
}) })

View File

@ -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"