keyboard.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. import { ReactiveCache } from '/imports/reactiveCache';
  2. import { FlowRouter } from 'meteor/ostrio:flow-router-extra';
  3. // XXX There is no reason to define these shortcuts globally, they should be
  4. // attached to a template (most of them will go in the `board` template).
  5. function getHoveredCardId() {
  6. const card = $('.js-minicard:hover').get(0);
  7. if (!card) return null;
  8. return Blaze.getData(card)._id;
  9. }
  10. function getSelectedCardId() {
  11. return Session.get('currentCard') || Session.get('selectedCard') || getHoveredCardId();
  12. }
  13. Mousetrap.bind('?', () => {
  14. FlowRouter.go('shortcuts');
  15. });
  16. Mousetrap.bind('w', () => {
  17. if (Sidebar.isOpen() && Sidebar.getView() === 'home') {
  18. Sidebar.toggle();
  19. } else {
  20. Sidebar.setView();
  21. }
  22. });
  23. Mousetrap.bind('q', () => {
  24. const currentBoardId = Session.get('currentBoard');
  25. const currentUserId = Meteor.userId();
  26. if (currentBoardId && currentUserId) {
  27. Filter.members.toggle(currentUserId);
  28. }
  29. });
  30. Mousetrap.bind('a', () => {
  31. const currentBoardId = Session.get('currentBoard');
  32. const currentUserId = Meteor.userId();
  33. if (currentBoardId && currentUserId) {
  34. Filter.assignees.toggle(currentUserId);
  35. }
  36. });
  37. Mousetrap.bind('x', () => {
  38. if (Filter.isActive()) {
  39. Filter.reset();
  40. }
  41. });
  42. Mousetrap.bind('f', () => {
  43. if (Sidebar.isOpen() && Sidebar.getView() === 'filter') {
  44. Sidebar.toggle();
  45. } else {
  46. Sidebar.setView('filter');
  47. }
  48. });
  49. Mousetrap.bind('/', () => {
  50. if (Sidebar.isOpen() && Sidebar.getView() === 'search') {
  51. Sidebar.toggle();
  52. } else {
  53. Sidebar.setView('search');
  54. }
  55. });
  56. Mousetrap.bind(['down', 'up'], (evt, key) => {
  57. if (!Utils.getCurrentCardId()) {
  58. return;
  59. }
  60. const nextFunc = key === 'down' ? 'next' : 'prev';
  61. const nextCard = $('.js-minicard.is-selected')
  62. [nextFunc]('.js-minicard')
  63. .get(0);
  64. if (nextCard) {
  65. const nextCardId = Blaze.getData(nextCard)._id;
  66. Utils.goCardId(nextCardId);
  67. }
  68. });
  69. numbArray = _.range(1,10).map(x => 'shift+'+String(x))
  70. Mousetrap.bind(numbArray, (evt, key) => {
  71. num = parseInt(key.substr(6, key.length));
  72. const currentUserId = Meteor.userId();
  73. if (currentUserId === null) {
  74. return;
  75. }
  76. const currentBoardId = Session.get('currentBoard');
  77. board = ReactiveCache.getBoard(currentBoardId);
  78. labels = board.labels;
  79. if(MultiSelection.isActive())
  80. {
  81. const cardIds = MultiSelection.getSelectedCardIds();
  82. for (const cardId of cardIds)
  83. {
  84. card = ReactiveCache.getCard(cardId);
  85. if(num <= board.labels.length)
  86. {
  87. card.removeLabel(labels[num-1]["_id"]);
  88. }
  89. }
  90. }
  91. });
  92. numArray = _.range(1,10).map(x => String(x))
  93. Mousetrap.bind(numArray, (evt, key) => {
  94. num = parseInt(key);
  95. const currentUserId = Meteor.userId();
  96. const currentBoardId = Session.get('currentBoard');
  97. if (currentUserId === null) {
  98. return;
  99. }
  100. board = ReactiveCache.getBoard(currentBoardId);
  101. labels = board.labels;
  102. if(MultiSelection.isActive() && ReactiveCache.getCurrentUser().isBoardMember())
  103. {
  104. const cardIds = MultiSelection.getSelectedCardIds();
  105. for (const cardId of cardIds)
  106. {
  107. card = ReactiveCache.getCard(cardId);
  108. if(num <= board.labels.length)
  109. {
  110. card.addLabel(labels[num-1]["_id"]);
  111. }
  112. }
  113. return;
  114. }
  115. const cardId = getSelectedCardId();
  116. if (!cardId) {
  117. return;
  118. }
  119. if (ReactiveCache.getCurrentUser().isBoardMember()) {
  120. const card = ReactiveCache.getCard(cardId);
  121. if(num <= board.labels.length)
  122. {
  123. card.toggleLabel(labels[num-1]["_id"]);
  124. }
  125. }
  126. });
  127. Mousetrap.bind('space', evt => {
  128. const cardId = getSelectedCardId();
  129. if (!cardId) {
  130. return;
  131. }
  132. const currentUserId = Meteor.userId();
  133. if (currentUserId === null) {
  134. return;
  135. }
  136. if (ReactiveCache.getCurrentUser().isBoardMember()) {
  137. const card = ReactiveCache.getCard(cardId);
  138. card.toggleMember(currentUserId);
  139. // We should prevent scrolling in card when spacebar is clicked
  140. // This should do it according to Mousetrap docs, but it doesn't
  141. evt.preventDefault();
  142. }
  143. });
  144. Mousetrap.bind('c', evt => {
  145. const cardId = getSelectedCardId();
  146. if (!cardId) {
  147. return;
  148. }
  149. const currentUserId = Meteor.userId();
  150. if (currentUserId === null) {
  151. return;
  152. }
  153. if (Utils.canModifyBoard()) {
  154. const card = ReactiveCache.getCard(cardId);
  155. card.archive();
  156. // We should prevent scrolling in card when spacebar is clicked
  157. // This should do it according to Mousetrap docs, but it doesn't
  158. evt.preventDefault();
  159. }
  160. });
  161. Template.keyboardShortcuts.helpers({
  162. mapping: [
  163. {
  164. keys: ['w'],
  165. action: 'shortcut-toggle-sidebar',
  166. },
  167. {
  168. keys: ['q'],
  169. action: 'shortcut-filter-my-cards',
  170. },
  171. {
  172. keys: ['a'],
  173. action: 'shortcut-filter-my-assigned-cards',
  174. },
  175. {
  176. keys: ['f'],
  177. action: 'shortcut-toggle-filterbar',
  178. },
  179. {
  180. keys: ['/'],
  181. action: 'shortcut-toggle-searchbar',
  182. },
  183. {
  184. keys: ['x'],
  185. action: 'shortcut-clear-filters',
  186. },
  187. {
  188. keys: ['?'],
  189. action: 'shortcut-show-shortcuts',
  190. },
  191. {
  192. keys: ['ESC'],
  193. action: 'shortcut-close-dialog',
  194. },
  195. {
  196. keys: ['@'],
  197. action: 'shortcut-autocomplete-members',
  198. },
  199. {
  200. keys: ['SPACE'],
  201. action: 'shortcut-assign-self',
  202. },
  203. {
  204. keys: ['c'],
  205. action: 'archive-card',
  206. },
  207. {
  208. keys: ['number keys 1-9'],
  209. action: 'toggle-labels'
  210. },
  211. {
  212. keys: ['shift + number keys 1-9'],
  213. action: 'remove-labels-multiselect'
  214. },
  215. ],
  216. });