From 7bb0aa74884d026bb6a0192bd2c4d0fb43f2953b Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 26 Apr 2020 02:41:26 +0200 Subject: Additional vote features --- client/components/cards/cardDetails.jade | 14 +++++++-- client/components/cards/cardDetails.js | 23 +++++--------- client/components/cards/minicard.jade | 2 ++ i18n/en.i18n.json | 2 ++ models/cards.js | 53 +++++++++++++++++++++++--------- 5 files changed, 62 insertions(+), 32 deletions(-) diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index ae97e0e9..85425c59 100644 --- a/client/components/cards/cardDetails.jade +++ b/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'}} diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index f31c3890..b8c7fa3f 100644 --- a/client/components/cards/cardDetails.js +++ b/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'); + }, }, ]; }, diff --git a/client/components/cards/minicard.jade b/client/components/cards/minicard.jade index b6ccd4d7..79dd9127 100644 --- a/client/components/cards/minicard.jade +++ b/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 diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index 864d60ce..0e22f871 100644 --- a/i18n/en.i18n.json +++ b/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", diff --git a/models/cards.js b/models/cards.js index 72153132..1633689e 100644 --- a/models/cards.js +++ b/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; -- cgit v1.2.3-1-g7c22