From a7cd381e968fca0df01aca3cd2e3dd67da4c27b6 Mon Sep 17 00:00:00 2001 From: Nedim Uka Date: Mon, 16 Apr 2018 17:10:06 +0200 Subject: [PATCH] Added redux structure that remebers state --- frontend/config/webpackDevServer.config.js | 1 + frontend/package-lock.json | 34 ++++++++++++ frontend/package.json | 2 + frontend/src/actions/index.js | 6 +++ .../App/Dashboard/dashboard.test.js | 14 +++-- .../src/components/App/Dashboard/index.js | 11 +++- .../Dummy/__snapshots__/dummy.test.js.snap | 10 ---- .../src/components/App/Dummy/dummy.test.js | 12 ----- frontend/src/components/App/Dummy/index.js | 8 --- frontend/src/components/App/Dummy/styles.scss | 3 -- .../src/components/App/Header/styles.scss | 4 +- frontend/src/components/App/Inbox/index.js | 13 +++-- frontend/src/components/App/Mytask/index.js | 11 +++- frontend/src/components/App/Root/index.js | 53 +++++++++++++++++++ frontend/src/components/App/index.js | 7 +-- frontend/src/index.js | 22 +++----- frontend/src/reducers/index.js | 7 +++ frontend/src/reducers/router.js | 14 +++++ 18 files changed, 166 insertions(+), 66 deletions(-) create mode 100644 frontend/src/actions/index.js delete mode 100644 frontend/src/components/App/Dummy/__snapshots__/dummy.test.js.snap delete mode 100644 frontend/src/components/App/Dummy/dummy.test.js delete mode 100644 frontend/src/components/App/Dummy/index.js delete mode 100644 frontend/src/components/App/Dummy/styles.scss create mode 100644 frontend/src/components/App/Root/index.js create mode 100644 frontend/src/reducers/index.js create mode 100644 frontend/src/reducers/router.js diff --git a/frontend/config/webpackDevServer.config.js b/frontend/config/webpackDevServer.config.js index f12d315..9e591dc 100644 --- a/frontend/config/webpackDevServer.config.js +++ b/frontend/config/webpackDevServer.config.js @@ -79,6 +79,7 @@ module.exports = function(proxy, allowedHost) { // See https://github.com/facebookincubator/create-react-app/issues/387. disableDotRule: true, }, + historyApiFallback: true, public: allowedHost, proxy, before(app) { diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 747467a..1e8fba1 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -7272,6 +7272,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" }, + "lodash-es": { + "version": "4.17.8", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.8.tgz", + "integrity": "sha512-I9mjAxengFAleSThFhhAhvba6fsO0hunb9/0sQ6qQihSZsJRBofv2rYH58WXaOb/O++eUmYpCLywSQ22GfU+sA==" + }, "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -10089,6 +10094,19 @@ "prop-types": "15.6.1" } }, + "react-redux": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz", + "integrity": "sha512-5VI8EV5hdgNgyjfmWzBbdrqUkrVRKlyTKk1sGH3jzM2M2Mhj/seQgPXaz6gVAj2lz/nz688AdTqMO18Lr24Zhg==", + "requires": { + "hoist-non-react-statics": "2.5.0", + "invariant": "2.2.4", + "lodash": "4.17.5", + "lodash-es": "4.17.8", + "loose-envify": "1.3.1", + "prop-types": "15.6.1" + } + }, "react-router": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.2.0.tgz", @@ -10257,6 +10275,17 @@ } } }, + "redux": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", + "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", + "requires": { + "lodash": "4.17.5", + "lodash-es": "4.17.8", + "loose-envify": "1.3.1", + "symbol-observable": "1.2.0" + } + }, "regenerate": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", @@ -11513,6 +11542,11 @@ "serviceworker-cache-polyfill": "4.0.0" } }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + }, "symbol-tree": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index 113e81e..0453a21 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -40,8 +40,10 @@ "react": "^16.3.1", "react-dev-utils": "^5.0.1", "react-dom": "^16.3.1", + "react-redux": "^5.0.7", "react-router-dom": "^4.2.2", "react-test-renderer": "^16.3.1", + "redux": "^3.7.2", "resolve": "1.6.0", "sass-loader": "^6.0.7", "style-loader": "0.19.0", diff --git a/frontend/src/actions/index.js b/frontend/src/actions/index.js new file mode 100644 index 0000000..b36e241 --- /dev/null +++ b/frontend/src/actions/index.js @@ -0,0 +1,6 @@ +export const INIT_PAGE = 'INIT_PAGE' + +export const initPage = titles => ({ + type: INIT_PAGE, + titles +}) \ No newline at end of file diff --git a/frontend/src/components/App/Dashboard/dashboard.test.js b/frontend/src/components/App/Dashboard/dashboard.test.js index 3fb06c3..2dc9376 100644 --- a/frontend/src/components/App/Dashboard/dashboard.test.js +++ b/frontend/src/components/App/Dashboard/dashboard.test.js @@ -1,12 +1,20 @@ import React from 'react'; import {MemoryRouter as Router} from 'react-router-dom' import Dashboard from './index'; +import {mount} from 'enzyme' import renderer from 'react-test-renderer'; test('Dummy renders correctly', () => { - const component = renderer.create( - , - ); + + const props = { + title: 'Dashboard', + } + + + // // const component = renderer.create( + // , + // ); + const component = mount(()) let tree = component.toJSON(); expect(tree).toMatchSnapshot(); }); \ No newline at end of file diff --git a/frontend/src/components/App/Dashboard/index.js b/frontend/src/components/App/Dashboard/index.js index 4d5d685..f0a2092 100644 --- a/frontend/src/components/App/Dashboard/index.js +++ b/frontend/src/components/App/Dashboard/index.js @@ -1,9 +1,16 @@ import React from 'react'; +import { connect } from 'react-redux' import styles from './styles.scss'; import Header from '../Header/index' const Dashboard = (props) => { - return
Dashboard
; + return
Title {props.title}
; }; -export default Dashboard; \ No newline at end of file +const mapStateToProps = (state) => { + return { + title: state.pageInitialised.titles.title, + } +} + +export default connect(mapStateToProps)(Dashboard); \ No newline at end of file diff --git a/frontend/src/components/App/Dummy/__snapshots__/dummy.test.js.snap b/frontend/src/components/App/Dummy/__snapshots__/dummy.test.js.snap deleted file mode 100644 index 267ee06..0000000 --- a/frontend/src/components/App/Dummy/__snapshots__/dummy.test.js.snap +++ /dev/null @@ -1,10 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Dummy renders correctly 1`] = ` -
- Hello, - Hamo -
-`; diff --git a/frontend/src/components/App/Dummy/dummy.test.js b/frontend/src/components/App/Dummy/dummy.test.js deleted file mode 100644 index 6c762e2..0000000 --- a/frontend/src/components/App/Dummy/dummy.test.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import Dummy from './index'; -import renderer from 'react-test-renderer'; - -test('Dummy renders correctly', () => { - const component = renderer.create( - , - ); - let tree = component.toJSON(); - expect(tree).toMatchSnapshot(); -}); - diff --git a/frontend/src/components/App/Dummy/index.js b/frontend/src/components/App/Dummy/index.js deleted file mode 100644 index 17b0f60..0000000 --- a/frontend/src/components/App/Dummy/index.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import styles from './styles.scss'; - -const Dummy = (props) => { - return
Hello, {props.name}
; -}; - -export default Dummy; \ No newline at end of file diff --git a/frontend/src/components/App/Dummy/styles.scss b/frontend/src/components/App/Dummy/styles.scss deleted file mode 100644 index 7955f5e..0000000 --- a/frontend/src/components/App/Dummy/styles.scss +++ /dev/null @@ -1,3 +0,0 @@ -.colored { - color: blueviolet; -} \ No newline at end of file diff --git a/frontend/src/components/App/Header/styles.scss b/frontend/src/components/App/Header/styles.scss index d842e29..883c5f7 100644 --- a/frontend/src/components/App/Header/styles.scss +++ b/frontend/src/components/App/Header/styles.scss @@ -1,6 +1,6 @@ .Header { - padding-top : 12px; - padding-bottom : 12px; + padding-top : 6px; + padding-bottom : 6px; display: flex; justify-content: space-between; align-items:center; diff --git a/frontend/src/components/App/Inbox/index.js b/frontend/src/components/App/Inbox/index.js index b8bf780..0665193 100644 --- a/frontend/src/components/App/Inbox/index.js +++ b/frontend/src/components/App/Inbox/index.js @@ -1,9 +1,16 @@ import React from 'react'; +import {connect} from 'react-redux' import styles from './styles.scss'; import Header from '../Header/index' -const Inbox = (props) => { - return
Inbox
; +const Inbox = (props) => { + return
Title {props.title}
; }; -export default Inbox; \ No newline at end of file +const mapStateToProps = (state) => { + return { + title: state.pageInitialised.titles.title, + } +} + +export default connect(mapStateToProps)(Inbox); \ No newline at end of file diff --git a/frontend/src/components/App/Mytask/index.js b/frontend/src/components/App/Mytask/index.js index 18b409f..a6b4bdb 100644 --- a/frontend/src/components/App/Mytask/index.js +++ b/frontend/src/components/App/Mytask/index.js @@ -1,9 +1,16 @@ import React from 'react'; +import { connect } from 'react-redux' import styles from './styles.scss'; import Header from '../Header/index' const MyTask = (props) => { - return
My Task
; + return
Title {props.title}
; }; -export default MyTask; \ No newline at end of file +const mapStateToProps = (state) => { + return { + title: state.pageInitialised.titles.title, + } +} + +export default connect(mapStateToProps)(MyTask); \ No newline at end of file diff --git a/frontend/src/components/App/Root/index.js b/frontend/src/components/App/Root/index.js new file mode 100644 index 0000000..4479c04 --- /dev/null +++ b/frontend/src/components/App/Root/index.js @@ -0,0 +1,53 @@ +import React, { Component } from 'react' +import { Provider } from 'react-redux' +import { BrowserRouter as Router, Route } from 'react-router-dom' + +import App from '../index' +import Inbox from '../Inbox/index'; +import MyTask from '../Mytask/index'; +import Dashboard from '../Dashboard/index'; +import { initPage } from '../../../actions/index' + +class Root extends Component { + + + render() { + return ( + + +
+ + + + +
+
+
+ ); + } + +} + +/** + * Pass this function to `react-router-dom` Route component property + * In orderd to triger redux action that is related to te Route path + * If such action exists + * + * @param {} WrappedComponent a React component to render + * @param {*} props a an object containing redux `store` to dispach initPage action with route path name + * @returns A new HIGHT ORDER React component from WrappedComponent after redux action is dispatched + */ +let mountComponentWithPathAction = function (WrappedComponent, props) { + return class extends Component { + + componentWillMount() { + props.store.dispatch(initPage({ pathName: this.props.location.pathname })) + } + + render() { + return + } + } +} + +export default Root \ No newline at end of file diff --git a/frontend/src/components/App/index.js b/frontend/src/components/App/index.js index 2653c34..b56e0a2 100644 --- a/frontend/src/components/App/index.js +++ b/frontend/src/components/App/index.js @@ -1,15 +1,10 @@ import React, { Component } from 'react'; -import styles from './styles.scss'; import Header from './Header'; class App extends Component { render() { return ( -
-
-

-
-
+
); } } diff --git a/frontend/src/index.js b/frontend/src/index.js index 9592b70..ab8be68 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -1,23 +1,15 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { BrowserRouter as Router, Route } from 'react-router-dom' +import { createStore } from 'redux' import './index.css'; -import App from './components/App'; import registerServiceWorker from './registerServiceWorker'; -import Inbox from './components/App/Inbox/index'; -import MyTask from './components/App/Mytask/index'; -import Dashboard from './components/App/Dashboard/index'; -import Dummy from './components/App/Dummy/index'; + +import subtaskIo from './reducers/index' +import Root from './components/App/Root/index'; + +const store = createStore(subtaskIo) ReactDOM.render( - -
- - - - -
-
- , + , document.getElementById('root')); registerServiceWorker(); diff --git a/frontend/src/reducers/index.js b/frontend/src/reducers/index.js new file mode 100644 index 0000000..3f974f5 --- /dev/null +++ b/frontend/src/reducers/index.js @@ -0,0 +1,7 @@ +import { combineReducers } from 'redux' +import pageInitialised from './router' + +const subtaskIo = combineReducers({ + pageInitialised, +}) +export default subtaskIo \ No newline at end of file diff --git a/frontend/src/reducers/router.js b/frontend/src/reducers/router.js new file mode 100644 index 0000000..83e4318 --- /dev/null +++ b/frontend/src/reducers/router.js @@ -0,0 +1,14 @@ +const pageInitialised = (state = { + titles: { title: 'Default title' }, +}, action) => { + switch (action.type) { + case 'INIT_PAGE': + return { + ...state, + titles: { title: action.titles.pathName } + } + default: + return state + } +} +export default pageInitialised \ No newline at end of file