From 564f57ec4d61d7b71d66097322dbb041cd495200 Mon Sep 17 00:00:00 2001 From: meriadec Date: Tue, 12 Jun 2018 10:26:22 +0200 Subject: [PATCH] Add accounts: handle cta wording and unselect all --- src/components/MainSideBar.js | 19 ++- .../modals/ImportAccounts/AccountRow.js | 4 +- .../ImportAccounts/steps/03-step-import.js | 159 ++++++++++++------ static/i18n/en/importAccounts.yml | 10 ++ 4 files changed, 130 insertions(+), 62 deletions(-) diff --git a/src/components/MainSideBar.js b/src/components/MainSideBar.js index 06bcafe6..3dcfb4f8 100644 --- a/src/components/MainSideBar.js +++ b/src/components/MainSideBar.js @@ -17,10 +17,13 @@ import type { UpdateStatus } from 'reducers/update' import { MODAL_RECEIVE, MODAL_SEND } from 'config/constants' +import { rgba } from 'styles/helpers' + import { accountsSelector } from 'reducers/accounts' import { openModal } from 'reducers/modals' import { getUpdateStatus } from 'reducers/update' +import Tooltip from 'components/base/Tooltip' import { SideBarList } from 'components/base/SideBar' import Box, { Tabbable } from 'components/base/Box' import Space from 'components/base/Space' @@ -140,9 +143,11 @@ class MainSideBar extends PureComponent { scroll title={t('sidebar:accounts')} titleRight={ - openModal('importAccounts')}> - - + t('importAccounts:title')}> + openModal('importAccounts')}> + + + } items={accountsItems} emptyText={t('emptyState:sidebar.text')} @@ -157,15 +162,15 @@ const PlusWrapper = styled(Tabbable).attrs({ cursor: 'pointer', borderRadius: 1, })` - opacity: 0.4; + color: ${p => p.theme.colors.smoke}; &:hover { - opacity: 1; + color: ${p => p.theme.colors.dark}; } - border: 1px dashed rgba(0, 0, 0, 0); + border: 1px solid transparent; &:focus { - border: 1px dashed rgba(0, 0, 0, 0.2); outline: none; + border-color: ${p => rgba(p.theme.colors.wallet, 0.3)}; } ` diff --git a/src/components/modals/ImportAccounts/AccountRow.js b/src/components/modals/ImportAccounts/AccountRow.js index 99251f28..e571e5bb 100644 --- a/src/components/modals/ImportAccounts/AccountRow.js +++ b/src/components/modals/ImportAccounts/AccountRow.js @@ -17,7 +17,7 @@ import IconCheck from 'icons/Check' type Props = { account: Account, isChecked: boolean, - isDisabled: boolean, + isDisabled?: boolean, onClick: Account => void, onAccountUpdate: Account => void, } @@ -110,7 +110,7 @@ export default class AccountRow extends PureComponent { fontSize={4} color="grey" /> - + ) } diff --git a/src/components/modals/ImportAccounts/steps/03-step-import.js b/src/components/modals/ImportAccounts/steps/03-step-import.js index 960304b3..76cc7987 100644 --- a/src/components/modals/ImportAccounts/steps/03-step-import.js +++ b/src/components/modals/ImportAccounts/steps/03-step-import.js @@ -50,13 +50,15 @@ class StepImport extends PureComponent { this.scanSubscription = bridge.scanAccountsOnDevice(currency, devicePath, { next: account => { - const { scannedAccounts, checkedAccountsIds } = this.props + const { scannedAccounts, checkedAccountsIds, existingAccounts } = this.props const hasAlreadyBeenScanned = !!scannedAccounts.find(a => account.id === a.id) + const hasAlreadyBeenImported = !!existingAccounts.find(a => account.id === a.id) + const isNewAccount = account.operations.length === 0 if (!hasAlreadyBeenScanned) { setState({ scannedAccounts: [...scannedAccounts, account], checkedAccountsIds: - account.operations.length > 0 + !hasAlreadyBeenImported && !isNewAccount ? uniq([...checkedAccountsIds, account.id]) : checkedAccountsIds, }) @@ -111,15 +113,17 @@ class StepImport extends PureComponent { }) } - handleToggleSelectAll = () => { + handleSelectAll = () => { const { scannedAccounts, setState } = this.props setState({ checkedAccountsIds: scannedAccounts.filter(a => a.operations.length > 0).map(a => a.id), }) } + handleUnselectAll = () => this.props.setState({ checkedAccountsIds: [] }) + render() { - const { scanStatus, err, scannedAccounts, checkedAccountsIds, existingAccounts } = this.props + const { scanStatus, err, scannedAccounts, checkedAccountsIds, existingAccounts, t } = this.props const importableAccounts = scannedAccounts.filter(acc => { if (acc.operations.length <= 0) { @@ -135,52 +139,69 @@ 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 + }) + return ( {err && {err.message}} - - {!!importableAccounts.length && ( - - - {`Account(s) to import (${importableAccounts.length})`} + {(!!importableAccounts.length || scanStatus === 'scanning') && ( + + {!!importableAccounts.length && ( + + + {t('importAccounts:accountToImportSubtitle', { + count: importableAccounts.length, + })} + + + {isAllSelected + ? t('importAccounts:unselectAll') + : t('importAccounts:selectAll')} + - - {'Select all'} - - - )} - - - {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' && ( - - - )} + + + {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 && ( @@ -190,7 +211,7 @@ class StepImport extends PureComponent { fontSize={2} style={{ textTransform: 'uppercase' }} > - {'Create account'} + {t('importAccounts:createNewAccount')} { )} @@ -233,12 +254,44 @@ export const LoadingRow = styled(Box).attrs({ border: 1px dashed ${p => p.theme.colors.fog}; ` -export const StepImportFooter = ({ scanStatus, onClickImport, checkedAccountsIds }: StepProps) => ( - -) +export const StepImportFooter = ({ + scanStatus, + onClickImport, + checkedAccountsIds, + scannedAccounts, + t, +}: StepProps) => { + const willCreateAccount = checkedAccountsIds.some(id => { + const account = scannedAccounts.find(a => a.id === id) + return account && account.operations.length === 0 + }) + + const willImportAccounts = checkedAccountsIds.some(id => { + const account = scannedAccounts.find(a => a.id === id) + return account && account.operations.length > 0 + }) + + const importedAccountsCount = checkedAccountsIds.filter(id => { + const account = scannedAccounts.find(acc => acc.id === id) + return account && account.operations.length > 0 + }).length + + const ctaWording = + willCreateAccount && willImportAccounts + ? `${t('importAccounts:cta.create')} / ${t('importAccounts:cta.import', { + count: importedAccountsCount, + })}` + : willCreateAccount + ? t('importAccounts:cta.create') + : t('importAccounts:cta.import', { count: importedAccountsCount }) + + return ( + + ) +} diff --git a/static/i18n/en/importAccounts.yml b/static/i18n/en/importAccounts.yml index e5d05c98..3a78ea12 100644 --- a/static/i18n/en/importAccounts.yml +++ b/static/i18n/en/importAccounts.yml @@ -4,3 +4,13 @@ breadcrumb: connectDevice: Connect device import: Import finish: End +accountToImportSubtitle: Account to import +accountToImportSubtitle_plural: 'Accounts to import ({{count}})' +selectAll: Select all +unselectAll: Unselect all +createNewAccount: Create new account +retrySync: Retry sync +cta: + create: 'Create account' + import: 'Import account' + import_plural: 'Import accounts'