├── .eslintrc ├── .gitignore ├── README.md ├── ep01-setup ├── README.md ├── app │ ├── components │ │ └── App.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep02-submit-input-field ├── README.md ├── app │ ├── components │ │ └── App.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep03-handle-onchange ├── README.md ├── app │ ├── components │ │ └── App.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep04-add-to-collection ├── README.md ├── app │ ├── components │ │ └── App.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep05-displaylist-component ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep06-delete-todo ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep07-mark-as-done ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep08-displayitem-component ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep09-display-count ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep10-switch-to-todo-part1 ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep11-switch-to-todo-part2 ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep12-make-done-really-work ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep13-clear-completed ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep14-add-id-to-todo ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep15-use-proptypes ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep16-new-css ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep17-edit-todo-part1 ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep18-edit-todo-part2 ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ └── stylesheets │ │ └── main.css ├── package.json └── webpack.config.js ├── ep19-call-api-jquery ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ ├── stylesheets │ │ └── main.css │ └── utils │ │ ├── api.js │ │ └── constants.js ├── package.json └── webpack.config.js ├── ep20-using-fetch ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ ├── stylesheets │ │ └── main.css │ └── utils │ │ ├── api.js │ │ └── constants.js ├── package.json └── webpack.config.js ├── ep21-general-refactoring ├── README.md ├── app │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ ├── stylesheets │ │ └── main.css │ └── utils │ │ ├── api.js │ │ └── constants.js ├── package.json └── webpack.config.js ├── ep22-building-todoactions ├── README.md ├── app │ ├── actions │ │ └── TodoActions.js │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ ├── stylesheets │ │ └── main.css │ └── utils │ │ ├── api.js │ │ └── constants.js ├── package.json └── webpack.config.js ├── ep23-building-todostore ├── README.md ├── app │ ├── actions │ │ └── TodoActions.js │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ ├── stores │ │ └── TodoStore.js │ ├── stylesheets │ │ └── main.css │ └── utils │ │ ├── api.js │ │ └── constants.js ├── package.json └── webpack.config.js ├── ep24-delete-todo-using-flux ├── README.md ├── app │ ├── actions │ │ └── TodoActions.js │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ ├── stores │ │ └── TodoStore.js │ ├── stylesheets │ │ └── main.css │ └── utils │ │ ├── api.js │ │ └── constants.js ├── package.json └── webpack.config.js ├── ep25-add-todo-using-flux ├── README.md ├── app │ ├── actions │ │ └── TodoActions.js │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ ├── stores │ │ └── TodoStore.js │ ├── stylesheets │ │ └── main.css │ └── utils │ │ ├── api.js │ │ └── constants.js ├── package.json └── webpack.config.js ├── ep26-enhance-todo-store ├── README.md ├── app │ ├── actions │ │ └── TodoActions.js │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── main.jsx │ ├── stores │ │ └── TodoStore.js │ ├── stylesheets │ │ └── main.css │ └── utils │ │ ├── api.js │ │ └── constants.js ├── package.json └── webpack.config.js ├── ep27-use-dispatcher ├── README.md ├── app │ ├── actions │ │ └── TodoActions.js │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── dispatcher │ │ └── AppDispatcher.js │ ├── main.jsx │ ├── stores │ │ └── TodoStore.js │ ├── stylesheets │ │ └── main.css │ └── utils │ │ ├── api.js │ │ └── constants.js ├── package.json └── webpack.config.js ├── ep28-more-dispatcher-usage ├── README.md ├── app │ ├── actions │ │ └── TodoActions.js │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── dispatcher │ │ └── AppDispatcher.js │ ├── main.jsx │ ├── stores │ │ └── TodoStore.js │ ├── stylesheets │ │ └── main.css │ └── utils │ │ ├── api.js │ │ └── constants.js ├── package.json └── webpack.config.js ├── ep29-emit ├── README.md ├── app │ ├── actions │ │ └── TodoActions.js │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ └── DisplayList.jsx │ ├── dispatcher │ │ └── AppDispatcher.js │ ├── main.jsx │ ├── stores │ │ └── TodoStore.js │ ├── stylesheets │ │ └── main.css │ └── utils │ │ ├── api.js │ │ └── constants.js ├── package.json └── webpack.config.js ├── ep30-extract-form-into-componenet-from-app ├── README.md ├── app │ ├── actions │ │ └── TodoActions.js │ ├── components │ │ ├── App.jsx │ │ ├── DisplayItem.jsx │ │ ├── DisplayList.jsx │ │ └── TodoForm.jsx │ ├── dispatcher │ │ └── AppDispatcher.js │ ├── main.jsx │ ├── stores │ │ └── TodoStore.js │ ├── stylesheets │ │ └── main.css │ └── utils │ │ ├── api.js │ │ └── constants.js ├── package.json └── webpack.config.js └── ep31-get-all-todos ├── README.md ├── app ├── actions │ └── TodoActions.js ├── components │ ├── App.jsx │ ├── DisplayItem.jsx │ ├── DisplayList.jsx │ └── TodoForm.jsx ├── dispatcher │ └── AppDispatcher.js ├── main.jsx ├── stores │ └── TodoStore.js ├── stylesheets │ └── main.css └── utils │ ├── api.js │ └── constants.js ├── package.json └── webpack.config.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "browser": true, 5 | "es6": true, 6 | "node": true, 7 | "jquery": true // This will remove warnings related to $ being undefined. PR #97 8 | }, 9 | "plugins": [ 10 | "react" // This will remove warnings related to React not being defined. PR #98 11 | ], 12 | "ecmaFeatures": { 13 | "arrowFunctions": true, 14 | "blockBindings": true, 15 | "classes": true, 16 | "defaultParams": true, 17 | "destructuring": true, 18 | "forOf": true, 19 | "generators": true, 20 | "modules": true, 21 | "spread": true, 22 | "templateStrings": true, 23 | "jsx": true 24 | }, 25 | "rules": { 26 | "consistent-return": [0], 27 | "key-spacing": [0], 28 | "quotes": [0], 29 | "new-cap": [0], 30 | "no-multi-spaces": [0], 31 | "no-shadow": [0], 32 | 33 | // allow alert 34 | "no-alert": [0], 35 | 36 | // in ReactJS it is common to have components defined first and then used later. PR #88 37 | "no-unused-vars": [0], 38 | 39 | //allow function names starting with underscore statements like this._executeQuery is being flagged. PR #86 40 | "no-underscore-dangle": [0], 41 | 42 | //In ReactNavite code it is common to have styles.xxx at the top while styles is defined later. PR #85 43 | "no-use-before-define": [0, "nofunc"], 44 | 45 | // Allow dangling commas 46 | "comma-dangle": [0], 47 | 48 | // Force space after keywords like if, else and before code blocks. PR #91 49 | "space-after-keywords": [2], 50 | "space-before-blocks": [2], 51 | 52 | // Don't warn if camelcase variable names are used. PR #96 53 | "camelcase": [0], 54 | 55 | // Prefer === over ==. PR #100 56 | "eqeqeq": [2] 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | **/node_modules/* 3 | build/* 4 | .idea 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # learn-reactjs-in-steps 2 | 3 | **These videos were created in 2015 and now they are out dated.** 4 | 5 | This is code repository for videos created as part of [Learn ReactJS in steps](http://bigbinary.com/videos/learn-reactjs-in-steps). 6 | 7 | In this application we start with a "Hello World" applillcation and we add features to the application to make a fully functional "TODO application". 8 | -------------------------------------------------------------------------------- /ep01-setup/README.md: -------------------------------------------------------------------------------- 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 | * [webpack docs](http://webpack.github.io/docs/) 13 | * [Source code](...) 14 | -------------------------------------------------------------------------------- /ep01-setup/app/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class App extends React.Component { 4 | render () { 5 | return
Hello World
; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ep01-setup/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep01-setup/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep01-setup/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "react": "^0.13.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ep01-setup/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep02-submit-input-field/README.md: -------------------------------------------------------------------------------- 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 | * [Exploring ES6](http://exploringjs.com/es6/index.html) 13 | * [Source code](...) 14 | -------------------------------------------------------------------------------- /ep02-submit-input-field/app/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class App extends React.Component { 4 | 5 | handleSubmit (event) { 6 | event.preventDefault(); 7 | console.log("form was submitted"); 8 | 9 | } 10 | 11 | render () { 12 | return
13 |

TODO

14 |
15 | 16 | 17 |
18 |
; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ep02-submit-input-field/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep02-submit-input-field/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep02-submit-input-field/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "react": "^0.13.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ep02-submit-input-field/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep03-handle-onchange/README.md: -------------------------------------------------------------------------------- 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 | * [Source code](...) 13 | -------------------------------------------------------------------------------- /ep03-handle-onchange/app/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class App extends React.Component { 4 | 5 | constructor () { 6 | super(); 7 | this.state = { text: '' }; 8 | } 9 | 10 | handleSubmit (event) { 11 | event.preventDefault(); 12 | console.log("form was submitted"); 13 | var text = this.state.text; 14 | console.log("submitted form has value ", text); 15 | this.setState({ text: '' }); 16 | } 17 | 18 | handleChange (event) { 19 | var text = event.target.value; 20 | console.log(text); 21 | this.setState({ text: text }); 22 | } 23 | 24 | render () { 25 | return
26 |

TODO

27 |
28 | 29 | 30 |
31 |
; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ep03-handle-onchange/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep03-handle-onchange/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep03-handle-onchange/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "react": "^0.13.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ep03-handle-onchange/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep04-add-to-collection/README.md: -------------------------------------------------------------------------------- 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 | * [Source code](...) 13 | -------------------------------------------------------------------------------- /ep04-add-to-collection/app/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class App extends React.Component { 4 | 5 | constructor () { 6 | super(); 7 | this.state = { text: '', items: [] }; 8 | } 9 | 10 | handleSubmit (event) { 11 | event.preventDefault(); 12 | console.log("form was submitted"); 13 | 14 | var text = this.state.text; 15 | var newItems = this.state.items.concat(text); 16 | 17 | console.log("submitted form has value ", text); 18 | this.setState({ text: '', items: newItems }); 19 | } 20 | 21 | handleChange (event) { 22 | var text = event.target.value; 23 | console.log(text); 24 | this.setState({ text: text }); 25 | } 26 | 27 | render () { 28 | return
29 |

TODO

30 |
31 | 32 | 33 |
34 | 35 |

36 | { this.state.items.toString() } 37 |

38 |
; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ep04-add-to-collection/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep04-add-to-collection/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep04-add-to-collection/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "react": "^0.13.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ep04-add-to-collection/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep05-displaylist-component/README.md: -------------------------------------------------------------------------------- 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 | * [Source code](...) 13 | -------------------------------------------------------------------------------- /ep05-displaylist-component/app/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayList from './DisplayList'; 3 | 4 | export default class App extends React.Component { 5 | 6 | constructor () { 7 | super(); 8 | this.state = { text: '', items: [] }; 9 | } 10 | 11 | handleSubmit (event) { 12 | event.preventDefault(); 13 | console.log("form was submitted"); 14 | 15 | var text = this.state.text; 16 | var newItems = this.state.items.concat(text); 17 | 18 | console.log("submitted form has value ", text); 19 | this.setState({ text: '', items: newItems }); 20 | } 21 | 22 | handleChange (event) { 23 | var text = event.target.value; 24 | console.log(text); 25 | this.setState({ text: text }); 26 | } 27 | 28 | render () { 29 | return
30 |

TODO

31 |
32 | 33 | 34 |
35 | 36 | 37 |
; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ep05-displaylist-component/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class DisplayList extends React.Component { 4 | 5 | render () { 6 | return
    7 | { this.props.items.map((item, i) => { 8 | return
  • { item }
  • ; 9 | }) } 10 |
; 11 | } 12 | 13 | } 14 | 15 | -------------------------------------------------------------------------------- /ep05-displaylist-component/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep05-displaylist-component/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep05-displaylist-component/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "react": "^0.13.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ep05-displaylist-component/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep06-delete-todo/README.md: -------------------------------------------------------------------------------- 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 | * [Source code](...) 13 | -------------------------------------------------------------------------------- /ep06-delete-todo/app/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayList from './DisplayList'; 3 | 4 | export default class App extends React.Component { 5 | 6 | constructor () { 7 | super(); 8 | this.state = { text: '', items: [] }; 9 | } 10 | 11 | handleDelete (itemToBeDeleted) { 12 | console.log(itemToBeDeleted); 13 | var newItems = this.state.items.filter( (_item) => { 14 | return _item != itemToBeDeleted 15 | } ) 16 | 17 | this.setState({ items: newItems }); 18 | } 19 | 20 | handleSubmit (event) { 21 | event.preventDefault(); 22 | console.log("form was submitted"); 23 | 24 | var text = this.state.text; 25 | var newItems = this.state.items.concat(text); 26 | 27 | console.log("submitted form has value ", text); 28 | this.setState({ text: '', items: newItems }); 29 | } 30 | 31 | handleChange (event) { 32 | var text = event.target.value; 33 | console.log(text); 34 | this.setState({ text: text }); 35 | } 36 | 37 | render () { 38 | return
39 |

TODO

40 |
41 | 42 | 43 |
44 | 45 | 48 |
; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /ep06-delete-todo/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class DisplayList extends React.Component { 4 | 5 | render () { 6 | return
    7 | { this.props.items.map((item, i) => { 8 | return
  • 9 | { item } 10 | 11 | [x] 12 | 13 |
  • ; 14 | }) } 15 |
; 16 | } 17 | 18 | } 19 | 20 | -------------------------------------------------------------------------------- /ep06-delete-todo/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep06-delete-todo/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep06-delete-todo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "react": "^0.13.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ep06-delete-todo/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep07-mark-as-done/README.md: -------------------------------------------------------------------------------- 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 | * [Source code](...) 13 | -------------------------------------------------------------------------------- /ep07-mark-as-done/app/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayList from './DisplayList'; 3 | 4 | export default class App extends React.Component { 5 | 6 | constructor () { 7 | super(); 8 | this.state = { text: '', items: ['eggs', 'banana', 'bread'] }; 9 | } 10 | 11 | handleDelete (itemToBeDeleted) { 12 | console.log(itemToBeDeleted); 13 | var newItems = this.state.items.filter( (_item) => { 14 | return _item != itemToBeDeleted 15 | } ) 16 | 17 | this.setState({ items: newItems }); 18 | } 19 | 20 | handleSubmit (event) { 21 | event.preventDefault(); 22 | console.log("form was submitted"); 23 | 24 | var text = this.state.text; 25 | var newItems = this.state.items.concat(text); 26 | 27 | console.log("submitted form has value ", text); 28 | this.setState({ text: '', items: newItems }); 29 | } 30 | 31 | handleChange (event) { 32 | var text = event.target.value; 33 | console.log(text); 34 | this.setState({ text: text }); 35 | } 36 | 37 | render () { 38 | return
39 |

TODO

40 |
41 | 42 | 43 |
44 | 45 | 48 |
; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /ep07-mark-as-done/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class DisplayList extends React.Component { 4 | 5 | constructor () { 6 | super(); 7 | this.state = { done: false }; 8 | } 9 | 10 | handleOnChange (event) { 11 | var _done = !this.state.done; 12 | this.setState({ done: _done }); 13 | } 14 | 15 | render () { 16 | return
    17 | { this.props.items.map((item, i) => { 18 | return
  • 19 | 24 | 25 | { item } 26 | 27 | [x] 28 | 29 |
  • ; 30 | }) } 31 |
; 32 | } 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /ep07-mark-as-done/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep07-mark-as-done/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep07-mark-as-done/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "react": "^0.13.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ep07-mark-as-done/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep08-displayitem-component/README.md: -------------------------------------------------------------------------------- 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 | * [Source code](...) 13 | -------------------------------------------------------------------------------- /ep08-displayitem-component/app/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayList from './DisplayList'; 3 | 4 | export default class App extends React.Component { 5 | 6 | constructor () { 7 | super(); 8 | this.state = { text: '', items: ['eggs', 'banana', 'bread'] }; 9 | } 10 | 11 | handleDelete (itemToBeDeleted) { 12 | console.log(itemToBeDeleted); 13 | var newItems = this.state.items.filter( (_item) => { 14 | return _item != itemToBeDeleted 15 | } ) 16 | 17 | this.setState({ items: newItems }); 18 | } 19 | 20 | handleSubmit (event) { 21 | event.preventDefault(); 22 | console.log("form was submitted"); 23 | 24 | var text = this.state.text; 25 | var newItems = this.state.items.concat(text); 26 | 27 | console.log("submitted form has value ", text); 28 | this.setState({ text: '', items: newItems }); 29 | } 30 | 31 | handleChange (event) { 32 | var text = event.target.value; 33 | console.log(text); 34 | this.setState({ text: text }); 35 | } 36 | 37 | render () { 38 | return
39 |

TODO

40 |
41 | 42 | 43 |
44 | 45 | 48 |
; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /ep08-displayitem-component/app/components/DisplayItem.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class DisplayItem extends React.Component { 4 | 5 | constructor () { 6 | super(); 7 | this.state = { done: false }; 8 | } 9 | 10 | handleOnChange (event) { 11 | var _done = !this.state.done; 12 | this.setState({ done: _done }); 13 | } 14 | 15 | render () { 16 | var item = this.props.item; 17 | 18 | return
  • 19 | 24 | 25 | { item } 26 | 27 | [x] 28 | 29 |
  • ; 30 | } 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /ep08-displayitem-component/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.items.map((item, i) => { 9 | return ; 13 | }) } 14 |
    15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /ep08-displayitem-component/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep08-displayitem-component/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep08-displayitem-component/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "react": "^0.13.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ep08-displayitem-component/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep09-display-count/README.md: -------------------------------------------------------------------------------- 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 | * [Source code](...) 13 | -------------------------------------------------------------------------------- /ep09-display-count/app/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayList from './DisplayList'; 3 | 4 | export default class App extends React.Component { 5 | 6 | constructor () { 7 | super(); 8 | this.state = { text: '', items: ['eggs', 'banana', 'bread'] }; 9 | } 10 | 11 | handleDelete (itemToBeDeleted) { 12 | console.log(itemToBeDeleted); 13 | var newItems = this.state.items.filter( (_item) => { 14 | return _item != itemToBeDeleted 15 | } ) 16 | 17 | this.setState({ items: newItems }); 18 | } 19 | 20 | handleSubmit (event) { 21 | event.preventDefault(); 22 | console.log("form was submitted"); 23 | 24 | var text = this.state.text; 25 | var newItems = this.state.items.concat(text); 26 | 27 | console.log("submitted form has value ", text); 28 | this.setState({ text: '', items: newItems }); 29 | } 30 | 31 | handleChange (event) { 32 | var text = event.target.value; 33 | console.log(text); 34 | this.setState({ text: text }); 35 | } 36 | 37 | render () { 38 | return
    39 |

    TODO

    40 |
    41 | 42 | 43 |
    44 | 45 |

    46 | Number of total tasks: { this.state.items.length } 47 |

    48 |

    49 | Number of total tasks done: { this.state.items.filter((item) => { item.done }).length } 50 |

    51 | 52 | 55 |
    ; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ep09-display-count/app/components/DisplayItem.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class DisplayItem extends React.Component { 4 | 5 | constructor () { 6 | super(); 7 | this.state = { done: false }; 8 | } 9 | 10 | handleDone (event) { 11 | var _done = !this.state.done; 12 | this.setState({ done: _done }); 13 | } 14 | 15 | render () { 16 | var item = this.props.item; 17 | 18 | return
  • 19 | 24 | 25 | { item } 26 | 27 | [x] 28 | 29 |
  • ; 30 | } 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /ep09-display-count/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.items.map((item, i) => { 9 | return ; 13 | }) } 14 |
    15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /ep09-display-count/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep09-display-count/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep09-display-count/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "react": "^0.13.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ep09-display-count/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep10-switch-to-todo-part1/README.md: -------------------------------------------------------------------------------- 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 | * [Source code](...) 13 | -------------------------------------------------------------------------------- /ep10-switch-to-todo-part1/app/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayList from './DisplayList'; 3 | 4 | export default class App extends React.Component { 5 | 6 | constructor () { 7 | super(); 8 | this.state = { title: '', todos: ['eggs', 'banana', 'bread'] }; 9 | } 10 | 11 | handleDelete (titleToBeDeleted) { 12 | var newTodos = this.state.todos.filter( (_title) => { 13 | return _title != titleToBeDeleted 14 | } ) 15 | 16 | this.setState({ todos: newTodos}); 17 | } 18 | 19 | handleSubmit (event) { 20 | event.preventDefault(); 21 | 22 | var title = this.state.title; 23 | var newTodos = this.state.todos.concat(title); 24 | 25 | this.setState({ title: '', todos: newTodos }); 26 | } 27 | 28 | handleChange (event) { 29 | var title = event.target.value; 30 | this.setState({ title: title }); 31 | } 32 | 33 | render () { 34 | return
    35 |

    TODO

    36 |
    37 | 38 | 39 |
    40 | 41 |

    42 | Number of total tasks: { this.state.todos.length } 43 |

    44 |

    45 | Number of total tasks done: { this.state.todos.filter((title) => { title.done }).length } 46 |

    47 | 48 | 51 |
    ; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ep10-switch-to-todo-part1/app/components/DisplayItem.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class DisplayItem extends React.Component { 4 | 5 | constructor () { 6 | super(); 7 | this.state = { done: false }; 8 | } 9 | 10 | handleDone (event) { 11 | var _done = !this.state.done; 12 | this.setState({ done: _done }); 13 | } 14 | 15 | render () { 16 | var title = this.props.title; 17 | 18 | return
  • 19 | 24 | 25 | { title } 26 | 27 | [x] 28 | 29 |
  • ; 30 | } 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /ep10-switch-to-todo-part1/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((title, i) => { 9 | return ; 13 | }) } 14 |
    15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /ep10-switch-to-todo-part1/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep10-switch-to-todo-part1/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep10-switch-to-todo-part1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "react": "^0.13.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ep10-switch-to-todo-part1/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep11-switch-to-todo-part2/README.md: -------------------------------------------------------------------------------- 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 | * [Source code](...) 13 | -------------------------------------------------------------------------------- /ep11-switch-to-todo-part2/app/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayList from './DisplayList'; 3 | 4 | export default class App extends React.Component { 5 | 6 | constructor () { 7 | super(); 8 | this.state = { title: '', todos: [ 9 | { title: 'eggs', done: false }, 10 | { title: 'banana', done: false }, 11 | { title: 'bread', done: false } 12 | ] }; 13 | } 14 | 15 | handleDelete (titleToBeDeleted) { 16 | var newTodos = this.state.todos.filter( (todo) => { 17 | return todo.title != titleToBeDeleted 18 | } ) 19 | 20 | this.setState({ todos: newTodos}); 21 | } 22 | 23 | handleSubmit (event) { 24 | event.preventDefault(); 25 | 26 | var title = this.state.title; 27 | var newTodos = this.state.todos.concat({ title: title, done: false }); 28 | 29 | this.setState({ title: '', todos: newTodos }); 30 | } 31 | 32 | handleChange (event) { 33 | var title = event.target.value; 34 | this.setState({ title: title }); 35 | } 36 | 37 | render () { 38 | return
    39 |

    TODO

    40 |
    41 | 42 | 43 |
    44 | 45 |

    46 | Number of total tasks: { this.state.todos.length } 47 |

    48 |

    49 | Number of total tasks done: { this.state.todos.filter((todo) => { todo.done }).length } 50 |

    51 | 52 | 55 |
    ; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ep11-switch-to-todo-part2/app/components/DisplayItem.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class DisplayItem extends React.Component { 4 | 5 | constructor () { 6 | super(); 7 | this.state = { done: false }; 8 | } 9 | 10 | handleDone (event) { 11 | var _done = !this.state.done; 12 | this.setState({ done: _done }); 13 | } 14 | 15 | render () { 16 | var title = this.props.title; 17 | 18 | return
  • 19 | 24 | 25 | { title } 26 | 27 | [x] 28 | 29 |
  • ; 30 | } 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /ep11-switch-to-todo-part2/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return ; 13 | }) } 14 |
    15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /ep11-switch-to-todo-part2/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep11-switch-to-todo-part2/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep11-switch-to-todo-part2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "react": "^0.13.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ep11-switch-to-todo-part2/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep12-make-done-really-work/README.md: -------------------------------------------------------------------------------- 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 | * [Source code](...) 13 | -------------------------------------------------------------------------------- /ep12-make-done-really-work/app/components/DisplayItem.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class DisplayItem extends React.Component { 4 | 5 | render () { 6 | var todo = this.props.todo; 7 | var title = todo.title; 8 | 9 | return
  • 10 | 15 | 16 | { title } 17 | 18 | [x] 19 | 20 |
  • ; 21 | } 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /ep12-make-done-really-work/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return ; 14 | }) } 15 |
    16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /ep12-make-done-really-work/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep12-make-done-really-work/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep12-make-done-really-work/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "react": "^0.13.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ep12-make-done-really-work/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep13-clear-completed/README.md: -------------------------------------------------------------------------------- 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 | * [Source code](...) 13 | -------------------------------------------------------------------------------- /ep13-clear-completed/app/components/DisplayItem.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class DisplayItem extends React.Component { 4 | 5 | render () { 6 | var todo = this.props.todo; 7 | var title = todo.title; 8 | 9 | return
  • 10 | 15 | 16 | { title } 17 | 18 | [x] 19 | 20 |
  • ; 21 | } 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /ep13-clear-completed/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return ; 14 | }) } 15 |
    16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /ep13-clear-completed/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep13-clear-completed/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep13-clear-completed/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "react": "^0.13.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ep13-clear-completed/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep14-add-id-to-todo/README.md: -------------------------------------------------------------------------------- 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 | * `npm install random-key --save` 13 | * [Source code](...) 14 | -------------------------------------------------------------------------------- /ep14-add-id-to-todo/app/components/DisplayItem.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class DisplayItem extends React.Component { 4 | 5 | render () { 6 | var todo = this.props.todo; 7 | 8 | return
  • 9 | 14 | 15 | { todo.title } 16 | 17 | [x] 18 | 19 |
  • ; 20 | } 21 | 22 | } 23 | 24 | -------------------------------------------------------------------------------- /ep14-add-id-to-todo/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return ; 14 | }) } 15 |
    16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /ep14-add-id-to-todo/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep14-add-id-to-todo/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep14-add-id-to-todo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "random-key": "^0.3.2", 27 | "react": "^0.13.3" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ep14-add-id-to-todo/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep15-use-proptypes/README.md: -------------------------------------------------------------------------------- 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 | * `npm install random-key --save` 13 | * [Source code](...) 14 | -------------------------------------------------------------------------------- /ep15-use-proptypes/app/components/DisplayItem.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class DisplayItem extends React.Component { 4 | 5 | render () { 6 | var todo = this.props.todo; 7 | 8 | return
  • 9 | 14 | 15 | { todo.title } 16 | 17 | [x] 18 | 19 |
  • ; 20 | } 21 | 22 | } 23 | 24 | DisplayItem.propTypes = { 25 | todo: React.PropTypes.object.isRequired, 26 | handleDone: React.PropTypes.func.isRequired, 27 | handleDelete: React.PropTypes.func.isRequired 28 | } 29 | -------------------------------------------------------------------------------- /ep15-use-proptypes/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return ; 14 | }) } 15 |
    16 | } 17 | 18 | } 19 | 20 | DisplayList.propTypes = { 21 | todos: React.PropTypes.array.isRequired, 22 | handleDone: React.PropTypes.func.isRequired, 23 | handleDelete: React.PropTypes.func.isRequired 24 | } 25 | -------------------------------------------------------------------------------- /ep15-use-proptypes/app/main.jsx: -------------------------------------------------------------------------------- 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 app = document.createElement('div'); 10 | document.body.appendChild(app); 11 | 12 | React.render(, app); 13 | } 14 | -------------------------------------------------------------------------------- /ep15-use-proptypes/app/stylesheets/main.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font-size: 200%; 3 | } 4 | -------------------------------------------------------------------------------- /ep15-use-proptypes/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "random-key": "^0.3.2", 27 | "react": "^0.13.3" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ep15-use-proptypes/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep16-new-css/README.md: -------------------------------------------------------------------------------- 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 | * `npm install random-key --save` 13 | * [Source code](...) 14 | -------------------------------------------------------------------------------- /ep16-new-css/app/components/DisplayItem.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class DisplayItem extends React.Component { 4 | 5 | render () { 6 | var todo = this.props.todo; 7 | 8 | return
  • 9 | 14 | 15 | 18 | 19 | 22 | [x] 23 | 24 |
  • ; 25 | } 26 | 27 | } 28 | 29 | DisplayItem.propTypes = { 30 | todo: React.PropTypes.object.isRequired, 31 | handleDone: React.PropTypes.func.isRequired, 32 | handleDelete: React.PropTypes.func.isRequired 33 | } 34 | -------------------------------------------------------------------------------- /ep16-new-css/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 14 |
      15 | }) } 16 |
    17 | } 18 | 19 | } 20 | 21 | DisplayList.propTypes = { 22 | todos: React.PropTypes.array.isRequired, 23 | handleDone: React.PropTypes.func.isRequired, 24 | handleDelete: React.PropTypes.func.isRequired 25 | } 26 | -------------------------------------------------------------------------------- /ep16-new-css/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep16-new-css/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "random-key": "^0.3.2", 27 | "react": "^0.13.3" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ep16-new-css/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep17-edit-todo-part1/README.md: -------------------------------------------------------------------------------- 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 | * `npm install random-key --save` 13 | * [Source code](...) 14 | -------------------------------------------------------------------------------- /ep17-edit-todo-part1/app/components/DisplayItem.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class DisplayItem extends React.Component { 4 | 5 | constructor () { 6 | super(); 7 | this.state = { editing: false } 8 | } 9 | 10 | handleEditing (event) { 11 | this.setState({ editing: true }); 12 | } 13 | 14 | handleEditingDone (event) { 15 | if (event.keyCode === 13 ) { // submit 16 | this.setState({ editing: false }); 17 | } 18 | } 19 | 20 | render () { 21 | var todo = this.props.todo; 22 | 23 | var viewStyle = {}; 24 | var editStyle = {}; 25 | 26 | if (this.state.editing) { 27 | viewStyle.display = 'none'; 28 | } else { 29 | editStyle.display = 'none'; 30 | } 31 | 32 | return
  • 33 |
    34 | 39 | 40 | 43 | 44 | 47 | [x] 48 | 49 |
    50 | 51 | 55 |
  • 56 | } 57 | 58 | } 59 | 60 | DisplayItem.propTypes = { 61 | todo: React.PropTypes.object.isRequired, 62 | handleDone: React.PropTypes.func.isRequired, 63 | handleDelete: React.PropTypes.func.isRequired 64 | } 65 | -------------------------------------------------------------------------------- /ep17-edit-todo-part1/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 14 |
      15 | }) } 16 |
    17 | } 18 | 19 | } 20 | 21 | DisplayList.propTypes = { 22 | todos: React.PropTypes.array.isRequired, 23 | handleDone: React.PropTypes.func.isRequired, 24 | handleDelete: React.PropTypes.func.isRequired 25 | } 26 | -------------------------------------------------------------------------------- /ep17-edit-todo-part1/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep17-edit-todo-part1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "random-key": "^0.3.2", 27 | "react": "^0.13.3" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ep17-edit-todo-part1/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep18-edit-todo-part2/README.md: -------------------------------------------------------------------------------- 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 | * `npm install random-key --save` 13 | * [Source code](...) 14 | -------------------------------------------------------------------------------- /ep18-edit-todo-part2/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 14 |
      15 | }) } 16 |
    17 | } 18 | 19 | } 20 | 21 | DisplayList.propTypes = { 22 | todos: React.PropTypes.array.isRequired, 23 | handleDone: React.PropTypes.func.isRequired, 24 | handleDelete: React.PropTypes.func.isRequired 25 | } 26 | -------------------------------------------------------------------------------- /ep18-edit-todo-part2/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep18-edit-todo-part2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "random-key": "^0.3.2", 27 | "react": "^0.13.3" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ep18-edit-todo-part2/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep19-call-api-jquery/README.md: -------------------------------------------------------------------------------- 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 | * `npm install jquery --save` 13 | -------------------------------------------------------------------------------- /ep19-call-api-jquery/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 14 |
      15 | }) } 16 |
    17 | } 18 | 19 | } 20 | 21 | DisplayList.propTypes = { 22 | todos: React.PropTypes.array.isRequired, 23 | handleDone: React.PropTypes.func.isRequired, 24 | handleDelete: React.PropTypes.func.isRequired 25 | } 26 | -------------------------------------------------------------------------------- /ep19-call-api-jquery/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep19-call-api-jquery/app/utils/api.js: -------------------------------------------------------------------------------- 1 | var Constants = require("./constants"); 2 | var $ = require('jquery'); 3 | 4 | var api = { 5 | getTasks (processDataCallback) { 6 | var url = Constants.BASE_URL + 'todos'; 7 | this.makeAjaxCall(url, 'GET', {}, processDataCallback) 8 | }, 9 | 10 | addTask (todo, processDataCallback) { 11 | var url = Constants.BASE_URL + 'todos'; 12 | this.makeAjaxCall(url, 'POST', todo, processDataCallback) 13 | }, 14 | 15 | markTaskDone (todo, processDataCallback) { 16 | var url = Constants.BASE_URL + 'todos/' + todo.id; 17 | var params = { done: todo.done }; 18 | this.makeAjaxCall(url, 'PUT', params, processDataCallback) 19 | }, 20 | 21 | deleteTask (idToBeDeleted, processDataCallback) { 22 | var url = Constants.BASE_URL + 'todos/' + idToBeDeleted; 23 | this.makeAjaxCall(url, 'DELETE', {}, processDataCallback) 24 | }, 25 | 26 | makeAjaxCall (url, type, params, processDataCallback) { 27 | $.ajax({ 28 | type: type, 29 | url: url, 30 | data: { 31 | api_key: Constants.API_KEY, 32 | todo: params 33 | }, 34 | dataType: 'json', 35 | success: function(data) { 36 | console.log(data); 37 | processDataCallback(data); 38 | }, 39 | error: function() { 40 | console.log("An error has occurred"); 41 | } 42 | }); 43 | } 44 | }; 45 | 46 | module.exports = api; 47 | -------------------------------------------------------------------------------- /ep19-call-api-jquery/app/utils/constants.js: -------------------------------------------------------------------------------- 1 | var Constants = { 2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", 3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" 4 | }; 5 | module.exports = Constants; 6 | -------------------------------------------------------------------------------- /ep19-call-api-jquery/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "jquery": "1.11.3", 27 | "random-key": "^0.3.2", 28 | "react": "^0.13.3" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ep19-call-api-jquery/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep20-using-fetch/README.md: -------------------------------------------------------------------------------- 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 | * `npm install fetch --save` 13 | -------------------------------------------------------------------------------- /ep20-using-fetch/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 14 |
      15 | }) } 16 |
    17 | } 18 | 19 | } 20 | 21 | DisplayList.propTypes = { 22 | todos: React.PropTypes.array.isRequired, 23 | handleDone: React.PropTypes.func.isRequired, 24 | handleDelete: React.PropTypes.func.isRequired 25 | } 26 | -------------------------------------------------------------------------------- /ep20-using-fetch/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep20-using-fetch/app/utils/api.js: -------------------------------------------------------------------------------- 1 | require('whatwg-fetch'); 2 | var Constants = require("./constants"); 3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } 4 | 5 | var api = { 6 | generateUrlWithApiKey(endpoint) { 7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; 8 | }, 9 | 10 | getTasks () { 11 | var url = this.generateUrlWithApiKey('todos'); 12 | return fetch(url) 13 | .then((res) => res.json()); 14 | }, 15 | 16 | addTask (todo) { 17 | var url = this.generateUrlWithApiKey('todos'); 18 | var options = { 19 | method: 'POST', 20 | headers: HEADER, 21 | body: JSON.stringify({todo: todo}) 22 | }; 23 | return fetch(url, options) 24 | .then((res) => res.json()); 25 | }, 26 | 27 | markTaskDone (todo) { 28 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 29 | var options = { 30 | method: 'PUT', 31 | headers: HEADER, 32 | body: JSON.stringify({done: todo.done}) 33 | }; 34 | return fetch(url, options) 35 | .then((res) => res.json()); 36 | }, 37 | 38 | deleteTask (idToBeDeleted, processDataCallback) { 39 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); 40 | return fetch(url, { method: 'DELETE' }) 41 | .then((res) => res.json()); 42 | }, 43 | 44 | }; 45 | 46 | module.exports = api; 47 | -------------------------------------------------------------------------------- /ep20-using-fetch/app/utils/constants.js: -------------------------------------------------------------------------------- 1 | var Constants = { 2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", 3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" 4 | }; 5 | module.exports = Constants; 6 | -------------------------------------------------------------------------------- /ep20-using-fetch/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "jquery": "1.11.3", 27 | "random-key": "^0.3.2", 28 | "react": "^0.13.3", 29 | "whatwg-fetch": "^0.9.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ep20-using-fetch/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep21-general-refactoring/README.md: -------------------------------------------------------------------------------- 1 | #### Setting up the application 2 | 3 | ``` 4 | npm install 5 | npm start 6 | ``` 7 | 8 | Visit http://localhost:8080 in browser. 9 | -------------------------------------------------------------------------------- /ep21-general-refactoring/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 14 |
      15 | }) } 16 |
    17 | } 18 | 19 | } 20 | 21 | DisplayList.propTypes = { 22 | todos: React.PropTypes.array.isRequired, 23 | toggleDone: React.PropTypes.func.isRequired, 24 | handleDelete: React.PropTypes.func.isRequired 25 | } 26 | -------------------------------------------------------------------------------- /ep21-general-refactoring/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep21-general-refactoring/app/utils/api.js: -------------------------------------------------------------------------------- 1 | require('whatwg-fetch'); 2 | var Constants = require("./constants"); 3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } 4 | 5 | var api = { 6 | generateUrlWithApiKey(endpoint) { 7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; 8 | }, 9 | 10 | getTodos () { 11 | var url = this.generateUrlWithApiKey('todos'); 12 | return fetch(url) 13 | .then((res) => res.json()) 14 | .catch( (error) => console.log('Failed to get all tasks list.', error) ); 15 | }, 16 | 17 | addTodo (todo) { 18 | var url = this.generateUrlWithApiKey('todos'); 19 | var options = { 20 | method: 'POST', 21 | headers: HEADER, 22 | body: JSON.stringify({todo: todo}) 23 | }; 24 | return fetch(url, options) 25 | .then((res) => res.json()) 26 | .catch( (error) => console.log('Failed to add a TODO.', error) ); 27 | }, 28 | 29 | markTodoDone (todo) { 30 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 31 | var options = { 32 | method: 'PUT', 33 | headers: HEADER, 34 | body: JSON.stringify({done: true}) 35 | }; 36 | return fetch(url, options) 37 | .then((res) => res.json()) 38 | .catch( (error) => console.log('Failed to mark task as done. ', error) ); 39 | }, 40 | 41 | markTodoUnDone (todo) { 42 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 43 | var options = { 44 | method: 'PUT', 45 | headers: HEADER, 46 | body: JSON.stringify({done: false}) 47 | }; 48 | return fetch(url, options) 49 | .then((res) => res.json()) 50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) ); 51 | }, 52 | 53 | deleteTodo (idToBeDeleted, processDataCallback) { 54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); 55 | return fetch(url, { method: 'DELETE' }) 56 | .then((res) => res.json()) 57 | .catch( (error) => console.log('Failed to delete TODO.', error) ); 58 | }, 59 | 60 | }; 61 | 62 | module.exports = api; 63 | -------------------------------------------------------------------------------- /ep21-general-refactoring/app/utils/constants.js: -------------------------------------------------------------------------------- 1 | var Constants = { 2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", 3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" 4 | }; 5 | module.exports = Constants; 6 | -------------------------------------------------------------------------------- /ep21-general-refactoring/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "jquery": "1.11.3", 27 | "random-key": "^0.3.2", 28 | "react": "^0.13.3", 29 | "whatwg-fetch": "^0.9.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ep21-general-refactoring/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep22-building-todoactions/README.md: -------------------------------------------------------------------------------- 1 | #### Setting up the application 2 | 3 | ``` 4 | npm install 5 | npm start 6 | ``` 7 | 8 | Visit http://localhost:8080 in browser. 9 | -------------------------------------------------------------------------------- /ep22-building-todoactions/app/actions/TodoActions.js: -------------------------------------------------------------------------------- 1 | var api = require("../utils/api"); 2 | 3 | var TodoActions = { 4 | 5 | markTodoDone: (todo) => { 6 | console.log("Marking TODO as done"); 7 | api.markTodoDone(todo) 8 | .then( () => { 9 | console.log("marked TODO as done successfully"); 10 | TodoActions.getAllTodos(); 11 | }) 12 | }, 13 | 14 | markTodoUnDone: (todo) => { 15 | console.log("Marking TODO as undone"); 16 | api.markTodoUnDone(todo) 17 | .then( () => { 18 | console.log("marked TODO as undone successfully"); 19 | TodoActions.getAllTodos(); 20 | }) 21 | }, 22 | 23 | getAllTodos: () => { 24 | api.getTodos() 25 | .then( (responseData) => { 26 | var todos = responseData.todos; 27 | console.log("new todos", todos); 28 | }) 29 | } 30 | 31 | } 32 | 33 | module.exports = TodoActions; 34 | -------------------------------------------------------------------------------- /ep22-building-todoactions/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 14 |
      15 | }) } 16 |
    17 | } 18 | 19 | } 20 | 21 | DisplayList.propTypes = { 22 | todos: React.PropTypes.array.isRequired, 23 | toggleDone: React.PropTypes.func.isRequired, 24 | handleDelete: React.PropTypes.func.isRequired 25 | } 26 | -------------------------------------------------------------------------------- /ep22-building-todoactions/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep22-building-todoactions/app/utils/api.js: -------------------------------------------------------------------------------- 1 | require('whatwg-fetch'); 2 | var Constants = require("./constants"); 3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } 4 | 5 | var api = { 6 | generateUrlWithApiKey(endpoint) { 7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; 8 | }, 9 | 10 | getTodos () { 11 | var url = this.generateUrlWithApiKey('todos'); 12 | return fetch(url) 13 | .then((res) => res.json()) 14 | .catch( (error) => console.log('Failed to get all tasks list.', error) ); 15 | }, 16 | 17 | addTodo (todo) { 18 | var url = this.generateUrlWithApiKey('todos'); 19 | var options = { 20 | method: 'POST', 21 | headers: HEADER, 22 | body: JSON.stringify({todo: todo}) 23 | }; 24 | return fetch(url, options) 25 | .then((res) => res.json()) 26 | .catch( (error) => console.log('Failed to add a TODO.', error) ); 27 | }, 28 | 29 | markTodoDone (todo) { 30 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 31 | var options = { 32 | method: 'PUT', 33 | headers: HEADER, 34 | body: JSON.stringify({done: true}) 35 | }; 36 | return fetch(url, options) 37 | .then((res) => res.json()) 38 | .catch( (error) => console.log('Failed to mark task as done. ', error) ); 39 | }, 40 | 41 | markTodoUnDone (todo) { 42 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 43 | var options = { 44 | method: 'PUT', 45 | headers: HEADER, 46 | body: JSON.stringify({done: false}) 47 | }; 48 | return fetch(url, options) 49 | .then((res) => res.json()) 50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) ); 51 | }, 52 | 53 | deleteTodo (idToBeDeleted, processDataCallback) { 54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); 55 | return fetch(url, { method: 'DELETE' }) 56 | .then((res) => res.json()) 57 | .catch( (error) => console.log('Failed to delete TODO.', error) ); 58 | }, 59 | 60 | }; 61 | 62 | module.exports = api; 63 | -------------------------------------------------------------------------------- /ep22-building-todoactions/app/utils/constants.js: -------------------------------------------------------------------------------- 1 | var Constants = { 2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", 3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" 4 | }; 5 | module.exports = Constants; 6 | -------------------------------------------------------------------------------- /ep22-building-todoactions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "jquery": "1.11.3", 27 | "random-key": "^0.3.2", 28 | "react": "^0.13.3", 29 | "whatwg-fetch": "^0.9.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ep22-building-todoactions/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep23-building-todostore/README.md: -------------------------------------------------------------------------------- 1 | #### Setting up the application 2 | 3 | ``` 4 | npm install 5 | npm start 6 | ``` 7 | 8 | Visit http://localhost:8080 in browser. 9 | -------------------------------------------------------------------------------- /ep23-building-todostore/app/actions/TodoActions.js: -------------------------------------------------------------------------------- 1 | var api = require("../utils/api"); 2 | var TodoStore = require("../stores/TodoStore"); 3 | 4 | var TodoActions = { 5 | 6 | markTodoDone: (todo) => { 7 | console.log("Marking TODO as done"); 8 | api.markTodoDone(todo) 9 | .then( () => { 10 | console.log("marked TODO as done successfully"); 11 | TodoActions.getAllTodos(); 12 | }) 13 | }, 14 | 15 | markTodoUnDone: (todo) => { 16 | console.log("Marking TODO as undone"); 17 | api.markTodoUnDone(todo) 18 | .then( () => { 19 | console.log("marked TODO as undone successfully"); 20 | TodoActions.getAllTodos(); 21 | }) 22 | }, 23 | 24 | getAllTodos: () => { 25 | api.getTodos() 26 | .then( (responseData) => { 27 | var todos = responseData.todos; 28 | console.log("new todos", todos); 29 | TodoStore.setTodos(todos); 30 | }) 31 | } 32 | 33 | } 34 | 35 | module.exports = TodoActions; 36 | -------------------------------------------------------------------------------- /ep23-building-todostore/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 14 |
      15 | }) } 16 |
    17 | } 18 | 19 | } 20 | 21 | DisplayList.propTypes = { 22 | todos: React.PropTypes.array.isRequired, 23 | toggleDone: React.PropTypes.func.isRequired, 24 | handleDelete: React.PropTypes.func.isRequired 25 | } 26 | -------------------------------------------------------------------------------- /ep23-building-todostore/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep23-building-todostore/app/stores/TodoStore.js: -------------------------------------------------------------------------------- 1 | var _todos = {}; 2 | var _callback; 3 | 4 | var TodoStore = { 5 | 6 | setTodos: (todos) => { 7 | _todos = todos; 8 | console.log("TodoStore", TodoStore.getTodos()); 9 | _callback(todos); 10 | }, 11 | 12 | getTodos: () => { 13 | return _todos; 14 | }, 15 | 16 | addChangeListener: function (callback) { 17 | console.log("registering callback for changelistener"); 18 | _callback = callback; 19 | } 20 | } 21 | 22 | module.exports = TodoStore; 23 | -------------------------------------------------------------------------------- /ep23-building-todostore/app/utils/api.js: -------------------------------------------------------------------------------- 1 | require('whatwg-fetch'); 2 | var Constants = require("./constants"); 3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } 4 | 5 | var api = { 6 | generateUrlWithApiKey(endpoint) { 7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; 8 | }, 9 | 10 | getTodos () { 11 | var url = this.generateUrlWithApiKey('todos'); 12 | return fetch(url) 13 | .then((res) => res.json()) 14 | .catch( (error) => console.log('Failed to get all tasks list.', error) ); 15 | }, 16 | 17 | addTodo (todo) { 18 | var url = this.generateUrlWithApiKey('todos'); 19 | var options = { 20 | method: 'POST', 21 | headers: HEADER, 22 | body: JSON.stringify({todo: todo}) 23 | }; 24 | return fetch(url, options) 25 | .then((res) => res.json()) 26 | .catch( (error) => console.log('Failed to add a TODO.', error) ); 27 | }, 28 | 29 | markTodoDone (todo) { 30 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 31 | var options = { 32 | method: 'PUT', 33 | headers: HEADER, 34 | body: JSON.stringify({done: true}) 35 | }; 36 | return fetch(url, options) 37 | .then((res) => res.json()) 38 | .catch( (error) => console.log('Failed to mark task as done. ', error) ); 39 | }, 40 | 41 | markTodoUnDone (todo) { 42 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 43 | var options = { 44 | method: 'PUT', 45 | headers: HEADER, 46 | body: JSON.stringify({done: false}) 47 | }; 48 | return fetch(url, options) 49 | .then((res) => res.json()) 50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) ); 51 | }, 52 | 53 | deleteTodo (idToBeDeleted, processDataCallback) { 54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); 55 | return fetch(url, { method: 'DELETE' }) 56 | .then((res) => res.json()) 57 | .catch( (error) => console.log('Failed to delete TODO.', error) ); 58 | }, 59 | 60 | }; 61 | 62 | module.exports = api; 63 | -------------------------------------------------------------------------------- /ep23-building-todostore/app/utils/constants.js: -------------------------------------------------------------------------------- 1 | var Constants = { 2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", 3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" 4 | }; 5 | module.exports = Constants; 6 | -------------------------------------------------------------------------------- /ep23-building-todostore/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "jquery": "1.11.3", 27 | "random-key": "^0.3.2", 28 | "react": "^0.13.3", 29 | "whatwg-fetch": "^0.9.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ep23-building-todostore/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep24-delete-todo-using-flux/README.md: -------------------------------------------------------------------------------- 1 | #### Setting up the application 2 | 3 | ``` 4 | npm install 5 | npm start 6 | ``` 7 | 8 | Visit http://localhost:8080 in browser. 9 | -------------------------------------------------------------------------------- /ep24-delete-todo-using-flux/app/actions/TodoActions.js: -------------------------------------------------------------------------------- 1 | var api = require("../utils/api"); 2 | var TodoStore = require("../stores/TodoStore"); 3 | 4 | var TodoActions = { 5 | 6 | deleteTodo: (todo) => { 7 | console.log("Deleting TODO"); 8 | api.deleteTodo(todo.id) 9 | .then( () => { 10 | console.log("Deleted TODO successfully"); 11 | TodoActions.getAllTodos(); 12 | }) 13 | }, 14 | 15 | markTodoDone: (todo) => { 16 | console.log("Marking TODO as done"); 17 | api.markTodoDone(todo) 18 | .then( () => { 19 | console.log("marked TODO as done successfully"); 20 | TodoActions.getAllTodos(); 21 | }) 22 | }, 23 | 24 | markTodoUnDone: (todo) => { 25 | console.log("Marking TODO as undone"); 26 | api.markTodoUnDone(todo) 27 | .then( () => { 28 | console.log("marked TODO as undone successfully"); 29 | TodoActions.getAllTodos(); 30 | }) 31 | }, 32 | 33 | getAllTodos: () => { 34 | api.getTodos() 35 | .then( (responseData) => { 36 | var todos = responseData.todos; 37 | console.log("new todos", todos); 38 | TodoStore.setTodos(todos); 39 | }) 40 | } 41 | 42 | } 43 | 44 | module.exports = TodoActions; 45 | -------------------------------------------------------------------------------- /ep24-delete-todo-using-flux/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 12 |
      13 | }) } 14 |
    15 | } 16 | 17 | } 18 | 19 | DisplayList.propTypes = { 20 | todos: React.PropTypes.array.isRequired 21 | } 22 | -------------------------------------------------------------------------------- /ep24-delete-todo-using-flux/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep24-delete-todo-using-flux/app/stores/TodoStore.js: -------------------------------------------------------------------------------- 1 | var _todos = {}; 2 | var _callback; 3 | 4 | var TodoStore = { 5 | 6 | setTodos: (todos) => { 7 | _todos = todos; 8 | console.log("TodoStore", TodoStore.getTodos()); 9 | _callback(todos); 10 | }, 11 | 12 | getTodos: () => { 13 | return _todos; 14 | }, 15 | 16 | addChangeListener: function (callback) { 17 | console.log("registering callback for changelistener"); 18 | _callback = callback; 19 | } 20 | } 21 | 22 | module.exports = TodoStore; 23 | -------------------------------------------------------------------------------- /ep24-delete-todo-using-flux/app/utils/api.js: -------------------------------------------------------------------------------- 1 | require('whatwg-fetch'); 2 | var Constants = require("./constants"); 3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } 4 | 5 | var api = { 6 | generateUrlWithApiKey(endpoint) { 7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; 8 | }, 9 | 10 | getTodos () { 11 | var url = this.generateUrlWithApiKey('todos'); 12 | return fetch(url) 13 | .then((res) => res.json()) 14 | .catch( (error) => console.log('Failed to get all tasks list.', error) ); 15 | }, 16 | 17 | addTodo (todo) { 18 | var url = this.generateUrlWithApiKey('todos'); 19 | var options = { 20 | method: 'POST', 21 | headers: HEADER, 22 | body: JSON.stringify({todo: todo}) 23 | }; 24 | return fetch(url, options) 25 | .then((res) => res.json()) 26 | .catch( (error) => console.log('Failed to add a TODO.', error) ); 27 | }, 28 | 29 | markTodoDone (todo) { 30 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 31 | var options = { 32 | method: 'PUT', 33 | headers: HEADER, 34 | body: JSON.stringify({done: true}) 35 | }; 36 | return fetch(url, options) 37 | .then((res) => res.json()) 38 | .catch( (error) => console.log('Failed to mark task as done. ', error) ); 39 | }, 40 | 41 | markTodoUnDone (todo) { 42 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 43 | var options = { 44 | method: 'PUT', 45 | headers: HEADER, 46 | body: JSON.stringify({done: false}) 47 | }; 48 | return fetch(url, options) 49 | .then((res) => res.json()) 50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) ); 51 | }, 52 | 53 | deleteTodo (idToBeDeleted, processDataCallback) { 54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); 55 | return fetch(url, { method: 'DELETE' }) 56 | .then((res) => res.json()) 57 | .catch( (error) => console.log('Failed to delete TODO.', error) ); 58 | }, 59 | 60 | }; 61 | 62 | module.exports = api; 63 | -------------------------------------------------------------------------------- /ep24-delete-todo-using-flux/app/utils/constants.js: -------------------------------------------------------------------------------- 1 | var Constants = { 2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", 3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" 4 | }; 5 | module.exports = Constants; 6 | -------------------------------------------------------------------------------- /ep24-delete-todo-using-flux/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "jquery": "1.11.3", 27 | "random-key": "^0.3.2", 28 | "react": "^0.13.3", 29 | "whatwg-fetch": "^0.9.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ep24-delete-todo-using-flux/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep25-add-todo-using-flux/README.md: -------------------------------------------------------------------------------- 1 | #### Setting up the application 2 | 3 | ``` 4 | npm install 5 | npm start 6 | ``` 7 | 8 | Visit http://localhost:8080 in browser. 9 | -------------------------------------------------------------------------------- /ep25-add-todo-using-flux/app/actions/TodoActions.js: -------------------------------------------------------------------------------- 1 | var api = require("../utils/api"); 2 | var TodoStore = require("../stores/TodoStore"); 3 | 4 | var TodoActions = { 5 | 6 | addTodo: (todo) => { 7 | console.log("adding TODO"); 8 | api.addTodo(todo) 9 | .then( () => { 10 | console.log("Added TODO successfully"); 11 | TodoActions.getAllTodos(); 12 | }) 13 | }, 14 | 15 | deleteTodo: (todo) => { 16 | console.log("Deleting TODO"); 17 | api.deleteTodo(todo.id) 18 | .then( () => { 19 | console.log("Deleted TODO successfully"); 20 | TodoActions.getAllTodos(); 21 | }) 22 | }, 23 | 24 | markTodoDone: (todo) => { 25 | console.log("Marking TODO as done"); 26 | api.markTodoDone(todo) 27 | .then( () => { 28 | console.log("marked TODO as done successfully"); 29 | TodoActions.getAllTodos(); 30 | }) 31 | }, 32 | 33 | markTodoUnDone: (todo) => { 34 | console.log("Marking TODO as undone"); 35 | api.markTodoUnDone(todo) 36 | .then( () => { 37 | console.log("marked TODO as undone successfully"); 38 | TodoActions.getAllTodos(); 39 | }) 40 | }, 41 | 42 | getAllTodos: () => { 43 | api.getTodos() 44 | .then( (responseData) => { 45 | var todos = responseData.todos; 46 | console.log("new todos", todos); 47 | TodoStore.setTodos(todos); 48 | }) 49 | } 50 | 51 | } 52 | 53 | module.exports = TodoActions; 54 | -------------------------------------------------------------------------------- /ep25-add-todo-using-flux/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 12 |
      13 | }) } 14 |
    15 | } 16 | 17 | } 18 | 19 | DisplayList.propTypes = { 20 | todos: React.PropTypes.array.isRequired 21 | } 22 | -------------------------------------------------------------------------------- /ep25-add-todo-using-flux/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep25-add-todo-using-flux/app/stores/TodoStore.js: -------------------------------------------------------------------------------- 1 | var _todos = {}; 2 | var _callback; 3 | 4 | var TodoStore = { 5 | 6 | setTodos: (todos) => { 7 | _todos = todos; 8 | console.log("TodoStore", TodoStore.getTodos()); 9 | _callback(todos); 10 | }, 11 | 12 | getTodos: () => { 13 | return _todos; 14 | }, 15 | 16 | addChangeListener: function (callback) { 17 | console.log("registering callback for changelistener"); 18 | _callback = callback; 19 | } 20 | } 21 | 22 | module.exports = TodoStore; 23 | -------------------------------------------------------------------------------- /ep25-add-todo-using-flux/app/utils/api.js: -------------------------------------------------------------------------------- 1 | require('whatwg-fetch'); 2 | var Constants = require("./constants"); 3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } 4 | 5 | var api = { 6 | generateUrlWithApiKey(endpoint) { 7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; 8 | }, 9 | 10 | getTodos () { 11 | var url = this.generateUrlWithApiKey('todos'); 12 | return fetch(url) 13 | .then((res) => res.json()) 14 | .catch( (error) => console.log('Failed to get all tasks list.', error) ); 15 | }, 16 | 17 | addTodo (todo) { 18 | var url = this.generateUrlWithApiKey('todos'); 19 | var options = { 20 | method: 'POST', 21 | headers: HEADER, 22 | body: JSON.stringify({todo: todo}) 23 | }; 24 | return fetch(url, options) 25 | .then((res) => res.json()) 26 | .catch( (error) => console.log('Failed to add a TODO.', error) ); 27 | }, 28 | 29 | markTodoDone (todo) { 30 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 31 | var options = { 32 | method: 'PUT', 33 | headers: HEADER, 34 | body: JSON.stringify({done: true}) 35 | }; 36 | return fetch(url, options) 37 | .then((res) => res.json()) 38 | .catch( (error) => console.log('Failed to mark task as done. ', error) ); 39 | }, 40 | 41 | markTodoUnDone (todo) { 42 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 43 | var options = { 44 | method: 'PUT', 45 | headers: HEADER, 46 | body: JSON.stringify({done: false}) 47 | }; 48 | return fetch(url, options) 49 | .then((res) => res.json()) 50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) ); 51 | }, 52 | 53 | deleteTodo (idToBeDeleted, processDataCallback) { 54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); 55 | return fetch(url, { method: 'DELETE' }) 56 | .then((res) => res.json()) 57 | .catch( (error) => console.log('Failed to delete TODO.', error) ); 58 | }, 59 | 60 | }; 61 | 62 | module.exports = api; 63 | -------------------------------------------------------------------------------- /ep25-add-todo-using-flux/app/utils/constants.js: -------------------------------------------------------------------------------- 1 | var Constants = { 2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", 3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" 4 | }; 5 | module.exports = Constants; 6 | -------------------------------------------------------------------------------- /ep25-add-todo-using-flux/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "jquery": "1.11.3", 27 | "random-key": "^0.3.2", 28 | "react": "^0.13.3", 29 | "whatwg-fetch": "^0.9.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ep25-add-todo-using-flux/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep26-enhance-todo-store/README.md: -------------------------------------------------------------------------------- 1 | #### Setting up the application 2 | 3 | ``` 4 | npm install 5 | npm start 6 | ``` 7 | 8 | Visit http://localhost:8080 in browser. 9 | -------------------------------------------------------------------------------- /ep26-enhance-todo-store/app/actions/TodoActions.js: -------------------------------------------------------------------------------- 1 | var api = require("../utils/api"); 2 | var TodoStore = require("../stores/TodoStore"); 3 | 4 | var TodoActions = { 5 | 6 | addTodo: (todo) => { 7 | console.log("adding TODO"); 8 | api.addTodo(todo) 9 | .then( () => { 10 | console.log("Added TODO successfully"); 11 | TodoActions.getAllTodosAndUpdateStore(); 12 | }) 13 | }, 14 | 15 | deleteTodo: (todo) => { 16 | console.log("Deleting TODO"); 17 | api.deleteTodo(todo.id) 18 | .then( () => { 19 | console.log("Deleted TODO successfully"); 20 | TodoStore.deleteTodo(todo); 21 | }) 22 | }, 23 | 24 | markTodoDone: (todo) => { 25 | console.log("Marking TODO as done"); 26 | api.markTodoDone(todo) 27 | .then( () => { 28 | console.log("marked TODO as done successfully"); 29 | TodoStore.markTodoDone(todo); 30 | }) 31 | }, 32 | 33 | markTodoUnDone: (todo) => { 34 | console.log("Marking TODO as undone"); 35 | api.markTodoUnDone(todo) 36 | .then( () => { 37 | console.log("marked TODO as undone successfully"); 38 | TodoStore.markTodoUnDone(todo); 39 | }) 40 | }, 41 | 42 | getAllTodosAndUpdateStore: () => { 43 | console.log("Performing getAllTodos"); 44 | api.getTodos() 45 | .then( (responseData) => { 46 | var todos = responseData.todos; 47 | console.log("new todos", todos); 48 | TodoStore.setTodos(todos); 49 | }) 50 | } 51 | 52 | } 53 | 54 | module.exports = TodoActions; 55 | -------------------------------------------------------------------------------- /ep26-enhance-todo-store/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 12 |
      13 | }) } 14 |
    15 | } 16 | 17 | } 18 | 19 | DisplayList.propTypes = { 20 | todos: React.PropTypes.array.isRequired 21 | } 22 | -------------------------------------------------------------------------------- /ep26-enhance-todo-store/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep26-enhance-todo-store/app/stores/TodoStore.js: -------------------------------------------------------------------------------- 1 | var _todos = {}; 2 | var _callback; 3 | 4 | var TodoStore = { 5 | 6 | deleteTodo: (todo) => { 7 | var newTodos = _todos.filter( (t) => { 8 | return t.id != todo.id 9 | } ) 10 | _todos = newTodos; 11 | _callback(_todos); 12 | }, 13 | 14 | markTodoDone: (todo) => { 15 | var _todo = _todos.filter((t) => { 16 | return t.id === todo.id; 17 | })[0]; 18 | 19 | _todo.done = true; 20 | _callback(_todos); 21 | }, 22 | 23 | markTodoUnDone: (todo) => { 24 | var _todo = _todos.filter((t) => { 25 | return t.id === todo.id; 26 | })[0]; 27 | 28 | _todo.done = false; 29 | _callback(_todos); 30 | }, 31 | 32 | setTodos: (todos) => { 33 | _todos = todos; 34 | console.log("TodoStore", TodoStore.getTodos()); 35 | _callback(todos); 36 | }, 37 | 38 | getTodos: () => { 39 | return _todos; 40 | }, 41 | 42 | addChangeListener: function (callback) { 43 | console.log("registering callback for changelistener"); 44 | _callback = callback; 45 | } 46 | } 47 | 48 | module.exports = TodoStore; 49 | -------------------------------------------------------------------------------- /ep26-enhance-todo-store/app/utils/api.js: -------------------------------------------------------------------------------- 1 | require('whatwg-fetch'); 2 | var Constants = require("./constants"); 3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } 4 | 5 | var api = { 6 | generateUrlWithApiKey(endpoint) { 7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; 8 | }, 9 | 10 | getTodos () { 11 | var url = this.generateUrlWithApiKey('todos'); 12 | return fetch(url) 13 | .then((res) => res.json()) 14 | .catch( (error) => console.log('Failed to get all tasks list.', error) ); 15 | }, 16 | 17 | addTodo (todo) { 18 | var url = this.generateUrlWithApiKey('todos'); 19 | var options = { 20 | method: 'POST', 21 | headers: HEADER, 22 | body: JSON.stringify({todo: todo}) 23 | }; 24 | return fetch(url, options) 25 | .then((res) => res.json()) 26 | .catch( (error) => console.log('Failed to add a TODO.', error) ); 27 | }, 28 | 29 | markTodoDone (todo) { 30 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 31 | var options = { 32 | method: 'PUT', 33 | headers: HEADER, 34 | body: JSON.stringify({done: true}) 35 | }; 36 | return fetch(url, options) 37 | .then((res) => res.json()) 38 | .catch( (error) => console.log('Failed to mark task as done. ', error) ); 39 | }, 40 | 41 | markTodoUnDone (todo) { 42 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 43 | var options = { 44 | method: 'PUT', 45 | headers: HEADER, 46 | body: JSON.stringify({done: false}) 47 | }; 48 | return fetch(url, options) 49 | .then((res) => res.json()) 50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) ); 51 | }, 52 | 53 | deleteTodo (idToBeDeleted, processDataCallback) { 54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); 55 | return fetch(url, { method: 'DELETE' }) 56 | .then((res) => res.json()) 57 | .catch( (error) => console.log('Failed to delete TODO.', error) ); 58 | }, 59 | 60 | }; 61 | 62 | module.exports = api; 63 | -------------------------------------------------------------------------------- /ep26-enhance-todo-store/app/utils/constants.js: -------------------------------------------------------------------------------- 1 | var Constants = { 2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", 3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" 4 | }; 5 | module.exports = Constants; 6 | -------------------------------------------------------------------------------- /ep26-enhance-todo-store/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "jquery": "1.11.3", 27 | "random-key": "^0.3.2", 28 | "react": "^0.13.3", 29 | "whatwg-fetch": "^0.9.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ep26-enhance-todo-store/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep27-use-dispatcher/README.md: -------------------------------------------------------------------------------- 1 | #### Setting up the application 2 | 3 | ``` 4 | npm install 5 | npm start 6 | ``` 7 | 8 | Visit http://localhost:8080 in browser. 9 | -------------------------------------------------------------------------------- /ep27-use-dispatcher/app/actions/TodoActions.js: -------------------------------------------------------------------------------- 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 | console.log("Added TODO successfully"); 12 | TodoActions.getAllTodosAndUpdateStore(); 13 | }) 14 | }, 15 | 16 | deleteTodo: (todo) => { 17 | console.log("Deleting TODO"); 18 | api.deleteTodo(todo.id) 19 | .then( () => { 20 | console.log("Deleted TODO successfully"); 21 | TodoStore.deleteTodo(todo); 22 | }) 23 | }, 24 | 25 | markTodoDone: (todo) => { 26 | console.log("Marking TODO as done"); 27 | api.markTodoDone(todo) 28 | .then( () => { 29 | console.log("marked TODO as done successfully"); 30 | //TodoStore.markTodoDone(todo); 31 | AppDispatcher.dispatch({ 32 | actionType: 'TODO_DONE', 33 | todo: todo 34 | }); 35 | 36 | }) 37 | }, 38 | 39 | markTodoUnDone: (todo) => { 40 | console.log("Marking TODO as undone"); 41 | api.markTodoUnDone(todo) 42 | .then( () => { 43 | console.log("marked TODO as undone successfully"); 44 | TodoStore.markTodoUnDone(todo); 45 | }) 46 | }, 47 | 48 | getAllTodosAndUpdateStore: () => { 49 | console.log("Performing getAllTodos"); 50 | api.getTodos() 51 | .then( (responseData) => { 52 | var todos = responseData.todos; 53 | console.log("new todos", todos); 54 | TodoStore.setTodos(todos); 55 | }) 56 | } 57 | 58 | } 59 | 60 | module.exports = TodoActions; 61 | -------------------------------------------------------------------------------- /ep27-use-dispatcher/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 12 |
      13 | }) } 14 |
    15 | } 16 | 17 | } 18 | 19 | DisplayList.propTypes = { 20 | todos: React.PropTypes.array.isRequired 21 | } 22 | -------------------------------------------------------------------------------- /ep27-use-dispatcher/app/dispatcher/AppDispatcher.js: -------------------------------------------------------------------------------- 1 | var Dispatcher = require('flux').Dispatcher; 2 | 3 | module.exports = new Dispatcher(); 4 | -------------------------------------------------------------------------------- /ep27-use-dispatcher/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep27-use-dispatcher/app/stores/TodoStore.js: -------------------------------------------------------------------------------- 1 | var AppDispatcher = require('../dispatcher/AppDispatcher'); 2 | 3 | AppDispatcher.register(function(action) { 4 | 5 | switch(action.actionType) { 6 | case 'TODO_DONE': 7 | console.log("Handling TODO_DONE using dispatcher in store"); 8 | TodoStore.markTodoDone(action.todo); 9 | break; 10 | } 11 | 12 | }); 13 | 14 | var _todos = {}; 15 | var _callback; 16 | 17 | var TodoStore = { 18 | 19 | deleteTodo: (todo) => { 20 | var newTodos = _todos.filter( (t) => { 21 | return t.id != todo.id 22 | } ) 23 | _todos = newTodos; 24 | _callback(_todos); 25 | }, 26 | 27 | markTodoDone: (todo) => { 28 | var _todo = _todos.filter((t) => { 29 | return t.id === todo.id; 30 | })[0]; 31 | 32 | _todo.done = true; 33 | _callback(_todos); 34 | }, 35 | 36 | markTodoUnDone: (todo) => { 37 | var _todo = _todos.filter((t) => { 38 | return t.id === todo.id; 39 | })[0]; 40 | 41 | _todo.done = false; 42 | _callback(_todos); 43 | }, 44 | 45 | setTodos: (todos) => { 46 | _todos = todos; 47 | console.log("TodoStore", TodoStore.getTodos()); 48 | _callback(todos); 49 | }, 50 | 51 | getTodos: () => { 52 | return _todos; 53 | }, 54 | 55 | addChangeListener: function (callback) { 56 | console.log("registering callback for changelistener"); 57 | _callback = callback; 58 | } 59 | } 60 | 61 | module.exports = TodoStore; 62 | -------------------------------------------------------------------------------- /ep27-use-dispatcher/app/utils/api.js: -------------------------------------------------------------------------------- 1 | require('whatwg-fetch'); 2 | var Constants = require("./constants"); 3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } 4 | 5 | var api = { 6 | generateUrlWithApiKey(endpoint) { 7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; 8 | }, 9 | 10 | getTodos () { 11 | var url = this.generateUrlWithApiKey('todos'); 12 | return fetch(url) 13 | .then((res) => res.json()) 14 | .catch( (error) => console.log('Failed to get all tasks list.', error) ); 15 | }, 16 | 17 | addTodo (todo) { 18 | var url = this.generateUrlWithApiKey('todos'); 19 | var options = { 20 | method: 'POST', 21 | headers: HEADER, 22 | body: JSON.stringify({todo: todo}) 23 | }; 24 | return fetch(url, options) 25 | .then((res) => res.json()) 26 | .catch( (error) => console.log('Failed to add a TODO.', error) ); 27 | }, 28 | 29 | markTodoDone (todo) { 30 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 31 | var options = { 32 | method: 'PUT', 33 | headers: HEADER, 34 | body: JSON.stringify({done: true}) 35 | }; 36 | return fetch(url, options) 37 | .then((res) => res.json()) 38 | .catch( (error) => console.log('Failed to mark task as done. ', error) ); 39 | }, 40 | 41 | markTodoUnDone (todo) { 42 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 43 | var options = { 44 | method: 'PUT', 45 | headers: HEADER, 46 | body: JSON.stringify({done: false}) 47 | }; 48 | return fetch(url, options) 49 | .then((res) => res.json()) 50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) ); 51 | }, 52 | 53 | deleteTodo (idToBeDeleted, processDataCallback) { 54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); 55 | return fetch(url, { method: 'DELETE' }) 56 | .then((res) => res.json()) 57 | .catch( (error) => console.log('Failed to delete TODO.', error) ); 58 | }, 59 | 60 | }; 61 | 62 | module.exports = api; 63 | -------------------------------------------------------------------------------- /ep27-use-dispatcher/app/utils/constants.js: -------------------------------------------------------------------------------- 1 | var Constants = { 2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", 3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" 4 | }; 5 | module.exports = Constants; 6 | -------------------------------------------------------------------------------- /ep27-use-dispatcher/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "flux": "^2.1.1", 27 | "jquery": "1.11.3", 28 | "random-key": "^0.3.2", 29 | "react": "^0.13.3", 30 | "whatwg-fetch": "^0.9.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ep27-use-dispatcher/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep28-more-dispatcher-usage/README.md: -------------------------------------------------------------------------------- 1 | #### Setting up the application 2 | 3 | ``` 4 | npm install 5 | npm start 6 | ``` 7 | 8 | Visit http://localhost:8080 in browser. 9 | -------------------------------------------------------------------------------- /ep28-more-dispatcher-usage/app/actions/TodoActions.js: -------------------------------------------------------------------------------- 1 | var api = require("../utils/api"); 2 | var TodoStore = require("../stores/TodoStore"); 3 | var AppDispatcher = require('../dispatcher/AppDispatcher'); 4 | var Constants = require("../utils/constants"); 5 | 6 | var TodoActions = { 7 | 8 | addTodo: (todo) => { 9 | api.addTodo(todo) 10 | .then( () => { 11 | TodoActions.getAllTodosAndUpdateStore(); 12 | }) 13 | }, 14 | 15 | deleteTodo: (todo) => { 16 | api.deleteTodo(todo.id) 17 | .then( () => { 18 | AppDispatcher.dispatch({ 19 | actionType: Constants.TODO_DELETE, 20 | todo: todo 21 | }); 22 | }) 23 | }, 24 | 25 | markTodoDone: (todo) => { 26 | api.markTodoDone(todo) 27 | .then( () => { 28 | AppDispatcher.dispatch({ 29 | actionType: Constants.TODO_DONE, 30 | todo: todo 31 | }); 32 | 33 | }) 34 | }, 35 | 36 | markTodoUnDone: (todo) => { 37 | api.markTodoUnDone(todo) 38 | .then( () => { 39 | AppDispatcher.dispatch({ 40 | actionType: Constants.TODO_UNDONE, 41 | todo: todo 42 | }); 43 | }) 44 | }, 45 | 46 | getAllTodosAndUpdateStore: () => { 47 | api.getTodos() 48 | .then( (responseData) => { 49 | var todos = responseData.todos; 50 | TodoStore.setTodos(todos); 51 | AppDispatcher.dispatch({ 52 | actionType: Constants.TODO_ADD 53 | }); 54 | }) 55 | } 56 | 57 | } 58 | 59 | module.exports = TodoActions; 60 | -------------------------------------------------------------------------------- /ep28-more-dispatcher-usage/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 12 |
      13 | }) 14 | } 15 |
    16 | } 17 | 18 | } 19 | 20 | DisplayList.propTypes = { 21 | todos: React.PropTypes.array.isRequired 22 | } 23 | -------------------------------------------------------------------------------- /ep28-more-dispatcher-usage/app/dispatcher/AppDispatcher.js: -------------------------------------------------------------------------------- 1 | var Dispatcher = require('flux').Dispatcher; 2 | 3 | module.exports = new Dispatcher(); 4 | -------------------------------------------------------------------------------- /ep28-more-dispatcher-usage/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep28-more-dispatcher-usage/app/stores/TodoStore.js: -------------------------------------------------------------------------------- 1 | var AppDispatcher = require('../dispatcher/AppDispatcher'); 2 | var Constants = require("../utils/constants"); 3 | 4 | AppDispatcher.register(function(action) { 5 | 6 | switch(action.actionType) { 7 | case Constants.TODO_DONE: 8 | TodoStore.markTodoDone(action.todo); 9 | break; 10 | 11 | case Constants.TODO_UNDONE: 12 | TodoStore.markTodoUnDone(action.todo); 13 | break; 14 | 15 | case Constants.TODO_DELETE: 16 | TodoStore.deleteTodo(action.todo); 17 | break; 18 | 19 | case Constants.TODO_ADD: 20 | TodoStore.getTodos(); 21 | break; 22 | } 23 | 24 | }); 25 | 26 | var _todos = {}; 27 | var _callback; 28 | 29 | var TodoStore = { 30 | 31 | deleteTodo: (todo) => { 32 | var newTodos = _todos.filter( (t) => { 33 | return t.id != todo.id 34 | } ) 35 | _todos = newTodos; 36 | _callback(_todos); 37 | }, 38 | 39 | markTodoDone: (todo) => { 40 | var _todo = _todos.filter((t) => { 41 | return t.id === todo.id; 42 | })[0]; 43 | 44 | _todo.done = true; 45 | _callback(_todos); 46 | }, 47 | 48 | markTodoUnDone: (todo) => { 49 | var _todo = _todos.filter((t) => { 50 | return t.id === todo.id; 51 | })[0]; 52 | 53 | _todo.done = false; 54 | _callback(_todos); 55 | }, 56 | 57 | setTodos: (todos) => { 58 | _todos = todos; 59 | console.log("TodoStore", TodoStore.getTodos()); 60 | _callback(todos); 61 | }, 62 | 63 | getTodos: () => { 64 | return _todos; 65 | _callback(todos); 66 | }, 67 | 68 | addChangeListener: function (callback) { 69 | console.log("registering callback for changelistener"); 70 | _callback = callback; 71 | } 72 | } 73 | 74 | module.exports = TodoStore; 75 | -------------------------------------------------------------------------------- /ep28-more-dispatcher-usage/app/utils/api.js: -------------------------------------------------------------------------------- 1 | require('whatwg-fetch'); 2 | var Constants = require("./constants"); 3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } 4 | 5 | var api = { 6 | generateUrlWithApiKey(endpoint) { 7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; 8 | }, 9 | 10 | getTodos () { 11 | var url = this.generateUrlWithApiKey('todos'); 12 | return fetch(url) 13 | .then((res) => res.json()) 14 | .catch( (error) => console.log('Failed to get all tasks list.', error) ); 15 | }, 16 | 17 | addTodo (todo) { 18 | var url = this.generateUrlWithApiKey('todos'); 19 | var options = { 20 | method: 'POST', 21 | headers: HEADER, 22 | body: JSON.stringify({todo: todo}) 23 | }; 24 | return fetch(url, options) 25 | .then((res) => res.json()) 26 | .catch( (error) => console.log('Failed to add a TODO.', error) ); 27 | }, 28 | 29 | markTodoDone (todo) { 30 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 31 | var options = { 32 | method: 'PUT', 33 | headers: HEADER, 34 | body: JSON.stringify({done: true}) 35 | }; 36 | return fetch(url, options) 37 | .then((res) => res.json()) 38 | .catch( (error) => console.log('Failed to mark task as done. ', error) ); 39 | }, 40 | 41 | markTodoUnDone (todo) { 42 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 43 | var options = { 44 | method: 'PUT', 45 | headers: HEADER, 46 | body: JSON.stringify({done: false}) 47 | }; 48 | return fetch(url, options) 49 | .then((res) => res.json()) 50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) ); 51 | }, 52 | 53 | deleteTodo (idToBeDeleted, processDataCallback) { 54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); 55 | return fetch(url, { method: 'DELETE' }) 56 | .then((res) => res.json()) 57 | .catch( (error) => console.log('Failed to delete TODO.', error) ); 58 | }, 59 | 60 | }; 61 | 62 | module.exports = api; 63 | -------------------------------------------------------------------------------- /ep28-more-dispatcher-usage/app/utils/constants.js: -------------------------------------------------------------------------------- 1 | var Constants = { 2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", 3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965", 4 | TODO_DONE: 'TODO_DONE', 5 | TODO_UNDONE: 'TODO_UNDONE', 6 | TODO_DELETE: 'TODO_DELETE', 7 | TODO_ADD: 'TODO_ADD' 8 | }; 9 | 10 | module.exports = Constants; 11 | -------------------------------------------------------------------------------- /ep28-more-dispatcher-usage/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "flux": "^2.1.1", 27 | "jquery": "1.11.3", 28 | "random-key": "^0.3.2", 29 | "react": "^0.13.3", 30 | "whatwg-fetch": "^0.9.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ep28-more-dispatcher-usage/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep29-emit/README.md: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /ep29-emit/app/actions/TodoActions.js: -------------------------------------------------------------------------------- 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 | 66 | } 67 | 68 | module.exports = TodoActions; 69 | -------------------------------------------------------------------------------- /ep29-emit/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 12 |
      13 | }) } 14 |
    15 | } 16 | 17 | } 18 | 19 | DisplayList.propTypes = { 20 | todos: React.PropTypes.array.isRequired 21 | } 22 | -------------------------------------------------------------------------------- /ep29-emit/app/dispatcher/AppDispatcher.js: -------------------------------------------------------------------------------- 1 | var Dispatcher = require('flux').Dispatcher; 2 | 3 | module.exports = new Dispatcher(); 4 | -------------------------------------------------------------------------------- /ep29-emit/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep29-emit/app/stores/TodoStore.js: -------------------------------------------------------------------------------- 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; 82 | -------------------------------------------------------------------------------- /ep29-emit/app/utils/api.js: -------------------------------------------------------------------------------- 1 | require('whatwg-fetch'); 2 | var Constants = require("./constants"); 3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } 4 | 5 | var api = { 6 | generateUrlWithApiKey(endpoint) { 7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; 8 | }, 9 | 10 | getTodos () { 11 | var url = this.generateUrlWithApiKey('todos'); 12 | return fetch(url) 13 | .then((res) => res.json()) 14 | .catch( (error) => console.log('Failed to get all tasks list.', error) ); 15 | }, 16 | 17 | addTodo (todo) { 18 | var url = this.generateUrlWithApiKey('todos'); 19 | var options = { 20 | method: 'POST', 21 | headers: HEADER, 22 | body: JSON.stringify({todo: todo}) 23 | }; 24 | return fetch(url, options) 25 | .then((res) => res.json()) 26 | .catch( (error) => console.log('Failed to add a TODO.', error) ); 27 | }, 28 | 29 | markTodoDone (todo) { 30 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 31 | var options = { 32 | method: 'PUT', 33 | headers: HEADER, 34 | body: JSON.stringify({done: true}) 35 | }; 36 | return fetch(url, options) 37 | .then((res) => res.json()) 38 | .catch( (error) => console.log('Failed to mark task as done. ', error) ); 39 | }, 40 | 41 | markTodoUnDone (todo) { 42 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 43 | var options = { 44 | method: 'PUT', 45 | headers: HEADER, 46 | body: JSON.stringify({done: false}) 47 | }; 48 | return fetch(url, options) 49 | .then((res) => res.json()) 50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) ); 51 | }, 52 | 53 | deleteTodo (idToBeDeleted, processDataCallback) { 54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); 55 | return fetch(url, { method: 'DELETE' }) 56 | .then((res) => res.json()) 57 | .catch( (error) => console.log('Failed to delete TODO.', error) ); 58 | }, 59 | 60 | }; 61 | 62 | module.exports = api; 63 | -------------------------------------------------------------------------------- /ep29-emit/app/utils/constants.js: -------------------------------------------------------------------------------- 1 | var Constants = { 2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", 3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" 4 | }; 5 | module.exports = Constants; 6 | -------------------------------------------------------------------------------- /ep29-emit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "flux": "^2.1.1", 27 | "jquery": "1.11.3", 28 | "object-assign": "^4.0.1", 29 | "random-key": "^0.3.2", 30 | "react": "^0.13.3", 31 | "whatwg-fetch": "^0.9.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ep29-emit/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep30-extract-form-into-componenet-from-app/README.md: -------------------------------------------------------------------------------- 1 | #### Setting up the application 2 | 3 | ``` 4 | npm install 5 | npm start 6 | ``` 7 | 8 | Visit http://localhost:8080 in browser. 9 | -------------------------------------------------------------------------------- /ep30-extract-form-into-componenet-from-app/app/actions/TodoActions.js: -------------------------------------------------------------------------------- 1 | var api = require("../utils/api"); 2 | var TodoStore = require("../stores/TodoStore"); 3 | var AppDispatcher = require('../dispatcher/AppDispatcher'); 4 | 5 | var TodoActions = { 6 | 7 | allTodos: () => { 8 | api.getTodos() 9 | .then( (responseData) => { 10 | console.log("Got All TODOs successfully"); 11 | AppDispatcher.dispatch({ 12 | actionType: 'TODO_ALL', 13 | todos: todos 14 | }); 15 | }) 16 | }, 17 | 18 | addTodo: (todo) => { 19 | console.log("adding TODO"); 20 | api.addTodo(todo) 21 | .then( () => { 22 | allTodos(); 23 | }) 24 | .then( () => { 25 | console.log("Added TODO successfully"); 26 | AppDispatcher.dispatch({ 27 | actionType: 'TODO_ADD' 28 | }); 29 | }) 30 | }, 31 | 32 | deleteTodo: (todo) => { 33 | console.log("Deleting TODO"); 34 | api.deleteTodo(todo.id) 35 | .then( () => { 36 | console.log("Deleted TODO successfully"); 37 | AppDispatcher.dispatch({ 38 | actionType: 'TODO_DELETE', 39 | todo: todo 40 | }); 41 | }) 42 | }, 43 | 44 | markTodoDone: (todo) => { 45 | console.log("Marking TODO as done"); 46 | api.markTodoDone(todo) 47 | .then( () => { 48 | console.log("marked TODO as done successfully"); 49 | AppDispatcher.dispatch({ 50 | actionType: 'TODO_DONE', 51 | todo: todo 52 | }); 53 | 54 | }) 55 | }, 56 | 57 | markTodoUnDone: (todo) => { 58 | console.log("Marking TODO as undone"); 59 | api.markTodoUnDone(todo) 60 | .then( () => { 61 | console.log("marked TODO as undone successfully"); 62 | AppDispatcher.dispatch({ 63 | actionType: 'TODO_UNDONE', 64 | todo: todo 65 | }); 66 | }) 67 | }, 68 | 69 | } 70 | 71 | module.exports = TodoActions; 72 | -------------------------------------------------------------------------------- /ep30-extract-form-into-componenet-from-app/app/components/App.jsx: -------------------------------------------------------------------------------- 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 | TodoActions.allTodos(); 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 :", todos); 24 | this.setState({todos: todos}); 25 | } 26 | TodoStore.addChangeListener(storeIsTellingUsThatDataHasChanged); 27 | } 28 | 29 | handleClearCompleted (event) { 30 | var newTodos = this.state.todos.filter((todo) => { return !todo.done}); 31 | this.setState({ todos: newTodos }); 32 | } 33 | 34 | render () { 35 | return
    36 | 37 | 39 |
    40 | All: ({ this.state.todos.length }) | 41 | Completed: ({ this.state.todos.filter((todo) => { return todo.done }).length }) | 42 | Pending: ({ this.state.todos.filter((todo) => { return !todo.done }).length }) | 43 | Clear Completed 44 |
    45 |
    46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ep30-extract-form-into-componenet-from-app/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 12 |
      13 | }) } 14 |
    15 | } 16 | 17 | } 18 | 19 | DisplayList.propTypes = { 20 | todos: React.PropTypes.array.isRequired 21 | } 22 | -------------------------------------------------------------------------------- /ep30-extract-form-into-componenet-from-app/app/components/TodoForm.jsx: -------------------------------------------------------------------------------- 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
    30 |

    TODO

    31 |
    32 | 35 |
    36 |
    ; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /ep30-extract-form-into-componenet-from-app/app/dispatcher/AppDispatcher.js: -------------------------------------------------------------------------------- 1 | var Dispatcher = require('flux').Dispatcher; 2 | 3 | module.exports = new Dispatcher(); 4 | -------------------------------------------------------------------------------- /ep30-extract-form-into-componenet-from-app/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep30-extract-form-into-componenet-from-app/app/utils/api.js: -------------------------------------------------------------------------------- 1 | require('whatwg-fetch'); 2 | var Constants = require("./constants"); 3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } 4 | 5 | var api = { 6 | generateUrlWithApiKey(endpoint) { 7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; 8 | }, 9 | 10 | getTodos () { 11 | var url = this.generateUrlWithApiKey('todos'); 12 | return fetch(url) 13 | .then((res) => res.json()) 14 | .catch( (error) => console.log('Failed to get all tasks list.', error) ); 15 | }, 16 | 17 | addTodo (todo) { 18 | var url = this.generateUrlWithApiKey('todos'); 19 | var options = { 20 | method: 'POST', 21 | headers: HEADER, 22 | body: JSON.stringify({todo: todo}) 23 | }; 24 | return fetch(url, options) 25 | .then((res) => res.json()) 26 | .catch( (error) => console.log('Failed to add a TODO.', error) ); 27 | }, 28 | 29 | markTodoDone (todo) { 30 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 31 | var options = { 32 | method: 'PUT', 33 | headers: HEADER, 34 | body: JSON.stringify({done: true}) 35 | }; 36 | return fetch(url, options) 37 | .then((res) => res.json()) 38 | .catch( (error) => console.log('Failed to mark task as done. ', error) ); 39 | }, 40 | 41 | markTodoUnDone (todo) { 42 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 43 | var options = { 44 | method: 'PUT', 45 | headers: HEADER, 46 | body: JSON.stringify({done: false}) 47 | }; 48 | return fetch(url, options) 49 | .then((res) => res.json()) 50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) ); 51 | }, 52 | 53 | deleteTodo (idToBeDeleted, processDataCallback) { 54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); 55 | return fetch(url, { method: 'DELETE' }) 56 | .then((res) => res.json()) 57 | .catch( (error) => console.log('Failed to delete TODO.', error) ); 58 | }, 59 | 60 | }; 61 | 62 | module.exports = api; 63 | -------------------------------------------------------------------------------- /ep30-extract-form-into-componenet-from-app/app/utils/constants.js: -------------------------------------------------------------------------------- 1 | var Constants = { 2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", 3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" 4 | }; 5 | module.exports = Constants; 6 | -------------------------------------------------------------------------------- /ep30-extract-form-into-componenet-from-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "flux": "^2.1.1", 27 | "jquery": "1.11.3", 28 | "object-assign": "^4.0.1", 29 | "random-key": "^0.3.2", 30 | "react": "^0.13.3", 31 | "whatwg-fetch": "^0.9.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ep30-extract-form-into-componenet-from-app/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /ep31-get-all-todos/README.md: -------------------------------------------------------------------------------- 1 | #### Setting up the application 2 | 3 | ``` 4 | npm install 5 | npm start 6 | ``` 7 | 8 | Visit http://localhost:8080 in browser. 9 | -------------------------------------------------------------------------------- /ep31-get-all-todos/app/actions/TodoActions.js: -------------------------------------------------------------------------------- 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; 66 | -------------------------------------------------------------------------------- /ep31-get-all-todos/app/components/App.jsx: -------------------------------------------------------------------------------- 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
    46 | 47 | 49 |
    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 | Clear Completed 54 |
    55 |
    56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ep31-get-all-todos/app/components/DisplayList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DisplayItem from './DisplayItem'; 3 | 4 | export default class DisplayList extends React.Component { 5 | 6 | render () { 7 | return
      8 | { this.props.todos.map((todo, i) => { 9 | return
      10 | 12 |
      13 | }) } 14 |
    15 | } 16 | 17 | } 18 | 19 | DisplayList.propTypes = { 20 | todos: React.PropTypes.array.isRequired 21 | } 22 | -------------------------------------------------------------------------------- /ep31-get-all-todos/app/components/TodoForm.jsx: -------------------------------------------------------------------------------- 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
    30 |

    TODO

    31 |
    32 | 35 |
    36 |
    ; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /ep31-get-all-todos/app/dispatcher/AppDispatcher.js: -------------------------------------------------------------------------------- 1 | var Dispatcher = require('flux').Dispatcher; 2 | 3 | module.exports = new Dispatcher(); 4 | -------------------------------------------------------------------------------- /ep31-get-all-todos/app/main.jsx: -------------------------------------------------------------------------------- 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(, div); 14 | } 15 | -------------------------------------------------------------------------------- /ep31-get-all-todos/app/stores/TodoStore.js: -------------------------------------------------------------------------------- 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; 82 | -------------------------------------------------------------------------------- /ep31-get-all-todos/app/utils/api.js: -------------------------------------------------------------------------------- 1 | require('whatwg-fetch'); 2 | var Constants = require("./constants"); 3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' } 4 | 5 | var api = { 6 | generateUrlWithApiKey(endpoint) { 7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY; 8 | }, 9 | 10 | getTodos () { 11 | var url = this.generateUrlWithApiKey('todos'); 12 | return fetch(url) 13 | .then((res) => res.json()) 14 | .catch( (error) => console.log('Failed to get all tasks list.', error) ); 15 | }, 16 | 17 | addTodo (todo) { 18 | var url = this.generateUrlWithApiKey('todos'); 19 | var options = { 20 | method: 'POST', 21 | headers: HEADER, 22 | body: JSON.stringify({todo: todo}) 23 | }; 24 | return fetch(url, options) 25 | .then((res) => res.json()) 26 | .catch( (error) => console.log('Failed to add a TODO.', error) ); 27 | }, 28 | 29 | markTodoDone (todo) { 30 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 31 | var options = { 32 | method: 'PUT', 33 | headers: HEADER, 34 | body: JSON.stringify({done: true}) 35 | }; 36 | return fetch(url, options) 37 | .then((res) => res.json()) 38 | .catch( (error) => console.log('Failed to mark task as done. ', error) ); 39 | }, 40 | 41 | markTodoUnDone (todo) { 42 | var url = this.generateUrlWithApiKey('todos/' + todo.id); 43 | var options = { 44 | method: 'PUT', 45 | headers: HEADER, 46 | body: JSON.stringify({done: false}) 47 | }; 48 | return fetch(url, options) 49 | .then((res) => res.json()) 50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) ); 51 | }, 52 | 53 | deleteTodo (idToBeDeleted, processDataCallback) { 54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted); 55 | return fetch(url, { method: 'DELETE' }) 56 | .then((res) => res.json()) 57 | .catch( (error) => console.log('Failed to delete TODO.', error) ); 58 | }, 59 | 60 | }; 61 | 62 | module.exports = api; 63 | -------------------------------------------------------------------------------- /ep31-get-all-todos/app/utils/constants.js: -------------------------------------------------------------------------------- 1 | var Constants = { 2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/", 3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965" 4 | }; 5 | module.exports = Constants; 6 | -------------------------------------------------------------------------------- /ep31-get-all-todos/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-reactjs-in-steps", 3 | "version": "0.0.1", 4 | "description": "Learn ReactJS in steps", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "TAGET=build webpack", 9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot" 10 | }, 11 | "author": "Neeraj Singh", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "babel-core": "^5.6.15", 15 | "babel-loader": "^5.3.1", 16 | "css-loader": "^0.15.1", 17 | "html-webpack-plugin": "^1.5.2", 18 | "node-libs-browser": "^0.5.2", 19 | "react-hot-loader": "^1.2.7", 20 | "style-loader": "^0.12.3", 21 | "webpack": "^1.10.1", 22 | "webpack-dev-server": "^1.10.1", 23 | "webpack-merge": "^0.1.2" 24 | }, 25 | "dependencies": { 26 | "flux": "^2.1.1", 27 | "jquery": "1.11.3", 28 | "object-assign": "^4.0.1", 29 | "random-key": "^0.3.2", 30 | "react": "^0.13.3", 31 | "whatwg-fetch": "^0.9.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ep31-get-all-todos/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var merge = require('webpack-merge'); 4 | 5 | var TARGET = process.env.TARGET; 6 | var ROOT_PATH = path.resolve(__dirname); 7 | 8 | var common = { 9 | entry: [path.resolve(ROOT_PATH, 'app/main')], 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'], 12 | }, 13 | output: { 14 | path: path.resolve(ROOT_PATH, 'build'), 15 | filename: 'bundle.js', 16 | }, 17 | plugins: [ 18 | new HtmlWebpackPlugin({ title: 'Todo app', }), 19 | ], 20 | module: { 21 | loaders: [ 22 | { 23 | test: /\.css$/, 24 | loaders: ['style', 'css'], 25 | }, 26 | { 27 | test: /\.jsx?$/, 28 | loader: 'babel?stage=1', 29 | include: path.resolve(ROOT_PATH, 'app'), 30 | } 31 | ], 32 | }, 33 | }; 34 | 35 | if (TARGET === 'build') { 36 | module.exports = common; 37 | } 38 | 39 | if (TARGET === 'dev') { 40 | module.exports = merge(common, { 41 | entry: [ 42 | 'webpack-dev-server/client?http://0.0.0.0:8080', 43 | 'webpack/hot/dev-server' 44 | ], 45 | module: { 46 | loaders: [ { 47 | test: /\.jsx?$/, 48 | loaders: ['react-hot', 'babel?stage=1'], 49 | include: path.resolve(ROOT_PATH, 'app'), 50 | }, 51 | ], 52 | }, 53 | }); 54 | } 55 | --------------------------------------------------------------------------------