From 15a7cf607e9c5457b2cb66a484cff15a3b3b282a Mon Sep 17 00:00:00 2001 From: meriadec Date: Wed, 13 Jun 2018 21:00:00 +0200 Subject: [PATCH 1/7] Rename ImportModal to AddAccountsModal --- src/components/DashboardPage/EmptyState.js | 4 ++- src/components/MainSideBar/index.js | 6 ++-- .../AccountRow.js | 0 .../{ImportAccounts => AddAccounts}/index.js | 33 ++++++++++--------- .../steps/01-step-choose-currency.js | 0 .../steps/02-step-connect-device.js | 2 +- .../steps/03-step-import.js | 28 ++++++++-------- .../steps/04-step-finish.js | 0 src/components/modals/index.js | 2 +- src/config/constants.js | 2 +- static/i18n/en/app.yml | 2 +- static/i18n/fr/app.yml | 2 +- 12 files changed, 42 insertions(+), 39 deletions(-) rename src/components/modals/{ImportAccounts => AddAccounts}/AccountRow.js (100%) rename src/components/modals/{ImportAccounts => AddAccounts}/index.js (86%) rename src/components/modals/{ImportAccounts => AddAccounts}/steps/01-step-choose-currency.js (100%) rename src/components/modals/{ImportAccounts => AddAccounts}/steps/02-step-connect-device.js (95%) rename src/components/modals/{ImportAccounts => AddAccounts}/steps/03-step-import.js (91%) rename src/components/modals/{ImportAccounts => AddAccounts}/steps/04-step-finish.js (100%) diff --git a/src/components/DashboardPage/EmptyState.js b/src/components/DashboardPage/EmptyState.js index 0d3726ca..e71476e8 100644 --- a/src/components/DashboardPage/EmptyState.js +++ b/src/components/DashboardPage/EmptyState.js @@ -8,6 +8,8 @@ import { compose } from 'redux' import { translate } from 'react-i18next' import { push } from 'react-router-redux' +import { MODAL_ADD_ACCOUNTS } from 'config/constants' + import { openModal } from 'reducers/modals' import type { T } from 'types/common' @@ -50,7 +52,7 @@ class EmptyState extends PureComponent { padded primary style={{ width: 120 }} - onClick={() => openModal('importAccounts')} + onClick={() => openModal(MODAL_ADD_ACCOUNTS)} > {t('app:emptyState.dashboard.buttons.addAccount')} diff --git a/src/components/MainSideBar/index.js b/src/components/MainSideBar/index.js index 28c8c5c8..5e0bc619 100644 --- a/src/components/MainSideBar/index.js +++ b/src/components/MainSideBar/index.js @@ -13,7 +13,7 @@ import type { Account } from '@ledgerhq/live-common/lib/types' import type { T } from 'types/common' import type { UpdateStatus } from 'reducers/update' -import { MODAL_RECEIVE, MODAL_SEND } from 'config/constants' +import { MODAL_RECEIVE, MODAL_SEND, MODAL_ADD_ACCOUNTS } from 'config/constants' import { accountsSelector } from 'reducers/accounts' import { openModal } from 'reducers/modals' @@ -70,7 +70,7 @@ class MainSideBar extends PureComponent { handleOpenReceiveModal = () => this.props.openModal(MODAL_RECEIVE) handleClickManager = () => this.push('/manager') handleClickExchange = () => this.push('/exchange') - handleOpenImportModal = () => this.props.openModal('importAccounts') + handleOpenImportModal = () => this.props.openModal(MODAL_ADD_ACCOUNTS) render() { const { t, accounts, location, updateStatus } = this.props @@ -78,7 +78,7 @@ class MainSideBar extends PureComponent { const addAccountButton = ( ) diff --git a/src/components/modals/ImportAccounts/AccountRow.js b/src/components/modals/AddAccounts/AccountRow.js similarity index 100% rename from src/components/modals/ImportAccounts/AccountRow.js rename to src/components/modals/AddAccounts/AccountRow.js diff --git a/src/components/modals/ImportAccounts/index.js b/src/components/modals/AddAccounts/index.js similarity index 86% rename from src/components/modals/ImportAccounts/index.js rename to src/components/modals/AddAccounts/index.js index ddac622a..ca712357 100644 --- a/src/components/modals/ImportAccounts/index.js +++ b/src/components/modals/AddAccounts/index.js @@ -10,6 +10,7 @@ import SyncSkipUnderPriority from 'components/SyncSkipUnderPriority' import type { Currency, Account } from '@ledgerhq/live-common/lib/types' +import { MODAL_ADD_ACCOUNTS } from 'config/constants' import type { T, Device } from 'types/common' import { getCurrentDevice } from 'reducers/devices' @@ -29,7 +30,7 @@ import StepFinish from './steps/04-step-finish' const createSteps = ({ t }: { t: T }) => [ { id: 'chooseCurrency', - label: t('app:importAccounts.breadcrumb.informations'), + label: t('app:addAccounts.breadcrumb.informations'), component: StepChooseCurrency, footer: StepChooseCurrencyFooter, onBack: null, @@ -37,7 +38,7 @@ const createSteps = ({ t }: { t: T }) => [ }, { id: 'connectDevice', - label: t('app:importAccounts.breadcrumb.connectDevice'), + label: t('app:addAccounts.breadcrumb.connectDevice'), component: StepConnectDevice, footer: StepConnectDeviceFooter, onBack: ({ transitionTo }: StepProps) => transitionTo('chooseCurrency'), @@ -45,7 +46,7 @@ const createSteps = ({ t }: { t: T }) => [ }, { id: 'import', - label: t('app:importAccounts.breadcrumb.import'), + label: t('app:addAccounts.breadcrumb.import'), component: StepImport, footer: StepImportFooter, onBack: ({ transitionTo }: StepProps) => transitionTo('chooseCurrency'), @@ -53,7 +54,7 @@ const createSteps = ({ t }: { t: T }) => [ }, { id: 'finish', - label: t('app:importAccounts.breadcrumb.finish'), + label: t('app:addAccounts.breadcrumb.finish'), component: StepFinish, footer: null, onBack: null, @@ -91,7 +92,7 @@ export type StepProps = { isAppOpened: boolean, transitionTo: StepId => void, setState: any => void, - onClickImport: void => Promise, + onClickAdd: void => Promise, onCloseModal: void => void, // scan process @@ -122,7 +123,7 @@ const INITIAL_STATE = { scanStatus: 'idle', } -class ImportAccounts extends PureComponent { +class AddAccounts extends PureComponent { state = INITIAL_STATE STEPS = createSteps({ t: this.props.t, @@ -136,24 +137,24 @@ class ImportAccounts extends PureComponent { this.setState(nextState) } - handleClickImport = async () => { + handleClickAdd = async () => { const { addAccount } = this.props const { scannedAccounts, checkedAccountsIds } = this.state const accountsIdsMap = checkedAccountsIds.reduce((acc, cur) => { acc[cur] = true return acc }, {}) - const accountsToImport = scannedAccounts.filter(account => accountsIdsMap[account.id] === true) - for (let i = 0; i < accountsToImport.length; i++) { + const accountsToAdd = scannedAccounts.filter(account => accountsIdsMap[account.id] === true) + for (let i = 0; i < accountsToAdd.length; i++) { await idleCallback() - addAccount(accountsToImport[i]) + addAccount(accountsToAdd[i]) } this.transitionTo('finish') } handleCloseModal = () => { const { closeModal } = this.props - closeModal('importAccounts') + closeModal(MODAL_ADD_ACCOUNTS) } render() { @@ -172,7 +173,7 @@ class ImportAccounts extends PureComponent { const step = this.STEPS[stepIndex] if (!step) { - throw new Error(`ImportAccountsModal: step ${stepId} doesn't exists`) + throw new Error(`AddAccountsModal: step ${stepId} doesn't exists`) } const { component: StepComponent, footer: StepFooter, hideFooter, onBack } = step @@ -187,7 +188,7 @@ class ImportAccounts extends PureComponent { scanStatus, err, isAppOpened, - onClickImport: this.handleClickImport, + onClickAdd: this.handleClickAdd, onCloseModal: this.handleCloseModal, transitionTo: this.transitionTo, setState: (...args) => this.setState(...args), @@ -195,14 +196,14 @@ class ImportAccounts extends PureComponent { return ( this.setState({ ...INITIAL_STATE })} render={({ onClose }) => ( onBack(stepProps) : void 0}> - {t('app:importAccounts.title')} + {t('app:addAccounts.title')} @@ -226,7 +227,7 @@ export default compose( mapDispatchToProps, ), translate(), -)(ImportAccounts) +)(AddAccounts) function idleCallback() { return new Promise(resolve => window.requestIdleCallback(resolve)) diff --git a/src/components/modals/ImportAccounts/steps/01-step-choose-currency.js b/src/components/modals/AddAccounts/steps/01-step-choose-currency.js similarity index 100% rename from src/components/modals/ImportAccounts/steps/01-step-choose-currency.js rename to src/components/modals/AddAccounts/steps/01-step-choose-currency.js diff --git a/src/components/modals/ImportAccounts/steps/02-step-connect-device.js b/src/components/modals/AddAccounts/steps/02-step-connect-device.js similarity index 95% rename from src/components/modals/ImportAccounts/steps/02-step-connect-device.js rename to src/components/modals/AddAccounts/steps/02-step-connect-device.js index ef05d478..2b89a929 100644 --- a/src/components/modals/ImportAccounts/steps/02-step-connect-device.js +++ b/src/components/modals/AddAccounts/steps/02-step-connect-device.js @@ -19,7 +19,7 @@ function StepConnectDevice({ t, currency, currentDevice, setState }: StepProps) - + {`You're about to import your `} {`${currency.name} (${ currency.ticker diff --git a/src/components/modals/ImportAccounts/steps/03-step-import.js b/src/components/modals/AddAccounts/steps/03-step-import.js similarity index 91% rename from src/components/modals/ImportAccounts/steps/03-step-import.js rename to src/components/modals/AddAccounts/steps/03-step-import.js index bd723ca4..528d1d7c 100644 --- a/src/components/modals/ImportAccounts/steps/03-step-import.js +++ b/src/components/modals/AddAccounts/steps/03-step-import.js @@ -160,7 +160,7 @@ class StepImport extends PureComponent { fontSize={2} style={{ textTransform: 'uppercase' }} > - {t('app:importAccounts.accountToImportSubtitle', { + {t('app:addAccounts.accountToImportSubtitle', { count: importableAccounts.length, })} @@ -170,8 +170,8 @@ class StepImport extends PureComponent { fontSize={3} > {isAllSelected - ? t('app:importAccounts.unselectAll') - : t('app:importAccounts.selectAll')} + ? t('app:addAccounts.unselectAll') + : t('app:addAccounts.selectAll')} )} @@ -211,7 +211,7 @@ class StepImport extends PureComponent { fontSize={2} style={{ textTransform: 'uppercase' }} > - {t('app:importAccounts.createNewAccount')} + {t('app:addAccounts.createNewAccount')} { )} @@ -256,7 +256,7 @@ export const LoadingRow = styled(Box).attrs({ export const StepImportFooter = ({ scanStatus, - onClickImport, + onClickAdd, checkedAccountsIds, scannedAccounts, t, @@ -266,30 +266,30 @@ export const StepImportFooter = ({ return account && account.operations.length === 0 }) - const willImportAccounts = checkedAccountsIds.some(id => { + const willAddAccounts = checkedAccountsIds.some(id => { const account = scannedAccounts.find(a => a.id === id) return account && account.operations.length > 0 }) - const importedAccountsCount = checkedAccountsIds.filter(id => { + const addedAccountsCount = checkedAccountsIds.filter(id => { const account = scannedAccounts.find(acc => acc.id === id) return account && account.operations.length > 0 }).length const ctaWording = - willCreateAccount && willImportAccounts - ? `${t('app:importAccounts.cta.create')} / ${t('app:importAccounts.cta.import', { - count: importedAccountsCount, + willCreateAccount && willAddAccounts + ? `${t('app:addAccounts.cta.create')} / ${t('app:addAccounts.cta.import', { + count: addedAccountsCount, })}` : willCreateAccount - ? t('app:importAccounts.cta.create') - : t('app:importAccounts.cta.import', { count: importedAccountsCount }) + ? t('app:addAccounts.cta.create') + : t('app:addAccounts.cta.import', { count: addedAccountsCount }) return ( diff --git a/src/components/modals/ImportAccounts/steps/04-step-finish.js b/src/components/modals/AddAccounts/steps/04-step-finish.js similarity index 100% rename from src/components/modals/ImportAccounts/steps/04-step-finish.js rename to src/components/modals/AddAccounts/steps/04-step-finish.js diff --git a/src/components/modals/index.js b/src/components/modals/index.js index 0c0f3bd0..2f942504 100644 --- a/src/components/modals/index.js +++ b/src/components/modals/index.js @@ -1,5 +1,5 @@ export Debug from './Debug' -export ImportAccounts from './ImportAccounts' +export AddAccounts from './AddAccounts' export OperationDetails from './OperationDetails' export Receive from './Receive' export Send from './Send' diff --git a/src/config/constants.js b/src/config/constants.js index 8d8940d6..4cbd1cf2 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -19,7 +19,7 @@ export const CHECK_UPDATE_DELAY = 5e3 export const DEVICE_DISCONNECT_DEBOUNCE = intFromEnv('LEDGER_DEVICE_DISCONNECT_DEBOUNCE', 500) -export const MODAL_ADD_ACCOUNT = 'MODAL_ADD_ACCOUNT' +export const MODAL_ADD_ACCOUNTS = 'MODAL_ADD_ACCOUNTS' export const MODAL_OPERATION_DETAILS = 'MODAL_OPERATION_DETAILS' export const MODAL_RECEIVE = 'MODAL_RECEIVE' export const MODAL_SEND = 'MODAL_SEND' diff --git a/static/i18n/en/app.yml b/static/i18n/en/app.yml index 02806506..49deffcf 100644 --- a/static/i18n/en/app.yml +++ b/static/i18n/en/app.yml @@ -116,7 +116,7 @@ exchange: genuinecheck: modal: title: Genuine check, bro -importAccounts: +addAccounts: title: Add accounts breadcrumb: informations: Informations diff --git a/static/i18n/fr/app.yml b/static/i18n/fr/app.yml index ec9d7aa5..fa72912c 100644 --- a/static/i18n/fr/app.yml +++ b/static/i18n/fr/app.yml @@ -117,7 +117,7 @@ exchange: genuinecheck: modal: title: Genuine check, bro -importAccounts: +addAccounts: title: Add accounts breadcrumb: informations: Informations From 7dd391df12cfb6330f4d1c491991e438f5dc3735 Mon Sep 17 00:00:00 2001 From: meriadec Date: Wed, 13 Jun 2018 21:00:01 +0200 Subject: [PATCH 2/7] Fix storybook and provide __STORYBOOK_ENV__ global --- .eslintrc | 1 + flow-defs/globals.js | 1 + src/globals.js | 7 ++++++- src/renderer/createStore.js | 6 ++++-- src/renderer/init.js | 9 ++------- webpack/plugins.js | 3 ++- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.eslintrc b/.eslintrc index 60aa4172..d30945b6 100644 --- a/.eslintrc +++ b/.eslintrc @@ -11,6 +11,7 @@ "__PRINT_MODE__": false, "__GLOBAL_STYLES__": false, "__APP_VERSION__": false, + "__STORYBOOK_ENV__": false, "__static": false, "window": false, "document": false, diff --git a/flow-defs/globals.js b/flow-defs/globals.js index 5e37fd59..fd239c40 100644 --- a/flow-defs/globals.js +++ b/flow-defs/globals.js @@ -8,6 +8,7 @@ declare var __PRINT_MODE__: string declare var __SENTRY_URL__: string declare var __GLOBAL_STYLES__: string declare var __APP_VERSION__: string +declare var __STORYBOOK_ENV__: string declare var __static: string declare var describe: Function declare var test: Function diff --git a/src/globals.js b/src/globals.js index 69bd02d1..c4d9dfd2 100644 --- a/src/globals.js +++ b/src/globals.js @@ -1,8 +1,13 @@ // @flow -const { NODE_ENV } = process.env +const { NODE_ENV, STORYBOOK_ENV } = process.env global.__ENV__ = NODE_ENV === 'development' ? NODE_ENV : 'production' global.__DEV__ = global.__ENV__ === 'development' global.__PROD__ = !global.__DEV__ +global.__STORYBOOK_ENV__ = STORYBOOK_ENV === '1' global.__GLOBAL_STYLES__ = require('./styles/reset') + +if (STORYBOOK_ENV === '1') { + global.__APP_VERSION__ = '1.0.0' +} diff --git a/src/renderer/createStore.js b/src/renderer/createStore.js index 75f46711..f5d6a949 100644 --- a/src/renderer/createStore.js +++ b/src/renderer/createStore.js @@ -6,7 +6,6 @@ import thunk from 'redux-thunk' import createHistory from 'history/createHashHistory' import type { HashHistory } from 'history' import logger from 'middlewares/logger' -import sentry from 'middlewares/sentry' import reducers from 'reducers' type Props = { @@ -20,7 +19,10 @@ export default ({ state, history, dbMiddleware }: Props) => { if (!history) { history = createHistory() } - const middlewares = [routerMiddleware(history), thunk, logger, sentry] + const middlewares = [routerMiddleware(history), thunk, logger] + if (!__STORYBOOK_ENV__) { + middlewares.push(require('middlewares/sentry').default) + } if (dbMiddleware) { middlewares.push(dbMiddleware) } diff --git a/src/renderer/init.js b/src/renderer/init.js index 1806aff1..5b01a2ed 100644 --- a/src/renderer/init.js +++ b/src/renderer/init.js @@ -11,6 +11,8 @@ import moment from 'moment' import createStore from 'renderer/createStore' import events from 'renderer/events' +import { enableGlobalTab, isGlobalTabEnabled } from 'config/global-tab' + import { fetchAccounts } from 'actions/accounts' import { fetchSettings } from 'actions/settings' import { isLocked } from 'reducers/application' @@ -29,15 +31,8 @@ import 'styles/global' const rootNode = document.getElementById('app') -// Github like focus style: -// - focus states are not visible by default -// - first time user hit tab, enable global tab to see focus states -let IS_GLOBAL_TAB_ENABLED = false const TAB_KEY = 9 -export const isGlobalTabEnabled = () => IS_GLOBAL_TAB_ENABLED -export const enableGlobalTab = () => (IS_GLOBAL_TAB_ENABLED = true) - async function init() { if (process.env.LEDGER_RESET_ALL) { await hardReset() diff --git a/webpack/plugins.js b/webpack/plugins.js index e1bfb18d..7dc4536f 100644 --- a/webpack/plugins.js +++ b/webpack/plugins.js @@ -3,7 +3,7 @@ const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer') const pkg = require('../package.json') require('../src/globals') -const { BUNDLE_ANALYZER, SENTRY_URL } = process.env +const { BUNDLE_ANALYZER, SENTRY_URL, STORYBOOK_ENV } = process.env module.exports = type => { const plugins = [ @@ -13,6 +13,7 @@ module.exports = type => { __DEV__, __PROD__, __SENTRY_URL__: JSON.stringify(SENTRY_URL || null), + __STORYBOOK_ENV__: JSON.stringify(STORYBOOK_ENV), 'process.env.NODE_ENV': JSON.stringify(__ENV__), }), ] From ed831d7e79fc1b207a701990290deab3464bfd76 Mon Sep 17 00:00:00 2001 From: meriadec Date: Wed, 13 Jun 2018 21:00:02 +0200 Subject: [PATCH 3/7] Factorize AddAccount code and create AccountsList --- .../AccountsList}/AccountRow.js | 2 +- src/components/base/AccountsList/index.js | 98 ++++++++++ src/components/base/AccountsList/stories.js | 30 +++ src/components/base/Box/Box.js | 2 + src/components/base/Box/Tabbable.js | 2 +- src/components/modals/AddAccounts/index.js | 3 +- .../AddAccounts/steps/03-step-import.js | 180 ++++++------------ src/config/global-tab.js | 7 + src/styles/theme.js | 3 - 9 files changed, 204 insertions(+), 123 deletions(-) rename src/components/{modals/AddAccounts => base/AccountsList}/AccountRow.js (98%) create mode 100644 src/components/base/AccountsList/index.js create mode 100644 src/components/base/AccountsList/stories.js create mode 100644 src/config/global-tab.js diff --git a/src/components/modals/AddAccounts/AccountRow.js b/src/components/base/AccountsList/AccountRow.js similarity index 98% rename from src/components/modals/AddAccounts/AccountRow.js rename to src/components/base/AccountsList/AccountRow.js index 32303cd9..26e607f8 100644 --- a/src/components/modals/AddAccounts/AccountRow.js +++ b/src/components/base/AccountsList/AccountRow.js @@ -110,7 +110,7 @@ export default class AccountRow extends PureComponent { fontSize={4} color="grey" /> - + ) } diff --git a/src/components/base/AccountsList/index.js b/src/components/base/AccountsList/index.js new file mode 100644 index 00000000..81714ab9 --- /dev/null +++ b/src/components/base/AccountsList/index.js @@ -0,0 +1,98 @@ +// @flow + +import React from 'react' +import styled from 'styled-components' +import { translate } from 'react-i18next' +import type { Account } from '@ledgerhq/live-common/lib/types' + +import Box from 'components/base/Box' +import FakeLink from 'components/base/FakeLink' +import Spinner from 'components/base/Spinner' +import type { T } from 'types/common' + +import AccountRow from './AccountRow' + +const AccountsList = ({ + accounts, + checkedIds, + onToggleAccount, + onUpdateAccount, + onSelectAll, + onUnselectAll, + isLoading, + title, + emptyText, + t, +}: { + accounts: Account[], + checkedIds: string[], + onToggleAccount: Account => void, + onUpdateAccount: Account => void, + onSelectAll: () => void, + onUnselectAll: () => void, + isLoading?: boolean, + title?: string, + emptyText?: string, + t: T, +}) => { + const withToggleAll = !!onSelectAll && !!onUnselectAll && accounts.length > 1 + const isAllSelected = accounts.every(acc => !!checkedIds.find(id => acc.id === id)) + return ( + + {(title || withToggleAll) && ( + + {title && ( + + {title} + + )} + {withToggleAll && ( + + {isAllSelected ? t('app:addAccounts.unselectAll') : t('app:addAccounts.selectAll')} + + )} + + )} + {accounts.length || isLoading ? ( + + {accounts.map(account => ( + id === account.id) !== undefined} + onClick={onToggleAccount} + onAccountUpdate={onUpdateAccount} + /> + ))} + {isLoading && ( + + + + )} + + ) : emptyText && !isLoading ? ( + + {emptyText} + + ) : null} + + ) +} + +const LoadingRow = styled(Box).attrs({ + horizontal: true, + borderRadius: 1, + px: 3, + align: 'center', + justify: 'center', +})` + height: 48px; + border: 1px dashed ${p => p.theme.colors.grey}; +` + +export default translate()(AccountsList) diff --git a/src/components/base/AccountsList/stories.js b/src/components/base/AccountsList/stories.js new file mode 100644 index 00000000..ba82c2d4 --- /dev/null +++ b/src/components/base/AccountsList/stories.js @@ -0,0 +1,30 @@ +// @flow + +import React from 'react' +import { genAccount } from '@ledgerhq/live-common/lib/mock/account' +import { storiesOf } from '@storybook/react' +import { action } from '@storybook/addon-actions' +import { boolean, text } from '@storybook/addon-knobs' + +import AccountsList from 'components/base/AccountsList' + +const stories = storiesOf('Components/base', module) + +const ACCOUNTS = [genAccount('a'), genAccount('b'), genAccount('c')] + +const CHECKED_IDS = [] + +stories.add('AccountsList', () => ( +
+ +
+)) diff --git a/src/components/base/Box/Box.js b/src/components/base/Box/Box.js index 8141f7f9..48f6246e 100644 --- a/src/components/base/Box/Box.js +++ b/src/components/base/Box/Box.js @@ -18,6 +18,7 @@ import fontFamily from 'styles/styled/fontFamily' export const styledTextAlign = style({ prop: 'textAlign', cssProperty: 'textAlign' }) export const styledCursor = style({ prop: 'cursor', cssProperty: 'cursor' }) +export const styledTextTransform = style({ prop: 'textTransform', cssProperty: 'textTransform' }) export default styled.div` ${alignItems}; @@ -32,6 +33,7 @@ export default styled.div` ${space}; ${styledTextAlign}; ${styledCursor}; + ${styledTextTransform}; display: flex; flex-shrink: ${p => (p.noShrink === true ? '0' : p.shrink === true ? '1' : '')}; diff --git a/src/components/base/Box/Tabbable.js b/src/components/base/Box/Tabbable.js index 7ce573c7..7a54d3ab 100644 --- a/src/components/base/Box/Tabbable.js +++ b/src/components/base/Box/Tabbable.js @@ -3,7 +3,7 @@ import React, { Component } from 'react' import styled from 'styled-components' -import { isGlobalTabEnabled } from 'renderer/init' +import { isGlobalTabEnabled } from 'config/global-tab' import { rgba } from 'styles/helpers' import Box from './Box' diff --git a/src/components/modals/AddAccounts/index.js b/src/components/modals/AddAccounts/index.js index ca712357..9e9a0858 100644 --- a/src/components/modals/AddAccounts/index.js +++ b/src/components/modals/AddAccounts/index.js @@ -130,9 +130,10 @@ class AddAccounts extends PureComponent { }) transitionTo = stepId => { + const { currency } = this.state let nextState = { stepId } if (stepId === 'chooseCurrency') { - nextState = { ...INITIAL_STATE } + nextState = { ...INITIAL_STATE, currency } } this.setState(nextState) } diff --git a/src/components/modals/AddAccounts/steps/03-step-import.js b/src/components/modals/AddAccounts/steps/03-step-import.js index 528d1d7c..0472d33e 100644 --- a/src/components/modals/AddAccounts/steps/03-step-import.js +++ b/src/components/modals/AddAccounts/steps/03-step-import.js @@ -1,7 +1,6 @@ // @flow -import React, { PureComponent } from 'react' -import styled from 'styled-components' +import React, { PureComponent, Fragment } from 'react' import type { Account } from '@ledgerhq/live-common/lib/types' import uniq from 'lodash/uniq' @@ -9,12 +8,9 @@ import { getBridgeForCurrency } from 'bridge' import Box from 'components/base/Box' import Button from 'components/base/Button' -import Spinner from 'components/base/Spinner' -import FakeLink from 'components/base/FakeLink' +import AccountsList from 'components/base/AccountsList' import IconExchange from 'icons/Exchange' -import AccountRow from '../AccountRow' - import type { StepProps } from '../index' class StepImport extends PureComponent { @@ -101,7 +97,7 @@ class StepImport extends PureComponent { } } - handleAccountUpdate = (updatedAccount: Account) => { + handleUpdateAccount = (updatedAccount: Account) => { const { scannedAccounts, setState } = this.props setState({ scannedAccounts: scannedAccounts.map(account => { @@ -123,7 +119,15 @@ class StepImport extends PureComponent { handleUnselectAll = () => this.props.setState({ checkedAccountsIds: [] }) render() { - const { scanStatus, err, scannedAccounts, checkedAccountsIds, existingAccounts, t } = this.props + const { + scanStatus, + currency, + err, + scannedAccounts, + checkedAccountsIds, + existingAccounts, + t, + } = this.props const importableAccounts = scannedAccounts.filter(acc => { if (acc.operations.length <= 0) { @@ -139,124 +143,63 @@ class StepImport extends PureComponent { return existingAccounts.find(a => a.id === acc.id) === undefined }) - const isAllSelected = scannedAccounts.filter(acc => acc.operations.length > 0).every(acc => { - const isChecked = !!checkedAccountsIds.find(id => acc.id === id) - const isImported = !!existingAccounts.find(a => acc.id === a.id) - return isChecked || isImported + const importableAccountsListTitle = t('app:addAccounts.accountToImportSubtitle', { + count: importableAccounts.length, }) - return ( - - {err && {err.message}} + const importableAccountsEmpty = `We didnt find any ${ + currency ? ` ${currency.name}}` : '' + } account to import.` + return ( + - {(!!importableAccounts.length || scanStatus === 'scanning') && ( - - {!!importableAccounts.length && ( - - - {t('app:addAccounts.accountToImportSubtitle', { - count: importableAccounts.length, - })} - - - {isAllSelected - ? t('app:addAccounts.unselectAll') - : t('app:addAccounts.selectAll')} - - - )} - - - {importableAccounts.map(account => { - const isChecked = checkedAccountsIds.find(id => id === account.id) !== undefined - const existingAccount = existingAccounts.find(a => a.id === account.id) - const isDisabled = existingAccount !== undefined - return ( - - ) - })} - - {scanStatus === 'scanning' && ( - - - - )} - - - )} - - {creatableAccounts.length > 0 && ( - - - - {t('app:addAccounts.createNewAccount')} - - - id === creatableAccounts[0].id) !== undefined - } - onClick={this.handleToggleAccount} - onAccountUpdate={this.handleAccountUpdate} - /> - - )} + + - - {['error'].includes(scanStatus) && ( + {err && ( + + {err.message} - )} - - + + )} + ) } } export default StepImport -export const LoadingRow = styled(Box).attrs({ - horizontal: true, - borderRadius: 1, - px: 3, - align: 'center', - justify: 'center', -})` - height: 48px; - border: 1px dashed ${p => p.theme.colors.fog}; -` - export const StepImportFooter = ({ scanStatus, onClickAdd, + onCloseModal, checkedAccountsIds, scannedAccounts, t, @@ -277,20 +220,23 @@ export const StepImportFooter = ({ }).length const ctaWording = - willCreateAccount && willAddAccounts - ? `${t('app:addAccounts.cta.create')} / ${t('app:addAccounts.cta.import', { - count: addedAccountsCount, - })}` - : willCreateAccount - ? t('app:addAccounts.cta.create') - : t('app:addAccounts.cta.import', { count: addedAccountsCount }) + scanStatus === 'scanning' + ? t('app:common.sync.syncing') + : willCreateAccount && willAddAccounts + ? `${t('app:addAccounts.cta.create')} / ${t('app:addAccounts.cta.import', { + count: addedAccountsCount, + })}` + : willCreateAccount + ? t('app:addAccounts.cta.create') + : willAddAccounts + ? t('app:addAccounts.cta.import', { count: addedAccountsCount }) + : t('app:common.close') + + const willClose = !willCreateAccount && !willAddAccounts + const onClick = willClose ? onCloseModal : onClickAdd return ( - ) diff --git a/src/config/global-tab.js b/src/config/global-tab.js new file mode 100644 index 00000000..ef64345f --- /dev/null +++ b/src/config/global-tab.js @@ -0,0 +1,7 @@ +// Github like focus style: +// - focus states are not visible by default +// - first time user hit tab, enable global tab to see focus states +let IS_GLOBAL_TAB_ENABLED = false + +export const isGlobalTabEnabled = () => IS_GLOBAL_TAB_ENABLED +export const enableGlobalTab = () => (IS_GLOBAL_TAB_ENABLED = true) diff --git a/src/styles/theme.js b/src/styles/theme.js index 15dd9de7..4914185f 100644 --- a/src/styles/theme.js +++ b/src/styles/theme.js @@ -1,7 +1,5 @@ // @flow -import { rgba } from 'styles/helpers' - export const space = [0, 5, 10, 15, 20, 30, 40, 50, 70] export const fontSizes = [8, 9, 10, 12, 13, 16, 18, 22, 32] export const radii = [0, 4] @@ -95,7 +93,6 @@ export default { topBarHeight: 58, sideBarWidth: 230, }, - focusBoxShadow: `${rgba(colors.wallet, 0.2)} 0 2px 5px`, radii, fontFamilies, fontSizes, From f0f016b236aacc365b4a12709617d0b24b72775c Mon Sep 17 00:00:00 2001 From: meriadec Date: Wed, 13 Jun 2018 21:00:03 +0200 Subject: [PATCH 4/7] Update footer of add account import step --- .../modals/AddAccounts/steps/03-step-import.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/components/modals/AddAccounts/steps/03-step-import.js b/src/components/modals/AddAccounts/steps/03-step-import.js index 0472d33e..79ae6d09 100644 --- a/src/components/modals/AddAccounts/steps/03-step-import.js +++ b/src/components/modals/AddAccounts/steps/03-step-import.js @@ -7,6 +7,7 @@ import uniq from 'lodash/uniq' import { getBridgeForCurrency } from 'bridge' import Box from 'components/base/Box' +import CurrencyBadge from 'components/base/CurrencyBadge' import Button from 'components/base/Button' import AccountsList from 'components/base/AccountsList' import IconExchange from 'icons/Exchange' @@ -202,6 +203,7 @@ export const StepImportFooter = ({ onCloseModal, checkedAccountsIds, scannedAccounts, + currency, t, }: StepProps) => { const willCreateAccount = checkedAccountsIds.some(id => { @@ -236,8 +238,11 @@ export const StepImportFooter = ({ const onClick = willClose ? onCloseModal : onClickAdd return ( - + + {currency && } + + ) } From 317b2fef36f0f5b27f0c5802ca921bc583fe833e Mon Sep 17 00:00:00 2001 From: meriadec Date: Wed, 13 Jun 2018 21:00:04 +0200 Subject: [PATCH 5/7] Visual & interaction improvements --- src/components/AccountPage/index.js | 36 ++++++++++++++-------- src/components/TopBar/ActivityIndicator.js | 4 +-- src/components/TopBar/ItemContainer.js | 9 +++--- src/components/TopBar/index.js | 9 ++++-- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/components/AccountPage/index.js b/src/components/AccountPage/index.js index f64ee39a..faa4ee3f 100644 --- a/src/components/AccountPage/index.js +++ b/src/components/AccountPage/index.js @@ -8,12 +8,13 @@ import { Redirect } from 'react-router' import styled from 'styled-components' import type { Currency, Account } from '@ledgerhq/live-common/lib/types' import SyncOneAccountOnMount from 'components/SyncOneAccountOnMount' +import Tooltip from 'components/base/Tooltip' import { MODAL_SEND, MODAL_RECEIVE, MODAL_SETTINGS_ACCOUNT } from 'config/constants' import type { T } from 'types/common' -import { darken } from 'styles/helpers' +import { rgba } from 'styles/helpers' import { accountSelector } from 'reducers/accounts' import { counterValueCurrencySelector, localeSelector } from 'reducers/settings' @@ -29,7 +30,7 @@ import { BalanceSinceDiff, BalanceSincePercent, } from 'components/BalanceSummary/BalanceInfos' -import Box from 'components/base/Box' +import Box, { Tabbable } from 'components/base/Box' import Button from 'components/base/Button' import FormattedVal from 'components/base/FormattedVal' import PillsDaysCount from 'components/PillsDaysCount' @@ -39,15 +40,22 @@ import StickyBackToTop from 'components/StickyBackToTop' import AccountHeader from './AccountHeader' import EmptyStateAccount from './EmptyStateAccount' -const ButtonSettings = styled(Button).attrs({ - small: true, +const ButtonSettings = styled(Tabbable).attrs({ + cursor: 'pointer', + align: 'center', + justify: 'center', + borderRadius: 1, })` - border: 2px solid ${p => p.theme.colors.grey}; - width: 30px; - padding: 0; + width: 40px; + height: 40px; + + &:hover { + color: ${p => (p.disabled ? '' : p.theme.colors.dark)}; + background: ${p => (p.disabled ? '' : rgba(p.theme.colors.fog, 0.2))}; + } &:active { - border: 2px solid ${p => darken(p.theme.colors.grey, 0.2)}; + background: ${p => (p.disabled ? '' : rgba(p.theme.colors.fog, 0.3))}; } ` @@ -120,11 +128,13 @@ class AccountPage extends PureComponent { )} - openModal(MODAL_SETTINGS_ACCOUNT, { account })}> - - - - + t('app:account.settings.title')}> + openModal(MODAL_SETTINGS_ACCOUNT, { account })}> + + + + + {account.operations.length > 0 ? ( diff --git a/src/components/TopBar/ActivityIndicator.js b/src/components/TopBar/ActivityIndicator.js index 12bed341..64c2373a 100644 --- a/src/components/TopBar/ActivityIndicator.js +++ b/src/components/TopBar/ActivityIndicator.js @@ -70,11 +70,11 @@ class ActivityIndicatorInner extends Component { render() { const { isPending, isError, t } = this.props const { hasClicked, isFirstSync } = this.state - const isDisabled = hasClicked || isError + const isDisabled = isFirstSync || hasClicked || isError const isRotating = isPending && (hasClicked || isFirstSync) return ( - + (p.isDisabled ? 'default' : 'pointer'), + cursor: p => (p.disabled ? 'default' : 'pointer'), horizontal: true, borderRadius: 1, })` height: 40px; + pointer-events: ${p => (p.disabled ? 'none' : 'unset')}; &:hover { - color: ${p => (p.isDisabled ? '' : p.theme.colors.dark)}; - background: ${p => (p.isDisabled ? '' : rgba(p.theme.colors.fog, 0.2))}; + color: ${p => (p.disabled ? '' : p.theme.colors.dark)}; + background: ${p => (p.disabled ? '' : rgba(p.theme.colors.fog, 0.2))}; } &:active { - background: ${p => (p.isDisabled ? '' : rgba(p.theme.colors.fog, 0.3))}; + background: ${p => (p.disabled ? '' : rgba(p.theme.colors.fog, 0.3))}; } ` diff --git a/src/components/TopBar/index.js b/src/components/TopBar/index.js index 19faec18..11b4bd1c 100644 --- a/src/components/TopBar/index.js +++ b/src/components/TopBar/index.js @@ -19,6 +19,7 @@ import IconSettings from 'icons/Settings' import Box from 'components/base/Box' import GlobalSearch from 'components/GlobalSearch' +import Tooltip from 'components/base/Tooltip' import ActivityIndicator from './ActivityIndicator' import ItemContainer from './ItemContainer' @@ -101,9 +102,11 @@ class TopBar extends PureComponent { - - - + t('app:settings.title')}> + + + + {hasPassword && ( // FIXME this should be a dedicated component. therefore this component don't need to connect() From 38c9e8106707d504122cc1c697bee6aef5415a34 Mon Sep 17 00:00:00 2001 From: meriadec Date: Wed, 13 Jun 2018 21:00:05 +0200 Subject: [PATCH 6/7] Create Ellipsis and use it in various places --- src/components/AccountPage/AccountHeader.js | 11 +++++++---- src/components/AccountPage/index.js | 4 ++-- src/components/DashboardPage/AccountCard.js | 7 ++++--- src/components/base/Ellipsis.js | 16 ++++++++++++++++ 4 files changed, 29 insertions(+), 9 deletions(-) create mode 100644 src/components/base/Ellipsis.js diff --git a/src/components/AccountPage/AccountHeader.js b/src/components/AccountPage/AccountHeader.js index 5c038fc3..51d619d5 100644 --- a/src/components/AccountPage/AccountHeader.js +++ b/src/components/AccountPage/AccountHeader.js @@ -6,6 +6,7 @@ import styled from 'styled-components' import type { Account } from '@ledgerhq/live-common/lib/types' import Box from 'components/base/Box' +import Ellipsis from 'components/base/Ellipsis' import Text from 'components/base/Text' import CryptoCurrencyIcon from '../CryptoCurrencyIcon' @@ -22,7 +23,7 @@ const AccountName = styled(Text).attrs({ ff: 'Museo Sans', fontSize: 7, })` - line-height: 1; + line-height: 1.1; ` type Props = { @@ -33,13 +34,15 @@ class AccountHeader extends PureComponent { render() { const { account } = this.props return ( - + - + {account.currency.name} - {account.name} + + {account.name} + ) diff --git a/src/components/AccountPage/index.js b/src/components/AccountPage/index.js index faa4ee3f..6486ffaf 100644 --- a/src/components/AccountPage/index.js +++ b/src/components/AccountPage/index.js @@ -108,9 +108,9 @@ class AccountPage extends PureComponent { // Force re-render account page, for avoid animation - + - + {account.operations.length > 0 && (