Add initial Angular boilerplate files.
Adds boilerplate files from `angularjs-gulp-browserify-boilerplate` to start work on Angular rewrite of the frontend. Change-Id: I54392c24f397496582f9d06d561d5c14a92ccbe6
This commit is contained in:
parent
80ae14c030
commit
0034283601
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,6 +1,9 @@
|
||||
# Project-specific ignores
|
||||
.idea
|
||||
stackviz/static/components/*
|
||||
node_modules
|
||||
build
|
||||
app/js/templates.js
|
||||
*.py[cod]
|
||||
|
||||
# C extensions
|
||||
|
20
.jshintrc
Normal file
20
.jshintrc
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"node": true,
|
||||
"jasmine": true,
|
||||
"browser": true,
|
||||
"esnext": true,
|
||||
"bitwise": true,
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
"immed": true,
|
||||
"indent": 2,
|
||||
"latedef": true,
|
||||
"noarg": true,
|
||||
"regexp": true,
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"strict": true,
|
||||
"trailing": true,
|
||||
"smarttabs": true,
|
||||
"newcap": false
|
||||
}
|
BIN
app/images/angular.png
Normal file
BIN
app/images/angular.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
BIN
app/images/browserify.png
Normal file
BIN
app/images/browserify.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
BIN
app/images/gulp.png
Normal file
BIN
app/images/gulp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
19
app/index.html
Normal file
19
app/index.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html class="no-js">
|
||||
<head>
|
||||
<base href="/">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title ng-bind="pageTitle"></title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<link rel="stylesheet" href="css/main.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div ui-view></div>
|
||||
|
||||
<script src="js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
8
app/js/constants.js
Normal file
8
app/js/constants.js
Normal file
@ -0,0 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
var AppSettings = {
|
||||
appTitle: 'Example Application',
|
||||
apiUrl: '/api/v1'
|
||||
};
|
||||
|
||||
module.exports = AppSettings;
|
8
app/js/controllers/_index.js
Normal file
8
app/js/controllers/_index.js
Normal file
@ -0,0 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
var angular = require('angular');
|
||||
var bulk = require('bulk-require');
|
||||
|
||||
module.exports = angular.module('app.controllers', []);
|
||||
|
||||
bulk(__dirname, ['./**/!(*_index|*.spec).js']);
|
18
app/js/controllers/example.js
Normal file
18
app/js/controllers/example.js
Normal file
@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
var controllersModule = require('./_index');
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
function ExampleCtrl() {
|
||||
|
||||
// ViewModel
|
||||
var vm = this;
|
||||
|
||||
vm.title = 'AngularJS, Gulp, and Browserify!';
|
||||
vm.number = 1234;
|
||||
|
||||
}
|
||||
|
||||
controllersModule.controller('ExampleCtrl', ExampleCtrl);
|
8
app/js/directives/_index.js
Normal file
8
app/js/directives/_index.js
Normal file
@ -0,0 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
var angular = require('angular');
|
||||
var bulk = require('bulk-require');
|
||||
|
||||
module.exports = angular.module('app.directives', []);
|
||||
|
||||
bulk(__dirname, ['./**/!(*_index|*.spec).js']);
|
21
app/js/directives/example.js
Normal file
21
app/js/directives/example.js
Normal file
@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
var directivesModule = require('./_index.js');
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
function exampleDirective() {
|
||||
|
||||
return {
|
||||
restrict: 'EA',
|
||||
link: function(scope, element) {
|
||||
element.on('click', function() {
|
||||
console.log('element clicked');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
directivesModule.directive('exampleDirective', exampleDirective);
|
34
app/js/main.js
Normal file
34
app/js/main.js
Normal file
@ -0,0 +1,34 @@
|
||||
'use strict';
|
||||
|
||||
var angular = require('angular');
|
||||
|
||||
// angular modules
|
||||
require('angular-ui-router');
|
||||
require('./templates');
|
||||
require('./controllers/_index');
|
||||
require('./services/_index');
|
||||
require('./directives/_index');
|
||||
|
||||
// create and bootstrap application
|
||||
angular.element(document).ready(function() {
|
||||
|
||||
var requires = [
|
||||
'ui.router',
|
||||
'templates',
|
||||
'app.controllers',
|
||||
'app.services',
|
||||
'app.directives'
|
||||
];
|
||||
|
||||
// mount on window for testing
|
||||
window.app = angular.module('app', requires);
|
||||
|
||||
angular.module('app').constant('AppSettings', require('./constants'));
|
||||
|
||||
angular.module('app').config(require('./on_config'));
|
||||
|
||||
angular.module('app').run(require('./on_run'));
|
||||
|
||||
angular.bootstrap(document, ['app']);
|
||||
|
||||
});
|
22
app/js/on_config.js
Normal file
22
app/js/on_config.js
Normal file
@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
function OnConfig($stateProvider, $locationProvider, $urlRouterProvider) {
|
||||
|
||||
$locationProvider.html5Mode(true);
|
||||
|
||||
$stateProvider
|
||||
.state('Home', {
|
||||
url: '/',
|
||||
controller: 'ExampleCtrl as home',
|
||||
templateUrl: 'home.html',
|
||||
title: 'Home'
|
||||
});
|
||||
|
||||
$urlRouterProvider.otherwise('/');
|
||||
|
||||
}
|
||||
|
||||
module.exports = OnConfig;
|
22
app/js/on_run.js
Normal file
22
app/js/on_run.js
Normal file
@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
function OnRun($rootScope, AppSettings) {
|
||||
|
||||
// change page title based on state
|
||||
$rootScope.$on('$stateChangeSuccess', function(event, toState) {
|
||||
$rootScope.pageTitle = '';
|
||||
|
||||
if ( toState.title ) {
|
||||
$rootScope.pageTitle += toState.title;
|
||||
$rootScope.pageTitle += ' \u2014 ';
|
||||
}
|
||||
|
||||
$rootScope.pageTitle += AppSettings.appTitle;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
module.exports = OnRun;
|
8
app/js/services/_index.js
Normal file
8
app/js/services/_index.js
Normal file
@ -0,0 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
var angular = require('angular');
|
||||
var bulk = require('bulk-require');
|
||||
|
||||
module.exports = angular.module('app.services', []);
|
||||
|
||||
bulk(__dirname, ['./**/!(*_index|*.spec).js']);
|
28
app/js/services/example.js
Normal file
28
app/js/services/example.js
Normal file
@ -0,0 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
var servicesModule = require('./_index.js');
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
function ExampleService($q, $http) {
|
||||
|
||||
var service = {};
|
||||
|
||||
service.get = function() {
|
||||
var deferred = $q.defer();
|
||||
|
||||
$http.get('apiPath').success(function(data) {
|
||||
deferred.resolve(data);
|
||||
}).error(function(err, status) {
|
||||
deferred.reject(err, status);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}
|
||||
|
||||
servicesModule.service('ExampleService', ExampleService);
|
42
app/styles/_typography.scss
Normal file
42
app/styles/_typography.scss
Normal file
@ -0,0 +1,42 @@
|
||||
p {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.heading {
|
||||
margin-bottom: 0.618em;
|
||||
|
||||
&.-large {
|
||||
font-size: $font-size--lg;
|
||||
font-weight: bold;
|
||||
line-height: $half-space * 3 / 2;
|
||||
}
|
||||
|
||||
&.-medium {
|
||||
font-size: $font-size--md;
|
||||
font-weight: normal;
|
||||
line-height: $half-space;
|
||||
}
|
||||
|
||||
&.-small {
|
||||
font-size: $font-size--sm;
|
||||
font-weight: bold;
|
||||
line-height: $half-space * 2 / 3;
|
||||
}
|
||||
|
||||
&.-smallest {
|
||||
font-size: $font-size--xs;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
@extend .heading.-large;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@extend .heading.-medium;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@extend .heading.-small;
|
||||
}
|
19
app/styles/_vars.scss
Normal file
19
app/styles/_vars.scss
Normal file
@ -0,0 +1,19 @@
|
||||
// colors
|
||||
$font-color--dark: #333;
|
||||
$font-color--light: #fff;
|
||||
$background--light: #eee;
|
||||
$background--dark: #222;
|
||||
$blue: #1f8de2;
|
||||
$green: #1fe27b;
|
||||
$red: #e21f3f;
|
||||
|
||||
// spacing
|
||||
$full-space: 40px;
|
||||
$half-space: 20px;
|
||||
|
||||
// font sizing
|
||||
$font-size--xs: 10px;
|
||||
$font-size--sm: 12px;
|
||||
$font-size--md: 16px;
|
||||
$font-size--lg: 24px;
|
||||
$font-size--xl: 32px;
|
9
app/styles/main.scss
Normal file
9
app/styles/main.scss
Normal file
@ -0,0 +1,9 @@
|
||||
@import 'vars';
|
||||
@import 'typography';
|
||||
|
||||
body {
|
||||
font-family: Helvetica, sans-serif;
|
||||
color: $font-color--dark;
|
||||
background-color: $background--light;
|
||||
padding: $half-space;
|
||||
}
|
7
app/views/home.html
Normal file
7
app/views/home.html
Normal file
@ -0,0 +1,7 @@
|
||||
<h1 class="heading -large">{{ home.title }}</h1>
|
||||
|
||||
<h3 class="heading -medium">Here is a fancy number served up courtesy of Angular: <span class="number-example">{{ home.number }}</span></h3>
|
||||
|
||||
<img src="images/angular.png" height="100" example-directive />
|
||||
<img src="images/gulp.png" height="100" />
|
||||
<img src="images/browserify.png" height="100" />
|
23
gulp/LICENSE
Normal file
23
gulp/LICENSE
Normal file
@ -0,0 +1,23 @@
|
||||
Imported from https://github.com/jakemmarsh/angularjs-gulp-browserify-boilerplate :
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Jake Marsh
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
59
gulp/config.js
Normal file
59
gulp/config.js
Normal file
@ -0,0 +1,59 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
|
||||
'browserPort' : 3000,
|
||||
'UIPort' : 3001,
|
||||
'serverPort' : 3002,
|
||||
|
||||
'styles': {
|
||||
'src' : 'app/styles/**/*.scss',
|
||||
'dest': 'build/css'
|
||||
},
|
||||
|
||||
'scripts': {
|
||||
'src' : 'app/js/**/*.js',
|
||||
'dest': 'build/js'
|
||||
},
|
||||
|
||||
'images': {
|
||||
'src' : 'app/images/**/*',
|
||||
'dest': 'build/images'
|
||||
},
|
||||
|
||||
'fonts': {
|
||||
'src' : ['app/fonts/**/*'],
|
||||
'dest': 'build/fonts'
|
||||
},
|
||||
|
||||
'views': {
|
||||
'watch': [
|
||||
'app/index.html',
|
||||
'app/views/**/*.html'
|
||||
],
|
||||
'src': 'app/views/**/*.html',
|
||||
'dest': 'app/js'
|
||||
},
|
||||
|
||||
'gzip': {
|
||||
'src': 'build/**/*.{html,xml,json,css,js,js.map}',
|
||||
'dest': 'build/',
|
||||
'options': {}
|
||||
},
|
||||
|
||||
'dist': {
|
||||
'root' : 'build'
|
||||
},
|
||||
|
||||
'browserify': {
|
||||
'entries' : ['./app/js/main.js'],
|
||||
'bundleName': 'main.js',
|
||||
'sourcemap' : true
|
||||
},
|
||||
|
||||
'test': {
|
||||
'karma': 'test/karma.conf.js',
|
||||
'protractor': 'test/protractor.conf.js'
|
||||
}
|
||||
|
||||
};
|
9
gulp/index.js
Normal file
9
gulp/index.js
Normal file
@ -0,0 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
var fs = require('fs');
|
||||
var onlyScripts = require('./util/scriptFilter');
|
||||
var tasks = fs.readdirSync('./gulp/tasks/').filter(onlyScripts);
|
||||
|
||||
tasks.forEach(function(task) {
|
||||
require('./tasks/' + task);
|
||||
});
|
17
gulp/tasks/browserSync.js
Normal file
17
gulp/tasks/browserSync.js
Normal file
@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
var config = require('../config');
|
||||
var browserSync = require('browser-sync');
|
||||
var gulp = require('gulp');
|
||||
|
||||
gulp.task('browserSync', function() {
|
||||
|
||||
browserSync({
|
||||
port: config.browserPort,
|
||||
ui: {
|
||||
port: config.UIPort
|
||||
},
|
||||
proxy: 'localhost:' + config.serverPort
|
||||
});
|
||||
|
||||
});
|
76
gulp/tasks/browserify.js
Normal file
76
gulp/tasks/browserify.js
Normal file
@ -0,0 +1,76 @@
|
||||
'use strict';
|
||||
|
||||
var config = require('../config');
|
||||
var gulp = require('gulp');
|
||||
var gulpif = require('gulp-if');
|
||||
var gutil = require('gulp-util');
|
||||
var source = require('vinyl-source-stream');
|
||||
var sourcemaps = require('gulp-sourcemaps');
|
||||
var buffer = require('vinyl-buffer');
|
||||
var streamify = require('gulp-streamify');
|
||||
var watchify = require('watchify');
|
||||
var browserify = require('browserify');
|
||||
var babelify = require('babelify');
|
||||
var uglify = require('gulp-uglify');
|
||||
var handleErrors = require('../util/handleErrors');
|
||||
var browserSync = require('browser-sync');
|
||||
var debowerify = require('debowerify');
|
||||
var ngAnnotate = require('browserify-ngannotate');
|
||||
|
||||
// Based on: http://blog.avisi.nl/2014/04/25/how-to-keep-a-fast-build-with-browserify-and-reactjs/
|
||||
function buildScript(file) {
|
||||
|
||||
var bundler = browserify({
|
||||
entries: config.browserify.entries,
|
||||
debug: true,
|
||||
cache: {},
|
||||
packageCache: {},
|
||||
fullPaths: true
|
||||
}, watchify.args);
|
||||
|
||||
if ( !global.isProd ) {
|
||||
bundler = watchify(bundler);
|
||||
bundler.on('update', function() {
|
||||
rebundle();
|
||||
});
|
||||
}
|
||||
|
||||
var transforms = [
|
||||
babelify,
|
||||
debowerify,
|
||||
ngAnnotate,
|
||||
'brfs',
|
||||
'bulkify'
|
||||
];
|
||||
|
||||
transforms.forEach(function(transform) {
|
||||
bundler.transform(transform);
|
||||
});
|
||||
|
||||
function rebundle() {
|
||||
var stream = bundler.bundle();
|
||||
var createSourcemap = global.isProd && config.browserify.sourcemap;
|
||||
|
||||
gutil.log('Rebundle...');
|
||||
|
||||
return stream.on('error', handleErrors)
|
||||
.pipe(source(file))
|
||||
.pipe(gulpif(createSourcemap, buffer()))
|
||||
.pipe(gulpif(createSourcemap, sourcemaps.init()))
|
||||
.pipe(gulpif(global.isProd, streamify(uglify({
|
||||
compress: { drop_console: true }
|
||||
}))))
|
||||
.pipe(gulpif(createSourcemap, sourcemaps.write('./')))
|
||||
.pipe(gulp.dest(config.scripts.dest))
|
||||
.pipe(browserSync.reload({ stream: true, once: true }));
|
||||
}
|
||||
|
||||
return rebundle();
|
||||
|
||||
}
|
||||
|
||||
gulp.task('browserify', function() {
|
||||
|
||||
return buildScript('main.js');
|
||||
|
||||
});
|
11
gulp/tasks/clean.js
Normal file
11
gulp/tasks/clean.js
Normal file
@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
var config = require('../config');
|
||||
var gulp = require('gulp');
|
||||
var del = require('del');
|
||||
|
||||
gulp.task('clean', function(cb) {
|
||||
|
||||
del([config.dist.root], cb);
|
||||
|
||||
});
|
9
gulp/tasks/deploy.js
Normal file
9
gulp/tasks/deploy.js
Normal file
@ -0,0 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
var gulp = require('gulp');
|
||||
|
||||
gulp.task('deploy', ['prod'], function() {
|
||||
|
||||
// Any deployment logic should go here
|
||||
|
||||
});
|
14
gulp/tasks/development.js
Normal file
14
gulp/tasks/development.js
Normal file
@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
var gulp = require('gulp');
|
||||
var runSequence = require('run-sequence');
|
||||
|
||||
gulp.task('dev', ['clean'], function(cb) {
|
||||
|
||||
cb = cb || function() {};
|
||||
|
||||
global.isProd = false;
|
||||
|
||||
runSequence(['styles', 'images', 'fonts', 'views', 'browserify'], 'watch', cb);
|
||||
|
||||
});
|
15
gulp/tasks/fonts.js
Normal file
15
gulp/tasks/fonts.js
Normal file
@ -0,0 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
var config = require('../config');
|
||||
var changed = require('gulp-changed');
|
||||
var gulp = require('gulp');
|
||||
var browserSync = require('browser-sync');
|
||||
|
||||
gulp.task('fonts', function() {
|
||||
|
||||
return gulp.src(config.fonts.src)
|
||||
.pipe(changed(config.fonts.dest)) // Ignore unchanged files
|
||||
.pipe(gulp.dest(config.fonts.dest))
|
||||
.pipe(browserSync.reload({ stream: true, once: true }));
|
||||
|
||||
});
|
13
gulp/tasks/gzip.js
Normal file
13
gulp/tasks/gzip.js
Normal file
@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
var gulp = require('gulp');
|
||||
var gzip = require('gulp-gzip');
|
||||
var config = require('../config');
|
||||
|
||||
gulp.task('gzip', function() {
|
||||
|
||||
return gulp.src(config.gzip.src)
|
||||
.pipe(gzip(config.gzip.options))
|
||||
.pipe(gulp.dest(config.gzip.dest));
|
||||
|
||||
});
|
18
gulp/tasks/images.js
Normal file
18
gulp/tasks/images.js
Normal file
@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
var config = require('../config');
|
||||
var changed = require('gulp-changed');
|
||||
var gulp = require('gulp');
|
||||
var gulpif = require('gulp-if');
|
||||
//var imagemin = require('gulp-imagemin');
|
||||
var browserSync = require('browser-sync');
|
||||
|
||||
gulp.task('images', function() {
|
||||
|
||||
return gulp.src(config.images.src)
|
||||
.pipe(changed(config.images.dest)) // Ignore unchanged files
|
||||
//.pipe(gulpif(global.isProd, imagemin())) // Optimize
|
||||
.pipe(gulp.dest(config.images.dest))
|
||||
.pipe(browserSync.reload({ stream: true, once: true }));
|
||||
|
||||
});
|
11
gulp/tasks/lint.js
Normal file
11
gulp/tasks/lint.js
Normal file
@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
var config = require('../config');
|
||||
var gulp = require('gulp');
|
||||
var jshint = require('gulp-jshint');
|
||||
|
||||
gulp.task('lint', function() {
|
||||
return gulp.src([config.scripts.src, '!app/js/templates.js'])
|
||||
.pipe(jshint())
|
||||
.pipe(jshint.reporter('jshint-stylish'));
|
||||
});
|
14
gulp/tasks/production.js
Normal file
14
gulp/tasks/production.js
Normal file
@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
var gulp = require('gulp');
|
||||
var runSequence = require('run-sequence');
|
||||
|
||||
gulp.task('prod', ['clean'], function(cb) {
|
||||
|
||||
cb = cb || function() {};
|
||||
|
||||
global.isProd = true;
|
||||
|
||||
runSequence(['styles', 'images', 'fonts', 'views', 'browserify'], 'gzip', cb);
|
||||
|
||||
});
|
23
gulp/tasks/protractor.js
Normal file
23
gulp/tasks/protractor.js
Normal file
@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
var gulp = require('gulp');
|
||||
var protractor = require('gulp-protractor').protractor;
|
||||
var webdriver = require('gulp-protractor').webdriver;
|
||||
var webdriverUpdate = require('gulp-protractor').webdriver_update;
|
||||
var config = require('../config');
|
||||
|
||||
gulp.task('webdriver-update', webdriverUpdate);
|
||||
gulp.task('webdriver', webdriver);
|
||||
|
||||
gulp.task('protractor', ['webdriver-update', 'webdriver', 'server'], function() {
|
||||
|
||||
return gulp.src('test/e2e/**/*.js')
|
||||
.pipe(protractor({
|
||||
configFile: config.test.protractor
|
||||
}))
|
||||
.on('error', function(err) {
|
||||
// Make sure failed tests cause gulp to exit non-zero
|
||||
throw err;
|
||||
});
|
||||
|
||||
});
|
36
gulp/tasks/server.js
Normal file
36
gulp/tasks/server.js
Normal file
@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
var config = require('../config');
|
||||
var http = require('http');
|
||||
var express = require('express');
|
||||
var gulp = require('gulp');
|
||||
var gutil = require('gulp-util');
|
||||
var morgan = require('morgan');
|
||||
|
||||
gulp.task('server', function() {
|
||||
|
||||
var server = express();
|
||||
|
||||
// log all requests to the console
|
||||
server.use(morgan('dev'));
|
||||
server.use(express.static(config.dist.root));
|
||||
|
||||
// Serve index.html for all routes to leave routing up to Angular
|
||||
server.all('/*', function(req, res) {
|
||||
res.sendFile('index.html', { root: 'build' });
|
||||
});
|
||||
|
||||
// Start webserver if not already running
|
||||
var s = http.createServer(server);
|
||||
s.on('error', function(err){
|
||||
if(err.code === 'EADDRINUSE'){
|
||||
gutil.log('Development server is already started at port ' + config.serverPort);
|
||||
}
|
||||
else {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
|
||||
s.listen(config.serverPort);
|
||||
|
||||
});
|
24
gulp/tasks/styles.js
Normal file
24
gulp/tasks/styles.js
Normal file
@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
var config = require('../config');
|
||||
var gulp = require('gulp');
|
||||
var sass = require('gulp-sass');
|
||||
var gulpif = require('gulp-if');
|
||||
var handleErrors = require('../util/handleErrors');
|
||||
var browserSync = require('browser-sync');
|
||||
var autoprefixer = require('gulp-autoprefixer');
|
||||
|
||||
gulp.task('styles', function () {
|
||||
|
||||
return gulp.src(config.styles.src)
|
||||
.pipe(sass({
|
||||
sourceComments: global.isProd ? 'none' : 'map',
|
||||
sourceMap: 'sass',
|
||||
outputStyle: global.isProd ? 'compressed' : 'nested'
|
||||
}))
|
||||
.pipe(autoprefixer("last 2 versions", "> 1%", "ie 8"))
|
||||
.on('error', handleErrors)
|
||||
.pipe(gulp.dest(config.styles.dest))
|
||||
.pipe(browserSync.reload({ stream: true }));
|
||||
|
||||
});
|
10
gulp/tasks/test.js
Normal file
10
gulp/tasks/test.js
Normal file
@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
var gulp = require('gulp');
|
||||
var runSequence = require('run-sequence');
|
||||
|
||||
gulp.task('test', ['server'], function() {
|
||||
|
||||
return runSequence('unit', 'protractor');
|
||||
|
||||
});
|
21
gulp/tasks/unit.js
Normal file
21
gulp/tasks/unit.js
Normal file
@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
var gulp = require('gulp');
|
||||
var karma = require('gulp-karma');
|
||||
var config = require('../config');
|
||||
|
||||
gulp.task('unit', ['views'], function() {
|
||||
|
||||
// Nonsensical source to fall back to files listed in karma.conf.js,
|
||||
// see https://github.com/lazd/gulp-karma/issues/9
|
||||
return gulp.src('./thisdoesntexist')
|
||||
.pipe(karma({
|
||||
configFile: config.test.karma,
|
||||
action: 'run'
|
||||
}))
|
||||
.on('error', function(err) {
|
||||
// Make sure failed tests cause gulp to exit non-zero
|
||||
throw err;
|
||||
});
|
||||
|
||||
});
|
21
gulp/tasks/views.js
Normal file
21
gulp/tasks/views.js
Normal file
@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
var config = require('../config');
|
||||
var gulp = require('gulp');
|
||||
var templateCache = require('gulp-angular-templatecache');
|
||||
|
||||
// Views task
|
||||
gulp.task('views', function() {
|
||||
|
||||
// Put our index.html in the dist folder
|
||||
gulp.src('app/index.html')
|
||||
.pipe(gulp.dest(config.dist.root));
|
||||
|
||||
// Process any other view files from app/views
|
||||
return gulp.src(config.views.src)
|
||||
.pipe(templateCache({
|
||||
standalone: true
|
||||
}))
|
||||
.pipe(gulp.dest(config.views.dest));
|
||||
|
||||
});
|
15
gulp/tasks/watch.js
Normal file
15
gulp/tasks/watch.js
Normal file
@ -0,0 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
var config = require('../config');
|
||||
var gulp = require('gulp');
|
||||
|
||||
gulp.task('watch', ['browserSync', 'server'], function() {
|
||||
|
||||
// Scripts are automatically watched and rebundled by Watchify inside Browserify task
|
||||
gulp.watch(config.scripts.src, ['lint']);
|
||||
gulp.watch(config.styles.src, ['styles']);
|
||||
gulp.watch(config.images.src, ['images']);
|
||||
gulp.watch(config.fonts.src, ['fonts']);
|
||||
gulp.watch(config.views.watch, ['views']);
|
||||
|
||||
});
|
25
gulp/util/bundleLogger.js
Normal file
25
gulp/util/bundleLogger.js
Normal file
@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
/* bundleLogger
|
||||
* ------------
|
||||
* Provides gulp style logs to the bundle method in browserify.js
|
||||
*/
|
||||
|
||||
var gutil = require('gulp-util');
|
||||
var prettyHrtime = require('pretty-hrtime');
|
||||
var startTime;
|
||||
|
||||
module.exports = {
|
||||
|
||||
start: function() {
|
||||
startTime = process.hrtime();
|
||||
gutil.log('Running', gutil.colors.green('\'bundle\'') + '...');
|
||||
},
|
||||
|
||||
end: function() {
|
||||
var taskTime = process.hrtime(startTime);
|
||||
var prettyTime = prettyHrtime(taskTime);
|
||||
gutil.log('Finished', gutil.colors.green('\'bundle\''), 'in', gutil.colors.magenta(prettyTime));
|
||||
}
|
||||
|
||||
};
|
27
gulp/util/handleErrors.js
Normal file
27
gulp/util/handleErrors.js
Normal file
@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
var notify = require('gulp-notify');
|
||||
|
||||
module.exports = function(error) {
|
||||
|
||||
if( !global.isProd ) {
|
||||
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
|
||||
// Send error to notification center with gulp-notify
|
||||
notify.onError({
|
||||
title: 'Compile Error',
|
||||
message: '<%= error.message %>'
|
||||
}).apply(this, args);
|
||||
|
||||
// Keep gulp from hanging on this task
|
||||
this.emit('end');
|
||||
|
||||
} else {
|
||||
// Log the error and stop the process
|
||||
// to prevent broken code from building
|
||||
console.log(error);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
};
|
11
gulp/util/scriptFilter.js
Normal file
11
gulp/util/scriptFilter.js
Normal file
@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
|
||||
// Filters out non .js files. Prevents
|
||||
// accidental inclusion of possible hidden files
|
||||
module.exports = function(name) {
|
||||
|
||||
return /(\.(js)$)/i.test(path.extname(name));
|
||||
|
||||
};
|
16
gulpfile.js
Normal file
16
gulpfile.js
Normal file
@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
* gulpfile.js
|
||||
* ===========
|
||||
* Rather than manage one giant configuration file responsible
|
||||
* for creating multiple tasks, each task has been broken out into
|
||||
* its own file in gulp/tasks. Any file in that folder gets automatically
|
||||
* required by the loop in ./gulp/index.js (required below).
|
||||
*
|
||||
* To add a new task, simply add a new task file to gulp/tasks.
|
||||
*/
|
||||
|
||||
global.isProd = false;
|
||||
|
||||
require('./gulp');
|
46
package.json
46
package.json
@ -6,18 +6,62 @@
|
||||
"repository": "none",
|
||||
"license": "Apache 2.0",
|
||||
"devDependencies": {
|
||||
"angular": "^1.3.15",
|
||||
"angular-mocks": "^1.3.15",
|
||||
"angular-ui-router": "^0.2.13",
|
||||
"babelify": "^5.0.4",
|
||||
"brfs": "^1.2.0",
|
||||
"browser-sync": "^2.7.6",
|
||||
"browserify": "^5.10.0",
|
||||
"browserify-istanbul": "^0.2.0",
|
||||
"browserify-ngannotate": "^0.1.0",
|
||||
"bulk-require": "^0.2.1",
|
||||
"bulkify": "^1.1.1",
|
||||
"debowerify": "^1.2.0",
|
||||
"del": "^0.1.3",
|
||||
"eslint": "^0.23.0",
|
||||
"eslint-config-openstack": "1.2.0",
|
||||
"express": "^4.7.2",
|
||||
"gulp": "^3.8.8",
|
||||
"gulp-angular-templatecache": "^1.3.0",
|
||||
"gulp-autoprefixer": "^2.0.0",
|
||||
"gulp-changed": "^1.0.0",
|
||||
"gulp-gzip": "^0.0.8",
|
||||
"gulp-if": "^1.2.5",
|
||||
"gulp-imagemin": "^1.1.0",
|
||||
"gulp-jshint": "^1.8.3",
|
||||
"gulp-karma": "0.0.4",
|
||||
"gulp-notify": "^2.0.0",
|
||||
"gulp-protractor": "0.0.11",
|
||||
"gulp-rename": "^1.2.0",
|
||||
"gulp-sass": "^1.3.3",
|
||||
"gulp-sourcemaps": "^1.3.0",
|
||||
"gulp-streamify": "0.0.5",
|
||||
"gulp-uglify": "^1.0.1",
|
||||
"gulp-util": "^3.0.1",
|
||||
"isparta": "^3.0.3",
|
||||
"jasmine-ajax": "^3.1.1",
|
||||
"jasmine-core": "^2.3.4",
|
||||
"jasmine-fixture": "^1.3.2",
|
||||
"jshint-stylish": "^1.0.0",
|
||||
"karma": "^0.13.4",
|
||||
"karma-babel-preprocessor": "^4.0.1",
|
||||
"karma-browserify": "^4.0.0",
|
||||
"karma-chrome-launcher": "0.1.8",
|
||||
"karma-cli": "0.0.4",
|
||||
"karma-coverage": "0.3.1",
|
||||
"karma-jasmine": "^0.3.6",
|
||||
"karma-phantomjs-launcher": "0.2.0",
|
||||
"phantomjs": "1.9.17"
|
||||
"morgan": "^1.6.1",
|
||||
"phantomjs": "1.9.17",
|
||||
"pretty-hrtime": "^1.0.0",
|
||||
"protractor": "^2.2.0",
|
||||
"run-sequence": "^1.1.2",
|
||||
"tiny-lr": "^0.1.6",
|
||||
"uglifyify": "^3.0.1",
|
||||
"vinyl-buffer": "^1.0.0",
|
||||
"vinyl-source-stream": "^1.1.0",
|
||||
"watchify": "^3.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "if [ ! -d .venv ]; then tox -epy27 --notest; fi",
|
||||
|
21
test/e2e/example_spec.js
Normal file
21
test/e2e/example_spec.js
Normal file
@ -0,0 +1,21 @@
|
||||
/*global browser, by */
|
||||
|
||||
'use strict';
|
||||
|
||||
describe('E2E: Example', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
browser.get('/');
|
||||
browser.waitForAngular();
|
||||
});
|
||||
|
||||
it('should route correctly', function() {
|
||||
expect(browser.getLocationAbsUrl()).toMatch('/');
|
||||
});
|
||||
|
||||
it('should show the number defined in the controller', function() {
|
||||
var element = browser.findElement(by.css('.number-example'));
|
||||
expect(element.getText()).toEqual('1234');
|
||||
});
|
||||
|
||||
});
|
12
test/e2e/routes_spec.js
Normal file
12
test/e2e/routes_spec.js
Normal file
@ -0,0 +1,12 @@
|
||||
/*global browser */
|
||||
|
||||
'use strict';
|
||||
|
||||
describe('E2E: Routes', function() {
|
||||
|
||||
it('should have a working home route', function() {
|
||||
browser.get('#/');
|
||||
expect(browser.getLocationAbsUrl()).toMatch('/');
|
||||
});
|
||||
|
||||
});
|
51
test/karma.conf.js
Normal file
51
test/karma.conf.js
Normal file
@ -0,0 +1,51 @@
|
||||
'use strict';
|
||||
|
||||
var istanbul = require('browserify-istanbul');
|
||||
var isparta = require('isparta');
|
||||
|
||||
module.exports = function(config) {
|
||||
|
||||
config.set({
|
||||
|
||||
basePath: '../',
|
||||
frameworks: ['jasmine', 'browserify'],
|
||||
preprocessors: {
|
||||
'app/js/**/*.js': ['browserify', 'babel', 'coverage']
|
||||
},
|
||||
browsers: ['Chrome'],
|
||||
reporters: ['progress', 'coverage'],
|
||||
|
||||
autoWatch: true,
|
||||
|
||||
browserify: {
|
||||
debug: true,
|
||||
transform: [
|
||||
'bulkify',
|
||||
istanbul({
|
||||
instrumenter: isparta,
|
||||
ignore: ['**/node_modules/**', '**/test/**']
|
||||
})
|
||||
]
|
||||
},
|
||||
|
||||
proxies: {
|
||||
'/': 'http://localhost:9876/'
|
||||
},
|
||||
|
||||
urlRoot: '/__karma__/',
|
||||
|
||||
files: [
|
||||
// 3rd-party resources
|
||||
'node_modules/angular/angular.min.js',
|
||||
'node_modules/angular-mocks/angular-mocks.js',
|
||||
|
||||
// app-specific code
|
||||
'app/js/main.js',
|
||||
|
||||
// test files
|
||||
'test/unit/**/*.js'
|
||||
]
|
||||
|
||||
});
|
||||
|
||||
};
|
32
test/protractor.conf.js
Normal file
32
test/protractor.conf.js
Normal file
@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
var gulpConfig = require('../gulp/config');
|
||||
|
||||
exports.config = {
|
||||
|
||||
allScriptsTimeout: 11000,
|
||||
|
||||
baseUrl: 'http://localhost:' + gulpConfig.serverPort + '/',
|
||||
|
||||
directConnect: true,
|
||||
|
||||
capabilities: {
|
||||
browserName: 'chrome',
|
||||
version: '',
|
||||
platform: 'ANY'
|
||||
},
|
||||
|
||||
framework: 'jasmine',
|
||||
|
||||
jasmineNodeOpts: {
|
||||
isVerbose: false,
|
||||
showColors: true,
|
||||
includeStackTrace: true,
|
||||
defaultTimeoutInterval: 30000
|
||||
},
|
||||
|
||||
specs: [
|
||||
'e2e/**/*.js'
|
||||
]
|
||||
|
||||
};
|
27
test/unit/constants_spec.js
Normal file
27
test/unit/constants_spec.js
Normal file
@ -0,0 +1,27 @@
|
||||
/*global angular */
|
||||
|
||||
'use strict';
|
||||
|
||||
describe('Unit: Constants', function() {
|
||||
|
||||
var constants;
|
||||
|
||||
beforeEach(function() {
|
||||
// instantiate the app module
|
||||
angular.mock.module('app');
|
||||
|
||||
// mock the directive
|
||||
angular.mock.inject(function(AppSettings) {
|
||||
constants = AppSettings;
|
||||
});
|
||||
});
|
||||
|
||||
it('should exist', function() {
|
||||
expect(constants).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have an application name', function() {
|
||||
expect(constants.appTitle).toEqual('Example Application');
|
||||
});
|
||||
|
||||
});
|
30
test/unit/controllers/example_spec.js
Normal file
30
test/unit/controllers/example_spec.js
Normal file
@ -0,0 +1,30 @@
|
||||
/*global angular */
|
||||
|
||||
'use strict';
|
||||
|
||||
describe('Unit: ExampleCtrl', function() {
|
||||
|
||||
var ctrl;
|
||||
|
||||
beforeEach(function() {
|
||||
// instantiate the app module
|
||||
angular.mock.module('app');
|
||||
|
||||
angular.mock.inject(function($controller) {
|
||||
ctrl = $controller('ExampleCtrl');
|
||||
});
|
||||
});
|
||||
|
||||
it('should exist', function() {
|
||||
expect(ctrl).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have a number variable equal to 1234', function() {
|
||||
expect(ctrl.number).toEqual(1234);
|
||||
});
|
||||
|
||||
it('should have a title variable equal to \'AngularJS, Gulp, and Browserify!\'', function() {
|
||||
expect(ctrl.title).toEqual('AngularJS, Gulp, and Browserify!');
|
||||
});
|
||||
|
||||
});
|
23
test/unit/services/example_spec.js
Normal file
23
test/unit/services/example_spec.js
Normal file
@ -0,0 +1,23 @@
|
||||
/*global angular */
|
||||
|
||||
'use strict';
|
||||
|
||||
describe('Unit: ExampleService', function() {
|
||||
|
||||
var service;
|
||||
|
||||
beforeEach(function() {
|
||||
// instantiate the app module
|
||||
angular.mock.module('app');
|
||||
|
||||
// mock the service
|
||||
angular.mock.inject(function(ExampleService) {
|
||||
service = ExampleService;
|
||||
});
|
||||
});
|
||||
|
||||
it('should exist', function() {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in New Issue
Block a user