aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app
diff options
context:
space:
mode:
Diffstat (limited to 'ui/app')
-rw-r--r--ui/app/account-and-transaction-details.js38
-rw-r--r--ui/app/account-detail.js123
-rw-r--r--ui/app/accounts/account-list-item.js91
-rw-r--r--ui/app/accounts/index.js164
-rw-r--r--ui/app/actions.js22
-rw-r--r--ui/app/add-token.js1
-rw-r--r--ui/app/app.js484
-rw-r--r--ui/app/components/account-dropdowns.js235
-rw-r--r--ui/app/components/account-info-link.js41
-rw-r--r--ui/app/components/drop-menu-item.js59
-rw-r--r--ui/app/components/dropdown.js92
-rw-r--r--ui/app/components/editable-label.js7
-rw-r--r--ui/app/components/ens-input.js7
-rw-r--r--ui/app/components/loading.js48
-rw-r--r--ui/app/components/network.js3
-rw-r--r--ui/app/components/pending-tx.js634
-rw-r--r--ui/app/components/shapeshift-form.js10
-rw-r--r--ui/app/components/tab-bar.js1
-rw-r--r--ui/app/components/token-list.js42
-rw-r--r--ui/app/components/transaction-list.js18
-rw-r--r--ui/app/components/tx-view.js228
-rw-r--r--ui/app/components/wallet-content-display.js56
-rw-r--r--ui/app/components/wallet-view.js97
-rw-r--r--ui/app/conf-tx.js89
-rw-r--r--ui/app/css/debug.css21
-rw-r--r--ui/app/css/index.scss13
-rw-r--r--ui/app/css/itcss/base/index.scss0
-rw-r--r--ui/app/css/itcss/components/buttons.scss83
-rw-r--r--ui/app/css/itcss/components/footer.scss4
-rw-r--r--ui/app/css/itcss/components/header.scss54
-rw-r--r--ui/app/css/itcss/components/hero-balance.scss96
-rw-r--r--ui/app/css/itcss/components/identicon.scss7
-rw-r--r--ui/app/css/itcss/components/index.scss8
-rw-r--r--ui/app/css/itcss/components/network.scss12
-rw-r--r--ui/app/css/itcss/components/newui-sections.scss109
-rw-r--r--ui/app/css/itcss/components/sections.scss (renamed from ui/app/css/index.css)221
-rw-r--r--ui/app/css/itcss/generic/index.scss64
-rw-r--r--ui/app/css/itcss/generic/reset.scss (renamed from ui/app/css/reset.css)6
-rw-r--r--ui/app/css/itcss/objects/index.scss0
-rw-r--r--ui/app/css/itcss/settings/index.scss2
-rw-r--r--ui/app/css/itcss/settings/typography.scss (renamed from ui/app/css/fonts.css)16
-rw-r--r--ui/app/css/itcss/settings/variables.scss13
-rw-r--r--ui/app/css/itcss/tools/index.scss2
-rw-r--r--ui/app/css/itcss/tools/utilities.scss (renamed from ui/app/css/lib.css)53
-rw-r--r--ui/app/css/itcss/trumps/index.scss (renamed from ui/app/css/transitions.css)13
-rw-r--r--ui/app/info.js26
-rw-r--r--ui/app/keychains/hd/create-vault-complete.js2
-rw-r--r--ui/app/keychains/hd/recover-seed/confirmation.js7
-rw-r--r--ui/app/main-container.js72
-rw-r--r--ui/app/reducers/app.js11
-rw-r--r--ui/app/send.js490
-rw-r--r--ui/app/unlock.js2
52 files changed, 2553 insertions, 1444 deletions
diff --git a/ui/app/account-and-transaction-details.js b/ui/app/account-and-transaction-details.js
new file mode 100644
index 000000000..03f2d9db5
--- /dev/null
+++ b/ui/app/account-and-transaction-details.js
@@ -0,0 +1,38 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+// Main Views
+const TxView = require('./components/tx-view')
+const WalletView = require('./components/wallet-view')
+
+module.exports = AccountAndTransactionDetails
+
+inherits(AccountAndTransactionDetails, Component)
+function AccountAndTransactionDetails () {
+ Component.call(this)
+}
+
+AccountAndTransactionDetails.prototype.render = function () {
+ return h('div', {
+ style: {
+ display: 'flex',
+ flex: '1 0 auto',
+ },
+ }, [
+ // wallet
+ h(WalletView, {
+ style: {
+ },
+ responsiveDisplayClassname: '.lap-visible',
+ }, [
+ ]),
+
+ // transaction
+ h(TxView, {
+ style: {
+ }
+ }, [
+ ]),
+ ])
+}
+
diff --git a/ui/app/account-detail.js b/ui/app/account-detail.js
index bed05a7fb..24561c32e 100644
--- a/ui/app/account-detail.js
+++ b/ui/app/account-detail.js
@@ -3,21 +3,17 @@ const extend = require('xtend')
const Component = require('react').Component
const h = require('react-hyperscript')
const connect = require('react-redux').connect
-const CopyButton = require('./components/copyButton')
-const AccountInfoLink = require('./components/account-info-link')
const actions = require('./actions')
-const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
const valuesFor = require('./util').valuesFor
-
const Identicon = require('./components/identicon')
const EthBalance = require('./components/eth-balance')
const TransactionList = require('./components/transaction-list')
const ExportAccountView = require('./components/account-export')
const ethUtil = require('ethereumjs-util')
const EditableLabel = require('./components/editable-label')
-const Tooltip = require('./components/tooltip')
const TabBar = require('./components/tab-bar')
const TokenList = require('./components/token-list')
+const AccountDropdowns = require('./components/account-dropdowns').AccountDropdowns
module.exports = connect(mapStateToProps)(AccountDetailScreen)
@@ -54,12 +50,13 @@ AccountDetailScreen.prototype.render = function () {
return (
- h('.account-detail-section', [
+ h('.account-detail-section.full-flex-height', [
- // identicon, label, balance, etc
+ // identicon, label, balance, etc
h('.account-data-subsection', {
style: {
margin: '0 20px',
+ flex: '1 0 auto',
},
}, [
@@ -84,6 +81,7 @@ AccountDetailScreen.prototype.render = function () {
style: {
lineHeight: '10px',
marginLeft: '15px',
+ width: '100%',
},
}, [
h(EditableLabel, {
@@ -98,7 +96,42 @@ AccountDetailScreen.prototype.render = function () {
// What is shown when not editing + edit text:
h('label.editing-label', [h('.edit-text', 'edit')]),
- h('h2.font-medium.color-forest', {name: 'edit'}, identity && identity.name),
+ h(
+ 'div',
+ {
+ style: {
+ display: 'flex',
+ justifyContent: 'flex-start',
+ alignItems: 'center',
+ },
+ },
+ [
+ h(
+ 'h2.font-medium.color-forest',
+ {
+ name: 'edit',
+ style: {
+ },
+ },
+ [
+ identity && identity.name,
+ ]
+ ),
+ h(
+ AccountDropdowns,
+ {
+ style: {
+ marginRight: '8px',
+ marginLeft: 'auto',
+ cursor: 'pointer',
+ },
+ selected,
+ network,
+ identities: props.identities,
+ },
+ ),
+ ]
+ ),
]),
h('.flex-row', {
style: {
@@ -124,56 +157,6 @@ AccountDetailScreen.prototype.render = function () {
color: '#AEAEAE',
},
}, checksumAddress),
-
- // copy and export
-
- h('.flex-row', {
- style: {
- justifyContent: 'flex-end',
- },
- }, [
-
- h(AccountInfoLink, { selected, network }),
-
- h(CopyButton, {
- value: checksumAddress,
- }),
-
- h(Tooltip, {
- title: 'QR Code',
- }, [
- h('i.fa.fa-qrcode.pointer.pop-hover', {
- onClick: () => props.dispatch(actions.showQrView(selected, identity ? identity.name : '')),
- style: {
- fontSize: '18px',
- position: 'relative',
- color: 'rgb(247, 134, 28)',
- top: '5px',
- marginLeft: '3px',
- marginRight: '3px',
- },
- }),
- ]),
-
- h(Tooltip, {
- title: 'Export Private Key',
- }, [
- h('div', {
- style: {
- display: 'flex',
- alignItems: 'center',
- },
- }, [
- h('img.cursor-pointer.color-orange', {
- src: 'images/key-32.png',
- onClick: () => this.requestAccountExport(selected),
- style: {
- height: '19px',
- },
- }),
- ]),
- ]),
- ]),
]),
// account ballence
@@ -197,14 +180,11 @@ AccountDetailScreen.prototype.render = function () {
},
}),
+ h('.flex-grow'),
+
h('button', {
onClick: () => props.dispatch(actions.buyEthView(selected)),
- style: {
- marginBottom: '20px',
- marginRight: '8px',
- position: 'absolute',
- left: '219px',
- },
+ style: { marginRight: '10px' },
}, 'BUY'),
h('button', {
@@ -219,14 +199,7 @@ AccountDetailScreen.prototype.render = function () {
]),
// subview (tx history, pk export confirm, buy eth warning)
- h(ReactCSSTransitionGroup, {
- className: 'css-transition-group',
- transitionName: 'main',
- transitionEnterTimeout: 300,
- transitionLeaveTimeout: 300,
- }, [
- this.subview(),
- ]),
+ this.subview(),
])
)
@@ -254,7 +227,7 @@ AccountDetailScreen.prototype.subview = function () {
AccountDetailScreen.prototype.tabSections = function () {
const { currentAccountTab } = this.props
- return h('section.tabSection', [
+ return h('section.tabSection.full-flex-height.grow-tenx', [
h(TabBar, {
tabs: [
@@ -305,7 +278,3 @@ AccountDetailScreen.prototype.transactionList = function () {
},
})
}
-
-AccountDetailScreen.prototype.requestAccountExport = function () {
- this.props.dispatch(actions.requestExportAccount())
-}
diff --git a/ui/app/accounts/account-list-item.js b/ui/app/accounts/account-list-item.js
deleted file mode 100644
index 10a0b6cc7..000000000
--- a/ui/app/accounts/account-list-item.js
+++ /dev/null
@@ -1,91 +0,0 @@
-const Component = require('react').Component
-const h = require('react-hyperscript')
-const inherits = require('util').inherits
-const ethUtil = require('ethereumjs-util')
-
-const EthBalance = require('../components/eth-balance')
-const CopyButton = require('../components/copyButton')
-const Identicon = require('../components/identicon')
-
-module.exports = AccountListItem
-
-inherits(AccountListItem, Component)
-function AccountListItem () {
- Component.call(this)
-}
-
-AccountListItem.prototype.render = function () {
- const { identity, selectedAddress, accounts, onShowDetail,
- conversionRate, currentCurrency } = this.props
-
- const checksumAddress = identity && identity.address && ethUtil.toChecksumAddress(identity.address)
- const isSelected = selectedAddress === identity.address
- const account = accounts[identity.address]
- const selectedClass = isSelected ? '.selected' : ''
-
- return (
- h(`.accounts-list-option.flex-row.flex-space-between.pointer.hover-white${selectedClass}`, {
- key: `account-panel-${identity.address}`,
- onClick: (event) => onShowDetail(identity.address, event),
- }, [
-
- h('.identicon-wrapper.flex-column.flex-center.select-none', [
- this.pendingOrNot(),
- this.indicateIfLoose(),
- h(Identicon, {
- address: identity.address,
- imageify: true,
- }),
- ]),
-
- // account address, balance
- h('.identity-data.flex-column.flex-justify-center.flex-grow.select-none', {
- style: {
- width: '200px',
- },
- }, [
- h('span', identity.name),
- h('span.font-small', {
- style: {
- overflow: 'hidden',
- textOverflow: 'ellipsis',
- },
- }, checksumAddress),
- h(EthBalance, {
- value: account && account.balance,
- currentCurrency,
- conversionRate,
- style: {
- lineHeight: '7px',
- marginTop: '10px',
- },
- }),
- ]),
-
- // copy button
- h('.identity-copy.flex-column', {
- style: {
- margin: '0 20px',
- },
- }, [
- h(CopyButton, {
- value: checksumAddress,
- }),
- ]),
- ])
- )
-}
-
-AccountListItem.prototype.indicateIfLoose = function () {
- try { // Sometimes keyrings aren't loaded yet:
- const type = this.props.keyring.type
- const isLoose = type !== 'HD Key Tree'
- return isLoose ? h('.keyring-label', 'LOOSE') : null
- } catch (e) { return }
-}
-
-AccountListItem.prototype.pendingOrNot = function () {
- const pending = this.props.pending
- if (pending.length === 0) return null
- return h('.pending-dot', pending.length)
-}
diff --git a/ui/app/accounts/index.js b/ui/app/accounts/index.js
deleted file mode 100644
index ac2615cd7..000000000
--- a/ui/app/accounts/index.js
+++ /dev/null
@@ -1,164 +0,0 @@
-const inherits = require('util').inherits
-const Component = require('react').Component
-const h = require('react-hyperscript')
-const connect = require('react-redux').connect
-const actions = require('../actions')
-const valuesFor = require('../util').valuesFor
-const findDOMNode = require('react-dom').findDOMNode
-const AccountListItem = require('./account-list-item')
-
-module.exports = connect(mapStateToProps)(AccountsScreen)
-
-function mapStateToProps (state) {
- const pendingTxs = valuesFor(state.metamask.unapprovedTxs)
- .filter(txMeta => txMeta.metamaskNetworkId === state.metamask.network)
- const pendingMsgs = valuesFor(state.metamask.unapprovedMsgs)
- const pending = pendingTxs.concat(pendingMsgs)
-
- return {
- accounts: state.metamask.accounts,
- identities: state.metamask.identities,
- unapprovedTxs: state.metamask.unapprovedTxs,
- selectedAddress: state.metamask.selectedAddress,
- scrollToBottom: state.appState.scrollToBottom,
- pending,
- keyrings: state.metamask.keyrings,
- conversionRate: state.metamask.conversionRate,
- currentCurrency: state.metamask.currentCurrency,
- }
-}
-
-inherits(AccountsScreen, Component)
-function AccountsScreen () {
- Component.call(this)
-}
-
-AccountsScreen.prototype.render = function () {
- const props = this.props
- const { keyrings, conversionRate, currentCurrency } = props
- const identityList = valuesFor(props.identities)
- const unapprovedTxList = valuesFor(props.unapprovedTxs)
-
- return (
-
- h('.accounts-section.flex-grow', [
-
- // subtitle and nav
- h('.section-title.flex-center', [
- h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
- onClick: this.goHome.bind(this),
- }),
- h('h2.page-subtitle', 'Select Account'),
- ]),
-
- h('hr.horizontal-line'),
-
- // identity selection
- h('section.identity-section', {
- style: {
- height: '418px',
- overflowY: 'auto',
- overflowX: 'hidden',
- },
- },
- [
- identityList.map((identity) => {
- const pending = this.props.pending.filter((txOrMsg) => {
- if ('txParams' in txOrMsg) {
- return txOrMsg.txParams.from === identity.address
- } else if ('msgParams' in txOrMsg) {
- return txOrMsg.msgParams.from === identity.address
- } else {
- return false
- }
- })
-
- const simpleAddress = identity.address.substring(2).toLowerCase()
- const keyring = keyrings.find((kr) => {
- return kr.accounts.includes(simpleAddress) ||
- kr.accounts.includes(identity.address)
- })
-
- return h(AccountListItem, {
- key: `acct-panel-${identity.address}`,
- identity,
- selectedAddress: this.props.selectedAddress,
- conversionRate,
- currentCurrency,
- accounts: this.props.accounts,
- onShowDetail: this.onShowDetail.bind(this),
- pending,
- keyring,
- })
- }),
-
- h('hr.horizontal-line'),
- h('div.footer.hover-white.pointer', {
- key: 'reveal-account-bar',
- onClick: () => {
- this.addNewAccount()
- },
- style: {
- display: 'flex',
- height: '40px',
- padding: '10px',
- justifyContent: 'center',
- alignItems: 'center',
- },
- }, [
- h('i.fa.fa-plus.fa-lg', {key: ''}),
- ]),
- h('hr.horizontal-line'),
- ]),
-
- unapprovedTxList.length ? (
-
- h('.unconftx-link.flex-row.flex-center', {
- onClick: this.navigateToConfTx.bind(this),
- }, [
- h('span', 'Unconfirmed Txs'),
- h('i.fa.fa-arrow-right.fa-lg'),
- ])
-
- ) : (
- null
- ),
- ])
- )
-}
-
-// If a new account was revealed, scroll to the bottom
-AccountsScreen.prototype.componentDidUpdate = function () {
- const scrollToBottom = this.props.scrollToBottom
-
- if (scrollToBottom) {
- var container = findDOMNode(this)
- var scrollable = container.querySelector('.identity-section')
- scrollable.scrollTop = scrollable.scrollHeight
- }
-}
-
-AccountsScreen.prototype.navigateToConfTx = function () {
- event.stopPropagation()
- this.props.dispatch(actions.showConfTxPage())
-}
-
-AccountsScreen.prototype.onShowDetail = function (address, event) {
- event.stopPropagation()
- this.props.dispatch(actions.showAccountDetail(address))
-}
-
-AccountsScreen.prototype.addNewAccount = function () {
- this.props.dispatch(actions.addNewAccount(0))
-}
-
-/* An optional view proposed in this design:
- * https://consensys.quip.com/zZVrAysM5znY
-AccountsScreen.prototype.addNewAccount = function () {
- this.props.dispatch(actions.navigateToNewAccountScreen())
-}
-*/
-
-AccountsScreen.prototype.goHome = function () {
- this.props.dispatch(actions.goHome())
-}
diff --git a/ui/app/actions.js b/ui/app/actions.js
index 8ff8bbbdd..13a767343 100644
--- a/ui/app/actions.js
+++ b/ui/app/actions.js
@@ -5,6 +5,11 @@ var actions = {
GO_HOME: 'GO_HOME',
goHome: goHome,
+ // sidebar state
+ SIDEBAR_OPEN: 'UI_SIDEBAR_OPEN',
+ SIDEBAR_CLOSE: 'UI_SIDEBAR_CLOSE',
+ showSidebar: showSidebar,
+ hideSidebar: hideSidebar,
// menu state
getNetworkStatus: 'getNetworkStatus',
// transition state
@@ -709,7 +714,7 @@ function markAccountsFound () {
//
// default rpc target refers to localhost:8545 in this instance.
-function setDefaultRpcTarget (rpcList) {
+function setDefaultRpcTarget () {
log.debug(`background.setDefaultRpcTarget`)
return (dispatch) => {
background.setDefaultRpc((err, result) => {
@@ -722,7 +727,7 @@ function setDefaultRpcTarget (rpcList) {
}
function setRpcTarget (newRpc) {
- log.debug(`background.setRpcTarget`)
+ log.debug(`background.setRpcTarget: ${newRpc}`)
return (dispatch) => {
background.setCustomRpc(newRpc, (err, result) => {
if (err) {
@@ -763,6 +768,19 @@ function useEtherscanProvider () {
}
}
+function showSidebar () {
+ return {
+ type: actions.SIDEBAR_OPEN,
+ }
+}
+
+function hideSidebar () {
+ return {
+ type: actions.SIDEBAR_CLOSE,
+ }
+}
+
+
function showLoadingIndication (message) {
return {
type: actions.SHOW_LOADING,
diff --git a/ui/app/add-token.js b/ui/app/add-token.js
index 15ef7a852..5c6dea4a0 100644
--- a/ui/app/add-token.js
+++ b/ui/app/add-token.js
@@ -212,7 +212,6 @@ AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address)
const [ symbol, decimals ] = results
if (symbol && decimals) {
- console.log('SETTING SYMBOL AND DECIMALS', { symbol, decimals })
this.setState({ symbol: symbol[0], decimals: decimals[0].toString() })
}
}
diff --git a/ui/app/app.js b/ui/app/app.js
index 1a63002e1..339e13fd7 100644
--- a/ui/app/app.js
+++ b/ui/app/app.js
@@ -3,20 +3,23 @@ const Component = require('react').Component
const connect = require('react-redux').connect
const h = require('react-hyperscript')
const actions = require('./actions')
-const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
// init
const InitializeMenuScreen = require('./first-time/init-menu')
const NewKeyChainScreen = require('./new-keychain')
// unlock
const UnlockScreen = require('./unlock')
// accounts
-const AccountsScreen = require('./accounts')
-const AccountDetailScreen = require('./account-detail')
+const MainContainer = require('./main-container')
const SendTransactionScreen = require('./send')
const ConfirmTxScreen = require('./conf-tx')
// notice
const NoticeScreen = require('./components/notice')
const generateLostAccountsNotice = require('../lib/lost-accounts-notice')
+
+// slideout menu
+const WalletView = require('./components/wallet-view')
+const SlideoutMenu = require('react-burger-menu').slide
+
// other views
const ConfigScreen = require('./config')
const AddTokenScreen = require('./add-token')
@@ -24,17 +27,17 @@ const Import = require('./accounts/import')
const InfoScreen = require('./info')
const Loading = require('./components/loading')
const SandwichExpando = require('sandwich-expando')
-const MenuDroppo = require('menu-droppo')
-const DropMenuItem = require('./components/drop-menu-item')
+const Dropdown = require('./components/dropdown').Dropdown
+const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem
const NetworkIndicator = require('./components/network')
-const Tooltip = require('./components/tooltip')
const BuyView = require('./components/buy-button-subview')
const QrView = require('./components/qr-code')
const HDCreateVaultComplete = require('./keychains/hd/create-vault-complete')
const HDRestoreVaultScreen = require('./keychains/hd/restore-vault')
const RevealSeedConfirmation = require('./keychains/hd/recover-seed/confirmation')
+const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
-module.exports = connect(mapStateToProps)(App)
+module.exports = connect(mapStateToProps, mapDispatchToProps)(App)
inherits(App, Component)
function App () { Component.call(this) }
@@ -42,6 +45,7 @@ function App () { Component.call(this) }
function mapStateToProps (state) {
return {
// state from plugin
+ sidebarOpen: state.appState.sidebarOpen,
isLoading: state.appState.isLoading,
loadingMessage: state.appState.loadingMessage,
noActiveNotices: state.metamask.noActiveNotices,
@@ -63,55 +67,104 @@ function mapStateToProps (state) {
}
}
+function mapDispatchToProps (dispatch) {
+ return {
+ hideSidebar: () => {dispatch(actions.hideSidebar())},
+ }
+}
+
App.prototype.render = function () {
var props = this.props
- const { isLoading, loadingMessage, transForward, network } = props
+ const { isLoading, loadingMessage, transForward, network, sidebarOpen } = props
const isLoadingNetwork = network === 'loading' && props.currentView.name !== 'config'
const loadMessage = loadingMessage || isLoadingNetwork ?
`Connecting to ${this.getNetworkName()}` : null
-
log.debug('Main ui render function')
return (
- h('.flex-column.flex-grow.full-height', {
+ h('.flex-column.full-height', {
style: {
// Windows was showing a vertical scroll bar:
- overflow: 'hidden',
+ overflowX: 'hidden',
+ // TODO: check with dev who committed L75, see if this still happens, and whether auto is enough
+ // overflowY: 'auto',
position: 'relative',
+ alignItems: 'center',
},
}, [
// app bar
this.renderAppBar(),
+
+ // sidebar
+ this.renderSidebar(),
+
+ // network dropdown
this.renderNetworkDropdown(),
- this.renderDropdown(),
+ // this.renderDropdown(),
h(Loading, {
isLoading: isLoading || isLoadingNetwork,
loadingMessage: loadMessage,
}),
- // panel content
- h('.app-primary.flex-grow' + (transForward ? '.from-right' : '.from-left'), {
- style: {
- height: '380px',
- width: '360px',
- },
- }, [
- h(ReactCSSTransitionGroup, {
- className: 'css-transition-group',
- transitionName: 'main',
- transitionEnterTimeout: 300,
- transitionLeaveTimeout: 300,
- }, [
- this.renderPrimary(),
- ]),
- ]),
+ // content
+ this.renderPrimary(),
])
)
}
+App.prototype.renderSidebar = function() {
+ // if (!this.props.sidebarOpen) {
+ // return null;
+ // }
+
+ return h('div', {
+ }, [
+ h('style', `
+ .sidebar-enter {
+ transition: transform 300ms ease-in-out;
+ transform: translateX(-100%);
+ }
+ .sidebar-enter.sidebar-enter-active {
+ transition: transform 300ms ease-in-out;
+ transform: translateX(0%);
+ }
+ .sidebar-leave {
+ transition: transform 200ms ease-out;
+ transform: translateX(0%);
+ }
+ .sidebar-leave.sidebar-leave-active {
+ transition: transform 200ms ease-out;
+ transform: translateX(-100%);
+ }
+ `),
+
+ h(ReactCSSTransitionGroup, {
+ transitionName: 'sidebar',
+ transitionEnterTimeout: 300,
+ transitionLeaveTimeout: 200,
+ }, [
+ // content
+ this.props.sidebarOpen ? h(WalletView, {
+ responsiveDisplayClassname: '.sidebar',
+ style: {},
+ }) : undefined,
+
+ ]),
+
+ // overlay
+ // TODO: add onClick for overlay to close sidebar
+ this.props.sidebarOpen ? h('div.sidebar-overlay', {
+ style: {},
+ onClick: () => {
+ this.props.hideSidebar()
+ },
+ }, []) : undefined,
+ ])
+}
+
App.prototype.renderAppBar = function () {
if (window.METAMASK_UI_TYPE === 'notification') {
return null
@@ -123,27 +176,17 @@ App.prototype.renderAppBar = function () {
return (
- h('div', [
+ h('.full-width', {
+ style: {}
+ }, [
h('.app-header.flex-row.flex-space-between', {
- style: {
- alignItems: 'center',
- visibility: props.isUnlocked ? 'visible' : 'none',
- background: props.isUnlocked ? 'white' : 'none',
- height: '36px',
- position: 'relative',
- zIndex: 12,
- },
+ style: {},
}, [
- h('div.left-menu-section', {
- style: {
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center',
- },
+ h('div.left-menu-wrapper', {
+ style: {},
}, [
-
// mini logo
h('img', {
height: 24,
@@ -151,6 +194,20 @@ App.prototype.renderAppBar = function () {
src: '/images/icon-128.png',
}),
+ // metamask name
+ h('h1', {
+ style: {
+ position: 'relative',
+ left: '9px',
+ },
+ }, 'MetaMask'),
+
+ ]),
+
+ h('div.network-component-wrapper', {
+ style: {},
+ }, [
+ // Network Indicator
h(NetworkIndicator, {
network: this.props.network,
provider: this.props.provider,
@@ -160,138 +217,132 @@ App.prototype.renderAppBar = function () {
this.setState({ isNetworkMenuOpen: !isNetworkMenuOpen })
},
}),
- ]),
-
- // metamask name
- props.isUnlocked && h('h1', {
- style: {
- position: 'relative',
- left: '9px',
- },
- }, 'MetaMask'),
-
- props.isUnlocked && h('div', {
- style: {
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center',
- },
- }, [
- // small accounts nav
- props.isUnlocked && h(Tooltip, { title: 'Switch Accounts' }, [
- h('img.cursor-pointer.color-orange', {
- src: 'images/switch_acc.svg',
- style: {
- width: '23.5px',
- marginRight: '8px',
- },
- onClick: (event) => {
- event.stopPropagation()
- this.props.dispatch(actions.showAccountsPage())
- },
- }),
- ]),
-
- // hamburger
- props.isUnlocked && h(SandwichExpando, {
- width: 16,
- barHeight: 2,
- padding: 0,
- isOpen: state.isMainMenuOpen,
- color: 'rgb(247,146,30)',
- onClick: (event) => {
- event.preventDefault()
- event.stopPropagation()
- this.setState({ isMainMenuOpen: !state.isMainMenuOpen })
- },
- }),
]),
]),
+
])
)
}
App.prototype.renderNetworkDropdown = function () {
const props = this.props
+ const { provider: { type: providerType, rpcTarget: activeNetwork } } = props
const rpcList = props.frequentRpcList
const state = this.state || {}
const isOpen = state.isNetworkMenuOpen
- return h(MenuDroppo, {
+ return h(Dropdown, {
isOpen,
onClickOutside: (event) => {
- this.setState({ isNetworkMenuOpen: !isOpen })
+ const { classList } = event.target
+ const isNotToggleElement = [
+ classList.contains('menu-icon'),
+ classList.contains('network-name'),
+ classList.contains('network-indicator'),
+ ].filter(bool => bool).length === 0;
+ // classes from three constituent nodes of the toggle element
+
+ if (isNotToggleElement) {
+ this.setState({ isNetworkMenuOpen: false })
+ }
},
zIndex: 11,
style: {
position: 'absolute',
- left: 0,
- top: '36px',
+ right: '2px',
+ top: '38px',
},
innerStyle: {
- background: 'white',
- boxShadow: '1px 1px 2px rgba(0,0,0,0.1)',
+ padding: '2px 16px 2px 0px',
},
- }, [ // DROP MENU ITEMS
- h('style', `
- .drop-menu-item:hover { background:rgb(235, 235, 235); }
- .drop-menu-item i { margin: 11px; }
- `),
-
- h(DropMenuItem, {
- label: 'Main Ethereum Network',
- closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
- action: () => props.dispatch(actions.setProviderType('mainnet')),
- icon: h('.menu-icon.diamond'),
- activeNetworkRender: props.network,
- provider: props.provider,
- }),
-
- h(DropMenuItem, {
- label: 'Ropsten Test Network',
- closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
- action: () => props.dispatch(actions.setProviderType('ropsten')),
- icon: h('.menu-icon.red-dot'),
- activeNetworkRender: props.network,
- provider: props.provider,
- }),
-
- h(DropMenuItem, {
- label: 'Kovan Test Network',
- closeMenu: () => this.setState({ isNetworkMenuOpen: false}),
- action: () => props.dispatch(actions.setProviderType('kovan')),
- icon: h('.menu-icon.hollow-diamond'),
- activeNetworkRender: props.network,
- provider: props.provider,
- }),
-
- h(DropMenuItem, {
- label: 'Rinkeby Test Network',
- closeMenu: () => this.setState({ isNetworkMenuOpen: false}),
- action: () => props.dispatch(actions.setProviderType('rinkeby')),
- icon: h('.menu-icon.golden-square'),
- activeNetworkRender: props.network,
- provider: props.provider,
- }),
-
- h(DropMenuItem, {
- label: 'Localhost 8545',
- closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
- action: () => props.dispatch(actions.setDefaultRpcTarget(rpcList)),
- icon: h('i.fa.fa-question-circle.fa-lg'),
- activeNetworkRender: props.provider.rpcTarget,
- }),
+ }, [
+
+ h(
+ DropdownMenuItem,
+ {
+ key: 'main',
+ closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
+ onClick: () => props.dispatch(actions.setProviderType('mainnet')),
+ },
+ [
+ h('.menu-icon.diamond'),
+ 'Main Ethereum Network',
+ providerType === 'mainnet' ? h('.check', '✓') : null,
+ ]
+ ),
+
+ h(
+ DropdownMenuItem,
+ {
+ key: 'ropsten',
+ closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
+ onClick: () => props.dispatch(actions.setProviderType('ropsten')),
+ },
+ [
+ h('.menu-icon.red-dot'),
+ 'Ropsten Test Network',
+ providerType === 'ropsten' ? h('.check', '✓') : null,
+ ]
+ ),
+
+ h(
+ DropdownMenuItem,
+ {
+ key: 'kovan',
+ closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
+ onClick: () => props.dispatch(actions.setProviderType('kovan')),
+ },
+ [
+ h('.menu-icon.hollow-diamond'),
+ 'Kovan Test Network',
+ providerType === 'kovan' ? h('.check', '✓') : null,
+ ]
+ ),
+
+ h(
+ DropdownMenuItem,
+ {
+ key: 'rinkeby',
+ closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
+ onClick: () => props.dispatch(actions.setProviderType('rinkeby')),
+ },
+ [
+ h('.menu-icon.golden-square'),
+ 'Rinkeby Test Network',
+ providerType === 'rinkeby' ? h('.check', '✓') : null,
+ ]
+ ),
+
+ h(
+ DropdownMenuItem,
+ {
+ key: 'default',
+ closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
+ onClick: () => props.dispatch(actions.setDefaultRpcTarget()),
+ },
+ [
+ h('i.fa.fa-question-circle.fa-lg.menu-icon'),
+ 'Localhost 8545',
+ activeNetwork === 'http://localhost:8545' ? h('.check', '✓') : null,
+ ]
+ ),
this.renderCustomOption(props.provider),
this.renderCommonRpc(rpcList, props.provider),
- h(DropMenuItem, {
- label: 'Custom RPC',
- closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
- action: () => this.props.dispatch(actions.showConfigPage()),
- icon: h('i.fa.fa-question-circle.fa-lg'),
- }),
+ h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
+ onClick: () => this.props.dispatch(actions.showConfigPage()),
+ },
+ [
+ h('i.fa.fa-question-circle.fa-lg.menu-icon'),
+ 'Custom RPC',
+ activeNetwork === 'custom' ? h('.check', '✓') : null,
+ ]
+ ),
])
}
@@ -300,54 +351,37 @@ App.prototype.renderDropdown = function () {
const state = this.state || {}
const isOpen = state.isMainMenuOpen
- return h(MenuDroppo, {
+ return h(Dropdown, {
isOpen: isOpen,
zIndex: 11,
onClickOutside: (event) => {
- this.setState({ isMainMenuOpen: !isOpen })
+ const { classList } = event.target
+ const isNotToggleElement = !classList.contains('sandwich-expando')
+ if (isNotToggleElement) {
+ this.setState({ isMainMenuOpen: false })
+ }
},
style: {
position: 'absolute',
- right: 0,
- top: '36px',
+ right: '2px',
+ top: '38px',
},
- innerStyle: {
- background: 'white',
- boxShadow: '1px 1px 2px rgba(0,0,0,0.1)',
- },
- }, [ // DROP MENU ITEMS
- h('style', `
- .drop-menu-item:hover { background:rgb(235, 235, 235); }
- .drop-menu-item i { margin: 11px; }
- `),
-
- h(DropMenuItem, {
- label: 'Settings',
- closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }),
- action: () => this.props.dispatch(actions.showConfigPage()),
- icon: h('i.fa.fa-gear.fa-lg'),
- }),
-
- h(DropMenuItem, {
- label: 'Import Account',
+ innerStyle: {},
+ }, [
+ h(DropdownMenuItem, {
closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }),
- action: () => this.props.dispatch(actions.showImportPage()),
- icon: h('i.fa.fa-arrow-circle-o-up.fa-lg'),
- }),
+ onClick: () => { this.props.dispatch(actions.showConfigPage()) },
+ }, 'Settings'),
- h(DropMenuItem, {
- label: 'Lock',
+ h(DropdownMenuItem, {
closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }),
- action: () => this.props.dispatch(actions.lockMetamask()),
- icon: h('i.fa.fa-lock.fa-lg'),
- }),
+ onClick: () => { this.props.dispatch(actions.lockMetamask()) },
+ }, 'Lock'),
- h(DropMenuItem, {
- label: 'Info/Help',
+ h(DropdownMenuItem, {
closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }),
- action: () => this.props.dispatch(actions.showInfoPage()),
- icon: h('i.fa.fa-question.fa-lg'),
- }),
+ onClick: () => { this.props.dispatch(actions.showInfoPage()) },
+ }, 'Info/Help'),
])
}
@@ -414,32 +448,22 @@ App.prototype.renderPrimary = function () {
// show unlock screen
if (!props.isUnlocked) {
- switch (props.currentView.name) {
-
- case 'restoreVault':
- log.debug('rendering restore vault screen')
- return h(HDRestoreVaultScreen, {key: 'HDRestoreVaultScreen'})
-
- case 'config':
- log.debug('rendering config screen from unlock screen.')
- return h(ConfigScreen, {key: 'config'})
-
- default:
- log.debug('rendering locked screen')
- return h(UnlockScreen, {key: 'locked'})
- }
+ return h(MainContainer, {
+ currentViewName: props.currentView.name,
+ isUnlocked: props.isUnlocked,
+ })
}
+ // Note for @Zanibar - isUnlocked stays true.
+ // console.log("props.isUnlocked", props.isUnlocked)
+ // console.log("props.isUnlocked", props.currentView.name)
+
// show current view
switch (props.currentView.name) {
- case 'accounts':
- log.debug('rendering accounts screen')
- return h(AccountsScreen, {key: 'accounts'})
-
case 'accountDetail':
- log.debug('rendering account detail screen')
- return h(AccountDetailScreen, {key: 'account-detail'})
+ log.debug('rendering main container')
+ return h(MainContainer, {key: 'account-detail'})
case 'sendTransaction':
log.debug('rendering send tx screen')
@@ -507,7 +531,7 @@ App.prototype.renderPrimary = function () {
default:
log.debug('rendering default, account detail screen')
- return h(AccountDetailScreen, {key: 'account-detail'})
+ return h(MainContainer, {key: 'account-detail'})
}
}
@@ -525,6 +549,8 @@ App.prototype.toggleMetamaskActive = function () {
App.prototype.renderCustomOption = function (provider) {
const { rpcTarget, type } = provider
+ const props = this.props
+
if (type !== 'rpc') return null
// Concatenate long URLs
@@ -539,13 +565,19 @@ App.prototype.renderCustomOption = function (provider) {
return null
default:
- return h(DropMenuItem, {
- label,
- key: rpcTarget,
- closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
- icon: h('i.fa.fa-question-circle.fa-lg'),
- activeNetworkRender: 'custom',
- })
+ return h(
+ DropdownMenuItem,
+ {
+ key: rpcTarget,
+ onClick: () => props.dispatch(actions.setRpcTarget(rpcTarget)),
+ closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
+ },
+ [
+ h('i.fa.fa-question-circle.fa-lg.menu-icon'),
+ label,
+ h('.check', '✓'),
+ ]
+ )
}
}
@@ -571,21 +603,27 @@ App.prototype.getNetworkName = function () {
}
App.prototype.renderCommonRpc = function (rpcList, provider) {
- const { rpcTarget } = provider
const props = this.props
+ const rpcTarget = provider.rpcTarget
return rpcList.map((rpc) => {
if ((rpc === 'http://localhost:8545') || (rpc === rpcTarget)) {
return null
} else {
- return h(DropMenuItem, {
- label: rpc,
- key: rpc,
- closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
- action: () => props.dispatch(actions.setRpcTarget(rpc)),
- icon: h('i.fa.fa-question-circle.fa-lg'),
- activeNetworkRender: rpc,
- })
+
+ return h(
+ DropdownMenuItem,
+ {
+ key: `common${rpc}`,
+ closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
+ onClick: () => props.dispatch(actions.setRpcTarget(rpc)),
+ },
+ [
+ h('i.fa.fa-question-circle.fa-lg.menu-icon'),
+ rpc,
+ rpcTarget === rpc ? h('.check', '✓') : null,
+ ]
+ )
}
})
}
diff --git a/ui/app/components/account-dropdowns.js b/ui/app/components/account-dropdowns.js
new file mode 100644
index 000000000..2813f4752
--- /dev/null
+++ b/ui/app/components/account-dropdowns.js
@@ -0,0 +1,235 @@
+const Component = require('react').Component
+const PropTypes = require('react').PropTypes
+const h = require('react-hyperscript')
+const actions = require('../actions')
+const genAccountLink = require('../../lib/account-link.js')
+const connect = require('react-redux').connect
+const Dropdown = require('./dropdown').Dropdown
+const DropdownMenuItem = require('./dropdown').DropdownMenuItem
+const Identicon = require('./identicon')
+const ethUtil = require('ethereumjs-util')
+const copyToClipboard = require('copy-to-clipboard')
+
+class AccountDropdowns extends Component {
+ constructor (props) {
+ super(props)
+ this.state = {
+ accountSelectorActive: false,
+ optionsMenuActive: false,
+ }
+ this.accountSelectorToggleClassName = 'fa-angle-down';
+ this.optionsMenuToggleClassName = 'fa-ellipsis-h';
+ }
+
+ renderAccounts () {
+ const { identities, selected } = this.props
+
+ return Object.keys(identities).map((key) => {
+ const identity = identities[key]
+ const isSelected = identity.address === selected
+
+ return h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => {},
+ onClick: () => {
+ this.props.actions.showAccountDetail(identity.address)
+ },
+ },
+ [
+ h(
+ Identicon,
+ {
+ address: identity.address,
+ diameter: 16,
+ },
+ ),
+ h('span', { style: { marginLeft: '10px' } }, identity.name || ''),
+ h('span', { style: { marginLeft: '10px' } }, isSelected ? h('.check', '✓') : null),
+ ]
+ )
+ })
+ }
+
+ renderAccountSelector () {
+ const { actions } = this.props
+ const { accountSelectorActive } = this.state
+
+ return h(
+ Dropdown,
+ {
+ style: {
+ marginLeft: '-125px',
+ minWidth: '180px',
+ overflowY: 'auto',
+ maxHeight: '300px',
+ },
+ isOpen: accountSelectorActive,
+ onClickOutside: (event) => {
+ const { classList } = event.target
+ const isNotToggleElement = !classList.contains(this.accountSelectorToggleClassName)
+ if (accountSelectorActive && isNotToggleElement) {
+ this.setState({ accountSelectorActive: false })
+ }
+ },
+ },
+ [
+ ...this.renderAccounts(),
+ h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => {},
+ onClick: () => actions.addNewAccount(),
+ },
+ [
+ h(
+ Identicon,
+ {
+ diameter: 16,
+ },
+ ),
+ h('span', { style: { marginLeft: '10px' } }, 'Create Account'),
+ ],
+ ),
+ h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => {},
+ onClick: () => actions.showImportPage(),
+ },
+ [
+ h(
+ Identicon,
+ {
+ diameter: 16,
+ },
+ ),
+ h('span', { style: { marginLeft: '10px' } }, 'Import Account'),
+ ]
+ ),
+ ]
+ )
+ }
+
+ renderAccountOptions () {
+ const { actions } = this.props
+ const { optionsMenuActive } = this.state
+
+ return h(
+ Dropdown,
+ {
+ style: {
+ marginLeft: '-162px',
+ minWidth: '180px',
+ },
+ isOpen: optionsMenuActive,
+ onClickOutside: () => {
+ const { classList } = event.target
+ const isNotToggleElement = !classList.contains(this.optionsMenuToggleClassName)
+ if (optionsMenuActive && isNotToggleElement) {
+ this.setState({ optionsMenuActive: false })
+ }
+ },
+ },
+ [
+ h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => {},
+ onClick: () => {
+ const { selected, network } = this.props
+ const url = genAccountLink(selected, network)
+ global.platform.openWindow({ url })
+ },
+ },
+ 'View account on Etherscan',
+ ),
+ h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => {},
+ onClick: () => {
+ const { selected } = this.props
+ const checkSumAddress = selected && ethUtil.toChecksumAddress(selected)
+ copyToClipboard(checkSumAddress)
+ },
+ },
+ 'Copy Address to clipboard',
+ ),
+ h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => {},
+ onClick: () => {
+ actions.requestAccountExport()
+ },
+ },
+ 'Export Private Key',
+ ),
+ ]
+ )
+ }
+
+ render () {
+ const { style } = this.props
+ const { optionsMenuActive, accountSelectorActive } = this.state
+
+ return h(
+ 'span',
+ {
+ style: style,
+ },
+ [
+ h(
+ 'i.fa.fa-angle-down',
+ {
+ style: {},
+ onClick: (event) => {
+ event.stopPropagation()
+ this.setState({
+ accountSelectorActive: !accountSelectorActive,
+ optionsMenuActive: false,
+ })
+ },
+ },
+ this.renderAccountSelector(),
+ ),
+ h(
+ 'i.fa.fa-ellipsis-h',
+ {
+ style: { 'marginLeft': '10px'},
+ onClick: (event) => {
+ event.stopPropagation()
+ this.setState({
+ accountSelectorActive: false,
+ optionsMenuActive: !optionsMenuActive,
+ })
+ },
+ },
+ this.renderAccountOptions()
+ ),
+ ]
+ )
+ }
+}
+
+AccountDropdowns.propTypes = {
+ identities: PropTypes.objectOf(PropTypes.object),
+ selected: PropTypes.string,
+}
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ actions: {
+ showConfigPage: () => dispatch(actions.showConfigPage()),
+ requestAccountExport: () => dispatch(actions.requestExportAccount()),
+ showAccountDetail: (address) => dispatch(actions.showAccountDetail(address)),
+ addNewAccount: () => dispatch(actions.addNewAccount()),
+ showImportPage: () => dispatch(actions.showImportPage()),
+ },
+ }
+}
+
+module.exports = {
+ AccountDropdowns: connect(null, mapDispatchToProps)(AccountDropdowns),
+}
diff --git a/ui/app/components/account-info-link.js b/ui/app/components/account-info-link.js
deleted file mode 100644
index 6526ab502..000000000
--- a/ui/app/components/account-info-link.js
+++ /dev/null
@@ -1,41 +0,0 @@
-const Component = require('react').Component
-const h = require('react-hyperscript')
-const inherits = require('util').inherits
-const Tooltip = require('./tooltip')
-const genAccountLink = require('../../lib/account-link')
-
-module.exports = AccountInfoLink
-
-inherits(AccountInfoLink, Component)
-function AccountInfoLink () {
- Component.call(this)
-}
-
-AccountInfoLink.prototype.render = function () {
- const { selected, network } = this.props
- const title = 'View account on Etherscan'
- const url = genAccountLink(selected, network)
-
- if (!url) {
- return null
- }
-
- return h('.account-info-link', {
- style: {
- display: 'flex',
- alignItems: 'center',
- },
- }, [
-
- h(Tooltip, {
- title,
- }, [
- h('i.fa.fa-info-circle.cursor-pointer.color-orange', {
- style: {
- margin: '5px',
- },
- onClick () { global.platform.openWindow({ url }) },
- }),
- ]),
- ])
-}
diff --git a/ui/app/components/drop-menu-item.js b/ui/app/components/drop-menu-item.js
deleted file mode 100644
index e42948209..000000000
--- a/ui/app/components/drop-menu-item.js
+++ /dev/null
@@ -1,59 +0,0 @@
-const Component = require('react').Component
-const h = require('react-hyperscript')
-const inherits = require('util').inherits
-
-module.exports = DropMenuItem
-
-inherits(DropMenuItem, Component)
-function DropMenuItem () {
- Component.call(this)
-}
-
-DropMenuItem.prototype.render = function () {
- return h('li.drop-menu-item', {
- onClick: () => {
- this.props.closeMenu()
- this.props.action()
- },
- style: {
- listStyle: 'none',
- padding: '6px 16px 6px 5px',
- fontFamily: 'Montserrat Regular',
- color: 'rgb(125, 128, 130)',
- cursor: 'pointer',
- display: 'flex',
- justifyContent: 'flex-start',
- },
- }, [
- this.props.icon,
- this.props.label,
- this.activeNetworkRender(),
- ])
-}
-
-DropMenuItem.prototype.activeNetworkRender = function () {
- const activeNetwork = this.props.activeNetworkRender
- const { provider } = this.props
- const providerType = provider ? provider.type : null
- if (activeNetwork === undefined) return
-
- switch (this.props.label) {
- case 'Main Ethereum Network':
- if (providerType === 'mainnet') return h('.check', '✓')
- break
- case 'Ropsten Test Network':
- if (providerType === 'ropsten') return h('.check', '✓')
- break
- case 'Kovan Test Network':
- if (providerType === 'kovan') return h('.check', '✓')
- break
- case 'Rinkeby Test Network':
- if (providerType === 'rinkeby') return h('.check', '✓')
- break
- case 'Localhost 8545':
- if (activeNetwork === 'http://localhost:8545') return h('.check', '✓')
- break
- default:
- if (activeNetwork === 'custom') return h('.check', '✓')
- }
-}
diff --git a/ui/app/components/dropdown.js b/ui/app/components/dropdown.js
new file mode 100644
index 000000000..759800fd6
--- /dev/null
+++ b/ui/app/components/dropdown.js
@@ -0,0 +1,92 @@
+const Component = require('react').Component
+const PropTypes = require('react').PropTypes
+const h = require('react-hyperscript')
+const MenuDroppo = require('menu-droppo')
+const extend = require('xtend')
+
+const noop = () => {}
+
+class Dropdown extends Component {
+ render () {
+ const { isOpen, onClickOutside, style, innerStyle, children } = this.props
+
+ const innerStyleDefaults = extend({
+ borderRadius: '4px',
+ padding: '8px 16px',
+ background: 'rgba(0, 0, 0, 0.8)',
+ boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px',
+ }, innerStyle)
+
+ return h(
+ MenuDroppo,
+ {
+ isOpen,
+ zIndex: 11,
+ onClickOutside,
+ style,
+ innerStyle: innerStyleDefaults,
+ },
+ [
+ h(
+ 'style',
+ `
+ li.dropdown-menu-item:hover { color:rgb(225, 225, 225); }
+ li.dropdown-menu-item { color: rgb(185, 185, 185); }
+ `
+ ),
+ ...children,
+ ]
+ )
+ }
+}
+
+Dropdown.defaultProps = {
+ isOpen: false,
+ onClick: noop,
+}
+
+Dropdown.propTypes = {
+ isOpen: PropTypes.bool.isRequired,
+ onClick: PropTypes.func.isRequired,
+ children: PropTypes.node,
+ style: PropTypes.object.isRequired,
+}
+
+class DropdownMenuItem extends Component {
+ render () {
+ const { onClick, closeMenu, children } = this.props
+
+ return h(
+ 'li.dropdown-menu-item',
+ {
+ onClick: () => {
+ onClick()
+ closeMenu()
+ },
+ style: {
+ listStyle: 'none',
+ padding: '8px 0px 8px 0px',
+ fontSize: '12px',
+ fontStyle: 'normal',
+ fontFamily: 'Montserrat Regular',
+ cursor: 'pointer',
+ display: 'flex',
+ justifyContent: 'flex-start',
+ alignItems: 'center',
+ },
+ },
+ children
+ )
+ }
+}
+
+DropdownMenuItem.propTypes = {
+ closeMenu: PropTypes.func.isRequired,
+ onClick: PropTypes.func.isRequired,
+ children: PropTypes.node,
+}
+
+module.exports = {
+ Dropdown,
+ DropdownMenuItem,
+}
diff --git a/ui/app/components/editable-label.js b/ui/app/components/editable-label.js
index 41936f5e0..167be7eaf 100644
--- a/ui/app/components/editable-label.js
+++ b/ui/app/components/editable-label.js
@@ -30,7 +30,12 @@ EditableLabel.prototype.render = function () {
} else {
return h('div.name-label', {
onClick: (event) => {
- this.setState({ isEditingLabel: true })
+ const nameAttribute = event.target.getAttribute('name')
+ // checks for class to handle smaller CTA above the account name
+ const classAttribute = event.target.getAttribute('class')
+ if (nameAttribute === 'edit' || classAttribute === 'edit-text') {
+ this.setState({ isEditingLabel: true })
+ }
},
}, this.props.children)
}
diff --git a/ui/app/components/ens-input.js b/ui/app/components/ens-input.js
index 3a33ebf74..93c07599d 100644
--- a/ui/app/components/ens-input.js
+++ b/ui/app/components/ens-input.js
@@ -44,6 +44,13 @@ EnsInput.prototype.render = function () {
return h('div', {
style: { width: '100%' },
}, [
+ h('span', {
+ style: {
+ textAlign: 'left',
+ }
+ }, [
+ 'To:'
+ ]),
h('input.large-input', opts),
// The address book functionality.
h('datalist#addresses',
diff --git a/ui/app/components/loading.js b/ui/app/components/loading.js
index 87d6f5d20..163792584 100644
--- a/ui/app/components/loading.js
+++ b/ui/app/components/loading.js
@@ -1,7 +1,6 @@
const inherits = require('util').inherits
const Component = require('react').Component
const h = require('react-hyperscript')
-const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
inherits(LoadingIndicator, Component)
@@ -15,35 +14,28 @@ LoadingIndicator.prototype.render = function () {
const { isLoading, loadingMessage } = this.props
return (
- h(ReactCSSTransitionGroup, {
- className: 'css-transition-group',
- transitionName: 'loader',
- transitionEnterTimeout: 150,
- transitionLeaveTimeout: 150,
+ isLoading ? h('.full-flex-height', {
+ style: {
+ left: '0px',
+ zIndex: 10,
+ position: 'absolute',
+ flexDirection: 'column',
+ display: 'flex',
+ justifyContent: 'center',
+ alignItems: 'center',
+ height: '100%',
+ width: '100%',
+ background: 'rgba(255, 255, 255, 0.8)',
+ },
}, [
+ h('img', {
+ src: 'images/loading.svg',
+ }),
- isLoading ? h('div', {
- style: {
- zIndex: 10,
- position: 'absolute',
- flexDirection: 'column',
- display: 'flex',
- justifyContent: 'center',
- alignItems: 'center',
- height: '100%',
- width: '100%',
- background: 'rgba(255, 255, 255, 0.8)',
- },
- }, [
- h('img', {
- src: 'images/loading.svg',
- }),
-
- h('br'),
-
- showMessageIfAny(loadingMessage),
- ]) : null,
- ])
+ h('br'),
+
+ showMessageIfAny(loadingMessage),
+ ]) : null
)
}
diff --git a/ui/app/components/network.js b/ui/app/components/network.js
index d5d3e18cd..ba1d0ea11 100644
--- a/ui/app/components/network.js
+++ b/ui/app/components/network.js
@@ -39,7 +39,6 @@ Network.prototype.render = function () {
}),
h('i.fa.fa-sort-desc'),
])
-
} else if (providerName === 'mainnet') {
hoverText = 'Main Ethereum Network'
iconName = 'ethereum-network'
@@ -61,7 +60,7 @@ Network.prototype.render = function () {
}
return (
- h('#network_component.pointer', {
+ h('.network-component.pointer', {
title: hoverText,
onClick: (event) => this.props.onClick(event),
}, [
diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js
index 5324ccd64..1c47440f2 100644
--- a/ui/app/components/pending-tx.js
+++ b/ui/app/components/pending-tx.js
@@ -20,6 +20,34 @@ const GWEI_FACTOR = new BN(1e9)
const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR)
const MIN_GAS_LIMIT_BN = new BN(21000)
+
+// Faked, for Icon
+const Identicon = require('./identicon')
+const ARAGON = '960b236A07cf122663c4303350609A66A7B288C0'
+
+// Next: create separate react components
+// roughly 5 components:
+// heroIcon
+// numericDisplay (contains symbol + currency)
+// divider
+// contentBox
+// actionButtons
+const sectionDivider = h('div', {
+ style: {
+ height:'1px',
+ background:'#E7E7E7',
+ },
+})
+
+const contentDivider = h('div', {
+ style: {
+ marginLeft: '16px',
+ marginRight: '16px',
+ height:'1px',
+ background:'#E7E7E7',
+ },
+})
+
module.exports = PendingTx
inherits(PendingTx, Component)
function PendingTx () {
@@ -70,344 +98,342 @@ PendingTx.prototype.render = function () {
this.inputs = []
return (
-
- h('div', {
- key: txMeta.id,
+ h('div.flex-column.flex-grow', {
+ style: {
+ // overflow: 'scroll',
+ minWidth: '355px', // TODO: maxWidth TBD, use home.html
+ },
}, [
- h('form#pending-tx-form', {
- onSubmit: this.onSubmit.bind(this),
-
+ // Main Send token Card
+ h('div.send-screen.flex-column.flex-grow', {
+ style: {
+ marginLeft: '3.5%',
+ marginRight: '3.5%',
+ background: '#FFFFFF', // $background-white
+ boxShadow: '0 2px 4px 0 rgba(0,0,0,0.08)',
+ }
}, [
+ h('section.flex-center.flex-row', {
+ style: {
+ zIndex: 15, // $token-icon-z-index
+ marginTop: '-35px',
+ }
+ }, [
+ h(Identicon, {
+ address: ARAGON,
+ diameter: 76,
+ }),
+ ]),
- // tx info
- h('div', [
+ //
+ // Required Fields
+ //
- h('.flex-row.flex-center', {
- style: {
- maxWidth: '100%',
- },
- }, [
+ h('h3.flex-center', {
+ style: {
+ marginTop: '-18px',
+ fontSize: '16px',
+ },
+ }, [
+ 'Confirm Transaction',
+ ]),
- h(MiniAccountPanel, {
- imageSeed: address,
- picOrder: 'right',
- }, [
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Bold, Montserrat, sans-serif',
- },
- }, identity.name),
-
- h(Copyable, {
- value: ethUtil.toChecksumAddress(address),
- }, [
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Light, Montserrat, sans-serif',
- },
- }, addressSummary(address, 6, 4, false)),
- ]),
-
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Light, Montserrat, sans-serif',
- },
- }, [
- h(EthBalance, {
- value: balance,
- conversionRate,
- currentCurrency,
- inline: true,
- labelColor: '#F7861C',
- }),
- ]),
- ]),
+ h('h3.flex-center', {
+ style: {
+ textAlign: 'center',
+ fontSize: '12px',
+ },
+ }, [
+ 'You\'re sending to Recipient ...5924',
+ ]),
- forwardCarrat(),
+ h('h3.flex-center', {
+ style: {
+ textAlign: 'center',
+ fontSize: '36px',
+ marginTop: '8px',
+ },
+ }, [
+ '0.24',
+ ]),
- this.miniAccountPanelForRecipient(),
- ]),
+ h('h3.flex-center', {
+ style: {
+ textAlign: 'center',
+ fontSize: '12px',
+ marginTop: '4px',
+ },
+ }, [
+ 'ANT',
+ ]),
- h('style', `
- .table-box {
- margin: 7px 0px 0px 0px;
- width: 100%;
- }
- .table-box .row {
- margin: 0px;
- background: rgb(236,236,236);
- display: flex;
- justify-content: space-between;
- font-family: Montserrat Light, sans-serif;
- font-size: 13px;
- padding: 5px 25px;
- }
- .table-box .row .value {
- font-family: Montserrat Regular;
- }
- `),
+ // error message
+ props.error && h('span.error.flex-center', props.error),
- h('.table-box', [
+ sectionDivider,
- // Ether Value
- // Currently not customizable, but easily modified
- // in the way that gas and gasLimit currently are.
- h('.row', [
- h('.cell.label', 'Amount'),
- h(EthBalance, { value: txParams.value, currentCurrency, conversionRate }),
- ]),
+ h('section.flex-row.flex-center', {
+ }, [
+ h('div', {
+ style: {
+ width: '50%',
+ }
+ }, [
+ h('span', {
+ style: {
+ textAlign: 'left',
+ fontSize: '12px',
+ }
+ }, [
+ 'From'
+ ])
+ ]),
- // Gas Limit (customizable)
- h('.cell.row', [
- h('.cell.label', 'Gas Limit'),
- h('.cell.value', {
- }, [
- h(BNInput, {
- name: 'Gas Limit',
- value: gasBn,
- precision: 0,
- scale: 0,
- // The hard lower limit for gas.
- min: MIN_GAS_LIMIT_BN.toString(10),
- max: safeGasLimit,
- suffix: 'UNITS',
- style: {
- position: 'relative',
- top: '5px',
- },
- onChange: this.gasLimitChanged.bind(this),
-
- ref: (hexInput) => { this.inputs.push(hexInput) },
- }),
- ]),
- ]),
+ h('div', {
+ style: {
+ width: '50%',
+ }
+ },[
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '10px',
+ marginBottom: '-10px',
+ },
+ }, 'Aragon Token'),
- // Gas Price (customizable)
- h('.cell.row', [
- h('.cell.label', 'Gas Price'),
- h('.cell.value', {
- }, [
- h(BNInput, {
- name: 'Gas Price',
- value: gasPriceBn,
- precision: 9,
- scale: 9,
- suffix: 'GWEI',
- min: MIN_GAS_PRICE_GWEI_BN.toString(10),
- style: {
- position: 'relative',
- top: '5px',
- },
- onChange: this.gasPriceChanged.bind(this),
- ref: (hexInput) => { this.inputs.push(hexInput) },
- }),
- ]),
- ]),
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '8px',
+ },
+ }, 'Your Balance 2.34 ANT')
+ ])
+ ]),
- // Max Transaction Fee (calculated)
- h('.cell.row', [
- h('.cell.label', 'Max Transaction Fee'),
- h(EthBalance, { value: txFeeBn.toString(16), currentCurrency, conversionRate }),
- ]),
+ contentDivider,
- h('.cell.row', {
+ h('section.flex-row.flex-center', {
+ }, [
+ h('div', {
+ style: {
+ width: '50%',
+ }
+ }, [
+ h('span', {
style: {
- fontFamily: 'Montserrat Regular',
- background: 'white',
- padding: '10px 25px',
- },
+ textAlign: 'left',
+ fontSize: '12px',
+ }
}, [
- h('.cell.label', 'Max Total'),
- h('.cell.value', {
- style: {
- display: 'flex',
- alignItems: 'center',
- },
- }, [
- h(EthBalance, {
- value: maxCost.toString(16),
- currentCurrency,
- conversionRate,
- inline: true,
- labelColor: 'black',
- fontSize: '16px',
- }),
- ]),
- ]),
+ 'To'
+ ])
+ ]),
- // Data size row:
- h('.cell.row', {
+ h('div', {
+ style: {
+ width: '50%',
+ }
+ },[
+ h('div', {
style: {
- background: '#f7f7f7',
- paddingBottom: '0px',
+ textAlign: 'left',
+ fontSize: '10px',
+ marginBottom: '-10px',
},
- }, [
- h('.cell.label'),
- h('.cell.value', {
- style: {
- fontFamily: 'Montserrat Light',
- fontSize: '11px',
- },
- }, `Data included: ${dataLength} bytes`),
- ]),
- ]), // End of Table
+ }, 'Ethereum Address'),
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '8px',
+ },
+ }, '...5924')
+ ])
]),
- h('style', `
- .conf-buttons button {
- margin-left: 10px;
- text-transform: uppercase;
- }
- `),
+ contentDivider,
- txMeta.simulationFails ?
- h('.error', {
- style: {
- marginLeft: 50,
- fontSize: '0.9em',
- },
- }, 'Transaction Error. Exception thrown in contract code.')
- : null,
-
- !isValidAddress ?
- h('.error', {
+ h('section.flex-row.flex-center', {
+ }, [
+ h('div', {
style: {
- marginLeft: 50,
- fontSize: '0.9em',
- },
- }, 'Recipient address is invalid. Sending this transaction will result in a loss of ETH.')
- : null,
-
- insufficientBalance ?
- h('span.error', {
+ width: '50%',
+ }
+ }, [
+ h('span', {
+ style: {
+ textAlign: 'left',
+ fontSize: '12px',
+ }
+ }, [
+ 'Gas Fee'
+ ])
+ ]),
+
+ h('div', {
style: {
- marginLeft: 50,
- fontSize: '0.9em',
- },
- }, 'Insufficient balance for transaction')
- : null,
-
- // send + cancel
- h('.flex-row.flex-space-around.conf-buttons', {
+ width: '50%',
+ }
+ },[
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '10px',
+ marginBottom: '-10px',
+ },
+ }, '$0.04 USD'),
+
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '8px',
+ },
+ }, '0.001575 ETH')
+ ])
+ ]),
+
+ contentDivider,
+
+ h('section.flex-row.flex-center', {
style: {
- display: 'flex',
- justifyContent: 'flex-end',
- margin: '14px 25px',
- },
+ backgroundColor: '#F6F6F6', // $wild-sand
+ borderRadius: '8px',
+ marginLeft: '10px',
+ marginRight: '10px',
+ paddingLeft: '6px',
+ paddingRight: '6px',
+ marginBottom: '10px',
+ }
}, [
+ h('div', {
+ style: {
+ width: '50%',
+ }
+ }, [
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '12px',
+ marginBottom: '-10px',
+ }
+ }, [
+ 'Total Tokens'
+ ]),
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '8px',
+ }
+ }, [
+ 'Total Gas'
+ ])
- insufficientBalance ?
- h('button.btn-green', {
- onClick: props.buyEth,
- }, 'Buy Ether')
- : null,
-
- h('button', {
- onClick: (event) => {
- this.resetGasFields()
- event.preventDefault()
- },
- }, 'Reset'),
-
- // Accept Button
- h('input.confirm.btn-green', {
- type: 'submit',
- value: 'SUBMIT',
- style: { marginLeft: '10px' },
- disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting,
- }),
+ ]),
- h('button.cancel.btn-red', {
- onClick: props.cancelTransaction,
- }, 'Reject'),
- ]),
- ]),
- ])
- )
-}
+ h('div', {
+ style: {
+ width: '50%',
+ }
+ },[
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '10px',
+ marginBottom: '-10px',
+ },
+ }, '0.24 ANT (127.00 USD)'),
-PendingTx.prototype.miniAccountPanelForRecipient = function () {
- const props = this.props
- const txData = props.txData
- const txParams = txData.txParams || {}
- const isContractDeploy = !('to' in txParams)
-
- // If it's not a contract deploy, send to the account
- if (!isContractDeploy) {
- return h(MiniAccountPanel, {
- imageSeed: txParams.to,
- picOrder: 'left',
- }, [
+ h('div', {
+ style: {
+ textAlign: 'left',
+ fontSize: '8px',
+ },
+ }, '0.249 ETH')
+ ])
+ ]),
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Bold, Montserrat, sans-serif',
- },
- }, nameForAddress(txParams.to, props.identities)),
+ ]), // end of container
- h(Copyable, {
- value: ethUtil.toChecksumAddress(txParams.to),
+ h('form#pending-tx-form.flex-column.flex-center', {
+ onSubmit: this.onSubmit.bind(this),
}, [
- h('span.font-small', {
+ // Reset Button
+ // h('button', {
+ // onClick: (event) => {
+ // this.resetGasFields()
+ // event.preventDefault()
+ // },
+ // }, 'Reset'),
+
+ // Accept Button
+ h('input.confirm.btn-green', {
+ type: 'submit',
+ value: 'CONFIRM',
style: {
- fontFamily: 'Montserrat Light, Montserrat, sans-serif',
+ marginTop: '8px',
+ width: '8em',
+ color: '#FFFFFF',
+ borderRadius: '2px',
+ fontSize: '12px',
+ lineHeight: '20px',
+ textAlign: 'center',
+ borderStyle: 'none',
},
- }, addressSummary(txParams.to, 6, 4, false)),
- ]),
-
- ])
- } else {
- return h(MiniAccountPanel, {
- picOrder: 'left',
- }, [
+ disabled: insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting,
+ }),
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Bold, Montserrat, sans-serif',
- },
- }, 'New Contract'),
-
- ])
- }
-}
-
-PendingTx.prototype.gasPriceChanged = function (newBN, valid) {
- log.info(`Gas price changed to: ${newBN.toString(10)}`)
- const txMeta = this.gatherTxMeta()
- txMeta.txParams.gasPrice = '0x' + newBN.toString('hex')
- this.setState({
- txData: clone(txMeta),
- valid,
- })
-}
-
-PendingTx.prototype.gasLimitChanged = function (newBN, valid) {
- log.info(`Gas limit changed to ${newBN.toString(10)}`)
- const txMeta = this.gatherTxMeta()
- txMeta.txParams.gas = '0x' + newBN.toString('hex')
- this.setState({
- txData: clone(txMeta),
- valid,
- })
+ // Cancel Button
+ h('button.cancel.btn-light', {
+ style: {
+ background: '#F7F7F7', // $alabaster
+ border: 'none',
+ opacity: 1,
+ width: '8em',
+ },
+ onClick: props.cancelTransaction,
+ }, 'CANCEL'),
+ ]),
+ ]) // end of minwidth wrapper
+ )
}
-PendingTx.prototype.resetGasFields = function () {
- log.debug(`pending-tx resetGasFields`)
-
- this.inputs.forEach((hexInput) => {
- if (hexInput) {
- hexInput.setValid()
- }
- })
-
- this.setState({
- txData: null,
- valid: true,
- })
-}
+// PendingTx.prototype.gasPriceChanged = function (newBN, valid) {
+// log.info(`Gas price changed to: ${newBN.toString(10)}`)
+// const txMeta = this.gatherTxMeta()
+// txMeta.txParams.gasPrice = '0x' + newBN.toString('hex')
+// this.setState({
+// txData: clone(txMeta),
+// valid,
+// })
+// }
+
+// PendingTx.prototype.gasLimitChanged = function (newBN, valid) {
+// log.info(`Gas limit changed to ${newBN.toString(10)}`)
+// const txMeta = this.gatherTxMeta()
+// txMeta.txParams.gas = '0x' + newBN.toString('hex')
+// this.setState({
+// txData: clone(txMeta),
+// valid,
+// })
+// }
+
+// PendingTx.prototype.resetGasFields = function () {
+// log.debug(`pending-tx resetGasFields`)
+
+// this.inputs.forEach((hexInput) => {
+// if (hexInput) {
+// hexInput.setValid()
+// }
+// })
+
+// this.setState({
+// txData: null,
+// valid: true,
+// })
+// }
PendingTx.prototype.onSubmit = function (event) {
event.preventDefault()
@@ -466,15 +492,3 @@ PendingTx.prototype.bnMultiplyByFraction = function (targetBN, numerator, denomi
const denomBN = new BN(denominator)
return targetBN.mul(numBN).div(denomBN)
}
-
-function forwardCarrat () {
- return (
- h('img', {
- src: 'images/forward-carrat.svg',
- style: {
- padding: '5px 6px 0px 10px',
- height: '37px',
- },
- })
- )
-}
diff --git a/ui/app/components/shapeshift-form.js b/ui/app/components/shapeshift-form.js
index e0a720426..76a265d63 100644
--- a/ui/app/components/shapeshift-form.js
+++ b/ui/app/components/shapeshift-form.js
@@ -2,7 +2,6 @@ const PersistentForm = require('../../lib/persistent-form')
const h = require('react-hyperscript')
const inherits = require('util').inherits
const connect = require('react-redux').connect
-const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
const actions = require('../actions')
const Qr = require('./qr-code')
const isValidAddress = require('../util').isValidAddress
@@ -24,14 +23,7 @@ function ShapeshiftForm () {
}
ShapeshiftForm.prototype.render = function () {
- return h(ReactCSSTransitionGroup, {
- className: 'css-transition-group',
- transitionName: 'main',
- transitionEnterTimeout: 300,
- transitionLeaveTimeout: 300,
- }, [
- this.props.qrRequested ? h(Qr, {key: 'qr'}) : this.renderMain(),
- ])
+ return this.props.qrRequested ? h(Qr, {key: 'qr'}) : this.renderMain()
}
ShapeshiftForm.prototype.renderMain = function () {
diff --git a/ui/app/components/tab-bar.js b/ui/app/components/tab-bar.js
index 6295e7dd9..bef444a48 100644
--- a/ui/app/components/tab-bar.js
+++ b/ui/app/components/tab-bar.js
@@ -21,6 +21,7 @@ TabBar.prototype.render = function () {
background: '#EBEBEB',
color: '#AEAEAE',
paddingTop: '4px',
+ minHeight: '30px',
},
}, tabs.map((tab) => {
const { key, content } = tab
diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js
index 20cfa897e..5ea31ae8d 100644
--- a/ui/app/components/token-list.js
+++ b/ui/app/components/token-list.js
@@ -47,10 +47,11 @@ TokenList.prototype.render = function () {
return h(TokenCell, tokenData)
})
- return h('div', [
- h('ol', {
+ return h('.full-flex-height', [
+ this.renderTokenStatusBar(),
+
+ h('ol.full-flex-height.flex-column', {
style: {
- height: '260px',
overflowY: 'auto',
display: 'flex',
flexDirection: 'column',
@@ -63,6 +64,7 @@ TokenList.prototype.render = function () {
flex-direction: row;
align-items: center;
padding: 10px;
+ min-height: 50px;
}
li.token-cell > h3 {
@@ -76,17 +78,37 @@ TokenList.prototype.render = function () {
`),
...tokenViews,
- tokenViews.length ? null : this.message('No Tokens Found.'),
+ h('.flex-grow'),
]),
- this.addTokenButtonElement(),
])
}
-TokenList.prototype.addTokenButtonElement = function () {
- return h('div', [
- h('div.footer.hover-white.pointer', {
+TokenList.prototype.renderTokenStatusBar = function () {
+ const { tokens } = this.state
+
+ let msg
+ if (tokens.length === 1) {
+ msg = `You own 1 token`
+ } else if (tokens.length === 1) {
+ msg = `You own ${tokens.length} tokens`
+ } else {
+ msg = `No tokens found`
+ }
+
+ return h('div', {
+ style: {
+ display: 'flex',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ minHeight: '70px',
+ padding: '10px',
+ },
+ }, [
+ h('span', msg),
+ h('button', {
key: 'reveal-account-bar',
- onClick: () => {
+ onClick: (event) => {
+ event.preventDefault()
this.props.addToken()
},
style: {
@@ -97,7 +119,7 @@ TokenList.prototype.addTokenButtonElement = function () {
alignItems: 'center',
},
}, [
- h('i.fa.fa-plus.fa-lg'),
+ 'ADD TOKEN',
]),
])
}
diff --git a/ui/app/components/transaction-list.js b/ui/app/components/transaction-list.js
index 3b4ba741e..69b72614c 100644
--- a/ui/app/components/transaction-list.js
+++ b/ui/app/components/transaction-list.js
@@ -24,7 +24,11 @@ TransactionList.prototype.render = function () {
return (
- h('section.transaction-list', [
+ h('section.transaction-list.full-flex-height', {
+ style: {
+ justifyContent: 'center',
+ },
+ }, [
h('style', `
.transaction-list .transaction-list-item:not(:last-of-type) {
@@ -39,7 +43,7 @@ TransactionList.prototype.render = function () {
h('.tx-list', {
style: {
overflowY: 'auto',
- height: '300px',
+ height: '100%',
padding: '0 20px',
textAlign: 'center',
},
@@ -64,13 +68,17 @@ TransactionList.prototype.render = function () {
},
})
})
- : h('.flex-center', {
+ : h('.flex-center.full-flex-height', {
style: {
flexDirection: 'column',
- height: '100%',
+ justifyContent: 'center',
},
}, [
- 'No transaction history.',
+ h('p', {
+ style: {
+ marginTop: '50px',
+ },
+ }, 'No transaction history.'),
]),
]),
])
diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js
new file mode 100644
index 000000000..2bc6daae5
--- /dev/null
+++ b/ui/app/components/tx-view.js
@@ -0,0 +1,228 @@
+const Component = require('react').Component
+const connect = require('react-redux').connect
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const actions = require('../actions')
+// slideout menu
+const SlideoutMenu = require('react-burger-menu').slide
+const WalletView = require('./wallet-view')
+
+const Identicon = require('./identicon')
+// const AccountDropdowns = require('./account-dropdowns').AccountDropdowns
+// const Content = require('./wallet-content-display')
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(TxView)
+
+function mapStateToProps (state) {
+ return {
+ sidebarOpen: state.appState.sidebarOpen,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ showSidebar: () => {dispatch(actions.showSidebar())},
+ hideSidebar: () => {dispatch(actions.hideSidebar())},
+ }
+}
+
+const contentDivider = h('div', {
+ style: {
+ marginLeft: '1.3em',
+ marginRight: '1.3em',
+ height:'1px',
+ background:'#E7E7E7', // TODO: make custom color
+ },
+})
+
+inherits(TxView, Component)
+function TxView () {
+ Component.call(this)
+}
+
+TxView.prototype.render = function () {
+ const selected = '0x82df11beb942BEeeD58d466fCb0F0791365C7684' // TODO: remove fake address
+
+ return h('div.tx-view.flex-column', {
+ style: {
+ flex: '62 0 62%',
+ background: '#FFFFFF',
+ }
+ }, [
+
+ h('div.flex-row.phone-visible', {
+ style: {
+ margin: '1em 0.9em',
+ alignItems: 'center'
+ },
+ onClick: () => {
+ this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar()
+ },
+ }, [
+ // burger
+ h('div.fa.fa-bars', {
+ style: {
+ fontSize: '1.3em',
+ },
+ }, []),
+
+ //account display
+ h('.identicon-wrapper.select-none', {
+ style: {
+ marginLeft: '0.9em',
+ },
+ }, [
+ h(Identicon, {
+ diameter: 24,
+ address: selected,
+ }),
+ ]),
+
+ h('span.account-name', {
+ style: {}
+ }, [
+ 'Account 1'
+ ]),
+
+ ]),
+
+ // laptop: flex-row, flex-center
+ // mobile: flex-column
+ h('div.hero-balance', {
+ style: {},
+ }, [
+
+ // laptop: 50px 50px
+ // mobile: 100px 100px
+ h('img.hero-balance-icon', {
+ src: '../images/eth_logo.svg',
+ style: {}
+ }),
+
+ // laptop: 5vw?
+ // phone: 50vw?
+ h('div.flex-column.hero-balance-display', {}, [
+ h('div.token-amount', {
+ style: {}
+ }, '1001.124 ETH'),
+
+ h('div.fiat-amount', {
+ style: {}
+ }, '$300,000 USD'),
+ ]),
+
+ // laptop: 10vw?
+ // phone: 75vw?
+ h('div.flex-row.flex-center.hero-balance-buttons', {
+ style: {}
+ }, [
+ h('button.btn-clear', {
+ style: {
+ textAlign: 'center',
+ },
+ }, 'BUY'),
+
+ h('button.btn-clear', {
+ style: {
+ textAlign: 'center',
+ marginLeft: '1.4em',
+ },
+ }, 'SEND'),
+
+ ]),
+ ]),
+
+ h('div.flex-row', {
+ style: {
+ margin: '1.8em 0.9em 0.8em 0.9em',
+ }
+ }, [
+
+ // tx-view-tab.js
+ h('div.flex-row', {
+ }, [
+
+ h('div', {
+ style: {
+ borderBottom: '0.07em solid black',
+ paddingBottom: '0.015em',
+ }
+ }, 'TRANSACTIONS'),
+
+ h('div', {
+ style: {
+ marginLeft: '1.25em',
+ }
+ }, 'TOKENS'),
+
+ ]),
+ ]),
+
+ contentDivider,
+
+ this.renderTransactionListItem(),
+
+ contentDivider,
+
+ this.renderTransactionListItem(),
+
+ contentDivider,
+
+ ])
+ // column
+ // tab row
+ // divider
+ // item
+}
+
+TxView.prototype.renderTransactionListItem = function () {
+ return h('div.flex-column', {
+ style: {
+ alignItems: 'stretch',
+ margin: '0.6em 1.3em 0.6em 1.3em',
+ }
+ }, [
+
+ h('div', {
+ style: {
+ flexGrow: 1,
+ marginTop: '0.3em',
+ }
+ }, 'Jul 01, 2017'),
+
+ h('div.flex-row', {
+ style: {
+ alignItems: 'stretch',
+ }
+ }, [
+
+ h('div', {
+ style: {
+ flexGrow: 1,
+ }
+ }, 'icon'),
+
+ h('div', {
+ style: {
+ flexGrow: 3,
+ }
+ }, 'Hash'),
+
+ h('div', {
+ style: {
+ flexGrow: 5,
+ }
+ }, 'Status'),
+
+ h('div', {
+ style: {
+ flexGrow: 2,
+ }
+ }, 'Details'),
+
+ ])
+
+ ])
+}
+
+
diff --git a/ui/app/components/wallet-content-display.js b/ui/app/components/wallet-content-display.js
new file mode 100644
index 000000000..3baffad69
--- /dev/null
+++ b/ui/app/components/wallet-content-display.js
@@ -0,0 +1,56 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+
+module.exports = WalletContentDisplay
+
+inherits(WalletContentDisplay, Component)
+function WalletContentDisplay () {
+ Component.call(this)
+}
+
+WalletContentDisplay.prototype.render = function () {
+ const { title, amount, fiatValue, active, style } = this.props
+
+ // TODO: Separate component: wallet-content-account
+ return h('div.flex-column', {
+ style: {
+ marginLeft: '1.3em',
+ alignItems: 'flex-start',
+ ...style,
+ }
+ }, [
+
+ h('span', {
+ style: {
+ fontSize: '1.1em',
+ },
+ }, title),
+
+ h('span', {
+ style: {
+ fontSize: '1.8em',
+ margin: '0.4em 0em',
+ },
+ }, amount),
+
+ h('span', {
+ style: {
+ fontSize: '1.3em',
+ },
+ }, fiatValue),
+
+ active && h('div', {
+ style: {
+ position: 'absolute',
+ marginLeft: '-1.3em',
+ height: '6em',
+ width: '0.3em',
+ background: '#D8D8D8', // TODO: add to resuable colors
+ }
+ }, [
+ ])
+ ])
+
+}
+
diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js
new file mode 100644
index 000000000..cb1448598
--- /dev/null
+++ b/ui/app/components/wallet-view.js
@@ -0,0 +1,97 @@
+const Component = require('react').Component
+const connect = require('react-redux').connect
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const Identicon = require('./identicon')
+const AccountDropdowns = require('./account-dropdowns').AccountDropdowns
+const Content = require('./wallet-content-display')
+const actions = require('../actions')
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(WalletView)
+
+function mapStateToProps (state) {
+ return {
+ network: state.metamask.network,
+ sidebarOpen: state.appState.sidebarOpen,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ showSendPage: () => {dispatch(actions.showSendPage())},
+ hideSidebar: () => {dispatch(actions.hideSidebar())},
+ }
+}
+
+inherits(WalletView, Component)
+function WalletView () {
+ Component.call(this)
+}
+
+const noop = () => {}
+
+WalletView.prototype.render = function () {
+ const selected = '0x82df11beb942BEeeD58d466fCb0F0791365C7684' // TODO: remove fake address
+ const { network, responsiveDisplayClassname, style } = this.props
+
+ return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), {
+ style: {
+ flex: '28 0 28%',
+ background: '#FAFAFA', // TODO: add to reusable colors
+ ...style,
+ }
+ }, [
+
+ // TODO: Separate component: wallet account details
+ h('div.flex-column', {
+ style: {}
+ }, [
+
+ h('.identicon-wrapper.select-none', [
+ h(Identicon, {
+ diameter: 24,
+ address: selected,
+ }),
+ ]),
+
+ h('span.account-name', {
+ style: {}
+ }, [
+ 'Account 1'
+ ]),
+
+ h(
+ AccountDropdowns,
+ {
+ style: {
+ marginLeft: 'auto',
+ cursor: 'pointer',
+ },
+ selected,
+ network, // TODO: this prop could be in the account dropdown container
+ identities: {},
+ },
+ ),
+
+ ]),
+
+ h(Content, {
+ title: 'Wallet',
+ amount: '1001.124 ETH',
+ fiatValue: '$300,000.00 USD',
+ active: true,
+ }),
+
+ // Wallet contents
+ h(Content, {
+ title: "Total Token Balance",
+ amount: "45.439 ETH",
+ fiatValue: "$13,000.00 USD",
+ active: false,
+ style: {
+ marginTop: '1.3em',
+ }
+ })
+
+ ])
+}
diff --git a/ui/app/conf-tx.js b/ui/app/conf-tx.js
index 747d3ce2b..4a8c616e2 100644
--- a/ui/app/conf-tx.js
+++ b/ui/app/conf-tx.js
@@ -1,6 +1,5 @@
const inherits = require('util').inherits
const Component = require('react').Component
-const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
const h = require('react-hyperscript')
const connect = require('react-redux').connect
const actions = require('./actions')
@@ -53,75 +52,25 @@ ConfirmTxScreen.prototype.render = function () {
log.info(`rendering a combined ${unconfTxList.length} unconf msg & txs`)
if (unconfTxList.length === 0) return h(Loading, { isLoading: true })
- return (
-
- h('.flex-column.flex-grow', [
-
- // subtitle and nav
- h('.section-title.flex-row.flex-center', [
- !isNotification ? h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
- onClick: this.goHome.bind(this),
- }) : null,
- h('h2.page-subtitle', 'Confirm Transaction'),
- isNotification ? h(NetworkIndicator, {
- network: network,
- provider: provider,
- }) : null,
- ]),
-
- h('h3', {
- style: {
- alignSelf: 'center',
- display: unconfTxList.length > 1 ? 'block' : 'none',
- },
- }, [
- h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
- style: {
- display: props.index === 0 ? 'none' : 'inline-block',
- },
- onClick: () => props.dispatch(actions.previousTx()),
- }),
- ` ${props.index + 1} of ${unconfTxList.length} `,
- h('i.fa.fa-arrow-right.fa-lg.cursor-pointer', {
- style: {
- display: props.index + 1 === unconfTxList.length ? 'none' : 'inline-block',
- },
- onClick: () => props.dispatch(actions.nextTx()),
- }),
- ]),
-
- warningIfExists(props.warning),
-
- h(ReactCSSTransitionGroup, {
- className: 'css-transition-group',
- transitionName: 'main',
- transitionEnterTimeout: 300,
- transitionLeaveTimeout: 300,
- }, [
-
- currentTxView({
- // Properties
- txData: txData,
- key: txData.id,
- selectedAddress: props.selectedAddress,
- accounts: props.accounts,
- identities: props.identities,
- conversionRate,
- currentCurrency,
- blockGasLimit,
- // Actions
- buyEth: this.buyEth.bind(this, txParams.from || props.selectedAddress),
- sendTransaction: this.sendTransaction.bind(this),
- cancelTransaction: this.cancelTransaction.bind(this, txData),
- signMessage: this.signMessage.bind(this, txData),
- signPersonalMessage: this.signPersonalMessage.bind(this, txData),
- cancelMessage: this.cancelMessage.bind(this, txData),
- cancelPersonalMessage: this.cancelPersonalMessage.bind(this, txData),
- }),
-
- ]),
- ])
- )
+ return currentTxView({
+ // Properties
+ txData: txData,
+ key: txData.id,
+ selectedAddress: props.selectedAddress,
+ accounts: props.accounts,
+ identities: props.identities,
+ conversionRate,
+ currentCurrency,
+ blockGasLimit,
+ // Actions
+ buyEth: this.buyEth.bind(this, txParams.from || props.selectedAddress),
+ sendTransaction: this.sendTransaction.bind(this),
+ cancelTransaction: this.cancelTransaction.bind(this, txData),
+ signMessage: this.signMessage.bind(this, txData),
+ signPersonalMessage: this.signPersonalMessage.bind(this, txData),
+ cancelMessage: this.cancelMessage.bind(this, txData),
+ cancelPersonalMessage: this.cancelPersonalMessage.bind(this, txData),
+ })
}
function currentTxView (opts) {
diff --git a/ui/app/css/debug.css b/ui/app/css/debug.css
deleted file mode 100644
index 3e125bcd4..000000000
--- a/ui/app/css/debug.css
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-debug / dev
-*/
-
-#app-content {
- border: 2px solid green;
-}
-
-#design-container {
- position: absolute;
- left: 360px;
- top: -42px;
- width: calc(100vw - 360px);
- height: 100vh;
- overflow: scroll;
-}
-
-#design-container img {
- width: 2000px;
- margin-right: 600px;
-} \ No newline at end of file
diff --git a/ui/app/css/index.scss b/ui/app/css/index.scss
new file mode 100644
index 000000000..01899ccad
--- /dev/null
+++ b/ui/app/css/index.scss
@@ -0,0 +1,13 @@
+/*
+ ITCSS
+
+ http://www.creativebloq.com/web-design/manage-large-css-projects-itcss-101517528
+ https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/
+ */
+@import './itcss/settings/index.scss';
+@import './itcss/tools/index.scss';
+@import './itcss/generic/index.scss';
+@import './itcss/base/index.scss';
+@import './itcss/objects/index.scss';
+@import './itcss/components/index.scss';
+@import './itcss/trumps/index.scss';
diff --git a/ui/app/css/itcss/base/index.scss b/ui/app/css/itcss/base/index.scss
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ui/app/css/itcss/base/index.scss
diff --git a/ui/app/css/itcss/components/buttons.scss b/ui/app/css/itcss/components/buttons.scss
new file mode 100644
index 000000000..114a2f892
--- /dev/null
+++ b/ui/app/css/itcss/components/buttons.scss
@@ -0,0 +1,83 @@
+/*
+ Buttons
+ */
+
+.btn-green {
+ background-color: #02C9B1; // TODO: reusable color in colors.css
+}
+
+button.btn-clear {
+ background: white;
+ border: 1px solid;
+}
+
+// No longer used in flat design, remove when modal buttons done
+// div.wallet-btn {
+// border: 1px solid rgb(91, 93, 103);
+// border-radius: 2px;
+// height: 30px;
+// width: 75px;
+// font-size: 0.8em;
+// text-align: center;
+// line-height: 25px;
+// }
+
+// .btn-red {
+// background: rgba(254, 35, 17, 1);
+// box-shadow: 0px 3px 6px rgba(254, 35, 17, 0.36);
+// }
+
+// button[disabled], input[type="submit"][disabled] {
+// cursor: not-allowed;
+// background: rgba(197, 197, 197, 1);
+// box-shadow: 0px 3px 6px rgba(197, 197, 197, 0.36);
+// }
+
+// button.spaced {
+// margin: 2px;
+// }
+
+// button:not([disabled]):hover, input[type="submit"]:not([disabled]):hover {
+// transform: scale(1.1);
+// }
+// button:not([disabled]):active, input[type="submit"]:not([disabled]):active {
+// transform: scale(0.95);
+// }
+
+button.primary {
+ padding: 8px 12px;
+ background: #F7861C;
+ box-shadow: 0px 3px 6px rgba(247, 134, 28, 0.36);
+ color: white;
+ font-size: 1.1em;
+ font-family: 'Montserrat Regular';
+ text-transform: uppercase;
+}
+
+.btn-light {
+ padding: 8px 12px;
+ // background: #FFFFFF; // $bg-white
+ box-shadow: 0px 3px 6px rgba(247, 134, 28, 0.36);
+ color: #585D67; // TODO: make reusable light button color
+ font-size: 1.1em;
+ font-family: 'Montserrat Regular';
+ text-transform: uppercase;
+ text-align: center;
+ line-height: 20px;
+ border-radius: 2px;
+ border: 1px solid #979797; // #TODO: make reusable light border color
+ opacity: 0.5;
+}
+
+// TODO: cleanup: not used anywhere
+button.btn-thin {
+ border: 1px solid;
+ border-color: #4D4D4D;
+ color: #4D4D4D;
+ background: rgb(255, 174, 41);
+ border-radius: 4px;
+ min-width: 200px;
+ margin: 12px 0;
+ padding: 6px;
+ font-size: 13px;
+}
diff --git a/ui/app/css/itcss/components/footer.scss b/ui/app/css/itcss/components/footer.scss
new file mode 100644
index 000000000..000a53eed
--- /dev/null
+++ b/ui/app/css/itcss/components/footer.scss
@@ -0,0 +1,4 @@
+.app-footer {
+ padding-bottom: 10px;
+ align-items: center;
+}
diff --git a/ui/app/css/itcss/components/header.scss b/ui/app/css/itcss/components/header.scss
new file mode 100644
index 000000000..405c45f7f
--- /dev/null
+++ b/ui/app/css/itcss/components/header.scss
@@ -0,0 +1,54 @@
+.app-header {
+ align-items: center;
+ visibility: visible;
+ background: rgb(239, 239, 239);
+ padding-top: 1.5vh;
+ height: 12vh;
+ max-height: 60px;
+ position: relative;
+ z-index: 12;
+ padding: 6px 8px;
+ // background: #EFEFEF; // $gallery
+
+ @media screen and (max-width: 575px) {
+ position: fixed;
+ height: 34px;
+ width: 100%;
+ box-shadow: 0px 2px 2px 1px rgba(0, 0, 0, 0.08);
+ z-index: 30;
+ }
+}
+
+.app-header h1 {
+ font-family: 'Montserrat Regular';
+ text-transform: uppercase;
+ color: #22232C; // $shark
+}
+
+h2.page-subtitle {
+ font-family: 'Montserrat Regular';
+ text-transform: uppercase;
+ color: #AEAEAE;
+ font-size: 1em;
+ margin: 12px;
+}
+
+.network-component-wrapper {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+
+ @media screen and (min-width: 576px) {
+ margin-bottom: 1.8em;
+ }
+}
+
+.left-menu-wrapper {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+
+ @media screen and (min-width: 576px) {
+ margin-bottom: 1.8em;
+ }
+} \ No newline at end of file
diff --git a/ui/app/css/itcss/components/hero-balance.scss b/ui/app/css/itcss/components/hero-balance.scss
new file mode 100644
index 000000000..fabba9ed8
--- /dev/null
+++ b/ui/app/css/itcss/components/hero-balance.scss
@@ -0,0 +1,96 @@
+$break-small: 575px;
+$break-medium: 780px;
+$break-large: 576px;
+
+.hero-balance {
+ @media screen and (max-width: $break-small) {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: center;
+ margin: 0.3em 0.9em 0.8em 0.9em;
+ }
+
+ @media screen and (min-width: $break-large) {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: center;
+ margin: 2.8em 0.9em 0.8em 0.9em;
+ }
+
+ .hero-balance-display {
+
+ @media screen and (max-width: $break-small) {
+ text-align: center;
+
+ .token-amount {
+ font-size: 175%;
+ margin-top: 12.5%;
+ }
+
+ .fiat-amount {
+ font-size: 115%;
+ margin-top: 8.5%;
+ color: #A0A0A0;
+ }
+ }
+
+ @media screen and (min-width: $break-large) {
+ flex-grow: 3;
+ margin-left: 3%;
+ justify-content: flex-start;
+ align-items: flex-start;
+
+ .token-amount {
+ font-size: 135%;
+ }
+
+ .fiat-amount {
+ margin-top: 0.25%;
+ font-size: 105%;
+ }
+
+ }
+
+ }
+
+ .hero-balance-icon {
+ border-radius: 25px;
+ width: 45px;
+ height: 45px;
+ // TODO: colors
+ border: 1px solid #DEDEDE;
+ }
+
+ .hero-balance-buttons {
+ @media screen and (max-width: $break-small) {
+ width: 100%;
+ height: 100px; // needed a round number to set the heights of the buttons inside
+ }
+
+ @media screen and (min-width: $break-large) {
+ flex-grow: 2;
+ }
+
+ button.btn-clear {
+ font-size: 75%;
+ background: white;
+ border: 1px solid;
+
+ @media screen and (max-width: $break-small) {
+ width: 28%;
+ height: 55%;
+ }
+
+ @media screen and (min-width: $break-large) {
+ width: 5%;
+ flex-grow: 2;
+ height: 4.2vh;
+ min-height: 28px;
+ font-size: .7em;
+ }
+ }
+
+ }
+} \ No newline at end of file
diff --git a/ui/app/css/itcss/components/identicon.scss b/ui/app/css/itcss/components/identicon.scss
new file mode 100644
index 000000000..2f2de6ed8
--- /dev/null
+++ b/ui/app/css/itcss/components/identicon.scss
@@ -0,0 +1,7 @@
+.identicon {
+ height: 46px;
+ width: 46px;
+ background-size: cover;
+ border-radius: 100%;
+ border: 3px solid gray;
+}
diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss
new file mode 100644
index 000000000..8b6698eed
--- /dev/null
+++ b/ui/app/css/itcss/components/index.scss
@@ -0,0 +1,8 @@
+@import './buttons.scss';
+@import './header.scss';
+@import './footer.scss';
+@import './identicon.scss';
+@import './network.scss';
+@import './newui-sections.scss';
+@import './hero-balance.scss';
+@import './sections.scss';
diff --git a/ui/app/css/itcss/components/network.scss b/ui/app/css/itcss/components/network.scss
new file mode 100644
index 000000000..fb135d190
--- /dev/null
+++ b/ui/app/css/itcss/components/network.scss
@@ -0,0 +1,12 @@
+.network-indicator {
+ display: flex;
+ align-items: center;
+ font-size: 0.6em;
+
+}
+
+.network-name {
+ width: 5.2em;
+ line-height: 9px;
+ text-rendering: geometricPrecision;
+}
diff --git a/ui/app/css/itcss/components/newui-sections.scss b/ui/app/css/itcss/components/newui-sections.scss
new file mode 100644
index 000000000..761e74561
--- /dev/null
+++ b/ui/app/css/itcss/components/newui-sections.scss
@@ -0,0 +1,109 @@
+/*
+ NewUI Container Elements
+ */
+
+// Main container
+.main-container {
+ position: absolute;
+ z-index: 18;
+ font-family: DIN OT;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: stretch;
+ overflow-y: scroll;
+}
+
+.sidebar {
+ flex: 1 0 230px;
+ background: rgb(250, 250, 250);
+ z-index: 26;
+ position: fixed;
+ top: 35px;
+ left: 0px;
+ right: 0px;
+ bottom: 0px;
+ opacity: 1;
+ visibility: visible;
+ will-change: transform;
+ overflow-y: auto;
+ box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 4px;
+ width: 85%;
+ height: 100%;
+}
+
+.sidebar-overlay {
+ z-index: 25;
+ position: fixed;
+ top: 35px;
+ left: 0px;
+ right: 0px;
+ bottom: 0px;
+ opacity: 1;
+ visibility: visible;
+ background-color: rgba(0, 0, 0, 0.3);
+}
+
+@media screen and (min-width: 576px) {
+ .lap-visible {
+ display: flex;
+ }
+
+ .phone-visible {
+ display: none;
+ }
+
+ .main-container {
+ margin-top: 35px;
+ width: 85%;
+ height: 90vh;
+ box-shadow: 0 0 7px 0 rgba(0,0,0,0.08);
+ }
+}
+
+@media screen and (min-width: 769px) {
+ .main-container {
+ margin-top: 35px;
+ width: 80%;
+ height: 82vh;
+ box-shadow: 0 0 7px 0 rgba(0,0,0,0.08);
+ }
+}
+
+@media screen and (min-width: 1281px) {
+ .main-container {
+ margin-top: 35px;
+ width: 65%;
+ height: 82vh;
+ box-shadow: 0 0 7px 0 rgba(0,0,0,0.08);
+ }
+}
+
+@media screen and (max-width: 575px) {
+ .lap-visible {
+ display: none;
+ }
+
+ .phone-visible {
+ display: flex;
+ }
+
+ .main-container {
+ margin-top: 35px;
+ width: 100%;
+ height: 100%;
+ }
+
+ button.btn-clear {
+ width: 93px;
+ height: 50px;
+ font-size: .7em;
+ background: white;
+ border: 1px solid;
+ }
+}
+
+// wallet view
+.account-name {
+ font-size: 102%;
+ margin-left: 3%;
+}
diff --git a/ui/app/css/index.css b/ui/app/css/itcss/components/sections.scss
index 808aafb4c..4a256c65b 100644
--- a/ui/app/css/index.css
+++ b/ui/app/css/itcss/components/sections.scss
@@ -1,151 +1,31 @@
/*
-faint orange (textfield shades) #FAF6F0
-light orange (button shades): #F5C26D
-dark orange (text): #F5A623
-borders/font/any gray: #4A4A4A
+App Sections
+ TODO: Move into separate files.
*/
/*
-application specific styles
+debug / dev
*/
-* {
- box-sizing: border-box;
-}
-
-html, body {
- font-family: 'Montserrat Regular', Arial;
- color: #4D4D4D;
- font-weight: 300;
- line-height: 1.4em;
- background: #F7F7F7;
-}
-
-input:focus, textarea:focus {
- outline: none;
-}
-
-#app-content {
- overflow-x: hidden;
- min-width: 357px;
- width: 360px;
- height: 500px;
-}
-
-button, input[type="submit"] {
- font-family: 'Montserrat Bold';
- outline: none;
- cursor: pointer;
- padding: 8px 12px;
- border: none;
- color: white;
- transform-origin: center center;
- transition: transform 50ms ease-in;
- /* default orange */
- background: rgba(247, 134, 28, 1);
- box-shadow: 0px 3px 6px rgba(247, 134, 28, 0.36);
-}
+// #app-content {
+// border: 2px solid green;
+// }
-.btn-green, input[type="submit"].btn-green {
- background: rgba(106, 195, 96, 1);
- box-shadow: 0px 3px 6px rgba(106, 195, 96, 0.36);
-}
+// #design-container {
+// position: absolute;
+// left: 360px;
+// top: -42px;
+// width: calc(100vw - 360px);
+// height: 100vh;
+// overflow: scroll;
+// }
-.btn-red {
- background: rgba(254, 35, 17, 1);
- box-shadow: 0px 3px 6px rgba(254, 35, 17, 0.36);
-}
+// #design-container img {
+// width: 2000px;
+// margin-right: 600px;
+// }
-button[disabled], input[type="submit"][disabled] {
- cursor: not-allowed;
- background: rgba(197, 197, 197, 1);
- box-shadow: 0px 3px 6px rgba(197, 197, 197, 0.36);
-}
-
-button.spaced {
- margin: 2px;
-}
-
-button:not([disabled]):hover, input[type="submit"]:not([disabled]):hover {
- transform: scale(1.1);
-}
-button:not([disabled]):active, input[type="submit"]:not([disabled]):active {
- transform: scale(0.95);
-}
-
-a {
- text-decoration: none;
- color: inherit;
-}
-
-a:hover{
- color: #df6b0e;
-}
-
-/*
-app
-*/
-
-.active {
- color: #909090;
-}
-
-button.primary {
- padding: 8px 12px;
- background: #F7861C;
- box-shadow: 0px 3px 6px rgba(247, 134, 28, 0.36);
- color: white;
- font-size: 1.1em;
- font-family: 'Montserrat Regular';
- text-transform: uppercase;
-}
-
-button.btn-thin {
- border: 1px solid;
- border-color: #4D4D4D;
- color: #4D4D4D;
- background: rgb(255, 174, 41);
- border-radius: 4px;
- min-width: 200px;
- margin: 12px 0;
- padding: 6px;
- font-size: 13px;
-}
-
-.app-header {
- padding: 6px 8px;
-}
-
-.app-header h1 {
- font-family: 'Montserrat Regular';
- text-transform: uppercase;
- color: #AEAEAE;
-}
-
-h2.page-subtitle {
- font-family: 'Montserrat Regular';
- text-transform: uppercase;
- color: #AEAEAE;
- font-size: 1em;
- margin: 12px;
-}
-
-.app-primary {
-
-}
-
-.app-footer {
- padding-bottom: 10px;
- align-items: center;
-}
-
-.identicon {
- height: 46px;
- width: 46px;
- background-size: cover;
- border-radius: 100%;
- border: 3px solid gray;
-}
+/* initialize */
textarea.twelve-word-phrase {
padding: 12px;
@@ -156,32 +36,6 @@ textarea.twelve-word-phrase {
resize: none;
}
-.network-indicator {
- display: flex;
- align-items: center;
- font-size: 0.6em;
-
-}
-
-.network-name {
- width: 5.2em;
- line-height: 9px;
- text-rendering: geometricPrecision;
-}
-
-.check {
- margin-left: 7px;
- color: #F7861C;
- flex: 1 0 auto;
- display: flex;
- justify-content: flex-end;
-}
-/*
-app sections
-*/
-
-/* initialize */
-
.initialize-screen hr {
width: 60px;
margin: 12px;
@@ -259,9 +113,6 @@ app sections
.unlock-screen input[type=password] {
width: 260px;
- /*height: 36px;
- margin-bottom: 24px;
- padding: 8px;*/
}
.sizing-input{
@@ -293,20 +144,6 @@ app sections
font-size: 1.2em;
}
-input.large-input, textarea.large-input {
- /*margin-bottom: 24px;*/
- padding: 8px;
-}
-
-input.large-input {
- height: 36px;
-}
-
-.letter-spacey {
- letter-spacing: 0.1em;
-}
-
-
/* accounts */
@@ -403,8 +240,16 @@ input.large-input {
/* account detail screen */
.account-detail-section {
+ display: flex;
+ flex-wrap: wrap;
+ overflow-y: auto;
+ flex-direction: inherit;
+}
+.grow-tenx {
+ flex-grow: 10;
}
+
.name-label{
}
@@ -421,6 +266,7 @@ input.large-input {
height: 100%;
visibility: hidden;
}
+
.editing-label {
display: flex;
justify-content: flex-start;
@@ -430,6 +276,7 @@ input.large-input {
text-rendering: geometricPrecision;
color: #F7861C;
}
+
.name-label:hover .edit-text {
visibility: visible;
}
@@ -447,12 +294,8 @@ input.large-input {
/* Send Screen */
-.send-screen {
-
-}
-
.send-screen section {
- margin: 8px 16px;
+ margin: 4px 16px;
}
.send-screen input {
@@ -663,5 +506,5 @@ div.message-container > div:first-child {
}
.pop-hover:hover {
- transform: scale(1.1);
-}
+ transform: scale(1.1);
+} \ No newline at end of file
diff --git a/ui/app/css/itcss/generic/index.scss b/ui/app/css/itcss/generic/index.scss
new file mode 100644
index 000000000..a0ce312cc
--- /dev/null
+++ b/ui/app/css/itcss/generic/index.scss
@@ -0,0 +1,64 @@
+/*
+ Generic
+ */
+
+@import './reset.scss';
+
+* {
+ box-sizing: border-box;
+}
+
+html, body {
+ font-family: 'Montserrat Regular', Arial;
+ color: #4D4D4D;
+ font-weight: 300;
+ line-height: 1.4em;
+ background: #F7F7F7;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+}
+
+html {
+ min-height: 500px;
+}
+
+.app-root {
+ overflow: hidden;
+ position: relative
+}
+
+.app-primary {
+ display: flex;
+}
+
+input:focus, textarea:focus {
+ outline: none;
+}
+
+#app-content {
+ overflow-x: hidden;
+ min-width: 357px;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+a {
+ text-decoration: none;
+ color: inherit;
+}
+
+a:hover{
+ color: #df6b0e;
+}
+
+input.large-input, textarea.large-input {
+ /*margin-bottom: 24px;*/
+ padding: 8px;
+}
+
+input.large-input {
+ height: 36px;
+}
diff --git a/ui/app/css/reset.css b/ui/app/css/itcss/generic/reset.scss
index 9ce89e8bc..fef74825d 100644
--- a/ui/app/css/reset.css
+++ b/ui/app/css/itcss/generic/reset.scss
@@ -45,4 +45,8 @@ q:before, q:after {
table {
border-collapse: collapse;
border-spacing: 0;
-} \ No newline at end of file
+}
+
+button {
+ border-style: none;
+}
diff --git a/ui/app/css/itcss/objects/index.scss b/ui/app/css/itcss/objects/index.scss
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ui/app/css/itcss/objects/index.scss
diff --git a/ui/app/css/itcss/settings/index.scss b/ui/app/css/itcss/settings/index.scss
new file mode 100644
index 000000000..446546d0c
--- /dev/null
+++ b/ui/app/css/itcss/settings/index.scss
@@ -0,0 +1,2 @@
+@import './variables.scss';
+@import './typography.scss';
diff --git a/ui/app/css/fonts.css b/ui/app/css/itcss/settings/typography.scss
index 3b9f581b9..2afaa26e1 100644
--- a/ui/app/css/fonts.css
+++ b/ui/app/css/itcss/settings/typography.scss
@@ -8,7 +8,6 @@
font-weight: normal;
font-style: normal;
font-size: 'small';
-
}
@font-face {
@@ -23,14 +22,21 @@
font-family: 'Montserrat Light';
src: url('/fonts/Montserrat/Montserrat-Light.woff') format('woff');
src: url('/fonts/Montserrat/Montserrat-Light.ttf') format('truetype');
- font-weight: normal;
- font-style: normal;
+ font-weight: normal;
+ font-style: normal;
}
@font-face {
font-family: 'Montserrat UltraLight';
src: url('/fonts/Montserrat/Montserrat-UltraLight.woff') format('woff');
src: url('/fonts/Montserrat/Montserrat-UltraLight.ttf') format('truetype');
- font-weight: normal;
- font-style: normal;
+ font-weight: normal;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'DIN OT';
+ src: url('/fonts/DIN_OT/DINOT-2.otf') format('opentype');
+ font-weight: normal;
+ font-style: normal;
}
diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/app/css/itcss/settings/variables.scss
new file mode 100644
index 000000000..6d105f2e3
--- /dev/null
+++ b/ui/app/css/itcss/settings/variables.scss
@@ -0,0 +1,13 @@
+/*
+ Variables
+ */
+
+// Colors
+$white-linen: #FAF6F0; // formerly 'faint orange (textfield shades)'
+$rajah: #F5C26D; // formerly 'light orange (button shades)'
+$buttercup: #F5A623; // formerly 'dark orange (text)'
+$tundora: #4A4A4A; // formerly 'borders/font/any gray'
+$gallery: #EFEFEF;
+$alabaster: #F7F7F7;
+$shark: #22232C;
+$wild-sand: #F6F6F6; \ No newline at end of file
diff --git a/ui/app/css/itcss/tools/index.scss b/ui/app/css/itcss/tools/index.scss
new file mode 100644
index 000000000..3634c839b
--- /dev/null
+++ b/ui/app/css/itcss/tools/index.scss
@@ -0,0 +1,2 @@
+@import './utilities.scss';
+
diff --git a/ui/app/css/lib.css b/ui/app/css/itcss/tools/utilities.scss
index 910a24ee2..5e26ede64 100644
--- a/ui/app/css/lib.css
+++ b/ui/app/css/itcss/tools/utilities.scss
@@ -1,15 +1,38 @@
+/*
+ Utility Classes
+ */
+
/* color */
.color-orange {
- color: #F7861C;
+ color: #F7861C; // TODO: move to settings/variables
}
.color-forest {
- color: #0A5448;
+ color: #0A5448; // TODO: move to settings/variables
}
/* lib */
+.full-size {
+ height: 100%;
+ width: 100%;
+}
+
+.full-width {
+ width: 100%;
+}
+
+.full-height {
+ height: 100%;
+}
+
+.full-flex-height {
+ display: flex;
+ flex: 1 1 auto;
+ flex-direction: column;
+}
+
.full-width {
width: 100%;
}
@@ -232,6 +255,10 @@ hr.horizontal-line {
align-items: center;
}
+.tabSection {
+ min-width: 350px;
+}
+
.menu-icon {
display: inline-block;
height: 9px;
@@ -266,3 +293,25 @@ hr.horizontal-line {
margin-top: 20px;
color: red;
}
+
+
+/*
+ Misc
+ */
+
+// Move into component-level contextual 'active' state later
+.letter-spacey {
+ letter-spacing: 0.1em;
+}
+
+.active {
+ color: #909090;
+}
+
+.check {
+ margin-left: 7px;
+ color: #F7861C;
+ flex: 1 0 auto;
+ display: flex;
+ justify-content: flex-end;
+}
diff --git a/ui/app/css/transitions.css b/ui/app/css/itcss/trumps/index.scss
index 393a944f9..6b0c999be 100644
--- a/ui/app/css/transitions.css
+++ b/ui/app/css/itcss/trumps/index.scss
@@ -1,3 +1,10 @@
+/*
+ Trumps
+ */
+
+
+// Transitions
+
/* universal */
.app-primary .main-enter {
position: absolute;
@@ -22,6 +29,11 @@
transition: transform 300ms ease-in;
}
+.sidebar.from-left {
+ transform: translateX(-320px);
+ transition: transform 300ms ease-in;
+}
+
/* loader transitions */
.loader-enter, .loader-leave-active {
opacity: 0.0;
@@ -39,4 +51,3 @@
.app-primary.from-left .main-enter:not(.main-enter-active) {
transform: translateX(-360px);
}
-
diff --git a/ui/app/info.js b/ui/app/info.js
index cb2e41f5b..899841c83 100644
--- a/ui/app/info.js
+++ b/ui/app/info.js
@@ -20,7 +20,11 @@ InfoScreen.prototype.render = function () {
const version = global.platform.getVersion()
return (
- h('.flex-column.flex-grow', [
+ h('.flex-column.flex-grow', {
+ style: {
+ maxWidth: '400px',
+ },
+ }, [
// subtitle and nav
h('.section-title.flex-row.flex-center', [
@@ -103,12 +107,7 @@ InfoScreen.prototype.render = function () {
target: '_blank',
}, 'Visit our Support Center'),
]),
- h('div.fa.fa-github', [
- h('a.info', {
- href: 'https://github.com/MetaMask/metamask-extension/issues/new',
- target: '_blank',
- }, 'Found a bug? Report it!'),
- ]),
+
h('div', [
h('a', {
href: 'https://metamask.io/',
@@ -126,6 +125,7 @@ InfoScreen.prototype.render = function () {
h('div.info', 'Visit our web site'),
]),
]),
+
h('div.fa.fa-slack', [
h('a.info', {
href: 'http://slack.metamask.io',
@@ -133,11 +133,13 @@ InfoScreen.prototype.render = function () {
}, 'Join the conversation on Slack'),
]),
- h('div.fa.fa-twitter', [
- h('a.info', {
- href: 'https://twitter.com/metamask_io',
- target: '_blank',
- }, 'Follow us on Twitter'),
+ h('div', [
+ h('.fa.fa-twitter', [
+ h('a.info', {
+ href: 'https://twitter.com/metamask_io',
+ target: '_blank',
+ }, 'Follow us on Twitter'),
+ ]),
]),
h('div.fa.fa-envelope', [
diff --git a/ui/app/keychains/hd/create-vault-complete.js b/ui/app/keychains/hd/create-vault-complete.js
index a318a9b50..c32751fff 100644
--- a/ui/app/keychains/hd/create-vault-complete.js
+++ b/ui/app/keychains/hd/create-vault-complete.js
@@ -47,8 +47,6 @@ CreateVaultCompleteScreen.prototype.render = function () {
h('div', {
style: {
- width: '360px',
- height: '78px',
fontSize: '1em',
marginTop: '10px',
textAlign: 'center',
diff --git a/ui/app/keychains/hd/recover-seed/confirmation.js b/ui/app/keychains/hd/recover-seed/confirmation.js
index 4ccbec9fc..4335186a5 100644
--- a/ui/app/keychains/hd/recover-seed/confirmation.js
+++ b/ui/app/keychains/hd/recover-seed/confirmation.js
@@ -23,7 +23,9 @@ RevealSeedConfirmation.prototype.render = function () {
return (
- h('.initialize-screen.flex-column.flex-center.flex-grow', [
+ h('.initialize-screen.flex-column.flex-center.flex-grow', {
+ style: { maxWidth: '420px' },
+ }, [
h('h3.flex-center.text-transform-uppercase', {
style: {
@@ -61,7 +63,7 @@ RevealSeedConfirmation.prototype.render = function () {
},
}),
- h('.flex-row.flex-space-between', {
+ h('.flex-row.flex-start', {
style: {
marginTop: 30,
width: '50%',
@@ -74,6 +76,7 @@ RevealSeedConfirmation.prototype.render = function () {
// submit
h('button.primary', {
+ style: { marginLeft: '10px' },
onClick: this.revealSeedWords.bind(this),
}, 'OK'),
diff --git a/ui/app/main-container.js b/ui/app/main-container.js
new file mode 100644
index 000000000..b00349c05
--- /dev/null
+++ b/ui/app/main-container.js
@@ -0,0 +1,72 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const TxView = require('./components/tx-view')
+const WalletView = require('./components/wallet-view')
+const SlideoutMenu = require('react-burger-menu').slide
+const AccountAndTransactionDetails = require('./account-and-transaction-details')
+const HDRestoreVaultScreen = require('./keychains/hd/restore-vault')
+const ConfigScreen = require('./config')
+const UnlockScreen = require('./unlock')
+
+module.exports = MainContainer
+
+inherits(MainContainer, Component)
+function MainContainer () {
+ Component.call(this)
+}
+
+MainContainer.prototype.render = function () {
+ // 3. summarize:
+ // switch statement goes inside MainContainer,
+ // or a method in renderPrimary
+ // - pass resulting h() to MainContainer
+ // - error checking in separate func
+ // - router in separate func
+ let contents = {
+ component: AccountAndTransactionDetails,
+ key: 'account-detail',
+ style: {},
+ }
+
+ if (this.props.isUnlocked === false) {
+ switch (this.props.currentViewName) {
+ case 'restoreVault':
+ log.debug('rendering restore vault screen')
+ contents = {
+ component: HDRestoreVaultScreen,
+ key: 'HDRestoreVaultScreen',
+ }
+ case 'config':
+ log.debug('rendering config screen from unlock screen.')
+ contents = {
+ component: ConfigScreen,
+ key: 'config',
+ }
+ default:
+ log.debug('rendering locked screen')
+ contents = {
+ component: UnlockScreen,
+ style: {
+ boxShadow: 'none',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ background: '#F7F7F7',
+ // must force 100%, because lock screen is full-width
+ width: '100%',
+ },
+ key: 'locked',
+ }
+ }
+ }
+
+ return h('div.main-container', {
+ style: contents.style,
+ }, [
+ h(contents.component, {
+ key: contents.key,
+ }, [])
+ ])
+}
+
diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js
index 2fcc9bfe0..bf1de4577 100644
--- a/ui/app/reducers/app.js
+++ b/ui/app/reducers/app.js
@@ -36,6 +36,7 @@ function reduceApp (state, action) {
var appState = extend({
shouldClose: false,
menuOpen: false,
+ sidebarOpen: false,
currentView: seedWords ? seedConfView : defaultView,
accountDetail: {
subview: 'transactions',
@@ -46,6 +47,16 @@ function reduceApp (state, action) {
}, state.appState)
switch (action.type) {
+ // sidebar methods
+ case actions.SIDEBAR_OPEN:
+ return extend(appState, {
+ sidebarOpen: true,
+ })
+
+ case actions.SIDEBAR_CLOSE:
+ return extend(appState, {
+ sidebarOpen: false,
+ })
// transition methods
diff --git a/ui/app/send.js b/ui/app/send.js
index a21a219eb..ab527019f 100644
--- a/ui/app/send.js
+++ b/ui/app/send.js
@@ -11,6 +11,9 @@ const isHex = require('./util').isHex
const EthBalance = require('./components/eth-balance')
const EnsInput = require('./components/ens-input')
const ethUtil = require('ethereumjs-util')
+
+const ARAGON = '960b236A07cf122663c4303350609A66A7B288C0'
+
module.exports = connect(mapStateToProps)(SendTransactionScreen)
function mapStateToProps (state) {
@@ -56,172 +59,425 @@ SendTransactionScreen.prototype.render = function () {
return (
- h('.send-screen.flex-column.flex-grow', [
-
- //
- // Sender Profile
- //
+ h('div.flex-column.flex-grow', {
+ style: {
+ minWidth: '355px', // TODO: maxWidth TBD, use home.html
+ },
+ }, [
- h('.account-data-subsection.flex-row.flex-grow', {
+ // Main Send token Card
+ h('div.send-screen.flex-column.flex-grow', {
style: {
- margin: '0 20px',
- },
+ marginLeft: '3.5%',
+ marginRight: '3.5%',
+ background: '#FFFFFF', // $background-white
+ boxShadow: '0 2px 4px 0 rgba(0,0,0,0.08)',
+ }
}, [
+ h('section.flex-center.flex-row', {
+ style: {
+ zIndex: 15, // $token-icon-z-index
+ marginTop: '-35px',
+ }
+ }, [
+ h(Identicon, {
+ address: ARAGON,
+ diameter: 76,
+ }),
+ ]),
- // header - identicon + nav
- h('.flex-row.flex-space-between', {
+ h('h3.flex-center', {
style: {
- marginTop: '15px',
+ marginTop: '-18px',
+ fontSize: '16px',
},
}, [
- // back button
- h('i.fa.fa-arrow-left.fa-lg.cursor-pointer.color-orange', {
- onClick: this.back.bind(this),
+ 'Send Tokens',
+ ]),
+
+ h('h3.flex-center', {
+ style: {
+ textAlign: 'center',
+ fontSize: '12px',
+ },
+ }, [
+ 'Send Tokens to anyone with an Ethereum account',
+ ]),
+
+ h('h3.flex-center', {
+ style: {
+ textAlign: 'center',
+ marginTop: '2px',
+ fontSize: '12px',
+ },
+ }, [
+ 'Your Aragon Token Balance is:',
+ ]),
+
+ h('h3.flex-center', {
+ style: {
+ textAlign: 'center',
+ fontSize: '36px',
+ marginTop: '8px',
+ },
+ }, [
+ '2.34',
+ ]),
+
+ h('h3.flex-center', {
+ style: {
+ textAlign: 'center',
+ fontSize: '12px',
+ marginTop: '4px',
+ },
+ }, [
+ 'ANT',
+ ]),
+
+ // error message
+ props.error && h('span.error.flex-center', props.error),
+
+ // 'to' field
+ h('section.flex-row.flex-center', {
+ style: {
+ fontSize: '12px',
+ },
+ }, [
+ h(EnsInput, {
+ name: 'address',
+ placeholder: 'Recipient Address',
+ onChange: this.recipientDidChange.bind(this),
+ network,
+ identities,
+ addressBook,
}),
+ ]),
- // large identicon
- h('.identicon-wrapper.flex-column.flex-center.select-none', [
- h(Identicon, {
- diameter: 62,
- address: address,
- }),
+ // 'amount' and send button
+ h('section.flex-column.flex-center', [
+ h('div.flex-row.flex-center', {
+ style: {
+ fontSize: '12px',
+ width: '100%',
+ justifyContent: 'space-between',
+ }
+ },[
+ h('span', { style: {} }, ['Amount']),
+ h('span', { style: {} }, ['Token <> USD']),
]),
- // invisible place holder
- h('i.fa.fa-users.fa-lg.invisible', {
+ h('input.large-input', {
+ name: 'amount',
+ placeholder: '0',
+ type: 'number',
style: {
- marginTop: '28px',
+ marginRight: '6px',
+ fontSize: '12px',
+ },
+ dataset: {
+ persistentFormId: 'tx-amount',
},
}),
]),
- // account label
+ h('section.flex-column.flex-center', [
+ h('div.flex-row.flex-center', {
+ style: {
+ fontSize: '12px',
+ width: '100%',
+ justifyContent: 'space-between',
+ }
+ },[
+ h('span', { style: {} }, ['Gas Fee:']),
+ h('span', { style: { fontSize: '8px' } }, ['What\'s this?']),
+ ]),
+
+ h('input.large-input', {
+ name: 'Gas Fee',
+ placeholder: '0',
+ type: 'number',
+ style: {
+ fontSize: '12px',
+ marginRight: '6px',
+ },
+ // dataset: {
+ // persistentFormId: 'tx-amount',
+ // },
+ }),
+
+ ]),
- h('.flex-column', {
+ h('section.flex-column.flex-center', {
style: {
- marginTop: '10px',
- alignItems: 'flex-start',
+ marginBottom: '10px',
},
}, [
- h('h2.font-medium.color-forest.flex-center', {
+ h('div.flex-row.flex-center', {
style: {
- paddingTop: '8px',
- marginBottom: '8px',
- },
- }, identity && identity.name),
+ fontSize: '12px',
+ width: '100%',
+ justifyContent: 'flex-start',
+ }
+ },[
+ h('span', { style: {} }, ['Transaction Memo (optional)']),
+ ]),
- // address and getter actions
- h('.flex-row.flex-center', {
+ h('input.large-input', {
+ name: 'memo',
+ placeholder: '',
+ type: 'string',
style: {
- marginBottom: '8px',
+ marginRight: '6px',
},
- }, [
+ }),
+ ]),
+ ]),
- h('div', {
- style: {
- lineHeight: '16px',
- },
- }, addressSummary(address)),
+ // Buttons underneath card
+ h('section.flex-column.flex-center', [
- ]),
+ h('button.btn-light', {
+ onClick: this.onSubmit.bind(this),
+ style: {
+ marginTop: '8px',
+ width: '8em',
+ background: '#FFFFFF'
+ },
+ }, 'Next'),
- // balance
- h('.flex-row.flex-center', [
+ h('button.btn-light', {
+ onClick: this.back.bind(this),
+ style: {
+ background: '#F7F7F7', // $alabaster
+ border: 'none',
+ opacity: 1,
+ width: '8em',
+ },
+ }, 'Cancel'),
+ ]),
+ ])
- h(EthBalance, {
- value: account && account.balance,
- conversionRate,
- currentCurrency,
- }),
+ )
+}
- ]),
- ]),
- ]),
+// WIP - hyperscript for renderSendToken - hook up later
+SendTransactionScreen.prototype.renderSendToken = function () {
+ this.persistentFormParentId = 'send-tx-form'
+
+ const props = this.props
+ const {
+ address,
+ account,
+ identity,
+ network,
+ identities,
+ addressBook,
+ conversionRate,
+ currentCurrency,
+ } = props
+
+ return (
- //
- // Required Fields
- //
+ h('div.flex-column.flex-grow', {
+ style: {
+ minWidth: '355px', // TODO: maxWidth TBD, use home.html
+ },
+ }, [
- h('h3.flex-center.text-transform-uppercase', {
+ // Main Send token Card
+ h('div.send-screen.flex-column.flex-grow', {
style: {
- background: '#EBEBEB',
- color: '#AEAEAE',
- marginTop: '15px',
- marginBottom: '16px',
- },
+ marginLeft: '3.5%',
+ marginRight: '3.5%',
+ background: '#FFFFFF', // $background-white
+ boxShadow: '0 2px 4px 0 rgba(0,0,0,0.08)',
+ }
}, [
- 'Send Transaction',
- ]),
+ h('section.flex-center.flex-row', {
+ style: {
+ zIndex: 15, // $token-icon-z-index
+ marginTop: '-35px',
+ }
+ }, [
+ h(Identicon, {
+ address: ARAGON,
+ diameter: 76,
+ }),
+ ]),
- // error message
- props.error && h('span.error.flex-center', props.error),
-
- // 'to' field
- h('section.flex-row.flex-center', [
- h(EnsInput, {
- name: 'address',
- placeholder: 'Recipient Address',
- onChange: this.recipientDidChange.bind(this),
- network,
- identities,
- addressBook,
- }),
- ]),
+ h('h3.flex-center', {
+ style: {
+ marginTop: '-18px',
+ fontSize: '16px',
+ },
+ }, [
+ 'Send Tokens',
+ ]),
- // 'amount' and send button
- h('section.flex-row.flex-center', [
+ h('h3.flex-center', {
+ style: {
+ textAlign: 'center',
+ fontSize: '12px',
+ },
+ }, [
+ 'Send Tokens to anyone with an Ethereum account',
+ ]),
- h('input.large-input', {
- name: 'amount',
- placeholder: 'Amount',
- type: 'number',
+ h('h3.flex-center', {
style: {
- marginRight: '6px',
+ textAlign: 'center',
+ marginTop: '2px',
+ fontSize: '12px',
},
- dataset: {
- persistentFormId: 'tx-amount',
+ }, [
+ 'Your Aragon Token Balance is:',
+ ]),
+
+ h('h3.flex-center', {
+ style: {
+ textAlign: 'center',
+ fontSize: '36px',
+ marginTop: '8px',
},
- }),
+ }, [
+ '2.34',
+ ]),
- h('button.primary', {
- onClick: this.onSubmit.bind(this),
+ h('h3.flex-center', {
style: {
- textTransform: 'uppercase',
+ textAlign: 'center',
+ fontSize: '12px',
+ marginTop: '4px',
},
- }, 'Next'),
+ }, [
+ 'ANT',
+ ]),
- ]),
+ // error message
+ props.error && h('span.error.flex-center', props.error),
- //
- // Optional Fields
- //
- h('h3.flex-center.text-transform-uppercase', {
- style: {
- background: '#EBEBEB',
- color: '#AEAEAE',
- marginTop: '16px',
- marginBottom: '16px',
- },
- }, [
- 'Transaction Data (optional)',
+ // 'to' field
+ h('section.flex-row.flex-center', {
+ style: {
+ fontSize: '12px',
+ },
+ }, [
+ h(EnsInput, {
+ name: 'address',
+ placeholder: 'Recipient Address',
+ onChange: this.recipientDidChange.bind(this),
+ network,
+ identities,
+ addressBook,
+ }),
+ ]),
+
+ // 'amount' and send button
+ h('section.flex-column.flex-center', [
+ h('div.flex-row.flex-center', {
+ style: {
+ fontSize: '12px',
+ width: '100%',
+ justifyContent: 'space-between',
+ }
+ },[
+ h('span', { style: {} }, ['Amount']),
+ h('span', { style: {} }, ['Token <> USD']),
+ ]),
+
+ h('input.large-input', {
+ name: 'amount',
+ placeholder: '0',
+ type: 'number',
+ style: {
+ marginRight: '6px',
+ fontSize: '12px',
+ },
+ dataset: {
+ persistentFormId: 'tx-amount',
+ },
+ }),
+
+ ]),
+
+ h('section.flex-column.flex-center', [
+ h('div.flex-row.flex-center', {
+ style: {
+ fontSize: '12px',
+ width: '100%',
+ justifyContent: 'space-between',
+ }
+ },[
+ h('span', { style: {} }, ['Gas Fee:']),
+ h('span', { style: { fontSize: '8px' } }, ['What\'s this?']),
+ ]),
+
+ h('input.large-input', {
+ name: 'Gas Fee',
+ placeholder: '0',
+ type: 'number',
+ style: {
+ fontSize: '12px',
+ marginRight: '6px',
+ },
+ // dataset: {
+ // persistentFormId: 'tx-amount',
+ // },
+ }),
+
+ ]),
+
+ h('section.flex-column.flex-center', {
+ style: {
+ marginBottom: '10px',
+ },
+ }, [
+ h('div.flex-row.flex-center', {
+ style: {
+ fontSize: '12px',
+ width: '100%',
+ justifyContent: 'flex-start',
+ }
+ },[
+ h('span', { style: {} }, ['Transaction Memo (optional)']),
+ ]),
+
+ h('input.large-input', {
+ name: 'memo',
+ placeholder: '',
+ type: 'string',
+ style: {
+ marginRight: '6px',
+ },
+ }),
+ ]),
]),
- // 'data' field
+ // Buttons underneath card
h('section.flex-column.flex-center', [
- h('input.large-input', {
- name: 'txData',
- placeholder: '0x01234',
+
+ h('button.btn-light', {
+ onClick: this.onSubmit.bind(this),
style: {
- width: '100%',
- resize: 'none',
+ marginTop: '8px',
+ width: '8em',
+ background: '#FFFFFF'
},
- dataset: {
- persistentFormId: 'tx-data',
+ }, 'Next'),
+
+ h('button.btn-light', {
+ onClick: this.back.bind(this),
+ style: {
+ background: '#F7F7F7', // $alabaster
+ border: 'none',
+ opacity: 1,
+ width: '8em',
},
- }),
+ }, 'Cancel'),
]),
])
+
)
}
@@ -248,7 +504,11 @@ SendTransactionScreen.prototype.onSubmit = function () {
const nickname = state.nickname || ' '
const input = document.querySelector('input[name="amount"]').value
const value = util.normalizeEthStringToWei(input)
- const txData = document.querySelector('input[name="txData"]').value
+ // TODO: check with team on whether txData is removed completely.
+ const txData = false;
+ // Must replace with memo data.
+ // const txData = document.querySelector('input[name="txData"]').value
+
const balance = this.props.balance
let message
@@ -267,7 +527,7 @@ SendTransactionScreen.prototype.onSubmit = function () {
return this.props.dispatch(actions.displayWarning(message))
}
- if (!isHex(ethUtil.stripHexPrefix(txData)) && txData) {
+ if (txData && !isHex(ethUtil.stripHexPrefix(txData))) {
message = 'Transaction data must be hex string.'
return this.props.dispatch(actions.displayWarning(message))
}
diff --git a/ui/app/unlock.js b/ui/app/unlock.js
index 1aee3c5d0..08235f0ea 100644
--- a/ui/app/unlock.js
+++ b/ui/app/unlock.js
@@ -46,7 +46,7 @@ UnlockScreen.prototype.render = function () {
id: 'password-box',
placeholder: 'enter password',
style: {
-
+ background: 'white',
},
onKeyPress: this.onKeyPress.bind(this),
onInput: this.inputChanged.bind(this),