aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/components/dropdowns
diff options
context:
space:
mode:
authorsdtsui <szehungdanieltsui@gmail.com>2017-08-14 14:31:49 +0800
committersdtsui <szehungdanieltsui@gmail.com>2017-08-14 14:31:49 +0800
commit88665ba150c74955ef11a1b3fbc0f158a1c321de (patch)
treed86b7ae10f71288d02afd2c8c2db5bbf6ec00fd6 /ui/app/components/dropdowns
parentb900da885ebb5b5581a670d9ca85761cecaa648f (diff)
downloadtangerine-wallet-browser-88665ba150c74955ef11a1b3fbc0f158a1c321de.tar.gz
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.js28
-rw-r--r--ui/app/components/dropdowns/account-selection-dropdown.js28
-rw-r--r--ui/app/components/dropdowns/components/account-dropdowns.js318
-rw-r--r--ui/app/components/dropdowns/components/dropdown.js95
-rw-r--r--ui/app/components/dropdowns/index.js18
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