multiSelection.js 3.8 KB

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