From b740381a7248e1e059cecedcf6cd6824abb792b3 Mon Sep 17 00:00:00 2001 From: Marc Hartmayer Date: Thu, 30 Apr 2020 01:03:37 +0200 Subject: Refuse to delete a card as long as there is link to it This fixes https://github.com/wekan/wekan/issues/2785. --- client/components/cards/cardDetails.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'client/components/cards') diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index 271fbe2f..e8e36178 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -967,7 +967,12 @@ BlazeComponent.extendComponent({ }, 'click .js-delete': Popup.afterConfirm('cardDelete', function() { Popup.close(); - Cards.remove(this._id); + // verify that there are no linked cards + if (Cards.find({ linkedId: this._id }).count() === 0) { + Cards.remove(this._id); + } else { + // TODO popup... + } Utils.goBoardId(this.boardId); }), 'change .js-field-parent-board'(event) { -- cgit v1.2.3-1-g7c22 From 079867ff3770272cf72280f8abc261f89a96a80e Mon Sep 17 00:00:00 2001 From: helioguardabaxo Date: Sat, 2 May 2020 14:48:49 -0300 Subject: Add white-space:normal to copy-to-clipboard button in card details --- client/components/cards/cardDetails.jade | 2 +- client/components/cards/cardDetails.styl | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'client/components/cards') diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index ae97e0e9..e9fb8b0f 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -519,7 +519,7 @@ template(name="cardMorePopup") = ' ' i.fa.colorful(class="{{#if board.isPublic}}fa-globe{{else}}fa-lock{{/if}}") input.inline-input(type="text" id="cardURL" readonly value="{{ absoluteUrl }}" autofocus="autofocus") - button.js-copy-card-link-to-clipboard(class="btn") {{_ 'copy-card-link-to-clipboard'}} + button.js-copy-card-link-to-clipboard(class="btn" id="clipboard") {{_ 'copy-card-link-to-clipboard'}} span.clearfix br h2 {{_ 'change-card-parent'}} diff --git a/client/components/cards/cardDetails.styl b/client/components/cards/cardDetails.styl index 3e2beadd..2d2d7ccf 100644 --- a/client/components/cards/cardDetails.styl +++ b/client/components/cards/cardDetails.styl @@ -10,6 +10,9 @@ avatar-radius = 50% left: -2000px top: 0px +#clipboard + white-space: normal + .assignee border-radius: 3px display: block -- cgit v1.2.3-1-g7c22 From 3cc0a93e0ea2399d239923e3a89d49d93a979684 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 3 May 2020 00:33:15 +0200 Subject: Card vote options in new fork --- client/components/cards/cardDate.js | 27 ++++++++ client/components/cards/cardDetails.jade | 79 +++++++++++++++--------- client/components/cards/cardDetails.js | 102 ++++++++++++++++++++++++------- client/components/cards/cardDetails.styl | 5 ++ client/components/cards/minicard.jade | 2 + 5 files changed, 164 insertions(+), 51 deletions(-) (limited to 'client/components/cards') diff --git a/client/components/cards/cardDate.js b/client/components/cards/cardDate.js index c4b5c6d8..9b2268e9 100644 --- a/client/components/cards/cardDate.js +++ b/client/components/cards/cardDate.js @@ -386,3 +386,30 @@ CardEndDate.register('cardEndDate'); return this.date.get().format('l'); } }.register('minicardEndDate')); + +class VoteEndDate extends CardDate { + onCreated() { + super.onCreated(); + const self = this; + self.autorun(() => { + self.date.set(moment(self.data().getVoteEnd())); + }); + } + classes() { + const classes = 'end-date' + ' '; + return classes; + } + showDate() { + return this.date.get().format('l LT'); + } + showTitle() { + return `${TAPi18n.__('card-end-on')} ${this.date.get().format('LLLL')}`; + } + + events() { + return super.events().concat({ + 'click .js-edit-date': Popup.open('editVoteEndDate'), + }); + } +} +VoteEndDate.register('voteEndDate'); diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index ae97e0e9..9f3b188b 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -202,9 +202,12 @@ template(name="cardDetails") if getVoteQuestion hr .vote-title - h3 - i.fa.fa-thumbs-up - card-details-item-title {{_ 'vote-question'}} + div.flex + h3 + i.fa.fa-thumbs-up + | {{_ 'vote-question'}} + if getVoteEnd + +voteEndDate .vote-result if votePublic a.card-label.card-label-green.js-show-positive-votes {{ voteCountPositive }} @@ -212,10 +215,13 @@ 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'}} - button.card-details-red.js-vote.js-vote-negative(class="{{#if $eq voteState false}}voted{{/if}}") {{_ 'vote-against'}} + if showVotingButtons + button.card-details-green.js-vote.js-vote-positive(class="{{#if voteState}}voted{{/if}}") {{_ 'vote-for-it'}} + button.card-details-red.js-vote.js-vote-negative(class="{{#if $eq voteState false}}voted{{/if}}") {{_ 'vote-against'}} //- XXX We should use "editable" to avoid repetiting ourselves if canModifyCard @@ -333,16 +339,10 @@ template(name="cardDetailsActionsPopup") //li: a.js-members {{_ 'card-edit-members'}} //li: a.js-labels {{_ 'card-edit-labels'}} //li: a.js-attachments {{_ 'card-edit-attachments'}} - if getVoteQuestion - li - a.js-cancel-voting - i.fa.fa-thumbs-up - | {{_ 'card-cancel-voting'}} - else - li - a.js-start-voting - i.fa.fa-thumbs-up - | {{_ 'card-start-voting'}} + li + a.js-start-voting + i.fa.fa-thumbs-up + | {{_ 'card-edit-voting'}} li a.js-custom-fields i.fa.fa-list-alt @@ -465,14 +465,14 @@ template(name="cardAssigneesPopup") i.fa.fa-check if currentUser.isWorker ul.pop-over-list.js-card-assignee-list - li.item(class="{{#if currentUser.isCardAssignee}}active{{/if}}") - a.name.js-select-assignee(href="#") - +userAvatar(userId=currentUser._id) - span.full-name - = currentUser.profile.fullname - | ({{ currentUser.username }}) - if currentUser.isCardAssignee - i.fa.fa-check + li.item(class="{{#if currentUser.isCardAssignee}}active{{/if}}") + a.name.js-select-assignee(href="#") + +userAvatar(userId=currentUser._id) + span.full-name + = currentUser.profile.fullname + | ({{ currentUser.username }}) + if currentUser.isCardAssignee + i.fa.fa-check template(name="userAvatarAssignee") a.assignee.js-assignee(title="{{userData.profile.fullname}} ({{userData.username}})") @@ -564,20 +564,39 @@ template(name="setCardColorPopup") template(name="cardDeletePopup") p {{_ "card-delete-pop"}} unless archived - p {{_ "card-delete-suggest-archive"}} + p {{_ "card-delete-suggest-archive"}} + button.js-confirm.negate.full(type="submit") {{_ 'delete'}} + +template(name="deleteVotePopup") + p {{_ "vote-delete-pop"}} button.js-confirm.negate.full(type="submit") {{_ 'delete'}} template(name="cardStartVotingPopup") form.edit-vote-question .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") + input.js-vote-field#vote(type="text" name="vote" value="{{getVoteQuestion}}" autofocus disabled="{{#if getVoteQuestion}}disabled{{/if}}") + .check-div + a.flex(class="{{#if getVoteQuestion}}is-disabled{{else}}js-toggle-vote-allow-non-members{{/if}}") + .materialCheckBox#vote-allow-non-members(name="vote-allow-non-members" class="{{#if voteAllowNonBoardMembers}}is-checked{{/if}}") + span {{_ 'allowNonBoardMembers'}} + .check-div + a.flex(class="{{#if getVoteQuestion}}is-disabled{{else}}js-toggle-vote-public{{/if}}") + .materialCheckBox#vote-public(name="vote-public" class="{{#if votePublic}}is-checked{{/if}}") + span {{_ 'vote-public'}} + .check-div.flex + i.fa.fa-hourglass-end + a.js-end-date + span + | {{_ 'card-end'}} + unless getVoteEnd + i.fa.fa-plus + if getVoteEnd + +voteEndDate - button.primary.confirm.js-submit {{_ 'save'}} - //- button.js-remove-color.negate.wide.right {{_ 'delete'}} + button.primary.js-submit {{_ 'save'}} + if getVoteQuestion + button.js-remove-vote.negate.wide.right {{_ 'delete'}} template(name="positiveVoteMembersPopup") ul.pop-over-list.js-card-member-list diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index 271fbe2f..7dcadfe3 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -54,21 +54,6 @@ 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()); @@ -148,6 +133,15 @@ BlazeComponent.extendComponent({ return result; }, + showVotingButtons() { + const card = this.currentData(); + return ( + (currentUser.isBoardMember() || + (currentUser && card.voteAllowNonBoardMembers())) && + !card.expiredVote() + ); + }, + onRendered() { if (Meteor.settings.public.CARD_OPENED_WEBHOOK_ENABLED) { // Send Webhook but not create Activities records --- @@ -611,11 +605,6 @@ Template.cardDetailsActionsPopup.events({ 'click .js-copy-card': Popup.open('copyCard'), 'click .js-copy-checklist-cards': Popup.open('copyChecklistToManyCards'), 'click .js-set-card-color': Popup.open('setCardColor'), - 'click .js-cancel-voting'(event) { - event.preventDefault(); - this.unsetVote(); - Popup.close(); - }, 'click .js-move-card-to-top'(event) { event.preventDefault(); const minOrder = _.min( @@ -1000,22 +989,93 @@ BlazeComponent.extendComponent({ events() { return [ { + 'click .js-end-date': Popup.open('editVoteEndDate'), 'submit .edit-vote-question'(evt) { 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', + ); + const endString = this.currentCard.getVoteEnd(); + + this.currentCard.setVoteQuestion( + voteQuestion, + publicVote, + allowNonBoardMembers, + ); + if (endString) { + this.currentCard.setVoteEnd(endString); + } Popup.close(); }, + 'click .js-remove-vote': Popup.afterConfirm('deleteVote', () => { + event.preventDefault(); + this.currentCard.unsetVote(); + 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'); + }, }, ]; }, }).register('cardStartVotingPopup'); +// editVoteEndDatePopup +(class extends DatePicker { + onCreated() { + super.onCreated(moment().format('YYYY-MM-DD HH:mm')); + this.data().getVoteEnd() && this.date.set(moment(this.data().getVoteEnd())); + } + events() { + return [ + { + 'submit .edit-date'(evt) { + evt.preventDefault(); + + // if no time was given, init with 12:00 + const time = + evt.target.time.value || + moment(new Date().setHours(12, 0, 0)).format('LT'); + + const dateString = `${evt.target.date.value} ${time}`; + const newDate = moment(dateString, 'L LT', true); + if (newDate.isValid()) { + // if active vote - store it + if (this.currentData().getVoteQuestion()) { + this._storeDate(newDate.toDate()); + Popup.close(); + } else { + this.currentData().vote = { end: newDate.toDate() }; // set vote end temp + Popup.back(); + } + } else { + this.error.set('invalid-date'); + evt.target.date.focus(); + } + }, + 'click .js-delete-date'(evt) { + evt.preventDefault(); + this._deleteDate(); + Popup.close(); + }, + }, + ]; + } + _storeDate(newDate) { + this.card.setVoteEnd(newDate); + } + _deleteDate() { + this.card.unsetVoteEnd(); + } +}.register('editVoteEndDatePopup')); + // Close the card details pane by pressing escape EscapeActions.register( 'detailsPane', diff --git a/client/components/cards/cardDetails.styl b/client/components/cards/cardDetails.styl index 3e2beadd..cfdc450d 100644 --- a/client/components/cards/cardDetails.styl +++ b/client/components/cards/cardDetails.styl @@ -337,6 +337,11 @@ card-details-color(background, color...) .vote-title display: flex justify-content: space-between + + .js-edit-date + align-self: baseline + margin-left: 5px + .vote-result display: flex .js-show-positive-votes 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 -- cgit v1.2.3-1-g7c22 From 2bb5a31fa4dffc412c9ac7bbe25205588fe5f28e Mon Sep 17 00:00:00 2001 From: Marco Volo Date: Fri, 8 May 2020 15:25:31 +0200 Subject: avatar-image fix --- client/components/cards/cardDetails.styl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'client/components/cards') diff --git a/client/components/cards/cardDetails.styl b/client/components/cards/cardDetails.styl index 3e2beadd..4ca23f39 100644 --- a/client/components/cards/cardDetails.styl +++ b/client/components/cards/cardDetails.styl @@ -37,6 +37,8 @@ avatar-radius = 50% position: absolute &.avatar-image + object-fit: cover; + object-position: center; height: 100% width: @height -- cgit v1.2.3-1-g7c22 From ea74a34d72fb0f33909858a640dbcd3a5fda5b7f Mon Sep 17 00:00:00 2001 From: Lauri Ojansivu Date: Thu, 14 May 2020 01:04:52 +0300 Subject: Add popup and changelog for linked card fixes. --- client/components/cards/cardDetails.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'client/components/cards') diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index 048a7e1a..441068b0 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -960,7 +960,18 @@ BlazeComponent.extendComponent({ if (Cards.find({ linkedId: this._id }).count() === 0) { Cards.remove(this._id); } else { - // TODO popup... + // TODO: Maybe later we can list where the linked cards are. + // Now here is popup with a hint that the card cannot be deleted + // as there are linked cards. + // Related: + // client/components/lists/listHeader.js about line 248 + // https://github.com/wekan/wekan/issues/2785 + const message = `${TAPi18n.__( + 'delete-linked-card-before-this-card', + )} linkedId: ${ + this._id + } at client/components/cards/cardDetails.js and https://github.com/wekan/wekan/issues/2785`; + alert(message); } Utils.goBoardId(this.boardId); }), -- cgit v1.2.3-1-g7c22