Skip to content
This repository has been archived by the owner on Jul 14, 2023. It is now read-only.

Commit

Permalink
Merge pull request #12 from education/feature/frontend-setup
Browse files Browse the repository at this point in the history
Setup react, photon-kit and flux architecture
  • Loading branch information
Nick Tikhonov committed Jul 5, 2016
2 parents 9136f6f + 19e6c50 commit ed31931
Show file tree
Hide file tree
Showing 19 changed files with 309 additions and 38 deletions.
4 changes: 4 additions & 0 deletions .babelrc
@@ -0,0 +1,4 @@
{
"presets": ["es2015", "react"],
"plugins": ["transform-object-assign"]
}
1 change: 1 addition & 0 deletions .eslintignore
@@ -0,0 +1 @@
dist
9 changes: 8 additions & 1 deletion .eslintrc.js
Expand Up @@ -32,6 +32,13 @@ module.exports = {
"semi": [
"error",
"never"
]
],
"jsx-quotes": [
"error",
"prefer-double"
],
"react/jsx-uses-vars": "error",
"react/jsx-uses-react": "error",
"react/jsx-no-bind": "error"
}
};
16 changes: 16 additions & 0 deletions 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(
<DockMonitor toggleVisibilityKey="ctrl-h"
changePositionKey="ctrl-q"
defaultIsVisible={true}>
<LogMonitor theme="tomorrow" />
</DockMonitor>
)

export default DevTools
8 changes: 8 additions & 0 deletions app/actions/index.js
@@ -0,0 +1,8 @@
import {SELECT_ITEM} from "../constants/actionTypes"

export const selectItem = (id) => {
return {
type: SELECT_ITEM,
id: id
}
}
25 changes: 25 additions & 0 deletions app/components/Item.jsx
@@ -0,0 +1,25 @@
import React, { PropTypes } from "react"
import {ListItem} from "react-photonkit"

const Item = ({
text,
active,
handleClick
}) => (
<div
onClick={handleClick}>
<ListItem
image="https://avatars3.githubusercontent.com/u/1744446?v=3&s=400"
title={text}
subtitle="subtitle"
active={active} />
</div>
)

Item.propTypes = {
text: PropTypes.string.isRequired,
active: PropTypes.bool.isRequired,
handleClick: PropTypes.func.isRequired
}

export default Item
30 changes: 30 additions & 0 deletions app/components/ItemList.jsx
@@ -0,0 +1,30 @@
import React, { PropTypes } from "react"
import { Pane, ListGroup } from "react-photonkit"
import Item from "./Item"

const ItemList = ({
items,
handleItemClick
}) => (
<Pane>
<ListGroup>
{items.map((todo) => {
return (
<Item
key={todo.id}
text={todo.text}
active={todo.active}
handleClick={function () { handleItemClick(todo.id) }}
/>
)
})}
</ListGroup>
</Pane>
)

ItemList.propTypes = {
items: PropTypes.array.isRequired,
handleItemClick: PropTypes.func.isRequired
}

export default ItemList
1 change: 1 addition & 0 deletions app/constants/actionTypes.js
@@ -0,0 +1 @@
export const SELECT_ITEM = "SELECT_ITEM"
19 changes: 19 additions & 0 deletions 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)
12 changes: 5 additions & 7 deletions app/index.html
Expand Up @@ -5,15 +5,13 @@
<title>Classroom Desktop 0.0.1</title>
</head>
<body>
<h1>Hello World! 0.0.1</h1>
<!-- All of the Node.js APIs are available in this renderer process. -->
We are using node <script>document.write(process.versions.node)</script>,
Chromium <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
<div id="app"></div>
</body>

<script>
// You can also require other files to run in this process
require('./renderer.js')
// This automatically transpiles ES6
require('babel-register');

require('./index')
</script>
</html>
35 changes: 35 additions & 0 deletions app/index.jsx
@@ -0,0 +1,35 @@
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"

let devToolsInstance
if (isDev) {
devToolsInstance = <DevTools />
}

const store = createStore(reducer, compose(DevTools.instrument()))

const render = () => {
ReactDOM.render(
<Provider store={store}>
<Window>
<Toolbar title="header" />
<Content>
<SelectableItemList />
</Content>
<Toolbar psType="footer" title="footer" />
{devToolsInstance}
</Window>
</Provider>
, document.getElementById("app"))
}

store.subscribe(render)
render()
7 changes: 7 additions & 0 deletions app/reducers/index.js
@@ -0,0 +1,7 @@
import { combineReducers } from "redux"

import items from "./items"

export default combineReducers({
items
})
43 changes: 43 additions & 0 deletions app/reducers/items.js
@@ -0,0 +1,43 @@
const initialState = [
{
id: 1,
text: "Item 1",
active: false
},
{
id: 2,
text: "Item 2",
active: true
}
]

const item = (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 state.map((each) => {
return item(each, action)
})

default:
return state
}
}

export default items
5 changes: 0 additions & 5 deletions app/renderer.js

This file was deleted.

22 changes: 19 additions & 3 deletions package.json
Expand Up @@ -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 --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": {
Expand All @@ -23,16 +23,32 @@
"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",
"eslint-plugin-standard": "^1.3.2"
"eslint-plugin-standard": "^1.3.2",
"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",
"chai": "^3.5.0",
"deep-freeze": "0.0.1",
"electron-is-dev": "^0.1.1",
"mocha": "^2.5.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",
"recompose": "^0.20.2",
"redux": "^3.5.2",
"winston": "^2.2.0"
}
}
17 changes: 17 additions & 0 deletions 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))
})
})
11 changes: 0 additions & 11 deletions test/dummy.js

This file was deleted.

11 changes: 0 additions & 11 deletions test/dummyTwo.js

This file was deleted.

71 changes: 71 additions & 0 deletions test/reducers.js
@@ -0,0 +1,71 @@
/* eslint-env mocha */

import { assert } from "chai"
import { SELECT_ITEM } from "../app/constants/actionTypes"
import deepFreeze from "deep-freeze"

import itemsReducer from "../app/reducers/items"

describe("reducers", () => {
describe("items reducer", () => {
it("should return the initial state", () => {
let expectedState = [
{
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 = [
{
id: 1,
text: "Item 1",
active: false
},
{
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,
id: 1
}

deepFreeze(initialState)

assert.deepEqual(
expectedState,
itemsReducer(initialState, action)
)
})
})
})

0 comments on commit ed31931

Please sign in to comment.