From 8f28a409c7dd90319f785e3fc4c1b26803f67f31 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 10 Apr 2020 01:46:36 +0200 Subject: Public vote --- client/components/cards/cardDetails.jade | 35 ++++++++++++++++---- client/components/cards/cardDetails.js | 25 ++++++++++---- client/components/cards/cardDetails.styl | 2 ++ i18n/en.i18n.json | 3 ++ models/cards.js | 56 +++++++++++++++++++++++++------- models/trelloCreator.js | 1 + 6 files changed, 98 insertions(+), 24 deletions(-) diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index 9cd581ea..99606ae4 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -206,12 +206,12 @@ template(name="cardDetails") i.fa.fa-thumbs-up card-details-item-title {{_ 'vote-question'}} .vote-result - .card-label.card-label-green - +viewer - = voteCountPositive - .card-label.card-label-red - +viewer - = voteCountNegative + if votePublic + a.card-label.card-label-green.js-show-positive-votes {{ voteCountPositive }} + a.card-label.card-label-red.js-show-negative-votes {{ voteCountNegative }} + else + .card-label.card-label-green {{ voteCountPositive }} + .card-label.card-label-red {{ voteCountNegative }} +viewer = getVoteQuestion button.card-details-green.js-vote.js-vote-positive(class="{{#if voteState}}voted{{/if}}") {{_ 'vote-for-it'}} @@ -572,6 +572,29 @@ 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 + .materialCheckBox#vote-public(name="vote-public") button.primary.confirm.js-submit {{_ 'save'}} //- button.js-remove-color.negate.wide.right {{_ 'delete'}} + +template(name="positiveVoteMembersPopup") + ul.pop-over-list.js-card-member-list + each m in voteMemberPositive + li.item + a.name + +userAvatar(userId=m._id) + span.full-name + = m.profile.fullname + | ({{ m.username }}) + +template(name="negativeVoteMembersPopup") + ul.pop-over-list.js-card-member-list + each m in voteMemberNegative + li.item + a.name + +userAvatar(userId=m._id) + span.full-name + = m.profile.fullname + | ({{ m.username }}) diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index 84ba21b1..6ca5d784 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -54,6 +54,12 @@ 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; @@ -382,6 +388,8 @@ BlazeComponent.extendComponent({ 'click .js-start-date': Popup.open('editCardStartDate'), 'click .js-due-date': Popup.open('editCardDueDate'), 'click .js-end-date': Popup.open('editCardEndDate'), + 'click .js-show-positive-votes':Popup.open('positiveVoteMembers'), + 'click .js-show-negative-votes': Popup.open('negativeVoteMembers'), 'mouseenter .js-card-details'() { const parentComponent = this.parentComponent().parentComponent(); //on mobile view parent is Board, not BoardBody. @@ -647,7 +655,7 @@ Template.cardDetailsActionsPopup.events({ }, }); -Template.editCardTitleForm.onRendered(function() { +Template.editCardTitleForm.onRendered(function () { autosize(this.$('.js-edit-card-title')); }); @@ -661,7 +669,7 @@ Template.editCardTitleForm.events({ }, }); -Template.editCardRequesterForm.onRendered(function() { +Template.editCardRequesterForm.onRendered(function () { autosize(this.$('.js-edit-card-requester')); }); @@ -674,7 +682,7 @@ Template.editCardRequesterForm.events({ }, }); -Template.editCardAssignerForm.onRendered(function() { +Template.editCardAssignerForm.onRendered(function () { autosize(this.$('.js-edit-card-assigner')); }); @@ -814,7 +822,7 @@ Template.copyChecklistToManyCardsPopup.events({ // copy subtasks cursor = Cards.find({ parentId: oldId }); - cursor.forEach(function() { + cursor.forEach(function () { 'use strict'; const subtask = arguments[0]; subtask.parentId = _id; @@ -963,7 +971,7 @@ BlazeComponent.extendComponent({ } } }, - 'click .js-delete': Popup.afterConfirm('cardDelete', function() { + 'click .js-delete': Popup.afterConfirm('cardDelete', function () { Popup.close(); Cards.remove(this._id); Utils.goBoardId(this.boardId); @@ -1001,9 +1009,14 @@ BlazeComponent.extendComponent({ 'submit .edit-vote-question'(evt) { evt.preventDefault(); const voteQuestion = evt.target.vote.value; - this.currentCard.setVoteQuestion(voteQuestion); + const publicVote = $('#vote-public').hasClass('is-checked'); + this.currentCard.setVoteQuestion(voteQuestion, publicVote); Popup.close(); }, + 'click a.js-toggle-vote-public'(event) { + event.preventDefault(); + $('#vote-public').toggleClass('is-checked'); + }, }, ]; }, diff --git a/client/components/cards/cardDetails.styl b/client/components/cards/cardDetails.styl index 6b3ca91c..199a12da 100644 --- a/client/components/cards/cardDetails.styl +++ b/client/components/cards/cardDetails.styl @@ -338,3 +338,5 @@ card-details-color(background, color...) justify-content: space-between .vote-result display: flex +.js-show-positive-votes + cursor: pointer diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index 0b194042..68c7acae 100644 --- a/i18n/en.i18n.json +++ b/i18n/en.i18n.json @@ -164,7 +164,10 @@ "cardCustomField-datePopup-title": "Change date", "cardCustomFieldsPopup-title": "Edit custom fields", "cardStartVotingPopup-title": "Start a vote", + "positiveVoteMembersPopup-title": "Proponents", + "negativeVoteMembersPopup-title": "Opponents", "vote-question": "Voting question", + "vote-public": "Public vote", "vote-for-it": "for it", "vote-against": "against", "cardDeletePopup-title": "Delete Card?", diff --git a/models/cards.js b/models/cards.js index 94b174bb..5a812679 100644 --- a/models/cards.js +++ b/models/cards.js @@ -336,6 +336,10 @@ Cards.attachSchema( optional: true, defaultValue: null, }, + 'vote.public': { + type: Boolean, + defaultValue: false, + }, }), ); @@ -728,7 +732,7 @@ Cards.helpers({ parentString(sep) { return this.parentList() - .map(function(elem) { + .map(function (elem) { return elem.title; }) .join(sep); @@ -1028,6 +1032,33 @@ Cards.helpers({ } }, + getVotePublic() { + if (this.isLinkedCard()) { + const card = Cards.findOne({ _id: this.linkedId }); + if (card && card.vote) return card.vote.public; + else return null; + } else if (this.isLinkedBoard()) { + const board = Boards.findOne({ _id: this.linkedId }); + if (board && board.vote) return board.vote.public; + else return null; + } else if (this.vote) { + return this.vote.public; + } else { + return null; + } + }, + + voteMemberPositive() { + if (this.vote && this.vote.positive) + return Users.find({ _id: { $in: this.vote.positive } }) + return [] + }, + voteMemberNegative() { + if (this.vote && this.vote.negative) + return Users.find({ _id: { $in: this.vote.negative } }) + return [] + }, + getId() { if (this.isLinked()) { return this.linkedId; @@ -1444,11 +1475,12 @@ Cards.mutations({ }, }; }, - setVoteQuestion(question) { + setVoteQuestion(question, public) { return { $set: { vote: { question, + public, positive: [], negative: [], }, @@ -1897,7 +1929,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; @@ -1943,7 +1975,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( @@ -1997,7 +2029,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); @@ -2007,7 +2039,7 @@ if (Meteor.isServer) { boardId: paramBoardId, swimlaneId: paramSwimlaneId, archived: false, - }).map(function(doc) { + }).map(function (doc) { return { _id: doc._id, title: doc.title, @@ -2031,7 +2063,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, ) { @@ -2044,7 +2076,7 @@ if (Meteor.isServer) { boardId: paramBoardId, listId: paramListId, archived: false, - }).map(function(doc) { + }).map(function (doc) { return { _id: doc._id, title: doc.title, @@ -2066,7 +2098,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; @@ -2098,7 +2130,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, ) { @@ -2205,7 +2237,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; @@ -2504,7 +2536,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; diff --git a/models/trelloCreator.js b/models/trelloCreator.js index 48dce7eb..28982f43 100644 --- a/models/trelloCreator.js +++ b/models/trelloCreator.js @@ -303,6 +303,7 @@ export class TrelloCreator { if (positiveVotes.length > 0) { cardToCreate.vote = { question: cardToCreate.title, + public: true, positive: positiveVotes, } } -- cgit v1.2.3-1-g7c22