multiSelection.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. function getCardsBetween(idA, idB) {
  2. function pluckId(doc) {
  3. return doc._id;
  4. }
  5. function getListsStrictlyBetween(id1, id2) {
  6. return Lists.find({
  7. $and: [
  8. { sort: { $gt: Lists.findOne(id1).sort } },
  9. { sort: { $lt: Lists.findOne(id2).sort } },
  10. ],
  11. archived: false,
  12. }).map(pluckId);
  13. }
  14. const cards = _.sortBy([Cards.findOne(idA), Cards.findOne(idB)], c => {
  15. return c.sort;
  16. });
  17. let selector;
  18. if (cards[0].listId === cards[1].listId) {
  19. selector = {
  20. listId: cards[0].listId,
  21. sort: {
  22. $gte: cards[0].sort,
  23. $lte: cards[1].sort,
  24. },
  25. archived: false,
  26. };
  27. } else {
  28. selector = {
  29. $or: [
  30. {
  31. listId: cards[0].listId,
  32. sort: { $lte: cards[0].sort },
  33. },
  34. {
  35. listId: {
  36. $in: getListsStrictlyBetween(cards[0].listId, cards[1].listId),
  37. },
  38. },
  39. {
  40. listId: cards[1].listId,
  41. sort: { $gte: cards[1].sort },
  42. },
  43. ],
  44. archived: false,
  45. };
  46. }
  47. return Cards.find(Filter.mongoSelector(selector)).map(pluckId);
  48. }
  49. MultiSelection = {
  50. sidebarView: 'multiselection',
  51. _selectedCards: new ReactiveVar([]),
  52. _isActive: new ReactiveVar(false),
  53. startRangeCardId: null,
  54. _sidebarWasOpen: false,
  55. reset() {
  56. this._selectedCards.set([]);
  57. },
  58. getMongoSelector() {
  59. return Filter.mongoSelector({
  60. _id: { $in: this._selectedCards.get() },
  61. });
  62. },
  63. isActive() {
  64. return this._isActive.get();
  65. },
  66. count() {
  67. return Cards.find(this.getMongoSelector()).count();
  68. },
  69. isEmpty() {
  70. return this.count() === 0;
  71. },
  72. getSelectedCardIds(){
  73. return this._selectedCards.curValue;
  74. },
  75. activate() {
  76. if (!this.isActive()) {
  77. this._sidebarWasOpen = Sidebar.isOpen();
  78. EscapeActions.executeUpTo('detailsPane');
  79. this._isActive.set(true);
  80. Tracker.flush();
  81. }
  82. Sidebar.setView(this.sidebarView);
  83. if(Utils.isMiniScreen()) {
  84. Sidebar.hide();
  85. }
  86. },
  87. disable() {
  88. if (this.isActive()) {
  89. this._isActive.set(false);
  90. if (Sidebar && Sidebar.getView() === this.sidebarView) {
  91. Sidebar.setView();
  92. if(!this._sidebarWasOpen) {
  93. Sidebar.hide();
  94. }
  95. }
  96. this.reset();
  97. }
  98. },
  99. add(cardIds) {
  100. return this.toggle(cardIds, { add: true, remove: false });
  101. },
  102. remove(cardIds) {
  103. return this.toggle(cardIds, { add: false, remove: true });
  104. },
  105. toggleRange(cardId) {
  106. const selectedCards = this._selectedCards.get();
  107. this.reset();
  108. if (!this.isActive() || selectedCards.length === 0) {
  109. this.toggle(cardId);
  110. } else {
  111. const startRange = selectedCards[selectedCards.length - 1];
  112. this.toggle(getCardsBetween(startRange, cardId));
  113. }
  114. },
  115. toggle(cardIds, options = {}) {
  116. cardIds = _.isString(cardIds) ? [cardIds] : cardIds;
  117. options = {
  118. add: true,
  119. remove: true,
  120. ...options,
  121. };
  122. if (!this.isActive()) {
  123. this.reset();
  124. this.activate();
  125. }
  126. const selectedCards = this._selectedCards.get();
  127. cardIds.forEach(cardId => {
  128. const indexOfCard = selectedCards.indexOf(cardId);
  129. if (options.remove && indexOfCard > -1)
  130. selectedCards.splice(indexOfCard, 1);
  131. else if (options.add) selectedCards.push(cardId);
  132. });
  133. this._selectedCards.set(selectedCards);
  134. },
  135. isSelected(cardId) {
  136. return this._selectedCards.get().indexOf(cardId) > -1;
  137. },
  138. };
  139. Blaze.registerHelper('MultiSelection', MultiSelection);
  140. EscapeActions.register(
  141. 'multiselection',
  142. () => {
  143. MultiSelection.disable();
  144. },
  145. () => {
  146. return MultiSelection.isActive();
  147. },
  148. {
  149. noClickEscapeOn: '.js-minicard,.js-board-sidebar-content',
  150. },
  151. );