cardDate.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. import { DatePicker } from '/client/lib/datepicker';
  2. Template.dateBadge.helpers({
  3. canModifyCard() {
  4. return (
  5. Meteor.user() &&
  6. Meteor.user().isBoardMember() &&
  7. !Meteor.user().isCommentOnly() &&
  8. !Meteor.user().isWorker()
  9. );
  10. },
  11. });
  12. // editCardReceivedDatePopup
  13. (class extends DatePicker {
  14. onCreated() {
  15. super.onCreated(moment().format('YYYY-MM-DD HH:mm'));
  16. this.data().getReceived() &&
  17. this.date.set(moment(this.data().getReceived()));
  18. }
  19. _storeDate(date) {
  20. this.card.setReceived(date);
  21. }
  22. _deleteDate() {
  23. this.card.unsetReceived();
  24. }
  25. }.register('editCardReceivedDatePopup'));
  26. // editCardStartDatePopup
  27. (class extends DatePicker {
  28. onCreated() {
  29. super.onCreated(moment().format('YYYY-MM-DD HH:mm'));
  30. this.data().getStart() && this.date.set(moment(this.data().getStart()));
  31. }
  32. onRendered() {
  33. super.onRendered();
  34. if (moment.isDate(this.card.getReceived())) {
  35. this.$('.js-datepicker').datepicker(
  36. 'setStartDate',
  37. this.card.getReceived(),
  38. );
  39. }
  40. }
  41. _storeDate(date) {
  42. this.card.setStart(date);
  43. }
  44. _deleteDate() {
  45. this.card.unsetStart();
  46. }
  47. }.register('editCardStartDatePopup'));
  48. // editCardDueDatePopup
  49. (class extends DatePicker {
  50. onCreated() {
  51. super.onCreated('1970-01-01 17:00:00');
  52. this.data().getDue() && this.date.set(moment(this.data().getDue()));
  53. }
  54. onRendered() {
  55. super.onRendered();
  56. if (moment.isDate(this.card.getStart())) {
  57. this.$('.js-datepicker').datepicker('setStartDate', this.card.getStart());
  58. }
  59. }
  60. _storeDate(date) {
  61. this.card.setDue(date);
  62. }
  63. _deleteDate() {
  64. this.card.unsetDue();
  65. }
  66. }.register('editCardDueDatePopup'));
  67. // editCardEndDatePopup
  68. (class extends DatePicker {
  69. onCreated() {
  70. super.onCreated(moment().format('YYYY-MM-DD HH:mm'));
  71. this.data().getEnd() && this.date.set(moment(this.data().getEnd()));
  72. }
  73. onRendered() {
  74. super.onRendered();
  75. if (moment.isDate(this.card.getStart())) {
  76. this.$('.js-datepicker').datepicker('setStartDate', this.card.getStart());
  77. }
  78. }
  79. _storeDate(date) {
  80. this.card.setEnd(date);
  81. }
  82. _deleteDate() {
  83. this.card.unsetEnd();
  84. }
  85. }.register('editCardEndDatePopup'));
  86. // Display received, start, due & end dates
  87. const CardDate = BlazeComponent.extendComponent({
  88. template() {
  89. return 'dateBadge';
  90. },
  91. onCreated() {
  92. const self = this;
  93. self.date = ReactiveVar();
  94. self.now = ReactiveVar(moment());
  95. window.setInterval(() => {
  96. self.now.set(moment());
  97. }, 60000);
  98. },
  99. showWeek() {
  100. return this.date.get().week().toString();
  101. },
  102. showDate() {
  103. // this will start working once mquandalle:moment
  104. // is updated to at least moment.js 2.10.5
  105. // until then, the date is displayed in the "L" format
  106. return this.date.get().calendar(null, {
  107. sameElse: 'llll',
  108. });
  109. },
  110. showISODate() {
  111. return this.date.get().toISOString();
  112. },
  113. });
  114. class CardReceivedDate extends CardDate {
  115. onCreated() {
  116. super.onCreated();
  117. const self = this;
  118. self.autorun(() => {
  119. self.date.set(moment(self.data().getReceived()));
  120. });
  121. }
  122. classes() {
  123. let classes = 'received-date ';
  124. const dueAt = this.data().getDue();
  125. const endAt = this.data().getEnd();
  126. const startAt = this.data().getStart();
  127. const theDate = this.date.get();
  128. // if dueAt, endAt and startAt exist & are > receivedAt, receivedAt doesn't need to be flagged
  129. if (
  130. (startAt && theDate.isAfter(startAt)) ||
  131. (endAt && theDate.isAfter(endAt)) ||
  132. (dueAt && theDate.isAfter(dueAt))
  133. )
  134. classes += 'long-overdue';
  135. else classes += 'current';
  136. return classes;
  137. }
  138. showTitle() {
  139. return `${TAPi18n.__('card-received-on')} ${this.date
  140. .get()
  141. .format('LLLL')}`;
  142. }
  143. events() {
  144. return super.events().concat({
  145. 'click .js-edit-date': Popup.open('editCardReceivedDate'),
  146. });
  147. }
  148. }
  149. CardReceivedDate.register('cardReceivedDate');
  150. class CardStartDate extends CardDate {
  151. onCreated() {
  152. super.onCreated();
  153. const self = this;
  154. self.autorun(() => {
  155. self.date.set(moment(self.data().getStart()));
  156. });
  157. }
  158. classes() {
  159. let classes = 'start-date' + ' ';
  160. const dueAt = this.data().getDue();
  161. const endAt = this.data().getEnd();
  162. const theDate = this.date.get();
  163. const now = this.now.get();
  164. // if dueAt or endAt exist & are > startAt, startAt doesn't need to be flagged
  165. if ((endAt && theDate.isAfter(endAt)) || (dueAt && theDate.isAfter(dueAt)))
  166. classes += 'long-overdue';
  167. else if (theDate.isAfter(now)) classes += '';
  168. else classes += 'current';
  169. return classes;
  170. }
  171. showTitle() {
  172. return `${TAPi18n.__('card-start-on')} ${this.date.get().format('LLLL')}`;
  173. }
  174. events() {
  175. return super.events().concat({
  176. 'click .js-edit-date': Popup.open('editCardStartDate'),
  177. });
  178. }
  179. }
  180. CardStartDate.register('cardStartDate');
  181. class CardDueDate extends CardDate {
  182. onCreated() {
  183. super.onCreated();
  184. const self = this;
  185. self.autorun(() => {
  186. self.date.set(moment(self.data().getDue()));
  187. });
  188. }
  189. classes() {
  190. let classes = 'due-date' + ' ';
  191. const endAt = this.data().getEnd();
  192. const theDate = this.date.get();
  193. const now = this.now.get();
  194. // if the due date is after the end date, green - done early
  195. if (endAt && theDate.isAfter(endAt)) classes += 'current';
  196. // if there is an end date, don't need to flag the due date
  197. else if (endAt) classes += '';
  198. else if (now.diff(theDate, 'days') >= 2) classes += 'long-overdue';
  199. else if (now.diff(theDate, 'minute') >= 0) classes += 'due';
  200. else if (now.diff(theDate, 'days') >= -1) classes += 'almost-due';
  201. return classes;
  202. }
  203. showTitle() {
  204. return `${TAPi18n.__('card-due-on')} ${this.date.get().format('LLLL')}`;
  205. }
  206. events() {
  207. return super.events().concat({
  208. 'click .js-edit-date': Popup.open('editCardDueDate'),
  209. });
  210. }
  211. }
  212. CardDueDate.register('cardDueDate');
  213. class CardEndDate extends CardDate {
  214. onCreated() {
  215. super.onCreated();
  216. const self = this;
  217. self.autorun(() => {
  218. self.date.set(moment(self.data().getEnd()));
  219. });
  220. }
  221. classes() {
  222. let classes = 'end-date' + ' ';
  223. const dueAt = this.data().getDue();
  224. const theDate = this.date.get();
  225. if (!dueAt) classes += '';
  226. else if (theDate.isBefore(dueAt)) classes += 'current';
  227. else if (theDate.isAfter(dueAt)) classes += 'due';
  228. return classes;
  229. }
  230. showTitle() {
  231. return `${TAPi18n.__('card-end-on')} ${this.date.get().format('LLLL')}`;
  232. }
  233. events() {
  234. return super.events().concat({
  235. 'click .js-edit-date': Popup.open('editCardEndDate'),
  236. });
  237. }
  238. }
  239. CardEndDate.register('cardEndDate');
  240. class CardCustomFieldDate extends CardDate {
  241. template() {
  242. return 'dateCustomField';
  243. }
  244. onCreated() {
  245. super.onCreated();
  246. const self = this;
  247. self.autorun(() => {
  248. self.date.set(moment(self.data().value));
  249. });
  250. }
  251. showWeek() {
  252. return this.date.get().week().toString();
  253. }
  254. showDate() {
  255. // this will start working once mquandalle:moment
  256. // is updated to at least moment.js 2.10.5
  257. // until then, the date is displayed in the "L" format
  258. return this.date.get().calendar(null, {
  259. sameElse: 'llll',
  260. });
  261. }
  262. showTitle() {
  263. return `${this.date.get().format('LLLL')}`;
  264. }
  265. classes() {
  266. return 'customfield-date';
  267. }
  268. events() {
  269. return [];
  270. }
  271. }
  272. CardCustomFieldDate.register('cardCustomFieldDate');
  273. (class extends CardReceivedDate {
  274. showDate() {
  275. return this.date.get().format('l');
  276. }
  277. }.register('minicardReceivedDate'));
  278. (class extends CardStartDate {
  279. showDate() {
  280. return this.date.get().format('l');
  281. }
  282. }.register('minicardStartDate'));
  283. (class extends CardDueDate {
  284. showDate() {
  285. return this.date.get().format('l');
  286. }
  287. }.register('minicardDueDate'));
  288. (class extends CardEndDate {
  289. showDate() {
  290. return this.date.get().format('l');
  291. }
  292. }.register('minicardEndDate'));
  293. (class extends CardCustomFieldDate {
  294. showDate() {
  295. return this.date.get().format('l');
  296. }
  297. }.register('minicardCustomFieldDate'));
  298. class VoteEndDate extends CardDate {
  299. onCreated() {
  300. super.onCreated();
  301. const self = this;
  302. self.autorun(() => {
  303. self.date.set(moment(self.data().getVoteEnd()));
  304. });
  305. }
  306. classes() {
  307. const classes = 'end-date' + ' ';
  308. return classes;
  309. }
  310. showDate() {
  311. return this.date.get().format('l LT');
  312. }
  313. showTitle() {
  314. return `${TAPi18n.__('card-end-on')} ${this.date.get().format('LLLL')}`;
  315. }
  316. events() {
  317. return super.events().concat({
  318. 'click .js-edit-date': Popup.open('editVoteEndDate'),
  319. });
  320. }
  321. }
  322. VoteEndDate.register('voteEndDate');
  323. class PokerEndDate extends CardDate {
  324. onCreated() {
  325. super.onCreated();
  326. const self = this;
  327. self.autorun(() => {
  328. self.date.set(moment(self.data().getPokerEnd()));
  329. });
  330. }
  331. classes() {
  332. const classes = 'end-date' + ' ';
  333. return classes;
  334. }
  335. showDate() {
  336. return this.date.get().format('l LT');
  337. }
  338. showTitle() {
  339. return `${TAPi18n.__('card-end-on')} ${this.date.get().format('LLLL')}`;
  340. }
  341. events() {
  342. return super.events().concat({
  343. 'click .js-edit-date': Popup.open('editPokerEndDate'),
  344. });
  345. }
  346. }
  347. PokerEndDate.register('pokerEndDate');