From e8fe44b598777452a502eb82abd812bd514ef752 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Fri, 28 Jul 2017 11:27:34 +0200 Subject: [PATCH 1/6] Add global loading bar --- src/components/app/index.js | 3 ++- src/components/loadingBar/index.js | 10 ++++++++++ src/components/loadingBar/loadingBar.css | 6 ++++++ src/components/loadingBar/loadingBar.js | 14 ++++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/components/loadingBar/index.js create mode 100644 src/components/loadingBar/loadingBar.css create mode 100644 src/components/loadingBar/loadingBar.js diff --git a/src/components/app/index.js b/src/components/app/index.js index 686b95904..b22952cad 100644 --- a/src/components/app/index.js +++ b/src/components/app/index.js @@ -11,7 +11,7 @@ import styles from './app.css'; import Metronome from '../../utils/metronome'; import Dialog from '../dialog'; import Tabs from '../tabs'; - // temporary, will be deleted with #347 +import LoadingBar from '../loadingBar'; // start dispatching sync ticks const metronome = new Metronome(); @@ -33,6 +33,7 @@ const App = () => ( + ); diff --git a/src/components/loadingBar/index.js b/src/components/loadingBar/index.js new file mode 100644 index 000000000..fad488caa --- /dev/null +++ b/src/components/loadingBar/index.js @@ -0,0 +1,10 @@ + +import { connect } from 'react-redux'; +import LoadingBar from './loadingBar'; + +const mapStateToProps = state => ({ + loadingBar: state.loadingBar, +}); + +export default connect(mapStateToProps)(LoadingBar); + diff --git a/src/components/loadingBar/loadingBar.css b/src/components/loadingBar/loadingBar.css new file mode 100644 index 000000000..8abed99fd --- /dev/null +++ b/src/components/loadingBar/loadingBar.css @@ -0,0 +1,6 @@ +.fixedAtTop { + position: fixed; + top: -10px; + right: 0; + width: 100vw; +} diff --git a/src/components/loadingBar/loadingBar.js b/src/components/loadingBar/loadingBar.js new file mode 100644 index 000000000..cc9cc9a06 --- /dev/null +++ b/src/components/loadingBar/loadingBar.js @@ -0,0 +1,14 @@ +import React from 'react'; +import ProgressBar from 'react-toolbox/lib/progress_bar'; +import styles from './loadingBar.css'; + +const LoadingBar = props => ( +
+ {props.loadingBar && props.loadingBar.length ? + : + null + } +
+); + +export default LoadingBar; From cad3526ae1a410afd98248f8d96b6179c1ae2219 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Mon, 31 Jul 2017 16:57:26 +0200 Subject: [PATCH 2/6] Fix some issues of loadingBar component --- src/components/loadingBar/index.js | 2 +- src/components/loadingBar/loadingBar.css | 3 ++- src/components/loadingBar/loadingBar.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/loadingBar/index.js b/src/components/loadingBar/index.js index fad488caa..86a17267f 100644 --- a/src/components/loadingBar/index.js +++ b/src/components/loadingBar/index.js @@ -3,7 +3,7 @@ import { connect } from 'react-redux'; import LoadingBar from './loadingBar'; const mapStateToProps = state => ({ - loadingBar: state.loadingBar, + loading: state.loading, }); export default connect(mapStateToProps)(LoadingBar); diff --git a/src/components/loadingBar/loadingBar.css b/src/components/loadingBar/loadingBar.css index 8abed99fd..537c6cc38 100644 --- a/src/components/loadingBar/loadingBar.css +++ b/src/components/loadingBar/loadingBar.css @@ -1,6 +1,7 @@ .fixedAtTop { position: fixed; - top: -10px; + top: -11px; right: 0; width: 100vw; + z-index: 201; } diff --git a/src/components/loadingBar/loadingBar.js b/src/components/loadingBar/loadingBar.js index cc9cc9a06..9c4110ce9 100644 --- a/src/components/loadingBar/loadingBar.js +++ b/src/components/loadingBar/loadingBar.js @@ -4,7 +4,7 @@ import styles from './loadingBar.css'; const LoadingBar = props => (
- {props.loadingBar && props.loadingBar.length ? + {props.loading.length ? : null } From 6b7598aa42844cc73285d10dbdf0b4d6bf7b00f2 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Mon, 31 Jul 2017 16:57:56 +0200 Subject: [PATCH 3/6] Add actions, reducers and utils for loading bar --- src/actions/loading.js | 19 +++++++++++++++++++ src/constants/actions.js | 2 ++ src/store/reducers/index.js | 1 + src/store/reducers/loading.js | 19 +++++++++++++++++++ src/utils/loading.js | 7 +++++++ 5 files changed, 48 insertions(+) create mode 100644 src/actions/loading.js create mode 100644 src/store/reducers/loading.js create mode 100644 src/utils/loading.js diff --git a/src/actions/loading.js b/src/actions/loading.js new file mode 100644 index 000000000..6a948d34b --- /dev/null +++ b/src/actions/loading.js @@ -0,0 +1,19 @@ +import actionTypes from '../constants/actions'; + +/** + * An action to dispatch loadingStarted + * + */ +export const loadingStarted = data => ({ + data, + type: actionTypes.loadingStarted, +}); + +/** + * An action to dispatch loadingFinished + * + */ +export const loadingFinished = data => ({ + data, + type: actionTypes.loadingFinished, +}); diff --git a/src/constants/actions.js b/src/constants/actions.js index 11fdbca0f..da81e2b76 100644 --- a/src/constants/actions.js +++ b/src/constants/actions.js @@ -8,6 +8,8 @@ const actionTypes = { dialogHidden: 'DIALOG_HIDDEN', forgedBlocksUpdated: 'FORGED_BLOCKS_UPDATED', forgingStatsUpdated: 'FORGING_STATS_UPDATED', + loadingStarted: 'LOADING_STARTED', + loadingFinished: 'LOADING_FINISHED', }; export default actionTypes; diff --git a/src/store/reducers/index.js b/src/store/reducers/index.js index 9dca54638..d2d18cd81 100644 --- a/src/store/reducers/index.js +++ b/src/store/reducers/index.js @@ -2,4 +2,5 @@ export { default as account } from './account'; export { default as peers } from './peers'; export { default as dialog } from './dialog'; export { default as forging } from './forging'; +export { default as loading } from './loading'; diff --git a/src/store/reducers/loading.js b/src/store/reducers/loading.js new file mode 100644 index 000000000..2d3ab5bdd --- /dev/null +++ b/src/store/reducers/loading.js @@ -0,0 +1,19 @@ +import actionTypes from '../../constants/actions'; + +/** + * + * @param {Array} state + * @param {Object} action + */ +const dialog = (state = [], action) => { + switch (action.type) { + case actionTypes.loadingStarted: + return [...state, action.data]; + case actionTypes.loadingFinished: + return state.filter(item => item !== action.data); + default: + return state; + } +}; + +export default dialog; diff --git a/src/utils/loading.js b/src/utils/loading.js new file mode 100644 index 000000000..793699a2e --- /dev/null +++ b/src/utils/loading.js @@ -0,0 +1,7 @@ +import { loadingStarted as loadingStartedAction, loadingFinished as loadingFinishedAction } from '../actions/loading'; +import store from '../store'; + + +export const loadingStarted = data => store.dispatch(loadingStartedAction(data)); + +export const loadingFinished = data => store.dispatch(loadingFinishedAction(data)); From bbeb24da19370974d62463a3dd3d882c55bdb0be Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Mon, 31 Jul 2017 16:58:31 +0200 Subject: [PATCH 4/6] Show loading bar on each api request --- src/utils/api/peers.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utils/api/peers.js b/src/utils/api/peers.js index fd94c4018..76d32f0bb 100644 --- a/src/utils/api/peers.js +++ b/src/utils/api/peers.js @@ -1,12 +1,16 @@ +import { loadingStarted, loadingFinished } from '../../utils/loading'; + /* eslint-disable */ export const requestToActivePeer = (activePeer, path, urlParams) => new Promise((resolve, reject) => { + loadingStarted(path); activePeer.sendRequest(path, urlParams, (data) => { if (data.success) { resolve(data); } else { reject(data); } + loadingFinished(path); }); }); /* eslint-enable */ From 7b5f0810dde8096faf9ff88b372b8bc4583b8bf9 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Mon, 31 Jul 2017 17:47:06 +0200 Subject: [PATCH 5/6] Add unit tests for loadingBar --- src/actions/loding.test.js | 33 +++++++++++++++++++ src/components/loadingBar/index.test.js | 19 +++++++++++ src/components/loadingBar/loadingBar.test.js | 17 ++++++++++ src/store/reducers/loding.test.js | 34 ++++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 src/actions/loding.test.js create mode 100644 src/components/loadingBar/index.test.js create mode 100644 src/components/loadingBar/loadingBar.test.js create mode 100644 src/store/reducers/loding.test.js diff --git a/src/actions/loding.test.js b/src/actions/loding.test.js new file mode 100644 index 000000000..ab9fa12ae --- /dev/null +++ b/src/actions/loding.test.js @@ -0,0 +1,33 @@ +import { expect } from 'chai'; +import actionTypes from '../constants/actions'; +import { + loadingStarted, + loadingFinished, +} from './loading'; + + +describe('actions: loading', () => { + describe('loadingStarted', () => { + it('should create an action to show loading bar', () => { + const data = 'test'; + + const expectedAction = { + data, + type: actionTypes.loadingStarted, + }; + expect(loadingStarted(data)).to.be.deep.equal(expectedAction); + }); + }); + + describe('loadingFinished', () => { + it('should create an action to hide loading bar', () => { + const data = 'test'; + + const expectedAction = { + data, + type: actionTypes.loadingFinished, + }; + expect(loadingFinished(data)).to.be.deep.equal(expectedAction); + }); + }); +}); diff --git a/src/components/loadingBar/index.test.js b/src/components/loadingBar/index.test.js new file mode 100644 index 000000000..52e8e58ce --- /dev/null +++ b/src/components/loadingBar/index.test.js @@ -0,0 +1,19 @@ +import React from 'react'; +import { expect } from 'chai'; +import { mount } from 'enzyme'; +import { Provider } from 'react-redux'; +import LoadingBar from './'; +import store from '../../store'; + + +describe('LoadingBar Container', () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(); + }); + + it('should render Send', () => { + expect(wrapper.find('LoadingBar')).to.have.lengthOf(1); + }); +}); diff --git a/src/components/loadingBar/loadingBar.test.js b/src/components/loadingBar/loadingBar.test.js new file mode 100644 index 000000000..4f366b24d --- /dev/null +++ b/src/components/loadingBar/loadingBar.test.js @@ -0,0 +1,17 @@ +import React from 'react'; +import { expect } from 'chai'; +import { mount } from 'enzyme'; +import LoadingBar from './loadingBar'; + + +describe('LoadingBar Container', () => { + it('should show ProgresBar if props.loading.length is not 0', () => { + const wrapper = mount(); + expect(wrapper.find('ProgressBar')).to.have.lengthOf(1); + }); + + it('should not show ProgresBar if props.loading.length is 0', () => { + const wrapper = mount(); + expect(wrapper.find('ProgressBar')).to.have.lengthOf(0); + }); +}); diff --git a/src/store/reducers/loding.test.js b/src/store/reducers/loding.test.js new file mode 100644 index 000000000..2b13bda28 --- /dev/null +++ b/src/store/reducers/loding.test.js @@ -0,0 +1,34 @@ +import chai, { expect } from 'chai'; +import sinonChai from 'sinon-chai'; +import loading from './loading'; +import actionTypes from '../../constants/actions'; + + +chai.use(sinonChai); + +describe('Reducer: loading(state, action)', () => { + let state; + + beforeEach(() => { + state = ['test1', 'test2']; + }); + + it('should return loading array with the new loading if action.type = actionTypes.loadingStarted', () => { + const action = { + type: actionTypes.loadingStarted, + data: 'test3', + }; + const changedState = loading(state, action); + expect(changedState).to.deep.equal([...state, action.data]); + }); + + it('should return loading array without action.data if action.type = actionTypes.loadingFinished', () => { + const action = { + type: actionTypes.loadingFinished, + data: 'test1', + }; + const changedState = loading(state, action); + expect(changedState).to.deep.equal(['test2']); + }); +}); + From 0b3b485d1c1dfd68da6d1733706193b25a4141fe Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Mon, 31 Jul 2017 17:47:40 +0200 Subject: [PATCH 6/6] Cover the case when loading is undefined --- src/components/loadingBar/loadingBar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/loadingBar/loadingBar.js b/src/components/loadingBar/loadingBar.js index 9c4110ce9..99827c14d 100644 --- a/src/components/loadingBar/loadingBar.js +++ b/src/components/loadingBar/loadingBar.js @@ -4,7 +4,7 @@ import styles from './loadingBar.css'; const LoadingBar = props => (
- {props.loading.length ? + {props.loading && props.loading.length ? : null }