From 8c4d58aa4508e3d54c3f69847347e78d09c63b97 Mon Sep 17 00:00:00 2001 From: Bruno Date: Sun, 10 Jun 2018 03:52:32 -0400 Subject: initial trezor support --- ui/app/actions.js | 42 ++++ ui/app/components/account-menu/index.js | 9 + .../pages/create-account/connect-hardware.js | 234 +++++++++++++++++++++ ui/app/components/pages/create-account/index.js | 25 ++- .../components/pages/create-account/new-account.js | 2 + ui/app/css/itcss/components/new-account.scss | 105 ++++++++- ui/app/routes.js | 2 + 7 files changed, 413 insertions(+), 6 deletions(-) create mode 100644 ui/app/components/pages/create-account/connect-hardware.js (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index 1edf692b6..758696203 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -79,6 +79,8 @@ var actions = { addNewKeyring, importNewAccount, addNewAccount, + connectHardware, + unlockTrezorAccount, NEW_ACCOUNT_SCREEN: 'NEW_ACCOUNT_SCREEN', navigateToNewAccountScreen, resetAccount, @@ -596,6 +598,46 @@ function addNewAccount () { } } +function connectHardware (deviceName, page) { + log.debug(`background.connectHardware`, deviceName, page) + return (dispatch, getState) => { + dispatch(actions.showLoadingIndication()) + return new Promise((resolve, reject) => { + background.connectHardware(deviceName, page, (err, accounts) => { + if (err) { + log.error(err) + dispatch(actions.displayWarning(err.message)) + return reject(err) + } + + dispatch(actions.hideLoadingIndication()) + + forceUpdateMetamaskState(dispatch) + return resolve(accounts) + }) + }) + } +} + +function unlockTrezorAccount (index) { + log.debug(`background.unlockTrezorAccount`, index) + return (dispatch, getState) => { + dispatch(actions.showLoadingIndication()) + return new Promise((resolve, reject) => { + background.unlockTrezorAccount(index, (err, accounts) => { + if (err) { + log.error(err) + dispatch(actions.displayWarning(err.message)) + return reject(err) + } + + dispatch(actions.hideLoadingIndication()) + return resolve() + }) + }) + } +} + function showInfoPage () { return { type: actions.SHOW_INFO_PAGE, diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index f34631ca8..629669dac 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -14,6 +14,7 @@ const { INFO_ROUTE, NEW_ACCOUNT_ROUTE, IMPORT_ACCOUNT_ROUTE, + CONNECT_HARDWARE_ROUTE, DEFAULT_ROUTE, } = require('../../routes') @@ -106,6 +107,14 @@ AccountMenu.prototype.render = function () { icon: h('img.account-menu__item-icon', { src: 'images/import-account.svg' }), text: this.context.t('importAccount'), }), + h(Item, { + onClick: () => { + toggleAccountMenu() + history.push(CONNECT_HARDWARE_ROUTE) + }, + icon: h('img.account-menu__item-icon', { src: 'images/connect-icon.svg' }), + text: this.context.t('connectHardware'), + }), h(Divider), h(Item, { onClick: () => { diff --git a/ui/app/components/pages/create-account/connect-hardware.js b/ui/app/components/pages/create-account/connect-hardware.js new file mode 100644 index 000000000..37b7414b3 --- /dev/null +++ b/ui/app/components/pages/create-account/connect-hardware.js @@ -0,0 +1,234 @@ +const { Component } = require('react') +const PropTypes = require('prop-types') +const h = require('react-hyperscript') +const connect = require('react-redux').connect +const actions = require('../../../actions') +const genAccountLink = require('../../../../lib/account-link.js') +const log = require('loglevel') +const { DEFAULT_ROUTE } = require('../../../routes') + +class ConnectHardwareForm extends Component { + constructor (props, context) { + super(props) + this.state = { + error: null, + response: null, + btnText: 'Connect to Trezor', // Test + selectedAccount: '', + accounts: [], + } + } + + connectToTrezor () { + if (this.state.accounts.length) { + return null + } + this.setState({ btnText: 'Connecting...' }) + this.getPage() + } + + getPage (page = 1) { + this.props + .connectHardware('trezor', page) + .then(accounts => { + if (accounts.length) { + this.setState({ accounts: accounts }) + } + }) + .catch(e => { + this.setState({ btnText: 'Connect to Trezor' }) + }) + } + + unlockAccount () { + if (this.state.selectedAccount === '') { + return Promise.reject({ error: 'You need to select an account!' }) + } + log.debug('should unlock account ', this.state.selectedAccount) + return this.props.unlockTrezorAccount(this.state.selectedAccount) + } + + handleRadioChange = e => { + log.debug('Selected account with index ', e.target.value) + + this.setState({ + selectedAccount: e.target.value, + error: null, + }) + } + + renderAccounts () { + if (!this.state.accounts.length) { + return null + } + log.debug('ACCOUNTS : ', this.state.accounts) + log.debug('SELECTED?', this.state.selectedAccount) + + return h('div.hw-account-list', [ + h('div.hw-account-list__title_wrapper', [ + h('div.hw-account-list__title', {}, ['Select an Address']), + h('div.hw-account-list__device', {}, ['Trezor - ETH']), + ]), + this.state.accounts.map((a, i) => { + return h('div.hw-account-list__item', { key: a.address }, [ + h('span.hw-account-list__item__index', a.index + 1), + h('div.hw-account-list__item__radio', [ + h('input', { + type: 'radio', + name: 'selectedAccount', + id: `address-${i}`, + value: a.index, + onChange: this.handleRadioChange, + }), + h( + 'label.hw-account-list__item__label', + { + htmlFor: `address-${i}`, + }, + `${a.address.slice(0, 4)}...${a.address.slice(-4)}` + ), + ]), + h('span.hw-account-list__item__balance', `${a.balance} ETH`), + h( + 'a.hw-account-list__item__link', + { + href: genAccountLink(a.address, this.props.network), + target: '_blank', + title: this.context.t('etherscanView'), + }, + h('img', { src: 'images/popout.svg' }) + ), + ]) + }), + ]) + } + + renderPagination () { + if (!this.state.accounts.length) { + return null + } + return h('div.hw-list-pagination', [ + h( + 'button.btn-primary.hw-list-pagination__button', + { + onClick: () => this.getPage(-1), + }, + '< Prev' + ), + + h( + 'button.btn-primary.hw-list-pagination__button', + { + onClick: () => this.getPage(), + }, + 'Next >' + ), + ]) + } + + renderButtons () { + if (!this.state.accounts.length) { + return null + } + const { history } = this.props + + return h('div.new-account-create-form__buttons', {}, [ + h( + 'button.btn-default.btn--large.new-account-create-form__button', + { + onClick: () => history.push(DEFAULT_ROUTE), + }, + [this.context.t('cancel')] + ), + + h( + 'button.btn-primary.btn--large.new-account-create-form__button', + { + onClick: () => { + this.unlockAccount(this.state.selectedAccount) + .then(() => history.push(DEFAULT_ROUTE)) + .catch(e => { + this.setState({ error: e.error }) + }) + }, + }, + [this.context.t('unlock')] + ), + ]) + } + + renderError () { + return this.state.error + ? h('span.error', { style: { marginBottom: 40 } }, this.state.error) + : null + } + + renderConnectButton () { + return !this.state.accounts.length + ? h( + 'button.btn-primary.btn--large', + { onClick: () => this.connectToTrezor(), style: { margin: 12 } }, + this.state.btnText + ) + : null + } + + render () { + return h('div.new-account-create-form', [ + this.renderError(), + this.renderConnectButton(), + this.renderAccounts(), + this.renderPagination(), + this.renderButtons(), + ]) + } +} + +ConnectHardwareForm.propTypes = { + hideModal: PropTypes.func, + showImportPage: PropTypes.func, + showConnectPage: PropTypes.func, + connectHardware: PropTypes.func, + unlockTrezorAccount: PropTypes.func, + numberOfExistingAccounts: PropTypes.number, + history: PropTypes.object, + t: PropTypes.func, + network: PropTypes.string, +} + +const mapStateToProps = state => { + const { + metamask: { network, selectedAddress, identities = {} }, + } = state + const numberOfExistingAccounts = Object.keys(identities).length + + return { + network, + address: selectedAddress, + numberOfExistingAccounts, + } +} + +const mapDispatchToProps = dispatch => { + return { + toCoinbase: address => + dispatch(actions.buyEth({ network: '1', address, amount: 0 })), + hideModal: () => dispatch(actions.hideModal()), + connectHardware: (deviceName, page) => { + return dispatch(actions.connectHardware(deviceName, page)) + }, + unlockTrezorAccount: index => { + return dispatch(actions.unlockTrezorAccount(index)) + }, + showImportPage: () => dispatch(actions.showImportPage()), + showConnectPage: () => dispatch(actions.showConnectPage()), + } +} + +ConnectHardwareForm.contextTypes = { + t: PropTypes.func, +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)( + ConnectHardwareForm +) diff --git a/ui/app/components/pages/create-account/index.js b/ui/app/components/pages/create-account/index.js index 6e3b93742..69a4db80a 100644 --- a/ui/app/components/pages/create-account/index.js +++ b/ui/app/components/pages/create-account/index.js @@ -8,7 +8,12 @@ const { getCurrentViewContext } = require('../../../selectors') const classnames = require('classnames') const NewAccountCreateForm = require('./new-account') const NewAccountImportForm = require('./import-account') -const { NEW_ACCOUNT_ROUTE, IMPORT_ACCOUNT_ROUTE } = require('../../../routes') +const ConnectHardwareForm = require('./connect-hardware') +const { + NEW_ACCOUNT_ROUTE, + IMPORT_ACCOUNT_ROUTE, + CONNECT_HARDWARE_ROUTE, +} = require('../../../routes') class CreateAccountPage extends Component { renderTabs () { @@ -36,6 +41,19 @@ class CreateAccountPage extends Component { }, [ this.context.t('import'), ]), + h( + 'div.new-account__tabs__tab', + { + className: classnames('new-account__tabs__tab', { + 'new-account__tabs__selected': matchPath(location.pathname, { + path: CONNECT_HARDWARE_ROUTE, + exact: true, + }), + }), + onClick: () => history.push(CONNECT_HARDWARE_ROUTE), + }, + this.context.t('connect') + ), ]) } @@ -57,6 +75,11 @@ class CreateAccountPage extends Component { path: IMPORT_ACCOUNT_ROUTE, component: NewAccountImportForm, }), + h(Route, { + exact: true, + path: CONNECT_HARDWARE_ROUTE, + component: ConnectHardwareForm, + }), ]), ]), ]) diff --git a/ui/app/components/pages/create-account/new-account.js b/ui/app/components/pages/create-account/new-account.js index 9c94990e0..402b8f03b 100644 --- a/ui/app/components/pages/create-account/new-account.js +++ b/ui/app/components/pages/create-account/new-account.js @@ -62,6 +62,7 @@ class NewAccountCreateForm extends Component { NewAccountCreateForm.propTypes = { hideModal: PropTypes.func, showImportPage: PropTypes.func, + showConnectPage: PropTypes.func, createAccount: PropTypes.func, numberOfExistingAccounts: PropTypes.number, history: PropTypes.object, @@ -92,6 +93,7 @@ const mapDispatchToProps = dispatch => { }) }, showImportPage: () => dispatch(actions.showImportPage()), + showConnectPage: () => dispatch(actions.showConnectPage()), } } diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index 293579058..2ecc157f1 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -28,7 +28,6 @@ &__tab { height: 54px; - width: 75px; padding: 15px 10px; color: $dusty-gray; font-family: Roboto; @@ -38,10 +37,6 @@ cursor: pointer; } - &__tab:first-of-type { - margin-right: 20px; - } - &__tab:hover { color: $black; border-bottom: none; @@ -158,6 +153,106 @@ } } +.hw-account-list { + display: flex; + flex: 1; + flex-flow: column; + width: 100%; + + &__title_wrapper { + display: flex; + flex-direction: row; + flex: 1; + } + + &__title { + margin-bottom: 23px; + align-self: flex-start; + color: $scorpion; + font-family: Roboto; + font-size: 16px; + line-height: 21px; + font-weight: bold; + display: flex; + flex: 1; + } + + &__device { + margin-bottom: 23px; + align-self: flex-end; + color: $scorpion; + font-family: Roboto; + font-size: 16px; + line-height: 21px; + font-weight: normal; + display: flex; + } + + &__item { + font-size: 15px; + flex-direction: row; + display: flex; + padding: 10px; + } + + &__item:nth-of-type(even) { + background-color: #fbfbfb; + } + + &__item:nth-of-type(odd) { + background: rgba(0, 0, 0, 0.03); + } + + &__item:hover { + background-color: rgba(0, 0, 0, 0.06); + } + + &__item__index { + display: flex; + margin-right: 20px; + } + + &__item__radio { + display: flex; + flex: 1; + } + + &__item__label { + margin-left: 10px; + display: flex; + flex: 1; + } + + &__item__balance { + display: flex; + flex: 1; + justify-content: center; + } + + &__item__link { + display: flex; + } + + &__item__link img { + width: 15px; + height: 15px; + } +} + +.hw-list-pagination { + display: flex; + align-self: flex-end; + margin-top: 10px; + + &__button { + height: 25px; + flex: initial; + min-width: 90px; + font-size: 12px; + } +} + + .new-account-create-form { display: flex; flex-flow: column; diff --git a/ui/app/routes.js b/ui/app/routes.js index 0ff3f644d..04f71165f 100644 --- a/ui/app/routes.js +++ b/ui/app/routes.js @@ -9,6 +9,7 @@ const ADD_TOKEN_ROUTE = '/add-token' const CONFIRM_ADD_TOKEN_ROUTE = '/confirm-add-token' const NEW_ACCOUNT_ROUTE = '/new-account' const IMPORT_ACCOUNT_ROUTE = '/new-account/import' +const CONNECT_HARDWARE_ROUTE = '/new-account/connect' const SEND_ROUTE = '/send' const CONFIRM_TRANSACTION_ROUTE = '/confirm-transaction' const SIGNATURE_REQUEST_ROUTE = '/confirm-transaction/signature-request' @@ -35,6 +36,7 @@ module.exports = { CONFIRM_ADD_TOKEN_ROUTE, NEW_ACCOUNT_ROUTE, IMPORT_ACCOUNT_ROUTE, + CONNECT_HARDWARE_ROUTE, SEND_ROUTE, CONFIRM_TRANSACTION_ROUTE, NOTICE_ROUTE, -- cgit v1.2.3 From d1880073f678dbdc52e07e62ec66c39eea5062a6 Mon Sep 17 00:00:00 2001 From: Bruno Date: Sun, 10 Jun 2018 21:10:22 -0400 Subject: balances working --- .../pages/create-account/connect-hardware.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware.js b/ui/app/components/pages/create-account/connect-hardware.js index 37b7414b3..6f1e03550 100644 --- a/ui/app/components/pages/create-account/connect-hardware.js +++ b/ui/app/components/pages/create-account/connect-hardware.js @@ -6,6 +6,7 @@ const actions = require('../../../actions') const genAccountLink = require('../../../../lib/account-link.js') const log = require('loglevel') const { DEFAULT_ROUTE } = require('../../../routes') +const { formatBalance } = require('../../../util') class ConnectHardwareForm extends Component { constructor (props, context) { @@ -57,10 +58,22 @@ class ConnectHardwareForm extends Component { }) } + getBalance (address) { + // Get the balance + log.debug('getBalance : ', address) + const { accounts } = this.props + const balanceValue = accounts && accounts[address] ? accounts[address].balance : '' + log.debug('balanceValue : ', balanceValue) + const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...' + log.debug('formattedBalance : ', formattedBalance) + return formattedBalance + } + renderAccounts () { if (!this.state.accounts.length) { return null } + log.debug('ACCOUNTS : ', this.state.accounts) log.debug('SELECTED?', this.state.selectedAccount) @@ -70,6 +83,7 @@ class ConnectHardwareForm extends Component { h('div.hw-account-list__device', {}, ['Trezor - ETH']), ]), this.state.accounts.map((a, i) => { + return h('div.hw-account-list__item', { key: a.address }, [ h('span.hw-account-list__item__index', a.index + 1), h('div.hw-account-list__item__radio', [ @@ -88,7 +102,7 @@ class ConnectHardwareForm extends Component { `${a.address.slice(0, 4)}...${a.address.slice(-4)}` ), ]), - h('span.hw-account-list__item__balance', `${a.balance} ETH`), + h('span.hw-account-list__item__balance', `${this.getBalance(a.address)}`), h( 'a.hw-account-list__item__link', { @@ -194,16 +208,18 @@ ConnectHardwareForm.propTypes = { history: PropTypes.object, t: PropTypes.func, network: PropTypes.string, + accounts: PropTypes.object, } const mapStateToProps = state => { const { - metamask: { network, selectedAddress, identities = {} }, + metamask: { network, selectedAddress, identities = {}, accounts = [] }, } = state const numberOfExistingAccounts = Object.keys(identities).length return { network, + accounts, address: selectedAddress, numberOfExistingAccounts, } -- cgit v1.2.3 From 8763ea898e7838d08315063b0e2181405a2ae3d5 Mon Sep 17 00:00:00 2001 From: Bruno Date: Wed, 13 Jun 2018 01:32:13 -0400 Subject: move TrezorKeyring to its own package --- ui/app/components/pages/create-account/connect-hardware.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware.js b/ui/app/components/pages/create-account/connect-hardware.js index 6f1e03550..152a4f275 100644 --- a/ui/app/components/pages/create-account/connect-hardware.js +++ b/ui/app/components/pages/create-account/connect-hardware.js @@ -25,10 +25,10 @@ class ConnectHardwareForm extends Component { return null } this.setState({ btnText: 'Connecting...' }) - this.getPage() + this.getPage(1) } - getPage (page = 1) { + getPage (page) { this.props .connectHardware('trezor', page) .then(accounts => { @@ -133,7 +133,7 @@ class ConnectHardwareForm extends Component { h( 'button.btn-primary.hw-list-pagination__button', { - onClick: () => this.getPage(), + onClick: () => this.getPage(1), }, 'Next >' ), -- cgit v1.2.3 From 86a8c98148447916915da99962d82ec5c5dd6cb7 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Mon, 2 Jul 2018 15:14:57 -0400 Subject: always open connect hardware in full screen mode --- ui/app/components/account-menu/index.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index 629669dac..be6963ac4 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -9,6 +9,10 @@ const actions = require('../../actions') const { Menu, Item, Divider, CloseArea } = require('../dropdowns/components/menu') const Identicon = require('../identicon') const { formatBalance } = require('../../util') +const { ENVIRONMENT_TYPE_POPUP } = require('../../../../app/scripts/lib/enums') +const { getEnvironmentType } = require('../../../../app/scripts/lib/util') + + const { SETTINGS_ROUTE, INFO_ROUTE, @@ -110,7 +114,11 @@ AccountMenu.prototype.render = function () { h(Item, { onClick: () => { toggleAccountMenu() - history.push(CONNECT_HARDWARE_ROUTE) + if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) { + global.platform.openExtensionInBrowser(CONNECT_HARDWARE_ROUTE) + } else { + history.push(CONNECT_HARDWARE_ROUTE) + } }, icon: h('img.account-menu__item-icon', { src: 'images/connect-icon.svg' }), text: this.context.t('connectHardware'), -- cgit v1.2.3 From f19ffaf08d49f33c395a25faf3eeb6b08d5285a4 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Mon, 2 Jul 2018 15:16:05 -0400 Subject: move hardcoded strings to localization file --- .../pages/create-account/connect-hardware.js | 24 +++++++--------------- 1 file changed, 7 insertions(+), 17 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware.js b/ui/app/components/pages/create-account/connect-hardware.js index 152a4f275..d022d7487 100644 --- a/ui/app/components/pages/create-account/connect-hardware.js +++ b/ui/app/components/pages/create-account/connect-hardware.js @@ -4,7 +4,6 @@ const h = require('react-hyperscript') const connect = require('react-redux').connect const actions = require('../../../actions') const genAccountLink = require('../../../../lib/account-link.js') -const log = require('loglevel') const { DEFAULT_ROUTE } = require('../../../routes') const { formatBalance } = require('../../../util') @@ -14,7 +13,7 @@ class ConnectHardwareForm extends Component { this.state = { error: null, response: null, - btnText: 'Connect to Trezor', // Test + btnText: context.t('connectToTrezor'), selectedAccount: '', accounts: [], } @@ -24,7 +23,7 @@ class ConnectHardwareForm extends Component { if (this.state.accounts.length) { return null } - this.setState({ btnText: 'Connecting...' }) + this.setState({ btnText: this.context.t('connecting')}) this.getPage(1) } @@ -37,21 +36,18 @@ class ConnectHardwareForm extends Component { } }) .catch(e => { - this.setState({ btnText: 'Connect to Trezor' }) + this.setState({ btnText: this.context.t('connectToTrezor') }) }) } unlockAccount () { if (this.state.selectedAccount === '') { - return Promise.reject({ error: 'You need to select an account!' }) + return Promise.reject({ error: this.context.t('accountSelectionRequired') }) } - log.debug('should unlock account ', this.state.selectedAccount) return this.props.unlockTrezorAccount(this.state.selectedAccount) } handleRadioChange = e => { - log.debug('Selected account with index ', e.target.value) - this.setState({ selectedAccount: e.target.value, error: null, @@ -60,12 +56,9 @@ class ConnectHardwareForm extends Component { getBalance (address) { // Get the balance - log.debug('getBalance : ', address) const { accounts } = this.props const balanceValue = accounts && accounts[address] ? accounts[address].balance : '' - log.debug('balanceValue : ', balanceValue) const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...' - log.debug('formattedBalance : ', formattedBalance) return formattedBalance } @@ -74,12 +67,9 @@ class ConnectHardwareForm extends Component { return null } - log.debug('ACCOUNTS : ', this.state.accounts) - log.debug('SELECTED?', this.state.selectedAccount) - return h('div.hw-account-list', [ h('div.hw-account-list__title_wrapper', [ - h('div.hw-account-list__title', {}, ['Select an Address']), + h('div.hw-account-list__title', {}, [this.context.t('selectAnAddress')]), h('div.hw-account-list__device', {}, ['Trezor - ETH']), ]), this.state.accounts.map((a, i) => { @@ -127,7 +117,7 @@ class ConnectHardwareForm extends Component { { onClick: () => this.getPage(-1), }, - '< Prev' + `< ${this.context.t('prev')}` ), h( @@ -135,7 +125,7 @@ class ConnectHardwareForm extends Component { { onClick: () => this.getPage(1), }, - 'Next >' + `${this.context.t('next')} >` ), ]) } -- cgit v1.2.3 From 9d3f2435e58e2454506ea1a5f7b85452a10edffa Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Tue, 3 Jul 2018 15:46:15 -0400 Subject: lint fix --- ui/app/components/pages/create-account/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/index.js b/ui/app/components/pages/create-account/index.js index ad2081315..d3de1ea01 100644 --- a/ui/app/components/pages/create-account/index.js +++ b/ui/app/components/pages/create-account/index.js @@ -12,7 +12,7 @@ const ConnectHardwareForm = require('./connect-hardware') const { NEW_ACCOUNT_ROUTE, IMPORT_ACCOUNT_ROUTE, - CONNECT_HARDWARE_ROUTE, + CONNECT_HARDWARE_ROUTE, } = require('../../../routes') class CreateAccountPage extends Component { -- cgit v1.2.3 From 313090efcc5200c56373cf312052217f1a1340ef Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Thu, 5 Jul 2018 16:11:41 -0400 Subject: added message for non-chrome browsers --- .../pages/create-account/connect-hardware.js | 27 +++++++++++++++++++++- ui/app/css/itcss/components/new-account.scss | 13 +++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware.js b/ui/app/components/pages/create-account/connect-hardware.js index d022d7487..c51b4c773 100644 --- a/ui/app/components/pages/create-account/connect-hardware.js +++ b/ui/app/components/pages/create-account/connect-hardware.js @@ -177,10 +177,35 @@ class ConnectHardwareForm extends Component { : null } + renderUnsupportedBrowser () { + return ( + [h('div.hw-unsupported-browser', [ + h('h3.hw-unsupported-browser__title', {}, 'Bummer! Your Browser is not supported...'), + h('p.hw-unsupported-browser__msg', {}, 'You need to use Metamask on Google Chrome in order to connect to your TREZOR device.'), + ]), + h( + 'button.btn-primary.btn--large', + { onClick: () => global.platform.openWindow({ + url: 'https://google.com/chrome', + }), style: { margin: 12 } }, + 'Download Google Chrome' + )] + ) + } + + renderConnectScreen () { + const isChrome = window.navigator.userAgent.search('Chrome') !== -1 + if (isChrome) { + return this.renderConnectButton() + } else { + return this.renderUnsupportedBrowser() + } + } + render () { return h('div.new-account-create-form', [ this.renderError(), - this.renderConnectButton(), + this.renderConnectScreen(), this.renderAccounts(), this.renderPagination(), this.renderButtons(), diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index 2ecc157f1..551025df3 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -153,6 +153,19 @@ } } +.hw-unsupported-browser { + &__title { + padding-top: 10px; + } + + &__msg { + font-size: 14px; + color: #9b9b9b; + margin-top: 15px; + margin-bottom: 15px; + } +} + .hw-account-list { display: flex; flex: 1; -- cgit v1.2.3 From ba5cde0995f956fb22825d604fe7d664677abaaa Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Thu, 5 Jul 2018 17:04:36 -0400 Subject: move strings to localization file --- .../pages/create-account/connect-hardware.js | 23 +++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware.js b/ui/app/components/pages/create-account/connect-hardware.js index c51b4c773..1e4ee38e3 100644 --- a/ui/app/components/pages/create-account/connect-hardware.js +++ b/ui/app/components/pages/create-account/connect-hardware.js @@ -179,17 +179,18 @@ class ConnectHardwareForm extends Component { renderUnsupportedBrowser () { return ( - [h('div.hw-unsupported-browser', [ - h('h3.hw-unsupported-browser__title', {}, 'Bummer! Your Browser is not supported...'), - h('p.hw-unsupported-browser__msg', {}, 'You need to use Metamask on Google Chrome in order to connect to your TREZOR device.'), - ]), - h( - 'button.btn-primary.btn--large', - { onClick: () => global.platform.openWindow({ - url: 'https://google.com/chrome', - }), style: { margin: 12 } }, - 'Download Google Chrome' - )] + [ + h('div.hw-unsupported-browser', [ + h('h3.hw-unsupported-browser__title', {}, this.context.t('browserNotSupported')), + h('p.hw-unsupported-browser__msg', {}, this.context.t('chromeRequiredForTrezor')), + ]), + h( + 'button.btn-primary.btn--large', + { onClick: () => global.platform.openWindow({ + url: 'https://google.com/chrome', + }), style: { margin: 12 } }, + this.context.t('downloadGoogleChrome') + )] ) } -- cgit v1.2.3 From 6c2730f24300449010bd3552d4d746bcb5dd176a Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Thu, 5 Jul 2018 17:45:28 -0400 Subject: Refactor UI --- .../pages/create-account/connect-hardware.js | 266 --------------------- .../connect-hardware/account-list.js | 137 +++++++++++ .../connect-hardware/connect-screen.js | 60 +++++ .../pages/create-account/connect-hardware/index.js | 131 ++++++++++ 4 files changed, 328 insertions(+), 266 deletions(-) delete mode 100644 ui/app/components/pages/create-account/connect-hardware.js create mode 100644 ui/app/components/pages/create-account/connect-hardware/account-list.js create mode 100644 ui/app/components/pages/create-account/connect-hardware/connect-screen.js create mode 100644 ui/app/components/pages/create-account/connect-hardware/index.js (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware.js b/ui/app/components/pages/create-account/connect-hardware.js deleted file mode 100644 index 1e4ee38e3..000000000 --- a/ui/app/components/pages/create-account/connect-hardware.js +++ /dev/null @@ -1,266 +0,0 @@ -const { Component } = require('react') -const PropTypes = require('prop-types') -const h = require('react-hyperscript') -const connect = require('react-redux').connect -const actions = require('../../../actions') -const genAccountLink = require('../../../../lib/account-link.js') -const { DEFAULT_ROUTE } = require('../../../routes') -const { formatBalance } = require('../../../util') - -class ConnectHardwareForm extends Component { - constructor (props, context) { - super(props) - this.state = { - error: null, - response: null, - btnText: context.t('connectToTrezor'), - selectedAccount: '', - accounts: [], - } - } - - connectToTrezor () { - if (this.state.accounts.length) { - return null - } - this.setState({ btnText: this.context.t('connecting')}) - this.getPage(1) - } - - getPage (page) { - this.props - .connectHardware('trezor', page) - .then(accounts => { - if (accounts.length) { - this.setState({ accounts: accounts }) - } - }) - .catch(e => { - this.setState({ btnText: this.context.t('connectToTrezor') }) - }) - } - - unlockAccount () { - if (this.state.selectedAccount === '') { - return Promise.reject({ error: this.context.t('accountSelectionRequired') }) - } - return this.props.unlockTrezorAccount(this.state.selectedAccount) - } - - handleRadioChange = e => { - this.setState({ - selectedAccount: e.target.value, - error: null, - }) - } - - getBalance (address) { - // Get the balance - const { accounts } = this.props - const balanceValue = accounts && accounts[address] ? accounts[address].balance : '' - const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...' - return formattedBalance - } - - renderAccounts () { - if (!this.state.accounts.length) { - return null - } - - return h('div.hw-account-list', [ - h('div.hw-account-list__title_wrapper', [ - h('div.hw-account-list__title', {}, [this.context.t('selectAnAddress')]), - h('div.hw-account-list__device', {}, ['Trezor - ETH']), - ]), - this.state.accounts.map((a, i) => { - - return h('div.hw-account-list__item', { key: a.address }, [ - h('span.hw-account-list__item__index', a.index + 1), - h('div.hw-account-list__item__radio', [ - h('input', { - type: 'radio', - name: 'selectedAccount', - id: `address-${i}`, - value: a.index, - onChange: this.handleRadioChange, - }), - h( - 'label.hw-account-list__item__label', - { - htmlFor: `address-${i}`, - }, - `${a.address.slice(0, 4)}...${a.address.slice(-4)}` - ), - ]), - h('span.hw-account-list__item__balance', `${this.getBalance(a.address)}`), - h( - 'a.hw-account-list__item__link', - { - href: genAccountLink(a.address, this.props.network), - target: '_blank', - title: this.context.t('etherscanView'), - }, - h('img', { src: 'images/popout.svg' }) - ), - ]) - }), - ]) - } - - renderPagination () { - if (!this.state.accounts.length) { - return null - } - return h('div.hw-list-pagination', [ - h( - 'button.btn-primary.hw-list-pagination__button', - { - onClick: () => this.getPage(-1), - }, - `< ${this.context.t('prev')}` - ), - - h( - 'button.btn-primary.hw-list-pagination__button', - { - onClick: () => this.getPage(1), - }, - `${this.context.t('next')} >` - ), - ]) - } - - renderButtons () { - if (!this.state.accounts.length) { - return null - } - const { history } = this.props - - return h('div.new-account-create-form__buttons', {}, [ - h( - 'button.btn-default.btn--large.new-account-create-form__button', - { - onClick: () => history.push(DEFAULT_ROUTE), - }, - [this.context.t('cancel')] - ), - - h( - 'button.btn-primary.btn--large.new-account-create-form__button', - { - onClick: () => { - this.unlockAccount(this.state.selectedAccount) - .then(() => history.push(DEFAULT_ROUTE)) - .catch(e => { - this.setState({ error: e.error }) - }) - }, - }, - [this.context.t('unlock')] - ), - ]) - } - - renderError () { - return this.state.error - ? h('span.error', { style: { marginBottom: 40 } }, this.state.error) - : null - } - - renderConnectButton () { - return !this.state.accounts.length - ? h( - 'button.btn-primary.btn--large', - { onClick: () => this.connectToTrezor(), style: { margin: 12 } }, - this.state.btnText - ) - : null - } - - renderUnsupportedBrowser () { - return ( - [ - h('div.hw-unsupported-browser', [ - h('h3.hw-unsupported-browser__title', {}, this.context.t('browserNotSupported')), - h('p.hw-unsupported-browser__msg', {}, this.context.t('chromeRequiredForTrezor')), - ]), - h( - 'button.btn-primary.btn--large', - { onClick: () => global.platform.openWindow({ - url: 'https://google.com/chrome', - }), style: { margin: 12 } }, - this.context.t('downloadGoogleChrome') - )] - ) - } - - renderConnectScreen () { - const isChrome = window.navigator.userAgent.search('Chrome') !== -1 - if (isChrome) { - return this.renderConnectButton() - } else { - return this.renderUnsupportedBrowser() - } - } - - render () { - return h('div.new-account-create-form', [ - this.renderError(), - this.renderConnectScreen(), - this.renderAccounts(), - this.renderPagination(), - this.renderButtons(), - ]) - } -} - -ConnectHardwareForm.propTypes = { - hideModal: PropTypes.func, - showImportPage: PropTypes.func, - showConnectPage: PropTypes.func, - connectHardware: PropTypes.func, - unlockTrezorAccount: PropTypes.func, - numberOfExistingAccounts: PropTypes.number, - history: PropTypes.object, - t: PropTypes.func, - network: PropTypes.string, - accounts: PropTypes.object, -} - -const mapStateToProps = state => { - const { - metamask: { network, selectedAddress, identities = {}, accounts = [] }, - } = state - const numberOfExistingAccounts = Object.keys(identities).length - - return { - network, - accounts, - address: selectedAddress, - numberOfExistingAccounts, - } -} - -const mapDispatchToProps = dispatch => { - return { - toCoinbase: address => - dispatch(actions.buyEth({ network: '1', address, amount: 0 })), - hideModal: () => dispatch(actions.hideModal()), - connectHardware: (deviceName, page) => { - return dispatch(actions.connectHardware(deviceName, page)) - }, - unlockTrezorAccount: index => { - return dispatch(actions.unlockTrezorAccount(index)) - }, - showImportPage: () => dispatch(actions.showImportPage()), - showConnectPage: () => dispatch(actions.showConnectPage()), - } -} - -ConnectHardwareForm.contextTypes = { - t: PropTypes.func, -} - -module.exports = connect(mapStateToProps, mapDispatchToProps)( - ConnectHardwareForm -) diff --git a/ui/app/components/pages/create-account/connect-hardware/account-list.js b/ui/app/components/pages/create-account/connect-hardware/account-list.js new file mode 100644 index 000000000..598865ad8 --- /dev/null +++ b/ui/app/components/pages/create-account/connect-hardware/account-list.js @@ -0,0 +1,137 @@ +const { Component } = require('react') +const PropTypes = require('prop-types') +const h = require('react-hyperscript') +const genAccountLink = require('../../../../lib/account-link.js') +const { DEFAULT_ROUTE } = require('../../../routes') +const { formatBalance } = require('../../../util') + +export default class AccountList extends Component { + constructor (props, context) { + super(props) + } + + getBalance (address) { + // Get the balance + const { accounts } = this.props + const balanceValue = accounts && accounts[address] ? accounts[address].balance : '' + const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...' + return formattedBalance + } + + renderAccounts () { + if (!this.props.accounts.length) { + return null + } + + return h('div.hw-account-list', [ + h('div.hw-account-list__title_wrapper', [ + h('div.hw-account-list__title', {}, [this.context.t('selectAnAddress')]), + h('div.hw-account-list__device', {}, ['Trezor - ETH']), + ]), + this.props.accounts.map((a, i) => { + + return h('div.hw-account-list__item', { key: a.address }, [ + h('span.hw-account-list__item__index', a.index + 1), + h('div.hw-account-list__item__radio', [ + h('input', { + type: 'radio', + name: 'selectedAccount', + id: `address-${i}`, + value: a.index, + onChange: (e) => this.props.onAccountChange(e.target.value), + }), + h( + 'label.hw-account-list__item__label', + { + htmlFor: `address-${i}`, + }, + `${a.address.slice(0, 4)}...${a.address.slice(-4)}` + ), + ]), + h('span.hw-account-list__item__balance', `${this.getBalance(a.address)}`), + h( + 'a.hw-account-list__item__link', + { + href: genAccountLink(a.address, this.props.network), + target: '_blank', + title: this.context.t('etherscanView'), + }, + h('img', { src: 'images/popout.svg' }) + ), + ]) + }), + ]) + } + + renderPagination () { + if (!this.state.accounts.length) { + return null + } + return h('div.hw-list-pagination', [ + h( + 'button.btn-primary.hw-list-pagination__button', + { + onClick: () => this.props.getPage(-1), + }, + `< ${this.context.t('prev')}` + ), + + h( + 'button.btn-primary.hw-list-pagination__button', + { + onClick: () => this.props.getPage(1), + }, + `${this.context.t('next')} >` + ), + ]) + } + + renderButtons () { + if (!this.state.accounts.length) { + return null + } + const { history } = this.props + + return h('div.new-account-create-form__buttons', {}, [ + h( + 'button.btn-default.btn--large.new-account-create-form__button', + { + onClick: () => history.push(DEFAULT_ROUTE), + }, + [this.context.t('cancel')] + ), + + h( + 'button.btn-primary.btn--large.new-account-create-form__button', + { + onClick: () => { + this.unlockAccount(this.state.selectedAccount) + .then(() => history.push(DEFAULT_ROUTE)) + .catch(e => { + this.setState({ error: e.error }) + }) + }, + }, + [this.context.t('unlock')] + ), + ]) + } + + render () { + return null + } + +} + + +AccountList.propTypes = { + accounts: PropTypes.object.isRequired, + onAccountChange: PropTypes.func.isRequired, + getPage: PropTypes.func.isRequired, + network: PropTypes.string, + history: PropTypes.object, +} + +AccountList.contextTypes = { + t: PropTypes.func, +} diff --git a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js new file mode 100644 index 000000000..1b064a15c --- /dev/null +++ b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js @@ -0,0 +1,60 @@ +const { Component } = require('react') +const PropTypes = require('prop-types') +const h = require('react-hyperscript') + +export default class ConnectScreen extends Component { + constructor (props, context) { + super(props) + } + + connectToTrezor = () => { + if (this.props.connectToTrezor) { + this.props.connectToTrezor() + } + } + + renderUnsupportedBrowser () { + return ( + [ + h('div.hw-unsupported-browser', [ + h('h3.hw-unsupported-browser__title', {}, this.context.t('browserNotSupported')), + h('p.hw-unsupported-browser__msg', {}, this.context.t('chromeRequiredForTrezor')), + ]), + h( + 'button.btn-primary.btn--large', + { onClick: () => global.platform.openWindow({ + url: 'https://google.com/chrome', + }), style: { margin: 12 } }, + this.context.t('downloadGoogleChrome') + )] + ) + } + + renderConnectButton () { + return !this.state.accounts.length + ? h( + 'button.btn-primary.btn--large', + { onClick: this.connectToTrezor, style: { margin: 12 } }, + this.props.btnText + ) + : null + } + + render () { + const isChrome = window.navigator.userAgent.search('Chrome') !== -1 + if (isChrome) { + return this.renderConnectButton() + } else { + return this.renderUnsupportedBrowser() + } + } +} + +ConnectScreen.propTypes = { + connectToTrezor: PropTypes.func.isRequired, + btnText: PropTypes.string, +} + +ConnectScreen.contextTypes = { + t: PropTypes.func, +} diff --git a/ui/app/components/pages/create-account/connect-hardware/index.js b/ui/app/components/pages/create-account/connect-hardware/index.js new file mode 100644 index 000000000..04e69162f --- /dev/null +++ b/ui/app/components/pages/create-account/connect-hardware/index.js @@ -0,0 +1,131 @@ +const { Component } = require('react') +const PropTypes = require('prop-types') +const h = require('react-hyperscript') +const connect = require('react-redux').connect +const actions = require('../../../actions') +const ConnectScreen = require('./connect-screen') +const AccountList = require('./account-list') + +class ConnectHardwareForm extends Component { + constructor (props, context) { + super(props) + this.state = { + error: null, + response: null, + btnText: context.t('connectToTrezor'), + selectedAccount: '', + accounts: [], + } + } + + connectToTrezor = () => { + if (this.state.accounts.length) { + return null + } + this.setState({ btnText: this.context.t('connecting')}) + this.getPage(1) + } + + onAccountChange = (account) => { + this.setState({selectedAccount: account, error: null}) + } + + getPage = (page) => { + this.props + .connectHardware('trezor', page) + .then(accounts => { + if (accounts.length) { + this.setState({ accounts: accounts }) + } + }) + .catch(e => { + this.setState({ btnText: this.context.t('connectToTrezor') }) + }) + } + + unlockAccount () { + if (this.state.selectedAccount === '') { + return Promise.reject({ error: this.context.t('accountSelectionRequired') }) + } + return this.props.unlockTrezorAccount(this.state.selectedAccount) + } + + + renderError () { + return this.state.error + ? h('span.error', { style: { marginBottom: 40 } }, this.state.error) + : null + } + + renderContent () { + if (!this.state.accounts.length) { + return h(ConnectScreen, { + connectToTrezor: this.connectToTrezor, + btnText: this.state.btnText, + }) + } + + return h(AccountList, { + accounts: this.state.accounts, + onAccountChange: this.onAccountChange, + network: this.props.network, + getPage: this.getPage, + history: this.props.history, + }) + } + + render () { + return h('div.new-account-create-form', [ + this.renderError(), + this.renderContent(), + ]) + } +} + +ConnectHardwareForm.propTypes = { + hideModal: PropTypes.func, + showImportPage: PropTypes.func, + showConnectPage: PropTypes.func, + connectHardware: PropTypes.func, + unlockTrezorAccount: PropTypes.func, + numberOfExistingAccounts: PropTypes.number, + history: PropTypes.object, + t: PropTypes.func, + network: PropTypes.string, + accounts: PropTypes.object, +} + +const mapStateToProps = state => { + const { + metamask: { network, selectedAddress, identities = {}, accounts = [] }, + } = state + const numberOfExistingAccounts = Object.keys(identities).length + + return { + network, + accounts, + address: selectedAddress, + numberOfExistingAccounts, + } +} + +const mapDispatchToProps = dispatch => { + return { + connectHardware: (deviceName, page) => { + return dispatch(actions.connectHardware(deviceName, page)) + }, + unlockTrezorAccount: index => { + return dispatch(actions.unlockTrezorAccount(index)) + }, + showImportPage: () => dispatch(actions.showImportPage()), + showConnectPage: () => dispatch(actions.showConnectPage()), + } +} + +ConnectHardwareForm.contextTypes = { + t: PropTypes.func, +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)( + ConnectHardwareForm +) -- cgit v1.2.3 From 6b2511f94f436a30c6c683f9da2c3142d9a6461c Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Thu, 5 Jul 2018 20:59:31 -0400 Subject: UI refactor --- .../connect-hardware/account-list.js | 111 ++++++++++----------- .../connect-hardware/connect-screen.js | 51 +++++----- .../pages/create-account/connect-hardware/index.js | 41 ++++++-- 3 files changed, 106 insertions(+), 97 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/account-list.js b/ui/app/components/pages/create-account/connect-hardware/account-list.js index 598865ad8..77e0af3ac 100644 --- a/ui/app/components/pages/create-account/connect-hardware/account-list.js +++ b/ui/app/components/pages/create-account/connect-hardware/account-list.js @@ -1,11 +1,10 @@ const { Component } = require('react') const PropTypes = require('prop-types') const h = require('react-hyperscript') -const genAccountLink = require('../../../../lib/account-link.js') -const { DEFAULT_ROUTE } = require('../../../routes') -const { formatBalance } = require('../../../util') +const genAccountLink = require('../../../../../lib/account-link.js') +const { formatBalance } = require('../../../../util') -export default class AccountList extends Component { +class AccountList extends Component { constructor (props, context) { super(props) } @@ -19,54 +18,48 @@ export default class AccountList extends Component { } renderAccounts () { - if (!this.props.accounts.length) { - return null - } - return h('div.hw-account-list', [ - h('div.hw-account-list__title_wrapper', [ - h('div.hw-account-list__title', {}, [this.context.t('selectAnAddress')]), - h('div.hw-account-list__device', {}, ['Trezor - ETH']), - ]), - this.props.accounts.map((a, i) => { + h('div.hw-account-list__title_wrapper', [ + h('div.hw-account-list__title', {}, [this.context.t('selectAnAddress')]), + h('div.hw-account-list__device', {}, ['Trezor - ETH']), + ]), + this.props.accounts.map((a, i) => { - return h('div.hw-account-list__item', { key: a.address }, [ - h('span.hw-account-list__item__index', a.index + 1), - h('div.hw-account-list__item__radio', [ - h('input', { - type: 'radio', - name: 'selectedAccount', - id: `address-${i}`, - value: a.index, - onChange: (e) => this.props.onAccountChange(e.target.value), - }), + return h('div.hw-account-list__item', { key: a.address }, [ + h('span.hw-account-list__item__index', a.index + 1), + h('div.hw-account-list__item__radio', [ + h('input', { + type: 'radio', + name: 'selectedAccount', + id: `address-${i}`, + value: a.index, + onChange: (e) => this.props.onAccountChange(e.target.value), + checked: this.props.selectedAccount === a.index.toString(), + }), + h( + 'label.hw-account-list__item__label', + { + htmlFor: `address-${i}`, + }, + `${a.address.slice(0, 4)}...${a.address.slice(-4)}` + ), + ]), + h('span.hw-account-list__item__balance', `${this.getBalance(a.address)}`), h( - 'label.hw-account-list__item__label', - { - htmlFor: `address-${i}`, - }, - `${a.address.slice(0, 4)}...${a.address.slice(-4)}` + 'a.hw-account-list__item__link', + { + href: genAccountLink(a.address, this.props.network), + target: '_blank', + title: this.context.t('etherscanView'), + }, + h('img', { src: 'images/popout.svg' }) ), - ]), - h('span.hw-account-list__item__balance', `${this.getBalance(a.address)}`), - h( - 'a.hw-account-list__item__link', - { - href: genAccountLink(a.address, this.props.network), - target: '_blank', - title: this.context.t('etherscanView'), - }, - h('img', { src: 'images/popout.svg' }) - ), - ]) - }), + ]) + }), ]) } renderPagination () { - if (!this.state.accounts.length) { - return null - } return h('div.hw-list-pagination', [ h( 'button.btn-primary.hw-list-pagination__button', @@ -87,30 +80,19 @@ export default class AccountList extends Component { } renderButtons () { - if (!this.state.accounts.length) { - return null - } - const { history } = this.props - return h('div.new-account-create-form__buttons', {}, [ h( 'button.btn-default.btn--large.new-account-create-form__button', { - onClick: () => history.push(DEFAULT_ROUTE), + onClick: this.props.onCancel.bind(this), }, [this.context.t('cancel')] ), h( - 'button.btn-primary.btn--large.new-account-create-form__button', + `button.btn-primary.btn--large.new-account-create-form__button ${this.props.selectedAccount === null ? '.btn-primary--disabled' : ''}`, { - onClick: () => { - this.unlockAccount(this.state.selectedAccount) - .then(() => history.push(DEFAULT_ROUTE)) - .catch(e => { - this.setState({ error: e.error }) - }) - }, + onClick: this.props.onUnlockAccount.bind(this), }, [this.context.t('unlock')] ), @@ -118,20 +100,29 @@ export default class AccountList extends Component { } render () { - return null + return h('div', {}, [ + this.renderAccounts(), + this.renderPagination(), + this.renderButtons(), + ]) } } AccountList.propTypes = { - accounts: PropTypes.object.isRequired, + accounts: PropTypes.array.isRequired, onAccountChange: PropTypes.func.isRequired, getPage: PropTypes.func.isRequired, network: PropTypes.string, + selectedAccount: PropTypes.string, history: PropTypes.object, + onUnlockAccount: PropTypes.func, + onCancel: PropTypes.func, } AccountList.contextTypes = { t: PropTypes.func, } + +module.exports = AccountList diff --git a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js index 1b064a15c..ec6a11b40 100644 --- a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js @@ -2,51 +2,43 @@ const { Component } = require('react') const PropTypes = require('prop-types') const h = require('react-hyperscript') -export default class ConnectScreen extends Component { +class ConnectScreen extends Component { constructor (props, context) { super(props) } - connectToTrezor = () => { - if (this.props.connectToTrezor) { - this.props.connectToTrezor() - } - } - renderUnsupportedBrowser () { return ( - [ - h('div.hw-unsupported-browser', [ - h('h3.hw-unsupported-browser__title', {}, this.context.t('browserNotSupported')), - h('p.hw-unsupported-browser__msg', {}, this.context.t('chromeRequiredForTrezor')), - ]), - h( - 'button.btn-primary.btn--large', - { onClick: () => global.platform.openWindow({ - url: 'https://google.com/chrome', - }), style: { margin: 12 } }, - this.context.t('downloadGoogleChrome') - )] + h('div', {}, [ + h('div.hw-unsupported-browser', [ + h('h3.hw-unsupported-browser__title', {}, this.context.t('browserNotSupported')), + h('p.hw-unsupported-browser__msg', {}, this.context.t('chromeRequiredForTrezor')), + ]), + h( + 'button.btn-primary.btn--large', + { onClick: () => global.platform.openWindow({ + url: 'https://google.com/chrome', + }), style: { margin: 12 } }, + this.context.t('downloadGoogleChrome') + ), + ]) ) } renderConnectButton () { - return !this.state.accounts.length - ? h( - 'button.btn-primary.btn--large', - { onClick: this.connectToTrezor, style: { margin: 12 } }, - this.props.btnText - ) - : null + return h( + 'button.btn-primary.btn--large', + { onClick: this.props.connectToTrezor.bind(this), style: { margin: 12 } }, + this.props.btnText + ) } render () { const isChrome = window.navigator.userAgent.search('Chrome') !== -1 if (isChrome) { return this.renderConnectButton() - } else { - return this.renderUnsupportedBrowser() } + return this.renderUnsupportedBrowser() } } @@ -58,3 +50,6 @@ ConnectScreen.propTypes = { ConnectScreen.contextTypes = { t: PropTypes.func, } + +module.exports = ConnectScreen + diff --git a/ui/app/components/pages/create-account/connect-hardware/index.js b/ui/app/components/pages/create-account/connect-hardware/index.js index 04e69162f..22c54d28c 100644 --- a/ui/app/components/pages/create-account/connect-hardware/index.js +++ b/ui/app/components/pages/create-account/connect-hardware/index.js @@ -2,9 +2,10 @@ const { Component } = require('react') const PropTypes = require('prop-types') const h = require('react-hyperscript') const connect = require('react-redux').connect -const actions = require('../../../actions') +const actions = require('../../../../actions') const ConnectScreen = require('./connect-screen') const AccountList = require('./account-list') +const { DEFAULT_ROUTE } = require('../../../../routes') class ConnectHardwareForm extends Component { constructor (props, context) { @@ -13,7 +14,7 @@ class ConnectHardwareForm extends Component { error: null, response: null, btnText: context.t('connectToTrezor'), - selectedAccount: '', + selectedAccount: null, accounts: [], } } @@ -23,11 +24,11 @@ class ConnectHardwareForm extends Component { return null } this.setState({ btnText: this.context.t('connecting')}) - this.getPage(1) + this.getPage(0) } onAccountChange = (account) => { - this.setState({selectedAccount: account, error: null}) + this.setState({selectedAccount: account.toString(), error: null}) } getPage = (page) => { @@ -35,7 +36,16 @@ class ConnectHardwareForm extends Component { .connectHardware('trezor', page) .then(accounts => { if (accounts.length) { - this.setState({ accounts: accounts }) + const newState = { accounts: accounts } + // Default to the first account + if (this.state.selectedAccount === null) { + const firstAccount = accounts[0] + newState.selectedAccount = firstAccount.index.toString() + // If the page doesn't contain the selected account, let's deselect it + } else if (!accounts.filter(a => a.index.toString() === '').lenght) { + newState.selectedAccount = null + } + this.setState(newState) } }) .catch(e => { @@ -43,13 +53,23 @@ class ConnectHardwareForm extends Component { }) } - unlockAccount () { - if (this.state.selectedAccount === '') { - return Promise.reject({ error: this.context.t('accountSelectionRequired') }) + onUnlockAccount = () => { + + if (this.state.selectedAccount === null) { + this.setState({ error: this.context.t('accountSelectionRequired') }) } - return this.props.unlockTrezorAccount(this.state.selectedAccount) + + this.props.unlockTrezorAccount(this.state.selectedAccount) + .then(_ => { + this.props.history.push(DEFAULT_ROUTE) + }).catch(e => { + this.setState({ error: e.toString() }) + }) } + onCancel = () => { + this.props.history.push(DEFAULT_ROUTE) + } renderError () { return this.state.error @@ -67,10 +87,13 @@ class ConnectHardwareForm extends Component { return h(AccountList, { accounts: this.state.accounts, + selectedAccount: this.state.selectedAccount, onAccountChange: this.onAccountChange, network: this.props.network, getPage: this.getPage, history: this.props.history, + onUnlockAccount: this.onUnlockAccount, + onCancel: this.onCancel, }) } -- cgit v1.2.3 From dddbb4250b30b7263eb97ddc2e23791166bcc98e Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Fri, 6 Jul 2018 20:04:20 -0400 Subject: update connect harwdware screen --- .../connect-hardware/connect-screen.js | 28 +++++++++++++++------- ui/app/css/itcss/components/new-account.scss | 6 ++++- 2 files changed, 25 insertions(+), 9 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js index ec6a11b40..cf6353bf8 100644 --- a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js @@ -10,9 +10,9 @@ class ConnectScreen extends Component { renderUnsupportedBrowser () { return ( h('div', {}, [ - h('div.hw-unsupported-browser', [ - h('h3.hw-unsupported-browser__title', {}, this.context.t('browserNotSupported')), - h('p.hw-unsupported-browser__msg', {}, this.context.t('chromeRequiredForTrezor')), + h('div.hw-connect', [ + h('h3.hw-connect__title', {}, this.context.t('browserNotSupported')), + h('p.hw-connect__msg', {}, this.context.t('chromeRequiredForTrezor')), ]), h( 'button.btn-primary.btn--large', @@ -25,18 +25,30 @@ class ConnectScreen extends Component { ) } - renderConnectButton () { - return h( + renderConnectScreen () { + return ( + h('div', {}, [ + h('div.hw-connect', [ + h('h3.hw-connect__title', {}, this.context.t('trezorHardwareWallet')), + h('p.hw-connect__msg', {}, this.context.t('connectToTrezorHelp')), + h('p.hw-connect__msg', {}, [ + this.context.t('connectToTrezorTrouble'), + h('a.___info-link', { url: 'https://support.metamask.io/', target: '_blank'}, this.context.t('learnMore')), + ]), + ]), + h( 'button.btn-primary.btn--large', - { onClick: this.props.connectToTrezor.bind(this), style: { margin: 12 } }, + { onClick: this.props.connectToTrezor.bind(this) }, this.props.btnText - ) + ), + ]) + ) } render () { const isChrome = window.navigator.userAgent.search('Chrome') !== -1 if (isChrome) { - return this.renderConnectButton() + return this.renderConnectScreen() } return this.renderUnsupportedBrowser() } diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index 551025df3..3d59081d8 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -153,7 +153,7 @@ } } -.hw-unsupported-browser { +.hw-connect { &__title { padding-top: 10px; } @@ -164,6 +164,10 @@ margin-top: 15px; margin-bottom: 15px; } + + &__info-link { + color: #2f9ae0; + } } .hw-account-list { -- cgit v1.2.3 From 512760154528c47213cc8ff75475c21e3e674a23 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Fri, 6 Jul 2018 20:37:08 -0400 Subject: copy updated --- .../pages/create-account/connect-hardware/connect-screen.js | 5 ++++- ui/app/css/itcss/components/new-account.scss | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js index cf6353bf8..dd9fdfba2 100644 --- a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js @@ -33,7 +33,10 @@ class ConnectScreen extends Component { h('p.hw-connect__msg', {}, this.context.t('connectToTrezorHelp')), h('p.hw-connect__msg', {}, [ this.context.t('connectToTrezorTrouble'), - h('a.___info-link', { url: 'https://support.metamask.io/', target: '_blank'}, this.context.t('learnMore')), + h('a.hw-connect__link', { + href: 'https://support.metamask.io/', + target: '_blank', + }, ` ${this.context.t('learnMore')}`), ]), ]), h( diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index 3d59081d8..7dfa839ab 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -165,7 +165,7 @@ margin-bottom: 15px; } - &__info-link { + &__link { color: #2f9ae0; } } -- cgit v1.2.3 From 7cca7ace2ea4cd4b9d3a242067c9a7c344406aba Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Mon, 9 Jul 2018 17:24:52 -0400 Subject: fix all the account related bugs --- .../connect-hardware/account-list.js | 11 +------- .../pages/create-account/connect-hardware/index.js | 29 +++++++++++++++++++--- 2 files changed, 27 insertions(+), 13 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/account-list.js b/ui/app/components/pages/create-account/connect-hardware/account-list.js index 77e0af3ac..170d8f0b3 100644 --- a/ui/app/components/pages/create-account/connect-hardware/account-list.js +++ b/ui/app/components/pages/create-account/connect-hardware/account-list.js @@ -2,21 +2,12 @@ const { Component } = require('react') const PropTypes = require('prop-types') const h = require('react-hyperscript') const genAccountLink = require('../../../../../lib/account-link.js') -const { formatBalance } = require('../../../../util') class AccountList extends Component { constructor (props, context) { super(props) } - getBalance (address) { - // Get the balance - const { accounts } = this.props - const balanceValue = accounts && accounts[address] ? accounts[address].balance : '' - const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...' - return formattedBalance - } - renderAccounts () { return h('div.hw-account-list', [ h('div.hw-account-list__title_wrapper', [ @@ -44,7 +35,7 @@ class AccountList extends Component { `${a.address.slice(0, 4)}...${a.address.slice(-4)}` ), ]), - h('span.hw-account-list__item__balance', `${this.getBalance(a.address)}`), + h('span.hw-account-list__item__balance', `${a.balance}`), h( 'a.hw-account-list__item__link', { diff --git a/ui/app/components/pages/create-account/connect-hardware/index.js b/ui/app/components/pages/create-account/connect-hardware/index.js index 22c54d28c..1aaa0be64 100644 --- a/ui/app/components/pages/create-account/connect-hardware/index.js +++ b/ui/app/components/pages/create-account/connect-hardware/index.js @@ -6,6 +6,7 @@ const actions = require('../../../../actions') const ConnectScreen = require('./connect-screen') const AccountList = require('./account-list') const { DEFAULT_ROUTE } = require('../../../../routes') +const { formatBalance } = require('../../../../util') class ConnectHardwareForm extends Component { constructor (props, context) { @@ -31,20 +32,42 @@ class ConnectHardwareForm extends Component { this.setState({selectedAccount: account.toString(), error: null}) } + getBalance (address) { + // Get the balance + const { accounts } = this.props + const balanceValue = accounts && accounts[address.toLowerCase()] ? accounts[address.toLowerCase()].balance : '' + const formattedBalance = balanceValue !== null ? formatBalance(balanceValue, 6) : '...' + console.log('[TREZOR]: got balance', address, accounts, balanceValue, formattedBalance) + return formattedBalance + } + getPage = (page) => { this.props .connectHardware('trezor', page) .then(accounts => { + console.log('[TREZOR]: GOT PAGE!', accounts) if (accounts.length) { - const newState = { accounts: accounts } + const newState = {} // Default to the first account if (this.state.selectedAccount === null) { const firstAccount = accounts[0] - newState.selectedAccount = firstAccount.index.toString() + newState.selectedAccount = firstAccount.index.toString() === '0' ? firstAccount.index.toString() : null + console.log('[TREZOR]: just defaulted to account', newState.selectedAccount) // If the page doesn't contain the selected account, let's deselect it - } else if (!accounts.filter(a => a.index.toString() === '').lenght) { + } else if (!accounts.filter(a => a.index.toString() === this.state.selectedAccount).length) { newState.selectedAccount = null + console.log('[TREZOR]: just removed default account', newState.selectedAccount) } + + console.log('[TREZOR]: mapping balances') + + // Map accounts with balances + newState.accounts = accounts.map(account => { + account.balance = this.getBalance(account.address) + return account + }) + + console.log('[TREZOR]: ABOUT TO RENDER ACCOUNTS: ', page, newState.accounts) this.setState(newState) } }) -- cgit v1.2.3 From 2de3039b6b21ca05ef185c078b67815448864c72 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Mon, 9 Jul 2018 17:55:37 -0400 Subject: fix account duplication --- ui/app/components/pages/create-account/connect-hardware/index.js | 6 ------ 1 file changed, 6 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/index.js b/ui/app/components/pages/create-account/connect-hardware/index.js index 1aaa0be64..126102235 100644 --- a/ui/app/components/pages/create-account/connect-hardware/index.js +++ b/ui/app/components/pages/create-account/connect-hardware/index.js @@ -37,7 +37,6 @@ class ConnectHardwareForm extends Component { const { accounts } = this.props const balanceValue = accounts && accounts[address.toLowerCase()] ? accounts[address.toLowerCase()].balance : '' const formattedBalance = balanceValue !== null ? formatBalance(balanceValue, 6) : '...' - console.log('[TREZOR]: got balance', address, accounts, balanceValue, formattedBalance) return formattedBalance } @@ -45,21 +44,17 @@ class ConnectHardwareForm extends Component { this.props .connectHardware('trezor', page) .then(accounts => { - console.log('[TREZOR]: GOT PAGE!', accounts) if (accounts.length) { const newState = {} // Default to the first account if (this.state.selectedAccount === null) { const firstAccount = accounts[0] newState.selectedAccount = firstAccount.index.toString() === '0' ? firstAccount.index.toString() : null - console.log('[TREZOR]: just defaulted to account', newState.selectedAccount) // If the page doesn't contain the selected account, let's deselect it } else if (!accounts.filter(a => a.index.toString() === this.state.selectedAccount).length) { newState.selectedAccount = null - console.log('[TREZOR]: just removed default account', newState.selectedAccount) } - console.log('[TREZOR]: mapping balances') // Map accounts with balances newState.accounts = accounts.map(account => { @@ -67,7 +62,6 @@ class ConnectHardwareForm extends Component { return account }) - console.log('[TREZOR]: ABOUT TO RENDER ACCOUNTS: ', page, newState.accounts) this.setState(newState) } }) -- cgit v1.2.3 From 9b81180ab10cf8ca59666104e862c0331e953591 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Tue, 10 Jul 2018 00:20:00 -0400 Subject: added ui to remove accounts --- ui/app/components/account-menu/index.js | 34 +++++++++++++++++++++++---- ui/app/css/itcss/components/account-menu.scss | 17 ++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) (limited to 'ui') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index be6963ac4..9530d6aeb 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -187,16 +187,42 @@ AccountMenu.prototype.renderAccounts = function () { h('div.account-menu__balance', formattedBalance), ]), - this.indicateIfLoose(keyring), + this.renderKeyringType(keyring), + this.renderForgetAccount(keyring, identity.address), ], ) }) } -AccountMenu.prototype.indicateIfLoose = function (keyring) { +AccountMenu.prototype.renderForgetAccount = function (keyring, address) { + // Any account that's not form the HD wallet can be forgotten + const type = keyring.type + const isForgetable = type !== 'HD Key Tree' + return isForgetable ? h('a.forget-account-icon', { onClick: (e) => this.forgetAccount(e, address) }, '') : null +} + +AccountMenu.prototype.forgetAccount = function (e, address) { + e.preventDefault() + e.stopPropagation() + console.log('should forget address: ', address) +} + +AccountMenu.prototype.renderKeyringType = function (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('imported')) : null + let label + switch (type) { + case 'Trezor Hardware': + label = this.context.t('hardware') + break + case 'Simple Key Pair': + label = this.context.t('imported') + break + default: + label = '' + } + + return label !== '' ? h('.keyring-label.allcaps', label) : null + } catch (e) { return } } diff --git a/ui/app/css/itcss/components/account-menu.scss b/ui/app/css/itcss/components/account-menu.scss index 96fba890c..20fc68424 100644 --- a/ui/app/css/itcss/components/account-menu.scss +++ b/ui/app/css/itcss/components/account-menu.scss @@ -72,6 +72,7 @@ background-color: $dusty-gray; color: $black; font-weight: normal; + letter-spacing: .5px; } } @@ -84,6 +85,22 @@ @media screen and (max-width: 575px) { padding: 12px 14px; } + + .forget-account-icon { + width: 25px; + margin-left: 10px; + } + + &:hover { + .forget-account-icon::after { + content: '\00D7'; + font-size: 25px; + color: $white; + cursor: pointer; + position: absolute; + margin-top: -5px; + } + } } &__account-info { -- cgit v1.2.3 From b9c2994d24e688305d63aaefd7fac88d88773ad9 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Tue, 10 Jul 2018 19:19:29 -0400 Subject: finish warning modal UI --- ui/app/components/account-menu/index.js | 5 ++ .../confirm-remove-account.component.js | 60 ++++++++++++++++++++++ .../confirm-remove-account.container.js | 13 +++++ .../modals/confirm-remove-account/index.js | 2 + ui/app/components/modals/index.scss | 11 ++++ ui/app/components/modals/modal.js | 19 ++++++- ui/app/css/itcss/components/account-menu.scss | 3 +- ui/app/css/itcss/components/new-account.scss | 1 + 8 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js create mode 100644 ui/app/components/modals/confirm-remove-account/confirm-remove-account.container.js create mode 100644 ui/app/components/modals/confirm-remove-account/index.js (limited to 'ui') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index 9530d6aeb..b561ea186 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -68,6 +68,9 @@ function mapDispatchToProps (dispatch) { dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, + showForgetAccountConfirmationModal: (address) => { + return dispatch(actions.showModal({ name: 'CONFIRM_FORGET_ACCOUNT', address })) + }, } } @@ -204,7 +207,9 @@ AccountMenu.prototype.renderForgetAccount = function (keyring, address) { AccountMenu.prototype.forgetAccount = function (e, address) { e.preventDefault() e.stopPropagation() + const { showForgetAccountConfirmationModal } = this.props console.log('should forget address: ', address) + showForgetAccountConfirmationModal(address) } AccountMenu.prototype.renderKeyringType = function (keyring) { diff --git a/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js b/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js new file mode 100644 index 000000000..93be2a4e7 --- /dev/null +++ b/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js @@ -0,0 +1,60 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import Button from '../../button' +import { addressSummary } from '../../../util' + +class ConfirmRemoveAccount extends Component { + static propTypes = { + hideModal: PropTypes.func.isRequired, + removeAccount: PropTypes.func.isRequired, + address: PropTypes.string.isRequired, + } + + static contextTypes = { + t: PropTypes.func, + } + + handleRemove () { + this.props.removeAccount(this.props.address) + .then(() => this.props.hideModal()) + } + + render () { + const { t } = this.context + + return ( +
+
+
+ { `${t('removeAccount')}` } +
+
+ {addressSummary(this.props.address)} +
+
+ { t('removeAccountDescription') } + { t('learnMore') } +
+
+
+ + +
+
+ ) + } +} + +export default ConfirmRemoveAccount diff --git a/ui/app/components/modals/confirm-remove-account/confirm-remove-account.container.js b/ui/app/components/modals/confirm-remove-account/confirm-remove-account.container.js new file mode 100644 index 000000000..9a612f2f6 --- /dev/null +++ b/ui/app/components/modals/confirm-remove-account/confirm-remove-account.container.js @@ -0,0 +1,13 @@ +import { connect } from 'react-redux' +import ConfirmRemoveAccount from './confirm-remove-account.component' + +const { hideModal, removeAccount } = require('../../../actions') + +const mapDispatchToProps = dispatch => { + return { + hideModal: () => dispatch(hideModal()), + removeAccount: (address) => dispatch(removeAccount(address)), + } +} + +export default connect(null, mapDispatchToProps)(ConfirmRemoveAccount) diff --git a/ui/app/components/modals/confirm-remove-account/index.js b/ui/app/components/modals/confirm-remove-account/index.js new file mode 100644 index 000000000..9763fbe05 --- /dev/null +++ b/ui/app/components/modals/confirm-remove-account/index.js @@ -0,0 +1,2 @@ +import ConfirmRemoveAccount from './confirm-remove-account.container' +module.exports = ConfirmRemoveAccount diff --git a/ui/app/components/modals/index.scss b/ui/app/components/modals/index.scss index ad6fe16d3..591e35148 100644 --- a/ui/app/components/modals/index.scss +++ b/ui/app/components/modals/index.scss @@ -17,6 +17,17 @@ text-align: center; font-size: .875rem; } + + &__address { + text-align: center; + font-size: 1rem; + margin-top: 20px; + margin-bottom: 20px; + } + + &__link { + color: #2f9ae0; + } &__content { overflow-y: auto; diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 85e85597a..758cfa4a2 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -1,4 +1,5 @@ -const Component = require('react').Component +const React = require('react') +const Component = React.Component const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect @@ -20,6 +21,7 @@ const HideTokenConfirmationModal = require('./hide-token-confirmation-modal') const CustomizeGasModal = require('../customize-gas-modal') const NotifcationModal = require('./notification-modal') const ConfirmResetAccount = require('./confirm-reset-account') +const ConfirmRemoveAccount = require('./confirm-remove-account') const TransactionConfirmed = require('./transaction-confirmed') const WelcomeBeta = require('./welcome-beta') const Notification = require('./notification') @@ -241,6 +243,19 @@ const MODALS = { }, }, + CONFIRM_FORGET_ACCOUNT: { + contents: h(ConfirmRemoveAccount), + mobileModalStyle: { + ...modalContainerMobileStyle, + }, + laptopModalStyle: { + ...modalContainerLaptopStyle, + }, + contentStyle: { + borderRadius: '8px', + }, + }, + NEW_ACCOUNT: { contents: [ h(NewAccountModal, {}, []), @@ -370,7 +385,7 @@ Modal.prototype.render = function () { backdropStyle: BACKDROPSTYLE, closeOnClick: !disableBackdropClick, }, - children, + React.cloneElement(children, {...this.props.modalState.props}, null), ) } diff --git a/ui/app/css/itcss/components/account-menu.scss b/ui/app/css/itcss/components/account-menu.scss index 20fc68424..ba5d176ef 100644 --- a/ui/app/css/itcss/components/account-menu.scss +++ b/ui/app/css/itcss/components/account-menu.scss @@ -88,7 +88,8 @@ .forget-account-icon { width: 25px; - margin-left: 10px; + padding-left: 10px; + height: 25px; } &:hover { diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index 7dfa839ab..66eb47378 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -156,6 +156,7 @@ .hw-connect { &__title { padding-top: 10px; + font-weight: 500; } &__msg { -- cgit v1.2.3 From 523cf9ad33d88719520ae5e7293329d133b64d4d Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Wed, 11 Jul 2018 00:20:40 -0400 Subject: account removal is working --- ui/app/actions.js | 21 +++++++++++++++++++++ ui/app/components/account-menu/index.js | 20 ++++++++++---------- .../confirm-remove-account.container.js | 8 +++++++- ui/app/components/modals/modal.js | 5 ++--- 4 files changed, 40 insertions(+), 14 deletions(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index f04de8fe8..3bdd548d3 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -83,6 +83,7 @@ var actions = { NEW_ACCOUNT_SCREEN: 'NEW_ACCOUNT_SCREEN', navigateToNewAccountScreen, resetAccount, + removeAccount, showNewVaultSeed: showNewVaultSeed, showInfoPage: showInfoPage, CLOSE_WELCOME_SCREEN: 'CLOSE_WELCOME_SCREEN', @@ -535,6 +536,26 @@ function resetAccount () { } } +function removeAccount (address) { + return dispatch => { + dispatch(actions.showLoadingIndication()) + + return new Promise((resolve, reject) => { + background.removeAccount(address, (err, account) => { + dispatch(actions.hideLoadingIndication()) + if (err) { + dispatch(actions.displayWarning(err.message)) + return reject(err) + } + + log.info('Account removed: ' + account) + dispatch(actions.showAccountsPage()) + resolve() + }) + }) + } +} + function addNewKeyring (type, opts) { return (dispatch) => { dispatch(actions.showLoadingIndication()) diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index b561ea186..73450c1bd 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -68,7 +68,7 @@ function mapDispatchToProps (dispatch) { dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, - showForgetAccountConfirmationModal: (address) => { + showRemoveAccountConfirmationModal: (address) => { return dispatch(actions.showModal({ name: 'CONFIRM_FORGET_ACCOUNT', address })) }, } @@ -156,7 +156,8 @@ AccountMenu.prototype.renderAccounts = function () { } = this.props const accountOrder = keyrings.reduce((list, keyring) => list.concat(keyring.accounts), []) - return accountOrder.map((address) => { + return accountOrder.filter(address => !!identities[address]).map((address) => { + const identity = identities[address] const isSelected = identity.address === selectedAddress @@ -191,25 +192,24 @@ AccountMenu.prototype.renderAccounts = function () { ]), this.renderKeyringType(keyring), - this.renderForgetAccount(keyring, identity.address), + this.renderRemoveAccount(keyring, identity.address), ], ) }) } -AccountMenu.prototype.renderForgetAccount = function (keyring, address) { +AccountMenu.prototype.renderRemoveAccount = function (keyring, address) { // Any account that's not form the HD wallet can be forgotten const type = keyring.type - const isForgetable = type !== 'HD Key Tree' - return isForgetable ? h('a.forget-account-icon', { onClick: (e) => this.forgetAccount(e, address) }, '') : null + const isRemovable = type !== 'HD Key Tree' + return isRemovable ? h('a.forget-account-icon', { onClick: (e) => this.removeAccount(e, address) }, '') : null } -AccountMenu.prototype.forgetAccount = function (e, address) { +AccountMenu.prototype.removeAccount = function (e, address) { e.preventDefault() e.stopPropagation() - const { showForgetAccountConfirmationModal } = this.props - console.log('should forget address: ', address) - showForgetAccountConfirmationModal(address) + const { showRemoveAccountConfirmationModal } = this.props + showRemoveAccountConfirmationModal(address) } AccountMenu.prototype.renderKeyringType = function (keyring) { diff --git a/ui/app/components/modals/confirm-remove-account/confirm-remove-account.container.js b/ui/app/components/modals/confirm-remove-account/confirm-remove-account.container.js index 9a612f2f6..fcb149b3f 100644 --- a/ui/app/components/modals/confirm-remove-account/confirm-remove-account.container.js +++ b/ui/app/components/modals/confirm-remove-account/confirm-remove-account.container.js @@ -3,6 +3,12 @@ import ConfirmRemoveAccount from './confirm-remove-account.component' const { hideModal, removeAccount } = require('../../../actions') +const mapStateToProps = state => { + return { + address: state.appState.modal.modalState.props.address, + } +} + const mapDispatchToProps = dispatch => { return { hideModal: () => dispatch(hideModal()), @@ -10,4 +16,4 @@ const mapDispatchToProps = dispatch => { } } -export default connect(null, mapDispatchToProps)(ConfirmRemoveAccount) +export default connect(mapStateToProps, mapDispatchToProps)(ConfirmRemoveAccount) diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 758cfa4a2..9ace56661 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -1,5 +1,4 @@ -const React = require('react') -const Component = React.Component +const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect @@ -385,7 +384,7 @@ Modal.prototype.render = function () { backdropStyle: BACKDROPSTYLE, closeOnClick: !disableBackdropClick, }, - React.cloneElement(children, {...this.props.modalState.props}, null), + children, ) } -- cgit v1.2.3 From 5a2a34591f8ab2aec3a056d5bb9e38ba5236cd07 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Wed, 11 Jul 2018 01:35:37 -0400 Subject: clean up --- ui/app/components/account-menu/index.js | 6 +++--- ui/app/components/modals/modal.js | 2 +- ui/app/css/itcss/components/account-menu.scss | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'ui') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index 73450c1bd..c15ecbc9c 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -69,7 +69,7 @@ function mapDispatchToProps (dispatch) { dispatch(actions.toggleAccountMenu()) }, showRemoveAccountConfirmationModal: (address) => { - return dispatch(actions.showModal({ name: 'CONFIRM_FORGET_ACCOUNT', address })) + return dispatch(actions.showModal({ name: 'CONFIRM_REMOVE_ACCOUNT', address })) }, } } @@ -199,10 +199,10 @@ AccountMenu.prototype.renderAccounts = function () { } AccountMenu.prototype.renderRemoveAccount = function (keyring, address) { - // Any account that's not form the HD wallet can be forgotten + // Any account that's not from the HD wallet Keyring can be removed const type = keyring.type const isRemovable = type !== 'HD Key Tree' - return isRemovable ? h('a.forget-account-icon', { onClick: (e) => this.removeAccount(e, address) }, '') : null + return isRemovable ? h('a.remove-account-icon', { onClick: (e) => this.removeAccount(e, address) }, '') : null } AccountMenu.prototype.removeAccount = function (e, address) { diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 9ace56661..e40944165 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -242,7 +242,7 @@ const MODALS = { }, }, - CONFIRM_FORGET_ACCOUNT: { + CONFIRM_REMOVE_ACCOUNT: { contents: h(ConfirmRemoveAccount), mobileModalStyle: { ...modalContainerMobileStyle, diff --git a/ui/app/css/itcss/components/account-menu.scss b/ui/app/css/itcss/components/account-menu.scss index ba5d176ef..9bce812e6 100644 --- a/ui/app/css/itcss/components/account-menu.scss +++ b/ui/app/css/itcss/components/account-menu.scss @@ -86,14 +86,14 @@ padding: 12px 14px; } - .forget-account-icon { + .remove-account-icon { width: 25px; padding-left: 10px; height: 25px; } &:hover { - .forget-account-icon::after { + .remove-account-icon::after { content: '\00D7'; font-size: 25px; color: $white; -- cgit v1.2.3 From 80e875308b4447ed38d7e0f677570d73956dd9de Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Wed, 11 Jul 2018 21:21:36 -0400 Subject: forget device and autiload account features added --- ui/app/actions.js | 44 ++++++++++++++++++++++ .../connect-hardware/account-list.js | 10 +++++ .../pages/create-account/connect-hardware/index.js | 31 ++++++++++++++- ui/app/css/itcss/components/new-account.scss | 11 ++++++ 4 files changed, 95 insertions(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index 3bdd548d3..9330a864b 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -79,6 +79,8 @@ var actions = { importNewAccount, addNewAccount, connectHardware, + checkHardwareStatus, + forgetDevice, unlockTrezorAccount, NEW_ACCOUNT_SCREEN: 'NEW_ACCOUNT_SCREEN', navigateToNewAccountScreen, @@ -622,6 +624,48 @@ function addNewAccount () { } } +function checkHardwareStatus (deviceName) { + log.debug(`background.checkHardwareStatus`, deviceName) + return (dispatch, getState) => { + dispatch(actions.showLoadingIndication()) + return new Promise((resolve, reject) => { + background.checkHardwareStatus(deviceName, (err, unlocked) => { + if (err) { + log.error(err) + dispatch(actions.displayWarning(err.message)) + return reject(err) + } + + dispatch(actions.hideLoadingIndication()) + + forceUpdateMetamaskState(dispatch) + return resolve(unlocked) + }) + }) + } +} + +function forgetDevice (deviceName) { + log.debug(`background.forgetDevice`, deviceName) + return (dispatch, getState) => { + dispatch(actions.showLoadingIndication()) + return new Promise((resolve, reject) => { + background.forgetDevice(deviceName, (err, response) => { + if (err) { + log.error(err) + dispatch(actions.displayWarning(err.message)) + return reject(err) + } + + dispatch(actions.hideLoadingIndication()) + + forceUpdateMetamaskState(dispatch) + return resolve() + }) + }) + } +} + function connectHardware (deviceName, page) { log.debug(`background.connectHardware`, deviceName, page) return (dispatch, getState) => { diff --git a/ui/app/components/pages/create-account/connect-hardware/account-list.js b/ui/app/components/pages/create-account/connect-hardware/account-list.js index 170d8f0b3..3bd6a00a7 100644 --- a/ui/app/components/pages/create-account/connect-hardware/account-list.js +++ b/ui/app/components/pages/create-account/connect-hardware/account-list.js @@ -90,11 +90,20 @@ class AccountList extends Component { ]) } + renderForgetDevice () { + return h('div.hw-forget-device-container', {}, [ + h('a', { + onClick: this.props.onForgetDevice.bind(this), + }, this.context.t('forgetDevice')), + ]) + } + render () { return h('div', {}, [ this.renderAccounts(), this.renderPagination(), this.renderButtons(), + this.renderForgetDevice(), ]) } @@ -104,6 +113,7 @@ class AccountList extends Component { AccountList.propTypes = { accounts: PropTypes.array.isRequired, onAccountChange: PropTypes.func.isRequired, + onForgetDevice: PropTypes.func.isRequired, getPage: PropTypes.func.isRequired, network: PropTypes.string, selectedAccount: PropTypes.string, diff --git a/ui/app/components/pages/create-account/connect-hardware/index.js b/ui/app/components/pages/create-account/connect-hardware/index.js index 126102235..9aef36cfb 100644 --- a/ui/app/components/pages/create-account/connect-hardware/index.js +++ b/ui/app/components/pages/create-account/connect-hardware/index.js @@ -13,13 +13,19 @@ class ConnectHardwareForm extends Component { super(props) this.state = { error: null, - response: null, btnText: context.t('connectToTrezor'), selectedAccount: null, accounts: [], } } + async componentDidMount () { + const unlocked = await this.props.checkHardwareStatus('trezor') + if (unlocked) { + this.getPage(0) + } + } + connectToTrezor = () => { if (this.state.accounts.length) { return null @@ -70,6 +76,20 @@ class ConnectHardwareForm extends Component { }) } + onForgetDevice = () => { + this.props.forgetDevice('trezor') + .then(_ => { + this.setState({ + error: null, + btnText: this.context.t('connectToTrezor'), + selectedAccount: null, + accounts: [], + }) + }).catch(e => { + this.setState({ error: e.toString() }) + }) + } + onUnlockAccount = () => { if (this.state.selectedAccount === null) { @@ -110,6 +130,7 @@ class ConnectHardwareForm extends Component { getPage: this.getPage, history: this.props.history, onUnlockAccount: this.onUnlockAccount, + onForgetDevice: this.onForgetDevice, onCancel: this.onCancel, }) } @@ -127,6 +148,8 @@ ConnectHardwareForm.propTypes = { showImportPage: PropTypes.func, showConnectPage: PropTypes.func, connectHardware: PropTypes.func, + checkHardwareStatus: PropTypes.func, + forgetDevice: PropTypes.func, unlockTrezorAccount: PropTypes.func, numberOfExistingAccounts: PropTypes.number, history: PropTypes.object, @@ -154,6 +177,12 @@ const mapDispatchToProps = dispatch => { connectHardware: (deviceName, page) => { return dispatch(actions.connectHardware(deviceName, page)) }, + checkHardwareStatus: (deviceName) => { + return dispatch(actions.checkHardwareStatus(deviceName)) + }, + forgetDevice: (deviceName) => { + return dispatch(actions.forgetDevice(deviceName)) + }, unlockTrezorAccount: index => { return dispatch(actions.unlockTrezorAccount(index)) }, diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index 66eb47378..e11c10dfe 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -270,6 +270,17 @@ } } +.hw-forget-device-container { + display: flex; + flex-flow: column; + align-items: center; + padding: 30px 30px 0; + + a { + color: #2f9ae0; + cursor: pointer; + } +} .new-account-create-form { display: flex; -- cgit v1.2.3 From 2a0a7853249284cb27831890f3b62847ea27eb83 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Thu, 12 Jul 2018 00:23:08 -0400 Subject: added tooltip --- ui/app/components/account-menu/index.js | 13 ++++++++++++- .../confirm-remove-account.component.js | 2 +- ui/app/css/itcss/components/account-menu.scss | 6 +++--- 3 files changed, 16 insertions(+), 5 deletions(-) (limited to 'ui') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index c15ecbc9c..c5b577cfd 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -11,6 +11,7 @@ const Identicon = require('../identicon') const { formatBalance } = require('../../util') const { ENVIRONMENT_TYPE_POPUP } = require('../../../../app/scripts/lib/enums') const { getEnvironmentType } = require('../../../../app/scripts/lib/util') +const Tooltip = require('../tooltip') const { @@ -202,7 +203,17 @@ AccountMenu.prototype.renderRemoveAccount = function (keyring, address) { // Any account that's not from the HD wallet Keyring can be removed const type = keyring.type const isRemovable = type !== 'HD Key Tree' - return isRemovable ? h('a.remove-account-icon', { onClick: (e) => this.removeAccount(e, address) }, '') : null + if (isRemovable) { + return h(Tooltip, { + title: this.context.t('removeAccount'), + position: 'bottom', + }, [ + h('a.remove-account-icon', { + onClick: (e) => this.removeAccount(e, address), + }, ''), + ]) + } + return null } AccountMenu.prototype.removeAccount = function (e, address) { diff --git a/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js b/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js index 93be2a4e7..d6c0c796d 100644 --- a/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js +++ b/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js @@ -26,7 +26,7 @@ class ConfirmRemoveAccount extends Component {
- { `${t('removeAccount')}` } + { `${t('removeAccount')}` }?
{addressSummary(this.props.address)} diff --git a/ui/app/css/itcss/components/account-menu.scss b/ui/app/css/itcss/components/account-menu.scss index 9bce812e6..b14753e23 100644 --- a/ui/app/css/itcss/components/account-menu.scss +++ b/ui/app/css/itcss/components/account-menu.scss @@ -87,9 +87,9 @@ } .remove-account-icon { - width: 25px; - padding-left: 10px; - height: 25px; + width: 15px; + margin-left: 10px; + height: 15px; } &:hover { -- cgit v1.2.3 From 4b528405eac7cea54c743307e6f577abd6ce9507 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Thu, 12 Jul 2018 13:19:51 -0400 Subject: catching up with develop --- ui/app/components/account-menu/index.js | 14 +++---- .../confirm-remove-account.component.js | 44 +++++++++++++++++++--- .../confirm-remove-account.container.js | 3 +- 3 files changed, 48 insertions(+), 13 deletions(-) (limited to 'ui') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index c5b577cfd..fc48b60f3 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -69,8 +69,8 @@ function mapDispatchToProps (dispatch) { dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, - showRemoveAccountConfirmationModal: (address) => { - return dispatch(actions.showModal({ name: 'CONFIRM_REMOVE_ACCOUNT', address })) + showRemoveAccountConfirmationModal: (identity) => { + return dispatch(actions.showModal({ name: 'CONFIRM_REMOVE_ACCOUNT', identity })) }, } } @@ -193,13 +193,13 @@ AccountMenu.prototype.renderAccounts = function () { ]), this.renderKeyringType(keyring), - this.renderRemoveAccount(keyring, identity.address), + this.renderRemoveAccount(keyring, identity), ], ) }) } -AccountMenu.prototype.renderRemoveAccount = function (keyring, address) { +AccountMenu.prototype.renderRemoveAccount = function (keyring, identity) { // Any account that's not from the HD wallet Keyring can be removed const type = keyring.type const isRemovable = type !== 'HD Key Tree' @@ -209,18 +209,18 @@ AccountMenu.prototype.renderRemoveAccount = function (keyring, address) { position: 'bottom', }, [ h('a.remove-account-icon', { - onClick: (e) => this.removeAccount(e, address), + onClick: (e) => this.removeAccount(e, identity), }, ''), ]) } return null } -AccountMenu.prototype.removeAccount = function (e, address) { +AccountMenu.prototype.removeAccount = function (e, identity) { e.preventDefault() e.stopPropagation() const { showRemoveAccountConfirmationModal } = this.props - showRemoveAccountConfirmationModal(address) + showRemoveAccountConfirmationModal(identity) } AccountMenu.prototype.renderKeyringType = function (keyring) { diff --git a/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js b/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js index d6c0c796d..b9dc6364f 100644 --- a/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js +++ b/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js @@ -2,12 +2,15 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import Button from '../../button' import { addressSummary } from '../../../util' +import Identicon from '../../identicon' +import genAccountLink from '../../../../lib/account-link' class ConfirmRemoveAccount extends Component { static propTypes = { hideModal: PropTypes.func.isRequired, removeAccount: PropTypes.func.isRequired, - address: PropTypes.string.isRequired, + identity: PropTypes.object.isRequired, + network: PropTypes.string.isRequired, } static contextTypes = { @@ -15,10 +18,43 @@ class ConfirmRemoveAccount extends Component { } handleRemove () { - this.props.removeAccount(this.props.address) + this.props.removeAccount(this.props.identity.address) .then(() => this.props.hideModal()) } + renderSelectedAccount () { + const { identity } = this.props + return ( +
+
+ +
+
+ Name + {identity.name} +
+
+ Public Address + { addressSummary(identity.address) } +
+
+ + + +
+
+ ) + } + render () { const { t } = this.context @@ -28,9 +64,7 @@ class ConfirmRemoveAccount extends Component {
{ `${t('removeAccount')}` }?
-
- {addressSummary(this.props.address)} -
+ { this.renderSelectedAccount() }
{ t('removeAccountDescription') } { t('learnMore') } diff --git a/ui/app/components/modals/confirm-remove-account/confirm-remove-account.container.js b/ui/app/components/modals/confirm-remove-account/confirm-remove-account.container.js index fcb149b3f..4b194c995 100644 --- a/ui/app/components/modals/confirm-remove-account/confirm-remove-account.container.js +++ b/ui/app/components/modals/confirm-remove-account/confirm-remove-account.container.js @@ -5,7 +5,8 @@ const { hideModal, removeAccount } = require('../../../actions') const mapStateToProps = state => { return { - address: state.appState.modal.modalState.props.address, + identity: state.appState.modal.modalState.props.identity, + network: state.metamask.network, } } -- cgit v1.2.3 From 5710e648bd77aa7be6e9a4ba1d7d3fe4ea20c010 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Thu, 12 Jul 2018 18:19:33 -0400 Subject: remove account modal updated --- .../confirm-remove-account.component.js | 19 ++++---- ui/app/components/modals/index.scss | 51 +++++++++++++++++++--- 2 files changed, 55 insertions(+), 15 deletions(-) (limited to 'ui') diff --git a/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js b/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js index b9dc6364f..5a9f0f289 100644 --- a/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js +++ b/ui/app/components/modals/confirm-remove-account/confirm-remove-account.component.js @@ -25,25 +25,24 @@ class ConfirmRemoveAccount extends Component { renderSelectedAccount () { const { identity } = this.props return ( -
-
+
+
-
- Name +
+ Name {identity.name}
-
- Public Address - { addressSummary(identity.address) } +
+ Public Address + { addressSummary(identity.address, 4, 4) }
-
+
Date: Fri, 13 Jul 2018 00:09:42 -0400 Subject: fix account balance bug --- ui/app/components/modals/index.scss | 2 +- .../pages/create-account/connect-hardware/index.js | 24 ++++++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) (limited to 'ui') diff --git a/ui/app/components/modals/index.scss b/ui/app/components/modals/index.scss index 1cefcb49c..e198cca44 100644 --- a/ui/app/components/modals/index.scss +++ b/ui/app/components/modals/index.scss @@ -53,7 +53,7 @@ } &__link { - margin-top: 16px; + margin-top: 14px; img { width: 15px; diff --git a/ui/app/components/pages/create-account/connect-hardware/index.js b/ui/app/components/pages/create-account/connect-hardware/index.js index 9aef36cfb..fa9cf4894 100644 --- a/ui/app/components/pages/create-account/connect-hardware/index.js +++ b/ui/app/components/pages/create-account/connect-hardware/index.js @@ -19,6 +19,18 @@ class ConnectHardwareForm extends Component { } } + componentWillReceiveProps (nextProps) { + const { accounts } = nextProps + const newAccounts = this.state.accounts.map(a => { + const normalizedAddress = a.address.toLowerCase() + const balanceValue = accounts[normalizedAddress] && accounts[normalizedAddress].balance || null + a.balance = balanceValue ? formatBalance(balanceValue, 6) : '...' + return a + }) + this.setState({accounts: newAccounts}) + } + + async componentDidMount () { const unlocked = await this.props.checkHardwareStatus('trezor') if (unlocked) { @@ -38,14 +50,6 @@ class ConnectHardwareForm extends Component { this.setState({selectedAccount: account.toString(), error: null}) } - getBalance (address) { - // Get the balance - const { accounts } = this.props - const balanceValue = accounts && accounts[address.toLowerCase()] ? accounts[address.toLowerCase()].balance : '' - const formattedBalance = balanceValue !== null ? formatBalance(balanceValue, 6) : '...' - return formattedBalance - } - getPage = (page) => { this.props .connectHardware('trezor', page) @@ -64,7 +68,9 @@ class ConnectHardwareForm extends Component { // Map accounts with balances newState.accounts = accounts.map(account => { - account.balance = this.getBalance(account.address) + const normalizedAddress = account.address.toLowerCase() + const balanceValue = this.props.accounts[normalizedAddress] && this.props.accounts[normalizedAddress].balance || null + account.balance = balanceValue ? formatBalance(balanceValue, 6) : '...' return account }) -- cgit v1.2.3 From 82a93bb2872809df19744afdd95c68485c0dcd25 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Fri, 13 Jul 2018 02:03:54 -0400 Subject: detect ability to open popup instead of browser --- .../create-account/connect-hardware/connect-screen.js | 14 ++++++++------ .../pages/create-account/connect-hardware/index.js | 5 +++++ 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js index dd9fdfba2..0dd8e285b 100644 --- a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js @@ -16,9 +16,11 @@ class ConnectScreen extends Component { ]), h( 'button.btn-primary.btn--large', - { onClick: () => global.platform.openWindow({ - url: 'https://google.com/chrome', - }), style: { margin: 12 } }, + { + onClick: () => global.platform.openWindow({ + url: 'https://google.com/chrome', + }), + }, this.context.t('downloadGoogleChrome') ), ]) @@ -49,8 +51,7 @@ class ConnectScreen extends Component { } render () { - const isChrome = window.navigator.userAgent.search('Chrome') !== -1 - if (isChrome) { + if (this.props.browserSupported) { return this.renderConnectScreen() } return this.renderUnsupportedBrowser() @@ -59,7 +60,8 @@ class ConnectScreen extends Component { ConnectScreen.propTypes = { connectToTrezor: PropTypes.func.isRequired, - btnText: PropTypes.string, + btnText: PropTypes.string.isRequired, + browserSupported: PropTypes.bool.isRequired, } ConnectScreen.contextTypes = { diff --git a/ui/app/components/pages/create-account/connect-hardware/index.js b/ui/app/components/pages/create-account/connect-hardware/index.js index fa9cf4894..689e88f2e 100644 --- a/ui/app/components/pages/create-account/connect-hardware/index.js +++ b/ui/app/components/pages/create-account/connect-hardware/index.js @@ -16,6 +16,7 @@ class ConnectHardwareForm extends Component { btnText: context.t('connectToTrezor'), selectedAccount: null, accounts: [], + browserSupported: true, } } @@ -78,6 +79,9 @@ class ConnectHardwareForm extends Component { } }) .catch(e => { + if (e === 'Window blocked') { + this.setState({ browserSupported: false }) + } this.setState({ btnText: this.context.t('connectToTrezor') }) }) } @@ -125,6 +129,7 @@ class ConnectHardwareForm extends Component { return h(ConnectScreen, { connectToTrezor: this.connectToTrezor, btnText: this.state.btnText, + browserSupported: this.state.browserSupported, }) } -- cgit v1.2.3 From 53995463883c062157a3d725e7cb8fe54486badb Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Fri, 13 Jul 2018 13:49:20 -0400 Subject: added affiliate link to trezor --- .../create-account/connect-hardware/connect-screen.js | 6 ++++++ ui/app/css/itcss/components/new-account.scss | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js index 0dd8e285b..8d9980b10 100644 --- a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js @@ -46,6 +46,12 @@ class ConnectScreen extends Component { { onClick: this.props.connectToTrezor.bind(this) }, this.props.btnText ), + h('div.hw-connect__get-trezor', {}, [ + h('a', { + href: 'https://shop.trezor.io/?a=metamask', + target: '_blank', + }, this.context.t('getYourTrezor')), + ]), ]) ) } diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index e11c10dfe..4552f0bf2 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -169,6 +169,21 @@ &__link { color: #2f9ae0; } + + &__get-trezor { + display: flex; + flex-flow: column; + align-items: center; + padding: 30px 30px 0; + width: 305px; + + a { + font-size: 14px; + text-align: center; + color: #2f9ae0; + cursor: pointer; + } + } } .hw-account-list { @@ -278,6 +293,7 @@ a { color: #2f9ae0; + font-size: 14px; cursor: pointer; } } -- cgit v1.2.3 From 55382e9842c4f4136c88e441298193cc7abd8ba9 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Fri, 13 Jul 2018 15:19:21 -0400 Subject: fix account selection --- ui/app/components/pages/create-account/connect-hardware/index.js | 8 ++++++-- ui/app/css/itcss/components/new-account.scss | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/index.js b/ui/app/components/pages/create-account/connect-hardware/index.js index 689e88f2e..dc9907f31 100644 --- a/ui/app/components/pages/create-account/connect-hardware/index.js +++ b/ui/app/components/pages/create-account/connect-hardware/index.js @@ -59,8 +59,11 @@ class ConnectHardwareForm extends Component { const newState = {} // Default to the first account if (this.state.selectedAccount === null) { - const firstAccount = accounts[0] - newState.selectedAccount = firstAccount.index.toString() === '0' ? firstAccount.index.toString() : null + accounts.forEach((a, i) => { + if (a.address.toLowerCase() === this.props.address) { + newState.selectedAccount = a.index.toString() + } + }) // If the page doesn't contain the selected account, let's deselect it } else if (!accounts.filter(a => a.index.toString() === this.state.selectedAccount).length) { newState.selectedAccount = null @@ -167,6 +170,7 @@ ConnectHardwareForm.propTypes = { t: PropTypes.func, network: PropTypes.string, accounts: PropTypes.object, + address: PropTypes.string, } const mapStateToProps = state => { diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index 4552f0bf2..a44fab3be 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -242,7 +242,7 @@ &__item__index { display: flex; - margin-right: 20px; + width: 28px; } &__item__radio { @@ -337,4 +337,8 @@ width: 150px; min-width: initial; } + + &__button.btn-primary--disabled { + cursor: 'not-allowed'; + } } -- cgit v1.2.3 From cb97517b26a7732cbb7c4a9f30f85b5fa596e608 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Tue, 17 Jul 2018 18:53:37 -0400 Subject: updated account list based on new designs --- .../connect-hardware/account-list.js | 38 ++++++++---- .../connect-hardware/connect-screen.js | 2 +- .../pages/create-account/connect-hardware/index.js | 2 +- ui/app/css/itcss/components/new-account.scss | 68 ++++++++++++++++++---- 4 files changed, 85 insertions(+), 25 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/account-list.js b/ui/app/components/pages/create-account/connect-hardware/account-list.js index 3bd6a00a7..06102e16f 100644 --- a/ui/app/components/pages/create-account/connect-hardware/account-list.js +++ b/ui/app/components/pages/create-account/connect-hardware/account-list.js @@ -8,16 +8,20 @@ class AccountList extends Component { super(props) } + renderHeader () { + return ( + h('div.hw-connect', [ + h('h3.hw-connect__title', {}, this.context.t('selectAnAccount')), + h('p.hw-connect__msg', {}, this.context.t('selectAnAccountHelp')), + ]) + ) + } + renderAccounts () { return h('div.hw-account-list', [ - h('div.hw-account-list__title_wrapper', [ - h('div.hw-account-list__title', {}, [this.context.t('selectAnAddress')]), - h('div.hw-account-list__device', {}, ['Trezor - ETH']), - ]), this.props.accounts.map((a, i) => { return h('div.hw-account-list__item', { key: a.address }, [ - h('span.hw-account-list__item__index', a.index + 1), h('div.hw-account-list__item__radio', [ h('input', { type: 'radio', @@ -32,10 +36,12 @@ class AccountList extends Component { { htmlFor: `address-${i}`, }, - `${a.address.slice(0, 4)}...${a.address.slice(-4)}` - ), + [ + h('span.hw-account-list__item__index', a.index + 1), + `${a.address.slice(0, 4)}...${a.address.slice(-4)}`, + h('span.hw-account-list__item__balance', `${a.balance}`), + ]), ]), - h('span.hw-account-list__item__balance', `${a.balance}`), h( 'a.hw-account-list__item__link', { @@ -71,9 +77,15 @@ class AccountList extends Component { } renderButtons () { - return h('div.new-account-create-form__buttons', {}, [ + const disabled = this.props.selectedAccount === null + const buttonProps = {} + if (disabled) { + buttonProps.disabled = true + } + + return h('div.new-account-connect-form__buttons', {}, [ h( - 'button.btn-default.btn--large.new-account-create-form__button', + 'button.btn-default.btn--large.new-account-connect-form__button', { onClick: this.props.onCancel.bind(this), }, @@ -81,9 +93,10 @@ class AccountList extends Component { ), h( - `button.btn-primary.btn--large.new-account-create-form__button ${this.props.selectedAccount === null ? '.btn-primary--disabled' : ''}`, + `button.btn-primary.btn--large.new-account-connect-form__button ${disabled ? '.btn-primary--disabled' : ''}`, { onClick: this.props.onUnlockAccount.bind(this), + ...buttonProps, }, [this.context.t('unlock')] ), @@ -99,7 +112,8 @@ class AccountList extends Component { } render () { - return h('div', {}, [ + return h('div.new-account-connect-form', {}, [ + this.renderHeader(), this.renderAccounts(), this.renderPagination(), this.renderButtons(), diff --git a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js index 8d9980b10..7fb36b511 100644 --- a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js @@ -29,7 +29,7 @@ class ConnectScreen extends Component { renderConnectScreen () { return ( - h('div', {}, [ + h('div.new-account-connect-form', {}, [ h('div.hw-connect', [ h('h3.hw-connect__title', {}, this.context.t('trezorHardwareWallet')), h('p.hw-connect__msg', {}, this.context.t('connectToTrezorHelp')), diff --git a/ui/app/components/pages/create-account/connect-hardware/index.js b/ui/app/components/pages/create-account/connect-hardware/index.js index dc9907f31..da42ddead 100644 --- a/ui/app/components/pages/create-account/connect-hardware/index.js +++ b/ui/app/components/pages/create-account/connect-hardware/index.js @@ -150,7 +150,7 @@ class ConnectHardwareForm extends Component { } render () { - return h('div.new-account-create-form', [ + return h('div', [ this.renderError(), this.renderContent(), ]) diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index a44fab3be..0eacf4615 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -157,13 +157,14 @@ &__title { padding-top: 10px; font-weight: 500; + font-size: 18px; } &__msg { font-size: 14px; color: #9b9b9b; - margin-top: 15px; - margin-bottom: 15px; + margin-top: 10px; + margin-bottom: 20px; } &__link { @@ -242,12 +243,16 @@ &__item__index { display: flex; - width: 28px; + width: 24px; } &__item__radio { display: flex; flex: 1; + + input { + margin-right: 9px; + } } &__item__label { @@ -264,6 +269,7 @@ &__item__link { display: flex; + margin-top: 3px; } &__item__link img { @@ -278,11 +284,55 @@ margin-top: 10px; &__button { - height: 25px; - flex: initial; - min-width: 90px; - font-size: 12px; + height: 19px; + display: flex; + width: 47px; + color: #33a4e7; + font-size: 14px; + line-height: 19px; + border: none; + min-width: 46px; + margin-right: 0px; + margin-left: 16px; + padding: 0px; + } +} + +.new-account-connect-form { + display: flex; + flex-flow: column; + align-items: center; + padding: 15px 30px 0; + + &__buttons { + margin-top: 39px; + display: flex; + width: 100%; + justify-content: space-between; + } + + &__button { + width: 150px; + min-width: initial; + } + + &__button.btn-primary { + background-color: #259DE5; + } + + &__button.btn-primary { + background-color: #259DE5; + color: #FFFFFF; } + + &__button.btn-primary--disabled { + cursor: not-allowed; + opacity: .5; + } + + + + } .hw-forget-device-container { @@ -337,8 +387,4 @@ width: 150px; min-width: initial; } - - &__button.btn-primary--disabled { - cursor: 'not-allowed'; - } } -- cgit v1.2.3 From cbb14f1d5e50c10865838a98452ecfb4b6cb8d6a Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Tue, 17 Jul 2018 21:57:19 -0400 Subject: fix browser not supported screen --- .../components/pages/create-account/connect-hardware/connect-screen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js index 7fb36b511..d4c479a58 100644 --- a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js @@ -9,7 +9,7 @@ class ConnectScreen extends Component { renderUnsupportedBrowser () { return ( - h('div', {}, [ + h('div.new-account-connect-form', {}, [ h('div.hw-connect', [ h('h3.hw-connect__title', {}, this.context.t('browserNotSupported')), h('p.hw-connect__msg', {}, this.context.t('chromeRequiredForTrezor')), -- cgit v1.2.3 From 49d1bdea8a47139cc814d3c49aa97bf2d542d3d5 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Wed, 18 Jul 2018 22:57:47 -0400 Subject: design done --- ui/app/components/account-menu/index.js | 2 +- .../connect-hardware/connect-screen.js | 109 +++++++++++++++----- ui/app/css/itcss/components/new-account.scss | 111 +++++++++++++++++---- 3 files changed, 178 insertions(+), 44 deletions(-) (limited to 'ui') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index fc48b60f3..9c063d31e 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -125,7 +125,7 @@ AccountMenu.prototype.render = function () { } }, icon: h('img.account-menu__item-icon', { src: 'images/connect-icon.svg' }), - text: this.context.t('connectHardware'), + text: this.context.t('connectHardwareWallet'), }), h(Divider), h(Item, { diff --git a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js index d4c479a58..47288c73f 100644 --- a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js @@ -27,34 +27,97 @@ class ConnectScreen extends Component { ) } + renderHeader () { + return ( + h('div.hw-connect__header', {}, [ + h('h3.hw-connect__header__title', {}, this.context.t(`hardwareSupport`)), + h('p.hw-connect__header__msg', {}, this.context.t(`hardwareSupportMsg`)), + ]) + ) + } + + renderTrezorAffiliateLink () { + return h('div.hw-connect__get-trezor', {}, [ + h('p.hw-connect__get-trezor__msg', {}, this.context.t(`dontHaveATrezorWallet`)), + h('a.hw-connect__get-trezor__link', { + href: 'https://shop.trezor.io/?a=metamask', + target: '_blank', + }, this.context.t('orderOneHere')), + ]) + } + + renderConnectToTrezorButton () { + return h( + 'button.btn-primary.btn--large', + { onClick: this.props.connectToTrezor.bind(this) }, + this.props.btnText + ) + } + + renderLearnMore () { + return ( + h('p.hw-connect__learn-more', {}, [ + this.context.t('learnMore'), + h('img.hw-connect__learn-more__arrow', { src: 'images/caret-right.svg'}), + ]) + ) + } + + renderTutorialSteps () { + const steps = [ + { + asset: 'hardware-wallet-step-1', + dimensions: {width: '225px', height: '75px'}, + }, + { + asset: 'hardware-wallet-step-2', + dimensions: {width: '300px', height: '100px'}, + }, + { + asset: 'hardware-wallet-step-3', + dimensions: {width: '120px', height: '90px'}, + }, + ] + + return h('.hw-tutorial', {}, + steps.map((step, i) => ( + h('div.hw-connect', [ + h('h3.hw-connect__title', {}, this.context.t(`step${i + 1}HardwareWallet`)), + h('p.hw-connect__msg', {}, this.context.t(`step${i + 1}HardwareWalletMsg`)), + h('img.hw-connect__step-asset', { src: `images/${step.asset}.svg`, ...step.dimensions }), + ]) + )) + ) + } + + renderFooter () { + return ( + h('div.hw-connect__footer', {}, [ + h('h3.hw-connect__footer__title', {}, this.context.t(`readyToConnect`)), + this.renderConnectToTrezorButton(), + h('p.hw-connect__footer__msg', {}, [ + this.context.t(`havingTroubleConnecting`), + h('a.hw-connect__footer__link', { + href: '#', + target: '_blank', + }, this.context.t('getHelp')), + ]), + ]) + ) + } + renderConnectScreen () { return ( h('div.new-account-connect-form', {}, [ - h('div.hw-connect', [ - h('h3.hw-connect__title', {}, this.context.t('trezorHardwareWallet')), - h('p.hw-connect__msg', {}, this.context.t('connectToTrezorHelp')), - h('p.hw-connect__msg', {}, [ - this.context.t('connectToTrezorTrouble'), - h('a.hw-connect__link', { - href: 'https://support.metamask.io/', - target: '_blank', - }, ` ${this.context.t('learnMore')}`), - ]), - ]), - h( - 'button.btn-primary.btn--large', - { onClick: this.props.connectToTrezor.bind(this) }, - this.props.btnText - ), - h('div.hw-connect__get-trezor', {}, [ - h('a', { - href: 'https://shop.trezor.io/?a=metamask', - target: '_blank', - }, this.context.t('getYourTrezor')), - ]), + this.renderHeader(), + this.renderTrezorAffiliateLink(), + this.renderConnectToTrezorButton(), + this.renderLearnMore(), + this.renderTutorialSteps(), + this.renderFooter(), ]) ) - } + } render () { if (this.props.browserSupported) { diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index 0eacf4615..5af743a2e 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -1,9 +1,8 @@ .new-account { - width: 376px; + width: 375px; background-color: #FFFFFF; box-shadow: 0 0 7px 0 rgba(0,0,0,0.08); z-index: 25; - padding-bottom: 31px; &__header { display: flex; @@ -153,10 +152,51 @@ } } +.hw-tutorial { + width: 375px; + border-top: 1px solid #D2D8DD; + border-bottom: 1px solid #D2D8DD; + overflow: visible; + display: block; + padding: 15px 30px; +} + .hw-connect { + &__header { + &__title { + margin-top: 5px; + margin-bottom: 15px; + font-size: 22px; + text-align: center; + } + + &__msg { + font-size: 14px; + color: #9b9b9b; + margin-top: 10px; + margin-bottom: 0px; + } + } + + &__learn-more { + margin-top: 15px; + font-size: 14px; + color: #5B5D67; + line-height: 19px; + text-align: center; + + &__arrow { + transform: rotate(90deg); + display: block; + text-align: center; + height: 30px; + margin: 0px auto 10px; + } + } + &__title { padding-top: 10px; - font-weight: 500; + font-weight: 400; font-size: 18px; } @@ -164,27 +204,59 @@ font-size: 14px; color: #9b9b9b; margin-top: 10px; - margin-bottom: 20px; + margin-bottom: 15px; } &__link { color: #2f9ae0; } + &__footer { + width: 100%; + + &__title { + padding-top: 15px; + padding-bottom: 12px; + font-weight: 400; + font-size: 18px; + text-align: center; + } + + &__msg { + font-size: 14px; + color: #9b9b9b; + margin-top: 12px; + margin-bottom: 27px; + } + + &__link { + color: #2f9ae0; + margin-left: 5px; + } + } + &__get-trezor { - display: flex; - flex-flow: column; - align-items: center; - padding: 30px 30px 0; - width: 305px; + width: 100%; + padding-bottom: 20px; + padding-top: 20px; + + &__msg { + font-size: 14px; + color: #9b9b9b; + } - a { + &__link { font-size: 14px; text-align: center; color: #2f9ae0; cursor: pointer; } } + + &__step-asset { + margin: 0px auto 20px; + display: flex; + } } .hw-account-list { @@ -303,6 +375,8 @@ flex-flow: column; align-items: center; padding: 15px 30px 0; + height: 710px; + overflow: auto; &__buttons { margin-top: 39px; @@ -316,23 +390,20 @@ min-width: initial; } - &__button.btn-primary { - background-color: #259DE5; - } - - &__button.btn-primary { + .btn-primary { background-color: #259DE5; color: #FFFFFF; + border: none; + width: 100%; + min-height: 54px; + font-weight: 300; + font-size: 14px; } &__button.btn-primary--disabled { cursor: not-allowed; opacity: .5; } - - - - } .hw-forget-device-container { @@ -352,7 +423,7 @@ display: flex; flex-flow: column; align-items: center; - padding: 30px 30px 0; + padding: 30px; &__input-label { color: $scorpion; -- cgit v1.2.3 From 2bfddc288e64f130d1677afca4448202181523ea Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Wed, 18 Jul 2018 23:12:49 -0400 Subject: scroll smooth --- .../create-account/connect-hardware/connect-screen.js | 14 +++++++++++--- ui/app/css/itcss/components/new-account.scss | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js index 47288c73f..5c6c54acf 100644 --- a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js @@ -54,9 +54,15 @@ class ConnectScreen extends Component { ) } + scrollToTutorial = (e) => { + if (this.referenceNode) this.referenceNode.scrollIntoView({behavior: 'smooth'}) + } + renderLearnMore () { return ( - h('p.hw-connect__learn-more', {}, [ + h('p.hw-connect__learn-more', { + onClick: this.scrollToTutorial, + }, [ this.context.t('learnMore'), h('img.hw-connect__learn-more__arrow', { src: 'images/caret-right.svg'}), ]) @@ -79,9 +85,11 @@ class ConnectScreen extends Component { }, ] - return h('.hw-tutorial', {}, + return h('.hw-tutorial', { + ref: node => { this.referenceNode = node }, + }, steps.map((step, i) => ( - h('div.hw-connect', [ + h('div.hw-connect', {}, [ h('h3.hw-connect__title', {}, this.context.t(`step${i + 1}HardwareWallet`)), h('p.hw-connect__msg', {}, this.context.t(`step${i + 1}HardwareWalletMsg`)), h('img.hw-connect__step-asset', { src: `images/${step.asset}.svg`, ...step.dimensions }), diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index 5af743a2e..8743d540f 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -184,6 +184,7 @@ color: #5B5D67; line-height: 19px; text-align: center; + cursor: pointer; &__arrow { transform: rotate(90deg); -- cgit v1.2.3 From 086ab6e1e1aa715b7a7918d10b8c1afcaeda38c7 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Wed, 18 Jul 2018 23:57:09 -0400 Subject: lint --- .../components/pages/create-account/connect-hardware/connect-screen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js index 5c6c54acf..55d2eadce 100644 --- a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js @@ -85,7 +85,7 @@ class ConnectScreen extends Component { }, ] - return h('.hw-tutorial', { + return h('.hw-tutorial', { ref: node => { this.referenceNode = node }, }, steps.map((step, i) => ( -- cgit v1.2.3 From a6e0eef8f4280041380a7c462069b2c205999130 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Thu, 19 Jul 2018 00:14:13 -0400 Subject: fix unsupported browser view --- .../pages/create-account/connect-hardware/connect-screen.js | 2 +- ui/app/css/itcss/components/new-account.scss | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js index 55d2eadce..bf4cf08f9 100644 --- a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js @@ -9,7 +9,7 @@ class ConnectScreen extends Component { renderUnsupportedBrowser () { return ( - h('div.new-account-connect-form', {}, [ + h('div.new-account-connect-form.unsupported-browser', {}, [ h('div.hw-connect', [ h('h3.hw-connect__title', {}, this.context.t('browserNotSupported')), h('p.hw-connect__msg', {}, this.context.t('chromeRequiredForTrezor')), diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index 8743d540f..29faacc1b 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -63,7 +63,7 @@ display: flex; flex-flow: column; align-items: center; - padding: 0 30px; + padding: 0 30px 30px; &__select-section { display: flex; @@ -379,6 +379,10 @@ height: 710px; overflow: auto; + &.unsupported-browser { + height: 210px; + } + &__buttons { margin-top: 39px; display: flex; -- cgit v1.2.3 From 514148ffa1652b4e23ffe04fbe23bb0eadbdecb7 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Thu, 19 Jul 2018 00:16:10 -0400 Subject: fix support link --- .../components/pages/create-account/connect-hardware/connect-screen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js index bf4cf08f9..cb2b86595 100644 --- a/ui/app/components/pages/create-account/connect-hardware/connect-screen.js +++ b/ui/app/components/pages/create-account/connect-hardware/connect-screen.js @@ -106,7 +106,7 @@ class ConnectScreen extends Component { h('p.hw-connect__footer__msg', {}, [ this.context.t(`havingTroubleConnecting`), h('a.hw-connect__footer__link', { - href: '#', + href: 'https://support.metamask.io/', target: '_blank', }, this.context.t('getHelp')), ]), -- cgit v1.2.3 From 76981c2ad9b0f8f13fa61ba3b60c07203a81eb57 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Thu, 19 Jul 2018 02:31:02 -0400 Subject: added new global alert --- ui/app/actions.js | 18 +++++++++++ ui/app/app.js | 20 +++++++----- ui/app/components/alert/index.js | 22 +++++++++++++ ui/app/css/itcss/components/alert.scss | 57 ++++++++++++++++++++++++++++++++++ ui/app/css/itcss/components/index.scss | 2 ++ ui/app/reducers/app.js | 15 +++++++++ 6 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 ui/app/components/alert/index.js create mode 100644 ui/app/css/itcss/components/alert.scss (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index 3da56ebc2..4557b5961 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -26,6 +26,11 @@ var actions = { SIDEBAR_CLOSE: 'UI_SIDEBAR_CLOSE', showSidebar: showSidebar, hideSidebar: hideSidebar, + // sidebar state + ALERT_OPEN: 'UI_ALERT_OPEN', + ALERT_CLOSE: 'UI_ALERT_CLOSE', + showAlert: showAlert, + hideAlert: hideAlert, // network dropdown open NETWORK_DROPDOWN_OPEN: 'UI_NETWORK_DROPDOWN_OPEN', NETWORK_DROPDOWN_CLOSE: 'UI_NETWORK_DROPDOWN_CLOSE', @@ -1724,6 +1729,19 @@ function hideSidebar () { } } +function showAlert (msg) { + return { + type: actions.ALERT_OPEN, + value: msg, + } +} + +function hideAlert () { + return { + type: actions.ALERT_CLOSE, + } +} + function showLoadingIndication (message) { return { diff --git a/ui/app/app.js b/ui/app/app.js index a00692df0..dbb6146d1 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -36,6 +36,8 @@ const AccountMenu = require('./components/account-menu') // Global Modals const Modal = require('./components/modals/index').Modal +// Global Alert +const Alert = require('./components/alert') const AppHeader = require('./components/app-header') @@ -93,6 +95,7 @@ class App extends Component { render () { const { isLoading, + alertMessage, loadingMessage, network, isMouseUser, @@ -126,6 +129,9 @@ class App extends Component { // global modal h(Modal, {}, []), + // global alert + h(Alert, {visible: this.props.alertOpen, msg: alertMessage}), + h(AppHeader), // sidebar @@ -149,14 +155,6 @@ class App extends Component { ) } - renderGlobalModal () { - return h(Modal, { - ref: 'modalRef', - }, [ - // h(BuyOptions, {}, []), - ]) - } - renderSidebar () { return h('div', [ h('style', ` @@ -265,11 +263,13 @@ App.propTypes = { setCurrentCurrencyToUSD: PropTypes.func, isLoading: PropTypes.bool, loadingMessage: PropTypes.string, + alertMessage: PropTypes.string, network: PropTypes.string, provider: PropTypes.object, frequentRpcList: PropTypes.array, currentView: PropTypes.object, sidebarOpen: PropTypes.bool, + alertOpen: PropTypes.bool, hideSidebar: PropTypes.func, isMascara: PropTypes.bool, isOnboarding: PropTypes.bool, @@ -305,6 +305,8 @@ function mapStateToProps (state) { const { networkDropdownOpen, sidebarOpen, + alertOpen, + alertMessage, isLoading, loadingMessage, } = appState @@ -330,6 +332,8 @@ function mapStateToProps (state) { // state from plugin networkDropdownOpen, sidebarOpen, + alertOpen, + alertMessage, isLoading, loadingMessage, noActiveNotices, diff --git a/ui/app/components/alert/index.js b/ui/app/components/alert/index.js new file mode 100644 index 000000000..fc39d41e2 --- /dev/null +++ b/ui/app/components/alert/index.js @@ -0,0 +1,22 @@ +const { Component } = require('react') +const PropTypes = require('prop-types') +const h = require('react-hyperscript') + +class Alert extends Component { + + render () { + const className = `.global-alert${this.props.visible ? '.visible' : '.hidden'}` + return ( + h(`div${className}`, {}, + h('a.msg', {}, this.props.msg) + ) + ) + } +} + +Alert.propTypes = { + visible: PropTypes.bool.isRequired, + msg: PropTypes.string, +} +module.exports = Alert + diff --git a/ui/app/css/itcss/components/alert.scss b/ui/app/css/itcss/components/alert.scss new file mode 100644 index 000000000..930fc3f54 --- /dev/null +++ b/ui/app/css/itcss/components/alert.scss @@ -0,0 +1,57 @@ +.global-alert { + position: relative; + width: 100%; + background-color: #33A4E7; + + .msg { + width: 100%; + display: block; + color: white; + font-size: 12px; + text-align: center; + } +} + +.global-alert.hidden { + animation: alertHidden .5s ease forwards; +} + +.global-alert.visible { + animation: alert .5s ease forwards; +} + +/* Animation */ +@keyframes alert { + 0% { + opacity: 0; + top: -50px; + padding: 0px; + line-height: 12px; + } + + 50% { + opacity: 1; + } + + 100% { + top: 0; + padding: 8px; + line-height: 12px; + } +} + +@keyframes alertHidden { + 0% { + top: 0; + opacity: 1; + padding: 8px; + line-height: 12px; + } + + 100% { + opacity: 0; + top: -50px; + padding: 0px; + line-height: 0px; + } +} diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index 5be040906..96ad5fe64 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -8,6 +8,8 @@ @import './modal.scss'; +@import './alert.scss'; + @import './newui-sections.scss'; @import './account-dropdown.scss'; diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js index f453812b9..50d8bcba7 100644 --- a/ui/app/reducers/app.js +++ b/ui/app/reducers/app.js @@ -49,6 +49,8 @@ function reduceApp (state, action) { }, }, sidebarOpen: false, + alertOpen: false, + alertMessage: null, networkDropdownOpen: false, currentView: seedWords ? seedConfView : defaultView, accountDetail: { @@ -88,6 +90,19 @@ function reduceApp (state, action) { sidebarOpen: false, }) + // sidebar methods + case actions.ALERT_OPEN: + return extend(appState, { + alertOpen: true, + alertMessage: action.value, + }) + + case actions.ALERT_CLOSE: + return extend(appState, { + alertOpen: false, + alertMessage: null, + }) + // modal methods: case actions.MODAL_OPEN: const { name, ...modalProps } = action.payload -- cgit v1.2.3 From df19163bf9611d75aaf8ea6da52651dbba9a5e00 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Thu, 19 Jul 2018 02:31:13 -0400 Subject: last css fixes --- .../connect-hardware/account-list.js | 8 +++---- .../pages/create-account/connect-hardware/index.js | 19 ++++++++++++++++ ui/app/css/itcss/components/new-account.scss | 25 ++++++++++++++++------ 3 files changed, 42 insertions(+), 10 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pages/create-account/connect-hardware/account-list.js b/ui/app/components/pages/create-account/connect-hardware/account-list.js index 06102e16f..c722d1f55 100644 --- a/ui/app/components/pages/create-account/connect-hardware/account-list.js +++ b/ui/app/components/pages/create-account/connect-hardware/account-list.js @@ -59,7 +59,7 @@ class AccountList extends Component { renderPagination () { return h('div.hw-list-pagination', [ h( - 'button.btn-primary.hw-list-pagination__button', + 'button.hw-list-pagination__button', { onClick: () => this.props.getPage(-1), }, @@ -67,7 +67,7 @@ class AccountList extends Component { ), h( - 'button.btn-primary.hw-list-pagination__button', + 'button.hw-list-pagination__button', { onClick: () => this.props.getPage(1), }, @@ -93,7 +93,7 @@ class AccountList extends Component { ), h( - `button.btn-primary.btn--large.new-account-connect-form__button ${disabled ? '.btn-primary--disabled' : ''}`, + `button.btn-primary.btn--large.new-account-connect-form__button.unlock ${disabled ? '.btn-primary--disabled' : ''}`, { onClick: this.props.onUnlockAccount.bind(this), ...buttonProps, @@ -112,7 +112,7 @@ class AccountList extends Component { } render () { - return h('div.new-account-connect-form', {}, [ + return h('div.new-account-connect-form.account-list', {}, [ this.renderHeader(), this.renderAccounts(), this.renderPagination(), diff --git a/ui/app/components/pages/create-account/connect-hardware/index.js b/ui/app/components/pages/create-account/connect-hardware/index.js index da42ddead..cc3761c04 100644 --- a/ui/app/components/pages/create-account/connect-hardware/index.js +++ b/ui/app/components/pages/create-account/connect-hardware/index.js @@ -51,11 +51,26 @@ class ConnectHardwareForm extends Component { this.setState({selectedAccount: account.toString(), error: null}) } + showTemporaryAlert () { + this.props.showAlert(this.context.t('hardwareWalletConnected')) + // Autohide the alert after 5 seconds + setTimeout(_ => { + this.props.hideAlert() + }, 5000) + } + getPage = (page) => { this.props .connectHardware('trezor', page) .then(accounts => { if (accounts.length) { + + // If we just loaded the accounts for the first time + // show the global alert + if (this.state.accounts.length === 0) { + this.showTemporaryAlert() + } + const newState = {} // Default to the first account if (this.state.selectedAccount === null) { @@ -164,6 +179,8 @@ ConnectHardwareForm.propTypes = { connectHardware: PropTypes.func, checkHardwareStatus: PropTypes.func, forgetDevice: PropTypes.func, + showAlert: PropTypes.func, + hideAlert: PropTypes.func, unlockTrezorAccount: PropTypes.func, numberOfExistingAccounts: PropTypes.number, history: PropTypes.object, @@ -203,6 +220,8 @@ const mapDispatchToProps = dispatch => { }, showImportPage: () => dispatch(actions.showImportPage()), showConnectPage: () => dispatch(actions.showConnectPage()), + showAlert: (msg) => dispatch(actions.showAlert(msg)), + hideAlert: () => dispatch(actions.hideAlert()), } } diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index 29faacc1b..b12afb124 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -299,7 +299,8 @@ font-size: 15px; flex-direction: row; display: flex; - padding: 10px; + padding-left: 10px; + padding-right: 10px; } &__item:nth-of-type(even) { @@ -324,14 +325,17 @@ flex: 1; input { - margin-right: 9px; + padding: 10px; + margin-top: 13px; } } &__item__label { - margin-left: 10px; display: flex; flex: 1; + padding-left: 10px; + padding-top: 10px; + padding-bottom: 10px; } &__item__balance { @@ -342,7 +346,7 @@ &__item__link { display: flex; - margin-top: 3px; + margin-top: 13px; } &__item__link img { @@ -359,7 +363,6 @@ &__button { height: 19px; display: flex; - width: 47px; color: #33a4e7; font-size: 14px; line-height: 19px; @@ -368,6 +371,8 @@ margin-right: 0px; margin-left: 16px; padding: 0px; + text-transform: uppercase; + font-family: Roboto; } } @@ -383,6 +388,10 @@ height: 210px; } + &.account-list { + height: auto; + } + &__buttons { margin-top: 39px; display: flex; @@ -405,6 +414,10 @@ font-size: 14px; } + &__button.unlock { + width: 50%; + } + &__button.btn-primary--disabled { cursor: not-allowed; opacity: .5; @@ -415,7 +428,7 @@ display: flex; flex-flow: column; align-items: center; - padding: 30px 30px 0; + padding: 22px; a { color: #2f9ae0; -- cgit v1.2.3