Browse Source

Add accounts: handle cta wording and unselect all

master
meriadec 7 years ago
parent
commit
564f57ec4d
No known key found for this signature in database GPG Key ID: 1D2FC2305E2CB399
  1. 19
      src/components/MainSideBar.js
  2. 4
      src/components/modals/ImportAccounts/AccountRow.js
  3. 159
      src/components/modals/ImportAccounts/steps/03-step-import.js
  4. 10
      static/i18n/en/importAccounts.yml

19
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<Props> {
scroll
title={t('sidebar:accounts')}
titleRight={
<PlusWrapper onClick={() => openModal('importAccounts')}>
<IconCirclePlus size={16} />
</PlusWrapper>
<Tooltip render={() => t('importAccounts:title')}>
<PlusWrapper onClick={() => openModal('importAccounts')}>
<IconCirclePlus size={16} />
</PlusWrapper>
</Tooltip>
}
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)};
}
`

4
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<Props, State> {
fontSize={4}
color="grey"
/>
<Radio isChecked={isChecked || isDisabled} />
<Radio isChecked={isChecked || !!isDisabled} />
</AccountRowContainer>
)
}

159
src/components/modals/ImportAccounts/steps/03-step-import.js

@ -50,13 +50,15 @@ class StepImport extends PureComponent<StepProps> {
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<StepProps> {
})
}
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<StepProps> {
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 (
<Box>
{err && <Box shrink>{err.message}</Box>}
<Box flow={5}>
<Box>
{!!importableAccounts.length && (
<Box horizontal mb={3} align="center">
<Box
ff="Open Sans|Bold"
color="dark"
fontSize={2}
style={{ textTransform: 'uppercase' }}
>
{`Account(s) to import (${importableAccounts.length})`}
{(!!importableAccounts.length || scanStatus === 'scanning') && (
<Box>
{!!importableAccounts.length && (
<Box horizontal mb={3} align="center">
<Box
ff="Open Sans|Bold"
color="dark"
fontSize={2}
style={{ textTransform: 'uppercase' }}
>
{t('importAccounts:accountToImportSubtitle', {
count: importableAccounts.length,
})}
</Box>
<FakeLink
ml="auto"
onClick={isAllSelected ? this.handleUnselectAll : this.handleSelectAll}
fontSize={3}
>
{isAllSelected
? t('importAccounts:unselectAll')
: t('importAccounts:selectAll')}
</FakeLink>
</Box>
<FakeLink ml="auto" onClick={this.handleToggleSelectAll} fontSize={3}>
{'Select all'}
</FakeLink>
</Box>
)}
<Box flow={2}>
{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 (
<AccountRow
key={account.id}
account={existingAccount || account}
isChecked={isChecked}
isDisabled={isDisabled}
onClick={this.handleToggleAccount}
onAccountUpdate={this.handleAccountUpdate}
/>
)
})}
{scanStatus === 'scanning' && (
<LoadingRow>
<Spinner color="grey" size={16} />
</LoadingRow>
)}
<Box flow={2}>
{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 (
<AccountRow
key={account.id}
account={existingAccount || account}
isChecked={isChecked}
isDisabled={isDisabled}
onClick={this.handleToggleAccount}
onAccountUpdate={this.handleAccountUpdate}
/>
)
})}
{scanStatus === 'scanning' && (
<LoadingRow>
<Spinner color="grey" size={16} />
</LoadingRow>
)}
</Box>
</Box>
</Box>
)}
{creatableAccounts.length > 0 && (
<Box>
<Box horizontal mb={3} align="center">
@ -190,7 +211,7 @@ class StepImport extends PureComponent<StepProps> {
fontSize={2}
style={{ textTransform: 'uppercase' }}
>
{'Create account'}
{t('importAccounts:createNewAccount')}
</Box>
</Box>
<AccountRow
@ -210,7 +231,7 @@ class StepImport extends PureComponent<StepProps> {
<Button small outline onClick={this.handleRetry}>
<Box horizontal flow={2} align="center">
<IconExchange size={13} />
<span>{'retry sync'}</span>
<span>{t('importAccounts:retrySync')}</span>
</Box>
</Button>
)}
@ -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) => (
<Button
primary
disabled={scanStatus !== 'finished' || checkedAccountsIds.length === 0}
onClick={() => onClickImport()}
>
{'Import accounts'}
</Button>
)
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 (
<Button
primary
disabled={scanStatus !== 'finished' || checkedAccountsIds.length === 0}
onClick={() => onClickImport()}
>
{ctaWording}
</Button>
)
}

10
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'

Loading…
Cancel
Save