Browse Source

Merge pull request #395 from NastiaS/accountSettingsPolish

adjust account settings to new designs
master
Gaëtan Renaudeau 7 years ago
committed by GitHub
parent
commit
7e2fd5f892
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 273
      src/components/modals/SettingsAccount.js
  2. 9
      static/i18n/en/account.yml
  3. 1
      static/i18n/en/common.yml

273
src/components/modals/SettingsAccount.js

@ -1,59 +1,47 @@
// @flow // @flow
import React, { PureComponent } from 'react' import React, { PureComponent } from 'react'
import styled from 'styled-components'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { compose } from 'redux'
import get from 'lodash/get' import get from 'lodash/get'
import { push } from 'react-router-redux' import { translate } from 'react-i18next'
import type { Account, Unit } from '@ledgerhq/live-common/lib/types'
import type { Account, Unit, Currency } from '@ledgerhq/live-common/lib/types'
import type { T } from 'types/common'
import { MODAL_SETTINGS_ACCOUNT } from 'config/constants' import { MODAL_SETTINGS_ACCOUNT } from 'config/constants'
import { updateAccount, removeAccount } from 'actions/accounts' import { updateAccount } from 'actions/accounts'
import { setDataModal, closeModal } from 'reducers/modals' import { setDataModal } from 'reducers/modals'
import CryptoCurrencyIcon from 'components/CryptoCurrencyIcon'
import Box from 'components/base/Box' import Box from 'components/base/Box'
import Button from 'components/base/Button' import Button from 'components/base/Button'
import Input from 'components/base/Input' import Input, { ErrorMessageInput } from 'components/base/Input'
import Select from 'components/base/Select/index' import Select from 'components/base/Select/index'
import Modal, { ModalBody, ModalTitle, ModalFooter, ModalContent } from 'components/base/Modal' import Modal, { ModalBody, ModalTitle, ModalFooter, ModalContent } from 'components/base/Modal'
import Label from 'components/base/Label'
import IconEdit from 'icons/Edit'
type State = { type State = {
accountName: string | null, accountName: string | null,
minConfirmations: number | null, accountUnit: Unit | null,
editName: boolean, accountNameError: boolean,
nameHovered: boolean,
editUnit: boolean,
} }
type Props = { type Props = {
closeModal: Function,
push: Function,
removeAccount: Function,
setDataModal: Function, setDataModal: Function,
updateAccount: Function, updateAccount: Function,
t: T,
} }
const mapDispatchToProps = { const mapDispatchToProps = {
closeModal,
push,
removeAccount,
setDataModal, setDataModal,
updateAccount, updateAccount,
} }
const defaultState = { const defaultState = {
editName: false,
accountName: null, accountName: null,
minConfirmations: null, accountUnit: null,
nameHovered: false, accountNameError: false,
editUnit: false,
}
function hasNoOperations(account: Account) {
return get(account, 'operations.length', 0) === 0
} }
class SettingsAccount extends PureComponent<Props, State> { class SettingsAccount extends PureComponent<Props, State> {
@ -62,9 +50,9 @@ class SettingsAccount extends PureComponent<Props, State> {
} }
getAccount(data: Object) { getAccount(data: Object) {
const { accountName, minConfirmations } = this.state const { accountName } = this.state
const account = get(data, 'account', {}) const account = get(data, 'account', {})
return { return {
...account, ...account,
...(accountName !== null ...(accountName !== null
@ -72,168 +60,101 @@ class SettingsAccount extends PureComponent<Props, State> {
name: accountName, name: accountName,
} }
: {}), : {}),
settings: {
...account.settings,
minConfirmations: minConfirmations || account.minConfirmations,
},
} }
} }
handleHoveredName = (state: boolean) => () =>
this.setState({
nameHovered: state,
})
handleChangeMinConfirmations = account => minConfirmations => {
const { updateAccount } = this.props
this.setState({ minConfirmations })
window.requestAnimationFrame(() => {
updateAccount({
...account,
minConfirmations: Number(minConfirmations),
})
})
}
handleEditName = (state: boolean) => () =>
this.setState({
nameHovered: false,
editName: state,
})
handleChangeName = (value: string) => handleChangeName = (value: string) =>
this.setState({ this.setState({
accountName: value, accountName: value,
}) })
handleCancelEditName = (data: Object) => () => { handleSubmit = (account: Account, onClose: () => void) => (
this.handleEditName(false)() e: SyntheticEvent<HTMLFormElement>,
this.setState({ ) => {
accountName: get(data, 'account.name', ''),
})
}
handleSubmitName = (account: Account) => (e: SyntheticEvent<HTMLFormElement>) => {
e.preventDefault() e.preventDefault()
const { updateAccount, setDataModal } = this.props const { updateAccount, setDataModal } = this.props
const { accountName } = this.state const { accountName, accountUnit } = this.state
if (accountName !== '') { if (accountName !== '') {
account = { ...account, unit: accountUnit || account.unit }
updateAccount(account) updateAccount(account)
setDataModal(MODAL_SETTINGS_ACCOUNT, { account }) setDataModal(MODAL_SETTINGS_ACCOUNT, { account })
onClose()
this.setState({ } else {
editName: false, this.setState({ accountNameError: true })
})
} }
} }
handleArchiveAccount = (account: Account) => () => { handleFocus = (name: string) => {
const { push, closeModal, updateAccount, removeAccount } = this.props switch (name) {
const shouldRemove = hasNoOperations(account) case 'accountName':
this.setState({ accountNameError: false })
if (shouldRemove) { break
removeAccount(account) default:
} else { break
updateAccount({ ...account, archived: true })
} }
closeModal(MODAL_SETTINGS_ACCOUNT)
push('/')
} }
handleHide = () => handleChangeUnit = (value: Unit) => {
this.setState({ this.setState({ accountUnit: value })
...defaultState,
})
handleChangeUnit = (value: Unit, account: Account) => {
const { updateAccount, setDataModal } = this.props
account = { ...account, unit: value }
updateAccount(account)
setDataModal(MODAL_SETTINGS_ACCOUNT, { account })
} }
render() { render() {
const { editName, nameHovered, editUnit } = this.state const { accountUnit, accountNameError } = this.state
const { t } = this.props
return ( return (
<Modal <Modal
name={MODAL_SETTINGS_ACCOUNT} name={MODAL_SETTINGS_ACCOUNT}
onHide={this.handleHide}
render={({ data, onClose }) => { render={({ data, onClose }) => {
const account = this.getAccount(data) const account = this.getAccount(data)
return ( return (
<ModalBody onClose={onClose}> <ModalBody onClose={onClose}>
<ModalTitle>{'Account settings'}</ModalTitle> <form onSubmit={this.handleSubmit(account, onClose)}>
<ModalContent flow={4}> <ModalTitle>{t('account:settings.title')}</ModalTitle>
<Box <ModalContent mb={3}>
alignItems="center" <Container>
flow={2} <Box>
horizontal <OptionRowTitle>{t('account:settings.accountName.title')}</OptionRowTitle>
onMouseEnter={this.handleHoveredName(true)} <OptionRowDesc>{t('account:settings.accountName.desc')}</OptionRowDesc>
onMouseLeave={this.handleHoveredName(false)} </Box>
> <Box>
<Box> <Input
{editName ? ( value={account.name}
<form onSubmit={this.handleSubmitName(account)}> onChange={this.handleChangeName}
<Box alignItems="center" horizontal flow={2}> renderLeft={<InputLeft currency={account.currency} />}
<Box> onFocus={() => this.handleFocus('accountName')}
<Input value={account.name} onChange={this.handleChangeName} /> />
</Box> {accountNameError && (
<Box flow={2} horizontal> <ErrorMessageInput>
<Button type="button" onClick={this.handleCancelEditName(data)}> {t('account:settings.accountName.error')}
Cancel </ErrorMessageInput>
</Button> )}
<Button type="submit" primary> </Box>
Ok </Container>
</Button> <Container>
</Box> <Box>
</Box> <OptionRowTitle>{t('account:settings.unit.title')}</OptionRowTitle>
</form> <OptionRowDesc>{t('account:settings.unit.desc')}</OptionRowDesc>
) : ( </Box>
account.name <Box style={{ width: 180 }}>
)} <Select
</Box> keyProp="code"
{!editName && onChange={this.handleChangeUnit}
nameHovered && ( renderSelected={item => item && item.code}
<Box onClick={this.handleEditName(true)} style={{ cursor: 'pointer' }}> value={accountUnit || account.unit}
<IconEdit size={16} /> items={account.currency.units}
</Box> />
)} </Box>
</Box> </Container>
<Box> </ModalContent>
<Label>{'Minimum confirmations'}</Label> <ModalFooter>
<Input <Button small ml="auto" type="submit" primary>
type="number" {t('common:apply')}
min={1} </Button>
max={100} </ModalFooter>
value={account.minConfirmations} </form>
onChange={this.handleChangeMinConfirmations(account)}
/>
</Box>
{editUnit && (
<Box>
<Label>{'Edit Units'}</Label>
<Select
keyProp="code"
onChange={value => this.handleChangeUnit(value, account)}
renderSelected={item => item && item.code}
value={account.unit}
items={account.currency.units}
/>
</Box>
)}
</ModalContent>
<ModalFooter horizontal justify="flex-end" flow={2}>
<Button onClick={this.handleArchiveAccount(account)}>
{hasNoOperations(account) ? 'Remove account' : 'Archive account'}
</Button>
<Button primary onClick={onClose}>
Go to account
</Button>
</ModalFooter>
</ModalBody> </ModalBody>
) )
}} }}
@ -242,4 +163,38 @@ class SettingsAccount extends PureComponent<Props, State> {
} }
} }
export default connect(null, mapDispatchToProps)(SettingsAccount) export default compose(connect(null, mapDispatchToProps), translate())(SettingsAccount)
export function InputLeft({ currency }: { currency: Currency }) {
return (
<Box ml={2} style={{ justifyContent: 'center' }} color={currency.color}>
<CryptoCurrencyIcon currency={currency} size={16} />
</Box>
)
}
export const Container = styled(Box).attrs({
flow: 2,
justify: 'space-between',
horizontal: true,
mb: 3,
pb: 4,
})`
border-bottom: 1px solid ${p => p.theme.colors.lightGrey};
`
export const OptionRowDesc = styled(Box).attrs({
ff: 'Open Sans|Regular',
fontSize: 3,
textAlign: 'left',
lineHeight: 1.69,
color: 'grey',
shrink: 1,
})``
export const OptionRowTitle = styled(Box).attrs({
ff: 'Open Sans|SemiBold',
color: 'black',
fontSize: 4,
textAlign: 'left',
lineHeight: 1.69,
})``

9
static/i18n/en/account.yml

@ -1,3 +1,12 @@
balance: Balance balance: Balance
receive: Receive receive: Receive
lastOperations: Last operations lastOperations: Last operations
settings:
title: Edit Account
accountName:
title: Account name
desc: Lorem ipsum dolort amet
error: Name is required
unit:
title: Unit
desc: Lorem ipsum dolort amet

1
static/i18n/en/common.yml

@ -1,6 +1,7 @@
ok: Okay ok: Okay
yes: Yes yes: Yes
no: No no: No
apply: Apply
confirm: Confirm confirm: Confirm
cancel: Cancel cancel: Cancel
continue: Continue continue: Continue

Loading…
Cancel
Save