From 75bf5181640b77143073bf7a10e5ffb505b895c5 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 12 Oct 2015 18:42:36 -0400 Subject: [PATCH 01/27] baseline for ep29 --- ep29-emit/README.md | 13 ++ ep29-emit/app/actions/TodoActions.js | 68 ++++++++ ep29-emit/app/components/App.jsx | 74 +++++++++ ep29-emit/app/components/DisplayItem.jsx | 86 ++++++++++ ep29-emit/app/components/DisplayList.jsx | 21 +++ ep29-emit/app/dispatcher/AppDispatcher.js | 3 + ep29-emit/app/main.jsx | 14 ++ ep29-emit/app/stores/TodoStore.js | 77 +++++++++ ep29-emit/app/stylesheets/main.css | 190 ++++++++++++++++++++++ ep29-emit/app/utils/api.js | 62 +++++++ ep29-emit/app/utils/constants.js | 5 + ep29-emit/package.json | 32 ++++ ep29-emit/webpack.config.js | 54 ++++++ 13 files changed, 699 insertions(+) create mode 100644 ep29-emit/README.md create mode 100644 ep29-emit/app/actions/TodoActions.js create mode 100644 ep29-emit/app/components/App.jsx create mode 100644 ep29-emit/app/components/DisplayItem.jsx create mode 100644 ep29-emit/app/components/DisplayList.jsx create mode 100644 ep29-emit/app/dispatcher/AppDispatcher.js create mode 100644 ep29-emit/app/main.jsx create mode 100644 ep29-emit/app/stores/TodoStore.js create mode 100644 ep29-emit/app/stylesheets/main.css create mode 100644 ep29-emit/app/utils/api.js create mode 100644 ep29-emit/app/utils/constants.js create mode 100644 ep29-emit/package.json create mode 100644 ep29-emit/webpack.config.js diff --git a/ep29-emit/README.md b/ep29-emit/README.md new file mode 100644 index 0000000..0f6225e --- /dev/null +++ b/ep29-emit/README.md @@ -0,0 +1,13 @@ +#### Setting up the application + +``` +npm install +npm start +``` + +Visit http://localhost:8080 in browser. + +#### Notes + +* `npm install random-key --save` +* [Source code](...) diff --git a/ep29-emit/app/actions/TodoActions.js b/ep29-emit/app/actions/TodoActions.js new file mode 100644 index 0000000..9da58ed --- /dev/null +++ b/ep29-emit/app/actions/TodoActions.js @@ -0,0 +1,68 @@ +var api = require("../utils/api"); +var TodoStore = require("../stores/TodoStore"); +var AppDispatcher = require('../dispatcher/AppDispatcher'); + +var TodoActions = { + + addTodo: (todo) => { + console.log("adding TODO"); + api.addTodo(todo) + .then( () => { + console.log("Added TODO successfully"); + TodoActions.getAllTodosAndUpdateStore(); + }) + }, + + deleteTodo: (todo) => { + console.log("Deleting TODO"); + api.deleteTodo(todo.id) + .then( () => { + console.log("Deleted TODO successfully"); + AppDispatcher.dispatch({ + actionType: 'TODO_DELETE', + todo: todo + }); + }) + }, + + markTodoDone: (todo) => { + console.log("Marking TODO as done"); + api.markTodoDone(todo) + .then( () => { + console.log("marked TODO as done successfully"); + AppDispatcher.dispatch({ + actionType: 'TODO_DONE', + todo: todo + }); + + }) + }, + + markTodoUnDone: (todo) => { + console.log("Marking TODO as undone"); + api.markTodoUnDone(todo) + .then( () => { + console.log("marked TODO as undone successfully"); + AppDispatcher.dispatch({ + actionType: 'TODO_UNDONE', + todo: todo + }); + }) + }, + + getAllTodosAndUpdateStore: () => { + console.log("Performing getAllTodos"); + api.getTodos() + .then( (responseData) => { + var todos = responseData.todos; + console.log("new todos", todos); + TodoStore.setTodos(todos); + AppDispatcher.dispatch({ + actionType: 'TODO_ADD' + }); + }) + } + +} + +module.exports = TodoActions; diff --git a/ep29-emit/app/components/App.jsx b/ep29-emit/app/components/App.jsx new file mode 100644 index 0000000..1dff5bb --- /dev/null +++ b/ep29-emit/app/components/App.jsx @@ -0,0 +1,74 @@ +import React from 'react'; +import DisplayList from './DisplayList'; + +var rand = require('random-key'); +var api = require("../utils/api"); +var TodoActions = require("../actions/TodoActions"); +var TodoStore = require("../stores/TodoStore"); + +export default class App extends React.Component { + + constructor () { + super(); + this.state = { title: '', todos: [] }; + + this.getAllTodos(); + } + + componentDidMount () { + var storeIsTellingUsThatDataHasChanged = (todos) => { + console.log("Store is telling us that data has change"); + this.setState({todos: todos}); + } + TodoStore.addChangeListener(storeIsTellingUsThatDataHasChanged); + } + + getAllTodos () { + api.getTodos() + .then( (responseData) => { + var todos = responseData.todos; + this.setState({todos: todos }); + TodoStore.setTodos(todos); + }) + } + + handleSubmit (event) { + event.preventDefault(); + + var newTodo = { title: this.state.title, done: false }; + + TodoActions.addTodo(newTodo); + this.setState({ title: '' }); + } + + handleChange (event) { + var title = event.target.value; + this.setState({ title: title }); + } + + handleClearCompleted (event) { + var newTodos = this.state.todos.filter((todo) => { return !todo.done}); + this.setState({ todos: newTodos }); + } + + render () { + return
+

TODO

+
+ +
+ + + +
+ All: ({ this.state.todos.length }) | + Completed: ({ this.state.todos.filter((todo) => { return todo.done }).length }) | + Pending: ({ this.state.todos.filter((todo) => { return !todo.done }).length }) | + Clear Completed +
+
; + } +} diff --git a/ep29-emit/app/components/DisplayItem.jsx b/ep29-emit/app/components/DisplayItem.jsx new file mode 100644 index 0000000..47d9af2 --- /dev/null +++ b/ep29-emit/app/components/DisplayItem.jsx @@ -0,0 +1,86 @@ +import React from 'react'; + +var TodoActions = require('../actions/TodoActions'); + +export default class DisplayItem extends React.Component { + + constructor () { + super(); + this.state = { editing: false } + } + + componentDidMount () { + this.setState({ changedText: this.props.todo.title }); + } + + handleEditing (event) { + this.setState({ editing: true, changedText: this.props.todo.title }); + } + + handleEditingDone (event) { + if (event.keyCode === 13 ) { // submit + this.setState({ editing: false }); + } + } + + handleEditingChange (event) { + var _changedText = event.target.value; + this.setState({ changedText: _changedText }); + } + + toggleDone (todo) { + if (todo.done) { + TodoActions.markTodoUnDone(todo); + } else { + TodoActions.markTodoDone(todo); + } + } + + handleDeleteTodoClick (todo) { + TodoActions.deleteTodo(todo); + } + + render () { + var todo = this.props.todo; + + var viewStyle = {}; + var editStyle = {}; + + if (this.state.editing) { + viewStyle.display = 'none'; + } else { + editStyle.display = 'none'; + } + + return
  • +
    + + + + + + [x] + +
    + + +
  • + } + +} + +DisplayItem.propTypes = { + todo: React.PropTypes.object.isRequired +} diff --git a/ep29-emit/app/components/DisplayList.jsx b/ep29-emit/app/components/DisplayList.jsx new file mode 100644 index 0000000..3cd852e --- /dev/null +++ b/ep29-emit/app/components/DisplayList.jsx @@ -0,0 +1,21 @@ +import React from 'react'; +import DisplayItem from './DisplayItem'; + +export default class DisplayList extends React.Component { + + render () { + return + } + +} + +DisplayList.propTypes = { + todos: React.PropTypes.array.isRequired +} diff --git a/ep29-emit/app/dispatcher/AppDispatcher.js b/ep29-emit/app/dispatcher/AppDispatcher.js new file mode 100644 index 0000000..5231a4e --- /dev/null +++ b/ep29-emit/app/dispatcher/AppDispatcher.js @@ -0,0 +1,3 @@ +var Dispatcher = require('flux').Dispatcher; + +module.exports = new Dispatcher(); diff --git a/ep29-emit/app/main.jsx b/ep29-emit/app/main.jsx new file mode 100644 index 0000000..aee7cdf --- /dev/null +++ b/ep29-emit/app/main.jsx @@ -0,0 +1,14 @@ +import './stylesheets/main.css'; + +import React from 'react'; +import App from './components/App'; + +main(); + +function main() { + var div = document.createElement('div'); + div.setAttribute("id", "todoapp"); + document.body.appendChild(div); + + React.render(, div); +} diff --git a/ep29-emit/app/stores/TodoStore.js b/ep29-emit/app/stores/TodoStore.js new file mode 100644 index 0000000..0db76d5 --- /dev/null +++ b/ep29-emit/app/stores/TodoStore.js @@ -0,0 +1,77 @@ +var AppDispatcher = require('../dispatcher/AppDispatcher'); + +AppDispatcher.register(function(action) { + + switch(action.actionType) { + case 'TODO_DONE': + console.log("Handling TODO_DONE using dispatcher in store"); + TodoStore.markTodoDone(action.todo); + break; + + case 'TODO_UNDONE': + console.log("Handling TODO_UNDONE using dispatcher in store"); + TodoStore.markTodoUnDone(action.todo); + break; + + case 'TODO_DELETE': + console.log("Handling TODO_DELETE using dispatcher in store"); + TodoStore.deleteTodo(action.todo); + break; + + case 'TODO_ADD': + console.log("Handling TODO_ADD using dispatcher in store"); + TodoStore.getTodos(); + break; + } + +}); + +var _todos = {}; +var _callback; + +var TodoStore = { + + deleteTodo: (todo) => { + var newTodos = _todos.filter( (t) => { + return t.id != todo.id + } ) + _todos = newTodos; + _callback(_todos); + }, + + markTodoDone: (todo) => { + var _todo = _todos.filter((t) => { + return t.id === todo.id; + })[0]; + + _todo.done = true; + _callback(_todos); + }, + + markTodoUnDone: (todo) => { + var _todo = _todos.filter((t) => { + return t.id === todo.id; + })[0]; + + _todo.done = false; + _callback(_todos); + }, + + setTodos: (todos) => { + _todos = todos; + console.log("TodoStore", TodoStore.getTodos()); + _callback(todos); + }, + + getTodos: () => { + return _todos; + _callback(todos); + }, + + addChangeListener: function (callback) { + console.log("registering callback for changelistener"); + _callback = callback; + } +} + +module.exports = TodoStore; diff --git a/ep29-emit/app/stylesheets/main.css b/ep29-emit/app/stylesheets/main.css new file mode 100644 index 0000000..ac2d81f --- /dev/null +++ b/ep29-emit/app/stylesheets/main.css @@ -0,0 +1,190 @@ +html, +body { + margin: 0; + padding: 0; +} + +body { + font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #eeeeee; + color: #333333; + width: 520px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; +} + +#todoapp { + background: #fff; + padding: 20px; + margin-bottom: 40px; + -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + -o-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + -webkit-border-radius: 0 0 5px 5px; + -moz-border-radius: 0 0 5px 5px; + -ms-border-radius: 0 0 5px 5px; + -o-border-radius: 0 0 5px 5px; + border-radius: 0 0 5px 5px; +} + +#todoapp h1 { + font-size: 36px; + font-weight: bold; + text-align: center; + padding: 0 0 10px 0; +} + +#todoapp input[type="text"] { + width: 466px; + font-size: 24px; + font-family: inherit; + line-height: 1.4em; + border: 0; + outline: none; + padding: 6px; + border: 1px solid #999999; + -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; + -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; + -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; + -o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; + box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; +} + +#todoapp input::-webkit-input-placeholder { + font-style: italic; +} + +#todo-list { + margin: 10px 0; + padding: 0; + list-style: none; +} + +#todo-list li { + padding: 18px 20px 18px 0; + position: relative; + font-size: 24px; + border-bottom: 1px solid #cccccc; +} + +#todo-list li:last-child { + border-bottom: none; +} + +#todo-list li.done label { + color: #777777; + text-decoration: line-through; +} + +#todo-list .destroy { + position: absolute; + right: 5px; + top: 20px; + display: none; + cursor: pointer; + width: 20px; + height: 20px; +} + +#todo-list li:hover .destroy { + display: block; +} + +#todo-list .destroy:hover { + background-position: 0 -20px; +} + +#todo-list li.editing { + border-bottom: none; + margin-top: -1px; + padding: 0; +} + +#todo-list li.editing:last-child { + margin-bottom: -1px; +} + +#todo-list li .view label { + word-break: break-word; +} + +#todoapp footer { + margin: 0 -20px -20px -20px; + overflow: hidden; + color: #555555; + background: #f4fce8; + border-top: 1px solid #ededed; + padding: 0 20px; + line-height: 37px; + -webkit-border-radius: 0 0 5px 5px; + -moz-border-radius: 0 0 5px 5px; + -ms-border-radius: 0 0 5px 5px; + -o-border-radius: 0 0 5px 5px; + border-radius: 0 0 5px 5px; +} + +#clear-completed { + float: right; + line-height: 20px; + text-decoration: none; + background: rgba(0, 0, 0, 0.1); + color: #555555; + font-size: 11px; + margin-top: 8px; + margin-bottom: 8px; + padding: 0 10px 1px; + cursor: pointer; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; + -ms-border-radius: 12px; + -o-border-radius: 12px; + border-radius: 12px; + -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; + -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; + -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; + -o-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; +} + +#clear-completed:hover { + background: rgba(0, 0, 0, 0.15); + -webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; + -moz-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; + -ms-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; + -o-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; + box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; +} + +#clear-completed:active { + position: relative; + top: 1px; +} + +#todo-count span { + font-weight: bold; +} + +#instructions { + margin: 10px auto; + color: #777777; + text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0; + text-align: center; +} + +#instructions a { + color: #336699; +} + +#credits { + margin: 30px auto; + color: #999; + text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0; + text-align: center; +} + +#credits a { + color: #888; +} diff --git a/ep29-emit/app/utils/api.js b/ep29-emit/app/utils/api.js new file mode 100644 index 0000000..1cfd44b --- /dev/null +++ b/ep29-emit/app/utils/api.js @@ -0,0 +1,62 @@ +require('whatwg-fetch'); +var Constants = require("./constants"); +var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } + +var api = { + generateUrlWithApiKey(endpoint) { + return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; + }, + + getTodos () { + var url = this.generateUrlWithApiKey('todos'); + return fetch(url) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to get all tasks list.', error) ); + }, + + addTodo (todo) { + var url = this.generateUrlWithApiKey('todos'); + var options = { + method: 'POST', + headers: HEADER, + body: JSON.stringify({todo: todo}) + }; + return fetch(url, options) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to add a TODO.', error) ); + }, + + markTodoDone (todo) { + var url = this.generateUrlWithApiKey('todos/' + todo.id); + var options = { + method: 'PUT', + headers: HEADER, + body: JSON.stringify({done: true}) + }; + return fetch(url, options) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to mark task as done. ', error) ); + }, + + markTodoUnDone (todo) { + var url = this.generateUrlWithApiKey('todos/' + todo.id); + var options = { + method: 'PUT', + headers: HEADER, + body: JSON.stringify({done: false}) + }; + return fetch(url, options) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to mark task as undone. ', error) ); + }, + + deleteTodo (idToBeDeleted, processDataCallback) { + var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); + return fetch(url, { method: 'DELETE' }) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to delete TODO.', error) ); + }, + +}; + +module.exports = api; diff --git a/ep29-emit/app/utils/constants.js b/ep29-emit/app/utils/constants.js new file mode 100644 index 0000000..2affc3c --- /dev/null +++ b/ep29-emit/app/utils/constants.js @@ -0,0 +1,5 @@ +var Constants = { + BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", + API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" +}; +module.exports = Constants; diff --git a/ep29-emit/package.json b/ep29-emit/package.json new file mode 100644 index 0000000..b0d9658 --- /dev/null +++ b/ep29-emit/package.json @@ -0,0 +1,32 @@ +{ + "name": "learning-reactjs-in-steps", + "version": "0.0.1", + "description": "Learn ReactJS in steps", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "TAGET=build webpack", + "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" + }, + "author": "Neeraj Singh", + "license": "ISC", + "devDependencies": { + "babel-core": "^5.6.15", + "babel-loader": "^5.3.1", + "css-loader": "^0.15.1", + "html-webpack-plugin": "^1.5.2", + "node-libs-browser": "^0.5.2", + "react-hot-loader": "^1.2.7", + "style-loader": "^0.12.3", + "webpack": "^1.10.1", + "webpack-dev-server": "^1.10.1", + "webpack-merge": "^0.1.2" + }, + "dependencies": { + "flux": "^2.1.1", + "jquery": "1.11.3", + "random-key": "^0.3.2", + "react": "^0.13.3", + "whatwg-fetch": "^0.9.0" + } +} diff --git a/ep29-emit/webpack.config.js b/ep29-emit/webpack.config.js new file mode 100644 index 0000000..bb8e6c1 --- /dev/null +++ b/ep29-emit/webpack.config.js @@ -0,0 +1,54 @@ +var path = require('path'); +var HtmlWebpackPlugin = require('html-webpack-plugin'); +var merge = require('webpack-merge'); + +var TARGET = process.env.TARGET; +var ROOT_PATH = path.resolve(__dirname); + +var common = { + entry: [path.resolve(ROOT_PATH, 'app/main')], + resolve: { + extensions: ['', '.js', '.jsx'], + }, + output: { + path: path.resolve(ROOT_PATH, 'build'), + filename: 'bundle.js', + }, + plugins: [ + new HtmlWebpackPlugin({ title: 'Todo app', }), + ], + module: { + loaders: [ + { + test: /\.css$/, + loaders: ['style', 'css'], + }, + { + test: /\.jsx?$/, + loader: 'babel?stage=1', + include: path.resolve(ROOT_PATH, 'app'), + } + ], + }, +}; + +if (TARGET === 'build') { + module.exports = common; +} + +if (TARGET === 'dev') { + module.exports = merge(common, { + entry: [ + 'webpack-dev-server/client?http://0.0.0.0:8080', + 'webpack/hot/dev-server' + ], + module: { + loaders: [ { + test: /\.jsx?$/, + loaders: ['react-hot', 'babel?stage=1'], + include: path.resolve(ROOT_PATH, 'app'), + }, + ], + }, + }); +} From 2360122ac54a483bee5f18181fc78420f1355c7c Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 12 Oct 2015 18:43:18 -0400 Subject: [PATCH 02/27] deleted comments from Actions --- ep28-more-dispatcher-usage/app/actions/TodoActions.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ep28-more-dispatcher-usage/app/actions/TodoActions.js b/ep28-more-dispatcher-usage/app/actions/TodoActions.js index 9da58ed..4ab006f 100644 --- a/ep28-more-dispatcher-usage/app/actions/TodoActions.js +++ b/ep28-more-dispatcher-usage/app/actions/TodoActions.js @@ -5,19 +5,15 @@ var AppDispatcher = require('../dispatcher/AppDispatcher'); var TodoActions = { addTodo: (todo) => { - console.log("adding TODO"); api.addTodo(todo) .then( () => { - console.log("Added TODO successfully"); TodoActions.getAllTodosAndUpdateStore(); }) }, deleteTodo: (todo) => { - console.log("Deleting TODO"); api.deleteTodo(todo.id) .then( () => { - console.log("Deleted TODO successfully"); AppDispatcher.dispatch({ actionType: 'TODO_DELETE', todo: todo @@ -26,10 +22,8 @@ var TodoActions = { }, markTodoDone: (todo) => { - console.log("Marking TODO as done"); api.markTodoDone(todo) .then( () => { - console.log("marked TODO as done successfully"); AppDispatcher.dispatch({ actionType: 'TODO_DONE', todo: todo @@ -39,10 +33,8 @@ var TodoActions = { }, markTodoUnDone: (todo) => { - console.log("Marking TODO as undone"); api.markTodoUnDone(todo) .then( () => { - console.log("marked TODO as undone successfully"); AppDispatcher.dispatch({ actionType: 'TODO_UNDONE', todo: todo @@ -51,11 +43,9 @@ var TodoActions = { }, getAllTodosAndUpdateStore: () => { - console.log("Performing getAllTodos"); api.getTodos() .then( (responseData) => { var todos = responseData.todos; - console.log("new todos", todos); TodoStore.setTodos(todos); AppDispatcher.dispatch({ actionType: 'TODO_ADD' From 5a29f671c0f572ae17004844bfad9582b9999045 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 12 Oct 2015 18:43:54 -0400 Subject: [PATCH 03/27] deleted log messages from Store --- ep28-more-dispatcher-usage/app/stores/TodoStore.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ep28-more-dispatcher-usage/app/stores/TodoStore.js b/ep28-more-dispatcher-usage/app/stores/TodoStore.js index 0db76d5..7371e13 100644 --- a/ep28-more-dispatcher-usage/app/stores/TodoStore.js +++ b/ep28-more-dispatcher-usage/app/stores/TodoStore.js @@ -4,22 +4,18 @@ AppDispatcher.register(function(action) { switch(action.actionType) { case 'TODO_DONE': - console.log("Handling TODO_DONE using dispatcher in store"); TodoStore.markTodoDone(action.todo); break; case 'TODO_UNDONE': - console.log("Handling TODO_UNDONE using dispatcher in store"); TodoStore.markTodoUnDone(action.todo); break; case 'TODO_DELETE': - console.log("Handling TODO_DELETE using dispatcher in store"); TodoStore.deleteTodo(action.todo); break; case 'TODO_ADD': - console.log("Handling TODO_ADD using dispatcher in store"); TodoStore.getTodos(); break; } From d607370b0177aaca7877cbba9cd4ffe1c112c516 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 12 Oct 2015 18:50:56 -0400 Subject: [PATCH 04/27] extracted constants to constants --- ep28-more-dispatcher-usage/app/actions/TodoActions.js | 9 +++++---- ep28-more-dispatcher-usage/app/stores/TodoStore.js | 9 +++++---- ep28-more-dispatcher-usage/app/utils/constants.js | 6 +++++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/ep28-more-dispatcher-usage/app/actions/TodoActions.js b/ep28-more-dispatcher-usage/app/actions/TodoActions.js index 4ab006f..b6f2666 100644 --- a/ep28-more-dispatcher-usage/app/actions/TodoActions.js +++ b/ep28-more-dispatcher-usage/app/actions/TodoActions.js @@ -1,6 +1,7 @@ var api = require("../utils/api"); var TodoStore = require("../stores/TodoStore"); var AppDispatcher = require('../dispatcher/AppDispatcher'); +var Constants = require("../utils/constants"); var TodoActions = { @@ -15,7 +16,7 @@ var TodoActions = { api.deleteTodo(todo.id) .then( () => { AppDispatcher.dispatch({ - actionType: 'TODO_DELETE', + actionType: Constants.TODO_DELETE, todo: todo }); }) @@ -25,7 +26,7 @@ var TodoActions = { api.markTodoDone(todo) .then( () => { AppDispatcher.dispatch({ - actionType: 'TODO_DONE', + actionType: Constants.TODO_DONE, todo: todo }); @@ -36,7 +37,7 @@ var TodoActions = { api.markTodoUnDone(todo) .then( () => { AppDispatcher.dispatch({ - actionType: 'TODO_UNDONE', + actionType: Constants.TODO_UNDONE, todo: todo }); }) @@ -48,7 +49,7 @@ var TodoActions = { var todos = responseData.todos; TodoStore.setTodos(todos); AppDispatcher.dispatch({ - actionType: 'TODO_ADD' + actionType: Constants.TODO_ADD }); }) } diff --git a/ep28-more-dispatcher-usage/app/stores/TodoStore.js b/ep28-more-dispatcher-usage/app/stores/TodoStore.js index 7371e13..f2b31f4 100644 --- a/ep28-more-dispatcher-usage/app/stores/TodoStore.js +++ b/ep28-more-dispatcher-usage/app/stores/TodoStore.js @@ -1,21 +1,22 @@ var AppDispatcher = require('../dispatcher/AppDispatcher'); +var Constants = require("../utils/constants"); AppDispatcher.register(function(action) { switch(action.actionType) { - case 'TODO_DONE': + case Constants.TODO_DONE: TodoStore.markTodoDone(action.todo); break; - case 'TODO_UNDONE': + case Constants.TODO_UNDONE: TodoStore.markTodoUnDone(action.todo); break; - case 'TODO_DELETE': + case Constants.TODO_DELETE: TodoStore.deleteTodo(action.todo); break; - case 'TODO_ADD': + case Constants.TODO_ADD: TodoStore.getTodos(); break; } diff --git a/ep28-more-dispatcher-usage/app/utils/constants.js b/ep28-more-dispatcher-usage/app/utils/constants.js index 2affc3c..6f68eaa 100644 --- a/ep28-more-dispatcher-usage/app/utils/constants.js +++ b/ep28-more-dispatcher-usage/app/utils/constants.js @@ -1,5 +1,9 @@ var Constants = { BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", - API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" + API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965", + TODO_DONE: 'TODO_DONE', + TODO_UNDONE: 'TODO_UNDONE', + TODO_DELETE: 'TODO_DELETE', + TODO_ADD: 'TODO_ADD' }; module.exports = Constants; From 1129bef698c19c7a9142062c984f2dbbdde8feba Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 12 Oct 2015 19:33:10 -0400 Subject: [PATCH 05/27] indentation --- ep28-more-dispatcher-usage/app/components/App.jsx | 1 - ep28-more-dispatcher-usage/app/components/DisplayList.jsx | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ep28-more-dispatcher-usage/app/components/App.jsx b/ep28-more-dispatcher-usage/app/components/App.jsx index 1dff5bb..b9150d2 100644 --- a/ep28-more-dispatcher-usage/app/components/App.jsx +++ b/ep28-more-dispatcher-usage/app/components/App.jsx @@ -11,7 +11,6 @@ export default class App extends React.Component { constructor () { super(); this.state = { title: '', todos: [] }; - this.getAllTodos(); } diff --git a/ep28-more-dispatcher-usage/app/components/DisplayList.jsx b/ep28-more-dispatcher-usage/app/components/DisplayList.jsx index 3cd852e..a254b58 100644 --- a/ep28-more-dispatcher-usage/app/components/DisplayList.jsx +++ b/ep28-more-dispatcher-usage/app/components/DisplayList.jsx @@ -10,7 +10,8 @@ export default class DisplayList extends React.Component { - }) } + }) + } } From 21bc1c95d8744346e962eed518eb35cd55506417 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 12 Oct 2015 19:34:36 -0400 Subject: [PATCH 06/27] blank line --- ep28-more-dispatcher-usage/app/utils/constants.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ep28-more-dispatcher-usage/app/utils/constants.js b/ep28-more-dispatcher-usage/app/utils/constants.js index 6f68eaa..3025eba 100644 --- a/ep28-more-dispatcher-usage/app/utils/constants.js +++ b/ep28-more-dispatcher-usage/app/utils/constants.js @@ -6,4 +6,5 @@ var Constants = { TODO_DELETE: 'TODO_DELETE', TODO_ADD: 'TODO_ADD' }; + module.exports = Constants; From 2bace811b53d2dee1efab5c291188b77825ff9e4 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Wed, 14 Oct 2015 15:49:58 -0400 Subject: [PATCH 07/27] register on --- ep29-emit/app/stores/TodoStore.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ep29-emit/app/stores/TodoStore.js b/ep29-emit/app/stores/TodoStore.js index 0db76d5..30a726d 100644 --- a/ep29-emit/app/stores/TodoStore.js +++ b/ep29-emit/app/stores/TodoStore.js @@ -27,7 +27,7 @@ AppDispatcher.register(function(action) { }); var _todos = {}; -var _callback; +var CHANGE_EVENT = 'change'; var TodoStore = { @@ -70,7 +70,7 @@ var TodoStore = { addChangeListener: function (callback) { console.log("registering callback for changelistener"); - _callback = callback; + this.on(CHANGE_EVENT, callback); } } From eaf4663862ae64c000f1b102b4b05d1647bfb422 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Wed, 14 Oct 2015 15:51:18 -0400 Subject: [PATCH 08/27] emitChange --- ep29-emit/app/stores/TodoStore.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ep29-emit/app/stores/TodoStore.js b/ep29-emit/app/stores/TodoStore.js index 30a726d..b2b9f1e 100644 --- a/ep29-emit/app/stores/TodoStore.js +++ b/ep29-emit/app/stores/TodoStore.js @@ -68,6 +68,10 @@ var TodoStore = { _callback(todos); }, + emitChange: function() { + this.emit(CHANGE_EVENT); + }, + addChangeListener: function (callback) { console.log("registering callback for changelistener"); this.on(CHANGE_EVENT, callback); From 1e87a588bbf0416b2f3fddd9afe5f5826e27626d Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Fri, 16 Oct 2015 10:39:47 -0400 Subject: [PATCH 09/27] updated README --- ep29-emit/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ep29-emit/README.md b/ep29-emit/README.md index 0f6225e..fb6770b 100644 --- a/ep29-emit/README.md +++ b/ep29-emit/README.md @@ -9,5 +9,5 @@ Visit http://localhost:8080 in browser. #### Notes -* `npm install random-key --save` +* [Nodejs Events](https://nodejs.org/api/events.html) * [Source code](...) From 43c732d7e8f3ae93ddd6df47ed65aece577a787c Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Fri, 16 Oct 2015 10:40:55 -0400 Subject: [PATCH 10/27] added EventEmitter --- ep29-emit/app/stores/TodoStore.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ep29-emit/app/stores/TodoStore.js b/ep29-emit/app/stores/TodoStore.js index b2b9f1e..4af13d7 100644 --- a/ep29-emit/app/stores/TodoStore.js +++ b/ep29-emit/app/stores/TodoStore.js @@ -1,4 +1,5 @@ var AppDispatcher = require('../dispatcher/AppDispatcher'); +var EventEmitter = require('events').EventEmitter; AppDispatcher.register(function(action) { From 3c820032553d49fa947516bf09b89806f99b3b5c Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Fri, 16 Oct 2015 10:41:54 -0400 Subject: [PATCH 11/27] use eventemitter --- ep29-emit/app/stores/TodoStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ep29-emit/app/stores/TodoStore.js b/ep29-emit/app/stores/TodoStore.js index 4af13d7..5aca376 100644 --- a/ep29-emit/app/stores/TodoStore.js +++ b/ep29-emit/app/stores/TodoStore.js @@ -30,7 +30,7 @@ AppDispatcher.register(function(action) { var _todos = {}; var CHANGE_EVENT = 'change'; -var TodoStore = { +var TodoStore = assign({}, EventEmitter.prototype, { deleteTodo: (todo) => { var newTodos = _todos.filter( (t) => { From f6bb456d06354483a4eb2f87e7727c7dbff3e042 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Fri, 16 Oct 2015 10:43:36 -0400 Subject: [PATCH 12/27] object-assign --- ep29-emit/README.md | 2 ++ ep29-emit/package.json | 1 + 2 files changed, 3 insertions(+) diff --git a/ep29-emit/README.md b/ep29-emit/README.md index fb6770b..497a54e 100644 --- a/ep29-emit/README.md +++ b/ep29-emit/README.md @@ -10,4 +10,6 @@ Visit http://localhost:8080 in browser. #### Notes * [Nodejs Events](https://nodejs.org/api/events.html) +* [object-assign](https://www.npmjs.com/package/object-assign) +* `npm install --save object-assign` * [Source code](...) diff --git a/ep29-emit/package.json b/ep29-emit/package.json index b0d9658..3a4ee8f 100644 --- a/ep29-emit/package.json +++ b/ep29-emit/package.json @@ -25,6 +25,7 @@ "dependencies": { "flux": "^2.1.1", "jquery": "1.11.3", + "object-assign": "^4.0.1", "random-key": "^0.3.2", "react": "^0.13.3", "whatwg-fetch": "^0.9.0" From 8ff55c459ac683094706382a42046751aea70278 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Sat, 17 Oct 2015 10:33:43 -0400 Subject: [PATCH 13/27] require object-assign --- ep29-emit/app/stores/TodoStore.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ep29-emit/app/stores/TodoStore.js b/ep29-emit/app/stores/TodoStore.js index 5aca376..5fbbf00 100644 --- a/ep29-emit/app/stores/TodoStore.js +++ b/ep29-emit/app/stores/TodoStore.js @@ -1,5 +1,6 @@ var AppDispatcher = require('../dispatcher/AppDispatcher'); var EventEmitter = require('events').EventEmitter; +var assign = require('object-assign'); AppDispatcher.register(function(action) { @@ -77,6 +78,6 @@ var TodoStore = assign({}, EventEmitter.prototype, { console.log("registering callback for changelistener"); this.on(CHANGE_EVENT, callback); } -} +}) module.exports = TodoStore; From d3ef6b12996db26e8b08656e1726ae54384536b5 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Sat, 17 Oct 2015 10:35:46 -0400 Subject: [PATCH 14/27] remove all _callbacks --- ep29-emit/app/stores/TodoStore.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ep29-emit/app/stores/TodoStore.js b/ep29-emit/app/stores/TodoStore.js index 5fbbf00..e927e6b 100644 --- a/ep29-emit/app/stores/TodoStore.js +++ b/ep29-emit/app/stores/TodoStore.js @@ -38,7 +38,6 @@ var TodoStore = assign({}, EventEmitter.prototype, { return t.id != todo.id } ) _todos = newTodos; - _callback(_todos); }, markTodoDone: (todo) => { @@ -47,7 +46,6 @@ var TodoStore = assign({}, EventEmitter.prototype, { })[0]; _todo.done = true; - _callback(_todos); }, markTodoUnDone: (todo) => { @@ -56,18 +54,15 @@ var TodoStore = assign({}, EventEmitter.prototype, { })[0]; _todo.done = false; - _callback(_todos); }, setTodos: (todos) => { _todos = todos; console.log("TodoStore", TodoStore.getTodos()); - _callback(todos); }, getTodos: () => { return _todos; - _callback(todos); }, emitChange: function() { From 9f4603bac7f25dfbc5b0313a27ec68ee2dc5e21f Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Sun, 18 Oct 2015 09:49:54 -0400 Subject: [PATCH 15/27] emit change --- ep29-emit/app/stores/TodoStore.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ep29-emit/app/stores/TodoStore.js b/ep29-emit/app/stores/TodoStore.js index e927e6b..f2fb5af 100644 --- a/ep29-emit/app/stores/TodoStore.js +++ b/ep29-emit/app/stores/TodoStore.js @@ -46,6 +46,7 @@ var TodoStore = assign({}, EventEmitter.prototype, { })[0]; _todo.done = true; + TodoStore.emitChange(); }, markTodoUnDone: (todo) => { @@ -54,6 +55,7 @@ var TodoStore = assign({}, EventEmitter.prototype, { })[0]; _todo.done = false; + TodoStore.emitChange(); }, setTodos: (todos) => { From c43dbb31290feefe3f6f7149388b54b598a5d789 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Sun, 18 Oct 2015 09:50:05 -0400 Subject: [PATCH 16/27] get TODOs --- ep29-emit/app/components/App.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ep29-emit/app/components/App.jsx b/ep29-emit/app/components/App.jsx index 1dff5bb..370ee75 100644 --- a/ep29-emit/app/components/App.jsx +++ b/ep29-emit/app/components/App.jsx @@ -16,8 +16,11 @@ export default class App extends React.Component { } componentDidMount () { - var storeIsTellingUsThatDataHasChanged = (todos) => { + var storeIsTellingUsThatDataHasChanged = () => { console.log("Store is telling us that data has change"); + var todos = TodoStore.getTodos(); + console.log("todos is"); + console.log(todos); this.setState({todos: todos}); } TodoStore.addChangeListener(storeIsTellingUsThatDataHasChanged); From 575189c7245603e95b9bd0dba1262d3136e0e4e4 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Sun, 18 Oct 2015 09:51:09 -0400 Subject: [PATCH 17/27] emitchange after deleting todo --- ep29-emit/app/stores/TodoStore.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ep29-emit/app/stores/TodoStore.js b/ep29-emit/app/stores/TodoStore.js index f2fb5af..eda3274 100644 --- a/ep29-emit/app/stores/TodoStore.js +++ b/ep29-emit/app/stores/TodoStore.js @@ -38,6 +38,7 @@ var TodoStore = assign({}, EventEmitter.prototype, { return t.id != todo.id } ) _todos = newTodos; + TodoStore.emitChange(); }, markTodoDone: (todo) => { From d8e4e0d41d77a6d1178f56cbaeb6329592a8062f Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Sun, 18 Oct 2015 09:51:50 -0400 Subject: [PATCH 18/27] emit change after adding todo --- ep29-emit/app/stores/TodoStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ep29-emit/app/stores/TodoStore.js b/ep29-emit/app/stores/TodoStore.js index eda3274..9c5ed9e 100644 --- a/ep29-emit/app/stores/TodoStore.js +++ b/ep29-emit/app/stores/TodoStore.js @@ -61,7 +61,7 @@ var TodoStore = assign({}, EventEmitter.prototype, { setTodos: (todos) => { _todos = todos; - console.log("TodoStore", TodoStore.getTodos()); + TodoStore.emitChange(); }, getTodos: () => { From e82562374631b7c1285ca3f1f36b27084e304e4b Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 16 Nov 2015 11:36:09 -0500 Subject: [PATCH 19/27] split method into two thens --- ep29-emit/app/actions/TodoActions.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/ep29-emit/app/actions/TodoActions.js b/ep29-emit/app/actions/TodoActions.js index 9da58ed..af8571b 100644 --- a/ep29-emit/app/actions/TodoActions.js +++ b/ep29-emit/app/actions/TodoActions.js @@ -7,9 +7,19 @@ var TodoActions = { addTodo: (todo) => { console.log("adding TODO"); api.addTodo(todo) + .then( () => { + api.getTodos() + .then( (responseData) => { + var todos = responseData.todos; + console.log("All todos", todos); + TodoStore.setTodos(todos); + }) + }) .then( () => { console.log("Added TODO successfully"); - TodoActions.getAllTodosAndUpdateStore(); + AppDispatcher.dispatch({ + actionType: 'TODO_ADD' + }); }) }, @@ -50,18 +60,8 @@ var TodoActions = { }) }, - getAllTodosAndUpdateStore: () => { - console.log("Performing getAllTodos"); - api.getTodos() - .then( (responseData) => { - var todos = responseData.todos; - console.log("new todos", todos); - TodoStore.setTodos(todos); - AppDispatcher.dispatch({ - actionType: 'TODO_ADD' - }); - }) - } + + } From d8357235d63215a7ec344118cfb495f357fbd90e Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 16 Nov 2015 16:11:55 -0500 Subject: [PATCH 20/27] baseline for ep30 --- .../README.md | 15 ++ .../app/actions/TodoActions.js | 68 +++++++ .../app/components/App.jsx | 77 +++++++ .../app/components/DisplayItem.jsx | 86 ++++++++ .../app/components/DisplayList.jsx | 21 ++ .../app/dispatcher/AppDispatcher.js | 3 + .../app/main.jsx | 14 ++ .../app/stores/TodoStore.js | 81 ++++++++ .../app/stylesheets/main.css | 190 ++++++++++++++++++ .../app/utils/api.js | 62 ++++++ .../app/utils/constants.js | 5 + .../package.json | 33 +++ .../webpack.config.js | 54 +++++ 13 files changed, 709 insertions(+) create mode 100644 ep30-extract-form-into-componenet-from-app/README.md create mode 100644 ep30-extract-form-into-componenet-from-app/app/actions/TodoActions.js create mode 100644 ep30-extract-form-into-componenet-from-app/app/components/App.jsx create mode 100644 ep30-extract-form-into-componenet-from-app/app/components/DisplayItem.jsx create mode 100644 ep30-extract-form-into-componenet-from-app/app/components/DisplayList.jsx create mode 100644 ep30-extract-form-into-componenet-from-app/app/dispatcher/AppDispatcher.js create mode 100644 ep30-extract-form-into-componenet-from-app/app/main.jsx create mode 100644 ep30-extract-form-into-componenet-from-app/app/stores/TodoStore.js create mode 100644 ep30-extract-form-into-componenet-from-app/app/stylesheets/main.css create mode 100644 ep30-extract-form-into-componenet-from-app/app/utils/api.js create mode 100644 ep30-extract-form-into-componenet-from-app/app/utils/constants.js create mode 100644 ep30-extract-form-into-componenet-from-app/package.json create mode 100644 ep30-extract-form-into-componenet-from-app/webpack.config.js diff --git a/ep30-extract-form-into-componenet-from-app/README.md b/ep30-extract-form-into-componenet-from-app/README.md new file mode 100644 index 0000000..497a54e --- /dev/null +++ b/ep30-extract-form-into-componenet-from-app/README.md @@ -0,0 +1,15 @@ +#### Setting up the application + +``` +npm install +npm start +``` + +Visit http://localhost:8080 in browser. + +#### Notes + +* [Nodejs Events](https://nodejs.org/api/events.html) +* [object-assign](https://www.npmjs.com/package/object-assign) +* `npm install --save object-assign` +* [Source code](...) diff --git a/ep30-extract-form-into-componenet-from-app/app/actions/TodoActions.js b/ep30-extract-form-into-componenet-from-app/app/actions/TodoActions.js new file mode 100644 index 0000000..af8571b --- /dev/null +++ b/ep30-extract-form-into-componenet-from-app/app/actions/TodoActions.js @@ -0,0 +1,68 @@ +var api = require("../utils/api"); +var TodoStore = require("../stores/TodoStore"); +var AppDispatcher = require('../dispatcher/AppDispatcher'); + +var TodoActions = { + + addTodo: (todo) => { + console.log("adding TODO"); + api.addTodo(todo) + .then( () => { + api.getTodos() + .then( (responseData) => { + var todos = responseData.todos; + console.log("All todos", todos); + TodoStore.setTodos(todos); + }) + }) + .then( () => { + console.log("Added TODO successfully"); + AppDispatcher.dispatch({ + actionType: 'TODO_ADD' + }); + }) + }, + + deleteTodo: (todo) => { + console.log("Deleting TODO"); + api.deleteTodo(todo.id) + .then( () => { + console.log("Deleted TODO successfully"); + AppDispatcher.dispatch({ + actionType: 'TODO_DELETE', + todo: todo + }); + }) + }, + + markTodoDone: (todo) => { + console.log("Marking TODO as done"); + api.markTodoDone(todo) + .then( () => { + console.log("marked TODO as done successfully"); + AppDispatcher.dispatch({ + actionType: 'TODO_DONE', + todo: todo + }); + + }) + }, + + markTodoUnDone: (todo) => { + console.log("Marking TODO as undone"); + api.markTodoUnDone(todo) + .then( () => { + console.log("marked TODO as undone successfully"); + AppDispatcher.dispatch({ + actionType: 'TODO_UNDONE', + todo: todo + }); + }) + }, + + + + +} + +module.exports = TodoActions; diff --git a/ep30-extract-form-into-componenet-from-app/app/components/App.jsx b/ep30-extract-form-into-componenet-from-app/app/components/App.jsx new file mode 100644 index 0000000..370ee75 --- /dev/null +++ b/ep30-extract-form-into-componenet-from-app/app/components/App.jsx @@ -0,0 +1,77 @@ +import React from 'react'; +import DisplayList from './DisplayList'; + +var rand = require('random-key'); +var api = require("../utils/api"); +var TodoActions = require("../actions/TodoActions"); +var TodoStore = require("../stores/TodoStore"); + +export default class App extends React.Component { + + constructor () { + super(); + this.state = { title: '', todos: [] }; + + this.getAllTodos(); + } + + componentDidMount () { + var storeIsTellingUsThatDataHasChanged = () => { + console.log("Store is telling us that data has change"); + var todos = TodoStore.getTodos(); + console.log("todos is"); + console.log(todos); + this.setState({todos: todos}); + } + TodoStore.addChangeListener(storeIsTellingUsThatDataHasChanged); + } + + getAllTodos () { + api.getTodos() + .then( (responseData) => { + var todos = responseData.todos; + this.setState({todos: todos }); + TodoStore.setTodos(todos); + }) + } + + handleSubmit (event) { + event.preventDefault(); + + var newTodo = { title: this.state.title, done: false }; + + TodoActions.addTodo(newTodo); + this.setState({ title: '' }); + } + + handleChange (event) { + var title = event.target.value; + this.setState({ title: title }); + } + + handleClearCompleted (event) { + var newTodos = this.state.todos.filter((todo) => { return !todo.done}); + this.setState({ todos: newTodos }); + } + + render () { + return
    +

    TODO

    +
    + +
    + + + +
    + All: ({ this.state.todos.length }) | + Completed: ({ this.state.todos.filter((todo) => { return todo.done }).length }) | + Pending: ({ this.state.todos.filter((todo) => { return !todo.done }).length }) | + Clear Completed +
    +
    ; + } +} diff --git a/ep30-extract-form-into-componenet-from-app/app/components/DisplayItem.jsx b/ep30-extract-form-into-componenet-from-app/app/components/DisplayItem.jsx new file mode 100644 index 0000000..47d9af2 --- /dev/null +++ b/ep30-extract-form-into-componenet-from-app/app/components/DisplayItem.jsx @@ -0,0 +1,86 @@ +import React from 'react'; + +var TodoActions = require('../actions/TodoActions'); + +export default class DisplayItem extends React.Component { + + constructor () { + super(); + this.state = { editing: false } + } + + componentDidMount () { + this.setState({ changedText: this.props.todo.title }); + } + + handleEditing (event) { + this.setState({ editing: true, changedText: this.props.todo.title }); + } + + handleEditingDone (event) { + if (event.keyCode === 13 ) { // submit + this.setState({ editing: false }); + } + } + + handleEditingChange (event) { + var _changedText = event.target.value; + this.setState({ changedText: _changedText }); + } + + toggleDone (todo) { + if (todo.done) { + TodoActions.markTodoUnDone(todo); + } else { + TodoActions.markTodoDone(todo); + } + } + + handleDeleteTodoClick (todo) { + TodoActions.deleteTodo(todo); + } + + render () { + var todo = this.props.todo; + + var viewStyle = {}; + var editStyle = {}; + + if (this.state.editing) { + viewStyle.display = 'none'; + } else { + editStyle.display = 'none'; + } + + return
  • +
    + + + + + + [x] + +
    + + +
  • + } + +} + +DisplayItem.propTypes = { + todo: React.PropTypes.object.isRequired +} diff --git a/ep30-extract-form-into-componenet-from-app/app/components/DisplayList.jsx b/ep30-extract-form-into-componenet-from-app/app/components/DisplayList.jsx new file mode 100644 index 0000000..3cd852e --- /dev/null +++ b/ep30-extract-form-into-componenet-from-app/app/components/DisplayList.jsx @@ -0,0 +1,21 @@ +import React from 'react'; +import DisplayItem from './DisplayItem'; + +export default class DisplayList extends React.Component { + + render () { + return
      + { this.props.todos.map((todo, i) => { + return
      + +
      + }) } +
    + } + +} + +DisplayList.propTypes = { + todos: React.PropTypes.array.isRequired +} diff --git a/ep30-extract-form-into-componenet-from-app/app/dispatcher/AppDispatcher.js b/ep30-extract-form-into-componenet-from-app/app/dispatcher/AppDispatcher.js new file mode 100644 index 0000000..5231a4e --- /dev/null +++ b/ep30-extract-form-into-componenet-from-app/app/dispatcher/AppDispatcher.js @@ -0,0 +1,3 @@ +var Dispatcher = require('flux').Dispatcher; + +module.exports = new Dispatcher(); diff --git a/ep30-extract-form-into-componenet-from-app/app/main.jsx b/ep30-extract-form-into-componenet-from-app/app/main.jsx new file mode 100644 index 0000000..aee7cdf --- /dev/null +++ b/ep30-extract-form-into-componenet-from-app/app/main.jsx @@ -0,0 +1,14 @@ +import './stylesheets/main.css'; + +import React from 'react'; +import App from './components/App'; + +main(); + +function main() { + var div = document.createElement('div'); + div.setAttribute("id", "todoapp"); + document.body.appendChild(div); + + React.render(, div); +} diff --git a/ep30-extract-form-into-componenet-from-app/app/stores/TodoStore.js b/ep30-extract-form-into-componenet-from-app/app/stores/TodoStore.js new file mode 100644 index 0000000..9c5ed9e --- /dev/null +++ b/ep30-extract-form-into-componenet-from-app/app/stores/TodoStore.js @@ -0,0 +1,81 @@ +var AppDispatcher = require('../dispatcher/AppDispatcher'); +var EventEmitter = require('events').EventEmitter; +var assign = require('object-assign'); + +AppDispatcher.register(function(action) { + + switch(action.actionType) { + case 'TODO_DONE': + console.log("Handling TODO_DONE using dispatcher in store"); + TodoStore.markTodoDone(action.todo); + break; + + case 'TODO_UNDONE': + console.log("Handling TODO_UNDONE using dispatcher in store"); + TodoStore.markTodoUnDone(action.todo); + break; + + case 'TODO_DELETE': + console.log("Handling TODO_DELETE using dispatcher in store"); + TodoStore.deleteTodo(action.todo); + break; + + case 'TODO_ADD': + console.log("Handling TODO_ADD using dispatcher in store"); + TodoStore.getTodos(); + break; + } + +}); + +var _todos = {}; +var CHANGE_EVENT = 'change'; + +var TodoStore = assign({}, EventEmitter.prototype, { + + deleteTodo: (todo) => { + var newTodos = _todos.filter( (t) => { + return t.id != todo.id + } ) + _todos = newTodos; + TodoStore.emitChange(); + }, + + markTodoDone: (todo) => { + var _todo = _todos.filter((t) => { + return t.id === todo.id; + })[0]; + + _todo.done = true; + TodoStore.emitChange(); + }, + + markTodoUnDone: (todo) => { + var _todo = _todos.filter((t) => { + return t.id === todo.id; + })[0]; + + _todo.done = false; + TodoStore.emitChange(); + }, + + setTodos: (todos) => { + _todos = todos; + TodoStore.emitChange(); + }, + + getTodos: () => { + return _todos; + }, + + emitChange: function() { + this.emit(CHANGE_EVENT); + }, + + addChangeListener: function (callback) { + console.log("registering callback for changelistener"); + this.on(CHANGE_EVENT, callback); + } +}) + +module.exports = TodoStore; diff --git a/ep30-extract-form-into-componenet-from-app/app/stylesheets/main.css b/ep30-extract-form-into-componenet-from-app/app/stylesheets/main.css new file mode 100644 index 0000000..ac2d81f --- /dev/null +++ b/ep30-extract-form-into-componenet-from-app/app/stylesheets/main.css @@ -0,0 +1,190 @@ +html, +body { + margin: 0; + padding: 0; +} + +body { + font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #eeeeee; + color: #333333; + width: 520px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; +} + +#todoapp { + background: #fff; + padding: 20px; + margin-bottom: 40px; + -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + -o-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + -webkit-border-radius: 0 0 5px 5px; + -moz-border-radius: 0 0 5px 5px; + -ms-border-radius: 0 0 5px 5px; + -o-border-radius: 0 0 5px 5px; + border-radius: 0 0 5px 5px; +} + +#todoapp h1 { + font-size: 36px; + font-weight: bold; + text-align: center; + padding: 0 0 10px 0; +} + +#todoapp input[type="text"] { + width: 466px; + font-size: 24px; + font-family: inherit; + line-height: 1.4em; + border: 0; + outline: none; + padding: 6px; + border: 1px solid #999999; + -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; + -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; + -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; + -o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; + box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; +} + +#todoapp input::-webkit-input-placeholder { + font-style: italic; +} + +#todo-list { + margin: 10px 0; + padding: 0; + list-style: none; +} + +#todo-list li { + padding: 18px 20px 18px 0; + position: relative; + font-size: 24px; + border-bottom: 1px solid #cccccc; +} + +#todo-list li:last-child { + border-bottom: none; +} + +#todo-list li.done label { + color: #777777; + text-decoration: line-through; +} + +#todo-list .destroy { + position: absolute; + right: 5px; + top: 20px; + display: none; + cursor: pointer; + width: 20px; + height: 20px; +} + +#todo-list li:hover .destroy { + display: block; +} + +#todo-list .destroy:hover { + background-position: 0 -20px; +} + +#todo-list li.editing { + border-bottom: none; + margin-top: -1px; + padding: 0; +} + +#todo-list li.editing:last-child { + margin-bottom: -1px; +} + +#todo-list li .view label { + word-break: break-word; +} + +#todoapp footer { + margin: 0 -20px -20px -20px; + overflow: hidden; + color: #555555; + background: #f4fce8; + border-top: 1px solid #ededed; + padding: 0 20px; + line-height: 37px; + -webkit-border-radius: 0 0 5px 5px; + -moz-border-radius: 0 0 5px 5px; + -ms-border-radius: 0 0 5px 5px; + -o-border-radius: 0 0 5px 5px; + border-radius: 0 0 5px 5px; +} + +#clear-completed { + float: right; + line-height: 20px; + text-decoration: none; + background: rgba(0, 0, 0, 0.1); + color: #555555; + font-size: 11px; + margin-top: 8px; + margin-bottom: 8px; + padding: 0 10px 1px; + cursor: pointer; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; + -ms-border-radius: 12px; + -o-border-radius: 12px; + border-radius: 12px; + -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; + -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; + -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; + -o-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; +} + +#clear-completed:hover { + background: rgba(0, 0, 0, 0.15); + -webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; + -moz-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; + -ms-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; + -o-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; + box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; +} + +#clear-completed:active { + position: relative; + top: 1px; +} + +#todo-count span { + font-weight: bold; +} + +#instructions { + margin: 10px auto; + color: #777777; + text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0; + text-align: center; +} + +#instructions a { + color: #336699; +} + +#credits { + margin: 30px auto; + color: #999; + text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0; + text-align: center; +} + +#credits a { + color: #888; +} diff --git a/ep30-extract-form-into-componenet-from-app/app/utils/api.js b/ep30-extract-form-into-componenet-from-app/app/utils/api.js new file mode 100644 index 0000000..1cfd44b --- /dev/null +++ b/ep30-extract-form-into-componenet-from-app/app/utils/api.js @@ -0,0 +1,62 @@ +require('whatwg-fetch'); +var Constants = require("./constants"); +var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } + +var api = { + generateUrlWithApiKey(endpoint) { + return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; + }, + + getTodos () { + var url = this.generateUrlWithApiKey('todos'); + return fetch(url) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to get all tasks list.', error) ); + }, + + addTodo (todo) { + var url = this.generateUrlWithApiKey('todos'); + var options = { + method: 'POST', + headers: HEADER, + body: JSON.stringify({todo: todo}) + }; + return fetch(url, options) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to add a TODO.', error) ); + }, + + markTodoDone (todo) { + var url = this.generateUrlWithApiKey('todos/' + todo.id); + var options = { + method: 'PUT', + headers: HEADER, + body: JSON.stringify({done: true}) + }; + return fetch(url, options) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to mark task as done. ', error) ); + }, + + markTodoUnDone (todo) { + var url = this.generateUrlWithApiKey('todos/' + todo.id); + var options = { + method: 'PUT', + headers: HEADER, + body: JSON.stringify({done: false}) + }; + return fetch(url, options) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to mark task as undone. ', error) ); + }, + + deleteTodo (idToBeDeleted, processDataCallback) { + var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); + return fetch(url, { method: 'DELETE' }) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to delete TODO.', error) ); + }, + +}; + +module.exports = api; diff --git a/ep30-extract-form-into-componenet-from-app/app/utils/constants.js b/ep30-extract-form-into-componenet-from-app/app/utils/constants.js new file mode 100644 index 0000000..2affc3c --- /dev/null +++ b/ep30-extract-form-into-componenet-from-app/app/utils/constants.js @@ -0,0 +1,5 @@ +var Constants = { + BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", + API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" +}; +module.exports = Constants; diff --git a/ep30-extract-form-into-componenet-from-app/package.json b/ep30-extract-form-into-componenet-from-app/package.json new file mode 100644 index 0000000..3a4ee8f --- /dev/null +++ b/ep30-extract-form-into-componenet-from-app/package.json @@ -0,0 +1,33 @@ +{ + "name": "learning-reactjs-in-steps", + "version": "0.0.1", + "description": "Learn ReactJS in steps", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "TAGET=build webpack", + "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" + }, + "author": "Neeraj Singh", + "license": "ISC", + "devDependencies": { + "babel-core": "^5.6.15", + "babel-loader": "^5.3.1", + "css-loader": "^0.15.1", + "html-webpack-plugin": "^1.5.2", + "node-libs-browser": "^0.5.2", + "react-hot-loader": "^1.2.7", + "style-loader": "^0.12.3", + "webpack": "^1.10.1", + "webpack-dev-server": "^1.10.1", + "webpack-merge": "^0.1.2" + }, + "dependencies": { + "flux": "^2.1.1", + "jquery": "1.11.3", + "object-assign": "^4.0.1", + "random-key": "^0.3.2", + "react": "^0.13.3", + "whatwg-fetch": "^0.9.0" + } +} diff --git a/ep30-extract-form-into-componenet-from-app/webpack.config.js b/ep30-extract-form-into-componenet-from-app/webpack.config.js new file mode 100644 index 0000000..bb8e6c1 --- /dev/null +++ b/ep30-extract-form-into-componenet-from-app/webpack.config.js @@ -0,0 +1,54 @@ +var path = require('path'); +var HtmlWebpackPlugin = require('html-webpack-plugin'); +var merge = require('webpack-merge'); + +var TARGET = process.env.TARGET; +var ROOT_PATH = path.resolve(__dirname); + +var common = { + entry: [path.resolve(ROOT_PATH, 'app/main')], + resolve: { + extensions: ['', '.js', '.jsx'], + }, + output: { + path: path.resolve(ROOT_PATH, 'build'), + filename: 'bundle.js', + }, + plugins: [ + new HtmlWebpackPlugin({ title: 'Todo app', }), + ], + module: { + loaders: [ + { + test: /\.css$/, + loaders: ['style', 'css'], + }, + { + test: /\.jsx?$/, + loader: 'babel?stage=1', + include: path.resolve(ROOT_PATH, 'app'), + } + ], + }, +}; + +if (TARGET === 'build') { + module.exports = common; +} + +if (TARGET === 'dev') { + module.exports = merge(common, { + entry: [ + 'webpack-dev-server/client?http://0.0.0.0:8080', + 'webpack/hot/dev-server' + ], + module: { + loaders: [ { + test: /\.jsx?$/, + loaders: ['react-hot', 'babel?stage=1'], + include: path.resolve(ROOT_PATH, 'app'), + }, + ], + }, + }); +} From 61571c1ff1affe141b4790e9e73e1c1904dc00ab Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 16 Nov 2015 16:29:14 -0500 Subject: [PATCH 21/27] extracted code into TodoForm --- .../app/components/App.jsx | 42 +++++-------------- .../app/components/TodoForm.jsx | 39 +++++++++++++++++ 2 files changed, 50 insertions(+), 31 deletions(-) create mode 100644 ep30-extract-form-into-componenet-from-app/app/components/TodoForm.jsx diff --git a/ep30-extract-form-into-componenet-from-app/app/components/App.jsx b/ep30-extract-form-into-componenet-from-app/app/components/App.jsx index 370ee75..dae7061 100644 --- a/ep30-extract-form-into-componenet-from-app/app/components/App.jsx +++ b/ep30-extract-form-into-componenet-from-app/app/components/App.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import TodoForm from './TodoForm'; import DisplayList from './DisplayList'; var rand = require('random-key'); @@ -35,43 +36,22 @@ export default class App extends React.Component { }) } - handleSubmit (event) { - event.preventDefault(); - - var newTodo = { title: this.state.title, done: false }; - - TodoActions.addTodo(newTodo); - this.setState({ title: '' }); - } - - handleChange (event) { - var title = event.target.value; - this.setState({ title: title }); - } - handleClearCompleted (event) { var newTodos = this.state.todos.filter((todo) => { return !todo.done}); this.setState({ todos: newTodos }); } render () { - return
    -

    TODO

    -
    - -
    - - + + - -
    - All: ({ this.state.todos.length }) | - Completed: ({ this.state.todos.filter((todo) => { return todo.done }).length }) | - Pending: ({ this.state.todos.filter((todo) => { return !todo.done }).length }) | - Clear Completed -
    -
    ; +
    + All: ({ this.state.todos.length }) | + Completed: ({ this.state.todos.filter((todo) => { return todo.done }).length }) | + Pending: ({ this.state.todos.filter((todo) => { return !todo.done }).length }) | + Clear Completed +
    + } } diff --git a/ep30-extract-form-into-componenet-from-app/app/components/TodoForm.jsx b/ep30-extract-form-into-componenet-from-app/app/components/TodoForm.jsx new file mode 100644 index 0000000..87916ed --- /dev/null +++ b/ep30-extract-form-into-componenet-from-app/app/components/TodoForm.jsx @@ -0,0 +1,39 @@ +import React from 'react'; +import DisplayList from './DisplayList'; +import DisplayItem from './DisplayItem'; + +var TodoActions = require('../actions/TodoActions'); + +export default class TodoForm extends React.Component { + + constructor () { + super(); + this.state = { editing: false } + } + + handleSubmit (event) { + event.preventDefault(); + + var newTodo = { title: this.state.title, done: false }; + + TodoActions.addTodo(newTodo); + this.setState({ title: '' }); + } + + handleChange (event) { + var title = event.target.value; + this.setState({ title: title }); + } + + render () { + return
    +

    TODO

    +
    + +
    +
    ; + } + +} From f89d93a5e756362a6b7f89dd4184357dc1a242b7 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 16 Nov 2015 16:31:59 -0500 Subject: [PATCH 22/27] deleted empty lines --- .../app/actions/TodoActions.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/ep30-extract-form-into-componenet-from-app/app/actions/TodoActions.js b/ep30-extract-form-into-componenet-from-app/app/actions/TodoActions.js index af8571b..649b648 100644 --- a/ep30-extract-form-into-componenet-from-app/app/actions/TodoActions.js +++ b/ep30-extract-form-into-componenet-from-app/app/actions/TodoActions.js @@ -60,9 +60,6 @@ var TodoActions = { }) }, - - - } module.exports = TodoActions; From 971c2cfda8f53cd09d09910a947d178cb4898ee0 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 16 Nov 2015 16:33:27 -0500 Subject: [PATCH 23/27] baseline for ep31 --- ep31-get-all-todos/README.md | 15 ++ ep31-get-all-todos/app/actions/TodoActions.js | 65 ++++++ ep31-get-all-todos/app/components/App.jsx | 57 ++++++ .../app/components/DisplayItem.jsx | 86 ++++++++ .../app/components/DisplayList.jsx | 21 ++ .../app/components/TodoForm.jsx | 39 ++++ .../app/dispatcher/AppDispatcher.js | 3 + ep31-get-all-todos/app/main.jsx | 14 ++ ep31-get-all-todos/app/stores/TodoStore.js | 81 ++++++++ ep31-get-all-todos/app/stylesheets/main.css | 190 ++++++++++++++++++ ep31-get-all-todos/app/utils/api.js | 62 ++++++ ep31-get-all-todos/app/utils/constants.js | 5 + ep31-get-all-todos/package.json | 33 +++ ep31-get-all-todos/webpack.config.js | 54 +++++ 14 files changed, 725 insertions(+) create mode 100644 ep31-get-all-todos/README.md create mode 100644 ep31-get-all-todos/app/actions/TodoActions.js create mode 100644 ep31-get-all-todos/app/components/App.jsx create mode 100644 ep31-get-all-todos/app/components/DisplayItem.jsx create mode 100644 ep31-get-all-todos/app/components/DisplayList.jsx create mode 100644 ep31-get-all-todos/app/components/TodoForm.jsx create mode 100644 ep31-get-all-todos/app/dispatcher/AppDispatcher.js create mode 100644 ep31-get-all-todos/app/main.jsx create mode 100644 ep31-get-all-todos/app/stores/TodoStore.js create mode 100644 ep31-get-all-todos/app/stylesheets/main.css create mode 100644 ep31-get-all-todos/app/utils/api.js create mode 100644 ep31-get-all-todos/app/utils/constants.js create mode 100644 ep31-get-all-todos/package.json create mode 100644 ep31-get-all-todos/webpack.config.js diff --git a/ep31-get-all-todos/README.md b/ep31-get-all-todos/README.md new file mode 100644 index 0000000..497a54e --- /dev/null +++ b/ep31-get-all-todos/README.md @@ -0,0 +1,15 @@ +#### Setting up the application + +``` +npm install +npm start +``` + +Visit http://localhost:8080 in browser. + +#### Notes + +* [Nodejs Events](https://nodejs.org/api/events.html) +* [object-assign](https://www.npmjs.com/package/object-assign) +* `npm install --save object-assign` +* [Source code](...) diff --git a/ep31-get-all-todos/app/actions/TodoActions.js b/ep31-get-all-todos/app/actions/TodoActions.js new file mode 100644 index 0000000..649b648 --- /dev/null +++ b/ep31-get-all-todos/app/actions/TodoActions.js @@ -0,0 +1,65 @@ +var api = require("../utils/api"); +var TodoStore = require("../stores/TodoStore"); +var AppDispatcher = require('../dispatcher/AppDispatcher'); + +var TodoActions = { + + addTodo: (todo) => { + console.log("adding TODO"); + api.addTodo(todo) + .then( () => { + api.getTodos() + .then( (responseData) => { + var todos = responseData.todos; + console.log("All todos", todos); + TodoStore.setTodos(todos); + }) + }) + .then( () => { + console.log("Added TODO successfully"); + AppDispatcher.dispatch({ + actionType: 'TODO_ADD' + }); + }) + }, + + deleteTodo: (todo) => { + console.log("Deleting TODO"); + api.deleteTodo(todo.id) + .then( () => { + console.log("Deleted TODO successfully"); + AppDispatcher.dispatch({ + actionType: 'TODO_DELETE', + todo: todo + }); + }) + }, + + markTodoDone: (todo) => { + console.log("Marking TODO as done"); + api.markTodoDone(todo) + .then( () => { + console.log("marked TODO as done successfully"); + AppDispatcher.dispatch({ + actionType: 'TODO_DONE', + todo: todo + }); + + }) + }, + + markTodoUnDone: (todo) => { + console.log("Marking TODO as undone"); + api.markTodoUnDone(todo) + .then( () => { + console.log("marked TODO as undone successfully"); + AppDispatcher.dispatch({ + actionType: 'TODO_UNDONE', + todo: todo + }); + }) + }, + +} + +module.exports = TodoActions; diff --git a/ep31-get-all-todos/app/components/App.jsx b/ep31-get-all-todos/app/components/App.jsx new file mode 100644 index 0000000..dae7061 --- /dev/null +++ b/ep31-get-all-todos/app/components/App.jsx @@ -0,0 +1,57 @@ +import React from 'react'; +import TodoForm from './TodoForm'; +import DisplayList from './DisplayList'; + +var rand = require('random-key'); +var api = require("../utils/api"); +var TodoActions = require("../actions/TodoActions"); +var TodoStore = require("../stores/TodoStore"); + +export default class App extends React.Component { + + constructor () { + super(); + this.state = { title: '', todos: [] }; + + this.getAllTodos(); + } + + componentDidMount () { + var storeIsTellingUsThatDataHasChanged = () => { + console.log("Store is telling us that data has change"); + var todos = TodoStore.getTodos(); + console.log("todos is"); + console.log(todos); + this.setState({todos: todos}); + } + TodoStore.addChangeListener(storeIsTellingUsThatDataHasChanged); + } + + getAllTodos () { + api.getTodos() + .then( (responseData) => { + var todos = responseData.todos; + this.setState({todos: todos }); + TodoStore.setTodos(todos); + }) + } + + handleClearCompleted (event) { + var newTodos = this.state.todos.filter((todo) => { return !todo.done}); + this.setState({ todos: newTodos }); + } + + render () { + return
    + + +
    + All: ({ this.state.todos.length }) | + Completed: ({ this.state.todos.filter((todo) => { return todo.done }).length }) | + Pending: ({ this.state.todos.filter((todo) => { return !todo.done }).length }) | + Clear Completed +
    +
    + } +} diff --git a/ep31-get-all-todos/app/components/DisplayItem.jsx b/ep31-get-all-todos/app/components/DisplayItem.jsx new file mode 100644 index 0000000..47d9af2 --- /dev/null +++ b/ep31-get-all-todos/app/components/DisplayItem.jsx @@ -0,0 +1,86 @@ +import React from 'react'; + +var TodoActions = require('../actions/TodoActions'); + +export default class DisplayItem extends React.Component { + + constructor () { + super(); + this.state = { editing: false } + } + + componentDidMount () { + this.setState({ changedText: this.props.todo.title }); + } + + handleEditing (event) { + this.setState({ editing: true, changedText: this.props.todo.title }); + } + + handleEditingDone (event) { + if (event.keyCode === 13 ) { // submit + this.setState({ editing: false }); + } + } + + handleEditingChange (event) { + var _changedText = event.target.value; + this.setState({ changedText: _changedText }); + } + + toggleDone (todo) { + if (todo.done) { + TodoActions.markTodoUnDone(todo); + } else { + TodoActions.markTodoDone(todo); + } + } + + handleDeleteTodoClick (todo) { + TodoActions.deleteTodo(todo); + } + + render () { + var todo = this.props.todo; + + var viewStyle = {}; + var editStyle = {}; + + if (this.state.editing) { + viewStyle.display = 'none'; + } else { + editStyle.display = 'none'; + } + + return
  • +
    + + + + + + [x] + +
    + + +
  • + } + +} + +DisplayItem.propTypes = { + todo: React.PropTypes.object.isRequired +} diff --git a/ep31-get-all-todos/app/components/DisplayList.jsx b/ep31-get-all-todos/app/components/DisplayList.jsx new file mode 100644 index 0000000..3cd852e --- /dev/null +++ b/ep31-get-all-todos/app/components/DisplayList.jsx @@ -0,0 +1,21 @@ +import React from 'react'; +import DisplayItem from './DisplayItem'; + +export default class DisplayList extends React.Component { + + render () { + return
      + { this.props.todos.map((todo, i) => { + return
      + +
      + }) } +
    + } + +} + +DisplayList.propTypes = { + todos: React.PropTypes.array.isRequired +} diff --git a/ep31-get-all-todos/app/components/TodoForm.jsx b/ep31-get-all-todos/app/components/TodoForm.jsx new file mode 100644 index 0000000..87916ed --- /dev/null +++ b/ep31-get-all-todos/app/components/TodoForm.jsx @@ -0,0 +1,39 @@ +import React from 'react'; +import DisplayList from './DisplayList'; +import DisplayItem from './DisplayItem'; + +var TodoActions = require('../actions/TodoActions'); + +export default class TodoForm extends React.Component { + + constructor () { + super(); + this.state = { editing: false } + } + + handleSubmit (event) { + event.preventDefault(); + + var newTodo = { title: this.state.title, done: false }; + + TodoActions.addTodo(newTodo); + this.setState({ title: '' }); + } + + handleChange (event) { + var title = event.target.value; + this.setState({ title: title }); + } + + render () { + return
    +

    TODO

    +
    + +
    +
    ; + } + +} diff --git a/ep31-get-all-todos/app/dispatcher/AppDispatcher.js b/ep31-get-all-todos/app/dispatcher/AppDispatcher.js new file mode 100644 index 0000000..5231a4e --- /dev/null +++ b/ep31-get-all-todos/app/dispatcher/AppDispatcher.js @@ -0,0 +1,3 @@ +var Dispatcher = require('flux').Dispatcher; + +module.exports = new Dispatcher(); diff --git a/ep31-get-all-todos/app/main.jsx b/ep31-get-all-todos/app/main.jsx new file mode 100644 index 0000000..aee7cdf --- /dev/null +++ b/ep31-get-all-todos/app/main.jsx @@ -0,0 +1,14 @@ +import './stylesheets/main.css'; + +import React from 'react'; +import App from './components/App'; + +main(); + +function main() { + var div = document.createElement('div'); + div.setAttribute("id", "todoapp"); + document.body.appendChild(div); + + React.render(, div); +} diff --git a/ep31-get-all-todos/app/stores/TodoStore.js b/ep31-get-all-todos/app/stores/TodoStore.js new file mode 100644 index 0000000..9c5ed9e --- /dev/null +++ b/ep31-get-all-todos/app/stores/TodoStore.js @@ -0,0 +1,81 @@ +var AppDispatcher = require('../dispatcher/AppDispatcher'); +var EventEmitter = require('events').EventEmitter; +var assign = require('object-assign'); + +AppDispatcher.register(function(action) { + + switch(action.actionType) { + case 'TODO_DONE': + console.log("Handling TODO_DONE using dispatcher in store"); + TodoStore.markTodoDone(action.todo); + break; + + case 'TODO_UNDONE': + console.log("Handling TODO_UNDONE using dispatcher in store"); + TodoStore.markTodoUnDone(action.todo); + break; + + case 'TODO_DELETE': + console.log("Handling TODO_DELETE using dispatcher in store"); + TodoStore.deleteTodo(action.todo); + break; + + case 'TODO_ADD': + console.log("Handling TODO_ADD using dispatcher in store"); + TodoStore.getTodos(); + break; + } + +}); + +var _todos = {}; +var CHANGE_EVENT = 'change'; + +var TodoStore = assign({}, EventEmitter.prototype, { + + deleteTodo: (todo) => { + var newTodos = _todos.filter( (t) => { + return t.id != todo.id + } ) + _todos = newTodos; + TodoStore.emitChange(); + }, + + markTodoDone: (todo) => { + var _todo = _todos.filter((t) => { + return t.id === todo.id; + })[0]; + + _todo.done = true; + TodoStore.emitChange(); + }, + + markTodoUnDone: (todo) => { + var _todo = _todos.filter((t) => { + return t.id === todo.id; + })[0]; + + _todo.done = false; + TodoStore.emitChange(); + }, + + setTodos: (todos) => { + _todos = todos; + TodoStore.emitChange(); + }, + + getTodos: () => { + return _todos; + }, + + emitChange: function() { + this.emit(CHANGE_EVENT); + }, + + addChangeListener: function (callback) { + console.log("registering callback for changelistener"); + this.on(CHANGE_EVENT, callback); + } +}) + +module.exports = TodoStore; diff --git a/ep31-get-all-todos/app/stylesheets/main.css b/ep31-get-all-todos/app/stylesheets/main.css new file mode 100644 index 0000000..ac2d81f --- /dev/null +++ b/ep31-get-all-todos/app/stylesheets/main.css @@ -0,0 +1,190 @@ +html, +body { + margin: 0; + padding: 0; +} + +body { + font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #eeeeee; + color: #333333; + width: 520px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; +} + +#todoapp { + background: #fff; + padding: 20px; + margin-bottom: 40px; + -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + -o-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; + -webkit-border-radius: 0 0 5px 5px; + -moz-border-radius: 0 0 5px 5px; + -ms-border-radius: 0 0 5px 5px; + -o-border-radius: 0 0 5px 5px; + border-radius: 0 0 5px 5px; +} + +#todoapp h1 { + font-size: 36px; + font-weight: bold; + text-align: center; + padding: 0 0 10px 0; +} + +#todoapp input[type="text"] { + width: 466px; + font-size: 24px; + font-family: inherit; + line-height: 1.4em; + border: 0; + outline: none; + padding: 6px; + border: 1px solid #999999; + -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; + -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; + -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; + -o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; + box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; +} + +#todoapp input::-webkit-input-placeholder { + font-style: italic; +} + +#todo-list { + margin: 10px 0; + padding: 0; + list-style: none; +} + +#todo-list li { + padding: 18px 20px 18px 0; + position: relative; + font-size: 24px; + border-bottom: 1px solid #cccccc; +} + +#todo-list li:last-child { + border-bottom: none; +} + +#todo-list li.done label { + color: #777777; + text-decoration: line-through; +} + +#todo-list .destroy { + position: absolute; + right: 5px; + top: 20px; + display: none; + cursor: pointer; + width: 20px; + height: 20px; +} + +#todo-list li:hover .destroy { + display: block; +} + +#todo-list .destroy:hover { + background-position: 0 -20px; +} + +#todo-list li.editing { + border-bottom: none; + margin-top: -1px; + padding: 0; +} + +#todo-list li.editing:last-child { + margin-bottom: -1px; +} + +#todo-list li .view label { + word-break: break-word; +} + +#todoapp footer { + margin: 0 -20px -20px -20px; + overflow: hidden; + color: #555555; + background: #f4fce8; + border-top: 1px solid #ededed; + padding: 0 20px; + line-height: 37px; + -webkit-border-radius: 0 0 5px 5px; + -moz-border-radius: 0 0 5px 5px; + -ms-border-radius: 0 0 5px 5px; + -o-border-radius: 0 0 5px 5px; + border-radius: 0 0 5px 5px; +} + +#clear-completed { + float: right; + line-height: 20px; + text-decoration: none; + background: rgba(0, 0, 0, 0.1); + color: #555555; + font-size: 11px; + margin-top: 8px; + margin-bottom: 8px; + padding: 0 10px 1px; + cursor: pointer; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; + -ms-border-radius: 12px; + -o-border-radius: 12px; + border-radius: 12px; + -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; + -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; + -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; + -o-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; +} + +#clear-completed:hover { + background: rgba(0, 0, 0, 0.15); + -webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; + -moz-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; + -ms-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; + -o-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; + box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; +} + +#clear-completed:active { + position: relative; + top: 1px; +} + +#todo-count span { + font-weight: bold; +} + +#instructions { + margin: 10px auto; + color: #777777; + text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0; + text-align: center; +} + +#instructions a { + color: #336699; +} + +#credits { + margin: 30px auto; + color: #999; + text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0; + text-align: center; +} + +#credits a { + color: #888; +} diff --git a/ep31-get-all-todos/app/utils/api.js b/ep31-get-all-todos/app/utils/api.js new file mode 100644 index 0000000..1cfd44b --- /dev/null +++ b/ep31-get-all-todos/app/utils/api.js @@ -0,0 +1,62 @@ +require('whatwg-fetch'); +var Constants = require("./constants"); +var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } + +var api = { + generateUrlWithApiKey(endpoint) { + return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; + }, + + getTodos () { + var url = this.generateUrlWithApiKey('todos'); + return fetch(url) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to get all tasks list.', error) ); + }, + + addTodo (todo) { + var url = this.generateUrlWithApiKey('todos'); + var options = { + method: 'POST', + headers: HEADER, + body: JSON.stringify({todo: todo}) + }; + return fetch(url, options) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to add a TODO.', error) ); + }, + + markTodoDone (todo) { + var url = this.generateUrlWithApiKey('todos/' + todo.id); + var options = { + method: 'PUT', + headers: HEADER, + body: JSON.stringify({done: true}) + }; + return fetch(url, options) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to mark task as done. ', error) ); + }, + + markTodoUnDone (todo) { + var url = this.generateUrlWithApiKey('todos/' + todo.id); + var options = { + method: 'PUT', + headers: HEADER, + body: JSON.stringify({done: false}) + }; + return fetch(url, options) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to mark task as undone. ', error) ); + }, + + deleteTodo (idToBeDeleted, processDataCallback) { + var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); + return fetch(url, { method: 'DELETE' }) + .then((res) => res.json()) + .catch( (error) => console.log('Failed to delete TODO.', error) ); + }, + +}; + +module.exports = api; diff --git a/ep31-get-all-todos/app/utils/constants.js b/ep31-get-all-todos/app/utils/constants.js new file mode 100644 index 0000000..2affc3c --- /dev/null +++ b/ep31-get-all-todos/app/utils/constants.js @@ -0,0 +1,5 @@ +var Constants = { + BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", + API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" +}; +module.exports = Constants; diff --git a/ep31-get-all-todos/package.json b/ep31-get-all-todos/package.json new file mode 100644 index 0000000..3a4ee8f --- /dev/null +++ b/ep31-get-all-todos/package.json @@ -0,0 +1,33 @@ +{ + "name": "learning-reactjs-in-steps", + "version": "0.0.1", + "description": "Learn ReactJS in steps", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "TAGET=build webpack", + "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" + }, + "author": "Neeraj Singh", + "license": "ISC", + "devDependencies": { + "babel-core": "^5.6.15", + "babel-loader": "^5.3.1", + "css-loader": "^0.15.1", + "html-webpack-plugin": "^1.5.2", + "node-libs-browser": "^0.5.2", + "react-hot-loader": "^1.2.7", + "style-loader": "^0.12.3", + "webpack": "^1.10.1", + "webpack-dev-server": "^1.10.1", + "webpack-merge": "^0.1.2" + }, + "dependencies": { + "flux": "^2.1.1", + "jquery": "1.11.3", + "object-assign": "^4.0.1", + "random-key": "^0.3.2", + "react": "^0.13.3", + "whatwg-fetch": "^0.9.0" + } +} diff --git a/ep31-get-all-todos/webpack.config.js b/ep31-get-all-todos/webpack.config.js new file mode 100644 index 0000000..bb8e6c1 --- /dev/null +++ b/ep31-get-all-todos/webpack.config.js @@ -0,0 +1,54 @@ +var path = require('path'); +var HtmlWebpackPlugin = require('html-webpack-plugin'); +var merge = require('webpack-merge'); + +var TARGET = process.env.TARGET; +var ROOT_PATH = path.resolve(__dirname); + +var common = { + entry: [path.resolve(ROOT_PATH, 'app/main')], + resolve: { + extensions: ['', '.js', '.jsx'], + }, + output: { + path: path.resolve(ROOT_PATH, 'build'), + filename: 'bundle.js', + }, + plugins: [ + new HtmlWebpackPlugin({ title: 'Todo app', }), + ], + module: { + loaders: [ + { + test: /\.css$/, + loaders: ['style', 'css'], + }, + { + test: /\.jsx?$/, + loader: 'babel?stage=1', + include: path.resolve(ROOT_PATH, 'app'), + } + ], + }, +}; + +if (TARGET === 'build') { + module.exports = common; +} + +if (TARGET === 'dev') { + module.exports = merge(common, { + entry: [ + 'webpack-dev-server/client?http://0.0.0.0:8080', + 'webpack/hot/dev-server' + ], + module: { + loaders: [ { + test: /\.jsx?$/, + loaders: ['react-hot', 'babel?stage=1'], + include: path.resolve(ROOT_PATH, 'app'), + }, + ], + }, + }); +} From 791d101c039c80b6640be69020194296c3b0d7cc Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 16 Nov 2015 16:40:29 -0500 Subject: [PATCH 24/27] TODO_ALL action --- .../app/actions/TodoActions.js | 18 ++++++++++++------ .../app/components/App.jsx | 7 +------ .../app/stores/TodoStore.js | 5 +++++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/ep30-extract-form-into-componenet-from-app/app/actions/TodoActions.js b/ep30-extract-form-into-componenet-from-app/app/actions/TodoActions.js index 649b648..bffb30d 100644 --- a/ep30-extract-form-into-componenet-from-app/app/actions/TodoActions.js +++ b/ep30-extract-form-into-componenet-from-app/app/actions/TodoActions.js @@ -4,16 +4,22 @@ var AppDispatcher = require('../dispatcher/AppDispatcher'); var TodoActions = { + allTodos: () => { + api.getTodos() + .then( (responseData) => { + console.log("Got All TODOs successfully"); + AppDispatcher.dispatch({ + actionType: 'TODO_ALL', + todos: todos + }); + }) + }, + addTodo: (todo) => { console.log("adding TODO"); api.addTodo(todo) .then( () => { - api.getTodos() - .then( (responseData) => { - var todos = responseData.todos; - console.log("All todos", todos); - TodoStore.setTodos(todos); - }) + allTodos(); }) .then( () => { console.log("Added TODO successfully"); diff --git a/ep30-extract-form-into-componenet-from-app/app/components/App.jsx b/ep30-extract-form-into-componenet-from-app/app/components/App.jsx index dae7061..db715e9 100644 --- a/ep30-extract-form-into-componenet-from-app/app/components/App.jsx +++ b/ep30-extract-form-into-componenet-from-app/app/components/App.jsx @@ -28,12 +28,7 @@ export default class App extends React.Component { } getAllTodos () { - api.getTodos() - .then( (responseData) => { - var todos = responseData.todos; - this.setState({todos: todos }); - TodoStore.setTodos(todos); - }) + TodoActions.allTodos(); } handleClearCompleted (event) { diff --git a/ep30-extract-form-into-componenet-from-app/app/stores/TodoStore.js b/ep30-extract-form-into-componenet-from-app/app/stores/TodoStore.js index 9c5ed9e..c4e4f59 100644 --- a/ep30-extract-form-into-componenet-from-app/app/stores/TodoStore.js +++ b/ep30-extract-form-into-componenet-from-app/app/stores/TodoStore.js @@ -24,6 +24,11 @@ AppDispatcher.register(function(action) { console.log("Handling TODO_ADD using dispatcher in store"); TodoStore.getTodos(); break; + + case 'TODO_ALL': + console.log("Handling TODO_ALL using dispatcher in store"); + TodoStore.setTodos(action.todos); + break; } }); From 9b5dfa30c401a65575104d64b8072ffec38499b0 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 16 Nov 2015 16:41:38 -0500 Subject: [PATCH 25/27] pulled up getAllTodos method --- .../app/components/App.jsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/ep30-extract-form-into-componenet-from-app/app/components/App.jsx b/ep30-extract-form-into-componenet-from-app/app/components/App.jsx index db715e9..3f27795 100644 --- a/ep30-extract-form-into-componenet-from-app/app/components/App.jsx +++ b/ep30-extract-form-into-componenet-from-app/app/components/App.jsx @@ -13,24 +13,19 @@ export default class App extends React.Component { super(); this.state = { title: '', todos: [] }; - this.getAllTodos(); + TodoActions.allTodos(); } componentDidMount () { var storeIsTellingUsThatDataHasChanged = () => { console.log("Store is telling us that data has change"); var todos = TodoStore.getTodos(); - console.log("todos is"); - console.log(todos); + console.log("todos :", todos); this.setState({todos: todos}); } TodoStore.addChangeListener(storeIsTellingUsThatDataHasChanged); } - getAllTodos () { - TodoActions.allTodos(); - } - handleClearCompleted (event) { var newTodos = this.state.todos.filter((todo) => { return !todo.done}); this.setState({ todos: newTodos }); From ed6a8a51bb8f5df74284756099bd5d8be7f4b3d0 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Mon, 16 Nov 2015 18:10:38 -0500 Subject: [PATCH 26/27] cleaned up README --- ep19-call-api-jquery/README.md | 3 +-- ep20-using-fetch/README.md | 3 +-- ep21-general-refactoring/README.md | 5 ----- ep22-building-todoactions/README.md | 5 ----- ep23-building-todostore/README.md | 5 ----- ep24-delete-todo-using-flux/README.md | 5 ----- ep25-add-todo-using-flux/README.md | 5 ----- ep26-enhance-todo-store/README.md | 5 ----- ep27-use-dispatcher/README.md | 5 ----- ep28-more-dispatcher-usage/README.md | 5 ----- ep29-emit/README.md | 1 - ep30-extract-form-into-componenet-from-app/README.md | 7 ------- ep31-get-all-todos/README.md | 7 ------- 13 files changed, 2 insertions(+), 59 deletions(-) diff --git a/ep19-call-api-jquery/README.md b/ep19-call-api-jquery/README.md index 0f6225e..2af3db9 100644 --- a/ep19-call-api-jquery/README.md +++ b/ep19-call-api-jquery/README.md @@ -9,5 +9,4 @@ Visit http://localhost:8080 in browser. #### Notes -* `npm install random-key --save` -* [Source code](...) +* `npm install jquery --save` diff --git a/ep20-using-fetch/README.md b/ep20-using-fetch/README.md index 0f6225e..a404b18 100644 --- a/ep20-using-fetch/README.md +++ b/ep20-using-fetch/README.md @@ -9,5 +9,4 @@ Visit http://localhost:8080 in browser. #### Notes -* `npm install random-key --save` -* [Source code](...) +* `npm install fetch --save` diff --git a/ep21-general-refactoring/README.md b/ep21-general-refactoring/README.md index 0f6225e..2712807 100644 --- a/ep21-general-refactoring/README.md +++ b/ep21-general-refactoring/README.md @@ -6,8 +6,3 @@ npm start ``` Visit http://localhost:8080 in browser. - -#### Notes - -* `npm install random-key --save` -* [Source code](...) diff --git a/ep22-building-todoactions/README.md b/ep22-building-todoactions/README.md index 0f6225e..2712807 100644 --- a/ep22-building-todoactions/README.md +++ b/ep22-building-todoactions/README.md @@ -6,8 +6,3 @@ npm start ``` Visit http://localhost:8080 in browser. - -#### Notes - -* `npm install random-key --save` -* [Source code](...) diff --git a/ep23-building-todostore/README.md b/ep23-building-todostore/README.md index 0f6225e..2712807 100644 --- a/ep23-building-todostore/README.md +++ b/ep23-building-todostore/README.md @@ -6,8 +6,3 @@ npm start ``` Visit http://localhost:8080 in browser. - -#### Notes - -* `npm install random-key --save` -* [Source code](...) diff --git a/ep24-delete-todo-using-flux/README.md b/ep24-delete-todo-using-flux/README.md index 0f6225e..2712807 100644 --- a/ep24-delete-todo-using-flux/README.md +++ b/ep24-delete-todo-using-flux/README.md @@ -6,8 +6,3 @@ npm start ``` Visit http://localhost:8080 in browser. - -#### Notes - -* `npm install random-key --save` -* [Source code](...) diff --git a/ep25-add-todo-using-flux/README.md b/ep25-add-todo-using-flux/README.md index 0f6225e..2712807 100644 --- a/ep25-add-todo-using-flux/README.md +++ b/ep25-add-todo-using-flux/README.md @@ -6,8 +6,3 @@ npm start ``` Visit http://localhost:8080 in browser. - -#### Notes - -* `npm install random-key --save` -* [Source code](...) diff --git a/ep26-enhance-todo-store/README.md b/ep26-enhance-todo-store/README.md index 0f6225e..2712807 100644 --- a/ep26-enhance-todo-store/README.md +++ b/ep26-enhance-todo-store/README.md @@ -6,8 +6,3 @@ npm start ``` Visit http://localhost:8080 in browser. - -#### Notes - -* `npm install random-key --save` -* [Source code](...) diff --git a/ep27-use-dispatcher/README.md b/ep27-use-dispatcher/README.md index 0f6225e..2712807 100644 --- a/ep27-use-dispatcher/README.md +++ b/ep27-use-dispatcher/README.md @@ -6,8 +6,3 @@ npm start ``` Visit http://localhost:8080 in browser. - -#### Notes - -* `npm install random-key --save` -* [Source code](...) diff --git a/ep28-more-dispatcher-usage/README.md b/ep28-more-dispatcher-usage/README.md index 0f6225e..2712807 100644 --- a/ep28-more-dispatcher-usage/README.md +++ b/ep28-more-dispatcher-usage/README.md @@ -6,8 +6,3 @@ npm start ``` Visit http://localhost:8080 in browser. - -#### Notes - -* `npm install random-key --save` -* [Source code](...) diff --git a/ep29-emit/README.md b/ep29-emit/README.md index 497a54e..cda0d27 100644 --- a/ep29-emit/README.md +++ b/ep29-emit/README.md @@ -12,4 +12,3 @@ Visit http://localhost:8080 in browser. * [Nodejs Events](https://nodejs.org/api/events.html) * [object-assign](https://www.npmjs.com/package/object-assign) * `npm install --save object-assign` -* [Source code](...) diff --git a/ep30-extract-form-into-componenet-from-app/README.md b/ep30-extract-form-into-componenet-from-app/README.md index 497a54e..2712807 100644 --- a/ep30-extract-form-into-componenet-from-app/README.md +++ b/ep30-extract-form-into-componenet-from-app/README.md @@ -6,10 +6,3 @@ npm start ``` Visit http://localhost:8080 in browser. - -#### Notes - -* [Nodejs Events](https://nodejs.org/api/events.html) -* [object-assign](https://www.npmjs.com/package/object-assign) -* `npm install --save object-assign` -* [Source code](...) diff --git a/ep31-get-all-todos/README.md b/ep31-get-all-todos/README.md index 497a54e..2712807 100644 --- a/ep31-get-all-todos/README.md +++ b/ep31-get-all-todos/README.md @@ -6,10 +6,3 @@ npm start ``` Visit http://localhost:8080 in browser. - -#### Notes - -* [Nodejs Events](https://nodejs.org/api/events.html) -* [object-assign](https://www.npmjs.com/package/object-assign) -* `npm install --save object-assign` -* [Source code](...) From 678c4669c15e982b63bdc7c4e51c20519675dced Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Fri, 2 Oct 2020 07:18:39 -0700 Subject: [PATCH 27/27] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 13b9ab4..1f07f5f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # learn-reactjs-in-steps +**These videos were created in 2015 and now they are out dated.** + This is code repository for videos created as part of [Learn ReactJS in steps](http://bigbinary.com/videos/learn-reactjs-in-steps). In this application we start with a "Hello World" applillcation and we add features to the application to make a fully functional "TODO application".