Browse Source

Merge pull request #249 from loeck/master

Update electron-webpack for use Webpack 4 and Babel 7
master
Meriadec Pillet 7 years ago
committed by GitHub
parent
commit
94f7688b4b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 29
      .babelrc
  2. 40
      .babelrc.js
  3. 4
      electron-builder.yml
  4. 27
      package.json
  5. 2
      scripts/dist.sh
  6. 2
      scripts/start.sh
  7. 2
      src/components/AccountPage/index.js
  8. 2
      src/components/BalanceSummary/index.js
  9. 2
      src/components/DashboardPage/AccountCard.js
  10. 17
      src/components/DevTools.js
  11. 2
      src/components/OperationsList/index.js
  12. 2
      src/components/SideBar/index.js
  13. 0
      src/components/base/Chart/Tooltip.js
  14. 0
      src/components/base/Chart/handleMouseEvents.js
  15. 0
      src/components/base/Chart/helpers.js
  16. 478
      src/components/base/Chart/index.js
  17. 2
      src/components/base/Chart/refreshDraw.js
  18. 0
      src/components/base/Chart/refreshNodes.js
  19. 2
      src/components/base/Chart/stories.js
  20. 0
      src/components/base/Chart/types.js
  21. 12
      src/components/base/FormattedVal/__tests__/__snapshots__/FormattedVal.test.js.snap
  22. 186
      src/components/base/NewChart/index.js
  23. 2
      src/components/modals/AddAccount/index.js
  24. 2
      src/components/modals/OperationDetails.js
  25. 2
      src/components/modals/Receive/index.js
  26. 2
      src/components/modals/Send/index.js
  27. 2
      src/components/modals/SettingsAccount.js
  28. 0
      src/config/constants.js
  29. 2
      src/renderer/events.js
  30. 4
      webpack/internals.config.js
  31. 2
      webpack/main.config.js
  32. 2
      webpack/renderer.config.js
  33. 5
      webpack/resolve.js
  34. 2549
      yarn.lock

29
.babelrc

@ -1,29 +0,0 @@
{
"presets": [
[
"env",
{
"loose": true,
"modules": false,
"targets": {
"electron": "1.8",
"node": "current"
}
}
],
"flow",
"react",
"stage-0"
],
"plugins": [["module-resolver", { "root": ["src"] }], "styled-components"],
"env": {
"test": {
"presets": [
"env",
"stage-0",
"react",
],
"plugins": [["module-resolver", { "root": ["src"] }], "styled-components"],
}
}
}

40
.babelrc.js

@ -0,0 +1,40 @@
const { NODE_ENV } = process.env
const presets = [
[
'@babel/preset-env',
{
loose: true,
modules: NODE_ENV === 'test' ? 'commonjs' : false,
targets: {
electron: '1.8',
node: 'current',
},
},
],
'@babel/preset-flow',
'@babel/preset-react',
'@babel/preset-stage-0',
]
const plugins = [
['babel-plugin-module-resolver', { root: ['src'] }],
[
'babel-plugin-styled-components',
{
displayName: NODE_ENV === 'development',
minify: NODE_ENV === 'production',
},
],
]
module.exports = {
presets,
plugins,
env: {
test: {
presets,
plugins,
},
},
}

4
electron-builder.yml

@ -85,7 +85,3 @@ files:
- "!node_modules/rxjs{,/**/*}" - "!node_modules/rxjs{,/**/*}"
- "!node_modules/source-map/dist{,/**/*}" - "!node_modules/source-map/dist{,/**/*}"
- "!node_modules/styled-components/src{,/**/*}" - "!node_modules/styled-components/src{,/**/*}"
- "!node_modules/victory-chart/{es,dist,src}{,/**/*}"
- "!node_modules/victory-core/{es,dist,src}{,/**/*}"
- "!node_modules/victory-pie{,/**/*}"
- "!node_modules/victory{,/**/*}"

27
package.json

@ -49,17 +49,16 @@
"@ledgerhq/hw-transport": "^4.7.3", "@ledgerhq/hw-transport": "^4.7.3",
"@ledgerhq/hw-transport-node-hid": "^4.7.3", "@ledgerhq/hw-transport-node-hid": "^4.7.3",
"axios": "^0.18.0", "axios": "^0.18.0",
"babel-runtime": "^6.26.0",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"bitcoinjs-lib": "^3.3.2", "bitcoinjs-lib": "^3.3.2",
"bs58check": "^2.1.1", "bs58check": "^2.1.1",
"color": "^3.0.0", "color": "^3.0.0",
"cross-env": "^5.1.4", "cross-env": "^5.1.4",
"d3": "^4.13.0", "d3": "^5.0.0",
"debug": "^3.1.0", "debug": "^3.1.0",
"downshift": "^1.31.2", "downshift": "^1.31.2",
"electron-store": "^1.3.0", "electron-store": "^1.3.0",
"electron-updater": "^2.21.3", "electron-updater": "^2.21.4",
"fuse.js": "^3.2.0", "fuse.js": "^3.2.0",
"history": "^4.7.2", "history": "^4.7.2",
"i18next": "^10.6.0", "i18next": "^10.6.0",
@ -92,37 +91,38 @@
"styled-components": "^3.2.3", "styled-components": "^3.2.3",
"styled-system": "^2.2.1", "styled-system": "^2.2.1",
"tippy.js": "^2.4.1", "tippy.js": "^2.4.1",
"victory": "^0.25.6",
"ws": "^5.1.0" "ws": "^5.1.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.0.0-beta.42",
"@babel/preset-env": "^7.0.0-beta.40",
"@babel/preset-flow": "^7.0.0-beta.40",
"@babel/preset-react": "^7.0.0-beta.40",
"@babel/preset-stage-0": "^7.0.0-beta.40",
"@storybook/addon-actions": "^3.3.15", "@storybook/addon-actions": "^3.3.15",
"@storybook/addon-knobs": "^3.3.15", "@storybook/addon-knobs": "^3.3.15",
"@storybook/addon-links": "^3.3.15", "@storybook/addon-links": "^3.3.15",
"@storybook/addon-options": "^3.3.15", "@storybook/addon-options": "^3.3.15",
"@storybook/addons": "^3.3.15", "@storybook/addons": "^3.3.15",
"@storybook/react": "^3.3.15", "@storybook/react": "^3.3.15",
"babel-core": "^6.26.0", "babel-core": "^7.0.0-0",
"babel-eslint": "^8.2.1", "babel-eslint": "^8.2.1",
"babel-jest": "^22.4.3",
"babel-plugin-module-resolver": "^3.1.1", "babel-plugin-module-resolver": "^3.1.1",
"babel-plugin-styled-components": "^1.5.0", "babel-plugin-styled-components": "^1.5.0",
"babel-preset-env": "^1.6.1",
"babel-preset-flow": "^6.23.0",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"chalk": "^2.3.1", "chalk": "^2.3.1",
"chance": "^1.0.13", "chance": "^1.0.13",
"concurrently": "^3.5.1", "concurrently": "^3.5.1",
"dotenv": "^5.0.1", "dotenv": "^5.0.1",
"electron": "1.8.4", "electron": "1.8.4",
"electron-builder": "^20.6.2", "electron-builder": "^20.8.0",
"electron-devtools-installer": "^2.2.3", "electron-devtools-installer": "^2.2.3",
"electron-rebuild": "^1.7.3", "electron-rebuild": "^1.7.3",
"electron-webpack": "1.13.0", "electron-webpack": "^2.0.1",
"eslint": "^4.19.1", "eslint": "^4.19.1",
"eslint-config-airbnb": "^16.1.0", "eslint-config-airbnb": "^16.1.0",
"eslint-config-prettier": "^2.9.0", "eslint-config-prettier": "^2.9.0",
"eslint-import-resolver-babel-module": "^4.0.0", "eslint-import-resolver-babel-module": "^5.0.0-beta.0",
"eslint-plugin-flowtype": "^2.46.0", "eslint-plugin-flowtype": "^2.46.0",
"eslint-plugin-import": "^2.9.0", "eslint-plugin-import": "^2.9.0",
"eslint-plugin-jsx-a11y": "^6.0.3", "eslint-plugin-jsx-a11y": "^6.0.3",
@ -138,8 +138,9 @@
"prettier": "^1.11.1", "prettier": "^1.11.1",
"react-hot-loader": "^4.0.0", "react-hot-loader": "^4.0.0",
"react-test-renderer": "^16.2.0", "react-test-renderer": "^16.2.0",
"webpack": "^3.11.0", "webpack": "^4.3.0",
"webpack-bundle-analyzer": "^2.11.1", "webpack-bundle-analyzer": "^2.11.1",
"webpack-cli": "^2.0.13",
"yaml-loader": "^0.5.0" "yaml-loader": "^0.5.0"
} }
} }

2
scripts/dist.sh

@ -1,5 +1,5 @@
#/bin/bash #/bin/bash
rm -rf dist && rm -rf dist &&
NODE_ENV=production webpack --config webpack/internals.config.js && NODE_ENV=production webpack-cli --config webpack/internals.config.js &&
electron-webpack electron-webpack

2
scripts/start.sh

@ -1,5 +1,5 @@
#/bin/bash #/bin/bash
concurrently --raw \ concurrently --raw \
"cross-env NODE_ENV=development webpack --watch --config webpack/internals.config.js" \ "cross-env NODE_ENV=development webpack-cli --watch --config webpack/internals.config.js" \
"cross-env NODE_ENV=development electron-webpack dev" "cross-env NODE_ENV=development electron-webpack dev"

2
src/components/AccountPage/index.js

@ -7,7 +7,7 @@ import { translate } from 'react-i18next'
import { Redirect } from 'react-router' import { Redirect } from 'react-router'
import styled from 'styled-components' import styled from 'styled-components'
import { MODAL_SEND, MODAL_RECEIVE, MODAL_SETTINGS_ACCOUNT } from 'constants' import { MODAL_SEND, MODAL_RECEIVE, MODAL_SETTINGS_ACCOUNT } from 'config/constants'
import type { T, Account } from 'types/common' import type { T, Account } from 'types/common'

2
src/components/BalanceSummary/index.js

@ -6,7 +6,7 @@ import { getFiatUnit } from '@ledgerhq/currencies'
import type { Account } from 'types/common' import type { Account } from 'types/common'
import Chart from 'components/base/NewChart' import Chart from 'components/base/Chart'
import Box, { Card } from 'components/base/Box' import Box, { Card } from 'components/base/Box'
import CalculateBalance from 'components/CalculateBalance' import CalculateBalance from 'components/CalculateBalance'
import FormattedVal from 'components/base/FormattedVal' import FormattedVal from 'components/base/FormattedVal'

2
src/components/DashboardPage/AccountCard.js

@ -5,7 +5,7 @@ import { getIconByCoinType } from '@ledgerhq/currencies/react'
import type { Account } from 'types/common' import type { Account } from 'types/common'
import Chart from 'components/base/NewChart' import Chart from 'components/base/Chart'
import Bar from 'components/base/Bar' import Bar from 'components/base/Bar'
import Box, { Card } from 'components/base/Box' import Box, { Card } from 'components/base/Box'
import CalculateBalance from 'components/CalculateBalance' import CalculateBalance from 'components/CalculateBalance'

17
src/components/DevTools.js

@ -5,7 +5,6 @@
import React, { PureComponent } from 'react' import React, { PureComponent } from 'react'
import { remote, ipcRenderer } from 'electron' import { remote, ipcRenderer } from 'electron'
import { translate } from 'react-i18next' import { translate } from 'react-i18next'
import VictoryArea from 'victory-chart/lib/components/victory-area/victory-area'
import styled from 'styled-components' import styled from 'styled-components'
import color from 'color' import color from 'color'
import fs from 'fs' import fs from 'fs'
@ -19,10 +18,10 @@ import filter from 'lodash/fp/filter'
import sortBy from 'lodash/fp/sortBy' import sortBy from 'lodash/fp/sortBy'
import chunk from 'lodash/chunk' import chunk from 'lodash/chunk'
import Chart from 'components/base/Chart'
import Box from 'components/base/Box' import Box from 'components/base/Box'
import Bar from 'components/base/Bar' import Bar from 'components/base/Bar'
import CopyToClipboard from 'components/base/CopyToClipboard' import CopyToClipboard from 'components/base/CopyToClipboard'
import { WrapperChart } from 'components/base/Chart'
import staticPath from 'helpers/staticPath' import staticPath from 'helpers/staticPath'
@ -139,6 +138,7 @@ class DevTools extends PureComponent<any, State> {
[ [
...(prev.cpuUsage[data.name] || []), ...(prev.cpuUsage[data.name] || []),
{ {
date: new Date().getTime().toString(),
value: parseFloat(data.value), value: parseFloat(data.value),
}, },
], ],
@ -247,7 +247,16 @@ class DevTools extends PureComponent<any, State> {
<Box>{k}</Box> <Box>{k}</Box>
</Box> </Box>
<Box> <Box>
<WrapperChart <Chart
id={k}
data={cpuUsage[k]}
dateFormat="%Q"
color="#8884d8"
height={50}
hideAxis
interactive={false}
/>
{/* <WrapperChart
height={50} height={50}
render={({ height, width }) => ( render={({ height, width }) => (
<VictoryArea <VictoryArea
@ -264,7 +273,7 @@ class DevTools extends PureComponent<any, State> {
padding={{ top: 10, right: 0, left: 0, bottom: 0 }} padding={{ top: 10, right: 0, left: 0, bottom: 0 }}
/> />
)} )}
/> /> */}
</Box> </Box>
</Box> </Box>
))} ))}

2
src/components/OperationsList/index.js

@ -13,7 +13,7 @@ import isEqual from 'lodash/isEqual'
import type { Account, Operation as OperationType, T } from 'types/common' import type { Account, Operation as OperationType, T } from 'types/common'
import { MODAL_OPERATION_DETAILS } from 'constants' import { MODAL_OPERATION_DETAILS } from 'config/constants'
import { openModal } from 'reducers/modals' import { openModal } from 'reducers/modals'

2
src/components/SideBar/index.js

@ -7,7 +7,7 @@ import styled from 'styled-components'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { getIconByCoinType } from '@ledgerhq/currencies/react' import { getIconByCoinType } from '@ledgerhq/currencies/react'
import { MODAL_SEND, MODAL_RECEIVE, MODAL_ADD_ACCOUNT } from 'constants' import { MODAL_SEND, MODAL_RECEIVE, MODAL_ADD_ACCOUNT } from 'config/constants'
import type { Account, T } from 'types/common' import type { Account, T } from 'types/common'

0
src/components/base/NewChart/Tooltip.js → src/components/base/Chart/Tooltip.js

0
src/components/base/NewChart/handleMouseEvents.js → src/components/base/Chart/handleMouseEvents.js

0
src/components/base/NewChart/helpers.js → src/components/base/Chart/helpers.js

478
src/components/base/Chart/index.js

@ -1,371 +1,187 @@
// @flow // @flow
/* eslint-disable react/no-multi-comp */ /**
* Chart
import React, { Fragment, Component, PureComponent } from 'react' * -----
*
import VictoryChart from 'victory-chart/lib/components/victory-chart/victory-chart' * XX
import VictoryArea from 'victory-chart/lib/components/victory-area/victory-area' * XXXX
import VictoryAxis from 'victory-chart/lib/components/victory-axis/victory-axis' * X XX X
import VictoryTooltip from 'victory-core/lib/victory-tooltip/victory-tooltip' * XXXX XX X
import VictoryVoronoiContainer from 'victory-chart/lib/components/containers/victory-voronoi-container' * XX X XX X
* X XXXX X XX X
import { space, colors, fontSizes } from 'styles/theme' * XX XX X XX XX XX
* XX XX XX XXXX
import Box from 'components/base/Box' * XX
import Text from 'components/base/Text' * XX
import { TooltipContainer } from 'components/base/Tooltip' * Usage:
*
const ANIMATION_DURATION = 600 * <Chart
const DEFAULT_PROPS = { * data={data}
color: 'blue', * interactive // Handle mouse events, display tooltip etc.
padding: 0, * color="#5f8ced" // Main color for line, gradient, etc.
} * height={300} // Fix height. Width is responsive to container.
* />
type Props = { *
height: number, * `data` looks like:
render: Function, *
* [
* { date: '2018-01-01', value: 10 },
* { date: '2018-01-02', value: 25 },
* { date: '2018-01-03', value: 50 },
* ]
*
*/
import React, { PureComponent } from 'react'
import * as d3 from 'd3'
import noop from 'lodash/noop'
import type { Unit } from '@ledgerhq/currencies'
import refreshNodes from './refreshNodes'
import refreshDraw from './refreshDraw'
import handleMouseEvents from './handleMouseEvents'
import { enrichData, generateColors, generateMargins, observeResize } from './helpers'
import type { Data } from './types'
export type Props = {
data: Data, // eslint-disable-line react/no-unused-prop-types
unit?: Unit, // eslint-disable-line react/no-unused-prop-types
id?: string, // eslint-disable-line react/no-unused-prop-types
height?: number,
tickXScale: string, // eslint-disable-line react/no-unused-prop-types
color?: string, // eslint-disable-line react/no-unused-prop-types
hideAxis?: boolean, // eslint-disable-line react/no-unused-prop-types
dateFormat?: string, // eslint-disable-line react/no-unused-prop-types
interactive?: boolean, // eslint-disable-line react/no-unused-prop-types
renderTooltip?: Function, // eslint-disable-line react/no-unused-prop-types
} }
type State = { class Chart extends PureComponent<Props> {
isAnimationActive: boolean, static defaultProps = {
width: number, color: '#000',
} dateFormat: '%Y-%m-%d',
height: 400,
export class WrapperChart extends PureComponent<Props, State> { hideAxis: false,
state = { id: 'chart',
isAnimationActive: true, interactive: true,
width: 0, tickXScale: 'month',
unit: undefined,
} }
componentDidMount() { componentDidMount() {
this._timeout = setTimeout( const { width } = this._ruler.getBoundingClientRect()
() => this._width = width
this.setState({ this.createChart()
isAnimationActive: false, observeResize(this._ruler, width => {
}), if (width !== this._width) {
ANIMATION_DURATION * 2, this._width = width
) this.refreshChart(this.props)
if (this._node) {
this._ro = new ResizeObserver(entries => {
const entry = entries.find(entry => this._node === entry.target)
if (entry) {
this.setState({
width: entry.contentRect.width,
})
} }
}) })
this._ro.observe(this._node)
} }
}
componentWillUnmount() {
clearTimeout(this._timeout)
if (this._ro) { componentDidUpdate(prevProps: Props) {
this._ro.disconnect() this.refreshChart(prevProps)
}
} }
_ro = undefined _ruler: any
_node = undefined _node: any
_timeout = undefined _width: number
refreshChart: Function
render() { createChart() {
const { render, height } = this.props const ctx = {
const { isAnimationActive, width } = this.state NODES: {},
return ( INVALIDATED: {},
<Box ff="Open Sans" innerRef={n => (this._node = n)} style={{ height }}> MARGINS: {},
{render({ isAnimationActive, height, width })} COLORS: {},
</Box> DATA: [],
) WIDTH: 0,
HEIGHT: 0,
x: noop,
y: noop,
} }
}
function getLinearGradient({ let firstRender = true
linearGradient,
id,
color,
}: {
linearGradient: LinearGradient,
id: string,
color: string,
}) {
return linearGradient.length > 0 ? (
<svg style={{ height: 0 }}>
<defs>
<linearGradient id={id} x1="0" y1="0" x2="0" y2="100%">
{linearGradient.map((g, i) => (
<stop
key={i} // eslint-disable-line react/no-array-index-key
offset={`${g[0]}%`}
stopColor={color}
stopOpacity={g[1]}
/>
))}
</linearGradient>
</defs>
</svg>
) : null
}
class CustomTooltip extends Component<any, any> {
static defaultEvents = VictoryTooltip.defaultEvents
state = this.props
componentWillMount() {
this._mounted = true
}
componentWillReceiveProps(nextProps) {
this._shouldRender = false
this.updateState(nextProps)
}
shouldComponentUpdate(nextProps) { // Keep reference to mouse handler to allow destroy when refresh
const isActive = nextProps.active === true let mouseHandler = null
const wasActive = this.props.active === true && !nextProps.active
return (isActive && this._shouldRender) || wasActive this.refreshChart = prevProps => {
} const { _node: node, props } = this
const { data: raw, color, dateFormat, height, hideAxis, interactive, renderTooltip } = props
componentWillUnmount() { ctx.DATA = enrichData(raw, d3.timeParse(dateFormat))
this._mounted = false
}
updateState = props => // Detect what needs to be updated
window.requestAnimationFrame(() => { ctx.INVALIDATED = {
this._shouldRender = true color: firstRender || (prevProps && color !== prevProps.color),
if (this._mounted) { margin: firstRender || (prevProps && hideAxis !== prevProps.hideAxis),
this.setState(props)
} }
}) firstRender = false
_shouldRender = false
_mounted = false
render() { // Reset color if needed
const { strokeWidth, dotColor, x, y, active, text, datum, renderer } = this.props if (ctx.INVALIDATED.color) {
ctx.COLORS = generateColors(color)
if (!active) {
return null
} }
return ( // Reset margins if needed
<g> if (ctx.INVALIDATED.margin) {
<circle ctx.MARGINS = generateMargins(hideAxis)
cx={x}
cy={y + space[2]}
r={strokeWidth}
stroke={dotColor}
strokeWidth={strokeWidth}
fill={colors.white}
/>
<foreignObject>
<TooltipContainer
style={{
position: 'absolute',
top: y - space[4],
left: x,
transform: `translate3d(-50%, 0, 0)`,
}}
>
<Text style={{ lineHeight: 1 }}>{renderer(text(datum))}</Text>
</TooltipContainer>
</foreignObject>
</g>
)
} }
}
type LinearGradient = Array<Array<*>> // Derived draw variables
ctx.HEIGHT = Math.max(0, (height || 0) - ctx.MARGINS.top - ctx.MARGINS.bottom)
ctx.WIDTH = Math.max(0, this._width - ctx.MARGINS.left - ctx.MARGINS.right)
type GenericChart = { // Scales and areas
id: string, const x = d3.scaleTime().range([0, ctx.WIDTH])
linearGradient: LinearGradient, const y = d3.scaleLinear().range([ctx.HEIGHT, 0])
strokeWidth: number, x.domain(d3.extent(ctx.DATA, d => d.parsedDate))
height: number, y.domain([0, d3.max(ctx.DATA, d => d.value)])
padding: Object | number, ctx.x = x
color: string, ctx.y = y
data: Array<Object>,
}
export const SimpleAreaChart = ({ // Reference to last tooltip, to prevent un-necessary re-render
linearGradient, let lastDisplayedTooltip = null
height,
data,
strokeWidth,
id,
padding,
color,
}: GenericChart) => (
<WrapperChart
height={height}
render={({ width }) => (
<Fragment>
{getLinearGradient({
linearGradient,
id,
color,
})}
<VictoryArea
domainPadding={{
y: [0, space[1]],
}}
data={data}
x="name"
y="value"
style={{
data: {
stroke: color,
fill: `url(#${id})`,
strokeWidth,
},
}}
padding={padding}
height={height}
width={width}
/>
</Fragment>
)}
/>
)
SimpleAreaChart.defaultProps = {
height: 50,
id: 'simple-chart',
linearGradient: [],
strokeWidth: 1,
...DEFAULT_PROPS,
}
type Chart = GenericChart & { // Add/remove nodes depending on props
renderLabels: Function, refreshNodes({ ctx, node, props })
renderTickX: Function,
renderTickY: Function,
renderTooltip: Function,
tickCountX: number,
tickCountY: number,
}
const AreaChartContainer = <VictoryVoronoiContainer voronoiDimension="x" /> // Redraw
refreshDraw({ ctx, props })
export class AreaChart extends PureComponent<Chart> { // Mouse handler
static defaultProps = { mouseHandler && mouseHandler.remove() // eslint-disable-line no-unused-expressions
height: 100, if (interactive) {
id: 'chart', mouseHandler = handleMouseEvents({
linearGradient: [[5, 0.2], [100, 0]], ctx,
strokeWidth: 2, props,
renderLabels: (d: Object) => d.y, shouldTooltipUpdate: d => d !== lastDisplayedTooltip,
renderTickX: (t: any) => t, onTooltipUpdate: d => (lastDisplayedTooltip = d),
renderTickY: (t: any) => t, renderTooltip,
...DEFAULT_PROPS, })
}
} }
_tooltip = ( this.refreshChart()
<CustomTooltip
strokeWidth={this.props.strokeWidth}
dotColor={this.props.color}
renderer={this.props.renderTooltip}
/>
)
render() {
const {
color,
data,
height,
id,
linearGradient,
padding,
renderLabels,
renderTickX,
renderTickY,
strokeWidth,
tickCountX,
tickCountY,
} = this.props
const tickLabelsStyle = {
fill: colors.grey,
fontSize: fontSizes[4],
fontFamily: 'inherit',
fontWeight: 'inherit',
} }
render() {
const { height } = this.props
return ( return (
<WrapperChart <div style={{ position: 'relative', height }} ref={n => (this._ruler = n)}>
height={height} <div
render={({ width }) => ( style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}
<Fragment> ref={n => (this._node = n)}
{getLinearGradient({
linearGradient,
id,
color,
})}
<VictoryChart
height={height}
width={width}
padding={padding}
domainPadding={{
y: [0, space[1]],
}}
containerComponent={AreaChartContainer}
>
<VictoryAxis
animate={false}
tickCount={tickCountX}
tickFormat={renderTickX}
style={{
axis: {
stroke: colors.fog,
},
tickLabels: {
...tickLabelsStyle,
padding: space[2],
},
}}
/>
<VictoryAxis
dependentAxis
tickCount={tickCountY}
tickFormat={renderTickY}
style={{
grid: {
stroke: colors.fog,
strokeDasharray: 5,
},
axis: {
stroke: null,
},
tickLabels: {
...tickLabelsStyle,
padding: space[4],
},
}}
/>
<VictoryArea
data={data}
x="name"
y="value"
labelComponent={this._tooltip}
labels={renderLabels}
style={{
data: {
stroke: color,
fill: `url(#${id})`,
strokeWidth,
},
}}
width={width}
/>
</VictoryChart>
</Fragment>
)}
/> />
</div>
) )
} }
} }
export default Chart

2
src/components/base/NewChart/refreshDraw.js → src/components/base/Chart/refreshDraw.js

@ -35,7 +35,7 @@ export default function refreshDraw({ ctx, props }: { ctx: CTX, props: Props })
const nbTicksX = getTickXCount(tickXScale) const nbTicksX = getTickXCount(tickXScale)
const renderTickX = getRenderTickX(tickXScale) const renderTickX = getRenderTickX(tickXScale)
const renderTickY = t => formatShort(unit, t) const renderTickY = t => (unit ? formatShort(unit, t) : t)
const area = d3 const area = d3
.area() .area()

0
src/components/base/NewChart/refreshNodes.js → src/components/base/Chart/refreshNodes.js

2
src/components/base/NewChart/stories.js → src/components/base/Chart/stories.js

@ -8,7 +8,7 @@ import { storiesOf } from '@storybook/react'
import { boolean, number } from '@storybook/addon-knobs' import { boolean, number } from '@storybook/addon-knobs'
import { color } from '@storybook/addon-knobs/react' import { color } from '@storybook/addon-knobs/react'
import Chart from 'components/base/NewChart' import Chart from 'components/base/Chart'
const stories = storiesOf('Components/base', module) const stories = storiesOf('Components/base', module)

0
src/components/base/NewChart/types.js → src/components/base/Chart/types.js

12
src/components/base/FormattedVal/__tests__/__snapshots__/FormattedVal.test.js.snap

@ -2,7 +2,7 @@
exports[`components FormattedVal renders a fiat 1`] = ` exports[`components FormattedVal renders a fiat 1`] = `
<span <span
className="FormattedVal__T-fevxLy hYRXSf Text-bUpXnE eAhrPH" className="sc-bwzfXH uTxCW sc-bdVaJa ijVSFT"
color="#66be54" color="#66be54"
> >
20.00 20.00
@ -11,7 +11,7 @@ exports[`components FormattedVal renders a fiat 1`] = `
exports[`components FormattedVal renders a formatted val 1`] = ` exports[`components FormattedVal renders a formatted val 1`] = `
<span <span
className="FormattedVal__T-fevxLy hYRXSf Text-bUpXnE eAhrPH" className="sc-bwzfXH uTxCW sc-bdVaJa ijVSFT"
color="#66be54" color="#66be54"
> >
4 4
@ -20,7 +20,7 @@ exports[`components FormattedVal renders a formatted val 1`] = `
exports[`components FormattedVal renders a percent 1`] = ` exports[`components FormattedVal renders a percent 1`] = `
<span <span
className="FormattedVal__T-fevxLy hYRXSf Text-bUpXnE eAhrPH" className="sc-bwzfXH uTxCW sc-bdVaJa ijVSFT"
color="#66be54" color="#66be54"
> >
30 % 30 %
@ -29,7 +29,7 @@ exports[`components FormattedVal renders a percent 1`] = `
exports[`components FormattedVal shows code 1`] = ` exports[`components FormattedVal shows code 1`] = `
<span <span
className="FormattedVal__T-fevxLy hYRXSf Text-bUpXnE eAhrPH" className="sc-bwzfXH uTxCW sc-bdVaJa ijVSFT"
color="#66be54" color="#66be54"
> >
BTC 4 BTC 4
@ -38,7 +38,7 @@ exports[`components FormattedVal shows code 1`] = `
exports[`components FormattedVal shows sign 1`] = ` exports[`components FormattedVal shows sign 1`] = `
<span <span
className="FormattedVal__T-fevxLy hYRXSf Text-bUpXnE eAhrPH" className="sc-bwzfXH uTxCW sc-bdVaJa ijVSFT"
color="#66be54" color="#66be54"
> >
+ 4 + 4
@ -47,7 +47,7 @@ exports[`components FormattedVal shows sign 1`] = `
exports[`components FormattedVal shows sign 2`] = ` exports[`components FormattedVal shows sign 2`] = `
<span <span
className="FormattedVal__T-fevxLy hYRXSf Text-bUpXnE fjJBpt" className="sc-bwzfXH uTxCW sc-bdVaJa lfEqUE"
color="#fa4352" color="#fa4352"
> >
- 4 - 4

186
src/components/base/NewChart/index.js

@ -1,186 +0,0 @@
// @flow
/**
* Chart
* -----
*
* XX
* XXXX
* X XX X
* XXXX XX X
* XX X XX X
* X XXXX X XX X
* XX XX X XX XX XX
* XX XX XX XXXX
* XX
* XX
* Usage:
*
* <Chart
* data={data}
* interactive // Handle mouse events, display tooltip etc.
* color="#5f8ced" // Main color for line, gradient, etc.
* height={300} // Fix height. Width is responsive to container.
* />
*
* `data` looks like:
*
* [
* { date: '2018-01-01', value: 10 },
* { date: '2018-01-02', value: 25 },
* { date: '2018-01-03', value: 50 },
* ]
*
*/
import React, { PureComponent } from 'react'
import * as d3 from 'd3'
import noop from 'lodash/noop'
import type { Unit } from '@ledgerhq/currencies'
import refreshNodes from './refreshNodes'
import refreshDraw from './refreshDraw'
import handleMouseEvents from './handleMouseEvents'
import { enrichData, generateColors, generateMargins, observeResize } from './helpers'
import type { Data } from './types'
export type Props = {
data: Data, // eslint-disable-line react/no-unused-prop-types
unit: Unit, // eslint-disable-line react/no-unused-prop-types
id?: string, // eslint-disable-line react/no-unused-prop-types
height?: number,
tickXScale: string, // eslint-disable-line react/no-unused-prop-types
color?: string, // eslint-disable-line react/no-unused-prop-types
hideAxis?: boolean, // eslint-disable-line react/no-unused-prop-types
dateFormat?: string, // eslint-disable-line react/no-unused-prop-types
interactive?: boolean, // eslint-disable-line react/no-unused-prop-types
renderTooltip?: Function, // eslint-disable-line react/no-unused-prop-types
}
class Chart extends PureComponent<Props> {
static defaultProps = {
id: 'chart',
color: '#000',
hideAxis: false,
interactive: true,
height: 400,
dateFormat: '%Y-%m-%d',
tickXScale: 'month',
}
componentDidMount() {
const { width } = this._ruler.getBoundingClientRect()
this._width = width
this.createChart()
observeResize(this._ruler, width => {
if (width !== this._width) {
this._width = width
this.refreshChart(this.props)
}
})
}
componentDidUpdate(prevProps: Props) {
this.refreshChart(prevProps)
}
_ruler: any
_node: any
_width: number
refreshChart: Function
createChart() {
const ctx = {
NODES: {},
INVALIDATED: {},
MARGINS: {},
COLORS: {},
DATA: [],
WIDTH: 0,
HEIGHT: 0,
x: noop,
y: noop,
}
let firstRender = true
// Keep reference to mouse handler to allow destroy when refresh
let mouseHandler = null
this.refreshChart = prevProps => {
const { _node: node, props } = this
const { data: raw, color, dateFormat, height, hideAxis, interactive, renderTooltip } = props
ctx.DATA = enrichData(raw, d3.timeParse(dateFormat))
// Detect what needs to be updated
ctx.INVALIDATED = {
color: firstRender || (prevProps && color !== prevProps.color),
margin: firstRender || (prevProps && hideAxis !== prevProps.hideAxis),
}
firstRender = false
// Reset color if needed
if (ctx.INVALIDATED.color) {
ctx.COLORS = generateColors(color)
}
// Reset margins if needed
if (ctx.INVALIDATED.margin) {
ctx.MARGINS = generateMargins(hideAxis)
}
// Derived draw variables
ctx.HEIGHT = Math.max(0, (height || 0) - ctx.MARGINS.top - ctx.MARGINS.bottom)
ctx.WIDTH = Math.max(0, this._width - ctx.MARGINS.left - ctx.MARGINS.right)
// Scales and areas
const x = d3.scaleTime().range([0, ctx.WIDTH])
const y = d3.scaleLinear().range([ctx.HEIGHT, 0])
x.domain(d3.extent(ctx.DATA, d => d.parsedDate))
y.domain([0, d3.max(ctx.DATA, d => d.value)])
ctx.x = x
ctx.y = y
// Reference to last tooltip, to prevent un-necessary re-render
let lastDisplayedTooltip = null
// Add/remove nodes depending on props
refreshNodes({ ctx, node, props })
// Redraw
refreshDraw({ ctx, props })
// Mouse handler
mouseHandler && mouseHandler.remove() // eslint-disable-line no-unused-expressions
if (interactive) {
mouseHandler = handleMouseEvents({
ctx,
props,
shouldTooltipUpdate: d => d !== lastDisplayedTooltip,
onTooltipUpdate: d => (lastDisplayedTooltip = d),
renderTooltip,
})
}
}
this.refreshChart()
}
render() {
const { height } = this.props
return (
<div style={{ position: 'relative', height }} ref={n => (this._ruler = n)}>
<div
style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}
ref={n => (this._node = n)}
/>
</div>
)
}
}
export default Chart

2
src/components/modals/AddAccount/index.js

@ -10,7 +10,7 @@ import { listCurrencies, getDefaultUnitByCoinType } from '@ledgerhq/currencies'
import type { Currency } from '@ledgerhq/currencies' import type { Currency } from '@ledgerhq/currencies'
import { MODAL_ADD_ACCOUNT } from 'constants' import { MODAL_ADD_ACCOUNT } from 'config/constants'
import type { Account, Device, T } from 'types/common' import type { Account, Device, T } from 'types/common'

2
src/components/modals/OperationDetails.js

@ -8,7 +8,7 @@ import moment from 'moment'
import type { T } from 'types/common' import type { T } from 'types/common'
import { MODAL_OPERATION_DETAILS } from 'constants' import { MODAL_OPERATION_DETAILS } from 'config/constants'
import Box from 'components/base/Box' import Box from 'components/base/Box'
import Button from 'components/base/Button' import Button from 'components/base/Button'

2
src/components/modals/Receive/index.js

@ -5,7 +5,7 @@ import { translate } from 'react-i18next'
import get from 'lodash/get' import get from 'lodash/get'
import { MODAL_RECEIVE } from 'constants' import { MODAL_RECEIVE } from 'config/constants'
import Box from 'components/base/Box' import Box from 'components/base/Box'
import Label from 'components/base/Label' import Label from 'components/base/Label'

2
src/components/modals/Send/index.js

@ -10,7 +10,7 @@ import type { Unit } from '@ledgerhq/currencies'
import type { T, Account } from 'types/common' import type { T, Account } from 'types/common'
import type { DoubleVal } from 'components/RequestAmount' import type { DoubleVal } from 'components/RequestAmount'
import { MODAL_SEND } from 'constants' import { MODAL_SEND } from 'config/constants'
import { getCounterValue } from 'reducers/settings' import { getCounterValue } from 'reducers/settings'

2
src/components/modals/SettingsAccount.js

@ -5,7 +5,7 @@ import { connect } from 'react-redux'
import get from 'lodash/get' import get from 'lodash/get'
import { push } from 'react-router-redux' import { push } from 'react-router-redux'
import { MODAL_SETTINGS_ACCOUNT } from 'constants' import { MODAL_SETTINGS_ACCOUNT } from 'config/constants'
import type { Account } from 'types/common' import type { Account } from 'types/common'

0
src/constants.js → src/config/constants.js

2
src/renderer/events.js

@ -7,7 +7,7 @@ import { getDefaultUnitByCoinType } from '@ledgerhq/currencies'
import type { Account } from 'types/common' import type { Account } from 'types/common'
import { CHECK_UPDATE_DELAY, SYNC_ACCOUNT_DELAY, SYNC_COUNTER_VALUES_DELAY } from 'constants' import { CHECK_UPDATE_DELAY, SYNC_ACCOUNT_DELAY, SYNC_COUNTER_VALUES_DELAY } from 'config/constants'
import { getAccounts, getAccountById } from 'reducers/accounts' import { getAccounts, getAccountById } from 'reducers/accounts'
import { getCounterValue } from 'reducers/settings' import { getCounterValue } from 'reducers/settings'

4
webpack/internals.config.js

@ -3,6 +3,7 @@ const fs = require('fs')
const webpackMain = require('electron-webpack/webpack.main.config') const webpackMain = require('electron-webpack/webpack.main.config')
const plugins = require('./plugins') const plugins = require('./plugins')
const resolve = require('./resolve')
const dirs = p => const dirs = p =>
fs fs
@ -16,6 +17,8 @@ const dirs = p =>
}, {}) }, {})
module.exports = webpackMain().then(config => ({ module.exports = webpackMain().then(config => ({
mode: config.mode,
context: config.context, context: config.context,
devtool: config.devtool, devtool: config.devtool,
target: config.target, target: config.target,
@ -26,6 +29,7 @@ module.exports = webpackMain().then(config => ({
}, },
resolve: { resolve: {
...resolve,
extensions: config.resolve.extensions, extensions: config.resolve.extensions,
}, },

2
webpack/main.config.js

@ -1,7 +1,9 @@
const plugins = require('./plugins') const plugins = require('./plugins')
const resolve = require('./resolve')
const config = { const config = {
plugins: plugins('main'), plugins: plugins('main'),
resolve,
} }
module.exports = config module.exports = config

2
webpack/renderer.config.js

@ -1,8 +1,10 @@
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin') const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
const plugins = require('./plugins') const plugins = require('./plugins')
const resolve = require('./resolve')
const config = { const config = {
resolve,
plugins: [...plugins('renderer'), new HardSourceWebpackPlugin()], plugins: [...plugins('renderer'), new HardSourceWebpackPlugin()],
devServer: { devServer: {
historyApiFallback: true, historyApiFallback: true,

5
webpack/resolve.js

@ -0,0 +1,5 @@
const path = require('path')
module.exports = {
modules: [path.resolve(__dirname, '../src'), path.resolve(__dirname, '../node_modules')],
}

2549
yarn.lock

File diff suppressed because it is too large
Loading…
Cancel
Save