From 1a3efd65a22ea9101aa6e224feed7a358bb09345 Mon Sep 17 00:00:00 2001 From: katowulf Date: Thu, 14 Aug 2014 18:27:30 -0700 Subject: [PATCH] Initial build structure and config are functional. Still to complete: login page, account page, chat example, and test units --- .gitignore | 1 + angularfire-config.json | 16 ++ app/index.js | 151 +++++++++++- common/index.js | 1 + package.json | 13 +- route/index.js | 13 +- templates/common/app/index.html | 22 +- .../common/app/scripts/angularfire/config.js | 8 + .../app/scripts/angularfire/firebase.utils.js | 87 +++++++ .../app/scripts/angularfire/simpleLogin.js | 227 ++++++++++++++++++ .../app/scripts/directives/ngHideAuth.js | 35 +++ .../app/scripts/directives/ngShowAuth.js | 34 +++ templates/common/app/views/chat.html | 5 + templates/common/app/views/login.html | 24 ++ templates/common/root/.jshintrc | 5 +- templates/common/root/_bower.json | 8 +- templates/javascript/app.js | 13 +- templates/javascript/controllers/chat.js | 15 ++ templates/javascript/controllers/login.js | 20 ++ templates/javascript/routes.with.login.js | 110 +++++++++ templates/javascript/routes.without.login.js | 22 ++ util/colors.js | 46 ++++ 22 files changed, 838 insertions(+), 38 deletions(-) create mode 100644 angularfire-config.json create mode 100644 templates/common/app/scripts/angularfire/config.js create mode 100644 templates/common/app/scripts/angularfire/firebase.utils.js create mode 100644 templates/common/app/scripts/angularfire/simpleLogin.js create mode 100644 templates/common/app/scripts/directives/ngHideAuth.js create mode 100644 templates/common/app/scripts/directives/ngShowAuth.js create mode 100644 templates/common/app/views/chat.html create mode 100644 templates/common/app/views/login.html create mode 100644 templates/javascript/controllers/chat.js create mode 100644 templates/javascript/controllers/login.js create mode 100644 templates/javascript/routes.with.login.js create mode 100644 templates/javascript/routes.without.login.js create mode 100644 util/colors.js diff --git a/.gitignore b/.gitignore index 547373185..0ff4ce9c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .DS_Store node_modules test/tmp +.idea diff --git a/angularfire-config.json b/angularfire-config.json new file mode 100644 index 000000000..511c790d3 --- /dev/null +++ b/angularfire-config.json @@ -0,0 +1,16 @@ +{ + "bower": { + "firebase": "1.0.x", + "angularfire": "0.8.x", + "mockfirebase": "0.3.x", + "simplelogin": "1.6.x" + }, + + "simpleLoginProviders": [ + { "name": "Email/Password", "value": "password", "checked": true }, + { "name": "Anonymous", "value": "anonymous" }, + { "name": "Facebook", "value": "facebook" }, + { "name": "Google", "value": "google" }, + { "name": "Twitter", "value": "twitter" } + ] +} \ No newline at end of file diff --git a/app/index.js b/app/index.js index 1920e7559..4e4e7a98d 100644 --- a/app/index.js +++ b/app/index.js @@ -8,12 +8,51 @@ var yosay = require('yosay'); var wiredep = require('wiredep'); var chalk = require('chalk'); +//angularfire +var afconfig = require('../angularfire-config.json'); +var colors = require('../util/colors.js'); +var FIREBASE_PROMPTS = [ + { + name: 'firebaseName', + message: colors('Name of your Firebase instance ' + + '(https//%yellow%/yellow.firebaseio.com)'), + required: true, + validate: function (input) { + if (!input || !input.match(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/)) { + return chalk.red('Your Firebase name may only contain [a-z], [0-9], and hyphen (-). ' + + 'It may not start or end with a hyphen.'); + } + return true; + } + }, { + name: 'loginModule', + message: 'Would you like to use FirebaseSimpleLogin for authentication?', + type: 'confirm' + }, { + type: 'checkbox', + name: 'simpleLoginProviders', + message: 'Which providers shall I install?', + choices: afconfig.simpleLoginProviders, + when: function(answers) { + return answers.loginModule; + }, + validate: function(picks) { + return picks.length > 0? true : 'Must pick at least one provider'; + }, + default: ['password'] + } +]; + var Generator = module.exports = function Generator(args, options) { yeoman.generators.Base.apply(this, arguments); this.argument('appname', { type: String, required: false }); this.appname = this.appname || path.basename(process.cwd()); this.appname = this._.camelize(this._.slugify(this._.humanize(this.appname))); + //angularfire + this.afconfig = afconfig; + this.angularFireSourceFiles = []; + this.option('app-suffix', { desc: 'Allow a custom suffix to be added to the module name', type: String, @@ -57,15 +96,15 @@ var Generator = module.exports = function Generator(args, options) { this.env.options.coffee = this.options.coffee; } - this.hookFor('angular:common', { + this.hookFor('angularfire:common', { args: args }); - this.hookFor('angular:main', { + this.hookFor('angularfire:main', { args: args }); - this.hookFor('angular:controller', { + this.hookFor('angularfire:controller', { args: args }); @@ -96,9 +135,17 @@ var Generator = module.exports = function Generator(args, options) { enabledComponents.push('angular-touch/angular-touch.js'); } + //angularfire + if (this.loginModule) { + enabledComponents.push('firebase-simple-login/firebase-simple-login.js'); + } + enabledComponents = [ 'angular/angular.js', - 'angular-mocks/angular-mocks.js' + 'angular-mocks/angular-mocks.js', + //angularfire + 'firebase/firebase.js', + 'angularfire/dist/angularfire.js' ].concat(enabledComponents).join(','); var jsExt = this.options.coffee ? 'coffee' : 'js'; @@ -126,10 +173,28 @@ var Generator = module.exports = function Generator(args, options) { }); if (this.env.options.ngRoute) { - this.invoke('angular:route', { - args: ['about'] + this.invoke('angularfire:route', { + //angularfire + args: ['chat'] }); } + + //angularfire + if(this.env.options.loginModule) { + if( this.env.options.ngRoute ) { + this.invoke('angularfire:route', { + args: ['login', true] + }); + } + else { + this.invoke('angularfire:controller', { + args: ['login', true] + }); + this.invoke('angularfire.view', { + args: ['login', true] + }); + } + } }); this.pkg = require('../package.json'); @@ -158,9 +223,26 @@ Generator.prototype.welcome = function welcome() { } }; +//angularfire +Generator.prototype.askFirebaseQuestions = function askForCompass() { + this.firebaseName = null; + this.loginModule = false; + this.simpleLoginProviders = []; + + var cb = this.async(); + this.prompt(FIREBASE_PROMPTS, function (props) { + FIREBASE_PROMPTS.forEach(function(prompt) { + this[prompt.name] = props[prompt.name]; + }, this); + cb(); + }.bind(this)); +}; + Generator.prototype.askForCompass = function askForCompass() { var cb = this.async(); + console.log('stuff', this.firebaseName, this.loginModule, this.simpleLoginProviders); + this.prompt([{ type: 'confirm', name: 'compass', @@ -270,6 +352,14 @@ Generator.prototype.askForModules = function askForModules() { angMods.push("'ngTouch'"); } + //angularfire + angMods.push("'firebase'"); + angMods.push("'firebase.utils'"); + if( this.loginModule ) { + this.env.options.simpleLogin = true; + angMods.push("'simpleLogin'"); + } + if (angMods.length) { this.env.options.angularDeps = '\n ' + angMods.join(',\n ') + '\n '; } @@ -291,12 +381,32 @@ Generator.prototype.bootstrapFiles = function bootstrapFiles() { ); }; +//todo make this its own subgenerator separate from Angular.js gen +//angularfire +Generator.prototype.copyAngularFireFiles = function() { + this._common('scripts/angularfire/config.js'); + this._common('scripts/angularfire/firebase.utils.js'); + + if( this.loginModule ) { + this._common('scripts/angularfire/simpleLogin.js'); + this._tpl('controllers/login'); + this._htmlTpl('views/login.html'); + } + + if( this.routeModule ) { + var withOrWithout = this.loginModule? 'with' : 'without'; + this._tpl('routes.' + withOrWithout + '.login', 'routes'); + } +}; + Generator.prototype.appJs = function appJs() { this.indexFile = this.appendFiles({ html: this.indexFile, fileType: 'js', optimizedPath: 'scripts/scripts.js', - sourceFileList: ['scripts/app.js', 'scripts/controllers/main.js'], + sourceFileList: ['scripts/app.js', 'scripts/controllers/main.js'] + //angularfire + .concat(this.angularFireSourceFiles), searchPath: ['.tmp', this.appPath] }); }; @@ -338,3 +448,30 @@ Generator.prototype._injectDependencies = function _injectDependencies() { }); } }; + +//angularfire +Generator.prototype._common = function(dest) { + this.angularFireSourceFiles.push(dest); + var appPath = this.options.appPath; + this.template(path.join('app', dest), path.join(appPath, dest)); +}; + +//angularfire +Generator.prototype._htmlTpl = function(dest) { + var join = path.join; + var appPath = this.options.appPath; + this.copy(join('app', dest), join(appPath, dest)); +}; + +//angularfire +Generator.prototype._tpl = function(src, dest) { + if( !dest ) { dest = src; } + var suff = this.options.coffee? '.coffee' : '.js'; + var destFileName = path.join('scripts', dest+suff); + this.angularFireSourceFiles.push(destFileName); + this.template( + // haaaaaack + path.join('..', this.options.coffee? 'coffee' : 'javascript', src+suff), + path.join(this.appPath, destFileName) + ); +}; diff --git a/common/index.js b/common/index.js index 526c45c2c..37bbc373f 100644 --- a/common/index.js +++ b/common/index.js @@ -32,5 +32,6 @@ Generator.prototype.setupEnv = function setupEnv() { copy('favicon.ico'); copy('robots.txt'); copy('views/main.html'); + this.directory(join('app', 'images'), join(appPath, 'images')); }; diff --git a/package.json b/package.json index 25d39f7e1..4993bd5e8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "generator-angular", - "version": "0.9.5", - "description": "Yeoman generator for AngularJS", + "name": "generator-angularfire", + "version": "0.8.1", + "description": "Yeoman generator for Angular+Firebase", "keywords": [ "yeoman-generator", "scaffold", @@ -9,9 +9,10 @@ "component", "front-end", "app", - "angular" + "angular", + "firebase" ], - "author": "The Yeoman Team", + "author": "Kato (with thanks to Yeoman team)", "main": "app/index.js", "files": [ "app", @@ -32,7 +33,7 @@ "script-base.js", "util.js" ], - "repository": "yeoman/generator-angular", + "repository": "yeoman/generator-angularfire", "scripts": { "test": "mocha" }, diff --git a/route/index.js b/route/index.js index 4ef2d3e64..758e61f98 100644 --- a/route/index.js +++ b/route/index.js @@ -12,7 +12,7 @@ var Generator = module.exports = function Generator() { var bower = require(path.join(process.cwd(), 'bower.json')); var match = require('fs').readFileSync(path.join( this.env.options.appPath, - 'scripts/app.' + (this.env.options.coffee ? 'coffee' : 'js') + 'scripts/routes.' + (this.env.options.coffee ? 'coffee' : 'js') ), 'utf-8').match(/\.when/); if ( @@ -29,6 +29,7 @@ var Generator = module.exports = function Generator() { util.inherits(Generator, ScriptBase); +//angularFire Generator.prototype.rewriteAppJs = function () { var coffee = this.env.options.coffee; @@ -36,7 +37,7 @@ Generator.prototype.rewriteAppJs = function () { this.on('end', function () { this.log(chalk.yellow( '\nangular-route is not installed. Skipping adding the route to ' + - 'scripts/app.' + (coffee ? 'coffee' : 'js') + 'scripts/routes.' + (coffee ? 'coffee' : 'js') )); }); return; @@ -50,7 +51,7 @@ Generator.prototype.rewriteAppJs = function () { var config = { file: path.join( this.env.options.appPath, - 'scripts/app.' + (coffee ? 'coffee' : 'js') + 'scripts/routes.' + (coffee ? 'coffee' : 'js') ), needle: '.otherwise', splicable: [ @@ -59,11 +60,13 @@ Generator.prototype.rewriteAppJs = function () { ] }; + var whenMethod = this.env.options.authRequired? 'whenAuthenticated' : 'when'; + if (coffee) { - config.splicable.unshift(".when '/" + this.uri + "',"); + config.splicable.unshift("." + whenMethod + " '/" + this.uri + "',"); } else { - config.splicable.unshift(".when('/" + this.uri + "', {"); + config.splicable.unshift("." + whenMethod + "('/" + this.uri + "', {"); config.splicable.push("})"); } diff --git a/templates/common/app/index.html b/templates/common/app/index.html index 5faeb7acc..d6df50472 100644 --- a/templates/common/app/index.html +++ b/templates/common/app/index.html @@ -24,16 +24,30 @@
+ + <% + if (ngRoute) { + %>
  • chat
  • + <% + if (loginModule) { + %>
  • + log in + account +
  • + <% + } + } else { + %>
  • link
  • + <% } + %>

    <%= appname %>

    <% if (ngRoute) { %>
    <% } else { - %>
    <% + + %>
    <% } %>