diff --git a/app/controllers/core.js b/app/controllers/core.js new file mode 100644 index 00000000..ea0642e9 --- /dev/null +++ b/app/controllers/core.js @@ -0,0 +1,10 @@ +'use strict'; + +/** + * Module dependencies. + */ +exports.index = function(req, res) { + res.render('index.html', { + user: req.user || null + }); +}; diff --git a/app/routes/core.js b/app/routes/core.js new file mode 100644 index 00000000..63e84a32 --- /dev/null +++ b/app/routes/core.js @@ -0,0 +1,7 @@ +'use strict'; + +module.exports = function(app) { + // Root routing + var core = require('../../app/controllers/core'); + app.get('/', core.index); +}; \ No newline at end of file diff --git a/app/tests/articles.js b/app/tests/articles.js new file mode 100644 index 00000000..67e700c0 --- /dev/null +++ b/app/tests/articles.js @@ -0,0 +1,63 @@ +'use strict'; + +/** + * Module dependencies. + */ +var should = require('should'), + mongoose = require('mongoose'), + User = mongoose.model('User'), + Article = mongoose.model('Article'); + +//Globals +var user; +var article; + +//The tests +describe('', function() { + describe('Model Article:', function() { + beforeEach(function(done) { + user = new User({ + firstName: 'Full', + lastName: 'Name', + displayName: 'Full Name', + email: 'test@test.com', + username: 'username', + password: 'password' + }); + + user.save(function() { + article = new Article({ + title: 'Article Title', + content: 'Article Content', + user: user + }); + + done(); + }); + }); + + describe('Method Save', function() { + it('should be able to save without problems', function(done) { + return article.save(function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should be able to show an error when try to save without title', function(done) { + article.title = ''; + + return article.save(function(err) { + should.exist(err); + done(); + }); + }); + }); + + afterEach(function(done) { + Article.remove().exec(); + User.remove().exec(); + done(); + }); + }); +}); \ No newline at end of file diff --git a/app/tests/users.js b/app/tests/users.js new file mode 100644 index 00000000..6b7cd884 --- /dev/null +++ b/app/tests/users.js @@ -0,0 +1,73 @@ +'use strict'; + +/** + * Module dependencies. + */ +var should = require('should'), + mongoose = require('mongoose'), + User = mongoose.model('User'); + +//Globals +var user, user2; + +//The tests +describe('', function() { + describe('Model User:', function() { + before(function(done) { + user = new User({ + firstName: 'Full', + lastName: 'Name', + displayName: 'Full Name', + email: 'test@test.com', + username: 'username', + password: 'password', + provider: 'local' + }); + user2 = new User({ + firstName: 'Full', + lastName: 'Name', + displayName: 'Full Name', + email: 'test@test.com', + username: 'username', + password: 'password', + provider: 'local' + }); + + done(); + }); + + describe('Method Save', function() { + it('should begin with no users', function(done) { + User.find({}, function(err, users) { + users.should.have.length(0); + done(); + }); + }); + + it('should be able to save whithout problems', function(done) { + user.save(done); + }); + + it('should fail to save an existing user again', function(done) { + user.save(); + return user2.save(function(err) { + should.exist(err); + done(); + }); + }); + + it('should be able to show an error when try to save without first name', function(done) { + user.firstName = ''; + return user.save(function(err) { + should.exist(err); + done(); + }); + }); + }); + + after(function(done) { + User.remove().exec(); + done(); + }); + }); +}); \ No newline at end of file diff --git a/app/views/layout.html b/app/views/layout.html new file mode 100644 index 00000000..169224c2 --- /dev/null +++ b/app/views/layout.html @@ -0,0 +1,85 @@ + + + + + {{title}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {% for modulesCSSFile in modulesCSSFiles %} + + {% endfor %} + + + + + + + +
+
+ {% block content %}{% endblock %} +
+
+ + + + + + + + + + + + + + + + + + + + + {% for modulesJSFile in modulesJSFiles %} + + {% endfor %} + + {% if process.env.NODE_ENV === 'development' %} + + + {% endif %} + + \ No newline at end of file diff --git a/config/env/travis.js b/config/env/travis.js new file mode 100644 index 00000000..6b49f231 --- /dev/null +++ b/config/env/travis.js @@ -0,0 +1,29 @@ +'use strict'; + +module.exports = { + db: 'mongodb://localhost/mean-travis', + port: 3001, + app: { + title: 'MEAN.JS - Travis Environment' + }, + facebook: { + clientID: 'APP_ID', + clientSecret: 'APP_SECRET', + callbackURL: 'http://localhost:3000/auth/facebook/callback' + }, + twitter: { + clientID: 'CONSUMER_KEY', + clientSecret: 'CONSUMER_SECRET', + callbackURL: 'http://localhost:3000/auth/twitter/callback' + }, + google: { + clientID: 'APP_ID', + clientSecret: 'APP_SECRET', + callbackURL: 'http://localhost:3000/auth/google/callback' + }, + linkedin: { + clientID: 'APP_ID', + clientSecret: 'APP_SECRET', + callbackURL: 'http://localhost:3000/auth/linkedin/callback' + } +}; \ No newline at end of file diff --git a/config/utilities.js b/config/utilities.js new file mode 100644 index 00000000..ee03717d --- /dev/null +++ b/config/utilities.js @@ -0,0 +1,38 @@ +'use strict'; + +/** + * Module dependencies. + */ +var fs = require('fs'); + +// Walk function to recursively get files +var _walk = function(root, regex, exclude, removePath) { + var output = []; + var directories = []; + + // First read through files + fs.readdirSync(root).forEach(function(file) { + var newPath = root + '/' + file; + var stat = fs.statSync(newPath); + + if (stat.isFile()) { + if (regex.test(file) && (!exclude || !exclude.test(file))) { + output.push(newPath.replace(removePath, '')); + } + } else if (stat.isDirectory()) { + directories.push(newPath); + } + }); + + // Then recursively add directories + directories.forEach(function(directory) { + output = output.concat(_walk(directory, regex, exclude, removePath)); + }); + + return output; +}; + +/** + * Exposing the walk function + */ +exports.walk = _walk; \ No newline at end of file diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 00000000..f518922e --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,65 @@ +'use strict'; + +/** + * Module dependencies. + */ +var utilities = require('./config/utilities'); + +// Grabbing module files using the walk function +var modulesJSFiles = utilities.walk('./public/modules', /(.*)\.(js)/, null, null); + +// Karma configuration +module.exports = function(config) { + config.set({ + // Frameworks to use + frameworks: ['jasmine'], + + // List of files / patterns to load in the browser + files: [ + 'public/lib/angular/angular.js', + 'public/lib/angular-mocks/angular-mocks.js', + 'public/lib/angular-cookies/angular-cookies.js', + 'public/lib/angular-resource/angular-resource.js', + 'public/lib/angular-route/angular-route.js', + 'public/lib/angular-bootstrap/ui-bootstrap.js', + 'public/lib/angular-ui-utils/ui-utils.js', + 'public/js/config.js', + 'public/js/application.js', + ].concat(modulesJSFiles), + + // Test results reporter to use + // Possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' + //reporters: ['progress'], + reporters: ['progress'], + + // Web server port + port: 9876, + + // Enable / disable colors in the output (reporters and logs) + colors: true, + + // Level of logging + // Possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + // Enable / disable watching file and executing tests whenever any file changes + autoWatch: true, + + // Start these browsers, currently available: + // - Chrome + // - ChromeCanary + // - Firefox + // - Opera + // - Safari (only Mac) + // - PhantomJS + // - IE (only Windows) + browsers: ['PhantomJS'], + + // If browser does not capture in given timeout [ms], kill it + captureTimeout: 60000, + + // Continuous Integration mode + // If true, it capture browsers, run tests and exit + singleRun: true + }); +}; \ No newline at end of file diff --git a/public/img/brand/favicon.ico b/public/img/brand/favicon.ico new file mode 100644 index 00000000..756ec7e8 Binary files /dev/null and b/public/img/brand/favicon.ico differ diff --git a/public/img/brand/logo.png b/public/img/brand/logo.png new file mode 100644 index 00000000..4bf6cde6 Binary files /dev/null and b/public/img/brand/logo.png differ diff --git a/public/js/application.js b/public/js/application.js new file mode 100644 index 00000000..19bb411e --- /dev/null +++ b/public/js/application.js @@ -0,0 +1,20 @@ +'use strict'; + +//Start by defining the main module and adding the module dependencies +angular.module(ApplicationConfiguration.applicationModuleName, ApplicationConfiguration.applicationModuleVendorDependencies); + +// Setting HTML5 Location Mode +angular.module(ApplicationConfiguration.applicationModuleName).config(['$locationProvider', + function($locationProvider) { + $locationProvider.hashPrefix('!'); + } +]); + +//Then define the init function for starting up the application +angular.element(document).ready(function() { + //Fixing facebook bug with redirect + if (window.location.hash === '#_=_') window.location.hash = '#!'; + + //Then init the app + angular.bootstrap(document, [ApplicationConfiguration.applicationModuleName]); +}); \ No newline at end of file diff --git a/public/modules/articles/articles.js b/public/modules/articles/articles.js new file mode 100755 index 00000000..ccc37b42 --- /dev/null +++ b/public/modules/articles/articles.js @@ -0,0 +1,4 @@ +'use strict'; + +// Use Applicaion configuration module to register a new module +ApplicationConfiguration.registerModule('mean.articles'); \ No newline at end of file diff --git a/public/modules/articles/config/routes.js b/public/modules/articles/config/routes.js new file mode 100755 index 00000000..4f2bc00f --- /dev/null +++ b/public/modules/articles/config/routes.js @@ -0,0 +1,20 @@ +'use strict'; + +//Setting up route +angular.module('mean.articles').config(['$routeProvider', + function($routeProvider) { + $routeProvider. + when('/articles', { + templateUrl: 'modules/articles/views/list.html' + }). + when('/articles/create', { + templateUrl: 'modules/articles/views/create.html' + }). + when('/articles/:articleId', { + templateUrl: 'modules/articles/views/view.html' + }). + when('/articles/:articleId/edit', { + templateUrl: 'modules/articles/views/edit.html' + }); + } +]); \ No newline at end of file diff --git a/public/modules/articles/controllers/articles.js b/public/modules/articles/controllers/articles.js new file mode 100644 index 00000000..5fd97605 --- /dev/null +++ b/public/modules/articles/controllers/articles.js @@ -0,0 +1,62 @@ +'use strict'; + +angular.module('mean.articles').controller('ArticlesController', ['$scope', '$routeParams', '$location', 'Authentication', 'Articles', + function($scope, $routeParams, $location, Authentication, Articles) { + $scope.authentication = Authentication; + + $scope.create = function() { + var article = new Articles({ + title: this.title, + content: this.content + }); + article.$save(function(response) { + $location.path('articles/' + response._id); + }); + + this.title = ''; + this.content = ''; + }; + + $scope.remove = function(article) { + if (article) { + article.$remove(); + + for (var i in $scope.articles) { + if ($scope.articles[i] === article) { + $scope.articles.splice(i, 1); + } + } + } else { + $scope.article.$remove(function() { + $location.path('articles'); + }); + } + }; + + $scope.update = function() { + var article = $scope.article; + if (!article.updated) { + article.updated = []; + } + article.updated.push(new Date().getTime()); + + article.$update(function() { + $location.path('articles/' + article._id); + }); + }; + + $scope.find = function() { + Articles.query(function(articles) { + $scope.articles = articles; + }); + }; + + $scope.findOne = function() { + Articles.get({ + articleId: $routeParams.articleId + }, function(article) { + $scope.article = article; + }); + }; + } +]); \ No newline at end of file diff --git a/public/modules/articles/services/articles.js b/public/modules/articles/services/articles.js new file mode 100644 index 00000000..69f9be88 --- /dev/null +++ b/public/modules/articles/services/articles.js @@ -0,0 +1,12 @@ +'use strict'; + +//Articles service used for articles REST endpoint +angular.module('mean.articles').factory('Articles', ['$resource', function($resource) { + return $resource('articles/:articleId', { + articleId: '@_id' + }, { + update: { + method: 'PUT' + } + }); +}]); \ No newline at end of file diff --git a/public/modules/articles/tests/articles.spec.js b/public/modules/articles/tests/articles.spec.js new file mode 100644 index 00000000..fa3fbbe9 --- /dev/null +++ b/public/modules/articles/tests/articles.spec.js @@ -0,0 +1,166 @@ +'use strict'; + +(function() { + // Articles Controller Spec + describe('MEAN controllers', function() { + describe('ArticlesController', function() { + // Initialize global variables + var ArticlesController, + scope, + $httpBackend, + $routeParams, + $location; + + // The $resource service augments the response object with methods for updating and deleting the resource. + // If we were to use the standard toEqual matcher, our tests would fail because the test values would not match + // the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher. + // When the toEqualData matcher compares two objects, it takes only object properties into + // account and ignores methods. + beforeEach(function() { + this.addMatchers({ + toEqualData: function(expected) { + return angular.equals(this.actual, expected); + } + }); + }); + + // Then we can start by loading the main application module + beforeEach(module('mean')); + + // The injector ignores leading and trailing underscores here (i.e. _$httpBackend_). + // This allows us to inject a service but then attach it to a variable + // with the same name as the service. + beforeEach(inject(function($controller, $rootScope, _$location_, _$routeParams_, _$httpBackend_) { + // Set a new global scope + scope = $rootScope.$new(); + + // Point global variables to injected services + $routeParams = _$routeParams_; + $httpBackend = _$httpBackend_; + $location = _$location_; + + // Initialize the Articles controller. + ArticlesController = $controller('ArticlesController', { + $scope: scope + }); + })); + + it('$scope.find() should create an array with at least one article object fetched from XHR', inject(function(Articles) { + // Create sample article using the Articles service + var sampleArticle = new Articles({ + title: 'An Article about MEAN', + content: 'MEAN rocks!' + }); + + // Create a sample articles array that includes the new article + var sampleArticles = [sampleArticle]; + + // Set GET response + $httpBackend.expectGET('articles').respond(sampleArticles); + + // Run controller functionality + scope.find(); + $httpBackend.flush(); + + // Test scope value + expect(scope.articles).toEqualData(sampleArticles); + })); + + it('$scope.findOne() should create an array with one article object fetched from XHR using a articleId URL parameter', inject(function(Articles) { + // Define a sample article object + var sampleArticle = new Articles({ + title: 'An Article about MEAN', + content: 'MEAN rocks!' + }); + + // Set the URL parameter + $routeParams.articleId = '525a8422f6d0f87f0e407a33'; + + // Set GET response + $httpBackend.expectGET(/articles\/([0-9a-fA-F]{24})$/).respond(sampleArticle); + + // Run controller functionality + scope.findOne(); + $httpBackend.flush(); + + // Test scope value + expect(scope.article).toEqualData(sampleArticle); + })); + + it('$scope.create() with valid form data should send a POST request with the form input values and then locate to new object URL', inject(function(Articles) { + // Create a sample article object + var sampleArticlePostData = new Articles({ + title: 'An Article about MEAN', + content: 'MEAN rocks!' + }); + + // Create a sample article response + var sampleArticleResponse = new Articles({ + _id: '525cf20451979dea2c000001', + title: 'An Article about MEAN', + content: 'MEAN rocks!' + }); + + // Fixture mock form input values + scope.title = 'An Article about MEAN'; + scope.content = 'MEAN rocks!'; + + // Set POST response + $httpBackend.expectPOST('articles', sampleArticlePostData).respond(sampleArticleResponse); + + // Run controller functionality + scope.create(); + $httpBackend.flush(); + + // Test form inputs are reset + expect(scope.title).toEqual(''); + expect(scope.content).toEqual(''); + + // Test URL redirection after the article was created + expect($location.path()).toBe('/articles/' + sampleArticleResponse._id); + })); + + it('$scope.update() should update a valid article', inject(function(Articles) { + // Define a sample article put data + var sampleArticlePutData = new Articles({ + _id: '525cf20451979dea2c000001', + title: 'An Article about MEAN', + content: 'MEAN Rocks!' + }); + + // Mock article in scope + scope.article = sampleArticlePutData; + + // Set PUT response + $httpBackend.expectPUT(/articles\/([0-9a-fA-F]{24})$/).respond(); + + // Run controller functionality + scope.update(); + $httpBackend.flush(); + + // Test URL location to new object + expect($location.path()).toBe('/articles/' + sampleArticlePutData._id); + })); + + it('$scope.remove() should send a DELETE request with a valid articleId and remove the article from the scope', inject(function(Articles) { + // Create new article object + var sampleArticle = new Articles({ + _id: '525a8422f6d0f87f0e407a33' + }); + + // Create new articles array and include the article + scope.articles = [sampleArticle]; + + // Set expected DELETE response + $httpBackend.expectDELETE(/articles\/([0-9a-fA-F]{24})$/).respond(204); + + // Run controller functionality + scope.remove(sampleArticle); + $httpBackend.flush(); + + // Test array after successful delete + expect(scope.articles.length).toBe(0); + })); + }); + }); +}()); \ No newline at end of file diff --git a/public/modules/articles/views/create.html b/public/modules/articles/views/create.html new file mode 100644 index 00000000..ed0bf7aa --- /dev/null +++ b/public/modules/articles/views/create.html @@ -0,0 +1,26 @@ +
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+
+
\ No newline at end of file diff --git a/public/modules/articles/views/edit.html b/public/modules/articles/views/edit.html new file mode 100644 index 00000000..790eafad --- /dev/null +++ b/public/modules/articles/views/edit.html @@ -0,0 +1,26 @@ +
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+
+
\ No newline at end of file diff --git a/public/modules/articles/views/list.html b/public/modules/articles/views/list.html new file mode 100644 index 00000000..d033e492 --- /dev/null +++ b/public/modules/articles/views/list.html @@ -0,0 +1,15 @@ +
+ + +
+ No articles yet, why don't you create one? +
+
\ No newline at end of file diff --git a/public/modules/articles/views/view.html b/public/modules/articles/views/view.html new file mode 100644 index 00000000..b7170c18 --- /dev/null +++ b/public/modules/articles/views/view.html @@ -0,0 +1,20 @@ +
+ + + + + Posted on {{article.created | date:'mediumDate'}} by {{article.user.displayName}} + +

+ {{article.content}} +

+
\ No newline at end of file diff --git a/public/modules/core/config/routes.js b/public/modules/core/config/routes.js new file mode 100755 index 00000000..b9a3cec3 --- /dev/null +++ b/public/modules/core/config/routes.js @@ -0,0 +1,11 @@ +'use strict'; + +// Setting up route +angular.module('mean.core').config(['$routeProvider', + function($routeProvider) { + $routeProvider. + when('/', { + templateUrl: 'modules/core/views/home.html' + }); + } +]); \ No newline at end of file diff --git a/public/modules/core/controllers/header.js b/public/modules/core/controllers/header.js new file mode 100644 index 00000000..803eb0b5 --- /dev/null +++ b/public/modules/core/controllers/header.js @@ -0,0 +1,19 @@ +'use strict'; + +angular.module('mean.core').controller('HeaderController', ['$scope', 'Authentication', + function($scope, Authentication) { + $scope.authentication = Authentication; + + $scope.menu = [{ + title: 'Articles', + link: 'articles', + uiRoute: '/articles' + }, { + title: 'New Article', + link: 'articles/create', + uiRoute: '/articles/create' + }]; + + $scope.isCollapsed = false; + } +]); \ No newline at end of file diff --git a/public/modules/core/controllers/home.js b/public/modules/core/controllers/home.js new file mode 100644 index 00000000..68e9dc90 --- /dev/null +++ b/public/modules/core/controllers/home.js @@ -0,0 +1,5 @@ +'use strict'; + +angular.module('mean.core').controller('HomeController', ['$scope', 'Authentication', function ($scope, Authentication) { + $scope.authentication = Authentication; +}]); \ No newline at end of file diff --git a/public/modules/core/core.js b/public/modules/core/core.js new file mode 100755 index 00000000..d4aeb106 --- /dev/null +++ b/public/modules/core/core.js @@ -0,0 +1,4 @@ +'use strict'; + +// Use Applicaion configuration module to register a new module +ApplicationConfiguration.registerModule('mean.core'); \ No newline at end of file diff --git a/public/modules/core/tests/header.spec.js b/public/modules/core/tests/header.spec.js new file mode 100644 index 00000000..5d25e3bf --- /dev/null +++ b/public/modules/core/tests/header.spec.js @@ -0,0 +1,26 @@ +'use strict'; + +(function() { + describe('MEAN controllers', function() { + describe('HeaderController', function() { + //Initialize global variables + var scope, + HeaderController; + + // Load the main application module + beforeEach(module('mean')); + + beforeEach(inject(function($controller, $rootScope) { + scope = $rootScope.$new(); + + HeaderController = $controller('HeaderController', { + $scope: scope + }); + })); + + it('should expose the authentication service', function() { + expect(scope.authentication).toBeTruthy(); + }); + }); + }); +})(); \ No newline at end of file diff --git a/public/modules/core/tests/home.spec.js b/public/modules/core/tests/home.spec.js new file mode 100644 index 00000000..b70d6be3 --- /dev/null +++ b/public/modules/core/tests/home.spec.js @@ -0,0 +1,26 @@ +'use strict'; + +(function() { + describe('MEAN controllers', function() { + describe('HomeController', function() { + //Initialize global variables + var scope, + HomeController; + + // Load the main application module + beforeEach(module('mean')); + + beforeEach(inject(function($controller, $rootScope) { + scope = $rootScope.$new(); + + HomeController = $controller('HomeController', { + $scope: scope + }); + })); + + it('should expose the authentication service', function() { + expect(scope.authentication).toBeTruthy(); + }); + }); + }); +})(); \ No newline at end of file diff --git a/public/modules/core/views/header.html b/public/modules/core/views/header.html new file mode 100644 index 00000000..47d48c7b --- /dev/null +++ b/public/modules/core/views/header.html @@ -0,0 +1,39 @@ +
+ + +
\ No newline at end of file diff --git a/public/modules/core/views/home.html b/public/modules/core/views/home.html new file mode 100644 index 00000000..7d02d4b3 --- /dev/null +++ b/public/modules/core/views/home.html @@ -0,0 +1,32 @@ +
+

THANK YOU FOR DOWNLOADING MEAN.JS

+
+

+ Before you begin we recommend you read about the basic building blocks that assemble a MEAN.JS application: +

+
+
MongoDB
+
+ Go through MongoDB Official Website and proceed to its Great Manual, which should help you understand NoSQL and MongoDB better. +
+
Express
+
+ The best way to understand Express is through its Official Website, particularly The Express Guide; you can also go through this StackOverflow Thread for more resources. +
+
AngularJS
+
+ Angular's Official Website is a great starting point. You can also use Thinkster Popular Guide, and the Egghead Videos. +
+
Node.js
+
+ Start by going through Node.js Official Website and this StackOverflow Thread, which should get you going with the Node.js platform in no time. +
+
+

+ When you're done with those resources and feel you understand the basic principals continue to the MEAN.JS Documentation. +

+
+
Enjoy & Keep Us Updated, +
The MEAN.JS Team. +
+
\ No newline at end of file diff --git a/public/modules/users/config/config.js b/public/modules/users/config/config.js new file mode 100644 index 00000000..2f1a9b25 --- /dev/null +++ b/public/modules/users/config/config.js @@ -0,0 +1,30 @@ +'use strict'; + +// Config HTTP Error Handling +angular.module('mean.users').config(['$httpProvider', + function($httpProvider) { + // Set the httpProvider "not authorized" interceptor + $httpProvider.interceptors.push(['$q', '$location', 'Authentication', + function($q, $location, Authentication) { + return { + responseError: function(rejection) { + switch (rejection.status) { + case 401: + // Deauthenticate the global user + Authentication.user = null; + + // Redirect to signin page + $location.path('signin'); + break; + case 403: + // Add unauthorized behaviour + break; + } + + return $q.reject(rejection); + } + }; + } + ]); + } +]); \ No newline at end of file diff --git a/public/modules/users/config/routes.js b/public/modules/users/config/routes.js new file mode 100755 index 00000000..65b5a533 --- /dev/null +++ b/public/modules/users/config/routes.js @@ -0,0 +1,14 @@ +'use strict'; + +// Setting up route +angular.module('mean.users').config(['$routeProvider', + function($routeProvider) { + $routeProvider. + when('/signup', { + templateUrl: 'modules/users/views/signup.html' + }). + when('/signin', { + templateUrl: 'modules/users/views/signin.html' + }); + } +]); \ No newline at end of file diff --git a/public/modules/users/controllers/authentication.js b/public/modules/users/controllers/authentication.js new file mode 100644 index 00000000..90b32441 --- /dev/null +++ b/public/modules/users/controllers/authentication.js @@ -0,0 +1,31 @@ +'use strict'; + +angular.module('mean.users').controller('AuthenticationController', ['$scope', '$http', '$location', 'Authentication', + function($scope, $http, $location, Authentication) { + $scope.authentication = Authentication; + + $scope.signup = function() { + $http.post('/auth/signup', $scope.credentials).success(function(data) { + //If successful we assign the data to the global user model + $scope.authentication.user = data; + + //And redirect to the index page + $location.path('/'); + }).error(function(data) { + $scope.error = data.message; + }); + }; + + $scope.signin = function() { + $http.post('/auth/signin', $scope.credentials).success(function(data) { + //If successful we assign the data to the global user model + $scope.authentication.user = data; + + //And redirect to the index page + $location.path('/'); + }).error(function(data) { + $scope.error = data.message; + }); + }; + } +]); \ No newline at end of file diff --git a/public/modules/users/img/buttons/facebook.png b/public/modules/users/img/buttons/facebook.png new file mode 100644 index 00000000..8ebea4f7 Binary files /dev/null and b/public/modules/users/img/buttons/facebook.png differ diff --git a/public/modules/users/img/buttons/google.png b/public/modules/users/img/buttons/google.png new file mode 100644 index 00000000..0c007125 Binary files /dev/null and b/public/modules/users/img/buttons/google.png differ diff --git a/public/modules/users/img/buttons/linkedin.png b/public/modules/users/img/buttons/linkedin.png new file mode 100644 index 00000000..ff039a42 Binary files /dev/null and b/public/modules/users/img/buttons/linkedin.png differ diff --git a/public/modules/users/img/buttons/twitter.png b/public/modules/users/img/buttons/twitter.png new file mode 100644 index 00000000..2e399c17 Binary files /dev/null and b/public/modules/users/img/buttons/twitter.png differ diff --git a/public/modules/users/services/authentication.js b/public/modules/users/services/authentication.js new file mode 100644 index 00000000..4aa6e87b --- /dev/null +++ b/public/modules/users/services/authentication.js @@ -0,0 +1,14 @@ +'use strict'; + +//Authentication service for user variables +angular.module('mean.users').factory('Authentication', [ + function() { + var _this = this; + + _this._data = { + user: window.user + }; + + return _this._data; + } +]); \ No newline at end of file diff --git a/public/modules/users/users.js b/public/modules/users/users.js new file mode 100755 index 00000000..c204eb04 --- /dev/null +++ b/public/modules/users/users.js @@ -0,0 +1,4 @@ +'use strict'; + +// Use Applicaion configuration module to register a new module +ApplicationConfiguration.registerModule('mean.users'); \ No newline at end of file diff --git a/public/modules/users/views/signin.html b/public/modules/users/views/signin.html new file mode 100644 index 00000000..1a7383c5 --- /dev/null +++ b/public/modules/users/views/signin.html @@ -0,0 +1,39 @@ +
+

Sign in using your social accounts

+ +

Or with your email

+
+ +
+
\ No newline at end of file diff --git a/public/modules/users/views/signup.html b/public/modules/users/views/signup.html new file mode 100644 index 00000000..bbe68b65 --- /dev/null +++ b/public/modules/users/views/signup.html @@ -0,0 +1,51 @@ +
+

Sign up using your social accounts

+ +

Or with your email

+
+ +
+
\ No newline at end of file