add hamburger menu to eth page (#10938)

* add hamburger menu to eth page

* change token-options to asset-options, use more direct selector for user address fetch
feature/default_network_editable
Alex Donesky 4 years ago committed by GitHub
parent 37159a58e1
commit 13a0389c96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      app/_locales/en/messages.json
  2. 3
      app/_locales/es/messages.json
  3. 3
      app/_locales/es_419/messages.json
  4. 3
      app/_locales/hi/messages.json
  5. 3
      app/_locales/id/messages.json
  6. 3
      app/_locales/it/messages.json
  7. 3
      app/_locales/ja/messages.json
  8. 3
      app/_locales/ko/messages.json
  9. 3
      app/_locales/ru/messages.json
  10. 3
      app/_locales/tl/messages.json
  11. 3
      app/_locales/vi/messages.json
  12. 3
      app/_locales/zh_CN/messages.json
  13. 4
      test/e2e/metamask-ui.spec.js
  14. 2
      ui/app/pages/asset/asset.scss
  15. 80
      ui/app/pages/asset/components/asset-options.js
  16. 32
      ui/app/pages/asset/components/native-asset.js
  17. 4
      ui/app/pages/asset/components/token-asset.js
  18. 76
      ui/app/pages/asset/components/token-options.js

@ -179,6 +179,9 @@
"asset": { "asset": {
"message": "Asset" "message": "Asset"
}, },
"assetOptions": {
"message": "Asset options"
},
"assets": { "assets": {
"message": "Assets" "message": "Assets"
}, },
@ -2132,9 +2135,6 @@
"tokenContractAddress": { "tokenContractAddress": {
"message": "Token Contract Address" "message": "Token Contract Address"
}, },
"tokenOptions": {
"message": "Token options"
},
"tokenSymbol": { "tokenSymbol": {
"message": "Token Symbol" "message": "Token Symbol"
}, },

@ -1855,9 +1855,6 @@
"tokenContractAddress": { "tokenContractAddress": {
"message": "Dirección del contrato de token" "message": "Dirección del contrato de token"
}, },
"tokenOptions": {
"message": "Opciones del Token"
},
"tokenSymbol": { "tokenSymbol": {
"message": "Símbolo del token" "message": "Símbolo del token"
}, },

@ -1855,9 +1855,6 @@
"tokenContractAddress": { "tokenContractAddress": {
"message": "Dirección de contrato del token" "message": "Dirección de contrato del token"
}, },
"tokenOptions": {
"message": "Opciones del Token"
},
"tokenSymbol": { "tokenSymbol": {
"message": "Símbolo del token" "message": "Símbolo del token"
}, },

@ -1819,9 +1819,6 @@
"tokenContractAddress": { "tokenContractAddress": {
"message": "टकन अनध पत" "message": "टकन अनध पत"
}, },
"tokenOptions": {
"message": "टकन किकलप"
},
"tokenSymbol": { "tokenSymbol": {
"message": "टकन करतक" "message": "टकन करतक"
}, },

@ -1819,9 +1819,6 @@
"tokenContractAddress": { "tokenContractAddress": {
"message": "Alamat Kontrak Token" "message": "Alamat Kontrak Token"
}, },
"tokenOptions": {
"message": "Opsi token"
},
"tokenSymbol": { "tokenSymbol": {
"message": "Simbol Token" "message": "Simbol Token"
}, },

@ -1878,9 +1878,6 @@
"tokenContractAddress": { "tokenContractAddress": {
"message": "Indirizzo Contratto Token" "message": "Indirizzo Contratto Token"
}, },
"tokenOptions": {
"message": "Opzioni token"
},
"tokenSymbol": { "tokenSymbol": {
"message": "Simbolo Token" "message": "Simbolo Token"
}, },

@ -1855,9 +1855,6 @@
"tokenContractAddress": { "tokenContractAddress": {
"message": "トークンコントラクトのアドレス" "message": "トークンコントラクトのアドレス"
}, },
"tokenOptions": {
"message": "トークンのオプション"
},
"tokenSymbol": { "tokenSymbol": {
"message": "トークンシンボル" "message": "トークンシンボル"
}, },

@ -1819,9 +1819,6 @@
"tokenContractAddress": { "tokenContractAddress": {
"message": "토큰 계약 주소" "message": "토큰 계약 주소"
}, },
"tokenOptions": {
"message": "토큰 옵션"
},
"tokenSymbol": { "tokenSymbol": {
"message": "토큰 기호" "message": "토큰 기호"
}, },

@ -1819,9 +1819,6 @@
"tokenContractAddress": { "tokenContractAddress": {
"message": "Адрес контракта токена" "message": "Адрес контракта токена"
}, },
"tokenOptions": {
"message": "Опции токена"
},
"tokenSymbol": { "tokenSymbol": {
"message": "Символ токена" "message": "Символ токена"
}, },

@ -1816,9 +1816,6 @@
"tokenContractAddress": { "tokenContractAddress": {
"message": "Address ng Kontrata ng Token" "message": "Address ng Kontrata ng Token"
}, },
"tokenOptions": {
"message": "Mga opsyon ng token"
},
"tokenSymbol": { "tokenSymbol": {
"message": "Simbolo ng Token" "message": "Simbolo ng Token"
}, },

@ -1819,9 +1819,6 @@
"tokenContractAddress": { "tokenContractAddress": {
"message": "Địa chỉ hợp đồng token" "message": "Địa chỉ hợp đồng token"
}, },
"tokenOptions": {
"message": "Tùy chọn token"
},
"tokenSymbol": { "tokenSymbol": {
"message": "Ký hiệu token" "message": "Ký hiệu token"
}, },

@ -1855,9 +1855,6 @@
"tokenContractAddress": { "tokenContractAddress": {
"message": "代币合约地址" "message": "代币合约地址"
}, },
"tokenOptions": {
"message": "代币选项"
},
"tokenSymbol": { "tokenSymbol": {
"message": "代币符号" "message": "代币符号"
}, },

@ -1508,9 +1508,9 @@ describe('MetaMask', function () {
describe('Hide token', function () { describe('Hide token', function () {
it('hides the token when clicked', async function () { it('hides the token when clicked', async function () {
await driver.clickElement('[data-testid="token-options__button"]'); await driver.clickElement('[data-testid="asset-options__button"]');
await driver.clickElement('[data-testid="token-options__hide"]'); await driver.clickElement('[data-testid="asset-options__hide"]');
// wait for confirm hide modal to be visible // wait for confirm hide modal to be visible
const confirmHideModal = await driver.findVisibleElement('span .modal'); const confirmHideModal = await driver.findVisibleElement('span .modal');

@ -32,7 +32,7 @@
} }
} }
.token-options { .asset-options {
&__button { &__button {
font-size: $font-size-paragraph; font-size: $font-size-paragraph;
color: $Black-100; color: $Black-100;

@ -0,0 +1,80 @@
import React, { useContext, useState } from 'react';
import PropTypes from 'prop-types';
import { I18nContext } from '../../../contexts/i18n';
import { Menu, MenuItem } from '../../../components/ui/menu';
const AssetOptions = ({
onRemove,
onViewEtherscan,
onViewAccountDetails,
tokenSymbol,
isNativeAsset,
}) => {
const t = useContext(I18nContext);
const [assetOptionsButtonElement, setAssetOptionsButtonElement] = useState(
null,
);
const [assetOptionsOpen, setAssetOptionsOpen] = useState(false);
return (
<>
<button
className="fas fa-ellipsis-v asset-options__button"
data-testid="asset-options__button"
onClick={() => setAssetOptionsOpen(true)}
ref={setAssetOptionsButtonElement}
title={t('assetOptions')}
/>
{assetOptionsOpen ? (
<Menu
anchorElement={assetOptionsButtonElement}
onHide={() => setAssetOptionsOpen(false)}
>
<MenuItem
iconClassName="fas fa-qrcode"
data-testid="asset-options__account-details"
onClick={() => {
setAssetOptionsOpen(false);
onViewAccountDetails();
}}
>
{t('accountDetails')}
</MenuItem>
<MenuItem
iconClassName="fas fa-external-link-alt asset-options__icon"
data-testid="asset-options__etherscan"
onClick={() => {
setAssetOptionsOpen(false);
onViewEtherscan();
}}
>
{t('viewOnEtherscan')}
</MenuItem>
{isNativeAsset ? null : (
<MenuItem
iconClassName="fas fa-trash-alt asset-options__icon"
data-testid="asset-options__hide"
onClick={() => {
setAssetOptionsOpen(false);
onRemove();
}}
>
{t('hideTokenSymbol', [tokenSymbol])}
</MenuItem>
)}
</Menu>
) : null}
</>
);
};
AssetOptions.propTypes = {
isNativeAsset: PropTypes.bool,
onRemove: PropTypes.func.isRequired,
onViewEtherscan: PropTypes.func.isRequired,
onViewAccountDetails: PropTypes.func.isRequired,
tokenSymbol: PropTypes.string,
};
export default AssetOptions;

@ -1,19 +1,30 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useSelector } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import TransactionList from '../../../components/app/transaction-list'; import TransactionList from '../../../components/app/transaction-list';
import { EthOverview } from '../../../components/app/wallet-overview'; import { EthOverview } from '../../../components/app/wallet-overview';
import { getSelectedIdentity } from '../../../selectors/selectors'; import {
getSelectedIdentity,
getCurrentChainId,
getRpcPrefsForCurrentProvider,
getSelectedAddress,
} from '../../../selectors/selectors';
import { showModal } from '../../../store/actions';
import getAccountLink from '../../../../lib/account-link';
import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; import { DEFAULT_ROUTE } from '../../../helpers/constants/routes';
import AssetNavigation from './asset-navigation'; import AssetNavigation from './asset-navigation';
import AssetOptions from './asset-options';
export default function NativeAsset({ nativeCurrency }) { export default function NativeAsset({ nativeCurrency }) {
const selectedAccountName = useSelector( const selectedAccountName = useSelector(
(state) => getSelectedIdentity(state).name, (state) => getSelectedIdentity(state).name,
); );
const dispatch = useDispatch();
const chainId = useSelector(getCurrentChainId);
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider);
const address = useSelector(getSelectedAddress);
const history = useHistory(); const history = useHistory();
return ( return (
@ -22,6 +33,19 @@ export default function NativeAsset({ nativeCurrency }) {
accountName={selectedAccountName} accountName={selectedAccountName}
assetName={nativeCurrency} assetName={nativeCurrency}
onBack={() => history.push(DEFAULT_ROUTE)} onBack={() => history.push(DEFAULT_ROUTE)}
optionsButton={
<AssetOptions
isNativeAsset
onViewEtherscan={() => {
global.platform.openTab({
url: getAccountLink(address, chainId, rpcPrefs),
});
}}
onViewAccountDetails={() => {
dispatch(showModal({ name: 'ACCOUNT_DETAILS' }));
}}
/>
}
/> />
<EthOverview className="asset__overview" /> <EthOverview className="asset__overview" />
<TransactionList hideTokenTransactions /> <TransactionList hideTokenTransactions />

@ -14,7 +14,7 @@ import { DEFAULT_ROUTE } from '../../../helpers/constants/routes';
import { showModal } from '../../../store/actions'; import { showModal } from '../../../store/actions';
import AssetNavigation from './asset-navigation'; import AssetNavigation from './asset-navigation';
import TokenOptions from './token-options'; import AssetOptions from './asset-options';
export default function TokenAsset({ token }) { export default function TokenAsset({ token }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -31,7 +31,7 @@ export default function TokenAsset({ token }) {
assetName={token.symbol} assetName={token.symbol}
onBack={() => history.push(DEFAULT_ROUTE)} onBack={() => history.push(DEFAULT_ROUTE)}
optionsButton={ optionsButton={
<TokenOptions <AssetOptions
onRemove={() => onRemove={() =>
dispatch(showModal({ name: 'HIDE_TOKEN_CONFIRMATION', token })) dispatch(showModal({ name: 'HIDE_TOKEN_CONFIRMATION', token }))
} }

@ -1,76 +0,0 @@
import React, { useContext, useState } from 'react';
import PropTypes from 'prop-types';
import { I18nContext } from '../../../contexts/i18n';
import { Menu, MenuItem } from '../../../components/ui/menu';
const TokenOptions = ({
onRemove,
onViewEtherscan,
onViewAccountDetails,
tokenSymbol,
}) => {
const t = useContext(I18nContext);
const [tokenOptionsButtonElement, setTokenOptionsButtonElement] = useState(
null,
);
const [tokenOptionsOpen, setTokenOptionsOpen] = useState(false);
return (
<>
<button
className="fas fa-ellipsis-v token-options__button"
data-testid="token-options__button"
onClick={() => setTokenOptionsOpen(true)}
ref={setTokenOptionsButtonElement}
title={t('tokenOptions')}
/>
{tokenOptionsOpen ? (
<Menu
anchorElement={tokenOptionsButtonElement}
onHide={() => setTokenOptionsOpen(false)}
>
<MenuItem
iconClassName="fas fa-qrcode"
data-testid="token-options__account-details"
onClick={() => {
setTokenOptionsOpen(false);
onViewAccountDetails();
}}
>
{t('accountDetails')}
</MenuItem>
<MenuItem
iconClassName="fas fa-external-link-alt token-options__icon"
data-testid="token-options__etherscan"
onClick={() => {
setTokenOptionsOpen(false);
onViewEtherscan();
}}
>
{t('viewOnEtherscan')}
</MenuItem>
<MenuItem
iconClassName="fas fa-trash-alt token-options__icon"
data-testid="token-options__hide"
onClick={() => {
setTokenOptionsOpen(false);
onRemove();
}}
>
{t('hideTokenSymbol', [tokenSymbol])}
</MenuItem>
</Menu>
) : null}
</>
);
};
TokenOptions.propTypes = {
onRemove: PropTypes.func.isRequired,
onViewEtherscan: PropTypes.func.isRequired,
onViewAccountDetails: PropTypes.func.isRequired,
tokenSymbol: PropTypes.string.isRequired,
};
export default TokenOptions;
Loading…
Cancel
Save