sidebar.js 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837
  1. import { TAPi18n } from '/imports/i18n';
  2. Sidebar = null;
  3. const defaultView = 'home';
  4. const MCB = '.materialCheckBox';
  5. const CKCLS = 'is-checked';
  6. const viewTitles = {
  7. filter: 'filter-cards',
  8. search: 'search-cards',
  9. multiselection: 'multi-selection',
  10. customFields: 'custom-fields',
  11. archives: 'archives',
  12. };
  13. BlazeComponent.extendComponent({
  14. mixins() {
  15. return [Mixins.InfiniteScrolling];
  16. },
  17. onCreated() {
  18. this._isOpen = new ReactiveVar(false);
  19. this._view = new ReactiveVar(defaultView);
  20. this._hideCardCounterList = new ReactiveVar(false);
  21. this._hideBoardMemberList = new ReactiveVar(false);
  22. Sidebar = this;
  23. },
  24. onDestroyed() {
  25. Sidebar = null;
  26. },
  27. isOpen() {
  28. return this._isOpen.get();
  29. },
  30. open() {
  31. if (!this._isOpen.get()) {
  32. this._isOpen.set(true);
  33. EscapeActions.executeUpTo('detailsPane');
  34. }
  35. },
  36. close() {
  37. if (this._isOpen.get()) {
  38. this._isOpen.set(false);
  39. EscapeActions.executeUpTo('detailsPane');
  40. this.toggle()
  41. }
  42. },
  43. hide() {
  44. if (this._isOpen.get()) {
  45. this._isOpen.set(false);
  46. }
  47. },
  48. toggle() {
  49. this._isOpen.set(!this._isOpen.get());
  50. },
  51. calculateNextPeak() {
  52. const sidebarElement = this.find('.js-board-sidebar-content');
  53. if (sidebarElement) {
  54. const altitude = sidebarElement.scrollHeight;
  55. this.callFirstWith(this, 'setNextPeak', altitude);
  56. }
  57. },
  58. reachNextPeak() {
  59. const activitiesComponent = this.childComponents('activities')[0];
  60. activitiesComponent.loadNextPage();
  61. },
  62. isTongueHidden() {
  63. return this.isOpen() && this.getView() !== defaultView;
  64. },
  65. scrollTop() {
  66. this.$('.js-board-sidebar-content').scrollTop(0);
  67. },
  68. getView() {
  69. return this._view.get();
  70. },
  71. setView(view) {
  72. view = _.isString(view) ? view : defaultView;
  73. if (this._view.get() !== view) {
  74. this._view.set(view);
  75. this.scrollTop();
  76. EscapeActions.executeUpTo('detailsPane');
  77. }
  78. this.open();
  79. },
  80. isDefaultView() {
  81. return this.getView() === defaultView;
  82. },
  83. getViewTemplate() {
  84. return `${this.getView()}Sidebar`;
  85. },
  86. getViewTitle() {
  87. return TAPi18n.__(viewTitles[this.getView()]);
  88. },
  89. showTongueTitle() {
  90. if (this.isOpen()) return `${TAPi18n.__('sidebar-close')}`;
  91. else return `${TAPi18n.__('sidebar-open')}`;
  92. },
  93. events() {
  94. return [
  95. {
  96. 'click .js-hide-sidebar': this.hide,
  97. 'click .js-toggle-sidebar': this.toggle,
  98. 'click .js-back-home': this.setView,
  99. 'click .js-toggle-minicard-label-text'() {
  100. currentUser = Meteor.user();
  101. if (currentUser) {
  102. Meteor.call('toggleMinicardLabelText');
  103. } else if (window.localStorage.getItem('hiddenMinicardLabelText')) {
  104. window.localStorage.removeItem('hiddenMinicardLabelText');
  105. location.reload();
  106. } else {
  107. window.localStorage.setItem('hiddenMinicardLabelText', 'true');
  108. location.reload();
  109. }
  110. },
  111. 'click .js-shortcuts'() {
  112. FlowRouter.go('shortcuts');
  113. },
  114. 'click .js-close-sidebar'() {
  115. Sidebar.toggle()
  116. },
  117. },
  118. ];
  119. },
  120. }).register('sidebar');
  121. Blaze.registerHelper('Sidebar', () => Sidebar);
  122. Template.homeSidebar.helpers({
  123. hiddenMinicardLabelText() {
  124. currentUser = Meteor.user();
  125. if (currentUser) {
  126. return (currentUser.profile || {}).hiddenMinicardLabelText;
  127. } else if (window.localStorage.getItem('hiddenMinicardLabelText')) {
  128. return true;
  129. } else {
  130. return false;
  131. }
  132. },
  133. });
  134. Template.boardInfoOnMyBoardsPopup.helpers({
  135. currentSetting() {
  136. return Settings.findOne();
  137. },
  138. hideCardCounterList() {
  139. return Utils.isMiniScreen() && Session.get('currentBoard');
  140. },
  141. hideBoardMemberList() {
  142. return Utils.isMiniScreen() && Session.get('currentBoard');
  143. },
  144. })
  145. EscapeActions.register(
  146. 'sidebarView',
  147. () => {
  148. Sidebar.setView(defaultView);
  149. },
  150. () => {
  151. return Sidebar && Sidebar.getView() !== defaultView;
  152. },
  153. );
  154. Template.memberPopup.helpers({
  155. user() {
  156. return Users.findOne(this.userId);
  157. },
  158. isBoardAdmin() {
  159. return Meteor.user().isBoardAdmin();
  160. },
  161. memberType() {
  162. const type = Users.findOne(this.userId).isBoardAdmin() ? 'admin' : 'normal';
  163. if (type === 'normal') {
  164. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  165. const commentOnly = currentBoard.hasCommentOnly(this.userId);
  166. const noComments = currentBoard.hasNoComments(this.userId);
  167. const worker = currentBoard.hasWorker(this.userId);
  168. if (commentOnly) {
  169. return TAPi18n.__('comment-only');
  170. } else if (noComments) {
  171. return TAPi18n.__('no-comments');
  172. } else if (worker) {
  173. return TAPi18n.__('worker');
  174. } else {
  175. return TAPi18n.__(type);
  176. }
  177. } else {
  178. return TAPi18n.__(type);
  179. }
  180. },
  181. isInvited() {
  182. return Users.findOne(this.userId).isInvitedTo(Session.get('currentBoard'));
  183. },
  184. });
  185. Template.boardMenuPopup.events({
  186. 'click .js-rename-board': Popup.open('boardChangeTitle'),
  187. 'click .js-open-rules-view'() {
  188. Modal.openWide('rulesMain');
  189. Popup.back();
  190. },
  191. 'click .js-custom-fields'() {
  192. Sidebar.setView('customFields');
  193. Popup.back();
  194. },
  195. 'click .js-open-archives'() {
  196. Sidebar.setView('archives');
  197. Popup.back();
  198. },
  199. 'click .js-change-board-color': Popup.open('boardChangeColor'),
  200. 'click .js-board-info-on-my-boards': Popup.open('boardInfoOnMyBoards'),
  201. 'click .js-change-language': Popup.open('changeLanguage'),
  202. 'click .js-archive-board ': Popup.afterConfirm('archiveBoard', function() {
  203. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  204. currentBoard.archive();
  205. // XXX We should have some kind of notification on top of the page to
  206. // confirm that the board was successfully archived.
  207. FlowRouter.go('home');
  208. }),
  209. 'click .js-delete-board': Popup.afterConfirm('deleteBoard', function() {
  210. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  211. Popup.back();
  212. Boards.remove(currentBoard._id);
  213. FlowRouter.go('home');
  214. }),
  215. 'click .js-outgoing-webhooks': Popup.open('outgoingWebhooks'),
  216. 'click .js-import-board': Popup.open('chooseBoardSource'),
  217. 'click .js-subtask-settings': Popup.open('boardSubtaskSettings'),
  218. 'click .js-card-settings': Popup.open('boardCardSettings'),
  219. 'click .js-minicard-settings': Popup.open('boardMinicardSettings'),
  220. 'click .js-export-board': Popup.open('exportBoard'),
  221. });
  222. Template.boardMenuPopup.onCreated(function() {
  223. this.apiEnabled = new ReactiveVar(false);
  224. Meteor.call('_isApiEnabled', (e, result) => {
  225. this.apiEnabled.set(result);
  226. });
  227. });
  228. Template.boardMenuPopup.helpers({
  229. isBoardAdmin() {
  230. return Meteor.user().isBoardAdmin();
  231. },
  232. withApi() {
  233. return Template.instance().apiEnabled.get();
  234. },
  235. exportUrl() {
  236. const params = {
  237. boardId: Session.get('currentBoard'),
  238. };
  239. const queryParams = {
  240. authToken: Accounts._storedLoginToken(),
  241. };
  242. return FlowRouter.path('/api/boards/:boardId/export', params, queryParams);
  243. },
  244. exportFilename() {
  245. const boardId = Session.get('currentBoard');
  246. return `export-board-${boardId}.json`;
  247. },
  248. });
  249. Template.memberPopup.events({
  250. 'click .js-filter-member'() {
  251. Filter.members.toggle(this.userId);
  252. Popup.back();
  253. },
  254. 'click .js-change-role': Popup.open('changePermissions'),
  255. 'click .js-remove-member': Popup.afterConfirm('removeMember', function() {
  256. // This works from removing member from board, card members and assignees.
  257. const boardId = Session.get('currentBoard');
  258. const memberId = this.userId;
  259. Cards.find({ boardId, members: memberId }).forEach(card => {
  260. card.unassignMember(memberId);
  261. });
  262. Cards.find({ boardId, assignees: memberId }).forEach(card => {
  263. card.unassignAssignee(memberId);
  264. });
  265. Boards.findOne(boardId).removeMember(memberId);
  266. Popup.back();
  267. }),
  268. 'click .js-leave-member': Popup.afterConfirm('leaveBoard', () => {
  269. const boardId = Session.get('currentBoard');
  270. Meteor.call('quitBoard', boardId, () => {
  271. Popup.back();
  272. FlowRouter.go('home');
  273. });
  274. }),
  275. });
  276. Template.removeMemberPopup.helpers({
  277. user() {
  278. return Users.findOne(this.userId);
  279. },
  280. board() {
  281. return Boards.findOne(Session.get('currentBoard'));
  282. },
  283. });
  284. Template.leaveBoardPopup.helpers({
  285. board() {
  286. return Boards.findOne(Session.get('currentBoard'));
  287. },
  288. });
  289. BlazeComponent.extendComponent({
  290. onCreated() {
  291. this.error = new ReactiveVar('');
  292. this.loading = new ReactiveVar(false);
  293. this.findOrgsOptions = new ReactiveVar({});
  294. this.findTeamsOptions = new ReactiveVar({});
  295. this.page = new ReactiveVar(1);
  296. this.teamPage = new ReactiveVar(1);
  297. this.autorun(() => {
  298. const limitOrgs = this.page.get() * Number.MAX_SAFE_INTEGER;
  299. this.subscribe('org', this.findOrgsOptions.get(), limitOrgs, () => {});
  300. });
  301. this.autorun(() => {
  302. const limitTeams = this.teamPage.get() * Number.MAX_SAFE_INTEGER;
  303. this.subscribe('team', this.findTeamsOptions.get(), limitTeams, () => {});
  304. });
  305. },
  306. onRendered() {
  307. this.setLoading(false);
  308. },
  309. setError(error) {
  310. this.error.set(error);
  311. },
  312. setLoading(w) {
  313. this.loading.set(w);
  314. },
  315. isLoading() {
  316. return this.loading.get();
  317. },
  318. tabs() {
  319. return [
  320. { name: TAPi18n.__('people'), slug: 'people' },
  321. { name: TAPi18n.__('organizations'), slug: 'organizations' },
  322. { name: TAPi18n.__('teams'), slug: 'teams' },
  323. ];
  324. },
  325. }).register('membersWidget');
  326. Template.membersWidget.helpers({
  327. isInvited() {
  328. const user = Meteor.user();
  329. return user && user.isInvitedTo(Session.get('currentBoard'));
  330. },
  331. isWorker() {
  332. const user = Meteor.user();
  333. if (user) {
  334. return Meteor.call(Boards.hasWorker(user.memberId));
  335. } else {
  336. return false;
  337. }
  338. },
  339. isBoardAdmin() {
  340. return Meteor.user().isBoardAdmin();
  341. },
  342. AtLeastOneOrgWasCreated(){
  343. let orgs = Org.find({}, {sort: { createdAt: -1 }});
  344. if(orgs === undefined)
  345. return false;
  346. return orgs.count() > 0;
  347. },
  348. AtLeastOneTeamWasCreated(){
  349. let teams = Team.find({}, {sort: { createdAt: -1 }});
  350. if(teams === undefined)
  351. return false;
  352. return teams.count() > 0;
  353. },
  354. });
  355. Template.membersWidget.events({
  356. 'click .js-member': Popup.open('member'),
  357. 'click .js-open-board-menu': Popup.open('boardMenu'),
  358. 'click .js-manage-board-members': Popup.open('addMember'),
  359. 'click .js-manage-board-addOrg': Popup.open('addBoardOrg'),
  360. 'click .js-manage-board-addTeam': Popup.open('addBoardTeam'),
  361. 'click .js-import': Popup.open('boardImportBoard'),
  362. submit: this.onSubmit,
  363. 'click .js-import-board': Popup.open('chooseBoardSource'),
  364. 'click .js-open-archived-board'() {
  365. Modal.open('archivedBoards');
  366. },
  367. 'click .sandstorm-powerbox-request-identity'() {
  368. window.sandstormRequestIdentity();
  369. },
  370. 'click .js-member-invite-accept'() {
  371. const boardId = Session.get('currentBoard');
  372. Meteor.user().removeInvite(boardId);
  373. },
  374. 'click .js-member-invite-decline'() {
  375. const boardId = Session.get('currentBoard');
  376. Meteor.call('quitBoard', boardId, (err, ret) => {
  377. if (!err && ret) {
  378. Meteor.user().removeInvite(boardId);
  379. FlowRouter.go('home');
  380. }
  381. });
  382. },
  383. });
  384. BlazeComponent.extendComponent({
  385. boardId() {
  386. return Session.get('currentBoard') || Integrations.Const.GLOBAL_WEBHOOK_ID;
  387. },
  388. integrations() {
  389. const boardId = this.boardId();
  390. return Integrations.find({ boardId: `${boardId}` }).fetch();
  391. },
  392. types() {
  393. return Integrations.Const.WEBHOOK_TYPES;
  394. },
  395. integration(cond) {
  396. const boardId = this.boardId();
  397. const condition = { boardId, ...cond };
  398. for (const k in condition) {
  399. if (!condition[k]) delete condition[k];
  400. }
  401. return Integrations.findOne(condition);
  402. },
  403. onCreated() {
  404. this.disabled = new ReactiveVar(false);
  405. },
  406. events() {
  407. return [
  408. {
  409. 'click a.flex'(evt) {
  410. this.disabled.set(!this.disabled.get());
  411. $(evt.target).toggleClass(CKCLS, this.disabled.get());
  412. },
  413. submit(evt) {
  414. evt.preventDefault();
  415. const url = evt.target.url.value;
  416. const boardId = this.boardId();
  417. let id = null;
  418. let integration = null;
  419. const title = evt.target.title.value;
  420. const token = evt.target.token.value;
  421. const type = evt.target.type.value;
  422. const enabled = !this.disabled.get();
  423. let remove = false;
  424. const values = {
  425. url,
  426. type,
  427. token,
  428. title,
  429. enabled,
  430. };
  431. if (evt.target.id) {
  432. id = evt.target.id.value;
  433. integration = this.integration({ _id: id });
  434. remove = !url;
  435. } else if (url) {
  436. integration = this.integration({ url, token });
  437. }
  438. if (remove) {
  439. Integrations.remove(integration._id);
  440. } else if (integration && integration._id) {
  441. Integrations.update(integration._id, {
  442. $set: values,
  443. });
  444. } else if (url) {
  445. Integrations.insert({
  446. ...values,
  447. userId: Meteor.userId(),
  448. enabled: true,
  449. boardId,
  450. activities: ['all'],
  451. });
  452. }
  453. Popup.back();
  454. },
  455. },
  456. ];
  457. },
  458. }).register('outgoingWebhooksPopup');
  459. BlazeComponent.extendComponent({
  460. template() {
  461. return 'chooseBoardSource';
  462. },
  463. }).register('chooseBoardSourcePopup');
  464. BlazeComponent.extendComponent({
  465. template() {
  466. return 'exportBoard';
  467. },
  468. withApi() {
  469. return Template.instance().apiEnabled.get();
  470. },
  471. exportUrl() {
  472. const params = {
  473. boardId: Session.get('currentBoard'),
  474. };
  475. const queryParams = {
  476. authToken: Accounts._storedLoginToken(),
  477. };
  478. return FlowRouter.path('/api/boards/:boardId/export', params, queryParams);
  479. },
  480. exportUrlExcel() {
  481. const params = {
  482. boardId: Session.get('currentBoard'),
  483. };
  484. const queryParams = {
  485. authToken: Accounts._storedLoginToken(),
  486. };
  487. return FlowRouter.path(
  488. '/api/boards/:boardId/exportExcel',
  489. params,
  490. queryParams,
  491. );
  492. },
  493. exportFilenameExcel() {
  494. const boardId = Session.get('currentBoard');
  495. return `export-board-excel-${boardId}.xlsx`;
  496. },
  497. exportCsvUrl() {
  498. const params = {
  499. boardId: Session.get('currentBoard'),
  500. };
  501. const queryParams = {
  502. authToken: Accounts._storedLoginToken(),
  503. delimiter: ',',
  504. };
  505. return FlowRouter.path(
  506. '/api/boards/:boardId/export/csv',
  507. params,
  508. queryParams,
  509. );
  510. },
  511. exportScsvUrl() {
  512. const params = {
  513. boardId: Session.get('currentBoard'),
  514. };
  515. const queryParams = {
  516. authToken: Accounts._storedLoginToken(),
  517. delimiter: ';',
  518. };
  519. return FlowRouter.path(
  520. '/api/boards/:boardId/export/csv',
  521. params,
  522. queryParams,
  523. );
  524. },
  525. exportTsvUrl() {
  526. const params = {
  527. boardId: Session.get('currentBoard'),
  528. };
  529. const queryParams = {
  530. authToken: Accounts._storedLoginToken(),
  531. delimiter: '\t',
  532. };
  533. return FlowRouter.path(
  534. '/api/boards/:boardId/export/csv',
  535. params,
  536. queryParams,
  537. );
  538. },
  539. exportJsonFilename() {
  540. const boardId = Session.get('currentBoard');
  541. return `export-board-${boardId}.json`;
  542. },
  543. exportCsvFilename() {
  544. const boardId = Session.get('currentBoard');
  545. return `export-board-${boardId}.csv`;
  546. },
  547. exportTsvFilename() {
  548. const boardId = Session.get('currentBoard');
  549. return `export-board-${boardId}.tsv`;
  550. },
  551. }).register('exportBoardPopup');
  552. Template.exportBoard.events({
  553. 'click .html-export-board': async event => {
  554. event.preventDefault();
  555. await ExportHtml(Popup)();
  556. },
  557. });
  558. Template.labelsWidget.events({
  559. 'click .js-label': Popup.open('editLabel'),
  560. 'click .js-add-label': Popup.open('createLabel'),
  561. });
  562. Template.labelsWidget.helpers({
  563. isBoardAdmin() {
  564. return Meteor.user().isBoardAdmin();
  565. },
  566. });
  567. // Board members can assign people or labels by drag-dropping elements from the
  568. // sidebar to the cards on the board. In order to re-initialize the jquery-ui
  569. // plugin any time a draggable member or label is modified or removed we use a
  570. // autorun function and register a dependency on the both members and labels
  571. // fields of the current board document.
  572. function draggableMembersLabelsWidgets() {
  573. this.autorun(() => {
  574. const currentBoardId = Tracker.nonreactive(() => {
  575. return Session.get('currentBoard');
  576. });
  577. Boards.findOne(currentBoardId, {
  578. fields: {
  579. members: 1,
  580. labels: 1,
  581. },
  582. });
  583. Tracker.afterFlush(() => {
  584. const $draggables = this.$('.js-member,.js-label');
  585. $draggables.draggable({
  586. appendTo: 'body',
  587. helper: 'clone',
  588. revert: 'invalid',
  589. revertDuration: 150,
  590. snap: false,
  591. snapMode: 'both',
  592. start() {
  593. EscapeActions.executeUpTo('popup-back');
  594. },
  595. });
  596. function userIsMember() {
  597. return Meteor.user() && Meteor.user().isBoardMember();
  598. }
  599. this.autorun(() => {
  600. $draggables.draggable('option', 'disabled', !userIsMember());
  601. });
  602. });
  603. });
  604. }
  605. Template.membersWidget.onRendered(draggableMembersLabelsWidgets);
  606. Template.labelsWidget.onRendered(draggableMembersLabelsWidgets);
  607. BlazeComponent.extendComponent({
  608. backgroundColors() {
  609. return Boards.simpleSchema()._schema.color.allowedValues;
  610. },
  611. isSelected() {
  612. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  613. return currentBoard.color === this.currentData().toString();
  614. },
  615. events() {
  616. return [
  617. {
  618. 'click .js-select-background'(evt) {
  619. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  620. const newColor = this.currentData().toString();
  621. currentBoard.setColor(newColor);
  622. evt.preventDefault();
  623. },
  624. },
  625. ];
  626. },
  627. }).register('boardChangeColorPopup');
  628. BlazeComponent.extendComponent({
  629. onCreated() {
  630. this.currentBoard = Boards.findOne(Session.get('currentBoard'));
  631. },
  632. allowsCardCounterList() {
  633. return this.currentBoard.allowsCardCounterList;
  634. },
  635. allowsBoardMemberList() {
  636. return this.currentBoard.allowsBoardMemberList;
  637. },
  638. events() {
  639. return [
  640. {
  641. 'click .js-field-has-cardcounterlist'(evt) {
  642. evt.preventDefault();
  643. this.currentBoard.allowsCardCounterList = !this.currentBoard
  644. .allowsCardCounterList;
  645. this.currentBoard.setAllowsCardCounterList(
  646. this.currentBoard.allowsCardCounterList,
  647. );
  648. $(`.js-field-has-cardcounterlist ${MCB}`).toggleClass(
  649. CKCLS,
  650. this.currentBoard.allowsCardCounterList,
  651. );
  652. $('.js-field-has-cardcounterlist').toggleClass(
  653. CKCLS,
  654. this.currentBoard.allowsCardCounterList,
  655. );
  656. },
  657. 'click .js-field-has-boardmemberlist'(evt) {
  658. evt.preventDefault();
  659. this.currentBoard.allowsBoardMemberList = !this.currentBoard
  660. .allowsBoardMemberList;
  661. this.currentBoard.setAllowsBoardMemberList(
  662. this.currentBoard.allowsBoardMemberList,
  663. );
  664. $(`.js-field-has-boardmemberlist ${MCB}`).toggleClass(
  665. CKCLS,
  666. this.currentBoard.allowsBoardMemberList,
  667. );
  668. $('.js-field-has-boardmemberlist').toggleClass(
  669. CKCLS,
  670. this.currentBoard.allowsBoardMemberList,
  671. );
  672. },
  673. },
  674. ];
  675. },
  676. }).register('boardInfoOnMyBoardsPopup');
  677. BlazeComponent.extendComponent({
  678. onCreated() {
  679. this.currentBoard = Boards.findOne(Session.get('currentBoard'));
  680. },
  681. allowsSubtasks() {
  682. return this.currentBoard.allowsSubtasks;
  683. },
  684. allowsReceivedDate() {
  685. return this.currentBoard.allowsReceivedDate;
  686. },
  687. isBoardSelected() {
  688. return this.currentBoard.subtasksDefaultBoardId === this.currentData()._id;
  689. },
  690. isNullBoardSelected() {
  691. return (
  692. this.currentBoard.subtasksDefaultBoardId === null ||
  693. this.currentBoard.subtasksDefaultBoardId === undefined
  694. );
  695. },
  696. boards() {
  697. return Boards.find(
  698. {
  699. archived: false,
  700. 'members.userId': Meteor.userId(),
  701. },
  702. {
  703. sort: { sort: 1 /* boards default sorting */ },
  704. },
  705. );
  706. },
  707. lists() {
  708. return Lists.find(
  709. {
  710. boardId: this.currentBoard._id,
  711. archived: false,
  712. },
  713. {
  714. sort: ['title'],
  715. },
  716. );
  717. },
  718. hasLists() {
  719. return this.lists().count() > 0;
  720. },
  721. isListSelected() {
  722. return this.currentBoard.subtasksDefaultBoardId === this.currentData()._id;
  723. },
  724. presentParentTask() {
  725. let result = this.currentBoard.presentParentTask;
  726. if (result === null || result === undefined) {
  727. result = 'no-parent';
  728. }
  729. return result;
  730. },
  731. events() {
  732. return [
  733. {
  734. 'click .js-field-has-subtasks'(evt) {
  735. evt.preventDefault();
  736. this.currentBoard.allowsSubtasks = !this.currentBoard.allowsSubtasks;
  737. this.currentBoard.setAllowsSubtasks(this.currentBoard.allowsSubtasks);
  738. $(`.js-field-has-subtasks ${MCB}`).toggleClass(
  739. CKCLS,
  740. this.currentBoard.allowsSubtasks,
  741. );
  742. $('.js-field-has-subtasks').toggleClass(
  743. CKCLS,
  744. this.currentBoard.allowsSubtasks,
  745. );
  746. $('.js-field-deposit-board').prop(
  747. 'disabled',
  748. !this.currentBoard.allowsSubtasks,
  749. );
  750. },
  751. 'change .js-field-deposit-board'(evt) {
  752. let value = evt.target.value;
  753. if (value === 'null') {
  754. value = null;
  755. }
  756. this.currentBoard.setSubtasksDefaultBoardId(value);
  757. evt.preventDefault();
  758. },
  759. 'change .js-field-deposit-list'(evt) {
  760. this.currentBoard.setSubtasksDefaultListId(evt.target.value);
  761. evt.preventDefault();
  762. },
  763. 'click .js-field-show-parent-in-minicard'(evt) {
  764. const value =
  765. evt.target.id ||
  766. $(evt.target).parent()[0].id ||
  767. $(evt.target)
  768. .parent()[0]
  769. .parent()[0].id;
  770. const options = [
  771. 'prefix-with-full-path',
  772. 'prefix-with-parent',
  773. 'subtext-with-full-path',
  774. 'subtext-with-parent',
  775. 'no-parent',
  776. ];
  777. options.forEach(function(element) {
  778. if (element !== value) {
  779. $(`#${element} ${MCB}`).toggleClass(CKCLS, false);
  780. $(`#${element}`).toggleClass(CKCLS, false);
  781. }
  782. });
  783. $(`#${value} ${MCB}`).toggleClass(CKCLS, true);
  784. $(`#${value}`).toggleClass(CKCLS, true);
  785. this.currentBoard.setPresentParentTask(value);
  786. evt.preventDefault();
  787. },
  788. },
  789. ];
  790. },
  791. }).register('boardSubtaskSettingsPopup');
  792. BlazeComponent.extendComponent({
  793. onCreated() {
  794. this.currentBoard = Boards.findOne(Session.get('currentBoard'));
  795. },
  796. allowsReceivedDate() {
  797. return this.currentBoard.allowsReceivedDate;
  798. },
  799. allowsStartDate() {
  800. return this.currentBoard.allowsStartDate;
  801. },
  802. allowsDueDate() {
  803. return this.currentBoard.allowsDueDate;
  804. },
  805. allowsEndDate() {
  806. return this.currentBoard.allowsEndDate;
  807. },
  808. allowsSubtasks() {
  809. return this.currentBoard.allowsSubtasks;
  810. },
  811. allowsCreator() {
  812. return (
  813. this.currentBoard.allowsCreator === null ||
  814. this.currentBoard.allowsCreator === undefined ||
  815. this.currentBoard.allowsCreator
  816. );
  817. },
  818. allowsMembers() {
  819. return this.currentBoard.allowsMembers;
  820. },
  821. allowsAssignee() {
  822. return this.currentBoard.allowsAssignee;
  823. },
  824. allowsAssignedBy() {
  825. return this.currentBoard.allowsAssignedBy;
  826. },
  827. allowsRequestedBy() {
  828. return this.currentBoard.allowsRequestedBy;
  829. },
  830. allowsCardSortingByNumber() {
  831. return this.currentBoard.allowsCardSortingByNumber;
  832. },
  833. allowsShowLists() {
  834. return this.currentBoard.allowsShowLists;
  835. },
  836. allowsLabels() {
  837. return this.currentBoard.allowsLabels;
  838. },
  839. allowsChecklists() {
  840. return this.currentBoard.allowsChecklists;
  841. },
  842. allowsAttachments() {
  843. return this.currentBoard.allowsAttachments;
  844. },
  845. allowsComments() {
  846. return this.currentBoard.allowsComments;
  847. },
  848. allowsCardNumber() {
  849. return this.currentBoard.allowsCardNumber;
  850. },
  851. allowsDescriptionTitle() {
  852. return this.currentBoard.allowsDescriptionTitle;
  853. },
  854. allowsDescriptionText() {
  855. return this.currentBoard.allowsDescriptionText;
  856. },
  857. isBoardSelected() {
  858. return this.currentBoard.dateSettingsDefaultBoardID;
  859. },
  860. isNullBoardSelected() {
  861. return (
  862. this.currentBoard.dateSettingsDefaultBoardId === null ||
  863. this.currentBoard.dateSettingsDefaultBoardId === undefined
  864. );
  865. },
  866. boards() {
  867. return Boards.find(
  868. {
  869. archived: false,
  870. 'members.userId': Meteor.userId(),
  871. },
  872. {
  873. sort: { sort: 1 /* boards default sorting */ },
  874. },
  875. );
  876. },
  877. lists() {
  878. return Lists.find(
  879. {
  880. boardId: this.currentBoard._id,
  881. archived: false,
  882. },
  883. {
  884. sort: ['title'],
  885. },
  886. );
  887. },
  888. hasLists() {
  889. return this.lists().count() > 0;
  890. },
  891. isListSelected() {
  892. return (
  893. this.currentBoard.dateSettingsDefaultBoardId === this.currentData()._id
  894. );
  895. },
  896. events() {
  897. return [
  898. {
  899. 'click .js-field-has-receiveddate'(evt) {
  900. evt.preventDefault();
  901. this.currentBoard.allowsReceivedDate = !this.currentBoard
  902. .allowsReceivedDate;
  903. this.currentBoard.setAllowsReceivedDate(
  904. this.currentBoard.allowsReceivedDate,
  905. );
  906. $(`.js-field-has-receiveddate ${MCB}`).toggleClass(
  907. CKCLS,
  908. this.currentBoard.allowsReceivedDate,
  909. );
  910. $('.js-field-has-receiveddate').toggleClass(
  911. CKCLS,
  912. this.currentBoard.allowsReceivedDate,
  913. );
  914. },
  915. 'click .js-field-has-startdate'(evt) {
  916. evt.preventDefault();
  917. this.currentBoard.allowsStartDate = !this.currentBoard
  918. .allowsStartDate;
  919. this.currentBoard.setAllowsStartDate(
  920. this.currentBoard.allowsStartDate,
  921. );
  922. $(`.js-field-has-startdate ${MCB}`).toggleClass(
  923. CKCLS,
  924. this.currentBoard.allowsStartDate,
  925. );
  926. $('.js-field-has-startdate').toggleClass(
  927. CKCLS,
  928. this.currentBoard.allowsStartDate,
  929. );
  930. },
  931. 'click .js-field-has-enddate'(evt) {
  932. evt.preventDefault();
  933. this.currentBoard.allowsEndDate = !this.currentBoard.allowsEndDate;
  934. this.currentBoard.setAllowsEndDate(this.currentBoard.allowsEndDate);
  935. $(`.js-field-has-enddate ${MCB}`).toggleClass(
  936. CKCLS,
  937. this.currentBoard.allowsEndDate,
  938. );
  939. $('.js-field-has-enddate').toggleClass(
  940. CKCLS,
  941. this.currentBoard.allowsEndDate,
  942. );
  943. },
  944. 'click .js-field-has-duedate'(evt) {
  945. evt.preventDefault();
  946. this.currentBoard.allowsDueDate = !this.currentBoard.allowsDueDate;
  947. this.currentBoard.setAllowsDueDate(this.currentBoard.allowsDueDate);
  948. $(`.js-field-has-duedate ${MCB}`).toggleClass(
  949. CKCLS,
  950. this.currentBoard.allowsDueDate,
  951. );
  952. $('.js-field-has-duedate').toggleClass(
  953. CKCLS,
  954. this.currentBoard.allowsDueDate,
  955. );
  956. },
  957. 'click .js-field-has-subtasks'(evt) {
  958. evt.preventDefault();
  959. this.currentBoard.allowsSubtasks = !this.currentBoard.allowsSubtasks;
  960. this.currentBoard.setAllowsSubtasks(this.currentBoard.allowsSubtasks);
  961. $(`.js-field-has-subtasks ${MCB}`).toggleClass(
  962. CKCLS,
  963. this.currentBoard.allowsSubtasks,
  964. );
  965. $('.js-field-has-subtasks').toggleClass(
  966. CKCLS,
  967. this.currentBoard.allowsSubtasks,
  968. );
  969. },
  970. 'click .js-field-has-creator'(evt) {
  971. evt.preventDefault();
  972. this.currentBoard.allowsCreator = !this.currentBoard.allowsCreator;
  973. this.currentBoard.setAllowsCreator(this.currentBoard.allowsCreator);
  974. $(`.js-field-has-creator ${MCB}`).toggleClass(
  975. CKCLS,
  976. this.currentBoard.allowsCreator,
  977. );
  978. $('.js-field-has-creator').toggleClass(
  979. CKCLS,
  980. this.currentBoard.allowsCreator,
  981. );
  982. },
  983. 'click .js-field-has-members'(evt) {
  984. evt.preventDefault();
  985. this.currentBoard.allowsMembers = !this.currentBoard.allowsMembers;
  986. this.currentBoard.setAllowsMembers(this.currentBoard.allowsMembers);
  987. $(`.js-field-has-members ${MCB}`).toggleClass(
  988. CKCLS,
  989. this.currentBoard.allowsMembers,
  990. );
  991. $('.js-field-has-members').toggleClass(
  992. CKCLS,
  993. this.currentBoard.allowsMembers,
  994. );
  995. },
  996. 'click .js-field-has-assignee'(evt) {
  997. evt.preventDefault();
  998. this.currentBoard.allowsAssignee = !this.currentBoard.allowsAssignee;
  999. this.currentBoard.setAllowsAssignee(this.currentBoard.allowsAssignee);
  1000. $(`.js-field-has-assignee ${MCB}`).toggleClass(
  1001. CKCLS,
  1002. this.currentBoard.allowsAssignee,
  1003. );
  1004. $('.js-field-has-assignee').toggleClass(
  1005. CKCLS,
  1006. this.currentBoard.allowsAssignee,
  1007. );
  1008. },
  1009. 'click .js-field-has-assigned-by'(evt) {
  1010. evt.preventDefault();
  1011. this.currentBoard.allowsAssignedBy = !this.currentBoard
  1012. .allowsAssignedBy;
  1013. this.currentBoard.setAllowsAssignedBy(
  1014. this.currentBoard.allowsAssignedBy,
  1015. );
  1016. $(`.js-field-has-assigned-by ${MCB}`).toggleClass(
  1017. CKCLS,
  1018. this.currentBoard.allowsAssignedBy,
  1019. );
  1020. $('.js-field-has-assigned-by').toggleClass(
  1021. CKCLS,
  1022. this.currentBoard.allowsAssignedBy,
  1023. );
  1024. },
  1025. 'click .js-field-has-requested-by'(evt) {
  1026. evt.preventDefault();
  1027. this.currentBoard.allowsRequestedBy = !this.currentBoard
  1028. .allowsRequestedBy;
  1029. this.currentBoard.setAllowsRequestedBy(
  1030. this.currentBoard.allowsRequestedBy,
  1031. );
  1032. $(`.js-field-has-requested-by ${MCB}`).toggleClass(
  1033. CKCLS,
  1034. this.currentBoard.allowsRequestedBy,
  1035. );
  1036. $('.js-field-has-requested-by').toggleClass(
  1037. CKCLS,
  1038. this.currentBoard.allowsRequestedBy,
  1039. );
  1040. },
  1041. 'click .js-field-has-card-sorting-by-number'(evt) {
  1042. evt.preventDefault();
  1043. this.currentBoard.allowsCardSortingByNumber = !this.currentBoard
  1044. .allowsCardSortingByNumber;
  1045. this.currentBoard.setAllowsCardSortingByNumber(
  1046. this.currentBoard.allowsCardSortingByNumber,
  1047. );
  1048. $(`.js-field-has-card-sorting-by-number ${MCB}`).toggleClass(
  1049. CKCLS,
  1050. this.currentBoard.allowsCardSortingByNumber,
  1051. );
  1052. $('.js-field-has-card-sorting-by-number').toggleClass(
  1053. CKCLS,
  1054. this.currentBoard.allowsCardSortingByNumber,
  1055. );
  1056. },
  1057. 'click .js-field-has-card-show-lists'(evt) {
  1058. evt.preventDefault();
  1059. this.currentBoard.allowsShowLists = !this.currentBoard
  1060. .allowsShowLists;
  1061. this.currentBoard.setAllowsShowLists(
  1062. this.currentBoard.allowsShowLists,
  1063. );
  1064. $(`.js-field-has-card-show-lists ${MCB}`).toggleClass(
  1065. CKCLS,
  1066. this.currentBoard.allowsShowLists,
  1067. );
  1068. $('.js-field-has-card-show-lists').toggleClass(
  1069. CKCLS,
  1070. this.currentBoard.allowsShowLists,
  1071. );
  1072. },
  1073. 'click .js-field-has-labels'(evt) {
  1074. evt.preventDefault();
  1075. this.currentBoard.allowsLabels = !this.currentBoard.allowsLabels;
  1076. this.currentBoard.setAllowsLabels(this.currentBoard.allowsLabels);
  1077. $(`.js-field-has-labels ${MCB}`).toggleClass(
  1078. CKCLS,
  1079. this.currentBoard.allowsAssignee,
  1080. );
  1081. $('.js-field-has-labels').toggleClass(
  1082. CKCLS,
  1083. this.currentBoard.allowsLabels,
  1084. );
  1085. },
  1086. 'click .js-field-has-description-title'(evt) {
  1087. evt.preventDefault();
  1088. this.currentBoard.allowsDescriptionTitle = !this.currentBoard
  1089. .allowsDescriptionTitle;
  1090. this.currentBoard.setAllowsDescriptionTitle(
  1091. this.currentBoard.allowsDescriptionTitle,
  1092. );
  1093. $(`.js-field-has-description-title ${MCB}`).toggleClass(
  1094. CKCLS,
  1095. this.currentBoard.allowsDescriptionTitle,
  1096. );
  1097. $('.js-field-has-description-title').toggleClass(
  1098. CKCLS,
  1099. this.currentBoard.allowsDescriptionTitle,
  1100. );
  1101. },
  1102. 'click .js-field-has-card-number'(evt) {
  1103. evt.preventDefault();
  1104. this.currentBoard.allowsCardNumber = !this.currentBoard
  1105. .allowsCardNumber;
  1106. this.currentBoard.setAllowsCardNumber(
  1107. this.currentBoard.allowsCardNumber,
  1108. );
  1109. $(`.js-field-has-card-number ${MCB}`).toggleClass(
  1110. CKCLS,
  1111. this.currentBoard.allowsCardNumber,
  1112. );
  1113. $('.js-field-has-card-number').toggleClass(
  1114. CKCLS,
  1115. this.currentBoard.allowsCardNumber,
  1116. );
  1117. },
  1118. 'click .js-field-has-description-text'(evt) {
  1119. evt.preventDefault();
  1120. this.currentBoard.allowsDescriptionText = !this.currentBoard
  1121. .allowsDescriptionText;
  1122. this.currentBoard.setAllowsDescriptionText(
  1123. this.currentBoard.allowsDescriptionText,
  1124. );
  1125. $(`.js-field-has-description-text ${MCB}`).toggleClass(
  1126. CKCLS,
  1127. this.currentBoard.allowsDescriptionText,
  1128. );
  1129. $('.js-field-has-description-text').toggleClass(
  1130. CKCLS,
  1131. this.currentBoard.allowsDescriptionText,
  1132. );
  1133. },
  1134. 'click .js-field-has-checklists'(evt) {
  1135. evt.preventDefault();
  1136. this.currentBoard.allowsChecklists = !this.currentBoard
  1137. .allowsChecklists;
  1138. this.currentBoard.setAllowsChecklists(
  1139. this.currentBoard.allowsChecklists,
  1140. );
  1141. $(`.js-field-has-checklists ${MCB}`).toggleClass(
  1142. CKCLS,
  1143. this.currentBoard.allowsChecklists,
  1144. );
  1145. $('.js-field-has-checklists').toggleClass(
  1146. CKCLS,
  1147. this.currentBoard.allowsChecklists,
  1148. );
  1149. },
  1150. 'click .js-field-has-attachments'(evt) {
  1151. evt.preventDefault();
  1152. this.currentBoard.allowsAttachments = !this.currentBoard
  1153. .allowsAttachments;
  1154. this.currentBoard.setAllowsAttachments(
  1155. this.currentBoard.allowsAttachments,
  1156. );
  1157. $(`.js-field-has-attachments ${MCB}`).toggleClass(
  1158. CKCLS,
  1159. this.currentBoard.allowsAttachments,
  1160. );
  1161. $('.js-field-has-attachments').toggleClass(
  1162. CKCLS,
  1163. this.currentBoard.allowsAttachments,
  1164. );
  1165. },
  1166. 'click .js-field-has-comments'(evt) {
  1167. evt.preventDefault();
  1168. this.currentBoard.allowsComments = !this.currentBoard.allowsComments;
  1169. this.currentBoard.setAllowsComments(this.currentBoard.allowsComments);
  1170. $(`.js-field-has-comments ${MCB}`).toggleClass(
  1171. CKCLS,
  1172. this.currentBoard.allowsComments,
  1173. );
  1174. $('.js-field-has-comments').toggleClass(
  1175. CKCLS,
  1176. this.currentBoard.allowsComments,
  1177. );
  1178. },
  1179. 'click .js-field-has-activities'(evt) {
  1180. evt.preventDefault();
  1181. this.currentBoard.allowsActivities = !this.currentBoard
  1182. .allowsActivities;
  1183. this.currentBoard.setAllowsActivities(
  1184. this.currentBoard.allowsActivities,
  1185. );
  1186. $(`.js-field-has-activities ${MCB}`).toggleClass(
  1187. CKCLS,
  1188. this.currentBoard.allowsActivities,
  1189. );
  1190. $('.js-field-has-activities').toggleClass(
  1191. CKCLS,
  1192. this.currentBoard.allowsActivities,
  1193. );
  1194. },
  1195. },
  1196. ];
  1197. },
  1198. }).register('boardCardSettingsPopup');
  1199. BlazeComponent.extendComponent({
  1200. onCreated() {
  1201. this.currentBoard = Boards.findOne(Session.get('currentBoard'));
  1202. },
  1203. allowsDescriptionTextOnMinicard() {
  1204. return this.currentBoard.allowsDescriptionTextOnMinicard;
  1205. },
  1206. lists() {
  1207. return Lists.find(
  1208. {
  1209. boardId: this.currentBoard._id,
  1210. archived: false,
  1211. },
  1212. {
  1213. sort: ['title'],
  1214. },
  1215. );
  1216. },
  1217. hasLists() {
  1218. return this.lists().count() > 0;
  1219. },
  1220. isListSelected() {
  1221. return (
  1222. this.currentBoard.dateSettingsDefaultBoardId === this.currentData()._id
  1223. );
  1224. },
  1225. events() {
  1226. return [
  1227. {
  1228. 'click .js-field-has-description-text-on-minicard'(evt) {
  1229. evt.preventDefault();
  1230. this.currentBoard.allowsDescriptionTextOnMinicard = !this.currentBoard
  1231. .allowsDescriptionTextOnMinicard;
  1232. this.currentBoard.setallowsDescriptionTextOnMinicard(
  1233. this.currentBoard.allowsDescriptionTextOnMinicard,
  1234. );
  1235. $(`.js-field-has-description-text-on-minicard ${MCB}`).toggleClass(
  1236. CKCLS,
  1237. this.currentBoard.allowsDescriptionTextOnMinicard,
  1238. );
  1239. $('.js-field-has-description-text-on-minicard').toggleClass(
  1240. CKCLS,
  1241. this.currentBoard.allowsDescriptionTextOnMinicard,
  1242. );
  1243. },
  1244. },
  1245. ];
  1246. },
  1247. }).register('boardMinicardSettingsPopup');
  1248. BlazeComponent.extendComponent({
  1249. onCreated() {
  1250. this.error = new ReactiveVar('');
  1251. this.loading = new ReactiveVar(false);
  1252. },
  1253. onRendered() {
  1254. this.find('.js-search-member input').focus();
  1255. this.setLoading(false);
  1256. },
  1257. isBoardMember() {
  1258. const userId = this.currentData().__originalId;
  1259. const user = Users.findOne(userId);
  1260. return user && user.isBoardMember();
  1261. },
  1262. isValidEmail(email) {
  1263. return SimpleSchema.RegEx.Email.test(email);
  1264. },
  1265. setError(error) {
  1266. this.error.set(error);
  1267. },
  1268. setLoading(w) {
  1269. this.loading.set(w);
  1270. },
  1271. isLoading() {
  1272. return this.loading.get();
  1273. },
  1274. inviteUser(idNameEmail) {
  1275. const boardId = Session.get('currentBoard');
  1276. this.setLoading(true);
  1277. const self = this;
  1278. Meteor.call('inviteUserToBoard', idNameEmail, boardId, (err, ret) => {
  1279. self.setLoading(false);
  1280. if (err) self.setError(err.error);
  1281. else if (ret.email) self.setError('email-sent');
  1282. else Popup.back();
  1283. });
  1284. },
  1285. events() {
  1286. return [
  1287. {
  1288. 'keyup input'() {
  1289. this.setError('');
  1290. },
  1291. 'click .js-select-member'() {
  1292. const userId = this.currentData().__originalId;
  1293. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  1294. if (!currentBoard.hasMember(userId)) {
  1295. this.inviteUser(userId);
  1296. }
  1297. },
  1298. 'click .js-email-invite'() {
  1299. const idNameEmail = $('.js-search-member input').val();
  1300. if (idNameEmail.indexOf('@') < 0 || this.isValidEmail(idNameEmail)) {
  1301. this.inviteUser(idNameEmail);
  1302. } else this.setError('email-invalid');
  1303. },
  1304. },
  1305. ];
  1306. },
  1307. }).register('addMemberPopup');
  1308. Template.addMemberPopup.helpers({
  1309. searchIndex: () => UserSearchIndex,
  1310. })
  1311. BlazeComponent.extendComponent({
  1312. onCreated() {
  1313. this.error = new ReactiveVar('');
  1314. this.loading = new ReactiveVar(false);
  1315. this.findOrgsOptions = new ReactiveVar({});
  1316. this.page = new ReactiveVar(1);
  1317. this.autorun(() => {
  1318. const limitOrgs = this.page.get() * Number.MAX_SAFE_INTEGER;
  1319. this.subscribe('org', this.findOrgsOptions.get(), limitOrgs, () => {});
  1320. });
  1321. },
  1322. onRendered() {
  1323. this.setLoading(false);
  1324. },
  1325. setError(error) {
  1326. this.error.set(error);
  1327. },
  1328. setLoading(w) {
  1329. this.loading.set(w);
  1330. },
  1331. isLoading() {
  1332. return this.loading.get();
  1333. },
  1334. events() {
  1335. return [
  1336. {
  1337. 'keyup input'() {
  1338. this.setError('');
  1339. },
  1340. 'change #jsBoardOrgs'() {
  1341. let currentBoard = Boards.findOne(Session.get('currentBoard'));
  1342. let selectElt = document.getElementById("jsBoardOrgs");
  1343. let selectedOrgId = selectElt.options[selectElt.selectedIndex].value;
  1344. let selectedOrgDisplayName = selectElt.options[selectElt.selectedIndex].text;
  1345. let boardOrganizations = [];
  1346. if(currentBoard.orgs !== undefined){
  1347. for(let i = 0; i < currentBoard.orgs.length; i++){
  1348. boardOrganizations.push(currentBoard.orgs[i]);
  1349. }
  1350. }
  1351. if(!boardOrganizations.some((org) => org.orgDisplayName == selectedOrgDisplayName)){
  1352. boardOrganizations.push({
  1353. "orgId": selectedOrgId,
  1354. "orgDisplayName": selectedOrgDisplayName,
  1355. "isActive" : true,
  1356. })
  1357. if (selectedOrgId != "-1") {
  1358. Meteor.call('setBoardOrgs', boardOrganizations, currentBoard._id);
  1359. }
  1360. }
  1361. Popup.back();
  1362. },
  1363. },
  1364. ];
  1365. },
  1366. }).register('addBoardOrgPopup');
  1367. Template.addBoardOrgPopup.helpers({
  1368. orgsDatas() {
  1369. let orgs = Org.find({}, {sort: { orgDisplayName: 1 }});
  1370. return orgs;
  1371. },
  1372. });
  1373. BlazeComponent.extendComponent({
  1374. onCreated() {
  1375. this.error = new ReactiveVar('');
  1376. this.loading = new ReactiveVar(false);
  1377. this.findOrgsOptions = new ReactiveVar({});
  1378. this.page = new ReactiveVar(1);
  1379. this.autorun(() => {
  1380. const limitOrgs = this.page.get() * Number.MAX_SAFE_INTEGER;
  1381. this.subscribe('org', this.findOrgsOptions.get(), limitOrgs, () => {});
  1382. });
  1383. },
  1384. onRendered() {
  1385. this.setLoading(false);
  1386. },
  1387. setError(error) {
  1388. this.error.set(error);
  1389. },
  1390. setLoading(w) {
  1391. this.loading.set(w);
  1392. },
  1393. isLoading() {
  1394. return this.loading.get();
  1395. },
  1396. events() {
  1397. return [
  1398. {
  1399. 'keyup input'() {
  1400. this.setError('');
  1401. },
  1402. 'click #leaveBoardBtn'(){
  1403. let stringOrgId = document.getElementById('hideOrgId').value;
  1404. let currentBoard = Boards.findOne(Session.get('currentBoard'));
  1405. let boardOrganizations = [];
  1406. if(currentBoard.orgs !== undefined){
  1407. for(let i = 0; i < currentBoard.orgs.length; i++){
  1408. if(currentBoard.orgs[i].orgId != stringOrgId){
  1409. boardOrganizations.push(currentBoard.orgs[i]);
  1410. }
  1411. }
  1412. }
  1413. Meteor.call('setBoardOrgs', boardOrganizations, currentBoard._id);
  1414. Popup.back();
  1415. },
  1416. 'click #cancelLeaveBoardBtn'(){
  1417. Popup.back();
  1418. },
  1419. },
  1420. ];
  1421. },
  1422. }).register('removeBoardOrgPopup');
  1423. Template.removeBoardOrgPopup.helpers({
  1424. org() {
  1425. return Org.findOne(this.orgId);
  1426. },
  1427. });
  1428. BlazeComponent.extendComponent({
  1429. onCreated() {
  1430. this.error = new ReactiveVar('');
  1431. this.loading = new ReactiveVar(false);
  1432. this.findOrgsOptions = new ReactiveVar({});
  1433. this.page = new ReactiveVar(1);
  1434. this.autorun(() => {
  1435. const limitTeams = this.page.get() * Number.MAX_SAFE_INTEGER;
  1436. this.subscribe('team', this.findOrgsOptions.get(), limitTeams, () => {});
  1437. });
  1438. this.findUsersOptions = new ReactiveVar({});
  1439. this.userPage = new ReactiveVar(1);
  1440. this.autorun(() => {
  1441. const limitUsers = this.userPage.get() * Number.MAX_SAFE_INTEGER;
  1442. this.subscribe('people', this.findUsersOptions.get(), limitUsers, () => {});
  1443. });
  1444. },
  1445. onRendered() {
  1446. this.setLoading(false);
  1447. },
  1448. setError(error) {
  1449. this.error.set(error);
  1450. },
  1451. setLoading(w) {
  1452. this.loading.set(w);
  1453. },
  1454. isLoading() {
  1455. return this.loading.get();
  1456. },
  1457. events() {
  1458. return [
  1459. {
  1460. 'keyup input'() {
  1461. this.setError('');
  1462. },
  1463. 'change #jsBoardTeams'() {
  1464. let currentBoard = Boards.findOne(Session.get('currentBoard'));
  1465. let selectElt = document.getElementById("jsBoardTeams");
  1466. let selectedTeamId = selectElt.options[selectElt.selectedIndex].value;
  1467. let selectedTeamDisplayName = selectElt.options[selectElt.selectedIndex].text;
  1468. let boardTeams = [];
  1469. if(currentBoard.teams !== undefined){
  1470. for(let i = 0; i < currentBoard.teams.length; i++){
  1471. boardTeams.push(currentBoard.teams[i]);
  1472. }
  1473. }
  1474. if(!boardTeams.some((team) => team.teamDisplayName == selectedTeamDisplayName)){
  1475. boardTeams.push({
  1476. "teamId": selectedTeamId,
  1477. "teamDisplayName": selectedTeamDisplayName,
  1478. "isActive" : true,
  1479. })
  1480. if (selectedTeamId != "-1") {
  1481. let members = currentBoard.members;
  1482. let query = {
  1483. "teams.teamId": { $in: boardTeams.map(t => t.teamId) },
  1484. };
  1485. const boardTeamUsers = Users.find(query, {
  1486. sort: { sort: 1 },
  1487. });
  1488. if(boardTeams !== undefined && boardTeams.length > 0){
  1489. let index;
  1490. if(boardTeamUsers && boardTeamUsers.count() > 0){
  1491. boardTeamUsers.forEach((u) => {
  1492. index = members.findIndex(function(m){ return m.userId == u._id});
  1493. if(index == -1){
  1494. members.push({
  1495. "isActive": true,
  1496. "isAdmin": u.isAdmin !== undefined ? u.isAdmin : false,
  1497. "isCommentOnly" : false,
  1498. "isNoComments" : false,
  1499. "userId": u._id,
  1500. });
  1501. }
  1502. });
  1503. }
  1504. }
  1505. Meteor.call('setBoardTeams', boardTeams, members, currentBoard._id);
  1506. }
  1507. }
  1508. Popup.back();
  1509. },
  1510. },
  1511. ];
  1512. },
  1513. }).register('addBoardTeamPopup');
  1514. Template.addBoardTeamPopup.helpers({
  1515. teamsDatas() {
  1516. let teams = Team.find({}, {sort: { teamDisplayName: 1 }});
  1517. return teams;
  1518. },
  1519. });
  1520. BlazeComponent.extendComponent({
  1521. onCreated() {
  1522. this.error = new ReactiveVar('');
  1523. this.loading = new ReactiveVar(false);
  1524. this.findOrgsOptions = new ReactiveVar({});
  1525. this.page = new ReactiveVar(1);
  1526. this.autorun(() => {
  1527. const limitTeams = this.page.get() * Number.MAX_SAFE_INTEGER;
  1528. this.subscribe('team', this.findOrgsOptions.get(), limitTeams, () => {});
  1529. });
  1530. this.findUsersOptions = new ReactiveVar({});
  1531. this.userPage = new ReactiveVar(1);
  1532. this.autorun(() => {
  1533. const limitUsers = this.userPage.get() * Number.MAX_SAFE_INTEGER;
  1534. this.subscribe('people', this.findUsersOptions.get(), limitUsers, () => {});
  1535. });
  1536. },
  1537. onRendered() {
  1538. this.setLoading(false);
  1539. },
  1540. setError(error) {
  1541. this.error.set(error);
  1542. },
  1543. setLoading(w) {
  1544. this.loading.set(w);
  1545. },
  1546. isLoading() {
  1547. return this.loading.get();
  1548. },
  1549. events() {
  1550. return [
  1551. {
  1552. 'keyup input'() {
  1553. this.setError('');
  1554. },
  1555. 'click #leaveBoardTeamBtn'(){
  1556. let stringTeamId = document.getElementById('hideTeamId').value;
  1557. let currentBoard = Boards.findOne(Session.get('currentBoard'));
  1558. let boardTeams = [];
  1559. if(currentBoard.teams !== undefined){
  1560. for(let i = 0; i < currentBoard.teams.length; i++){
  1561. if(currentBoard.teams[i].teamId != stringTeamId){
  1562. boardTeams.push(currentBoard.teams[i]);
  1563. }
  1564. }
  1565. }
  1566. let members = currentBoard.members;
  1567. let query = {
  1568. "teams.teamId": stringTeamId
  1569. };
  1570. const boardTeamUsers = Users.find(query, {
  1571. sort: { sort: 1 },
  1572. });
  1573. if(currentBoard.teams !== undefined && currentBoard.teams.length > 0){
  1574. let index;
  1575. if(boardTeamUsers && boardTeamUsers.count() > 0){
  1576. boardTeamUsers.forEach((u) => {
  1577. index = members.findIndex(function(m){ return m.userId == u._id});
  1578. if(index !== -1 && (u.isAdmin === undefined || u.isAdmin == false)){
  1579. members.splice(index, 1);
  1580. }
  1581. });
  1582. }
  1583. }
  1584. Meteor.call('setBoardTeams', boardTeams, members, currentBoard._id);
  1585. Popup.back();
  1586. },
  1587. 'click #cancelLeaveBoardTeamBtn'(){
  1588. Popup.back();
  1589. },
  1590. },
  1591. ];
  1592. },
  1593. }).register('removeBoardTeamPopup');
  1594. Template.removeBoardTeamPopup.helpers({
  1595. team() {
  1596. return Team.findOne(this.teamId);
  1597. },
  1598. });
  1599. Template.changePermissionsPopup.events({
  1600. 'click .js-set-admin, click .js-set-normal, click .js-set-no-comments, click .js-set-comment-only, click .js-set-worker'(
  1601. event,
  1602. ) {
  1603. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  1604. const memberId = this.userId;
  1605. const isAdmin = $(event.currentTarget).hasClass('js-set-admin');
  1606. const isCommentOnly = $(event.currentTarget).hasClass(
  1607. 'js-set-comment-only',
  1608. );
  1609. const isNoComments = $(event.currentTarget).hasClass('js-set-no-comments');
  1610. const isWorker = $(event.currentTarget).hasClass('js-set-worker');
  1611. currentBoard.setMemberPermission(
  1612. memberId,
  1613. isAdmin,
  1614. isNoComments,
  1615. isCommentOnly,
  1616. isWorker,
  1617. );
  1618. Popup.back(1);
  1619. },
  1620. });
  1621. Template.changePermissionsPopup.helpers({
  1622. isAdmin() {
  1623. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  1624. return currentBoard.hasAdmin(this.userId);
  1625. },
  1626. isNormal() {
  1627. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  1628. return (
  1629. !currentBoard.hasAdmin(this.userId) &&
  1630. !currentBoard.hasNoComments(this.userId) &&
  1631. !currentBoard.hasCommentOnly(this.userId) &&
  1632. !currentBoard.hasWorker(this.userId)
  1633. );
  1634. },
  1635. isNoComments() {
  1636. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  1637. return (
  1638. !currentBoard.hasAdmin(this.userId) &&
  1639. currentBoard.hasNoComments(this.userId)
  1640. );
  1641. },
  1642. isCommentOnly() {
  1643. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  1644. return (
  1645. !currentBoard.hasAdmin(this.userId) &&
  1646. currentBoard.hasCommentOnly(this.userId)
  1647. );
  1648. },
  1649. isWorker() {
  1650. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  1651. return (
  1652. !currentBoard.hasAdmin(this.userId) && currentBoard.hasWorker(this.userId)
  1653. );
  1654. },
  1655. isLastAdmin() {
  1656. const currentBoard = Boards.findOne(Session.get('currentBoard'));
  1657. return (
  1658. currentBoard.hasAdmin(this.userId) && currentBoard.activeAdmins() === 1
  1659. );
  1660. },
  1661. });