rulesHelper.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. var nodemailer = require('nodemailer');
  2. RulesHelper = {
  3. executeRules(activity) {
  4. const matchingRules = this.findMatchingRules(activity);
  5. for (let i = 0; i < matchingRules.length; i++) {
  6. const action = matchingRules[i].getAction();
  7. if (action !== undefined) {
  8. this.performAction(activity, action);
  9. }
  10. }
  11. },
  12. findMatchingRules(activity) {
  13. const activityType = activity.activityType;
  14. if (TriggersDef[activityType] === undefined) {
  15. return [];
  16. }
  17. const matchingFields = TriggersDef[activityType].matchingFields;
  18. const matchingMap = this.buildMatchingFieldsMap(activity, matchingFields);
  19. const matchingTriggers = Triggers.find(matchingMap);
  20. const matchingRules = [];
  21. matchingTriggers.forEach(function(trigger) {
  22. const rule = trigger.getRule();
  23. // Check that for some unknown reason there are some leftover triggers
  24. // not connected to any rules
  25. if (rule !== undefined) {
  26. matchingRules.push(trigger.getRule());
  27. }
  28. });
  29. return matchingRules;
  30. },
  31. buildMatchingFieldsMap(activity, matchingFields) {
  32. const matchingMap = { activityType: activity.activityType };
  33. matchingFields.forEach(field => {
  34. // Creating a matching map with the actual field of the activity
  35. // and with the wildcard (for example: trigger when a card is added
  36. // in any [*] board
  37. let value = activity[field];
  38. if (field === 'oldListName') {
  39. const oldList = Lists.findOne({ _id: activity.oldListId });
  40. if (oldList) {
  41. value = oldList.title;
  42. }
  43. } else if (field === 'oldSwimlaneName') {
  44. const oldSwimlane = Swimlanes.findOne({ _id: activity.oldSwimlaneId });
  45. if (oldSwimlane) {
  46. value = oldSwimlane.title;
  47. }
  48. }
  49. matchingMap[field] = {
  50. $in: [value, '*'],
  51. };
  52. });
  53. return matchingMap;
  54. },
  55. performAction(activity, action) {
  56. const card = Cards.findOne({ _id: activity.cardId });
  57. const boardId = activity.boardId;
  58. if (
  59. action.actionType === 'moveCardToTop' ||
  60. action.actionType === 'moveCardToBottom'
  61. ) {
  62. let list;
  63. let listId;
  64. if (action.listName === '*') {
  65. list = card.list();
  66. if (boardId !== action.boardId) {
  67. list = Lists.findOne({ title: list.title, boardId: action.boardId });
  68. }
  69. } else {
  70. list = Lists.findOne({
  71. title: action.listName,
  72. boardId: action.boardId,
  73. });
  74. }
  75. if (list === undefined) {
  76. listId = '';
  77. } else {
  78. listId = list._id;
  79. }
  80. let swimlane;
  81. let swimlaneId;
  82. if (action.swimlaneName === '*') {
  83. swimlane = Swimlanes.findOne(card.swimlaneId);
  84. if (boardId !== action.boardId) {
  85. swimlane = Swimlanes.findOne({
  86. title: swimlane.title,
  87. boardId: action.boardId,
  88. });
  89. }
  90. } else {
  91. swimlane = Swimlanes.findOne({
  92. title: action.swimlaneName,
  93. boardId: action.boardId,
  94. });
  95. }
  96. if (swimlane === undefined) {
  97. swimlaneId = Swimlanes.findOne({
  98. title: 'Default',
  99. boardId: action.boardId,
  100. })._id;
  101. } else {
  102. swimlaneId = swimlane._id;
  103. }
  104. if (action.actionType === 'moveCardToTop') {
  105. const minOrder = _.min(
  106. list.cardsUnfiltered(swimlaneId).map(c => c.sort),
  107. );
  108. card.move(action.boardId, swimlaneId, listId, minOrder - 1);
  109. } else {
  110. const maxOrder = _.max(
  111. list.cardsUnfiltered(swimlaneId).map(c => c.sort),
  112. );
  113. card.move(action.boardId, swimlaneId, listId, maxOrder + 1);
  114. }
  115. }
  116. if (action.actionType === 'sendEmail') {
  117. const to = action.emailTo;
  118. const text = action.emailMsg || '';
  119. const subject = action.emailSubject || '';
  120. try {
  121. if (process.env.MAIL_SERVICE !== '') {
  122. let transporter = nodemailer.createTransport({
  123. service: process.env.MAIL_SERVICE,
  124. auth: {
  125. user: process.env.MAIL_SERVICE_USER,
  126. pass: process.env.MAIL_SERVICE_PASSWORD
  127. },
  128. })
  129. let info = transporter.sendMail({
  130. to,
  131. from: Accounts.emailTemplates.from,
  132. subject,
  133. text,
  134. })
  135. } else {
  136. Email.send({
  137. to,
  138. from: Accounts.emailTemplates.from,
  139. subject,
  140. text,
  141. });
  142. }
  143. } catch (e) {
  144. // eslint-disable-next-line no-console
  145. console.error(e);
  146. return;
  147. }
  148. }
  149. if (action.actionType === 'setDate') {
  150. try {
  151. const currentDateTime = new Date();
  152. switch (action.dateField) {
  153. case 'startAt': {
  154. const resStart = card.getStart();
  155. if (typeof resStart === 'undefined') {
  156. card.setStart(currentDateTime);
  157. }
  158. break;
  159. }
  160. case 'endAt': {
  161. const resEnd = card.getEnd();
  162. if (typeof resEnd === 'undefined') {
  163. card.setEnd(currentDateTime);
  164. }
  165. break;
  166. }
  167. case 'dueAt': {
  168. const resDue = card.getDue();
  169. if (typeof resDue === 'undefined') {
  170. card.setDue(currentDateTime);
  171. }
  172. break;
  173. }
  174. case 'receivedAt': {
  175. const resReceived = card.getReceived();
  176. if (typeof resReceived === 'undefined') {
  177. card.setReceived(currentDateTime);
  178. }
  179. break;
  180. }
  181. }
  182. } catch (e) {
  183. // eslint-disable-next-line no-console
  184. console.error(e);
  185. return;
  186. }
  187. }
  188. if (action.actionType === 'updateDate') {
  189. const currentDateTimeUpdate = new Date();
  190. switch (action.dateField) {
  191. case 'startAt': {
  192. card.setStart(currentDateTimeUpdate);
  193. break;
  194. }
  195. case 'endAt': {
  196. card.setEnd(currentDateTimeUpdate);
  197. break;
  198. }
  199. case 'dueAt': {
  200. card.setDue(currentDateTimeUpdate);
  201. break;
  202. }
  203. case 'receivedAt': {
  204. card.setReceived(currentDateTimeUpdate);
  205. break;
  206. }
  207. }
  208. }
  209. if (action.actionType === 'removeDate') {
  210. switch (action.dateField) {
  211. case 'startAt': {
  212. card.unsetStart();
  213. break;
  214. }
  215. case 'endAt': {
  216. card.unsetEnd();
  217. break;
  218. }
  219. case 'dueAt': {
  220. card.unsetDue();
  221. break;
  222. }
  223. case 'receivedAt': {
  224. card.unsetReceived();
  225. break;
  226. }
  227. }
  228. }
  229. if (action.actionType === 'archive') {
  230. card.archive();
  231. }
  232. if (action.actionType === 'unarchive') {
  233. card.restore();
  234. }
  235. if (action.actionType === 'setColor') {
  236. card.setColor(action.selectedColor);
  237. }
  238. if (action.actionType === 'addLabel') {
  239. card.addLabel(action.labelId);
  240. }
  241. if (action.actionType === 'removeLabel') {
  242. card.removeLabel(action.labelId);
  243. }
  244. if (action.actionType === 'addMember') {
  245. const memberId = Users.findOne({ username: action.username })._id;
  246. card.assignMember(memberId);
  247. }
  248. if (action.actionType === 'removeMember') {
  249. if (action.username === '*') {
  250. const members = card.members;
  251. for (let i = 0; i < members.length; i++) {
  252. card.unassignMember(members[i]);
  253. }
  254. } else {
  255. const memberId = Users.findOne({ username: action.username })._id;
  256. card.unassignMember(memberId);
  257. }
  258. }
  259. if (action.actionType === 'checkAll') {
  260. const checkList = Checklists.findOne({
  261. title: action.checklistName,
  262. cardId: card._id,
  263. });
  264. checkList.checkAllItems();
  265. }
  266. if (action.actionType === 'uncheckAll') {
  267. const checkList = Checklists.findOne({
  268. title: action.checklistName,
  269. cardId: card._id,
  270. });
  271. checkList.uncheckAllItems();
  272. }
  273. if (action.actionType === 'checkItem') {
  274. const checkList = Checklists.findOne({
  275. title: action.checklistName,
  276. cardId: card._id,
  277. });
  278. const checkItem = ChecklistItems.findOne({
  279. title: action.checkItemName,
  280. checkListId: checkList._id,
  281. });
  282. checkItem.check();
  283. }
  284. if (action.actionType === 'uncheckItem') {
  285. const checkList = Checklists.findOne({
  286. title: action.checklistName,
  287. cardId: card._id,
  288. });
  289. const checkItem = ChecklistItems.findOne({
  290. title: action.checkItemName,
  291. checkListId: checkList._id,
  292. });
  293. checkItem.uncheck();
  294. }
  295. if (action.actionType === 'addChecklist') {
  296. Checklists.insert({
  297. title: action.checklistName,
  298. cardId: card._id,
  299. sort: 0,
  300. });
  301. }
  302. if (action.actionType === 'removeChecklist') {
  303. Checklists.remove({
  304. title: action.checklistName,
  305. cardId: card._id,
  306. sort: 0,
  307. });
  308. }
  309. if (action.actionType === 'addSwimlane') {
  310. Swimlanes.insert({
  311. title: action.swimlaneName,
  312. boardId,
  313. sort: 0,
  314. });
  315. }
  316. if (action.actionType === 'addChecklistWithItems') {
  317. const checkListId = Checklists.insert({
  318. title: action.checklistName,
  319. cardId: card._id,
  320. sort: 0,
  321. });
  322. const itemsArray = action.checklistItems.split(',');
  323. const checkList = Checklists.findOne({ _id: checkListId });
  324. for (let i = 0; i < itemsArray.length; i++) {
  325. ChecklistItems.insert({
  326. title: itemsArray[i],
  327. checklistId: checkListId,
  328. cardId: card._id,
  329. sort: checkList.itemCount(),
  330. });
  331. }
  332. }
  333. if (action.actionType === 'createCard') {
  334. const list = Lists.findOne({ title: action.listName, boardId });
  335. let listId = '';
  336. let swimlaneId = '';
  337. const swimlane = Swimlanes.findOne({
  338. title: action.swimlaneName,
  339. boardId,
  340. });
  341. if (list === undefined) {
  342. listId = '';
  343. } else {
  344. listId = list._id;
  345. }
  346. if (swimlane === undefined) {
  347. swimlaneId = Swimlanes.findOne({ title: 'Default', boardId })._id;
  348. } else {
  349. swimlaneId = swimlane._id;
  350. }
  351. Cards.insert({
  352. title: action.cardName,
  353. listId,
  354. swimlaneId,
  355. sort: 0,
  356. boardId,
  357. });
  358. }
  359. },
  360. };