├── .gitignore ├── README.md ├── ajax-loader.gif ├── build └── README.md ├── index.html ├── package.json └── src ├── App.jsx ├── actions └── LocationActions.js ├── alt.js ├── components └── Locations.jsx ├── sources └── LocationSource.js └── stores ├── FavoritesStore.js └── LocationStore.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build/app.js 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Alt Tutorial 2 | 3 | ## Getting Started 4 | 5 | ```bash 6 | git clone https://github.com/goatslacker/alt-tutorial.git 7 | cd alt-tutorial 8 | npm install 9 | npm start 10 | ``` 11 | 12 | ## License 13 | 14 | MIT 15 | -------------------------------------------------------------------------------- /ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goatslacker/alt-tutorial/f1ca04d3ee374f2c31b8510779a3ed834efab569/ajax-loader.gif -------------------------------------------------------------------------------- /build/README.md: -------------------------------------------------------------------------------- 1 | Build files go here 2 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "alt-tutorial", 3 | "version": "1.0.0", 4 | "description": "A simple flux tutorial built with alt and react", 5 | "main": "server.js", 6 | "dependencies": { 7 | "alt": "^0.16.0", 8 | "react": "^0.12.2" 9 | }, 10 | "devDependencies": { 11 | "browserify": "^8.0.3", 12 | "reactify": "^0.17.1" 13 | }, 14 | "scripts": { 15 | "build": "browserify -t [reactify --es6] src/App.jsx > build/app.js", 16 | "start": "npm run build && open 'index.html' " 17 | }, 18 | "author": "Josh Perez ", 19 | "license": "MIT" 20 | } 21 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var Locations = require('./components/Locations.jsx'); 3 | 4 | React.render( 5 | , 6 | document.getElementById('ReactApp') 7 | ); 8 | -------------------------------------------------------------------------------- /src/actions/LocationActions.js: -------------------------------------------------------------------------------- 1 | var alt = require('../alt'); 2 | 3 | class LocationActions { 4 | updateLocations(locations) { 5 | this.dispatch(locations); 6 | } 7 | 8 | fetchLocations() { 9 | this.dispatch(); 10 | } 11 | 12 | locationsFailed(errorMessage) { 13 | this.dispatch(errorMessage); 14 | } 15 | 16 | favoriteLocation(location) { 17 | this.dispatch(location); 18 | } 19 | } 20 | 21 | module.exports = alt.createActions(LocationActions); 22 | -------------------------------------------------------------------------------- /src/alt.js: -------------------------------------------------------------------------------- 1 | var Alt = require('alt'); 2 | var alt = new Alt(); 3 | var chromeDebug = require('alt/utils/chromeDebug') 4 | 5 | chromeDebug(alt); 6 | 7 | module.exports = alt; 8 | -------------------------------------------------------------------------------- /src/components/Locations.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var AltContainer = require('alt/AltContainer'); 3 | var LocationStore = require('../stores/LocationStore'); 4 | var FavoritesStore = require('../stores/FavoritesStore'); 5 | var LocationActions = require('../actions/LocationActions'); 6 | 7 | var Favorites = React.createClass({ 8 | render() { 9 | return ( 10 | 17 | ); 18 | } 19 | }); 20 | 21 | var AllLocations = React.createClass({ 22 | addFave(ev) { 23 | var location = LocationStore.getLocation( 24 | Number(ev.target.getAttribute('data-id')) 25 | ); 26 | LocationActions.favoriteLocation(location); 27 | }, 28 | 29 | render() { 30 | if (this.props.errorMessage) { 31 | return ( 32 |
{this.props.errorMessage}
33 | ); 34 | } 35 | 36 | if (LocationStore.isLoading()) { 37 | return ( 38 |
39 | 40 |
41 | ) 42 | } 43 | 44 | return ( 45 | 60 | ); 61 | } 62 | }); 63 | 64 | var Locations = React.createClass({ 65 | componentDidMount() { 66 | LocationStore.fetchLocations(); 67 | }, 68 | 69 | render() { 70 | return ( 71 |
72 |

Locations

73 | 74 | 75 | 76 | 77 |

Favorites

78 | 79 | 80 | 81 |
82 | ); 83 | } 84 | }); 85 | 86 | module.exports = Locations; 87 | -------------------------------------------------------------------------------- /src/sources/LocationSource.js: -------------------------------------------------------------------------------- 1 | var LocationActions = require('../actions/LocationActions'); 2 | 3 | var mockData = [ 4 | { id: 0, name: 'Abu Dhabi' }, 5 | { id: 1, name: 'Berlin' }, 6 | { id: 2, name: 'Bogota' }, 7 | { id: 3, name: 'Buenos Aires' }, 8 | { id: 4, name: 'Cairo' }, 9 | { id: 5, name: 'Chicago' }, 10 | { id: 6, name: 'Lima' }, 11 | { id: 7, name: 'London' }, 12 | { id: 8, name: 'Miami' }, 13 | { id: 9, name: 'Moscow' }, 14 | { id: 10, name: 'Mumbai' }, 15 | { id: 11, name: 'Paris' }, 16 | { id: 12, name: 'San Francisco' } 17 | ]; 18 | 19 | var LocationSource = { 20 | fetchLocations() { 21 | return { 22 | remote() { 23 | return new Promise(function (resolve, reject) { 24 | // simulate an asynchronous flow where data is fetched on 25 | // a remote server somewhere. 26 | setTimeout(function () { 27 | 28 | // change this to `false` to see the error action being handled. 29 | if (true) { 30 | // resolve with some mock data 31 | resolve(mockData); 32 | } else { 33 | reject('Things have broken'); 34 | } 35 | }, 250); 36 | }); 37 | }, 38 | 39 | local() { 40 | // Never check locally, always fetch remotely. 41 | return null; 42 | }, 43 | 44 | success: LocationActions.updateLocations, 45 | error: LocationActions.locationsFailed, 46 | loading: LocationActions.fetchLocations 47 | } 48 | } 49 | }; 50 | 51 | module.exports = LocationSource; 52 | -------------------------------------------------------------------------------- /src/stores/FavoritesStore.js: -------------------------------------------------------------------------------- 1 | var alt = require('../alt'); 2 | var LocationActions = require('../actions/LocationActions'); 3 | 4 | class FavoritesStore { 5 | constructor() { 6 | this.locations = []; 7 | 8 | this.bindListeners({ 9 | addFavoriteLocation: LocationActions.FAVORITE_LOCATION 10 | }); 11 | } 12 | 13 | addFavoriteLocation(location) { 14 | this.locations.push(location); 15 | } 16 | } 17 | 18 | module.exports = alt.createStore(FavoritesStore, 'FavoritesStore'); 19 | -------------------------------------------------------------------------------- /src/stores/LocationStore.js: -------------------------------------------------------------------------------- 1 | var alt = require('../alt'); 2 | var LocationActions = require('../actions/LocationActions'); 3 | var LocationSource = require('../sources/LocationSource'); 4 | var FavoritesStore = require('./FavoritesStore'); 5 | 6 | class LocationStore { 7 | constructor() { 8 | this.locations = []; 9 | this.errorMessage = null; 10 | 11 | this.bindListeners({ 12 | handleUpdateLocations: LocationActions.UPDATE_LOCATIONS, 13 | handleFetchLocations: LocationActions.FETCH_LOCATIONS, 14 | handleLocationsFailed: LocationActions.LOCATIONS_FAILED, 15 | setFavorites: LocationActions.FAVORITE_LOCATION 16 | }); 17 | 18 | this.exportPublicMethods({ 19 | getLocation: this.getLocation 20 | }); 21 | 22 | this.exportAsync(LocationSource); 23 | } 24 | 25 | handleUpdateLocations(locations) { 26 | this.locations = locations; 27 | this.errorMessage = null; 28 | } 29 | 30 | handleFetchLocations() { 31 | this.locations = []; 32 | } 33 | 34 | handleLocationsFailed(errorMessage) { 35 | this.errorMessage = errorMessage; 36 | } 37 | 38 | resetAllFavorites() { 39 | this.locations = this.locations.map((location) => { 40 | return { 41 | id: location.id, 42 | name: location.name, 43 | has_favorite: false 44 | }; 45 | }); 46 | } 47 | 48 | setFavorites(location) { 49 | this.waitFor(FavoritesStore); 50 | 51 | var favoritedLocations = FavoritesStore.getState().locations; 52 | 53 | this.resetAllFavorites(); 54 | 55 | favoritedLocations.forEach((location) => { 56 | // find each location in the array 57 | for (var i = 0; i < this.locations.length; i += 1) { 58 | 59 | // set has_favorite to true 60 | if (this.locations[i].id === location.id) { 61 | this.locations[i].has_favorite = true; 62 | break; 63 | } 64 | } 65 | }); 66 | } 67 | 68 | getLocation(id) { 69 | var { locations } = this.getState(); 70 | for (var i = 0; i < locations.length; i += 1) { 71 | if (locations[i].id === id) { 72 | return locations[i]; 73 | } 74 | } 75 | 76 | return null; 77 | } 78 | } 79 | 80 | module.exports = alt.createStore(LocationStore, 'LocationStore'); 81 | --------------------------------------------------------------------------------