Browse Source

Additional vote features

Nico 5 years ago
parent
commit
7bb0aa7488

+ 12 - 2
client/components/cards/cardDetails.jade

@@ -212,6 +212,8 @@ template(name="cardDetails")
           else
             .card-label.card-label-green {{ voteCountPositive }}
             .card-label.card-label-red {{ voteCountNegative }}
+          unless ($and currentBoard.isPublic voteAllowNonBoardMembers )
+            .card-label.card-label-gray  {{ voteCount }} {{_ 'r-of' }} {{ currentBoard.activeMembers.length }}
       +viewer
         = getVoteQuestion
       button.card-details-green.js-vote.js-vote-positive(class="{{#if voteState}}voted{{/if}}") {{_ 'vote-for-it'}}
@@ -572,9 +574,17 @@ template(name="cardStartVotingPopup")
     .fields
       label(for="vote") {{_ 'vote-question'}}
       input.js-vote-field#vote(type="text" name="vote" value="{{card.getVoteQuestion}}" autofocus)
-      label(for="vote-public") {{_ 'vote-public'}}
-        a.js-toggle-vote-public
+      .check-div
+        a.flex.js-toggle-vote-public
           .materialCheckBox#vote-public(name="vote-public")
+          span {{_ 'vote-public'}}
+      .check-div
+        a.flex.js-toggle-vote-allow-non-members
+          .materialCheckBox#vote-allow-non-members(name="vote-allow-non-members")
+          span {{_ 'allowNonBoardMembers'}}
+      //- label(for="vote-public") {{_ 'vote-public'}}
+      //-   a.js-toggle-vote-public
+      //-     .materialCheckBox#vote-public(name="vote-public")
 
     button.primary.confirm.js-submit {{_ 'save'}}
     //- button.js-remove-color.negate.wide.right {{_ 'delete'}}

+ 7 - 16
client/components/cards/cardDetails.js

@@ -54,21 +54,7 @@ BlazeComponent.extendComponent({
     }
     return null;
   },
-  votePublic() {
-    const card = this.currentData();
-    if (card.vote) return card.vote.public;
-    return null;
-  },
-  voteCountPositive() {
-    const card = this.currentData();
-    if (card.vote && card.vote.positive) return card.vote.positive.length;
-    return null;
-  },
-  voteCountNegative() {
-    const card = this.currentData();
-    if (card.vote && card.vote.negative) return card.vote.negative.length;
-    return null;
-  },
+
   isWatching() {
     const card = this.currentData();
     return card.findWatcher(Meteor.userId());
@@ -1001,13 +987,18 @@ BlazeComponent.extendComponent({
           evt.preventDefault();
           const voteQuestion = evt.target.vote.value;
           const publicVote = $('#vote-public').hasClass('is-checked');
-          this.currentCard.setVoteQuestion(voteQuestion, publicVote);
+          const allowNonBoardMembers = $('#vote-allow-non-members').hasClass('is-checked');
+          this.currentCard.setVoteQuestion(voteQuestion, publicVote,allowNonBoardMembers);
           Popup.close();
         },
         'click a.js-toggle-vote-public'(event) {
           event.preventDefault();
           $('#vote-public').toggleClass('is-checked');
         },
+        'click a.js-toggle-vote-allow-non-members'(event) {
+          event.preventDefault();
+          $('#vote-allow-non-members').toggleClass('is-checked');
+        },
       },
     ];
   },

+ 2 - 0
client/components/cards/minicard.jade

@@ -103,7 +103,9 @@ template(name="minicard")
       if getVoteQuestion
         .badge.badge-state-image-only(title=getVoteQuestion)
           span.badge-icon.fa.fa-thumbs-up
+          span.badge-text {{ voteCountPositive }}
           span.badge-icon.fa.fa-thumbs-down
+          span.badge-text {{ voteCountNegative }}
       if attachments.count
         .badge
           span.badge-icon.fa.fa-paperclip

+ 2 - 0
i18n/en.i18n.json

@@ -166,6 +166,7 @@
   "cardStartVotingPopup-title": "Start a vote",
   "positiveVoteMembersPopup-title": "Proponents",
   "negativeVoteMembersPopup-title": "Opponents",
+  "allowNonBoardMembers": "Allow non board members",
   "vote-question": "Voting question",
   "vote-public": "Public vote",
   "vote-for-it": "for it",
@@ -675,6 +676,7 @@
   "r-of-checklist": "of checklist",
   "r-send-email": "Send an email",
   "r-to": "to",
+  "r-of": "of",
   "r-subject": "subject",
   "r-rule-details": "Rule details",
   "r-d-move-to-top-gen": "Move card to top of its list",

+ 39 - 14
models/cards.js

@@ -340,6 +340,10 @@ Cards.attachSchema(
       type: Boolean,
       defaultValue: false,
     },
+    'vote.allowNonBoardMembers': {
+      type: Boolean,
+      defaultValue: false,
+    },
   }),
 );
 
@@ -347,8 +351,8 @@ Cards.allow({
   insert(userId, doc) {
     return allowIsBoardMember(userId, Boards.findOne(doc.boardId));
   },
-  update(userId, doc) {
-    return allowIsBoardMember(userId, Boards.findOne(doc.boardId));
+  update(userId, doc, fields) {
+    return allowIsBoardMember(userId, Boards.findOne(doc.boardId)) || _.isEqual(fields, ['vote', 'modifiedAt', 'dateLastActivity']);
   },
   remove(userId, doc) {
     return allowIsBoardMember(userId, Boards.findOne(doc.boardId));
@@ -732,7 +736,7 @@ Cards.helpers({
 
   parentString(sep) {
     return this.parentList()
-      .map(function(elem) {
+      .map(function (elem) {
         return elem.title;
       })
       .join(sep);
@@ -1152,6 +1156,26 @@ Cards.helpers({
   isTemplateCard() {
     return this.type === 'template-card';
   },
+
+  votePublic() {
+    if (this.vote) return this.vote.public;
+    return null;
+  },
+  voteAllowNonBoardMembers() {
+    if (this.vote) return this.vote.allowNonBoardMembers;
+    return null;
+  },
+  voteCountNegative() {
+    if (this.vote && this.vote.negative) return this.vote.negative.length;
+    return null;
+  },
+  voteCountPositive() {
+    if (this.vote && this.vote.positive) return this.vote.positive.length;
+    return null;
+  },
+  voteCount() {
+    return this.voteCountPositive() + this.voteCountNegative()
+  },
 });
 
 Cards.mutations({
@@ -1475,12 +1499,13 @@ Cards.mutations({
       },
     };
   },
-  setVoteQuestion(question, public) {
+  setVoteQuestion(question, public, allowNonBoardMembers) {
     return {
       $set: {
         vote: {
           question,
           public,
+          allowNonBoardMembers,
           positive: [],
           negative: [],
         },
@@ -1929,7 +1954,7 @@ if (Meteor.isServer) {
   });
 
   //New activity for card moves
-  Cards.after.update(function(userId, doc, fieldNames) {
+  Cards.after.update(function (userId, doc, fieldNames) {
     const oldListId = this.previous.listId;
     const oldSwimlaneId = this.previous.swimlaneId;
     const oldBoardId = this.previous.boardId;
@@ -1975,7 +2000,7 @@ if (Meteor.isServer) {
         // change list modifiedAt, when user modified the key values in timingaction array, if it's endAt, put the modifiedAt of list back to one year ago for sorting purpose
         const modifiedAt = new Date(
           new Date(value).getTime() -
-            (action === 'endAt' ? 365 * 24 * 3600 * 1e3 : 0),
+          (action === 'endAt' ? 365 * 24 * 3600 * 1e3 : 0),
         ); // set it as 1 year before
         const boardId = list.boardId;
         Lists.direct.update(
@@ -2029,7 +2054,7 @@ if (Meteor.isServer) {
   JsonRoutes.add(
     'GET',
     '/api/boards/:boardId/swimlanes/:swimlaneId/cards',
-    function(req, res) {
+    function (req, res) {
       const paramBoardId = req.params.boardId;
       const paramSwimlaneId = req.params.swimlaneId;
       Authentication.checkBoardAccess(req.userId, paramBoardId);
@@ -2039,7 +2064,7 @@ if (Meteor.isServer) {
           boardId: paramBoardId,
           swimlaneId: paramSwimlaneId,
           archived: false,
-        }).map(function(doc) {
+        }).map(function (doc) {
           return {
             _id: doc._id,
             title: doc.title,
@@ -2063,7 +2088,7 @@ if (Meteor.isServer) {
    *                title: string,
    *                description: string}]
    */
-  JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId/cards', function(
+  JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId/cards', function (
     req,
     res,
   ) {
@@ -2076,7 +2101,7 @@ if (Meteor.isServer) {
         boardId: paramBoardId,
         listId: paramListId,
         archived: false,
-      }).map(function(doc) {
+      }).map(function (doc) {
         return {
           _id: doc._id,
           title: doc.title,
@@ -2098,7 +2123,7 @@ if (Meteor.isServer) {
   JsonRoutes.add(
     'GET',
     '/api/boards/:boardId/lists/:listId/cards/:cardId',
-    function(req, res) {
+    function (req, res) {
       const paramBoardId = req.params.boardId;
       const paramListId = req.params.listId;
       const paramCardId = req.params.cardId;
@@ -2130,7 +2155,7 @@ if (Meteor.isServer) {
    * @param {string} [assignees] the array of maximum one ID of assignee of the new card
    * @return_type {_id: string}
    */
-  JsonRoutes.add('POST', '/api/boards/:boardId/lists/:listId/cards', function(
+  JsonRoutes.add('POST', '/api/boards/:boardId/lists/:listId/cards', function (
     req,
     res,
   ) {
@@ -2237,7 +2262,7 @@ if (Meteor.isServer) {
   JsonRoutes.add(
     'PUT',
     '/api/boards/:boardId/lists/:listId/cards/:cardId',
-    function(req, res) {
+    function (req, res) {
       Authentication.checkUserId(req.userId);
       const paramBoardId = req.params.boardId;
       const paramCardId = req.params.cardId;
@@ -2536,7 +2561,7 @@ if (Meteor.isServer) {
   JsonRoutes.add(
     'DELETE',
     '/api/boards/:boardId/lists/:listId/cards/:cardId',
-    function(req, res) {
+    function (req, res) {
       Authentication.checkUserId(req.userId);
       const paramBoardId = req.params.boardId;
       const paramListId = req.params.listId;