From c9d30da6b2fb21eaa041db079a541c8909a865bb Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Tue, 27 Nov 2018 10:56:10 +0100 Subject: [PATCH] split SendForm into networks --- .../Send/components/AdvancedForm/index.js | 2 +- .../components/PendingTransactions/index.js | 2 +- .../Account/Send/{ => ethereum}/Container.js | 0 .../views/Account/Send/ethereum/index.js | 406 ++++++++++++++++++ src/views/Wallet/views/Account/Send/index.js | 30 +- .../views/Account/Send/ripple/Container.js | 39 ++ .../Wallet/views/Account/Send/ripple/index.js | 406 ++++++++++++++++++ 7 files changed, 882 insertions(+), 3 deletions(-) rename src/views/Wallet/views/Account/Send/{ => ethereum}/Container.js (100%) create mode 100644 src/views/Wallet/views/Account/Send/ethereum/index.js create mode 100644 src/views/Wallet/views/Account/Send/ripple/Container.js create mode 100644 src/views/Wallet/views/Account/Send/ripple/index.js diff --git a/src/views/Wallet/views/Account/Send/components/AdvancedForm/index.js b/src/views/Wallet/views/Account/Send/components/AdvancedForm/index.js index 6af73ddd..bd0fb790 100644 --- a/src/views/Wallet/views/Account/Send/components/AdvancedForm/index.js +++ b/src/views/Wallet/views/Account/Send/components/AdvancedForm/index.js @@ -11,7 +11,7 @@ import Icon from 'components/Icon'; import ICONS from 'config/icons'; import { FONT_SIZE } from 'config/variables'; -import type { Props as BaseProps } from '../../Container'; +import type { Props as BaseProps } from '../../ethereum/Container'; type Props = BaseProps & { children: React.Node, diff --git a/src/views/Wallet/views/Account/Send/components/PendingTransactions/index.js b/src/views/Wallet/views/Account/Send/components/PendingTransactions/index.js index 63c5dfb8..92b55827 100644 --- a/src/views/Wallet/views/Account/Send/components/PendingTransactions/index.js +++ b/src/views/Wallet/views/Account/Send/components/PendingTransactions/index.js @@ -9,7 +9,7 @@ import ScaleText from 'react-scale-text'; import type { Network } from 'reducers/LocalStorageReducer'; import type { Token } from 'reducers/TokensReducer'; -import type { Props as BaseProps } from '../../Container'; +import type { BaseProps } from '../../index'; type Props = { pending: $PropertyType<$ElementType, 'pending'>, diff --git a/src/views/Wallet/views/Account/Send/Container.js b/src/views/Wallet/views/Account/Send/ethereum/Container.js similarity index 100% rename from src/views/Wallet/views/Account/Send/Container.js rename to src/views/Wallet/views/Account/Send/ethereum/Container.js diff --git a/src/views/Wallet/views/Account/Send/ethereum/index.js b/src/views/Wallet/views/Account/Send/ethereum/index.js new file mode 100644 index 00000000..97638549 --- /dev/null +++ b/src/views/Wallet/views/Account/Send/ethereum/index.js @@ -0,0 +1,406 @@ +/* @flow */ + +import React from 'react'; +import styled, { css } from 'styled-components'; +import { Select } from 'components/Select'; +import Button from 'components/Button'; +import Input from 'components/inputs/Input'; +import Icon from 'components/Icon'; +import Link from 'components/Link'; +import ICONS from 'config/icons'; +import { FONT_SIZE, FONT_WEIGHT, TRANSITION } from 'config/variables'; +import colors from 'config/colors'; +import P from 'components/Paragraph'; +import { H2 } from 'components/Heading'; +import Content from 'views/Wallet/components/Content'; +import type { Token } from 'flowtype'; +import AdvancedForm from '../components/AdvancedForm'; +import PendingTransactions from '../components/PendingTransactions'; + +import type { Props } from './Container'; + +// TODO: Decide on a small screen width for the whole app +// and put it inside config/variables.js +const SmallScreenWidth = '850px'; + +const AmountInputLabelWrapper = styled.div` + display: flex; + justify-content: space-between; +`; + +const AmountInputLabel = styled.span` + text-align: right; + color: ${colors.TEXT_SECONDARY}; +`; + +const InputRow = styled.div` + margin: 20px 0; +`; + +const SetMaxAmountButton = styled(Button)` + height: 40px; + padding: 0 10px; + display: flex; + align-items: center; + justify-content: center; + + font-size: ${FONT_SIZE.SMALLER}; + font-weight: ${FONT_WEIGHT.SMALLEST}; + color: ${colors.TEXT_SECONDARY}; + + border-radius: 0; + border: 1px solid ${colors.DIVIDER}; + border-right: 0; + border-left: 0; + background: transparent; + transition: ${TRANSITION.HOVER}; + + &:hover { + background: ${colors.GRAY_LIGHT}; + } + + ${props => props.isActive && css` + color: ${colors.WHITE}; + background: ${colors.GREEN_PRIMARY}; + border-color: ${colors.GREEN_PRIMARY}; + + &:hover { + background: ${colors.GREEN_SECONDARY}; + } + + &:active { + background: ${colors.GREEN_TERTIARY}; + } + `} +`; + +const CurrencySelect = styled(Select)` + min-width: 77px; + height: 40px; + flex: 0.2; +`; + +const FeeOptionWrapper = styled.div` + display: flex; + justify-content: space-between; +`; + +const FeeLabelWrapper = styled.div` + display: flex; + align-items: center; + margin-bottom: 4px; +`; + +const FeeLabel = styled.span` + color: ${colors.TEXT_SECONDARY}; +`; + +const UpdateFeeWrapper = styled.span` + margin-left: 8px; + display: flex; + align-items: center; + font-size: ${FONT_SIZE.SMALLER}; + color: ${colors.WARNING_PRIMARY}; +`; + +const StyledLink = styled(Link)` + margin-left: 4px; + white-space: nowrap; +`; + +const ToggleAdvancedSettingsWrapper = styled.div` + min-height: 40px; + margin-bottom: 20px; + display: flex; + flex-direction: row; + justify-content: space-between; + + @media screen and (max-width: ${SmallScreenWidth}) { + ${props => (props.isAdvancedSettingsHidden && css` + flex-direction: column; + `)} + } +`; + +const ToggleAdvancedSettingsButton = styled(Button)` + min-height: 40px; + padding: 0; + display: flex; + align-items: center; + font-weight: ${FONT_WEIGHT.BIGGER}; +`; + +const SendButton = styled(Button)` + min-width: ${props => (props.isAdvancedSettingsHidden ? '50%' : '100%')}; + font-size: 13px; + + @media screen and (max-width: ${SmallScreenWidth}) { + margin-top: ${props => (props.isAdvancedSettingsHidden ? '10px' : 0)}; + } +`; + +const AdvancedSettingsIcon = styled(Icon)` + margin-left: 10px; +`; + +// render helpers +const getAddressInputState = (address: string, addressErrors: string, addressWarnings: string): string => { + let state = ''; + if (address && !addressErrors) { + state = 'success'; + } + if (addressWarnings && !addressErrors) { + state = 'warning'; + } + if (addressErrors) { + state = 'error'; + } + return state; +}; + +const getAmountInputState = (amountErrors: string, amountWarnings: string): string => { + let state = ''; + if (amountWarnings && !amountErrors) { + state = 'warning'; + } + if (amountErrors) { + state = 'error'; + } + return state; +}; + +const getTokensSelectData = (tokens: Array, accountNetwork: any): Array<{ value: string, label: string }> => { + const tokensSelectData: Array<{ value: string, label: string }> = tokens.map(t => ({ value: t.symbol, label: t.symbol })); + tokensSelectData.unshift({ value: accountNetwork.symbol, label: accountNetwork.symbol }); + + return tokensSelectData; +}; + +// stateless component +const AccountSend = (props: Props) => { + const device = props.wallet.selectedDevice; + const { + account, + network, + discovery, + tokens, + shouldRender, + loader, + } = props.selectedAccount; + const { + address, + amount, + setMax, + networkSymbol, + currency, + feeLevels, + selectedFeeLevel, + gasPriceNeedsUpdate, + total, + errors, + warnings, + infos, + sending, + advanced, + } = props.sendForm; + + const { + toggleAdvanced, + onAddressChange, + onAmountChange, + onSetMax, + onCurrencyChange, + onFeeLevelChange, + updateFeeLevels, + onSend, + } = props.sendFormActions; + const { type, title, message } = loader; + if (!device || !account || !discovery || !network || !shouldRender) return ; + + const isCurrentCurrencyToken = networkSymbol !== currency; + + let selectedTokenBalance = 0; + const selectedToken = tokens.find(t => t.symbol === currency); + if (selectedToken) { + selectedTokenBalance = selectedToken.balance; + } + + let isSendButtonDisabled: boolean = Object.keys(errors).length > 0 || total === '0' || amount.length === 0 || address.length === 0 || sending; + let sendButtonText: string = 'Send'; + if (networkSymbol !== currency && amount.length > 0 && !errors.amount) { + sendButtonText += ` ${amount} ${currency.toUpperCase()}`; + } else if (networkSymbol === currency && total !== '0') { + sendButtonText += ` ${total} ${network.symbol}`; + } + + if (!device.connected) { + sendButtonText = 'Device is not connected'; + isSendButtonDisabled = true; + } else if (!device.available) { + sendButtonText = 'Device is unavailable'; + isSendButtonDisabled = true; + } else if (!discovery.completed) { + sendButtonText = 'Loading accounts'; + isSendButtonDisabled = true; + } + + const tokensSelectData = getTokensSelectData(tokens, network); + const tokensSelectValue = tokensSelectData.find(t => t.value === currency); + const isAdvancedSettingsHidden = !advanced; + + return ( + + +

Send Ethereum or tokens

+ + onAddressChange(event.target.value)} + /> + + + + + Amount + {(isCurrentCurrencyToken && selectedToken) && ( + You have: {selectedTokenBalance} {selectedToken.symbol} + )} + + )} + value={amount} + onChange={event => onAmountChange(event.target.value)} + bottomText={errors.amount || warnings.amount || infos.amount} + sideAddons={[ + ( + onSetMax()} + isActive={setMax} + > + {!setMax && ( + + )} + {setMax && ( + + )} + Set max + + ), + ( + + ), + ]} + /> + + + + + Fee + {gasPriceNeedsUpdate && ( + + + Recommended fees updated. Click here to use them + + )} + + onAddressChange(event.target.value)} + /> + + + + + Amount + {(isCurrentCurrencyToken && selectedToken) && ( + You have: {selectedTokenBalance} {selectedToken.symbol} + )} + + )} + value={amount} + onChange={event => onAmountChange(event.target.value)} + bottomText={errors.amount || warnings.amount || infos.amount} + sideAddons={[ + ( + onSetMax()} + isActive={setMax} + > + {!setMax && ( + + )} + {setMax && ( + + )} + Set max + + ), + ( + + ), + ]} + /> + + + + + Fee + {gasPriceNeedsUpdate && ( + + + Recommended fees updated. Click here to use them + + )} + +