From 59650ed96fccea1269bbc17a17db92538c569d1c Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Mon, 20 Jun 2016 09:55:43 -0700 Subject: [PATCH 01/16] add front-end dependencies --- package.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/package.json b/package.json index 021a5049..e87ffe42 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,11 @@ "chai": "^3.5.0", "electron-is-dev": "^0.1.1", "mocha": "^2.5.3", + "node-jsx": "^0.13.3", + "react": "^15.1.0", + "react-dom": "^15.1.0", + "react-photonkit": "^0.4.1", + "react-router": "^2.4.1", "winston": "^2.2.0" } } From 25948746e6acec3fd43871ce10dcd139838b6219 Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Mon, 20 Jun 2016 10:17:53 -0700 Subject: [PATCH 02/16] add starter code --- app/components/app.jsx | 16 ++++++++++++++++ app/index.html | 13 ++++++------- app/index.js | 6 ++++++ app/renderer.js | 5 ----- app/routes.jsx | 12 ++++++++++++ 5 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 app/components/app.jsx create mode 100644 app/index.js delete mode 100644 app/renderer.js create mode 100644 app/routes.jsx diff --git a/app/components/app.jsx b/app/components/app.jsx new file mode 100644 index 00000000..fd239218 --- /dev/null +++ b/app/components/app.jsx @@ -0,0 +1,16 @@ +"use strict" + +const React = require('react') +const Window = require('react-photonkit').Window + +var App = React.createClass({ + render: () => { + return ( + +

Hello World!

+
+ ) + } +}) + +module.exports = App diff --git a/app/index.html b/app/index.html index 26988b20..926fe165 100644 --- a/app/index.html +++ b/app/index.html @@ -5,15 +5,14 @@ Classroom Desktop 0.0.1 -

Hello World! 0.0.1

- - We are using node , - Chromium , - and Electron . +
diff --git a/app/index.js b/app/index.js new file mode 100644 index 00000000..27313ba3 --- /dev/null +++ b/app/index.js @@ -0,0 +1,6 @@ +"use strict" + +const render = require("react-dom").render +const routes = require("./routes") + +render(routes, document.getElementById("app")) diff --git a/app/renderer.js b/app/renderer.js deleted file mode 100644 index 31c58dc3..00000000 --- a/app/renderer.js +++ /dev/null @@ -1,5 +0,0 @@ -const logger = require("./renderer-logger") - -setInterval(() => { - logger.info("Browser log!") -}, 1000) diff --git a/app/routes.jsx b/app/routes.jsx new file mode 100644 index 00000000..0ae8a185 --- /dev/null +++ b/app/routes.jsx @@ -0,0 +1,12 @@ +"use strict" + +const {hashHistory, Route, Router} = require("react-router") +const React = require("react") + +const App = require("./components/app") + +module.exports = ( + + + +) From 66f8736a91c30cee99d9a781fddc5e5715be82c2 Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Mon, 20 Jun 2016 10:25:45 -0700 Subject: [PATCH 03/16] update eslint --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e87ffe42..68f21ef4 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "devDependencies": { "electron-packager": "^7.0.4", "electron-prebuilt": "^1.2.0", - "eslint": "^2.12.0", + "eslint": "^2.13.0", "eslint-config-standard": "^5.3.1", "eslint-plugin-promise": "^1.3.2", "eslint-plugin-react": "^5.2.1", From 21d2253eb1e2f47fe551c295cda59869ff2ede45 Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Mon, 20 Jun 2016 11:06:00 -0700 Subject: [PATCH 04/16] fix eslint scope and linting jsx files --- .eslintignore | 2 ++ .eslintrc.js | 4 +++- app/routes.jsx | 2 +- package.json | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 .eslintignore diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..de4d1f00 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +dist +node_modules diff --git a/.eslintrc.js b/.eslintrc.js index ebf8b95b..6ab3efd3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -32,6 +32,8 @@ module.exports = { "semi": [ "error", "never" - ] + ], + "react/jsx-uses-vars": "error", + "react/jsx-uses-react": "error" } }; diff --git a/app/routes.jsx b/app/routes.jsx index 0ae8a185..d54a38c7 100644 --- a/app/routes.jsx +++ b/app/routes.jsx @@ -1,7 +1,7 @@ "use strict" -const {hashHistory, Route, Router} = require("react-router") const React = require("react") +const {hashHistory, Route, Router} = require("react-router") const App = require("./components/app") diff --git a/package.json b/package.json index 68f21ef4..e25e8b9c 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "main": "main.js", "scripts": { "start": "electron main.js", - "test": "node_modules/.bin/eslint . && node_modules/mocha/bin/mocha test", + "test": "node_modules/.bin/eslint **/*.js **/*.jsx && node_modules/mocha/bin/mocha test", "build-mac": "electron-packager . Classroom --platform=darwin --arch=x64 --out=dist --overwrite" }, "repository": { From e89f620042c438647eaf9ef2c043d17e8b026544 Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Mon, 20 Jun 2016 11:19:52 -0700 Subject: [PATCH 05/16] fix eslint scoping again --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e25e8b9c..1b8bfb22 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "main": "main.js", "scripts": { "start": "electron main.js", - "test": "node_modules/.bin/eslint **/*.js **/*.jsx && node_modules/mocha/bin/mocha test", + "test": "node_modules/.bin/eslint --ext .js,.jsx . && node_modules/mocha/bin/mocha test", "build-mac": "electron-packager . Classroom --platform=darwin --arch=x64 --out=dist --overwrite" }, "repository": { From 4f3c28749f8c334c3d215d5da3ac1bc46454ef59 Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Mon, 20 Jun 2016 11:29:22 -0700 Subject: [PATCH 06/16] fix style errors and add a few photonkit components --- app/components/app.jsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/components/app.jsx b/app/components/app.jsx index fd239218..8946903c 100644 --- a/app/components/app.jsx +++ b/app/components/app.jsx @@ -1,13 +1,15 @@ "use strict" -const React = require('react') -const Window = require('react-photonkit').Window +const React = require("react") +const {Window, Toolbar, Content} = require("react-photonkit") var App = React.createClass({ render: () => { return ( -

Hello World!

+ + +
) } From 9afd16b7a2dc198152ff1ded903f8ff8d5a194f7 Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Tue, 21 Jun 2016 10:18:44 -0700 Subject: [PATCH 07/16] strip down app, replace node-jsx with babel --- .babelrc | 1 + .eslintrc.js | 4 ++++ app/components/app.jsx | 18 ------------------ app/index.html | 7 ++----- app/index.js | 6 ------ app/index.jsx | 32 ++++++++++++++++++++++++++++++++ app/routes.jsx | 12 ------------ package.json | 10 ++++++++-- 8 files changed, 47 insertions(+), 43 deletions(-) create mode 100644 .babelrc delete mode 100644 app/components/app.jsx delete mode 100644 app/index.js create mode 100644 app/index.jsx delete mode 100644 app/routes.jsx diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..b00b3d64 --- /dev/null +++ b/.babelrc @@ -0,0 +1 @@ +{ "presets": ["es2015", "react"] } diff --git a/.eslintrc.js b/.eslintrc.js index 6ab3efd3..7dc49720 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -33,6 +33,10 @@ module.exports = { "error", "never" ], + "jsx-quotes": [ + "error", + "prefer-double" + ], "react/jsx-uses-vars": "error", "react/jsx-uses-react": "error" } diff --git a/app/components/app.jsx b/app/components/app.jsx deleted file mode 100644 index 8946903c..00000000 --- a/app/components/app.jsx +++ /dev/null @@ -1,18 +0,0 @@ -"use strict" - -const React = require("react") -const {Window, Toolbar, Content} = require("react-photonkit") - -var App = React.createClass({ - render: () => { - return ( - - - - - - ) - } -}) - -module.exports = App diff --git a/app/index.html b/app/index.html index 926fe165..69300ebf 100644 --- a/app/index.html +++ b/app/index.html @@ -9,10 +9,7 @@ diff --git a/app/index.js b/app/index.js deleted file mode 100644 index 27313ba3..00000000 --- a/app/index.js +++ /dev/null @@ -1,6 +0,0 @@ -"use strict" - -const render = require("react-dom").render -const routes = require("./routes") - -render(routes, document.getElementById("app")) diff --git a/app/index.jsx b/app/index.jsx new file mode 100644 index 00000000..c33b772c --- /dev/null +++ b/app/index.jsx @@ -0,0 +1,32 @@ +import * as React from "react" +import * as ReactDOM from "react-dom" +import {Window, Toolbar, Content, Pane, ListGroup, ListItem} from "react-photonkit" + +const App = () => { + return ( + + + + + + + + ... + + + + + + ) +} + +ReactDOM.render( + +, document.getElementById("app")) diff --git a/app/routes.jsx b/app/routes.jsx deleted file mode 100644 index d54a38c7..00000000 --- a/app/routes.jsx +++ /dev/null @@ -1,12 +0,0 @@ -"use strict" - -const React = require("react") -const {hashHistory, Route, Router} = require("react-router") - -const App = require("./components/app") - -module.exports = ( - - - -) diff --git a/package.json b/package.json index 1b8bfb22..326a7917 100644 --- a/package.json +++ b/package.json @@ -27,17 +27,23 @@ "eslint-config-standard": "^5.3.1", "eslint-plugin-promise": "^1.3.2", "eslint-plugin-react": "^5.2.1", - "eslint-plugin-standard": "^1.3.2" + "eslint-plugin-standard": "^1.3.2", + "redux-devtools": "^3.3.1" }, "dependencies": { + "babel-preset-es2015": "^6.9.0", + "babel-preset-react": "^6.5.0", + "babel-register": "^6.9.0", "chai": "^3.5.0", "electron-is-dev": "^0.1.1", "mocha": "^2.5.3", - "node-jsx": "^0.13.3", "react": "^15.1.0", "react-dom": "^15.1.0", "react-photonkit": "^0.4.1", + "react-redux": "^4.4.5", "react-router": "^2.4.1", + "react-router-redux": "^4.0.5", + "redux": "^3.5.2", "winston": "^2.2.0" } } From 783b40ea6e106e1755a3caf891ab815038fee9c6 Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Tue, 21 Jun 2016 10:29:41 -0700 Subject: [PATCH 08/16] add basic redux code --- app/index.jsx | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/app/index.jsx b/app/index.jsx index c33b772c..01db48bf 100644 --- a/app/index.jsx +++ b/app/index.jsx @@ -1,6 +1,24 @@ import * as React from "react" import * as ReactDOM from "react-dom" import {Window, Toolbar, Content, Pane, ListGroup, ListItem} from "react-photonkit" +import {createStore} from "redux" + +const reducer = (state, action) => { + switch (action.type) { + case "SELECT_ITEM": + return state + default: + return state + } +} + +const render = () => { + ReactDOM.render( + + , document.getElementById("app")) +} + +const store = createStore(reducer) const App = () => { return ( @@ -18,7 +36,6 @@ const App = () => { image="https://avatars3.githubusercontent.com/u/1744446?v=3&s=400" title="list item" subtitle="subtitle" /> - ... @@ -27,6 +44,5 @@ const App = () => { ) } -ReactDOM.render( - -, document.getElementById("app")) +store.subscribe(render) +render() From cc2d1f1eb104499c9c27fbc166176665679cd90f Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Tue, 21 Jun 2016 14:55:37 -0700 Subject: [PATCH 09/16] barebones react redux app --- .babelrc | 5 ++- app/DevTools.jsx | 16 +++++++++ app/index.jsx | 85 ++++++++++++++++++++++++++++++++++++++++-------- package.json | 5 ++- 4 files changed, 95 insertions(+), 16 deletions(-) create mode 100644 app/DevTools.jsx diff --git a/.babelrc b/.babelrc index b00b3d64..e1d3c5df 100644 --- a/.babelrc +++ b/.babelrc @@ -1 +1,4 @@ -{ "presets": ["es2015", "react"] } +{ + "presets": ["es2015", "react"], + "plugins": ["transform-object-assign"] +} diff --git a/app/DevTools.jsx b/app/DevTools.jsx new file mode 100644 index 00000000..506a87a3 --- /dev/null +++ b/app/DevTools.jsx @@ -0,0 +1,16 @@ +import React from "react" + +import { createDevTools } from "redux-devtools" + +import LogMonitor from "redux-devtools-log-monitor" +import DockMonitor from "redux-devtools-dock-monitor" + +const DevTools = createDevTools( + + + +) + +export default DevTools diff --git a/app/index.jsx b/app/index.jsx index 01db48bf..9ac76b31 100644 --- a/app/index.jsx +++ b/app/index.jsx @@ -1,43 +1,100 @@ import * as React from "react" import * as ReactDOM from "react-dom" import {Window, Toolbar, Content, Pane, ListGroup, ListItem} from "react-photonkit" -import {createStore} from "redux" +import {createStore, compose} from "redux" +import DevTools from "./DevTools" -const reducer = (state, action) => { +const initialState = [ + { + id: 1, + text: "Item 1", + active: false + }, + { + id: 2, + text: "Item 2", + active: true + } +] + +const itemReducer = (state, action) => { switch (action.type) { case "SELECT_ITEM": + if (action.id === state.id) { + return Object.assign({}, state, {active: !state.active}) + } else { + return state + } + default: return state + } +} + +const reducer = (state, action) => { + if (typeof state === "undefined") { + return initialState + } + + switch (action.type) { + case "SELECT_ITEM": + return state.map((item) => { + return itemReducer(item, action) + }) default: return state } } +const store = createStore(reducer, compose(DevTools.instrument())) + const render = () => { ReactDOM.render( - + { + store.dispatch({ + type: "SELECT_ITEM", + id: id + }) + }}/> , document.getElementById("app")) } -const store = createStore(reducer) +const Item = ({ + text, + active, + handleClick +}) => { + return +} -const App = () => { +const App = ({ + todos, + handleItemClick +}) => { return ( - - + {todos.map((todo) => { + return ( + { handleItemClick(todo.id) }} + /> + ) + })} + diff --git a/package.json b/package.json index 326a7917..e1ed44bf 100644 --- a/package.json +++ b/package.json @@ -28,9 +28,12 @@ "eslint-plugin-promise": "^1.3.2", "eslint-plugin-react": "^5.2.1", "eslint-plugin-standard": "^1.3.2", - "redux-devtools": "^3.3.1" + "redux-devtools": "^3.3.1", + "redux-devtools-dock-monitor": "^1.1.1", + "redux-devtools-log-monitor": "^1.0.11" }, "dependencies": { + "babel-plugin-transform-object-assign": "^6.8.0", "babel-preset-es2015": "^6.9.0", "babel-preset-react": "^6.5.0", "babel-register": "^6.9.0", From 815cd984f6ada669c389d047e37bebe2a168c6e7 Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Tue, 21 Jun 2016 15:03:22 -0700 Subject: [PATCH 10/16] its alive --- app/index.jsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/app/index.jsx b/app/index.jsx index 9ac76b31..e19cd7c6 100644 --- a/app/index.jsx +++ b/app/index.jsx @@ -65,12 +65,16 @@ const Item = ({ active, handleClick }) => { - return + return ( +
+ +
+ ) } const App = ({ @@ -94,9 +98,9 @@ const App = ({ })} - + ) } From 32c751d0970683e0a543c09e4d1cc19abc352ed2 Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Thu, 23 Jun 2016 17:01:19 -0600 Subject: [PATCH 11/16] implement sample app using react-redux --- app/actions/index.js | 8 ++ app/components/Item.jsx | 27 +++++++ app/components/ItemList.jsx | 32 ++++++++ app/containers/SelectableItemList.jsx | 19 +++++ app/index.jsx | 110 ++++---------------------- app/reducers/items.js | 47 +++++++++++ 6 files changed, 148 insertions(+), 95 deletions(-) create mode 100644 app/actions/index.js create mode 100644 app/components/Item.jsx create mode 100644 app/components/ItemList.jsx create mode 100644 app/containers/SelectableItemList.jsx create mode 100644 app/reducers/items.js diff --git a/app/actions/index.js b/app/actions/index.js new file mode 100644 index 00000000..42ebae3e --- /dev/null +++ b/app/actions/index.js @@ -0,0 +1,8 @@ +const SELECT_ITEM = "SELECT_ITEM" + +export const selectItem = (id) => { + return { + type: SELECT_ITEM, + id: id + } +} diff --git a/app/components/Item.jsx b/app/components/Item.jsx new file mode 100644 index 00000000..1d7fcb45 --- /dev/null +++ b/app/components/Item.jsx @@ -0,0 +1,27 @@ +import React, { PropTypes } from "react" +import {ListItem} from "react-photonkit" + +const Item = ({ + text, + active, + handleClick +}) => { + return ( +
+ +
+ ) +} + +Item.propTypes = { + text: PropTypes.string.isRequired, + active: PropTypes.bool.isRequired, + handleClick: PropTypes.func.isRequired +} + +export default Item diff --git a/app/components/ItemList.jsx b/app/components/ItemList.jsx new file mode 100644 index 00000000..d9d18f59 --- /dev/null +++ b/app/components/ItemList.jsx @@ -0,0 +1,32 @@ +import React, { PropTypes } from "react" +import { Pane, ListGroup } from "react-photonkit" +import Item from "./Item" + +const ItemList = ({ + items, + handleItemClick +}) => { + return ( + + + {items.map((todo) => { + return ( + { handleItemClick(todo.id) }} + /> + ) + })} + + + ) +} + +ItemList.propTypes = { + items: PropTypes.array.isRequired, + handleItemClick: PropTypes.func.isRequired +} + +export default ItemList diff --git a/app/containers/SelectableItemList.jsx b/app/containers/SelectableItemList.jsx new file mode 100644 index 00000000..a1fb677b --- /dev/null +++ b/app/containers/SelectableItemList.jsx @@ -0,0 +1,19 @@ +import { connect } from "react-redux" +import { selectItem } from "../actions" +import ItemList from "../components/ItemList" + +const mapStateToProps = (state) => { + return { + items: state.items + } +} + +const mapDispatchToProps = (dispatch) => { + return { + handleItemClick: (id) => { + dispatch(selectItem(id)) + } + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(ItemList) diff --git a/app/index.jsx b/app/index.jsx index e19cd7c6..d79f8a13 100644 --- a/app/index.jsx +++ b/app/index.jsx @@ -1,109 +1,29 @@ import * as React from "react" import * as ReactDOM from "react-dom" -import {Window, Toolbar, Content, Pane, ListGroup, ListItem} from "react-photonkit" +import {Window, Toolbar, Content} from "react-photonkit" import {createStore, compose} from "redux" import DevTools from "./DevTools" -const initialState = [ - { - id: 1, - text: "Item 1", - active: false - }, - { - id: 2, - text: "Item 2", - active: true - } -] +import SelectableItemList from "./containers/SelectableItemList" +import { Provider } from "react-redux" -const itemReducer = (state, action) => { - switch (action.type) { - case "SELECT_ITEM": - if (action.id === state.id) { - return Object.assign({}, state, {active: !state.active}) - } else { - return state - } - default: - return state - } -} - -const reducer = (state, action) => { - if (typeof state === "undefined") { - return initialState - } - - switch (action.type) { - case "SELECT_ITEM": - return state.map((item) => { - return itemReducer(item, action) - }) - default: - return state - } -} - -const store = createStore(reducer, compose(DevTools.instrument())) +import items from "./reducers/items" +const store = createStore(items, compose(DevTools.instrument())) const render = () => { ReactDOM.render( - { - store.dispatch({ - type: "SELECT_ITEM", - id: id - }) - }}/> + + + + + + + + + + , document.getElementById("app")) } -const Item = ({ - text, - active, - handleClick -}) => { - return ( -
- -
- ) -} - -const App = ({ - todos, - handleItemClick -}) => { - return ( - - - - - - {todos.map((todo) => { - return ( - { handleItemClick(todo.id) }} - /> - ) - })} - - - - - - - ) -} - store.subscribe(render) render() diff --git a/app/reducers/items.js b/app/reducers/items.js new file mode 100644 index 00000000..3915b329 --- /dev/null +++ b/app/reducers/items.js @@ -0,0 +1,47 @@ +const initialState = { + items: [ + { + id: 1, + text: "Item 1", + active: false + }, + { + id: 2, + text: "Item 2", + active: true + } + ] +} + +const itemReducer = (state, action) => { + switch (action.type) { + case "SELECT_ITEM": + if (action.id === state.id) { + return Object.assign({}, state, {active: !state.active}) + } else { + return state + } + default: + return state + } +} + +const items = (state, action) => { + if (typeof state === "undefined") { + return initialState + } + + switch (action.type) { + case "SELECT_ITEM": + return { + items: state.items.map((item) => { + return itemReducer(item, action) + }) + } + + default: + return state + } +} + +export default items From 2a17252d2ce1b030b700bac9e79911b8d6d0b5d5 Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Thu, 23 Jun 2016 17:24:07 -0600 Subject: [PATCH 12/16] write some tests for actions and reducers --- app/actions/index.js | 2 +- app/constants/actionTypes.js | 1 + package.json | 2 +- test/actions.js | 17 +++++++++ test/dummy.js | 11 ------ test/dummyTwo.js | 11 ------ test/reducers.js | 74 ++++++++++++++++++++++++++++++++++++ 7 files changed, 94 insertions(+), 24 deletions(-) create mode 100644 app/constants/actionTypes.js create mode 100644 test/actions.js delete mode 100644 test/dummy.js delete mode 100644 test/dummyTwo.js create mode 100644 test/reducers.js diff --git a/app/actions/index.js b/app/actions/index.js index 42ebae3e..bdab72a1 100644 --- a/app/actions/index.js +++ b/app/actions/index.js @@ -1,4 +1,4 @@ -const SELECT_ITEM = "SELECT_ITEM" +import {SELECT_ITEM} from "../constants/actionTypes" export const selectItem = (id) => { return { diff --git a/app/constants/actionTypes.js b/app/constants/actionTypes.js new file mode 100644 index 00000000..c2459e04 --- /dev/null +++ b/app/constants/actionTypes.js @@ -0,0 +1 @@ +export const SELECT_ITEM = "SELECT_ITEM" diff --git a/package.json b/package.json index e1ed44bf..c13f0afe 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "main": "main.js", "scripts": { "start": "electron main.js", - "test": "node_modules/.bin/eslint --ext .js,.jsx . && node_modules/mocha/bin/mocha test", + "test": "node_modules/.bin/eslint --ext .js,.jsx . && node_modules/mocha/bin/mocha --compilers js:babel-core/register test", "build-mac": "electron-packager . Classroom --platform=darwin --arch=x64 --out=dist --overwrite" }, "repository": { diff --git a/test/actions.js b/test/actions.js new file mode 100644 index 00000000..ae3a8bdc --- /dev/null +++ b/test/actions.js @@ -0,0 +1,17 @@ +/* eslint-env mocha */ + +import { assert } from "chai" +import { SELECT_ITEM } from "../app/constants/actionTypes" +import { selectItem } from "../app/actions" + +describe("actions", () => { + it("should create an action to select an item", () => { + const id = 1 + const expectedAction = { + type: SELECT_ITEM, + id: id + } + + assert.deepEqual(expectedAction, selectItem(id)) + }) +}) diff --git a/test/dummy.js b/test/dummy.js deleted file mode 100644 index 90c8103e..00000000 --- a/test/dummy.js +++ /dev/null @@ -1,11 +0,0 @@ -/* eslint-env mocha */ - -const assert = require("chai").assert - -describe("arithmetic", () => { - describe("numbers", () => { - it("should add up correctly", () => { - assert.equal(2, 1 + 1) - }) - }) -}) diff --git a/test/dummyTwo.js b/test/dummyTwo.js deleted file mode 100644 index 39bfcc8d..00000000 --- a/test/dummyTwo.js +++ /dev/null @@ -1,11 +0,0 @@ -/* eslint-env mocha */ - -const assert = require("chai").assert - -describe("objects", () => { - describe("strings", () => { - it("should concatenate", () => { - assert.equal("helloworld", "hello" + "world") - }) - }) -}) diff --git a/test/reducers.js b/test/reducers.js new file mode 100644 index 00000000..795ca9bf --- /dev/null +++ b/test/reducers.js @@ -0,0 +1,74 @@ +/* eslint-env mocha */ + +import { assert } from "chai" +import { SELECT_ITEM } from "../app/constants/actionTypes" + +import itemsReducer from "../app/reducers/items" + +describe("reducers", () => { + describe("items reducer", () => { + it("should return the initial state", () => { + let expectedState = { + items: [ + { + id: 1, + text: "Item 1", + active: false + }, + { + id: 2, + text: "Item 2", + active: true + } + ] + } + + assert.deepEqual( + expectedState, + itemsReducer(undefined, {}) + ) + }) + + it("should select the correct item", () => { + let initialState = { + items: [ + { + id: 1, + text: "Item 1", + active: false + }, + { + id: 2, + text: "Item 2", + active: true + } + ] + } + + let expectedState = { + items: [ + { + id: 1, + text: "Item 1", + active: true + }, + { + id: 2, + text: "Item 2", + active: true + } + ] + } + + let action = { + type: SELECT_ITEM, + id: 1 + } + + assert.deepEqual( + expectedState, + itemsReducer(initialState, action) + ) + }) + }) +}) From 1b063dc7dace2e1e1c178b7679120ce3e0b8898e Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Thu, 23 Jun 2016 21:53:44 -0600 Subject: [PATCH 13/16] refactor reducers to use combineReducers --- .eslintignore | 1 - app/components/Item.jsx | 22 +++++------ app/components/ItemList.jsx | 34 ++++++++-------- app/index.html | 2 + app/index.jsx | 14 +++++-- app/reducers/index.js | 7 ++++ app/reducers/items.js | 36 ++++++++--------- test/reducers.js | 78 +++++++++++++++++-------------------- 8 files changed, 97 insertions(+), 97 deletions(-) create mode 100644 app/reducers/index.js diff --git a/.eslintignore b/.eslintignore index de4d1f00..1521c8b7 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1 @@ dist -node_modules diff --git a/app/components/Item.jsx b/app/components/Item.jsx index 1d7fcb45..ea07c98c 100644 --- a/app/components/Item.jsx +++ b/app/components/Item.jsx @@ -5,18 +5,16 @@ const Item = ({ text, active, handleClick -}) => { - return ( -
- -
- ) -} +}) => ( +
+ +
+) Item.propTypes = { text: PropTypes.string.isRequired, diff --git a/app/components/ItemList.jsx b/app/components/ItemList.jsx index d9d18f59..8603ac46 100644 --- a/app/components/ItemList.jsx +++ b/app/components/ItemList.jsx @@ -5,24 +5,22 @@ import Item from "./Item" const ItemList = ({ items, handleItemClick -}) => { - return ( - - - {items.map((todo) => { - return ( - { handleItemClick(todo.id) }} - /> - ) - })} - - - ) -} +}) => ( + + + {items.map((todo) => { + return ( + { handleItemClick(todo.id) }} + /> + ) + })} + + +) ItemList.propTypes = { items: PropTypes.array.isRequired, diff --git a/app/index.html b/app/index.html index 69300ebf..7f1c0fbe 100644 --- a/app/index.html +++ b/app/index.html @@ -9,7 +9,9 @@ diff --git a/app/index.jsx b/app/index.jsx index d79f8a13..46684516 100644 --- a/app/index.jsx +++ b/app/index.jsx @@ -2,13 +2,19 @@ import * as React from "react" import * as ReactDOM from "react-dom" import {Window, Toolbar, Content} from "react-photonkit" import {createStore, compose} from "redux" +import { Provider } from "react-redux" +import isDev from "electron-is-dev" import DevTools from "./DevTools" +import reducer from "./reducers" import SelectableItemList from "./containers/SelectableItemList" -import { Provider } from "react-redux" -import items from "./reducers/items" -const store = createStore(items, compose(DevTools.instrument())) +let devToolsInstance +if (isDev) { + devToolsInstance = +} + +const store = createStore(reducer, compose(DevTools.instrument())) const render = () => { ReactDOM.render( @@ -19,7 +25,7 @@ const render = () => { - + {devToolsInstance} , document.getElementById("app")) diff --git a/app/reducers/index.js b/app/reducers/index.js new file mode 100644 index 00000000..d2d2455a --- /dev/null +++ b/app/reducers/index.js @@ -0,0 +1,7 @@ +import { combineReducers } from "redux" + +import items from "./items" + +export default combineReducers({ + items +}) diff --git a/app/reducers/items.js b/app/reducers/items.js index 3915b329..97446397 100644 --- a/app/reducers/items.js +++ b/app/reducers/items.js @@ -1,19 +1,17 @@ -const initialState = { - items: [ - { - id: 1, - text: "Item 1", - active: false - }, - { - id: 2, - text: "Item 2", - active: true - } - ] -} +const initialState = [ + { + id: 1, + text: "Item 1", + active: false + }, + { + id: 2, + text: "Item 2", + active: true + } +] -const itemReducer = (state, action) => { +const item = (state, action) => { switch (action.type) { case "SELECT_ITEM": if (action.id === state.id) { @@ -33,11 +31,9 @@ const items = (state, action) => { switch (action.type) { case "SELECT_ITEM": - return { - items: state.items.map((item) => { - return itemReducer(item, action) - }) - } + return state.map((each) => { + return item(each, action) + }) default: return state diff --git a/test/reducers.js b/test/reducers.js index 795ca9bf..272619d8 100644 --- a/test/reducers.js +++ b/test/reducers.js @@ -8,20 +8,18 @@ import itemsReducer from "../app/reducers/items" describe("reducers", () => { describe("items reducer", () => { it("should return the initial state", () => { - let expectedState = { - items: [ - { - id: 1, - text: "Item 1", - active: false - }, - { - id: 2, - text: "Item 2", - active: true - } - ] - } + let expectedState = [ + { + id: 1, + text: "Item 1", + active: false + }, + { + id: 2, + text: "Item 2", + active: true + } + ] assert.deepEqual( expectedState, @@ -30,35 +28,31 @@ describe("reducers", () => { }) it("should select the correct item", () => { - let initialState = { - items: [ - { - id: 1, - text: "Item 1", - active: false - }, - { - id: 2, - text: "Item 2", - active: true - } - ] - } + let initialState = [ + { + id: 1, + text: "Item 1", + active: false + }, + { + id: 2, + text: "Item 2", + active: true + } + ] - let expectedState = { - items: [ - { - id: 1, - text: "Item 1", - active: true - }, - { - id: 2, - text: "Item 2", - active: true - } - ] - } + let expectedState = [ + { + id: 1, + text: "Item 1", + active: true + }, + { + id: 2, + text: "Item 2", + active: true + } + ] let action = { type: SELECT_ITEM, From 64a7cf4294a629538a6a6ee169d379212d90c168 Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Thu, 23 Jun 2016 22:16:56 -0600 Subject: [PATCH 14/16] add deepfreeze to test reducer immutability --- package.json | 1 + test/reducers.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/package.json b/package.json index c13f0afe..4a83eac5 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "babel-preset-react": "^6.5.0", "babel-register": "^6.9.0", "chai": "^3.5.0", + "deep-freeze": "0.0.1", "electron-is-dev": "^0.1.1", "mocha": "^2.5.3", "react": "^15.1.0", diff --git a/test/reducers.js b/test/reducers.js index 272619d8..bce77e20 100644 --- a/test/reducers.js +++ b/test/reducers.js @@ -2,6 +2,7 @@ import { assert } from "chai" import { SELECT_ITEM } from "../app/constants/actionTypes" +import deepFreeze from "deep-freeze" import itemsReducer from "../app/reducers/items" @@ -59,6 +60,8 @@ describe("reducers", () => { id: 1 } + deepFreeze(initialState) + assert.deepEqual( expectedState, itemsReducer(initialState, action) From 253f40893b6baff1f640e54393e6534bdbb52e4e Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Tue, 5 Jul 2016 08:23:18 -0700 Subject: [PATCH 15/16] add jsx-no-bind rule --- .eslintrc.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index 7dc49720..ed360b75 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -38,6 +38,7 @@ module.exports = { "prefer-double" ], "react/jsx-uses-vars": "error", - "react/jsx-uses-react": "error" + "react/jsx-uses-react": "error", + "react/jsx-no-bind": "error" } }; From 19e6c5039ab10465246872a7d158ac850d198a54 Mon Sep 17 00:00:00 2001 From: Nick Tikhonov Date: Tue, 5 Jul 2016 08:54:35 -0700 Subject: [PATCH 16/16] remove binding --- app/components/ItemList.jsx | 2 +- package.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/components/ItemList.jsx b/app/components/ItemList.jsx index 8603ac46..d50880c8 100644 --- a/app/components/ItemList.jsx +++ b/app/components/ItemList.jsx @@ -14,7 +14,7 @@ const ItemList = ({ key={todo.id} text={todo.text} active={todo.active} - handleClick={() => { handleItemClick(todo.id) }} + handleClick={function () { handleItemClick(todo.id) }} /> ) })} diff --git a/package.json b/package.json index 4a83eac5..ed1760fe 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "react-redux": "^4.4.5", "react-router": "^2.4.1", "react-router-redux": "^4.0.5", + "recompose": "^0.20.2", "redux": "^3.5.2", "winston": "^2.2.0" }