mirror of
https://github.com/wekan/wekan.git
synced 2025-04-24 14:08:31 -04:00
Since 07cc454
(ie the switch to Meteor 1.2) we includes the `es5-shim`
polyfill to support methods like `Array.prototype.forEach` in a
consistent way across all supported browsers (IE8+).
MDG recently released a blog post recommending the use of these native
methods instead of underscore [0]. We know follow this recommendation.
This commit also favor some ES6 features (argument defaults,
destructing assignment) in places where we didn’t use them.
[0]: http://info.meteor.com/blog/es2015-get-started
162 lines
3.4 KiB
JavaScript
162 lines
3.4 KiB
JavaScript
|
|
function getCardsBetween(idA, idB) {
|
|
|
|
function pluckId(doc) {
|
|
return doc._id;
|
|
}
|
|
|
|
function getListsStrictlyBetween(id1, id2) {
|
|
return Lists.find({
|
|
$and: [
|
|
{ sort: { $gt: Lists.findOne(id1).sort } },
|
|
{ sort: { $lt: Lists.findOne(id2).sort } },
|
|
],
|
|
archived: false,
|
|
}).map(pluckId);
|
|
}
|
|
|
|
const cards = _.sortBy([Cards.findOne(idA), Cards.findOne(idB)], (c) => {
|
|
return c.sort;
|
|
});
|
|
|
|
let selector;
|
|
if (cards[0].listId === cards[1].listId) {
|
|
selector = {
|
|
listId: cards[0].listId,
|
|
sort: {
|
|
$gte: cards[0].sort,
|
|
$lte: cards[1].sort,
|
|
},
|
|
archived: false,
|
|
};
|
|
} else {
|
|
selector = {
|
|
$or: [{
|
|
listId: cards[0].listId,
|
|
sort: { $lte: cards[0].sort },
|
|
}, {
|
|
listId: {
|
|
$in: getListsStrictlyBetween(cards[0].listId, cards[1].listId),
|
|
},
|
|
}, {
|
|
listId: cards[1].listId,
|
|
sort: { $gte: cards[1].sort },
|
|
}],
|
|
archived: false,
|
|
};
|
|
}
|
|
|
|
return Cards.find(Filter.mongoSelector(selector)).map(pluckId);
|
|
}
|
|
|
|
MultiSelection = {
|
|
sidebarView: 'multiselection',
|
|
|
|
_selectedCards: new ReactiveVar([]),
|
|
|
|
_isActive: new ReactiveVar(false),
|
|
|
|
startRangeCardId: null,
|
|
|
|
reset() {
|
|
this._selectedCards.set([]);
|
|
},
|
|
|
|
getMongoSelector() {
|
|
return Filter.mongoSelector({
|
|
_id: { $in: this._selectedCards.get() },
|
|
});
|
|
},
|
|
|
|
isActive() {
|
|
return this._isActive.get();
|
|
},
|
|
|
|
count() {
|
|
return Cards.find(this.getMongoSelector()).count();
|
|
},
|
|
|
|
isEmpty() {
|
|
return this.count() === 0;
|
|
},
|
|
|
|
activate() {
|
|
if (!this.isActive()) {
|
|
EscapeActions.executeUpTo('detailsPane');
|
|
this._isActive.set(true);
|
|
Tracker.flush();
|
|
}
|
|
Sidebar.setView(this.sidebarView);
|
|
},
|
|
|
|
disable() {
|
|
if (this.isActive()) {
|
|
this._isActive.set(false);
|
|
if (Sidebar && Sidebar.getView() === this.sidebarView) {
|
|
Sidebar.setView();
|
|
}
|
|
this.reset();
|
|
}
|
|
},
|
|
|
|
add(cardIds) {
|
|
return this.toggle(cardIds, { add: true, remove: false });
|
|
},
|
|
|
|
remove(cardIds) {
|
|
return this.toggle(cardIds, { add: false, remove: true });
|
|
},
|
|
|
|
toggleRange(cardId) {
|
|
const selectedCards = this._selectedCards.get();
|
|
let startRange;
|
|
this.reset();
|
|
if (!this.isActive() || selectedCards.length === 0) {
|
|
this.toggle(cardId);
|
|
} else {
|
|
startRange = selectedCards[selectedCards.length - 1];
|
|
this.toggle(getCardsBetween(startRange, cardId));
|
|
}
|
|
},
|
|
|
|
toggle(cardIds, options = {}) {
|
|
cardIds = _.isString(cardIds) ? [cardIds] : cardIds;
|
|
options = {
|
|
add: true,
|
|
remove: true,
|
|
...options,
|
|
};
|
|
|
|
if (!this.isActive()) {
|
|
this.reset();
|
|
this.activate();
|
|
}
|
|
|
|
const selectedCards = this._selectedCards.get();
|
|
|
|
cardIds.forEach((cardId) => {
|
|
const indexOfCard = selectedCards.indexOf(cardId);
|
|
|
|
if (options.remove && indexOfCard > -1)
|
|
selectedCards.splice(indexOfCard, 1);
|
|
|
|
else if (options.add)
|
|
selectedCards.push(cardId);
|
|
});
|
|
|
|
this._selectedCards.set(selectedCards);
|
|
},
|
|
|
|
isSelected(cardId) {
|
|
return this._selectedCards.get().indexOf(cardId) > -1;
|
|
},
|
|
};
|
|
|
|
Blaze.registerHelper('MultiSelection', MultiSelection);
|
|
|
|
EscapeActions.register('multiselection',
|
|
() => { MultiSelection.disable(); },
|
|
() => { return MultiSelection.isActive(); }, {
|
|
noClickEscapeOn: '.js-minicard,.js-board-sidebar-content',
|
|
}
|
|
);
|