diff options
author | Chi Kei Chan <chikeichan@gmail.com> | 2019-03-22 07:03:30 +0800 |
---|---|---|
committer | Dan J Miller <danjm.com@gmail.com> | 2019-03-22 07:03:30 +0800 |
commit | 31175625b446cb5d18b17db23018bca8b14d280c (patch) | |
tree | f54e159883deef003fb281267025edf796eb8004 /ui/app/components/dropdowns | |
parent | 7287133e15fab22299e07704206e85bc855d1064 (diff) | |
download | tangerine-wallet-browser-31175625b446cb5d18b17db23018bca8b14d280c.tar tangerine-wallet-browser-31175625b446cb5d18b17db23018bca8b14d280c.tar.gz tangerine-wallet-browser-31175625b446cb5d18b17db23018bca8b14d280c.tar.bz2 tangerine-wallet-browser-31175625b446cb5d18b17db23018bca8b14d280c.tar.lz tangerine-wallet-browser-31175625b446cb5d18b17db23018bca8b14d280c.tar.xz tangerine-wallet-browser-31175625b446cb5d18b17db23018bca8b14d280c.tar.zst tangerine-wallet-browser-31175625b446cb5d18b17db23018bca8b14d280c.zip |
Folder restructure (#6304)
* Remove ui/app/keychains/
* Remove ui/app/img/ (unused images)
* Move conversion-util to helpers/utils/
* Move token-util to helpers/utils/
* Move /helpers/*.js inside /helpers/utils/
* Move util tests inside /helpers/utils/
* Renameand move confirm-transaction/util.js to helpers/utils/
* Move higher-order-components to helpers/higher-order-components/
* Move infura-conversion.json to helpers/constants/
* Move all utility functions to helpers/utils/
* Move pages directory to top-level
* Move all constants to helpers/constants/
* Move metametrics inside helpers/
* Move app and root inside pages/
* Move routes inside helpers/
* Re-organize ducks/
* Move reducers to ducks/
* Move selectors inside selectors/
* Move test out of test folder
* Move action, reducer, store inside store/
* Move ui components inside ui/
* Move UI components inside ui/
* Move connected components inside components/app/
* Move i18n-helper inside helpers/
* Fix unit tests
* Fix unit test
* Move pages components
* Rename routes component
* Move reducers to ducks/index
* Fix bad path in unit test
Diffstat (limited to 'ui/app/components/dropdowns')
-rw-r--r-- | ui/app/components/dropdowns/account-details-dropdown.js | 131 | ||||
-rw-r--r-- | ui/app/components/dropdowns/components/account-dropdowns.js | 473 | ||||
-rw-r--r-- | ui/app/components/dropdowns/components/dropdown.js | 112 | ||||
-rw-r--r-- | ui/app/components/dropdowns/components/menu.js | 51 | ||||
-rw-r--r-- | ui/app/components/dropdowns/components/network-dropdown-icon.js | 47 | ||||
-rw-r--r-- | ui/app/components/dropdowns/index.js | 11 | ||||
-rw-r--r-- | ui/app/components/dropdowns/network-dropdown.js | 378 | ||||
-rw-r--r-- | ui/app/components/dropdowns/simple-dropdown.js | 92 | ||||
-rw-r--r-- | ui/app/components/dropdowns/tests/dropdown.test.js | 37 | ||||
-rw-r--r-- | ui/app/components/dropdowns/tests/menu.test.js | 87 | ||||
-rw-r--r-- | ui/app/components/dropdowns/tests/network-dropdown-icon.test.js | 25 | ||||
-rw-r--r-- | ui/app/components/dropdowns/tests/network-dropdown.test.js | 97 | ||||
-rw-r--r-- | ui/app/components/dropdowns/token-menu-dropdown.js | 68 |
13 files changed, 0 insertions, 1609 deletions
diff --git a/ui/app/components/dropdowns/account-details-dropdown.js b/ui/app/components/dropdowns/account-details-dropdown.js deleted file mode 100644 index bda8b9517..000000000 --- a/ui/app/components/dropdowns/account-details-dropdown.js +++ /dev/null @@ -1,131 +0,0 @@ -const Component = require('react').Component -const PropTypes = require('prop-types') -const h = require('react-hyperscript') -const inherits = require('util').inherits -const connect = require('react-redux').connect -const actions = require('../../actions') -const { getSelectedIdentity } = require('../../selectors') -const genAccountLink = require('../../../lib/account-link.js') -const { Menu, Item, CloseArea } = require('./components/menu') - -AccountDetailsDropdown.contextTypes = { - t: PropTypes.func, - metricsEvent: PropTypes.func, -} - -module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsDropdown) - -function mapStateToProps (state) { - return { - selectedIdentity: getSelectedIdentity(state), - network: state.metamask.network, - keyrings: state.metamask.keyrings, - } -} - -function mapDispatchToProps (dispatch) { - return { - showAccountDetailModal: () => { - dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) - }, - viewOnEtherscan: (address, network) => { - global.platform.openWindow({ url: genAccountLink(address, network) }) - }, - showRemoveAccountConfirmationModal: (identity) => { - return dispatch(actions.showModal({ name: 'CONFIRM_REMOVE_ACCOUNT', identity })) - }, - } -} - -inherits(AccountDetailsDropdown, Component) -function AccountDetailsDropdown () { - Component.call(this) - - this.onClose = this.onClose.bind(this) -} - -AccountDetailsDropdown.prototype.onClose = function (e) { - e.stopPropagation() - this.props.onClose() -} - -AccountDetailsDropdown.prototype.render = function () { - const { - selectedIdentity, - network, - keyrings, - showAccountDetailModal, - viewOnEtherscan, - showRemoveAccountConfirmationModal } = this.props - - const address = selectedIdentity.address - - const keyring = keyrings.find((kr) => { - return kr.accounts.includes(address) - }) - - const isRemovable = keyring.type !== 'HD Key Tree' - - return h(Menu, { className: 'account-details-dropdown', isShowing: true }, [ - h(CloseArea, { - onClick: this.onClose, - }), - h(Item, { - onClick: (e) => { - e.stopPropagation() - this.context.metricsEvent({ - eventOpts: { - category: 'Navigation', - action: 'Account Options', - name: 'Clicked Expand View', - }, - }) - global.platform.openExtensionInBrowser() - this.props.onClose() - }, - text: this.context.t('expandView'), - icon: h(`img`, { src: 'images/expand.svg', style: { height: '15px' } }), - }), - h(Item, { - onClick: (e) => { - e.stopPropagation() - showAccountDetailModal() - this.context.metricsEvent({ - eventOpts: { - category: 'Navigation', - action: 'Account Options', - name: 'Viewed Account Details', - }, - }) - this.props.onClose() - }, - text: this.context.t('accountDetails'), - icon: h(`img`, { src: 'images/info.svg', style: { height: '15px' } }), - }), - h(Item, { - onClick: (e) => { - e.stopPropagation() - this.context.metricsEvent({ - eventOpts: { - category: 'Navigation', - action: 'Account Options', - name: 'Clicked View on Etherscan', - }, - }) - viewOnEtherscan(address, network) - this.props.onClose() - }, - text: this.context.t('viewOnEtherscan'), - icon: h(`img`, { src: 'images/open-etherscan.svg', style: { height: '15px' } }), - }), - isRemovable ? h(Item, { - onClick: (e) => { - e.stopPropagation() - showRemoveAccountConfirmationModal(selectedIdentity) - this.props.onClose() - }, - text: this.context.t('removeAccount'), - icon: h(`img`, { src: 'images/hide.svg', style: { height: '15px' } }), - }) : null, - ]) -} diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js deleted file mode 100644 index e6b3e0c0c..000000000 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ /dev/null @@ -1,473 +0,0 @@ -const Component = require('react').Component -const PropTypes = require('prop-types') -const h = require('react-hyperscript') -const actions = require('../../../actions') -const genAccountLink = require('../../../../lib/account-link.js') -const connect = require('react-redux').connect -const Dropdown = require('./dropdown').Dropdown -const DropdownMenuItem = require('./dropdown').DropdownMenuItem -import Identicon from '../../identicon' -const { checksumAddress } = require('../../../util') -const copyToClipboard = require('copy-to-clipboard') -const { formatBalance } = require('../../../util') - - -class AccountDropdowns extends Component { - constructor (props) { - super(props) - this.state = { - accountSelectorActive: false, - optionsMenuActive: false, - } - // Used for orangeaccount selector icon - // this.accountSelectorToggleClassName = 'accounts-selector' - this.accountSelectorToggleClassName = 'fa-angle-down' - this.optionsMenuToggleClassName = 'fa-ellipsis-h' - } - - renderAccounts () { - const { identities, accounts, selected, menuItemStyles, actions, keyrings, ticker } = this.props - - return Object.keys(identities).map((key, index) => { - const identity = identities[key] - const isSelected = identity.address === selected - - const balanceValue = accounts[key].balance - const formattedBalance = balanceValue ? formatBalance(balanceValue, 6, true, ticker) : '...' - const simpleAddress = identity.address.substring(2).toLowerCase() - - const keyring = keyrings.find((kr) => { - return kr.accounts.includes(simpleAddress) || - kr.accounts.includes(identity.address) - }) - - return h( - DropdownMenuItem, - { - closeMenu: () => {}, - onClick: () => { - this.props.actions.showAccountDetail(identity.address) - }, - style: Object.assign( - { - marginTop: index === 0 ? '5px' : '', - fontSize: '24px', - width: '260px', - }, - menuItemStyles, - ), - }, - [ - h('div.flex-row.flex-center', {}, [ - - h('span', { - style: { - flex: '1 1 0', - minWidth: '20px', - minHeight: '30px', - }, - }, [ - h('span', { - style: { - flex: '1 1 auto', - fontSize: '14px', - }, - }, isSelected ? h('i.fa.fa-check') : null), - ]), - - h( - Identicon, - { - address: identity.address, - diameter: 24, - style: { - flex: '1 1 auto', - marginLeft: '10px', - }, - }, - ), - - h('span.flex-column', { - style: { - flex: '10 10 auto', - width: '175px', - alignItems: 'flex-start', - justifyContent: 'center', - marginLeft: '10px', - position: 'relative', - }, - }, [ - this.indicateIfLoose(keyring), - h('span.account-dropdown-name', { - style: { - fontSize: '18px', - maxWidth: '145px', - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - }, - }, identity.name || ''), - - h('span.account-dropdown-balance', { - style: { - fontSize: '14px', - fontFamily: 'Avenir', - fontWeight: 500, - }, - }, formattedBalance), - ]), - - h('span', { - style: { - flex: '3 3 auto', - }, - }, [ - h('span.account-dropdown-edit-button.allcaps', { - style: { - fontSize: '16px', - }, - onClick: () => { - actions.showEditAccountModal(identity) - }, - }, [ - this.context.t('edit'), - ]), - ]), - - ]), - ] - ) - }) - } - - indicateIfLoose (keyring) { - try { // Sometimes keyrings aren't loaded yet: - const type = keyring.type - const isLoose = type !== 'HD Key Tree' - return isLoose ? h('.keyring-label.allcaps', this.context.t('loose')) : null - } catch (e) { return } - } - - renderAccountSelector () { - const { actions, useCssTransition, innerStyle, sidebarOpen } = this.props - const { accountSelectorActive, menuItemStyles } = this.state - - return h( - Dropdown, - { - useCssTransition, - style: { - marginLeft: '-185px', - marginTop: '50px', - minWidth: '180px', - overflowY: 'auto', - maxHeight: '300px', - width: '300px', - }, - innerStyle, - isOpen: accountSelectorActive, - onClickOutside: (event) => { - const { classList } = event.target - const isNotToggleElement = !classList.contains(this.accountSelectorToggleClassName) - if (accountSelectorActive && isNotToggleElement) { - this.setState({ accountSelectorActive: false }) - } - }, - }, - [ - ...this.renderAccounts(), - h( - DropdownMenuItem, - { - closeMenu: () => {}, - style: Object.assign( - {}, - menuItemStyles, - ), - onClick: () => actions.showNewAccountPageCreateForm(), - }, - [ - h( - 'i.fa.fa-plus.fa-lg', - { - style: { - marginLeft: '8px', - }, - } - ), - h('span', { - style: { - marginLeft: '14px', - fontFamily: 'DIN OT', - fontSize: '16px', - lineHeight: '23px', - }, - }, this.context.t('createAccount')), - ], - ), - h( - DropdownMenuItem, - { - closeMenu: () => { - if (sidebarOpen) { - actions.hideSidebar() - } - }, - onClick: () => actions.showNewAccountPageImportForm(), - style: Object.assign( - {}, - menuItemStyles, - ), - }, - [ - h( - 'i.fa.fa-download.fa-lg', - { - style: { - marginLeft: '8px', - }, - } - ), - h('span', { - style: { - marginLeft: '20px', - marginBottom: '5px', - fontFamily: 'DIN OT', - fontSize: '16px', - lineHeight: '23px', - }, - }, this.context.t('importAccount')), - ] - ), - ] - ) - } - - renderAccountOptions () { - const { actions, dropdownWrapperStyle, useCssTransition } = this.props - const { optionsMenuActive, menuItemStyles } = this.state - const dropdownMenuItemStyle = { - fontFamily: 'DIN OT', - fontSize: 16, - lineHeight: '24px', - padding: '8px', - } - - return h( - Dropdown, - { - useCssTransition, - style: Object.assign( - { - marginLeft: '-10px', - position: 'absolute', - width: '29vh', // affects both mobile and laptop views - }, - dropdownWrapperStyle, - ), - isOpen: optionsMenuActive, - onClickOutside: (event) => { - const { classList } = event.target - const isNotToggleElement = !classList.contains(this.optionsMenuToggleClassName) - if (optionsMenuActive && isNotToggleElement) { - this.setState({ optionsMenuActive: false }) - } - }, - }, - [ - h( - DropdownMenuItem, - { - closeMenu: () => {}, - onClick: () => { - this.props.actions.showAccountDetailModal() - }, - style: Object.assign( - dropdownMenuItemStyle, - menuItemStyles, - ), - }, - this.context.t('accountDetails'), - ), - h( - DropdownMenuItem, - { - closeMenu: () => {}, - onClick: () => { - const { selected, network } = this.props - const url = genAccountLink(selected, network) - global.platform.openWindow({ url }) - }, - style: Object.assign( - dropdownMenuItemStyle, - menuItemStyles, - ), - }, - this.context.t('etherscanView'), - ), - h( - DropdownMenuItem, - { - closeMenu: () => {}, - onClick: () => { - const { selected } = this.props - copyToClipboard(checksumAddress(selected)) - }, - style: Object.assign( - dropdownMenuItemStyle, - menuItemStyles, - ), - }, - this.context.t('copyAddress'), - ), - h( - DropdownMenuItem, - { - closeMenu: () => {}, - onClick: () => this.props.actions.showExportPrivateKeyModal(), - style: Object.assign( - dropdownMenuItemStyle, - menuItemStyles, - ), - }, - this.context.t('exportPrivateKey'), - ), - h( - DropdownMenuItem, - { - closeMenu: () => {}, - onClick: () => { - actions.hideSidebar() - actions.showAddTokenPage() - }, - style: Object.assign( - dropdownMenuItemStyle, - menuItemStyles, - ), - }, - this.context.t('addToken'), - ), - - ] - ) - } - - render () { - const { style, enableAccountsSelector, enableAccountOptions } = this.props - const { optionsMenuActive, accountSelectorActive } = this.state - - return h( - 'span', - { - style: style, - }, - [ - enableAccountsSelector && h( - 'i.fa.fa-angle-down', - { - style: { - cursor: 'pointer', - }, - onClick: (event) => { - event.stopPropagation() - this.setState({ - accountSelectorActive: !accountSelectorActive, - optionsMenuActive: false, - }) - }, - }, - this.renderAccountSelector(), - ), - enableAccountOptions && h( - 'i.fa.fa-ellipsis-h', - { - style: { - fontSize: '135%', - cursor: 'pointer', - }, - onClick: (event) => { - event.stopPropagation() - this.setState({ - accountSelectorActive: false, - optionsMenuActive: !optionsMenuActive, - }) - }, - }, - this.renderAccountOptions() - ), - ] - ) - } -} - -AccountDropdowns.defaultProps = { - enableAccountsSelector: false, - enableAccountOptions: false, -} - -AccountDropdowns.propTypes = { - identities: PropTypes.objectOf(PropTypes.object), - selected: PropTypes.string, - keyrings: PropTypes.array, - accounts: PropTypes.object, - menuItemStyles: PropTypes.object, - actions: PropTypes.object, - // actions.showAccountDetail: , - useCssTransition: PropTypes.bool, - innerStyle: PropTypes.object, - sidebarOpen: PropTypes.bool, - dropdownWrapperStyle: PropTypes.string, - // actions.showAccountDetailModal: , - network: PropTypes.number, - // actions.showExportPrivateKeyModal: , - style: PropTypes.object, - ticker: PropTypes.string, - enableAccountsSelector: PropTypes.bool, - enableAccountOption: PropTypes.bool, - enableAccountOptions: PropTypes.bool, - t: PropTypes.func, -} - -const mapDispatchToProps = (dispatch) => { - return { - actions: { - hideSidebar: () => dispatch(actions.hideSidebar()), - showConfigPage: () => dispatch(actions.showConfigPage()), - showAccountDetail: (address) => dispatch(actions.showAccountDetail(address)), - showAccountDetailModal: () => { - dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) - }, - showEditAccountModal: (identity) => { - dispatch(actions.showModal({ - name: 'EDIT_ACCOUNT_NAME', - identity, - })) - }, - showNewAccountPageCreateForm: () => dispatch(actions.showNewAccountPage({ form: 'CREATE' })), - showExportPrivateKeyModal: () => { - dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' })) - }, - showAddTokenPage: () => { - dispatch(actions.showAddTokenPage()) - }, - addNewAccount: () => dispatch(actions.addNewAccount()), - showNewAccountPageImportForm: () => dispatch(actions.showNewAccountPage({ form: 'IMPORT' })), - showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), - }, - } -} - -function mapStateToProps (state) { - return { - ticker: state.metamask.ticker, - keyrings: state.metamask.keyrings, - sidebarOpen: state.appState.sidebar.isOpen, - } -} - -AccountDropdowns.contextTypes = { - t: PropTypes.func, -} - -module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDropdowns) - diff --git a/ui/app/components/dropdowns/components/dropdown.js b/ui/app/components/dropdowns/components/dropdown.js deleted file mode 100644 index 149f063a7..000000000 --- a/ui/app/components/dropdowns/components/dropdown.js +++ /dev/null @@ -1,112 +0,0 @@ -const Component = require('react').Component -const PropTypes = require('prop-types') -const h = require('react-hyperscript') -const MenuDroppo = require('../../menu-droppo') -const extend = require('xtend') - -const noop = () => {} - -class Dropdown extends Component { - render () { - const { - containerClassName, - isOpen, - onClickOutside, - style, - innerStyle, - children, - useCssTransition, - } = this.props - - const innerStyleDefaults = extend({ - borderRadius: '4px', - padding: '8px 16px', - background: 'rgba(0, 0, 0, 0.8)', - boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', - }, innerStyle) - - return h( - MenuDroppo, - { - containerClassName, - useCssTransition, - isOpen, - zIndex: 55, - onClickOutside, - style, - innerStyle: innerStyleDefaults, - }, - [ - h( - 'style', - ` - li.dropdown-menu-item:hover { - color:rgb(225, 225, 225); - background-color: rgba(255, 255, 255, 0.05); - border-radius: 4px; - } - li.dropdown-menu-item { color: rgb(185, 185, 185); } - ` - ), - ...children, - ] - ) - } -} - -Dropdown.defaultProps = { - isOpen: false, - onClick: noop, - useCssTransition: false, -} - -Dropdown.propTypes = { - isOpen: PropTypes.bool.isRequired, - onClick: PropTypes.func.isRequired, - children: PropTypes.node, - style: PropTypes.object.isRequired, - onClickOutside: PropTypes.func, - innerStyle: PropTypes.object, - useCssTransition: PropTypes.bool, - containerClassName: PropTypes.string, -} - -class DropdownMenuItem extends Component { - render () { - const { onClick, closeMenu, children, style } = this.props - - return h( - 'li.dropdown-menu-item', - { - onClick: () => { - onClick() - closeMenu() - }, - style: Object.assign({ - listStyle: 'none', - padding: '8px 0px', - fontSize: '18px', - fontStyle: 'normal', - cursor: 'pointer', - display: 'flex', - justifyContent: 'flex-start', - alignItems: 'center', - color: 'white', - }, style), - }, - children - ) - } -} - -DropdownMenuItem.propTypes = { - closeMenu: PropTypes.func.isRequired, - onClick: PropTypes.func.isRequired, - children: PropTypes.node, - style: PropTypes.object, -} - -module.exports = { - Dropdown, - DropdownMenuItem, -} diff --git a/ui/app/components/dropdowns/components/menu.js b/ui/app/components/dropdowns/components/menu.js deleted file mode 100644 index f6d8a139e..000000000 --- a/ui/app/components/dropdowns/components/menu.js +++ /dev/null @@ -1,51 +0,0 @@ -const inherits = require('util').inherits -const Component = require('react').Component -const h = require('react-hyperscript') - -inherits(Menu, Component) -function Menu () { Component.call(this) } - -Menu.prototype.render = function () { - const { className = '', children, isShowing } = this.props - return isShowing - ? h('div', { className: `menu ${className}` }, children) - : h('noscript') -} - -inherits(Item, Component) -function Item () { Component.call(this) } - -Item.prototype.render = function () { - const { - icon, - children, - text, - className = '', - onClick, - } = this.props - const itemClassName = `menu__item ${className} ${onClick ? 'menu__item--clickable' : ''}` - const iconComponent = icon ? h('div.menu__item__icon', [icon]) : null - const textComponent = text ? h('div.menu__item__text', text) : null - - return children - ? h('div', { className: itemClassName, onClick }, children) - : h('div.menu__item', { className: itemClassName, onClick }, [ iconComponent, textComponent ] - .filter(d => Boolean(d)) - ) -} - -inherits(Divider, Component) -function Divider () { Component.call(this) } - -Divider.prototype.render = function () { - return h('div.menu__divider') -} - -inherits(CloseArea, Component) -function CloseArea () { Component.call(this) } - -CloseArea.prototype.render = function () { - return h('div.menu__close-area', { onClick: this.props.onClick }) -} - -module.exports = { Menu, Item, Divider, CloseArea } diff --git a/ui/app/components/dropdowns/components/network-dropdown-icon.js b/ui/app/components/dropdowns/components/network-dropdown-icon.js deleted file mode 100644 index d4a2c2ff7..000000000 --- a/ui/app/components/dropdowns/components/network-dropdown-icon.js +++ /dev/null @@ -1,47 +0,0 @@ -const inherits = require('util').inherits -const Component = require('react').Component -const h = require('react-hyperscript') - - -inherits(NetworkDropdownIcon, Component) -module.exports = NetworkDropdownIcon - -function NetworkDropdownIcon () { - Component.call(this) -} - -NetworkDropdownIcon.prototype.render = function () { - const { - backgroundColor, - isSelected, - innerBorder = 'none', - diameter = '12', - loading, - } = this.props - - return loading - ? h('span.pointer.network-indicator', { - style: { - display: 'flex', - alignItems: 'center', - flexDirection: 'row', - }, - }, [ - h('img', { - style: { - width: '27px', - }, - src: 'images/loading.svg', - }), - ]) - : h(`.menu-icon-circle${isSelected ? '--active' : ''}`, {}, - h('div', { - style: { - background: backgroundColor, - border: innerBorder, - height: `${diameter}px`, - width: `${diameter}px`, - }, - }) - ) -} diff --git a/ui/app/components/dropdowns/index.js b/ui/app/components/dropdowns/index.js deleted file mode 100644 index 605507058..000000000 --- a/ui/app/components/dropdowns/index.js +++ /dev/null @@ -1,11 +0,0 @@ -// Reusable Dropdown Components -// TODO: Refactor into separate components -const Dropdown = require('./components/dropdown').Dropdown - -// App-Specific Instances -const NetworkDropdown = require('./network-dropdown').default - -module.exports = { - NetworkDropdown, - Dropdown, -} diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js deleted file mode 100644 index 90355a97c..000000000 --- a/ui/app/components/dropdowns/network-dropdown.js +++ /dev/null @@ -1,378 +0,0 @@ -const Component = require('react').Component -const PropTypes = require('prop-types') -const h = require('react-hyperscript') -const inherits = require('util').inherits -const connect = require('react-redux').connect -const { withRouter } = require('react-router-dom') -const { compose } = require('recompose') -const actions = require('../../actions') -const Dropdown = require('./components/dropdown').Dropdown -const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem -const NetworkDropdownIcon = require('./components/network-dropdown-icon') -const R = require('ramda') -const { SETTINGS_ROUTE } = require('../../routes') - -// classes from nodes of the toggle element. -const notToggleElementClassnames = [ - 'menu-icon', - 'network-name', - 'network-indicator', - 'network-caret', - 'network-component', -] - -function mapStateToProps (state) { - return { - provider: state.metamask.provider, - frequentRpcListDetail: state.metamask.frequentRpcListDetail || [], - networkDropdownOpen: state.appState.networkDropdownOpen, - network: state.metamask.network, - } -} - -function mapDispatchToProps (dispatch) { - return { - hideModal: () => { - dispatch(actions.hideModal()) - }, - setProviderType: (type) => { - dispatch(actions.setProviderType(type)) - }, - setDefaultRpcTarget: type => { - dispatch(actions.setDefaultRpcTarget(type)) - }, - setRpcTarget: (target, network, ticker, nickname) => { - dispatch(actions.setRpcTarget(target, network, ticker, nickname)) - }, - delRpcTarget: (target) => { - dispatch(actions.delRpcTarget(target)) - }, - showNetworkDropdown: () => dispatch(actions.showNetworkDropdown()), - hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()), - } -} - - -inherits(NetworkDropdown, Component) -function NetworkDropdown () { - Component.call(this) -} - -NetworkDropdown.contextTypes = { - t: PropTypes.func, - metricsEvent: PropTypes.func, -} - -module.exports = compose( - withRouter, - connect(mapStateToProps, mapDispatchToProps) -)(NetworkDropdown) - - -// TODO: specify default props and proptypes -NetworkDropdown.prototype.render = function () { - const props = this.props - const { provider: { type: providerType, rpcTarget: activeNetwork } } = props - const rpcListDetail = props.frequentRpcListDetail - const isOpen = this.props.networkDropdownOpen - const dropdownMenuItemStyle = { - fontSize: '16px', - lineHeight: '20px', - padding: '12px 0', - } - - return h(Dropdown, { - isOpen, - onClickOutside: (event) => { - const { classList } = event.target - const isInClassList = className => classList.contains(className) - const notToggleElementIndex = R.findIndex(isInClassList)(notToggleElementClassnames) - - if (notToggleElementIndex === -1) { - this.props.hideNetworkDropdown() - } - }, - containerClassName: 'network-droppo', - zIndex: 55, - style: { - position: 'absolute', - top: '58px', - width: '309px', - zIndex: '55px', - }, - innerStyle: { - padding: '18px 8px', - }, - }, [ - - h('div.network-dropdown-header', {}, [ - h('div.network-dropdown-title', {}, this.context.t('networks')), - - h('div.network-dropdown-divider'), - - h('div.network-dropdown-content', - {}, - this.context.t('defaultNetwork') - ), - ]), - - h( - DropdownMenuItem, - { - key: 'main', - closeMenu: () => this.props.hideNetworkDropdown(), - onClick: () => this.handleClick('mainnet'), - style: { ...dropdownMenuItemStyle, borderColor: '#038789' }, - }, - [ - providerType === 'mainnet' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), - h(NetworkDropdownIcon, { - backgroundColor: '#29B6AF', // $java - isSelected: providerType === 'mainnet', - }), - h('span.network-name-item', { - style: { - color: providerType === 'mainnet' ? '#ffffff' : '#9b9b9b', - }, - }, this.context.t('mainnet')), - ] - ), - - h( - DropdownMenuItem, - { - key: 'ropsten', - closeMenu: () => this.props.hideNetworkDropdown(), - onClick: () => this.handleClick('ropsten'), - style: dropdownMenuItemStyle, - }, - [ - providerType === 'ropsten' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), - h(NetworkDropdownIcon, { - backgroundColor: '#ff4a8d', // $wild-strawberry - isSelected: providerType === 'ropsten', - }), - h('span.network-name-item', { - style: { - color: providerType === 'ropsten' ? '#ffffff' : '#9b9b9b', - }, - }, this.context.t('ropsten')), - ] - ), - - h( - DropdownMenuItem, - { - key: 'kovan', - closeMenu: () => this.props.hideNetworkDropdown(), - onClick: () => this.handleClick('kovan'), - style: dropdownMenuItemStyle, - }, - [ - providerType === 'kovan' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), - h(NetworkDropdownIcon, { - backgroundColor: '#7057ff', // $cornflower-blue - isSelected: providerType === 'kovan', - }), - h('span.network-name-item', { - style: { - color: providerType === 'kovan' ? '#ffffff' : '#9b9b9b', - }, - }, this.context.t('kovan')), - ] - ), - - h( - DropdownMenuItem, - { - key: 'rinkeby', - closeMenu: () => this.props.hideNetworkDropdown(), - onClick: () => this.handleClick('rinkeby'), - style: dropdownMenuItemStyle, - }, - [ - providerType === 'rinkeby' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), - h(NetworkDropdownIcon, { - backgroundColor: '#f6c343', // $saffron - isSelected: providerType === 'rinkeby', - }), - h('span.network-name-item', { - style: { - color: providerType === 'rinkeby' ? '#ffffff' : '#9b9b9b', - }, - }, this.context.t('rinkeby')), - ] - ), - - h( - DropdownMenuItem, - { - key: 'default', - closeMenu: () => this.props.hideNetworkDropdown(), - onClick: () => this.handleClick('localhost'), - style: dropdownMenuItemStyle, - }, - [ - providerType === 'localhost' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), - h(NetworkDropdownIcon, { - isSelected: providerType === 'localhost', - innerBorder: '1px solid #9b9b9b', - }), - h('span.network-name-item', { - style: { - color: providerType === 'localhost' ? '#ffffff' : '#9b9b9b', - }, - }, this.context.t('localhost')), - ] - ), - - this.renderCustomOption(props.provider), - this.renderCommonRpc(rpcListDetail, props.provider), - - h( - DropdownMenuItem, - { - closeMenu: () => this.props.hideNetworkDropdown(), - onClick: () => this.props.history.push(SETTINGS_ROUTE), - style: dropdownMenuItemStyle, - }, - [ - activeNetwork === 'custom' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), - h(NetworkDropdownIcon, { - isSelected: activeNetwork === 'custom', - innerBorder: '1px solid #9b9b9b', - }), - h('span.network-name-item', { - style: { - color: activeNetwork === 'custom' ? '#ffffff' : '#9b9b9b', - }, - }, this.context.t('customRPC')), - ] - ), - - ]) -} - -NetworkDropdown.prototype.handleClick = function (newProviderType) { - const { provider: { type: providerType }, setProviderType } = this.props - const { metricsEvent } = this.context - - metricsEvent({ - eventOpts: { - category: 'Navigation', - action: 'Home', - name: 'Switched Networks', - }, - customVariables: { - fromNetwork: providerType, - toNetwork: newProviderType, - }, - }) - setProviderType(newProviderType) -} - -NetworkDropdown.prototype.getNetworkName = function () { - const { provider } = this.props - const providerName = provider.type - - let name - - if (providerName === 'mainnet') { - name = this.context.t('mainnet') - } else if (providerName === 'ropsten') { - name = this.context.t('ropsten') - } else if (providerName === 'kovan') { - name = this.context.t('kovan') - } else if (providerName === 'rinkeby') { - name = this.context.t('rinkeby') - } else { - name = provider.nickname || this.context.t('unknownNetwork') - } - - return name -} - -NetworkDropdown.prototype.renderCommonRpc = function (rpcListDetail, provider) { - const props = this.props - const reversedRpcListDetail = rpcListDetail.slice().reverse() - - return reversedRpcListDetail.map((entry) => { - const rpc = entry.rpcUrl - const ticker = entry.ticker || 'ETH' - const nickname = entry.nickname || '' - const currentRpcTarget = provider.type === 'rpc' && rpc === provider.rpcTarget - - if ((rpc === 'http://localhost:8545') || currentRpcTarget) { - return null - } else { - const chainId = entry.chainId - return h( - DropdownMenuItem, - { - key: `common${rpc}`, - closeMenu: () => this.props.hideNetworkDropdown(), - onClick: () => props.setRpcTarget(rpc, chainId, ticker, nickname), - style: { - fontSize: '16px', - lineHeight: '20px', - padding: '12px 0', - }, - }, - [ - currentRpcTarget ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), - h('i.fa.fa-question-circle.fa-med.menu-icon-circle'), - h('span.network-name-item', { - style: { - color: currentRpcTarget ? '#ffffff' : '#9b9b9b', - }, - }, nickname || rpc), - h('i.fa.fa-times.delete', - { - onClick: (e) => { - e.stopPropagation() - props.delRpcTarget(rpc) - }, - }), - ] - ) - } - }) -} - -NetworkDropdown.prototype.renderCustomOption = function (provider) { - const { rpcTarget, type, ticker, nickname } = provider - const props = this.props - const network = props.network - - if (type !== 'rpc') return null - - switch (rpcTarget) { - - case 'http://localhost:8545': - return null - - default: - return h( - DropdownMenuItem, - { - key: rpcTarget, - onClick: () => props.setRpcTarget(rpcTarget, network, ticker, nickname), - closeMenu: () => this.props.hideNetworkDropdown(), - style: { - fontSize: '16px', - lineHeight: '20px', - padding: '12px 0', - }, - }, - [ - h('i.fa.fa-check'), - h('i.fa.fa-question-circle.fa-med.menu-icon-circle'), - h('span.network-name-item', { - style: { - color: '#ffffff', - }, - }, nickname || rpcTarget), - ] - ) - } -} diff --git a/ui/app/components/dropdowns/simple-dropdown.js b/ui/app/components/dropdowns/simple-dropdown.js deleted file mode 100644 index bba088ed1..000000000 --- a/ui/app/components/dropdowns/simple-dropdown.js +++ /dev/null @@ -1,92 +0,0 @@ -const { Component } = require('react') -const PropTypes = require('prop-types') -const h = require('react-hyperscript') -const classnames = require('classnames') -const R = require('ramda') - -class SimpleDropdown extends Component { - constructor (props) { - super(props) - this.state = { - isOpen: false, - } - } - - getDisplayValue () { - const { selectedOption, options } = this.props - const matchesOption = option => option.value === selectedOption - const matchingOption = R.find(matchesOption)(options) - return matchingOption - ? matchingOption.displayValue || matchingOption.value - : selectedOption - } - - handleClose () { - this.setState({ isOpen: false }) - } - - toggleOpen () { - const { isOpen } = this.state - this.setState({ isOpen: !isOpen }) - } - - renderOptions () { - const { options, onSelect, selectedOption } = this.props - - return h('div', [ - h('div.simple-dropdown__close-area', { - onClick: event => { - event.stopPropagation() - this.handleClose() - }, - }), - h('div.simple-dropdown__options', [ - ...options.map(option => { - return h( - 'div.simple-dropdown__option', - { - className: classnames({ - 'simple-dropdown__option--selected': option.value === selectedOption, - }), - key: option.value, - onClick: () => { - if (option.value !== selectedOption) { - onSelect(option.value) - } - - this.handleClose() - }, - }, - option.displayValue || option.value, - ) - }), - ]), - ]) - } - - render () { - const { placeholder } = this.props - const { isOpen } = this.state - - return h( - 'div.simple-dropdown', - { - onClick: () => this.toggleOpen(), - }, - [ - h('div.simple-dropdown__selected', this.getDisplayValue() || placeholder || 'Select'), - h('i.fa.fa-caret-down.fa-lg.simple-dropdown__caret'), - isOpen && this.renderOptions(), - ] - ) - } -} - -SimpleDropdown.propTypes = { - options: PropTypes.array.isRequired, - placeholder: PropTypes.string, - onSelect: PropTypes.func, - selectedOption: PropTypes.string, -} - -module.exports = SimpleDropdown diff --git a/ui/app/components/dropdowns/tests/dropdown.test.js b/ui/app/components/dropdowns/tests/dropdown.test.js deleted file mode 100644 index 2b026589a..000000000 --- a/ui/app/components/dropdowns/tests/dropdown.test.js +++ /dev/null @@ -1,37 +0,0 @@ -import React from 'react' -import assert from 'assert' -import sinon from 'sinon' -import { shallow } from 'enzyme' -import { DropdownMenuItem } from '../components/dropdown.js' - -describe('', () => { - let wrapper - const onClickSpy = sinon.spy() - const closeMenuSpy = sinon.spy() - - beforeEach(() => { - wrapper = shallow( - <DropdownMenuItem - onClick = {onClickSpy} - style = {{test: 'style'}} - closeMenu = {closeMenuSpy} - > - </DropdownMenuItem> - ) - }) - - it('renders li with dropdown-menu-item class', () => { - assert.equal(wrapper.find('li.dropdown-menu-item').length, 1) - }) - - it('adds style based on props passed', () => { - assert.equal(wrapper.prop('style').test, 'style') - }) - - it('simulates click event and calls onClick and closeMenu', () => { - wrapper.prop('onClick')() - assert.equal(onClickSpy.callCount, 1) - assert.equal(closeMenuSpy.callCount, 1) - }) - -}) diff --git a/ui/app/components/dropdowns/tests/menu.test.js b/ui/app/components/dropdowns/tests/menu.test.js deleted file mode 100644 index 9f5f13f00..000000000 --- a/ui/app/components/dropdowns/tests/menu.test.js +++ /dev/null @@ -1,87 +0,0 @@ -import React from 'react' -import assert from 'assert' -import sinon from 'sinon' -import { shallow } from 'enzyme' -import { Menu, Item, Divider, CloseArea } from '../components/menu' - -describe('Dropdown Menu Components', () => { - - describe('Menu', () => { - let wrapper - - beforeEach(() => { - wrapper = shallow( - <Menu className = {'Test Class'} isShowing = {true}/> - ) - }) - - it('adds prop className to menu', () => { - assert.equal(wrapper.find('.menu').prop('className'), 'menu Test Class') - }) - - }) - - describe('Item', () => { - let wrapper - - const onClickSpy = sinon.spy() - - beforeEach(() => { - wrapper = shallow( - <Item - icon = {'test icon'} - text = {'test text'} - className = {'test className'} - onClick = {onClickSpy} - /> - ) - }) - - it('add className based on props', () => { - assert.equal(wrapper.find('.menu__item').prop('className'), 'menu__item menu__item test className menu__item--clickable') - }) - - it('simulates onClick called', () => { - wrapper.find('.menu__item').prop('onClick')() - assert.equal(onClickSpy.callCount, 1) - }) - - it('adds icon based on icon props', () => { - assert.equal(wrapper.find('.menu__item__icon').text(), 'test icon') - }) - - it('adds html text based on text props', () => { - assert.equal(wrapper.find('.menu__item__text').text(), 'test text') - }) - }) - - describe('Divider', () => { - let wrapper - - before(() => { - wrapper = shallow(<Divider />) - }) - - it('renders menu divider', () => { - assert.equal(wrapper.find('.menu__divider').length, 1) - }) - }) - - describe('CloseArea', () => { - let wrapper - - const onClickSpy = sinon.spy() - - beforeEach(() => { - wrapper = shallow(<CloseArea - onClick = {onClickSpy} - />) - }) - - it('simulates click', () => { - wrapper.prop('onClick')() - assert.equal(onClickSpy.callCount, 1) - }) - }) - -}) diff --git a/ui/app/components/dropdowns/tests/network-dropdown-icon.test.js b/ui/app/components/dropdowns/tests/network-dropdown-icon.test.js deleted file mode 100644 index 67b192c11..000000000 --- a/ui/app/components/dropdowns/tests/network-dropdown-icon.test.js +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react' -import assert from 'assert' -import { shallow } from 'enzyme' -import NetworkDropdownIcon from '../components/network-dropdown-icon' - -describe('Network Dropdown Icon', () => { - let wrapper - - beforeEach(() => { - wrapper = shallow(<NetworkDropdownIcon - backgroundColor = {'red'} - isSelected = {false} - innerBorder = {'none'} - diameter = {'12'} - />) - }) - - it('adds style props based on props', () => { - const styleProp = wrapper.find('.menu-icon-circle').children().prop('style') - assert.equal(styleProp.background, 'red') - assert.equal(styleProp.border, 'none') - assert.equal(styleProp.height, '12px') - assert.equal(styleProp.width, '12px') - }) -}) diff --git a/ui/app/components/dropdowns/tests/network-dropdown.test.js b/ui/app/components/dropdowns/tests/network-dropdown.test.js deleted file mode 100644 index 88ad56851..000000000 --- a/ui/app/components/dropdowns/tests/network-dropdown.test.js +++ /dev/null @@ -1,97 +0,0 @@ -import React from 'react' -import assert from 'assert' -import { createMockStore } from 'redux-test-utils' -import { mountWithRouter } from '../../../../../test/lib/render-helpers' -import NetworkDropdown from '../network-dropdown' -import { DropdownMenuItem } from '../components/dropdown' -import NetworkDropdownIcon from '../components/network-dropdown-icon' - -describe('Network Dropdown', () => { - let wrapper - - describe('NetworkDropdown in appState in false', () => { - const mockState = { - metamask: { - provider: { - type: 'test', - }, - }, - appState: { - networkDropdown: false, - }, - } - - const store = createMockStore(mockState) - - beforeEach(() => { - wrapper = mountWithRouter( - <NetworkDropdown store={store} /> - ) - }) - - it('checks for network droppo class', () => { - assert.equal(wrapper.find('.network-droppo').length, 1) - }) - - it('renders only one child when networkDropdown is false in state', () => { - assert.equal(wrapper.children().length, 1) - }) - - }) - - describe('NetworkDropdown in appState is true', () => { - const mockState = { - metamask: { - provider: { - 'type': 'test', - }, - frequentRpcListDetail: [ - { rpcUrl: 'http://localhost:7545' }, - ], - }, - appState: { - 'networkDropdownOpen': true, - }, - } - const store = createMockStore(mockState) - - beforeEach(() => { - wrapper = mountWithRouter( - <NetworkDropdown store={store}/>, - ) - }) - - it('renders 7 DropDownMenuItems ', () => { - assert.equal(wrapper.find(DropdownMenuItem).length, 7) - }) - - it('checks background color for first NetworkDropdownIcon', () => { - assert.equal(wrapper.find(NetworkDropdownIcon).at(0).prop('backgroundColor'), '#29B6AF') // Main Ethereum Network Teal - }) - - it('checks background color for second NetworkDropdownIcon', () => { - assert.equal(wrapper.find(NetworkDropdownIcon).at(1).prop('backgroundColor'), '#ff4a8d') // Ropsten Red - }) - - it('checks background color for third NetworkDropdownIcon', () => { - assert.equal(wrapper.find(NetworkDropdownIcon).at(2).prop('backgroundColor'), '#7057ff') // Kovan Purple - }) - - it('checks background color for fourth NetworkDropdownIcon', () => { - assert.equal(wrapper.find(NetworkDropdownIcon).at(3).prop('backgroundColor'), '#f6c343') // Rinkeby Yellow - }) - - it('checks background color for fifth NetworkDropdownIcon', () => { - assert.equal(wrapper.find(NetworkDropdownIcon).at(4).prop('innerBorder'), '1px solid #9b9b9b') - }) - - it('checks dropdown for frequestRPCList from state ', () => { - assert.equal(wrapper.find(DropdownMenuItem).at(5).text(), '✓http://localhost:7545') - }) - - it('checks background color for sixth NetworkDropdownIcon', () => { - assert.equal(wrapper.find(NetworkDropdownIcon).at(5).prop('innerBorder'), '1px solid #9b9b9b') - }) - - }) -}) diff --git a/ui/app/components/dropdowns/token-menu-dropdown.js b/ui/app/components/dropdowns/token-menu-dropdown.js deleted file mode 100644 index 8a072b1bc..000000000 --- a/ui/app/components/dropdowns/token-menu-dropdown.js +++ /dev/null @@ -1,68 +0,0 @@ -const Component = require('react').Component -const PropTypes = require('prop-types') -const h = require('react-hyperscript') -const inherits = require('util').inherits -const connect = require('react-redux').connect -const actions = require('../../actions') -const genAccountLink = require('etherscan-link').createAccountLink -const { Menu, Item, CloseArea } = require('./components/menu') - -TokenMenuDropdown.contextTypes = { - t: PropTypes.func, -} - -module.exports = connect(mapStateToProps, mapDispatchToProps)(TokenMenuDropdown) - -function mapStateToProps (state) { - return { - network: state.metamask.network, - } -} - -function mapDispatchToProps (dispatch) { - return { - showHideTokenConfirmationModal: (token) => { - dispatch(actions.showModal({ name: 'HIDE_TOKEN_CONFIRMATION', token })) - }, - } -} - - -inherits(TokenMenuDropdown, Component) -function TokenMenuDropdown () { - Component.call(this) - - this.onClose = this.onClose.bind(this) -} - -TokenMenuDropdown.prototype.onClose = function (e) { - e.stopPropagation() - this.props.onClose() -} - -TokenMenuDropdown.prototype.render = function () { - const { showHideTokenConfirmationModal } = this.props - - return h(Menu, { className: 'token-menu-dropdown', isShowing: true }, [ - h(CloseArea, { - onClick: this.onClose, - }), - h(Item, { - onClick: (e) => { - e.stopPropagation() - showHideTokenConfirmationModal(this.props.token) - this.props.onClose() - }, - text: this.context.t('hideToken'), - }), - h(Item, { - onClick: (e) => { - e.stopPropagation() - const url = genAccountLink(this.props.token.address, this.props.network) - global.platform.openWindow({ url }) - this.props.onClose() - }, - text: this.context.t('viewOnEtherscan'), - }), - ]) -} |