Merge pull request #3006 from NicoP-S/master

Public vote
This commit is contained in:
Lauri Ojansivu 2020-04-10 12:05:10 +03:00 committed by GitHub
commit a81921382a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 98 additions and 24 deletions

View file

@ -206,12 +206,12 @@ template(name="cardDetails")
i.fa.fa-thumbs-up i.fa.fa-thumbs-up
card-details-item-title {{_ 'vote-question'}} card-details-item-title {{_ 'vote-question'}}
.vote-result .vote-result
.card-label.card-label-green if votePublic
+viewer a.card-label.card-label-green.js-show-positive-votes {{ voteCountPositive }}
= voteCountPositive a.card-label.card-label-red.js-show-negative-votes {{ voteCountNegative }}
.card-label.card-label-red else
+viewer .card-label.card-label-green {{ voteCountPositive }}
= voteCountNegative .card-label.card-label-red {{ voteCountNegative }}
+viewer +viewer
= getVoteQuestion = getVoteQuestion
button.card-details-green.js-vote.js-vote-positive(class="{{#if voteState}}voted{{/if}}") {{_ 'vote-for-it'}} 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 .fields
label(for="vote") {{_ 'vote-question'}} label(for="vote") {{_ 'vote-question'}}
input.js-vote-field#vote(type="text" name="vote" value="{{card.getVoteQuestion}}" autofocus) 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.primary.confirm.js-submit {{_ 'save'}}
//- button.js-remove-color.negate.wide.right {{_ 'delete'}} //- 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
| (<span class="username">{{ m.username }}</span>)
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
| (<span class="username">{{ m.username }}</span>)

View file

@ -54,6 +54,12 @@ BlazeComponent.extendComponent({
} }
return null; return null;
}, },
votePublic() {
const card = this.currentData();
if (card.vote)
return card.vote.public
return null
},
voteCountPositive() { voteCountPositive() {
const card = this.currentData(); const card = this.currentData();
if (card.vote && card.vote.positive) return card.vote.positive.length; 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-start-date': Popup.open('editCardStartDate'),
'click .js-due-date': Popup.open('editCardDueDate'), 'click .js-due-date': Popup.open('editCardDueDate'),
'click .js-end-date': Popup.open('editCardEndDate'), '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'() { 'mouseenter .js-card-details'() {
const parentComponent = this.parentComponent().parentComponent(); const parentComponent = this.parentComponent().parentComponent();
//on mobile view parent is Board, not BoardBody. //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')); 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')); 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')); autosize(this.$('.js-edit-card-assigner'));
}); });
@ -814,7 +822,7 @@ Template.copyChecklistToManyCardsPopup.events({
// copy subtasks // copy subtasks
cursor = Cards.find({ parentId: oldId }); cursor = Cards.find({ parentId: oldId });
cursor.forEach(function() { cursor.forEach(function () {
'use strict'; 'use strict';
const subtask = arguments[0]; const subtask = arguments[0];
subtask.parentId = _id; 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(); Popup.close();
Cards.remove(this._id); Cards.remove(this._id);
Utils.goBoardId(this.boardId); Utils.goBoardId(this.boardId);
@ -1001,9 +1009,14 @@ BlazeComponent.extendComponent({
'submit .edit-vote-question'(evt) { 'submit .edit-vote-question'(evt) {
evt.preventDefault(); evt.preventDefault();
const voteQuestion = evt.target.vote.value; const voteQuestion = evt.target.vote.value;
this.currentCard.setVoteQuestion(voteQuestion); const publicVote = $('#vote-public').hasClass('is-checked');
this.currentCard.setVoteQuestion(voteQuestion, publicVote);
Popup.close(); Popup.close();
}, },
'click a.js-toggle-vote-public'(event) {
event.preventDefault();
$('#vote-public').toggleClass('is-checked');
},
}, },
]; ];
}, },

View file

@ -338,3 +338,5 @@ card-details-color(background, color...)
justify-content: space-between justify-content: space-between
.vote-result .vote-result
display: flex display: flex
.js-show-positive-votes
cursor: pointer

View file

@ -164,7 +164,10 @@
"cardCustomField-datePopup-title": "Change date", "cardCustomField-datePopup-title": "Change date",
"cardCustomFieldsPopup-title": "Edit custom fields", "cardCustomFieldsPopup-title": "Edit custom fields",
"cardStartVotingPopup-title": "Start a vote", "cardStartVotingPopup-title": "Start a vote",
"positiveVoteMembersPopup-title": "Proponents",
"negativeVoteMembersPopup-title": "Opponents",
"vote-question": "Voting question", "vote-question": "Voting question",
"vote-public": "Public vote",
"vote-for-it": "for it", "vote-for-it": "for it",
"vote-against": "against", "vote-against": "against",
"cardDeletePopup-title": "Delete Card?", "cardDeletePopup-title": "Delete Card?",

View file

@ -336,6 +336,10 @@ Cards.attachSchema(
optional: true, optional: true,
defaultValue: null, defaultValue: null,
}, },
'vote.public': {
type: Boolean,
defaultValue: false,
},
}), }),
); );
@ -728,7 +732,7 @@ Cards.helpers({
parentString(sep) { parentString(sep) {
return this.parentList() return this.parentList()
.map(function(elem) { .map(function (elem) {
return elem.title; return elem.title;
}) })
.join(sep); .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() { getId() {
if (this.isLinked()) { if (this.isLinked()) {
return this.linkedId; return this.linkedId;
@ -1444,11 +1475,12 @@ Cards.mutations({
}, },
}; };
}, },
setVoteQuestion(question) { setVoteQuestion(question, public) {
return { return {
$set: { $set: {
vote: { vote: {
question, question,
public,
positive: [], positive: [],
negative: [], negative: [],
}, },
@ -1897,7 +1929,7 @@ if (Meteor.isServer) {
}); });
//New activity for card moves //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 oldListId = this.previous.listId;
const oldSwimlaneId = this.previous.swimlaneId; const oldSwimlaneId = this.previous.swimlaneId;
const oldBoardId = this.previous.boardId; 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 // 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( const modifiedAt = new Date(
new Date(value).getTime() - new Date(value).getTime() -
(action === 'endAt' ? 365 * 24 * 3600 * 1e3 : 0), (action === 'endAt' ? 365 * 24 * 3600 * 1e3 : 0),
); // set it as 1 year before ); // set it as 1 year before
const boardId = list.boardId; const boardId = list.boardId;
Lists.direct.update( Lists.direct.update(
@ -1997,7 +2029,7 @@ if (Meteor.isServer) {
JsonRoutes.add( JsonRoutes.add(
'GET', 'GET',
'/api/boards/:boardId/swimlanes/:swimlaneId/cards', '/api/boards/:boardId/swimlanes/:swimlaneId/cards',
function(req, res) { function (req, res) {
const paramBoardId = req.params.boardId; const paramBoardId = req.params.boardId;
const paramSwimlaneId = req.params.swimlaneId; const paramSwimlaneId = req.params.swimlaneId;
Authentication.checkBoardAccess(req.userId, paramBoardId); Authentication.checkBoardAccess(req.userId, paramBoardId);
@ -2007,7 +2039,7 @@ if (Meteor.isServer) {
boardId: paramBoardId, boardId: paramBoardId,
swimlaneId: paramSwimlaneId, swimlaneId: paramSwimlaneId,
archived: false, archived: false,
}).map(function(doc) { }).map(function (doc) {
return { return {
_id: doc._id, _id: doc._id,
title: doc.title, title: doc.title,
@ -2031,7 +2063,7 @@ if (Meteor.isServer) {
* title: string, * title: string,
* description: string}] * description: string}]
*/ */
JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId/cards', function( JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId/cards', function (
req, req,
res, res,
) { ) {
@ -2044,7 +2076,7 @@ if (Meteor.isServer) {
boardId: paramBoardId, boardId: paramBoardId,
listId: paramListId, listId: paramListId,
archived: false, archived: false,
}).map(function(doc) { }).map(function (doc) {
return { return {
_id: doc._id, _id: doc._id,
title: doc.title, title: doc.title,
@ -2066,7 +2098,7 @@ if (Meteor.isServer) {
JsonRoutes.add( JsonRoutes.add(
'GET', 'GET',
'/api/boards/:boardId/lists/:listId/cards/:cardId', '/api/boards/:boardId/lists/:listId/cards/:cardId',
function(req, res) { function (req, res) {
const paramBoardId = req.params.boardId; const paramBoardId = req.params.boardId;
const paramListId = req.params.listId; const paramListId = req.params.listId;
const paramCardId = req.params.cardId; 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 * @param {string} [assignees] the array of maximum one ID of assignee of the new card
* @return_type {_id: string} * @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, req,
res, res,
) { ) {
@ -2205,7 +2237,7 @@ if (Meteor.isServer) {
JsonRoutes.add( JsonRoutes.add(
'PUT', 'PUT',
'/api/boards/:boardId/lists/:listId/cards/:cardId', '/api/boards/:boardId/lists/:listId/cards/:cardId',
function(req, res) { function (req, res) {
Authentication.checkUserId(req.userId); Authentication.checkUserId(req.userId);
const paramBoardId = req.params.boardId; const paramBoardId = req.params.boardId;
const paramCardId = req.params.cardId; const paramCardId = req.params.cardId;
@ -2504,7 +2536,7 @@ if (Meteor.isServer) {
JsonRoutes.add( JsonRoutes.add(
'DELETE', 'DELETE',
'/api/boards/:boardId/lists/:listId/cards/:cardId', '/api/boards/:boardId/lists/:listId/cards/:cardId',
function(req, res) { function (req, res) {
Authentication.checkUserId(req.userId); Authentication.checkUserId(req.userId);
const paramBoardId = req.params.boardId; const paramBoardId = req.params.boardId;
const paramListId = req.params.listId; const paramListId = req.params.listId;

View file

@ -303,6 +303,7 @@ export class TrelloCreator {
if (positiveVotes.length > 0) { if (positiveVotes.length > 0) {
cardToCreate.vote = { cardToCreate.vote = {
question: cardToCreate.title, question: cardToCreate.title,
public: true,
positive: positiveVotes, positive: positiveVotes,
} }
} }