2
0

boardHeader.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. const DOWNCLS = 'fa-sort-down';
  2. const UPCLS = 'fa-sort-up';
  3. Template.boardMenuPopup.events({
  4. 'click .js-rename-board': Popup.open('boardChangeTitle'),
  5. 'click .js-custom-fields'() {
  6. Sidebar.setView('customFields');
  7. Popup.close();
  8. },
  9. 'click .js-open-archives'() {
  10. Sidebar.setView('archives');
  11. Popup.close();
  12. },
  13. 'click .js-change-board-color': Popup.open('boardChangeColor'),
  14. 'click .js-change-language': Popup.open('changeLanguage'),
  15. 'click .js-archive-board ': Popup.afterConfirm('archiveBoard', function() {
  16. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  17. currentBoard.archive();
  18. // XXX We should have some kind of notification on top of the page to
  19. // confirm that the board was successfully archived.
  20. FlowRouter.go('home');
  21. }),
  22. 'click .js-delete-board': Popup.afterConfirm('deleteBoard', function() {
  23. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  24. Popup.close();
  25. Boards.remove(currentBoard._id);
  26. FlowRouter.go('home');
  27. }),
  28. 'click .js-outgoing-webhooks': Popup.open('outgoingWebhooks'),
  29. 'click .js-import-board': Popup.open('chooseBoardSource'),
  30. 'click .js-subtask-settings': Popup.open('boardSubtaskSettings'),
  31. });
  32. Template.boardMenuPopup.helpers({
  33. exportUrl() {
  34. const params = {
  35. boardId: Session.get('currentBoard'),
  36. };
  37. const queryParams = {
  38. authToken: Accounts._storedLoginToken(),
  39. };
  40. return FlowRouter.path('/api/boards/:boardId/export', params, queryParams);
  41. },
  42. exportFilename() {
  43. const boardId = Session.get('currentBoard');
  44. return `wekan-export-board-${boardId}.json`;
  45. },
  46. });
  47. Template.boardChangeTitlePopup.events({
  48. submit(event, templateInstance) {
  49. const newTitle = templateInstance
  50. .$('.js-board-name')
  51. .val()
  52. .trim();
  53. const newDesc = templateInstance
  54. .$('.js-board-desc')
  55. .val()
  56. .trim();
  57. if (newTitle) {
  58. this.rename(newTitle);
  59. this.setDescription(newDesc);
  60. Popup.close();
  61. }
  62. event.preventDefault();
  63. },
  64. });
  65. BlazeComponent.extendComponent({
  66. watchLevel() {
  67. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  68. return currentBoard && currentBoard.getWatchLevel(Meteor.userId());
  69. },
  70. isStarred() {
  71. const boardId = Session.get('currentBoard');
  72. const user = Meteor.user();
  73. return user && user.hasStarred(boardId);
  74. },
  75. // Only show the star counter if the number of star is greater than 2
  76. showStarCounter() {
  77. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  78. return currentBoard && currentBoard.stars >= 2;
  79. },
  80. showSort() {
  81. return Meteor.user().hasSortBy();
  82. },
  83. directionClass() {
  84. return this.currentDirection() === -1 ? DOWNCLS : UPCLS;
  85. },
  86. changeDirection() {
  87. const direction = 0 - this.currentDirection() === -1 ? '-' : '';
  88. Meteor.call('setListSortBy', direction + this.currentListSortBy());
  89. },
  90. currentDirection() {
  91. return Meteor.user().getListSortByDirection();
  92. },
  93. currentListSortBy() {
  94. return Meteor.user().getListSortBy();
  95. },
  96. listSortShortDesc() {
  97. return `list-label-short-${this.currentListSortBy()}`;
  98. },
  99. events() {
  100. return [
  101. {
  102. 'click .js-edit-board-title': Popup.open('boardChangeTitle'),
  103. 'click .js-star-board'() {
  104. Meteor.user().toggleBoardStar(Session.get('currentBoard'));
  105. },
  106. 'click .js-open-board-menu': Popup.open('boardMenu'),
  107. 'click .js-change-visibility': Popup.open('boardChangeVisibility'),
  108. 'click .js-watch-board': Popup.open('boardChangeWatch'),
  109. 'click .js-open-archived-board'() {
  110. Modal.open('archivedBoards');
  111. },
  112. 'click .js-toggle-board-view'() {
  113. const currentUser = Meteor.user();
  114. if (
  115. (currentUser.profile || {}).boardView === 'board-view-swimlanes'
  116. ) {
  117. currentUser.setBoardView('board-view-cal');
  118. } else if (
  119. (currentUser.profile || {}).boardView === 'board-view-lists'
  120. ) {
  121. currentUser.setBoardView('board-view-swimlanes');
  122. } else if (
  123. (currentUser.profile || {}).boardView === 'board-view-cal'
  124. ) {
  125. currentUser.setBoardView('board-view-lists');
  126. } else {
  127. currentUser.setBoardView('board-view-swimlanes');
  128. }
  129. },
  130. 'click .js-toggle-sidebar'() {
  131. Sidebar.toggle();
  132. },
  133. 'click .js-open-filter-view'() {
  134. Sidebar.setView('filter');
  135. },
  136. 'click .js-open-sort-view'(evt) {
  137. const target = evt.target;
  138. if (target.tagName === 'I') {
  139. // click on the text, popup choices
  140. this.changeDirection();
  141. } else {
  142. // change the sort order
  143. Popup.open('listsort')(evt);
  144. }
  145. },
  146. 'click .js-filter-reset'(event) {
  147. event.stopPropagation();
  148. Sidebar.setView();
  149. Filter.reset();
  150. },
  151. 'click .js-open-search-view'() {
  152. Sidebar.setView('search');
  153. },
  154. 'click .js-open-rules-view'() {
  155. Modal.openWide('rulesMain');
  156. },
  157. 'click .js-multiselection-activate'() {
  158. const currentCard = Session.get('currentCard');
  159. MultiSelection.activate();
  160. if (currentCard) {
  161. MultiSelection.add(currentCard);
  162. }
  163. },
  164. 'click .js-multiselection-reset'(event) {
  165. event.stopPropagation();
  166. MultiSelection.disable();
  167. },
  168. 'click .js-log-in'() {
  169. FlowRouter.go('atSignIn');
  170. },
  171. },
  172. ];
  173. },
  174. }).register('boardHeaderBar');
  175. Template.boardHeaderBar.helpers({
  176. canModifyBoard() {
  177. return (
  178. Meteor.user() &&
  179. Meteor.user().isBoardMember() &&
  180. !Meteor.user().isCommentOnly()
  181. );
  182. },
  183. });
  184. const CreateBoard = BlazeComponent.extendComponent({
  185. template() {
  186. return 'createBoard';
  187. },
  188. onCreated() {
  189. this.visibilityMenuIsOpen = new ReactiveVar(false);
  190. this.visibility = new ReactiveVar('private');
  191. this.boardId = new ReactiveVar('');
  192. },
  193. visibilityCheck() {
  194. return this.currentData() === this.visibility.get();
  195. },
  196. setVisibility(visibility) {
  197. this.visibility.set(visibility);
  198. this.visibilityMenuIsOpen.set(false);
  199. },
  200. toggleVisibilityMenu() {
  201. this.visibilityMenuIsOpen.set(!this.visibilityMenuIsOpen.get());
  202. },
  203. onSubmit(event) {
  204. event.preventDefault();
  205. const title = this.find('.js-new-board-title').value;
  206. const visibility = this.visibility.get();
  207. this.boardId.set(
  208. Boards.insert({
  209. title,
  210. permission: visibility,
  211. }),
  212. );
  213. Swimlanes.insert({
  214. title: 'Default',
  215. boardId: this.boardId.get(),
  216. });
  217. Utils.goBoardId(this.boardId.get());
  218. },
  219. events() {
  220. return [
  221. {
  222. 'click .js-select-visibility'() {
  223. this.setVisibility(this.currentData());
  224. },
  225. 'click .js-change-visibility': this.toggleVisibilityMenu,
  226. 'click .js-import': Popup.open('boardImportBoard'),
  227. submit: this.onSubmit,
  228. 'click .js-import-board': Popup.open('chooseBoardSource'),
  229. 'click .js-board-template': Popup.open('searchElement'),
  230. },
  231. ];
  232. },
  233. }).register('createBoardPopup');
  234. (class HeaderBarCreateBoard extends CreateBoard {
  235. onSubmit(event) {
  236. super.onSubmit(event);
  237. // Immediately star boards crated with the headerbar popup.
  238. Meteor.user().toggleBoardStar(this.boardId.get());
  239. }
  240. }.register('headerBarCreateBoardPopup'));
  241. BlazeComponent.extendComponent({
  242. visibilityCheck() {
  243. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  244. return this.currentData() === currentBoard.permission;
  245. },
  246. selectBoardVisibility() {
  247. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  248. const visibility = this.currentData();
  249. currentBoard.setVisibility(visibility);
  250. Popup.close();
  251. },
  252. events() {
  253. return [
  254. {
  255. 'click .js-select-visibility': this.selectBoardVisibility,
  256. },
  257. ];
  258. },
  259. }).register('boardChangeVisibilityPopup');
  260. BlazeComponent.extendComponent({
  261. watchLevel() {
  262. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  263. return currentBoard.getWatchLevel(Meteor.userId());
  264. },
  265. watchCheck() {
  266. return this.currentData() === this.watchLevel();
  267. },
  268. events() {
  269. return [
  270. {
  271. 'click .js-select-watch'() {
  272. const level = this.currentData();
  273. Meteor.call(
  274. 'watch',
  275. 'board',
  276. Session.get('currentBoard'),
  277. level,
  278. (err, ret) => {
  279. if (!err && ret) Popup.close();
  280. },
  281. );
  282. },
  283. },
  284. ];
  285. },
  286. }).register('boardChangeWatchPopup');
  287. BlazeComponent.extendComponent({
  288. onCreated() {
  289. //this.sortBy = new ReactiveVar();
  290. ////this.sortDirection = new ReactiveVar();
  291. //this.setSortBy();
  292. this.downClass = DOWNCLS;
  293. this.upClass = UPCLS;
  294. },
  295. allowedSortValues() {
  296. const types = [];
  297. const pushed = {};
  298. Meteor.user()
  299. .getListSortTypes()
  300. .forEach(type => {
  301. const key = type.replace(/^-/, '');
  302. if (pushed[key] === undefined) {
  303. types.push({
  304. name: key,
  305. label: `list-label-${key}`,
  306. shortLabel: `list-label-short-${key}`,
  307. });
  308. pushed[key] = 1;
  309. }
  310. });
  311. return types;
  312. },
  313. Direction() {
  314. return Meteor.user().getListSortByDirection() === -1
  315. ? this.downClass
  316. : this.upClass;
  317. },
  318. sortby() {
  319. return Meteor.user().getListSortBy();
  320. },
  321. setSortBy(type = null) {
  322. const user = Meteor.user();
  323. if (type === null) {
  324. type = user._getListSortBy();
  325. } else {
  326. let value = '';
  327. if (type.map) {
  328. // is an array
  329. value = (type[1] === -1 ? '-' : '') + type[0];
  330. }
  331. Meteor.call('setListSortBy', value);
  332. }
  333. //this.sortBy.set(type[0]);
  334. //this.sortDirection.set(type[1]);
  335. },
  336. events() {
  337. return [
  338. {
  339. 'click .js-sort-by'(evt) {
  340. evt.preventDefault();
  341. const target = evt.target;
  342. const sortby = target.getAttribute('name');
  343. const down = !!target.querySelector(`.${this.upClass}`);
  344. const direction = down ? -1 : 1;
  345. this.setSortBy([sortby, direction]);
  346. if (Utils.isMiniScreen) {
  347. Popup.close();
  348. }
  349. },
  350. },
  351. ];
  352. },
  353. }).register('listsortPopup');