diff options
author | sdtsui <szehungdanieltsui@gmail.com> | 2017-08-14 14:31:49 +0800 |
---|---|---|
committer | sdtsui <szehungdanieltsui@gmail.com> | 2017-08-14 14:31:49 +0800 |
commit | 88665ba150c74955ef11a1b3fbc0f158a1c321de (patch) | |
tree | d86b7ae10f71288d02afd2c8c2db5bbf6ec00fd6 /ui/app/components/dropdowns | |
parent | b900da885ebb5b5581a670d9ca85761cecaa648f (diff) | |
download | tangerine-wallet-browser-88665ba150c74955ef11a1b3fbc0f158a1c321de.tar tangerine-wallet-browser-88665ba150c74955ef11a1b3fbc0f158a1c321de.tar.gz tangerine-wallet-browser-88665ba150c74955ef11a1b3fbc0f158a1c321de.tar.bz2 tangerine-wallet-browser-88665ba150c74955ef11a1b3fbc0f158a1c321de.tar.lz tangerine-wallet-browser-88665ba150c74955ef11a1b3fbc0f158a1c321de.tar.xz tangerine-wallet-browser-88665ba150c74955ef11a1b3fbc0f158a1c321de.tar.zst tangerine-wallet-browser-88665ba150c74955ef11a1b3fbc0f158a1c321de.zip |
Extract dropdown component into components/dropdowns, hook up to app
Diffstat (limited to 'ui/app/components/dropdowns')
-rw-r--r-- | ui/app/components/dropdowns/account-options-dropdown.js | 28 | ||||
-rw-r--r-- | ui/app/components/dropdowns/account-selection-dropdown.js | 28 | ||||
-rw-r--r-- | ui/app/components/dropdowns/components/account-dropdowns.js | 318 | ||||
-rw-r--r-- | ui/app/components/dropdowns/components/dropdown.js | 95 | ||||
-rw-r--r-- | ui/app/components/dropdowns/index.js | 18 |
5 files changed, 479 insertions, 8 deletions
diff --git a/ui/app/components/dropdowns/account-options-dropdown.js b/ui/app/components/dropdowns/account-options-dropdown.js new file mode 100644 index 000000000..7d7188ec4 --- /dev/null +++ b/ui/app/components/dropdowns/account-options-dropdown.js @@ -0,0 +1,28 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const AccountDropdowns = require('./components/account-dropdowns') + +inherits(AccountOptionsDropdown, Component) +function AccountOptionsDropdown () { + Component.call(this) +} + +module.exports = AccountOptionsDropdown + +// TODO: specify default props and proptypes +// TODO: hook up to state, connect to redux to clean up API +AccountOptionsDropdown.prototype.render = function () { + const { selected, network, identities, style, dropdownWrapperStyle, menuItemStyles } = this.props + + return h(AccountDropdowns, { + enableAccountOptions: true, + enableAccountsSelector: false, + selected: selectedAddress, + network, + identities, + style: !!style ? style : {}, + dropdownWrapperStyle: !!dropdownWrapperStyle ? dropdownWrapperStyle : {}, + menuItemStyles: !!menuItemStyles ? menuItemStyles : {}, + }, []) +} diff --git a/ui/app/components/dropdowns/account-selection-dropdown.js b/ui/app/components/dropdowns/account-selection-dropdown.js new file mode 100644 index 000000000..ccb73bde7 --- /dev/null +++ b/ui/app/components/dropdowns/account-selection-dropdown.js @@ -0,0 +1,28 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const AccountDropdowns = require('./components/account-dropdowns') + +inherits(AccountSelectionDropdown, Component) +function AccountSelectionDropdown () { + Component.call(this) +} + +module.exports = AccountSelectionDropdown + +// TODO: specify default props and proptypes +// TODO: hook up to state, connect to redux to clean up API +AccountSelectionDropdown.prototype.render = function () { + const { selected, network, identities, style, dropdownWrapperStyle, menuItemStyles } = this.props + + return h(AccountDropdowns, { + enableAccountOptions: false, + enableAccountsSelector: true, + selected: selectedAddress, + network, + identities, + style: !!style ? style : {}, + dropdownWrapperStyle: !!dropdownWrapperStyle ? dropdownWrapperStyle : {}, + menuItemStyles: !!menuItemStyles ? menuItemStyles : {}, + }, []) +} diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js new file mode 100644 index 000000000..ee41829c9 --- /dev/null +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -0,0 +1,318 @@ +const Component = require('react').Component +const PropTypes = require('react').PropTypes +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 +const Identicon = require('../../identicon') +const ethUtil = require('ethereumjs-util') +const copyToClipboard = require('copy-to-clipboard') + +class AccountDropdowns extends Component { + constructor (props) { + super(props) + this.state = { + accountSelectorActive: false, + optionsMenuActive: false, + } + this.accountSelectorToggleClassName = 'accounts-selector' + this.optionsMenuToggleClassName = 'fa-ellipsis-h' + } + + renderAccounts () { + const { identities, selected, menuItemStyles, dropdownWrapperStyle } = this.props + + return Object.keys(identities).map((key, index) => { + const identity = identities[key] + const isSelected = identity.address === selected + + return h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + this.props.actions.showAccountDetail(identity.address) + }, + style: Object.assign( + { + marginTop: index === 0 ? '5px' : '', + fontSize: '24px', + }, + menuItemStyles, + ), + }, + [ + h( + Identicon, + { + address: identity.address, + diameter: 32, + style: { + marginLeft: '10px', + }, + }, + ), + h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, identity.name || ''), + h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, isSelected ? h('.check', '✓') : null), + ] + ) + }) + } + + renderAccountSelector () { + const { actions, dropdownWrapperStyle } = this.props + const { accountSelectorActive, menuItemStyles } = this.state + + return h( + Dropdown, + { + useCssTransition: true, // Hardcoded because account selector is temporarily in app-header + style: { + marginLeft: '-238px', + marginTop: '38px', + minWidth: '180px', + overflowY: 'auto', + maxHeight: '300px', + width: '300px', + }, + innerStyle: { + padding: '8px 25px', + }, + 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: () => {}, + onClick: () => actions.addNewAccount(), + style: Object.assign( + {}, + menuItemStyles, + ), + }, + [ + h( + Identicon, + { + style: { + marginLeft: '10px', + }, + diameter: 32, + }, + ), + h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, 'Create Account'), + ], + ), + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => actions.showImportPage(), + style: Object.assign( + {}, + menuItemStyles, + ), + }, + [ + h( + Identicon, + { + style: { + marginLeft: '10px', + }, + diameter: 32, + }, + ), + h('span', { + style: { + marginLeft: '20px', + fontSize: '24px', + marginBottom: '5px', + }, + }, 'Import Account'), + ] + ), + ] + ) + } + + renderAccountOptions () { + const { actions, dropdownWrapperStyle } = this.props + const { optionsMenuActive, menuItemStyles } = this.state + + return h( + Dropdown, + { + style: Object.assign( + { + marginLeft: '-10px', + position: 'absolute', + width: '29vh', // affects both mobile and laptop views + }, + dropdownWrapperStyle, + ), + isOpen: optionsMenuActive, + onClickOutside: () => { + const { classList } = event.target + const isNotToggleElement = !classList.contains(this.optionsMenuToggleClassName) + if (optionsMenuActive && isNotToggleElement) { + this.setState({ optionsMenuActive: false }) + } + }, + }, + [ + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + const { selected, network } = this.props + const url = genAccountLink(selected, network) + global.platform.openWindow({ url }) + }, + style: Object.assign( + {}, + menuItemStyles, + ), + }, + 'View account on Etherscan', + ), + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + const { selected, identities } = this.props + var identity = identities[selected] + actions.showQrView(selected, identity ? identity.name : '') + }, + style: Object.assign( + {}, + menuItemStyles, + ), + }, + 'Show QR Code', + ), + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + const { selected } = this.props + const checkSumAddress = selected && ethUtil.toChecksumAddress(selected) + copyToClipboard(checkSumAddress) + }, + style: Object.assign( + {}, + menuItemStyles, + ), + }, + 'Copy Address to clipboard', + ), + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + actions.requestAccountExport() + }, + style: Object.assign( + {}, + menuItemStyles, + ), + }, + 'Export Private Key', + ), + ] + ) + } + + render () { + const { style, enableAccountsSelector, enableAccountOptions, dropdownWrapperStyle } = this.props + const { optionsMenuActive, accountSelectorActive } = this.state + + return h( + 'span', + { + style: style, + }, + [ + enableAccountsSelector && h( + 'i.fa.fa-angle-down', + // 'div.cursor-pointer.color-orange.accounts-selector', + { + style: { + // fontSize: '135%', + // background: 'url(images/switch_acc.svg) white center center no-repeat', + // height: '25px', + // width: '25px', + // transform: 'scale(0.75)', + // marginRight: '3px', + }, + onClick: (event) => { + event.stopPropagation() + this.setState({ + accountSelectorActive: !accountSelectorActive, + optionsMenuActive: false, + }) + }, + }, + this.renderAccountSelector(), + ), + enableAccountOptions && h( + 'i.fa.fa-ellipsis-h', + { + style: { + fontSize: '135%', + }, + 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, // TODO: refactor to be more explicit: selectedAddress +} + +const mapDispatchToProps = (dispatch) => { + return { + actions: { + showConfigPage: () => dispatch(actions.showConfigPage()), + requestAccountExport: () => dispatch(actions.requestExportAccount()), + showAccountDetail: (address) => dispatch(actions.showAccountDetail(address)), + addNewAccount: () => dispatch(actions.addNewAccount()), + showImportPage: () => dispatch(actions.showImportPage()), + showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), + }, + } +} + +module.exports = connect(null, mapDispatchToProps)(AccountDropdowns) + diff --git a/ui/app/components/dropdowns/components/dropdown.js b/ui/app/components/dropdowns/components/dropdown.js new file mode 100644 index 000000000..1f35f0c70 --- /dev/null +++ b/ui/app/components/dropdowns/components/dropdown.js @@ -0,0 +1,95 @@ +const Component = require('react').Component +const PropTypes = require('react').PropTypes +const h = require('react-hyperscript') +const MenuDroppo = require('../../menu-droppo') +const extend = require('xtend') + +const noop = () => {} + +class Dropdown extends Component { + render () { + const { 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, + { + useCssTransition, + isOpen, + zIndex: 30, + onClickOutside, + style, + innerStyle: innerStyleDefaults, + }, + [ + h( + 'style', + ` + li.dropdown-menu-item:hover { color:rgb(225, 225, 225); } + 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, +} + +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', + fontFamily: 'Montserrat Regular', + 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, +} + +module.exports = { + Dropdown, + DropdownMenuItem, +} diff --git a/ui/app/components/dropdowns/index.js b/ui/app/components/dropdowns/index.js index 6723a2048..d21c795f5 100644 --- a/ui/app/components/dropdowns/index.js +++ b/ui/app/components/dropdowns/index.js @@ -1,16 +1,18 @@ // Reusable Dropdown Components -// const Dropdown = require('./dropdown') //TODO: Refactor into separate components -// const AccountDropdowns = require('./account-dropdowns') +//TODO: Refactor into separate components +const Dropdown = require('./components/dropdown').Dropdown +const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem +const AccountDropdowns = require('./components/account-dropdowns') // App-Specific Instances -// const AccountSelectionDropdown = require('./account-selection-dropdown') -// const AccountOptionsDropdown = require('./account-options-dropdown') +const AccountSelectionDropdown = require('./account-selection-dropdown') +const AccountOptionsDropdown = require('./account-options-dropdown') const NetworkDropdown = require('./network-dropdown').default module.exports = { - // AccountSelectionDropdown, - // AccountOptionsDropdown, + AccountSelectionDropdown, + AccountOptionsDropdown, NetworkDropdown, - // Dropdown, - // AccountDropdowns, + Dropdown, + AccountDropdowns, }
\ No newline at end of file |