Skip to content

Commit b8eb93a

Browse files
committed
### Main
- **Remove `Immutable.js` in favor of `Immer`** - **Migrate from `enzyme` to `react-testing-library`** - New instructions for snapshot and behavior testing - **Embracing Hooks** - Add `eslint-plugin-react-hooks` - Migrate all class components to functions - Add `useInjectSaga` and `useInjectReducer` hooks - Remove generator options to extend `Component` or `PureComponent`. Replace with a `React.memo` option. - **Use `React.lazy` and `Suspense` instead of `loadable-components` to code-split and asynchronously load components** - **Upgrades to Babel 7, React 16.6, ESLint 5, styled-components 4** - Config file and Babel plugin cleanup - Fix extract-intl script for Babel 7 - **Upgrade Webpack to v4** - Syntax / function changes (mode, optimization, etc.) - Remove webpack loader syntax from main app - Better SVG handling - **Webpack improvements** - Removal of dll plugin - Gzipping and better optimization config in prod - react-app-polyfill for targeted IE support - Switch from UglifyJS to Terser plugin - Icons generated by webpack-pwa-manifest plugin - **Upgrade Enzyme to v3** - Add in new Adapter, as required - Minor Jest config tweaks to include new Enzyme setup config - **Added support for node v9, v8** - Removed support for node v6 - **Add Prettier** - **Upgrade ESLint to v4** - **Add stylelint and stylelint config** ### Internals updates - Many dependency updates including: - react and react-dom (`16.6` to `16.8.6`) - react-redux (`5` to `7`) - connected-react-router (`4` to `6`) - react-router-dom (`4` to `5`) - redux-saga (`0.16` to `1`) - sanitize.css (`4` to `8`) - Update default saga injection mode to DAEMON - Update generators to reflect all the stack changes - Migrate default Node version to `lts/dubnium` - Fix support for `stylelint` - Fix setup script for Windows environments - Generate passing tests for components/containers - Rewrite generators code - Complete rewrite or `generate-templates-for-linting.js` - `webpack.DefinePlugin` => `webpack.EnvironmentPlugin` - New Webpack code splitting config - Remove `process.noDeprecation = true` - Migration from deprecated react-router-redux to connected-react-router - Migration from react-loadable to loadable-components - Quick start - Clone to a named directory - Scoped variables in i18n messages - Use .prettierrc path relative to .eslintrc.js - Fixes to generators - babel-plugin-lodash for easier import syntax - Miscellaneous fixes
1 parent 663408c commit b8eb93a

File tree

123 files changed

+12959
-12194
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

123 files changed

+12959
-12194
lines changed

.eslintrc.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
const fs = require('fs');
2+
const path = require('path');
23

3-
const prettierOptions = JSON.parse(fs.readFileSync('./.prettierrc', 'utf8'));
4+
const prettierOptions = JSON.parse(
5+
fs.readFileSync(path.resolve(__dirname, '.prettierrc'), 'utf8'),
6+
);
47

58
module.exports = {
69
parser: 'babel-eslint',
710
extends: ['airbnb', 'prettier', 'prettier/react'],
8-
plugins: ['prettier', 'redux-saga', 'react', 'jsx-a11y'],
11+
plugins: ['prettier', 'redux-saga', 'react', 'react-hooks', 'jsx-a11y'],
912
env: {
13+
jest: true,
1014
browser: true,
1115
node: true,
12-
jest: true,
1316
es6: true,
1417
},
1518
parserOptions: {
@@ -41,21 +44,34 @@ module.exports = {
4144
],
4245
'jsx-a11y/aria-props': 2,
4346
'jsx-a11y/heading-has-content': 0,
44-
'jsx-a11y/label-has-for': 2,
47+
'jsx-a11y/label-has-associated-control': [
48+
2,
49+
{
50+
// NOTE: If this error triggers, either disable it or add
51+
// your custom components, labels and attributes via these options
52+
// See https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/label-has-associated-control.md
53+
controlComponents: ['Input'],
54+
},
55+
],
56+
'jsx-a11y/label-has-for': 0,
4557
'jsx-a11y/mouse-events-have-key-events': 2,
4658
'jsx-a11y/role-has-required-aria-props': 2,
4759
'jsx-a11y/role-supports-aria-props': 2,
4860
'max-len': 0,
4961
'newline-per-chained-call': 0,
5062
'no-confusing-arrow': 0,
5163
'no-console': 1,
64+
'no-unused-vars': 2,
5265
'no-use-before-define': 0,
5366
'prefer-template': 2,
67+
'react/destructuring-assignment': 0,
68+
'react-hooks/rules-of-hooks': 'error',
5469
'react/jsx-closing-tag-location': 0,
5570
'react/forbid-prop-types': 0,
5671
'react/jsx-first-prop-new-line': [2, 'multiline'],
5772
'react/jsx-filename-extension': 0,
5873
'react/jsx-no-target-blank': 0,
74+
'react/jsx-uses-vars': 2,
5975
'react/require-default-props': 0,
6076
'react/require-extension': 0,
6177
'react/self-closing-comp': 0,

.travis.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
language: node_js
22

33
node_js:
4-
- 7
5-
- 6
6-
- 5
4+
- 'node'
5+
- 'lts/*'
76

87
script:
98
- node ./internals/scripts/generate-templates-for-linting
10-
- npm run test
9+
- npm test -- --maxWorkers=4
1110
- npm run build
1211

1312
before_install:

app/app.js

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,26 @@
66
*/
77

88
// Needed for redux-saga es6 generator support
9-
import 'babel-polyfill';
9+
import '@babel/polyfill';
1010

1111
// Import all the third party stuff
1212
import React from 'react';
1313
import ReactDOM from 'react-dom';
14-
import { applyMiddleware } from 'redux';
15-
import { Route } from 'react-router-dom';
1614
import { Provider } from 'react-redux';
17-
import { ConnectedRouter } from 'react-router-redux';
15+
import { ConnectedRouter } from 'connected-react-router';
1816
import FontFaceObserver from 'fontfaceobserver';
19-
import createHistory from 'history/createBrowserHistory';
20-
import { syncHistory } from 'redux-simple-router';
17+
import history from 'utils/history';
2118
import 'sanitize.css/sanitize.css';
2219

2320
// Import root app
24-
import App from 'containers/App/index';
21+
import App from 'containers/App';
2522

2623
// Import Language Provider
2724
import LanguageProvider from 'containers/LanguageProvider/index';
2825

2926
// Load the favicon, the manifest.json file and the .htaccess file
3027
/* eslint-disable import/no-unresolved, import/extensions */
3128
import '!file-loader?name=[name].[ext]!./images/favicon.png';
32-
import '!file-loader?name=[name].[ext]!./images/icon-72x72.png';
33-
import '!file-loader?name=[name].[ext]!./images/icon-96x96.png';
34-
import '!file-loader?name=[name].[ext]!./images/icon-128x128.png';
35-
import '!file-loader?name=[name].[ext]!./images/icon-144x144.png';
36-
import '!file-loader?name=[name].[ext]!./images/icon-152x152.png';
37-
import '!file-loader?name=[name].[ext]!./images/icon-192x192.png';
38-
import '!file-loader?name=[name].[ext]!./images/icon-384x384.png';
39-
import '!file-loader?name=[name].[ext]!./images/icon-512x512.png';
40-
import '!file-loader?name=[name].[ext]!./manifest.json';
4129
import '!file-loader?name=[name].[ext]!./osd.xml';
4230
import '!file-loader?name=[name].[ext]!./sitemap.xml';
4331
import 'file-loader?name=[name].[ext]!./.htaccess';
@@ -79,24 +67,15 @@ openSansObserver.load().then(
7967
);
8068

8169
// Create redux store with history
82-
const initialState = {};
83-
const history = createHistory();
84-
// Sync dispatched route actions to the history
85-
const reduxRouterMiddleware = syncHistory(history);
86-
const createStoreWithMiddleware = applyMiddleware(reduxRouterMiddleware)(
87-
configureStore,
88-
);
89-
90-
// const store = configureStore(initialState, history);
91-
const store = createStoreWithMiddleware(initialState, history);
70+
const store = configureStore(initialState, history);
9271
const MOUNT_NODE = document.getElementById('app');
9372

9473
const render = messages => {
9574
ReactDOM.render(
9675
<Provider store={store}>
9776
<LanguageProvider messages={messages}>
9877
<ConnectedRouter history={history}>
99-
<Route component={App} />
78+
<App />
10079
</ConnectedRouter>
10180
</LanguageProvider>
10281
</Provider>,
@@ -127,3 +106,10 @@ if (!window.Intl) {
127106
} else {
128107
render(translationMessages);
129108
}
109+
110+
// Install ServiceWorker and AppCache in the end since
111+
// it's not most important operation and if main code fails,
112+
// we do not want it installed
113+
if (process.env.NODE_ENV === 'production') {
114+
require('offline-plugin/runtime').install(); // eslint-disable-line global-require
115+
}

app/components/AssetInfo/index.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import React from 'react';
88
import PropTypes from 'prop-types';
99
import { compose } from 'redux';
1010
import { connect } from 'react-redux';
11-
import { routeActions } from 'redux-simple-router';
1211
import { Link } from 'react-router-dom';
1312
import styled from 'styled-components';
1413
import moment from 'moment/src/moment';

app/components/BlockList/index.jsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import styled from 'styled-components';
1010
import { Table, UncontrolledTooltip } from 'reactstrap';
1111

1212
import { FormattedMessage } from 'react-intl';
13-
import { routeActions } from 'redux-simple-router';
1413
import { connect } from 'react-redux';
1514
import { compose } from 'redux';
1615
import { createStructuredSelector } from 'reselect';
@@ -22,7 +21,7 @@ import AssetLink from 'components/AssetLink';
2221
import { FormattedUnixDateTime } from 'components/FormattedDateTime';
2322
import ColoredHash from 'components/ColoredHash';
2423
import SanitizedFormattedNumber from 'components/SanitizedFormattedNumber';
25-
import InformationIcon from 'react-icons/lib/io/informatcircled';
24+
import { InformationIcon } from 'react-icons/io';
2625

2726
import messages from './messages';
2827

@@ -253,7 +252,6 @@ BlockList.propTypes = {
253252

254253
function mapDispatchToProps(dispatch) {
255254
return {
256-
changeRoute: url => dispatch(routeActions.push(url)),
257255
getProperty: propertyId => dispatch(startFetch(propertyId)),
258256
dispatch,
259257
};

app/components/CrowdsaleInfo/index.jsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import React from 'react';
88
import PropTypes from 'prop-types';
9-
import { routeActions } from 'redux-simple-router';
109
import { connect } from 'react-redux';
1110
import { compose } from 'redux';
1211
import SanitizedFormattedNumber from 'components/SanitizedFormattedNumber';
@@ -120,7 +119,6 @@ CrowdsaleInfo.propTypes = {
120119

121120
function mapDispatchToProps(dispatch) {
122121
return {
123-
changeRoute: url => dispatch(routeActions.push(url)),
124122
dispatch,
125123
};
126124
}

app/components/CrowdsaleTransaction/index.jsx

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,11 @@ import PropTypes from 'prop-types';
99
import { compose } from 'redux';
1010
import { connect } from 'react-redux';
1111
import { Link } from 'react-router-dom';
12-
import { routeActions } from 'redux-simple-router';
1312
import { Col, Row, Tooltip } from 'reactstrap';
1413
import styled from 'styled-components';
1514

1615
import CopyToClipboard from 'react-copy-to-clipboard';
17-
import CopyIcon from 'react-icons/lib/io/ios-copy';
18-
import ArrowIconRight from 'react-icons/lib/io/arrow-right-c';
19-
import ArrowIconDown from 'react-icons/lib/io/arrow-down-c';
16+
import { ArrowIconDown, ArrowIconRight, CopyIcon } from 'react-icons/io';
2017

2118
import { CONFIRMATIONS } from 'containers/Transactions/constants';
2219
import { FormattedUnixDateTime } from 'components/FormattedDateTime';
@@ -84,56 +81,56 @@ const GrayArrowIconDown = styled(ArrowIconDown).attrs({
8481
class CrowdsaleTransaction extends React.PureComponent { // eslint-disable-line react/prefer-stateless-function
8582
constructor(props) {
8683
super(props);
87-
84+
8885
this.toggleTxTooltip = this.toggleTxTooltip.bind(this);
8986
this.toggleSenderTooltip = this.toggleSenderTooltip.bind(this);
9087
this.toggleRefererTooltip = this.toggleRefererTooltip.bind(this);
91-
88+
9289
this.state = {
9390
tooltipTxOpen: false,
9491
tooltipSenderOpen: false,
9592
tooltipRefererOpen: false,
9693
};
9794
}
98-
95+
9996
toggleTxTooltip() {
10097
this.setState({ tooltipTxOpen: true });
10198
setTimeout(() => this.setState({ tooltipTxOpen: false }), 1000);
10299
}
103-
100+
104101
toggleSenderTooltip() {
105102
this.setState({ tooltipSenderOpen: true });
106103
setTimeout(() => this.setState({ tooltipSenderOpen: false }), 1000);
107104
}
108-
105+
109106
toggleRefererTooltip() {
110107
this.setState({ tooltipRefererOpen: true });
111108
setTimeout(() => this.setState({ tooltipRefererOpen: false }), 1000);
112109
}
113-
110+
114111
getHighlightIfOwner(address) {
115112
return (this.isOwner(address) ? 'text-success' : '');
116113
}
117-
114+
118115
isOwner(address) {
119116
return (this.props.addr ? this.props.addr === address : false);
120117
}
121-
118+
122119
render() {
123120
let statusCSSClass = 'btn btn-primary btn-block font-weight-light w-50';
124121
statusCSSClass = (this.props.valid ? `${statusCSSClass} btn-blue` : (this.props.confirmations === 0 ? `${statusCSSClass} btn-warning` : `${statusCSSClass} btn-danger`));
125-
122+
126123
const status = StatusConfirmation({
127124
valid: this.props.valid,
128125
confirmations: this.props.confirmations,
129126
confirmed: CONFIRMATIONS,
130127
});
131-
128+
132129
let arrowcname;
133130
let arrowcnameright;
134131
let addresscname;
135132
let showreferencecname;
136-
133+
137134
if (this.props.referenceaddress) {
138135
arrowcname = 'transaction-arrow-icon';
139136
arrowcnameright = 'd-md-inline-flex';
@@ -143,11 +140,11 @@ class CrowdsaleTransaction extends React.PureComponent { // eslint-disable-line
143140
arrowcname = 'd-none';
144141
addresscname = 'd-none';
145142
}
146-
143+
147144
const txcopyid = `txid_${this.props.txid.slice(0, 12)}`;
148145
const sendercopyid = `s-${txcopyid}`;
149146
const referercopyid = `r-${txcopyid}`;
150-
147+
151148
const TransactionLabel = (props) => (props.type_int === 51 ?
152149
<WrapperTxLabel>{props.crowdsale.propertyname} crowdsale started</WrapperTxLabel> :
153150
<WrapperTxLabel>
@@ -167,7 +164,7 @@ class CrowdsaleTransaction extends React.PureComponent { // eslint-disable-line
167164
(+<SanitizedFormattedNumber value={props.issuertokens} fractionDigits={8}/> to Issuer)
168165
</WrapperTxLabel>
169166
);
170-
167+
171168
const txAsset = this.props.type_int === 51 ?
172169
{
173170
...this.props.crowdsale,
@@ -176,8 +173,8 @@ class CrowdsaleTransaction extends React.PureComponent { // eslint-disable-line
176173
{
177174
...this.props.dessiredToken,
178175
name: this.props.dessiredToken.propertyname,
179-
}
180-
176+
};
177+
181178
return (
182179
<div className="transation-result mx-auto text-center-down-md">
183180
<Row className="align-items-end pb-0">
@@ -186,7 +183,11 @@ class CrowdsaleTransaction extends React.PureComponent { // eslint-disable-line
186183
<AssetLogo
187184
asset={txAsset}
188185
prop={txAsset.propertyid}
189-
style={{width: '4rem', height: '4rem', marginRight: '7px'}}
186+
style={{
187+
width: '4rem',
188+
height: '4rem',
189+
marginRight: '7px',
190+
}}
190191
/>
191192
</AssetLink>
192193
</Col>
@@ -298,7 +299,6 @@ CrowdsaleTransaction.propTypes = {
298299

299300
function mapDispatchToProps(dispatch) {
300301
return {
301-
changeRoute: (url) => dispatch(routeActions.push(url)),
302302
dispatch,
303303
};
304304
}

app/components/ErrorBoundary/index.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { compose } from 'redux';
1111
import injectReducer from 'utils/injectReducer';
1212

1313
import { Alert, Button, Modal, ModalHeader, ModalBody, ModalFooter, Jumbotron } from 'reactstrap';
14-
import { routeActions } from 'redux-simple-router';
1514
import { makeSelectStatus } from 'components/ServiceBlock/selectors';
1615
import { Link } from 'react-router-dom';
1716
import moment from 'moment/src/moment';

app/components/ErrorBoundary/reducer.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import {
66
ERROR_CLEAN,
77
} from './constants';
88

9-
const initialState = fromJS({
9+
const initialState = {
1010
error: null,
1111
errorInfo: null,
1212
modal: false,
13-
});
13+
};
1414

1515
const errorBoundaryReducer = (state = initialState, action = {}) => {
1616
const { error, errorInfo, type } = action;

app/components/Footer/index.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import { FormattedMessage } from 'react-intl';
33
import styled from 'styled-components';
4-
import HeartIcon from 'react-icons/lib/io/heart';
4+
import { HeartIcon } from 'react-icons/io';
55
import messages from './messages';
66

77
const Wrapper = styled.footer`
@@ -30,7 +30,7 @@ function Footer() {
3030
<FormattedMessage
3131
{...messages.authorMessage}
3232
values={{
33-
love: <HeartIcon color="red" size={24} />,
33+
love: <HeartIcon color="red" size={24}/>,
3434
author: <A href="http://www.omnilayer.org/">The Omni Foundation</A>,
3535
}}
3636
/>

app/components/Header/index.jsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import React from 'react';
88
import PropTypes from 'prop-types';
99
import { compose } from 'redux';
1010
import { connect } from 'react-redux';
11-
import { routeActions } from 'redux-simple-router';
1211
import styled from 'styled-components';
1312
import SearchBox from 'components/SearchBox';
1413
import { ECOSYSTEM_PROD_NAME, ECOSYSTEM_TEST_NAME } from 'containers/App/constants';
@@ -175,7 +174,6 @@ NavbarToggler.propTypes = {
175174

176175
function mapDispatchToProps(dispatch) {
177176
return {
178-
changeRoute: (url) => dispatch(routeActions.push(url)),
179177
dispatch,
180178
};
181179
}

0 commit comments

Comments
 (0)