Skip to content
Permalink
Browse files

Merge remote-tracking branch 'upstream/master'

  • Loading branch information...
francisdaigle committed Jan 16, 2016
2 parents a9a7c48 + 3dee3fc commit e15eedf7384bc783919dd9a62084ef198cd2eee7
Showing with 1,370 additions and 115 deletions.
  1. +1 −1 CONTRIBUTING.md
  2. +10 −4 config/assets/default.js
  3. +1 −0 config/env/default.js
  4. +2 −2 config/lib/app.js
  5. +51 −0 gulpfile.js
  6. +7 −0 modules/articles/client/articles.client.module.js
  7. +71 −0 modules/articles/client/config/articles.client.routes.js
  8. +52 −0 modules/articles/client/controllers/articles.client.controller.js
  9. +15 −0 modules/articles/client/controllers/list.articles.client.controller.js
  10. +19 −0 modules/articles/client/services/articles.client.service.js
  11. +28 −0 modules/articles/client/views/form-article.client.view.html
  12. +21 −0 modules/articles/client/views/list-articles.client.view.html
  13. +23 −0 modules/articles/client/views/view-article.client.view.html
  14. +72 −0 modules/articles/server/policies/articles.server.policy.js
  15. +172 −0 modules/articles/tests/client/articles.client.controller.tests.js
  16. +195 −0 modules/articles/tests/client/articles.client.routes.tests.js
  17. +92 −0 modules/articles/tests/client/list.articles.client.controller.tests.js
  18. +408 −0 modules/articles/tests/server/article.server.routes.tests.js
  19. +5 −3 modules/chat/client/chat.client.module.js
  20. +10 −5 modules/chat/client/config/chat.client.config.js
  21. +12 −5 modules/chat/client/config/chat.client.routes.js
  22. +40 −28 modules/chat/client/controllers/chat.client.controller.js
  23. +5 −5 modules/chat/client/views/chat.client.view.html
  24. +24 −24 modules/chat/tests/client/chat.client.controller.tests.js
  25. +1 −1 modules/core/client/app/init.js
  26. +4 −2 modules/core/client/services/interceptors/auth.interceptor.client.service.js
  27. +19 −1 modules/core/server/controllers/core.server.controller.js
  28. +4 −1 modules/core/tests/client/interceptors/auth.interceptor.client.tests.js
  29. +1 −0 modules/core/tests/server/core.server.config.tests.js
  30. +0 −30 modules/users/client/config/users.client.config.js
  31. +0 −1 modules/users/server/controllers/users/users.password.server.controller.js
  32. +0 −1 modules/users/server/controllers/users/users.profile.server.controller.js
  33. +1 −0 modules/users/tests/server/user.server.model.tests.js
  34. +4 −1 package.json
@@ -59,7 +59,7 @@ Fixes #82
* The scope should be where the change took place.
* Examples: users, core, config, articles
* Subject:
* The subject line should be clear and consice as to what is being accomplished in the commit.
* The subject line should be clear and concise as to what is being accomplished in the commit.
* General Rules:
* No Line in the Commit message can be longer than 80 characters.
* Refrence: [Angular Conventions](https://github.com/ajoslin/conventional-changelog/blob/master/conventions/angular.md)
@@ -42,18 +42,24 @@ module.exports = {
'modules/*/client/*.js',
'modules/*/client/**/*.js'
],
img: [
'modules/**/*/img/**/*.jpg',
'modules/**/*/img/**/*.png',
'modules/**/*/img/**/*.gif',
'modules/**/*/img/**/*.svg'
],
views: ['modules/*/client/views/**/*.html'],
templates: ['build/templates.js']
},
server: {
gruntConfig: 'gruntfile.js',
gulpConfig: 'gulpfile.js',
gruntConfig: ['gruntfile.js'],
gulpConfig: ['gulpfile.js'],
allJS: ['server.js', 'config/**/*.js', 'modules/*/server/**/*.js'],
models: 'modules/*/server/models/**/*.js',
routes: ['modules/!(core)/server/routes/**/*.js', 'modules/core/server/routes/**/*.js'],
sockets: 'modules/*/server/sockets/**/*.js',
config: 'modules/*/server/config/*.js',
config: ['modules/*/server/config/*.js'],
policies: 'modules/*/server/policies/*.js',
views: 'modules/*/server/views/*.html'
views: ['modules/*/server/views/*.html']
}
};
@@ -8,6 +8,7 @@ module.exports = {
googleAnalyticsTrackingID: process.env.GOOGLE_ANALYTICS_TRACKING_ID || 'GOOGLE_ANALYTICS_TRACKING_ID'
},
port: process.env.PORT || 3000,
host: process.env.HOST || '0.0.0.0',
templateEngine: 'swig',
// Session Cookie settings
sessionCookie: {
@@ -40,8 +40,8 @@ module.exports.start = function start(callback) {

_this.init(function (app, db, config) {

// Start the app by listening on <port>
app.listen(config.port, function () {
// Start the app by listening on <port> at <host>
app.listen(config.port, config.host, function () {

// Logging initialization
console.log('--');
@@ -6,6 +6,7 @@
var _ = require('lodash'),
defaultAssets = require('./config/assets/default'),
testAssets = require('./config/assets/test'),
glob = require('glob'),
gulp = require('gulp'),
gulpLoadPlugins = require('gulp-load-plugins'),
runSequence = require('run-sequence'),
@@ -14,8 +15,10 @@ var _ = require('lodash'),
'gulp-angular-templatecache': 'templateCache'
}
}),
pngquant = require('imagemin-pngquant'),
path = require('path'),
endOfLine = require('os').EOL,
argv = require('yargs').argv,
protractor = require('gulp-protractor').protractor,
webdriver_update = require('gulp-protractor').webdriver_update,
webdriver_standalone = require('gulp-protractor').webdriver_standalone,
@@ -66,6 +69,35 @@ gulp.task('watch', function () {
gulp.watch(defaultAssets.server.gulpConfig, ['jshint']);
gulp.watch(defaultAssets.client.views).on('change', plugins.livereload.changed);
}

if (process.env.NODE_ENV === 'test') {
// Add Server Test file rules
gulp.watch([testAssets.tests.server, defaultAssets.server.allJS], ['test:server']).on('change', function (file) {
var runOnlyChangedTestFile = argv.onlyChanged ? true : false;

// check if we should only run a changed test file
if (runOnlyChangedTestFile) {
var changedTestFiles = [];

// iterate through server test glob patterns
_.forEach(testAssets.tests.server, function (pattern) {
// determine if the changed (watched) file is a server test
_.forEach(glob.sync(pattern), function (f) {
var filePath = path.resolve(f);

if (filePath === path.resolve(file.path)) {
changedTestFiles.push(f);
}
});
});

// set task argument for tracking changed test files
argv.changedTestFiles = changedTestFiles;
}

plugins.livereload.changed();
});
}
});

// CSS linting task
@@ -159,6 +191,17 @@ gulp.task('less', function () {
.pipe(gulp.dest('./modules/'));
});

// Imagemin task
gulp.task('imagemin', function () {
return gulp.src(defaultAssets.client.img)
.pipe(plugins.imagemin({
progressive: true,
svgoPlugins: [{ removeViewBox: false }],
use: [pngquant()]
}))
.pipe(gulp.dest('public/dist/img'));
});

// Angular template cache task
gulp.task('templatecache', function () {
var re = new RegExp('\\' + path.sep + 'client\\' + path.sep, 'g');
@@ -248,6 +291,14 @@ gulp.task('test:server', function (done) {
runSequence('env:test', 'lint', 'mocha', done);
});

// Watch all server files for changes & run server tests (test:server) task on changes
// optional arguments:
// --onlyChanged - optional argument for specifying that only the tests in a changed Server Test file will be run
// example usage: gulp test:server:watch --onlyChanged
gulp.task('test:server:watch', function (done) {
runSequence('test:server', 'watch', done);
});

gulp.task('test:client', function (done) {
runSequence('env:test', 'lint', 'karma', done);
});
@@ -0,0 +1,7 @@
(function (app) {
'use strict';

app.registerModule('articles');
app.registerModule('articles.services');
app.registerModule('articles.routes', ['ui.router', 'articles.services']);
})(ApplicationConfiguration);
@@ -0,0 +1,71 @@
(function () {
'use strict';

angular
.module('articles.routes')
.config(routeConfig);

routeConfig.$inject = ['$stateProvider'];

function routeConfig($stateProvider) {
$stateProvider
.state('articles', {
abstract: true,
url: '/articles',
template: '<ui-view/>'
})
.state('articles.list', {
url: '',
templateUrl: 'modules/articles/client/views/list-articles.client.view.html',
controller: 'ArticlesListController',
controllerAs: 'vm'
})
.state('articles.create', {
url: '/create',
templateUrl: 'modules/articles/client/views/form-article.client.view.html',
controller: 'ArticlesController',
controllerAs: 'vm',
resolve: {
articleResolve: newArticle
},
data: {
roles: ['user', 'admin']
}
})
.state('articles.edit', {
url: '/:articleId/edit',
templateUrl: 'modules/articles/client/views/form-article.client.view.html',
controller: 'ArticlesController',
controllerAs: 'vm',
resolve: {
articleResolve: getArticle
},
data: {
roles: ['user', 'admin']
}
})
.state('articles.view', {
url: '/:articleId',
templateUrl: 'modules/articles/client/views/view-article.client.view.html',
controller: 'ArticlesController',
controllerAs: 'vm',
resolve: {
articleResolve: getArticle
}
});
}

getArticle.$inject = ['$stateParams', 'ArticlesService'];

function getArticle($stateParams, ArticlesService) {
return ArticlesService.get({
articleId: $stateParams.articleId
}).$promise;
}

newArticle.$inject = ['ArticlesService'];

function newArticle(ArticlesService) {
return new ArticlesService();
}
})();
@@ -0,0 +1,52 @@
(function () {
'use strict';

angular
.module('articles')
.controller('ArticlesController', ArticlesController);

ArticlesController.$inject = ['$scope', '$state', 'articleResolve', 'Authentication'];

function ArticlesController($scope, $state, article, Authentication) {
var vm = this;

vm.article = article;
vm.authentication = Authentication;
vm.error = null;
vm.form = {};
vm.remove = remove;
vm.save = save;

// Remove existing Article
function remove() {
if (confirm('Are you sure you want to delete?')) {
vm.article.$remove($state.go('articles.list'));
}
}

// Save Article
function save(isValid) {
if (!isValid) {
$scope.$broadcast('show-errors-check-validity', 'vm.form.articleForm');
return false;
}

// TODO: move create/update logic to service
if (vm.article._id) {
vm.article.$update(successCallback, errorCallback);
} else {
vm.article.$save(successCallback, errorCallback);
}

function successCallback(res) {
$state.go('articles.view', {
articleId: res._id
});
}

function errorCallback(res) {
vm.error = res.data.message;
}
}
}
})();
@@ -0,0 +1,15 @@
(function () {
'use strict';

angular
.module('articles')
.controller('ArticlesListController', ArticlesListController);

ArticlesListController.$inject = ['ArticlesService'];

function ArticlesListController(ArticlesService) {
var vm = this;

vm.articles = ArticlesService.query();
}
})();
@@ -0,0 +1,19 @@
(function () {
'use strict';

angular
.module('articles.services')
.factory('ArticlesService', ArticlesService);

ArticlesService.$inject = ['$resource'];

function ArticlesService($resource) {
return $resource('api/articles/:articleId', {
articleId: '@_id'
}, {
update: {
method: 'PUT'
}
});
}
})();
@@ -0,0 +1,28 @@
<section>
<div class="page-header">
<h1>{{vm.article._id ? 'Edit Article' : 'New Article'}}</h1>
</div>
<div class="col-md-12">
<form name="vm.form.articleForm" class="form-horizontal" ng-submit="vm.save(vm.form.articleForm.$valid)" novalidate>
<fieldset>
<div class="form-group" show-errors>
<label class="control-label" for="title">Title</label>
<input name="title" type="text" ng-model="vm.article.title" id="title" class="form-control" placeholder="Title" required>
<div ng-messages="vm.form.articleForm.title.$error" role="alert">
<p class="help-block error-text" ng-message="required">Article title is required.</p>
</div>
</div>
<div class="form-group">
<label class="control-label" for="content">Content</label>
<textarea name="content" data-ng-model="vm.article.content" id="content" class="form-control" cols="30" rows="10" placeholder="Content"></textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-default">{{vm.article._id ? 'Update' : 'Create'}}</button>
</div>
<div ng-show="vm.error" class="text-danger">
<strong ng-bind="vm.error"></strong>
</div>
</fieldset>
</form>
</div>
</section>
@@ -0,0 +1,21 @@
<section>
<div class="page-header">
<h1>Articles</h1>
</div>
<div class="list-group">
<a ng-repeat="article in vm.articles" ui-sref="articles.view({ articleId: article._id })" class="list-group-item">
<small class="list-group-item-text">
Posted on
<span ng-bind="article.created | date:'mediumDate'"></span>
by
<span ng-if="article.user" ng-bind="article.user.displayName"></span>
<span ng-if="!article.user">Deleted User</span>
</small>
<h4 class="list-group-item-heading" ng-bind="article.title"></h4>
<p class="list-group-item-text" ng-bind="article.content"></p>
</a>
</div>
<div class="alert alert-warning text-center" ng-if="vm.articles.$resolved && !vm.articles.length">
No articles yet, why don't you <a ui-sref="articles.create">create one</a>?
</div>
</section>
@@ -0,0 +1,23 @@
<section>
<div class="page-header">
<h1 ng-bind="vm.article.title"></h1>
</div>
<div class="pull-right" ng-show="vm.authentication.user._id == vm.article.user._id">
<a class="btn btn-primary" ui-sref="articles.edit({ articleId: vm.article._id })">
<i class="glyphicon glyphicon-edit"></i>
</a>
<a class="btn btn-primary" ng-click="vm.remove()">
<i class="glyphicon glyphicon-trash"></i>
</a>
</div>
<small>
<em class="text-muted">
Posted on
<span ng-bind="vm.article.created | date:'mediumDate'"></span>
by
<span ng-if="vm.article.user" ng-bind="vm.article.user.displayName"></span>
<span ng-if="!vm.article.user">Deleted User</span>
</em>
</small>
<p class="lead" ng-bind="vm.article.content"></p>
</section>

0 comments on commit e15eedf

Please sign in to comment.
You can’t perform that action at this time.