commit
7929ff5908
27
package.json
27
package.json
|
@ -33,14 +33,14 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gnosis.pm/safe-contracts": "^1.0.0",
|
"@gnosis.pm/safe-contracts": "^1.0.0",
|
||||||
"@gnosis.pm/util-contracts": "2.0.4",
|
"@gnosis.pm/util-contracts": "2.0.4",
|
||||||
"@material-ui/core": "4.4.3",
|
"@material-ui/core": "4.5.0",
|
||||||
"@material-ui/icons": "4.4.3",
|
"@material-ui/icons": "4.4.3",
|
||||||
"@testing-library/jest-dom": "4.1.0",
|
"@testing-library/jest-dom": "4.1.0",
|
||||||
"@welldone-software/why-did-you-render": "3.3.5",
|
"@welldone-software/why-did-you-render": "3.3.5",
|
||||||
"axios": "0.19.0",
|
"axios": "0.19.0",
|
||||||
"bignumber.js": "9.0.0",
|
"bignumber.js": "9.0.0",
|
||||||
"connected-react-router": "6.5.2",
|
"connected-react-router": "6.5.2",
|
||||||
"date-fns": "2.3.0",
|
"date-fns": "2.4.1",
|
||||||
"ethereum-ens": "0.7.8",
|
"ethereum-ens": "0.7.8",
|
||||||
"final-form": "4.18.5",
|
"final-form": "4.18.5",
|
||||||
"history": "4.10.1",
|
"history": "4.10.1",
|
||||||
|
@ -50,15 +50,16 @@
|
||||||
"notistack": "https://github.com/gnosis/notistack.git#v0.9.4",
|
"notistack": "https://github.com/gnosis/notistack.git#v0.9.4",
|
||||||
"optimize-css-assets-webpack-plugin": "5.0.3",
|
"optimize-css-assets-webpack-plugin": "5.0.3",
|
||||||
"qrcode.react": "^0.9.3",
|
"qrcode.react": "^0.9.3",
|
||||||
"react": "16.9.0",
|
"react": "16.10.2",
|
||||||
"react-dom": "16.9.0",
|
"react-dom": "16.10.2",
|
||||||
"react-final-form": "6.3.0",
|
"react-final-form": "6.3.0",
|
||||||
"react-final-form-listeners": "^1.0.2",
|
"react-final-form-listeners": "^1.0.2",
|
||||||
"react-hot-loader": "4.12.14",
|
"react-hot-loader": "4.12.14",
|
||||||
"react-infinite-scroll-component": "4.5.3",
|
"react-infinite-scroll-component": "4.5.3",
|
||||||
"react-qr-reader": "^2.2.1",
|
"react-qr-reader": "^2.2.1",
|
||||||
"react-redux": "7.1.1",
|
"react-redux": "7.1.1",
|
||||||
"react-router-dom": "^5.1.0",
|
"react-router-dom": "5.1.2",
|
||||||
|
"react-window": "^1.8.5",
|
||||||
"recompose": "^0.30.0",
|
"recompose": "^0.30.0",
|
||||||
"redux": "4.0.4",
|
"redux": "4.0.4",
|
||||||
"redux-actions": "^2.6.5",
|
"redux-actions": "^2.6.5",
|
||||||
|
@ -96,7 +97,7 @@
|
||||||
"@storybook/addon-knobs": "5.2.1",
|
"@storybook/addon-knobs": "5.2.1",
|
||||||
"@storybook/addon-links": "5.2.1",
|
"@storybook/addon-links": "5.2.1",
|
||||||
"@storybook/react": "5.2.1",
|
"@storybook/react": "5.2.1",
|
||||||
"@testing-library/react": "9.1.4",
|
"@testing-library/react": "9.3.0",
|
||||||
"autoprefixer": "9.6.1",
|
"autoprefixer": "9.6.1",
|
||||||
"babel-core": "^7.0.0-bridge.0",
|
"babel-core": "^7.0.0-bridge.0",
|
||||||
"babel-eslint": "10.0.3",
|
"babel-eslint": "10.0.3",
|
||||||
|
@ -108,17 +109,17 @@
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"css-loader": "3.2.0",
|
"css-loader": "3.2.0",
|
||||||
"detect-port": "^1.3.0",
|
"detect-port": "^1.3.0",
|
||||||
"eslint": "6.4.0",
|
"eslint": "5.16.0",
|
||||||
"eslint-config-airbnb": "18.0.1",
|
"eslint-config-airbnb": "18.0.1",
|
||||||
"eslint-plugin-flowtype": "4.3.0",
|
"eslint-plugin-flowtype": "4.3.0",
|
||||||
"eslint-plugin-import": "2.18.2",
|
"eslint-plugin-import": "2.18.2",
|
||||||
"eslint-plugin-jest": "22.17.0",
|
"eslint-plugin-jest": "22.17.0",
|
||||||
"eslint-plugin-jsx-a11y": "6.2.3",
|
"eslint-plugin-jsx-a11y": "6.2.3",
|
||||||
"eslint-plugin-react": "7.14.3",
|
"eslint-plugin-react": "7.15.0",
|
||||||
"ethereumjs-abi": "0.6.8",
|
"ethereumjs-abi": "0.6.8",
|
||||||
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||||
"file-loader": "4.2.0",
|
"file-loader": "4.2.0",
|
||||||
"flow-bin": "0.108.0",
|
"flow-bin": "0.109.0",
|
||||||
"fs-extra": "8.1.0",
|
"fs-extra": "8.1.0",
|
||||||
"html-loader": "^0.5.5",
|
"html-loader": "^0.5.5",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
|
@ -135,15 +136,15 @@
|
||||||
"storybook-host": "5.1.0",
|
"storybook-host": "5.1.0",
|
||||||
"storybook-router": "^0.3.4",
|
"storybook-router": "^0.3.4",
|
||||||
"style-loader": "1.0.0",
|
"style-loader": "1.0.0",
|
||||||
"truffle": "5.0.37",
|
"truffle": "5.0.39",
|
||||||
"truffle-contract": "4.0.31",
|
"truffle-contract": "4.0.31",
|
||||||
"truffle-solidity-loader": "0.1.32",
|
"truffle-solidity-loader": "0.1.32",
|
||||||
"uglifyjs-webpack-plugin": "2.2.0",
|
"uglifyjs-webpack-plugin": "2.2.0",
|
||||||
"url-loader": "^2.1.0",
|
"url-loader": "^2.1.0",
|
||||||
"webpack": "4.41.0",
|
"webpack": "4.41.0",
|
||||||
"webpack-bundle-analyzer": "3.5.1",
|
"webpack-bundle-analyzer": "3.5.2",
|
||||||
"webpack-cli": "3.3.9",
|
"webpack-cli": "3.3.9",
|
||||||
"webpack-dev-server": "3.8.1",
|
"webpack-dev-server": "3.8.2",
|
||||||
"webpack-manifest-plugin": "^2.1.1"
|
"webpack-manifest-plugin": "2.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
17
readme.md
17
readme.md
|
@ -22,21 +22,17 @@ We use [yarn](https://yarnpkg.com) in our infrastacture, so we decided to go wit
|
||||||
|
|
||||||
A step by step series of examples that tell you have to get a development env running
|
A step by step series of examples that tell you have to get a development env running
|
||||||
|
|
||||||
Run ganache in one terminal
|
Install dependencies for the project:
|
||||||
```
|
|
||||||
ganache-cli -b 3
|
|
||||||
```
|
|
||||||
|
|
||||||
Start the project in the other one
|
|
||||||
```
|
```
|
||||||
yarn install
|
yarn install
|
||||||
```
|
```
|
||||||
|
|
||||||
For Rinkeby:
|
For using the Rinkeby services:
|
||||||
```
|
```
|
||||||
yarn start
|
yarn start
|
||||||
```
|
```
|
||||||
For Mainnet:
|
|
||||||
|
If you prefer using Mainnet ones:
|
||||||
```
|
```
|
||||||
yarn start-mainnet
|
yarn start-mainnet
|
||||||
```
|
```
|
||||||
|
@ -122,7 +118,10 @@ We use [SemVer](http://semver.org/) for versioning. For the versions available,
|
||||||
|
|
||||||
## Authors
|
## Authors
|
||||||
|
|
||||||
See the list of [contributors](https://github.com/gnosis/gnosis-team-safe/contributors) who participated in this project.
|
- Germán Martínez([germartinez](https://github.com/germartinez))
|
||||||
|
- Mikhail Mikheev([mikheevm](https://github.com/mikheevm))
|
||||||
|
|
||||||
|
See the full list of [contributors](https://github.com/gnosis/gnosis-team-safe/contributors) who participated in this project.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import Tooltip from '@material-ui/core/Tooltip'
|
import Tooltip from '@material-ui/core/Tooltip'
|
||||||
import { withStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import Img from '~/components/layout/Img'
|
import Img from '~/components/layout/Img'
|
||||||
import { copyToClipboard } from '~/utils/clipboard'
|
import { copyToClipboard } from '~/utils/clipboard'
|
||||||
import { xs } from '~/theme/variables'
|
import { xs } from '~/theme/variables'
|
||||||
import CopyIcon from './copy.svg'
|
import CopyIcon from './copy.svg'
|
||||||
|
|
||||||
const styles = () => ({
|
const useStyles = makeStyles({
|
||||||
container: {
|
container: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
@ -20,19 +20,24 @@ const styles = () => ({
|
||||||
backgroundColor: '#F0EFEE',
|
backgroundColor: '#F0EFEE',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
inreasedPopperZindex: {
|
||||||
|
zIndex: 2001,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
type CopyBtnProps = {
|
type CopyBtnProps = {
|
||||||
content: string,
|
content: string,
|
||||||
classes: Object,
|
increaseZindex?: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
const CopyBtn = ({ content, classes }: CopyBtnProps) => {
|
const CopyBtn = ({ content, increaseZindex = false }: CopyBtnProps) => {
|
||||||
if (!navigator.clipboard) {
|
if (!navigator.clipboard) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const [clicked, setClicked] = useState<boolean>(false)
|
const [clicked, setClicked] = useState<boolean>(false)
|
||||||
|
const classes = useStyles()
|
||||||
|
const customClasses = increaseZindex ? { popper: classes.inreasedPopperZindex } : {}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
|
@ -47,6 +52,7 @@ const CopyBtn = ({ content, classes }: CopyBtnProps) => {
|
||||||
}
|
}
|
||||||
}, 300)
|
}, 300)
|
||||||
}}
|
}}
|
||||||
|
classes={customClasses}
|
||||||
>
|
>
|
||||||
<div className={classes.container}>
|
<div className={classes.container}>
|
||||||
<Img
|
<Img
|
||||||
|
@ -63,4 +69,4 @@ const CopyBtn = ({ content, classes }: CopyBtnProps) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withStyles(styles)(CopyBtn)
|
export default CopyBtn
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Tooltip from '@material-ui/core/Tooltip'
|
import Tooltip from '@material-ui/core/Tooltip'
|
||||||
import { withStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import Img from '~/components/layout/Img'
|
import Img from '~/components/layout/Img'
|
||||||
import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
||||||
import { xs } from '~/theme/variables'
|
import { xs } from '~/theme/variables'
|
||||||
import SearchIcon from './search.svg'
|
import SearchIcon from './search.svg'
|
||||||
|
|
||||||
const styles = () => ({
|
const useStyles = makeStyles({
|
||||||
container: {
|
container: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
@ -19,30 +19,34 @@ const styles = () => ({
|
||||||
backgroundColor: '#F0EFEE',
|
backgroundColor: '#F0EFEE',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
inreasedPopperZindex: {
|
||||||
|
zIndex: 2001,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
type EtherscanBtnProps = {
|
type EtherscanBtnProps = {
|
||||||
type: 'tx' | 'address',
|
type: 'tx' | 'address',
|
||||||
value: string,
|
value: string,
|
||||||
classes: Object,
|
increaseZindex?: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
const EtherscanBtn = ({
|
const EtherscanBtn = ({ type, value, increaseZindex = false }: EtherscanBtnProps) => {
|
||||||
type, value, classes,
|
const classes = useStyles()
|
||||||
}: EtherscanBtnProps) => (
|
const customClasses = increaseZindex ? { popper: classes.inreasedPopperZindex } : {}
|
||||||
<Tooltip title="Show details on Etherscan" placement="top">
|
|
||||||
<a
|
|
||||||
className={classes.container}
|
|
||||||
href={getEtherScanLink(type, value)}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
aria-label="Show details on Etherscan"
|
|
||||||
>
|
|
||||||
<Img src={SearchIcon} height={20} alt="Etherscan" />
|
|
||||||
</a>
|
|
||||||
</Tooltip>
|
|
||||||
)
|
|
||||||
|
|
||||||
const EtherscanBtnWithStyles = withStyles(styles)(EtherscanBtn)
|
return (
|
||||||
|
<Tooltip title="Show details on Etherscan" placement="top" classes={customClasses}>
|
||||||
|
<a
|
||||||
|
className={classes.container}
|
||||||
|
href={getEtherScanLink(type, value)}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
aria-label="Show details on Etherscan"
|
||||||
|
>
|
||||||
|
<Img src={SearchIcon} height={20} alt="Etherscan" />
|
||||||
|
</a>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export default EtherscanBtnWithStyles
|
export default EtherscanBtn
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
// @flow
|
||||||
|
import * as React from 'react'
|
||||||
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
|
import Paragraph from '~/components/layout/Paragraph'
|
||||||
|
import Col from '~/components/layout/Col'
|
||||||
|
import {
|
||||||
|
xs, sm, md, border,
|
||||||
|
} from '~/theme/variables'
|
||||||
|
|
||||||
|
export const TOGGLE_SIDEBAR_BTN_TESTID = 'TOGGLE_SIDEBAR_BTN'
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
container: {
|
||||||
|
flexGrow: 0,
|
||||||
|
padding: `0 ${md}`,
|
||||||
|
},
|
||||||
|
counter: {
|
||||||
|
background: border,
|
||||||
|
padding: `${xs} ${sm}`,
|
||||||
|
borderRadius: '3px',
|
||||||
|
marginLeft: sm,
|
||||||
|
lineHeight: 'normal',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const EarlyAccessLabel = () => {
|
||||||
|
const classes = useStyles()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Col start="xs" middle="xs" className={classes.container}>
|
||||||
|
<Paragraph size="xs" className={classes.counter}>
|
||||||
|
Early access
|
||||||
|
</Paragraph>
|
||||||
|
</Col>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EarlyAccessLabel
|
|
@ -16,6 +16,7 @@ import {
|
||||||
border, sm, md, headerHeight,
|
border, sm, md, headerHeight,
|
||||||
} from '~/theme/variables'
|
} from '~/theme/variables'
|
||||||
import Provider from './Provider'
|
import Provider from './Provider'
|
||||||
|
import EarlyAccessLabel from './EarlyAccessLabel'
|
||||||
import SafeListHeader from './SafeListHeader'
|
import SafeListHeader from './SafeListHeader'
|
||||||
|
|
||||||
const logo = require('../assets/gnosis-safe-logo.svg')
|
const logo = require('../assets/gnosis-safe-logo.svg')
|
||||||
|
@ -66,6 +67,7 @@ const Layout = openHoc(({
|
||||||
<Divider />
|
<Divider />
|
||||||
<SafeListHeader />
|
<SafeListHeader />
|
||||||
<Divider />
|
<Divider />
|
||||||
|
<EarlyAccessLabel />
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<Provider open={open} toggle={toggle} info={providerInfo}>
|
<Provider open={open} toggle={toggle} info={providerInfo}>
|
||||||
{(providerRef) => (
|
{(providerRef) => (
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import OpenInNew from '@material-ui/icons/OpenInNew'
|
|
||||||
import { withStyles } from '@material-ui/core/styles'
|
import { withStyles } from '@material-ui/core/styles'
|
||||||
import Dot from '@material-ui/icons/FiberManualRecord'
|
import Dot from '@material-ui/icons/FiberManualRecord'
|
||||||
|
import EtherscanBtn from '~/components/EtherscanBtn'
|
||||||
|
import CopyBtn from '~/components/CopyBtn'
|
||||||
import Paragraph from '~/components/layout/Paragraph'
|
import Paragraph from '~/components/layout/Paragraph'
|
||||||
import Link from '~/components/layout/Link'
|
|
||||||
import Button from '~/components/layout/Button'
|
import Button from '~/components/layout/Button'
|
||||||
import Identicon from '~/components/Identicon'
|
import Identicon from '~/components/Identicon'
|
||||||
import Hairline from '~/components/layout/Hairline'
|
import Hairline from '~/components/layout/Hairline'
|
||||||
|
@ -14,11 +14,10 @@ import Row from '~/components/layout/Row'
|
||||||
import Block from '~/components/layout/Block'
|
import Block from '~/components/layout/Block'
|
||||||
import Spacer from '~/components/Spacer'
|
import Spacer from '~/components/Spacer'
|
||||||
import {
|
import {
|
||||||
xs, sm, md, lg, background, secondary, warning, connected as connectedBg,
|
xs, sm, md, lg, background, warning, connected as connectedBg,
|
||||||
} from '~/theme/variables'
|
} from '~/theme/variables'
|
||||||
import { upperFirst } from '~/utils/css'
|
import { upperFirst } from '~/utils/css'
|
||||||
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
||||||
import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
|
||||||
import CircleDot from '~/components/Header/component/CircleDot'
|
import CircleDot from '~/components/Header/component/CircleDot'
|
||||||
|
|
||||||
const metamaskIcon = require('../../assets/metamask-icon.svg')
|
const metamaskIcon = require('../../assets/metamask-icon.svg')
|
||||||
|
@ -34,11 +33,6 @@ type Props = {
|
||||||
onDisconnect: Function,
|
onDisconnect: Function,
|
||||||
}
|
}
|
||||||
|
|
||||||
const openIconStyle = {
|
|
||||||
height: '16px',
|
|
||||||
color: secondary,
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = () => ({
|
const styles = () => ({
|
||||||
container: {
|
container: {
|
||||||
padding: `${md} 12px`,
|
padding: `${md} 12px`,
|
||||||
|
@ -65,7 +59,7 @@ const styles = () => ({
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
letterSpacing: '-0.5px',
|
letterSpacing: '-0.5px',
|
||||||
fontSize: '12px',
|
marginRight: sm,
|
||||||
},
|
},
|
||||||
labels: {
|
labels: {
|
||||||
fontSize: '12px',
|
fontSize: '12px',
|
||||||
|
@ -118,14 +112,15 @@ const UserDetails = ({
|
||||||
<CircleDot keySize={30} circleSize={75} dotSize={25} dotTop={50} dotRight={25} mode="warning" hideDot />
|
<CircleDot keySize={30} circleSize={75} dotSize={25} dotTop={50} dotRight={25} mode="warning" hideDot />
|
||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Paragraph className={classes.address} size="xs" noMargin>
|
<Paragraph className={classes.address} size="sm" noMargin>
|
||||||
{address}
|
{address}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
{userAddress && (
|
{userAddress && (
|
||||||
<Link className={classes.open} to={getEtherScanLink('address', userAddress)} target="_blank">
|
<>
|
||||||
<OpenInNew style={openIconStyle} />
|
<CopyBtn content={userAddress} increaseZindex />
|
||||||
</Link>
|
<EtherscanBtn type="address" value={userAddress} increaseZindex />
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</Block>
|
</Block>
|
||||||
</Block>
|
</Block>
|
||||||
|
@ -146,9 +141,11 @@ const UserDetails = ({
|
||||||
Wallet
|
Wallet
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
{provider === 'safe'
|
{provider === 'safe' ? (
|
||||||
? <Img className={classes.logo} src={safeIcon} height={14} alt="Safe client" />
|
<Img className={classes.logo} src={safeIcon} height={14} alt="Safe client" />
|
||||||
: <Img className={classes.logo} src={metamaskIcon} height={14} alt="Metamask client" />}
|
) : (
|
||||||
|
<Img className={classes.logo} src={metamaskIcon} height={14} alt="Metamask client" />
|
||||||
|
)}
|
||||||
<Paragraph noMargin align="right" weight="bolder" className={classes.labels}>
|
<Paragraph noMargin align="right" weight="bolder" className={classes.labels}>
|
||||||
{upperFirst(provider)}
|
{upperFirst(provider)}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
// @flow
|
||||||
|
import React from 'react'
|
||||||
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
|
import Block from '~/components/layout/Block'
|
||||||
|
import Link from '~/components/layout/Link'
|
||||||
|
import { sm, primary } from '~/theme/variables'
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
container: {
|
||||||
|
padding: `${sm} 0`,
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
color: primary,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const LegalLinks = () => {
|
||||||
|
const classes = useStyles()
|
||||||
|
return (
|
||||||
|
<Block className={classes.container} justify="space-around">
|
||||||
|
<Link className={classes.link} to="https://safe.gnosis.io/terms-of-use-072018.html" target="_blank">
|
||||||
|
Terms
|
||||||
|
</Link>
|
||||||
|
<Link className={classes.link} to="https://safe.gnosis.io/privacy-policy-052019.html" target="_blank">
|
||||||
|
Privacy
|
||||||
|
</Link>
|
||||||
|
<Link className={classes.link} to="https://safe.gnosis.io/licenses-092019.html" target="_blank">
|
||||||
|
Licenses
|
||||||
|
</Link>
|
||||||
|
<Link className={classes.link} to="https://safe.gnosis.io/imprint.html" target="_blank">
|
||||||
|
Imprint
|
||||||
|
</Link>
|
||||||
|
</Block>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LegalLinks
|
|
@ -24,7 +24,7 @@ const DefaultBadge = () => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Block align="left" className={classes.container}>
|
<Block justify="left" className={classes.container}>
|
||||||
<Img src={StarIcon} alt="Star Icon" />
|
<Img src={StarIcon} alt="Star Icon" />
|
||||||
<Paragraph noMargin size="xs">
|
<Paragraph noMargin size="xs">
|
||||||
default
|
default
|
||||||
|
|
|
@ -14,6 +14,7 @@ import Identicon from '~/components/Identicon'
|
||||||
import {
|
import {
|
||||||
mediumFontSize, sm, secondary, primary,
|
mediumFontSize, sm, secondary, primary,
|
||||||
} from '~/theme/variables'
|
} from '~/theme/variables'
|
||||||
|
import { formatAmount } from '~/logic/tokens/utils/formatAmount'
|
||||||
import { shortVersionOf, sameAddress } from '~/logic/wallets/ethAddresses'
|
import { shortVersionOf, sameAddress } from '~/logic/wallets/ethAddresses'
|
||||||
import { type Safe } from '~/routes/safe/store/models/safe'
|
import { type Safe } from '~/routes/safe/store/models/safe'
|
||||||
import { SAFELIST_ADDRESS } from '~/routes/routes'
|
import { SAFELIST_ADDRESS } from '~/routes/routes'
|
||||||
|
@ -71,7 +72,11 @@ const SafeList = ({
|
||||||
<MuiList className={classes.list}>
|
<MuiList className={classes.list}>
|
||||||
{safes.map((safe) => (
|
{safes.map((safe) => (
|
||||||
<React.Fragment key={safe.address}>
|
<React.Fragment key={safe.address}>
|
||||||
<Link to={`${SAFELIST_ADDRESS}/${safe.address}`} onClick={onSafeClick} data-testid={SIDEBAR_SAFELIST_ROW_TESTID}>
|
<Link
|
||||||
|
to={`${SAFELIST_ADDRESS}/${safe.address}`}
|
||||||
|
onClick={onSafeClick}
|
||||||
|
data-testid={SIDEBAR_SAFELIST_ROW_TESTID}
|
||||||
|
>
|
||||||
<ListItem classes={{ root: classes.listItemRoot }}>
|
<ListItem classes={{ root: classes.listItemRoot }}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<Identicon address={safe.address} diameter={32} className={classes.icon} />
|
<Identicon address={safe.address} diameter={32} className={classes.icon} />
|
||||||
|
@ -82,9 +87,7 @@ const SafeList = ({
|
||||||
classes={{ primary: classes.safeName, secondary: classes.safeAddress }}
|
classes={{ primary: classes.safeName, secondary: classes.safeAddress }}
|
||||||
/>
|
/>
|
||||||
<Paragraph size="lg" color="primary">
|
<Paragraph size="lg" color="primary">
|
||||||
{safe.ethBalance}
|
{`${formatAmount(safe.ethBalance)} ETH`}
|
||||||
{' '}
|
|
||||||
ETH
|
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
{sameAddress(defaultSafe, safe.address) ? (
|
{sameAddress(defaultSafe, safe.address) ? (
|
||||||
<DefaultBadge />
|
<DefaultBadge />
|
||||||
|
|
|
@ -12,15 +12,17 @@ import Link from '~/components/layout/Link'
|
||||||
import Spacer from '~/components/Spacer'
|
import Spacer from '~/components/Spacer'
|
||||||
import Hairline from '~/components/layout/Hairline'
|
import Hairline from '~/components/layout/Hairline'
|
||||||
import Row from '~/components/layout/Row'
|
import Row from '~/components/layout/Row'
|
||||||
|
import { WELCOME_ADDRESS } from '~/routes/routes'
|
||||||
import { type Safe } from '~/routes/safe/store/models/safe'
|
import { type Safe } from '~/routes/safe/store/models/safe'
|
||||||
import { defaultSafeSelector } from '~/routes/safe/store/selectors'
|
import { defaultSafeSelector } from '~/routes/safe/store/selectors'
|
||||||
import setDefaultSafe from '~/routes/safe/store/actions/setDefaultSafe'
|
import setDefaultSafe from '~/routes/safe/store/actions/setDefaultSafe'
|
||||||
import { sortedSafeListSelector } from './selectors'
|
import { sortedSafeListSelector } from './selectors'
|
||||||
import useSidebarStyles from './style'
|
|
||||||
import SafeList from './SafeList'
|
import SafeList from './SafeList'
|
||||||
import { WELCOME_ADDRESS } from '~/routes/routes'
|
import LegalLinks from './LegalLinks'
|
||||||
|
import useSidebarStyles from './style'
|
||||||
|
|
||||||
const { useState, useEffect } = React
|
|
||||||
|
const { useState, useEffect, useMemo } = React
|
||||||
|
|
||||||
type TSidebarContext = {
|
type TSidebarContext = {
|
||||||
isOpen: boolean,
|
isOpen: boolean,
|
||||||
|
@ -83,7 +85,7 @@ const Sidebar = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const filteredSafes = filterBy(filter, safes)
|
const filteredSafes = useMemo(() => filterBy(filter, safes), [safes, filter])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarContext.Provider value={{ isOpen, toggleSidebar }}>
|
<SidebarContext.Provider value={{ isOpen, toggleSidebar }}>
|
||||||
|
@ -128,6 +130,7 @@ const Sidebar = ({
|
||||||
setDefaultSafe={setDefaultSafeAction}
|
setDefaultSafe={setDefaultSafeAction}
|
||||||
defaultSafe={defaultSafe}
|
defaultSafe={defaultSafe}
|
||||||
/>
|
/>
|
||||||
|
<LegalLinks />
|
||||||
</Drawer>
|
</Drawer>
|
||||||
</ClickAwayListener>
|
</ClickAwayListener>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -21,6 +21,7 @@ type Props<K> = {
|
||||||
children: Function,
|
children: Function,
|
||||||
size: number,
|
size: number,
|
||||||
defaultFixed: boolean,
|
defaultFixed: boolean,
|
||||||
|
defaultRowsPerPage: number,
|
||||||
defaultOrder: 'desc' | 'asc',
|
defaultOrder: 'desc' | 'asc',
|
||||||
noBorder: boolean,
|
noBorder: boolean,
|
||||||
disablePagination: boolean,
|
disablePagination: boolean,
|
||||||
|
@ -31,7 +32,7 @@ type State = {
|
||||||
order?: Order,
|
order?: Order,
|
||||||
orderBy?: string,
|
orderBy?: string,
|
||||||
orderProp: boolean,
|
orderProp: boolean,
|
||||||
rowsPerPage: number,
|
rowsPerPage?: number,
|
||||||
fixed?: boolean,
|
fixed?: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ class GnoTable<K> extends React.Component<Props<K>, State> {
|
||||||
orderBy: undefined,
|
orderBy: undefined,
|
||||||
fixed: undefined,
|
fixed: undefined,
|
||||||
orderProp: false,
|
orderProp: false,
|
||||||
rowsPerPage: 5,
|
rowsPerPage: undefined,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +148,7 @@ class GnoTable<K> extends React.Component<Props<K>, State> {
|
||||||
defaultOrderBy,
|
defaultOrderBy,
|
||||||
defaultOrder,
|
defaultOrder,
|
||||||
defaultFixed,
|
defaultFixed,
|
||||||
|
defaultRowsPerPage,
|
||||||
noBorder,
|
noBorder,
|
||||||
} = this.props
|
} = this.props
|
||||||
const {
|
const {
|
||||||
|
@ -154,6 +156,7 @@ class GnoTable<K> extends React.Component<Props<K>, State> {
|
||||||
} = this.state
|
} = this.state
|
||||||
const orderByParam = orderBy || defaultOrderBy
|
const orderByParam = orderBy || defaultOrderBy
|
||||||
const orderParam = order || defaultOrder
|
const orderParam = order || defaultOrder
|
||||||
|
const displayRows = rowsPerPage || defaultRowsPerPage
|
||||||
const fixedParam = typeof fixed !== 'undefined' ? fixed : !!defaultFixed
|
const fixedParam = typeof fixed !== 'undefined' ? fixed : !!defaultFixed
|
||||||
|
|
||||||
const paginationClasses = {
|
const paginationClasses = {
|
||||||
|
@ -165,10 +168,10 @@ class GnoTable<K> extends React.Component<Props<K>, State> {
|
||||||
let sortedData = stableSort(data, getSorting(orderParam, orderByParam, orderProp), fixedParam)
|
let sortedData = stableSort(data, getSorting(orderParam, orderByParam, orderProp), fixedParam)
|
||||||
|
|
||||||
if (!disablePagination) {
|
if (!disablePagination) {
|
||||||
sortedData = sortedData.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
sortedData = sortedData.slice(page * displayRows, page * displayRows + displayRows)
|
||||||
}
|
}
|
||||||
|
|
||||||
const emptyRows = rowsPerPage - Math.min(rowsPerPage, data.length - page * rowsPerPage)
|
const emptyRows = displayRows - Math.min(displayRows, data.length - page * displayRows)
|
||||||
const isEmpty = size === 0
|
const isEmpty = size === 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -191,7 +194,7 @@ class GnoTable<K> extends React.Component<Props<K>, State> {
|
||||||
<TablePagination
|
<TablePagination
|
||||||
component="div"
|
component="div"
|
||||||
count={size}
|
count={size}
|
||||||
rowsPerPage={rowsPerPage}
|
rowsPerPage={displayRows}
|
||||||
rowsPerPageOptions={[5, 10, 25, 50, 100]}
|
rowsPerPageOptions={[5, 10, 25, 50, 100]}
|
||||||
page={page}
|
page={page}
|
||||||
backIconButtonProps={backProps}
|
backIconButtonProps={backProps}
|
||||||
|
@ -209,6 +212,7 @@ class GnoTable<K> extends React.Component<Props<K>, State> {
|
||||||
GnoTable.defaultProps = {
|
GnoTable.defaultProps = {
|
||||||
defaultOrder: 'asc',
|
defaultOrder: 'asc',
|
||||||
disablePagination: false,
|
disablePagination: false,
|
||||||
|
defaultRowsPerPage: 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withStyles(styles)(GnoTable)
|
export default withStyles(styles)(GnoTable)
|
||||||
|
|
|
@ -12,7 +12,7 @@ const cx = classNames.bind(styles)
|
||||||
type Props = {
|
type Props = {
|
||||||
margin?: Size,
|
margin?: Size,
|
||||||
padding?: Size,
|
padding?: Size,
|
||||||
align?: 'center' | 'right' | 'left',
|
justify?: 'center' | 'right' | 'left' | 'space-around',
|
||||||
children: React.Node,
|
children: React.Node,
|
||||||
className?: string,
|
className?: string,
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,12 @@ type Props = {
|
||||||
class Block extends PureComponent<Props> {
|
class Block extends PureComponent<Props> {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
margin, padding, align, children, className, ...props
|
margin, padding, justify, 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, align)} {...props}>
|
<div className={cx(className, 'block', margin, paddingStyle, justify)} {...props}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -52,6 +52,12 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.space-around {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
.right {
|
.right {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -36,7 +36,7 @@ const instanciateMasterCopies = async () => {
|
||||||
const ProxyFactory = getCreateProxyFactoryContract(web3)
|
const ProxyFactory = getCreateProxyFactoryContract(web3)
|
||||||
proxyFactoryMaster = await ProxyFactory.deployed()
|
proxyFactoryMaster = await ProxyFactory.deployed()
|
||||||
|
|
||||||
// Initialize safe master copy
|
// Initialize Safe master copy
|
||||||
const GnosisSafe = getGnosisSafeContract(web3)
|
const GnosisSafe = getGnosisSafeContract(web3)
|
||||||
safeMaster = await GnosisSafe.deployed()
|
safeMaster = await GnosisSafe.deployed()
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ export const saveSafes = async (safes: Object) => {
|
||||||
try {
|
try {
|
||||||
await saveToStorage(SAFES_KEY, safes)
|
await saveToStorage(SAFES_KEY, safes)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error storing safe info in localstorage', err)
|
console.error('Error storing Safe info in localstorage', err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ export const saveDefaultSafe = async (safeAddress: string): Promise<void> => {
|
||||||
await saveToStorage(DEFAULT_SAFE_KEY, safeAddress)
|
await saveToStorage(DEFAULT_SAFE_KEY, safeAddress)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.error('Error saving default safe to storage: ', err)
|
console.error('Error saving default Safe to storage: ', err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,11 @@ const fetchTokenList = () => {
|
||||||
const apiUrl = getRelayUrl()
|
const apiUrl = getRelayUrl()
|
||||||
const url = `${apiUrl}/tokens`
|
const url = `${apiUrl}/tokens`
|
||||||
|
|
||||||
return axios.get(url)
|
return axios.get(url, {
|
||||||
|
params: {
|
||||||
|
limit: 300,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export default fetchTokenList
|
export default fetchTokenList
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
// This is pretty new so I'll leave the docs here
|
||||||
|
// https://v8.dev/features/intl-numberformat
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat
|
||||||
|
|
||||||
|
// Locale is an empty array because we want it to use user's locale
|
||||||
|
const lt1kFormatter = new Intl.NumberFormat([], { maximumFractionDigits: 5 })
|
||||||
|
const lt10kFormatter = new Intl.NumberFormat([], { maximumFractionDigits: 4 })
|
||||||
|
const lt100kFormatter = new Intl.NumberFormat([], { maximumFractionDigits: 3 })
|
||||||
|
const lt1mFormatter = new Intl.NumberFormat([], { maximumFractionDigits: 2 })
|
||||||
|
const lt10mFormatter = new Intl.NumberFormat([], { maximumFractionDigits: 1 })
|
||||||
|
const lt100mFormatter = new Intl.NumberFormat([], { maximumFractionDigits: 0 })
|
||||||
|
// same format for billions and trillions
|
||||||
|
const lt1000tFormatter = new Intl.NumberFormat([], { maximumFractionDigits: 3, notation: 'compact' })
|
||||||
|
|
||||||
|
export const formatAmount = (number: string | number) => {
|
||||||
|
let numberFloat = parseFloat(number)
|
||||||
|
|
||||||
|
if (numberFloat < 1000) {
|
||||||
|
numberFloat = lt1kFormatter.format(numberFloat)
|
||||||
|
} else if (numberFloat < 10000) {
|
||||||
|
numberFloat = lt10kFormatter.format(numberFloat)
|
||||||
|
} else if (numberFloat < 100000) {
|
||||||
|
numberFloat = lt100kFormatter.format(numberFloat)
|
||||||
|
} else if (numberFloat < 1000000) {
|
||||||
|
numberFloat = lt1mFormatter.format(numberFloat)
|
||||||
|
} else if (numberFloat < 10000000) {
|
||||||
|
numberFloat = lt10mFormatter.format(numberFloat)
|
||||||
|
} else if (numberFloat < 100000000) {
|
||||||
|
numberFloat = lt100mFormatter.format(numberFloat)
|
||||||
|
} else if (numberFloat < 10 ** 15) {
|
||||||
|
numberFloat = lt1000tFormatter.format(numberFloat)
|
||||||
|
} else {
|
||||||
|
numberFloat = '> 1000T'
|
||||||
|
}
|
||||||
|
|
||||||
|
return numberFloat
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ import { loadFromStorage, saveToStorage } from '~/utils/storage'
|
||||||
export const ACTIVE_TOKENS_KEY = 'ACTIVE_TOKENS'
|
export const ACTIVE_TOKENS_KEY = 'ACTIVE_TOKENS'
|
||||||
export const CUSTOM_TOKENS_KEY = 'CUSTOM_TOKENS'
|
export const CUSTOM_TOKENS_KEY = 'CUSTOM_TOKENS'
|
||||||
|
|
||||||
// Tokens which are active at least in one of used safes in the app should be saved to localstorage
|
// Tokens which are active at least in one of used Safes in the app should be saved to localstorage
|
||||||
// to avoid iterating a large amount of data of tokens from the backend
|
// to avoid iterating a large amount of data of tokens from the backend
|
||||||
// Custom tokens should be saved too unless they're deleted (marking them as inactive doesn't count)
|
// Custom tokens should be saved too unless they're deleted (marking them as inactive doesn't count)
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ export const getEtherScanLink = (type: 'address' | 'tx', value: string) => {
|
||||||
let web3
|
let web3
|
||||||
export const getWeb3 = () => web3 || (window.web3 && new Web3(window.web3.currentProvider)) || (window.ethereum && new Web3(window.ethereum))
|
export const getWeb3 = () => web3 || (window.web3 && new Web3(window.web3.currentProvider)) || (window.ethereum && new Web3(window.ethereum))
|
||||||
|
|
||||||
const getProviderName: Function = (web3Provider): boolean => {
|
const getProviderName: Function = (web3Provider): string => {
|
||||||
let name
|
let name
|
||||||
|
|
||||||
switch (web3Provider.currentProvider.constructor.name) {
|
switch (web3Provider.currentProvider.constructor.name) {
|
||||||
|
@ -58,7 +58,7 @@ const getProviderName: Function = (web3Provider): boolean => {
|
||||||
name = WALLET_PROVIDER.METAMASK
|
name = WALLET_PROVIDER.METAMASK
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
name = 'UNKNOWN'
|
name = 'Wallet'
|
||||||
}
|
}
|
||||||
|
|
||||||
return name
|
return name
|
||||||
|
@ -86,10 +86,7 @@ export const getProviderInfo: Function = async (): Promise<ProviderProps> => {
|
||||||
if (window.ethereum) {
|
if (window.ethereum) {
|
||||||
web3Provider = window.ethereum
|
web3Provider = window.ethereum
|
||||||
try {
|
try {
|
||||||
const accounts = await web3Provider.enable()
|
await web3Provider.enable()
|
||||||
if (!accounts) {
|
|
||||||
throw new Error()
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error when enabling web3 provider', error)
|
console.error('Error when enabling web3 provider', error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,8 @@ const styles = () => ({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export const SAFE_INSTANCE_ERROR = 'Address given is not a safe instance'
|
export const SAFE_INSTANCE_ERROR = 'Address given is not a Safe instance'
|
||||||
export const SAFE_MASTERCOPY_ERROR = 'Mastercopy used by this safe is not the same'
|
export const SAFE_MASTERCOPY_ERROR = 'Mastercopy used by this Safe is not the same'
|
||||||
|
|
||||||
// In case of an error here, it will be swallowed by final-form
|
// In case of an error here, it will be swallowed by final-form
|
||||||
// So if you're experiencing any strang behaviours like freeze or hanging
|
// So if you're experiencing any strang behaviours like freeze or hanging
|
||||||
|
@ -135,13 +135,13 @@ const Details = ({ classes, errors, form }: Props) => (
|
||||||
<Block margin="sm">
|
<Block margin="sm">
|
||||||
<Paragraph noMargin size="md" color="primary" className={classes.links}>
|
<Paragraph noMargin size="md" color="primary" className={classes.links}>
|
||||||
By continuing you consent with the
|
By continuing you consent with the
|
||||||
{' '}
|
|
||||||
<a rel="noopener noreferrer" href="https://safe.gnosis.io/terms" target="_blank">
|
<a rel="noopener noreferrer" href="https://safe.gnosis.io/terms" target="_blank">
|
||||||
terms of use
|
terms of use
|
||||||
</a>
|
</a>
|
||||||
{' '}
|
|
||||||
and
|
and
|
||||||
{' '}
|
|
||||||
<a rel="noopener noreferrer" href="https://safe.gnosis.io/privacy" target="_blank">
|
<a rel="noopener noreferrer" href="https://safe.gnosis.io/privacy" target="_blank">
|
||||||
privacy policy
|
privacy policy
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -164,7 +164,7 @@ class ReviewComponent extends React.PureComponent<Props, State> {
|
||||||
<Paragraph size="lg" noMargin>
|
<Paragraph size="lg" noMargin>
|
||||||
{values[getOwnerNameBy(index)]}
|
{values[getOwnerNameBy(index)]}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Paragraph size="md" color="disabled" noMargin>
|
<Paragraph size="md" color="disabled" noMargin>
|
||||||
{address}
|
{address}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
|
@ -19,7 +19,7 @@ type Props = SelectorProps & Actions
|
||||||
export const loadSafe = async (
|
export const loadSafe = async (
|
||||||
safeName: string,
|
safeName: string,
|
||||||
safeAddress: string,
|
safeAddress: string,
|
||||||
owners: Array,
|
owners: Array<*>,
|
||||||
addSafe: Function,
|
addSafe: Function,
|
||||||
) => {
|
) => {
|
||||||
const safeProps = await buildSafe(safeAddress, safeName)
|
const safeProps = await buildSafe(safeAddress, safeName)
|
||||||
|
|
|
@ -17,7 +17,7 @@ const store = new Store({
|
||||||
|
|
||||||
storiesOf('Routes /open', module)
|
storiesOf('Routes /open', module)
|
||||||
.addDecorator(FrameDecorator)
|
.addDecorator(FrameDecorator)
|
||||||
.add('Open safe with all props set', () => {
|
.add('Open Safe with all props set', () => {
|
||||||
getProviderInfo()
|
getProviderInfo()
|
||||||
const provider = 'METAMASK'
|
const provider = 'METAMASK'
|
||||||
const userAccount = '0x03db1a8b26d08df23337e9276a36b474510f0023'
|
const userAccount = '0x03db1a8b26d08df23337e9276a36b474510f0023'
|
||||||
|
|
|
@ -144,7 +144,7 @@ const ReviewComponent = ({ values, classes, userAccount }: Props) => {
|
||||||
<Paragraph size="lg" noMargin>
|
<Paragraph size="lg" noMargin>
|
||||||
{name}
|
{name}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Paragraph size="md" color="disabled" noMargin>
|
<Paragraph size="md" color="disabled" noMargin>
|
||||||
{addresses[index]}
|
{addresses[index]}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
|
@ -66,7 +66,7 @@ const ScanQRModal = ({
|
||||||
<Hairline />
|
<Hairline />
|
||||||
<Col layout="column" middle="xs" className={classes.detailsContainer}>
|
<Col layout="column" middle="xs" className={classes.detailsContainer}>
|
||||||
{hasWebcam === null ? (
|
{hasWebcam === null ? (
|
||||||
<Block align="center" className={classes.loaderContainer}>
|
<Block justify="center" className={classes.loaderContainer}>
|
||||||
<CircularProgress />
|
<CircularProgress />
|
||||||
</Block>
|
</Block>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -9,7 +9,7 @@ const FrameDecorator = (story) => <div className={styles.frame}>{story()}</div>
|
||||||
|
|
||||||
storiesOf('Routes /opening', module)
|
storiesOf('Routes /opening', module)
|
||||||
.addDecorator(FrameDecorator)
|
.addDecorator(FrameDecorator)
|
||||||
.add('View while safe is being deployed', () => (
|
.add('View while Safe is being deployed', () => (
|
||||||
<Component
|
<Component
|
||||||
name="Super Vault 2000"
|
name="Super Vault 2000"
|
||||||
tx="0xed163e50e2e85695f5edafeba51d6be1758549858d12611ed4dcc96feaa19fc9"
|
tx="0xed163e50e2e85695f5edafeba51d6be1758549858d12611ed4dcc96feaa19fc9"
|
||||||
|
|
|
@ -16,7 +16,7 @@ const AssetTableCell = (props: Props) => {
|
||||||
const { asset } = props
|
const { asset } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Block align="left">
|
<Block justify="left">
|
||||||
<Img src={asset.logoUri} height={26} alt={asset.name} onError={setImageToPlaceholder} />
|
<Img src={asset.logoUri} height={26} alt={asset.name} onError={setImageToPlaceholder} />
|
||||||
<Paragraph size="lg" style={{ marginLeft: 10 }} noMargin>{asset.name}</Paragraph>
|
<Paragraph size="lg" style={{ marginLeft: 10 }} noMargin>{asset.name}</Paragraph>
|
||||||
</Block>
|
</Block>
|
||||||
|
|
|
@ -92,7 +92,7 @@ const Receive = ({
|
||||||
<Block className={classes.qrContainer}>
|
<Block className={classes.qrContainer}>
|
||||||
<QRCode value={safeAddress} size={135} />
|
<QRCode value={safeAddress} size={135} />
|
||||||
</Block>
|
</Block>
|
||||||
<Block align="center" className={classes.addressContainer}>
|
<Block justify="center" className={classes.addressContainer}>
|
||||||
<Identicon address={safeAddress} diameter={32} />
|
<Identicon address={safeAddress} diameter={32} />
|
||||||
<Paragraph
|
<Paragraph
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
|
@ -72,7 +72,7 @@ const ReviewTx = ({
|
||||||
txData = tokenInstance.contract.methods.transfer(tx.recipientAddress, txAmount).encodeABI()
|
txData = tokenInstance.contract.methods.transfer(tx.recipientAddress, txAmount).encodeABI()
|
||||||
// txAmount should be 0 if we send tokens
|
// txAmount should be 0 if we send tokens
|
||||||
// the real value is encoded in txData and will be used by the contract
|
// the real value is encoded in txData and will be used by the contract
|
||||||
// if txAmount > 0 it would send ETH from the safe
|
// if txAmount > 0 it would send ETH from the Safe
|
||||||
txAmount = 0
|
txAmount = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import SelectField from '~/components/forms/SelectField'
|
||||||
import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils'
|
import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils'
|
||||||
import { required } from '~/components/forms/validator'
|
import { required } from '~/components/forms/validator'
|
||||||
import { type Token } from '~/logic/tokens/store/model/token'
|
import { type Token } from '~/logic/tokens/store/model/token'
|
||||||
|
import { formatAmount } from '~/logic/tokens/utils/formatAmount'
|
||||||
import { selectedTokenStyles, selectStyles } from './style'
|
import { selectedTokenStyles, selectStyles } from './style'
|
||||||
|
|
||||||
type SelectFieldProps = {
|
type SelectFieldProps = {
|
||||||
|
@ -35,7 +36,7 @@ const SelectedToken = ({ token, classes }: SelectedTokenProps) => (
|
||||||
<ListItemText
|
<ListItemText
|
||||||
className={classes.tokenData}
|
className={classes.tokenData}
|
||||||
primary={token.name}
|
primary={token.name}
|
||||||
secondary={`${token.balance} ${token.symbol}`}
|
secondary={`${formatAmount(token.balance)} ${token.symbol}`}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
@ -54,7 +55,7 @@ const TokenSelectField = ({ tokens, classes, initialValue }: SelectFieldProps) =
|
||||||
const [initialToken, setInitialToken] = useState<InitialTokenType>('')
|
const [initialToken, setInitialToken] = useState<InitialTokenType>('')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const selectedToken = tokens.find(token => token.name === initialValue)
|
const selectedToken = tokens.find((token) => token.name === initialValue)
|
||||||
setInitialToken(selectedToken || '')
|
setInitialToken(selectedToken || '')
|
||||||
}, [initialValue])
|
}, [initialValue])
|
||||||
|
|
||||||
|
@ -64,16 +65,16 @@ const TokenSelectField = ({ tokens, classes, initialValue }: SelectFieldProps) =
|
||||||
component={SelectField}
|
component={SelectField}
|
||||||
classes={{ selectMenu: classes.selectMenu }}
|
classes={{ selectMenu: classes.selectMenu }}
|
||||||
validate={required}
|
validate={required}
|
||||||
renderValue={token => <SelectedTokenStyled token={token} />}
|
renderValue={(token) => <SelectedTokenStyled token={token} />}
|
||||||
initialValue={initialToken}
|
initialValue={initialToken}
|
||||||
displayEmpty
|
displayEmpty
|
||||||
>
|
>
|
||||||
{tokens.map(token => (
|
{tokens.map((token) => (
|
||||||
<MenuItem key={token.address} value={token}>
|
<MenuItem key={token.address} value={token}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<Img src={token.logoUri} height={28} alt={token.name} onError={setImageToPlaceholder} />
|
<Img src={token.logoUri} height={28} alt={token.name} onError={setImageToPlaceholder} />
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText primary={token.name} secondary={`${token.balance} ${token.symbol}`} />
|
<ListItemText primary={token.name} secondary={`${formatAmount(token.balance)} ${token.symbol}`} />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
@ -42,7 +42,7 @@ const Tokens = (props: Props) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Row align="center" grow className={classes.heading}>
|
<Row align="center" grow className={classes.heading}>
|
||||||
<Paragraph className={classes.manage} noMargin weight="bolder">
|
<Paragraph size="xl" noMargin weight="bolder">
|
||||||
Manage Tokens
|
Manage Tokens
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<IconButton onClick={onClose} disableRipple data-testid={MANAGE_TOKENS_MODAL_CLOSE_BUTTON_TEST_ID}>
|
<IconButton onClick={onClose} disableRipple data-testid={MANAGE_TOKENS_MODAL_CLOSE_BUTTON_TEST_ID}>
|
||||||
|
|
|
@ -174,7 +174,7 @@ const AddCustomToken = (props: Props) => {
|
||||||
className={classes.addressInput}
|
className={classes.addressInput}
|
||||||
testId={ADD_CUSTOM_TOKEN_DECIMALS_INPUT_TEST_ID}
|
testId={ADD_CUSTOM_TOKEN_DECIMALS_INPUT_TEST_ID}
|
||||||
/>
|
/>
|
||||||
<Block align="left">
|
<Block justify="left">
|
||||||
<Field name="showForAllSafes" component={Checkbox} type="checkbox" className={classes.checkbox} />
|
<Field name="showForAllSafes" component={Checkbox} type="checkbox" className={classes.checkbox} />
|
||||||
<Paragraph weight="bolder" size="md" className={classes.checkboxLabel}>
|
<Paragraph weight="bolder" size="md" className={classes.checkboxLabel}>
|
||||||
Activate token for all Safes
|
Activate token for all Safes
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
// @flow
|
||||||
|
import React, { memo } from 'react'
|
||||||
|
import { List, Set } from 'immutable'
|
||||||
|
import { withStyles } from '@material-ui/core/styles'
|
||||||
|
import ListItem from '@material-ui/core/ListItem'
|
||||||
|
import ListItemIcon from '@material-ui/core/ListItemIcon'
|
||||||
|
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'
|
||||||
|
import ListItemText from '@material-ui/core/ListItemText'
|
||||||
|
import Switch from '@material-ui/core/Switch'
|
||||||
|
import Img from '~/components/layout/Img'
|
||||||
|
import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils'
|
||||||
|
import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers'
|
||||||
|
import { type Token } from '~/logic/tokens/store/model/token'
|
||||||
|
import { styles } from './style'
|
||||||
|
|
||||||
|
export const TOGGLE_TOKEN_TEST_ID = 'toggle-token-btn'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
data: {
|
||||||
|
activeTokensAddresses: Set<string>,
|
||||||
|
tokens: List<Token>,
|
||||||
|
onSwitch: Function,
|
||||||
|
},
|
||||||
|
style: Object,
|
||||||
|
index: number,
|
||||||
|
classes: Object,
|
||||||
|
}
|
||||||
|
|
||||||
|
const TokenRow = memo(({
|
||||||
|
data, index, classes, style,
|
||||||
|
}: Props) => {
|
||||||
|
const { tokens, activeTokensAddresses, onSwitch } = data
|
||||||
|
const token: Token = tokens.get(index)
|
||||||
|
const isActive = activeTokensAddresses.has(token.address)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={style}>
|
||||||
|
<ListItem className={classes.token} classes={{ root: classes.tokenRoot }}>
|
||||||
|
<ListItemIcon className={classes.tokenIcon}>
|
||||||
|
<Img src={token.logoUri} height={28} alt={token.name} onError={setImageToPlaceholder} />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={token.symbol} secondary={token.name} />
|
||||||
|
{token.address !== ETH_ADDRESS && (
|
||||||
|
<ListItemSecondaryAction>
|
||||||
|
<Switch
|
||||||
|
onChange={onSwitch(token)}
|
||||||
|
checked={isActive}
|
||||||
|
inputProps={{ 'data-testid': `${token.symbol}_${TOGGLE_TOKEN_TEST_ID}` }}
|
||||||
|
/>
|
||||||
|
</ListItemSecondaryAction>
|
||||||
|
)}
|
||||||
|
</ListItem>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default withStyles(styles)(TokenRow)
|
|
@ -2,30 +2,23 @@
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { List, Set } from 'immutable'
|
import { List, Set } from 'immutable'
|
||||||
import cn from 'classnames'
|
import cn from 'classnames'
|
||||||
|
import { FixedSizeList } from 'react-window'
|
||||||
import SearchBar from 'material-ui-search-bar'
|
import SearchBar from 'material-ui-search-bar'
|
||||||
import { withStyles } from '@material-ui/core/styles'
|
import { withStyles } from '@material-ui/core/styles'
|
||||||
import MuiList from '@material-ui/core/List'
|
import MuiList from '@material-ui/core/List'
|
||||||
import ListItem from '@material-ui/core/ListItem'
|
|
||||||
import ListItemIcon from '@material-ui/core/ListItemIcon'
|
|
||||||
import CircularProgress from '@material-ui/core/CircularProgress'
|
import CircularProgress from '@material-ui/core/CircularProgress'
|
||||||
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'
|
|
||||||
import ListItemText from '@material-ui/core/ListItemText'
|
|
||||||
import Switch from '@material-ui/core/Switch'
|
|
||||||
import Search from '@material-ui/icons/Search'
|
import Search from '@material-ui/icons/Search'
|
||||||
import Img from '~/components/layout/Img'
|
|
||||||
import Block from '~/components/layout/Block'
|
import Block from '~/components/layout/Block'
|
||||||
import Button from '~/components/layout/Button'
|
import Button from '~/components/layout/Button'
|
||||||
import Divider from '~/components/layout/Divider'
|
import Divider from '~/components/layout/Divider'
|
||||||
import Hairline from '~/components/layout/Hairline'
|
import Hairline from '~/components/layout/Hairline'
|
||||||
import Spacer from '~/components/Spacer'
|
import Spacer from '~/components/Spacer'
|
||||||
import Row from '~/components/layout/Row'
|
import Row from '~/components/layout/Row'
|
||||||
import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers'
|
|
||||||
import { type Token } from '~/logic/tokens/store/model/token'
|
import { type Token } from '~/logic/tokens/store/model/token'
|
||||||
import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils'
|
import TokenRow from './TokenRow'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
|
||||||
export const ADD_CUSTOM_TOKEN_BUTTON_TEST_ID = 'add-custom-token-btn'
|
export const ADD_CUSTOM_TOKEN_BUTTON_TEST_ID = 'add-custom-token-btn'
|
||||||
export const TOGGLE_TOKEN_TEST_ID = 'toggle-token-btn'
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
classes: Object,
|
classes: Object,
|
||||||
|
@ -50,10 +43,12 @@ const filterBy = (filter: string, tokens: List<Token>): List<Token> => tokens.fi
|
||||||
|
|
||||||
// OPTIMIZATION IDEA (Thanks Andre)
|
// OPTIMIZATION IDEA (Thanks Andre)
|
||||||
// Calculate active tokens on component mount, store it in component state
|
// Calculate active tokens on component mount, store it in component state
|
||||||
// After user closes modal, dispatch an action so we dont have 100500 actions
|
// After user closes modal, dispatch an action so we don't have 100500 actions
|
||||||
// And selectors dont recalculate
|
// And selectors don't recalculate
|
||||||
|
|
||||||
class Tokens extends React.Component<Props, State> {
|
class Tokens extends React.Component<Props, State> {
|
||||||
|
renderCount = 0
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
filter: '',
|
filter: '',
|
||||||
activeTokensAddresses: Set([]),
|
activeTokensAddresses: Set([]),
|
||||||
|
@ -85,7 +80,7 @@ class Tokens extends React.Component<Props, State> {
|
||||||
const { activeTokensAddresses } = this.state
|
const { activeTokensAddresses } = this.state
|
||||||
const { updateActiveTokens, safeAddress } = this.props
|
const { updateActiveTokens, safeAddress } = this.props
|
||||||
|
|
||||||
updateActiveTokens(safeAddress, activeTokensAddresses.toList())
|
updateActiveTokens(safeAddress, activeTokensAddresses)
|
||||||
}
|
}
|
||||||
|
|
||||||
onCancelSearch = () => {
|
onCancelSearch = () => {
|
||||||
|
@ -110,6 +105,18 @@ class Tokens extends React.Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createItemData = (tokens, activeTokensAddresses) => ({
|
||||||
|
tokens,
|
||||||
|
activeTokensAddresses,
|
||||||
|
onSwitch: this.onSwitch,
|
||||||
|
})
|
||||||
|
|
||||||
|
getItemKey = (index, { tokens }) => {
|
||||||
|
const token: Token = tokens.get(index)
|
||||||
|
|
||||||
|
return token.address
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { classes, tokens, setActiveScreen } = this.props
|
const { classes, tokens, setActiveScreen } = this.props
|
||||||
const { filter, activeTokensAddresses } = this.state
|
const { filter, activeTokensAddresses } = this.state
|
||||||
|
@ -122,6 +129,7 @@ class Tokens extends React.Component<Props, State> {
|
||||||
const switchToAddCustomTokenScreen = () => setActiveScreen('addCustomToken')
|
const switchToAddCustomTokenScreen = () => setActiveScreen('addCustomToken')
|
||||||
|
|
||||||
const filteredTokens = filterBy(filter, tokens)
|
const filteredTokens = filterBy(filter, tokens)
|
||||||
|
const itemData = this.createItemData(filteredTokens, activeTokensAddresses)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -143,42 +151,35 @@ class Tokens extends React.Component<Props, State> {
|
||||||
size="small"
|
size="small"
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.add}
|
className={classes.add}
|
||||||
|
classes={{ label: classes.addBtnLabel }}
|
||||||
onClick={switchToAddCustomTokenScreen}
|
onClick={switchToAddCustomTokenScreen}
|
||||||
testId={ADD_CUSTOM_TOKEN_BUTTON_TEST_ID}
|
testId={ADD_CUSTOM_TOKEN_BUTTON_TEST_ID}
|
||||||
>
|
>
|
||||||
+ ADD CUSTOM TOKEN
|
+ Add custom token
|
||||||
</Button>
|
</Button>
|
||||||
</Row>
|
</Row>
|
||||||
<Hairline />
|
<Hairline />
|
||||||
</Block>
|
</Block>
|
||||||
<MuiList className={classes.list}>
|
{!tokens.size && (
|
||||||
{!tokens.size && (
|
<Block justify="center" className={classes.progressContainer}>
|
||||||
<Block align="center" className={classes.progressContainer}>
|
<CircularProgress />
|
||||||
<CircularProgress />
|
</Block>
|
||||||
</Block>
|
)}
|
||||||
)}
|
{tokens.size > 0 && (
|
||||||
{filteredTokens.map((token: Token) => {
|
<MuiList className={classes.list}>
|
||||||
const isActive = activeTokensAddresses.has(token.address)
|
<FixedSizeList
|
||||||
|
height={413}
|
||||||
return (
|
width={500}
|
||||||
<ListItem key={token.address} className={classes.token}>
|
overscanCount={process.env.NODE_ENV === 'test' ? 100 : 10}
|
||||||
<ListItemIcon className={classes.tokenIcon}>
|
itemCount={filteredTokens.size}
|
||||||
<Img src={token.logoUri} height={28} alt={token.name} onError={setImageToPlaceholder} />
|
itemData={itemData}
|
||||||
</ListItemIcon>
|
itemSize={51}
|
||||||
<ListItemText primary={token.symbol} secondary={token.name} />
|
itemKey={this.getItemKey}
|
||||||
{token.address !== ETH_ADDRESS && (
|
>
|
||||||
<ListItemSecondaryAction>
|
{TokenRow}
|
||||||
<Switch
|
</FixedSizeList>
|
||||||
onChange={this.onSwitch(token)}
|
</MuiList>
|
||||||
checked={isActive}
|
)}
|
||||||
inputProps={{ 'data-testid': `${token.symbol}_${TOGGLE_TOKEN_TEST_ID}` }}
|
|
||||||
/>
|
|
||||||
</ListItemSecondaryAction>
|
|
||||||
)}
|
|
||||||
</ListItem>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</MuiList>
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
|
|
||||||
export const styles = () => ({
|
export const styles = () => ({
|
||||||
root: {
|
root: {
|
||||||
minHeight: '48px',
|
minHeight: '52px',
|
||||||
},
|
},
|
||||||
search: {
|
search: {
|
||||||
color: secondaryText,
|
color: secondaryText,
|
||||||
|
@ -20,6 +20,9 @@ export const styles = () => ({
|
||||||
paddingRight: md,
|
paddingRight: md,
|
||||||
paddingLeft: md,
|
paddingLeft: md,
|
||||||
},
|
},
|
||||||
|
addBtnLabel: {
|
||||||
|
fontSize: mediumFontSize,
|
||||||
|
},
|
||||||
actions: {
|
actions: {
|
||||||
height: '50px',
|
height: '50px',
|
||||||
},
|
},
|
||||||
|
@ -33,6 +36,10 @@ export const styles = () => ({
|
||||||
minHeight: '50px',
|
minHeight: '50px',
|
||||||
borderBottom: `1px solid ${border}`,
|
borderBottom: `1px solid ${border}`,
|
||||||
},
|
},
|
||||||
|
tokenRoot: {
|
||||||
|
paddingTop: 0,
|
||||||
|
paddingBottom: 0,
|
||||||
|
},
|
||||||
searchInput: {
|
searchInput: {
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
lineHeight: 'initial',
|
lineHeight: 'initial',
|
||||||
|
@ -49,6 +56,8 @@ export const styles = () => ({
|
||||||
},
|
},
|
||||||
tokenIcon: {
|
tokenIcon: {
|
||||||
marginRight: md,
|
marginRight: md,
|
||||||
|
height: '28px',
|
||||||
|
width: '28px',
|
||||||
},
|
},
|
||||||
progressContainer: {
|
progressContainer: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { lg, sm } from '~/theme/variables'
|
import { lg, md } from '~/theme/variables'
|
||||||
|
|
||||||
export const styles = () => ({
|
export const styles = () => ({
|
||||||
heading: {
|
heading: {
|
||||||
padding: `${sm} ${lg}`,
|
padding: `${md} ${lg}`,
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
maxHeight: '75px',
|
maxHeight: '75px',
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
},
|
},
|
||||||
manage: {
|
|
||||||
fontSize: '24px',
|
|
||||||
},
|
|
||||||
close: {
|
close: {
|
||||||
height: '35px',
|
height: '35px',
|
||||||
width: '35px',
|
width: '35px',
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { List } from 'immutable'
|
||||||
import { type Token } from '~/logic/tokens/store/model/token'
|
import { type Token } from '~/logic/tokens/store/model/token'
|
||||||
import { buildOrderFieldFrom, FIXED, type SortRow } from '~/components/Table/sorting'
|
import { buildOrderFieldFrom, FIXED, type SortRow } from '~/components/Table/sorting'
|
||||||
import { type Column } from '~/components/Table/TableHead'
|
import { type Column } from '~/components/Table/TableHead'
|
||||||
|
import { formatAmount } from '~/logic/tokens/utils/formatAmount'
|
||||||
|
|
||||||
export const BALANCE_TABLE_ASSET_ID = 'asset'
|
export const BALANCE_TABLE_ASSET_ID = 'asset'
|
||||||
export const BALANCE_TABLE_BALANCE_ID = 'balance'
|
export const BALANCE_TABLE_BALANCE_ID = 'balance'
|
||||||
|
@ -19,7 +20,7 @@ export const getBalanceData = (activeTokens: List<Token>): List<BalanceRow> => {
|
||||||
const rows = activeTokens.map((token: Token) => ({
|
const rows = activeTokens.map((token: Token) => ({
|
||||||
[BALANCE_TABLE_ASSET_ID]: { name: token.name, logoUri: token.logoUri },
|
[BALANCE_TABLE_ASSET_ID]: { name: token.name, logoUri: token.logoUri },
|
||||||
[buildOrderFieldFrom(BALANCE_TABLE_ASSET_ID)]: token.name,
|
[buildOrderFieldFrom(BALANCE_TABLE_ASSET_ID)]: token.name,
|
||||||
[BALANCE_TABLE_BALANCE_ID]: `${token.balance} ${token.symbol}`,
|
[BALANCE_TABLE_BALANCE_ID]: `${formatAmount(token.balance)} ${token.symbol}`,
|
||||||
[buildOrderFieldFrom(BALANCE_TABLE_BALANCE_ID)]: Number(token.balance),
|
[buildOrderFieldFrom(BALANCE_TABLE_BALANCE_ID)]: Number(token.balance),
|
||||||
[FIXED]: token.get('symbol') === 'ETH',
|
[FIXED]: token.get('symbol') === 'ETH',
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -155,6 +155,7 @@ class Balances extends React.Component<Props, State> {
|
||||||
<Table
|
<Table
|
||||||
label="Balances"
|
label="Balances"
|
||||||
defaultOrderBy={BALANCE_TABLE_ASSET_ID}
|
defaultOrderBy={BALANCE_TABLE_ASSET_ID}
|
||||||
|
defaultRowsPerPage={10}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
data={filteredData}
|
data={filteredData}
|
||||||
size={filteredData.size}
|
size={filteredData.size}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
import OpenInNew from '@material-ui/icons/OpenInNew'
|
|
||||||
import Tabs from '@material-ui/core/Tabs'
|
import Tabs from '@material-ui/core/Tabs'
|
||||||
import Tab from '@material-ui/core/Tab'
|
import Tab from '@material-ui/core/Tab'
|
||||||
import CallMade from '@material-ui/icons/CallMade'
|
import CallMade from '@material-ui/icons/CallMade'
|
||||||
|
@ -13,7 +12,8 @@ import Identicon from '~/components/Identicon'
|
||||||
import Heading from '~/components/layout/Heading'
|
import Heading from '~/components/layout/Heading'
|
||||||
import Row from '~/components/layout/Row'
|
import Row from '~/components/layout/Row'
|
||||||
import Button from '~/components/layout/Button'
|
import Button from '~/components/layout/Button'
|
||||||
import Link from '~/components/layout/Link'
|
import EtherscanBtn from '~/components/EtherscanBtn'
|
||||||
|
import CopyBtn from '~/components/CopyBtn'
|
||||||
import Paragraph from '~/components/layout/Paragraph'
|
import Paragraph from '~/components/layout/Paragraph'
|
||||||
import Modal from '~/components/Modal'
|
import Modal from '~/components/Modal'
|
||||||
import SendModal from './Balances/SendModal'
|
import SendModal from './Balances/SendModal'
|
||||||
|
@ -21,9 +21,7 @@ import Receive from './Balances/Receive'
|
||||||
import NoSafe from '~/components/NoSafe'
|
import NoSafe from '~/components/NoSafe'
|
||||||
import { type SelectorProps } from '~/routes/safe/container/selector'
|
import { type SelectorProps } from '~/routes/safe/container/selector'
|
||||||
import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
||||||
import {
|
import { border } from '~/theme/variables'
|
||||||
secondary, border,
|
|
||||||
} from '~/theme/variables'
|
|
||||||
import { copyToClipboard } from '~/utils/clipboard'
|
import { copyToClipboard } from '~/utils/clipboard'
|
||||||
import { type Actions } from '../container/actions'
|
import { type Actions } from '../container/actions'
|
||||||
import Balances from './Balances'
|
import Balances from './Balances'
|
||||||
|
@ -49,14 +47,9 @@ type Props = SelectorProps &
|
||||||
onShow: Function,
|
onShow: Function,
|
||||||
onHide: Function,
|
onHide: Function,
|
||||||
showSendFunds: Function,
|
showSendFunds: Function,
|
||||||
hideSendFunds: Function
|
hideSendFunds: Function,
|
||||||
}
|
}
|
||||||
|
|
||||||
const openIconStyle = {
|
|
||||||
height: '16px',
|
|
||||||
color: secondary,
|
|
||||||
}
|
|
||||||
|
|
||||||
class Layout extends React.Component<Props, State> {
|
class Layout extends React.Component<Props, State> {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
@ -119,13 +112,12 @@ class Layout extends React.Component<Props, State> {
|
||||||
</Heading>
|
</Heading>
|
||||||
{!granted && <Block className={classes.readonly}>Read Only</Block>}
|
{!granted && <Block className={classes.readonly}>Read Only</Block>}
|
||||||
</Row>
|
</Row>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Paragraph size="md" color="disabled" onClick={this.copyAddress} title="Click to copy" noMargin>
|
<Paragraph size="md" color="disabled" className={classes.address} onClick={this.copyAddress} title="Click to copy" noMargin>
|
||||||
{address}
|
{address}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Link className={classes.open} to={etherScanLink} target="_blank">
|
<CopyBtn content={address} />
|
||||||
<OpenInNew style={openIconStyle} />
|
<EtherscanBtn type="address" value={address} />
|
||||||
</Link>
|
|
||||||
</Block>
|
</Block>
|
||||||
</Block>
|
</Block>
|
||||||
<Block className={classes.balance}>
|
<Block className={classes.balance}>
|
||||||
|
@ -139,7 +131,7 @@ class Layout extends React.Component<Props, State> {
|
||||||
disabled={!granted}
|
disabled={!granted}
|
||||||
>
|
>
|
||||||
<CallMade alt="Send Transaction" className={classNames(classes.leftIcon, classes.iconSmall)} />
|
<CallMade alt="Send Transaction" className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||||
Send
|
Send
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
|
@ -149,7 +141,7 @@ class Layout extends React.Component<Props, State> {
|
||||||
onClick={onShow('Receive')}
|
onClick={onShow('Receive')}
|
||||||
>
|
>
|
||||||
<CallReceived alt="Receive Transaction" className={classNames(classes.leftIcon, classes.iconSmall)} />
|
<CallReceived alt="Receive Transaction" className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||||
Receive
|
Receive
|
||||||
</Button>
|
</Button>
|
||||||
</Row>
|
</Row>
|
||||||
</Block>
|
</Block>
|
||||||
|
@ -221,12 +213,7 @@ class Layout extends React.Component<Props, State> {
|
||||||
open={showReceive}
|
open={showReceive}
|
||||||
paperClassName={classes.receiveModal}
|
paperClassName={classes.receiveModal}
|
||||||
>
|
>
|
||||||
<Receive
|
<Receive safeName={name} safeAddress={address} etherScanLink={etherScanLink} onClose={onHide('Receive')} />
|
||||||
safeName={name}
|
|
||||||
safeAddress={address}
|
|
||||||
etherScanLink={etherScanLink}
|
|
||||||
onClose={onHide('Receive')}
|
|
||||||
/>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -106,7 +106,7 @@ const ReviewAddOwner = ({
|
||||||
<Paragraph weight="bolder" size="lg" noMargin>
|
<Paragraph weight="bolder" size="lg" noMargin>
|
||||||
{owner.name}
|
{owner.name}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Paragraph size="md" color="disabled" noMargin>
|
<Paragraph size="md" color="disabled" noMargin>
|
||||||
{owner.address}
|
{owner.address}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
@ -135,7 +135,7 @@ const ReviewAddOwner = ({
|
||||||
<Paragraph weight="bolder" size="lg" noMargin>
|
<Paragraph weight="bolder" size="lg" noMargin>
|
||||||
{values.ownerName}
|
{values.ownerName}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Paragraph size="md" color="disabled" noMargin>
|
<Paragraph size="md" color="disabled" noMargin>
|
||||||
{values.ownerAddress}
|
{values.ownerAddress}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
|
@ -98,7 +98,7 @@ const EditOwnerComponent = ({
|
||||||
/>
|
/>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Identicon address={ownerAddress} diameter={32} />
|
<Identicon address={ownerAddress} diameter={32} />
|
||||||
<Paragraph style={{ marginLeft: 10 }} size="md" color="disabled" noMargin>
|
<Paragraph style={{ marginLeft: 10 }} size="md" color="disabled" noMargin>
|
||||||
{ownerAddress}
|
{ownerAddress}
|
||||||
|
|
|
@ -11,7 +11,7 @@ type Props = {
|
||||||
const OwnerAddressTableCell = (props: Props) => {
|
const OwnerAddressTableCell = (props: Props) => {
|
||||||
const { address } = props
|
const { address } = props
|
||||||
return (
|
return (
|
||||||
<Block align="left">
|
<Block justify="left">
|
||||||
<Identicon address={address} diameter={32} />
|
<Identicon address={address} diameter={32} />
|
||||||
<Paragraph style={{ marginLeft: 10 }}>{address}</Paragraph>
|
<Paragraph style={{ marginLeft: 10 }}>{address}</Paragraph>
|
||||||
</Block>
|
</Block>
|
||||||
|
|
|
@ -64,7 +64,7 @@ const CheckOwner = ({
|
||||||
<Paragraph size="lg" noMargin weight="bolder">
|
<Paragraph size="lg" noMargin weight="bolder">
|
||||||
{ownerName}
|
{ownerName}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Paragraph size="md" color="disabled" noMargin>
|
<Paragraph size="md" color="disabled" noMargin>
|
||||||
{ownerAddress}
|
{ownerAddress}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
|
@ -118,7 +118,7 @@ const ReviewRemoveOwner = ({
|
||||||
<Paragraph weight="bolder" size="lg" noMargin>
|
<Paragraph weight="bolder" size="lg" noMargin>
|
||||||
{owner.name}
|
{owner.name}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Paragraph size="md" color="disabled" noMargin>
|
<Paragraph size="md" color="disabled" noMargin>
|
||||||
{owner.address}
|
{owner.address}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
@ -152,7 +152,7 @@ const ReviewRemoveOwner = ({
|
||||||
<Paragraph weight="bolder" size="lg" noMargin>
|
<Paragraph weight="bolder" size="lg" noMargin>
|
||||||
{ownerName}
|
{ownerName}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Paragraph size="md" color="disabled" noMargin>
|
<Paragraph size="md" color="disabled" noMargin>
|
||||||
{ownerAddress}
|
{ownerAddress}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
|
@ -95,7 +95,7 @@ const OwnerForm = ({
|
||||||
<Paragraph size="lg" noMargin weight="bolder">
|
<Paragraph size="lg" noMargin weight="bolder">
|
||||||
{ownerName}
|
{ownerName}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Paragraph size="md" color="disabled" noMargin>
|
<Paragraph size="md" color="disabled" noMargin>
|
||||||
{ownerAddress}
|
{ownerAddress}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
|
@ -121,7 +121,7 @@ const ReviewRemoveOwner = ({
|
||||||
<Paragraph weight="bolder" size="lg" noMargin>
|
<Paragraph weight="bolder" size="lg" noMargin>
|
||||||
{owner.name}
|
{owner.name}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Paragraph size="md" color="disabled" noMargin>
|
<Paragraph size="md" color="disabled" noMargin>
|
||||||
{owner.address}
|
{owner.address}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
@ -155,7 +155,7 @@ const ReviewRemoveOwner = ({
|
||||||
<Paragraph weight="bolder" size="lg" noMargin>
|
<Paragraph weight="bolder" size="lg" noMargin>
|
||||||
{ownerName}
|
{ownerName}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Paragraph size="md" color="disabled" noMargin>
|
<Paragraph size="md" color="disabled" noMargin>
|
||||||
{ownerAddress}
|
{ownerAddress}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
@ -181,7 +181,7 @@ const ReviewRemoveOwner = ({
|
||||||
<Paragraph weight="bolder" size="lg" noMargin>
|
<Paragraph weight="bolder" size="lg" noMargin>
|
||||||
{values.ownerName}
|
{values.ownerName}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Paragraph size="md" color="disabled" noMargin>
|
<Paragraph size="md" color="disabled" noMargin>
|
||||||
{values.ownerAddress}
|
{values.ownerAddress}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
|
@ -58,7 +58,7 @@ const RemoveSafeComponent = ({
|
||||||
<Paragraph size="lg" noMargin weight="bolder">
|
<Paragraph size="lg" noMargin weight="bolder">
|
||||||
{safeName}
|
{safeName}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Block align="center" className={classes.user}>
|
<Block justify="center" className={classes.user}>
|
||||||
<Paragraph size="md" color="disabled" noMargin>
|
<Paragraph size="md" color="disabled" noMargin>
|
||||||
{safeAddress}
|
{safeAddress}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
|
@ -11,7 +11,7 @@ const NoTransactions = () => (
|
||||||
<Row data-testid={NO_TRANSACTION_ROW_TEST_ID}>
|
<Row data-testid={NO_TRANSACTION_ROW_TEST_ID}>
|
||||||
<Col xs={12} center="xs" sm={10} smOffset={2} start="sm" margin="md">
|
<Col xs={12} center="xs" sm={10} smOffset={2} start="sm" margin="md">
|
||||||
<Paragraph size="lg">
|
<Paragraph size="lg">
|
||||||
<Bold>No transactions found for this safe</Bold>
|
<Bold>No transactions found for this Safe</Bold>
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
|
@ -14,6 +14,9 @@ export const styles = () => ({
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
},
|
},
|
||||||
|
address: {
|
||||||
|
marginRight: sm,
|
||||||
|
},
|
||||||
user: {
|
user: {
|
||||||
justifyContent: 'left',
|
justifyContent: 'left',
|
||||||
},
|
},
|
||||||
|
|
|
@ -18,7 +18,6 @@ import { safeTransactionsSelector } from '~/routes/safe/store/selectors/index'
|
||||||
import { orderedTokenListSelector, tokensSelector } from '~/logic/tokens/store/selectors'
|
import { orderedTokenListSelector, tokensSelector } from '~/logic/tokens/store/selectors'
|
||||||
import { type Token } from '~/logic/tokens/store/model/token'
|
import { type Token } from '~/logic/tokens/store/model/token'
|
||||||
import { type Transaction, type TransactionStatus } from '~/routes/safe/store/models/transaction'
|
import { type Transaction, type TransactionStatus } from '~/routes/safe/store/models/transaction'
|
||||||
import { type TokenBalance } from '~/routes/safe/store/models/tokenBalance'
|
|
||||||
import { safeParamAddressSelector } from '../store/selectors'
|
import { safeParamAddressSelector } from '../store/selectors'
|
||||||
import { getEthAsToken } from '~/logic/tokens/utils/tokenHelpers'
|
import { getEthAsToken } from '~/logic/tokens/utils/tokenHelpers'
|
||||||
|
|
||||||
|
@ -84,14 +83,14 @@ const extendedSafeTokensSelector: Selector<GlobalState, RouterProps, List<Token>
|
||||||
safeBalancesSelector,
|
safeBalancesSelector,
|
||||||
tokensSelector,
|
tokensSelector,
|
||||||
safeEthAsTokenSelector,
|
safeEthAsTokenSelector,
|
||||||
(safeTokens: List<string>, balances: List<TokenBalance>, tokensList: Map<string, Token>, ethAsToken: Token) => {
|
(safeTokens: List<string>, balances: Map<string, string>, tokensList: Map<string, Token>, ethAsToken: Token) => {
|
||||||
const extendedTokens = Map().withMutations((map) => {
|
const extendedTokens = Map().withMutations((map) => {
|
||||||
safeTokens.forEach((tokenAddress: string) => {
|
safeTokens.forEach((tokenAddress: string) => {
|
||||||
const baseToken = tokensList.get(tokenAddress)
|
const baseToken = tokensList.get(tokenAddress)
|
||||||
const tokenBalance = balances.find((tknBalance) => tknBalance.address === tokenAddress)
|
const tokenBalance = balances.get(tokenAddress)
|
||||||
|
|
||||||
if (baseToken) {
|
if (baseToken) {
|
||||||
map.set(tokenAddress, baseToken.set('balance', tokenBalance ? tokenBalance.balance : '0'))
|
map.set(tokenAddress, baseToken.set('balance', tokenBalance || '0'))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ export default (safeAddress: string) => async (dispatch: ReduxDispatch<GlobalSta
|
||||||
dispatch(addSafe(safeProps))
|
dispatch(addSafe(safeProps))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.error('Error while updating safe information: ', err)
|
console.error('Error while updating Safe information: ', err)
|
||||||
|
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Dispatch as ReduxDispatch } from 'redux'
|
import type { Dispatch as ReduxDispatch } from 'redux'
|
||||||
import { List } from 'immutable'
|
import { Map, List } from 'immutable'
|
||||||
import { BigNumber } from 'bignumber.js'
|
import { BigNumber } from 'bignumber.js'
|
||||||
import { type GlobalState } from '~/store/index'
|
import { type GlobalState } from '~/store/index'
|
||||||
import { type Token } from '~/logic/tokens/store/model/token'
|
import { type Token } from '~/logic/tokens/store/model/token'
|
||||||
import TokenBalanceRecord from '~/routes/safe/store/models/tokenBalance'
|
|
||||||
import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens'
|
import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens'
|
||||||
import updateSafe from './updateSafe'
|
import updateSafe from './updateSafe'
|
||||||
import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers'
|
import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers'
|
||||||
|
@ -36,13 +35,20 @@ const fetchTokenBalances = (safeAddress: string, tokens: List<Token>) => async (
|
||||||
const withBalances = await Promise.all(
|
const withBalances = await Promise.all(
|
||||||
tokens.map(async (token) => {
|
tokens.map(async (token) => {
|
||||||
const balance = await calculateBalanceOf(token.address, safeAddress, token.decimals)
|
const balance = await calculateBalanceOf(token.address, safeAddress, token.decimals)
|
||||||
return TokenBalanceRecord({
|
return {
|
||||||
address: token.address,
|
address: token.address,
|
||||||
balance,
|
balance,
|
||||||
})
|
}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
dispatch(updateSafe({ address: safeAddress, balances: List(withBalances) }))
|
|
||||||
|
const balances = Map().withMutations((map) => {
|
||||||
|
withBalances.forEach(({ address, balance }) => {
|
||||||
|
map.set(address, balance)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
dispatch(updateSafe({ address: safeAddress, balances }))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.error('Error when fetching token balances:', err)
|
console.error('Error when fetching token balances:', err)
|
||||||
|
|
|
@ -11,7 +11,7 @@ const loadDefaultSafe = () => async (dispatch: ReduxDispatch<GlobalState>) => {
|
||||||
dispatch(setDefaultSafe(defaultSafe))
|
dispatch(setDefaultSafe(defaultSafe))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.error('Error while getting defautl safe from storage:', err)
|
console.error('Error while getting defautl Safe from storage:', err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ const loadSafesFromStorage = () => async (dispatch: ReduxDispatch<GlobalState>)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.error('Error while getting safes from storage:', err)
|
console.error('Error while getting Safes from storage:', err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { List } from 'immutable'
|
import { Set } from 'immutable'
|
||||||
import type { Dispatch as ReduxDispatch } from 'redux'
|
import type { Dispatch as ReduxDispatch } from 'redux'
|
||||||
import { type GlobalState } from '~/store'
|
import { type GlobalState } from '~/store'
|
||||||
import updateSafe from './updateSafe'
|
import updateSafe from './updateSafe'
|
||||||
|
@ -14,7 +14,7 @@ import updateSafe from './updateSafe'
|
||||||
// },
|
// },
|
||||||
// })
|
// })
|
||||||
|
|
||||||
const updateActiveTokens = (safeAddress: string, activeTokens: List<string>) => async (
|
const updateActiveTokens = (safeAddress: string, activeTokens: Set<string>) => async (
|
||||||
dispatch: ReduxDispatch<GlobalState>,
|
dispatch: ReduxDispatch<GlobalState>,
|
||||||
) => {
|
) => {
|
||||||
dispatch(updateSafe({ address: safeAddress, activeTokens }))
|
dispatch(updateSafe({ address: safeAddress, activeTokens }))
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { List, Record } from 'immutable'
|
import {
|
||||||
|
List, Record, Map, Set,
|
||||||
|
} from 'immutable'
|
||||||
import type { RecordFactory, RecordOf } from 'immutable'
|
import type { RecordFactory, RecordOf } from 'immutable'
|
||||||
import type { Owner } from '~/routes/safe/store/models/owner'
|
import type { Owner } from '~/routes/safe/store/models/owner'
|
||||||
import TokenBalance from '~/routes/safe/store/models/tokenBalance'
|
|
||||||
|
|
||||||
export type SafeProps = {
|
export type SafeProps = {
|
||||||
name: string,
|
name: string,
|
||||||
address: string,
|
address: string,
|
||||||
threshold: number,
|
threshold: number,
|
||||||
owners: List<Owner>,
|
owners: List<Owner>,
|
||||||
balances?: List<TokenBalance>,
|
balances: Map<string, string>,
|
||||||
activeTokens?: List<string>,
|
activeTokens: Set<string>,
|
||||||
ethBalance?: string,
|
ethBalance?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,8 +21,8 @@ const SafeRecord: RecordFactory<SafeProps> = Record({
|
||||||
threshold: 0,
|
threshold: 0,
|
||||||
ethBalance: 0,
|
ethBalance: 0,
|
||||||
owners: List([]),
|
owners: List([]),
|
||||||
activeTokens: List([]),
|
activeTokens: new Set([]),
|
||||||
balances: List([]),
|
balances: Map({}),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type Safe = RecordOf<SafeProps>
|
export type Safe = RecordOf<SafeProps>
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
// @flow
|
|
||||||
import { Record } from 'immutable'
|
|
||||||
import type { RecordFactory, RecordOf } from 'immutable'
|
|
||||||
|
|
||||||
export type TokenBalanceProps = {
|
|
||||||
address: string,
|
|
||||||
balance: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
const TokenBalanceRecord: RecordFactory<TokenBalanceProps> = Record({
|
|
||||||
address: '',
|
|
||||||
balance: '0',
|
|
||||||
})
|
|
||||||
|
|
||||||
export type TokenBalance = RecordOf<TokenBalanceProps>
|
|
||||||
|
|
||||||
export default TokenBalanceRecord
|
|
|
@ -1,9 +1,8 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { Map, List } from 'immutable'
|
import { Map, Set } from 'immutable'
|
||||||
import { handleActions, type ActionType } from 'redux-actions'
|
import { handleActions, type ActionType } from 'redux-actions'
|
||||||
import { ADD_SAFE, buildOwnersFrom } from '~/routes/safe/store/actions/addSafe'
|
import { ADD_SAFE, buildOwnersFrom } from '~/routes/safe/store/actions/addSafe'
|
||||||
import SafeRecord, { type SafeProps } from '~/routes/safe/store/models/safe'
|
import SafeRecord, { type SafeProps } from '~/routes/safe/store/models/safe'
|
||||||
import TokenBalance from '~/routes/safe/store/models/tokenBalance'
|
|
||||||
import { makeOwner, type OwnerProps } from '~/routes/safe/store/models/owner'
|
import { makeOwner, type OwnerProps } from '~/routes/safe/store/models/owner'
|
||||||
import { UPDATE_SAFE } from '~/routes/safe/store/actions/updateSafe'
|
import { UPDATE_SAFE } from '~/routes/safe/store/actions/updateSafe'
|
||||||
import { ACTIVATE_TOKEN_FOR_ALL_SAFES } from '~/routes/safe/store/actions/activateTokenForAllSafes'
|
import { ACTIVATE_TOKEN_FOR_ALL_SAFES } from '~/routes/safe/store/actions/activateTokenForAllSafes'
|
||||||
|
@ -22,8 +21,8 @@ export const buildSafe = (storedSafe: SafeProps) => {
|
||||||
const names = storedSafe.owners.map((owner: OwnerProps) => owner.name)
|
const names = storedSafe.owners.map((owner: OwnerProps) => owner.name)
|
||||||
const addresses = storedSafe.owners.map((owner: OwnerProps) => owner.address)
|
const addresses = storedSafe.owners.map((owner: OwnerProps) => owner.address)
|
||||||
const owners = buildOwnersFrom(Array.from(names), Array.from(addresses))
|
const owners = buildOwnersFrom(Array.from(names), Array.from(addresses))
|
||||||
const activeTokens = List(storedSafe.activeTokens)
|
const activeTokens = Set(storedSafe.activeTokens)
|
||||||
const balances = storedSafe.balances.map((balance) => TokenBalance(balance))
|
const balances = Map(storedSafe.balances)
|
||||||
|
|
||||||
const safe: SafeProps = {
|
const safe: SafeProps = {
|
||||||
...storedSafe,
|
...storedSafe,
|
||||||
|
@ -60,7 +59,7 @@ export default handleActions<SafeReducerState, *>(
|
||||||
[ADD_SAFE]: (state: SafeReducerState, action: ActionType<Function>): SafeReducerState => {
|
[ADD_SAFE]: (state: SafeReducerState, action: ActionType<Function>): SafeReducerState => {
|
||||||
const { safe }: { safe: SafeProps } = action.payload
|
const { safe }: { safe: SafeProps } = action.payload
|
||||||
|
|
||||||
// if you add a new safe it needs to be set as a record
|
// if you add a new Safe it needs to be set as a record
|
||||||
// in case of update it shouldn't, because a record would be initialized
|
// in case of update it shouldn't, because a record would be initialized
|
||||||
// with initial props and it would overwrite existing ones
|
// with initial props and it would overwrite existing ones
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
|
import OpenInNew from '@material-ui/icons/OpenInNew'
|
||||||
import Block from '~/components/layout/Block'
|
import Block from '~/components/layout/Block'
|
||||||
import Heading from '~/components/layout/Heading'
|
import Heading from '~/components/layout/Heading'
|
||||||
import Img from '~/components/layout/Img'
|
import Img from '~/components/layout/Img'
|
||||||
import Button from '~/components/layout/Button'
|
import Button from '~/components/layout/Button'
|
||||||
import Link from '~/components/layout/Link'
|
import Link from '~/components/layout/Link'
|
||||||
import { OPEN_ADDRESS, LOAD_ADDRESS } from '~/routes/routes'
|
import { OPEN_ADDRESS, LOAD_ADDRESS } from '~/routes/routes'
|
||||||
import { marginButtonImg } from '~/theme/variables'
|
import { marginButtonImg, secondary } from '~/theme/variables'
|
||||||
import styles from './Layout.scss'
|
import styles from './Layout.scss'
|
||||||
|
|
||||||
const safe = require('../assets/safe.svg')
|
const safe = require('../assets/safe.svg')
|
||||||
|
@ -16,6 +17,12 @@ type Props = {
|
||||||
provider: string,
|
provider: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const openIconStyle = {
|
||||||
|
height: '13px',
|
||||||
|
color: secondary,
|
||||||
|
marginBottom: '-2px',
|
||||||
|
}
|
||||||
|
|
||||||
type SafeProps = {
|
type SafeProps = {
|
||||||
provider: string,
|
provider: string,
|
||||||
size?: 'small' | 'medium' | 'large',
|
size?: 'small' | 'medium' | 'large',
|
||||||
|
@ -59,9 +66,9 @@ export const LoadSafe = ({ size, provider }: SafeProps) => (
|
||||||
const Welcome = ({ provider }: Props) => (
|
const Welcome = ({ provider }: Props) => (
|
||||||
<Block className={styles.safe}>
|
<Block className={styles.safe}>
|
||||||
<Heading tag="h1" weight="bold" align="center" margin="lg">
|
<Heading tag="h1" weight="bold" align="center" margin="lg">
|
||||||
Welcome to the Gnosis
|
Welcome to
|
||||||
<br />
|
<br />
|
||||||
Safe Team Edition
|
Gnosis Safe For Teams
|
||||||
</Heading>
|
</Heading>
|
||||||
<Heading tag="h3" align="center" margin="xl">
|
<Heading tag="h3" align="center" margin="xl">
|
||||||
The Gnosis Safe for Teams is geared towards teams managing shared
|
The Gnosis Safe for Teams is geared towards teams managing shared
|
||||||
|
@ -71,6 +78,11 @@ const Welcome = ({ provider }: Props) => (
|
||||||
wallet with redesigned smart contracts, cheaper setup and transaction
|
wallet with redesigned smart contracts, cheaper setup and transaction
|
||||||
<br />
|
<br />
|
||||||
costs as well as an enhanced user experience.
|
costs as well as an enhanced user experience.
|
||||||
|
{' '}
|
||||||
|
<a className={styles.learnMoreLink} href="https://safe.gnosis.io/teams" target="_blank" rel="noopener noreferrer">
|
||||||
|
Learn more
|
||||||
|
<OpenInNew style={openIconStyle} />
|
||||||
|
</a>
|
||||||
</Heading>
|
</Heading>
|
||||||
<Block className={styles.safeActions} margin="md">
|
<Block className={styles.safeActions} margin="md">
|
||||||
<CreateSafe size="large" provider={provider} />
|
<CreateSafe size="large" provider={provider} />
|
||||||
|
|
|
@ -13,3 +13,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.learnMoreLink {
|
||||||
|
color: $secondary;
|
||||||
|
}
|
||||||
|
|
|
@ -17,14 +17,14 @@ export type DomSafe = {
|
||||||
export const renderSafeInDom = async (owners: number = 1, threshold: number = 1): Promise<DomSafe> => {
|
export const renderSafeInDom = async (owners: number = 1, threshold: number = 1): Promise<DomSafe> => {
|
||||||
// create store
|
// create store
|
||||||
const store = aNewStore()
|
const store = aNewStore()
|
||||||
// deploy safe updating store
|
// deploy Safe updating store
|
||||||
const address = await aMinedSafe(store, owners, threshold)
|
const address = await aMinedSafe(store, owners, threshold)
|
||||||
// have available accounts
|
// have available accounts
|
||||||
const accounts = await getWeb3().eth.getAccounts()
|
const accounts = await getWeb3().eth.getAccounts()
|
||||||
// navigate to SAFE route
|
// navigate to SAFE route
|
||||||
const SafeDom = renderSafeView(store, address)
|
const SafeDom = renderSafeView(store, address)
|
||||||
|
|
||||||
// add funds to safe
|
// add funds to Safe
|
||||||
await sendEtherTo(address, '0.1')
|
await sendEtherTo(address, '0.1')
|
||||||
// wait until funds are displayed and buttons are enabled
|
// wait until funds are displayed and buttons are enabled
|
||||||
await sleep(3000)
|
await sleep(3000)
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { waitForElement } from '@testing-library/react'
|
import { waitForElement } from '@testing-library/react'
|
||||||
import { List } from 'immutable'
|
import { Set, Map } from 'immutable'
|
||||||
import { aNewStore } from '~/store'
|
import { aNewStore } from '~/store'
|
||||||
import { sleep } from '~/utils/timer'
|
import { sleep } from '~/utils/timer'
|
||||||
import { aMinedSafe } from '~/test/builder/safe.redux.builder'
|
import { aMinedSafe } from '~/test/builder/safe.redux.builder'
|
||||||
import { sendTokenTo, sendEtherTo } from '~/test/utils/tokenMovements'
|
import { sendTokenTo, sendEtherTo } from '~/test/utils/tokenMovements'
|
||||||
import { renderSafeView } from '~/test/builder/safe.dom.utils'
|
import { renderSafeView } from '~/test/builder/safe.dom.utils'
|
||||||
import { dispatchAddTokenToList } from '~/test/utils/transactions/moveTokens.helper'
|
import { dispatchAddTokenToList } from '~/test/utils/transactions/moveTokens.helper'
|
||||||
import TokenBalanceRecord from '~/routes/safe/store/models/tokenBalance'
|
|
||||||
import { calculateBalanceOf } from '~/routes/safe/store/actions/fetchTokenBalances'
|
import { calculateBalanceOf } from '~/routes/safe/store/actions/fetchTokenBalances'
|
||||||
import updateActiveTokens from '~/routes/safe/store/actions/updateActiveTokens'
|
import updateActiveTokens from '~/routes/safe/store/actions/updateActiveTokens'
|
||||||
import '@testing-library/jest-dom/extend-expect'
|
import '@testing-library/jest-dom/extend-expect'
|
||||||
|
@ -34,12 +33,11 @@ describe('DOM > Feature > Balances', () => {
|
||||||
const safeTokenBalance = await calculateBalanceOf(tokenAddress, safeAddress, 18)
|
const safeTokenBalance = await calculateBalanceOf(tokenAddress, safeAddress, 18)
|
||||||
expect(safeTokenBalance).toBe(tokensAmount)
|
expect(safeTokenBalance).toBe(tokensAmount)
|
||||||
|
|
||||||
const balanceAsRecord = TokenBalanceRecord({
|
const balances = Map({
|
||||||
address: tokenAddress,
|
[tokenAddress]: safeTokenBalance,
|
||||||
balance: safeTokenBalance,
|
|
||||||
})
|
})
|
||||||
store.dispatch(updateActiveTokens(safeAddress, List([tokenAddress])))
|
store.dispatch(updateActiveTokens(safeAddress, Set([tokenAddress])))
|
||||||
store.dispatch(updateSafe({ address: safeAddress, balances: List([balanceAsRecord]) }))
|
store.dispatch(updateSafe({ address: safeAddress, balances }))
|
||||||
await sleep(1000)
|
await sleep(1000)
|
||||||
|
|
||||||
const balanceRows = SafeDom.getAllByTestId(BALANCE_ROW_TEST_ID)
|
const balanceRows = SafeDom.getAllByTestId(BALANCE_ROW_TEST_ID)
|
||||||
|
|
|
@ -107,7 +107,7 @@ const deploySafe = async (createSafeForm: any, threshold: number, numOwners: num
|
||||||
fireEvent.submit(form)
|
fireEvent.submit(form)
|
||||||
})
|
})
|
||||||
|
|
||||||
// giving some time to the component for updating its state with safe
|
// giving some time to the component for updating its state with Safe
|
||||||
// before destroying its context
|
// before destroying its context
|
||||||
return whenSafeDeployed()
|
return whenSafeDeployed()
|
||||||
}
|
}
|
||||||
|
@ -120,8 +120,8 @@ const aDeployedSafe = async (specificStore: Store<GlobalState>, threshold?: numb
|
||||||
return safeAddress
|
return safeAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('DOM > Feature > CREATE a safe', () => {
|
describe('DOM > Feature > CREATE a Safe', () => {
|
||||||
it('fills correctly the safe form with 4 owners and 4 threshold and creates a safe', async () => {
|
it('fills correctly the Safe form with 4 owners and 4 threshold and creates a Safe', async () => {
|
||||||
const owners = 4
|
const owners = 4
|
||||||
const threshold = 4
|
const threshold = 4
|
||||||
const store = aNewStore()
|
const store = aNewStore()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { fireEvent } from '@testing-library/react'
|
import { fireEvent } from '@testing-library/react'
|
||||||
import { List } from 'immutable'
|
import { Map, Set } from 'immutable'
|
||||||
import { aNewStore } from '~/store'
|
import { aNewStore } from '~/store'
|
||||||
import { aMinedSafe } from '~/test/builder/safe.redux.builder'
|
import { aMinedSafe } from '~/test/builder/safe.redux.builder'
|
||||||
import { sendTokenTo, sendEtherTo } from '~/test/utils/tokenMovements'
|
import { sendTokenTo, sendEtherTo } from '~/test/utils/tokenMovements'
|
||||||
|
@ -8,7 +8,6 @@ import { renderSafeView } from '~/test/builder/safe.dom.utils'
|
||||||
import { getWeb3, getBalanceInEtherOf } from '~/logic/wallets/getWeb3'
|
import { getWeb3, getBalanceInEtherOf } from '~/logic/wallets/getWeb3'
|
||||||
import { dispatchAddTokenToList } from '~/test/utils/transactions/moveTokens.helper'
|
import { dispatchAddTokenToList } from '~/test/utils/transactions/moveTokens.helper'
|
||||||
import { sleep } from '~/utils/timer'
|
import { sleep } from '~/utils/timer'
|
||||||
import TokenBalanceRecord from '~/routes/safe/store/models/tokenBalance'
|
|
||||||
import { calculateBalanceOf } from '~/routes/safe/store/actions/fetchTokenBalances'
|
import { calculateBalanceOf } from '~/routes/safe/store/actions/fetchTokenBalances'
|
||||||
import updateActiveTokens from '~/routes/safe/store/actions/updateActiveTokens'
|
import updateActiveTokens from '~/routes/safe/store/actions/updateActiveTokens'
|
||||||
import '@testing-library/jest-dom/extend-expect'
|
import '@testing-library/jest-dom/extend-expect'
|
||||||
|
@ -78,12 +77,12 @@ describe('DOM > Feature > Sending Funds', () => {
|
||||||
const safeTokenBalance = await calculateBalanceOf(tokenAddress, safeAddress, 18)
|
const safeTokenBalance = await calculateBalanceOf(tokenAddress, safeAddress, 18)
|
||||||
expect(safeTokenBalance).toBe(tokensAmount)
|
expect(safeTokenBalance).toBe(tokensAmount)
|
||||||
|
|
||||||
const balanceAsRecord = TokenBalanceRecord({
|
const balances = Map({
|
||||||
address: tokenAddress,
|
[tokenAddress]: safeTokenBalance,
|
||||||
balance: safeTokenBalance,
|
|
||||||
})
|
})
|
||||||
store.dispatch(updateActiveTokens(safeAddress, List([tokenAddress])))
|
|
||||||
store.dispatch(updateSafe({ address: safeAddress, balances: List([balanceAsRecord]) }))
|
store.dispatch(updateActiveTokens(safeAddress, Set([tokenAddress])))
|
||||||
|
store.dispatch(updateSafe({ address: safeAddress, balances }))
|
||||||
await sleep(1000)
|
await sleep(1000)
|
||||||
|
|
||||||
// Open send funds modal
|
// Open send funds modal
|
||||||
|
|
|
@ -42,8 +42,8 @@ const renderLoadSafe = async (localStore: Store<GlobalState>) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('DOM > Feature > LOAD a safe', () => {
|
describe('DOM > Feature > LOAD a Safe', () => {
|
||||||
it('load correctly a created safe', async () => {
|
it('load correctly a created Safe', async () => {
|
||||||
const store = aNewStore()
|
const store = aNewStore()
|
||||||
const address = await aMinedSafe(store)
|
const address = await aMinedSafe(store)
|
||||||
const LoadSafePage = await renderLoadSafe(store)
|
const LoadSafePage = await renderLoadSafe(store)
|
||||||
|
|
|
@ -17,7 +17,7 @@ describe('DOM > Feature > Settings - Name', () => {
|
||||||
safeAddress = await aMinedSafe(store)
|
safeAddress = await aMinedSafe(store)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Changes safe name', async () => {
|
it('Changes Safe name', async () => {
|
||||||
const INITIAL_NAME = 'Safe Name'
|
const INITIAL_NAME = 'Safe Name'
|
||||||
const NEW_NAME = 'NEW SAFE NAME'
|
const NEW_NAME = 'NEW SAFE NAME'
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ describe('DOM > Feature > Sidebar', () => {
|
||||||
safeAddress = await aMinedSafe(store)
|
safeAddress = await aMinedSafe(store)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Shows "default" label for a single safe', async () => {
|
it('Shows "default" label for a single Safe', async () => {
|
||||||
const SafeDom = await renderSafeView(store, safeAddress)
|
const SafeDom = await renderSafeView(store, safeAddress)
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
|
@ -29,7 +29,7 @@ describe('DOM > Feature > Sidebar', () => {
|
||||||
expect(safes[0]).toContainElement(SafeDom.getByText('default'))
|
expect(safes[0]).toContainElement(SafeDom.getByText('default'))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Changes default safe', async () => {
|
it('Changes default Safe', async () => {
|
||||||
const SafeDom = await renderSafeView(store, safeAddress)
|
const SafeDom = await renderSafeView(store, safeAddress)
|
||||||
await aMinedSafe(store)
|
await aMinedSafe(store)
|
||||||
|
|
||||||
|
@ -39,17 +39,19 @@ describe('DOM > Feature > Sidebar', () => {
|
||||||
fireEvent.click(SafeDom.getByTestId(TOGGLE_SIDEBAR_BTN_TESTID))
|
fireEvent.click(SafeDom.getByTestId(TOGGLE_SIDEBAR_BTN_TESTID))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await sleep(400)
|
||||||
|
|
||||||
const safes = SafeDom.getAllByTestId(SIDEBAR_SAFELIST_ROW_TESTID)
|
const safes = SafeDom.getAllByTestId(SIDEBAR_SAFELIST_ROW_TESTID)
|
||||||
expect(safes.length).toBe(2)
|
expect(safes.length).toBe(2)
|
||||||
|
|
||||||
expect(safes[1]).toContainElement(SafeDom.getByText('default'))
|
expect(safes[0]).toContainElement(SafeDom.getByText('default'))
|
||||||
expect(safes[0]).toContainElement(SafeDom.getByText('Make default'))
|
expect(safes[1]).toContainElement(SafeDom.getByText('Make default'))
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
fireEvent.click(SafeDom.getByText('Make default'))
|
fireEvent.click(SafeDom.getByText('Make default'))
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(safes[0]).toContainElement(SafeDom.getByText('default'))
|
expect(safes[1]).toContainElement(SafeDom.getByText('default'))
|
||||||
expect(safes[1]).toContainElement(SafeDom.getByText('Make default'))
|
expect(safes[0]).toContainElement(SafeDom.getByText('Make default'))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
import { waitForElement } from '@testing-library/react'
|
||||||
import { List } from 'immutable'
|
import { List } from 'immutable'
|
||||||
import { getWeb3 } from '~/logic/wallets/getWeb3'
|
import { getWeb3 } from '~/logic/wallets/getWeb3'
|
||||||
import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements'
|
import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements'
|
||||||
|
@ -52,26 +53,25 @@ describe('DOM > Feature > Enable and disable default tokens', () => {
|
||||||
|
|
||||||
// WHEN
|
// WHEN
|
||||||
const TokensDom = await renderSafeView(store, safeAddress)
|
const TokensDom = await renderSafeView(store, safeAddress)
|
||||||
await sleep(400)
|
|
||||||
|
|
||||||
// Check if only ETH is enabled
|
// Check if only ETH is enabled
|
||||||
let balanceRows = TokensDom.getAllByTestId(BALANCE_ROW_TEST_ID)
|
let balanceRows = await waitForElement(() => TokensDom.getAllByTestId(BALANCE_ROW_TEST_ID))
|
||||||
expect(balanceRows.length).toBe(1)
|
expect(balanceRows.length).toBe(1)
|
||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
clickOnManageTokens(TokensDom)
|
clickOnManageTokens(TokensDom)
|
||||||
toggleToken(TokensDom, 'FTE')
|
await toggleToken(TokensDom, 'FTE')
|
||||||
toggleToken(TokensDom, 'STE')
|
await toggleToken(TokensDom, 'STE')
|
||||||
closeManageTokensModal(TokensDom)
|
closeManageTokensModal(TokensDom)
|
||||||
|
|
||||||
|
// Wait for active tokens to save
|
||||||
|
await sleep(1500)
|
||||||
|
|
||||||
// Check if tokens were enabled
|
// Check if tokens were enabled
|
||||||
balanceRows = TokensDom.getAllByTestId(BALANCE_ROW_TEST_ID)
|
balanceRows = TokensDom.getAllByTestId(BALANCE_ROW_TEST_ID)
|
||||||
expect(balanceRows.length).toBe(3)
|
expect(balanceRows.length).toBe(3)
|
||||||
expect(balanceRows[1]).toHaveTextContent('FTE')
|
expect(balanceRows[1]).toHaveTextContent('FTE')
|
||||||
expect(balanceRows[2]).toHaveTextContent('STE')
|
expect(balanceRows[2]).toHaveTextContent('STE')
|
||||||
|
|
||||||
await sleep(1000)
|
|
||||||
|
|
||||||
const tokensFromStorage = await getActiveTokens()
|
const tokensFromStorage = await getActiveTokens()
|
||||||
|
|
||||||
expect(Object.keys(tokensFromStorage)).toContain(firstErc20Token.address)
|
expect(Object.keys(tokensFromStorage)).toContain(firstErc20Token.address)
|
||||||
|
@ -79,9 +79,10 @@ describe('DOM > Feature > Enable and disable default tokens', () => {
|
||||||
|
|
||||||
// disable tokens
|
// disable tokens
|
||||||
clickOnManageTokens(TokensDom)
|
clickOnManageTokens(TokensDom)
|
||||||
toggleToken(TokensDom, 'FTE')
|
await toggleToken(TokensDom, 'FTE')
|
||||||
toggleToken(TokensDom, 'STE')
|
await toggleToken(TokensDom, 'STE')
|
||||||
closeManageTokensModal(TokensDom)
|
closeManageTokensModal(TokensDom)
|
||||||
|
await sleep(1500)
|
||||||
|
|
||||||
// check if tokens were disabled
|
// check if tokens were disabled
|
||||||
balanceRows = TokensDom.getAllByTestId(BALANCE_ROW_TEST_ID)
|
balanceRows = TokensDom.getAllByTestId(BALANCE_ROW_TEST_ID)
|
||||||
|
|
|
@ -1,32 +1,38 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { fireEvent } from '@testing-library/react'
|
import { fireEvent, waitForElement, act } from '@testing-library/react'
|
||||||
import { MANAGE_TOKENS_BUTTON_TEST_ID } from '~/routes/safe/components/Balances'
|
import { MANAGE_TOKENS_BUTTON_TEST_ID } from '~/routes/safe/components/Balances'
|
||||||
import {
|
import { ADD_CUSTOM_TOKEN_BUTTON_TEST_ID } from '~/routes/safe/components/Balances/Tokens/screens/TokenList'
|
||||||
ADD_CUSTOM_TOKEN_BUTTON_TEST_ID,
|
import { TOGGLE_TOKEN_TEST_ID } from '~/routes/safe/components/Balances/Tokens/screens/TokenList/TokenRow'
|
||||||
TOGGLE_TOKEN_TEST_ID,
|
|
||||||
} from '~/routes/safe/components/Balances/Tokens/screens/TokenList'
|
|
||||||
import { MANAGE_TOKENS_MODAL_CLOSE_BUTTON_TEST_ID } from '~/routes/safe/components/Balances/Tokens'
|
import { MANAGE_TOKENS_MODAL_CLOSE_BUTTON_TEST_ID } from '~/routes/safe/components/Balances/Tokens'
|
||||||
|
|
||||||
export const clickOnManageTokens = (dom: any): void => {
|
export const clickOnManageTokens = (dom: any): void => {
|
||||||
const btn = dom.getByTestId(MANAGE_TOKENS_BUTTON_TEST_ID)
|
const btn = dom.getByTestId(MANAGE_TOKENS_BUTTON_TEST_ID)
|
||||||
|
|
||||||
fireEvent.click(btn)
|
act(() => {
|
||||||
|
fireEvent.click(btn)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const clickOnAddCustomToken = (dom: any): void => {
|
export const clickOnAddCustomToken = (dom: any): void => {
|
||||||
const btn = dom.getByTestId(ADD_CUSTOM_TOKEN_BUTTON_TEST_ID)
|
const btn = dom.getByTestId(ADD_CUSTOM_TOKEN_BUTTON_TEST_ID)
|
||||||
|
|
||||||
fireEvent.click(btn)
|
act(() => {
|
||||||
|
fireEvent.click(btn)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const toggleToken = (dom: any, symbol: string): void => {
|
export const toggleToken = async (dom: any, symbol: string): Promise<void> => {
|
||||||
const btn = dom.getByTestId(`${symbol}_${TOGGLE_TOKEN_TEST_ID}`)
|
const btn = await waitForElement(() => dom.getByTestId(`${symbol}_${TOGGLE_TOKEN_TEST_ID}`))
|
||||||
|
|
||||||
fireEvent.click(btn)
|
act(() => {
|
||||||
|
fireEvent.click(btn)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const closeManageTokensModal = (dom: any) => {
|
export const closeManageTokensModal = (dom: any) => {
|
||||||
const btn = dom.getByTestId(MANAGE_TOKENS_MODAL_CLOSE_BUTTON_TEST_ID)
|
const btn = dom.getByTestId(MANAGE_TOKENS_MODAL_CLOSE_BUTTON_TEST_ID)
|
||||||
|
|
||||||
fireEvent.click(btn)
|
act(() => {
|
||||||
|
fireEvent.click(btn)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,7 +246,7 @@ export default createMuiTheme({
|
||||||
caption: {
|
caption: {
|
||||||
fontFamily: 'Averta, monospace',
|
fontFamily: 'Averta, monospace',
|
||||||
fontSize: mediumFontSize,
|
fontSize: mediumFontSize,
|
||||||
order: 3,
|
order: 2,
|
||||||
color: disabled,
|
color: disabled,
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
|
@ -254,6 +254,10 @@ export default createMuiTheme({
|
||||||
width: '60px',
|
width: '60px',
|
||||||
padding: `0 ${md} 0 0`,
|
padding: `0 ${md} 0 0`,
|
||||||
},
|
},
|
||||||
|
select: {
|
||||||
|
paddingRight: 30,
|
||||||
|
minWidth: '20px',
|
||||||
|
},
|
||||||
actions: {
|
actions: {
|
||||||
order: 4,
|
order: 4,
|
||||||
color: disabled,
|
color: disabled,
|
||||||
|
|
438
yarn.lock
438
yarn.lock
|
@ -1332,6 +1332,13 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.2"
|
regenerator-runtime "^0.13.2"
|
||||||
|
|
||||||
|
"@babel/runtime@^7.6.0":
|
||||||
|
version "7.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.2.tgz#c3d6e41b304ef10dcf13777a33e7694ec4a9a6dd"
|
||||||
|
integrity sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==
|
||||||
|
dependencies:
|
||||||
|
regenerator-runtime "^0.13.2"
|
||||||
|
|
||||||
"@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4":
|
"@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4":
|
||||||
version "7.4.4"
|
version "7.4.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237"
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237"
|
||||||
|
@ -1753,14 +1760,14 @@
|
||||||
"@types/istanbul-reports" "^1.1.1"
|
"@types/istanbul-reports" "^1.1.1"
|
||||||
"@types/yargs" "^13.0.0"
|
"@types/yargs" "^13.0.0"
|
||||||
|
|
||||||
"@material-ui/core@4.4.3":
|
"@material-ui/core@4.5.0":
|
||||||
version "4.4.3"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.4.3.tgz#65665d2c4e9cb84e018774e1471f6d0417f4535e"
|
resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.5.0.tgz#7e57cc40988c71b6340e3b2569b47dbac1820351"
|
||||||
integrity sha512-Lz8sMFeCrtq5/pbhqClWFHpveL0huixjca0tw7uvh9xKKB7VyyYOyTu7RamSZLxb34UCSMPlobR+KK25Nqzkqw==
|
integrity sha512-UHVAjU+1uDtA+OMBNBHb4RlCZOu514XeYPafNJv+GTdXBDr1SCPK7yqRE6TV1/bulxlDusTgu5Q6BAUgpmO4MA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.4.4"
|
"@babel/runtime" "^7.4.4"
|
||||||
"@material-ui/styles" "^4.4.3"
|
"@material-ui/styles" "^4.5.0"
|
||||||
"@material-ui/system" "^4.4.3"
|
"@material-ui/system" "^4.5.0"
|
||||||
"@material-ui/types" "^4.1.1"
|
"@material-ui/types" "^4.1.1"
|
||||||
"@material-ui/utils" "^4.4.0"
|
"@material-ui/utils" "^4.4.0"
|
||||||
"@types/react-transition-group" "^4.2.0"
|
"@types/react-transition-group" "^4.2.0"
|
||||||
|
@ -1781,10 +1788,10 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.4.4"
|
"@babel/runtime" "^7.4.4"
|
||||||
|
|
||||||
"@material-ui/styles@^4.4.3":
|
"@material-ui/styles@^4.5.0":
|
||||||
version "4.4.3"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.4.3.tgz#78239177723660093cc9a277db5759c01c693c2a"
|
resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.5.0.tgz#4e591b8d44c7ecce318634bd8ac652499b6c277a"
|
||||||
integrity sha512-kNUdHFWsrvWKIEPx8Xy2/qayqsGMrYmCMq+FIiJiYczVZl5hiS8j5+KayonnpVta/O+Dktk+cxWkVcgwtxMrHg==
|
integrity sha512-O0NSAECHK9f3DZK6wy56PZzp8b/7KSdfpJs8DSC7vnXUAoMPCTtchBKLzMtUsNlijiJFeJjSxNdQfjWXgyur5A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.4.4"
|
"@babel/runtime" "^7.4.4"
|
||||||
"@emotion/hash" "^0.7.1"
|
"@emotion/hash" "^0.7.1"
|
||||||
|
@ -1794,20 +1801,20 @@
|
||||||
csstype "^2.5.2"
|
csstype "^2.5.2"
|
||||||
deepmerge "^4.0.0"
|
deepmerge "^4.0.0"
|
||||||
hoist-non-react-statics "^3.2.1"
|
hoist-non-react-statics "^3.2.1"
|
||||||
jss "10.0.0-alpha.25"
|
jss "^10.0.0"
|
||||||
jss-plugin-camel-case "10.0.0-alpha.25"
|
jss-plugin-camel-case "^10.0.0"
|
||||||
jss-plugin-default-unit "10.0.0-alpha.25"
|
jss-plugin-default-unit "^10.0.0"
|
||||||
jss-plugin-global "10.0.0-alpha.25"
|
jss-plugin-global "^10.0.0"
|
||||||
jss-plugin-nested "10.0.0-alpha.25"
|
jss-plugin-nested "^10.0.0"
|
||||||
jss-plugin-props-sort "10.0.0-alpha.25"
|
jss-plugin-props-sort "^10.0.0"
|
||||||
jss-plugin-rule-value-function "10.0.0-alpha.25"
|
jss-plugin-rule-value-function "^10.0.0"
|
||||||
jss-plugin-vendor-prefixer "10.0.0-alpha.25"
|
jss-plugin-vendor-prefixer "^10.0.0"
|
||||||
prop-types "^15.7.2"
|
prop-types "^15.7.2"
|
||||||
|
|
||||||
"@material-ui/system@^4.4.3":
|
"@material-ui/system@^4.5.0":
|
||||||
version "4.4.3"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.4.3.tgz#68ca8cf83614255fcd5b9d3a72ce8ee58a43a5c7"
|
resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.5.0.tgz#3235f5d7da8b8af4df425e4f065990c16dee8097"
|
||||||
integrity sha512-Cb05vLXsaCzssXD/iZKa0/qC6YOwbFWnYdnOEdkXZ3Fn2Ytz7rsnMgFejUSQV1luVhUBlEIm8DVz40N25WwW7w==
|
integrity sha512-vR0PbMTzLnuuVCoYNQ13zyhLa/4s/UA9P9JbNuHBOOkfrHn53ShINiG0v05EgfwizfULLtc7mNvsGAgIyyp/hQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.4.4"
|
"@babel/runtime" "^7.4.4"
|
||||||
deepmerge "^4.0.0"
|
deepmerge "^4.0.0"
|
||||||
|
@ -2497,10 +2504,10 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
defer-to-connect "^1.0.1"
|
defer-to-connect "^1.0.1"
|
||||||
|
|
||||||
"@testing-library/dom@^6.1.0":
|
"@testing-library/dom@^6.3.0":
|
||||||
version "6.1.0"
|
version "6.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-6.1.0.tgz#8d5a954158e81ecd7c994907f4ec240296ed823b"
|
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-6.4.1.tgz#4efd38d896b9b2255025acf9567e2360e1f4814f"
|
||||||
integrity sha512-qivqFvnbVIH3DyArFofEU/jlOhkGIioIemOy9A9M/NQTpPyDDQmtVkAfoB18RKN581f0s/RJMRBbq9WfMIhFTw==
|
integrity sha512-bjPHLO5NzlTvA57Tfz8txHEUmnOed3NuvObB2ttoKfO6A/utr7TZt9bDHHcYymcZIG2IsQZLix/m4ZKkedDDwQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.5.5"
|
"@babel/runtime" "^7.5.5"
|
||||||
"@sheerun/mutationobserver-shim" "^0.3.2"
|
"@sheerun/mutationobserver-shim" "^0.3.2"
|
||||||
|
@ -2524,13 +2531,13 @@
|
||||||
pretty-format "^24.0.0"
|
pretty-format "^24.0.0"
|
||||||
redent "^3.0.0"
|
redent "^3.0.0"
|
||||||
|
|
||||||
"@testing-library/react@9.1.4":
|
"@testing-library/react@9.3.0":
|
||||||
version "9.1.4"
|
version "9.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-9.1.4.tgz#4cc1a228a944c0f468ee501e7da1651d8bbd9902"
|
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-9.3.0.tgz#1dabf46d1ea018a1c89acecc0e7b86859b34c0f8"
|
||||||
integrity sha512-fQ/PXZoLcmnS1W5ZiM3P7XBy2x6Hm9cJAT/ZDuZKzJ1fS1rN3j31p7ReAqUe3N1kJ46sNot0n1oiGbz7FPU+FA==
|
integrity sha512-FTPCwmLo0tLtP50Au2uGz4/N1BcJTnBx4StDVHZ47zPMEj1/+J2rk/RTj8SLoHRKWCtcmhN4wRmudOXQNP29/w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.5.5"
|
"@babel/runtime" "^7.6.0"
|
||||||
"@testing-library/dom" "^6.1.0"
|
"@testing-library/dom" "^6.3.0"
|
||||||
"@types/testing-library__react" "^9.1.0"
|
"@types/testing-library__react" "^9.1.0"
|
||||||
|
|
||||||
"@truffle/blockchain-utils@^0.0.11":
|
"@truffle/blockchain-utils@^0.0.11":
|
||||||
|
@ -3037,11 +3044,6 @@ acorn-jsx@^5.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e"
|
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e"
|
||||||
integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==
|
integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==
|
||||||
|
|
||||||
acorn-jsx@^5.0.2:
|
|
||||||
version "5.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f"
|
|
||||||
integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==
|
|
||||||
|
|
||||||
acorn-walk@^6.0.1, acorn-walk@^6.1.1:
|
acorn-walk@^6.0.1, acorn-walk@^6.1.1:
|
||||||
version "6.2.0"
|
version "6.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
|
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
|
||||||
|
@ -3067,11 +3069,6 @@ acorn@^6.0.1, acorn@^6.0.7, acorn@^6.2.0, acorn@^6.2.1:
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.1.tgz#3ed8422d6dec09e6121cc7a843ca86a330a86b51"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.1.tgz#3ed8422d6dec09e6121cc7a843ca86a330a86b51"
|
||||||
integrity sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==
|
integrity sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==
|
||||||
|
|
||||||
acorn@^7.0.0:
|
|
||||||
version "7.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.0.0.tgz#26b8d1cd9a9b700350b71c0905546f64d1284e7a"
|
|
||||||
integrity sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==
|
|
||||||
|
|
||||||
address@1.0.3:
|
address@1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9"
|
resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9"
|
||||||
|
@ -6426,10 +6423,10 @@ data-urls@^1.0.0:
|
||||||
whatwg-mimetype "^2.2.0"
|
whatwg-mimetype "^2.2.0"
|
||||||
whatwg-url "^7.0.0"
|
whatwg-url "^7.0.0"
|
||||||
|
|
||||||
date-fns@2.3.0:
|
date-fns@2.4.1:
|
||||||
version "2.3.0"
|
version "2.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.3.0.tgz#017eae725d0c46173b572da025fb5e4e534270fd"
|
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.4.1.tgz#b53f9bb65ae6bd9239437035710e01cf383b625e"
|
||||||
integrity sha512-A8o+iXBVqQayl9Z39BHgb7m/zLOfhF7LK82t+n9Fq1adds1vaUn8ByVoADqWLe4OTc6BZYc/FdbdTwufNYqkJw==
|
integrity sha512-2RhmH/sjDSCYW2F3ZQxOUx/I7PvzXpi89aQL2d3OAxSTwLx6NilATeUbe0menFE3Lu5lFkOFci36ivimwYHHxw==
|
||||||
|
|
||||||
date-now@^0.1.4:
|
date-now@^0.1.4:
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
|
@ -7338,20 +7335,20 @@ eslint-plugin-jsx-a11y@6.2.3:
|
||||||
has "^1.0.3"
|
has "^1.0.3"
|
||||||
jsx-ast-utils "^2.2.1"
|
jsx-ast-utils "^2.2.1"
|
||||||
|
|
||||||
eslint-plugin-react@7.14.3:
|
eslint-plugin-react@7.15.0:
|
||||||
version "7.14.3"
|
version "7.15.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.14.3.tgz#911030dd7e98ba49e1b2208599571846a66bdf13"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.15.0.tgz#4808b19cf7b4c439454099d4eb8f0cf0e9fe31dd"
|
||||||
integrity sha512-EzdyyBWC4Uz2hPYBiEJrKCUi2Fn+BJ9B/pJQcjw5X+x/H2Nm59S4MJIvL4O5NEE0+WbnQwEBxWY03oUk+Bc3FA==
|
integrity sha512-NbIh/yVXoltm8Df28PiPRanfCZAYubGqXU391MTCpW955Vum7S0nZdQYXGAvDh9ye4aNCmOR6YcYZsfMbEQZQA==
|
||||||
dependencies:
|
dependencies:
|
||||||
array-includes "^3.0.3"
|
array-includes "^3.0.3"
|
||||||
doctrine "^2.1.0"
|
doctrine "^2.1.0"
|
||||||
has "^1.0.3"
|
has "^1.0.3"
|
||||||
jsx-ast-utils "^2.1.0"
|
jsx-ast-utils "^2.2.1"
|
||||||
object.entries "^1.1.0"
|
object.entries "^1.1.0"
|
||||||
object.fromentries "^2.0.0"
|
object.fromentries "^2.0.0"
|
||||||
object.values "^1.1.0"
|
object.values "^1.1.0"
|
||||||
prop-types "^15.7.2"
|
prop-types "^15.7.2"
|
||||||
resolve "^1.10.1"
|
resolve "^1.12.0"
|
||||||
|
|
||||||
eslint-scope@^3.7.1:
|
eslint-scope@^3.7.1:
|
||||||
version "3.7.3"
|
version "3.7.3"
|
||||||
|
@ -7369,14 +7366,6 @@ eslint-scope@^4.0.0, eslint-scope@^4.0.3:
|
||||||
esrecurse "^4.1.0"
|
esrecurse "^4.1.0"
|
||||||
estraverse "^4.1.1"
|
estraverse "^4.1.1"
|
||||||
|
|
||||||
eslint-scope@^5.0.0:
|
|
||||||
version "5.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9"
|
|
||||||
integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==
|
|
||||||
dependencies:
|
|
||||||
esrecurse "^4.1.0"
|
|
||||||
estraverse "^4.1.1"
|
|
||||||
|
|
||||||
eslint-utils@^1.3.1:
|
eslint-utils@^1.3.1:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.0.tgz#e2c3c8dba768425f897cf0f9e51fe2e241485d4c"
|
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.0.tgz#e2c3c8dba768425f897cf0f9e51fe2e241485d4c"
|
||||||
|
@ -7384,67 +7373,12 @@ eslint-utils@^1.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint-visitor-keys "^1.0.0"
|
eslint-visitor-keys "^1.0.0"
|
||||||
|
|
||||||
eslint-utils@^1.4.2:
|
|
||||||
version "1.4.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab"
|
|
||||||
integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==
|
|
||||||
dependencies:
|
|
||||||
eslint-visitor-keys "^1.0.0"
|
|
||||||
|
|
||||||
eslint-visitor-keys@^1.0.0:
|
eslint-visitor-keys@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
|
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
|
||||||
integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==
|
integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==
|
||||||
|
|
||||||
eslint-visitor-keys@^1.1.0:
|
eslint@5.16.0, eslint@^5.0.0, eslint@^5.5.0:
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
|
|
||||||
integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
|
|
||||||
|
|
||||||
eslint@6.4.0:
|
|
||||||
version "6.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.4.0.tgz#5aa9227c3fbe921982b2eda94ba0d7fae858611a"
|
|
||||||
integrity sha512-WTVEzK3lSFoXUovDHEbkJqCVPEPwbhCq4trDktNI6ygs7aO41d4cDT0JFAT5MivzZeVLWlg7vHL+bgrQv/t3vA==
|
|
||||||
dependencies:
|
|
||||||
"@babel/code-frame" "^7.0.0"
|
|
||||||
ajv "^6.10.0"
|
|
||||||
chalk "^2.1.0"
|
|
||||||
cross-spawn "^6.0.5"
|
|
||||||
debug "^4.0.1"
|
|
||||||
doctrine "^3.0.0"
|
|
||||||
eslint-scope "^5.0.0"
|
|
||||||
eslint-utils "^1.4.2"
|
|
||||||
eslint-visitor-keys "^1.1.0"
|
|
||||||
espree "^6.1.1"
|
|
||||||
esquery "^1.0.1"
|
|
||||||
esutils "^2.0.2"
|
|
||||||
file-entry-cache "^5.0.1"
|
|
||||||
functional-red-black-tree "^1.0.1"
|
|
||||||
glob-parent "^5.0.0"
|
|
||||||
globals "^11.7.0"
|
|
||||||
ignore "^4.0.6"
|
|
||||||
import-fresh "^3.0.0"
|
|
||||||
imurmurhash "^0.1.4"
|
|
||||||
inquirer "^6.4.1"
|
|
||||||
is-glob "^4.0.0"
|
|
||||||
js-yaml "^3.13.1"
|
|
||||||
json-stable-stringify-without-jsonify "^1.0.1"
|
|
||||||
levn "^0.3.0"
|
|
||||||
lodash "^4.17.14"
|
|
||||||
minimatch "^3.0.4"
|
|
||||||
mkdirp "^0.5.1"
|
|
||||||
natural-compare "^1.4.0"
|
|
||||||
optionator "^0.8.2"
|
|
||||||
progress "^2.0.0"
|
|
||||||
regexpp "^2.0.1"
|
|
||||||
semver "^6.1.2"
|
|
||||||
strip-ansi "^5.2.0"
|
|
||||||
strip-json-comments "^3.0.1"
|
|
||||||
table "^5.2.3"
|
|
||||||
text-table "^0.2.0"
|
|
||||||
v8-compile-cache "^2.0.3"
|
|
||||||
|
|
||||||
eslint@^5.0.0, eslint@^5.5.0:
|
|
||||||
version "5.16.0"
|
version "5.16.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea"
|
resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea"
|
||||||
integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==
|
integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==
|
||||||
|
@ -7503,15 +7437,6 @@ espree@^5.0.1:
|
||||||
acorn-jsx "^5.0.0"
|
acorn-jsx "^5.0.0"
|
||||||
eslint-visitor-keys "^1.0.0"
|
eslint-visitor-keys "^1.0.0"
|
||||||
|
|
||||||
espree@^6.1.1:
|
|
||||||
version "6.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.1.tgz#7f80e5f7257fc47db450022d723e356daeb1e5de"
|
|
||||||
integrity sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ==
|
|
||||||
dependencies:
|
|
||||||
acorn "^7.0.0"
|
|
||||||
acorn-jsx "^5.0.2"
|
|
||||||
eslint-visitor-keys "^1.1.0"
|
|
||||||
|
|
||||||
esprima@^3.1.3, esprima@~3.1.0:
|
esprima@^3.1.3, esprima@~3.1.0:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
|
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
|
||||||
|
@ -8588,10 +8513,10 @@ flatted@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08"
|
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08"
|
||||||
integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==
|
integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==
|
||||||
|
|
||||||
flow-bin@0.108.0:
|
flow-bin@0.109.0:
|
||||||
version "0.108.0"
|
version "0.109.0"
|
||||||
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.108.0.tgz#6a42c85fd664d23dd937d925851e8e6ab5d71393"
|
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.109.0.tgz#dcdcb7402dd85b58200392d8716ccf14e5a8c24c"
|
||||||
integrity sha512-hPEyCP1J8rdhNDfCAA5w7bN6HUNBDcHVg/ABU5JVo0gUFMx+uRewpyEH8LlLBGjVQuIpbaPpaqpoaQhAVyaYww==
|
integrity sha512-tpcMTpAGIRivYhFV3KJq+zHI2HzcXo8MoGe9pXS4G/UZuey2Faq/e8/gdph2WF0erRlML5hmwfwiq7v9c25c7w==
|
||||||
|
|
||||||
flow-stoplight@^1.0.0:
|
flow-stoplight@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
|
@ -9086,13 +9011,6 @@ glob-parent@^3.1.0:
|
||||||
is-glob "^3.1.0"
|
is-glob "^3.1.0"
|
||||||
path-dirname "^1.0.0"
|
path-dirname "^1.0.0"
|
||||||
|
|
||||||
glob-parent@^5.0.0:
|
|
||||||
version "5.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954"
|
|
||||||
integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==
|
|
||||||
dependencies:
|
|
||||||
is-glob "^4.0.1"
|
|
||||||
|
|
||||||
glob-stream@^6.1.0:
|
glob-stream@^6.1.0:
|
||||||
version "6.1.0"
|
version "6.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4"
|
resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4"
|
||||||
|
@ -9826,7 +9744,7 @@ http-https@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4"
|
resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4"
|
||||||
integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=
|
integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=
|
||||||
|
|
||||||
http-proxy-middleware@^0.19.1:
|
http-proxy-middleware@0.19.1:
|
||||||
version "0.19.1"
|
version "0.19.1"
|
||||||
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a"
|
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a"
|
||||||
integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==
|
integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==
|
||||||
|
@ -10090,25 +10008,6 @@ inquirer@^6.2.0, inquirer@^6.2.2:
|
||||||
strip-ansi "^5.1.0"
|
strip-ansi "^5.1.0"
|
||||||
through "^2.3.6"
|
through "^2.3.6"
|
||||||
|
|
||||||
inquirer@^6.4.1:
|
|
||||||
version "6.5.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca"
|
|
||||||
integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==
|
|
||||||
dependencies:
|
|
||||||
ansi-escapes "^3.2.0"
|
|
||||||
chalk "^2.4.2"
|
|
||||||
cli-cursor "^2.1.0"
|
|
||||||
cli-width "^2.0.0"
|
|
||||||
external-editor "^3.0.3"
|
|
||||||
figures "^2.0.0"
|
|
||||||
lodash "^4.17.12"
|
|
||||||
mute-stream "0.0.7"
|
|
||||||
run-async "^2.2.0"
|
|
||||||
rxjs "^6.4.0"
|
|
||||||
string-width "^2.1.0"
|
|
||||||
strip-ansi "^5.1.0"
|
|
||||||
through "^2.3.6"
|
|
||||||
|
|
||||||
internal-ip@^4.3.0:
|
internal-ip@^4.3.0:
|
||||||
version "4.3.0"
|
version "4.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907"
|
resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907"
|
||||||
|
@ -10171,10 +10070,10 @@ is-absolute-url@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
|
resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
|
||||||
integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=
|
integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=
|
||||||
|
|
||||||
is-absolute-url@^3.0.2:
|
is-absolute-url@^3.0.3:
|
||||||
version "3.0.2"
|
version "3.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.2.tgz#554f2933e7385cc46e94351977ca2081170a206e"
|
resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698"
|
||||||
integrity sha512-+5g/wLlcm1AcxSP7014m6GvbPHswDx980vD/3bZaap8aGV9Yfs7Q6y6tfaupgZ5O74Byzc8dGrSCJ+bFXx0KdA==
|
integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==
|
||||||
|
|
||||||
is-absolute@^1.0.0:
|
is-absolute@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
|
@ -10399,7 +10298,7 @@ is-glob@^3.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-extglob "^2.1.0"
|
is-extglob "^2.1.0"
|
||||||
|
|
||||||
is-glob@^4.0.0, is-glob@^4.0.1:
|
is-glob@^4.0.0:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
|
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
|
||||||
integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
|
integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
|
||||||
|
@ -11391,76 +11290,76 @@ jsqr@^1.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/jsqr/-/jsqr-1.2.0.tgz#f93fc65fa7d1ded78b1bcb020fa044352b04261a"
|
resolved "https://registry.yarnpkg.com/jsqr/-/jsqr-1.2.0.tgz#f93fc65fa7d1ded78b1bcb020fa044352b04261a"
|
||||||
integrity sha512-wKcQS9QC2VHGk7aphWCp1RrFyC0CM6fMgC5prZZ2KV/Lk6OKNoCod9IR6bao+yx3KPY0gZFC5dc+h+KFzCI0Wg==
|
integrity sha512-wKcQS9QC2VHGk7aphWCp1RrFyC0CM6fMgC5prZZ2KV/Lk6OKNoCod9IR6bao+yx3KPY0gZFC5dc+h+KFzCI0Wg==
|
||||||
|
|
||||||
jss-plugin-camel-case@10.0.0-alpha.25:
|
jss-plugin-camel-case@^10.0.0:
|
||||||
version "10.0.0-alpha.25"
|
version "10.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.0.0-alpha.25.tgz#ea4389de47ccf3b4757f76e62cbb2e8b96b7a2c2"
|
resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.0.0.tgz#d601bae2e8e2041cc526add289dcd7062db0a248"
|
||||||
integrity sha512-J5ZEGDTy9ddqdTUPAF4SJQ25u5kiG1ORP8F+ZPEZAkkiMQJp+/Aol4I7xhTS2aW1Lhg8xNxdhdRfBi5yU7wOvg==
|
integrity sha512-yALDL00+pPR4FJh+k07A8FeDvfoPPuXU48HLy63enAubcVd3DnS+2rgqPXglHDGixIDVkCSXecl/l5GAMjzIbA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.3.1"
|
"@babel/runtime" "^7.3.1"
|
||||||
hyphenate-style-name "^1.0.3"
|
hyphenate-style-name "^1.0.3"
|
||||||
jss "10.0.0-alpha.25"
|
jss "10.0.0"
|
||||||
|
|
||||||
jss-plugin-default-unit@10.0.0-alpha.25:
|
jss-plugin-default-unit@^10.0.0:
|
||||||
version "10.0.0-alpha.25"
|
version "10.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.0.0-alpha.25.tgz#df5b39bbc0114146101bb3cf8bc7e281e3d0f454"
|
resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.0.0.tgz#601caf5f576fc0c66986fbe8a9aa37307a3a3ea3"
|
||||||
integrity sha512-auOG459B+yEqkojgaXH02SYO9+xjmAxlmP+WbzhVpXqOFJ2CN/kaxd8P4NJZLdj3BQxHiM7WIyMVh786StE+EA==
|
integrity sha512-sURozIOdCtGg9ap18erQ+ijndAfEGtTaetxfU3H4qwC18Bi+fdvjlY/ahKbuu0ASs7R/+WKCP7UaRZOjUDMcdQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.3.1"
|
"@babel/runtime" "^7.3.1"
|
||||||
jss "10.0.0-alpha.25"
|
jss "10.0.0"
|
||||||
|
|
||||||
jss-plugin-global@10.0.0-alpha.25:
|
jss-plugin-global@^10.0.0:
|
||||||
version "10.0.0-alpha.25"
|
version "10.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.0.0-alpha.25.tgz#2b6a6a14ef6cdb9994dbadf709e480d5c871b5f6"
|
resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.0.0.tgz#0fed1b6461e0d57d6e394f877529009bc1cb3cb6"
|
||||||
integrity sha512-cS98Q8X8jwltuaBZd9eYuxMXxkUL+mJGl2Ok3/nmJzH9nLzj6i7kLxSoDtuJNqsRmbP7ogIXVozJUq9lUu2hlQ==
|
integrity sha512-80ofWKSQUo62bxLtRoTNe0kFPtHgUbAJeOeR36WEGgWIBEsXLyXOnD5KNnjPqG4heuEkz9eSLccjYST50JnI7Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.3.1"
|
"@babel/runtime" "^7.3.1"
|
||||||
jss "10.0.0-alpha.25"
|
jss "10.0.0"
|
||||||
|
|
||||||
jss-plugin-nested@10.0.0-alpha.25:
|
jss-plugin-nested@^10.0.0:
|
||||||
version "10.0.0-alpha.25"
|
version "10.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.0.0-alpha.25.tgz#b8e29d336e1850047914511681d56330e3ea24ac"
|
resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.0.0.tgz#d37ecc013c3b0d0e4acc2b48f6b62da6ae53948b"
|
||||||
integrity sha512-7sk7/6mX1YTgXe+AyeD1zEyKTgIGbbhYtg+wWQcHJlE1flW2JHfcQ5mw84FgHcHQRQ8Dq3l9I3aEY51ev0J1Wg==
|
integrity sha512-waxxwl/po1hN3azTyixKnr8ReEqUv5WK7WsO+5AWB0bFndML5Yqnt8ARZ90HEg8/P6WlqE/AB2413TkCRZE8bA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.3.1"
|
"@babel/runtime" "^7.3.1"
|
||||||
jss "10.0.0-alpha.25"
|
jss "10.0.0"
|
||||||
tiny-warning "^1.0.2"
|
tiny-warning "^1.0.2"
|
||||||
|
|
||||||
jss-plugin-props-sort@10.0.0-alpha.25:
|
jss-plugin-props-sort@^10.0.0:
|
||||||
version "10.0.0-alpha.25"
|
version "10.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.0.0-alpha.25.tgz#dfaa1a6bf9863ae9593b99bf51cd26caea2fe0ec"
|
resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.0.0.tgz#38a13407384c2a4a7c026659488350669b953b18"
|
||||||
integrity sha512-8B/6QLQuUX8cIlZbXdjEm5l0jCX4EgacYMcFJhdKwDKEZYeAghpgQQrCKl0/CYHW7iFge5wim67P+uL6QxMzyw==
|
integrity sha512-41mf22CImjwNdtOG3r+cdC8+RhwNm616sjHx5YlqTwtSJLyLFinbQC/a4PIFk8xqf1qpFH1kEAIw+yx9HaqZ3g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.3.1"
|
"@babel/runtime" "^7.3.1"
|
||||||
jss "10.0.0-alpha.25"
|
jss "10.0.0"
|
||||||
|
|
||||||
jss-plugin-rule-value-function@10.0.0-alpha.25:
|
jss-plugin-rule-value-function@^10.0.0:
|
||||||
version "10.0.0-alpha.25"
|
version "10.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.0.0-alpha.25.tgz#35350da52334a6031808e197526227434c194277"
|
resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.0.0.tgz#3ec1b781b7c86080136dbef6c36e91f20244b72e"
|
||||||
integrity sha512-CQQtWO+/OZRGaFRBSGQUgAci9YlVtdoXcWQKBNo70tmpp+kaXKlFNCYaL3jmHbJHMiwKQYG2RYFQNIrwJ9SGmA==
|
integrity sha512-Jw+BZ8JIw1f12V0SERqGlBT1JEPWax3vuZpMym54NAXpPb7R1LYHiCTIlaJUyqvIfEy3kiHMtgI+r2whGgRIxQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.3.1"
|
"@babel/runtime" "^7.3.1"
|
||||||
jss "10.0.0-alpha.25"
|
jss "10.0.0"
|
||||||
|
|
||||||
jss-plugin-vendor-prefixer@10.0.0-alpha.25:
|
jss-plugin-vendor-prefixer@^10.0.0:
|
||||||
version "10.0.0-alpha.25"
|
version "10.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.0.0-alpha.25.tgz#bc0c4b6dcb28d4801775cbad70ad9bc7e0c7707b"
|
resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.0.0.tgz#400280535b0f483a9c78105afe4eee61b70018eb"
|
||||||
integrity sha512-5FXpB/TiwckbrkoDCmd27YsWCESl1K4hAX/oro2/geEXgnVQvDgQOf2eWCsjYO2K1lYPPXtskMfws/Q3eKmbYg==
|
integrity sha512-qslqvL0MUbWuzXJWdUxpj6mdNUX8jr4FFTo3aZnAT65nmzWL7g8oTr9ZxmTXXgdp7ANhS1QWE7036/Q2isFBpw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.3.1"
|
"@babel/runtime" "^7.3.1"
|
||||||
css-vendor "^2.0.6"
|
css-vendor "^2.0.6"
|
||||||
jss "10.0.0-alpha.25"
|
jss "10.0.0"
|
||||||
|
|
||||||
jss@10.0.0-alpha.25:
|
jss@10.0.0, jss@^10.0.0:
|
||||||
version "10.0.0-alpha.25"
|
version "10.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jss/-/jss-10.0.0-alpha.25.tgz#20a506d8159e3f6bd91e133d54ffd3df0ffd3010"
|
resolved "https://registry.yarnpkg.com/jss/-/jss-10.0.0.tgz#998d5026c02accae15708de83bd6ba57bac977d2"
|
||||||
integrity sha512-zqKnXv181B9vue2yYhmVhc+6ggbbxHF/33rjXfXEjaa22nOvknTI21QDfq3oZ8uCC50kcFp3Z8KU1ghUXdFvIA==
|
integrity sha512-TPpDFsiBjuERiL+dFDq8QCdiF9oDasPcNqCKLGCo/qED3fNYOQ8PX2lZhknyTiAt3tZrfOFbb0lbQ9lTjPZxsQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.3.1"
|
"@babel/runtime" "^7.3.1"
|
||||||
csstype "^2.6.5"
|
csstype "^2.6.5"
|
||||||
is-in-browser "^1.1.3"
|
is-in-browser "^1.1.3"
|
||||||
tiny-warning "^1.0.2"
|
tiny-warning "^1.0.2"
|
||||||
|
|
||||||
jsx-ast-utils@^2.1.0, jsx-ast-utils@^2.2.1:
|
jsx-ast-utils@^2.2.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.1.tgz#4d4973ebf8b9d2837ee91a8208cc66f3a2776cfb"
|
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.1.tgz#4d4973ebf8b9d2837ee91a8208cc66f3a2776cfb"
|
||||||
integrity sha512-v3FxCcAf20DayI+uxnCuw795+oOIkVu6EnJ1+kSzhqqTZHNkTZ7B66ZgLp4oLJ/gbA64cI0B7WRoHZMSRdyVRQ==
|
integrity sha512-v3FxCcAf20DayI+uxnCuw795+oOIkVu6EnJ1+kSzhqqTZHNkTZ7B66ZgLp4oLJ/gbA64cI0B7WRoHZMSRdyVRQ==
|
||||||
|
@ -12234,6 +12133,11 @@ memdown@~3.0.0:
|
||||||
ltgt "~2.2.0"
|
ltgt "~2.2.0"
|
||||||
safe-buffer "~5.1.1"
|
safe-buffer "~5.1.1"
|
||||||
|
|
||||||
|
"memoize-one@>=3.1.1 <6":
|
||||||
|
version "5.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0"
|
||||||
|
integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==
|
||||||
|
|
||||||
memoize-one@^5.0.0:
|
memoize-one@^5.0.0:
|
||||||
version "5.0.5"
|
version "5.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.5.tgz#8cd3809555723a07684afafcd6f756072ac75d7e"
|
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.5.tgz#8cd3809555723a07684afafcd6f756072ac75d7e"
|
||||||
|
@ -12746,10 +12650,10 @@ node-fetch@^2.6.0:
|
||||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
|
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
|
||||||
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
|
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
|
||||||
|
|
||||||
node-forge@0.8.2:
|
node-forge@0.9.0:
|
||||||
version "0.8.2"
|
version "0.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.8.2.tgz#b4bcc59fb12ce77a8825fc6a783dfe3182499c5a"
|
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"
|
||||||
integrity sha512-mXQ9GBq1N3uDCyV1pdSzgIguwgtVpM7f5/5J4ipz12PKWElmPpVWLDuWl8iXmhysr21+WmX/OJ5UKx82wjomgg==
|
integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==
|
||||||
|
|
||||||
node-int64@^0.4.0:
|
node-int64@^0.4.0:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
|
@ -14705,15 +14609,15 @@ react-docgen@^4.1.0:
|
||||||
node-dir "^0.1.10"
|
node-dir "^0.1.10"
|
||||||
recast "^0.17.3"
|
recast "^0.17.3"
|
||||||
|
|
||||||
react-dom@16.9.0:
|
react-dom@16.10.2:
|
||||||
version "16.9.0"
|
version "16.10.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.9.0.tgz#5e65527a5e26f22ae3701131bcccaee9fb0d3962"
|
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.10.2.tgz#4840bce5409176bc3a1f2bd8cb10b92db452fda6"
|
||||||
integrity sha512-YFT2rxO9hM70ewk9jq0y6sQk8cL02xm4+IzYBz75CQGlClQQ1Bxq0nhHF6OtSbit+AIahujJgb/CPRibFkMNJQ==
|
integrity sha512-kWGDcH3ItJK4+6Pl9DZB16BXYAZyrYQItU4OMy0jAkv5aNqc+mAKb4TpFtAteI6TJZu+9ZlNhaeNQSVQDHJzkw==
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
prop-types "^15.6.2"
|
prop-types "^15.6.2"
|
||||||
scheduler "^0.15.0"
|
scheduler "^0.16.2"
|
||||||
|
|
||||||
react-dom@^16.8.3:
|
react-dom@^16.8.3:
|
||||||
version "16.8.6"
|
version "16.8.6"
|
||||||
|
@ -14893,23 +14797,23 @@ react-redux@7.1.1:
|
||||||
prop-types "^15.7.2"
|
prop-types "^15.7.2"
|
||||||
react-is "^16.9.0"
|
react-is "^16.9.0"
|
||||||
|
|
||||||
react-router-dom@^5.1.0:
|
react-router-dom@5.1.2:
|
||||||
version "5.1.0"
|
version "5.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.1.0.tgz#48ad018d71fb7835212587e4c90bd2e3d2417e31"
|
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.1.2.tgz#06701b834352f44d37fbb6311f870f84c76b9c18"
|
||||||
integrity sha512-OkxKbMKjO7IkYqnoaZNX19MnwgjhxwZE871cPUTq0YU2wpIw7QwGxSnSoNRMOa7wO1TwvJJMFpgiEB4C/gVhTw==
|
integrity sha512-7BPHAaIwWpZS074UKaw1FjVdZBSVWEk8IuDXdB+OkLb8vd/WRQIpA4ag9WQk61aEfQs47wHyjWUoUGGZxpQXew==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.1.2"
|
"@babel/runtime" "^7.1.2"
|
||||||
history "^4.9.0"
|
history "^4.9.0"
|
||||||
loose-envify "^1.3.1"
|
loose-envify "^1.3.1"
|
||||||
prop-types "^15.6.2"
|
prop-types "^15.6.2"
|
||||||
react-router "5.1.0"
|
react-router "5.1.2"
|
||||||
tiny-invariant "^1.0.2"
|
tiny-invariant "^1.0.2"
|
||||||
tiny-warning "^1.0.0"
|
tiny-warning "^1.0.0"
|
||||||
|
|
||||||
react-router@5.1.0:
|
react-router@5.1.2:
|
||||||
version "5.1.0"
|
version "5.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.1.0.tgz#739d0f3a57476363374e20d6e33e97f5ce2e00a3"
|
resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.1.2.tgz#6ea51d789cb36a6be1ba5f7c0d48dd9e817d3418"
|
||||||
integrity sha512-n9HXxaL/6yRlig9XPfGyagI8+bUNdqcu7FUAx0/Z+Us22Z8iHsbkyJ21Inebn9HOxI5Nxlfc8GNabkNSeXfhqw==
|
integrity sha512-yjEuMFy1ONK246B+rsa0cUam5OeAQ8pyclRDgpxuSCrAlJ1qN9uZ5IgyKC7gQg0w8OM50NXHEegPh/ks9YuR2A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.1.2"
|
"@babel/runtime" "^7.1.2"
|
||||||
history "^4.9.0"
|
history "^4.9.0"
|
||||||
|
@ -15000,10 +14904,18 @@ react-transition-group@^4.3.0:
|
||||||
loose-envify "^1.4.0"
|
loose-envify "^1.4.0"
|
||||||
prop-types "^15.6.2"
|
prop-types "^15.6.2"
|
||||||
|
|
||||||
react@16.9.0:
|
react-window@^1.8.5:
|
||||||
version "16.9.0"
|
version "1.8.5"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-16.9.0.tgz#40ba2f9af13bc1a38d75dbf2f4359a5185c4f7aa"
|
resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.5.tgz#a56b39307e79979721021f5d06a67742ecca52d1"
|
||||||
integrity sha512-+7LQnFBwkiw+BobzOF6N//BdoNw0ouwmSJTEm9cglOOmsg/TMiFHZLe2sEoN5M7LgJTj9oHH0gxklfnQe66S1w==
|
integrity sha512-HeTwlNa37AFa8MDZFZOKcNEkuF2YflA0hpGPiTT9vR7OawEt+GZbfM6wqkBahD3D3pUjIabQYzsnY/BSJbgq6Q==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.0.0"
|
||||||
|
memoize-one ">=3.1.1 <6"
|
||||||
|
|
||||||
|
react@16.10.2:
|
||||||
|
version "16.10.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/react/-/react-16.10.2.tgz#a5ede5cdd5c536f745173c8da47bda64797a4cf0"
|
||||||
|
integrity sha512-MFVIq0DpIhrHFyqLU0S3+4dIcBhhOvBE8bJ/5kHPVOVaGdo0KuiQzpcjCPsf585WvhypqtrMILyoE2th6dT+Lw==
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
|
@ -15686,7 +15598,7 @@ resolve@1.1.7:
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
||||||
integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
|
integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
|
||||||
|
|
||||||
resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.8.1, resolve@~1.11.1:
|
resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.8.1, resolve@~1.11.1:
|
||||||
version "1.11.1"
|
version "1.11.1"
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e"
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e"
|
||||||
integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==
|
integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==
|
||||||
|
@ -15905,10 +15817,10 @@ scheduler@^0.13.6:
|
||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
|
|
||||||
scheduler@^0.15.0:
|
scheduler@^0.16.2:
|
||||||
version "0.15.0"
|
version "0.16.2"
|
||||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.15.0.tgz#6bfcf80ff850b280fed4aeecc6513bc0b4f17f8e"
|
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.16.2.tgz#f74cd9d33eff6fc554edfb79864868e4819132c1"
|
||||||
integrity sha512-xAefmSfN6jqAa7Kuq7LIJY0bwAPG3xlCj0HMEBQk1lxYiDKZscY2xJ5U/61ZTrYbmNQbXa+gc7czPkVo11tnCg==
|
integrity sha512-BqYVWqwz6s1wZMhjFvLfVR5WXP7ZY32M/wYPo04CcuPM7XZEbV2TBNW7Z0UkguPTl0dWMA59VbNXxK6q+pHItg==
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
|
@ -16046,12 +15958,12 @@ select@^1.1.2:
|
||||||
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
|
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
|
||||||
integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=
|
integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=
|
||||||
|
|
||||||
selfsigned@^1.10.6:
|
selfsigned@^1.10.7:
|
||||||
version "1.10.6"
|
version "1.10.7"
|
||||||
resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.6.tgz#7b3cd37ed9c2034261a173af1a1aae27d8169b67"
|
resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b"
|
||||||
integrity sha512-i3+CeqxL7DpAazgVpAGdKMwHuL63B5nhJMh9NQ7xmChGkA3jNFflq6Jyo1LLJYcr3idWiNOPWHCrm4zMayLG4w==
|
integrity sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==
|
||||||
dependencies:
|
dependencies:
|
||||||
node-forge "0.8.2"
|
node-forge "0.9.0"
|
||||||
|
|
||||||
semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0:
|
semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
|
@ -16080,7 +15992,7 @@ semver@6.2.0, semver@^6.0.0, semver@^6.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db"
|
||||||
integrity sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==
|
integrity sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==
|
||||||
|
|
||||||
semver@^6.1.2, semver@^6.2.0, semver@^6.3.0:
|
semver@^6.2.0, semver@^6.3.0:
|
||||||
version "6.3.0"
|
version "6.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||||
|
@ -16881,11 +16793,6 @@ strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||||
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
|
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
|
||||||
|
|
||||||
strip-json-comments@^3.0.1:
|
|
||||||
version "3.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7"
|
|
||||||
integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==
|
|
||||||
|
|
||||||
style-loader@1.0.0:
|
style-loader@1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.0.0.tgz#1d5296f9165e8e2c85d24eee0b7caf9ec8ca1f82"
|
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.0.0.tgz#1d5296f9165e8e2c85d24eee0b7caf9ec8ca1f82"
|
||||||
|
@ -17958,10 +17865,10 @@ truffle-workflow-compile@^2.1.3:
|
||||||
truffle-external-compile "^1.0.15"
|
truffle-external-compile "^1.0.15"
|
||||||
truffle-resolver "^5.0.15"
|
truffle-resolver "^5.0.15"
|
||||||
|
|
||||||
truffle@5.0.37:
|
truffle@5.0.39:
|
||||||
version "5.0.37"
|
version "5.0.39"
|
||||||
resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.37.tgz#10da6f1bb9e661c4ccec75c295554bc4434f6b18"
|
resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.39.tgz#5710ba8f60a7184d9eb51d632308f2af0a2e8aff"
|
||||||
integrity sha512-od3mnu6sCV7sYbJCLSDV66RZ4bYeuLQ1QDpjGQHyJMB5AIw+u8GnxBmj6MKBOWHC+zixnwkRwS9yTYpj5IObFg==
|
integrity sha512-2a17t4o6r0rNMpeQXBc51nXigtIaP9/sU8N2zflaazvzYgDgLMZfqh/dir2mTfyybOsrR47NL310p+6+c8u8VA==
|
||||||
dependencies:
|
dependencies:
|
||||||
app-module-path "^2.2.0"
|
app-module-path "^2.2.0"
|
||||||
mocha "5.2.0"
|
mocha "5.2.0"
|
||||||
|
@ -18479,11 +18386,6 @@ v8-compile-cache@2.0.3:
|
||||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe"
|
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe"
|
||||||
integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==
|
integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==
|
||||||
|
|
||||||
v8-compile-cache@^2.0.3:
|
|
||||||
version "2.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e"
|
|
||||||
integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==
|
|
||||||
|
|
||||||
v8flags@^2.1.1:
|
v8flags@^2.1.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4"
|
resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4"
|
||||||
|
@ -19675,10 +19577,10 @@ webidl-conversions@^4.0.2:
|
||||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
|
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
|
||||||
integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
|
integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
|
||||||
|
|
||||||
webpack-bundle-analyzer@3.5.1:
|
webpack-bundle-analyzer@3.5.2:
|
||||||
version "3.5.1"
|
version "3.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.5.1.tgz#84aabb1547178d842ebb4ccc7324084b6c3b0ea9"
|
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.5.2.tgz#ac02834f4b31de8e27d71e6c7a612301ebddb79f"
|
||||||
integrity sha512-CDdaT3TTu4F9X3tcDq6PNJOiNGgREOM0WdN2vVAoUUn+M6NLB5kJ543HImCWbrDwOpbpGARSwU8r+u0Pl367kA==
|
integrity sha512-g9spCNe25QYUVqHRDkwG414GTok2m7pTTP0wr6l0J50Z3YLS04+BGodTqqoVBL7QfU/U/9p/oiI5XFOyfZ7S/A==
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn "^6.0.7"
|
acorn "^6.0.7"
|
||||||
acorn-walk "^6.1.1"
|
acorn-walk "^6.1.1"
|
||||||
|
@ -19721,10 +19623,10 @@ webpack-dev-middleware@^3.7.0:
|
||||||
range-parser "^1.2.1"
|
range-parser "^1.2.1"
|
||||||
webpack-log "^2.0.0"
|
webpack-log "^2.0.0"
|
||||||
|
|
||||||
webpack-dev-middleware@^3.7.1:
|
webpack-dev-middleware@^3.7.2:
|
||||||
version "3.7.1"
|
version "3.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.1.tgz#1167aea02afa034489869b8368fe9fed1aea7d09"
|
resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3"
|
||||||
integrity sha512-5MWu9SH1z3hY7oHOV6Kbkz5x7hXbxK56mGHNqHTe6d+ewxOwKUxoUJBs7QIaJb33lPjl9bJZ3X0vCoooUzC36A==
|
integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==
|
||||||
dependencies:
|
dependencies:
|
||||||
memory-fs "^0.4.1"
|
memory-fs "^0.4.1"
|
||||||
mime "^2.4.4"
|
mime "^2.4.4"
|
||||||
|
@ -19732,10 +19634,10 @@ webpack-dev-middleware@^3.7.1:
|
||||||
range-parser "^1.2.1"
|
range-parser "^1.2.1"
|
||||||
webpack-log "^2.0.0"
|
webpack-log "^2.0.0"
|
||||||
|
|
||||||
webpack-dev-server@3.8.1:
|
webpack-dev-server@3.8.2:
|
||||||
version "3.8.1"
|
version "3.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.8.1.tgz#485b64c4aadc23f601e72114b40c1b1fea31d9f1"
|
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.8.2.tgz#3292427bf6510da9a3ac2d500b924a4197667ff9"
|
||||||
integrity sha512-9F5DnfFA9bsrhpUCAfQic/AXBVHvq+3gQS+x6Zj0yc1fVVE0erKh2MV4IV12TBewuTrYeeTIRwCH9qLMvdNvTw==
|
integrity sha512-0xxogS7n5jHDQWy0WST0q6Ykp7UGj4YvWh+HVN71JoE7BwPxMZrwgraBvmdEMbDVMBzF0u+mEzn8TQzBm5NYJQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-html "0.0.7"
|
ansi-html "0.0.7"
|
||||||
bonjour "^3.5.0"
|
bonjour "^3.5.0"
|
||||||
|
@ -19746,18 +19648,18 @@ webpack-dev-server@3.8.1:
|
||||||
del "^4.1.1"
|
del "^4.1.1"
|
||||||
express "^4.17.1"
|
express "^4.17.1"
|
||||||
html-entities "^1.2.1"
|
html-entities "^1.2.1"
|
||||||
http-proxy-middleware "^0.19.1"
|
http-proxy-middleware "0.19.1"
|
||||||
import-local "^2.0.0"
|
import-local "^2.0.0"
|
||||||
internal-ip "^4.3.0"
|
internal-ip "^4.3.0"
|
||||||
ip "^1.1.5"
|
ip "^1.1.5"
|
||||||
is-absolute-url "^3.0.2"
|
is-absolute-url "^3.0.3"
|
||||||
killable "^1.0.1"
|
killable "^1.0.1"
|
||||||
loglevel "^1.6.4"
|
loglevel "^1.6.4"
|
||||||
opn "^5.5.0"
|
opn "^5.5.0"
|
||||||
p-retry "^3.0.1"
|
p-retry "^3.0.1"
|
||||||
portfinder "^1.0.24"
|
portfinder "^1.0.24"
|
||||||
schema-utils "^1.0.0"
|
schema-utils "^1.0.0"
|
||||||
selfsigned "^1.10.6"
|
selfsigned "^1.10.7"
|
||||||
semver "^6.3.0"
|
semver "^6.3.0"
|
||||||
serve-index "^1.9.1"
|
serve-index "^1.9.1"
|
||||||
sockjs "0.3.19"
|
sockjs "0.3.19"
|
||||||
|
@ -19766,7 +19668,7 @@ webpack-dev-server@3.8.1:
|
||||||
strip-ansi "^3.0.1"
|
strip-ansi "^3.0.1"
|
||||||
supports-color "^6.1.0"
|
supports-color "^6.1.0"
|
||||||
url "^0.11.0"
|
url "^0.11.0"
|
||||||
webpack-dev-middleware "^3.7.1"
|
webpack-dev-middleware "^3.7.2"
|
||||||
webpack-log "^2.0.0"
|
webpack-log "^2.0.0"
|
||||||
ws "^6.2.1"
|
ws "^6.2.1"
|
||||||
yargs "12.0.5"
|
yargs "12.0.5"
|
||||||
|
@ -19789,10 +19691,10 @@ webpack-log@^2.0.0:
|
||||||
ansi-colors "^3.0.0"
|
ansi-colors "^3.0.0"
|
||||||
uuid "^3.3.2"
|
uuid "^3.3.2"
|
||||||
|
|
||||||
webpack-manifest-plugin@^2.1.1:
|
webpack-manifest-plugin@2.2.0:
|
||||||
version "2.1.1"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-2.1.1.tgz#6b3e280327815b83152c79f42d0ca13b665773c4"
|
resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-2.2.0.tgz#19ca69b435b0baec7e29fbe90fb4015de2de4f16"
|
||||||
integrity sha512-2zqJ6mvc3yoiqfDjghAIpljhLSDh/G7vqGrzYcYqqRCd/ZZZCAuc/YPE5xG0LGpLgDJRhUNV1H+znyyhIxahzA==
|
integrity sha512-9S6YyKKKh/Oz/eryM1RyLVDVmy3NSPV0JXMRhZ18fJsq+AwGxUY34X54VNwkzYcEmEkDwNxuEOboCZEebJXBAQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
fs-extra "^7.0.0"
|
fs-extra "^7.0.0"
|
||||||
lodash ">=3.5 <5"
|
lodash ">=3.5 <5"
|
||||||
|
|
Loading…
Reference in New Issue