lists.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. Lists = new Mongo.Collection('lists');
  2. Lists.attachSchema(new SimpleSchema({
  3. title: {
  4. type: String,
  5. },
  6. archived: {
  7. type: Boolean,
  8. autoValue() { // eslint-disable-line consistent-return
  9. if (this.isInsert && !this.isSet) {
  10. return false;
  11. }
  12. },
  13. },
  14. boardId: {
  15. type: String,
  16. },
  17. createdAt: {
  18. type: Date,
  19. autoValue() { // eslint-disable-line consistent-return
  20. if (this.isInsert) {
  21. return new Date();
  22. } else {
  23. this.unset();
  24. }
  25. },
  26. },
  27. sort: {
  28. type: Number,
  29. decimal: true,
  30. // XXX We should probably provide a default
  31. optional: true,
  32. },
  33. updatedAt: {
  34. type: Date,
  35. optional: true,
  36. autoValue() { // eslint-disable-line consistent-return
  37. if (this.isUpdate) {
  38. return new Date();
  39. } else {
  40. this.unset();
  41. }
  42. },
  43. },
  44. wipLimit: {
  45. type: Object,
  46. optional: true,
  47. },
  48. 'wipLimit.value': {
  49. type: Number,
  50. decimal: false,
  51. autoValue() {
  52. if(this.isInsert){
  53. return 0;
  54. }
  55. return this.value;
  56. },
  57. optional: true,
  58. },
  59. 'wipLimit.enabled':{
  60. type: Boolean,
  61. autoValue() {
  62. if(this.isInsert){
  63. return false;
  64. }
  65. return this.value;
  66. },
  67. optional: true,
  68. },
  69. }));
  70. Lists.allow({
  71. insert(userId, doc) {
  72. return allowIsBoardMemberNonComment(userId, Boards.findOne(doc.boardId));
  73. },
  74. update(userId, doc) {
  75. return allowIsBoardMemberNonComment(userId, Boards.findOne(doc.boardId));
  76. },
  77. remove(userId, doc) {
  78. return allowIsBoardMemberNonComment(userId, Boards.findOne(doc.boardId));
  79. },
  80. fetch: ['boardId'],
  81. });
  82. Lists.helpers({
  83. cards() {
  84. return Cards.find(Filter.mongoSelector({
  85. listId: this._id,
  86. archived: false,
  87. }), { sort: ['sort'] });
  88. },
  89. allCards() {
  90. return Cards.find({ listId: this._id });
  91. },
  92. board() {
  93. return Boards.findOne(this.boardId);
  94. },
  95. getWipLimit(option){
  96. const list = Lists.findOne({ _id: this._id });
  97. if(!list.wipLimit) { // Necessary check to avoid exceptions for the case where the doc doesn't have the wipLimit field yet set
  98. return 0;
  99. } else if(!option) {
  100. return list.wipLimit;
  101. } else {
  102. return list.wipLimit[option] ? list.wipLimit[option] : 0; // Necessary check to avoid exceptions for the case where the doc doesn't have the wipLimit field yet set
  103. }
  104. },
  105. });
  106. Lists.mutations({
  107. rename(title) {
  108. return { $set: { title } };
  109. },
  110. archive() {
  111. return { $set: { archived: true } };
  112. },
  113. restore() {
  114. return { $set: { archived: false } };
  115. },
  116. toggleWipLimit(toggle) {
  117. return { $set: { 'wipLimit.enabled': toggle } };
  118. },
  119. setWipLimit(limit) {
  120. return { $set: { 'wipLimit.value': limit } };
  121. },
  122. });
  123. Meteor.methods({
  124. applyWipLimit(listId, limit){
  125. check(listId, String);
  126. check(limit, Number);
  127. Lists.findOne({ _id: listId }).setWipLimit(limit);
  128. },
  129. enableWipLimit(listId) {
  130. check(listId, String);
  131. const list = Lists.findOne({ _id: listId });
  132. if(list.getWipLimit()){ // Necessary check to avoid exceptions for the case where the doc doesn't have the wipLimit field yet set
  133. list.toggleWipLimit(!list.getWipLimit('enabled'));
  134. } else {
  135. list.toggleWipLimit(true); // First time toggle is always to 'true' because default is 'false'
  136. }
  137. },
  138. });
  139. Lists.hookOptions.after.update = { fetchPrevious: false };
  140. if (Meteor.isServer) {
  141. Meteor.startup(() => {
  142. Lists._collection._ensureIndex({ boardId: 1 });
  143. });
  144. Lists.after.insert((userId, doc) => {
  145. Activities.insert({
  146. userId,
  147. type: 'list',
  148. activityType: 'createList',
  149. boardId: doc.boardId,
  150. listId: doc._id,
  151. });
  152. });
  153. Lists.before.remove((userId, doc) => {
  154. Activities.insert({
  155. userId,
  156. type: 'list',
  157. activityType: 'removeList',
  158. boardId: doc.boardId,
  159. listId: doc._id,
  160. title: doc.title,
  161. });
  162. });
  163. Lists.after.update((userId, doc) => {
  164. if (doc.archived) {
  165. Activities.insert({
  166. userId,
  167. type: 'list',
  168. activityType: 'archivedList',
  169. listId: doc._id,
  170. boardId: doc.boardId,
  171. });
  172. }
  173. });
  174. }
  175. //LISTS REST API
  176. if (Meteor.isServer) {
  177. JsonRoutes.add('GET', '/api/boards/:boardId/lists', function (req, res, next) {
  178. const paramBoardId = req.params.boardId;
  179. Authentication.checkBoardAccess( req.userId, paramBoardId);
  180. JsonRoutes.sendResult(res, {
  181. code: 200,
  182. data: Lists.find({ boardId: paramBoardId, archived: false }).map(function (doc) {
  183. return {
  184. _id: doc._id,
  185. title: doc.title,
  186. };
  187. }),
  188. });
  189. });
  190. JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId', function (req, res, next) {
  191. const paramBoardId = req.params.boardId;
  192. const paramListId = req.params.listId;
  193. Authentication.checkBoardAccess( req.userId, paramBoardId);
  194. JsonRoutes.sendResult(res, {
  195. code: 200,
  196. data: Lists.findOne({ _id: paramListId, boardId: paramBoardId, archived: false }),
  197. });
  198. });
  199. JsonRoutes.add('POST', '/api/boards/:boardId/lists', function (req, res, next) {
  200. Authentication.checkUserId( req.userId);
  201. const paramBoardId = req.params.boardId;
  202. const id = Lists.insert({
  203. title: req.body.title,
  204. boardId: paramBoardId,
  205. });
  206. JsonRoutes.sendResult(res, {
  207. code: 200,
  208. data: {
  209. _id: id,
  210. },
  211. });
  212. });
  213. JsonRoutes.add('DELETE', '/api/boards/:boardId/lists/:listId', function (req, res, next) {
  214. Authentication.checkUserId( req.userId);
  215. const paramBoardId = req.params.boardId;
  216. const paramListId = req.params.listId;
  217. Lists.remove({ _id: paramListId, boardId: paramBoardId });
  218. JsonRoutes.sendResult(res, {
  219. code: 200,
  220. data: {
  221. _id: paramListId,
  222. },
  223. });
  224. });
  225. }