You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

215 lines
5.5 KiB

  1. // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  2. // MIT License. See license.txt
  3. wn.provide("wn.views.calendar");
  4. wn.provide("wn.views.calendars");
  5. wn.views.CalendarFactory = wn.views.Factory.extend({
  6. make: function(route) {
  7. var me = this;
  8. wn.model.with_doctype(route[1], function() {
  9. var options = {
  10. doctype: route[1],
  11. page: me.make_page()
  12. };
  13. $.extend(options, wn.views.calendar[route[1]] || {});
  14. wn.views.calendars[route[1]] = new wn.views.Calendar(options);
  15. });
  16. }
  17. });
  18. wn.views.Calendar = Class.extend({
  19. init: function(options) {
  20. $.extend(this, options);
  21. wn.require('assets/webnotes/js/lib/fullcalendar/fullcalendar.css');
  22. wn.require('assets/webnotes/js/lib/fullcalendar/fullcalendar.js');
  23. this.make_page();
  24. this.setup_options();
  25. this.make();
  26. },
  27. make_page: function() {
  28. var module = locals.DocType[this.doctype].module;
  29. this.page.appframe.set_title(wn._("Calendar") + " - " + wn._(this.doctype));
  30. this.page.appframe.add_module_icon(module==="Core" ? "Calendar" : module)
  31. this.page.appframe.set_views_for(this.doctype, "calendar");
  32. this.page.appframe.add_button("New", function() {
  33. var doc = wn.model.get_new_doc(me.doctype);
  34. wn.set_route("Form", me.doctype, doc.name);
  35. }, "icon-plus");
  36. var me = this;
  37. $(this.page).on("show", function() {
  38. me.$cal.fullCalendar("refetchEvents");
  39. })
  40. },
  41. make: function() {
  42. var me = this;
  43. this.$wrapper = $(this.page).find(".layout-main");
  44. this.$cal = $("<div>").appendTo(this.$wrapper);
  45. wn.utils.set_footnote(this, this.$wrapper, wn._("Select or drag across time slots to create a new event."));
  46. //
  47. // $('<div class="help"></div>')
  48. // .html(wn._("Select dates to create a new ") + wn._(me.doctype))
  49. // .appendTo(this.$wrapper);
  50. this.$cal.fullCalendar(this.cal_options);
  51. },
  52. field_map: {
  53. "id": "name",
  54. "start": "start",
  55. "end": "end",
  56. "allDay": "all_day",
  57. },
  58. styles: {
  59. "standard": {
  60. "color": "#999"
  61. },
  62. "important": {
  63. "color": "#b94a48"
  64. },
  65. "warning": {
  66. "color": "#f89406"
  67. },
  68. "success": {
  69. "color": "#468847"
  70. },
  71. "info": {
  72. "color": "#3a87ad"
  73. },
  74. "inverse": {
  75. "color": "#333333"
  76. }
  77. },
  78. setup_options: function() {
  79. var me = this;
  80. this.cal_options = {
  81. header: {
  82. left: 'prev,next today',
  83. center: 'title',
  84. right: 'month,agendaWeek,agendaDay'
  85. },
  86. editable: true,
  87. selectable: true,
  88. selectHelper: true,
  89. events: function(start, end, callback) {
  90. return wn.call({
  91. method: me.get_events_method || "webnotes.widgets.calendar.get_events",
  92. type: "GET",
  93. args: me.get_args(start, end),
  94. callback: function(r) {
  95. var events = r.message;
  96. me.prepare_events(events);
  97. callback(events);
  98. }
  99. })
  100. },
  101. eventClick: function(event, jsEvent, view) {
  102. // edit event description or delete
  103. var doctype = event.doctype || me.doctype;
  104. if(wn.model.can_read(doctype)) {
  105. wn.set_route("Form", doctype, event.name);
  106. }
  107. },
  108. eventDrop: function(event, dayDelta, minuteDelta, allDay, revertFunc) {
  109. me.update_event(event, revertFunc);
  110. },
  111. eventResize: function(event, dayDelta, minuteDelta, allDay, revertFunc) {
  112. me.update_event(event, revertFunc);
  113. },
  114. select: function(startDate, endDate, allDay, jsEvent, view) {
  115. if(jsEvent.day_clicked && view.name=="month")
  116. return;
  117. var event = wn.model.get_new_doc(me.doctype);
  118. event[me.field_map.start] = wn.datetime.get_datetime_as_string(startDate);
  119. if(me.field_map.end)
  120. event[me.field_map.end] = wn.datetime.get_datetime_as_string(endDate);
  121. if(me.field_map.allDay)
  122. event[me.field_map.allDay] = allDay ? 1 : 0;
  123. wn.set_route("Form", me.doctype, event.name);
  124. },
  125. dayClick: function(date, allDay, jsEvent, view) {
  126. jsEvent.day_clicked = true;
  127. return false;
  128. }
  129. };
  130. if(this.options) {
  131. $.extend(this.cal_options, this.options);
  132. }
  133. },
  134. get_args: function(start, end) {
  135. return {
  136. doctype: this.doctype,
  137. start: wn.datetime.get_datetime_as_string(start),
  138. end: wn.datetime.get_datetime_as_string(end)
  139. }
  140. },
  141. prepare_events: function(events) {
  142. var me = this;
  143. $.each(events, function(i, d) {
  144. d.id = d.name;
  145. d.editable = wn.model.can_write(d.doctype || me.doctype);
  146. // do not allow submitted/cancelled events to be moved / extended
  147. if(d.docstatus && d.docstatus > 0) {
  148. d.editable = false;
  149. }
  150. $.each(me.field_map, function(target, source) {
  151. d[target] = d[source];
  152. });
  153. if(!me.field_map.allDay)
  154. d.allDay = 1;
  155. if(d.status) {
  156. if(me.style_map) {
  157. $.extend(d, me.styles[me.style_map[d.status]] || {});
  158. } else {
  159. $.extend(d, me.styles[wn.utils.guess_style(d.status, "standard")]);
  160. }
  161. } else {
  162. $.extend(d, me.styles["standard"]);
  163. }
  164. })
  165. },
  166. update_event: function(event, revertFunc) {
  167. var me = this;
  168. wn.model.remove_from_locals(me.doctype, event.name);
  169. return wn.call({
  170. method: me.update_event_method || "webnotes.widgets.calendar.update_event",
  171. args: me.get_update_args(event),
  172. callback: function(r) {
  173. if(r.exc) {
  174. show_alert("Unable to update event.")
  175. revertFunc();
  176. }
  177. }
  178. });
  179. },
  180. get_update_args: function(event) {
  181. var args = {
  182. name: event[this.field_map.id]
  183. };
  184. args[this.field_map.start]
  185. = wn.datetime.get_datetime_as_string(event.start);
  186. if(this.field_map.end)
  187. args[this.field_map.end] = wn.datetime.get_datetime_as_string(event.end);
  188. if(this.field_map.allDay)
  189. args[this.field_map.allDay] = event.allDay ? 1 : 0;
  190. args.doctype = event.doctype || this.doctype;
  191. return { args: args, field_map: this.field_map };
  192. }
  193. })