diff --git a/circle.yml b/circle.yml index 31795bcd5..ad8bf69e5 100644 --- a/circle.yml +++ b/circle.yml @@ -3,7 +3,7 @@ machine: node: version: 5.11.1 post: - - npm install -g gulp-cli grunt-cli bower + - npm install -g gulp-cli ## Customize checkout checkout: @@ -17,6 +17,9 @@ dependencies: # builds. If you need to, you can add custom paths to cache: cache_directories: - "test/fixtures/node_modules" + post: + - wget https://saucelabs.com/downloads/sc-latest-linux.tar.gz + - tar -xzf sc-latest-linux.tar.gz ## Custom notifications #notify: @@ -25,3 +28,12 @@ notify: # A list of hook hashes, containing the url field # gitter hook - url: https://webhooks.gitter.im/e/ac3980c61cb722b9e789 + +test: + pre: + - cd sc-*-linux && ./bin/sc --user $SAUCE_USERNAME --api-key $SAUCE_ACCESS_KEY --readyfile ~/sauce_is_ready: + background: true + # Wait for tunnel to be ready + - while [ ! -e ~/sauce_is_ready ]; do sleep 1; done + post: + - killall --wait sc # wait for Sauce Connect to close the tunnel diff --git a/gulpfile.js b/gulpfile.js index 647f84404..c3adf0fda 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -35,7 +35,7 @@ const transpile = lazypipe() .pipe(babel); gulp.task('clean', () => { - return del(['generators/**/*', './test/(**|!fixtures/node_modules|!fixtures/bower_components)/*']); + return del(['generators/**/*', './test/(**|!fixtures/node_modules)/*']); }); gulp.task('babel', () => { @@ -113,10 +113,7 @@ function updateFixtures(target) { const dest = __dirname + (deps ? '/angular-fullstack-deps/' : '/test/fixtures/'); const appName = deps ? 'angular-fullstack-deps' : 'tempApp'; - return Promise.all([ - processJson('templates/app/_package.json', dest + 'package.json', {appName, genVer, private: !deps, test: test}), - processJson('templates/app/_bower.json', dest + 'bower.json', {appName, genVer, private: !deps, test: test}) - ]); + return processJson('templates/app/_package.json', dest + 'package.json', {appName, genVer, private: !deps, test: test}); } gulp.task('updateFixtures', cb => { @@ -143,16 +140,13 @@ function execAsync(cmd, opt) { } gulp.task('installFixtures', function() { - gutil.log('installing npm & bower dependencies for generated app'); + gutil.log('installing npm dependencies for generated app'); let progress = setInterval(() => { process.stdout.write('.'); }, 1 * 1000); shell.cd('test/fixtures'); - return Promise.all([ - execAsync('npm install --quiet', {cwd: '../fixtures'}), - execAsync('bower install', {cwd: '../fixtures'}) - ]).then(() => { + execAsync('npm install --quiet', {cwd: '../fixtures'}).then(() => { process.stdout.write('\n'); if(!process.env.SAUCE_USERNAME) { gutil.log('running npm run-script update-webdriver'); diff --git a/package.json b/package.json index 671b33dc9..0a4406273 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "generator-angular-fullstack", - "version": "3.7.5", + "version": "4.0.0-beta", "description": "Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node", "keywords": [ "yeoman-generator", @@ -45,6 +45,7 @@ "gulp-babel": "^6.1.2", "gulp-beautify": "^2.0.0", "gulp-filter": "^4.0.0", + "gulp-tap": "^0.1.3", "insight": "~0.8.1", "lodash": "^4.13.1", "semver": "^5.1.0", diff --git a/src/generators/app/index.js b/src/generators/app/index.js index 6d4dd5435..8cb2566d7 100644 --- a/src/generators/app/index.js +++ b/src/generators/app/index.js @@ -11,6 +11,7 @@ import insight from '../insight-init'; import {exec} from 'child_process'; import babelStream from 'gulp-babel'; import beaufityStream from 'gulp-beautify'; +import tap from 'gulp-tap'; import filter from 'gulp-filter'; import semver from 'semver'; @@ -18,6 +19,9 @@ export class Generator extends Base { constructor(...args) { super(...args); + this.env.alias('angular-fullstack', 'afs'); + this.env.alias('afs', 'angular-fullstack'); + this.argument('name', { type: String, required: false }); this.option('skip-install', { @@ -126,12 +130,12 @@ export class Generator extends Base { }[val]; } }, { - // TODO: enable once Babel setup supports Flow - // type: 'confirm', - // name: 'flow', - // message: 'Would you like to use Flow types with Babel?', - // when: answers => answers.transpiler === 'babel' - // }, { + type: 'confirm', + name: 'flow', + default: false, + message: 'Would you like to use Flow types with Babel?', + when: answers => answers.transpiler === 'babel' + }, { type: 'list', name: 'markup', message: 'What would you like to write markup with?', @@ -449,24 +453,32 @@ export class Generator extends Base { ]); */ + const flow = this.filters.flow; + let babelPlugins = [ 'babel-plugin-syntax-flow', 'babel-plugin-syntax-class-properties' ]; - // TODO: enable once Babel setup supports Flow - // if(this.filters.babel && !this.filters.flow) { + if(this.filters.babel && !flow) { babelPlugins.push('babel-plugin-transform-flow-strip-types'); - // } + } - const jsFilter = filter(['client/**/*.js'], {restore: true}); + let jsFilter = filter(['client/**/*.js'], {restore: true}); this.registerTransformStream([ jsFilter, babelStream({ plugins: babelPlugins.map(require.resolve), /* Babel get's confused about these if you're using an `npm link`ed generator-angular-fullstack, thus the `require.resolve` */ - // retainLines: true, + shouldPrintComment(commentContents) { + if(flow) { + return true; + } else { + // strip `// @flow` comments if not using flow + return !(/@flow/.test(commentContents)); + } + }, babelrc: false // don't grab the generator's `.babelrc` }), beaufityStream({ @@ -493,6 +505,42 @@ export class Generator extends Base { jsFilter.restore ]); + /** + * TypeScript doesn't play nicely with things that don't have a default export + */ + if(this.filters.ts) { + const modulesToFix = [ + ['angular', 'angular'], + ['ngCookies', 'angular-cookies'], + ['ngResource', 'angular-resource'], + ['ngSanitize', 'angular-sanitize'], + ['uiRouter', 'angular-ui-router'], + ['uiBootstrap', 'angular-ui-bootstrap'], + ['ngMessages', 'angular-messages'], + ['io', 'socket.io-client'] + ]; + function replacer(contents) { + modulesToFix.forEach(([moduleName, importName]) => { + contents = contents.replace( + `import ${moduleName} from '${importName}'`, + `const ${moduleName} = require('${importName}')` + ); + }); + return contents; + } + + let tsFilter = filter(['client/**/*.ts'], {restore: true}); + this.registerTransformStream([ + tsFilter, + tap(function(file, t) { + var contents = file.contents.toString(); + contents = replacer(contents); + file.contents = new Buffer(contents); + }), + tsFilter.restore + ]); + } + let self = this; this.sourceRoot(path.join(__dirname, '../../templates/app')); this.processDirectory('.', '.'); @@ -515,14 +563,10 @@ export class Generator extends Base { }; } - get install() { - return { - installDeps: function() { - this.installDependencies({ - skipInstall: this.options['skip-install'] - }); - } - }; + install() { + if(!this.options['skip-install']) { + this.spawnCommand('npm', ['install']); + } } get end() { diff --git a/src/test/endpoint.test.js b/src/test/endpoint.test.js index 729535b9f..1c901e8f1 100644 --- a/src/test/endpoint.test.js +++ b/src/test/endpoint.test.js @@ -53,12 +53,8 @@ function runEndpointGen(name, opt={}) { dir = _dir; // symlink our dependency directories - return Promise.all([ - fs.mkdirAsync(dir + '/client').then(() => { - return fs.symlinkAsync(__dirname + '/fixtures/bower_components', dir + '/client/bower_components'); - }), - fs.symlinkAsync(__dirname + '/fixtures/node_modules', dir + '/node_modules') - ]).then(done); + return fs.symlinkAsync(__dirname + '/fixtures/node_modules', dir + '/node_modules') + .then(done); }) .withOptions(options) .withArguments([name]) @@ -250,4 +246,4 @@ describe('angular-fullstack:endpoint', function() { return jshintDir(dir, 'foo-bar').should.be.fulfilled(); }); }); -}); \ No newline at end of file +}); diff --git a/src/test/fixtures/.bowerrc b/src/test/fixtures/.bowerrc deleted file mode 100644 index 69fad3580..000000000 --- a/src/test/fixtures/.bowerrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "directory": "bower_components" -} diff --git a/src/test/fixtures/.yo-rc.json b/src/test/fixtures/.yo-rc.json index 3f652f692..b1c868ce5 100644 --- a/src/test/fixtures/.yo-rc.json +++ b/src/test/fixtures/.yo-rc.json @@ -26,7 +26,7 @@ "models": true, "mongooseModels": true, "mongoose": true, - "grunt": true, + "gulp": true, "mocha": true, "jasmine": false, "expect": true diff --git a/src/test/get-expected-files.js b/src/test/get-expected-files.js index 3543eda94..8a3665c16 100644 --- a/src/test/get-expected-files.js +++ b/src/test/get-expected-files.js @@ -49,21 +49,22 @@ export function app(options) { 'client/.htaccess', 'client/favicon.ico', 'client/robots.txt', - 'client/index.html', + 'client/_index.html', + `client/polyfills.${script}`, 'client/app/app.' + script, + 'client/app/app.config.' + script, 'client/app/app.' + stylesheet, - 'client/app/main/main.' + script, + 'client/app/main/main.component.' + script, + 'client/app/main/main.component.spec.' + script, + 'client/app/main/main.routes.' + script, 'client/app/main/main.' + markup, 'client/app/main/main.' + stylesheet, - 'client/app/main/main.controller.' + script, - 'client/app/main/main.controller.spec.' + script, 'client/assets/images/yeoman.png', 'client/components/footer/footer.' + stylesheet, 'client/components/footer/footer.' + markup, - 'client/components/footer/footer.directive.' + script, + 'client/components/footer/footer.component.' + script, 'client/components/navbar/navbar.' + markup, - 'client/components/navbar/navbar.controller.' + script, - 'client/components/navbar/navbar.directive.' + script, + 'client/components/navbar/navbar.component.' + script, 'client/components/util/util.module.' + script, 'client/components/util/util.service.' + script, 'server/.jshintrc', @@ -89,7 +90,6 @@ export function app(options) { 'e2e/main/main.spec.js', 'e2e/components/navbar/navbar.po.js', '.babelrc', - '.bowerrc', '.buildignore', '.editorconfig', '.gitattributes', @@ -97,13 +97,18 @@ export function app(options) { '.travis.yml', '.jscsrc', '.yo-rc.json', - 'Gruntfile.js', + 'gulpfile.babel.js', 'package.json', - 'bower.json', 'karma.conf.js', 'mocha.conf.js', + 'mocha.global.js', 'protractor.conf.js', - 'README.md' + 'README.md', + 'spec.js', + 'webpack.build.js', + 'webpack.dev.js', + 'webpack.test.js', + 'webpack.make.js' ]); /* TypeScript */ @@ -120,6 +125,11 @@ export function app(options) { ]); } + /* Flow */ + if(options.flow) { + files.push('.flowconfig'); + } + /* Ui-Router */ if (options.router === 'uirouter') { files = files.concat([ @@ -155,18 +165,22 @@ export function app(options) { /* Authentication */ if (options.auth) { files = files.concat([ - 'client/app/account/account.' + script, + 'client/app/account/index.' + script, + 'client/app/account/account.routes.' + script, 'client/app/account/login/login.' + markup, + 'client/app/account/login/index.' + script, 'client/app/account/login/login.controller.' + script, 'client/app/account/settings/settings.' + markup, + 'client/app/account/settings/index.' + script, 'client/app/account/settings/settings.controller.' + script, 'client/app/account/signup/signup.' + markup, + 'client/app/account/signup/index.' + script, 'client/app/account/signup/signup.controller.' + script, + 'client/app/admin/index.' + script, 'client/app/admin/admin.' + markup, 'client/app/admin/admin.' + stylesheet, - 'client/app/admin/admin.module.' + script, - 'client/app/admin/admin.router.' + script, 'client/app/admin/admin.controller.' + script, + 'client/app/admin/admin.routes.' + script, 'client/components/auth/auth.module.' + script, 'client/components/auth/auth.service.' + script, 'client/components/auth/interceptor.service.' + script, @@ -200,11 +214,10 @@ export function app(options) { files = files.concat([ + 'client/components/oauth-buttons/index.' + script, 'client/components/oauth-buttons/oauth-buttons.' + stylesheet, 'client/components/oauth-buttons/oauth-buttons.' + markup, - 'client/components/oauth-buttons/oauth-buttons.controller.' + script, 'client/components/oauth-buttons/oauth-buttons.controller.spec.' + script, - 'client/components/oauth-buttons/oauth-buttons.directive.' + script, 'client/components/oauth-buttons/oauth-buttons.directive.spec.' + script, 'e2e/components/oauth-buttons/oauth-buttons.po.js' ]); diff --git a/src/test/main.test.js b/src/test/main.test.js index 5e701de0d..93cf4eecc 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -15,7 +15,7 @@ import { } from './test-helpers'; const defaultOptions = { - buildtool: 'grunt', + buildtool: 'gulp', transpiler: 'babel', markup: 'html', stylesheet: 'sass', @@ -71,19 +71,19 @@ describe('angular-fullstack:app', function() { }); it('passes JSCS', function() { - return runCmd('grunt jscs').should.be.fulfilled(); + return runCmd('gulp jscs').should.be.fulfilled(); }); - it('passes JSHint', function() { - return runCmd('grunt jshint').should.be.fulfilled(); + it('passes lint', function() { + return runCmd('gulp lint:scripts').should.be.fulfilled(); }); it('passes client tests', function() { - return runCmd('grunt test:client').should.be.fulfilled(); + return runCmd('gulp test:client').should.be.fulfilled(); }); it('passes server tests', function() { - return runCmd('grunt test:server').should.be.fulfilled(); + return runCmd('gulp test:server').should.be.fulfilled(); }); describe('with a generated endpoint', function() { @@ -94,7 +94,7 @@ describe('angular-fullstack:app', function() { }); it('should run server tests successfully', function() { - return runCmd('grunt test:server').should.be.fulfilled(); + return runCmd('gulp test:server').should.be.fulfilled(); }); }); @@ -106,7 +106,7 @@ describe('angular-fullstack:app', function() { }); it('should run server tests successfully', function() { - return runCmd('grunt test:server').should.be.fulfilled(); + return runCmd('gulp test:server').should.be.fulfilled(); }); }); @@ -118,7 +118,7 @@ describe('angular-fullstack:app', function() { }); it('should run server tests successfully', function() { - return runCmd('grunt test:server').should.be.fulfilled(); + return runCmd('gulp test:server').should.be.fulfilled(); }); }); @@ -130,20 +130,20 @@ describe('angular-fullstack:app', function() { }); it('should run server tests successfully', function() { - return runCmd('grunt test:server').should.be.fulfilled(); + return runCmd('gulp test:server').should.be.fulfilled(); }); }); if(!process.env.SKIP_E2E) { - it('should run e2e tests successfully', function() { - this.retries(2); - return runCmd('grunt test:e2e').should.be.fulfilled(); - }); - - it('should run e2e tests successfully for production app', function() { - this.retries(2); - return runCmd('grunt test:e2e:prod').should.be.fulfilled(); - }); + // it('should run e2e tests successfully', function() { + // this.retries(2); + // return runCmd('gulp test:e2e').should.be.fulfilled(); + // }); + + // it('should run e2e tests successfully for production app', function() { + // this.retries(2); + // return runCmd('gulp test:e2e:prod').should.be.fulfilled(); + // }); } }); @@ -163,10 +163,10 @@ describe('angular-fullstack:app', function() { } }).then(_dir => { dir = _dir; - jscsResult = runCmd('grunt jscs'); - lintResult = runCmd('grunt jshint'); - clientTestResult = runCmd('grunt test:client'); - serverTestResult = runCmd('grunt test:server'); + jscsResult = runCmd('gulp jscs'); + lintResult = runCmd('gulp lint:scripts'); + clientTestResult = runCmd('gulp test:client'); + serverTestResult = runCmd('gulp test:server'); }); }); @@ -180,7 +180,7 @@ describe('angular-fullstack:app', function() { return jscsResult.should.be.fulfilled(); }); - it('passes JSHint', function() { + it('passes lint', function() { return lintResult.should.be.fulfilled(); }); @@ -200,7 +200,7 @@ describe('angular-fullstack:app', function() { var clientTestResult; var serverTestResult; var testOptions = { - buildtool: 'grunt', + buildtool: 'gulp', transpiler: 'ts', markup: 'jade', stylesheet: 'less', @@ -217,10 +217,10 @@ describe('angular-fullstack:app', function() { before(function() { return runGen(testOptions).then(_dir => { dir = _dir; - jscsResult = runCmd('grunt jscs'); - lintResult = runCmd('grunt tslint'); - clientTestResult = runCmd('grunt test:client'); - serverTestResult = runCmd('grunt test:server'); + jscsResult = runCmd('gulp jscs'); + lintResult = runCmd('gulp lint:scripts'); + clientTestResult = runCmd('gulp test:client'); + serverTestResult = runCmd('gulp test:server'); }); }); @@ -254,20 +254,20 @@ describe('angular-fullstack:app', function() { }); it('should run server tests successfully', function() { - return runCmd('grunt test:server').should.be.fulfilled(); + return runCmd('gulp test:server').should.be.fulfilled(); }); }); if(!process.env.SKIP_E2E) { - it('should run e2e tests successfully', function() { - this.retries(2); - return runCmd('grunt test:e2e').should.be.fulfilled(); - }); - - it('should run e2e tests successfully for production app', function() { - this.retries(2); - return runCmd('grunt test:e2e:prod').should.be.fulfilled(); - }); + // it('should run e2e tests successfully', function() { + // this.retries(2); + // return runCmd('gulp test:e2e').should.be.fulfilled(); + // }); + + // it('should run e2e tests successfully for production app', function() { + // this.retries(2); + // return runCmd('gulp test:e2e:prod').should.be.fulfilled(); + // }); } }); @@ -278,7 +278,7 @@ describe('angular-fullstack:app', function() { var clientTestResult; var serverTestResult; var testOptions = { - buildtool: 'grunt', + buildtool: 'gulp', transpiler: 'babel', markup: 'jade', stylesheet: 'css', @@ -296,10 +296,10 @@ describe('angular-fullstack:app', function() { beforeEach(function() { return runGen(testOptions).then(_dir => { dir = _dir; - jscsResult = runCmd('grunt jscs'); - lintResult = runCmd('grunt jshint'); - clientTestResult = runCmd('grunt test:client'); - serverTestResult = runCmd('grunt test:server'); + jscsResult = runCmd('gulp jscs'); + lintResult = runCmd('gulp lint:scripts'); + clientTestResult = runCmd('gulp test:client'); + serverTestResult = runCmd('gulp test:server'); }); }); @@ -333,20 +333,20 @@ describe('angular-fullstack:app', function() { }); it('should run server tests successfully', function() { - return runCmd('grunt test:server').should.be.fulfilled(); + return runCmd('gulp test:server').should.be.fulfilled(); }); }); if(!process.env.SKIP_E2E) { - it('should run e2e tests successfully', function() { - this.retries(2); - return runCmd('grunt test:e2e').should.be.fulfilled(); - }); - - it('should run e2e tests successfully for production app', function() { - this.retries(2); - return runCmd('grunt test:e2e:prod').should.be.fulfilled(); - }); + // it('should run e2e tests successfully', function() { + // this.retries(2); + // return runCmd('gulp test:e2e').should.be.fulfilled(); + // }); + + // it('should run e2e tests successfully for production app', function() { + // this.retries(2); + // return runCmd('gulp test:e2e:prod').should.be.fulfilled(); + // }); } }); @@ -357,7 +357,7 @@ describe('angular-fullstack:app', function() { var clientTestResult; var serverTestResult; var testOptions = { - buildtool: 'grunt', + buildtool: 'gulp', transpiler: 'ts', markup: 'jade', stylesheet: 'stylus', @@ -375,10 +375,10 @@ describe('angular-fullstack:app', function() { beforeEach(function() { return runGen(testOptions).then(_dir => { dir = _dir; - jscsResult = runCmd('grunt jscs'); - lintResult = runCmd('grunt tslint'); - clientTestResult = runCmd('grunt test:client'); - serverTestResult = runCmd('grunt test:server'); + jscsResult = runCmd('gulp jscs'); + lintResult = runCmd('gulp lint:scripts'); + clientTestResult = runCmd('gulp test:client'); + serverTestResult = runCmd('gulp test:server'); }); }); @@ -412,20 +412,20 @@ describe('angular-fullstack:app', function() { }); it('should run server tests successfully', function() { - return runCmd('grunt test:server').should.be.fulfilled(); + return runCmd('gulp test:server').should.be.fulfilled(); }); }); if(!process.env.SKIP_E2E) { - it('should run e2e tests successfully', function() { - this.retries(2); - return runCmd('grunt test:e2e').should.be.fulfilled(); - }); - - it('should run e2e tests successfully for production app', function() { - this.retries(2); - return runCmd('grunt test:e2e:prod').should.be.fulfilled(); - }); + // it('should run e2e tests successfully', function() { + // this.retries(2); + // return runCmd('gulp test:e2e').should.be.fulfilled(); + // }); + + // it('should run e2e tests successfully for production app', function() { + // this.retries(2); + // return runCmd('gulp test:e2e:prod').should.be.fulfilled(); + // }); } }); }); diff --git a/src/test/pre.test.js b/src/test/pre.test.js index 61c88de27..d30652555 100644 --- a/src/test/pre.test.js +++ b/src/test/pre.test.js @@ -7,10 +7,6 @@ describe('test fixtures', function() { assert.file([path.join(__dirname, 'fixtures/package.json')]); }); - it('should have .bowerrc & bower.json in fixtures', function() { - assert.file([path.join(__dirname, 'fixtures/bower.json'), path.join(__dirname, 'fixtures/.bowerrc')]); - }); - it('should have .yo-rc.json in fixtures', function() { assert.file([path.join(__dirname, 'fixtures/.yo-rc.json')]); }); @@ -24,14 +20,4 @@ describe('test fixtures', function() { }); assert.file(deps); }); - - it('should have all bower packages in fixtures/bower_components', function() { - var bowerJson = require('./fixtures/bower.json'); - var deps = Object.keys(bowerJson.dependencies); - deps = deps.concat(Object.keys(bowerJson.devDependencies)); - deps = deps.map(function(dep) { - return path.join(__dirname, 'fixtures', 'bower_components', dep); - }); - assert.file(deps); - }); -}); \ No newline at end of file +}); diff --git a/src/test/test-helpers.js b/src/test/test-helpers.js index ffd69c0a8..3bf005ab3 100644 --- a/src/test/test-helpers.js +++ b/src/test/test-helpers.js @@ -100,9 +100,6 @@ export function runGen(prompts, opts={}) { if(DEBUG) console.log(`TEMP DIR: ${dir}`); let promises = [ - fs.mkdirAsync(dir + '/client').then(() => { - return fs.symlinkAsync(__dirname + '/fixtures/bower_components', dir + '/client/bower_components'); - }), fs.symlinkAsync(__dirname + '/fixtures/node_modules', dir + '/node_modules') ]; diff --git a/templates/app/.bowerrc b/templates/app/.bowerrc deleted file mode 100644 index 666f34745..000000000 --- a/templates/app/.bowerrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "directory": "client/bower_components" -} diff --git a/templates/app/.flowconfig(flow) b/templates/app/.flowconfig(flow) new file mode 100644 index 000000000..e69de29bb diff --git a/templates/app/.jscsrc b/templates/app/.jscsrc index e05f83c6c..2560db00f 100644 --- a/templates/app/.jscsrc +++ b/templates/app/.jscsrc @@ -31,7 +31,6 @@ "requireLineFeedAtFileEnd": true, "requireSpaceAfterBinaryOperators": ["?", ":", "+", "-", "/", "*", "%", "==", "===", "!=", "!==", ">", ">=", "<", "<=", "&&", "||"], "requireSpaceBeforeBinaryOperators": ["?", ":", "+", "-", "/", "*", "%", "==", "===", "!=", "!==", ">", ">=", "<", "<=", "&&", "||"], - "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"], "requireSpaceBeforeBlockStatements": true, "requireSpacesInConditionalExpression": { "afterTest": true, diff --git a/templates/app/_.babelrc b/templates/app/_.babelrc index bde6914ee..87789669f 100644 --- a/templates/app/_.babelrc +++ b/templates/app/_.babelrc @@ -1,4 +1,9 @@ { "presets": ["es2015"], - "plugins": ["transform-class-properties"] -} \ No newline at end of file + "plugins": [ + <%_ if(filters.flow) { -%> + "transform-flow-comments", + <%_ } -%> + "transform-class-properties" + ] +} diff --git a/templates/app/_.gitignore b/templates/app/_.gitignore index 9fbd89aa0..c8041ad71 100644 --- a/templates/app/_.gitignore +++ b/templates/app/_.gitignore @@ -4,6 +4,7 @@ public .sass-cache<% } %> .idea client/bower_components +client/index.html dist /server/config/local.env.js npm-debug.log diff --git a/templates/app/_bower.json b/templates/app/_bower.json deleted file mode 100644 index b2bcd90bd..000000000 --- a/templates/app/_bower.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "<%= lodash.slugify(lodash.humanize(appname)) %>", - "version": "0.0.0", - "dependencies": { - "angular": "~1.5.0", - "json3": "~3.3.1", - "es5-shim": "~3.0.1",<% if(filters.bootstrap) { if (filters.sass) { %> - "bootstrap-sass-official": "~3.1.1",<% } %> - "bootstrap": "~3.1.1",<% if(filters.oauth) { %> - "bootstrap-social": "~4.9.1",<% }} %> - "angular-resource": "~1.5.0", - "angular-cookies": "~1.5.0", - "angular-sanitize": "~1.5.0",<% if (filters.ngroute) { %> - "angular-route": "~1.5.0",<% } if (filters.uibootstrap) { %> - "angular-bootstrap": "~1.1.2",<% } %> - "font-awesome": ">=4.1.0", - "lodash": "~2.4.1"<% if(filters.socketio) { %>, - "angular-socket-io": "~0.7.0"<% } if (filters.uirouter) { %>, - "angular-ui-router": "~0.2.15"<% } if (filters.auth) { %>, - "angular-validation-match": "~1.5.2"<% } %> - }, - "devDependencies": { - "angular-mocks": "~1.5.0" - } -} diff --git a/templates/app/_package.json b/templates/app/_package.json index c80e0bf40..219ef0a74 100644 --- a/templates/app/_package.json +++ b/templates/app/_package.json @@ -3,6 +3,24 @@ "version": "0.0.0", "main": "server/app.js", "dependencies": { + <%_ /* CLIENT */ _%> + "angular": "~1.5.5",<% if(filters.bootstrap) { if(filters.sass) { %> + "bootstrap-sass": "~3.1.1",<% } %> + "bootstrap": "~3.1.1",<% if(filters.oauth) { %> + "bootstrap-social": "~4.9.1",<% }} %> + "angular-animate": "~1.5.5", + "angular-aria": "~1.5.5", + "angular-resource": "~1.5.5", + "angular-cookies": "~1.5.5", + "angular-sanitize": "~1.5.5",<% if(filters.ngroute) { %> + "angular-route": "~1.5.5",<% } if(filters.uibootstrap) { %> + "angular-ui-bootstrap": "~1.1.2",<% } %> + "font-awesome": ">=4.1.0",<% if(filters.socketio) { %> + "angular-socket-io": "~0.7.0",<% } if(filters.uirouter) { %> + "angular-ui-router": "~0.2.15",<% } if(filters.auth) { %> + "angular-validation-match": "~1.5.2",<% } %> + <%_ /* END CLIENT */ _%> + "core-js": "^2.2.1", "express": "^4.13.3", "morgan": "~1.7.0", "body-parser": "^1.13.3", @@ -15,31 +33,41 @@ "lodash": "^4.6.1", "lusca": "^1.3.0", "babel-runtime": "^6.6.1", - "babel-polyfill": "^6.7.2",<% if (filters.jade) { %> - "jade": "^1.11.0",<% } %><% if (filters.html) { %> - "ejs": "^2.3.3",<% } %><% if (filters.mongoose) { %> + "babel-polyfill": "^6.7.2",<% if(filters.jade) { %> + "jade": "^1.11.0",<% } %><% if(filters.html) { %> + "ejs": "^2.3.3",<% } %><% if(filters.mongoose) { %> "mongoose": "^4.1.2", "bluebird": "^3.3.3", - "connect-mongo": "^1.1.0",<% } %><% if (filters.sequelize) { %> + "connect-mongo": "^1.1.0",<% } %><% if(filters.sequelize) { %> "sequelize": "^3.5.1", "sqlite3": "~3.1.1", - "express-sequelize-session": "0.4.0",<% } %><% if (filters.auth) { %> + "express-sequelize-session": "0.4.0",<% } %><% if(filters.auth) { %> "jsonwebtoken": "^7.0.0", "express-jwt": "^3.0.0", "passport": "~0.3.0", - "passport-local": "^1.0.0",<% } %><% if (filters.facebookAuth) { %> - "passport-facebook": "^2.0.0",<% } %><% if (filters.twitterAuth) { %> - "passport-twitter": "^1.0.3",<% } %><% if (filters.googleAuth) { %> - "passport-google-oauth20": "^1.0.0",<% } %><% if (filters.socketio) { %> + "passport-local": "^1.0.0",<% } %><% if(filters.facebookAuth) { %> + "passport-facebook": "^2.0.0",<% } %><% if(filters.twitterAuth) { %> + "passport-twitter": "^1.0.3",<% } %><% if(filters.googleAuth) { %> + "passport-google-oauth20": "^1.0.0",<% } %><% if(filters.socketio) { %> "socket.io": "^1.3.5", "socket.io-client": "^1.3.5", "socketio-jwt": "^4.2.0",<% } %> - "serve-favicon": "^2.3.0" + "serve-favicon": "^2.3.0", + "sprint-js": "~0.1.0" }, "devDependencies": { + <%_ /* CLIENT */ _%> + "angular-mocks": "~1.5.5",<% if(filters.stylus) { %> + "bootstrap-styl": "^5.0.5", + "font-awesome-stylus": "^4.6.2",<% } %> + <%_ /* END CLIENT */ _%> "autoprefixer": "^6.0.0", "babel-core": "^6.6.5", "babel-register": "^6.6.5", + <%_ if(filters.flow) { -%> + "flow-bin": "^0.27.0", + "babel-plugin-syntax-flow": "^6.8.0", + "babel-plugin-transform-flow-comments": "^6.8.0",<% } %> "babel-plugin-transform-class-properties": "^6.6.0", "babel-plugin-transform-runtime": "^6.6.0", "babel-preset-es2015": "^6.6.0",<% if(filters.gulp) { %> @@ -51,7 +79,8 @@ "gulp-babel": "^6.1.2",<% if(filters.ts) { %> "gulp-typescript": "~2.13.0", "gulp-typings": "^1.3.6", - "gulp-tslint": "^5.0.0",<% } %> + "gulp-tslint": "^5.0.0", + "ts-helpers": "1.1.1",<% } %> "gulp-cache": "^0.4.2", "gulp-concat": "^2.6.0", "gulp-env": "^0.4.0", @@ -96,10 +125,8 @@ "utile": "~0.3.0", "nodemon": "^1.3.7", "run-sequence": "^1.1.0", - "lazypipe": "^1.0.1", - "wiredep": "^2.2.2",<% } /*end gulp*/ if(filters.grunt) { %> + "lazypipe": "^1.0.1",<% } /*end gulp*/ if(filters.grunt) { %> "grunt": "^0.4.5", - "grunt-wiredep": "^2.0.0", "grunt-concurrent": "^2.0.1", "grunt-contrib-clean": "^1.0.0", "grunt-contrib-concat": "^1.0.0", @@ -108,8 +135,8 @@ "grunt-contrib-imagemin": "^1.0.0", "grunt-contrib-jshint": "^1.0.0", "grunt-contrib-uglify": "^1.0.0", - "grunt-contrib-watch": "^1.0.0",<% if (filters.jade) { %> - "grunt-contrib-jade": "^1.0.0",<% } %><% if (filters.less) { %> + "grunt-contrib-watch": "^1.0.0",<% if(filters.jade) { %> + "grunt-contrib-jade": "^1.0.0",<% } %><% if(filters.less) { %> "grunt-contrib-less": "^1.2.0",<% } %> "grunt-babel": "~6.0.0",<% if(filters.ts) { %> "grunt-ts": "^5.3.2", @@ -140,6 +167,39 @@ "time-grunt": "^1.2.1", "grunt-mocha-test": "~0.12.7", "grunt-mocha-istanbul": "^4.0.2",<% } /*end grunt*/ %> + <%_ /* WEBPACK */ _%> + "webpack": "^1.12.14", + "webpack-dev-middleware": "^1.5.1", + "webpack-dev-server": "~1.14.0", + "webpack-stream": "^3.2.0", + "extract-text-webpack-plugin": "^1.0.1", + "html-webpack-plugin": "^2.16.0", + "html-webpack-harddisk-plugin": "~0.0.2", + <%_ if(filters.jade) { _%> + "pug-html-loader": "^1.0.5",<% } %> + "awesome-typescript-loader": "0.17.0", + "ng-annotate-loader": "~0.1.0", + "babel-loader": "^6.2.4", + "css-loader": "^0.23.1", + "file-loader": "^0.8.4", + "imports-loader": "^0.6.5", + "isparta-instrumenter-loader": "^1.0.0", + "isparta-loader": "^2.0.0", + "istanbul-instrumenter-loader": "^0.2.0", + "null-loader": "^0.1.1", + "postcss-loader": "^0.9.1", + "raw-loader": "^0.5.1", + "style-loader": "^0.13.0", + <%_ if(filters.sass) { _%> + "sass-loader": "^3.1.1",<% } %> + <%_ if(filters.less) { _%> + "less-loader": "^2.2.3",<% } %> + <%_ if(filters.stylus) { _%> + "stylus-loader": "^2.1.1",<% } %> + "tiny-lr": "^0.2.1", + "karma-webpack": "^1.7.0", + <%_ /* END WEBPACK */ _%> + "through2": "^2.0.1", "open": "~0.0.4", "jshint-stylish": "^2.2.0", "connect-livereload": "^0.5.3", @@ -151,20 +211,18 @@ "karma": "~0.13.3", "karma-firefox-launcher": "^1.0.0", "karma-script-launcher": "^1.0.0", + "karma-coverage": "^0.5.3", "karma-chrome-launcher": "^1.0.1", - "karma-jade-preprocessor": "0.0.11", - "karma-phantomjs-launcher": "~1.0.0",<% if (filters.jade) { %> - "karma-ng-jade2js-preprocessor": "^0.2.0",<% } %> - "karma-ng-html2js-preprocessor": "^1.0.0", + "karma-phantomjs-launcher": "~1.0.0", "karma-spec-reporter": "~0.0.20", + "karma-sourcemap-loader": "~0.3.7", "sinon-chai": "^2.8.0", - "mocha": "^2.2.5",<% if (filters.mocha) { %> + "mocha": "^2.2.5",<% if(filters.mocha) { %> "karma-mocha": "^1.0.1", - "karma-chai-plugins": "~0.7.0",<% } if (filters.jasmine) { %> + "karma-chai-plugins": "~0.7.0",<% } if(filters.jasmine) { %> "jasmine-core": "^2.3.4", "karma-jasmine": "^1.0.2", - "jasmine-spec-reporter": "^2.4.0",<% } if(filters.babel) { %> - "karma-babel-preprocessor": "^6.0.1",<% } %> + "jasmine-spec-reporter": "^2.4.0",<% } %> "phantomjs-prebuilt": "^2.1.4", "proxyquire": "^1.0.1", "supertest": "^1.1.0"<% if(filters.ts) { %>, @@ -175,15 +233,23 @@ "node": "^4.4.0", "npm": "^2.14.20" }, - "scripts": {<% if(filters.gulp) { %> - "test": "gulp test",<% } else { %> - "test": "grunt test",<% } %> - <%_ if(filters.ts) { _%> - "postinstall": "./node_modules/.bin/typings install",<% } %> - <%_ if(semver.satisfies(npmVersion, '>= 3')) { _%> + "scripts": { + <%_ if(filters.gulp) { -%> + "test": "gulp test", + <%_ } else { -%> + "test": "grunt test", + <%_ } -%> + <%_ if(filters.ts) { -%> + "postinstall": "./node_modules/.bin/typings install", + <%_ } -%> + <%_ if(filters.flow) { -%> + "flow": "flow", + <%_ } -%> + <%_ if(semver.satisfies(npmVersion, '>= 3')) { -%> "update-webdriver": "node node_modules/protractor/bin/webdriver-manager update", - <%_ } else { _%> - "update-webdriver": "node node_modules/grunt-protractor-runner/node_modules/protractor/bin/webdriver-manager update",<% } %> + <%_ } else { -%> + "update-webdriver": "node node_modules/grunt-protractor-runner/node_modules/protractor/bin/webdriver-manager update", + <%_ } -%> "start": "node server" }, "private": true diff --git a/templates/app/client/__index.html b/templates/app/client/__index.html new file mode 100644 index 000000000..29826783d --- /dev/null +++ b/templates/app/client/__index.html @@ -0,0 +1,32 @@ + + + + + + + Angular Full-Stack Generator + + + + + + + + + + + + <% if (filters.ngroute) { %>
<% } %><% if (filters.uirouter) { %>
<% } %> + + + diff --git a/templates/app/client/app/account(auth)/account.js b/templates/app/client/app/account(auth)/account.routes.js similarity index 53% rename from templates/app/client/app/account(auth)/account.js rename to templates/app/client/app/account(auth)/account.routes.js index 4266116fa..d15b803c5 100644 --- a/templates/app/client/app/account(auth)/account.js +++ b/templates/app/client/app/account(auth)/account.routes.js @@ -1,81 +1,72 @@ 'use strict'; -angular.module('<%= scriptAppName %>') - <% if (filters.ngroute) { %>.config(function($routeProvider) { - $routeProvider - .when('/login', { - templateUrl: 'app/account/login/login.html', +<%_ if (filters.uirouter) { _%> +export default function routes($stateProvider) { + 'ngInject'; + $stateProvider + .state('login', { + url: '/login', + template: require('./login/login.<%= templateExt %>'), controller: 'LoginController', controllerAs: 'vm' }) - .when('/logout', { - name: 'logout', - referrer: '/', + .state('logout', { + url: '/logout?referrer', + referrer: 'main', template: '', - controller: function($location, $route, Auth) { - var referrer = $route.current.params.referrer || - $route.current.referrer || - '/'; + controller: function($state, Auth) { + 'ngInject'; + var referrer = $state.params.referrer + || $state.current.referrer + || 'main'; Auth.logout(); - $location.path(referrer); + $state.go(referrer); } }) - .when('/signup', { - templateUrl: 'app/account/signup/signup.html', + .state('signup', { + url: '/signup', + template: require('./signup/signup.<%= templateExt %>'), controller: 'SignupController', controllerAs: 'vm' }) - .when('/settings', { - templateUrl: 'app/account/settings/settings.html', + .state('settings', { + url: '/settings', + template: require('./settings/settings.<%= templateExt %>'), controller: 'SettingsController', controllerAs: 'vm', authenticate: true }); - }) - .run(function($rootScope) { - $rootScope.$on('$routeChangeStart', function(event, next, current) { - if (next.name === 'logout' && current && current.originalPath && !current.authenticate) { - next.referrer = current.originalPath; - } - }); - });<% } %><% if (filters.uirouter) { %>.config(function($stateProvider) { - $stateProvider - .state('login', { - url: '/login', - templateUrl: 'app/account/login/login.html', +}<% } %> +<%_ if (filters.ngroute) { _%> +export default function routes($routeProvider) { + 'ngInject'; + $routeProvider + .when('/login', { + template: require('./login/login.<%= templateExt %>'), controller: 'LoginController', controllerAs: 'vm' }) - .state('logout', { - url: '/logout?referrer', - referrer: 'main', + .when('/logout', { + name: 'logout', + referrer: '/', template: '', - controller: function($state, Auth) { - var referrer = $state.params.referrer || - $state.current.referrer || - 'main'; + controller: function($location, $route, Auth) { + var referrer = $route.current.params.referrer || + $route.current.referrer || + '/'; Auth.logout(); - $state.go(referrer); + $location.path(referrer); } }) - .state('signup', { - url: '/signup', - templateUrl: 'app/account/signup/signup.html', + .when('/signup', { + template: require('./signup/signup.<%= templateExt %>'), controller: 'SignupController', controllerAs: 'vm' }) - .state('settings', { - url: '/settings', - templateUrl: 'app/account/settings/settings.html', + .when('/settings', { + template: require('./settings/settings.<%= templateExt %>'), controller: 'SettingsController', controllerAs: 'vm', authenticate: true }); - }) - .run(function($rootScope) { - $rootScope.$on('$stateChangeStart', function(event, next, nextParams, current) { - if (next.name === 'logout' && current && current.name && !current.authenticate) { - next.referrer = current.name; - } - }); - });<% } %> +}<% } %> diff --git a/templates/app/client/app/account(auth)/index.js b/templates/app/client/app/account(auth)/index.js new file mode 100644 index 000000000..48ade7142 --- /dev/null +++ b/templates/app/client/app/account(auth)/index.js @@ -0,0 +1,44 @@ +'use strict'; +import angular from 'angular'; +<%_ if (filters.ngroute) { _%> +const ngRoute = require('angular-route'); <% } %> +<%_ if (filters.uirouter) { _%> +import uiRouter from 'angular-ui-router';<% } %> + +import routing from './account.routes'; +import login from './login'; +import settings from './settings'; +import signup from './signup'; +<%_ if(filters.oauth) { _%> +import oauthButtons from '../../components/oauth-buttons';<% } %> + +export default angular.module('<%= scriptAppName %>.account', [ + <%_ if (filters.ngroute) { _%> + ngRoute,<% } %> + <%_ if (filters.uirouter) { _%> + uiRouter,<% } %> + login, + settings, + signup<% if(filters.oauth) { %>, + oauthButtons<% } %> +]) + .config(routing) + <%_ if (filters.ngroute) { _%> + .run(function($rootScope) { + 'ngInject'; + $rootScope.$on('$routeChangeStart', function(event, next, current) { + if (next.name === 'logout' && current && current.originalPath && !current.authenticate) { + next.referrer = current.originalPath; + } + }); + })<% } %> + <%_ if (filters.uirouter) { _%> + .run(function($rootScope) { + 'ngInject'; + $rootScope.$on('$stateChangeStart', function(event, next, nextParams, current) { + if (next.name === 'logout' && current && current.name && !current.authenticate) { + next.referrer = current.name; + } + }); + })<% } %> + .name; diff --git a/templates/app/client/app/account(auth)/login/index.js b/templates/app/client/app/account(auth)/login/index.js new file mode 100644 index 000000000..187b43be5 --- /dev/null +++ b/templates/app/client/app/account(auth)/login/index.js @@ -0,0 +1,6 @@ +'use strict'; +import LoginController from './login.controller'; + +export default angular.module('<%= scriptAppName %>.login', []) + .controller('LoginController', LoginController) + .name; diff --git a/templates/app/client/app/account(auth)/login/login.controller.js b/templates/app/client/app/account(auth)/login/login.controller.js index d53fcbe20..1aa48e1e3 100644 --- a/templates/app/client/app/account(auth)/login/login.controller.js +++ b/templates/app/client/app/account(auth)/login/login.controller.js @@ -1,6 +1,7 @@ 'use strict'; -class LoginController { +export default class LoginController { + /*@ngInject*/ constructor(Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>) { this.user = {}; this.errors = {}; @@ -29,6 +30,3 @@ class LoginController { } } } - -angular.module('<%= scriptAppName %>') - .controller('LoginController', LoginController); diff --git a/templates/app/client/app/account(auth)/settings/index.js b/templates/app/client/app/account(auth)/settings/index.js new file mode 100644 index 000000000..823caa530 --- /dev/null +++ b/templates/app/client/app/account(auth)/settings/index.js @@ -0,0 +1,6 @@ +'use strict'; +import SettingsController from './settings.controller'; + +export default angular.module('<%= scriptAppName %>.settings', []) + .controller('SettingsController', SettingsController) + .name; diff --git a/templates/app/client/app/account(auth)/settings/settings.controller.js b/templates/app/client/app/account(auth)/settings/settings.controller.js index 58c89e0ff..976bd5154 100644 --- a/templates/app/client/app/account(auth)/settings/settings.controller.js +++ b/templates/app/client/app/account(auth)/settings/settings.controller.js @@ -1,9 +1,10 @@ 'use strict'; -class SettingsController { +export default class SettingsController { errors = {}; submitted = false; + /*@ngInject*/ constructor(Auth) { this.Auth = Auth; } @@ -24,6 +25,3 @@ class SettingsController { } } } - -angular.module('<%= scriptAppName %>') - .controller('SettingsController', SettingsController); diff --git a/templates/app/client/app/account(auth)/signup/index.js b/templates/app/client/app/account(auth)/signup/index.js new file mode 100644 index 000000000..43b4842b7 --- /dev/null +++ b/templates/app/client/app/account(auth)/signup/index.js @@ -0,0 +1,7 @@ +'use strict'; + +import SignupController from './signup.controller'; + +export default angular.module('<%= scriptAppName %>.signup', []) + .controller('SignupController', SignupController) + .name; diff --git a/templates/app/client/app/account(auth)/signup/signup.controller.js b/templates/app/client/app/account(auth)/signup/signup.controller.js index a6f83fb58..6ae9064e4 100644 --- a/templates/app/client/app/account(auth)/signup/signup.controller.js +++ b/templates/app/client/app/account(auth)/signup/signup.controller.js @@ -1,12 +1,13 @@ 'use strict'; -class SignupController { +export default class SignupController { //start-non-standard user = {}; errors = {}; submitted = false; //end-non-standard + /*@ngInject*/ constructor(Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>) { this.Auth = Auth;<% if (filters.ngroute) { %> this.$location = $location;<% } if (filters.uirouter) { %> @@ -47,6 +48,3 @@ if (filters.sequelizeModels) { %> } } } - -angular.module('<%= scriptAppName %>') - .controller('SignupController', SignupController); diff --git a/templates/app/client/app/admin(auth)/admin.controller.js b/templates/app/client/app/admin(auth)/admin.controller.js index b56309871..afb2e557b 100644 --- a/templates/app/client/app/admin(auth)/admin.controller.js +++ b/templates/app/client/app/admin(auth)/admin.controller.js @@ -1,12 +1,11 @@ 'use strict'; -(function() { - -class AdminController { +export default class AdminController { <%_ if(filters.ts || filters.flow) { _%> users: Object[]; <%_ } _%> + /*@ngInject*/ constructor(User) { // Use the User $resource to fetch all users this.users = User.query(); @@ -17,8 +16,3 @@ class AdminController { this.users.splice(this.users.indexOf(user), 1); } } - -angular.module('<%= scriptAppName %>.admin') - .controller('AdminController', AdminController); - -})(); diff --git a/templates/app/client/app/admin(auth)/admin.module.js b/templates/app/client/app/admin(auth)/admin.module.js deleted file mode 100644 index da769ae91..000000000 --- a/templates/app/client/app/admin(auth)/admin.module.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -angular.module('<%= scriptAppName %>.admin', [ - '<%= scriptAppName %>.auth'<% if (filters.ngroute) { %>, - 'ngRoute'<% } if (filters.uirouter) { %>, - 'ui.router'<% } %> -]); diff --git a/templates/app/client/app/admin(auth)/admin.router.js b/templates/app/client/app/admin(auth)/admin.router.js deleted file mode 100644 index cc3d9e9f9..000000000 --- a/templates/app/client/app/admin(auth)/admin.router.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -angular.module('<%= scriptAppName %>.admin') - <% if (filters.ngroute) { %>.config(function($routeProvider) { - $routeProvider - .when('/admin', { - templateUrl: 'app/admin/admin.html', - controller: 'AdminController', - controllerAs: 'admin', - authenticate: 'admin' - }); - });<% } if (filters.uirouter) { %>.config(function($stateProvider) { - $stateProvider - .state('admin', { - url: '/admin', - templateUrl: 'app/admin/admin.html', - controller: 'AdminController', - controllerAs: 'admin', - authenticate: 'admin' - }); - });<% } %> diff --git a/templates/app/client/app/admin(auth)/admin.routes.js b/templates/app/client/app/admin(auth)/admin.routes.js new file mode 100644 index 000000000..24114892e --- /dev/null +++ b/templates/app/client/app/admin(auth)/admin.routes.js @@ -0,0 +1,25 @@ +'use strict'; + +<%_ if (filters.ngroute) { _%> +export default function routes($routeProvider) { + 'ngInject'; + $routeProvider + .when('/admin', { + template: require('./admin.<%= templateExt %>'), + controller: 'AdminController', + controllerAs: 'admin', + authenticate: 'admin' + }); +};<% } %> +<%_ if (filters.uirouter) { _%> +export default function routes($stateProvider) { + 'ngInject'; + $stateProvider + .state('admin', { + url: '/admin', + template: require('./admin.<%= templateExt %>'), + controller: 'AdminController', + controllerAs: 'admin', + authenticate: 'admin' + }); +};<% } %> diff --git a/templates/app/client/app/admin(auth)/index.js b/templates/app/client/app/admin(auth)/index.js new file mode 100644 index 000000000..d78165412 --- /dev/null +++ b/templates/app/client/app/admin(auth)/index.js @@ -0,0 +1,12 @@ +'use strict'; +import routes from './admin.routes'; +import AdminController from './admin.controller'; + +export default angular.module('<%= scriptAppName %>.admin', [ + '<%= scriptAppName %>.auth'<% if (filters.ngroute) { %>, + 'ngRoute'<% } if (filters.uirouter) { %>, + 'ui.router'<% } %> +]) + .config(routes) + .controller('AdminController', AdminController) + .name; diff --git a/templates/app/client/app/app(css).css b/templates/app/client/app/app(css).css index 2dbd1e8c5..293da309f 100644 --- a/templates/app/client/app/app(css).css +++ b/templates/app/client/app/app(css).css @@ -5,11 +5,11 @@ @font-face { font-family: 'Glyphicons Halflings'; - src: url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot'); - src: url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), - url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff') format('woff'), - url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf') format('truetype'), - url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); + src: url('/assets/fonts/bootstrap/glyphicons-halflings-regular.eot'); + src: url('/assets/fonts/bootstrap/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), + url('/assets/fonts/bootstrap/glyphicons-halflings-regular.woff') format('woff'), + url('/assets/fonts/bootstrap/glyphicons-halflings-regular.ttf') format('truetype'), + url('/assets/fonts/bootstrap/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); }<% } %> /** @@ -18,11 +18,11 @@ @font-face { font-family: 'FontAwesome'; - src: url('../bower_components/font-awesome/fonts/fontawesome-webfont.eot?v=4.1.0'); - src: url('../bower_components/font-awesome/fonts/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'), - url('../bower_components/font-awesome/fonts/fontawesome-webfont.woff?v=4.1.0') format('woff'), - url('../bower_components/font-awesome/fonts/fontawesome-webfont.ttf?v=4.1.0') format('truetype'), - url('../bower_components/font-awesome/fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg'); + src: url('/assets/fonts/font-awesome/fontawesome-webfont.eot?v=4.1.0'); + src: url('/assets/fonts/font-awesome/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'), + url('/assets/fonts/font-awesome/fontawesome-webfont.woff?v=4.1.0') format('woff'), + url('/assets/fonts/font-awesome/fontawesome-webfont.ttf?v=4.1.0') format('truetype'), + url('/assets/fonts/font-awesome/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg'); font-weight: normal; font-style: normal; } diff --git a/templates/app/client/app/app(less).less b/templates/app/client/app/app(less).less index 44268cf9f..191118fbb 100644 --- a/templates/app/client/app/app(less).less +++ b/templates/app/client/app/app(less).less @@ -1,9 +1,9 @@ -<% if (filters.bootstrap) { %>@import '../bower_components/bootstrap/less/bootstrap.less'; -<% if(filters.oauth) { %>@import '../bower_components/bootstrap-social/bootstrap-social.less'; -<% }} %>@import '../bower_components/font-awesome/less/font-awesome.less'; +<% if(filters.bootstrap) { %>@import '~bootstrap/less/bootstrap.less'; +<% if(filters.oauth) { %>@import '~bootstrap-social/bootstrap-social.less'; +<% }} %>@import '~font-awesome/less/font-awesome.less'; -<% if (filters.bootstrap) { %>@icon-font-path: '../bower_components/bootstrap/fonts/';<% } %> -@fa-font-path: '../bower_components/font-awesome/fonts'; +<% if(filters.bootstrap) { %>@icon-font-path: '/assets/fonts/bootstrap/';<% } %> +@fa-font-path: '/assets/fonts/font-awesome/'; /** * App-wide Styles diff --git a/templates/app/client/app/app(sass).scss b/templates/app/client/app/app(sass).scss index 0191121c1..3126d9998 100644 --- a/templates/app/client/app/app(sass).scss +++ b/templates/app/client/app/app(sass).scss @@ -1,8 +1,13 @@ -<% if (filters.bootstrap) { %>$icon-font-path: "../bower_components/bootstrap-sass-official/vendor/assets/fonts/bootstrap/"; -@import '../bower_components/bootstrap-sass-official/vendor/assets/stylesheets/bootstrap'; -<% if(filters.oauth) { %>@import '../bower_components/bootstrap-social/bootstrap-social.scss'; -<% }} %>$fa-font-path: "../bower_components/font-awesome/fonts"; -@import '../bower_components/font-awesome/scss/font-awesome'; +<%_ if (filters.bootstrap) { _%> +$icon-font-path: '/assets/fonts/bootstrap/'; +@import '~bootstrap-sass/vendor/assets/stylesheets/bootstrap'; +<%_ if(filters.oauth) { _%> +@import '~bootstrap-social/bootstrap-social.scss'; +<% }} _%> +$fa-font-path: '/assets/fonts/font-awesome/'; +@import '~font-awesome/scss/font-awesome'; + +// @import url(http://fonts.googleapis.com/css?family=Open+Sans:300,400,600,900|Roboto:300,500,700,900); /** * App-wide Styles diff --git a/templates/app/client/app/app(stylus).styl b/templates/app/client/app/app(stylus).styl index ca1778ffd..0fc016ef5 100644 --- a/templates/app/client/app/app(stylus).styl +++ b/templates/app/client/app/app(stylus).styl @@ -1,32 +1,11 @@ -@import "../bower_components/font-awesome/css/font-awesome.css" -<% if (filters.bootstrap) { %>@import "../bower_components/bootstrap/dist/css/bootstrap.css" -<% if (filters.oauth) { %>@import "../bower_components/bootstrap-social/bootstrap-social.css" -<% } %> -// -// Bootstrap Fonts -// - -@font-face - font-family: 'Glyphicons Halflings' - src: url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot') - src: url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), - url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff') format('woff'), - url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf') format('truetype'), - url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); -<% } %> -// -// Font Awesome Fonts -// +$fa-font-path = '../assets/fonts/font-awesome/' +@import '~font-awesome-stylus/stylus/index' -@font-face - font-family: 'FontAwesome' - src: url('../bower_components/font-awesome/fonts/fontawesome-webfont.eot?v=4.1.0') - src: url('../bower_components/font-awesome/fonts/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'), - url('../bower_components/font-awesome/fonts/fontawesome-webfont.woff?v=4.1.0') format('woff'), - url('../bower_components/font-awesome/fonts/fontawesome-webfont.ttf?v=4.1.0') format('truetype'), - url('../bower_components/font-awesome/fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg'); - font-weight: normal - font-style: normal +<%_ if (filters.bootstrap) { %> +$icon-font-path = '../assets/fonts/bootstrap/' +@import '~bootstrap-styl/bootstrap/index'; +<% if (filters.oauth) { %>@import '~bootstrap-social/bootstrap-social.css' +<% } %><% } %> // // App-wide Styles diff --git a/templates/app/client/app/app.config.js b/templates/app/client/app/app.config.js new file mode 100644 index 000000000..3b3ea607b --- /dev/null +++ b/templates/app/client/app/app.config.js @@ -0,0 +1,15 @@ +'use strict'; + +export function routeConfig(<% if (filters.ngroute) { %>$routeProvider<% } if (filters.uirouter) { %>$urlRouterProvider<% } %>, $locationProvider) { + 'ngInject'; + <%_ if(filters.ngroute) { _%> + $routeProvider + .otherwise({ + redirectTo: '/' + });<% } %> + <%_ if(filters.uirouter) { _%> + $urlRouterProvider + .otherwise('/');<% } %> + + $locationProvider.html5Mode(true); +} diff --git a/templates/app/client/app/app.js b/templates/app/client/app/app.js index a9d9f2b09..d0b622947 100644 --- a/templates/app/client/app/app.js +++ b/templates/app/client/app/app.js @@ -1,13 +1,84 @@ 'use strict'; +import angular from 'angular'; +// import ngAnimate from 'angular-animate'; +import ngCookies from 'angular-cookies'; +import ngResource from 'angular-resource'; +import ngSanitize from 'angular-sanitize'; +<%_ if(filters.socketio) { _%> +import 'angular-socket-io';<% } %> +<%_ if(filters.ngroute) { _%> +const ngRoute = require('angular-route');<% } %> +<%_ if(filters.uirouter) { _%> +import uiRouter from 'angular-ui-router';<% } %> +<%_ if(filters.uibootstrap) { _%> +import uiBootstrap from 'angular-ui-bootstrap';<% } %> +// import ngMessages from 'angular-messages'; +<%_ if(filters.auth) { _%> +//import ngValidationMatch from 'angular-validation-match';<% } %> -angular.module('<%= scriptAppName %>', [<%- angularModules %>]) - .config(function(<% if (filters.ngroute) { %>$routeProvider<% } if (filters.uirouter) { %>$urlRouterProvider<% } %>, $locationProvider) {<% if (filters.ngroute) { %> - $routeProvider - .otherwise({ - redirectTo: '/' - });<% } if (filters.uirouter) { %> - $urlRouterProvider - .otherwise('/');<% } %> - $locationProvider.html5Mode(true); +import {routeConfig} from './app.config'; + +<%_ if(filters.auth) { _%> +import _Auth from '../components/auth/auth.module'; +import account from './account'; +import admin from './admin';<% } %> +import navbar from '../components/navbar/navbar.component'; +import footer from '../components/footer/footer.component'; +import main from './main/main.component'; +import './app.constant'; +import util from '../components/util/util.module'; +<%_ if(filters.socketio) { _%> +import socket from '../components/socket/socket.service';<% } %> + + +import './app.<%= styleExt %>'; + +angular.module('<%= scriptAppName %>', [ + // ngAnimate, + ngCookies, + ngResource, + ngSanitize, + <%_ if(filters.socketio) { %> + 'btford.socket-io',<% } %> + <%_ if(filters.ngroute) { %> + ngRoute,<% } _%> + <%_ if(filters.uirouter) { %> + uiRouter,<% } _%> + <%_ if(filters.uibootstrap) { %> + uiBootstrap,<% } %> + // ngMessages, + <%_ if(filters.auth) { %> + // ngValidationMatch, + _Auth, + account, + admin,<% } _%> + navbar, + footer, + main, + '<%= scriptAppName %>.constants', + <%_ if(filters.socketio) { _%> + socket,<% } %> + util +]) + .config(routeConfig) + <%_ if(filters.auth) { _%> + .run(function($rootScope, $location, Auth) { + 'ngInject'; + // Redirect to login if route requires auth and you're not logged in + $rootScope.$on('$stateChangeStart', function(event, next) { + Auth.isLoggedIn(function(loggedIn) { + if(next.authenticate && !loggedIn) { + $location.path('/login'); + } + }); + }); + })<% } %>; + +angular + .element(document) + .ready(() => { + angular.bootstrap(document, ['<%= scriptAppName %>'], { + strictDi: true + }); }); diff --git a/templates/app/client/app/main/main.component.js b/templates/app/client/app/main/main.component.js new file mode 100644 index 000000000..fab99e6a3 --- /dev/null +++ b/templates/app/client/app/main/main.component.js @@ -0,0 +1,52 @@ +import angular from 'angular'; +<%_ if(filters.ngroute) { _%> +const ngRoute = require('angular-route');<% } _%> +<%_ if(filters.uirouter) { _%> +import uiRouter from 'angular-ui-router';<% } _%> + +import routing from './main.routes'; + +export class MainController { + /*@ngInject*/ + constructor($http<% if(filters.socketio) { %>, $scope, socket<% } %>) { + this.$http = $http;<% if (filters.socketio) { %> + this.socket = socket;<% } %> + this.awesomeThings = []; + <%_ if (filters.socketio) { _%> + + $scope.$on('$destroy', function() { + socket.unsyncUpdates('thing'); + });<% } %> + } + + $onInit() { + this.$http.get('/api/things').then(response => { + this.awesomeThings = response.data;<% if (filters.socketio) { %> + this.socket.syncUpdates('thing', this.awesomeThings);<% } %> + }); + }<% if (filters.models) { %> + + addThing() { + if (this.newThing) { + this.$http.post('/api/things', { name: this.newThing }); + this.newThing = ''; + } + } + + deleteThing(thing) { + this.$http.delete('/api/things/' + thing._id); + }<% } %> +} + +export default angular.module('<%= scriptAppName %>.main', [ + <%_ if(filters.ngroute) { _%> + ngRoute<% } _%> + <%_ if(filters.uirouter) { _%> + uiRouter<% } _%> +]) + .config(routing) + .component('main', { + template: require('./main.<%= templateExt %>'), + controller: MainController + }) + .name; diff --git a/templates/app/client/app/main/main.controller.spec.js b/templates/app/client/app/main/main.component.spec.js similarity index 75% rename from templates/app/client/app/main/main.controller.spec.js rename to templates/app/client/app/main/main.component.spec.js index 67982faa0..ac10b1c54 100644 --- a/templates/app/client/app/main/main.controller.spec.js +++ b/templates/app/client/app/main/main.component.spec.js @@ -1,11 +1,15 @@ 'use strict'; -describe('Component: mainComponent', function() { +import main from './main.component'; +import {MainController} from './main.component'; - // load the controller's module - beforeEach(module('<%= scriptAppName %>'));<% if (filters.uirouter) {%> - beforeEach(module('stateMock'));<% } %><% if (filters.socketio) {%> - beforeEach(module('socketMock'));<% } %> +describe('Component: MainComponent', function() { + + beforeEach(angular.mock.module(main)); + <%_ if (filters.uirouter) { _%> + beforeEach(angular.mock.module('stateMock'));<% } _%> + <%_ if (filters.socketio) { _%> + beforeEach(angular.mock.module('socketMock'));<% } %> var scope; var mainComponent;<% if (filters.uirouter) {%> diff --git a/templates/app/client/app/main/main.controller.js b/templates/app/client/app/main/main.controller.js deleted file mode 100644 index 02f408164..000000000 --- a/templates/app/client/app/main/main.controller.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; - -(function() { - -class MainController { - - constructor($http<% if (filters.socketio) { %>, $scope, socket<% } %>) { - this.$http = $http;<% if (filters.socketio) { %> - this.socket = socket;<% } %> - this.awesomeThings = [];<% if (filters.socketio) { %> - - $scope.$on('$destroy', function() { - socket.unsyncUpdates('thing'); - });<% } %> - } - - $onInit() { - this.$http.get('/api/things').then(response => { - this.awesomeThings = response.data;<% if (filters.socketio) { %> - this.socket.syncUpdates('thing', this.awesomeThings);<% } %> - }); - }<% if (filters.models) { %> - - addThing() { - if (this.newThing) { - this.$http.post('/api/things', { name: this.newThing }); - this.newThing = ''; - } - } - - deleteThing(thing) { - this.$http.delete('/api/things/' + thing._id); - }<% } %> -} - -angular.module('<%= scriptAppName %>') - .component('main', { - templateUrl: 'app/main/main.html', - controller: MainController - }); - -})(); diff --git a/templates/app/client/app/main/main.js b/templates/app/client/app/main/main.js deleted file mode 100644 index 9d5f59887..000000000 --- a/templates/app/client/app/main/main.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -angular.module('<%= scriptAppName %>') - <% if (filters.ngroute) { %>.config(function($routeProvider) { - $routeProvider - .when('/', { - template: '
' - }); - });<% } %><% if (filters.uirouter) { %>.config(function($stateProvider) { - $stateProvider - .state('main', { - url: '/', - template: '
' - }); - });<% } %> diff --git a/templates/app/client/app/main/main.routes.js b/templates/app/client/app/main/main.routes.js new file mode 100644 index 000000000..95c7968a9 --- /dev/null +++ b/templates/app/client/app/main/main.routes.js @@ -0,0 +1,19 @@ +'use strict'; + +<%_ if(filters.ngroute) { _%> +export default function routes($routeProvider) { + 'ngInject'; + $routeProvider + .when('/', { + template: '
' + }); +};<% } %> +<%_ if(filters.uirouter) { _%> +export default function routes($stateProvider) { + 'ngInject'; + $stateProvider + .state('main', { + url: '/', + template: '
' + }); +};<% } %> diff --git a/templates/app/client/components/auth(auth)/auth.module.js b/templates/app/client/components/auth(auth)/auth.module.js index 60ce6e321..a4f22d887 100644 --- a/templates/app/client/components/auth(auth)/auth.module.js +++ b/templates/app/client/components/auth(auth)/auth.module.js @@ -1,12 +1,32 @@ 'use strict'; +import angular from 'angular'; +// import constants from '../../app/app.constant'; +import util from '../util/util.module'; +import ngCookies from 'angular-cookies'; +import {authInterceptor} from './interceptor.service'; +import {routerDecorator} from './router.decorator'; +import {AuthService} from './auth.service'; +import {UserResource} from './user.service'; +<%_ if (filters.ngroute) { _%> +const ngRoute = require('angular-route');<% } %> +<%_ if (filters.uirouter) { _%> +import uiRouter from 'angular-ui-router';<% } %> -angular.module('<%= scriptAppName %>.auth', [ +function addInterceptor($httpProvider) { + 'ngInject'; + $httpProvider.interceptors.push('authInterceptor'); +} + +export default angular.module('<%= scriptAppName %>.auth', [ '<%= scriptAppName %>.constants', - '<%= scriptAppName %>.util', - 'ngCookies'<% if (filters.ngroute) { %>, - 'ngRoute'<% } if (filters.uirouter) { %>, - 'ui.router'<% } %> + util, + ngCookies<% if(filters.ngroute) { %>, + ngRoute<% } if(filters.uirouter) { %>, + uiRouter<% } %> ]) - .config(function($httpProvider) { - $httpProvider.interceptors.push('authInterceptor'); - }); + .factory('authInterceptor', authInterceptor) + .run(routerDecorator) + .factory('Auth', AuthService) + .factory('User', UserResource) + .config(['$httpProvider', addInterceptor]) + .name; diff --git a/templates/app/client/components/auth(auth)/auth.service.js b/templates/app/client/components/auth(auth)/auth.service.js index 3a75c5a9a..08a91603a 100644 --- a/templates/app/client/components/auth(auth)/auth.service.js +++ b/templates/app/client/components/auth(auth)/auth.service.js @@ -1,8 +1,8 @@ 'use strict'; +// @flow -(function() { - -function AuthService($location, $http, $cookies, $q, appConfig, Util, User) { +export function AuthService($location, $http, $cookies, $q, appConfig, Util, User) { + 'ngInject'; var safeCb = Util.safeCb; var currentUser = {}; var userRoles = appConfig.userRoles || []; @@ -182,8 +182,3 @@ function AuthService($location, $http, $cookies, $q, appConfig, Util, User) { return Auth; } - -angular.module('<%= scriptAppName %>.auth') - .factory('Auth', AuthService); - -})(); diff --git a/templates/app/client/components/auth(auth)/interceptor.service.js b/templates/app/client/components/auth(auth)/interceptor.service.js index 72c3441b0..e868b8924 100644 --- a/templates/app/client/components/auth(auth)/interceptor.service.js +++ b/templates/app/client/components/auth(auth)/interceptor.service.js @@ -1,10 +1,10 @@ 'use strict'; -(function() { - -function authInterceptor($rootScope, $q, $cookies<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>, Util) { - <% if (filters.uirouter) { %>var state; - <% } %>return { +export function authInterceptor($rootScope, $q, $cookies<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>, Util) { + 'ngInject'; + <%_ if (filters.uirouter) { _%> + var state;<% } %> + return { // Add authorization token to headers request(config) { config.headers = config.headers || {}; @@ -17,7 +17,10 @@ function authInterceptor($rootScope, $q, $cookies<% if (filters.ngroute) { %>, $ // Intercept 401s and redirect you to login responseError(response) { if (response.status === 401) { - <% if (filters.ngroute) { %>$location.path('/login');<% } if (filters.uirouter) { %>(state || (state = $injector.get('$state'))).go('login');<% } %> + <%_ if (filters.ngroute) { _%> + $location.path('/login');<% } %> + <%_ if (filters.uirouter) { _%> + (state || (state = $injector.get('$state'))).go('login');<% } %> // remove any stale tokens $cookies.remove('token'); } @@ -25,8 +28,3 @@ function authInterceptor($rootScope, $q, $cookies<% if (filters.ngroute) { %>, $ } }; } - -angular.module('<%= scriptAppName %>.auth') - .factory('authInterceptor', authInterceptor); - -})(); diff --git a/templates/app/client/components/auth(auth)/router.decorator.js b/templates/app/client/components/auth(auth)/router.decorator.js index 752ad0720..5c135293b 100644 --- a/templates/app/client/components/auth(auth)/router.decorator.js +++ b/templates/app/client/components/auth(auth)/router.decorator.js @@ -1,39 +1,40 @@ 'use strict'; +import * as _ from 'lodash'; -(function() { +export function routerDecorator($rootScope<% if(filters.ngroute) { %>, $location<% } if(filters.uirouter) { %>, $state<% } %>, Auth) { + 'ngInject'; + // Redirect to login if route requires auth and the user is not logged in, or doesn't have required role + $rootScope.$on(<% if(filters.ngroute) { %>'$routeChangeStart'<% } %><% if(filters.uirouter) { %>'$stateChangeStart'<% } %>, function(event, next) { + if(!next.authenticate) { + return; + } -angular.module('<%= scriptAppName %>.auth') - .run(function($rootScope<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $state<% } %>, Auth) { - // Redirect to login if route requires auth and the user is not logged in, or doesn't have required role - $rootScope.$on(<% if (filters.ngroute) { %>'$routeChangeStart'<% } %><% if (filters.uirouter) { %>'$stateChangeStart'<% } %>, function(event, next) { - if (!next.authenticate) { - return; - } + if(typeof next.authenticate === 'string') { + Auth.hasRole(next.authenticate, _.noop).then(has => { + if(has) { + return; + } - if (typeof next.authenticate === 'string') { - Auth.hasRole(next.authenticate, _.noop).then(has => { - if (has) { - return; - } - - event.preventDefault(); - return Auth.isLoggedIn(_.noop).then(is => {<% if (filters.ngroute) { %> - $location.path(is ? '/' : '/login');<% } if (filters.uirouter) { %> - $state.go(is ? 'main' : 'login');<% } %> - }); + event.preventDefault(); + return Auth.isLoggedIn(_.noop).then(is => { + <%_ if(filters.ngroute) { _%> + $location.path(is ? '/' : '/login');<% } %> + <%_ if(filters.uirouter) { _%> + $state.go(is ? 'main' : 'login');<% } %> }); - } else { - Auth.isLoggedIn(_.noop).then(is => { - if (is) { - return; - } + }); + } else { + Auth.isLoggedIn(_.noop).then(is => { + if(is) { + return; + } - event.preventDefault();<% if (filters.ngroute) { %> - $location.path('/login');<% } if (filters.uirouter) { %> - $state.go('login');<% } %> - }); - } - }); + event.preventDefault(); + <%_ if(filters.ngroute) { _%> + $location.path('/login');<% } %> + <%_ if(filters.uirouter) { _%> + $state.go('login');<% } %> + }); + } }); - -})(); +}; diff --git a/templates/app/client/components/auth(auth)/user.service.js b/templates/app/client/components/auth(auth)/user.service.js index 63f4040d0..a458a89a2 100644 --- a/templates/app/client/components/auth(auth)/user.service.js +++ b/templates/app/client/components/auth(auth)/user.service.js @@ -1,8 +1,7 @@ 'use strict'; -(function() { - -function UserResource($resource) { +export function UserResource($resource) { + 'ngInject'; return $resource('/api/users/:id/:controller', { id: '@_id' }, { @@ -20,8 +19,3 @@ function UserResource($resource) { } }); } - -angular.module('<%= scriptAppName %>.auth') - .factory('User', UserResource); - -})(); diff --git a/templates/app/client/components/footer/footer.component.js b/templates/app/client/components/footer/footer.component.js new file mode 100644 index 000000000..88b9312a7 --- /dev/null +++ b/templates/app/client/components/footer/footer.component.js @@ -0,0 +1,10 @@ +import angular from 'angular'; + +export class FooterComponent {} + +export default angular.module('directives.footer', []) + .component('footer', { + template: require('./footer.<%= templateExt %>'), + controller: FooterComponent + }) + .name; diff --git a/templates/app/client/components/footer/footer.directive.js b/templates/app/client/components/footer/footer.directive.js deleted file mode 100644 index 9ed31900c..000000000 --- a/templates/app/client/components/footer/footer.directive.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -angular.module('<%= scriptAppName %>') - .directive('footer', function() { - return { - templateUrl: 'components/footer/footer.html', - restrict: 'E', - link: function(scope, element) { - element.addClass('footer'); - } - }; - }); diff --git a/templates/app/client/components/modal(uibootstrap)/modal.service.js b/templates/app/client/components/modal(uibootstrap)/modal.service.js index d7807e6b5..91d94894c 100644 --- a/templates/app/client/components/modal(uibootstrap)/modal.service.js +++ b/templates/app/client/components/modal(uibootstrap)/modal.service.js @@ -1,73 +1,76 @@ 'use strict'; -angular.module('<%= scriptAppName %>') - .factory('Modal', function($rootScope, $uibModal) { - /** - * Opens a modal - * @param {Object} scope - an object to be merged with modal's scope - * @param {String} modalClass - (optional) class(es) to be applied to the modal - * @return {Object} - the instance $uibModal.open() returns - */ - function openModal(scope = {}, modalClass = 'modal-default') { - var modalScope = $rootScope.$new(); +export function Modal($rootScope, $uibModal) { + /** + * Opens a modal + * @param {Object} scope - an object to be merged with modal's scope + * @param {String} modalClass - (optional) class(es) to be applied to the modal + * @return {Object} - the instance $uibModal.open() returns + */ + function openModal(scope = {}, modalClass = 'modal-default') { + var modalScope = $rootScope.$new(); - angular.extend(modalScope, scope); + angular.extend(modalScope, scope); - return $uibModal.open({ - templateUrl: 'components/modal/modal.html', - windowClass: modalClass, - scope: modalScope - }); - } + return $uibModal.open({ + template: require('./modal.<%= templateExt %>'), + windowClass: modalClass, + scope: modalScope + }); + } - // Public API here - return { + // Public API here + return { - /* Confirmation modals */ - confirm: { + /* Confirmation modals */ + confirm: { + /** + * Create a function to open a delete confirmation modal (ex. ng-click='myModalFn(name, arg1, arg2...)') + * @param {Function} del - callback, ran when delete is confirmed + * @return {Function} - the function to open the modal (ex. myModalFn) + */ + delete(del = angular.noop) { /** - * Create a function to open a delete confirmation modal (ex. ng-click='myModalFn(name, arg1, arg2...)') - * @param {Function} del - callback, ran when delete is confirmed - * @return {Function} - the function to open the modal (ex. myModalFn) + * Open a delete confirmation modal + * @param {String} name - name or info to show on modal + * @param {All} - any additional args are passed straight to del callback */ - delete(del = angular.noop) { - /** - * Open a delete confirmation modal - * @param {String} name - name or info to show on modal - * @param {All} - any additional args are passed straight to del callback - */ - return function() { - var args = Array.prototype.slice.call(arguments), - name = args.shift(), - deleteModal; + return function() { + var args = Array.prototype.slice.call(arguments), + name = args.shift(), + deleteModal; - deleteModal = openModal({ - modal: { - dismissable: true, - title: 'Confirm Delete', - html: '

Are you sure you want to delete ' + name + ' ?

', - buttons: [{ - classes: 'btn-danger', - text: 'Delete', - click: function(e) { - deleteModal.close(e); - } - }, { - classes: 'btn-default', - text: 'Cancel', - click: function(e) { - deleteModal.dismiss(e); - } - }] - } - }, 'modal-danger'); + deleteModal = openModal({ + modal: { + dismissable: true, + title: 'Confirm Delete', + html: '

Are you sure you want to delete ' + name + ' ?

', + buttons: [{ + classes: 'btn-danger', + text: 'Delete', + click: function(e) { + deleteModal.close(e); + } + }, { + classes: 'btn-default', + text: 'Cancel', + click: function(e) { + deleteModal.dismiss(e); + } + }] + } + }, 'modal-danger'); - deleteModal.result.then(function(event) { - del.apply(event, args); - }); - }; - } + deleteModal.result.then(function(event) { + del.apply(event, args); + }); + }; } - }; - }); + } + }; +} + +export default angular.module('<%= scriptAppName %>') + .factory('Modal', Modal) + .name; diff --git a/templates/app/client/components/navbar/navbar(html).html b/templates/app/client/components/navbar/navbar(html).html index 4b6692d36..79d7b5a78 100644 --- a/templates/app/client/components/navbar/navbar(html).html +++ b/templates/app/client/components/navbar/navbar(html).html @@ -1,7 +1,7 @@ -