(Fix) Basic mobile responsiveness (#532)
* (fix) header mobile version * (fix) send / receive responsive * (fix) footer overflowing * (fix) responsive settings menu * (fix) scrolling menu tabs * (fix) responsive tables * (fix) a few modal windows' responsive issues * (remove) unused files * (fix) sidebar responsive * (fix) load safe responsive * (fix) create safe responsiveness * (fix) text wrap * (fix) remove modal responsiveness * (fix) name wrap * (update) yarn.lock
This commit is contained in:
parent
16b3dc0f2a
commit
165a088b1b
|
@ -8,6 +8,6 @@
|
|||
<title>Gnosis Safe Multisig</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<div id="root" style="overflow: hidden;"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -51,7 +51,6 @@ const useStyles = makeStyles({
|
|||
gridTemplateColumns: '1fr',
|
||||
paddingBottom: '30px',
|
||||
rowGap: '10px',
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
gridTemplateColumns: '1fr 1fr 1fr',
|
||||
paddingBottom: '0',
|
||||
|
|
|
@ -10,8 +10,10 @@ import GnoButtonLink from '~/components/layout/ButtonLink'
|
|||
|
||||
const useStyles = makeStyles({
|
||||
footer: {
|
||||
boxSizing: 'border-box',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
flexShrink: '1',
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'center',
|
||||
margin: '0 auto',
|
||||
|
@ -54,11 +56,10 @@ const Footer = () => {
|
|||
return (
|
||||
<footer className={classes.footer}>
|
||||
<span className={classes.item}>
|
||||
©
|
||||
{' '}
|
||||
©
|
||||
{date.getFullYear()}
|
||||
{' '}
|
||||
Gnosis
|
||||
Gnosis
|
||||
</span>
|
||||
<span className={classes.sep}>|</span>
|
||||
<Link className={cn(classes.item, classes.link)} to="https://safe.gnosis.io/terms" target="_blank">
|
||||
|
@ -85,7 +86,11 @@ const Footer = () => {
|
|||
Preferences
|
||||
</GnoButtonLink>
|
||||
<span className={classes.sep}>|</span>
|
||||
<Link className={cn(classes.item, classes.link)} to="https://github.com/gnosis/safe-react/releases" target="_blank">
|
||||
<Link
|
||||
className={cn(classes.item, classes.link)}
|
||||
to="https://github.com/gnosis/safe-react/releases"
|
||||
target="_blank"
|
||||
>
|
||||
{appVersion}
|
||||
</Link>
|
||||
</footer>
|
||||
|
|
|
@ -4,14 +4,19 @@ import { withStyles } from '@material-ui/core/styles'
|
|||
import Dot from '@material-ui/icons/FiberManualRecord'
|
||||
import Block from '~/components/layout/Block'
|
||||
import Img from '~/components/layout/Img'
|
||||
import { fancy, border, warning } from '~/theme/variables'
|
||||
import {
|
||||
fancy, border, warning, screenSm,
|
||||
} from '~/theme/variables'
|
||||
|
||||
const key = require('../assets/key.svg')
|
||||
const triangle = require('../assets/triangle.svg')
|
||||
|
||||
const styles = () => ({
|
||||
root: {
|
||||
display: 'flex',
|
||||
display: 'none',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
display: 'flex',
|
||||
},
|
||||
},
|
||||
dot: {
|
||||
position: 'relative',
|
||||
|
|
|
@ -13,7 +13,7 @@ import Img from '~/components/layout/Img'
|
|||
import Row from '~/components/layout/Row'
|
||||
import Spacer from '~/components/Spacer'
|
||||
import {
|
||||
border, sm, md, headerHeight,
|
||||
border, sm, md, headerHeight, screenSm,
|
||||
} from '~/theme/variables'
|
||||
import Provider from './Provider'
|
||||
import NetworkLabel from './NetworkLabel'
|
||||
|
@ -30,26 +30,34 @@ type Props = Open & {
|
|||
const styles = () => ({
|
||||
root: {
|
||||
backgroundColor: 'white',
|
||||
padding: 0,
|
||||
boxShadow: '0 0 10px 0 rgba(33, 48, 77, 0.1)',
|
||||
minWidth: '280px',
|
||||
borderRadius: sm,
|
||||
boxShadow: '0 0 10px 0 rgba(33, 48, 77, 0.1)',
|
||||
marginTop: '11px',
|
||||
minWidth: '280px',
|
||||
padding: 0,
|
||||
},
|
||||
summary: {
|
||||
borderBottom: `solid 2px ${border}`,
|
||||
alignItems: 'center',
|
||||
height: headerHeight,
|
||||
boxShadow: '0 2px 4px 0 rgba(212, 212, 211, 0.59)',
|
||||
backgroundColor: 'white',
|
||||
zIndex: 1301,
|
||||
borderBottom: `solid 2px ${border}`,
|
||||
boxShadow: '0 2px 4px 0 rgba(212, 212, 211, 0.59)',
|
||||
flexWrap: 'nowrap',
|
||||
height: headerHeight,
|
||||
position: 'fixed',
|
||||
width: '100%',
|
||||
zIndex: 1301,
|
||||
},
|
||||
logo: {
|
||||
padding: `${sm} ${md}`,
|
||||
flexBasis: '95px',
|
||||
flexGrow: 0,
|
||||
flexShrink: '0',
|
||||
flexGrow: '0',
|
||||
maxWidth: '55px',
|
||||
padding: sm,
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
maxWidth: 'none',
|
||||
paddingLeft: md,
|
||||
paddingRight: md,
|
||||
},
|
||||
},
|
||||
popper: {
|
||||
zIndex: 2000,
|
||||
|
@ -65,46 +73,46 @@ const Layout = openHoc(
|
|||
providerInfo,
|
||||
providerDetails,
|
||||
}: Props) => (
|
||||
<Row className={classes.summary}>
|
||||
<Col start="xs" middle="xs" className={classes.logo}>
|
||||
<Link to="/">
|
||||
<Img src={logo} height={32} alt="Gnosis Team Safe" />
|
||||
</Link>
|
||||
</Col>
|
||||
<Divider />
|
||||
<SafeListHeader />
|
||||
<Divider />
|
||||
<NetworkLabel />
|
||||
<Spacer />
|
||||
<Provider open={open} toggle={toggle} info={providerInfo}>
|
||||
{(providerRef) => (
|
||||
<Popper
|
||||
open={open}
|
||||
anchorEl={providerRef.current}
|
||||
placement="bottom"
|
||||
className={classes.popper}
|
||||
popperOptions={{ positionFixed: true }}
|
||||
>
|
||||
{({ TransitionProps }) => (
|
||||
<Grow {...TransitionProps}>
|
||||
<>
|
||||
<ClickAwayListener
|
||||
onClickAway={clickAway}
|
||||
mouseEvent="onClick"
|
||||
touchEvent={false}
|
||||
>
|
||||
<List className={classes.root} component="div">
|
||||
{providerDetails}
|
||||
</List>
|
||||
</ClickAwayListener>
|
||||
</>
|
||||
</Grow>
|
||||
)}
|
||||
</Popper>
|
||||
)}
|
||||
</Provider>
|
||||
</Row>
|
||||
),
|
||||
<Row className={classes.summary}>
|
||||
<Col start="xs" middle="xs" className={classes.logo}>
|
||||
<Link to="/">
|
||||
<Img src={logo} height={32} alt="Gnosis Team Safe" />
|
||||
</Link>
|
||||
</Col>
|
||||
<Divider />
|
||||
<SafeListHeader />
|
||||
<Divider />
|
||||
<NetworkLabel />
|
||||
<Spacer />
|
||||
<Provider open={open} toggle={toggle} info={providerInfo}>
|
||||
{(providerRef) => (
|
||||
<Popper
|
||||
anchorEl={providerRef.current}
|
||||
className={classes.popper}
|
||||
open={open}
|
||||
placement="bottom"
|
||||
popperOptions={{ positionFixed: true }}
|
||||
>
|
||||
{({ TransitionProps }) => (
|
||||
<Grow {...TransitionProps}>
|
||||
<>
|
||||
<ClickAwayListener
|
||||
onClickAway={clickAway}
|
||||
mouseEvent="onClick"
|
||||
touchEvent={false}
|
||||
>
|
||||
<List className={classes.root} component="div">
|
||||
{providerDetails}
|
||||
</List>
|
||||
</ClickAwayListener>
|
||||
</>
|
||||
</Grow>
|
||||
)}
|
||||
</Popper>
|
||||
)}
|
||||
</Provider>
|
||||
</Row>
|
||||
),
|
||||
)
|
||||
|
||||
export default withStyles(styles)(Layout)
|
||||
|
|
|
@ -5,7 +5,7 @@ import { getNetwork } from '~/config'
|
|||
import Paragraph from '~/components/layout/Paragraph'
|
||||
import Col from '~/components/layout/Col'
|
||||
import {
|
||||
xs, sm, md, border,
|
||||
xs, sm, md, border, screenSm,
|
||||
} from '~/theme/variables'
|
||||
|
||||
const network = getNetwork()
|
||||
|
@ -14,14 +14,22 @@ const formattedNetwork = network[0].toUpperCase() + network.substring(1).toLower
|
|||
const useStyles = makeStyles({
|
||||
container: {
|
||||
flexGrow: 0,
|
||||
padding: `0 ${md}`,
|
||||
padding: `0 ${sm}`,
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
paddingLeft: md,
|
||||
paddingRight: md,
|
||||
},
|
||||
},
|
||||
text: {
|
||||
background: border,
|
||||
padding: `${xs} ${sm}`,
|
||||
borderRadius: '3px',
|
||||
marginLeft: sm,
|
||||
lineHeight: 'normal',
|
||||
margin: '0',
|
||||
padding: `${xs} ${sm}`,
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
marginLeft: '8px',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import ExpandMore from '@material-ui/icons/ExpandMore'
|
|||
import Col from '~/components/layout/Col'
|
||||
import Divider from '~/components/layout/Divider'
|
||||
import { type Open } from '~/components/hoc/OpenHoc'
|
||||
import { sm, md } from '~/theme/variables'
|
||||
import { sm, md, screenSm } from '~/theme/variables'
|
||||
|
||||
type Props = Open & {
|
||||
classes: Object,
|
||||
|
@ -18,22 +18,29 @@ type Props = Open & {
|
|||
|
||||
const styles = () => ({
|
||||
root: {
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexBasis: '284px',
|
||||
marginRight: '20px',
|
||||
display: 'flex',
|
||||
height: '100%',
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
flexBasis: '284px',
|
||||
marginRight: '20px',
|
||||
},
|
||||
},
|
||||
provider: {
|
||||
padding: `${sm} ${md}`,
|
||||
alignItems: 'center',
|
||||
flex: '1 1 auto',
|
||||
display: 'flex',
|
||||
cursor: 'pointer',
|
||||
display: 'flex',
|
||||
flex: '1 1 auto',
|
||||
padding: sm,
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
paddingLeft: md,
|
||||
paddingRight: md,
|
||||
},
|
||||
},
|
||||
expand: {
|
||||
width: '30px',
|
||||
height: '30px',
|
||||
width: '30px',
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import { withStyles } from '@material-ui/core/styles'
|
|||
import Dot from '@material-ui/icons/FiberManualRecord'
|
||||
import Paragraph from '~/components/layout/Paragraph'
|
||||
import Col from '~/components/layout/Col'
|
||||
import { connected as connectedBg, sm } from '~/theme/variables'
|
||||
import { screenSm, connected as connectedBg, sm } from '~/theme/variables'
|
||||
import Identicon from '~/components/Identicon'
|
||||
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
||||
import CircleDot from '~/components/Header/components/CircleDot'
|
||||
|
@ -21,23 +21,33 @@ const styles = () => ({
|
|||
network: {
|
||||
fontFamily: 'Averta, sans-serif',
|
||||
},
|
||||
logo: {
|
||||
height: '15px',
|
||||
width: '15px',
|
||||
top: '12px',
|
||||
position: 'relative',
|
||||
right: '10px',
|
||||
backgroundColor: '#ffffff',
|
||||
identicon: {
|
||||
display: 'none',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
display: 'block',
|
||||
},
|
||||
},
|
||||
dot: {
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: '15px',
|
||||
color: connectedBg,
|
||||
display: 'none',
|
||||
height: '15px',
|
||||
position: 'relative',
|
||||
right: '10px',
|
||||
top: '12px',
|
||||
width: '15px',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
display: 'block',
|
||||
},
|
||||
},
|
||||
account: {
|
||||
paddingRight: sm,
|
||||
alignItems: 'start',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'left',
|
||||
alignItems: 'start',
|
||||
flexGrow: 1,
|
||||
justifyContent: 'left',
|
||||
paddingRight: sm,
|
||||
},
|
||||
address: {
|
||||
letterSpacing: '-0.5px',
|
||||
|
@ -56,8 +66,8 @@ const ProviderInfo = ({
|
|||
<>
|
||||
{connected && (
|
||||
<>
|
||||
<Identicon address={identiconAddress} diameter={30} />
|
||||
<Dot className={classes.logo} />
|
||||
<Identicon className={classes.identicon} address={identiconAddress} diameter={30} />
|
||||
<Dot className={classes.dot} />
|
||||
</>
|
||||
)}
|
||||
{!connected && <CircleDot keySize={14} circleSize={35} dotSize={16} dotTop={24} dotRight={11} mode="warning" />}
|
||||
|
|
|
@ -17,15 +17,16 @@ const styles = () => ({
|
|||
fontFamily: 'Averta, sans-serif',
|
||||
},
|
||||
account: {
|
||||
paddingRight: sm,
|
||||
alignItems: 'start',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'start',
|
||||
flexGrow: 1,
|
||||
justifyContent: 'center',
|
||||
paddingRight: sm,
|
||||
},
|
||||
connect: {
|
||||
letterSpacing: '-0.5px',
|
||||
whiteSpace: 'nowrap',
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import ExpandLessIcon from '@material-ui/icons/ExpandLess'
|
|||
import Paragraph from '~/components/layout/Paragraph'
|
||||
import Col from '~/components/layout/Col'
|
||||
import {
|
||||
xs, sm, md, border,
|
||||
xs, sm, md, border, screenSm,
|
||||
} from '~/theme/variables'
|
||||
import { safesCountSelector } from '~/routes/safe/store/selectors'
|
||||
import { SidebarContext } from '~/components/Sidebar'
|
||||
|
@ -18,7 +18,11 @@ export const TOGGLE_SIDEBAR_BTN_TESTID = 'TOGGLE_SIDEBAR_BTN'
|
|||
const useStyles = makeStyles({
|
||||
container: {
|
||||
flexGrow: 0,
|
||||
padding: `0 ${md}`,
|
||||
padding: `0 ${sm}`,
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
paddingLeft: md,
|
||||
paddingRight: md,
|
||||
},
|
||||
},
|
||||
counter: {
|
||||
background: border,
|
||||
|
@ -60,7 +64,7 @@ const SafeListHeader = ({ safesCount }: Props) => {
|
|||
)
|
||||
}
|
||||
|
||||
export default connect<Object, Object, ?Function, ?Object>(
|
||||
export default connect<Object, Object,?Function,?Object>(
|
||||
// $FlowFixMe
|
||||
(state) => ({ safesCount: safesCountSelector(state) }),
|
||||
null,
|
||||
|
|
|
@ -81,11 +81,11 @@ class HeaderComponent extends React.PureComponent<Props, State> {
|
|||
|
||||
return (
|
||||
<UserDetails
|
||||
provider={provider}
|
||||
network={network}
|
||||
userAddress={userAddress}
|
||||
connected={available}
|
||||
network={network}
|
||||
onDisconnect={this.onDisconnect}
|
||||
provider={provider}
|
||||
userAddress={userAddress}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ const useStyles = makeStyles({
|
|||
},
|
||||
safeName: {
|
||||
color: primary,
|
||||
overflowWrap: 'break-word',
|
||||
},
|
||||
safeAddress: {
|
||||
color: disabled,
|
||||
|
|
|
@ -97,32 +97,34 @@ const Sidebar = ({
|
|||
<SidebarContext.Provider value={{ isOpen, toggleSidebar }}>
|
||||
<ClickAwayListener onClickAway={toggleSidebar}>
|
||||
<Drawer
|
||||
className={classes.sidebar}
|
||||
open={isOpen}
|
||||
onKeyDown={handleEsc}
|
||||
classes={{ paper: classes.sidebarPaper }}
|
||||
ModalProps={{ onBackdropClick: toggleSidebar }}
|
||||
className={classes.sidebar}
|
||||
classes={{ paper: classes.sidebarPaper }}
|
||||
onKeyDown={handleEsc}
|
||||
open={isOpen}
|
||||
>
|
||||
<Row align="center">
|
||||
<SearchIcon className={classes.searchIcon} />
|
||||
<SearchBar
|
||||
classes={searchClasses}
|
||||
placeholder="Search by name or address"
|
||||
searchIcon={<div />}
|
||||
onChange={handleFilterChange}
|
||||
onCancelSearch={handleFilterCancel}
|
||||
value={filter}
|
||||
/>
|
||||
<Divider />
|
||||
<Spacer />
|
||||
<Row className={classes.topComponents} align="center">
|
||||
<Row className={classes.searchWrapper} align="center">
|
||||
<SearchIcon className={classes.searchIcon} />
|
||||
<SearchBar
|
||||
classes={searchClasses}
|
||||
onCancelSearch={handleFilterCancel}
|
||||
onChange={handleFilterChange}
|
||||
placeholder="Search by name or address"
|
||||
searchIcon={<div />}
|
||||
value={filter}
|
||||
/>
|
||||
</Row>
|
||||
<Divider className={classes.divider} />
|
||||
<Spacer className={classes.spacer} />
|
||||
<Button
|
||||
component={Link}
|
||||
to={WELCOME_ADDRESS}
|
||||
className={classes.addSafeBtn}
|
||||
variant="contained"
|
||||
size="small"
|
||||
color="primary"
|
||||
component={Link}
|
||||
onClick={toggleSidebar}
|
||||
size="small"
|
||||
to={WELCOME_ADDRESS}
|
||||
variant="contained"
|
||||
>
|
||||
+ Add Safe
|
||||
</Button>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import {
|
||||
xs, mediumFontSize, secondaryText, md, headerHeight,
|
||||
xs, mediumFontSize, secondaryText, md, headerHeight, screenSm,
|
||||
} from '~/theme/variables'
|
||||
|
||||
const sidebarWidth = '400px'
|
||||
|
@ -12,17 +12,50 @@ const sidebarBorderRadius = '8px'
|
|||
|
||||
const useSidebarStyles = makeStyles({
|
||||
sidebar: {
|
||||
width: sidebarWidth,
|
||||
marginLeft: sidebarMarginLeft,
|
||||
borderRadius: sidebarBorderRadius,
|
||||
marginLeft: sidebarMarginLeft,
|
||||
top: sidebarMarginTop,
|
||||
width: sidebarWidth,
|
||||
},
|
||||
sidebarPaper: {
|
||||
width: sidebarWidth,
|
||||
marginLeft: sidebarMarginLeft,
|
||||
top: `calc(${headerHeight} + ${sidebarMarginTop})`,
|
||||
maxHeight: `calc(100vh - ${headerHeight} - ${sidebarMarginTop} - ${sidebarMarginBottom})`,
|
||||
borderRadius: sidebarBorderRadius,
|
||||
marginLeft: sidebarMarginLeft,
|
||||
maxHeight: `calc(100vh - ${headerHeight} - ${sidebarMarginTop} - ${sidebarMarginBottom})`,
|
||||
top: `calc(${headerHeight} + ${sidebarMarginTop})`,
|
||||
width: sidebarWidth,
|
||||
maxWidth: `calc(100% - ${sidebarMarginLeft} - ${sidebarMarginLeft})`,
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
maxWidth: 'none',
|
||||
},
|
||||
},
|
||||
topComponents: {
|
||||
alignItems: 'center',
|
||||
flexFlow: 'column',
|
||||
paddingBottom: '30px',
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
flexFlow: 'row',
|
||||
paddingBottom: '0',
|
||||
},
|
||||
},
|
||||
searchWrapper: {
|
||||
width: '100%',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
width: 'auto',
|
||||
},
|
||||
},
|
||||
divider: {
|
||||
display: 'none',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
display: 'block',
|
||||
},
|
||||
},
|
||||
spacer: {
|
||||
display: 'none',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
display: 'block',
|
||||
},
|
||||
},
|
||||
headerPlaceholder: {
|
||||
minHeight: headerHeight,
|
||||
|
@ -48,14 +81,16 @@ const useSidebarStyles = makeStyles({
|
|||
},
|
||||
},
|
||||
searchContainer: {
|
||||
width: '190px',
|
||||
flexGrow: '1',
|
||||
marginLeft: xs,
|
||||
marginRight: xs,
|
||||
minWidth: '190px',
|
||||
},
|
||||
searchRoot: {
|
||||
letterSpacing: '-0.5px',
|
||||
border: 'none',
|
||||
boxShadow: 'none',
|
||||
flexGrow: '1',
|
||||
'& > button': {
|
||||
display: 'none',
|
||||
},
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
// @flow
|
||||
import * as React from 'react'
|
||||
|
||||
type Props = {
|
||||
className?: string,
|
||||
}
|
||||
|
||||
const style = {
|
||||
flexGrow: 1,
|
||||
}
|
||||
|
||||
export default () => <div style={style} />
|
||||
export default ({ className }: Props) => <div className={className} style={style} />
|
||||
|
|
|
@ -2,11 +2,15 @@
|
|||
import * as React from 'react'
|
||||
import { border } from '~/theme/variables'
|
||||
|
||||
const style = {
|
||||
height: '100%',
|
||||
borderRight: `solid 2px ${border}`,
|
||||
type Props = {
|
||||
className?: string,
|
||||
}
|
||||
|
||||
const Divider = () => <div style={style} />
|
||||
const style = {
|
||||
borderRight: `solid 2px ${border}`,
|
||||
height: '100%',
|
||||
}
|
||||
|
||||
const Divider = ({ className }: Props) => <div className={className} style={style} />
|
||||
|
||||
export default Divider
|
||||
|
|
|
@ -12,16 +12,19 @@ const calculateStyleFrom = (color?: string, margin?: Size) => ({
|
|||
})
|
||||
|
||||
type Props = {
|
||||
margin?: Size,
|
||||
className?: string,
|
||||
color?: string,
|
||||
margin?: Size,
|
||||
style?: Object,
|
||||
}
|
||||
|
||||
const Hairline = ({ margin, color, style }: Props) => {
|
||||
const Hairline = ({
|
||||
margin, color, style, className,
|
||||
}: Props) => {
|
||||
const calculatedStyles = calculateStyleFrom(color, margin)
|
||||
const mergedStyles = { ...calculatedStyles, ...(style || {}) }
|
||||
|
||||
return <div style={mergedStyles} />
|
||||
return <div style={mergedStyles} className={className} />
|
||||
}
|
||||
|
||||
export default Hairline
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// @flow
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import TableContainer from '@material-ui/core/TableContainer'
|
||||
import Block from '~/components/layout/Block'
|
||||
import Field from '~/components/forms/Field'
|
||||
import { required } from '~/components/forms/validator'
|
||||
|
@ -14,7 +15,7 @@ import Hairline from '~/components/layout/Hairline'
|
|||
import EtherscanBtn from '~/components/EtherscanBtn'
|
||||
import CopyBtn from '~/components/CopyBtn'
|
||||
import {
|
||||
sm, md, lg, border, disabled, extraSmallFontSize,
|
||||
sm, md, lg, border, disabled, extraSmallFontSize, screenSm,
|
||||
} from '~/theme/variables'
|
||||
import { getOwnerNameBy, getOwnerAddressBy } from '~/routes/open/components/fields'
|
||||
import { FIELD_LOAD_ADDRESS, THRESHOLD } from '~/routes/load/components/fields'
|
||||
|
@ -30,8 +31,13 @@ const styles = () => ({
|
|||
display: 'flex',
|
||||
justifyContent: 'flex-start',
|
||||
},
|
||||
ownerNames: {
|
||||
maxWidth: '400px',
|
||||
ownerName: {
|
||||
marginBottom: '15px',
|
||||
minWidth: '100%',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
marginBottom: '0',
|
||||
minWidth: '0',
|
||||
},
|
||||
},
|
||||
ownerAddresses: {
|
||||
alignItems: 'center',
|
||||
|
@ -118,39 +124,41 @@ const OwnerListComponent = (props: Props) => {
|
|||
</Paragraph>
|
||||
</Block>
|
||||
<Hairline />
|
||||
<Row className={classes.header}>
|
||||
<Col xs={4}>NAME</Col>
|
||||
<Col xs={8}>ADDRESS</Col>
|
||||
</Row>
|
||||
<Hairline />
|
||||
<Block margin="md" padding="md">
|
||||
{owners.map((address, index) => (
|
||||
<Row key={address} className={classes.owner}>
|
||||
<Col xs={4}>
|
||||
<Field
|
||||
className={classes.name}
|
||||
name={getOwnerNameBy(index)}
|
||||
component={TextField}
|
||||
type="text"
|
||||
validate={required}
|
||||
initialValue={`Owner #${index + 1}`}
|
||||
placeholder="Owner Name*"
|
||||
text="Owner Name"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={8}>
|
||||
<Row className={classes.ownerAddresses}>
|
||||
<Identicon address={address} diameter={32} />
|
||||
<Paragraph size="md" color="disabled" noMargin className={classes.address}>
|
||||
{address}
|
||||
</Paragraph>
|
||||
<CopyBtn content={address} />
|
||||
<EtherscanBtn type="address" value={address} />
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
))}
|
||||
</Block>
|
||||
<TableContainer>
|
||||
<Row className={classes.header}>
|
||||
<Col xs={4}>NAME</Col>
|
||||
<Col xs={8}>ADDRESS</Col>
|
||||
</Row>
|
||||
<Hairline />
|
||||
<Block margin="md" padding="md">
|
||||
{owners.map((address, index) => (
|
||||
<Row key={address} className={classes.owner}>
|
||||
<Col className={classes.ownerName} xs={4}>
|
||||
<Field
|
||||
className={classes.name}
|
||||
component={TextField}
|
||||
initialValue={`Owner #${index + 1}`}
|
||||
name={getOwnerNameBy(index)}
|
||||
placeholder="Owner Name*"
|
||||
text="Owner Name"
|
||||
type="text"
|
||||
validate={required}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={8}>
|
||||
<Row className={classes.ownerAddresses}>
|
||||
<Identicon address={address} diameter={32} />
|
||||
<Paragraph size="md" color="disabled" noMargin className={classes.address}>
|
||||
{address}
|
||||
</Paragraph>
|
||||
<CopyBtn content={address} />
|
||||
<EtherscanBtn type="address" value={address} />
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
))}
|
||||
</Block>
|
||||
</TableContainer>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import * as React from 'react'
|
||||
import classNames from 'classnames'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import TableContainer from '@material-ui/core/TableContainer'
|
||||
import Block from '~/components/layout/Block'
|
||||
import Identicon from '~/components/Identicon'
|
||||
import OpenPaper from '~/components/Stepper/OpenPaper'
|
||||
|
@ -12,7 +13,7 @@ import Paragraph from '~/components/layout/Paragraph'
|
|||
import CopyBtn from '~/components/CopyBtn'
|
||||
import Hairline from '~/components/layout/Hairline'
|
||||
import {
|
||||
xs, sm, lg, border,
|
||||
xs, sm, lg, border, screenSm,
|
||||
} from '~/theme/variables'
|
||||
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
||||
import { getAccountsFrom } from '~/routes/open/utils/safeDataExtractor'
|
||||
|
@ -22,7 +23,23 @@ import type { LayoutProps } from '../Layout'
|
|||
|
||||
const styles = () => ({
|
||||
root: {
|
||||
flexDirection: 'column',
|
||||
minHeight: '300px',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
},
|
||||
detailsColumn: {
|
||||
minWidth: '100%',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
minWidth: '0',
|
||||
},
|
||||
},
|
||||
ownersColumn: {
|
||||
minWidth: '100%',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
minWidth: '0',
|
||||
},
|
||||
},
|
||||
details: {
|
||||
padding: lg,
|
||||
|
@ -40,9 +57,10 @@ const styles = () => ({
|
|||
whiteSpace: 'nowrap',
|
||||
},
|
||||
owner: {
|
||||
alignItems: 'center',
|
||||
minWidth: 'fit-content',
|
||||
padding: sm,
|
||||
paddingLeft: lg,
|
||||
alignItems: 'center',
|
||||
},
|
||||
user: {
|
||||
justifyContent: 'left',
|
||||
|
@ -101,7 +119,7 @@ class ReviewComponent extends React.PureComponent<Props, State> {
|
|||
return (
|
||||
<>
|
||||
<Row className={classes.root}>
|
||||
<Col xs={4} layout="column">
|
||||
<Col className={classes.detailsColumn} xs={4} layout="column">
|
||||
<Block className={classes.details}>
|
||||
<Block margin="lg">
|
||||
<Paragraph size="lg" color="primary" noMargin>
|
||||
|
@ -147,37 +165,39 @@ class ReviewComponent extends React.PureComponent<Props, State> {
|
|||
</Block>
|
||||
</Block>
|
||||
</Col>
|
||||
<Col xs={8} layout="column">
|
||||
<Block className={classes.owners}>
|
||||
<Paragraph size="lg" color="primary" noMargin>
|
||||
{`${getNumOwnersFrom(values)} Safe owners`}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
<Hairline />
|
||||
{owners.map((address, index) => (
|
||||
<React.Fragment key={address}>
|
||||
<Row className={classes.owner}>
|
||||
<Col xs={1} align="center">
|
||||
<Identicon address={address} diameter={32} />
|
||||
</Col>
|
||||
<Col xs={11}>
|
||||
<Block className={classNames(classes.name, classes.userName)}>
|
||||
<Paragraph size="lg" noMargin>
|
||||
{values[getOwnerNameBy(index)]}
|
||||
</Paragraph>
|
||||
<Block justify="center" className={classes.user}>
|
||||
<Paragraph size="md" color="disabled" noMargin>
|
||||
{address}
|
||||
<Col className={classes.ownersColumn} xs={8} layout="column">
|
||||
<TableContainer>
|
||||
<Block className={classes.owners}>
|
||||
<Paragraph size="lg" color="primary" noMargin>
|
||||
{`${getNumOwnersFrom(values)} Safe owners`}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
<Hairline />
|
||||
{owners.map((address, index) => (
|
||||
<>
|
||||
<Row className={classes.owner}>
|
||||
<Col xs={1} align="center">
|
||||
<Identicon address={address} diameter={32} />
|
||||
</Col>
|
||||
<Col xs={11}>
|
||||
<Block className={classNames(classes.name, classes.userName)}>
|
||||
<Paragraph size="lg" noMargin>
|
||||
{values[getOwnerNameBy(index)]}
|
||||
</Paragraph>
|
||||
<CopyBtn content={address} />
|
||||
<EtherscanBtn type="address" value={address} />
|
||||
<Block justify="center" className={classes.user}>
|
||||
<Paragraph size="md" color="disabled" noMargin>
|
||||
{address}
|
||||
</Paragraph>
|
||||
<CopyBtn content={address} />
|
||||
<EtherscanBtn type="address" value={address} />
|
||||
</Block>
|
||||
</Block>
|
||||
</Block>
|
||||
</Col>
|
||||
</Row>
|
||||
{index !== owners.length - 1 && <Hairline />}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Col>
|
||||
</Row>
|
||||
{index !== owners.length - 1 && <Hairline />}
|
||||
</>
|
||||
))}
|
||||
</TableContainer>
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import * as React from 'react'
|
||||
import classNames from 'classnames'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import TableContainer from '@material-ui/core/TableContainer'
|
||||
import { estimateGasForDeployingSafe } from '~/logic/contracts/safeContracts'
|
||||
import { getNamesFrom, getAccountsFrom } from '~/routes/open/utils/safeDataExtractor'
|
||||
import Block from '~/components/layout/Block'
|
||||
|
@ -14,7 +15,7 @@ import Row from '~/components/layout/Row'
|
|||
import Paragraph from '~/components/layout/Paragraph'
|
||||
import { formatAmount } from '~/logic/tokens/utils/formatAmount'
|
||||
import {
|
||||
sm, md, lg, border, background,
|
||||
sm, md, lg, border, background, screenSm,
|
||||
} from '~/theme/variables'
|
||||
import Hairline from '~/components/layout/Hairline'
|
||||
import { getWeb3 } from '~/logic/wallets/getWeb3'
|
||||
|
@ -25,6 +26,21 @@ const { useEffect, useState } = React
|
|||
const styles = () => ({
|
||||
root: {
|
||||
minHeight: '300px',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
},
|
||||
detailsColumn: {
|
||||
minWidth: '100%',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
minWidth: '0',
|
||||
},
|
||||
},
|
||||
ownersColumn: {
|
||||
minWidth: '100%',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
minWidth: '0',
|
||||
},
|
||||
},
|
||||
details: {
|
||||
padding: lg,
|
||||
|
@ -33,10 +49,10 @@ const styles = () => ({
|
|||
},
|
||||
info: {
|
||||
backgroundColor: background,
|
||||
padding: lg,
|
||||
justifyContent: 'center',
|
||||
textAlign: 'center',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
padding: lg,
|
||||
textAlign: 'center',
|
||||
},
|
||||
owners: {
|
||||
padding: lg,
|
||||
|
@ -49,8 +65,10 @@ const styles = () => ({
|
|||
whiteSpace: 'nowrap',
|
||||
},
|
||||
owner: {
|
||||
padding: md,
|
||||
alignItems: 'center',
|
||||
minWidth: 'fit-content',
|
||||
padding: sm,
|
||||
paddingLeft: lg,
|
||||
},
|
||||
user: {
|
||||
justifyContent: 'left',
|
||||
|
@ -102,7 +120,7 @@ const ReviewComponent = ({ values, classes, userAccount }: Props) => {
|
|||
return (
|
||||
<>
|
||||
<Row className={classes.root}>
|
||||
<Col xs={4} layout="column">
|
||||
<Col className={classes.detailsColumn} xs={4} layout="column">
|
||||
<Block className={classes.details}>
|
||||
<Block margin="lg">
|
||||
<Paragraph size="lg" color="primary" noMargin>
|
||||
|
@ -127,37 +145,39 @@ const ReviewComponent = ({ values, classes, userAccount }: Props) => {
|
|||
</Block>
|
||||
</Block>
|
||||
</Col>
|
||||
<Col xs={8} layout="column">
|
||||
<Block className={classes.owners}>
|
||||
<Paragraph size="lg" color="primary" noMargin>
|
||||
{`${numOwners} Safe owners`}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
<Hairline />
|
||||
{names.map((name, index) => (
|
||||
<React.Fragment key={`name${index}`}>
|
||||
<Row className={classes.owner}>
|
||||
<Col xs={1} align="center">
|
||||
<Identicon address={addresses[index]} diameter={32} />
|
||||
</Col>
|
||||
<Col xs={11}>
|
||||
<Block className={classNames(classes.name, classes.userName)}>
|
||||
<Paragraph size="lg" noMargin>
|
||||
{name}
|
||||
</Paragraph>
|
||||
<Block justify="center" className={classes.user}>
|
||||
<Paragraph size="md" color="disabled" noMargin>
|
||||
{addresses[index]}
|
||||
<Col className={classes.ownersColumn} xs={8} layout="column">
|
||||
<TableContainer>
|
||||
<Block className={classes.owners}>
|
||||
<Paragraph size="lg" color="primary" noMargin>
|
||||
{`${numOwners} Safe owners`}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
<Hairline />
|
||||
{names.map((name, index) => (
|
||||
<React.Fragment key={`name${index}`}>
|
||||
<Row className={classes.owner}>
|
||||
<Col xs={1} align="center">
|
||||
<Identicon address={addresses[index]} diameter={32} />
|
||||
</Col>
|
||||
<Col xs={11}>
|
||||
<Block className={classNames(classes.name, classes.userName)}>
|
||||
<Paragraph size="lg" noMargin>
|
||||
{name}
|
||||
</Paragraph>
|
||||
<CopyBtn content={addresses[index]} />
|
||||
<EtherscanBtn type="address" value={addresses[index]} />
|
||||
<Block justify="center" className={classes.user}>
|
||||
<Paragraph size="md" color="disabled" noMargin>
|
||||
{addresses[index]}
|
||||
</Paragraph>
|
||||
<CopyBtn content={addresses[index]} />
|
||||
<EtherscanBtn type="address" value={addresses[index]} />
|
||||
</Block>
|
||||
</Block>
|
||||
</Block>
|
||||
</Col>
|
||||
</Row>
|
||||
<Hairline />
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Col>
|
||||
</Row>
|
||||
<Hairline />
|
||||
</React.Fragment>
|
||||
))}
|
||||
</TableContainer>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className={classes.info} align="center">
|
||||
|
|
|
@ -132,7 +132,7 @@ const SafeOwners = (props: Props) => {
|
|||
|
||||
return (
|
||||
<Row key={`owner${index}`} className={classes.owner}>
|
||||
<Col xs={4}>
|
||||
<Col className={classes.ownerName} xs={4}>
|
||||
<Field
|
||||
className={classes.name}
|
||||
name={getOwnerNameBy(index)}
|
||||
|
@ -143,7 +143,7 @@ const SafeOwners = (props: Props) => {
|
|||
text="Owner Name"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={6}>
|
||||
<Col className={classes.ownerAddress} xs={6}>
|
||||
<AddressInput
|
||||
name={addressName}
|
||||
component={TextField}
|
||||
|
@ -193,8 +193,8 @@ const SafeOwners = (props: Props) => {
|
|||
<Paragraph size="md" color="primary">
|
||||
Any transaction requires the confirmation of:
|
||||
</Paragraph>
|
||||
<Row margin="xl" align="center">
|
||||
<Col xs={2}>
|
||||
<Row className={classes.ownersAmount} margin="xl" align="center">
|
||||
<Col className={classes.ownersAmountItem} xs={2}>
|
||||
<Field
|
||||
name={FIELD_CONFIRMATIONS}
|
||||
component={SelectField}
|
||||
|
@ -208,7 +208,7 @@ const SafeOwners = (props: Props) => {
|
|||
))}
|
||||
</Field>
|
||||
</Col>
|
||||
<Col xs={10}>
|
||||
<Col className={classes.ownersAmountItem} xs={10}>
|
||||
<Paragraph size="lg" color="primary" noMargin className={classes.owners}>
|
||||
out of
|
||||
{' '}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// @flow
|
||||
import {
|
||||
md, lg, sm, disabled, extraSmallFontSize,
|
||||
md, lg, sm, disabled, extraSmallFontSize, screenSm,
|
||||
} from '~/theme/variables'
|
||||
|
||||
export const styles = () => ({
|
||||
|
@ -11,11 +11,32 @@ export const styles = () => ({
|
|||
padding: `${md} ${lg}`,
|
||||
},
|
||||
owner: {
|
||||
padding: `0 ${lg}`,
|
||||
flexDirection: 'column',
|
||||
marginTop: '12px',
|
||||
padding: `0 ${lg}`,
|
||||
'&:first-child': {
|
||||
marginTop: 0,
|
||||
},
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
},
|
||||
ownerName: {
|
||||
marginBottom: '5px',
|
||||
minWidth: '100%',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
marginBottom: '0',
|
||||
minWidth: '0',
|
||||
},
|
||||
},
|
||||
ownerAddress: {
|
||||
marginBottom: '15px',
|
||||
minWidth: '100%',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
marginBottom: '0',
|
||||
minWidth: '0',
|
||||
},
|
||||
},
|
||||
header: {
|
||||
padding: `${sm} ${lg}`,
|
||||
|
@ -45,4 +66,16 @@ export const styles = () => ({
|
|||
owners: {
|
||||
paddingLeft: md,
|
||||
},
|
||||
ownersAmount: {
|
||||
flexDirection: 'column',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
},
|
||||
ownersAmountItem: {
|
||||
minWidth: '100%',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
minWidth: '0',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
@ -9,6 +9,7 @@ import { withStyles } from '@material-ui/core/styles'
|
|||
import classNames from 'classnames/bind'
|
||||
import CallMade from '@material-ui/icons/CallMade'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
import TableContainer from '@material-ui/core/TableContainer'
|
||||
import Block from '~/components/layout/Block'
|
||||
import Row from '~/components/layout/Row'
|
||||
import { type Column, cellWidth } from '~/components/Table/TableHead'
|
||||
|
@ -123,97 +124,99 @@ const AddressBookTable = ({ classes }: Props) => {
|
|||
</Col>
|
||||
</Row>
|
||||
<Block className={classes.formContainer}>
|
||||
<Table
|
||||
label="Owners"
|
||||
columns={columns}
|
||||
data={addressBook}
|
||||
size={addressBook.size}
|
||||
defaultFixed
|
||||
disableLoadingOnEmptyTable
|
||||
defaultRowsPerPage={25}
|
||||
>
|
||||
{(sortedData: List<OwnerRow>) => sortedData.map((row: AddressBookEntry, index: number) => {
|
||||
const userOwner = isUserOwnerOnAnySafe(safesList, row.address)
|
||||
const hideBorderBottom = index >= 3
|
||||
<TableContainer>
|
||||
<Table
|
||||
label="Owners"
|
||||
columns={columns}
|
||||
data={addressBook}
|
||||
size={addressBook.size}
|
||||
defaultFixed
|
||||
disableLoadingOnEmptyTable
|
||||
defaultRowsPerPage={25}
|
||||
>
|
||||
{(sortedData: List<OwnerRow>) => sortedData.map((row: AddressBookEntry, index: number) => {
|
||||
const userOwner = isUserOwnerOnAnySafe(safesList, row.address)
|
||||
const hideBorderBottom = index >= 3
|
||||
&& index === sortedData.size - 1
|
||||
&& classes.noBorderBottom
|
||||
return (
|
||||
<TableRow
|
||||
tabIndex={-1}
|
||||
key={index}
|
||||
className={cn(
|
||||
classes.hide,
|
||||
hideBorderBottom,
|
||||
)}
|
||||
data-testid={ADDRESS_BOOK_ROW_ID}
|
||||
>
|
||||
{autoColumns.map((column: Column) => (
|
||||
<TableCell
|
||||
key={column.id}
|
||||
style={cellWidth(column.width)}
|
||||
align={column.align}
|
||||
component="td"
|
||||
>
|
||||
{column.id === AB_ADDRESS_ID ? (
|
||||
<OwnerAddressTableCell
|
||||
address={row[column.id]}
|
||||
showLinks
|
||||
/>
|
||||
) : (
|
||||
row[column.id]
|
||||
)}
|
||||
</TableCell>
|
||||
))}
|
||||
<TableCell component="td">
|
||||
<Row align="end" className={classes.actions}>
|
||||
<Img
|
||||
alt="Edit entry"
|
||||
className={classes.editEntryButton}
|
||||
src={RenameOwnerIcon}
|
||||
onClick={() => {
|
||||
setSelectedEntry({ entry: { ...row, isOwnerAddress: userOwner } })
|
||||
setEditCreateEntryModalOpen(true)
|
||||
}}
|
||||
testId={EDIT_ENTRY_BUTTON}
|
||||
/>
|
||||
<Img
|
||||
alt="Remove entry"
|
||||
className={userOwner ? classes.removeEntryButtonDisabled : classes.removeEntryButton}
|
||||
src={userOwner ? RemoveOwnerIconDisabled : RemoveOwnerIcon}
|
||||
onClick={() => {
|
||||
if (!userOwner) {
|
||||
setSelectedEntry({ entry: row })
|
||||
setDeleteEntryModalOpen(true)
|
||||
}
|
||||
}}
|
||||
testId={REMOVE_ENTRY_BUTTON}
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="small"
|
||||
color="primary"
|
||||
className={classes.send}
|
||||
testId={SEND_ENTRY_BUTTON}
|
||||
onClick={() => {
|
||||
setSelectedEntry({ entry: row })
|
||||
setSendFundsModalOpen(true)
|
||||
}}
|
||||
return (
|
||||
<TableRow
|
||||
tabIndex={-1}
|
||||
key={index}
|
||||
className={cn(
|
||||
classes.hide,
|
||||
hideBorderBottom,
|
||||
)}
|
||||
data-testid={ADDRESS_BOOK_ROW_ID}
|
||||
>
|
||||
{autoColumns.map((column: Column) => (
|
||||
<TableCell
|
||||
key={column.id}
|
||||
style={cellWidth(column.width)}
|
||||
align={column.align}
|
||||
component="td"
|
||||
>
|
||||
<CallMade
|
||||
alt="Send Transaction"
|
||||
className={classNames(
|
||||
classes.leftIcon,
|
||||
classes.iconSmall,
|
||||
)}
|
||||
{column.id === AB_ADDRESS_ID ? (
|
||||
<OwnerAddressTableCell
|
||||
address={row[column.id]}
|
||||
showLinks
|
||||
/>
|
||||
) : (
|
||||
row[column.id]
|
||||
)}
|
||||
</TableCell>
|
||||
))}
|
||||
<TableCell component="td">
|
||||
<Row align="end" className={classes.actions}>
|
||||
<Img
|
||||
alt="Edit entry"
|
||||
className={classes.editEntryButton}
|
||||
src={RenameOwnerIcon}
|
||||
onClick={() => {
|
||||
setSelectedEntry({ entry: { ...row, isOwnerAddress: userOwner } })
|
||||
setEditCreateEntryModalOpen(true)
|
||||
}}
|
||||
testId={EDIT_ENTRY_BUTTON}
|
||||
/>
|
||||
<Img
|
||||
alt="Remove entry"
|
||||
className={userOwner ? classes.removeEntryButtonDisabled : classes.removeEntryButton}
|
||||
src={userOwner ? RemoveOwnerIconDisabled : RemoveOwnerIcon}
|
||||
onClick={() => {
|
||||
if (!userOwner) {
|
||||
setSelectedEntry({ entry: row })
|
||||
setDeleteEntryModalOpen(true)
|
||||
}
|
||||
}}
|
||||
testId={REMOVE_ENTRY_BUTTON}
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="small"
|
||||
color="primary"
|
||||
className={classes.send}
|
||||
testId={SEND_ENTRY_BUTTON}
|
||||
onClick={() => {
|
||||
setSelectedEntry({ entry: row })
|
||||
setSendFundsModalOpen(true)
|
||||
}}
|
||||
>
|
||||
<CallMade
|
||||
alt="Send Transaction"
|
||||
className={classNames(
|
||||
classes.leftIcon,
|
||||
classes.iconSmall,
|
||||
)}
|
||||
/>
|
||||
Send
|
||||
</Button>
|
||||
</Row>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
})}
|
||||
</Table>
|
||||
</Button>
|
||||
</Row>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
})}
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</Block>
|
||||
<CreateEditEntryModal
|
||||
onClose={() => setEditCreateEntryModalOpen(false)}
|
||||
|
|
|
@ -14,7 +14,7 @@ import Col from '~/components/layout/Col'
|
|||
import EtherscanBtn from '~/components/EtherscanBtn'
|
||||
import CopyBtn from '~/components/CopyBtn'
|
||||
import {
|
||||
sm, lg, md, secondaryText,
|
||||
sm, lg, md, secondaryText, screenSm,
|
||||
} from '~/theme/variables'
|
||||
import { copyToClipboard } from '~/utils/clipboard'
|
||||
|
||||
|
@ -53,11 +53,23 @@ const styles = () => ({
|
|||
},
|
||||
},
|
||||
addressContainer: {
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
margin: `${lg} 0`,
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
},
|
||||
address: {
|
||||
marginLeft: sm,
|
||||
marginRight: sm,
|
||||
maxWidth: '70%',
|
||||
overflowWrap: 'break-word',
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
maxWidth: 'none',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import { List } from 'immutable'
|
|||
import classNames from 'classnames/bind'
|
||||
import TableRow from '@material-ui/core/TableRow'
|
||||
import TableCell from '@material-ui/core/TableCell'
|
||||
import TableContainer from '@material-ui/core/TableContainer'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import CallMade from '@material-ui/icons/CallMade'
|
||||
import CallReceived from '@material-ui/icons/CallReceived'
|
||||
|
@ -148,93 +149,95 @@ class Balances extends React.Component<Props, State> {
|
|||
</Modal>
|
||||
</Col>
|
||||
</Row>
|
||||
<Table
|
||||
label="Balances"
|
||||
defaultOrderBy={BALANCE_TABLE_ASSET_ID}
|
||||
defaultRowsPerPage={10}
|
||||
columns={columns}
|
||||
data={filteredData}
|
||||
size={filteredData.size}
|
||||
defaultFixed
|
||||
>
|
||||
{(sortedData: Array<BalanceRow>) => sortedData.map((row: any, index: number) => (
|
||||
<TableRow tabIndex={-1} key={index} className={classes.hide} data-testid={BALANCE_ROW_TEST_ID}>
|
||||
{autoColumns.map((column: Column) => {
|
||||
const { id, width, align } = column
|
||||
let cellItem
|
||||
switch (id) {
|
||||
case BALANCE_TABLE_ASSET_ID: {
|
||||
cellItem = <AssetTableCell asset={row[id]} />
|
||||
break
|
||||
<TableContainer>
|
||||
<Table
|
||||
columns={columns}
|
||||
data={filteredData}
|
||||
defaultFixed
|
||||
defaultOrderBy={BALANCE_TABLE_ASSET_ID}
|
||||
defaultRowsPerPage={10}
|
||||
label="Balances"
|
||||
size={filteredData.size}
|
||||
>
|
||||
{(sortedData: Array<BalanceRow>) => sortedData.map((row: any, index: number) => (
|
||||
<TableRow tabIndex={-1} key={index} className={classes.hide} data-testid={BALANCE_ROW_TEST_ID}>
|
||||
{autoColumns.map((column: Column) => {
|
||||
const { id, width, align } = column
|
||||
let cellItem
|
||||
switch (id) {
|
||||
case BALANCE_TABLE_ASSET_ID: {
|
||||
cellItem = <AssetTableCell asset={row[id]} />
|
||||
break
|
||||
}
|
||||
case BALANCE_TABLE_BALANCE_ID: {
|
||||
cellItem = (
|
||||
<div>
|
||||
{row[id]}
|
||||
</div>
|
||||
)
|
||||
break
|
||||
}
|
||||
case BALANCE_TABLE_VALUE_ID: {
|
||||
cellItem = <div className={classes.currencyValueRow}>{row[id]}</div>
|
||||
break
|
||||
}
|
||||
default: {
|
||||
cellItem = null
|
||||
break
|
||||
}
|
||||
}
|
||||
case BALANCE_TABLE_BALANCE_ID: {
|
||||
cellItem = (
|
||||
<div>
|
||||
{row[id]}
|
||||
</div>
|
||||
)
|
||||
break
|
||||
}
|
||||
case BALANCE_TABLE_VALUE_ID: {
|
||||
cellItem = <div className={classes.currencyValueRow}>{row[id]}</div>
|
||||
break
|
||||
}
|
||||
default: {
|
||||
cellItem = null
|
||||
break
|
||||
}
|
||||
}
|
||||
return (
|
||||
<TableCell
|
||||
key={id}
|
||||
style={cellWidth(width)}
|
||||
align={align}
|
||||
component="td"
|
||||
>
|
||||
{cellItem}
|
||||
</TableCell>
|
||||
)
|
||||
})}
|
||||
<TableCell component="td">
|
||||
<Row align="end" className={classes.actions}>
|
||||
{granted && (
|
||||
return (
|
||||
<TableCell
|
||||
key={id}
|
||||
style={cellWidth(width)}
|
||||
align={align}
|
||||
component="td"
|
||||
>
|
||||
{cellItem}
|
||||
</TableCell>
|
||||
)
|
||||
})}
|
||||
<TableCell component="td">
|
||||
<Row align="end" className={classes.actions}>
|
||||
{granted && (
|
||||
<Button
|
||||
variant="contained"
|
||||
size="small"
|
||||
color="primary"
|
||||
className={classes.send}
|
||||
onClick={() => this.showSendFunds(row.asset.address)}
|
||||
testId="balance-send-btn"
|
||||
>
|
||||
<CallMade alt="Send Transaction" className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||
Send
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant="contained"
|
||||
size="small"
|
||||
color="primary"
|
||||
className={classes.send}
|
||||
onClick={() => this.showSendFunds(row.asset.address)}
|
||||
testId="balance-send-btn"
|
||||
className={classes.receive}
|
||||
onClick={this.onShow('Receive')}
|
||||
>
|
||||
<CallMade alt="Send Transaction" className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||
Send
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant="contained"
|
||||
size="small"
|
||||
color="primary"
|
||||
className={classes.receive}
|
||||
onClick={this.onShow('Receive')}
|
||||
>
|
||||
<CallReceived alt="Receive Transaction" className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||
<CallReceived alt="Receive Transaction" className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||
Receive
|
||||
</Button>
|
||||
</Row>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</Table>
|
||||
</Button>
|
||||
</Row>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<SendModal
|
||||
onClose={this.hideSendFunds}
|
||||
activeScreenType="sendFunds"
|
||||
createTransaction={createTransaction}
|
||||
ethBalance={ethBalance}
|
||||
isOpen={sendFunds.isOpen}
|
||||
onClose={this.hideSendFunds}
|
||||
safeAddress={safeAddress}
|
||||
safeName={safeName}
|
||||
ethBalance={ethBalance}
|
||||
tokens={activeTokens}
|
||||
selectedToken={sendFunds.selectedToken}
|
||||
createTransaction={createTransaction}
|
||||
activeScreenType="sendFunds"
|
||||
tokens={activeTokens}
|
||||
/>
|
||||
<Modal
|
||||
title="Receive Tokens"
|
||||
|
|
|
@ -20,7 +20,10 @@ export const styles = (theme: Object) => ({
|
|||
fontSize: 16,
|
||||
},
|
||||
receiveModal: {
|
||||
height: '544px',
|
||||
height: 'auto',
|
||||
maxWidth: 'calc(100% - 30px)',
|
||||
minHeight: '544px',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
hide: {
|
||||
'&:hover': {
|
||||
|
|
|
@ -133,93 +133,86 @@ const Layout = (props: Props) => {
|
|||
return (
|
||||
<>
|
||||
<Block className={classes.container} margin="xl">
|
||||
<Identicon address={address} diameter={50} />
|
||||
<Block className={classes.name}>
|
||||
<Row>
|
||||
<Heading tag="h2" color="primary" testId={SAFE_VIEW_NAME_HEADING_TEST_ID}>
|
||||
{name}
|
||||
</Heading>
|
||||
{!granted && <Block className={classes.readonly}>Read Only</Block>}
|
||||
</Row>
|
||||
<Block justify="center" className={classes.user}>
|
||||
<Paragraph size="md" className={classes.address} color="disabled" noMargin>
|
||||
{address}
|
||||
</Paragraph>
|
||||
<CopyBtn content={address} />
|
||||
<EtherscanBtn type="address" value={address} />
|
||||
<Row className={classes.userInfo}>
|
||||
<Identicon address={address} diameter={50} />
|
||||
<Block className={classes.name}>
|
||||
<Row>
|
||||
<Heading className={classes.nameText} tag="h2" color="primary" testId={SAFE_VIEW_NAME_HEADING_TEST_ID}>
|
||||
{name}
|
||||
</Heading>
|
||||
{!granted && <Block className={classes.readonly}>Read Only</Block>}
|
||||
</Row>
|
||||
<Block justify="center" className={classes.user}>
|
||||
<Paragraph size="md" className={classes.address} color="disabled" noMargin>
|
||||
{address}
|
||||
</Paragraph>
|
||||
<CopyBtn content={address} />
|
||||
<EtherscanBtn type="address" value={address} />
|
||||
</Block>
|
||||
</Block>
|
||||
</Block>
|
||||
</Row>
|
||||
<Block className={classes.balance}>
|
||||
<Row align="end" className={classes.actions}>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="small"
|
||||
color="primary"
|
||||
className={classes.send}
|
||||
onClick={() => showSendFunds('Ether')}
|
||||
disabled={!granted}
|
||||
>
|
||||
<CallMade alt="Send Transaction" className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||
Send
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="small"
|
||||
color="primary"
|
||||
className={classes.receive}
|
||||
onClick={onShow('Receive')}
|
||||
>
|
||||
<CallReceived alt="Receive Transaction" className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||
Receive
|
||||
</Button>
|
||||
</Row>
|
||||
<Button
|
||||
className={classes.send}
|
||||
color="primary"
|
||||
disabled={!granted}
|
||||
onClick={() => showSendFunds('Ether')}
|
||||
size="small"
|
||||
variant="contained"
|
||||
>
|
||||
<CallMade alt="Send Transaction" className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||
Send
|
||||
</Button>
|
||||
<Button
|
||||
className={classes.receive}
|
||||
color="primary"
|
||||
onClick={onShow('Receive')}
|
||||
size="small"
|
||||
variant="contained"
|
||||
>
|
||||
<CallReceived alt="Receive Transaction" className={classNames(classes.leftIcon, classes.iconSmall)} />
|
||||
Receive
|
||||
</Button>
|
||||
</Block>
|
||||
</Block>
|
||||
<Row>
|
||||
<Tabs
|
||||
value={location.pathname}
|
||||
onChange={handleCallToRouter}
|
||||
indicatorColor="secondary"
|
||||
textColor="secondary"
|
||||
>
|
||||
<Tab
|
||||
classes={{
|
||||
selected: classes.tabWrapperSelected,
|
||||
wrapper: classes.tabWrapper,
|
||||
}}
|
||||
label={labelBalances}
|
||||
value={`${match.url}/balances`}
|
||||
data-testid={BALANCES_TAB_BTN_TEST_ID}
|
||||
/>
|
||||
<Tab
|
||||
classes={{
|
||||
selected: classes.tabWrapperSelected,
|
||||
wrapper: classes.tabWrapper,
|
||||
}}
|
||||
label={labelTransactions}
|
||||
value={`${match.url}/transactions`}
|
||||
data-testid={TRANSACTIONS_TAB_BTN_TEST_ID}
|
||||
/>
|
||||
<Tab
|
||||
classes={{
|
||||
selected: classes.tabWrapperSelected,
|
||||
wrapper: classes.tabWrapper,
|
||||
}}
|
||||
label={labelAddressBook}
|
||||
value={`${match.url}/address-book`}
|
||||
data-testid={ADDRESS_BOOK_TAB_BTN_TEST_ID}
|
||||
/>
|
||||
<Tab
|
||||
classes={{
|
||||
selected: classes.tabWrapperSelected,
|
||||
wrapper: classes.tabWrapper,
|
||||
}}
|
||||
label={labelSettings}
|
||||
value={`${match.url}/settings`}
|
||||
data-testid={SETTINGS_TAB_BTN_TEST_ID}
|
||||
/>
|
||||
</Tabs>
|
||||
</Row>
|
||||
<Tabs variant="scrollable" value={location.pathname} onChange={handleCallToRouter} indicatorColor="secondary" textColor="secondary">
|
||||
<Tab
|
||||
classes={{
|
||||
selected: classes.tabWrapperSelected,
|
||||
wrapper: classes.tabWrapper,
|
||||
}}
|
||||
data-testid={BALANCES_TAB_BTN_TEST_ID}
|
||||
label={labelBalances}
|
||||
value={`${match.url}/balances`}
|
||||
/>
|
||||
<Tab
|
||||
classes={{
|
||||
selected: classes.tabWrapperSelected,
|
||||
wrapper: classes.tabWrapper,
|
||||
}}
|
||||
data-testid={TRANSACTIONS_TAB_BTN_TEST_ID}
|
||||
label={labelTransactions}
|
||||
value={`${match.url}/transactions`}
|
||||
/>
|
||||
<Tab
|
||||
classes={{
|
||||
selected: classes.tabWrapperSelected,
|
||||
wrapper: classes.tabWrapper,
|
||||
}}
|
||||
data-testid={ADDRESS_BOOK_TAB_BTN_TEST_ID}
|
||||
label={labelAddressBook}
|
||||
value={`${match.url}/address-book`}
|
||||
/>
|
||||
<Tab
|
||||
classes={{
|
||||
selected: classes.tabWrapperSelected,
|
||||
wrapper: classes.tabWrapper,
|
||||
}}
|
||||
data-testid={SETTINGS_TAB_BTN_TEST_ID}
|
||||
label={labelSettings}
|
||||
value={`${match.url}/settings`}
|
||||
/>
|
||||
</Tabs>
|
||||
<Hairline color={border} style={{ marginTop: '-2px' }} />
|
||||
<Switch>
|
||||
<Route
|
||||
|
@ -283,13 +276,7 @@ const Layout = (props: Props) => {
|
|||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path={`${match.path}/address-book`}
|
||||
render={() => (
|
||||
<AddressBookTable />
|
||||
)}
|
||||
/>
|
||||
<Route exact path={`${match.path}/address-book`} render={() => <AddressBookTable />} />
|
||||
<Redirect to={`${match.path}/balances`} />
|
||||
</Switch>
|
||||
<SendModal
|
||||
|
@ -304,11 +291,11 @@ const Layout = (props: Props) => {
|
|||
activeScreenType="chooseTxType"
|
||||
/>
|
||||
<Modal
|
||||
title="Receive Tokens"
|
||||
description="Receive Tokens Form"
|
||||
handleClose={onHide('Receive')}
|
||||
open={showReceive}
|
||||
paperClassName={classes.receiveModal}
|
||||
title="Receive Tokens"
|
||||
>
|
||||
<Receive safeName={name} safeAddress={address} onClose={onHide('Receive')} />
|
||||
</Modal>
|
||||
|
|
|
@ -5,6 +5,7 @@ import { List } from 'immutable'
|
|||
import { withStyles } from '@material-ui/core/styles'
|
||||
import TableRow from '@material-ui/core/TableRow'
|
||||
import TableCell from '@material-ui/core/TableCell'
|
||||
import TableContainer from '@material-ui/core/TableContainer'
|
||||
import Block from '~/components/layout/Block'
|
||||
import Col from '~/components/layout/Col'
|
||||
import Table from '~/components/Table'
|
||||
|
@ -145,66 +146,68 @@ class ManageOwners extends React.Component<Props, State> {
|
|||
Add, remove and replace owners or rename existing owners. Owner names are only stored locally and never
|
||||
shared with Gnosis or any third parties.
|
||||
</Paragraph>
|
||||
<Table
|
||||
label="Owners"
|
||||
defaultOrderBy={OWNERS_TABLE_NAME_ID}
|
||||
columns={columns}
|
||||
data={ownerData}
|
||||
size={ownerData.size}
|
||||
disablePagination
|
||||
defaultFixed
|
||||
noBorder
|
||||
>
|
||||
{(sortedData: List<OwnerRow>) => sortedData.map((row: any, index: number) => (
|
||||
<TableRow
|
||||
tabIndex={-1}
|
||||
key={index}
|
||||
className={cn(classes.hide, index >= 3 && index === sortedData.size - 1 && classes.noBorderBottom)}
|
||||
data-testid={OWNERS_ROW_TEST_ID}
|
||||
>
|
||||
{autoColumns.map((column: Column) => (
|
||||
<TableCell key={column.id} style={cellWidth(column.width)} align={column.align} component="td">
|
||||
{column.id === OWNERS_TABLE_ADDRESS_ID ? (
|
||||
<OwnerAddressTableCell address={row[column.id]} />
|
||||
) : (
|
||||
row[column.id]
|
||||
)}
|
||||
</TableCell>
|
||||
))}
|
||||
<TableCell component="td">
|
||||
<Row align="end" className={classes.actions}>
|
||||
<Img
|
||||
alt="Edit owner"
|
||||
className={classes.editOwnerIcon}
|
||||
src={RenameOwnerIcon}
|
||||
onClick={this.onShow('EditOwner', row)}
|
||||
testId={RENAME_OWNER_BTN_TEST_ID}
|
||||
/>
|
||||
{granted && (
|
||||
<>
|
||||
<Img
|
||||
alt="Replace owner"
|
||||
className={classes.replaceOwnerIcon}
|
||||
src={ReplaceOwnerIcon}
|
||||
onClick={this.onShow('ReplaceOwner', row)}
|
||||
testId={REPLACE_OWNER_BTN_TEST_ID}
|
||||
/>
|
||||
{ownerData.size > 1 && (
|
||||
<TableContainer>
|
||||
<Table
|
||||
label="Owners"
|
||||
defaultOrderBy={OWNERS_TABLE_NAME_ID}
|
||||
columns={columns}
|
||||
data={ownerData}
|
||||
size={ownerData.size}
|
||||
disablePagination
|
||||
defaultFixed
|
||||
noBorder
|
||||
>
|
||||
{(sortedData: List<OwnerRow>) => sortedData.map((row: any, index: number) => (
|
||||
<TableRow
|
||||
tabIndex={-1}
|
||||
key={index}
|
||||
className={cn(classes.hide, index >= 3 && index === sortedData.size - 1 && classes.noBorderBottom)}
|
||||
data-testid={OWNERS_ROW_TEST_ID}
|
||||
>
|
||||
{autoColumns.map((column: Column) => (
|
||||
<TableCell key={column.id} style={cellWidth(column.width)} align={column.align} component="td">
|
||||
{column.id === OWNERS_TABLE_ADDRESS_ID ? (
|
||||
<OwnerAddressTableCell address={row[column.id]} />
|
||||
) : (
|
||||
row[column.id]
|
||||
)}
|
||||
</TableCell>
|
||||
))}
|
||||
<TableCell component="td">
|
||||
<Row align="end" className={classes.actions}>
|
||||
<Img
|
||||
alt="Edit owner"
|
||||
className={classes.editOwnerIcon}
|
||||
src={RenameOwnerIcon}
|
||||
onClick={this.onShow('EditOwner', row)}
|
||||
testId={RENAME_OWNER_BTN_TEST_ID}
|
||||
/>
|
||||
{granted && (
|
||||
<>
|
||||
<Img
|
||||
alt="Remove owner"
|
||||
className={classes.removeOwnerIcon}
|
||||
src={RemoveOwnerIcon}
|
||||
onClick={this.onShow('RemoveOwner', row)}
|
||||
testId={REMOVE_OWNER_BTN_TEST_ID}
|
||||
alt="Replace owner"
|
||||
className={classes.replaceOwnerIcon}
|
||||
src={ReplaceOwnerIcon}
|
||||
onClick={this.onShow('ReplaceOwner', row)}
|
||||
testId={REPLACE_OWNER_BTN_TEST_ID}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) }
|
||||
</Row>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</Table>
|
||||
{ownerData.size > 1 && (
|
||||
<Img
|
||||
alt="Remove owner"
|
||||
className={classes.removeOwnerIcon}
|
||||
src={RemoveOwnerIcon}
|
||||
onClick={this.onShow('RemoveOwner', row)}
|
||||
testId={REMOVE_OWNER_BTN_TEST_ID}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) }
|
||||
</Row>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</Block>
|
||||
{granted && (
|
||||
<>
|
||||
|
|
|
@ -38,7 +38,7 @@ type Props = Actions & {
|
|||
const RemoveSafeComponent = ({
|
||||
onClose, isOpen, classes, safeAddress, etherScanLink, safeName, removeSafe,
|
||||
}: Props) => (
|
||||
<Modal title="Remove Safe" description="Remove the selected Safe" handleClose={onClose} open={isOpen}>
|
||||
<Modal paperClassName={classes.modal} title="Remove Safe" description="Remove the selected Safe" handleClose={onClose} open={isOpen}>
|
||||
<Row align="center" grow className={classes.heading}>
|
||||
<Paragraph className={classes.manage} noMargin weight="bolder">
|
||||
Remove Safe
|
||||
|
|
|
@ -5,10 +5,10 @@ import {
|
|||
|
||||
export const styles = () => ({
|
||||
heading: {
|
||||
padding: `${sm} ${lg}`,
|
||||
boxSizing: 'border-box',
|
||||
justifyContent: 'space-between',
|
||||
maxHeight: '75px',
|
||||
boxSizing: 'border-box',
|
||||
padding: `${sm} ${lg}`,
|
||||
},
|
||||
container: {
|
||||
minHeight: '369px',
|
||||
|
@ -54,4 +54,9 @@ export const styles = () => ({
|
|||
cursor: 'pointer',
|
||||
},
|
||||
},
|
||||
modal: {
|
||||
height: 'auto',
|
||||
maxWidth: 'calc(100% - 30px)',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
})
|
||||
|
|
|
@ -12,16 +12,16 @@ export const styles = () => ({
|
|||
maxWidth: '460px',
|
||||
},
|
||||
saveBtn: {
|
||||
marginRight: sm,
|
||||
fontWeight: boldFont,
|
||||
marginRight: sm,
|
||||
},
|
||||
controlsRow: {
|
||||
padding: lg,
|
||||
position: 'absolute',
|
||||
borderTop: `2px solid ${border}`,
|
||||
bottom: 0,
|
||||
boxSizing: 'border-box',
|
||||
padding: lg,
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
borderTop: `2px solid ${border}`,
|
||||
},
|
||||
versionNumber: {
|
||||
height: '21px',
|
||||
|
|
|
@ -117,7 +117,7 @@ class Settings extends React.Component<Props, State> {
|
|||
/>
|
||||
</Row>
|
||||
<Block className={classes.root}>
|
||||
<Col xs={3} layout="column">
|
||||
<Col className={classes.menuWrapper} layout="column">
|
||||
<Block className={classes.menu}>
|
||||
<Row
|
||||
className={cn(classes.menuOption, menuOptionIndex === 1 && classes.active)}
|
||||
|
@ -126,7 +126,7 @@ class Settings extends React.Component<Props, State> {
|
|||
<SafeDetailsIcon />
|
||||
Safe details
|
||||
</Row>
|
||||
<Hairline />
|
||||
<Hairline className={classes.hairline} />
|
||||
<Row
|
||||
className={cn(classes.menuOption, menuOptionIndex === 2 && classes.active)}
|
||||
onClick={this.handleChange(2)}
|
||||
|
@ -138,7 +138,7 @@ class Settings extends React.Component<Props, State> {
|
|||
{owners.size}
|
||||
</Paragraph>
|
||||
</Row>
|
||||
<Hairline />
|
||||
<Hairline className={classes.hairline} />
|
||||
<Row
|
||||
className={cn(classes.menuOption, menuOptionIndex === 3 && classes.active)}
|
||||
onClick={this.handleChange(3)}
|
||||
|
@ -146,10 +146,10 @@ class Settings extends React.Component<Props, State> {
|
|||
<RequiredConfirmationsIcon />
|
||||
Policies
|
||||
</Row>
|
||||
<Hairline />
|
||||
<Hairline className={classes.hairline} />
|
||||
</Block>
|
||||
</Col>
|
||||
<Col xs={9} layout="column">
|
||||
<Col className={classes.contents} layout="column">
|
||||
<Block className={classes.container}>
|
||||
{menuOptionIndex === 1 && (
|
||||
<SafeDetails safeAddress={safeAddress} safeName={safeName} updateSafe={updateSafe} />
|
||||
|
|
|
@ -1,36 +1,85 @@
|
|||
// @flow
|
||||
import {
|
||||
xs, sm, md, border, secondary, bolderFont, background, largeFontSize, fontColor,
|
||||
xs, sm, md, border, secondary, bolderFont, background, largeFontSize, fontColor, screenSm,
|
||||
} from '~/theme/variables'
|
||||
|
||||
export const styles = () => ({
|
||||
root: {
|
||||
backgroundColor: 'white',
|
||||
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
||||
minHeight: '505px',
|
||||
marginBottom: '54px',
|
||||
display: 'flex',
|
||||
borderRadius: sm,
|
||||
boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
marginBottom: '54px',
|
||||
minHeight: '505px',
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
letterSpacing: '-0.5px',
|
||||
},
|
||||
menuWrapper: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
flexGrow: '0',
|
||||
maxWidth: '100%',
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
flexDirection: 'row',
|
||||
maxWidth: 'unset',
|
||||
},
|
||||
},
|
||||
menu: {
|
||||
borderRight: `solid 2px ${border}`,
|
||||
borderBottom: `solid 2px ${border}`,
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
flexGrow: '1',
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
borderBottom: 'none',
|
||||
borderRight: `solid 2px ${border}`,
|
||||
flexDirection: 'column',
|
||||
width: '250px',
|
||||
},
|
||||
},
|
||||
menuOption: {
|
||||
alignItems: 'center',
|
||||
borderRight: `solid 1px ${border}`,
|
||||
boxSizing: 'border-box',
|
||||
cursor: 'pointer',
|
||||
fontSize: largeFontSize,
|
||||
flexGrow: '1',
|
||||
flexShrink: '1',
|
||||
fontSize: '13px',
|
||||
justifyContent: 'center',
|
||||
lineHeight: '1.2',
|
||||
padding: `${md} 0 ${md} ${md}`,
|
||||
minWidth: '0',
|
||||
padding: `${md} ${sm}`,
|
||||
width: '100%',
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
borderRight: 'none',
|
||||
flexGrow: '0',
|
||||
fontSize: largeFontSize,
|
||||
justifyContent: 'flex-start',
|
||||
padding: `${md} 0 ${md} ${md}`,
|
||||
},
|
||||
'&:last-of-type': {
|
||||
borderRight: 'none',
|
||||
},
|
||||
'&:first-child': {
|
||||
borderTopLeftRadius: sm,
|
||||
},
|
||||
'& svg': {
|
||||
display: 'block',
|
||||
marginRight: sm,
|
||||
marginRight: xs,
|
||||
maxWidth: '16px',
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
marginRight: sm,
|
||||
},
|
||||
},
|
||||
'& .fill': {
|
||||
fill: fontColor,
|
||||
|
@ -44,7 +93,18 @@ export const styles = () => ({
|
|||
fill: secondary,
|
||||
},
|
||||
},
|
||||
contents: {
|
||||
width: '100%',
|
||||
},
|
||||
hairline: {
|
||||
display: 'none',
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
display: 'block',
|
||||
},
|
||||
},
|
||||
container: {
|
||||
flexGrow: '1',
|
||||
height: '100%',
|
||||
position: 'relative',
|
||||
},
|
||||
|
|
|
@ -8,6 +8,7 @@ import ExpandLess from '@material-ui/icons/ExpandLess'
|
|||
import ExpandMore from '@material-ui/icons/ExpandMore'
|
||||
import TableRow from '@material-ui/core/TableRow'
|
||||
import TableCell from '@material-ui/core/TableCell'
|
||||
import TableContainer from '@material-ui/core/TableContainer'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import Block from '~/components/layout/Block'
|
||||
import Row from '~/components/layout/Row'
|
||||
|
@ -81,77 +82,79 @@ const TxsTable = ({
|
|||
|
||||
return (
|
||||
<Block className={classes.container}>
|
||||
<Table
|
||||
label="Transactions"
|
||||
defaultOrderBy={TX_TABLE_ID}
|
||||
defaultOrder="desc"
|
||||
defaultRowsPerPage={25}
|
||||
columns={columns}
|
||||
data={filteredData}
|
||||
size={filteredData.size}
|
||||
defaultFixed
|
||||
>
|
||||
{(sortedData: Array<TransactionRow>) => sortedData.map((row: any, index: number) => (
|
||||
<React.Fragment key={index}>
|
||||
<TableRow
|
||||
tabIndex={-1}
|
||||
className={cn(classes.row, expandedTx === row.tx.safeTxHash && classes.expandedRow)}
|
||||
onClick={() => handleTxExpand(row.tx.safeTxHash)}
|
||||
data-testid={TRANSACTION_ROW_TEST_ID}
|
||||
>
|
||||
{autoColumns.map((column: Column) => (
|
||||
<TableCell
|
||||
key={column.id}
|
||||
className={cn(classes.cell, row.status === 'cancelled' && classes.cancelledRow)}
|
||||
style={cellWidth(column.width)}
|
||||
align={column.align}
|
||||
component="td"
|
||||
>
|
||||
{row[column.id]}
|
||||
<TableContainer>
|
||||
<Table
|
||||
label="Transactions"
|
||||
defaultOrderBy={TX_TABLE_ID}
|
||||
defaultOrder="desc"
|
||||
defaultRowsPerPage={25}
|
||||
columns={columns}
|
||||
data={filteredData}
|
||||
size={filteredData.size}
|
||||
defaultFixed
|
||||
>
|
||||
{(sortedData: Array<TransactionRow>) => sortedData.map((row: any, index: number) => (
|
||||
<React.Fragment key={index}>
|
||||
<TableRow
|
||||
tabIndex={-1}
|
||||
className={cn(classes.row, expandedTx === row.tx.safeTxHash && classes.expandedRow)}
|
||||
onClick={() => handleTxExpand(row.tx.safeTxHash)}
|
||||
data-testid={TRANSACTION_ROW_TEST_ID}
|
||||
>
|
||||
{autoColumns.map((column: Column) => (
|
||||
<TableCell
|
||||
key={column.id}
|
||||
className={cn(classes.cell, row.status === 'cancelled' && classes.cancelledRow)}
|
||||
style={cellWidth(column.width)}
|
||||
align={column.align}
|
||||
component="td"
|
||||
>
|
||||
{row[column.id]}
|
||||
</TableCell>
|
||||
))}
|
||||
<TableCell component="td">
|
||||
<Row align="end" className={classes.actions}>
|
||||
<Status status={row.status} />
|
||||
</Row>
|
||||
</TableCell>
|
||||
))}
|
||||
<TableCell component="td">
|
||||
<Row align="end" className={classes.actions}>
|
||||
<Status status={row.status} />
|
||||
</Row>
|
||||
</TableCell>
|
||||
<TableCell style={expandCellStyle}>
|
||||
{!row.tx.creationTx && (
|
||||
<IconButton disableRipple>
|
||||
{expandedTx === row.safeTxHash ? <ExpandLess /> : <ExpandMore />}
|
||||
</IconButton>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
{!row.tx.creationTx && (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
style={{ paddingBottom: 0, paddingTop: 0 }}
|
||||
colSpan={6}
|
||||
className={classes.extendedTxContainer}
|
||||
>
|
||||
<Collapse
|
||||
in={expandedTx === row.tx.safeTxHash}
|
||||
timeout="auto"
|
||||
component={ExpandedTxComponent}
|
||||
unmountOnExit
|
||||
tx={row[TX_TABLE_RAW_TX_ID]}
|
||||
cancelTx={row[TX_TABLE_RAW_CANCEL_TX_ID]}
|
||||
threshold={threshold}
|
||||
owners={owners}
|
||||
granted={granted}
|
||||
userAddress={userAddress}
|
||||
createTransaction={createTransaction}
|
||||
processTransaction={processTransaction}
|
||||
safeAddress={safeAddress}
|
||||
nonce={nonce}
|
||||
/>
|
||||
<TableCell style={expandCellStyle}>
|
||||
{!row.tx.creationTx && (
|
||||
<IconButton disableRipple>
|
||||
{expandedTx === row.safeTxHash ? <ExpandLess /> : <ExpandMore />}
|
||||
</IconButton>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Table>
|
||||
{!row.tx.creationTx && (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
style={{ paddingBottom: 0, paddingTop: 0 }}
|
||||
colSpan={6}
|
||||
className={classes.extendedTxContainer}
|
||||
>
|
||||
<Collapse
|
||||
in={expandedTx === row.tx.safeTxHash}
|
||||
timeout="auto"
|
||||
component={ExpandedTxComponent}
|
||||
unmountOnExit
|
||||
tx={row[TX_TABLE_RAW_TX_ID]}
|
||||
cancelTx={row[TX_TABLE_RAW_CANCEL_TX_ID]}
|
||||
threshold={threshold}
|
||||
owners={owners}
|
||||
granted={granted}
|
||||
userAddress={userAddress}
|
||||
createTransaction={createTransaction}
|
||||
processTransaction={processTransaction}
|
||||
safeAddress={safeAddress}
|
||||
nonce={nonce}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</Block>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
// @flow
|
||||
import {
|
||||
sm, xs, smallFontSize, secondaryText, secondary,
|
||||
sm, xs, smallFontSize, secondaryText, secondary, screenSm,
|
||||
} from '~/theme/variables'
|
||||
|
||||
export const styles = () => ({
|
||||
container: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
},
|
||||
userInfo: {
|
||||
flexWrap: 'nowrap',
|
||||
marginBottom: sm,
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
marginBottom: '0',
|
||||
},
|
||||
},
|
||||
name: {
|
||||
marginLeft: sm,
|
||||
|
@ -16,12 +25,22 @@ export const styles = () => ({
|
|||
},
|
||||
address: {
|
||||
marginRight: sm,
|
||||
overflow: 'hidden',
|
||||
maxWidth: '50%',
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
overflow: 'visible',
|
||||
maxWidth: 'none',
|
||||
},
|
||||
},
|
||||
user: {
|
||||
justifyContent: 'left',
|
||||
},
|
||||
receiveModal: {
|
||||
height: '544px',
|
||||
height: 'auto',
|
||||
maxWidth: 'calc(100% - 30px)',
|
||||
minHeight: '544px',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
open: {
|
||||
paddingLeft: sm,
|
||||
|
@ -31,39 +50,53 @@ export const styles = () => ({
|
|||
},
|
||||
},
|
||||
readonly: {
|
||||
backgroundColor: secondaryText,
|
||||
borderRadius: xs,
|
||||
color: '#ffffff',
|
||||
fontSize: smallFontSize,
|
||||
letterSpacing: '0.5px',
|
||||
color: '#ffffff',
|
||||
backgroundColor: secondaryText,
|
||||
textTransform: 'uppercase',
|
||||
padding: `0 ${sm}`,
|
||||
marginLeft: sm,
|
||||
borderRadius: xs,
|
||||
lineHeight: '28px',
|
||||
marginLeft: sm,
|
||||
padding: `0 ${sm}`,
|
||||
textTransform: 'uppercase',
|
||||
},
|
||||
iconSmall: {
|
||||
fontSize: 16,
|
||||
},
|
||||
balance: {
|
||||
marginLeft: 'auto',
|
||||
display: 'flex',
|
||||
overflow: 'hidden',
|
||||
width: '100%',
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
marginLeft: 'auto',
|
||||
width: 'auto',
|
||||
},
|
||||
},
|
||||
receive: {
|
||||
width: '95px',
|
||||
minWidth: '95px',
|
||||
marginLeft: sm,
|
||||
borderRadius: '4px',
|
||||
marginLeft: sm,
|
||||
width: '50%',
|
||||
|
||||
'& > span': {
|
||||
fontSize: '14px',
|
||||
},
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
minWidth: '95px',
|
||||
width: 'auto',
|
||||
},
|
||||
},
|
||||
send: {
|
||||
width: '75px',
|
||||
minWidth: '75px',
|
||||
borderRadius: '4px',
|
||||
width: '50%',
|
||||
|
||||
'& > span': {
|
||||
fontSize: '14px',
|
||||
},
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
minWidth: '75px',
|
||||
width: 'auto',
|
||||
},
|
||||
},
|
||||
leftIcon: {
|
||||
marginRight: sm,
|
||||
|
@ -84,4 +117,9 @@ export const styles = () => ({
|
|||
fill: secondary,
|
||||
},
|
||||
},
|
||||
nameText: {
|
||||
overflowWrap: 'break-word',
|
||||
wordBreak: 'break-word',
|
||||
whiteSpace: 'normal',
|
||||
},
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue