Skip to content

Commit 971c2cf

Browse files
baseline for ep31
1 parent f89d93a commit 971c2cf

File tree

14 files changed

+725
-0
lines changed

14 files changed

+725
-0
lines changed

ep31-get-all-todos/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#### Setting up the application
2+
3+
```
4+
npm install
5+
npm start
6+
```
7+
8+
Visit http://localhost:8080 in browser.
9+
10+
#### Notes
11+
12+
* [Nodejs Events](https://nodejs.org/api/events.html)
13+
* [object-assign](https://www.npmjs.com/package/object-assign)
14+
* `npm install --save object-assign`
15+
* [Source code](...)
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
var api = require("../utils/api");
2+
var TodoStore = require("../stores/TodoStore");
3+
var AppDispatcher = require('../dispatcher/AppDispatcher');
4+
5+
var TodoActions = {
6+
7+
addTodo: (todo) => {
8+
console.log("adding TODO");
9+
api.addTodo(todo)
10+
.then( () => {
11+
api.getTodos()
12+
.then( (responseData) => {
13+
var todos = responseData.todos;
14+
console.log("All todos", todos);
15+
TodoStore.setTodos(todos);
16+
})
17+
})
18+
.then( () => {
19+
console.log("Added TODO successfully");
20+
AppDispatcher.dispatch({
21+
actionType: 'TODO_ADD'
22+
});
23+
})
24+
},
25+
26+
deleteTodo: (todo) => {
27+
console.log("Deleting TODO");
28+
api.deleteTodo(todo.id)
29+
.then( () => {
30+
console.log("Deleted TODO successfully");
31+
AppDispatcher.dispatch({
32+
actionType: 'TODO_DELETE',
33+
todo: todo
34+
});
35+
})
36+
},
37+
38+
markTodoDone: (todo) => {
39+
console.log("Marking TODO as done");
40+
api.markTodoDone(todo)
41+
.then( () => {
42+
console.log("marked TODO as done successfully");
43+
AppDispatcher.dispatch({
44+
actionType: 'TODO_DONE',
45+
todo: todo
46+
});
47+
48+
})
49+
},
50+
51+
markTodoUnDone: (todo) => {
52+
console.log("Marking TODO as undone");
53+
api.markTodoUnDone(todo)
54+
.then( () => {
55+
console.log("marked TODO as undone successfully");
56+
AppDispatcher.dispatch({
57+
actionType: 'TODO_UNDONE',
58+
todo: todo
59+
});
60+
})
61+
},
62+
63+
}
64+
65+
module.exports = TodoActions;
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import React from 'react';
2+
import TodoForm from './TodoForm';
3+
import DisplayList from './DisplayList';
4+
5+
var rand = require('random-key');
6+
var api = require("../utils/api");
7+
var TodoActions = require("../actions/TodoActions");
8+
var TodoStore = require("../stores/TodoStore");
9+
10+
export default class App extends React.Component {
11+
12+
constructor () {
13+
super();
14+
this.state = { title: '', todos: [] };
15+
16+
this.getAllTodos();
17+
}
18+
19+
componentDidMount () {
20+
var storeIsTellingUsThatDataHasChanged = () => {
21+
console.log("Store is telling us that data has change");
22+
var todos = TodoStore.getTodos();
23+
console.log("todos is");
24+
console.log(todos);
25+
this.setState({todos: todos});
26+
}
27+
TodoStore.addChangeListener(storeIsTellingUsThatDataHasChanged);
28+
}
29+
30+
getAllTodos () {
31+
api.getTodos()
32+
.then( (responseData) => {
33+
var todos = responseData.todos;
34+
this.setState({todos: todos });
35+
TodoStore.setTodos(todos);
36+
})
37+
}
38+
39+
handleClearCompleted (event) {
40+
var newTodos = this.state.todos.filter((todo) => { return !todo.done});
41+
this.setState({ todos: newTodos });
42+
}
43+
44+
render () {
45+
return <div>
46+
<TodoForm />
47+
<DisplayList
48+
todos={this.state.todos} />
49+
<footer>
50+
All: ({ this.state.todos.length }) |
51+
Completed: ({ this.state.todos.filter((todo) => { return todo.done }).length }) |
52+
Pending: ({ this.state.todos.filter((todo) => { return !todo.done }).length }) |
53+
<a href='#' onClick={this.handleClearCompleted.bind(this)}>Clear Completed</a>
54+
</footer>
55+
</div>
56+
}
57+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import React from 'react';
2+
3+
var TodoActions = require('../actions/TodoActions');
4+
5+
export default class DisplayItem extends React.Component {
6+
7+
constructor () {
8+
super();
9+
this.state = { editing: false }
10+
}
11+
12+
componentDidMount () {
13+
this.setState({ changedText: this.props.todo.title });
14+
}
15+
16+
handleEditing (event) {
17+
this.setState({ editing: true, changedText: this.props.todo.title });
18+
}
19+
20+
handleEditingDone (event) {
21+
if (event.keyCode === 13 ) { // submit
22+
this.setState({ editing: false });
23+
}
24+
}
25+
26+
handleEditingChange (event) {
27+
var _changedText = event.target.value;
28+
this.setState({ changedText: _changedText });
29+
}
30+
31+
toggleDone (todo) {
32+
if (todo.done) {
33+
TodoActions.markTodoUnDone(todo);
34+
} else {
35+
TodoActions.markTodoDone(todo);
36+
}
37+
}
38+
39+
handleDeleteTodoClick (todo) {
40+
TodoActions.deleteTodo(todo);
41+
}
42+
43+
render () {
44+
var todo = this.props.todo;
45+
46+
var viewStyle = {};
47+
var editStyle = {};
48+
49+
if (this.state.editing) {
50+
viewStyle.display = 'none';
51+
} else {
52+
editStyle.display = 'none';
53+
}
54+
55+
return <li className={ todo.done ? 'done' : '' }>
56+
<div style={viewStyle} onDoubleClick={this.handleEditing.bind(this)}>
57+
<input
58+
checked={todo.done}
59+
onChange={this.toggleDone.bind(this, todo)}
60+
type="checkbox"
61+
style={{ fontSize: 'x-large' }} />
62+
63+
<label>
64+
{ this.state.changedText }
65+
</label>
66+
67+
<a href='#'
68+
className="destroy"
69+
onClick={ this.handleDeleteTodoClick.bind(this, todo) }>
70+
[x]
71+
</a>
72+
</div>
73+
74+
<input type="text"
75+
onKeyDown={this.handleEditingDone.bind(this)}
76+
onChange={this.handleEditingChange.bind(this)}
77+
style={editStyle}
78+
value={this.state.changedText} />
79+
</li>
80+
}
81+
82+
}
83+
84+
DisplayItem.propTypes = {
85+
todo: React.PropTypes.object.isRequired
86+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React from 'react';
2+
import DisplayItem from './DisplayItem';
3+
4+
export default class DisplayList extends React.Component {
5+
6+
render () {
7+
return <ul id="todo-list">
8+
{ this.props.todos.map((todo, i) => {
9+
return <section id="main" key={todo.id}>
10+
<DisplayItem
11+
todo={todo} />
12+
</section>
13+
}) }
14+
</ul>
15+
}
16+
17+
}
18+
19+
DisplayList.propTypes = {
20+
todos: React.PropTypes.array.isRequired
21+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from 'react';
2+
import DisplayList from './DisplayList';
3+
import DisplayItem from './DisplayItem';
4+
5+
var TodoActions = require('../actions/TodoActions');
6+
7+
export default class TodoForm extends React.Component {
8+
9+
constructor () {
10+
super();
11+
this.state = { editing: false }
12+
}
13+
14+
handleSubmit (event) {
15+
event.preventDefault();
16+
17+
var newTodo = { title: this.state.title, done: false };
18+
19+
TodoActions.addTodo(newTodo);
20+
this.setState({ title: '' });
21+
}
22+
23+
handleChange (event) {
24+
var title = event.target.value;
25+
this.setState({ title: title });
26+
}
27+
28+
render () {
29+
return <div>
30+
<h1> TODO </h1>
31+
<form onSubmit={this.handleSubmit.bind(this)}>
32+
<input type="text"
33+
onChange={this.handleChange.bind(this)}
34+
value={this.state.title} />
35+
</form>
36+
</div>;
37+
}
38+
39+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
var Dispatcher = require('flux').Dispatcher;
2+
3+
module.exports = new Dispatcher();

ep31-get-all-todos/app/main.jsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import './stylesheets/main.css';
2+
3+
import React from 'react';
4+
import App from './components/App';
5+
6+
main();
7+
8+
function main() {
9+
var div = document.createElement('div');
10+
div.setAttribute("id", "todoapp");
11+
document.body.appendChild(div);
12+
13+
React.render(<App />, div);
14+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
var AppDispatcher = require('../dispatcher/AppDispatcher');
2+
var EventEmitter = require('events').EventEmitter;
3+
var assign = require('object-assign');
4+
5+
AppDispatcher.register(function(action) {
6+
7+
switch(action.actionType) {
8+
case 'TODO_DONE':
9+
console.log("Handling TODO_DONE using dispatcher in store");
10+
TodoStore.markTodoDone(action.todo);
11+
break;
12+
13+
case 'TODO_UNDONE':
14+
console.log("Handling TODO_UNDONE using dispatcher in store");
15+
TodoStore.markTodoUnDone(action.todo);
16+
break;
17+
18+
case 'TODO_DELETE':
19+
console.log("Handling TODO_DELETE using dispatcher in store");
20+
TodoStore.deleteTodo(action.todo);
21+
break;
22+
23+
case 'TODO_ADD':
24+
console.log("Handling TODO_ADD using dispatcher in store");
25+
TodoStore.getTodos();
26+
break;
27+
}
28+
29+
});
30+
31+
var _todos = {};
32+
var CHANGE_EVENT = 'change';
33+
34+
var TodoStore = assign({}, EventEmitter.prototype, {
35+
36+
deleteTodo: (todo) => {
37+
var newTodos = _todos.filter( (t) => {
38+
return t.id != todo.id
39+
} )
40+
_todos = newTodos;
41+
TodoStore.emitChange();
42+
},
43+
44+
markTodoDone: (todo) => {
45+
var _todo = _todos.filter((t) => {
46+
return t.id === todo.id;
47+
})[0];
48+
49+
_todo.done = true;
50+
TodoStore.emitChange();
51+
},
52+
53+
markTodoUnDone: (todo) => {
54+
var _todo = _todos.filter((t) => {
55+
return t.id === todo.id;
56+
})[0];
57+
58+
_todo.done = false;
59+
TodoStore.emitChange();
60+
},
61+
62+
setTodos: (todos) => {
63+
_todos = todos;
64+
TodoStore.emitChange();
65+
},
66+
67+
getTodos: () => {
68+
return _todos;
69+
},
70+
71+
emitChange: function() {
72+
this.emit(CHANGE_EVENT);
73+
},
74+
75+
addChangeListener: function (callback) {
76+
console.log("registering callback for changelistener");
77+
this.on(CHANGE_EVENT, callback);
78+
}
79+
})
80+
81+
module.exports = TodoStore;

0 commit comments

Comments
 (0)