Browse Source

Commit 11-2: Display notifications in the header.

- plus realigned code more with the original
Frederic G. MARAND 9 years ago
parent
commit
aa3c838092

+ 2 - 1
.meteor/packages

@@ -9,6 +9,7 @@ iron:router
 twbs:bootstrap
 underscore
 sacha:spin
-ian:accounts-ui-bootstrap-3
 accounts-password
+ian:accounts-ui-bootstrap-3
 audit-argument-checks
+

+ 1 - 1
.meteor/platforms

@@ -1,2 +1,2 @@
-browser
 server
+browser

+ 7 - 0
LICENSE.txt

@@ -0,0 +1,7 @@
+Copyright (C) 2012--2014 Discover Meteor
+
+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.

+ 34 - 0
README.markdown

@@ -0,0 +1,34 @@
+# Microscope
+
+Microscope is a simple social news app that lets you share links, comment, and vote on them.
+
+It was built with [Meteor](http://meteor.com) as a companion app to [The Meteor Book](http://themeteorbook.com), and is the "little brother" of [Telescope](http://telesc.pe), the (much more complex) open-source social news app that was the inspiration for the book.
+
+Microscope itself is free and open-source, and is a good example of common Meteor app patterns such as:
+
+- Routing
+- User Accounts
+- Notifications
+- Errors
+- Publications/Subscriptions
+- Permissions
+
+## This Repository
+
+The commits to this repository are organized in a very linear fashion, corresponding to progress throughout the book. Commits are tagged in the format `chapterX-Y`, indicating the `Y`th commit of chapter `X`.
+
+Also, note that as the book focuses on _development_, all CSS is committed in a single commit early on.
+
+### Branches
+
+There are 2 branches in this repository which correspond to advanced code that is covered in sidebars of the book, and outside of the main code progression. They are tagged `sidebarX-Y`, corresponding to the sidebar number in the book.
+
+### Developing on Nitrous.IO
+
+Start hacking on this app on
+[Nitrous.IO](https://www.nitrous.io/?utm_source=github.com&utm_campaign=Microscope&utm_medium=hackonnitrous)
+in seconds:
+
+[![Hack DiscoverMeteor/Microscope on
+Nitrous.IO](https://d3o0mnbgv6k92a.cloudfront.net/assets/hack-l-v1-3cc067e71372f6045e1949af9d96095b.png)](https://www.nitrous.io/hack_button?source=embed&runtime=nodejs&repo=DiscoverMeteor%2FMicroscope&file_to_open=README.nitrous.md)
+

+ 14 - 0
README.nitrous.md

@@ -0,0 +1,14 @@
+# Setup for Nitrous.IO
+
+Before you can run this project, you will need to install Meteor with Autoparts, and install Meteorite with NPM.
+
+Run the following commands in the Terminal below:
+
+1. `cd ~/workspace/Microscope/`
+2. `parts install meteor`
+3. `npm install -g meteorite`
+4. `mrt update`
+5. `meteor`
+
+Go to the "Preview Menu" and click "Port 3000"
+

+ 1 - 10
client/helpers/config.js

@@ -1,12 +1,3 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 31/08/15
- * Time: 13:11
- */
-
 Accounts.ui.config({
   passwordSignupFields: 'USERNAME_ONLY'
-});
+});

+ 3 - 13
client/helpers/errors.js

@@ -1,16 +1,6 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 03/09/15
- * Time: 16:46
- */
-
-// Local client-only collection.
+// Local (client-only) collection.
 Errors = new Mongo.Collection(null);
 
-// Global
-throwError = function(message) {
-  Errors.insert({ message: message });
+throwError = function (message) {
+  Errors.insert({message: message});
 };

+ 4 - 4
client/templates/application/layout.html

@@ -1,10 +1,10 @@
 <template name="layout">
   <div class="container">
-    {{> header }}
-    {{> errors }}
+    {{> header}}
+    {{> errors}}
     <div id="main">
       {{! IronRouter magic }}
-      {{> yield }}
+      {{> yield}}
     </div>
   </div>
-</template>
+</template>

+ 0 - 0
client/templates/not_found.html → client/templates/application/not_found.html


+ 2 - 2
client/templates/comments/commment_item.html → client/templates/comments/comment_item.html

@@ -2,8 +2,8 @@
   <li>
     <h4>
       <span class="author">{{author}}</span>
-      <span class="date">{{submittedText}}</span>
+      <span class="date">on {{submittedText}}</span>
     </h4>
     <p>{{body}}</p>
   </li>
-</template>
+</template>

+ 1 - 10
client/templates/comments/comment_item.js

@@ -1,14 +1,5 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 05/09/15
- * Time: 22:10
- */
-
 Template.commentItem.helpers({
   submittedText: function () {
     return this.submitted.toString();
   }
-});
+});

+ 2 - 2
client/templates/comments/comment_submit.html

@@ -7,6 +7,6 @@
         <span class="help-block">{{errorMessage 'body'}}</span>
       </div>
     </div>
-    <button type="submit" class="btn btn-primary">Add comment</button>
+    <button type="submit" class="btn btn-primary">Add Comment</button>
   </form>
-</template>
+</template>

+ 4 - 14
client/templates/comments/comment_submit.js

@@ -1,12 +1,3 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 06/09/15
- * Time: 22:05
- */
-
 Template.commentSubmit.onCreated(function () {
   Session.set('commentSubmitErrors', {});
 });
@@ -17,7 +8,7 @@ Template.commentSubmit.helpers({
   },
   errorClass: function (field) {
     return !!Session.get('commentSubmitErrors')[field] ? 'has-error' : '';
-  },
+  }
 });
 
 Template.commentSubmit.events({
@@ -32,17 +23,16 @@ Template.commentSubmit.events({
 
     var errors = {};
     if (!comment.body) {
-      errors.body =  'Please write some content';
+      errors.body = "Please write some content";
       return Session.set('commentSubmitErrors', errors);
     }
 
     Meteor.call('commentInsert', comment, function (error, commentId) {
       if (error) {
         throwError(error.reason);
-      }
-      else {
+      } else {
         $body.val('');
       }
     });
   }
-});
+});

+ 2 - 2
client/templates/includes/access_denied.html

@@ -1,6 +1,6 @@
 <template name="accessDenied">
   <div class="access-denied page jumbotron">
-    <h2>Access denied</h2>
+    <h2>Access Denied</h2>
     <p>You can't get here! Please log in.</p>
   </div>
-</template>
+</template>

+ 1 - 11
client/templates/includes/errors.js

@@ -1,12 +1,3 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 03/09/15
- * Time: 17:22
- */
-
 Template.errors.helpers({
   errors: function () {
     return Errors.find();
@@ -15,8 +6,7 @@ Template.errors.helpers({
 
 Template.error.onRendered(function () {
   var error = this.data;
-  Meteor._debug(this.data);
   Meteor.setTimeout(function () {
     Errors.remove(error._id);
   }, 3000);
-});
+});

+ 7 - 2
client/templates/includes/header.html

@@ -13,7 +13,12 @@
     <div class="collapse navbar-collapse" id="navigation">
       <ul class="nav navbar-nav">
         {{#if currentUser}}
-          <li><a href="{{ pathFor 'postSubmit' }}">Submit Post</a></li>
+          <li>
+            <a href="{{ pathFor 'postSubmit' }}">Submit Post</a>
+          </li>
+          <li class="dropdown">
+            {{> notifications}}
+          </li>
           {{/if}}
       </ul>
       <ul class="nav navbar-nav navbar-right">
@@ -21,4 +26,4 @@
       </ul>
     </div>
   </nav>
-</template>
+</template>

+ 26 - 0
client/templates/notifications/notifications.html

@@ -0,0 +1,26 @@
+<template name="notifications">
+  <a href="#" class="dropdown-toggle" data-toggle="dropdown">
+    Notifications
+    {{#if notificationCount }}
+      <span class="badge badge-inverse">{{ notificationCount }}</span>
+    {{/if}}
+    <b class="caret"></b>
+  </a>
+  <ul class="notification dropdown-menu">
+    {{#if notificationCount }}
+      {{#each notifications}}
+        {{> notificationItem }}
+      {{/each}}
+    {{else}}
+      <li><span>No Notifications</span></li>
+    {{/if}}
+  </ul>
+</template>
+
+<template name="notificationItem">
+  <li>
+    <a href="{{ notificationPostPath }}">
+      <strong>{{ commenterName }}</strong> commented on your post
+    </a>
+  </li>
+</template>

+ 28 - 0
client/templates/notifications/notifications.js

@@ -0,0 +1,28 @@
+Template.notifications.helpers({
+  notifications: function () {
+    return Notifications.find({
+      userId: Meteor.userId(),
+      read: false
+    });
+  },
+
+  notificationCount: function () {
+    return Notifications.find({
+      userId: Meteor.userId(),
+      read: false
+    }).count();
+  }
+});
+
+Template.notificationItem.helpers({
+  notificationPostPath: function () {
+    return Router.routes.postPage.path({ _id: this.postId });
+  }
+});
+
+Template.notificationItem.events({
+  'click a': function () {
+    // Here, "this" is a Notification document..
+    Notifications.update(this._id, { $set : { read: true }});
+  }
+});

+ 9 - 7
client/templates/posts/post_edit.html

@@ -2,18 +2,20 @@
   <form class="main form page">
     <div class="form-group {{ errorClass 'url' }}">
       <label class="control-label" for="url">URL</label>
-      <input type="text" name="url" id="url" value="{{url}}" placeholder="Your URL" class="form-control" />
-      <span class="help-block">{{ errorMessage 'url' }}</span>
+      <div class="controls">
+        <input name="url" id="url" type="text" value="{{url}}" placeholder="Your URL" class="form-control" />
+        <span class="help-block">{{ errorMessage 'url' }}</span>
+      </div>
     </div>
-
     <div class="form-group {{ errorClass 'title' }}">
       <label class="control-label" for="title">Title</label>
-      <input type="text" name="title" id="title" value="{{title}}" placeholder="Name yout post" class="form-control" />
-      <span class="help-block">{{ errorMessage 'title' }}</span>
+      <div class="controls">
+        <input name="title" id="title" type="text" value="{{title}}" placeholder="Name your post" class="form-control" />
+        <span class="help-block">{{ errorMessage 'title' }}</span>
+      </div>
     </div>
-
     <input type="submit" value="Submit" class="btn btn-primary submit" />
     <hr />
     <a class="btn btn-danger delete" href="#">Delete post</a>
   </form>
-</template>
+</template>

+ 16 - 25
client/templates/posts/post_edit.js

@@ -1,11 +1,16 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 02/09/15
- * Time: 08:43
- */
+Template.postEdit.onCreated(function () {
+  Session.set('postEditErrors', {});
+});
+
+Template.postEdit.helpers({
+  errorMessage: function (field) {
+    return Session.get('postEditErrors')[field];
+  },
+
+  errorClass: function (field) {
+    return !!Session.get('postEditErrors')[field] ? 'has-error' : '';
+  }
+});
 
 Template.postEdit.events({
   'submit form': function (e) {
@@ -27,7 +32,8 @@ Template.postEdit.events({
     Posts.update(currentPostId, { $set: postProperties }, function (error) {
       // Display the error to the user and abort.
       if (error) {
-        return throwError(error.reason);
+        // Display the error to the user.
+        throwError(error.reason);
       }
       else {
         Router.go('postPage', { _id: currentPostId });
@@ -43,20 +49,5 @@ Template.postEdit.events({
       Posts.remove(currentPostId);
       Router.go('postsList');
     }
-
   }
-});
-
-Template.postEdit.onCreated(function () {
-  Session.set('postEditErrors', {});
-});
-
-Template.postEdit.helpers({
-  errorMessage: function (field) {
-    return Session.get('postEditErrors')[field];
-  },
-
-  errorClass: function (field) {
-    return Session.get('postEditErrors')[field] ? 'has-error' : '';
-  }
-});
+});

+ 3 - 2
client/templates/posts/post_item.html

@@ -2,7 +2,8 @@
   <div class="post">
     <div class="post-content">
       <h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3>
-      <p>Submitted by {{author}},
+      <p>
+        submitted by {{author}},
         <a href="{{pathFor 'postPage' }}">{{commentsCount}} comments</a>
         {{#if ownPost}}<a href="{{pathFor 'postEdit' }}">Edit</a>{{/if}}
       </p>
@@ -15,4 +16,4 @@
     }}
     <a href="{{pathFor 'postPage'}}" class="discuss btn btn-default">Discuss</a>
   </div>
-</template>
+</template>

+ 1 - 10
client/templates/posts/post_item.js

@@ -1,12 +1,3 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 30/08/15
- * Time: 10:15
- */
-
 Template.postItem.helpers({
   ownPost: function ()  {
     // Template is invoked in the context of a Post, so 'this' is a Post.
@@ -18,4 +9,4 @@ Template.postItem.helpers({
     a.href = this.url;
     return a.hostname;
   }
-});
+});

+ 3 - 1
client/templates/posts/post_page.html

@@ -1,15 +1,17 @@
 <template name="postPage">
   <div class="post-page page">
     {{> postItem}}
+
     <ul class="comments">
       {{#each comments}}
         {{> commentItem}}
       {{/each}}
     </ul>
+
     {{#if currentUser}}
       {{> commentSubmit}}
     {{else}}
       <p>Please log in to leave a comment.</p>
     {{/if}}
   </div>
-</template>
+</template>

+ 1 - 10
client/templates/posts/post_page.js

@@ -1,16 +1,7 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 05/09/15
- * Time: 22:06
- */
-
 Template.postPage.helpers({
   comments: function () {
     return Comments.find({
       postId: this._id
     });
   }
-});
+});

+ 3 - 1
client/templates/posts/post_submit.html

@@ -9,9 +9,11 @@
     </div>
     <div class="form-group {{ errorClass 'title' }}">
       <label class="control-label" for="title">Title</label>
+      <div class="controls">
       <input name="title" id="title" type="text" value="" placeholder="Name your post" class="form-control" />
       <span class="help-block">{{ errorMessage 'title' }}</span>
     </div>
+    </div>
     <input type="submit" value="Submit" class="btn btn-primary" />
   </form>
-</template>
+</template>

+ 16 - 23
client/templates/posts/post_submit.js

@@ -1,11 +1,16 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 31/08/15
- * Time: 20:47
- */
+Template.postSubmit.onCreated(function () {
+  Session.set('postSubmitErrors', {});
+});
+
+Template.postSubmit.helpers({
+  errorMessage: function (field) {
+    return Session.get('postSubmitErrors')[field];
+  },
+
+  errorClass: function (field) {
+    return !!Session.get('postSubmitErrors')[field] ? 'has-error' : '';
+  }
+});
 
 Template.postSubmit.events({
   'submit form': function (e) {
@@ -28,6 +33,8 @@ Template.postSubmit.events({
       if (error) {
         return throwError(error.reason);
       }
+
+      // Show this result but route anyway.
       if (result.postExists) {
         throwError("This link has already been posted");
       }
@@ -35,18 +42,4 @@ Template.postSubmit.events({
       Router.go('postPage', { _id: result._id });
     });
   }
-});
-
-Template.postSubmit.onCreated(function () {
-  Session.set('postSubmitErrors', {});
-});
-
-Template.postSubmit.helpers({
-  errorMessage: function (field) {
-    return Session.get('postSubmitErrors')[field];
-  },
-
-  errorClass: function (field) {
-    return Session.get('postSubmitErrors')[field] ? 'has-error' : '';
-  }
-});
+});

+ 2 - 2
client/templates/posts/posts_list.html

@@ -1,7 +1,7 @@
 <template name="postsList">
-  <div class="posts">
+  <div class="posts page">
     {{#each posts}}
       {{> postItem}}
     {{/each}}
   </div>
-</template>
+</template>

+ 1 - 10
client/templates/posts/posts_list.js

@@ -1,14 +1,5 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 30/08/15
- * Time: 10:07
- */
 Template.postsList.helpers({
   posts: function () {
     return Posts.find({}, { sort: { submitted: -1 }});
   }
-});
-
+});

+ 5 - 10
lib/collections/comments.js

@@ -1,12 +1,3 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 05/09/15
- * Time: 21:47
- */
-
 Comments = new Mongo.Collection('comments');
 
 Meteor.methods({
@@ -16,8 +7,10 @@ Meteor.methods({
       postId: String,
       body: String
     });
+
     var user = Meteor.user();
     var post = Posts.findOne(commentAttributes.postId);
+
     if (!post) {
       throw new Meteor.Error('invalid-comment', 'You must comment on a post');
     }
@@ -26,12 +19,14 @@ Meteor.methods({
       author: user.username,
       submitted: new Date()
     });
+
+    // Update the post with the number of comments.
     Posts.update(comment.postId, {
       $inc: { commentsCount: 1 }
     });
 
     // Create the comment, save its id.
-    comment._id = Comment.insert(comment);
+    comment._id = Comments.insert(comment);
 
     // Now create a notification, informing the post author that there's been a
     // comment created on their post.

+ 2 - 12
lib/collections/notifications.js

@@ -1,17 +1,7 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 07/09/15
- * Time: 18:48
- */
-
-// Notifications are sent to a post author when someone comments on their post.
 Notifications = new Mongo.Collection('notifications');
 
 Notifications.allow({
-  'update': function (userId, doc, fieldNames) {
+  update: function (userId, doc, fieldNames) {
     // Only allow post author to update, and only the "read" field.
     return ownsDocument(userId, doc) &&
       fieldNames.length === 1 && fieldNames[0] === 'read';
@@ -21,7 +11,7 @@ Notifications.allow({
 createCommentNotification = function (comment) {
   var post = Posts.findOne(comment.postId);
   if (comment.userId !== post.userId) {
-    Notification.insert({
+    Notifications.insert({
       userId: post.userId,
       postId: post._id,
       commentId: comment._id,

+ 16 - 24
lib/collections/posts.js

@@ -1,17 +1,6 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 30/08/15
- * Time: 10:48
- */
-
 // Not a "var", to make it global.
 Posts = new Mongo.Collection('posts');
 
-// Removed Posts.allow : we no longer trigger inserts from client.
-
 Posts.allow({
   update: function (userId, post) {
     return ownsDocument(userId, post);
@@ -24,6 +13,7 @@ Posts.allow({
 Posts.deny({
   update: function (userId, post, fieldNames) {
     // _.without() is like PHP array_diff($source, ...$keys).
+    // May only edit the following two fields:
     return (_.without(fieldNames, "url", "title").length > 0);
   }
 });
@@ -38,11 +28,23 @@ Posts.deny({
   }
 });
 
+validatePost = function (post) {
+  var errors = {};
+  if (!post.title) {
+    errors.title = "Please fill in a headline";
+  }
+  if (!post.url) {
+    errors.url = "Please fill in a URL";
+  }
+
+  return errors;
+};
+
 // This is in lib/ instead of server/ for latency compensation.
 Meteor.methods({
   postInsert: function(postAttributes) {
     "use strict";
-    check(Meteor.userId(), String);
+    check(this.userId, String); // Or Meteor.userId() ?
     check(postAttributes, {
       title: String,
       url: String
@@ -70,21 +72,11 @@ Meteor.methods({
       submitted: new Date(),
       commentsCount: 0
     });
+
     var postId =  Posts.insert(post);
+
     return {
       _id: postId
     };
   }
 });
-
-validatePost = function (post) {
-  var errors = {};
-  if (!post.title) {
-    errors.title = "Please fill in a headline";
-  }
-  if (!post.url) {
-    errors.url = "Please fill in a URL";
-  }
-
-  return errors;
-};

+ 1 - 10
lib/permissions.js

@@ -1,13 +1,4 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 02/09/15
- * Time: 08:58
- */
-
 // Global, so no "var".
 ownsDocument = function (userId, doc) {
   return doc && doc.userId === userId;
-};
+};

+ 11 - 22
lib/router.js

@@ -1,16 +1,7 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 30/08/15
- * Time: 16:47
- */
-
 Router.configure({
-  layoutTemplate: "layout",
-  loadingTemplate: "loading",
-  notFoundTemplate: "notFound",
+  layoutTemplate: 'layout',
+  loadingTemplate: 'loading',
+  notFoundTemplate: 'notFound',
   waitOn: function () {
     return [
       Meteor.subscribe('posts'),
@@ -48,27 +39,25 @@ Router.route('/submit', {
   name: 'postSubmit'
 });
 
-// Faire une 404 si la page matche la route postPage, mais pas son argument.
-// Déclenché pour toute valeur "falsy" (null, false, undefined, empty).
-Router.onBeforeAction('dataNotFound', {
-  only: 'postPage'
-});
-
 var requireLogin = function () {
   if (!Meteor.user()) {
     if (Meteor.loggingIn()) {
       // Défini dans Router.configure().
       this.render(this.loadingTemplate);
-    }
-    else {
+    } else {
       this.render('accessDenied');
     }
-  }
-  else {
+  } else {
     this.next();
   }
 };
 
+// Faire une 404 si la page matche la route postPage, mais pas son argument.
+// Déclenché pour toute valeur "falsy" (null, false, undefined, empty).
+Router.onBeforeAction('dataNotFound', {
+  only: 'postPage'
+});
+
 // Appliquer le contrôle d'accès à la route postSubmit.
 Router.onBeforeAction(requireLogin, {
   only: 'postSubmit'

+ 7 - 15
server/fixtures.js

@@ -1,12 +1,4 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 30/08/15
- * Time: 11:33
- */
-
+// Fixture data.
 if (Posts.find().count() === 0) {
   var now = new Date().getTime();
 
@@ -22,10 +14,10 @@ if (Posts.find().count() === 0) {
   var sacha = Meteor.users.findOne(sachaId);
 
   var telescopeId = Posts.insert({
-    title: "Introducing Telescope",
+    title: 'Introducing Telescope',
     userId: sacha._id,
     author: sacha.profile.name,
-    url: "http://sachagreif.com/introducing-telescope",
+    url: 'http://sachagreif.com/introducing-telescope/',
     submitted: new Date(now - 7 * 3600 * 1000),
     commentsCount: 2
   });
@@ -47,19 +39,19 @@ if (Posts.find().count() === 0) {
   });
 
   Posts.insert({
-    title: "Meteor",
+    title: 'Meteor',
     userId: tom._id,
     author: tom.profile.name,
-    url: "http://meteor.com",
+    url: 'http://meteor.com',
     submitted: new Date(now - 10 * 3600 * 1000),
     commentsCount: 0
   });
 
   Posts.insert({
-    title: "The Meteor book",
+    title: 'The Meteor Book',
     userId: tom._id,
     author: tom.profile.name,
-    url: "http://themeteorbook.com",
+    url: 'http://themeteorbook.com',
     submitted: new Date(now - 12 * 3600 * 1000),
     commentsCount: 0
   });

+ 0 - 9
server/publications.js

@@ -1,12 +1,3 @@
-/**
- * @file
- *
- *
- * User: marand
- * Date: 30/08/15
- * Time: 11:53
- */
-
 Meteor.publish('posts', function() {
   return Posts.find();
 });