├── src ├── sass │ ├── styles.scss │ ├── _basic.scss │ └── _beanStyles.scss ├── js │ ├── flux │ │ ├── alt.js │ │ ├── stores │ │ │ ├── BeanListStore.js │ │ │ └── BeanItemStore.js │ │ └── actions │ │ │ ├── BeanItemActions.js │ │ │ └── BeanListActions.js │ ├── index.js │ ├── react │ │ ├── router.js │ │ ├── pages │ │ │ ├── BeanItemEditPage.js │ │ │ ├── BeanListPage.js │ │ │ └── BeanItemPage.js │ │ ├── components │ │ │ ├── BeanPowerListItem.js │ │ │ ├── BeanListItem.js │ │ │ └── BeanProfile.js │ │ ├── routes.js │ │ └── App.js │ └── api │ │ ├── BeanWebAPI.js │ │ └── EXAMPLE_DATA.js └── image │ └── bean_stencil.png ├── .gitignore ├── public ├── image │ └── bean_stencil.png └── stylesheets │ ├── styles.min.css │ └── styles.css ├── gulpfile.js ├── gulp ├── tasks │ ├── clean.js │ ├── watch.js │ ├── liveserver.js │ ├── webserver.js │ ├── webpack.js │ ├── reloadserver.js │ ├── images.js │ ├── xDEPx_reactscripts.js │ ├── _default.js │ ├── xDEPx_scripts.js │ └── styles.js └── webpack.config.js ├── index.html ├── README.md ├── package.json └── npm-debug.log /src/sass/styles.scss: -------------------------------------------------------------------------------- 1 | @import "basic"; 2 | @import "beanStyles"; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /.idea 3 | /.sass-cache 4 | /_projectfiles -------------------------------------------------------------------------------- /src/js/flux/alt.js: -------------------------------------------------------------------------------- 1 | var Alt = require('alt'); 2 | 3 | var alt = new Alt(); 4 | 5 | module.exports = alt; -------------------------------------------------------------------------------- /src/image/bean_stencil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lostpebble/alt-react-router-example/HEAD/src/image/bean_stencil.png -------------------------------------------------------------------------------- /public/image/bean_stencil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lostpebble/alt-react-router-example/HEAD/public/image/bean_stencil.png -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var requireDir = require('require-dir'); 2 | var gulp = require('gulp'); 3 | 4 | requireDir('./gulp/tasks', {recurse: true}); -------------------------------------------------------------------------------- /gulp/tasks/clean.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var del = require('del'); 3 | 4 | gulp.task('clean', function(cb) { 5 | del(['public/stylesheets', 'public/js', 'public/images'], cb); 6 | }); -------------------------------------------------------------------------------- /src/sass/_basic.scss: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: sans-serif; 3 | color: #091521; 4 | background-color : #fffefd; 5 | } 6 | 7 | ul { 8 | list-style-type: none; 9 | padding: 0px; 10 | } -------------------------------------------------------------------------------- /gulp/tasks/watch.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | gulp.task('watch', function() { 4 | gulp.watch('src/sass/**/*.scss', ['styles']); 5 | gulp.watch('src/image/**/*', ['images']); 6 | }); -------------------------------------------------------------------------------- /src/js/index.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var router = require('./react/router'); 3 | 4 | router.run((Handler, state) => { 5 | React.render(, document.body); 6 | }); -------------------------------------------------------------------------------- /src/js/react/router.js: -------------------------------------------------------------------------------- 1 | var ReactRouter = require('react-router'); 2 | var routes = require('./routes'); 3 | 4 | var router = ReactRouter.create({ 5 | location : ReactRouter.HashLocation, 6 | routes : routes 7 | }); 8 | 9 | module.exports = router; -------------------------------------------------------------------------------- /gulp/tasks/liveserver.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | // Starts webserver 4 | // 5 | // Reloads server on changes to output folder 6 | 7 | gulp.task('liveserver', ['webserver'], function() { 8 | gulp.watch('./public/**/*', ['reloadserver']); 9 | }); -------------------------------------------------------------------------------- /gulp/tasks/webserver.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var connect = require('gulp-connect'); 3 | 4 | var webserverOptions = { 5 | livereload : true, 6 | root : [__dirname+"/../../"] 7 | }; 8 | 9 | gulp.task('webserver', function() { 10 | connect.server(webserverOptions); 11 | }); -------------------------------------------------------------------------------- /gulp/tasks/webpack.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var webpack = require("gulp-webpack"); 3 | var webpackconfig = require("../webpack.config"); 4 | 5 | gulp.task("webpack", function() { 6 | return gulp.src('./src/js/index.js') 7 | .pipe(webpack(webpackconfig)) 8 | .pipe(gulp.dest('public/js/')); 9 | }); 10 | -------------------------------------------------------------------------------- /gulp/tasks/reloadserver.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var connect = require('gulp-connect'); 3 | var notify = require('gulp-notify'); 4 | 5 | gulp.task('reloadserver', function() { 6 | gulp.src("index.html") 7 | .pipe(connect.reload()) 8 | .pipe(notify({message: "Server reloaded"})); 9 | }); -------------------------------------------------------------------------------- /gulp/tasks/images.js: -------------------------------------------------------------------------------- 1 | gulp = require('gulp'); 2 | imagemin = require('gulp-imagemin'); 3 | notify = require('gulp-notify'); 4 | 5 | gulp.task('images', function() { 6 | return gulp.src('src/image/*') 7 | .pipe(imagemin({ 8 | progressive: true 9 | })) 10 | .pipe(gulp.dest('public/image')) 11 | .pipe(notify({message: "Image task complete"})); 12 | }); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | alt react-router example 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/js/react/pages/BeanItemEditPage.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | 3 | // Editing beans is not implemented yet 4 | // Todo: Make the edit page 5 | 6 | var BeanItemEditPage = React.createClass({ 7 | render() { 8 | return ( 9 |
10 |

e.d.i.t.i.n.g bean : {this.props.params.beanID}

11 |
12 | ); 13 | } 14 | }); 15 | 16 | module.exports = BeanItemEditPage; -------------------------------------------------------------------------------- /gulp/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | entry: [ 5 | './src/js/index' 6 | ], 7 | output: { 8 | filename: 'bundle.js' 9 | }, 10 | resolve: { 11 | extensions: ['', '.js', '.jsx'] 12 | }, 13 | watch: true, 14 | module: { 15 | loaders: [ 16 | { test: /\.js$/, loaders: ['jsx?harmony'], exclude: /node_modules/ } 17 | ] 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /src/js/react/components/BeanPowerListItem.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | 3 | var BeanPowerListItem = React.createClass({ 4 | 5 | render() { 6 | return( 7 |
  • 8 | {this.props.power.power_name} 9 | {this.props.power.power_description} 10 |
  • 11 | ) 12 | } 13 | }); 14 | 15 | module.exports = BeanPowerListItem; -------------------------------------------------------------------------------- /src/js/react/components/BeanListItem.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var { Link } = require('react-router'); 3 | 4 | var BeanListItem = React.createClass({ 5 | 6 | render() { 7 | var itemStyle = { 8 | color: this.props.bean.bean_color 9 | }; 10 | 11 | return( 12 | 13 |
  • 14 | {this.props.bean.bean_name} 15 |
  • 16 | 17 | ) 18 | } 19 | }); 20 | 21 | module.exports = BeanListItem; -------------------------------------------------------------------------------- /src/js/flux/stores/BeanListStore.js: -------------------------------------------------------------------------------- 1 | var BeanListActions = require('../actions/BeanListActions'); 2 | var alt = require('../alt'); 3 | 4 | class BeanListStore { 5 | constructor() { 6 | this.bindActions(BeanListActions); 7 | 8 | this.loadingBeanList = false; 9 | this.beanList = []; 10 | } 11 | 12 | onRequestBeanList() { 13 | this.loadingBeanList = true; 14 | } 15 | 16 | onReceiveBeanList(rawList) { 17 | this._init(rawList); 18 | this.loadingBeanList = false; 19 | } 20 | 21 | _init(rawList) { 22 | this.beanList = rawList; 23 | } 24 | } 25 | 26 | module.exports = alt.createStore(BeanListStore); -------------------------------------------------------------------------------- /gulp/tasks/xDEPx_reactscripts.js: -------------------------------------------------------------------------------- 1 | // DEPRECIATED : only here if you decide to switch the JS bundling to Gulp again for some reason 2 | // 3 | // Remember to add the required packages back into your package.json file 4 | // 5 | //var gulp = require('gulp'); 6 | //var concat = require('gulp-concat'); 7 | //var notify = require('gulp-notify'); 8 | //var react = require('gulp-react'); 9 | // 10 | //gulp.task('reactscripts', function() { 11 | // return gulp.src('src/react/**/*.jsx') 12 | // .pipe(react()) 13 | // .pipe(concat('reactscripts.js')) 14 | // .pipe(gulp.dest('src/scripts')) 15 | // .pipe(notify({ message: 'React task complete' })); 16 | //}); -------------------------------------------------------------------------------- /src/js/react/routes.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var { Route, DefaultRoute } = require('react-router'); 3 | 4 | var App = require('./App'); 5 | 6 | var BeanListPage = require('./pages/BeanListPage'); 7 | var BeanItemPage = require('./pages/BeanItemPage'); 8 | var BeanItemEditPage = require('./pages/BeanItemEditPage'); 9 | 10 | var routes = ( 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | 18 | module.exports = routes; -------------------------------------------------------------------------------- /gulp/tasks/_default.js: -------------------------------------------------------------------------------- 1 | gulp = require('gulp'); 2 | runSequence = require('run-sequence'); 3 | 4 | // DEFAULT TASK 5 | // ************ 6 | // 7 | // { CLEANS output folders } then 8 | // { COMPILES images, scripts and styles } and 9 | // { WATCHES images, scripts and styles for changes } 10 | // 11 | // TASKS 12 | // 13 | // clean output folders : clean 14 | // compile images : images 15 | // javascript compile + watch : webpack 16 | // styles compile : styles 17 | // styles and images watch : watch 18 | 19 | gulp.task('default', ['clean'], function() { 20 | runSequence( ['images', 'webpack', 'styles', 'watch'] ); 21 | }); -------------------------------------------------------------------------------- /src/js/react/App.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var { RouteHandler, Link } = require('react-router'); 3 | var { PropTypes } = React; 4 | 5 | var App = React.createClass({ 6 | 7 | propTypes: { 8 | params: PropTypes.object.isRequired, 9 | query: PropTypes.object.isRequired 10 | }, 11 | 12 | render: function() { 13 | return ( 14 |
    15 |

    Beans of War

    16 |
      17 |
    • HOME
    • 18 |
    19 | 20 |
    21 | ); 22 | } 23 | }); 24 | 25 | module.exports = App; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | alt react-router example 2 | ======================== 3 | 4 | An example project showing a way to create react-router React projects with the Alt flux implementation. 5 | 6 | ### Install and run 7 | 8 | ``` 9 | npm install 10 | npm start 11 | ``` 12 | 13 | ### Building on top of this project 14 | 15 | I used gulp to compile all the scripts (forwarded to webpack), images and the SCSS styles. 16 | 17 | To compile and watch scripts, styles and images just run: 18 | ``` 19 | gulp 20 | ``` 21 | 22 | Then, to start a live server, in a different console window, you can run **either**: 23 | ``` 24 | gulp liveserver 25 | npm start 26 | ``` 27 | 28 | This also will refresh the live server if any changes to scripts, styles or images are detected. -------------------------------------------------------------------------------- /gulp/tasks/xDEPx_scripts.js: -------------------------------------------------------------------------------- 1 | // DEPRECIATED : only here if you decide to switch the JS bundling to Gulp again for some reason 2 | // 3 | // Remember to add the required packages back into your package.json file 4 | // 5 | //var gulp = require('gulp'); 6 | //var concat = require('gulp-concat'); 7 | //var notify = require('gulp-notify'); 8 | //var rename = require('gulp-rename'); 9 | //var uglify = require('gulp-uglify'); 10 | //var connect = require('gulp-connect'); 11 | // 12 | //gulp.task('scripts', function() { 13 | // return gulp.src('src/scripts/**/*.js') 14 | // .pipe(concat('main.js')) 15 | // .pipe(gulp.dest('public/js')) 16 | // .pipe(rename({suffix: '.min'})) 17 | // .pipe(uglify()) 18 | // .pipe(gulp.dest('public/js')) 19 | // .pipe(notify({ message: 'Scripts task complete' })) 20 | // .pipe(connect.reload()); 21 | //}); -------------------------------------------------------------------------------- /src/js/flux/stores/BeanItemStore.js: -------------------------------------------------------------------------------- 1 | var alt = require('../alt'); 2 | var BeanItemActions = require('../actions/BeanItemActions'); 3 | 4 | class BeanItemStore { 5 | constructor() { 6 | this.bindActions(BeanItemActions); 7 | 8 | this.loadingBeanItem = false; 9 | this.beanItem = {}; 10 | this.beanItemError = null; 11 | } 12 | 13 | onRequestBeanItem() { 14 | this.loadingBeanItem = true; 15 | this.beanItemError = null; 16 | } 17 | 18 | onReceiveBeanItem(rawBeanItem) { 19 | this._init(rawBeanItem); 20 | this.loadingBeanItem = false; 21 | } 22 | 23 | onReceiveBeanItemError(error) { 24 | this.beanItemError = error; 25 | this.loadingBeanItem = false; 26 | } 27 | 28 | _init(rawBeanItem) { 29 | this.beanItem = rawBeanItem; 30 | } 31 | } 32 | 33 | module.exports = alt.createStore(BeanItemStore); -------------------------------------------------------------------------------- /src/js/flux/actions/BeanItemActions.js: -------------------------------------------------------------------------------- 1 | var alt = require('../alt'); 2 | var BeanWebAPI = require('../../api/BeanWebAPI'); 3 | 4 | class BeanItemActions { 5 | 6 | receiveBeanItem(beanItem) { 7 | this.dispatch(beanItem); 8 | } 9 | 10 | receiveBeanItemError(error) { 11 | this.dispatch(error); 12 | } 13 | 14 | requestBeanItem(beanID) { 15 | var actionDispatcher = this; 16 | 17 | actionDispatcher.dispatch(); 18 | 19 | BeanWebAPI.requestBeanItem(beanID).then(function(beanItem) { 20 | 21 | actionDispatcher.actions.receiveBeanItem(beanItem); 22 | console.log("received bean item"); 23 | 24 | }).catch(function(error) { 25 | 26 | actionDispatcher.actions.receiveBeanItemError(error); 27 | console.log(error); 28 | 29 | }); 30 | 31 | console.log("requested bean item"); 32 | } 33 | } 34 | 35 | module.exports = alt.createActions(BeanItemActions); -------------------------------------------------------------------------------- /gulp/tasks/styles.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var sass = require('gulp-ruby-sass'); 3 | var autoprefixer = require('gulp-autoprefixer'); 4 | var rename = require('gulp-rename'); 5 | var minifycss = require('gulp-minify-css'); 6 | var notify = require('gulp-notify'); 7 | 8 | var autoprefixerCompatibility = 9 | ['> 1%', 10 | 'last 2 versions', 11 | 'Opera >= 12', 12 | 'Chrome >= 25', 13 | 'Firefox >= 13', 14 | 'ie >= 9']; 15 | 16 | gulp.task('styles', function() { 17 | return gulp.src('src/sass/styles.scss') 18 | .pipe(sass({ style: 'expanded', "sourcemap=none": true })) 19 | .pipe(autoprefixer({browsers: autoprefixerCompatibility, cascade: false})) 20 | .pipe(gulp.dest('public/stylesheets')) 21 | .pipe(rename({suffix: '.min'})) 22 | .pipe(minifycss()) 23 | .pipe(gulp.dest('public/stylesheets')) 24 | .pipe(notify({ message:'Styles task complete' })); 25 | }); -------------------------------------------------------------------------------- /src/js/flux/actions/BeanListActions.js: -------------------------------------------------------------------------------- 1 | var alt = require('../alt'); 2 | var BeanWebAPI = require('../../api/BeanWebAPI'); 3 | 4 | class BeanListActions { 5 | 6 | receiveBeanList(list) { 7 | this.dispatch(list); 8 | } 9 | 10 | requestBeanList() { 11 | // Have to reference "this" so we can call 12 | // our own actions inside the promise return 13 | var actionDispatcher = this; 14 | 15 | // Call this action 16 | actionDispatcher.dispatch(); 17 | 18 | // Promise is returned, when resolved call the received bean list action 19 | BeanWebAPI.requestBeanList().then(function(list) { 20 | 21 | actionDispatcher.actions.receiveBeanList(list); 22 | console.log("received the bean list"); 23 | 24 | }).catch(function(error) { 25 | console.log(error); 26 | }); 27 | 28 | console.log("requested the bean list"); 29 | } 30 | } 31 | 32 | module.exports = alt.createActions(BeanListActions); 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "alt-react-router-example", 3 | "version": "1.0.0", 4 | "description": "Starter for React projects", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "gulp liveserver" 9 | }, 10 | "author": "Paul Myburgh", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "del": "^1.1.0", 14 | "gulp": "^3.8.10", 15 | "gulp-autoprefixer": "^2.0.0", 16 | "gulp-connect": "^2.2.0", 17 | "gulp-imagemin": "^2.0.0", 18 | "gulp-minify-css": "^0.3.11", 19 | "gulp-notify": "^2.0.1", 20 | "gulp-rename": "^1.2.0", 21 | "gulp-ruby-sass": "^0.7.1", 22 | "gulp-webpack": "^1.2.0", 23 | "jsx-loader": "^0.12.2", 24 | "require-dir": "^0.1.0", 25 | "run-sequence": "^1.0.2" 26 | }, 27 | "dependencies": { 28 | "alt": "^0.16.7", 29 | "node-libs-browser": "^0.5.2", 30 | "react": "^0.13.3", 31 | "react-router": "^0.13.3", 32 | "webpack": "^1.9.10" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /public/stylesheets/styles.min.css: -------------------------------------------------------------------------------- 1 | body{font-family:sans-serif;color:#091521;background-color:#fffefd}ul{list-style-type:none;padding:0}li.bean-list-item{display:block;float:left;font-size:3em;background-color:#F8FBFC;border:1px solid #cce7f3;margin-right:5px;margin-top:5px;border-radius:6px;padding:6px 13px}li.bean-list-item:hover{background-color:#fff;border-bottom:1px solid #b0b9d1;border-top:1px solid #bcc5dd;box-shadow:0 0 17px rgba(90,110,120,.2);-webkit-transition:box-shadow .3s;-moz-transition:box-shadow .3s;-o-transition:box-shadow .3s;transition:box-shadow .3s;cursor:pointer}span.power-name{font-style:italic;font-weight:700;margin-right:20px}.bean-item-page{text-align:center}.bean-item-page .error{color:red;margin:30px}.bean-item-page .loading-element{font-size:2em;margin:20px}.navigation{padding:10px}.navigation a{text-decoration:none;color:#fbfbfb}.navigation .navigation-item{font-weight:700;display:inline;font-size:1.5em;padding:5px;background-color:#9a9ea4;-webkit-transition:.3s linear;-moz-transition:.3s linear;-o-transition:.3s linear;transition:.3s linear}.navigation .navigation-item:hover{background-color:#afb3b9} -------------------------------------------------------------------------------- /src/js/api/BeanWebAPI.js: -------------------------------------------------------------------------------- 1 | var fakeData = require('./EXAMPLE_DATA'); 2 | 3 | // Emulate API requests 4 | 5 | class BeanWebApi { 6 | 7 | // API requests using the Promise interface 8 | 9 | // TODO: caching data that has already been received from the server 10 | 11 | static requestBeanList() { 12 | return new Promise(function(resolve, reject) { 13 | 14 | setTimeout(function() { 15 | resolve(fakeData.getList); 16 | }, Math.random() * 2000 + 1000); 17 | 18 | // Short timeout for testing 19 | /*setTimeout(function() { 20 | resolve(fakeData.getList); 21 | }, 1);*/ 22 | }); 23 | } 24 | 25 | static requestBeanItem(beanID) { 26 | return new Promise(function(resolve, reject) { 27 | 28 | setTimeout(function() { 29 | if (fakeData.getBean[beanID]) { 30 | resolve(fakeData.getBean[beanID]); 31 | } else { 32 | reject("Bean item does not exist"); 33 | } 34 | 35 | }, Math.random() * 700 + 100); 36 | }); 37 | } 38 | } 39 | 40 | module.exports = BeanWebApi; -------------------------------------------------------------------------------- /src/js/react/components/BeanProfile.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var BeanPowerListItem = require('./BeanPowerListItem'); 3 | 4 | var BeanProfile = React.createClass({ 5 | 6 | render() { 7 | var beanColor = this.props.beanItem.bean_color; 8 | 9 | var imgStyle = { 10 | backgroundColor : beanColor 11 | }; 12 | 13 | var spanStyle = { 14 | color: beanColor 15 | }; 16 | 17 | if (this.props.beanItem.bean_powers) { 18 | var beanPowers = this.props.beanItem.bean_powers.map(function(power) { 19 | return ( 20 | 21 | ) 22 | }); 23 | } 24 | 25 | return ( 26 |
    27 | 28 |

    The {this.props.beanItem.bean_name} bean

    29 |
    {this.props.beanItem.bean_description}
    30 |
    31 |

    Powers

    32 |
      {beanPowers}
    33 |
    34 |
    35 | ) 36 | } 37 | }); 38 | 39 | module.exports = BeanProfile; -------------------------------------------------------------------------------- /src/sass/_beanStyles.scss: -------------------------------------------------------------------------------- 1 | li.bean-list-item { 2 | display: block; 3 | float: left; 4 | font-size: 3em; 5 | background-color: #F8FBFC; 6 | border: 1px solid #cce7f3; 7 | // border-bottom: 2px solid white; 8 | margin-right: 5px; 9 | margin-top: 5px; 10 | border-radius: 6px; 11 | padding: 6px 13px; 12 | } 13 | 14 | li.bean-list-item:hover { 15 | background-color: white; 16 | border-bottom: 1px solid #b0b9d1; 17 | border-top: 1px solid #bcc5dd; 18 | box-shadow: 0px 0px 17px rgba(90, 110, 120, 0.2); 19 | transition: box-shadow 0.3s; 20 | // border-bottom: 2px solid #9098af; 21 | cursor: pointer; 22 | } 23 | 24 | span.power-name { 25 | font-style: italic; 26 | font-weight: bold; 27 | margin-right: 20px; 28 | /* min-width: 200px; */ 29 | } 30 | 31 | .bean-item-page { 32 | text-align: center; 33 | 34 | .error { 35 | color : red; 36 | margin: 30px; 37 | } 38 | 39 | .loading-element { 40 | font-size: 2em; 41 | margin: 20px; 42 | } 43 | } 44 | 45 | .navigation { 46 | padding: 10px; 47 | 48 | a { 49 | text-decoration: none; 50 | color: #fbfbfb; 51 | } 52 | 53 | .navigation-item { 54 | font-weight: bold; 55 | display: inline; 56 | font-size: 1.5em; 57 | padding: 5px; 58 | background-color: #9a9ea4; 59 | transition: 0.3s linear; 60 | } 61 | 62 | .navigation-item:hover { 63 | background-color: #afb3b9; 64 | 65 | } 66 | } -------------------------------------------------------------------------------- /public/stylesheets/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: sans-serif; 3 | color: #091521; 4 | background-color: #fffefd; 5 | } 6 | 7 | ul { 8 | list-style-type: none; 9 | padding: 0px; 10 | } 11 | 12 | li.bean-list-item { 13 | display: block; 14 | float: left; 15 | font-size: 3em; 16 | background-color: #F8FBFC; 17 | border: 1px solid #cce7f3; 18 | margin-right: 5px; 19 | margin-top: 5px; 20 | border-radius: 6px; 21 | padding: 6px 13px; 22 | } 23 | 24 | li.bean-list-item:hover { 25 | background-color: white; 26 | border-bottom: 1px solid #b0b9d1; 27 | border-top: 1px solid #bcc5dd; 28 | box-shadow: 0px 0px 17px rgba(90, 110, 120, 0.2); 29 | -webkit-transition: box-shadow 0.3s; 30 | -moz-transition: box-shadow 0.3s; 31 | -o-transition: box-shadow 0.3s; 32 | transition: box-shadow 0.3s; 33 | cursor: pointer; 34 | } 35 | 36 | span.power-name { 37 | font-style: italic; 38 | font-weight: bold; 39 | margin-right: 20px; 40 | /* min-width: 200px; */ 41 | } 42 | 43 | .bean-item-page { 44 | text-align: center; 45 | } 46 | .bean-item-page .error { 47 | color: red; 48 | margin: 30px; 49 | } 50 | .bean-item-page .loading-element { 51 | font-size: 2em; 52 | margin: 20px; 53 | } 54 | 55 | .navigation { 56 | padding: 10px; 57 | } 58 | .navigation a { 59 | text-decoration: none; 60 | color: #fbfbfb; 61 | } 62 | .navigation .navigation-item { 63 | font-weight: bold; 64 | display: inline; 65 | font-size: 1.5em; 66 | padding: 5px; 67 | background-color: #9a9ea4; 68 | -webkit-transition: 0.3s linear; 69 | -moz-transition: 0.3s linear; 70 | -o-transition: 0.3s linear; 71 | transition: 0.3s linear; 72 | } 73 | .navigation .navigation-item:hover { 74 | background-color: #afb3b9; 75 | } 76 | -------------------------------------------------------------------------------- /src/js/react/pages/BeanListPage.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var BeanListActions = require('../../flux/actions/BeanListActions'); 3 | var BeanListStore = require('../../flux/stores/BeanListStore'); 4 | var ListenerMixin = require('alt/mixins/ListenerMixin'); 5 | 6 | var BeanListItem = require('../components/BeanListItem'); 7 | 8 | var BeanListPage = React.createClass({ 9 | mixins: [ListenerMixin], 10 | 11 | getInitialState() { 12 | return BeanListStore.getState(); 13 | }, 14 | 15 | componentWillMount() { 16 | this.listenTo(BeanListStore, this._onChange); 17 | }, 18 | 19 | componentDidMount() { 20 | 21 | // Simple way of implementing a caching of sorts... 22 | // Should probably be implemented properly in the 23 | // Web API though, not at the view level 24 | 25 | if (!this.state.beanList.length) { 26 | BeanListActions.requestBeanList(); 27 | } 28 | }, 29 | 30 | _onChange() { 31 | this.setState( BeanListStore.getState() ); 32 | }, 33 | 34 | render() { 35 | var beanList = null; 36 | 37 | if (this.state.loadingBeanList) { 38 | beanList = ( 39 |
    LOADING...
    40 | ); 41 | } else { 42 | beanList = this.state.beanList.map(function(listItem) { 43 | return ( 44 | 45 | ); 46 | }) 47 | } 48 | 49 | return ( 50 |
    51 |

    Take your pick

    52 |
      53 | {beanList} 54 |
    55 |
    56 | ); 57 | } 58 | }); 59 | 60 | module.exports = BeanListPage; -------------------------------------------------------------------------------- /npm-debug.log: -------------------------------------------------------------------------------- 1 | 0 info it worked if it ends with ok 2 | 1 verbose cli [ 'node', 3 | 1 verbose cli 'C:\\Users\\Paul\\AppData\\Roaming\\npm\\node_modules\\npm\\bin\\npm-cli.js', 4 | 1 verbose cli 'start' ] 5 | 2 info using npm@2.3.0 6 | 3 info using node@v0.10.36 7 | 4 verbose run-script [ 'prestart', 'start', 'poststart' ] 8 | 5 info prestart alt-react-router-example@1.0.0 9 | 6 info start alt-react-router-example@1.0.0 10 | 7 verbose unsafe-perm in lifecycle true 11 | 8 info alt-react-router-example@1.0.0 Failed to exec start script 12 | 9 verbose stack Error: alt-react-router-example@1.0.0 start: `gulp liveserver` 13 | 9 verbose stack Exit status 8 14 | 9 verbose stack at EventEmitter. (C:\Users\Paul\AppData\Roaming\npm\node_modules\npm\lib\utils\lifecycle.js:213:16) 15 | 9 verbose stack at EventEmitter.emit (events.js:98:17) 16 | 9 verbose stack at ChildProcess. (C:\Users\Paul\AppData\Roaming\npm\node_modules\npm\lib\utils\spawn.js:14:12) 17 | 9 verbose stack at ChildProcess.emit (events.js:98:17) 18 | 9 verbose stack at maybeClose (child_process.js:766:16) 19 | 9 verbose stack at Process.ChildProcess._handle.onexit (child_process.js:833:5) 20 | 10 verbose pkgid alt-react-router-example@1.0.0 21 | 11 verbose cwd D:\Dev\Flux\simple-alt 22 | 12 error Windows_NT 6.2.9200 23 | 13 error argv "node" "C:\\Users\\Paul\\AppData\\Roaming\\npm\\node_modules\\npm\\bin\\npm-cli.js" "start" 24 | 14 error node v0.10.36 25 | 15 error npm v2.3.0 26 | 16 error code ELIFECYCLE 27 | 17 error alt-react-router-example@1.0.0 start: `gulp liveserver` 28 | 17 error Exit status 8 29 | 18 error Failed at the alt-react-router-example@1.0.0 start script 'gulp liveserver'. 30 | 18 error This is most likely a problem with the alt-react-router-example package, 31 | 18 error not with npm itself. 32 | 18 error Tell the author that this fails on your system: 33 | 18 error gulp liveserver 34 | 18 error You can get their info via: 35 | 18 error npm owner ls alt-react-router-example 36 | 18 error There is likely additional logging output above. 37 | 19 verbose exit [ 1, true ] 38 | -------------------------------------------------------------------------------- /src/js/react/pages/BeanItemPage.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var BeanItemStore = require('../../flux/stores/BeanItemStore'); 3 | var BeanItemActions = require('../../flux/actions/BeanItemActions'); 4 | var ListenerMixin = require('alt/mixins/ListenerMixin'); 5 | 6 | var BeanPowerListItem = require('../components/BeanPowerListItem'); 7 | var BeanProfile = require('../components/BeanProfile'); 8 | 9 | var BeanItemPage = React.createClass({ 10 | mixins: [ListenerMixin], 11 | 12 | getInitialState() { 13 | return BeanItemStore.getState(); 14 | }, 15 | 16 | componentWillMount() { 17 | this.listenTo(BeanItemStore, this._onChange); 18 | }, 19 | 20 | componentDidMount() { 21 | BeanItemActions.requestBeanItem(this.props.params.beanID); 22 | }, 23 | 24 | _onChange() { 25 | this.setState(BeanItemStore.getState()); 26 | }, 27 | 28 | componentWillReceiveProps(nextProps) { 29 | if (this.props.params !== nextProps.params) { 30 | BeanItemActions.requestBeanItem(nextProps.params.beanID); 31 | } 32 | }, 33 | 34 | render() { 35 | 36 | var elementToDisplay = null; 37 | 38 | // First check if it's loading 39 | // Then once loaded, check if there's an error 40 | // Show whatever element is required for each stage 41 | 42 | if (this.state.loadingBeanItem) { 43 | elementToDisplay = ( 44 |
    LOADING BEAN...
    45 | ) 46 | } else { 47 | if (this.state.beanItemError) { 48 | elementToDisplay = ( 49 |
    {this.state.beanItemError}
    50 | ) 51 | } else { 52 | elementToDisplay = ( 53 | 54 | ) 55 | } 56 | } 57 | 58 | return ( 59 |
    60 | {elementToDisplay} 61 |
    62 | ); 63 | } 64 | }); 65 | 66 | module.exports = BeanItemPage; -------------------------------------------------------------------------------- /src/js/api/EXAMPLE_DATA.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "getList" : [ 3 | { 4 | "bean_id" : "wildwest0", 5 | "bean_name" : "Wild West", 6 | "bean_color" : "#D4B881" 7 | }, 8 | 9 | { 10 | "bean_id" : "aquatic0", 11 | "bean_name" : "Aquatic", 12 | "bean_color" : "#77A8C3" 13 | }, 14 | 15 | { 16 | "bean_id" : "zuluwarrior0", 17 | "bean_name" : "Zulu Warrior", 18 | "bean_color" : "#806744" 19 | }, 20 | 21 | { 22 | "bean_id" : "godzilla0", 23 | "bean_name" : "Godzilla", 24 | "bean_color" : "#546B58" 25 | }, 26 | 27 | { 28 | "bean_id" : "doesnotexist0", 29 | "bean_name" : "Erroneous", 30 | "bean_color" : "#D14B49" 31 | } 32 | ], 33 | 34 | "getBean" : { 35 | "wildwest0" : { 36 | "bean_id" : "wildwest0", 37 | "bean_name" : "Wild West", 38 | "bean_color" : "#D4B881", 39 | "bean_description" : "Gunslinging bean from the wild American frontier", 40 | "bean_powers" : [ 41 | { 42 | "power_name" : "Whip", 43 | "power_description" : "Whip with a whip" 44 | }, 45 | { 46 | "power_name" : "Shoot", 47 | "power_description" : "Quick-draw a gun and shoot from the hip" 48 | } 49 | ] 50 | }, 51 | "aquatic0" : { 52 | "bean_id" : "aquatic0", 53 | "bean_name" : "Aquatic", 54 | "bean_color" : "#77A8C3", 55 | "bean_description" : "A bean at home in the ocean", 56 | "bean_powers" : [ 57 | { 58 | "power_name" : "Squirt", 59 | "power_description" : "Sprays water at enemies" 60 | }, 61 | { 62 | "power_name" : "Typhoon", 63 | "power_description" : "Creates a massive storm" 64 | }, 65 | { 66 | "power_name" : "Splash", 67 | "power_description" : "Magikarp flashbacks.. Pretty much useless" 68 | } 69 | ] 70 | }, 71 | "zuluwarrior0" : { 72 | "bean_id" : "zuluwarrior0", 73 | "bean_name" : "Zulu Warrior", 74 | "bean_color" : "#806744", 75 | "bean_description" : "Legendary African fighter bean", 76 | "bean_powers" : [ 77 | { 78 | "power_name" : "Stab", 79 | "power_description" : "Thrusts with its spear" 80 | }, 81 | { 82 | "power_name" : "Warcry", 83 | "power_description" : "Rallies allies and strikes fear in enemies with an intimidating warcry" 84 | } 85 | ] 86 | }, 87 | "godzilla0" : { 88 | "bean_id" : "godzilla0", 89 | "bean_name" : "Godzilla", 90 | "bean_color" : "#546B58", 91 | "bean_description" : "The arrogance of men is thinking nature is in their control and not the other way around...", 92 | "bean_powers" : [ 93 | { 94 | "power_name" : "Atomic Breath", 95 | "power_description" : "A concentrated blast of radiation" 96 | }, 97 | { 98 | "power_name" : "Roar", 99 | "power_description" : "A low, groaning bellow" 100 | } 101 | ] 102 | } 103 | } 104 | }; --------------------------------------------------------------------------------