mirror of
https://github.com/wekan/wekan.git
synced 2026-02-21 15:34:07 +01:00
Implement multi-selection
The UI and the internal APIs are still rough around the edges but the feature is basically working. You can now select multiple cards and move them together or (un|)assign them a label.
This commit is contained in:
parent
6457615e6a
commit
2c0030da62
45 changed files with 883 additions and 933 deletions
|
|
@ -10,13 +10,12 @@ template(name="listBody")
|
|||
+inlinedForm(autoclose=false position="bottom")
|
||||
+addCardForm(listId=_id position="bottom")
|
||||
else
|
||||
if newCardFormIsVisible.get
|
||||
a.open-card-composer.js-open-inlined-form
|
||||
i.fa.fa-plus
|
||||
| {{_ 'add-card'}}
|
||||
a.open-minicard-composer.js-open-inlined-form
|
||||
i.fa.fa-plus
|
||||
| {{_ 'add-card'}}
|
||||
|
||||
template(name="addCardForm")
|
||||
.minicard.js-composer
|
||||
.minicard.minicard-composer.js-composer
|
||||
.minicard-labels.js-minicard-composer-labels
|
||||
.minicard-details.clearfix
|
||||
textarea.minicard-composer-textarea.js-card-title(autofocus)
|
||||
|
|
|
|||
|
|
@ -34,18 +34,17 @@ BlazeComponent.extendComponent({
|
|||
}
|
||||
|
||||
if ($.trim(title)) {
|
||||
Cards.insert({
|
||||
var _id = Cards.insert({
|
||||
title: title,
|
||||
listId: this.data()._id,
|
||||
boardId: this.data().board()._id,
|
||||
sort: sortIndex
|
||||
}, function(err, _id) {
|
||||
// In case the filter is active we need to add the newly inserted card
|
||||
// in the list of exceptions -- cards that are not filtered. Otherwise
|
||||
// the card will disappear instantly.
|
||||
// See https://github.com/libreboard/libreboard/issues/80
|
||||
Filter.addException(_id);
|
||||
});
|
||||
// In case the filter is active we need to add the newly inserted card in
|
||||
// the list of exceptions -- cards that are not filtered. Otherwise the
|
||||
// card will disappear instantly.
|
||||
// See https://github.com/libreboard/libreboard/issues/80
|
||||
Filter.addException(_id);
|
||||
|
||||
// We keep the form opened, empty it, and scroll to it.
|
||||
textarea.val('').focus();
|
||||
|
|
@ -55,10 +54,6 @@ BlazeComponent.extendComponent({
|
|||
}
|
||||
},
|
||||
|
||||
showNewCardForm: function(value) {
|
||||
this.newCardFormIsVisible.set(value);
|
||||
},
|
||||
|
||||
scrollToBottom: function() {
|
||||
var container = this.firstNode();
|
||||
$(container).animate({
|
||||
|
|
@ -66,14 +61,10 @@ BlazeComponent.extendComponent({
|
|||
});
|
||||
},
|
||||
|
||||
onCreated: function() {
|
||||
this.newCardFormIsVisible = new ReactiveVar(true);
|
||||
},
|
||||
|
||||
events: function() {
|
||||
return [{
|
||||
submit: this.addCard,
|
||||
'click .open-card-composer': this.scrollToBottom
|
||||
'click .open-minicard-composer': this.scrollToBottom
|
||||
}];
|
||||
}
|
||||
}).register('listBody');
|
||||
|
|
|
|||
|
|
@ -8,10 +8,6 @@ BlazeComponent.extendComponent({
|
|||
this.componentChildren('listBody')[0].openForm(options);
|
||||
},
|
||||
|
||||
showNewCardForm: function(value) {
|
||||
this.componentChildren('listBody')[0].showNewCardForm(value);
|
||||
},
|
||||
|
||||
onCreated: function() {
|
||||
this.newCardFormIsVisible = new ReactiveVar(true);
|
||||
},
|
||||
|
|
@ -35,30 +31,59 @@ BlazeComponent.extendComponent({
|
|||
connectWith: '.js-minicards',
|
||||
tolerance: 'pointer',
|
||||
appendTo: '.js-lists',
|
||||
helper: 'clone',
|
||||
items: itemsSelector,
|
||||
placeholder: 'minicard placeholder',
|
||||
start: function(event, ui) {
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
Popup.close();
|
||||
boardComponent.showNewCardForms(false);
|
||||
helper: function(evt, item) {
|
||||
var helper = item.clone();
|
||||
if (MultiSelection.isActive()) {
|
||||
var andNOthers = $cards.find('.js-minicard.is-checked').length - 1;
|
||||
if (andNOthers > 0) {
|
||||
helper.append($(Blaze.toHTML(HTML.DIV(
|
||||
// XXX Super bad class name
|
||||
{'class': 'and-n-other'},
|
||||
// XXX Need to translate
|
||||
'and ' + andNOthers + ' other cards.'
|
||||
))));
|
||||
}
|
||||
}
|
||||
return helper;
|
||||
},
|
||||
stop: function(event, ui) {
|
||||
items: itemsSelector,
|
||||
placeholder: 'minicard-wrapper placeholder',
|
||||
start: function(evt, ui) {
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
EscapeActions.executeLowerThan('popup');
|
||||
boardComponent.setIsDragging(true);
|
||||
},
|
||||
stop: function(evt, ui) {
|
||||
// To attribute the new index number, we need to get the dom element
|
||||
// of the previous and the following card -- if any.
|
||||
var cardDomElement = ui.item.get(0);
|
||||
var prevCardDomElement = ui.item.prev('.js-minicard').get(0);
|
||||
var nextCardDomElement = ui.item.next('.js-minicard').get(0);
|
||||
var sort = Utils.getSortIndex(prevCardDomElement, nextCardDomElement);
|
||||
var cardId = Blaze.getData(cardDomElement)._id;
|
||||
var listId = Blaze.getData(ui.item.parents('.list').get(0))._id;
|
||||
Cards.update(cardId, {
|
||||
$set: {
|
||||
listId: listId,
|
||||
sort: sort
|
||||
}
|
||||
});
|
||||
boardComponent.showNewCardForms(true);
|
||||
|
||||
if (MultiSelection.isActive()) {
|
||||
Cards.find(MultiSelection.getMongoSelector()).forEach(function(c) {
|
||||
Cards.update(c._id, {
|
||||
$set: {
|
||||
listId: listId,
|
||||
sort: sort
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
var cardId = Blaze.getData(cardDomElement)._id;
|
||||
Cards.update(cardId, {
|
||||
$set: {
|
||||
listId: listId,
|
||||
// XXX Using the same sort index for multiple cards is
|
||||
// unacceptable. Keep that only until we figure out if we want to
|
||||
// refactor the whole sorting mecanism or do something more basic.
|
||||
sort: sort
|
||||
}
|
||||
});
|
||||
}
|
||||
boardComponent.setIsDragging(false);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -93,10 +93,13 @@
|
|||
overflow-y: auto
|
||||
padding: 5px 11px
|
||||
|
||||
.minicards form
|
||||
margin-bottom: 9px
|
||||
|
||||
.ps-scrollbar-y-rail
|
||||
transform: translateX(2px)
|
||||
|
||||
.open-card-composer
|
||||
.open-minicard-composer
|
||||
border-radius: 2px
|
||||
color: #8c8c8c
|
||||
display: block
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ template(name="listActionPopup")
|
|||
if cards.count
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li: a.js-select-cards {{_ 'list-select-cards'}}
|
||||
li: a.js-move-cards {{_ 'list-move-cards'}}
|
||||
li: a.js-archive-cards {{_ 'list-archive-cards'}}
|
||||
hr
|
||||
|
|
|
|||
|
|
@ -6,6 +6,14 @@ Template.listActionPopup.events({
|
|||
Popup.close();
|
||||
},
|
||||
'click .js-list-subscribe': function() {},
|
||||
'click .js-select-cards': function() {
|
||||
var cardIds = Cards.find(
|
||||
{listId: this._id},
|
||||
{fields: { _id: 1 }}
|
||||
).map(function(card) { return card._id; });
|
||||
MultiSelection.add(cardIds);
|
||||
Popup.close();
|
||||
},
|
||||
'click .js-move-cards': Popup.open('listMoveCards'),
|
||||
'click .js-archive-cards': Popup.afterConfirm('listArchiveCards', function() {
|
||||
Cards.find({listId: this._id}).forEach(function(card) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue