Ver código fonte

Step 3: Users can up and down vote webpages by clicking a plus or a minus button.

- users need to be logged in, and can only vote once per site
- they can change their vote, but not unvote
Frederic G. MARAND 9 anos atrás
pai
commit
ab2c9921f2

+ 3 - 0
.eslintrc.js

@@ -16,6 +16,9 @@ module.exports = {
     "Accounts": true,
     "Session": true,
 
+    // From built-in Underscore.
+    "_": true,
+
     // From check.
     "check": true,
 

+ 5 - 0
client/helpers.js

@@ -0,0 +1,5 @@
+/**
+ * Global helpers, common to all templates.
+ */
+
+Template.registerHelper("isLoggedIn", isLoggedIn);

+ 0 - 3
client/website_form.js

@@ -10,7 +10,6 @@ Template.website_form.events({
   },
 
   "submit .js-save-website-form": function (event) {
-
     // here is an example of how to get the url out of the form:
     const url = event.target.url.value;
     const title = event.target.title.value;
@@ -25,5 +24,3 @@ Template.website_form.events({
     return false;
   }
 });
-
-Template.website_form.helpers({ isLoggedIn });

+ 9 - 7
client/website_item.html

@@ -5,12 +5,14 @@
     <p>
       {{description}}
     </p>
-    <a href="#" class="btn btn-default js-upvote">
-      <span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>
-    </a>
-    <a href="#" class="btn btn-default js-downvote">
-      <span class="glyphicon glyphicon-arrow-down" aria-hidden="true"></span>
-    </a>
-    <!-- you will be putting your up and down vote buttons in here! -->
+    {{#if isLoggedIn }}
+      <a href="#" class="btn btn-default js-upvote {{ upVoted }}">
+        <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
+      </a>
+      <a href="#" class="btn btn-default js-downvote {{ downVoted }}">
+        <span class="glyphicon glyphicon-minus-sign" aria-hidden="true"></span>
+      </a>
+      <!-- you will be putting your up and down vote buttons in here! -->
+    {{/if}}
   </li>
 </template>

+ 32 - 3
client/website_item.js

@@ -7,27 +7,56 @@
  */
 
 Template.website_item.events({
-  "click .js-upvote": function (event) {
+  "click .js-upvote": function () {
     // Example of how you can access the id for the website in the database
     // (this is the data context for the template)
     const websiteId = this._id;
     console.log("Up voting website with id " + websiteId);
     // Put the code in here to add a vote to a website!
+    const userId = Meteor.userId();
+    const modifiers = {
+      $addToSet: {
+        plus: userId
+      },
+      $pull: {
+        minus: userId
+      }
+    };
+    Websites.update({ _id: websiteId }, modifiers);
 
     // Prevent the button from reloading the page.
     return false;
   },
 
-  "click .js-downvote": function (event) {
-
+  "click .js-downvote": function () {
     // example of how you can access the id for the website in the database
     // (this is the data context for the template)
     const websiteId = this._id;
     console.log("Down voting website with id " + websiteId);
 
     // Put the code in here to remove a vote from a website!
+    const userId = Meteor.userId();
+    const modifiers = {
+      $addToSet: {
+        minus: userId
+      },
+      $pull: {
+        plus: userId
+      }
+    };
+    Websites.update({ _id: websiteId }, modifiers);
 
     // Prevent the button from reloading the page
     return false;
   }
 });
+
+Template.website_item.helpers({
+  upVoted: function () {
+    return _.contains(this.plus, Meteor.userId()) ? "btn-success" : "";
+  },
+
+  downVoted: function () {
+    return _.contains(this.minus, Meteor.userId()) ? "btn-danger" : "";
+  }
+});

+ 0 - 4
lib/collections.js

@@ -1,6 +1,2 @@
 Websites = new Mongo.Collection("websites");
-
-Websites.validate = function () {
-
-};
 // See security in server/collections.js

+ 27 - 0
server/collections.js

@@ -42,6 +42,33 @@ Websites.allow({
       // return false;
     }
 
+    return true;
+  },
+
+  /**
+   * Access check for update operations. NOT SAFE: needs deeper modifier checks.
+   *
+   * @param {String} userId
+   *   The user attempting the modification.
+   * @param {Object} doc
+   *   The original document to modify.
+   * @param {Array} fields
+   *   The list of affected fields.
+   * @param {Object} modifier
+   *   The MongoDB update modifier.
+   * @returns {boolean}
+   *   True to allow update.
+   */
+  update: function (userId, doc, fields, modifier) {
+    if (!userId) {
+      throw new Meteor.Error("logged-out", "User must be logged to vote on a site.");
+    }
+    const orderedFields = fields.sort();
+    if (!_.isEqual(orderedFields, ["minus", "plus"])) {
+      throw new Meteor.Error("invalid-field", "May only update minus and plus.");
+    }
+
+    // FIXME : check modifier.
     return true;
   }
 });