Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
...
  • 4 commits
  • 19 files changed
  • 0 commit comments
  • 1 contributor
View
1 packages/articles/README.md
@@ -1 +0,0 @@
-README: articles
View
51 packages/articles/app.js
@@ -1,51 +0,0 @@
-'use strict';
-
-/*
- * Defining the Package
- */
-var Module = require('meanio').Module;
-
-var Articles = new Module('Articles');
-
-/*
- * All MEAN packages require registration
- * Dependency injection is used to define required modules
- */
-Articles.register(function(app, auth, database) {
-
- //We enable routing. By default the Package Object is passed to the routes
- Articles.routes(app, auth, database);
-
- //We are adding a link to the main menu for all authenticated users
- Articles.menus.add({
- 'roles': ['authenticated'],
- 'title': 'Articles',
- 'link': 'all articles'
- });
- Articles.menus.add({
- 'roles': ['authenticated'],
- 'title': 'Create New Article',
- 'link': 'create article'
- });
-
- /*
- //Uncomment to use. Requires meanio@0.3.7 or above
- // Save settings with callback
- // Use this for saving data from administration pages
- Articles.settings({'someSetting':'some value'},function (err, settings) {
- //you now have the settings object
- });
-
- // Another save settings example this time with no callback
- // This writes over the last settings.
- Articles.settings({'anotherSettings':'some value'});
-
- // Get settings. Retrieves latest saved settigns
- Articles.settings(function (err, settings) {
- //you now have the settings object
- });
- */
- Articles.aggregateAsset('css', 'articles.css');
-
- return Articles;
-});
View
16 packages/articles/package.json
@@ -1,16 +0,0 @@
-{
- "name": "articles",
- "version": "0.0.1",
- "description": "Articles example pacakge",
- "author": {
- "name": "Linnovate"
- },
- "mean": "0.3.3",
- "engines": {
- "node": "0.10.x",
- "npm": "1.4.x"
- },
- "dependencies": {
- },
- "license": "GPL"
-}
View
6 packages/articles/public/assets/css/articles.css
@@ -1,6 +0,0 @@
-h1 {
- text-align: center
-}
-ul.articles li:not(:last-child) {
- border-bottom: 1px solid #ccc
-}
View
BIN packages/articles/public/assets/img/logo.png
Deleted file not rendered
View
75 packages/articles/public/controllers/articles.js
@@ -1,75 +0,0 @@
-'use strict';
-
-angular.module('mean').controller('ArticlesController', ['$scope', '$stateParams', '$location', 'Global', 'Articles',
- function($scope, $stateParams, $location, Global, Articles) {
- $scope.global = Global;
-
- $scope.hasAuthorization = function(article) {
- if (!article || !article.user) return false;
- return $scope.global.isAdmin || article.user._id === $scope.global.user._id;
- };
-
- $scope.create = function(isValid) {
- if (isValid) {
- var article = new Articles({
- title: this.title,
- content: this.content
- });
- article.$save(function(response) {
- $location.path('articles/' + response._id);
- });
-
- this.title = '';
- this.content = '';
- } else {
- $scope.submitted = true;
- }
- };
-
- $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(response) {
- $location.path('articles');
- });
- }
- };
-
- $scope.update = function(isValid) {
- if (isValid) {
- var article = $scope.article;
- if (!article.updated) {
- article.updated = [];
- }
- article.updated.push(new Date().getTime());
-
- article.$update(function() {
- $location.path('articles/' + article._id);
- });
- } else {
- $scope.submitted = true;
- }
- };
-
- $scope.find = function() {
- Articles.query(function(articles) {
- $scope.articles = articles;
- });
- };
-
- $scope.findOne = function() {
- Articles.get({
- articleId: $stateParams.articleId
- }, function(article) {
- $scope.article = article;
- });
- };
- }
-]);
View
57 packages/articles/public/routes/articles.js
@@ -1,57 +0,0 @@
-'use strict';
-
-//Setting up route
-angular.module('mean').config(['$stateProvider',
- function($stateProvider) {
- // Check if the user is connected
- var checkLoggedin = function($q, $timeout, $http, $location) {
- // Initialize a new promise
- var deferred = $q.defer();
-
- // Make an AJAX call to check if the user is logged in
- $http.get('/loggedin').success(function(user) {
- // Authenticated
- if (user !== '0') $timeout(deferred.resolve);
-
- // Not Authenticated
- else {
- $timeout(deferred.reject);
- $location.url('/login');
- }
- });
-
- return deferred.promise;
- };
-
- // states for my app
- $stateProvider
- .state('all articles', {
- url: '/articles',
- templateUrl: 'articles/views/list.html',
- resolve: {
- loggedin: checkLoggedin
- }
- })
- .state('create article', {
- url: '/articles/create',
- templateUrl: 'articles/views/create.html',
- resolve: {
- loggedin: checkLoggedin
- }
- })
- .state('edit article', {
- url: '/articles/:articleId/edit',
- templateUrl: 'articles/views/edit.html',
- resolve: {
- loggedin: checkLoggedin
- }
- })
- .state('article by id', {
- url: '/articles/:articleId',
- templateUrl: 'articles/views/view.html',
- resolve: {
- loggedin: checkLoggedin
- }
- });
- }
-]);
View
14 packages/articles/public/services/articles.js
@@ -1,14 +0,0 @@
-'use strict';
-
-//Articles service used for articles REST endpoint
-angular.module('mean').factory('Articles', ['$resource',
- function($resource) {
- return $resource('articles/:articleId', {
- articleId: '@_id'
- }, {
- update: {
- method: 'PUT'
- }
- });
- }
-]);
View
28 packages/articles/public/views/create.html
@@ -1,28 +0,0 @@
-<section data-ng-controller="ArticlesController">
- <form name="articleForm" class="form-horizontal col-md-6" role="form" data-ng-submit="create(articleForm.$valid)" novalidate>
- <div class="form-group" ng-class="{ 'has-error' : submitted && articleForm.title.$invalid }">
- <label mean-token="'create-title'" class="col-md-3 control-label">Title</label>
- <div class="col-md-9">
- <input name="title" type="text" class="form-control" data-ng-model="title" id="title" placeholder="Title" required>
- <div ng-show="submitted && articleForm.title.$invalid" class="help-block">
- <p ng-show="articleForm.title.$error.required">Title is required</p>
- </div>
- </div>
-
- </div>
- <div class="form-group" ng-class="{ 'has-error' : submitted && articleForm.content.$invalid }">
- <label mean-token="'create-content'" for="content" class="col-md-3 control-label">Content</label>
- <div class="col-md-9">
- <textarea name="content" data-ng-model="content" id="content" cols="30" rows="10" placeholder="Content" class="form-control" required></textarea>
- <div ng-show="submitted && articleForm.content.$invalid" class="help-block">
- <p ng-show="articleForm.content.$error.required">Content is required</p>
- </div>
- </div>
- </div>
- <div class="form-group">
- <div class="col-md-offset-3 col-md-9">
- <button type="submit" class="btn btn-info">Submit</button>
- </div>
- </div>
- </form>
-</section>
View
28 packages/articles/public/views/edit.html
@@ -1,28 +0,0 @@
-<section data-ng-controller="ArticlesController" data-ng-init="findOne()">
- <form name="articleForm" class="form-horizontal col-md-6" role="form" data-ng-submit="update(articleForm.$valid)" novalidate>
- <div class="form-group" ng-class="{ 'has-error' : submitted && articleForm.title.$invalid }">
- <label mean-token="'edit-title'" for="title" class="col-md-2 control-label">Title</label>
- <div class="col-md-10">
- <input name="title" type="text" class="form-control" data-ng-model="article.title" id="title" placeholder="Title" required>
- <div ng-show="submitted && articleForm.title.$invalid" class="help-block">
- <p ng-show="articleForm.title.$error.required">Title is required</p>
- </div>
- </div>
-
- </div>
- <div class="form-group" ng-class="{ 'has-error' : submitted && articleForm.content.$invalid }">
- <label mean-token="'edit-content'" for="content" class="col-md-2 control-label">Content</label>
- <div class="col-md-10">
- <textarea name="content" data-ng-model="article.content" id="content" cols="30" rows="10" placeholder="Content" class="form-control" required></textarea>
- <div ng-show="submitted && articleForm.content.$invalid" class="help-block">
- <p ng-show="articleForm.content.$error.required">Content is required</p>
- </div>
- </div>
- </div>
- <div class="form-group">
- <div class="col-md-offset-2 col-md-10">
- <button mean-token="'edit-submit'" type="submit" class="btn btn-default">Submit</button>
- </div>
- </div>
- </form>
-</section>
View
21 packages/articles/public/views/list.html
@@ -1,21 +0,0 @@
-<section data-ng-controller="ArticlesController" data-ng-init="find()">
- <ul class="articles unstyled">
- <li data-ng-repeat="article in articles">
- <span>{{article.created | date:'medium'}}</span> /
- <span>{{article.user.name}}</span>
- <h2>
- <a data-ng-href="#!/articles/{{article._id}}">{{article.title}}</a>
- <span data-ng-if="hasAuthorization(article)">
- <a class="btn" href="/#!/articles/{{article._id}}/edit">
- <i class="glyphicon glyphicon-edit"></i>
- </a>
- <a class="btn" data-ng-click="remove(article);">
- <i class="glyphicon glyphicon-trash"></i>
- </a>
- </span>
- </h2>
- <div>{{article.content}}</div>
- </li>
- </ul>
- <h1 data-ng-hide="!articles || articles.length">No articles yet. <br> Why don't you <a href="/#!/articles/create">Create One</a>?</h1>
-</section>
View
14 packages/articles/public/views/view.html
@@ -1,14 +0,0 @@
-<section data-ng-controller="ArticlesController" data-ng-init="findOne()">
- <span>{{article.created | date:'medium'}}</span> /
- <span>{{article.user.name}}</span>
- <h2>{{article.title}}</h2>
- <div data-ng-if="hasAuthorization(article)">
- <a class="btn" href="/#!/articles/{{article._id}}/edit">
- <i class="glyphicon glyphicon-edit"></i>
- </a>
- <a class="btn" data-ng-click="remove(article);">
- <i class="glyphicon glyphicon-trash"></i>
- </a>
- </div>
- <div>{{article.content}}</div>
-</section>
View
97 packages/articles/server/controllers/articles.js
@@ -1,97 +0,0 @@
-'use strict';
-
-/**
- * Module dependencies.
- */
-var mongoose = require('mongoose'),
- Article = mongoose.model('Article'),
- _ = require('lodash');
-
-
-/**
- * Find article by id
- */
-exports.article = function(req, res, next, id) {
- Article.load(id, function(err, article) {
- if (err) return next(err);
- if (!article) return next(new Error('Failed to load article ' + id));
- req.article = article;
- next();
- });
-};
-
-/**
- * Create an article
- */
-exports.create = function(req, res) {
- var article = new Article(req.body);
- article.user = req.user;
-
- article.save(function(err) {
- if (err) {
- return res.jsonp(500, {
- error: 'Cannot save the article'
- });
- }
- res.jsonp(article);
-
- });
-};
-
-/**
- * Update an article
- */
-exports.update = function(req, res) {
- var article = req.article;
-
- article = _.extend(article, req.body);
-
- article.save(function(err) {
- if (err) {
- return res.jsonp(500, {
- error: 'Cannot update the article'
- });
- }
- res.jsonp(article);
-
- });
-};
-
-/**
- * Delete an article
- */
-exports.destroy = function(req, res) {
- var article = req.article;
-
- article.remove(function(err) {
- if (err) {
- return res.jsonp(500, {
- error: 'Cannot delete the article'
- });
- }
- res.jsonp(article);
-
- });
-};
-
-/**
- * Show an article
- */
-exports.show = function(req, res) {
- res.jsonp(req.article);
-};
-
-/**
- * List of Articles
- */
-exports.all = function(req, res) {
- Article.find().sort('-created').populate('user', 'name username').exec(function(err, articles) {
- if (err) {
- return res.jsonp(500, {
- error: 'Cannot list the articles'
- });
- }
- res.jsonp(articles);
-
- });
-};
View
54 packages/articles/server/models/article.js
@@ -1,54 +0,0 @@
-'use strict';
-
-/**
- * Module dependencies.
- */
-var mongoose = require('mongoose'),
- Schema = mongoose.Schema;
-
-
-/**
- * Article Schema
- */
-var ArticleSchema = new Schema({
- created: {
- type: Date,
- default: Date.now
- },
- title: {
- type: String,
- required: true,
- trim: true
- },
- content: {
- type: String,
- required: true,
- trim: true
- },
- user: {
- type: Schema.ObjectId,
- ref: 'User'
- }
-});
-
-/**
- * Validations
- */
-ArticleSchema.path('title').validate(function(title) {
- return !!title;
-}, 'Title cannot be blank');
-
-ArticleSchema.path('content').validate(function(content) {
- return !!content;
-}, 'Content cannot be blank');
-
-/**
- * Statics
- */
-ArticleSchema.statics.load = function(id, cb) {
- this.findOne({
- _id: id
- }).populate('user', 'name username').exec(cb);
-};
-
-mongoose.model('Article', ArticleSchema);
View
25 packages/articles/server/routes/articles.js
@@ -1,25 +0,0 @@
-'use strict';
-
-var articles = require('../controllers/articles');
-
-// Article authorization helpers
-var hasAuthorization = function(req, res, next) {
- if (!req.user.isAdmin && req.article.user.id !== req.user.id) {
- return res.send(401, 'User is not authorized');
- }
- next();
-};
-
-module.exports = function(Articles, app, auth) {
-
- app.route('/articles')
- .get(articles.all)
- .post(auth.requiresLogin, articles.create);
- app.route('/articles/:articleId')
- .get(articles.show)
- .put(auth.requiresLogin, hasAuthorization, articles.update)
- .delete(auth.requiresLogin, hasAuthorization, articles.destroy);
-
- // Finish with setting up the articleId param
- app.param('articleId', articles.article);
-};
View
198 packages/articles/test/karma/controllers/articles.spec.js
@@ -1,198 +0,0 @@
-'use strict';
-
-(function() {
- // Articles Controller Spec
- describe('MEAN controllers', function() {
- describe('ArticlesController', function() {
- // 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 use a newly-defined 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);
- }
- });
- });
-
- // Load the controllers module
- beforeEach(module('mean'));
-
- // Initialize the controller and a mock scope
- var ArticlesController,
- scope,
- $httpBackend,
- $stateParams,
- $location;
-
- // 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_, _$stateParams_, _$httpBackend_) {
-
- scope = $rootScope.$new();
-
- ArticlesController = $controller('ArticlesController', {
- $scope: scope
- });
-
- $stateParams = _$stateParams_;
-
- $httpBackend = _$httpBackend_;
-
- $location = _$location_;
-
- }));
-
- it('$scope.find() should create an array with at least one article object ' +
- 'fetched from XHR', function() {
-
- // test expected GET request
- $httpBackend.expectGET('articles').respond([{
- title: 'An Article about MEAN',
- content: 'MEAN rocks!'
- }]);
-
- // run controller
- scope.find();
- $httpBackend.flush();
-
- // test scope value
- expect(scope.articles).toEqualData([{
- title: 'An Article about MEAN',
- content: 'MEAN rocks!'
- }]);
-
- });
-
- it('$scope.findOne() should create an array with one article object fetched ' +
- 'from XHR using a articleId URL parameter', function() {
- // fixture URL parament
- $stateParams.articleId = '525a8422f6d0f87f0e407a33';
-
- // fixture response object
- var testArticleData = function() {
- return {
- title: 'An Article about MEAN',
- content: 'MEAN rocks!'
- };
- };
-
- // test expected GET request with response object
- $httpBackend.expectGET(/articles\/([0-9a-fA-F]{24})$/).respond(testArticleData());
-
- // run controller
- scope.findOne();
- $httpBackend.flush();
-
- // test scope value
- expect(scope.article).toEqualData(testArticleData());
-
- });
-
- it('$scope.create() with valid form data should send a POST request ' +
- 'with the form input values and then ' +
- 'locate to new object URL', function() {
-
- // fixture expected POST data
- var postArticleData = function() {
- return {
- title: 'An Article about MEAN',
- content: 'MEAN rocks!'
- };
- };
-
- // fixture expected response data
- var responseArticleData = function() {
- return {
- _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!';
-
- // test post request is sent
- $httpBackend.expectPOST('articles', postArticleData()).respond(responseArticleData());
-
- // Run controller
- scope.create(true);
- $httpBackend.flush();
-
- // test form input(s) are reset
- expect(scope.title).toEqual('');
- expect(scope.content).toEqual('');
-
- // test URL location to new object
- expect($location.path()).toBe('/articles/' + responseArticleData()._id);
- });
-
- it('$scope.update(true) should update a valid article', inject(function(Articles) {
-
- // fixture rideshare
- var putArticleData = function() {
- return {
- _id: '525a8422f6d0f87f0e407a33',
- title: 'An Article about MEAN',
- to: 'MEAN is great!'
- };
- };
-
- // mock article object from form
- var article = new Articles(putArticleData());
-
- // mock article in scope
- scope.article = article;
-
- // test PUT happens correctly
- $httpBackend.expectPUT(/articles\/([0-9a-fA-F]{24})$/).respond();
-
- // testing the body data is out for now until an idea for testing the dynamic updated array value is figured out
- //$httpBackend.expectPUT(/articles\/([0-9a-fA-F]{24})$/, putArticleData()).respond();
- /*
- Error: Expected PUT /articles\/([0-9a-fA-F]{24})$/ with different data
- EXPECTED: {"_id":"525a8422f6d0f87f0e407a33","title":"An Article about MEAN","to":"MEAN is great!"}
- GOT: {"_id":"525a8422f6d0f87f0e407a33","title":"An Article about MEAN","to":"MEAN is great!","updated":[1383534772975]}
- */
-
- // run controller
- scope.update(true);
- $httpBackend.flush();
-
- // test URL location to new object
- expect($location.path()).toBe('/articles/' + putArticleData()._id);
-
- }));
-
- it('$scope.remove() should send a DELETE request with a valid articleId ' +
- 'and remove the article from the scope', inject(function(Articles) {
-
- // fixture rideshare
- var article = new Articles({
- _id: '525a8422f6d0f87f0e407a33'
- });
-
- // mock rideshares in scope
- scope.articles = [];
- scope.articles.push(article);
-
- // test expected rideshare DELETE request
- $httpBackend.expectDELETE(/articles\/([0-9a-fA-F]{24})$/).respond(204);
-
- // run controller
- scope.remove(article);
- $httpBackend.flush();
-
- // test after successful delete URL location articles lis
- //expect($location.path()).toBe('/articles');
- expect(scope.articles.length).toBe(0);
-
- }));
- });
- });
-}());
View
64 packages/articles/test/mocha/article/model.js
@@ -1,64 +0,0 @@
-'use strict';
-
-// there has to be a better way to bootstrap package models for mocha tests
-require('../../../server/models/article');
-
-/**
- * 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('<Unit Test>', function() {
- describe('Model Article:', function() {
- beforeEach(function(done) {
- user = new User({
- name: 'Full name',
- email: 'test@test.com',
- username: 'user',
- 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();
- user.remove();
- done();
- });
- });
-});
View
8 server/views/includes/foot.html
@@ -1,8 +1,8 @@
-{% for file in assets.js %}
- <script type="text/javascript" src="{{file}}"></script>
+{% for file in assets.core.js %}
+<script type="text/javascript" src="/{{file}}"></script>
{% endfor %}
{% if (process.env.NODE_ENV == 'development') %}
- <!-- Livereload script rendered -->
- <script type="text/javascript" src="{{'http://' + req.host + ':35729/livereload.js'}}"></script>
+<!-- Livereload script rendered -->
+<script type="text/javascript" src="{{'http://' + req.host + ':35729/livereload.js'}}"></script>
{% endif %}
View
20 server/views/includes/head.html
@@ -1,29 +1,29 @@
<head>
+<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1">
- <title>{{title}}</title>
+ <title>{{appName}} - {{title}}</title>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<meta name="keywords" content="node.js, express, mongoose, mongodb, angularjs, swig">
- <meta name="description" content="MEAN: MongoDB, ExpressJS, AngularJS, NodeJS.">
-
- <link href="/img/icons/favicon.ico" rel="shortcut icon" type="image/x-icon">
+ <meta name="description" content="MEAN - A Modern Stack: MongoDB, ExpressJS, AngularJS, NodeJS. (BONUS: Passport User Support).">
<meta property="fb:app_id" content="APP_ID">
<meta property="og:title" content="{{appName}} - {{title}}">
- <meta property="og:description" content="MEAN: MongoDB, ExpressJS, AngularJS, NodeJS.">
+ <meta property="og:description" content="MEAN - A Modern Stack: MongoDB, ExpressJS, AngularJS, NodeJS. (BONUS: Passport User Support).">
<meta property="og:type" content="website">
<meta property="og:url" content="APP_URL">
<meta property="og:image" content="APP_LOGO">
<meta property="og:site_name" content="MEAN - A Modern Stack">
<meta property="fb:admins" content="APP_ADMIN">
- {% for file in assets.css %}
- <link rel="stylesheet" href="{{file}}">
+ <link rel="stylesheet" href="/system/lib/bootstrap/dist/css/bootstrap.css">
+ {% for file in assets.core.css %}
+ <link rel="stylesheet" href="/{{file}}">
{% endfor %}
-<!--[if lt IE 9]>
+ <!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
-<![endif]-->
-</head>
+ <![endif]-->
+</head>

No commit comments for this range

Something went wrong with that request. Please try again.