Browse Source

Add ImportAccounts component

master
Loëck Vézien 7 years ago
parent
commit
5909f730c0
No known key found for this signature in database GPG Key ID: CBCDCE384E853AC4
  1. 2
      package.json
  2. 26
      src/components/SelectAccount.js
  3. 5
      src/components/base/Select/index.js
  4. 73
      src/components/modals/AddAccount/ImportAccounts.js
  5. 97
      src/components/modals/AddAccount/index.js
  6. 41
      src/components/modals/Send.js
  7. 1
      src/main/app.js
  8. 6
      yarn.lock

2
package.json

@ -65,7 +65,7 @@
"raven-js": "^3.22.1", "raven-js": "^3.22.1",
"react": "^16.2.0", "react": "^16.2.0",
"react-dom": "^16.2.0", "react-dom": "^16.2.0",
"react-i18next": "^7.3.2", "react-i18next": "^7.3.4",
"react-mortal": "^3.0.1", "react-mortal": "^3.0.1",
"react-motion": "^0.5.2", "react-motion": "^0.5.2",
"react-redux": "^5.0.6", "react-redux": "^5.0.6",

26
src/components/SelectAccount.js

@ -2,22 +2,16 @@
import React from 'react' import React from 'react'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import values from 'lodash/values'
import type { MapStateToProps } from 'react-redux' import type { MapStateToProps } from 'react-redux'
import { getAccounts } from 'reducers/accounts' import { getAccounts } from 'reducers/accounts'
import Select from 'components/base/Select' import Select from 'components/base/Select'
import Text from 'components/base/Text'
import type { Account } from 'types/common' import type { Account } from 'types/common'
function renderItem(accounts) {
return item => <span>{(accounts.find(a => a.id === item) || {}).name}</span>
}
const mapStateToProps: MapStateToProps<*, *, *> = state => ({ const mapStateToProps: MapStateToProps<*, *, *> = state => ({
accounts: values(getAccounts(state)), accounts: Object.entries(getAccounts(state)).map(([, account]: [string, any]) => account),
}) })
type Props = { type Props = {
@ -28,18 +22,18 @@ type Props = {
const SelectAccount = ({ accounts, value, onChange }: Props) => ( const SelectAccount = ({ accounts, value, onChange }: Props) => (
<Select <Select
itemToString={item => item}
value={value} value={value}
renderSelected={item => item.name}
renderItem={item => (
<div key={item.id}>
{item.name} - {item.data.balance}
</div>
)}
keyProp="id"
items={accounts}
placeholder="Choose an account" placeholder="Choose an account"
items={accounts.map(a => a.id)}
onChange={onChange} onChange={onChange}
renderItem={renderItem(accounts)}
renderSelected={renderItem(accounts)}
renderHighlight={(text, key) => (
<Text key={key} fontWeight="bold">
{text}
</Text>
)}
/> />
) )
export default connect(mapStateToProps)(SelectAccount) export default connect(mapStateToProps)(SelectAccount)

5
src/components/base/Select/index.js

@ -103,10 +103,7 @@ class Select extends PureComponent<Props> {
<Dropdown> <Dropdown>
{items.length ? ( {items.length ? (
items.map((item, i) => ( items.map((item, i) => (
<ItemWrapper <ItemWrapper key={keyProp ? item[keyProp] : item.key} {...getItemProps({ item })}>
key={keyProp ? item[keyProp] : item.key || item}
{...getItemProps({ item })}
>
<Item highlighted={i === highlightedIndex}> <Item highlighted={i === highlightedIndex}>
{renderItem ? renderItem(item) : <span>{item.name_highlight || item.name}</span>} {renderItem ? renderItem(item) : <span>{item.name_highlight || item.name}</span>}
</Item> </Item>

73
src/components/modals/AddAccount/ImportAccounts.js

@ -0,0 +1,73 @@
// @flow
import React, { PureComponent } from 'react'
import { formatBTC } from 'helpers/format'
import Box from 'components/base/Box'
import Button from 'components/base/Button'
type Props = {
accounts: Array<Object>,
onImportAccounts: Function,
}
type State = {
accountsSelected: Array<string>,
}
class ImportAccounts extends PureComponent<Props, State> {
state = {
accountsSelected: [],
}
handleSelectAccount = (id: string, selected: boolean) => () =>
this.setState(prev => ({
accountsSelected: selected
? prev.accountsSelected.filter(v => v !== id)
: [...prev.accountsSelected, id],
}))
render() {
const { accounts, onImportAccounts } = this.props
const { accountsSelected } = this.state
const canImportAccounts = accountsSelected.length > 0
return (
<Box>
<Box>Import Accounts</Box>
<Box>
{accounts.map(account => {
const selected = accountsSelected.includes(account.id)
return (
<Box
key={account.id}
horizontal
flow={10}
onClick={this.handleSelectAccount(account.id, selected)}
>
<Box>{selected ? 'yes' : 'no'}</Box>
<Box>
<Box>Balance: {formatBTC(account.balance)}</Box>
<Box>Transactions: {account.transactions.length}</Box>
</Box>
</Box>
)
})}
</Box>
<Box>
<Button
primary
disabled={!canImportAccounts}
onClick={onImportAccounts(accountsSelected)}
>
Import accounts
</Button>
</Box>
</Box>
)
}
}
export default ImportAccounts

97
src/components/modals/AddAccount.js → src/components/modals/AddAccount/index.js

@ -22,6 +22,8 @@ import Label from 'components/base/Label'
import Modal, { ModalBody } from 'components/base/Modal' import Modal, { ModalBody } from 'components/base/Modal'
import Select from 'components/base/Select' import Select from 'components/base/Select'
import ImportAccounts from './ImportAccounts'
const Steps = { const Steps = {
createAccount: (props: Object) => ( createAccount: (props: Object) => (
<form onSubmit={props.onSubmit}> <form onSubmit={props.onSubmit}>
@ -69,41 +71,51 @@ const Steps = {
</div> </div>
), ),
listAccounts: (props: Object) => { listAccounts: (props: Object) => {
const accounts = [] const accounts = Object.entries(props.accounts).map(([, account]: [string, any]) => account)
const existingAccounts = accounts.filter(account => account.transactions.length > 0)
let newAccount = null // const newAccount = accounts.find(account => account.transactions.length === 0)
Object.entries(props.accounts).forEach(([, account]: [string, any]) => {
const hasTransactions = account.transactions.length > 0
if (hasTransactions) {
accounts.push(account)
} else {
newAccount = account
}
})
return ( return (
<div> <Box>
{accounts.map(account => ( <ImportAccounts {...props} accounts={existingAccounts} />
<div key={account.id} style={{ marginBottom: 10 }}> </Box>
<div>Balance: {account.balance}</div>
<div>Transactions: {account.transactions.length}</div>
<div>
<Button onClick={props.onAddAccount(account)}>Import</Button>
</div>
</div>
))}
{props.canCreateAccount && newAccount !== null ? (
<div>
<Button onClick={props.onAddAccount(newAccount)}>Create new account</Button>
</div>
) : (
<div>You cannot create new account</div>
)}
</div>
) )
}, },
// listAccounts: (props: Object) => {
// const accounts = []
//
// let newAccount = null
//
// Object.entries(props.accounts).forEach(([, account]: [string, any]) => {
// const hasTransactions = account.transactions.length > 0
//
// if (hasTransactions) {
// accounts.push(account)
// } else {
// newAccount = account
// }
// })
//
// return (
// <div>
// {accounts.map(account => (
// <div key={account.id} style={{ marginBottom: 10 }}>
// <div>Balance: {formatBTC(account.balance)}</div>
// <div>Transactions: {account.transactions.length}</div>
// <div>
// <Button onClick={props.onAddAccount(account)}>Import</Button>
// </div>
// </div>
// ))}
// {props.canCreateAccount && newAccount !== null ? (
// <div>
// <Button onClick={props.onAddAccount(newAccount)}>Create new account</Button>
// </div>
// ) : (
// <div>You cannot create new account</div>
// )}
// </div>
// )
// },
} }
type InputValue = { type InputValue = {
@ -211,6 +223,7 @@ class AddAccountModal extends PureComponent<Props, State> {
accounts, accounts,
canCreateAccount, canCreateAccount,
onAddAccount: this.handleAddAccount, onAddAccount: this.handleAddAccount,
onImportAccounts: this.handleImportAccounts,
}), }),
} }
} }
@ -237,7 +250,7 @@ class AddAccountModal extends PureComponent<Props, State> {
handleAddAccount = account => () => { handleAddAccount = account => () => {
const { inputValue } = this.state const { inputValue } = this.state
const { addAccount, closeModal } = this.props const { addAccount } = this.props
const { id, ...data } = account const { id, ...data } = account
@ -247,10 +260,22 @@ class AddAccountModal extends PureComponent<Props, State> {
type: inputValue.wallet, type: inputValue.wallet,
data, data,
}) })
}
closeModal('add-account') handleImportAccounts = accountsSelected => () => {
const { inputValue, accounts } = this.state
this.handleClose() const { addAccount } = this.props
Object.entries(accounts).forEach(([, account]: [string, any], i) => {
if (accountsSelected.includes(account.id)) {
addAccount({
id: account.id,
name: `Account ${i + 1}`,
type: inputValue.wallet,
data: account,
})
}
})
} }
handleChangeInput = (key: $Keys<InputValue>) => (value: $Values<InputValue>) => handleChangeInput = (key: $Keys<InputValue>) => (value: $Values<InputValue>) =>

41
src/components/modals/Send.js

@ -2,17 +2,11 @@
import React, { Fragment, PureComponent } from 'react' import React, { Fragment, PureComponent } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { connect } from 'react-redux'
import type { MapStateToProps } from 'react-redux'
import type { Accounts } from 'types/common'
import { getAccounts } from 'reducers/accounts'
import Button from 'components/base/Button' import Button from 'components/base/Button'
import Input from 'components/base/Input' import Input from 'components/base/Input'
import Modal, { ModalBody } from 'components/base/Modal' import Modal, { ModalBody } from 'components/base/Modal'
import Select from 'components/base/Select' import SelectAccount from 'components/SelectAccount'
const Label = styled.label` const Label = styled.label`
display: block; display: block;
@ -26,7 +20,7 @@ const Steps = {
e.preventDefault() e.preventDefault()
if ( if (
props.value.account.trim() === '' || !props.value.account ||
props.value.address.trim() === '' || props.value.address.trim() === '' ||
props.value.amount.trim() === '' props.value.amount.trim() === ''
) { ) {
@ -39,14 +33,7 @@ const Steps = {
<div>amount</div> <div>amount</div>
<div> <div>
<Label>Account to debit</Label> <Label>Account to debit</Label>
<Select <SelectAccount onChange={props.onChangeInput('account')} value={props.value.account} />
onChange={item => props.onChangeInput('account')(item.key)}
renderSelected={item => item.name}
items={Object.entries(props.accounts).map(([id, account]: [string, any]) => ({
key: id,
name: account.name,
}))}
/>
</div> </div>
<div> <div>
<Label>Recipient address</Label> <Label>Recipient address</Label>
@ -64,59 +51,49 @@ const Steps = {
<div>summary</div> <div>summary</div>
<div>{props.value.amount}</div> <div>{props.value.amount}</div>
<div>to {props.value.address}</div> <div>to {props.value.address}</div>
<div>from {props.account.name}</div> <div>from {props.value.account.name}</div>
</div> </div>
), ),
} }
type InputValue = { type InputValue = {
account: string, account: any,
address: string, address: string,
amount: string, amount: string,
} }
type Step = 'amount' | 'summary' type Step = 'amount' | 'summary'
type Props = {
accounts: Accounts,
}
type State = { type State = {
inputValue: InputValue, inputValue: InputValue,
step: Step, step: Step,
} }
const mapStateToProps: MapStateToProps<*, *, *> = state => ({
accounts: getAccounts(state),
})
const defaultState = { const defaultState = {
inputValue: { inputValue: {
account: '', account: undefined,
address: '', address: '',
amount: '', amount: '',
}, },
step: 'amount', step: 'amount',
} }
class Send extends PureComponent<Props, State> { class Send extends PureComponent<{}, State> {
state = { state = {
...defaultState, ...defaultState,
} }
getStepProps() { getStepProps() {
const { accounts } = this.props
const { inputValue, step } = this.state const { inputValue, step } = this.state
const props = (predicate, props) => (predicate ? props : {}) const props = (predicate, props) => (predicate ? props : {})
return { return {
...props(step === 'amount', { ...props(step === 'amount', {
accounts,
onChangeInput: this.handleChangeInput, onChangeInput: this.handleChangeInput,
value: inputValue, value: inputValue,
}), }),
...props(step === 'summary', { ...props(step === 'summary', {
account: accounts[inputValue.account],
value: inputValue, value: inputValue,
}), }),
onChangeStep: this.handleChangeStep, onChangeStep: this.handleChangeStep,
@ -131,7 +108,7 @@ class Send extends PureComponent<Props, State> {
}, },
})) }))
handleChangeStep = step => handleChangeStep = (step: Step) =>
this.setState({ this.setState({
step, step,
}) })
@ -163,4 +140,4 @@ class Send extends PureComponent<Props, State> {
} }
} }
export default connect(mapStateToProps)(Send) export default Send

1
src/main/app.js

@ -17,6 +17,7 @@ function createMainWindow() {
vibrancy: 'ultra-dark', // https://github.com/electron/electron/issues/10521 vibrancy: 'ultra-dark', // https://github.com/electron/electron/issues/10521
} }
: {}), : {}),
center: true,
show: true, show: true,
height: MIN_HEIGHT, height: MIN_HEIGHT,
width: MIN_WIDTH, width: MIN_WIDTH,

6
yarn.lock

@ -7322,9 +7322,9 @@ react-html-attributes@^1.3.0:
dependencies: dependencies:
html-element-attributes "^1.0.0" html-element-attributes "^1.0.0"
react-i18next@^7.3.2: react-i18next@^7.3.4:
version "7.3.2" version "7.3.4"
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-7.3.2.tgz#5036dc0371808bd8afe0c9a4a738ebd39721e33b" resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-7.3.4.tgz#d5932d47ac7f0d723eecef492ea97b7232673706"
dependencies: dependencies:
hoist-non-react-statics "2.3.1" hoist-non-react-statics "2.3.1"
html-parse-stringify2 "2.0.1" html-parse-stringify2 "2.0.1"

Loading…
Cancel
Save