Skip to content

Commit 05a838d

Browse files
committed
Set up a basic react router
1 parent 363b56f commit 05a838d

33 files changed

+1440
-0
lines changed

meetingapp/.babelrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"presets": [
3+
"es2015",
4+
"react",
5+
"stage-0"
6+
]
7+
}

meetingapp/README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# [TodoMVC](http://todomvc.parseapp.com/)
2+
3+
It is easy and fast to learn how a design pattern works by implementing a todo list.
4+
<br>
5+
Here we implement a todo list using **Redux** architecture.
6+
<br>
7+
(Click the above title link to see demo)
8+
9+
## Project structure
10+
```
11+
|-- todomvc
12+
|-- .babelrc # Babel configuration file, makes us able to write es6 syntax
13+
|-- README.md # Ignore it
14+
|-- package.json # Node package configuration
15+
|-- webpack.config.js # Webpack configuration file
16+
|-- app # App src code
17+
| |-- index.js # Entry point of app, config in webpack.config.js
18+
| |-- __tests__ # Jest unit test
19+
| |-- actions # Redux actions
20+
| |-- components # React dumb component
21+
| |-- containers # React smart component, composed by dumb component
22+
| |-- reducers # Redux reducers
23+
| |-- store # Redux store
24+
|-- build # Webpack build/deploy output folder
25+
|-- bundle.js # You can change output file name in webpack.config.js
26+
|-- index.html # After build or deploy, you can open this file to see demo
27+
|-- style.css # You can change output file name in webpack.config.js
28+
29+
```
30+
31+
## Setup workflow
32+
### Installation
33+
First open your command line, clone this project (suppose you have installed [git command line tool](https://git-scm.com/)) or simply download the ZIP to your prefered directory .
34+
35+
```
36+
git clone https://github.com/HowardLoTW/react-redux-sample.git
37+
cd react-redux-sample/todomvc
38+
```
39+
Suppose you have installed [nodejs](https://nodejs.org/en/) (required node version 4.x or upper. I'm using node v5.3.0 & npm v3.3.12).
40+
<br>Type 'npm install' in your command line to install dependencies.
41+
```
42+
npm install
43+
```
44+
45+
### Development
46+
```
47+
npm run dev
48+
```
49+
Open your browser and navigate to http://localhost:8080/webpack-dev-server/
50+
51+
### Testing
52+
```
53+
npm run test
54+
```
55+
56+
### Build
57+
```
58+
npm run build
59+
```
60+
61+
### Deploy
62+
```
63+
npm run deploy
64+
```
65+
66+
## About CSS with React
67+
In this project, I use the following css tools and it works well with React. And of course you can use another css tools to write css in your project.
68+
1. [Css Modules](https://github.com/css-modules/css-modules)
69+
2. [classnames](https://github.com/JedWatson/classnames)
70+
71+
You can checkout the following talks for more information:
72+
1. [The case for CSS modules - Mark Dalgleish](https://www.youtube.com/watch?v=zR1lOuyQEt8)
73+
2. [Michael Chan - Inline Styles: themes, media queries, contexts, & when it's best to use CSS](https://www.youtube.com/watch?v=ERB1TJBn32c)
74+
3. [CSS with React.js](https://www.youtube.com/watch?v=FXlWWhKevaw)
75+
76+
## Reference
77+
1. More setup workflow information, please refer to [react-webpack-cookbook](https://christianalfoni.github.io/react-webpack-cookbook/index.html)
78+
2. [Learn to implement Redux architecture in React app](http://rackt.org/redux/index.html)
79+
3. [More Redux example](https://github.com/rackt/redux)
80+
81+
82+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
jest.dontMock('../../actions/todo');
2+
3+
const Todo = require('../../actions/todo');
4+
5+
describe('todo actions', () => {
6+
7+
it('addTodo should create a ADD_TODO action', () => {
8+
expect(Todo.addTodo('This is a new todo')).toEqual({
9+
type: Todo.Action.ADD_TODO,
10+
payload: { text: 'This is a new todo' }
11+
})
12+
})
13+
14+
it('editTodo should creat a EDIT_TODO action', () => {
15+
expect(Todo.editTodo(1, 'This is a edited todo')).toEqual({
16+
type: Todo.Action.EDIT_TODO,
17+
payload: { todoID: 1, text: 'This is a edited todo' }
18+
})
19+
})
20+
21+
it('toggleTodo should creat a TOGGLE_TODO action', () => {
22+
expect(Todo.toggleTodo(1)).toEqual({
23+
type: Todo.Action.TOGGLE_TODO,
24+
payload: { todoID: 1 }
25+
})
26+
})
27+
28+
it('deleteTodo should creat a DELETE_TODO action', () => {
29+
expect(Todo.deleteTodo(1)).toEqual({
30+
type: Todo.Action.DELETE_TODO,
31+
payload: { todoID: 1 }
32+
})
33+
})
34+
35+
it('deleteCompletedTodos should creat a DELETE_COMPELETED_TODOS action', () => {
36+
expect(Todo.deleteCompletedTodos()).toEqual({
37+
type: Todo.Action.DELETE_COMPELETED_TODOS
38+
})
39+
})
40+
})
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
jest.dontMock('../../actions/visibility-filter');
2+
3+
const Filter = require('../../actions/visibility-filter');
4+
5+
describe('visibility filter actions', () => {
6+
7+
it('setVisibilityFilter should create a SET_VISIBILITY_FILTER action', () => {
8+
expect(Filter.setVisibilityFilter(Filter.VisibilityFilter.SHOW_ALL_TODOS)).toEqual({
9+
type: Filter.Action.SET_VISIBILITY_FILTER,
10+
payload: { filter: Filter.VisibilityFilter.SHOW_ALL_TODOS }
11+
})
12+
})
13+
})
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
jest.dontMock('../../actions/todo');
2+
jest.dontMock('../../reducers/todo');
3+
4+
const _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
5+
const TodoAction = require('../../actions/todo');
6+
const todo = _interopRequire(require('../../reducers/todo'));
7+
8+
describe('todo reducers', () => {
9+
10+
it('should handle initial state', () => {
11+
12+
expect(todo(undefined, {})).toEqual([]);
13+
})
14+
15+
it('should handle ADD_TODO', () => {
16+
17+
const prevState = [
18+
{ id: 1, text: 'todo 1', completed: false }
19+
]
20+
21+
const newState = [
22+
{ id: 1, text: 'todo 1', completed: false },
23+
{ id: 2, text: 'todo 2', completed: false }
24+
]
25+
26+
expect(todo(prevState, TodoAction.addTodo('todo 2'))).toEqual(newState);
27+
})
28+
29+
it('should handle EDIT_TODO', () => {
30+
31+
const prevState = [
32+
{ id: 1, text: 'todo 1', completed: false },
33+
{ id: 2, text: 'todo 2', completed: false }
34+
]
35+
36+
const newState = [
37+
{ id: 1, text: 'todo 1', completed: false },
38+
{ id: 2, text: 'todo edited', completed: false }
39+
]
40+
41+
expect(todo(prevState, TodoAction.editTodo(2, 'todo edited'))).toEqual(newState);
42+
})
43+
44+
it('should handle TOGGLE_TODO', () => {
45+
46+
const prevState = [
47+
{ id: 1, text: 'todo 1', completed: false },
48+
{ id: 2, text: 'todo 2', completed: false }
49+
]
50+
51+
const newState = [
52+
{ id: 1, text: 'todo 1', completed: false },
53+
{ id: 2, text: 'todo 2', completed: true }
54+
]
55+
56+
expect(todo(prevState, TodoAction.toggleTodo(2))).toEqual(newState);
57+
})
58+
59+
it('should handle DELETE_TODO', () => {
60+
61+
const prevState = [
62+
{ id: 1, text: 'todo 1', completed: false },
63+
{ id: 2, text: 'todo 2', completed: false }
64+
]
65+
66+
const newState = [
67+
{ id: 1, text: 'todo 1', completed: false }
68+
]
69+
70+
expect(todo(prevState, TodoAction.deleteTodo(2))).toEqual(newState);
71+
})
72+
73+
it('should handle DELETE_COMPELETED_TODOS', () => {
74+
75+
const prevState = [
76+
{ id: 1, text: 'todo 1', completed: false },
77+
{ id: 2, text: 'todo 2', completed: true },
78+
{ id: 3, text: 'todo 3', completed: false },
79+
{ id: 4, text: 'todo 4', completed: true }
80+
]
81+
82+
const newState = [
83+
{ id: 1, text: 'todo 1', completed: false },
84+
{ id: 3, text: 'todo 3', completed: false }
85+
]
86+
87+
expect(todo(prevState, TodoAction.deleteCompletedTodos())).toEqual(newState);
88+
})
89+
})
90+
91+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
jest.dontMock('../../actions/visibility-filter');
2+
jest.dontMock('../../reducers/visibility-filter');
3+
4+
const _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
5+
const Filter = require('../../actions/visibility-filter');
6+
const visibilityFilter = _interopRequire(require('../../reducers/visibility-filter'));
7+
8+
describe('visibility filter reducers', () => {
9+
10+
it('should handle initial state', () => {
11+
expect(visibilityFilter(undefined, {})).toEqual(Filter.VisibilityFilter.SHOW_ALL_TODOS);
12+
})
13+
14+
it('should set handle SET_VISIBILITY_FILTER', () => {
15+
16+
const prevState = Filter.VisibilityFilter.SHOW_ALL_TODOS;
17+
const newState = Filter.VisibilityFilter.SHOW_COMPLETED_TODOS;
18+
19+
expect(visibilityFilter(prevState, Filter.setVisibilityFilter(Filter.VisibilityFilter.SHOW_COMPLETED_TODOS))).toEqual(newState);
20+
})
21+
})
22+
23+

meetingapp/app/actions/todo.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* Defines actions related to todo list data.
3+
*/
4+
5+
/* Action types */
6+
export const Action = {
7+
ADD_TODO: 'ADD_TODO',
8+
EDIT_TODO: 'EDIT_TODO',
9+
TOGGLE_TODO: 'TOGGLE_TODO',
10+
DELETE_TODO: 'DELETE_TODO',
11+
DELETE_COMPELETED_TODOS: 'DELETE_COMPELETED_TODOS'
12+
}
13+
14+
/**
15+
* Action Creators
16+
* Create actions that contains action types and payloads of information that send data to the store.
17+
* Interface follows the 'Flux Action Standard' (https://github.com/acdlite/flux-standard-action).
18+
*/
19+
20+
export function addTodo(text) {
21+
return {
22+
type: Action.ADD_TODO,
23+
payload: { text }
24+
}
25+
}
26+
27+
export function editTodo(todoID, text) {
28+
return {
29+
type: Action.EDIT_TODO,
30+
payload: { todoID, text }
31+
}
32+
}
33+
34+
export function toggleTodo(todoID) {
35+
return {
36+
type: Action.TOGGLE_TODO,
37+
payload: { todoID }
38+
}
39+
}
40+
41+
export function deleteTodo(todoID) {
42+
return {
43+
type: Action.DELETE_TODO,
44+
payload: { todoID }
45+
}
46+
}
47+
48+
export function deleteCompletedTodos() {
49+
return {
50+
type: Action.DELETE_COMPELETED_TODOS
51+
}
52+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Defines actions related to todo list visibility.
3+
*/
4+
5+
/* Action types */
6+
export const Action = {
7+
SET_VISIBILITY_FILTER: 'SET_VISIBILITY_FILTER',
8+
}
9+
10+
/* Constants */
11+
export const VisibilityFilter = {
12+
SHOW_ALL_TODOS: 'SHOW_ALL_TODOS',
13+
SHOW_COMPLETED_TODOS: 'SHOW_COMPLETED_TODOS',
14+
SHOW_UNCOMPLETED_TODOS: 'SHOW_UNCOMPLETED_TODOS'
15+
}
16+
17+
/**
18+
* Action Creators :
19+
* Create actions that contains action types and payloads of information that send data to the store.
20+
* Interface follows the 'Flux Action Standard' (https://github.com/acdlite/flux-standard-action).
21+
*/
22+
23+
export function setVisibilityFilter(filter) {
24+
return {
25+
type: Action.SET_VISIBILITY_FILTER,
26+
payload: { filter }
27+
}
28+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
.container {
2+
padding: 15px 25px 15px 25px;
3+
border-top: 1px solid rgba(0,0,0,0.1);
4+
color: rgba(0,0,0,0.3);
5+
font-size: 0.9rem;
6+
}
7+
8+
.active {
9+
color: #fc6c85;
10+
}
11+
12+
.itemleft {
13+
margin-right: 60px;
14+
}
15+
16+
.col {
17+
display: inline-block;
18+
}
19+
20+
.spacing {
21+
margin-right: 10px;
22+
}
23+
24+
.alignright {
25+
float: right;
26+
}

0 commit comments

Comments
 (0)