1 /*---------------------------------------------------------
3 *---------------------------------------------------------*/
5 openerp.web_calendar = function(openerp) {
6 QWeb.add_template('/web_calendar/static/src/xml/web_calendar.xml');
7 openerp.web.views.add('calendar', 'openerp.web_calendar.CalendarView');
8 openerp.web_calendar.CalendarView = openerp.web.View.extend({
10 init: function(parent, element_id, dataset, view_id, options) {
11 this._super(parent, element_id);
12 this.set_default_options(options);
13 this.dataset = dataset;
14 this.model = dataset.model;
15 this.view_id = view_id;
16 this.domain = this.dataset.domain || [];
17 this.context = this.dataset.context || {};
18 this.has_been_loaded = $.Deferred();
19 this.creating_event_id = null;
20 this.dataset_events = [];
21 if (this.options.action_views_ids.form) {
22 this.form_dialog = new openerp.web_calendar.CalendarFormDialog(this, {}, this.options.action_views_ids.form, dataset);
23 this.form_dialog.start();
25 this.COLOR_PALETTE = ['#f57900', '#cc0000', '#d400a8', '#75507b', '#3465a4', '#73d216', '#c17d11', '#edd400',
26 '#fcaf3e', '#ef2929', '#ff00c9', '#ad7fa8', '#729fcf', '#8ae234', '#e9b96e', '#fce94f',
27 '#ff8e00', '#ff0000', '#b0008c', '#9000ff', '#0078ff', '#00ff00', '#e6ff00', '#ffff00',
28 '#905000', '#9b0000', '#840067', '#510090', '#0000c9', '#009b00', '#9abe00', '#ffc900' ];
32 this.rpc("/web/view/load", {"model": this.model, "view_id": this.view_id, "view_type":"calendar", 'toolbar': true}, this.on_loaded);
37 on_loaded: function(data) {
38 this.fields_view = data;
39 this.calendar_fields = {};
40 this.ids = this.dataset.ids;
41 this.color_values = [];
42 this.info_fields = [];
44 this.name = this.fields_view.name || this.fields_view.arch.attrs.string;
45 this.view_id = this.fields_view.view_id;
47 this.date_start = this.fields_view.arch.attrs.date_start;
48 this.date_delay = this.fields_view.arch.attrs.date_delay;
49 this.date_stop = this.fields_view.arch.attrs.date_stop;
51 this.colors = this.fields_view.arch.attrs.colors;
52 this.day_length = this.fields_view.arch.attrs.day_length || 8;
53 this.color_field = this.fields_view.arch.attrs.color;
54 this.fields = this.fields_view.fields;
57 this.calendar_fields.date_start = {'name': this.date_start, 'kind': this.fields[this.date_start].type};
59 if (this.date_delay) {
60 if (this.fields[this.date_delay].type != 'float') {
61 throw new Error("Calendar view has a 'date_delay' type != float");
63 this.calendar_fields.date_delay = {'name': this.date_delay, 'kind': this.fields[this.date_delay].type};
66 this.calendar_fields.date_stop = {'name': this.date_stop, 'kind': this.fields[this.date_stop].type};
68 if (!this.date_delay && !this.date_stop) {
69 throw new Error("Calendar view has none of the following attributes : 'date_stop', 'date_delay'");
72 for (var fld = 0; fld < this.fields_view.arch.children.length; fld++) {
73 this.info_fields.push(this.fields_view.arch.children[fld].attrs.name);
75 this.$element.html(QWeb.render("CalendarView", {"fields_view": this.fields_view}));
77 if (this.options.sidebar && this.options.sidebar_id) {
78 this.sidebar = new openerp.web.Sidebar(this, this.options.sidebar_id);
80 this.sidebar.navigator = new openerp.web_calendar.SidebarNavigator(this.sidebar, this.sidebar.add_section('navigator', "Navigator"), this);
81 this.sidebar.responsible = new openerp.web_calendar.SidebarResponsible(this.sidebar, this.sidebar.add_section('responsible', "Responsible"), this);
82 this.sidebar.add_toolbar(this.fields_view.toolbar);
83 this.set_common_sidebar_sections(this.sidebar);
84 this.sidebar.do_unfold();
85 this.sidebar.do_fold.add_last(this.refresh_scheduler);
86 this.sidebar.do_unfold.add_last(this.refresh_scheduler);
87 this.sidebar.do_toggle.add_last(this.refresh_scheduler);
90 this.init_scheduler();
91 this.has_been_loaded.resolve();
92 if (this.dataset.ids.length) {
93 this.dataset.read_ids(this.dataset.ids, _.keys(this.fields), this.on_events_loaded);
96 init_scheduler: function() {
99 if (this.fields[this.date_start]['type'] == 'time') {
100 scheduler.config.xml_date = "%H:%M:%S";
102 scheduler.config.xml_date = "%Y-%m-%d %H:%i";
104 scheduler.config.api_date = "%Y-%m-%d %H:%i";
105 scheduler.config.multi_day = true; //Multi day events are not rendered in daily and weekly views
106 scheduler.config.start_on_monday = true;
107 scheduler.config.scroll_hour = 8;
108 scheduler.config.drag_resize = true;
109 scheduler.config.drag_create = true;
111 // Initialize Sceduler
112 this.mode = this.mode || 'month';
113 scheduler.init('openerp_scheduler', null, this.mode);
115 scheduler.detachAllEvents();
116 scheduler.attachEvent('onEventAdded', this.do_create_event);
117 scheduler.attachEvent('onEventDeleted', this.do_delete_event);
118 scheduler.attachEvent('onEventChanged', this.do_save_event);
119 scheduler.attachEvent('onDblClick', this.do_edit_event);
120 scheduler.attachEvent('onBeforeLightbox', this.do_edit_event);
122 this.mini_calendar = scheduler.renderCalendar({
123 container: this.sidebar.navigator.element_id,
125 date: scheduler._date,
126 handler: function(date, calendar) {
127 scheduler.setCurrentView(date, 'day');
131 refresh_scheduler: function() {
132 scheduler.setCurrentView(scheduler._date);
134 refresh_minical: function() {
135 scheduler.updateCalendar(this.mini_calendar);
137 reload_event: function(id) {
138 this.dataset.read_ids([id], _.keys(this.fields), this.on_events_loaded);
140 get_color: function(key) {
141 if (this.color_map[key]) {
142 return this.color_map[key];
144 var index = _.keys(this.color_map).length % this.COLOR_PALETTE.length;
145 var color = this.COLOR_PALETTE[index];
146 this.color_map[key] = color;
149 on_events_loaded: function(events, fn_filter, no_filter_reload) {
152 //To parse Events we have to convert date Format
155 for (var e = 0; e < events.length; e++) {
157 if (!evt[this.date_start]) {
158 this.notification.warn("Start date is not defined for event :", evt['id']);
162 if (this.color_field) {
163 var filter = evt[this.color_field];
165 var filter_value = (typeof filter === 'object') ? filter[0] : filter;
166 if (typeof(fn_filter) === 'function' && !fn_filter(filter_value)) {
171 label: (typeof filter === 'object') ? filter[1] : filter,
172 color: this.get_color(filter_value)
174 if (!sidebar_items[filter_value]) {
175 sidebar_items[filter_value] = filter_item;
177 evt.color = filter_item.color;
178 evt.textColor = '#ffffff';
182 if (this.fields[this.date_start]['type'] == 'date') {
183 evt[this.date_start] = openerp.web.str_to_date(evt[this.date_start]).set({hour: 9}).toString('yyyy-MM-dd HH:mm:ss');
185 if (this.date_stop && evt[this.date_stop] && this.fields[this.date_stop]['type'] == 'date') {
186 evt[this.date_stop] = openerp.web.str_to_date(evt[this.date_stop]).set({hour: 17}).toString('yyyy-MM-dd HH:mm:ss');
188 res_events.push(this.convert_event(evt));
190 scheduler.parse(res_events, 'json');
191 this.refresh_scheduler();
192 this.refresh_minical();
193 if (!no_filter_reload) {
194 this.sidebar.responsible.on_events_loaded(sidebar_items);
197 convert_event: function(evt) {
198 var date_start = openerp.web.str_to_datetime(evt[this.date_start]),
199 date_stop = this.date_stop ? openerp.web.str_to_datetime(evt[this.date_stop]) : null,
200 date_delay = evt[this.date_delay] || null,
202 res_description = [];
204 if (this.info_fields) {
205 var fld = evt[this.info_fields[0]];
206 res_text = (typeof fld == 'object') ? fld[fld.length -1] : res_text = fld;
208 var sliced_info_fields = this.info_fields.slice(1);
209 for (var sl_fld in sliced_info_fields) {
210 var slc_fld = evt[sliced_info_fields[sl_fld]];
211 if (typeof slc_fld == 'object') {
212 res_description.push(slc_fld[slc_fld.length - 1]);
213 } else if (slc_fld) {
214 res_description.push(slc_fld);
218 if (!date_stop && date_delay) {
219 date_stop = date_start.clone().addHours(date_delay);
222 'start_date': date_start.toString('yyyy-MM-dd HH:mm:ss'),
223 'end_date': date_stop.toString('yyyy-MM-dd HH:mm:ss'),
226 'title': res_description.join()
232 r.textColor = evt.textColor;
236 do_create_event: function(event_id, event_obj) {
238 data = this.get_event_data(event_obj);
239 this.dataset.create(data, function(r) {
240 var id = parseInt(r.result, 10);
241 self.dataset.ids.push(id);
242 scheduler.changeEventId(event_id, id);
243 self.refresh_minical();
244 }, function(r, event) {
245 self.creating_event_id = event_id;
246 self.form_dialog.form.on_record_loaded(data);
247 self.form_dialog.open();
248 event.preventDefault();
251 do_save_event: function(event_id, event_obj) {
253 data = this.get_event_data(event_obj);
254 this.dataset.write(parseInt(event_id, 10), data, {}, function() {
255 self.refresh_minical();
258 do_delete_event: function(event_id, event_obj) {
260 // dhtmlx sends this event even when it does not exist in openerp.
261 // Eg: use cancel in dhtmlx new event dialog
262 if (_.indexOf(this.dataset.ids, parseInt(event_id, 10)) > -1) {
263 this.dataset.unlink(parseInt(event_id, 10), function() {
264 self.refresh_minical();
268 do_edit_event: function(event_id) {
269 event_id = parseInt(event_id, 10);
270 var index = _.indexOf(this.dataset.ids, event_id);
272 this.dataset.index = index;
273 this.form_dialog.form.do_show();
274 this.form_dialog.open();
279 get_event_data: function(event_obj) {
283 data[this.date_start] = openerp.web.datetime_to_str(event_obj.start_date);
284 if (this.date_stop) {
285 data[this.date_stop] = openerp.web.datetime_to_str(event_obj.end_date);
287 if (this.date_delay) {
288 var diff_seconds = Math.round((event_obj.end_date.getTime() - event_obj.start_date.getTime()) / 1000);
289 data[this.date_delay] = diff_seconds / 3600;
293 do_search: function(domains, contexts, groupbys) {
295 scheduler.clearAll();
296 $.when(this.has_been_loaded).then(function() {
297 self.rpc('/web/session/eval_domain_and_context', {
300 group_by_seq: groupbys
301 }, function (results) {
302 // TODO: handle non-empty results.group_by with read_group
303 self.dataset.context = self.context = results.context;
304 self.dataset.domain = self.domain = results.domain;
305 self.dataset.read_slice(_.keys(self.fields), {
308 }, function(events) {
309 self.dataset_events = events;
310 self.on_events_loaded(events);
316 do_show: function () {
318 $.when(this.has_been_loaded).then(function() {
319 self.$element.show();
321 self.sidebar.$element.show();
325 do_hide: function () {
326 this.$element.hide();
328 this.sidebar.$element.hide();
331 get_selected_ids: function() {
332 // no way to select a record anyway
337 openerp.web_calendar.CalendarFormDialog = openerp.web.Dialog.extend({
338 init: function(view, options, view_id, dataset) {
339 this._super(view, options);
340 this.dataset = dataset;
341 this.view_id = view_id;
346 this.form = new openerp.web.FormView(this, this.element_id, this.dataset, this.view_id, {
351 this.form.on_created.add_last(this.on_form_dialog_saved);
352 this.form.on_saved.add_last(this.on_form_dialog_saved);
354 on_form_dialog_saved: function() {
355 var id = this.dataset.ids[this.dataset.index];
356 if (this.view.creating_event_id) {
357 scheduler.changeEventId(this.view.creating_event_id, id);
358 this.view.creating_event_id = null;
360 this.view.reload_event(id);
363 on_close: function() {
364 if (this.view.creating_event_id) {
365 scheduler.deleteEvent(this.view.creating_event_id);
366 this.view.creating_event_id = null;
371 openerp.web_calendar.SidebarResponsible = openerp.web.Widget.extend({
372 init: function(parent, element_id, view) {
373 this._super(parent, element_id);
375 this.$element.delegate('input:checkbox', 'change', this.on_filter_click);
377 on_events_loaded: function(filters) {
378 this.$element.html(QWeb.render('CalendarView.sidebar.responsible', { filters: filters }));
380 on_filter_click: function(e) {
381 var responsibles = [],
383 this.$element.find('div.oe_calendar_responsible input:checked').each(function() {
384 responsibles.push($(this).val());
386 scheduler.clearAll();
387 if (responsibles.length) {
388 this.view.on_events_loaded(this.view.dataset_events, function(filter_value) {
389 return _.indexOf(responsibles, filter_value.toString()) > -1;
392 this.view.on_events_loaded(this.view.dataset_events, false, true);
397 openerp.web_calendar.SidebarNavigator = openerp.web.Widget.extend({
398 init: function(parent, element_id, view) {
399 this._super(parent, element_id);
402 on_events_loaded: function(events) {
407 // DEBUG_RPC:rpc.request:('execute', 'addons-dsh-l10n_us', 1, '*', ('ir.filters', 'get_filters', u'res.partner'))
408 // vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: