diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index 5553e2c8e..497023d20 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -163,7 +163,7 @@ describe('MetaMask', function () { }) it('balance renders', async function () { - const balance = await driver.findElement(By.css('.transaction-view-balance__primary-balance')) + const balance = await driver.findElement(By.css('.eth-overview__primary-balance')) await driver.wait(until.elementTextMatches(balance, /100\s*ETH/)) await driver.delay(regularDelayMs) }) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index 964453818..6b38f059c 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -751,7 +751,7 @@ describe('MetaMask', function () { }) it('renders the correct ETH balance', async function () { - const balance = await driver.findElement(By.css('.transaction-view-balance__primary-balance')) + const balance = await driver.findElement(By.css('.eth-overview__primary-balance')) await driver.delay(regularDelayMs) await driver.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/), 10000) const tokenAmount = await balance.getText() @@ -829,7 +829,7 @@ describe('MetaMask', function () { }) it('renders the balance for the new token', async function () { - const balance = await driver.findElement(By.css('.transaction-view-balance .transaction-view-balance__primary-balance')) + const balance = await driver.findElement(By.css('.wallet-overview .token-overview__primary-balance')) await driver.wait(until.elementTextMatches(balance, /^10.000\s*TST\s*$/)) const tokenAmount = await balance.getText() assert.ok(/^10.000\s*TST\s*$/.test(tokenAmount)) @@ -996,7 +996,7 @@ describe('MetaMask', function () { await driver.clickElement(By.css('.token-cell')) await driver.delay(1000) - const tokenBalanceAmount = await driver.findElements(By.css('.transaction-view-balance__primary-balance')) + const tokenBalanceAmount = await driver.findElements(By.css('.token-overview__primary-balance')) await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /7.500\s*TST/), 10000) }) }) @@ -1254,7 +1254,7 @@ describe('MetaMask', function () { }) it('renders the balance for the chosen token', async function () { - const balance = await driver.findElement(By.css('.transaction-view-balance__primary-balance')) + const balance = await driver.findElement(By.css('.token-overview__primary-balance')) await driver.wait(until.elementTextMatches(balance, /0\s*BAT/)) await driver.delay(regularDelayMs) }) diff --git a/test/e2e/tests/simple-send.spec.js b/test/e2e/tests/simple-send.spec.js index e108f46ba..88f45b25b 100644 --- a/test/e2e/tests/simple-send.spec.js +++ b/test/e2e/tests/simple-send.spec.js @@ -15,7 +15,7 @@ describe('MetaMask Browser Extension', function () { const passwordField = await driver.findElement(By.css('#password')) await passwordField.sendKeys('correct horse battery staple') await passwordField.sendKeys(Key.ENTER) - await driver.clickElement(By.css('[data-testid="transaction-view-send"]')) + await driver.clickElement(By.css('[data-testid="eth-overview-send"]')) const recipientAddressField = await driver.findElement(By.css('[data-testid="ens-input"]')) await recipientAddressField.sendKeys('0x985c30949c92df7a0bd42e0f3e3d539ece98db24') const amountField = await driver.findElement(By.css('.unit-input__input')) diff --git a/test/integration/lib/currency-localization.js b/test/integration/lib/currency-localization.js index 500b6fd72..769f2c38b 100644 --- a/test/integration/lib/currency-localization.js +++ b/test/integration/lib/currency-localization.js @@ -37,7 +37,7 @@ async function runCurrencyLocalizationTest (assert) { reactTriggerChange(selectState[0]) await timeout(1000) const txView = await queryAsync($, '.home__main-view') - const heroBalance = await findAsync($(txView), '.transaction-view-balance__balance') - const fiatAmount = await findAsync($(heroBalance), '.transaction-view-balance__secondary-balance') + const heroBalance = await findAsync($(txView), '.eth-overview__balance') + const fiatAmount = await findAsync($(heroBalance), '.eth-overview__secondary-balance') assert.equal(fiatAmount[0].textContent, '₱102,707.97PHP') } diff --git a/ui/app/components/app/index.scss b/ui/app/components/app/index.scss index d44f4942f..d633e7e05 100644 --- a/ui/app/components/app/index.scss +++ b/ui/app/components/app/index.scss @@ -62,8 +62,6 @@ @import 'transaction-breakdown/index'; -@import 'transaction-view-balance/index'; - @import 'transaction-list/index'; @import 'transaction-list-item/index'; @@ -111,3 +109,5 @@ @import 'permissions-connect-header/index'; @import 'permissions-connect-footer/index'; + +@import 'wallet-overview/index'; diff --git a/ui/app/components/app/transaction-view-balance/index.js b/ui/app/components/app/transaction-view-balance/index.js deleted file mode 100644 index 8824737f7..000000000 --- a/ui/app/components/app/transaction-view-balance/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './transaction-view-balance.container' diff --git a/ui/app/components/app/transaction-view-balance/tests/token-view-balance.component.test.js b/ui/app/components/app/transaction-view-balance/tests/token-view-balance.component.test.js deleted file mode 100644 index fc11d0914..000000000 --- a/ui/app/components/app/transaction-view-balance/tests/token-view-balance.component.test.js +++ /dev/null @@ -1,76 +0,0 @@ -import React from 'react' -import assert from 'assert' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import TokenBalance from '../../../ui/token-balance' -import UserPreferencedCurrencyDisplay from '../../user-preferenced-currency-display' -import { SEND_ROUTE } from '../../../../helpers/constants/routes' -import TransactionViewBalance from '../transaction-view-balance.component' - -const propsMethodSpies = { - showDepositModal: sinon.spy(), -} - -const historySpies = { - push: sinon.spy(), -} - -const t = (str1, str2) => (str2 ? str1 + str2 : str1) -const metricsEvent = () => ({}) - -describe('TransactionViewBalance Component', function () { - afterEach(function () { - propsMethodSpies.showDepositModal.resetHistory() - historySpies.push.resetHistory() - }) - - it('should render ETH balance properly', function () { - const wrapper = shallow(( - - ), { context: { t, metricsEvent } }) - - assert.equal(wrapper.find('.transaction-view-balance').length, 1) - assert.equal(wrapper.find('.transaction-view-balance__button').length, 2) - assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).length, 2) - - const buttons = wrapper.find('.transaction-view-balance__buttons') - assert.equal(propsMethodSpies.showDepositModal.callCount, 0) - buttons.childAt(0).simulate('click') - assert.equal(propsMethodSpies.showDepositModal.callCount, 1) - assert.equal(historySpies.push.callCount, 0) - buttons.childAt(1).simulate('click') - assert.equal(historySpies.push.callCount, 1) - assert.equal(historySpies.push.getCall(0).args[0], SEND_ROUTE) - }) - - it('should render token balance properly', function () { - const token = { - address: '0x35865238f0bec9d5ce6abff0fdaebe7b853dfcc5', - decimals: '2', - symbol: 'ABC', - } - - const wrapper = shallow(( - - ), { context: { t } }) - - assert.equal(wrapper.find('.transaction-view-balance').length, 1) - assert.equal(wrapper.find('.transaction-view-balance__button').length, 1) - assert.equal(wrapper.find(TokenBalance).length, 1) - }) -}) diff --git a/ui/app/components/app/transaction-view-balance/transaction-view-balance.component.js b/ui/app/components/app/transaction-view-balance/transaction-view-balance.component.js deleted file mode 100644 index b11dd0a8b..000000000 --- a/ui/app/components/app/transaction-view-balance/transaction-view-balance.component.js +++ /dev/null @@ -1,144 +0,0 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import Button from '../../ui/button' -import Identicon from '../../ui/identicon' -import TokenBalance from '../../ui/token-balance' -import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display' -import { SEND_ROUTE } from '../../../helpers/constants/routes' -import { PRIMARY, SECONDARY } from '../../../helpers/constants/common' -import Tooltip from '../../ui/tooltip-v2' - -export default class TransactionViewBalance extends PureComponent { - static contextTypes = { - t: PropTypes.func, - metricsEvent: PropTypes.func, - } - - static propTypes = { - showDepositModal: PropTypes.func, - selectedToken: PropTypes.object, - history: PropTypes.object, - balance: PropTypes.string, - assetImage: PropTypes.string, - balanceIsCached: PropTypes.bool, - showFiat: PropTypes.bool, - } - - static defaultProps = { - showFiat: true, - } - - renderBalance () { - const { selectedToken, balance, balanceIsCached, showFiat } = this.props - - return selectedToken - ? ( -
- -
- ) : ( - -
-
- - { - balanceIsCached ? * : null - } -
- { - showFiat && ( - - ) - } -
-
- ) - } - - renderButtons () { - const { t, metricsEvent } = this.context - const { selectedToken, showDepositModal, history } = this.props - - return ( -
- { - !selectedToken && ( - - ) - } - -
- ) - } - - render () { - const { selectedToken, assetImage } = this.props - - return ( -
-
- - { this.renderBalance() } -
- { this.renderButtons() } -
- ) - } -} diff --git a/ui/app/components/app/transaction-view-balance/transaction-view-balance.container.js b/ui/app/components/app/transaction-view-balance/transaction-view-balance.container.js deleted file mode 100644 index db9273a0d..000000000 --- a/ui/app/components/app/transaction-view-balance/transaction-view-balance.container.js +++ /dev/null @@ -1,44 +0,0 @@ -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { compose } from 'redux' -import TransactionViewBalance from './transaction-view-balance.component' -import { - getSelectedToken, - getSelectedAddress, - getNativeCurrency, - getSelectedTokenAssetImage, - getMetaMaskAccounts, - isBalanceCached, - preferencesSelector, - getIsMainnet, -} from '../../../selectors' -import { showModal } from '../../../store/actions' - -const mapStateToProps = (state) => { - const { showFiatInTestnets } = preferencesSelector(state) - const isMainnet = getIsMainnet(state) - const selectedAddress = getSelectedAddress(state) - const accounts = getMetaMaskAccounts(state) - const account = accounts[selectedAddress] - const { balance } = account - - return { - selectedToken: getSelectedToken(state), - balance, - nativeCurrency: getNativeCurrency(state), - assetImage: getSelectedTokenAssetImage(state), - balanceIsCached: isBalanceCached(state), - showFiat: (isMainnet || !!showFiatInTestnets), - } -} - -const mapDispatchToProps = (dispatch) => { - return { - showDepositModal: () => dispatch(showModal({ name: 'DEPOSIT_ETHER' })), - } -} - -export default compose( - withRouter, - connect(mapStateToProps, mapDispatchToProps) -)(TransactionViewBalance) diff --git a/ui/app/components/app/wallet-overview/eth-overview.js b/ui/app/components/app/wallet-overview/eth-overview.js new file mode 100644 index 000000000..b9c51fe1c --- /dev/null +++ b/ui/app/components/app/wallet-overview/eth-overview.js @@ -0,0 +1,111 @@ +import React, { useContext } from 'react' +import { useDispatch, useSelector } from 'react-redux' +import classnames from 'classnames' +import { useHistory } from 'react-router-dom' + +import Button from '../../ui/button' +import Identicon from '../../ui/identicon' +import { I18nContext } from '../../../contexts/i18n' +import WalletOverview from './wallet-overview' +import { SEND_ROUTE } from '../../../helpers/constants/routes' +import { useMetricEvent } from '../../../hooks/useMetricEvent' +import Tooltip from '../../ui/tooltip-v2' +import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display' +import { PRIMARY, SECONDARY } from '../../../helpers/constants/common' +import { showModal } from '../../../store/actions' +import { isBalanceCached, getSelectedAccount, getShouldShowFiat } from '../../../selectors/selectors' + +const EthOverview = () => { + const dispatch = useDispatch() + const t = useContext(I18nContext) + const sendEvent = useMetricEvent({ + eventOpts: { + category: 'Navigation', + action: 'Home', + name: 'Clicked Send: Eth', + }, + }) + const depositEvent = useMetricEvent({ + eventOpts: { + category: 'Navigation', + action: 'Home', + name: 'Clicked Deposit', + }, + }) + const history = useHistory() + const balanceIsCached = useSelector(isBalanceCached) + const showFiat = useSelector(getShouldShowFiat) + const selectedAccount = useSelector(getSelectedAccount) + const { balance } = selectedAccount + + return ( + +
+
+ + { + balanceIsCached ? * : null + } +
+ { + showFiat && ( + + ) + } +
+ + )} + buttons={( + <> + + + + )} + icon={} + /> + ) +} + +EthOverview.propTypes = { + +} + +export default EthOverview diff --git a/ui/app/components/app/wallet-overview/index.js b/ui/app/components/app/wallet-overview/index.js new file mode 100644 index 000000000..e8205ea58 --- /dev/null +++ b/ui/app/components/app/wallet-overview/index.js @@ -0,0 +1,2 @@ +export { default as EthOverview } from './eth-overview' +export { default as TokenOverview } from './token-overview' diff --git a/ui/app/components/app/transaction-view-balance/index.scss b/ui/app/components/app/wallet-overview/index.scss similarity index 70% rename from ui/app/components/app/transaction-view-balance/index.scss rename to ui/app/components/app/wallet-overview/index.scss index cdb09db8a..f177544c0 100644 --- a/ui/app/components/app/transaction-view-balance/index.scss +++ b/ui/app/components/app/wallet-overview/index.scss @@ -1,4 +1,4 @@ -.transaction-view-balance { +.wallet-overview { display: flex; justify-content: space-between; align-items: center; @@ -12,6 +12,30 @@ width: 100%; } + &__balance { + flex: 1; + display: flex; + flex-direction: row; + align-items: center; + min-width: 0; + + @media screen and (max-width: $break-small) { + flex-direction: column; + width: 100%; + } + } + + &__buttons { + display: flex; + flex-direction: row; + + @media screen and (max-width: $break-small) { + margin-bottom: 16px; + } + } +} + +.eth-overview { &__balance { margin: 0 12px; display: flex; @@ -40,7 +64,6 @@ line-height: 45px; width: 100%; justify-content: center; - } } @@ -65,25 +88,41 @@ color: $Grey-400; } - &__balance-container { - flex: 1; + &__button { + min-width: initial; + width: 100px; + + &:not(:last-child) { + margin-right: 12px; + } + } +} + +.token-overview { + &__balance { + margin: 0 12px; display: flex; - flex-direction: row; - align-items: center; + flex-direction: column; min-width: 0; + position: relative; @media screen and (max-width: $break-small) { - flex-direction: column; - width: 100%; + align-items: center; + margin: 16px 0; + padding: 0 16px; + max-width: 100%; } } - &__buttons { - display: flex; - flex-direction: row; + &__primary-balance { + font-size: 1.5rem; + color: $black; @media screen and (max-width: $break-small) { - margin-bottom: 16px; + font-size: 32px; + line-height: 45px; + width: 100%; + justify-content: center; } } diff --git a/ui/app/components/app/wallet-overview/token-overview.js b/ui/app/components/app/wallet-overview/token-overview.js new file mode 100644 index 000000000..a91fee0b7 --- /dev/null +++ b/ui/app/components/app/wallet-overview/token-overview.js @@ -0,0 +1,69 @@ +import React, { useContext } from 'react' +import PropTypes from 'prop-types' +import { useSelector } from 'react-redux' +import { useHistory } from 'react-router-dom' + +import Button from '../../ui/button' +import Identicon from '../../ui/identicon' +import TokenBalance from '../../ui/token-balance' +import { I18nContext } from '../../../contexts/i18n' +import WalletOverview from './wallet-overview' +import { SEND_ROUTE } from '../../../helpers/constants/routes' +import { useMetricEvent } from '../../../hooks/useMetricEvent' +import { getAssetImages } from '../../../selectors/selectors' + +const TokenOverview = ({ token }) => { + const t = useContext(I18nContext) + const sendTokenEvent = useMetricEvent({ + eventOpts: { + category: 'Navigation', + action: 'Home', + name: 'Clicked Send: Token', + }, + }) + const history = useHistory() + const assetImages = useSelector(getAssetImages) + + return ( + + + + )} + buttons={( + + )} + icon={( + + )} + /> + ) +} + +TokenOverview.propTypes = { + token: PropTypes.shape({ + address: PropTypes.string.isRequired, + decimals: PropTypes.number, + symbol: PropTypes.string, + }).isRequired, +} + +export default TokenOverview diff --git a/ui/app/components/app/wallet-overview/wallet-overview.js b/ui/app/components/app/wallet-overview/wallet-overview.js new file mode 100644 index 000000000..6a6c27594 --- /dev/null +++ b/ui/app/components/app/wallet-overview/wallet-overview.js @@ -0,0 +1,24 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const WalletOverview = ({ balance, buttons, icon }) => { + return ( +
+
+ { icon } + { balance } +
+
+ { buttons } +
+
+ ) +} + +WalletOverview.propTypes = { + balance: PropTypes.element.isRequired, + buttons: PropTypes.element.isRequired, + icon: PropTypes.element.isRequired, +} + +export default WalletOverview diff --git a/ui/app/pages/home/home.component.js b/ui/app/pages/home/home.component.js index c3aaea152..998593fb3 100644 --- a/ui/app/pages/home/home.component.js +++ b/ui/app/pages/home/home.component.js @@ -8,13 +8,13 @@ import HomeNotification from '../../components/app/home-notification' import MultipleNotifications from '../../components/app/multiple-notifications' import WalletView from '../../components/app/wallet-view' import TransactionList from '../../components/app/transaction-list' -import TransactionViewBalance from '../../components/app/transaction-view-balance' import MenuBar from '../../components/app/menu-bar' import Popover from '../../components/ui/popover' import Button from '../../components/ui/button' import ConnectedSites from '../connected-sites' import ConnectedAccounts from '../connected-accounts' import { Tabs, Tab } from '../../components/ui/tabs' +import { EthOverview, TokenOverview } from '../../components/app/wallet-overview' import { RESTORE_VAULT_ROUTE, @@ -51,6 +51,11 @@ export default class Home extends PureComponent { totalUnapprovedCount: PropTypes.number.isRequired, setConnectedStatusPopoverHasBeenShown: PropTypes.func, connectedStatusPopoverHasBeenShown: PropTypes.bool, + selectedToken: PropTypes.shape({ + address: PropTypes.string.isRequired, + decimals: PropTypes.number, + symbol: PropTypes.string, + }), } UNSAFE_componentWillMount () { @@ -208,6 +213,7 @@ export default class Home extends PureComponent { history, connectedStatusPopoverHasBeenShown, isPopup, + selectedToken, } = this.props if (forgottenPassword) { @@ -218,6 +224,10 @@ export default class Home extends PureComponent { return null } + const homeOverview = selectedToken + ? + : + return (
@@ -235,7 +245,7 @@ export default class Home extends PureComponent {
- + { homeOverview }
@@ -245,7 +255,7 @@ export default class Home extends PureComponent {
- + { homeOverview }
{ threeBoxSynced, showRestorePrompt, selectedAddress, + selectedToken: getSelectedToken(state), threeBoxLastUpdated, firstPermissionsRequestId, totalUnapprovedCount,