From 5909f730c033f54c314c06ebe249f537c769a719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=ABck=20V=C3=A9zien?= Date: Fri, 26 Jan 2018 17:17:31 +0100 Subject: [PATCH 1/5] Add ImportAccounts component --- package.json | 2 +- src/components/SelectAccount.js | 26 ++--- src/components/base/Select/index.js | 5 +- .../modals/AddAccount/ImportAccounts.js | 73 ++++++++++++++ .../{AddAccount.js => AddAccount/index.js} | 97 ++++++++++++------- src/components/modals/Send.js | 41 ++------ src/main/app.js | 1 + yarn.lock | 6 +- 8 files changed, 159 insertions(+), 92 deletions(-) create mode 100644 src/components/modals/AddAccount/ImportAccounts.js rename src/components/modals/{AddAccount.js => AddAccount/index.js} (75%) diff --git a/package.json b/package.json index 92c60ab9..deec998d 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "raven-js": "^3.22.1", "react": "^16.2.0", "react-dom": "^16.2.0", - "react-i18next": "^7.3.2", + "react-i18next": "^7.3.4", "react-mortal": "^3.0.1", "react-motion": "^0.5.2", "react-redux": "^5.0.6", diff --git a/src/components/SelectAccount.js b/src/components/SelectAccount.js index 40e9a6c9..08957cb5 100644 --- a/src/components/SelectAccount.js +++ b/src/components/SelectAccount.js @@ -2,22 +2,16 @@ import React from 'react' import { connect } from 'react-redux' -import values from 'lodash/values' import type { MapStateToProps } from 'react-redux' import { getAccounts } from 'reducers/accounts' import Select from 'components/base/Select' -import Text from 'components/base/Text' import type { Account } from 'types/common' -function renderItem(accounts) { - return item => {(accounts.find(a => a.id === item) || {}).name} -} - const mapStateToProps: MapStateToProps<*, *, *> = state => ({ - accounts: values(getAccounts(state)), + accounts: Object.entries(getAccounts(state)).map(([, account]: [string, any]) => account), }) type Props = { @@ -28,18 +22,18 @@ type Props = { const SelectAccount = ({ accounts, value, onChange }: Props) => ( props.onChangeInput('account')(item.key)} - renderSelected={item => item.name} - items={Object.entries(props.accounts).map(([id, account]: [string, any]) => ({ - key: id, - name: account.name, - }))} - /> +
@@ -64,59 +51,49 @@ const Steps = {
summary
{props.value.amount}
to {props.value.address}
-
from {props.account.name}
+
from {props.value.account.name}
), } type InputValue = { - account: string, + account: any, address: string, amount: string, } type Step = 'amount' | 'summary' -type Props = { - accounts: Accounts, -} type State = { inputValue: InputValue, step: Step, } -const mapStateToProps: MapStateToProps<*, *, *> = state => ({ - accounts: getAccounts(state), -}) - const defaultState = { inputValue: { - account: '', + account: undefined, address: '', amount: '', }, step: 'amount', } -class Send extends PureComponent { +class Send extends PureComponent<{}, State> { state = { ...defaultState, } getStepProps() { - const { accounts } = this.props const { inputValue, step } = this.state const props = (predicate, props) => (predicate ? props : {}) return { ...props(step === 'amount', { - accounts, onChangeInput: this.handleChangeInput, value: inputValue, }), ...props(step === 'summary', { - account: accounts[inputValue.account], value: inputValue, }), onChangeStep: this.handleChangeStep, @@ -131,7 +108,7 @@ class Send extends PureComponent { }, })) - handleChangeStep = step => + handleChangeStep = (step: Step) => this.setState({ step, }) @@ -163,4 +140,4 @@ class Send extends PureComponent { } } -export default connect(mapStateToProps)(Send) +export default Send diff --git a/src/main/app.js b/src/main/app.js index f182d09c..c98d98ae 100644 --- a/src/main/app.js +++ b/src/main/app.js @@ -17,6 +17,7 @@ function createMainWindow() { vibrancy: 'ultra-dark', // https://github.com/electron/electron/issues/10521 } : {}), + center: true, show: true, height: MIN_HEIGHT, width: MIN_WIDTH, diff --git a/yarn.lock b/yarn.lock index af50b281..2db86db9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7322,9 +7322,9 @@ react-html-attributes@^1.3.0: dependencies: html-element-attributes "^1.0.0" -react-i18next@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-7.3.2.tgz#5036dc0371808bd8afe0c9a4a738ebd39721e33b" +react-i18next@^7.3.4: + version "7.3.4" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-7.3.4.tgz#d5932d47ac7f0d723eecef492ea97b7232673706" dependencies: hoist-non-react-statics "2.3.1" html-parse-stringify2 "2.0.1" From 455ce114a62a1c7d3864013153d58ea421b61b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=ABck=20V=C3=A9zien?= Date: Mon, 29 Jan 2018 11:29:14 +0100 Subject: [PATCH 2/5] Create Checkbox component, add Import for multiple accounts --- package.json | 21 ++- src/components/ReceiveBox.js | 2 +- src/components/SideBar/index.js | 2 +- src/components/base/Checkbox/index.js | 93 +++++++++++ src/components/base/Checkbox/stories.js | 9 ++ src/components/base/Icon.js | 6 +- src/components/base/Modal/index.js | 3 +- src/components/base/Select/index.js | 2 +- .../modals/AddAccount/ImportAccounts.js | 75 +++++++-- src/components/modals/AddAccount/index.js | 22 ++- src/renderer/head.js | 8 - src/renderer/index.js | 1 - src/styles/global.js | 5 +- static/i18n/en/translation.yml | 6 +- static/i18n/fr/translation.yml | 6 +- yarn.lock | 144 +++++++++++------- 16 files changed, 294 insertions(+), 111 deletions(-) create mode 100644 src/components/base/Checkbox/index.js create mode 100644 src/components/base/Checkbox/stories.js delete mode 100644 src/renderer/head.js diff --git a/package.json b/package.json index deec998d..f40856df 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,11 @@ "webpack-sources": "1.0.1" }, "dependencies": { + "@fortawesome/fontawesome": "^1.1.3", + "@fortawesome/fontawesome-free-brands": "^5.0.6", + "@fortawesome/fontawesome-free-regular": "^5.0.6", + "@fortawesome/fontawesome-free-solid": "^5.0.6", + "@fortawesome/react-fontawesome": "^0.0.17", "@ledgerhq/common": "2.0.5", "@ledgerhq/hw-app-btc": "^2.1.0", "@ledgerhq/hw-app-eth": "^2.1.0", @@ -50,7 +55,7 @@ "bs58check": "^2.1.1", "color": "^3.0.0", "cross-env": "^5.1.3", - "downshift": "^1.25.0", + "downshift": "^1.26.0", "electron-store": "^1.3.0", "electron-updater": "^2.20.1", "fuse.js": "^3.2.0", @@ -81,12 +86,12 @@ "styled-system": "^1.1.1" }, "devDependencies": { - "@storybook/addon-actions": "^3.3.10", - "@storybook/addon-knobs": "^3.3.10", - "@storybook/addon-links": "^3.3.10", - "@storybook/addon-options": "^3.3.10", - "@storybook/addons": "^3.3.10", - "@storybook/react": "^3.3.10", + "@storybook/addon-actions": "^3.3.11", + "@storybook/addon-knobs": "^3.3.11", + "@storybook/addon-links": "^3.3.11", + "@storybook/addon-options": "^3.3.11", + "@storybook/addons": "^3.3.11", + "@storybook/react": "^3.3.11", "babel-core": "^6.26.0", "babel-eslint": "^8.2.1", "babel-loader": "^7.1.2", @@ -108,7 +113,7 @@ "eslint-plugin-flowtype": "^2.42.0", "eslint-plugin-import": "^2.8.0", "eslint-plugin-jsx-a11y": "^6.0.3", - "eslint-plugin-react": "^7.6.0", + "eslint-plugin-react": "^7.6.1", "flow-bin": "^0.64.0", "flow-typed": "^2.2.3", "husky": "^0.14.3", diff --git a/src/components/ReceiveBox.js b/src/components/ReceiveBox.js index 7e708658..9e81c88c 100644 --- a/src/components/ReceiveBox.js +++ b/src/components/ReceiveBox.js @@ -65,7 +65,7 @@ const ReceiveBox = ({ address }: Props) => ( {'Print'} - + {'Share'} diff --git a/src/components/SideBar/index.js b/src/components/SideBar/index.js index d9c721b1..c2ee7ff6 100644 --- a/src/components/SideBar/index.js +++ b/src/components/SideBar/index.js @@ -70,7 +70,7 @@ class SideBar extends PureComponent { {t('sidebar.menu')}
- + {t('dashboard.title')} diff --git a/src/components/base/Checkbox/index.js b/src/components/base/Checkbox/index.js new file mode 100644 index 00000000..a0ec9526 --- /dev/null +++ b/src/components/base/Checkbox/index.js @@ -0,0 +1,93 @@ +// @flow + +import React, { PureComponent } from 'react' +import styled from 'styled-components' + +import Box from 'components/base/Box' +import Icon from 'components/base/Icon' + +const Base = styled(Box).attrs({ + align: 'center', + justify: 'center', + relative: true, +})` + background-color: ${p => (p.checked ? p.theme.colors.blue : p.theme.colors.white)}; + box-shadow: 0 0 0 ${p => (p.checked ? 4 : 1)}px + ${p => (p.checked ? p.theme.colors.cream : p.theme.colors.argile)}; + border-radius: 50%; + font-size: 7px; + + height: 19px; + width: 19px; + transition: all ease-in-out 0.1s; + + input[type='checkbox'] { + bottom: 0; + cursor: pointer; + height: 100%; + left: 0; + opacity: 0; + position: absolute; + right: 0; + top: 0; + width: 100%; + z-index: 10; + } + + > span { + position: relative; + top: 1px; + opacity: ${p => (p.checked ? 1 : 0)}; + transition: all ease-in-out 0.1s; + } +` + +type Props = { + checked?: boolean, + onChange?: Function, +} + +type State = { + checked: boolean, +} + +class Checkbox extends PureComponent { + state = { + checked: this.props.checked || false, + } + + componentWillReceiveProps(nextProps: Props) { + if (nextProps.checked) { + this.setState({ + checked: nextProps.checked, + }) + } + } + + handleChange = (e: SyntheticInputEvent) => { + const { onChange } = this.props + const { checked } = e.target + + this.setState({ + checked, + }) + + if (onChange) { + onChange(checked) + } + } + + render() { + const { checked } = this.state + const { onChange, ...props } = this.props + + return ( + + + + + ) + } +} + +export default Checkbox diff --git a/src/components/base/Checkbox/stories.js b/src/components/base/Checkbox/stories.js new file mode 100644 index 00000000..34222a4b --- /dev/null +++ b/src/components/base/Checkbox/stories.js @@ -0,0 +1,9 @@ +import React from 'react' +import { storiesOf } from '@storybook/react' +import { boolean } from '@storybook/addon-knobs' + +import Checkbox from 'components/base/Checkbox' + +const stories = storiesOf('Checkbox', module) + +stories.add('basic', () => ) diff --git a/src/components/base/Icon.js b/src/components/base/Icon.js index 6d441189..858e33c2 100644 --- a/src/components/base/Icon.js +++ b/src/components/base/Icon.js @@ -3,15 +3,15 @@ import React from 'react' import styled from 'styled-components' import { fontSize, color } from 'styled-system' +import FontAwesomeIcon from '@fortawesome/react-fontawesome' -const Container = styled.div` +const Container = styled.span` ${fontSize}; ${color}; - line-height: 1; ` export default ({ name, ...props }: { name: string }) => ( - + ) diff --git a/src/components/base/Modal/index.js b/src/components/base/Modal/index.js index a4ee6a87..3e0ca236 100644 --- a/src/components/base/Modal/index.js +++ b/src/components/base/Modal/index.js @@ -50,7 +50,7 @@ const Container = styled(Box).attrs({ pointerEvents: p.isVisible ? 'auto' : 'none', }), })` - overflow: hidden; + overflow: scroll; position: fixed; z-index: 20; ` @@ -69,6 +69,7 @@ const Wrapper = styled(Box).attrs({ bg: 'transparent', flow: 20, mt: 100, + mb: 100, style: p => ({ opacity: p.op, transform: `translate3d(0, ${p.offset}px, 0)`, diff --git a/src/components/base/Select/index.js b/src/components/base/Select/index.js index d595d98e..50bf06a6 100644 --- a/src/components/base/Select/index.js +++ b/src/components/base/Select/index.js @@ -91,7 +91,7 @@ const FloatingTriangles = styled(Box).attrs({ class Select extends PureComponent { static defaultProps = { - itemToString: (item: Object) => item.name, + itemToString: (item: Object) => item && item.name, keyProp: undefined, } diff --git a/src/components/modals/AddAccount/ImportAccounts.js b/src/components/modals/AddAccount/ImportAccounts.js index 289cc8df..493ac968 100644 --- a/src/components/modals/AddAccount/ImportAccounts.js +++ b/src/components/modals/AddAccount/ImportAccounts.js @@ -1,24 +1,40 @@ // @flow import React, { PureComponent } from 'react' +import { translate } from 'react-i18next' + +import type { T } from 'types/common' import { formatBTC } from 'helpers/format' import Box from 'components/base/Box' import Button from 'components/base/Button' +import Checkbox from 'components/base/Checkbox' +import Input from 'components/base/Input' type Props = { + t: T, accounts: Array, onImportAccounts: Function, } type State = { accountsSelected: Array, + accountsName: Object, } class ImportAccounts extends PureComponent { state = { accountsSelected: [], + accountsName: this.props.accounts.reduce((result, value, index) => { + result[value.id] = { + placeholder: this.props.t(`addAccount.import.placeholder`, { + index: index + 1, + }), + } + + return result + }, {}), } handleSelectAccount = (id: string, selected: boolean) => () => @@ -28,9 +44,32 @@ class ImportAccounts extends PureComponent { : [...prev.accountsSelected, id], })) - render() { + handleChangeInput = (id: string) => (value: string) => + this.setState(prev => ({ + accountsName: { + ...prev.accountsName, + [id]: { + ...prev.accountsName[id], + value, + }, + }, + })) + + handleImportAccounts = () => { const { accounts, onImportAccounts } = this.props - const { accountsSelected } = this.state + const { accountsSelected, accountsName } = this.state + + const importAccounts = accountsSelected.map(id => ({ + ...accounts.find(a => a.id === id), + name: accountsName[id].value || accountsName[id].placeholder, + })) + + onImportAccounts(importAccounts) + } + + render() { + const { accounts } = this.props + const { accountsSelected, accountsName } = this.state const canImportAccounts = accountsSelected.length > 0 @@ -40,15 +79,25 @@ class ImportAccounts extends PureComponent { {accounts.map(account => { const selected = accountsSelected.includes(account.id) + const accountName = accountsName[account.id] return ( - - {selected ? 'yes' : 'no'} + + + + + + + Balance: {formatBTC(account.balance)} Transactions: {account.transactions.length} @@ -57,11 +106,7 @@ class ImportAccounts extends PureComponent { })} - @@ -70,4 +115,4 @@ class ImportAccounts extends PureComponent { } } -export default ImportAccounts +export default translate()(ImportAccounts) diff --git a/src/components/modals/AddAccount/index.js b/src/components/modals/AddAccount/index.js index 96275f38..5e8e879c 100644 --- a/src/components/modals/AddAccount/index.js +++ b/src/components/modals/AddAccount/index.js @@ -262,20 +262,18 @@ class AddAccountModal extends PureComponent { }) } - handleImportAccounts = accountsSelected => () => { - const { inputValue, accounts } = this.state + handleImportAccounts = accountsSelected => { + const { inputValue } = this.state 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, - }) - } - }) + accountsSelected.forEach(({ id, name, ...account }) => + addAccount({ + id, + name, + type: inputValue.wallet, + data: account, + }), + ) } handleChangeInput = (key: $Keys) => (value: $Values) => diff --git a/src/renderer/head.js b/src/renderer/head.js deleted file mode 100644 index f1ff7bf7..00000000 --- a/src/renderer/head.js +++ /dev/null @@ -1,8 +0,0 @@ -const list = ['https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css'] - -list.forEach(href => { - const tag = document.createElement('link') - tag.setAttribute('rel', 'stylesheet') - tag.setAttribute('href', href) - document.head.appendChild(tag) -}) diff --git a/src/renderer/index.js b/src/renderer/index.js index 20da31e8..eb26a1a0 100644 --- a/src/renderer/index.js +++ b/src/renderer/index.js @@ -17,7 +17,6 @@ import { getLanguage } from 'reducers/settings' import App from 'components/App' import 'styles/global' -import 'renderer/head' if (__PROD__ && __SENTRY_URL__) { Raven.config(__SENTRY_URL__, { allowSecretKey: true }).install() diff --git a/src/styles/global.js b/src/styles/global.js index 3aa3891d..7f15327a 100644 --- a/src/styles/global.js +++ b/src/styles/global.js @@ -1,8 +1,11 @@ // @flow +/* eslint-disable no-unused-expressions */ + import { injectGlobal } from 'styled-components' +import '@fortawesome/fontawesome-free-solid' +import '@fortawesome/fontawesome-free-regular' -/* eslint-disable no-unused-expressions */ injectGlobal` * { box-sizing: border-box; diff --git a/static/i18n/en/translation.yml b/static/i18n/en/translation.yml index 58ca606a..6beace79 100644 --- a/static/i18n/en/translation.yml +++ b/static/i18n/en/translation.yml @@ -1,9 +1,6 @@ common: ok: Okay cancel: Cancel - connectedDevices: You have {{count}} device connected - connectedDevices_0: You don't have device connected - connectedDevices_plural: You have {{count}} devices connected language: en: English @@ -26,6 +23,9 @@ receive: addAccount: title: Add account + import: + placeholder: Account {{index}} + settings: title: Settings diff --git a/static/i18n/fr/translation.yml b/static/i18n/fr/translation.yml index 1b7db075..b46f4439 100644 --- a/static/i18n/fr/translation.yml +++ b/static/i18n/fr/translation.yml @@ -1,9 +1,6 @@ common: ok: Okay cancel: Annuler - connectedDevices: You have {{count}} device connected - connectedDevices_0: You don't have device connected - connectedDevices_plural: You have {{count}} devices connected language: en: Anglais @@ -26,6 +23,9 @@ receive: addAccount: title: Ajouter un compte + import: + placeholder: Compte {{index}} + settings: title: Réglages diff --git a/yarn.lock b/yarn.lock index 2db86db9..9818d244 100644 --- a/yarn.lock +++ b/yarn.lock @@ -78,6 +78,40 @@ lodash "^4.2.0" to-fast-properties "^2.0.0" +"@fortawesome/fontawesome-common-types@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.1.2.tgz#d6aa075058f0c984d6e2ebcbc0052c1f7f9bea72" + +"@fortawesome/fontawesome-free-brands@^5.0.6": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free-brands/-/fontawesome-free-brands-5.0.6.tgz#fee054ce0c4d74019020f6353ca85cfb408de719" + dependencies: + "@fortawesome/fontawesome-common-types" "^0.1.2" + +"@fortawesome/fontawesome-free-regular@^5.0.6": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free-regular/-/fontawesome-free-regular-5.0.6.tgz#fafc624025a247c1a1bbb5080b9902a490cd79f5" + dependencies: + "@fortawesome/fontawesome-common-types" "^0.1.2" + +"@fortawesome/fontawesome-free-solid@^5.0.6": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free-solid/-/fontawesome-free-solid-5.0.6.tgz#6bb5acdd081b03ab25b7684f7089b37ed3d20740" + dependencies: + "@fortawesome/fontawesome-common-types" "^0.1.2" + +"@fortawesome/fontawesome@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome/-/fontawesome-1.1.3.tgz#7a4844345cbc7fb238f5f1788af73bd302ee9b80" + dependencies: + "@fortawesome/fontawesome-common-types" "^0.1.2" + +"@fortawesome/react-fontawesome@^0.0.17": + version "0.0.17" + resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.0.17.tgz#69abd135523187044f533cadc5458f829d43961f" + dependencies: + humps "^2.0.1" + "@ledgerhq/common@2.0.5": version "2.0.5" resolved "https://registry.yarnpkg.com/@ledgerhq/common/-/common-2.0.5.tgz#5f5eca4ac907914d700540c20b3d733cd7a25a93" @@ -118,9 +152,9 @@ dependencies: events "^1.1.1" -"@storybook/addon-actions@^3.3.10": - version "3.3.10" - resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-3.3.10.tgz#f3e4b538d8260364c55a3ba1e301a2fab9d8d3f2" +"@storybook/addon-actions@^3.3.11": + version "3.3.11" + resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-3.3.11.tgz#158a64f01c97fcf6922e7a370c6519d216544bcd" dependencies: deep-equal "^1.0.1" global "^4.3.2" @@ -129,9 +163,9 @@ react-inspector "^2.2.2" uuid "^3.1.0" -"@storybook/addon-knobs@^3.3.10": - version "3.3.10" - resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-3.3.10.tgz#25f32cd3d32a1667dc9d8ae484ddfd6223fcffef" +"@storybook/addon-knobs@^3.3.11": + version "3.3.11" + resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-3.3.11.tgz#ab53a627f9517d922e1a1f6b874bd76ae2fc3b08" dependencies: babel-runtime "^6.26.0" deep-equal "^1.0.1" @@ -145,41 +179,41 @@ react-textarea-autosize "^5.2.1" util-deprecate "^1.0.2" -"@storybook/addon-links@^3.3.10": - version "3.3.10" - resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-3.3.10.tgz#4e6c1a0b0bf5b18101bc5001b858b33202ae8209" +"@storybook/addon-links@^3.3.11": + version "3.3.11" + resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-3.3.11.tgz#7bc57baddd1502153ee94cf11fcb88d49131b211" dependencies: - "@storybook/components" "^3.3.10" + "@storybook/components" "^3.3.11" global "^4.3.2" prop-types "^15.5.10" -"@storybook/addon-options@^3.3.10": - version "3.3.10" - resolved "https://registry.yarnpkg.com/@storybook/addon-options/-/addon-options-3.3.10.tgz#536796b6223616a4a8b3c2851c7efbe66036bc8a" +"@storybook/addon-options@^3.3.11": + version "3.3.11" + resolved "https://registry.yarnpkg.com/@storybook/addon-options/-/addon-options-3.3.11.tgz#2e4a5fd9b4a5875104aed232dff0f7f257a9611b" -"@storybook/addons@^3.3.10": - version "3.3.10" - resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-3.3.10.tgz#8753007d872013d2376ba71b14396eef3159673b" +"@storybook/addons@^3.3.11": + version "3.3.11" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-3.3.11.tgz#7f85136d6da785160658aee512fd3cac99780f42" -"@storybook/channel-postmessage@^3.3.10": - version "3.3.10" - resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-3.3.10.tgz#4f22b5a665d3c95eb61cf41bbb06872009ace7b5" +"@storybook/channel-postmessage@^3.3.11": + version "3.3.11" + resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-3.3.11.tgz#a379f96f7819ba3752bb471ebf90ad07c3fc28ea" dependencies: - "@storybook/channels" "^3.3.10" + "@storybook/channels" "^3.3.11" global "^4.3.2" json-stringify-safe "^5.0.1" -"@storybook/channels@^3.3.10": - version "3.3.10" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-3.3.10.tgz#0b15d47c2ea0cb1c7b735955d74e9d3ca99cdc42" +"@storybook/channels@^3.3.11": + version "3.3.11" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-3.3.11.tgz#569f1c7c364aeb076df78eb829c58f9c9f0a3936" -"@storybook/client-logger@^3.3.10": - version "3.3.10" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-3.3.10.tgz#6f8b85c3dfad229794fee88f930df59b163ee144" +"@storybook/client-logger@^3.3.11": + version "3.3.11" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-3.3.11.tgz#35c851dbed2067201189847c7aa92f8d567a4d61" -"@storybook/components@^3.3.10": - version "3.3.10" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-3.3.10.tgz#f213a129ed49de33cdaf116da2c2b662b8eb3ea0" +"@storybook/components@^3.3.11": + version "3.3.11" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-3.3.11.tgz#cb2a48b52e7cb45408172f4462f4730ca6970e78" dependencies: glamor "^2.20.40" glamorous "^4.11.2" @@ -193,9 +227,9 @@ "@storybook/react-simple-di" "^1.2.1" babel-runtime "6.x.x" -"@storybook/node-logger@^3.3.10": - version "3.3.10" - resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-3.3.10.tgz#d9c09a622713ec4726cdd292e798aa98c0503c15" +"@storybook/node-logger@^3.3.11": + version "3.3.11" + resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-3.3.11.tgz#e459cbf8da75e2671a08de4f6dfe32b556b20af6" dependencies: chalk "^2.3.0" npmlog "^4.1.2" @@ -225,17 +259,17 @@ dependencies: babel-runtime "^6.5.0" -"@storybook/react@^3.3.10": - version "3.3.10" - resolved "https://registry.yarnpkg.com/@storybook/react/-/react-3.3.10.tgz#a55f8f804f3f01d76f1b7e8675e818ee4c107324" - dependencies: - "@storybook/addon-actions" "^3.3.10" - "@storybook/addon-links" "^3.3.10" - "@storybook/addons" "^3.3.10" - "@storybook/channel-postmessage" "^3.3.10" - "@storybook/client-logger" "^3.3.10" - "@storybook/node-logger" "^3.3.10" - "@storybook/ui" "^3.3.10" +"@storybook/react@^3.3.11": + version "3.3.11" + resolved "https://registry.yarnpkg.com/@storybook/react/-/react-3.3.11.tgz#5438d40aa095dd7b0c2f4e8e51a83fd5151df0c1" + dependencies: + "@storybook/addon-actions" "^3.3.11" + "@storybook/addon-links" "^3.3.11" + "@storybook/addons" "^3.3.11" + "@storybook/channel-postmessage" "^3.3.11" + "@storybook/client-logger" "^3.3.11" + "@storybook/node-logger" "^3.3.11" + "@storybook/ui" "^3.3.11" airbnb-js-shims "^1.4.0" autoprefixer "^7.2.3" babel-loader "^7.1.2" @@ -287,11 +321,11 @@ webpack-dev-middleware "^1.12.2" webpack-hot-middleware "^2.21.0" -"@storybook/ui@^3.3.10": - version "3.3.10" - resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-3.3.10.tgz#99a83b988b01cde1df61b87a58227a50ed196dd1" +"@storybook/ui@^3.3.11": + version "3.3.11" + resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-3.3.11.tgz#df500b97739da484d51d6a1bcb52ce3866ad2148" dependencies: - "@storybook/components" "^3.3.10" + "@storybook/components" "^3.3.11" "@storybook/mantra-core" "^1.7.2" "@storybook/react-komposer" "^2.0.3" babel-runtime "^6.26.0" @@ -3126,9 +3160,9 @@ dotenv@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-4.0.0.tgz#864ef1379aced55ce6f95debecdce179f7a0cd1d" -downshift@^1.25.0: - version "1.25.0" - resolved "https://registry.yarnpkg.com/downshift/-/downshift-1.25.0.tgz#7f6e2dda4aa5ddbb2932401bd61e7b741e92c02e" +downshift@^1.26.0: + version "1.26.0" + resolved "https://registry.yarnpkg.com/downshift/-/downshift-1.26.0.tgz#1ee954fef129861f977c6b9effe93fb78e7dc363" duplexer3@^0.1.4: version "0.1.4" @@ -3602,9 +3636,9 @@ eslint-plugin-jsx-a11y@^6.0.3: emoji-regex "^6.1.0" jsx-ast-utils "^2.0.0" -eslint-plugin-react@^7.6.0: - version "7.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.6.0.tgz#351651188c74c5b2fecc2717e3936b7207baa728" +eslint-plugin-react@^7.6.1: + version "7.6.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.6.1.tgz#5d0e908be599f0c02fbf4eef0c7ed6f29dff7633" dependencies: doctrine "^2.0.2" has "^1.0.1" @@ -4758,6 +4792,10 @@ https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" +humps@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/humps/-/humps-2.0.1.tgz#dd02ea6081bd0568dc5d073184463957ba9ef9aa" + husky@^0.14.3: version "0.14.3" resolved "https://registry.yarnpkg.com/husky/-/husky-0.14.3.tgz#c69ed74e2d2779769a17ba8399b54ce0b63c12c3" From 1537bd9eb8b23cbbbb01f1af67f1600e45063852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=ABck=20V=C3=A9zien?= Date: Mon, 29 Jan 2018 14:08:12 +0100 Subject: [PATCH 3/5] Change flow for create new account --- package.json | 4 +- src/components/AccountPage.js | 2 +- .../modals/AddAccount/CreateAccount.js | 69 ++++++++++ .../modals/AddAccount/ImportAccounts.js | 66 +++++----- src/components/modals/AddAccount/index.js | 123 ++++++------------ yarn.lock | 11 +- 6 files changed, 153 insertions(+), 122 deletions(-) create mode 100644 src/components/modals/AddAccount/CreateAccount.js diff --git a/package.json b/package.json index f40856df..4279ca9a 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "redux-thunk": "^2.2.0", "shortid": "^2.2.8", "source-map-support": "^0.5.3", - "styled-components": "^3.0.2", + "styled-components": "^3.1.1", "styled-system": "^1.1.1" }, "devDependencies": { @@ -120,7 +120,7 @@ "lint-staged": "^6.1.0", "node-loader": "^0.6.0", "prettier": "^1.10.2", - "react-hot-loader": "^4.0.0-beta.17", + "react-hot-loader": "^4.0.0-beta.18", "webpack": "^3.10.0" } } diff --git a/src/components/AccountPage.js b/src/components/AccountPage.js index 0ace4d77..5de58ea0 100644 --- a/src/components/AccountPage.js +++ b/src/components/AccountPage.js @@ -39,7 +39,7 @@ class AccountPage extends PureComponent { - {formatBTC(accountData.balance)} + {formatBTC(accountData.balance)} diff --git a/src/components/modals/AddAccount/CreateAccount.js b/src/components/modals/AddAccount/CreateAccount.js new file mode 100644 index 00000000..1cfe40c6 --- /dev/null +++ b/src/components/modals/AddAccount/CreateAccount.js @@ -0,0 +1,69 @@ +// @flow + +import React, { PureComponent } from 'react' + +import Box from 'components/base/Box' +import Button from 'components/base/Button' +import Input from 'components/base/Input' +import Label from 'components/base/Label' + +type Props = { + account: Object, + onAddAccount: Function, +} + +type State = { + accountName: string, +} + +class CreateAccount extends PureComponent { + state = { + accountName: '', + } + + handleCreateAccount = (e: SyntheticEvent) => { + e.preventDefault() + + const { accountName } = this.state + const { onAddAccount, account } = this.props + + if (accountName.trim() === '') { + return + } + + onAddAccount({ + ...account, + name: accountName, + }) + } + + handleChangeInput = (value: string) => + this.setState({ + accountName: value, + }) + + render() { + const { accountName } = this.state + + return ( + + Create Account +
+ + + + + + + + + +
+
+ ) + } +} + +export default CreateAccount diff --git a/src/components/modals/AddAccount/ImportAccounts.js b/src/components/modals/AddAccount/ImportAccounts.js index 493ac968..f6bbc805 100644 --- a/src/components/modals/AddAccount/ImportAccounts.js +++ b/src/components/modals/AddAccount/ImportAccounts.js @@ -55,7 +55,9 @@ class ImportAccounts extends PureComponent { }, })) - handleImportAccounts = () => { + handleImportAccounts = (e: SyntheticEvent) => { + e.preventDefault() + const { accounts, onImportAccounts } = this.props const { accountsSelected, accountsName } = this.state @@ -76,40 +78,42 @@ class ImportAccounts extends PureComponent { return ( Import Accounts - - {accounts.map(account => { - const selected = accountsSelected.includes(account.id) - const accountName = accountsName[account.id] - return ( - - - - - +
+ + {accounts.map(account => { + const selected = accountsSelected.includes(account.id) + const accountName = accountsName[account.id] + return ( + - - Balance: {formatBTC(account.balance)} - Transactions: {account.transactions.length} + + + + + Balance: {formatBTC(account.balance)} + Transactions: {account.transactions.length} + - - ) - })} - - - - + ) + })} + + + + +
) } diff --git a/src/components/modals/AddAccount/index.js b/src/components/modals/AddAccount/index.js index 5e8e879c..0b5e008e 100644 --- a/src/components/modals/AddAccount/index.js +++ b/src/components/modals/AddAccount/index.js @@ -17,15 +17,15 @@ import { addAccount } from 'actions/accounts' import Box from 'components/base/Box' import Text from 'components/base/Text' import Button from 'components/base/Button' -import Input from 'components/base/Input' import Label from 'components/base/Label' import Modal, { ModalBody } from 'components/base/Modal' import Select from 'components/base/Select' +import CreateAccount from './CreateAccount' import ImportAccounts from './ImportAccounts' const Steps = { - createAccount: (props: Object) => ( + chooseWallet: (props: Object) => (
@@ -42,10 +42,6 @@ const Steps = { ]} /> - - - - - // - // - // ))} - // {props.canCreateAccount && newAccount !== null ? ( - //
- // - //
- // ) : ( - //
You cannot create new account
- // )} - // - // ) - // }, } type InputValue = { - accountName: string, wallet: string, } -type Step = 'createAccount' | 'connectDevice' | 'inProgress' | 'listAccounts' +type Step = 'chooseWallet' | 'connectDevice' | 'inProgress' | 'listAccounts' type Props = { accounts: Accounts, @@ -152,12 +118,11 @@ const mapDispatchToProps = { const defaultState = { inputValue: { - accountName: '', wallet: '', }, accounts: {}, progress: null, - step: 'createAccount', + step: 'chooseWallet', } class AddAccountModal extends PureComponent { @@ -207,7 +172,7 @@ class AddAccountModal extends PureComponent { const props = (predicate, props) => (predicate ? props : {}) return { - ...props(step === 'createAccount', { + ...props(step === 'chooseWallet', { value: inputValue, onSubmit: this.handleSubmit, onChangeInput: this.handleChangeInput, @@ -248,33 +213,9 @@ class AddAccountModal extends PureComponent { } } - handleAddAccount = account => () => { - const { inputValue } = this.state - const { addAccount } = this.props - - const { id, ...data } = account - - addAccount({ - id, - name: inputValue.accountName, - type: inputValue.wallet, - data, - }) - } - - handleImportAccounts = accountsSelected => { - const { inputValue } = this.state - const { addAccount } = this.props + handleAddAccount = account => this.addAccount(account) - accountsSelected.forEach(({ id, name, ...account }) => - addAccount({ - id, - name, - type: inputValue.wallet, - data: account, - }), - ) - } + handleImportAccounts = accounts => accounts.forEach(account => this.addAccount(account)) handleChangeInput = (key: $Keys) => (value: $Values) => this.setState(prev => ({ @@ -289,7 +230,7 @@ class AddAccountModal extends PureComponent { const { inputValue } = this.state - if (inputValue.accountName.trim() === '' || inputValue.wallet.trim() === '') { + if (inputValue.wallet.trim() === '') { return } @@ -305,6 +246,18 @@ class AddAccountModal extends PureComponent { }) } + addAccount = ({ id, name, ...data }) => { + const { inputValue } = this.state + const { addAccount } = this.props + + addAccount({ + id, + name, + type: inputValue.wallet, + data, + }) + } + _timeout = undefined render() { @@ -315,7 +268,7 @@ class AddAccountModal extends PureComponent { return ( ( diff --git a/yarn.lock b/yarn.lock index 9818d244..e8e5d2ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8571,9 +8571,9 @@ style-loader@^0.19.0, style-loader@^0.19.1: loader-utils "^1.0.2" schema-utils "^0.3.0" -styled-components@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-3.0.2.tgz#dbcd66ee84d444ee4332a7f74027e8a675191593" +styled-components@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-3.1.1.tgz#7896819070b2663c6519f428017d6ca7e2a3c7cd" dependencies: buffer "^5.0.3" css-to-react-native "^2.0.3" @@ -8582,6 +8582,7 @@ styled-components@^3.0.2: is-plain-object "^2.0.1" prop-types "^15.5.4" stylis "^3.4.0" + stylis-rule-sheet "^0.0.7" supports-color "^3.2.3" styled-system@^1.1.1: @@ -8590,6 +8591,10 @@ styled-system@^1.1.1: dependencies: prop-types "^15.6.0" +stylis-rule-sheet@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.7.tgz#5c51dc879141a61821c2094ba91d2cbcf2469c6c" + stylis@^3.4.0: version "3.4.8" resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.4.8.tgz#94380babbcd4c75726215794ca985b38ec96d1a3" From 4e2f72ff1cae12093128e70f9287fff64d10726a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=ABck=20V=C3=A9zien?= Date: Mon, 29 Jan 2018 14:34:11 +0100 Subject: [PATCH 4/5] Clean import accounts --- src/components/modals/AddAccount/index.js | 13 +++++++++++++ src/internals/usb/wallet/accounts.js | 2 +- src/internals/usb/wallet/index.js | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/components/modals/AddAccount/index.js b/src/components/modals/AddAccount/index.js index 0b5e008e..dda994d4 100644 --- a/src/components/modals/AddAccount/index.js +++ b/src/components/modals/AddAccount/index.js @@ -134,6 +134,19 @@ class AddAccountModal extends PureComponent { ipcRenderer.on('msg', this.handleWalletRequest) } + componentWillReceiveProps(nextProps) { + if (nextProps.accounts) { + this.setState(prev => ({ + accounts: Object.keys(prev.accounts).reduce((result, value) => { + if (!nextProps.accounts[value]) { + result[value] = prev.accounts[value] + } + return result + }, {}), + })) + } + } + componentDidUpdate() { const { step } = this.state const { currentDevice } = this.props diff --git a/src/internals/usb/wallet/accounts.js b/src/internals/usb/wallet/accounts.js index 620fce5b..5513381e 100644 --- a/src/internals/usb/wallet/accounts.js +++ b/src/internals/usb/wallet/accounts.js @@ -122,7 +122,7 @@ export default async ({ const hasTransactions = account.transactions.length > 0 - accounts[currentAccount] = { + accounts[xpub58] = { id: xpub58, ...account, } diff --git a/src/internals/usb/wallet/index.js b/src/internals/usb/wallet/index.js index f00ab756..3e79c0b1 100644 --- a/src/internals/usb/wallet/index.js +++ b/src/internals/usb/wallet/index.js @@ -31,6 +31,7 @@ export default (sendEvent: Function) => ({ currentAccounts, onProgress: progress => sendEvent('wallet.getAccounts.progress', progress, { kill: false }), }) + sendEvent('wallet.getAccounts.success', data) } catch (err) { sendEvent('wallet.getAccounts.fail', err.stack || err) From 3ffa72ea916611352d77ffbebc941198c71ecef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=ABck=20V=C3=A9zien?= Date: Mon, 29 Jan 2018 14:45:48 +0100 Subject: [PATCH 5/5] Add icon in Storybook --- .eslintrc | 5 +-- package.json | 1 - .../base/{Icon.js => Icon/index.js} | 2 +- src/components/base/Icon/stories.js | 36 +++++++++++++++++++ yarn.lock | 20 ++++------- 5 files changed, 47 insertions(+), 17 deletions(-) rename src/components/base/{Icon.js => Icon/index.js} (88%) create mode 100644 src/components/base/Icon/stories.js diff --git a/.eslintrc b/.eslintrc index 86f3e0cd..90a81046 100644 --- a/.eslintrc +++ b/.eslintrc @@ -13,8 +13,8 @@ "rules": { "camelcase": 0, "import/no-extraneous-dependencies": 0, - "import/prefer-default-export": 0, "import/no-named-as-default": 0, + "import/prefer-default-export": 0, "jsx-a11y/anchor-is-valid": 0, "jsx-a11y/label-has-for": 0, "new-cap": 0, @@ -28,6 +28,7 @@ "react/forbid-prop-types": 0, "react/jsx-curly-brace-presence": 0, "react/jsx-filename-extension": 0, + "react/jsx-no-target-blank": 0, "react/prefer-stateless-function": 0, }, "settings": { @@ -35,7 +36,7 @@ "babel-module": {}, }, "flowtype": { - "onlyFilesWithFlowAnnotation": true + "onlyFilesWithFlowAnnotation": true, } }, } diff --git a/package.json b/package.json index 4279ca9a..11d77a68 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ }, "dependencies": { "@fortawesome/fontawesome": "^1.1.3", - "@fortawesome/fontawesome-free-brands": "^5.0.6", "@fortawesome/fontawesome-free-regular": "^5.0.6", "@fortawesome/fontawesome-free-solid": "^5.0.6", "@fortawesome/react-fontawesome": "^0.0.17", diff --git a/src/components/base/Icon.js b/src/components/base/Icon/index.js similarity index 88% rename from src/components/base/Icon.js rename to src/components/base/Icon/index.js index 858e33c2..3735c4ce 100644 --- a/src/components/base/Icon.js +++ b/src/components/base/Icon/index.js @@ -12,6 +12,6 @@ const Container = styled.span` export default ({ name, ...props }: { name: string }) => ( - + ) diff --git a/src/components/base/Icon/stories.js b/src/components/base/Icon/stories.js new file mode 100644 index 00000000..db88eaa7 --- /dev/null +++ b/src/components/base/Icon/stories.js @@ -0,0 +1,36 @@ +// @flow + +import React from 'react' +import { storiesOf } from '@storybook/react' +import { text, number } from '@storybook/addon-knobs' + +import Icon from 'components/base/Icon' + +const stories = storiesOf('Icon', module) + +const Wrapper = ({ children }: { children: any }) => ( +
+
+ (Change the icon value with{' '} + + FontAwesome + {' '} + icon) +
+ {children} +
+) + +stories.add('basic', () => ( + + + +)) diff --git a/yarn.lock b/yarn.lock index e8e5d2ef..834b63f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -82,12 +82,6 @@ version "0.1.2" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.1.2.tgz#d6aa075058f0c984d6e2ebcbc0052c1f7f9bea72" -"@fortawesome/fontawesome-free-brands@^5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free-brands/-/fontawesome-free-brands-5.0.6.tgz#fee054ce0c4d74019020f6353ca85cfb408de719" - dependencies: - "@fortawesome/fontawesome-common-types" "^0.1.2" - "@fortawesome/fontawesome-free-regular@^5.0.6": version "5.0.6" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free-regular/-/fontawesome-free-regular-5.0.6.tgz#fafc624025a247c1a1bbb5080b9902a490cd79f5" @@ -7345,14 +7339,14 @@ react-fuzzy@^0.5.1: fuse.js "^3.0.1" prop-types "^15.5.9" -react-hot-loader@^4.0.0-beta.17: - version "4.0.0-beta.17" - resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.0.0-beta.17.tgz#484ff64221fc456698d6a24cd2a107b66f024eaa" +react-hot-loader@^4.0.0-beta.18: + version "4.0.0-beta.18" + resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.0.0-beta.18.tgz#5a3d1b5bd813633380b88c0c660019dbf638975d" dependencies: fast-levenshtein "^2.0.6" global "^4.3.0" hoist-non-react-statics "^2.3.1" - react-stand-in "^4.0.0-beta.17" + react-stand-in "^4.0.0-beta.18" react-html-attributes@^1.3.0: version "1.4.1" @@ -7472,9 +7466,9 @@ react-split-pane@^0.1.74: prop-types "^15.5.10" react-style-proptype "^3.0.0" -react-stand-in@^4.0.0-beta.17: - version "4.0.0-beta.17" - resolved "https://registry.yarnpkg.com/react-stand-in/-/react-stand-in-4.0.0-beta.17.tgz#c65216f5109ae9db2a961812a96ea5a5e416184b" +react-stand-in@^4.0.0-beta.18: + version "4.0.0-beta.18" + resolved "https://registry.yarnpkg.com/react-stand-in/-/react-stand-in-4.0.0-beta.18.tgz#67d83309ae5d95526a2d1124beaa7ab093085cb2" dependencies: shallowequal "^1.0.2"