├── .gitignore
├── README.md
├── app
├── RestHelper.js
├── components
│ ├── GroceryItem.jsx
│ ├── GroceryItemList.jsx
│ └── GroceryListAddItem.jsx
├── dispatcher.js
├── index.ejs
├── main.jsx
├── stores
│ ├── GroceryItemActionCreator.jsx
│ └── GroceryItemStore.jsx
└── styles.css
├── bower.json
├── gulpfile.js
├── package.json
├── server
├── database.js
├── main.js
├── models
│ └── GroceryItem.js
├── routes
│ └── items.js
└── seed.js
└── snippets.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | bower_components
3 | test/coverage
4 | .tmp
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### Usage Instructions
2 |
3 | #### To run the app,
4 | 1. Make sure `mongodb` is running in the background.
5 | 2. Install global dependencies with `npm install -g gulp bower react-tools browserify`
6 | 3. Install dependencies with `npm install; bower install`
7 | 4. Run app with `gulp serve`
8 |
9 |
10 | ### Glossary
11 |
12 | ## Dispatcher
13 | A simple emitter. Object register with the emitter to listen for an event, and when the event occurs, the objects are notified.
14 | Something tells the dispatcher it wants to listen for an event with a command called `register` or `on`.
15 | Here is an example:
16 | ```javascript
17 | exampleDispatcher.on('app-start',function(){alert("Hello")});
18 | `setTimeout(function(){exampleDispatcher.emit('app-start')},1000);` // hello
19 | ```
20 | The dispatcher's `on` or `register` function will either take two arguments, or take one argument and return a promise. The first argument is a string called the `type` of the listener. The `type` is basically the name of the event, like `sound-done` or `button-clicked`. The second argument, or the promise returned, is resolve every time the event occurs.
21 | Note that some promise architectures do not allow promises to be resolved more than once. To avoid this confusion, it is recommended that you use a callback.
22 | It is important to understand dispatcher are just a loose set of architecture rules and there are no hard and fast requirements.
23 |
24 | ## Store
25 | A utility that listens for particular kind of dispatcher events and is responsible for the handling of one element.
26 | For example, in an Address Book app, you would have a `Contacts` store.
27 | Stores fire change events, allow consumers to listen for change events, and allows direct interaction with the elements in the store.
28 | A contact store might, for example, have a function to add, edit or delete contacts that can be used by various components in your app.
29 | Stores usually contain a local copy of the database or part of the database, to allow for instant response to user interaction. Stores will then negotiate the update with a long-term storage solution in a custom manner.
30 |
31 | ## State
32 | A React component's state. A component can change it's own state, but not the state of other components. In order to change the state of another component, an app must make the appropriate request to a store.
33 |
34 | ## Props
35 | The properties of a React component. A component cannot change its own properties. The properties of a React component can only be set by its parent. In order to change the props of a component which is not the child of the caller, a request must be passed to the appropriate store.
36 |
37 | ## JSX
38 | A React-specific variant of JavaScript. JSX can be compiled into JavaScript code containing React components. JSX must be compiled as it cannot be read by web browsers.
39 |
40 | ### JSX Transformer
41 | A tool used to transform JSX without any backend. Can be used in the browser. Not used for production.
42 |
43 | ### Reactify
44 | A useful Browserify plugin which compiles JSX in to JavaScript as it is being browserified.
45 |
--------------------------------------------------------------------------------
/app/RestHelper.js:
--------------------------------------------------------------------------------
1 | let $ = require('jquery');
2 |
3 | module.exports = {
4 | get(url){
5 | return new Promise(function(success,error){
6 | $.ajax({
7 | url:url,
8 | dataType:"json",
9 | success,
10 | error
11 | });
12 | });
13 | },
14 | del(url){
15 | return new Promise(function(success,error){
16 | $.ajax({
17 | url:url,
18 | type:'DELETE',
19 | success,
20 | error
21 | })
22 | })
23 | },
24 | post(url,data){
25 | return new Promise(function(success,error){
26 | $.ajax({
27 | url,
28 | type:'POST',
29 | data,
30 | success,
31 | error
32 | })
33 | })
34 | },
35 | patch(url,data){
36 | return new Promise(function(success,error){
37 | $.ajax({
38 | url,
39 | type:'PATCH',
40 | data,
41 | success,
42 | error
43 | })
44 | })
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/components/GroceryItem.jsx:
--------------------------------------------------------------------------------
1 | var dispatcher = require("./../dispatcher.js");
2 | var groceryAction = require("./../stores/GroceryItemActionCreator.jsx");
3 | var React = require('react/addons');
4 | var cx = React.addons.classSet;
5 |
6 | module.exports = React.createClass({
7 |
8 | togglePurchased:function(e){
9 | e.preventDefault();
10 |
11 | if (!this.props.item.purchased){
12 | groceryAction.buy(this.props.item);
13 | } else {
14 | groceryAction.unbuy(this.props.item);
15 | }
16 | },
17 | delete:function(e){
18 | e.preventDefault();
19 | groceryAction.delete(this.props.item);
20 | },
21 | render:function(){
22 | return (
23 |