From 8cca1716611bb420f48bfd82a449aa7cf4cab05f Mon Sep 17 00:00:00 2001 From: "vda (OpenERP)" Date: Tue, 31 May 2011 16:55:45 +0530 Subject: [PATCH] [FIX] Calendar. bzr revid: vda@tinyerp.com-20110531112545-laa8rp2xxx9ympgk --- addons/base_calendar/controllers/main.py | 350 +---------------- .../base_calendar/static/src/js/calendar.js | 370 +++++++++++------- .../static/src/xml/base_calendar.xml | 10 +- 3 files changed, 233 insertions(+), 497 deletions(-) diff --git a/addons/base_calendar/controllers/main.py b/addons/base_calendar/controllers/main.py index a54d75c5b9b..41ede2bb7ab 100644 --- a/addons/base_calendar/controllers/main.py +++ b/addons/base_calendar/controllers/main.py @@ -1,356 +1,10 @@ from base.controllers.main import View -import openerpweb, time, math, re, datetime as DT, pytz - -COLOR_PALETTE = ['#f57900', '#cc0000', '#d400a8', '#75507b', '#3465a4', '#73d216', '#c17d11', '#edd400', - '#fcaf3e', '#ef2929', '#ff00c9', '#ad7fa8', '#729fcf', '#8ae234', '#e9b96e', '#fce94f', - '#ff8e00', '#ff0000', '#b0008c', '#9000ff', '#0078ff', '#00ff00', '#e6ff00', '#ffff00', - '#905000', '#9b0000', '#840067', '#510090', '#0000c9', '#009b00', '#9abe00', '#ffc900', ] - -_colorline = ['#%02x%02x%02x' % (25 + ((r + 10) % 11) * 23, 5 + ((g + 1) % 11) * 20, 25 + ((b + 4) % 11) * 23) for r in range(11) for g in range(11) for b in range(11) ] - -DT_SERVER_FORMATS = { - 'datetime' : '%Y-%m-%d %H:%M:%S', - 'date' : '%Y-%m-%d', - 'time' : '%H:%M:%S' -} - -DT_FORMAT_INFO = {'datetime' : ('%Y-%m-%d %H:%M:%S', DT.datetime, 0, 6), - 'date': ('%Y-%m-%d', DT.date, 0, 3), - 'time': ('%H:%M:%S', DT.time, 3, 6)} - -def choice_colors(n): - if n > len(COLOR_PALETTE): - return _colorline[0:-1:len(_colorline) / (n + 1)] - elif n: - return COLOR_PALETTE[:n] - return [] +import openerpweb class CalendarView(View): _cp_path = "/base_calendar/calendarview" - mode = 'month' - date_start = None - date_delay = None - date_stop = None - color_field = None - day_length = 8 - use_search = False - selected_day = None - date_format = '%Y-%m-%d' - info_fields = [] - fields = {} - events = [] - - colors = {} - color_values = [] - - remote_timezone = 'utc' - client_timezone = False - - calendar_fields = {} - concurrency_info = None - - ids = [] - model = '' - domain = [] - context = {} - @openerpweb.jsonrequest def load(self, req, model, view_id): fields_view = self.fields_view_get(req, model, view_id, 'calendar') - return {'fields_view':fields_view} - - def convert(self, event): - fields = [self.date_start] - if self.date_stop: - fields.append(self.date_stop) - - for fld in fields: - fld_type = self.fields[fld]['type'] - fmt = DT_SERVER_FORMATS[fld_type] - if event[fld] and fmt: - event[fld] = time.strptime(event[fld], fmt) - - # default start/stop time is 9:00 AM / 5:00 PM - if fld_type == 'date' and event[fld]: - ds = list(event[fld]) - if fld == self.date_start: - ds[3] = 9 - elif fld == self.date_stop: - ds[3] = 17 - event[fld] = tuple(ds) - - - @openerpweb.jsonrequest - def schedule_events(self, req, **kw): - self.model = kw['model'] - self.mode = kw.get('mode') or self.mode or 'month' - self.fields = kw['fields'] - self.color_field = kw.get('color_field') or self.color_field or None - self.colors = kw.get('colors') or {} - self.calendar_fields = kw['calendar_fields'] - self.info_fields = kw['info_fields'] - self.date_start = self.calendar_fields['date_start']['name'] - self.domain = kw.get('domain') or [] - - self.remote_timezone = req.session.remote_timezone - self.client_timezone = req.session.client_timezone - - if self.calendar_fields.get('date_stop'): - self.date_stop = self.calendar_fields['date_stop']['name'] - - if self.calendar_fields.get('date_delay'): - self.date_delay = self.calendar_fields['date_delay']['name'] - - model = req.session.model(self.model) - event_ids = model.search(self.domain) - - self.events = model.read(event_ids, self.fields.keys()) - result = [] - self.date_format = req.session._lang and req.session._lang['date_format'] - - if self.color_field: - for evt in self.events: - key = evt[self.color_field] - name = key - value = key - if isinstance(key, list): # M2O, XMLRPC returns List instead of Tuple - name = key[0] - value = key[-1] - evt[self.color_field] = key = key[-1] - if isinstance(key, tuple): # M2O - value, name = key - self.colors[key] = (name, value, None) - - colors = choice_colors(len(self.colors)) - for i, (key, value) in enumerate(self.colors.items()): - self.colors[key] = [value[0], value[1], colors[i]] - - for evt in self.events: - self.convert(evt) - a = self.get_event_widget(evt) - result.append(a) - - return {'result':result,'sidebar':self.colors} - - def parsedatetime(self, string): - - kind = 'datetime' - - if '-' in string and ':' in string: - kind = 'datetime' - elif '-' in string: - kind = 'date' - elif ':' in string: - kind = 'time' - - fmt, obj, i, j = DT_FORMAT_INFO[kind] - return obj(*time.strptime(string, fmt)[i:j]) - - def parse_datetime(self, value, kind="datetime", as_timetuple=False): - server_format = DT_SERVER_FORMATS[kind] - local_format = self.date_format - if not value: - return False - - if isinstance(value, (time.struct_time, tuple)): - value = time.strftime(local_format, value) - - try: - value = time.strptime(value, local_format) - except ValueError: - try: - # might be in server format already (e.g. filter domain) - value = time.strptime(value, server_format) - except ValueError: - try: - dt = list(time.localtime()) - dt[2] = int(value) - value = tuple(dt) - except: - return False - - if kind == "datetime": - try: - value = self.tz_convert(value, 'parse') - except Exception,e: - print "*******************Error in timezone parsing *********",e - - if as_timetuple: - return value - - return time.strftime(server_format, value) - - - @openerpweb.jsonrequest - def edit_events(self, req,**kw): - data = {} - ds = self.parsedatetime(kw['start_date']) - de = self.parsedatetime(kw['end_date']) - data[kw['calendar_fields']['date_start']['name']] = self.parse_datetime(ds.timetuple()) - - if 'date_stop' in kw['calendar_fields']: - data[kw['calendar_fields']['date_stop']['name']] = self.parse_datetime(de.timetuple()) - elif 'date_delay' in kw['calendar_fields']: - day_length = kw['calendar_fields']['day_length'] - - tds = time.mktime(ds.timetuple()) - tde = time.mktime(de.timetuple()) - - n = (tde - tds) / (60 * 60) - - if n > day_length: - d = math.floor(n / 24) - h = n % 24 - - n = d * day_length + h - - data[kw['calendar_fields']['date_delay']['name']] = n - error = None - try: - req.session.model(kw['model']).write([int(kw['id'])], data) - except Exception, e: - error = e - return error - - def tz_convert(self, struct_time, action): - # if no client timezone is configured, consider the client is in the same - # timezone as the server - lzone = pytz.timezone(self.client_timezone or self.remote_timezone) - szone = pytz.timezone(self.remote_timezone) - dt = DT.datetime.fromtimestamp(time.mktime(struct_time)) - - if action == 'parse': - fromzone = lzone - tozone = szone - elif action == 'format': - fromzone = szone - tozone = lzone - else: - raise Exception("_tz_convert action should be 'parse' or 'format'. Not '%s'" % (action, )) - - localized_original_datetime = fromzone.localize(dt, is_dst=True) - destination_datetime = localized_original_datetime.astimezone(tozone) - return destination_datetime.timetuple() - - def format_datetime(self, value, kind="datetime", as_timetuple=False): - """Convert date value to the local datetime considering timezone info. - - @param value: the date value - @param kind: type of the date value (date, time or datetime) - @param as_timetuple: return timetuple - - @type value: basestring or time.time_tuple) - - @return: string or timetuple - """ - - server_format = DT_SERVER_FORMATS[kind] - local_format = self.date_format - - if not value: - return '' - - if isinstance(value, (time.struct_time, tuple)): - value = time.strftime(server_format, value) - - if isinstance(value, DT.datetime): - value = value - try: - value = DT.datetime.strptime(value[:10], server_format) - return value.strftime(local_format) - except: - return '' - - value = value.strip() - - # remove trailing miliseconds - value = re.sub("(.*?)(\s+\d{2}:\d{2}:\d{2})(\.\d+)?$", "\g<1>\g<2>", value) - - # add time part in value if missing - if kind == 'datetime' and not re.search('\s+\d{2}:\d{2}:\d{2}?$', value): - value += ' 00:00:00' - - # remove time part from value - elif kind == 'date': - value = re.sub('\s+\d{2}:\d{2}:\d{2}(\.\d+)?$', '', value) - - value = time.strptime(value, server_format) - - if kind == "datetime": - try: - value = self.tz_convert(value, 'format') - except Exception, e: - print "\n\n\n************ Error in timezone formatting", e - - if as_timetuple: - return value - - return time.strftime(local_format, value) - - def get_event_widget(self, event): - title = '' # the title - description = [] # the description - - if self.info_fields: - - f = self.info_fields[0] - s = event[f] - - if isinstance(s, (tuple, list)): s = s[-1] - - title = s - for f in self.info_fields[1:]: - s = event[f] - if isinstance(s, (tuple, list)): - s = s[-1] - if s: - description.append(str(s)) - - starts = event.get(self.date_start) - ends = event.get(self.date_delay) or 1.0 - span = 0 - - if starts and ends: - - n = 0 - h = ends - - if ends == self.day_length: - span = 1 - - elif ends > self.day_length: - n = ends / self.day_length - h = ends % self.day_length - - n = int(math.floor(n)) - - if h > 0: - span = n + 1 - else: - span = n - ends = time.localtime(time.mktime(starts) + (h * 60 * 60) + (n * 24 * 60 * 60)) - - if starts and self.date_stop: - - ends = event.get(self.date_stop) - if not ends: - ends = time.localtime(time.mktime(starts) + 60 * 60) - - tds = time.mktime(starts) - tde = time.mktime(ends) - - if tds >= tde: - tde = tds + 60 * 60 - ends = time.localtime(tde) - - n = (tde - tds) / (60 * 60) - - if n >= self.day_length: - span = math.ceil(n / 24) - - starts = self.format_datetime(starts, "datetime", True) - ends = self.format_datetime(ends, "datetime", True) - title = title.strip() - description = ', '.join(description).strip() - return {'id': event['id'], 'start_date': str(DT.datetime(*starts[:6])), 'end_date': str(DT.datetime(*ends[:6])), 'text': title, 'title': description, 'color': self.colors[event[self.color_field]][-1]} + return {'fields_view': fields_view} diff --git a/addons/base_calendar/static/src/js/calendar.js b/addons/base_calendar/static/src/js/calendar.js index 96a7fad8178..5e6d52fc93a 100644 --- a/addons/base_calendar/static/src/js/calendar.js +++ b/addons/base_calendar/static/src/js/calendar.js @@ -11,14 +11,13 @@ openerp.base_calendar.CalendarView = openerp.base.Controller.extend({ this._super(session, element_id); this.view_manager = view_manager; this.dataset = dataset; - this.dataset_index = 0; this.model = dataset.model; this.view_id = view_id; this.fields_view = {}; this.widgets = {}; this.widgets_counter = 0; this.fields = this.dataset.fields ? this.dataset.fields: {}; - this.datarecord = {}; + this.ids = this.dataset.ids; this.name = ""; this.date_start = ""; this.date_delay = ""; @@ -35,23 +34,22 @@ openerp.base_calendar.CalendarView = openerp.base.Controller.extend({ start: function() { this.rpc("/base_calendar/calendarview/load", {"model": this.model, "view_id": this.view_id}, this.on_loaded); }, - on_loaded: function(result) { - var self = this; - var params = {}; - this.fields_view = result.fields_view; - this.name = this.fields_view.name || this.fields_view.arch.attrs.string; + on_loaded: function(data) { + + this.fields_view = data.fields_view; + this.name = this.fields_view.name || this.fields_view.arch.attrs.string; this.view_id = this.fields_view.view_id; - - this.date_start = this.fields_view.arch.attrs.date_start; + + this.date_start = this.fields_view.arch.attrs.date_start; this.date_delay = this.fields_view.arch.attrs.date_delay; this.date_stop = this.fields_view.arch.attrs.date_stop; - - this.colors = this.fields_view.arch.attrs.colors; + + this.colors = this.fields_view.arch.attrs.colors; this.day_length = this.fields_view.arch.attrs.day_length || 8; this.color_field = this.fields_view.arch.attrs.color; this.fields = this.fields_view.fields; - - //* Calendar Fields * + + //* Calendar Fields * this.calendar_fields['date_start'] = {'name': this.date_start, 'kind': this.fields[this.date_start]['type']}; if(this.date_delay) @@ -59,121 +57,181 @@ openerp.base_calendar.CalendarView = openerp.base.Controller.extend({ if(this.date_stop) this.calendar_fields['date_stop'] = {'name': this.date_stop, 'kind': this.fields[this.date_stop]['type']}; - - this.calendar_fields['day_length'] = this.day_length; - //* ------- * - for(var fld=0;fld',{'width':'100%','cellspacing': 0, 'cellpadding': 0, 'id':'cal-sidebar-option'}) - ) - for(s in sidebar) { - jQuery('#cal-sidebar-option').append( - jQuery('').append( - jQuery('').append( - jQuery('
') - .append( - jQuery('', - { - 'type': 'checkbox', - 'id':sidebar[s][0], - 'value':sidebar[s][0] - }).bind('click',function(){ - self.reload_scheduler() - }), - sidebar[s][1] - ) - .css('background-color',sidebar[s][sidebar[s].length-1]) - ) - ) - ) - } - }, - - convert_date_format: function(start_date, end_date) { - var params = {}; - params['start_date'] = start_date.getFullYear() +'-' + start_date.getMonth()+'-' + start_date.getDate()+' '+start_date.getHours()+':'+start_date.getMinutes()+':'+start_date.getSeconds(); - if(end_date) { - params['end_date'] = end_date.getFullYear() +'-' + end_date.getMonth()+'-' + end_date.getDate()+' '+end_date.getHours()+':'+end_date.getMinutes()+':'+end_date.getSeconds(); - } - return params; - }, - - edit_event: function(evt_id, evt_object) { - var dates = this.convert_date_format(evt_object.start_date, evt_object.end_date); - this.rpc( - '/base_calendar/calendarview/edit_events', - { - 'start_date': dates.start_date, - 'end_date': dates.end_date, - 'id': evt_id, - 'model': this.model, - 'info_fields': this.info_fields, - 'fields': this.fields, - 'calendar_fields': this.calendar_fields - } - ); - }, - - mini_calendar: function() { + + //To parse Events we have to convert date Format + var res_events = []; + for(var e=0;e this.day_length) { + n = end / this.day_length; + h = end % this.day_length; + n = parseInt(Math.floor(n)); + + if(h > 0) + span = n + 1 + else + span = n + } + var end_date = openerp.base.parse_datetime(start); + end = end_date.add({hours: h, minutes: n}) + } + if(start && this.date_stop) { + var tds = start = openerp.base.parse_datetime(start); + var tde = ends = openerp.base.parse_datetime(event[this.date_stop]); + if(event[this.date_stop] == undefined) { + if(tds) { + end = (tds.getOrdinalNumber() + 60 * 60) + } + } + + if(tds && tde) { + //time.mktime equivalent + tds = (tds.getOrdinalNumber() / 1e3 >> 0) - (tds.getOrdinalNumber() < 0); + tde = (tde.getOrdinalNumber() / 1e3 >> 0) - (tde.getOrdinalNumber() < 0); + + } + if(tds >= tde) { + tde = tds + 60 * 60; + } + + n = (tde - tds) / (60 * 60); + if (n >= this.day_length) { + span = Math.ceil(n / 24); + } + } + + return { + 'start_date': start.toString('yyyy-MM-dd HH:mm:ss'), + 'end_date': end.toString('yyyy-MM-dd HH:mm:ss'), + 'text': res_text, + 'id': event['id'], + 'title': res_description.join() + } + }, + + mini_calendar: function() { if(scheduler.isCalendarVisible()) { scheduler.destroyCalendar(); @@ -189,11 +247,22 @@ openerp.base_calendar.CalendarView = openerp.base.Controller.extend({ }); } }, - - reload_scheduler: function() { -// self.color_field - console.log('Reload Scheduler>>>') - }, + + do_search: function(domains, contexts, groupbys) { + var self = this; + this.rpc('/base/session/eval_domain_and_context', { + domains: domains, + contexts: contexts, + group_by_seq: groupbys + }, function (results) { + // TODO: handle non-empty results.group_by with read_group + self.dataset.context = self.context = results.context; + self.dataset.domain = self.domain = results.domain; + self.dataset.read_slice(self.fields, 0, self.limit,function(events){ + self.schedule_events(events) + }); + }); + }, do_show: function () { this.$element.show(); @@ -201,23 +270,42 @@ openerp.base_calendar.CalendarView = openerp.base.Controller.extend({ do_hide: function () { this.$element.hide(); + }, + + popup_event: function(event_id) { + var action_manager = this.view_manager.session.action_manager; + + var action = { + "res_model": this.dataset.model, + "res_id": event_id, + "views":[[false,"form"]], + "type":"ir.actions.act_window", + "view_type":"form", + "view_mode":"form" + } + + action.flags = { + search_view: false, + sidebar : false, + views_switcher : false, + action_buttons : false, + pager: false + } + var element_id = _.uniqueId("act_window_dialog"); + var dialog = jQuery('
', { + 'id': element_id + }).dialog({ + modal: true, + width: 'auto', + height: 'auto' + }); + + var action_manager = new openerp.base.ActionManager(this.session, element_id); + action_manager.start(); + action_manager.do_action(action); } }); -//openerp.base.Action = openerp.base.Action.extend({ -// do_action_window: function(action) { -// this._super.apply(this,arguments); -// for(var i = 0; i < action.views.length; i++) { -// if(action.views[i][1] == "calendar") { -// this.calendar_id = action.views[i][0]; -// break; -// } -// } -// // IF there is a view calender -// // if(this.calendar_id -// }, -//}); - }; // DEBUG_RPC:rpc.request:('execute', 'addons-dsh-l10n_us', 1, '*', ('ir.filters', 'get_filters', u'res.partner')) diff --git a/addons/base_calendar/static/src/xml/base_calendar.xml b/addons/base_calendar/static/src/xml/base_calendar.xml index 02d67be05bb..59f77cbb0bc 100644 --- a/addons/base_calendar/static/src/xml/base_calendar.xml +++ b/addons/base_calendar/static/src/xml/base_calendar.xml @@ -1,15 +1,9 @@