├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── .travis.yml ├── LICENSE ├── README.md ├── app ├── index.js └── templates │ ├── About.js │ ├── Gruntfile.js │ ├── README.md │ ├── _bower.json │ ├── _package.json │ ├── about_how_to.md │ ├── about_my_app.md │ ├── all.routes.js │ ├── app.js │ ├── bowerrc │ ├── db.js │ ├── editorconfig │ ├── gitignore │ ├── index.html │ ├── jshintrc │ └── main.js ├── bbmc ├── README.md ├── index.js └── templates │ ├── collection.js │ └── model.js ├── formbb ├── README.md ├── index.js └── templates │ └── form.js ├── listbb ├── README.md ├── index.js └── templates │ └── list.js ├── mgroutes ├── index.js └── templates │ ├── controller.js │ ├── model.js │ └── routes.js ├── package.json ├── shell ├── README.md ├── index.js └── templates │ └── shell.js ├── tab ├── README.md ├── index.js └── templates │ └── tab.js ├── tablebb ├── README.md ├── index.js └── templates │ └── table.js ├── test ├── test-creation.js └── test-load.js └── tools.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | temp/ 3 | /.idea/* 4 | *.iml 5 | *.log -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 4, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "regexp": true, 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "white": true 21 | } 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.8' 4 | - '0.10' 5 | before_install: 6 | - currentfolder=${PWD##*/} 7 | - if [ "$currentfolder" != 'generator-react-app' ]; then cd .. && eval "mv $currentfolder generator-react-app" && cd generator-react-app; fi 8 | 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 Philippe CHARRIERE 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #generator-react-app 2 | 3 | A generator for [Yeoman](http://yeoman.io). 4 | 5 | What can i do with it ? 6 | 7 | - generate single page application with [React](http://facebook.github.io/react/index.html), jQuery, Backbone and Bootstrap. 8 | - it uses [Browserifiy](http://browserify.org/) 9 | - it uses Grunt with **grunt-browserify** and **grunt-contrib-watch** 10 | - generate Mongoose + Express project 11 | - generate some React "bootstrapped" components ("skeleton" component, tabulation) (more to come) 12 | - generate some React "bootstrapped" components linked to Backbone Models or Collections (more to come) 13 | 14 | ##Sub generators list : 15 | 16 | - `yo react-app:mgroutes Human` : generate express routes, mongoose Human Model, Human Controller 17 | - `yo react-app:bbmc Human` generate Backbone a Human Model and Collection.js 18 | - `yo react-app:formbb HumanForm Human` generate a form linked to a Backbone Human Model 19 | - `yo react-app:tablebb HumansTable Human` generate a table linked to a Backbone Human Collection 20 | - `yo react-app:listbb HumansList Human` generate a list linked to a Backbone Human Collection 21 | 22 | 23 | - `yo react-app:tab ApplicationTab` create a "Bootstrap" Tab (and tab panes) inside a container (ie:`div`) 24 | - `yo react-app:shell MyComponent tagName` create a React Component skeleton 25 | 26 | 27 | ##Getting Started 28 | 29 | ###Install 30 | 31 | To install generator-react-app from npm, run: 32 | 33 | ``` 34 | $ npm install -g generator-react-app 35 | ``` 36 | 37 | ###Create an application 38 | 39 | ####1-ignition 40 | 41 | mkdir myapp 42 | cd myapp 43 | yo react-app 44 | 45 | ####2-generate 46 | 47 | _____ _ _____ 48 | | __ |___ ___ ___| |_ ___| _ |___ ___ 49 | | -| -_| .'| _| _|___| | . | . | 50 | |__|__|___|__,|___|_| |__|__| _| _| 51 | |_| |_| 52 | Hi! This is a React-Express-Mongoose Generator :) Enjoy! 53 | [?] Application name? MyApplication 54 | [?] DataBase name? mydatabase 55 | 56 | Type your application name (ie: `MyApplication`), then database name (ie: `mydatabase`) and valid, and wait ... 57 | 58 | ####3-first launch 59 | 60 | - start MongoDb (`mongod`) 61 | - start `grunt watch` 62 | - start Application : `node app.js` (use node monitor it's useful) 63 | - open your webapp : [http://localhost:3000](http://localhost:3000) 64 | 65 | ###Add Express routes, Mongoose Schemas, models and controllers (back side) 66 | 67 | Type `yo react-app:mgroutes Human` (where `Human` is the model name), then describe schema and url (keep default value) 68 | 69 | [?] mongoose schema (ie: name: String, remark: String)? firstName : String, lastName : String 70 | [?] url? humans 71 | 72 | 3 files are created : 73 | 74 | create models/Human.js 75 | create routes/Humans.routes.js 76 | create controllers/HumansCtrl.js 77 | 78 | **Remark**: Each time, `./all.routes.js` file is automatically updated (to load all routes) 79 | 80 | ###Add Backbone Model and Collection 81 | 82 | Type `yo react-app:bbmc Human`, it generates 2 files: 83 | 84 | - `public/modules/models/HumanModel.js` 85 | - `public/modules/models/HumansCollection.js` 86 | 87 | ###You need form and data table 88 | 89 | ####1-create human form 90 | 91 | Type `yo react-app:formbb HumanForm Human` (where `HumanForm` is the React component Name, `Human` the associated model) 92 | 93 | [?] model name (ie: Book) Human 94 | [?] fields (for UI) (ie : title, author)? firstName, lastName 95 | [?] url? humans 96 | 97 | - Fill the Model name (keep default value) 98 | - Fill the fields (same as Mongoose Schema) 99 | - Fill url (keep default value) 100 | 101 | 1 new file is generated : 102 | 103 | create public/js/react_components/HumanForm.js 104 | 105 | ####2-create humans data table 106 | 107 | Type `yo react-app:tablebb HumansTable Human` 108 | 109 | [?] model name (ie: Book) Human 110 | [?] fields (for UI) (ie : title, author)? firstName, lastName 111 | [?] url? humans 112 | 113 | 1 new file is generated : 114 | 115 | create public/js/react_components/HumansTable.js 116 | 117 | ####3-integrate our 2 components 118 | 119 | Open `public/js/modules/main.js` and replace content with this : 120 | 121 | /** @jsx React.DOM */ 122 | var React = require('react'); 123 | var Backbone = require("backbone"); 124 | var About = require('../react_components/About'); 125 | 126 | var HumanForm = require('../react_components/HumanForm'); 127 | var HumansTable = require('../react_components/HumansTable'); 128 | 129 | Backbone.history.start(); 130 | 131 | React.renderComponent( 132 | , 133 | document.querySelector('HumansTable') 134 | ); 135 | 136 | React.renderComponent( 137 | , 138 | document.querySelector('HumanForm') 139 | ); 140 | 141 | Then open `public/index.html` and replace : 142 | 143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 | 152 | by 153 | 154 |
155 |
156 |
157 | 158 |
159 |
160 | 161 |
162 |
163 |
164 | 165 | You can now re-start `node app.js`. That's All! 166 | 167 | ##Other sub generators 168 | 169 | - Tab : `yo react-app:tab ApplicationTab div` create a "Bootstrap" Tab (and tab panes) inside a container (ie:`div`) 170 | - Shell : `yo react-app:shell MyComponent div` create a React Component skeleton 171 | - **more to come** ... WIP 172 | 173 | **Remark**: all components are generated to the `public/js/components` directory. Each time, `public/js/all.scripts.js` file is automatically updated (to load components) 174 | 175 | ###Shell sample : 176 | 177 | /** @jsx React.DOM */ 178 | var MyComponent = React.createClass({ 179 | 180 | getInitialState: function() { 181 | return {content:"..."}; 182 | }, 183 | 184 | componentWillMount: function() {}, 185 | componentDidMount: function() {}, 186 | 187 | render: function() { 188 | return ( 189 |
190 | {this.state.content} 191 |
192 | ); 193 | } 194 | }); 195 | 196 | ####Use MyComponent : 197 | 198 | /*--- javascript side ---*/ 199 | React.renderComponent( 200 | , 201 | document.querySelector('.mycomponent') 202 | ); 203 | 204 | 205 |
206 | 207 | ###Put components inside Tab component 208 | 209 | Add dependencies : 210 | 211 | var HumanForm = require('./HumanForm'); 212 | var HumansTable = require('./HumansTable'); 213 | 214 | This is the `render` method of a Tab component : 215 | 216 | render: function() { 217 | 218 | return ( 219 |
220 | 221 | 226 | 227 |
228 |
229 |
content of HumanForm
230 |
231 |
232 |
content of HumanTable
233 |
234 | 235 |
236 |
237 | ); 238 | } 239 | 240 | If you want to use our Form and Table components inside Tab component, it's simple, you have just to change panes content like that : 241 | 242 |
243 |
244 |
245 | 246 |
247 |
248 |
249 |
250 | 251 |
252 |
253 |
254 | 255 | and replace source code of `main.js` by this : 256 | 257 | /** @jsx React.DOM */ 258 | var React = require('react'); 259 | var Backbone = require("backbone"); 260 | 261 | var BigTab = require('../react_components/BigTab'); 262 | 263 | Backbone.history.start(); 264 | 265 | React.renderComponent( 266 | , 267 | document.querySelector('BigTab') 268 | ); 269 | 270 | and update `index.html` : 271 | 272 | Replace 273 | 274 |
275 |
276 |
277 | 278 |
279 |
280 | 281 |
282 |
283 |
284 | 285 | By 286 | 287 |
288 | 289 |
290 | 291 | That's all 292 | 293 | ##Backbone generators 294 | 295 | - Model and Collection : `yo react-app:bbmc Human` generate `public/modules/models/HumanModel.js` and `public/modules/models/HumansCollection.js` 296 | 297 | 298 | ## License 299 | 300 | [MIT License](http://en.wikipedia.org/wiki/MIT_License) 301 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | var path = require('path'); 4 | var yeoman = require('yeoman-generator'); 5 | 6 | 7 | var ReactAppGenerator = module.exports = function ReactAppGenerator(args, options, config) { 8 | yeoman.generators.Base.apply(this, arguments); 9 | 10 | this.on('end', function () { 11 | //this.installDependencies({ skipInstall: options['skip-install'] }); 12 | this.installDependencies(); 13 | }); 14 | 15 | this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json'))); 16 | }; 17 | 18 | util.inherits(ReactAppGenerator, yeoman.generators.Base); 19 | 20 | ReactAppGenerator.prototype.askFor = function askFor() { 21 | var cb = this.async(); 22 | 23 | // have Yeoman greet the user. 24 | // console.log(this.yeoman); 25 | console.log(" _____ _ _____ "); 26 | console.log("| __ |___ ___ ___| |_ ___| _ |___ ___ "); 27 | console.log("| -| -_| .'| _| _|___| | . | . | "); 28 | console.log("|__|__|___|__,|___|_| |__|__| _| _| "); 29 | console.log(" |_| |_| "); 30 | console.log("Hi! This is a React-Express-Mongoose Generator :) Enjoy!"); 31 | 32 | var prompts = [ 33 | {name : "applicationName", message : "Application name?"}, 34 | {name : "dataBaseName", message : "DataBase name?"} 35 | ]; 36 | 37 | this.prompt(prompts, function (props) { 38 | this.applicationName = props.applicationName; 39 | this.dataBaseName = props.dataBaseName; 40 | 41 | cb(); 42 | }.bind(this)); 43 | }; 44 | 45 | ReactAppGenerator.prototype.app = function app() { 46 | 47 | /*=== front side structure ===*/ 48 | this.mkdir("public"); 49 | this.mkdir("public/js"); 50 | 51 | this.mkdir("public/js/docs"); 52 | 53 | this.mkdir("public/js/modules"); 54 | this.mkdir("public/js/modules/models"); 55 | this.mkdir("public/js/react_components"); 56 | 57 | //this.mkdir("public/js/shims"); 58 | 59 | /*=== "static" assets ===*/ 60 | this.template('index.html', "public/index.html"); 61 | this.template('main.js', "public/js/modules/main.js"); 62 | this.template('About.js', "public/js/react_components/About.js"); 63 | 64 | /*=== back side structure ===*/ 65 | 66 | this.mkdir("db"); 67 | 68 | /*=== "dynamic" assets ===*/ 69 | 70 | this.template("db.js", "db/db.js"); 71 | 72 | this.template('about_my_app.md', "public/js/docs/about_my_app.md"); 73 | this.template('about_how_to.md', "public/js/docs/about_how_to.md"); 74 | 75 | 76 | this.copy("Gruntfile.js", "Gruntfile.js"); 77 | 78 | this.template('_bower.json', "bower.json"); 79 | this.template('bowerrc', ".bowerrc"); 80 | 81 | this.template('_package.json', "package.json"); 82 | this.copy('gitignore', ".gitignore"); 83 | 84 | this.template('README.md', 'README.md'); 85 | 86 | //express part 87 | this.template('app.js', "app.js"); 88 | this.copy('all.routes.js', "all.routes.js"); 89 | 90 | }; 91 | 92 | ReactAppGenerator.prototype.projectfiles = function projectfiles() { 93 | this.copy('editorconfig', '.editorconfig'); 94 | this.copy('jshintrc', '.jshintrc'); 95 | }; 96 | -------------------------------------------------------------------------------- /app/templates/About.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | var React = require('react') 3 | , $ = window.jQuery = require("jquery") 4 | , markdown = require( "markdown" ).markdown; 5 | 6 | var About = React.createClass({ 7 | 8 | componentDidMount: function() { 9 | $.get(this.props.docLocation, function(data) { 10 | this.refs.content.getDOMNode().innerHTML = markdown.toHTML(data) 11 | }.bind(this)); 12 | }, 13 | 14 | render: function() { 15 | return ( 16 |
17 |
18 | ); 19 | } 20 | }); 21 | 22 | module.exports = About 23 | -------------------------------------------------------------------------------- /app/templates/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | grunt.initConfig({ 3 | pkg: grunt.file.readJSON('package.json'), 4 | browserify: { 5 | options:{ 6 | transform: [ require('grunt-react').browserify ] 7 | }, 8 | client: { 9 | src: ['public/js/react_components/**/*.js', 'public/js/modules/main.js'], 10 | dest: 'public/js/app.built.js' 11 | } 12 | }, 13 | watch: { 14 | files: [ "public/js/modules/**/*.js", "public/js/shims/**/*.js", "public/js/react_components/*.js"], 15 | tasks: [ 'browserify' ] 16 | } 17 | }) 18 | grunt.loadNpmTasks('grunt-browserify') 19 | grunt.loadNpmTasks('grunt-contrib-watch') 20 | } 21 | -------------------------------------------------------------------------------- /app/templates/README.md: -------------------------------------------------------------------------------- 1 | #<%= _.capitalize(applicationName) %> 2 | 3 | -------------------------------------------------------------------------------- /app/templates/_bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= _.slugify(applicationName) %>", 3 | "version": "0.0.0", 4 | "dependencies": { 5 | "bootstrap" : "3.1.1" 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /app/templates/_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hello-<%= _.slugify(applicationName) %>", 3 | "description" : "this is a killer app", 4 | "version": "0.0.0", 5 | "repository" : { 6 | "type" : "git", 7 | "url" : "https://github.com/you/yourapp.git" 8 | }, 9 | "license" : "MIT", 10 | "author" : { 11 | "name" : "your name", 12 | "twitter" : "@your_twitter_pseudo", 13 | "url" : "http://www.your.site" 14 | }, 15 | "dependencies": { 16 | "express": "4.1.x", 17 | "body-parser": "1.0.2", 18 | "mongoose": "3.8.x", 19 | "node-uuid" : "1.4.1", 20 | "jquery": "2.1.1", 21 | "underscore":"1.6.0", 22 | "backbone":"1.1.2", 23 | "react":"0.10.0", 24 | "markdown":"0.5.0" 25 | }, 26 | "devDependencies": { 27 | "grunt": "~0.4.2", 28 | "browserify": "~3.28.2", 29 | "grunt-browserify": "~1.3.1", 30 | "grunt-contrib-watch": "~0.5.3", 31 | "grunt-react": "~0.6.0" 32 | } 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/templates/about_how_to.md: -------------------------------------------------------------------------------- 1 | ##How To ... 2 | 3 | -------------------------------------------------------------------------------- /app/templates/about_my_app.md: -------------------------------------------------------------------------------- 1 | ##About <%= _.capitalize(applicationName) %> 2 | -------------------------------------------------------------------------------- /app/templates/all.routes.js: -------------------------------------------------------------------------------- 1 | var AllRoutes = function(app, mongoose) { 2 | //foo 3 | } 4 | module.exports = AllRoutes; -------------------------------------------------------------------------------- /app/templates/app.js: -------------------------------------------------------------------------------- 1 | /*=== Main Application ===*/ 2 | var express = require('express') 3 | , http = require('http') 4 | , bodyParser = require('body-parser') 5 | , app = express() 6 | , http_port = 3000 7 | , args = process.argv.splice(2); 8 | 9 | app.use(express.static(__dirname + '/public')); 10 | 11 | require("./db/db").once('open', function callback () { 12 | /*=== insert routes here ===*/ 13 | require("./all.routes")(app); 14 | }); 15 | 16 | app.listen(args[0] || http_port); 17 | console.log("Listening on " + http_port); 18 | -------------------------------------------------------------------------------- /app/templates/bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "public/js/bower_components" 3 | } -------------------------------------------------------------------------------- /app/templates/db.js: -------------------------------------------------------------------------------- 1 | /*=== DataBase configuration ===*/ 2 | var mongoose = require('mongoose'); 3 | mongoose.connect('mongodb://localhost/<%= dataBaseName %>'); 4 | 5 | var db = mongoose.connection; 6 | db.on('error', console.error.bind(console, 'connection error:')); 7 | 8 | module.exports = db; -------------------------------------------------------------------------------- /app/templates/editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /app/templates/gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log -------------------------------------------------------------------------------- /app/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= _.capitalize(applicationName) %> 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |

<%= applicationName %>

19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/templates/jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 4, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "regexp": true, 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "white": true 21 | } 22 | -------------------------------------------------------------------------------- /app/templates/main.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | var React = require('react'); 3 | var Backbone = require("backbone"); 4 | Backbone.$ = window.$ = require("jquery") 5 | 6 | var About = require('../react_components/About'); 7 | 8 | Backbone.history.start(); 9 | 10 | React.renderComponent( 11 | , 12 | document.querySelector('.about_my_app') 13 | ); 14 | 15 | React.renderComponent( 16 | , 17 | document.querySelector('.about_how_to') 18 | ); 19 | 20 | -------------------------------------------------------------------------------- /bbmc/README.md: -------------------------------------------------------------------------------- 1 | yo react-app:bbmc Human 2 | -------------------------------------------------------------------------------- /bbmc/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | var yeoman = require('yeoman-generator'); 4 | 5 | var BbmcGenerator = module.exports = function BbmcGenerator(args, options, config) { 6 | yeoman.generators.NamedBase.apply(this, arguments); 7 | this.modelName = arguments[0][0]; 8 | 9 | }; 10 | 11 | util.inherits(BbmcGenerator, yeoman.generators.NamedBase); 12 | 13 | BbmcGenerator.prototype.askFor = function askFor() { 14 | var cb = this.async(); 15 | 16 | var prompts = [ 17 | {name : "modelName", message : "model name (ie: Book)", default : this.modelName}, 18 | {name : "defaults", message : "defaults (ie: name: 'John Doe', remark: 'N/A')?"}, 19 | {name : "url", message : "url?", default : this.modelName.toLowerCase()+"s"} 20 | ]; 21 | 22 | this.prompt(prompts, function (props) { 23 | this.modelName = props.modelName; 24 | this.defaults = props.defaults; 25 | 26 | this.url = props.url; 27 | 28 | cb(); 29 | 30 | }.bind(this)); 31 | }; 32 | 33 | 34 | BbmcGenerator.prototype.files = function files() { 35 | this.template('model.js',"public/js/modules/models/"+this.modelName+"Model.js") 36 | this.template('collection.js',"public/js/modules/models/"+this.modelName+"sCollection.js") 37 | }; 38 | -------------------------------------------------------------------------------- /bbmc/templates/collection.js: -------------------------------------------------------------------------------- 1 | var Backbone = require("backbone"); 2 | var <%= modelName %>Model = require("./<%= modelName %>Model"); 3 | 4 | var <%= modelName %>sCollection = Backbone.Collection.extend({ 5 | url : "<%= url %>", 6 | model: <%= modelName %>Model 7 | }); 8 | 9 | module.exports = <%= modelName %>sCollection; 10 | 11 | -------------------------------------------------------------------------------- /bbmc/templates/model.js: -------------------------------------------------------------------------------- 1 | var Backbone = require("backbone"); 2 | 3 | var <%= modelName %>Model = Backbone.Model.extend({ 4 | defaults : function (){ 5 | return { 6 | <%= defaults %> 7 | } 8 | }, 9 | urlRoot : "<%= url %>", 10 | idAttribute: "_id" 11 | }); 12 | 13 | module.exports = <%= modelName %>Model; -------------------------------------------------------------------------------- /formbb/README.md: -------------------------------------------------------------------------------- 1 | yo react-app:formbb HumanForm Human 2 | -------------------------------------------------------------------------------- /formbb/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | var yeoman = require('yeoman-generator'); 4 | 5 | var FormbbGenerator = module.exports = function FormbbGenerator(args, options, config) { 6 | yeoman.generators.NamedBase.apply(this, arguments); 7 | this.componentName = arguments[0][0]; 8 | //this.tagName = arguments[0][1]; 9 | this.modelName = arguments[0][1]; 10 | 11 | //this.on('end', function () { }); 12 | }; 13 | 14 | util.inherits(FormbbGenerator, yeoman.generators.NamedBase); 15 | 16 | FormbbGenerator.prototype.askFor = function askFor() { 17 | var cb = this.async(); 18 | 19 | var prompts = [ 20 | {name : "modelName", message : "model name (ie: Book)", default : this.modelName}, 21 | {name : "fields", message : "fields (for UI) (ie : title, author)?"}, 22 | {name : "url", message : "url?", default : this.modelName.toLowerCase()+"s"} 23 | ]; 24 | 25 | this.routes = []; 26 | 27 | this.prompt(prompts, function (props) { 28 | this.modelName = props.modelName; 29 | this.url = props.url; 30 | this.fields = []; 31 | props.fields.split(",").forEach(function(item) { 32 | this.fields.push(item.trim()); 33 | }.bind(this)) 34 | 35 | cb(); 36 | 37 | }.bind(this)); 38 | }; 39 | 40 | 41 | FormbbGenerator.prototype.files = function files() { 42 | this.template('form.js',"public/js/react_components/"+this.componentName+".js") 43 | 44 | }; 45 | -------------------------------------------------------------------------------- /formbb/templates/form.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 3 | /* 4 | var <%= componentName %> = require('../react_components/<%= componentName %>'); 5 | React.renderComponent( 6 | <<%= componentName %>/>, 7 | document.querySelector('<%= componentName %>') 8 | ); 9 | */ 10 | 11 | var React = require('react') 12 | , <%= modelName %>Model = require("../modules/models/<%= modelName %>Model"); 13 | 14 | var <%= componentName %> = React.createClass({ 15 | 16 | getInitialState: function() { 17 | return {data : [], message : ""}; 18 | }, 19 | 20 | render: function() { 21 | return ( 22 |
23 | <% _.each(fields, function(field) { %>
24 | 25 |
26 | <% }); %> 27 |
28 | 29 |
30 |
{this.state.message}
31 |
32 | ); 33 | }, 34 | 35 | componentDidMount: function() {}, 36 | componentWillMount: function() {}, 37 | handleSubmit : function() { 38 | <% _.each(fields, function(field) { %>var <%= field %> = this.refs.<%= field %>.getDOMNode().value.trim(); 39 | <% }); %> 40 | <% _.each(fields, function(field) { %>if (!<%= field %>) {return false;} 41 | <% }); %> 42 | var data = {}; 43 | <% _.each(fields, function(field) { %>data.<%= field %> = <%= field %>; 44 | <% }); %> 45 | 46 | var <%= _.slugify(modelName) %>= new <%= modelName %>Model(data); 47 | 48 | <%= _.slugify(modelName) %>.save() 49 | .done(function(data) { 50 | this.setState({ 51 | message : <%= _.slugify(modelName) %>.get("_id") + " added!" 52 | }); 53 | <% _.each(fields, function(field) { %>this.refs.<%= field %>.getDOMNode().value = ''; 54 | <% }); %> 55 | this.refs.<%= fields[0] %>.getDOMNode().focus(); 56 | }.bind(this)) 57 | .fail(function(err) { 58 | this.setState({ 59 | message : err.responseText + " " + err.statusText 60 | }); 61 | }.bind(this)); 62 | 63 | return false; 64 | } 65 | 66 | }); 67 | 68 | module.exports = <%= componentName %>; 69 | -------------------------------------------------------------------------------- /listbb/README.md: -------------------------------------------------------------------------------- 1 | yo react-app:listbb HumansList Human 2 | -------------------------------------------------------------------------------- /listbb/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | var yeoman = require('yeoman-generator'); 4 | 5 | var ListbbGenerator = module.exports = function ListbbGenerator(args, options, config) { 6 | yeoman.generators.NamedBase.apply(this, arguments); 7 | this.componentName = arguments[0][0]; 8 | //this.tagName = arguments[0][1]; 9 | this.modelName = arguments[0][1]; 10 | 11 | //this.on('end', function () { }); 12 | }; 13 | 14 | util.inherits(ListbbGenerator, yeoman.generators.NamedBase); 15 | 16 | ListbbGenerator.prototype.askFor = function askFor() { 17 | var cb = this.async(); 18 | 19 | var prompts = [ 20 | {name : "modelName", message : "model name (ie: Book)", default : this.modelName}, 21 | {name : "fields", message : "fields (for UI) (ie : title, author)?"}, 22 | {name : "url", message : "url?", default : this.modelName.toLowerCase()+"s"} 23 | ]; 24 | 25 | this.routes = []; 26 | 27 | this.prompt(prompts, function (props) { 28 | this.modelName = props.modelName; 29 | this.url = props.url; 30 | this.fields = [] 31 | props.fields.split(",").forEach(function(item) { 32 | this.fields.push(item.trim()); 33 | }.bind(this)) 34 | 35 | this.properties = []; 36 | 37 | this.fields.forEach(function(field){ 38 | this.properties.push(field+" : "+ '""'); 39 | }.bind(this)); 40 | 41 | this.properties = this.properties.join(","); 42 | 43 | cb(); 44 | 45 | }.bind(this)); 46 | }; 47 | 48 | 49 | 50 | ListbbGenerator.prototype.files = function files() { 51 | this.template('list.js',"public/js/react_components/"+this.componentName+".js") 52 | }; 53 | -------------------------------------------------------------------------------- /listbb/templates/list.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 3 | /* 4 | var <%= componentName %> = require('../react_components/<%= componentName %>'); 5 | React.renderComponent( 6 | <<%= componentName %> pollInterval={500}/>, 7 | document.querySelector('<%= componentName %>') 8 | ); 9 | */ 10 | 11 | var React = require('react') 12 | , Backbone = require("backbone") 13 | , <%= modelName %>Model = require("../modules/models/<%= modelName %>Model") 14 | , <%= modelName %>sCollection = require("../modules/models/<%= modelName %>sCollection"); 15 | 16 | var <%= componentName %> = React.createClass({ 17 | 18 | getInitialState: function() { 19 | return {data : [], message : ""}; 20 | }, 21 | 22 | render: function() { 23 | 24 | var <%= _.slugify(modelName) %>sNodes = this.state.data.map(function(<%= _.slugify(modelName) %>){ 25 | var deleteLink = "#delete_<%= _.slugify(modelName) %>/" + <%= _.slugify(modelName) %>._id; 26 | 27 | return ( 28 |
  • 29 | <% _.each(fields, function(field) { %>{<%= _.slugify(modelName) %>.<%= field %>}{" "} 30 | <% }); %>delete 31 |
  • 32 | 33 | ); 34 | }); 35 | 36 | return ( 37 |
    38 | {this.state.message} 39 |
      40 | {<%= _.slugify(modelName) %>sNodes} 41 |
    42 |
    43 | ); 44 | }, 45 | 46 | get<%= modelName %>s : function() { 47 | 48 | var <%= _.slugify(modelName) %>s = new <%= modelName %>sCollection(); 49 | 50 | <%= _.slugify(modelName) %>s.fetch() 51 | .done(function(data){ 52 | this.setState({data : <%= _.slugify(modelName) %>s.toJSON(), message : Date()}); 53 | }.bind(this)) 54 | .fail(function(err){ 55 | this.setState({ 56 | message : err.responseText + " " + err.statusText 57 | }); 58 | }.bind(this)) 59 | }, 60 | componentWillMount: function() { 61 | this.get<%= modelName %>s(); 62 | setInterval(this.get<%= modelName %>s, this.props.pollInterval); 63 | }, 64 | componentDidMount: function() { 65 | var Router = Backbone.Router.extend({ 66 | routes : { 67 | "delete_<%= _.slugify(modelName) %>/:id" : "<%= _.slugify(modelName) %>" 68 | }, 69 | initialize : function() { 70 | console.log("Initialize router of <%= componentName %> component"); 71 | }, 72 | <%= _.slugify(modelName) %> : function(id){ 73 | console.log("=== delete <%= _.slugify(modelName) %> ===", id); 74 | new <%= modelName %>Model({_id:id}).destroy(); 75 | this.navigate('/'); 76 | } 77 | }); 78 | this.router = new Router() 79 | } 80 | 81 | }); 82 | 83 | module.exports = <%= componentName %>; 84 | 85 | -------------------------------------------------------------------------------- /mgroutes/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | 4 | var yeoman = require('yeoman-generator'); 5 | 6 | var MgroutesGenerator = module.exports = function MgroutesGenerator(args, options, config) { 7 | yeoman.generators.NamedBase.apply(this, arguments); 8 | 9 | this.on('end', function () { 10 | 11 | var fs = require('fs'); 12 | // read all routes files for update all.routes.js 13 | var files = fs.readdirSync('./routes'); 14 | var routes = []; 15 | files.filter(function(file) { return file.substr(-10) == '.routes.js'; }) 16 | .forEach(function(file) { 17 | if (file!=="all.routes.js"){ 18 | routes.push('require("./routes/'+file.split(".js")[0]+'")(app);') 19 | } 20 | }); 21 | 22 | var stream = fs.createWriteStream("all.routes.js"); 23 | stream.once('open', function(fd) { 24 | stream.write("var AllRoutes = function(app) {\n"); 25 | routes.forEach(function(line){ 26 | stream.write(" "+line+"\n"); 27 | }); 28 | stream.write("}\n"); 29 | stream.write("module.exports = AllRoutes;\n"); 30 | stream.end(); 31 | }); 32 | 33 | console.log("Routes updated ...") 34 | 35 | }); 36 | 37 | }; 38 | 39 | util.inherits(MgroutesGenerator, yeoman.generators.NamedBase); 40 | 41 | MgroutesGenerator.prototype.askFor = function askFor() { 42 | var cb = this.async(); 43 | 44 | var prompts = [ 45 | {name : "schema", message : "mongoose schema (ie: name: String, remark: String)?"}, 46 | {name : "url", message : "url?", default : this.name.toLowerCase()+"s"} 47 | 48 | ]; 49 | 50 | this.routes = []; 51 | 52 | this.prompt(prompts, function (props) { 53 | this.schema = props.schema; 54 | this.url = props.url; 55 | cb(); 56 | }.bind(this)); 57 | }; 58 | 59 | MgroutesGenerator.prototype.files = function files() { 60 | this.mkdir("models"); 61 | this.mkdir("routes"); 62 | this.mkdir("controllers"); 63 | this.template("model.js", "models/"+this.name+".js") 64 | this.template('routes.js', "routes/"+this.name+"s.routes.js"); 65 | this.template('controller.js', "controllers/"+this.name+"sCtrl.js"); 66 | }; 67 | -------------------------------------------------------------------------------- /mgroutes/templates/controller.js: -------------------------------------------------------------------------------- 1 | /*=== <%= name %> Controller ===*/ 2 | 3 | var <%= name %> = require("../models/<%= name %>")(); 4 | 5 | var <%= name %>sCtrl = { 6 | create : function(req, res) { 7 | var <%= _.slugify(name) %> = new <%= name %>(req.body) 8 | <%= _.slugify(name) %>.save(function (err, <%= _.slugify(name) %>) { 9 | res.send(<%= _.slugify(name) %>); 10 | }); 11 | }, 12 | fetchAll : function(req, res) { 13 | <%= name %>.find(function (err, <%= _.slugify(name) %>s) { 14 | res.send(<%= _.slugify(name) %>s); 15 | }); 16 | }, 17 | fetch : function(req, res) { 18 | <%= name %>.find({_id:req.params.id}, function (err, <%= _.slugify(name) %>s) { 19 | res.send(<%= _.slugify(name) %>s[0]); 20 | }); 21 | }, 22 | update : function(req, res) { 23 | delete req.body._id 24 | <%= name %>.update({_id:req.params.id}, req.body, function (err, <%= _.slugify(name) %>) { 25 | res.send(<%= _.slugify(name) %>); 26 | }); 27 | }, 28 | delete : function(req, res) { 29 | <%= name %>.findOneAndRemove({_id:req.params.id}, function (err, <%= _.slugify(name) %>) { 30 | res.send(<%= _.slugify(name) %>); 31 | }); 32 | } 33 | } 34 | 35 | module.exports = <%= name %>sCtrl; 36 | -------------------------------------------------------------------------------- /mgroutes/templates/model.js: -------------------------------------------------------------------------------- 1 | /*=== <%= name %> Model ===*/ 2 | 3 | var mongoose = require('mongoose'); 4 | 5 | var <%= name %>Model = function() { 6 | 7 | var <%= name %>Schema = mongoose.Schema({ 8 | <%= schema %> 9 | }); 10 | 11 | return mongoose.model('<%= name %>', <%= name %>Schema); 12 | } 13 | 14 | module.exports = <%= name %>Model; 15 | -------------------------------------------------------------------------------- /mgroutes/templates/routes.js: -------------------------------------------------------------------------------- 1 | /*=== <%= name %> CRUD Routes ===*/ 2 | var <%= name %>sCtrl = require("../controllers/<%= name %>sCtrl"); 3 | 4 | var <%= name %>sRoutes = function(app) { 5 | 6 | app.post("/<%= url %>", function(req, res) { 7 | <%= name %>sCtrl.create(req, res); 8 | }); 9 | 10 | app.get("/<%= url %>", function(req, res) { 11 | <%= name %>sCtrl.fetchAll(req, res); 12 | }); 13 | 14 | app.get("/<%= url %>/:id", function(req, res) { //try findById 15 | <%= name %>sCtrl.fetch(req, res); 16 | }); 17 | 18 | app.put("/<%= url %>/:id", function(req, res) { 19 | <%= name %>sCtrl.update(req, res); 20 | }); 21 | 22 | app.delete("/<%= url %>/:id", function(req, res) { 23 | <%= name %>sCtrl.delete(req, res); 24 | }); 25 | 26 | } 27 | 28 | module.exports = <%= name %>sRoutes; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-react-app", 3 | "version": "0.1.9", 4 | "description": "A generator for Yeoman with React, jQuery, Backbone, Bootstrap, Browserify, Express and Mongoose", 5 | "keywords": [ 6 | "yeoman-generator", "react", "bootstrap", "mongoose", "express", "jquery", "backbone", "browserify" 7 | ], 8 | "homepage": "https://github.com/k33g/generator-react-app", 9 | "bugs": "https://github.com/k33g/generator-react-app/issues", 10 | "author": { 11 | "name": "@k33g_org", 12 | "email": "ph.charriere@gmail.com", 13 | "url": "https://github.com/k33g" 14 | }, 15 | "main": "app/index.js", 16 | "repository": { 17 | "type": "git", 18 | "url": "git://github.com/k33g/generator-react-app.git" 19 | }, 20 | "scripts": { 21 | "test": "mocha" 22 | }, 23 | "dependencies": { 24 | "yeoman-generator": "~0.14.0" 25 | }, 26 | "devDependencies": { 27 | "mocha": "~1.14.0" 28 | }, 29 | "peerDependencies": { 30 | "yo": ">=1.0.0" 31 | }, 32 | "engines": { 33 | "node": ">=0.8.0", 34 | "npm": ">=1.2.10" 35 | }, 36 | "licenses": [ 37 | { 38 | "type": "MIT" 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /shell/README.md: -------------------------------------------------------------------------------- 1 | yo react-app:shell MyComponent div 2 | -------------------------------------------------------------------------------- /shell/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | var yeoman = require('yeoman-generator'); 4 | 5 | var ShellGenerator = module.exports = function ShellGenerator(args, options, config) { 6 | yeoman.generators.NamedBase.apply(this, arguments); 7 | this.componentName = arguments[0][0]; 8 | this.tagName = arguments[0][1]; 9 | 10 | }; 11 | 12 | util.inherits(ShellGenerator, yeoman.generators.NamedBase); 13 | 14 | ShellGenerator.prototype.files = function files() { 15 | this.template('shell.js',"public/js/react_components/"+this.componentName+".js") 16 | }; 17 | -------------------------------------------------------------------------------- /shell/templates/shell.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 3 | /* 4 | var <%= componentName %> = require('../react_components/<%= componentName %>'); 5 | React.renderComponent( 6 | <<%= componentName %>/>, 7 | document.querySelector('<%= componentName %>') 8 | ); 9 | */ 10 | 11 | var React = require('react') 12 | 13 | var <%= componentName %> = React.createClass({ 14 | 15 | getInitialState: function() { 16 | return {content:"..."}; 17 | }, 18 | 19 | render: function() { 20 | return ( 21 | <<%= tagName %>> 22 | {this.state.content} 23 | > 24 | ); 25 | }, 26 | componentWillMount: function() {}, 27 | componentDidMount: function() {} 28 | 29 | }); 30 | 31 | module.exports = <%= componentName %>; 32 | -------------------------------------------------------------------------------- /tab/README.md: -------------------------------------------------------------------------------- 1 | yo react-app:tab BigTab 2 | -------------------------------------------------------------------------------- /tab/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | var yeoman = require('yeoman-generator'); 4 | 5 | var TableGenerator = module.exports = function TableGenerator(args, options, config) { 6 | yeoman.generators.NamedBase.apply(this, arguments); 7 | this.componentName = arguments[0][0]; 8 | //this.tagName = arguments[0][1]; 9 | 10 | }; 11 | 12 | util.inherits(TableGenerator, yeoman.generators.NamedBase); 13 | 14 | TableGenerator.prototype.askFor = function askFor() { 15 | var cb = this.async(); 16 | 17 | var prompts = [ 18 | {name : "tabLabels", message : "tab labels (for UI) (home, news, ...)?"} 19 | ]; 20 | 21 | this.routes = []; 22 | 23 | this.prompt(prompts, function (props) { 24 | this.tabLabels = [] 25 | props.tabLabels.split(",").forEach(function(label) { 26 | this.tabLabels.push(label.trim()); 27 | }.bind(this)) 28 | 29 | cb(); 30 | 31 | }.bind(this)); 32 | }; 33 | 34 | TableGenerator.prototype.files = function files() { 35 | this.template('tab.js',"public/js/react_components/"+this.componentName+".js") 36 | }; 37 | -------------------------------------------------------------------------------- /tab/templates/tab.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 3 | /* 4 | var <%= componentName %> = require('../react_components/<%= componentName %>'); 5 | React.renderComponent( 6 | <<%= componentName %> id={"42"}/>, 7 | document.querySelector('<%= componentName %>') 8 | ); 9 | */ 10 | var React = require('react') 11 | , $ = window.jQuery = require("jquery") 12 | , bootstrap = require("../bower_components/bootstrap/dist/js/bootstrap.min"); 13 | 14 | 15 | var <%= componentName %> = React.createClass({ 16 | 17 | getInitialState: function() {}, 18 | 19 | render: function() { 20 | 21 | return ( 22 |
    23 |
      24 | <% _.each(tabLabels, function(label) { %>
    • <%= label %>
    • 25 | <% }); %> 26 |
    27 | 28 |
    29 | <% _.each(tabLabels, function(label) { %>
    30 |
    content of <%= label %>
    31 |
    32 | <% }); %> 33 |
    34 |
    35 | ); 36 | }, 37 | componentDidMount: function() { 38 | $('#'+this.props.id+' ul a').click(function (e) { 39 | e.preventDefault() 40 | $(this).tab('show') 41 | }) 42 | $('#'+this.props.id+' ul a:first').tab('show') 43 | }, 44 | componentWillMount: function() {} 45 | }); 46 | 47 | module.exports = <%= componentName %>; 48 | -------------------------------------------------------------------------------- /tablebb/README.md: -------------------------------------------------------------------------------- 1 | yo react-app:tablebb HumansTable Human 2 | -------------------------------------------------------------------------------- /tablebb/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | var yeoman = require('yeoman-generator'); 4 | 5 | var TablebbGenerator = module.exports = function TablebbGenerator(args, options, config) { 6 | yeoman.generators.NamedBase.apply(this, arguments); 7 | this.componentName = arguments[0][0]; 8 | //this.tagName = arguments[0][1]; 9 | this.modelName = arguments[0][1]; 10 | 11 | //this.on('end', function () { }); 12 | }; 13 | 14 | util.inherits(TablebbGenerator, yeoman.generators.NamedBase); 15 | 16 | TablebbGenerator.prototype.askFor = function askFor() { 17 | var cb = this.async(); 18 | 19 | var prompts = [ 20 | {name : "modelName", message : "model name (ie: Book)", default : this.modelName}, 21 | {name : "fields", message : "fields (for UI) (ie : title, author)?"}, 22 | {name : "url", message : "url?", default : this.modelName.toLowerCase()+"s"} 23 | ]; 24 | 25 | 26 | this.routes = []; 27 | 28 | this.prompt(prompts, function (props) { 29 | this.modelName = props.modelName; 30 | this.url = props.url; 31 | this.fields = [] 32 | props.fields.split(",").forEach(function(item) { 33 | this.fields.push(item.trim()); 34 | }.bind(this)) 35 | 36 | this.properties = []; 37 | 38 | this.fields.forEach(function(field){ 39 | this.properties.push(field+" : "+ '""'); 40 | }.bind(this)); 41 | 42 | this.properties = this.properties.join(","); 43 | 44 | 45 | cb(); 46 | 47 | }.bind(this)); 48 | }; 49 | 50 | TablebbGenerator.prototype.files = function files() { 51 | this.template('table.js',"public/js/react_components/"+this.componentName+".js") 52 | }; 53 | -------------------------------------------------------------------------------- /tablebb/templates/table.js: -------------------------------------------------------------------------------- 1 | /** @jsx React.DOM */ 2 | 3 | /* 4 | var <%= componentName %> = require('../react_components/<%= componentName %>'); 5 | React.renderComponent( 6 | <<%= componentName %> pollInterval={500}/>, 7 | document.querySelector('<%= componentName %>') 8 | ); 9 | */ 10 | 11 | var React = require('react') 12 | , Backbone = require("backbone") 13 | , <%= modelName %>Model = require("../modules/models/<%= modelName %>Model") 14 | , <%= modelName %>sCollection = require("../modules/models/<%= modelName %>sCollection"); 15 | 16 | var <%= componentName %> = React.createClass({ 17 | 18 | getInitialState: function() { 19 | return {data : [], message : ""}; 20 | }, 21 | 22 | render: function() { 23 | 24 | var <%= _.slugify(modelName) %>sRows = this.state.data.map(function(<%= _.slugify(modelName) %>){ 25 | var deleteLink = "#delete_<%= _.slugify(modelName) %>/" + <%= _.slugify(modelName) %>._id; 26 | 27 | return ( 28 | 29 | <% _.each(fields, function(field) { %>{<%= _.slugify(modelName) %>.<%= field %>} 30 | <% }); %> 31 | delete{" "}{<%= _.slugify(modelName) %>._id} 32 | 33 | ); 34 | }); 35 | 36 | return ( 37 |
    38 | {this.state.message} 39 | 40 | 41 | 42 | <% _.each(fields, function(field) { %><% }); %> 43 | 44 | 45 | 46 | 47 | {<%= _.slugify(modelName) %>sRows} 48 | 49 |
    <%= field %>_id
    50 |
    51 | ); 52 | }, 53 | 54 | get<%= modelName %>s : function() { 55 | 56 | var <%= _.slugify(modelName) %>s = new <%= modelName %>sCollection(); 57 | 58 | <%= _.slugify(modelName) %>s.fetch() 59 | .done(function(data){ 60 | this.setState({data : <%= _.slugify(modelName) %>s.toJSON(), message : Date()}); 61 | }.bind(this)) 62 | .fail(function(err){ 63 | this.setState({ 64 | message : err.responseText + " " + err.statusText 65 | }); 66 | }.bind(this)) 67 | }, 68 | 69 | componentWillMount: function() { 70 | this.get<%= modelName %>s(); 71 | setInterval(this.get<%= modelName %>s, this.props.pollInterval); 72 | }, 73 | 74 | componentDidMount: function() { 75 | var Router = Backbone.Router.extend({ 76 | routes : { 77 | "delete_<%= _.slugify(modelName) %>/:id" : "delete<%= modelName %>" 78 | }, 79 | initialize : function() { 80 | console.log("Initialize router of <%= componentName %> component"); 81 | }, 82 | delete<%= modelName %> : function(id){ 83 | console.log("=== delete <%= _.slugify(modelName) %> ===", id); 84 | new <%= modelName %>Model({_id:id}).destroy(); 85 | this.navigate('/'); 86 | } 87 | }); 88 | this.router = new Router() 89 | } 90 | 91 | }); 92 | 93 | module.exports = <%= componentName %>; 94 | -------------------------------------------------------------------------------- /test/test-creation.js: -------------------------------------------------------------------------------- 1 | /*global describe, beforeEach, it*/ 2 | 'use strict'; 3 | 4 | var path = require('path'); 5 | var helpers = require('yeoman-generator').test; 6 | 7 | 8 | describe('react-app generator', function () { 9 | beforeEach(function (done) { 10 | helpers.testDirectory(path.join(__dirname, 'temp'), function (err) { 11 | if (err) { 12 | return done(err); 13 | } 14 | 15 | this.app = helpers.createGenerator('react-app:app', [ 16 | '../../app' 17 | ]); 18 | done(); 19 | }.bind(this)); 20 | }); 21 | 22 | it('creates expected files', function (done) { 23 | var expected = [ 24 | // add files you expect to exist here. 25 | '.jshintrc', 26 | '.editorconfig' 27 | ]; 28 | 29 | helpers.mockPrompt(this.app, { 30 | 'someOption': true 31 | }); 32 | this.app.options['skip-install'] = true; 33 | this.app.run({}, function () { 34 | helpers.assertFiles(expected); 35 | done(); 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /test/test-load.js: -------------------------------------------------------------------------------- 1 | /*global describe, beforeEach, it*/ 2 | 'use strict'; 3 | 4 | var assert = require('assert'); 5 | 6 | describe('react-app generator', function () { 7 | it('can be imported without blowing up', function () { 8 | var app = require('../app'); 9 | assert(app !== undefined); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /tools.js: -------------------------------------------------------------------------------- 1 | 2 | var tools ={ 3 | scriptsList : function() { 4 | 5 | var fs = require('fs'); 6 | // read all components files 7 | var files = fs.readdirSync('./public/js/models'); 8 | console.log(files); 9 | var components = []; 10 | files.forEach(function(file) { 11 | components.push(" 'js/models/"+file+"'\n") 12 | }); 13 | 14 | files = fs.readdirSync('./public/js/components'); 15 | 16 | files.forEach(function(file) { 17 | components.push(" 'js/components/"+file+"'\n") 18 | }); 19 | 20 | var stream = fs.createWriteStream("./public/js/all.scripts.js"); 21 | stream.once('open', function(fd) { 22 | stream.write("function getBBComponents(){ return [\n"); 23 | stream.write(components.join(",")); 24 | stream.write("];};\n"); 25 | 26 | stream.write('\n') 27 | stream.write('getBBComponents().forEach(function(s){\n') 28 | stream.write(' var script = document.createElement("script");\n') 29 | stream.write(' script.src = s;\n') 30 | stream.write(' script.type = "text/jsx";\n') 31 | stream.write(' document.querySelector("head").appendChild(script);\n') 32 | stream.write('})\n') 33 | stream.write('\n') 34 | 35 | stream.end(); 36 | }); 37 | 38 | console.log("scripts list updated ...") 39 | } 40 | } 41 | 42 | module.exports = tools; 43 | 44 | 45 | 46 | 47 | 48 | --------------------------------------------------------------------------------