""" EventCalendar.py Version 0.99a July 22, 2009 * Base 0.99 version * Add ErikMartin's Defaults patch (defaults-099-01) * Add AlanSnelson 2008-11-05 patch for Moin 1.8.0 caching methods * Add tidyup patch for 1.6.1 (EventCalendar-099.py.patch) NeoCoin * Add Weeknumber patch from KlausMariaPfeiffer 2008-01-25 * Add label colour patch DavidOCallahan 2006-07-18 {see here for names: http://www.w3schools.com/html/html_colornames.asp} * Add pagelinks-099-01.patch for OrphanedPages maintenance. * Add showpagelist, to append list of contributing pages pagelist-099-01.patch (except: default now off not on) * Add event sorting patch RuthIvimey 2007-05-17 * Fix url_prefix usage DaveGore 2008-04-04 Not included: ErikMartin's Label Priority patch - too big a patch for this wrapup release. RuthIvimey's page label colour patch - not sure of side-effects HyungyongKim's unicode patch: described as temporary EventCalendar.py Version 0.99 May 22, 2006 This macro gives a list of the events recorded at the sub-pages in the form of various views: monthly, weekly, daily, simple-month, list, and upcoming. @copyright: 2006 by Seungik Lee gmail.com> http://www.silee.net/ @license: GPL For more information, please visit http://moinmoin.wikiwikiweb.de/MacroMarket/EventCalendar * To list the events in a page, just insert [[EventCalendar]] * To insert an event, insert the event information in any pages of specified category (CategoryEventCalendar by default). * category: the category of the event data to be used in the calendar. default: 'CategoryEventCalendar' * menubar: shows menubar or not (1: show, 0: no menubar). default: 1 * monthlywidth: calendar width in pixel or percent (monthly view). default: '600' (pixel) * simplewidth: calendar width in pixel or percent (simpleview). default: '150' (pixel) * firstview: initial calendar view: monthly, weekly, daily, list, simple, upcoming. default: 'monthly' * curdate: initial calendar date (in YYYYMM format). default: current month * upcomingrange: # of days for the range of upcoming event list. default: 7 (days) * changeview: enables to change the calendar view or not (1: enalbed, 0: disabled). default: 1 * numcal: # of calendar. default: 1 * showlastweekday: shows the event at the last weekday if the recurred weekday is not available. (1: enalbed, 0: disabled). default: 0 * showerror: shows error messages below the calendar if event data format is invalid. (1: enalbed, 0: disabled). default: 1 * showpagelist: shows a list of the pages used for event data below the calendar. (1: enalbed, 0: disabled). default: 0 * showweeknumber: shows the week number of the year (1: enalbed, 0: disabled). default: 0 * Event data fields: ... [default_description:: [page_default_description_text]] [default_bgcolor:: [page_default_background_color]] [label_def:: [label_name], [label_background_color]] == == start:: <startdate> [starttime] [end:: [enddate] [endtime]] [description:: [description_text]] [bgcolor:: [custom_background_color]] [recur:: <recur_freq> <recur_type> [until <recur_until>]] [label:: <label_name>] ... ---- CategoryEventCalendar * default_bgcolor, default_description: default values of bgcolor and description in the page if unavailable. optional * label_def: label definition with name, bgcolor. optional * title: event title. required * should be enclosed with heading marker ('='), Title cannot be omitted. * startdate: date of start. required * should be in date format or date format * starttime: time of start. optional * should be in time format * enddate: date of end. optional * should be in date format or date format. If omitted, it will be assigned equal to <startdate>. * endtime: time of end. optional * should be in time format. Both of start|end Time can be omitted but not either of them. * description: description of the event. optional * any text with no markup. should be in a line. * bgcolor: custom background color of the event in monthly view. optional * e.g., #abcdef * recur: recurrence information of the event. optional * recur_freq: how many intervals, digit or 'last' for weekday, required * recur_type: [day|week|weekday|month|year], required * day: every [recur_freq] days * week: every [recur_freq] weeks * weekday: on the same weekday of [recur_freq]-th week of the month. or 'last weekday' * month: on the same day of [recur_freq]-th month * year: on the same day of [recur_freq]-th year * recur_until: recurred until when, date format, optional * e.g., 10 day, 2 week until 2006-06-31, 3 weekday, 6 month until 2007-12-31, 1 year * label: custom label for specific name, bgcolor. optional * The order of the fields after an event title does not matter. * Priority of bgcolor: bgcolor > default_bgcolor > label_bgcolor * Datetime format: * Date format: * YYYY/MM/DD, YYYY-MM-DD, YYYY.MM.DD: 2006/05/12; 2006-05-12; 2006.05.12; 2006-5-12; 06/5/12 * B DD, YYYY: May 12, 2006; May 5th, 2006; January 1st, 2006; Jan 5, 06 * YYYYMMDD, YYMMDD: 20060512; 060512 * Year: YY = 20YY. e.g., 06-2-2 = 2006-02-02, allowed 1900 ~ 2099 only. * Time format: * H:M, HHMM: 12:00; 22:00; 2:00; 2 (= 2 o'clock); 2200; 12:0; 2:0 * I:M PP, IIMM PP: 12:00 PM; 3:00p; 2a (= 2 o'clock AM); 3:0pm; 0200 am; 10pm <Event Data Examples> == Default values == default_bgcolor:: #c0c0c0 default_description:: testing... == Labels == label_def:: Holiday, #ff0000 label_def:: Meeting, #00ff00 === Test event === start:: 2006-01-10 02:00p end:: 2006-01-12 17:00 description:: test event bgcolor:: #cfcfcf === Jinah's Birthday === start:: 1977-10-20 recur:: 1 year label:: Holiday === Weekly meeting === start:: Jan 17, 2006 7:00pm end:: 21:00 recur:: 1 week until 061231 label:: Meeting ---- CategoryEventCalendar <Notes> * It caches all the page list of the specified category and the event information. * If you added/removed a page into/from a category, you need to do 'Delete cache' in the macro page. * 'MonthCalendar.py' developed by Thomas Waldmann <ThomasWaldmann@gmx.de> has inspired this macro. * Much buggy.. : please report bugs and suggest your ideas. * If you missed to add css for EventCalender, monthly view may not be readable. * Insert the EventCalendar css classes into the screen.css of an appropriate theme. """ from MoinMoin import wikiutil, config, search, caching from MoinMoin.Page import Page import re, calendar, time, datetime import codecs, os, urllib, sha try: import cPickle as pickle except ImportError: import pickle # Set pickle protocol, see http://docs.python.org/lib/node64.html PICKLE_PROTOCOL = pickle.HIGHEST_PROTOCOL # The following line sets the calendar to have either Sunday or Monday as # the first day of the week. Only SUNDAY or MONDAY (case sensitive) are # valid here. All other values will not make good calendars. # XXX change here ----------------vvvvvv calendar.setfirstweekday(calendar.MONDAY) class Globs: month_style_us = 1 # 1: October 2005; 2: 2005 / 10 defaultcategory = 'CategoryEventCalendar' upcomingrange = 7 # days dailystart = 9 dailyend = 18 pagename = '' baseurl = '' subname = '' wkend = '' months = '' wkdays = '' today = '' now = '' request = None formatter = None cal_action = '' debugmsg = '' errormsg = '' page_action = '' form_vals = {} events = None labels = None class Params: menubar = 0 monthlywidth = '' weeklywidth = '' dailywidth = '' simplewidth = '' firstview = '' curdate = '' bgcolor = '' category = '' upcomingrange = 0 changeview = 0 numcal = 1 showlastweekday = 0 showerror = 1 showpagelist = 0 showweeknumber = 0 debug = 0 class EventcalError(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) def execute(macro, args): request = macro.request formatter = macro.formatter # INITIALIZATION ---------------------------------------- setglobalvalues(macro) getparams(args) # allowed actions allowed_action = ['monthly', 'list', 'simple', 'upcoming', 'daily', 'weekly'] default_action = Params.firstview # Internal variables cal_action = '' form_vals = {} # PROCESSING ARGUEMENTS ---------------------------------------- if args: args=request.getText(args) for item in macro.form.items(): if not form_vals.has_key(item[0]): try: form_vals[item[0]]=item[1][0] except AttributeError: pass # PROCESSING ACTIONS ---------------------------------------- cal_action = form_vals.get('calaction', default_action) page_action = form_vals.get('action', 'show') if not cal_action in allowed_action: cal_action = default_action form_vals['calaction'] = cal_action Globs.form_vals = form_vals # CONTROL FUNCTIONS ---------------------------------------- html = [] html_result = '' Globs.cal_action = cal_action Globs.page_action = page_action # redirect to the appropriate view if cal_action == 'monthly': html_result = showcalendar() if cal_action == 'list': html_result = showeventlist() if cal_action == 'simple': html_result = showsimplecalendar() if cal_action == 'upcoming': html_result = showupcomingeventlist() if cal_action == 'daily': html_result = showdailycalendar() if cal_action == 'weekly': html_result = showweeklycalendar() # format output html.append( html_result ) html.append( showmenubar() ) html.append( showpagelist() ) if Params.showerror and Globs.errormsg: html.append(u'<p><i><font size="2" color="#aa0000"><ol>%s</ol></font></i>' % Globs.errormsg) if Params.debug and Globs.debugmsg: html.append(u'<p><b>Debug messages:</b><font color="#000099"><ol>%s</ol></font>' % Globs.debugmsg) return formatter.rawHTML(u''.join(html)) def getparams(args): # process arguments params = {} if args: # Arguments are comma delimited key=value pairs sargs = args.split(',') for item in sargs: sitem = item.split('=') if len(sitem) == 2: key, value = sitem[0], sitem[1] params[key.strip()] = value.strip() # category name: # default: 'CategoryEventCalendar' Params.category = params.get('category', Globs.defaultcategory) # menu bar: shows menubar or not (1: show, 0: no menubar) # default: 1 try: Params.menubar = int(params.get('menubar', 1)) except (TypeError, ValueError): Params.menubar = 1 # calendar width in pixel or percent (monthly) # default: 600px Params.monthlywidth = params.get('monthlywidth', '600') if Params.monthlywidth: Params.monthlywidth = ' width="%s" ' % Params.monthlywidth # calendar width in pixel or percent (weekly) # default: 600px Params.weeklywidth = params.get('weeklywidth', '600') if Params.weeklywidth: Params.weeklywidth = ' width="%s" ' % Params.weeklywidth # calendar width in pixel or percent (daily) # default: 600px Params.dailywidth = params.get('dailywidth', '600') if Params.monthlywidth: Params.dailywidth = ' width="%s" ' % Params.dailywidth # calendar width in pixel or percent (simply) # default: 150px Params.simplewidth = params.get('simplewidth', '150') if Params.simplewidth: # Params.simplewidth = Params.simplewidth.replace('%', '%%') Params.simplewidth = ' width="%s" ' % Params.simplewidth # calendar view: monthly, list, simple # default: 'monthly' Params.firstview = params.get('firstview', 'monthly') # calendar date: in YYYYMM format (in monthly, simple view) # default: current month Params.curdate = params.get('curdate', '') # upcoming range: # of days for upcoming event list # default: 7 try: Params.upcomingrange = int(params.get('upcomingrange', Globs.upcomingrange)) except (TypeError, ValueError): Params.upcomingrange = Globs.upcomingrange # number of calendar: # of calendar for monthly & simple view # default: 1 try: Params.numcal = int(params.get('numcal', '1')) except (TypeError, ValueError): Params.numcal = 1 # change view enabled? # default: 1 try: Params.changeview = int(params.get('changeview', '1')) except (TypeError, ValueError): Params.changeview = 1 # shows the event at the last weekday if the recurred weekday is not available. # default: 0 try: Params.showlastweekday = int(params.get('showlastweekday', '0')) except (TypeError, ValueError): Params.showlastweekday = 0 # show error message? # default: 1 try: Params.showerror = int(params.get('showerror', '1')) except (TypeError, ValueError): Params.showerror = 1 # show week number? # default: 0 try: Params.showweeknumber = int(params.get('showweeknumber', '0')) except (TypeError, ValueError): Params.showweeknumber = 0 # show definition table # default: 1 try: Params.showpagelist = int(params.get('showpagelist', '0')) except (TypeError, ValueError): Params.showpagelist = 1 # default bgcolor Params.bgcolor = '#ddffdd' def setglobalvalues(macro): request = macro.request formatter = macro.formatter # Useful variables Globs.baseurl = request.getBaseURL() + '/' Globs.pagename = formatter.page.page_name Globs.request = request Globs.formatter = formatter Globs.pageurl = '%s/%s' % (request.getScriptname(), wikiutil.quoteWikinameURL(formatter.page.page_name)) # This fixes the subpages bug. subname is now used instead of pagename when creating certain urls Globs.subname = Globs.pagename.split('/')[-1] pagepath = formatter.page.getPagePath() Globs.pagepath = formatter.page.getPagePath() # european / US differences months = ('January','February','March','April','May','June','July','August','September','October','November','December') # Set things up for Monday or Sunday as the first day of the week if calendar.firstweekday() == calendar.MONDAY: wkend = 6 wkdays = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun') elif calendar.firstweekday() == calendar.SUNDAY: wkend = 0 wkdays = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat') Globs.months = months Globs.wkdays = wkdays Globs.wkend = wkend year, month, day, h, m, s, wd, yd, ds = request.user.getTime(time.time()) Globs.today = datetime.date(year, month, day) Globs.now = datetime.time(h, m, s) Globs.debugmsg = '' Globs.errormsg = '' def showReferPageParsed(event, targettext='title', showdesc=0): request = Globs.request pagename = Globs.pagename refer = event['refer'] targettext = event[targettext] startdate = event['startdate'] enddate = event['enddate'] description = event['description'] starttime = event['starttime'] endtime = event['endtime'] hid = event['hid'] refer_url = '%s/%s' % (request.getScriptname(), wikiutil.quoteWikinameURL(refer)) if not Params.changeview: refer_url = '' hid = '' if showdesc: if (startdate == enddate) and (starttime and endtime): timedescription = '(%s:%s ~ %s:%s)' % (starttime[:2], starttime[2:], endtime[:2], endtime[2:]) if description: timedescription = '%s ' % timedescription else: timedescription = '' targetlink = '<a href="%s#%s" title="%s%s">%s</a>' % ( refer_url, hid, timedescription, wikiutil.escape(description), wikiutil.escape(targettext) ) else: targetlink = '<a href="%s#%s">%s</a>' % ( refer_url, hid, wikiutil.escape(targettext)) return targetlink def showReferPageParsedForLabel(thelabel, targettext='name', showdesc=1): request = Globs.request pagename = Globs.pagename labels = Globs.labels label_bgcolor = '' refer = '' if labels and labels.has_key(thelabel): targettext = labels[thelabel][targettext] refer = labels[thelabel]['refer'] if showdesc: label_bgcolor = labels[thelabel]['bgcolor'] if not refer: return '<i>%s</i>' % thelabel refer_url = '%s/%s' % (request.getScriptname(), wikiutil.quoteWikinameURL(refer)) if showdesc: targetlink = '<a href="%s" title="%s">%s</a>' % ( refer_url, label_bgcolor, wikiutil.escape(targettext) ) else: targetlink = '<a href="%s">%s</a>' % ( refer_url, wikiutil.escape(targettext)) return targetlink def getheadingid(request, referpage, title): pntt = (referpage + title).encode(config.charset) hid = "head-" + sha.new(pntt).hexdigest() if not hasattr(request, '_eventcal_headings'): request._eventcal_headings = {} request._eventcal_headings.setdefault(pntt, 0) request._eventcal_headings[pntt] += 1 if request._eventcal_headings[pntt] > 1: hid += '-%d'%(request._eventcal_headings[pntt],) return hid def getquerystring(req_fields): m_query = [] tmp_form_vals = Globs.form_vals # format querystring # action should be poped out for field in req_fields: if tmp_form_vals.has_key(field): m_query.append(u'%s=%s' % (field, tmp_form_vals[field]) ) if 'prevcalaction' in req_fields: if not tmp_form_vals.has_key('prevcalaction'): m_query.append(u'%s=%s' % ('prevcalaction', tmp_form_vals['calaction']) ) m_query = u'&'.join(m_query) if m_query: m_query = '&%s' % m_query return m_query # bottom menu bar def showmenubar(): request = Globs.request cal_action = Globs.cal_action page_name = Globs.pagename page_url = Globs.pageurl if not Params.menubar: return '' if cal_action == 'simple': menuwidth = Params.simplewidth elif cal_action == 'monthly': menuwidth = Params.monthlywidth else: menuwidth = '' left_menu_selected = [] right_menu_selected = [] # Go Today year, month, day = gettodaydate() mnu_curmonthcal = u'<a href="%s?calaction=%s&caldate=%d%02d%02d%s" title="Go Today">[Today]</a>' % (page_url, cal_action, year, month, day, getquerystring(['numcal'])) # List View mnu_listview = u'<a href="%s?calaction=list%s" title="List of all events">[List]</a>' % (page_url, getquerystring(['caldate', 'numcal'])) # Monthly View mnu_monthview = u'<a href="%s?calaction=monthly%s" title="Monthly view">[Monthly]</a>' % (page_url, getquerystring(['caldate', 'numcal']) ) # Simple Calendar View mnu_simpleview = u'<a href="%s?calaction=simple%s" title="Simple calendar view">[Simple]</a>' % (page_url, getquerystring(['caldate', 'numcal']) ) # Upcoming Event List mnu_upcomingview = u'<a href="%s?calaction=upcoming%s" title="Upcoming event list">[Upcoming]</a>' % (page_url, getquerystring(['caldate', 'numcal']) ) # Daily View mnu_dayview = u'<a href="%s?calaction=daily%s" title="Daily view">[Daily]</a>' % (page_url, getquerystring(['caldate', 'numcal']) ) # Weekly View mnu_weekview = u'<a href="%s?calaction=weekly%s" title="Weekly view">[Weekly]</a>' % (page_url, getquerystring(['caldate', 'numcal']) ) html = [ u'\r\n', u'<table class="eventcalendar_menubar" %s>', u' <tr>', u' <td class="eventcalendar_menubar" align="left">%s</td>', u' <td class="eventcalendar_menubar" align="right">%s</td>', u' </tr>', u'</table>', ] if cal_action == 'list': left_menu_selected.append(mnu_monthview) left_menu_selected.append(mnu_weekview) left_menu_selected.append(mnu_dayview) left_menu_selected.append(mnu_simpleview) right_menu_selected.append(mnu_upcomingview) elif cal_action == 'simple': left_menu_selected.append(mnu_monthview) left_menu_selected.append(mnu_weekview) left_menu_selected.append(mnu_dayview) right_menu_selected.append(mnu_listview) right_menu_selected.append(mnu_upcomingview) right_menu_selected.append(mnu_curmonthcal) elif cal_action == 'upcoming': left_menu_selected.append(mnu_monthview) left_menu_selected.append(mnu_weekview) left_menu_selected.append(mnu_dayview) left_menu_selected.append(mnu_simpleview) right_menu_selected.append(mnu_listview) elif cal_action == 'weekly': left_menu_selected.append(mnu_monthview) left_menu_selected.append(mnu_dayview) left_menu_selected.append(mnu_simpleview) right_menu_selected.append(mnu_upcomingview) right_menu_selected.append(mnu_listview) right_menu_selected.append(mnu_curmonthcal) elif cal_action == 'daily': left_menu_selected.append(mnu_monthview) left_menu_selected.append(mnu_weekview) left_menu_selected.append(mnu_simpleview) right_menu_selected.append(mnu_upcomingview) right_menu_selected.append(mnu_listview) right_menu_selected.append(mnu_curmonthcal) else: left_menu_selected.append(mnu_weekview) left_menu_selected.append(mnu_dayview) left_menu_selected.append(mnu_simpleview) right_menu_selected.append(mnu_upcomingview) right_menu_selected.append(mnu_listview) right_menu_selected.append(mnu_curmonthcal) left_menu_selected = u'\r\n'.join(left_menu_selected) right_menu_selected = u'\r\n'.join(right_menu_selected) html = u'\r\n'.join(html) html = html % (menuwidth, left_menu_selected, right_menu_selected) return html def show_page_list(): html = "" request = Globs.request formatter = Globs.formatter if Params.showpagelist: source_pages = [] events, cal_events, labels = loadEvents() for eid in events.keys(): event = events[eid] refer = event['refer'] refer_url = '%s/%s' % (request.getScriptname(), wikiutil.quoteWikinameURL(refer)) targetlink = '<a href="%s">%s</a>' % ( refer_url, wikiutil.escape(refer)) source_pages.append( targetlink ) from sets import Set page_set = Set(source_pages) html = "\n" html += formatter.paragraph(1) html += "Constructed from events defined on these pages" html += formatter.paragraph(0) html += "\n" html += formatter.bullet_list(1) html += "\n" for p in page_set: html += formatter.listitem(1) html += p html += formatter.listitem(0) html += "\n" html += formatter.bullet_list(0) html += "\n" return html def getdatefield(str_date): str_year = '' str_month = '' str_day = '' if len(str_date) == 6: # year+month str_year = str_date[:4] str_month = str_date[4:] str_day = '1' elif len(str_date) == 8: # year+month+day str_year = str_date[:4] str_month = str_date[4:6] str_day = str_date[6:] elif len(str_date) == 10: # year+?+month+?+day str_year = str_date[:4] str_month = str_date[5:7] str_day = str_date[8:] else: raise ValueError # It raises exception if the input date is incorrect temp = datetime.date(int(str_year), int(str_month), int(str_day)) return temp.year, temp.month, temp.day def gettimefield(str_time): str_hour = '' str_min = '' if len(str_time) == 4: # hour+minute str_hour = str_time[:2] str_min = str_time[2:] elif len(str_time) == 5: # hour+?+minute str_hour = str_time[:2] str_min = str_time[3:] else: raise ValueError # It raises exception if the input date is incorrect temp = datetime.time(int(str_hour), int(str_min)) return temp.hour, temp.minute def gettodaydate(): today = Globs.today return today.year, today.month, today.day def cal_listhead(): html = [ u' <tr>', u' <td class="list_head">Title</td>', u' <td class="list_head">Start Date</td>', u' <td class="list_head">End Date</td>', u' <td class="list_head">Recurrence</td>', u' <td class="list_head">Label</td>', u' <td class="list_head">Description</td>', u' <td class="list_head">Reference</td>', u' </tr>', ] return u'\r\n'.join(html) def showeventlist(): debug('Show Calendar: List view') request = Globs.request formatter = Globs.formatter html_event_rows = [] html_list_header = cal_listhead() # read all the events events, cal_events, labels = loadEvents() # sort events sorted_eventids = events.keys() sorted_eventids.sort(comp_list_events) for eid in sorted_eventids: if not events[eid]['clone']: html_event_rows.append( listshow_event(events[eid]) ) html_event_rows = u'\r\n'.join(html_event_rows) html_list_table = [ u'\r\n<div id="eventlist">', u'<table class="eventlist">', u'%s' % html_list_header, u'%s' % html_event_rows, u'</table>', u'</div>', ] html_list_table = u'\r\n'.join(html_list_table) return html_list_table def listshow_event(event): if event['recur_freq']: if event['recur_freq'] == -1: recur_desc = 'last %s' % event['recur_type'] else: recur_desc = 'every %d %s' % (event['recur_freq'], event['recur_type']) if event['recur_until']: recur_desc = '%s until %s' % (recur_desc, formatcfgdatetime(event['recur_until'])) else: recur_desc = '' html = [ u' <tr>', u' <td class="list_entry">%s</td>' % converttext(event['title']), u' <td class="list_entry">%s</td>' % formatcfgdatetime(event['startdate'], event['starttime']), u' <td class="list_entry">%s</td>' % formatcfgdatetime(event['enddate'], event['endtime']), u' <td class="list_entry">%s</td>' % recur_desc, u' <td class="list_entry">%s</td>' % showReferPageParsedForLabel(event['label']), u' <td class="list_entry">%s</td>' % converttext(event['description']), u' <td class="list_entry">%s</td>' % showReferPageParsed(event, 'refer'), u' </tr>', ] return u'\r\n'.join(html) def showupcomingeventlist(): debug('Show Calendar: Upcoming Event View') request = Globs.request formatter = Globs.formatter html_event_rows = [] html_list_header = cal_listhead() year, month, day = gettodaydate() day_delta = datetime.timedelta(days=Params.upcomingrange) cur_date = datetime.date(year, month, day) next_range = cur_date + day_delta # set ranges of events datefrom = u'%04d%02d%02d' % (year, month, day) dateto = u'%04d%02d%02d' % (next_range.year, next_range.month, next_range.day) # read all the events (no cache) events, cal_events, labels = loadEvents(datefrom, dateto, 1) nowtime = formattimeobject(Globs.now) datefrom = formatcfgdatetime(cur_date, nowtime) #u'%04d-%02d-%02d %s:%s' % (year, month, day, nowtime[:2], nowtime[2:]) dateto = formatcfgdatetime(formatdateobject(next_range)) #u'%04d-%02d-%02d' % (next_range.year, next_range.month, next_range.day) # sort events sorted_eventids = events.keys() sorted_eventids.sort(comp_list_events) for eid in sorted_eventids: if events[eid]['enddate'] >= formatdateobject(Globs.today): if (not events[eid]['endtime']) or events[eid]['endtime'] >= formattimeobject(Globs.now): html_event_rows.append( listshow_event(events[eid]) ) html_event_rows = u'\r\n'.join(html_event_rows) html_list_table = [ u'\r\n<div id="eventlist">', u'<table class="eventlist">', u'<tr><td colspan="7" class="list_entry" style="border-width: 0px;"><b>Upcoming Event List: %s ~ %s</b><p><br><p></td></tr>' % (datefrom, dateto), u'%s' % html_list_header, u'%s' % html_event_rows, u'</table>', u'</div>', ] html_list_table = u'\r\n'.join(html_list_table) return html_list_table def showcalendar(): request = Globs.request formatter = Globs.formatter form_vals = Globs.form_vals html = [] if form_vals.has_key('caldate'): try: year, month, str_temp = getdatefield(form_vals['caldate']) except (TypeError, ValueError): errormsgcode('invalid_caldate') year, month, dy = gettodaydate() elif Params.curdate: try: year, month, str_temp = getdatefield(Params.curdate) except (TypeError, ValueError): errormsgcode('invalid_curdate') year, month, dy = gettodaydate() else: year, month, dy = gettodaydate() # check number of calendar numcal = Params.numcal if form_vals.has_key('numcal'): try: numcal = int(form_vals['numcal']) except (TypeError, ValueError): errormsgcode('invalid_numcal') if numcal < 1: numcal = 1 elif numcal > 12: numcal = 12 for index in range(numcal): cyear, cmonth = yearmonthplusoffset(year, month, index) cal_html = showeventcalendar(cyear, cmonth) html.append(cal_html) return u''.join(html) def showdailycalendar(): request = Globs.request formatter = Globs.formatter form_vals = Globs.form_vals if form_vals.has_key('caldate'): try: year, month, dy = getdatefield(form_vals['caldate']) if len(form_vals['caldate']) <= 6: tyear, tmonth, tdy = gettodaydate() if tyear == year and month == tmonth: dy = tdy except (TypeError, ValueError): errormsgcode('invalid_caldate') year, month, dy = gettodaydate() elif Params.curdate: try: year, month, dy = getdatefield(Params.curdate) except (TypeError, ValueError): errormsgcode('invalid_curdate') year, month, dy = gettodaydate() else: year, month, dy = gettodaydate() html = showdailyeventcalendar(year, month, dy) return u''.join(html) def showweeklycalendar(): request = Globs.request formatter = Globs.formatter form_vals = Globs.form_vals if form_vals.has_key('caldate'): try: year, month, dy = getdatefield(form_vals['caldate']) if len(form_vals['caldate']) <= 6: tyear, tmonth, tdy = gettodaydate() if tyear == year and month == tmonth: dy = tdy except (TypeError, ValueError): errormsgcode('invalid_caldate') year, month, dy = gettodaydate() elif Params.curdate: try: year, month, dy = getdatefield(Params.curdate) except (TypeError, ValueError): errormsgcode('invalid_curdate') year, month, dy = gettodaydate() else: year, month, dy = gettodaydate() html = showweeklyeventcalendar(year, month, dy) return u''.join(html) def showsimplecalendar(): request = Globs.request formatter = Globs.formatter form_vals = Globs.form_vals html = [] if form_vals.has_key('caldate'): try: year, month, str_temp = getdatefield(form_vals['caldate']) except (TypeError, ValueError): errormsgcode('invalid_caldate') year, month, dy = gettodaydate() elif Params.curdate: try: year, month, str_temp = getdatefield(Params.curdate) except (TypeError, ValueError): errormsgcode('invalid_curdate') year, month, dy = gettodaydate() else: year, month, dy = gettodaydate() # check number of calendar numcal = Params.numcal if form_vals.has_key('numcal'): try: numcal = int(form_vals['numcal']) except (TypeError, ValueError): errormsgcode('invalid_numcal') if numcal < 1: numcal = 1 elif numcal > 12: numcal = 12 for index in range(numcal): cyear, cmonth = yearmonthplusoffset(year, month, index) cal_html = showsimpleeventcalendar(cyear, cmonth) html.append(cal_html) return u''.join(html) # sort events in cal_events by length of days of the event def comp_cal_events(xid, yid): events = Globs.events if events[xid]['date_len'] > events[yid]['date_len']: return -1 elif events[xid]['date_len'] == events[yid]['date_len']: if events[xid]['date_len'] == 1: if events[xid]['starttime'] == events[yid]['starttime']: return cmp(events[yid]['time_len'], events[xid]['time_len']) else: return cmp(events[xid]['starttime'], events[yid]['starttime']) else: return 0 else: return 1 # sort events in the list by start date of the event def comp_list_events(xid, yid): events = Globs.events if events[xid]['startdate'] == events[yid]['startdate']: return cmp(events[xid]['starttime'], events[yid]['starttime']) else: return cmp(events[xid]['startdate'], events[yid]['startdate']) # load events from wiki pages def loadEvents(datefrom='', dateto='', nocache=0): request = Globs.request debug('Loading event information.') events = {} labels = {} cal_events = {} raw_events = {} raw_events, labels = loadEventsFromWikiPages() # handling cal_events if datefrom or dateto: # cache configurations arena = Page(request, Globs.pagename) eventkey = 'events' filteredeventkey = 'events_%s-%s' % (datefrom, dateto) caleventkey = 'calevents_%s-%s' % (datefrom, dateto) cache_events = caching.CacheEntry(request, arena, eventkey, scope='item') cache_filteredevents = caching.CacheEntry(request, arena, filteredeventkey, scope='item') cache_calevents = caching.CacheEntry(request, arena, caleventkey, scope='item') dirty = 1 debug('Checking cal_events cache') if not (cache_calevents.needsUpdate(cache_events._filename()) or cache_filteredevents.needsUpdate(cache_events._filename())): try: events = pickle.loads(cache_filteredevents.content()) cal_events = pickle.loads(cache_calevents.content()) debug('Cached event (filtered) information is used: total %d events' % len(events)) dirty = 0 except (pickle.UnpicklingError, IOError, EOFError, ValueError): debug('Picke error at fetching cached events (filtered)') events = {} cal_events = {} # if cache is dirty, update the cache if dirty: debug('Checking event cache: it\'s dirty or requested to refresh') debug('Building new cal_event information') try: datefrom, dateto = int(datefrom), int(dateto) except (TypeError, ValueError): datefrom, dateto = 0, 0 clone_num = 0 for e_id in raw_events.keys(): cur_event = raw_events[e_id] # handling event recurrence recur_freq = cur_event['recur_freq'] if recur_freq or recur_freq == -1: if not (cur_event['recur_until'] and int(cur_event['recur_until']) < datefrom) or int(cur_event['startdate']) > dateto: if not (int(cur_event['enddate']) < datefrom or int(cur_event['startdate']) > dateto): # generating cal_events for iteself events[e_id] = cur_event.copy() insertcalevents(cal_events, datefrom, dateto, e_id, cur_event['startdate'], cur_event['enddate']) delta_date_len = datetime.timedelta(days = int(cur_event['date_len']) - 1 ) if cur_event['recur_type'] == 'day': day_delta = int(recur_freq) startdate = getdatetimefromstring(cur_event['startdate']) datefrom_date = getdatetimefromstring(datefrom) if int(datefrom) > int(cur_event['startdate']): diffs = datefrom_date - startdate q_delta = diffs.days / day_delta if diffs.days % day_delta > 0: q_delta += 1 else: q_delta = 1 while 1: if q_delta == 0: q_delta += 1 continue recurred_startdate = startdate + datetime.timedelta(days = q_delta * day_delta ) recurred_enddate = recurred_startdate + delta_date_len new_startdate = formatdateobject(recurred_startdate) new_enddate = formatdateobject(recurred_enddate) if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)): break clone_num += 1 clone_id = 'c%d' % clone_num events[clone_id] = cur_event.copy() events[clone_id]['id'] = clone_id events[clone_id]['startdate'] = new_startdate events[clone_id]['enddate'] = new_enddate events[clone_id]['clone'] = 1 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate) q_delta += 1 elif cur_event['recur_type'] == 'week': day_delta = int(recur_freq) * 7 startdate = getdatetimefromstring(cur_event['startdate']) datefrom_date = getdatetimefromstring(datefrom) if int(datefrom) > int(cur_event['startdate']): diffs = datefrom_date - startdate q_delta = diffs.days / day_delta if diffs.days % day_delta > 0: q_delta += 1 else: q_delta = 1 while 1: if q_delta == 0: q_delta += 1 continue recurred_startdate = startdate + datetime.timedelta(days = q_delta * day_delta ) recurred_enddate = recurred_startdate + delta_date_len new_startdate = formatdateobject(recurred_startdate) new_enddate = formatdateobject(recurred_enddate) if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)): break clone_num += 1 clone_id = 'c%d' % clone_num events[clone_id] = cur_event.copy() events[clone_id]['id'] = clone_id events[clone_id]['startdate'] = new_startdate events[clone_id]['enddate'] = new_enddate events[clone_id]['clone'] = 1 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate) q_delta += 1 elif cur_event['recur_type'] == 'weekday': syear, smonth, sday = getdatefield(cur_event['startdate']) cyear, cmonth, cday = getdatefield(str(datefrom)) recur_weekday = calendar.weekday(syear, smonth, sday) while 1: firstweekday, daysinmonth = calendar.monthrange(cyear, cmonth) firstmatch = (recur_weekday - firstweekday) % 7 + 1 if recur_freq == -1: therecur_day = xrange(firstmatch, daysinmonth + 1, 7)[-1] else: #XXX should handle error try: therecur_day = xrange(firstmatch, daysinmonth + 1, 7)[recur_freq-1] except IndexError: if Params.showlastweekday: # if no matched weekday, the last weekday will be displayed therecur_day = xrange(firstmatch, daysinmonth + 1, 7)[-1] else: # if no matched weekday, no event will be displayed cyear, cmonth = yearmonthplusoffset(cyear, cmonth, 1) continue recurred_startdate = datetime.date(cyear, cmonth, therecur_day) recurred_enddate = recurred_startdate + delta_date_len new_startdate = formatdateobject(recurred_startdate) new_enddate = formatdateobject(recurred_enddate) if int(new_startdate) < int(datefrom) or new_startdate == cur_event['startdate']: cyear, cmonth = yearmonthplusoffset(cyear, cmonth, 1) continue if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)): break clone_num += 1 clone_id = 'c%d' % clone_num events[clone_id] = cur_event.copy() events[clone_id]['id'] = clone_id events[clone_id]['startdate'] = new_startdate events[clone_id]['enddate'] = new_enddate events[clone_id]['clone'] = 1 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate) cyear, cmonth = yearmonthplusoffset(cyear, cmonth, 1) elif cur_event['recur_type'] == 'month': cyear, cmonth, therecurday = getdatefield(cur_event['startdate']) while 1: cyear, cmonth = yearmonthplusoffset(cyear, cmonth, recur_freq) firstweekday, daysinmonth = calendar.monthrange(cyear, cmonth) recur_day = therecurday if daysinmonth < recur_day: recur_day = daysinmonth new_startdate = formatDate(cyear, cmonth, recur_day) if int(new_startdate) < int(datefrom): continue recurred_startdate = datetime.date(cyear, cmonth, recur_day) recurred_enddate = recurred_startdate + delta_date_len new_startdate = formatdateobject(recurred_startdate) new_enddate = formatdateobject(recurred_enddate) if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)): break clone_num += 1 clone_id = 'c%d' % clone_num events[clone_id] = cur_event.copy() events[clone_id]['id'] = clone_id events[clone_id]['startdate'] = new_startdate events[clone_id]['enddate'] = new_enddate events[clone_id]['clone'] = 1 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate) elif cur_event['recur_type'] == 'year': ryear, rmonth, rday = getdatefield(cur_event['startdate']) cyear, cmonth, cday = getdatefield(str(datefrom)) while 1: ryear += recur_freq new_startdate = formatDate(ryear, rmonth, rday) if int(new_startdate) < int(datefrom): continue if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)): break recurred_startdate = datetime.date(ryear, rmonth, rday) recurred_enddate = recurred_startdate + delta_date_len new_startdate = formatdateobject(recurred_startdate) new_enddate = formatdateobject(recurred_enddate) clone_num += 1 clone_id = 'c%d' % clone_num events[clone_id] = cur_event.copy() events[clone_id]['id'] = clone_id events[clone_id]['startdate'] = new_startdate events[clone_id]['enddate'] = new_enddate events[clone_id]['clone'] = 1 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate) else: if not (int(cur_event['enddate']) < datefrom or int(cur_event['startdate']) > dateto): events[e_id] = cur_event.copy() insertcalevents(cal_events, datefrom, dateto, e_id, cur_event['startdate'], cur_event['enddate']) # sort cal_events # store event list into global variables in order to sort them Globs.events = events for eachdate in cal_events.keys(): cal_events[eachdate].sort(comp_cal_events) # cache update if not nocache: cache_filteredevents.update(pickle.dumps(events, PICKLE_PROTOCOL)) cache_calevents.update(pickle.dumps(cal_events, PICKLE_PROTOCOL)) else: events = raw_events # store event list into global variables in order to sort them Globs.events = events Globs.labels = labels debug(u'Total %d events are loaded finally.' % len(events)) debug(u'Total %d labels are loaded finally.' % len(labels)) return events, cal_events, labels def loadEventsFromWikiPages(): events = {} labels = {} cached_event_loaded = 0 dirty = 0 eventrecord_list = [] labelrecord_list = [] eventpages = [] stored_errmsg = '' request = Globs.request formatter = Globs.formatter category = Params.category # cache configurations arena = Page(request, Globs.pagename) eventkey = 'events' labelkey = 'labels' pagelistkey = 'eventpages' errmsglistkey = 'eventcalerrormsglist' cache_events = caching.CacheEntry(request, arena, eventkey, scope='item') cache_labels = caching.CacheEntry(request, arena, labelkey, scope='item') cache_pages = caching.CacheEntry(request, arena, pagelistkey, scope='item') cache_errmsglist = caching.CacheEntry(request, arena, errmsglistkey, scope='item') # page list cache debug('Checking page list cache') # check the time at which page list cache has been created cp_mtime = cache_pages.mtime() timedelta_days = 9999 if cp_mtime: cp_date = datetime.datetime.fromtimestamp(cp_mtime) today = datetime.datetime.fromtimestamp(time.time()) datediff = today - cp_date timedelta_days = datediff.days debug('Time from page list cache built = %s' % datediff) if Globs.page_action == 'refresh' or cache_pages.needsUpdate(arena._text_filename()) or timedelta_days >= 1: categorypages = searchPages(request, category) for page in categorypages: # this is to workaround the bug in the category search returning # pages that only referance the category but are not in it # i.e. in the paramiter list for this macro if not page.page_name == request.page.page_name: formatter.pagelink(1, pagename=page.page_name) eventpages.append(page.page_name) cache_pages.update('\n'.join(eventpages).encode('utf-8')) debug('New page list is built: %d pages' % len(eventpages)) else: eventpages = cache_pages.content().decode('utf-8').split('\n') debug('Cached page list is used: %d pages' % len(eventpages)) if not Globs.page_action == 'refresh': # check the cache validity for page_name in eventpages: p = Page(request, page_name) e_ref = page_name if cache_events.needsUpdate(p._text_filename()) or cache_labels.needsUpdate(p._text_filename()) or cache_errmsglist.needsUpdate(p._text_filename()): dirty = 1 break else: dirty = 1 if dirty: # generating events dirty_local = 0 debug_records = {} eventrecordkey = 'eventrecords' labelrecordkey = 'labelrecords' errmsgkey = 'eventcalerrormsg' # fetch event records from each page in the category for page_name in eventpages: p = Page(request, page_name) e_ref = page_name cache_errmsg = caching.CacheEntry(request, p, errmsgkey, scope='item') cache_eventrecords = caching.CacheEntry(request, p, eventrecordkey, scope='item') cache_labelrecords = caching.CacheEntry(request, p, labelrecordkey, scope='item') if cache_eventrecords.needsUpdate(p._text_filename()) or cache_labelrecords.needsUpdate(p._text_filename()) or Globs.page_action == 'refresh': page_content = p.get_raw_body() eventrecords, labelrecords = getEventRecordFromPage(page_content, e_ref) debug_records[e_ref] = '%d events are fetched from %s' % (len(eventrecords), e_ref) # XXXXX #debug('events: %s' % eventrecords) #debug('labels: %s' % labelrecords) cache_eventrecords.update(pickle.dumps(eventrecords, PICKLE_PROTOCOL)) cache_labelrecords.update(pickle.dumps(labelrecords, PICKLE_PROTOCOL)) cache_errmsg.update(pickle.dumps(Globs.errormsg, PICKLE_PROTOCOL)) stored_errmsg += Globs.errormsg Globs.errormsg = '' else: try: eventrecords = pickle.loads(cache_eventrecords.content()) labelrecords = pickle.loads(cache_labelrecords.content()) Globs.errormsg = pickle.loads(cache_errmsg.content()) debug_records[e_ref] = '%d cached eventrecords are used from %s' % (len(eventrecords), e_ref) except (pickle.UnpicklingError, IOError, EOFError, ValueError): dirty = 1 page_content = p.get_raw_body() eventrecords, labelrecords = getEventRecordFromPage(page_content, e_ref) debug_records[e_ref] = '%d eventrecords are fetched from %s due to pickle error' % (len(eventrecords), e_ref) cache_eventrecords.update(pickle.dumps(eventrecords, PICKLE_PROTOCOL)) cache_labelrecords.update(pickle.dumps(labelrecords, PICKLE_PROTOCOL)) cache_errmsg.update(pickle.dumps(Globs.errormsg, PICKLE_PROTOCOL)) eventrecord_list.append(eventrecords) labelrecord_list.append(labelrecords) stored_errmsg += Globs.errormsg Globs.errormsg = '' debug('Checking event cache: it\'s dirty or requested to refresh') else: debug('Checking event cache: still valid') try: events = pickle.loads(cache_events.content()) labels = pickle.loads(cache_labels.content()) stored_errmsg = pickle.loads(cache_errmsglist.content()) cached_event_loaded = 1 debug('Cached event information is used: total %d events' % len(events)) except (pickle.UnpicklingError, IOError, EOFError, ValueError): events = {} labels = {} stored_errmsg = '' debug('Picke error at fetching cached events') # if it needs refreshed, generate events dictionary if not cached_event_loaded: # XXX: just for debugging debug('Building new event information') for page_name in eventpages: debug(debug_records[page_name]) for eventrecords in eventrecord_list: for evtrecord in eventrecords: e_id = evtrecord['id'] events[e_id] = evtrecord for labelrecords in labelrecord_list: for label in labelrecords: c_id = label['name'] if not labels.has_key(c_id): labels[c_id] = label else: stored_errmsg += u'<li>%s\n' % geterrormsg('redefined_label', label['refer'], label['name']) # after generating updated events, update the cache cache_events.update(pickle.dumps(events, PICKLE_PROTOCOL)) cache_labels.update(pickle.dumps(labels, PICKLE_PROTOCOL)) cache_errmsglist.update(pickle.dumps(stored_errmsg, PICKLE_PROTOCOL)) debug('Event information is newly built: total %d events' % len(events)) Globs.errormsg = stored_errmsg # end of updating events block return events, labels def getEventRecordFromPage(pagecontent, referpage): request = Globs.request eventrecords = [] labelrecords = [] page_bgcolor = '' page_description = '' e_num = 0 # fetch the page default bgcolor regex_page_bgcolor = r""" (?P<req_field>^[ ]+default_bgcolor::[ ]+) ( (?P<pagebgcolor>(\#[0-9a-fA-F]{6}|[a-zA-Z]+)) \s*? $ )? """ pattern = re.compile(regex_page_bgcolor, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE) match = pattern.search(pagecontent) if match: if match.group('pagebgcolor'): page_bgcolor = match.group('pagebgcolor') else: errormsg( geterrormsg('invalid_default_bgcolor', referpage) ) # fetch the page default description regex_page_description = r""" (?P<req_field>^[ ]+default_description::[ ]+) ( (?P<pagedescription>.*?) \s*? $ )? """ pattern = re.compile(regex_page_description, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE) match = pattern.search(pagecontent) if match: if match.group('pagedescription'): page_description = match.group('pagedescription') else: errormsg( geterrormsg('empty_default_description', referpage) ) # fetch the label definition regex_label_definition = r""" (?P<reqfield>^[ ]+label_def::[ ]+) ( (?P<name>[^,^:^\s]+?) [,: ]+ (?P<bgcolor>(\#[0-9a-fA-F]{6}|[a-zA-Z]+)) \s*? $ )? """ pattern = re.compile(regex_label_definition, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE) match = pattern.findall(pagecontent) if match: for matchitem in match: labelitem = {} label_name = matchitem[2] label_bgcolor = matchitem[3] if label_name and label_bgcolor: labelitem['name'] = label_name labelitem['bgcolor'] = label_bgcolor labelitem['refer'] = referpage labelrecords.append(labelitem) else: errormsg( geterrormsg('empty_label_definition', referpage) ) continue # fetch event item regex_eventitem = r""" (?P<eventitem> (?P<heading>^\s*(?P<hmarker>=+)\s(?P<eventtitle>.*?)\s(?P=hmarker) $) (?P<eventdetail> .*? (?= ^\s*(?P<nexthmarker>=+)\s(?P<nexteventtitle>.*?)\s(?P=nexthmarker) $ | \Z ) ) ) """ pattern = re.compile(regex_eventitem, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE) match = pattern.findall(pagecontent) if match: for matchitem in match: eventitem = {} eventtitle = matchitem[3] eventdetail = matchitem[4] e_headid = getheadingid(request, referpage, eventtitle) if not eventdetail: continue #debug('Examininng "%s" event from %s ..' % (eventtitle, referpage)) try: e_start_date, e_start_time, e_end_date, e_end_time, e_bgcolor, e_label, e_description, e_recur_freq, e_recur_type, e_recur_until = geteventfield(eventdetail) except EventcalError, errmsgcode: if not errmsgcode.value == 'pass': errormsg( geterrormsg(errmsgcode.value, referpage, eventtitle, e_headid) ) continue #except TypeError, ValueError: # errormsg('undefined') # continue # set default values if not e_bgcolor: e_bgcolor = page_bgcolor if not e_description: e_description = page_description e_num += 1 e_id = 'e_%s_%d' % (referpage, e_num) eventitem['id'] = e_id eventitem['title'] = eventtitle eventitem['startdate'] = e_start_date eventitem['starttime'] = e_start_time eventitem['enddate'] = e_end_date eventitem['endtime'] = e_end_time eventitem['title'] = eventtitle eventitem['refer'] = referpage eventitem['bgcolor'] = e_bgcolor eventitem['label'] = e_label eventitem['description'] = e_description eventitem['recur_freq'] = e_recur_freq eventitem['recur_type'] = e_recur_type eventitem['recur_until'] = e_recur_until try: eventitem['date_len'] = diffday(e_start_date, e_end_date) + 1 eventitem['clone'] = 0 eventitem['hid'] = e_headid if eventitem['date_len'] == 1 and e_start_time and e_end_time: eventitem['time_len'] = difftime(e_start_time, e_end_time) + 1 else: eventitem['time_len'] = 0 except EventcalError, errmsgcode: debug('Failed to add "%s" event from %s ..' % (eventtitle, referpage)) errormsg( geterrormsg(errmsgcode.value, referpage, eventtitle, e_headid) ) continue eventrecords.append(eventitem) #debug('Added "%s" event from %s ..' % (eventtitle, referpage)) return eventrecords, labelrecords def geteventfield(detail): # START DATE REGEX ---------------------------- regex_startdate = r""" (?P<reqfield>^[ ]+start::(?=[ ]+)) ( (?P<startdate> [ ]+ ( (?P<startdate1> (?P<startyear1>19\d{2} | 20\d{2} | \d{2} ) [./-] (?P<startmonth1>1[012] | 0[1-9] | [1-9]) [./-] (?P<startday1>3[01] | 0[1-9] | [12]\d | [1-9]) ) | (?P<startdate2> (?P<startmonth2>january|jan|february|feb|march|mar|april|apr|may|june|jun|july|jul|august|aug|september|sep|october|oct|november|nov|december|dec) [ ]+ (?P<startday2>3[01] | 0[1-9] | [12]\d | [1-9]) (?: st | nd | rd | th )? [ ,]+ (?P<startyear2>19\d{2} | 20\d{2} | \d{2}) ) | (?P<startdate3> (?P<startyear3>19\d{2} | 20\d{2} | \d{2} ) (?P<startmonth3>1[012] | 0[1-9]) (?P<startday3>3[01] | 0[1-9] | [12]\d) ) ) ) (?P<starttime> [ ,]+ ( (?P<starttime1> (?P<starthour1> 1[0-2] | [0]?[1-9] ) ( (?: [.:]) (?P<startminute1>[0-5]\d{0,1} | [6-9]) )? [ ]* (?P<am1> am | pm | p | a ) ) | (?P<starttime2> (?P<starthour2> | [01]\d{0,1} | 2[0-3] | [1-9]) ( (?: [.:]) (?P<startminute2>[0-5]\d{0,1} | [6-9]) )? ) | (?P<starttime3> (?P<starthour3> [01]\d | 2[0-3]) (?P<startminute3> [0-5]\d)? ) | (?P<starttime4> (?P<starthour4> 0[1-9] | 1[0-2]) (?P<startminute4> [0-5]\d)? [ ]* (?P<am4> am | pm | p | a ) ) ) )? \s*? $ )? """ # END DATE REGEX ---------------------------- regex_enddate = r""" (?P<reqfield>^[ ]+end::(?=[ ]+)) ( (?P<enddate> [ ]+ ( (?P<enddate1> (?P<endyear1>19\d{2} | 20\d{2} | \d{2} ) [./-] (?P<endmonth1>1[012] | 0[1-9] | [1-9]) [./-] (?P<endday1>3[01] | 0[1-9] | [12]\d | [1-9]) ) | (?P<enddate2> (?P<endmonth2>january|jan|february|feb|march|mar|april|apr|may|june|jun|july|jul|august|aug|september|sep|october|oct|november|nov|december|dec) [ ]+ (?P<endday2>3[01] | 0[1-9] | [12]\d | [1-9]) (?: st | nd | rd | th )? [ ,]+ (?P<endyear2>19\d{2} | 20\d{2} | \d{2}) ) | (?P<enddate3> (?P<endyear3>19\d{2} | 20\d{2} | \d{2} ) (?P<endmonth3>1[012] | 0[1-9]) (?P<endday3>3[01] | 0[1-9] | [12]\d) ) ) )? (?P<endtime> [ ,]+ ( (?P<endtime1> (?P<endhour1> 1[0-2] | [0]?[1-9] ) ( (?: [.:]) (?P<endminute1>[0-5]\d{0,1} | [6-9]) )? [ ]* (?P<am1> am | pm | p | a ) ) | (?P<endtime2> (?P<endhour2> | [01]\d{0,1} | 2[0-3] | [1-9]) ( (?: [.:]) (?P<endminute2>[0-5]\d{0,1} | [6-9]) )? ) | (?P<endtime3> (?P<endhour3> [01]\d | 2[0-3]) (?P<endminute3> [0-5]\d)? ) | (?P<endtime4> (?P<endhour4> 0[1-9] | 1[0-2]) (?P<endminute4> [0-5]\d)? [ ]* (?P<am4> am | pm | p | a ) ) ) )? \s*? $ )? """ regex_bgcolor = r""" (?P<reqfield>^[ ]+bgcolor::[ ]+) ( (?P<bgcolor>(\#[0-9a-fA-F]{6}|[a-zA-Z]+))? \s*? $ )? """ regex_description = r""" (?P<reqfield>^[ ]+description::[ ]+) ( (?P<description>.*?) \s*? $ )? """ regex_recur = r""" (?P<reqfield>^[ ]+recur::[ ]+) ( (?P<recur_freq>\d+|last) \s+ (?P<recur_type>weekday|day|week|month|year) ( \s+ (?P<recur_until_req>until) \s+ (?P<recur_until> (?P<enddate> (?P<enddate1> (?P<endyear1>19\d{2} | 20\d{2} | \d{2} ) [./-] (?P<endmonth1>1[012] | 0[1-9] | [1-9]) [./-] (?P<endday1>3[01] | 0[1-9] | [12]\d | [1-9]) ) | (?P<enddate2> (?P<endmonth2>january|jan|february|feb|march|mar|april|apr|may|june|jun|july|jul|august|aug|september|sep|october|oct|november|nov|december|dec) \s+ (?P<endday2>3[01] | 0[1-9] | [12]\d | [1-9]) (?: st | nd | rd | th )? [\s,]+ (?P<endyear2>19\d{2} | 20\d{2} | \d{2}) ) | (?P<enddate3> (?P<endyear3>19\d{2} | 20\d{2} | \d{2} ) (?P<endmonth3>1[012] | 0[1-9]) (?P<endday3>3[01] | 0[1-9] | [12]\d) ) )? )? )? \s*? $ )? """ regex_label = r""" (?P<reqfield>^[ ]+label::[ ]+) ( (?P<name>[^,^:^\s]+?) \s*? $ )? """ # need help on regular expressions for more efficient/flexible form # compile regular expression objects pattern_startdate = re.compile(regex_startdate, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE) pattern_enddate = re.compile(regex_enddate, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE) pattern_bgcolor = re.compile(regex_bgcolor, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE) pattern_label = re.compile(regex_label, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE) pattern_description = re.compile(regex_description, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE) pattern_recur = re.compile(regex_recur, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE) ##################### retrieve startdate match = pattern_startdate.search(detail) if match: if match.group('startdate'): passed = 1 # yyyy/mm/dd: 2006/05/10; 06/05/10, if match.group('startdate1'): if len(match.group('startyear1')) == 2: startyear = '20%s' % match.group('startyear1') else: startyear = match.group('startyear1') startmonth = match.group('startmonth1') startday = match.group('startday1') # M dd, yyyy: May 10, 2006; Jan 10th, 2006; Jan 10, 06 elif match.group('startdate2'): if len(match.group('startyear2')) == 2: startyear = '20%s' % match.group('startyear2') else: startyear = match.group('startyear2') startmonth = getNumericalMonth(match.group('startmonth2')) if not startmonth: raise EventcalError('invalid_startdate') startday = match.group('startday2') # yyyymmdd: 20060510, 060510 elif match.group('startdate3'): if len(match.group('startyear3')) == 2: startyear = '20%s' % match.group('startyear3') else: startyear = match.group('startyear3') startmonth = match.group('startmonth3') startday = match.group('startday3') else: if len(match.group('startdate').strip()) > 0: raise EventcalError('invalid_startdate') else: passed = 0 if passed: startdate = '%d/%02d/%02d' % (int(startyear), int(startmonth), int(startday)) else: startdate = '' else: startdate = '' if match.group('starttime'): passed = 1 # 12h with ':': 12:00; 9:00pm if match.group('starttime1'): starthour = int(match.group('starthour1')) if match.group('startminute1'): startmin = int(match.group('startminute1')) else: startmin = 0 if starthour < 12 and match.group('am1').lower().startswith('p'): starthour += 12 # 24h with ':': 12:00; 23:00 elif match.group('starttime2'): starthour = int(match.group('starthour2')) if match.group('startminute2'): startmin = int(match.group('startminute2')) else: startmin = 0 # 24h without ':': 1200; 2300 elif match.group('starttime3'): starthour = int(match.group('starthour3')) if match.group('startminute3'): startmin = int(match.group('startminute3')) else: startmin = 0 # 12h without ':': 1200; 0900pm elif match.group('starttime4'): starthour = int(match.group('starthour4')) if match.group('startminute4'): startmin = int(match.group('startminute4')) else: startmin = 0 if starthour < 12 and match.group('am4').lower().startswith('p'): starthour += 12 else: if len(match.group('starttime').strip()) > 0: raise EventcalError('invalid_starttime') else: passed = 0 if passed: starttime = '%02d:%02d' % (int(starthour), int(startmin)) else: starttime = '' else: starttime = '' if not startdate: raise EventcalError('invalid_start') else: raise EventcalError('pass') ##################### retrieve enddate match = pattern_enddate.search(detail) if match: if match.group('enddate'): passed = 1 # yyyy/mm/dd: 2006/05/10; 06/05/10, if match.group('enddate1'): if len(match.group('endyear1')) == 2: endyear = '20%s' % match.group('endyear1') else: endyear = match.group('endyear1') endmonth = match.group('endmonth1') endday = match.group('endday1') # M dd, yyyy: May 10, 2006; Jan 10th, 2006; Jan 10, 06 elif match.group('enddate2'): if len(match.group('endyear2')) == 2: endyear = '20%s' % match.group('endyear2') else: endyear = match.group('endyear2') endmonth = getNumericalMonth(match.group('endmonth2')) if not endmonth: raise EventcalError('invalid_enddate') endday = match.group('endday2') # yyyymmdd: 20060510, 060510 elif match.group('enddate3'): if len(match.group('endyear3')) == 2: endyear = '20%s' % match.group('endyear3') else: endyear = match.group('endyear3') endmonth = match.group('endmonth3') endday = match.group('endday3') else: if len(match.group('enddate').strip()) > 0: raise EventcalError('invalid_enddate') else: passed = 0 if passed: enddate = '%d/%02d/%02d' % (int(endyear), int(endmonth), int(endday)) else: enddate = '' else: enddate = '' if match.group('endtime'): passed = 1 # 12h with ':': 12:00; 9:00pm if match.group('endtime1'): endhour = int(match.group('endhour1')) if match.group('endminute1'): endmin = int(match.group('endminute1')) else: endmin = 0 if endhour < 12 and match.group('am1').lower() == 'pm': endhour += 12 # 24h with ':': 12:00; 23:00 elif match.group('endtime2'): endhour = int(match.group('endhour2')) if match.group('endminute2'): endmin = int(match.group('endminute2')) else: endmin = 0 # 24h without ':': 1200; 2300 elif match.group('endtime3'): endhour = int(match.group('endhour3')) if match.group('endminute3'): endmin = int(match.group('endminute3')) else: endmin = 0 # 12h without ':': 1200; 0900pm elif match.group('endtime4'): endhour = int(match.group('endhour4')) if match.group('endminute4'): endmin = int(match.group('endminute4')) else: endmin = 0 if endhour < 12 and match.group('am4').lower() == 'pm': endhour += 12 else: if len(match.group('endtime').strip()) > 0: raise EventcalError('invalid_endtime') else: passed = 0 if passed: endtime = '%02d:%02d' % (int(endhour), int(endmin)) else: endtime = '' else: endtime = '' if not (enddate or endtime): raise EventcalError('invalid_end') else: enddate = '' endtime = '' ##################### retrieve bgcolor match = pattern_bgcolor.search(detail) if match: if match.group('bgcolor'): bgcolor = match.group('bgcolor') else: errormsgcode('invalid_bgcolor') bgcolor = '' else: bgcolor = '' ##################### retrieve label match = pattern_label.search(detail) if match: if match.group('name'): label = match.group('name') else: errormsgcode('invalid_label') label = '' else: label = '' ##################### retrieve description match = pattern_description.search(detail) if match: if match.group('description'): description = match.group('description') else: errormsgcode('empty_description') description = '' else: description = '' ##################### retrieve recurrence match = pattern_recur.search(detail) if match: if match.group('recur_freq') and match.group('recur_type'): if match.group('recur_freq') == 'last': if match.group('recur_type') == 'weekday': recur_freq = -1 recur_type = match.group('recur_type') recur_until = match.group('recur_until') else: recur_freq = 0 recur_type = '' recur_until = '' else: recur_freq = int(match.group('recur_freq')) recur_type = match.group('recur_type') if match.group('recur_until_req'): if match.group('recur_until'): # yyyy/mm/dd: 2006/05/10; 06/05/10, if match.group('enddate1'): if len(match.group('endyear1')) == 2: endyear = '20%s' % match.group('endyear1') else: endyear = match.group('endyear1') endmonth = match.group('endmonth1') endday = match.group('endday1') # M dd, yyyy: May 10, 2006; Jan 10th, 2006; Jan 10, 06 elif match.group('enddate2'): if len(match.group('endyear2')) == 2: endyear = '20%s' % match.group('endyear2') else: endyear = match.group('endyear2') endmonth = getNumericalMonth(match.group('endmonth2')) if not endmonth: raise EventcalError('invalid_recur_until') endday = match.group('endday2') # yyyymmdd: 20060510, 060510 elif match.group('enddate3'): if len(match.group('endyear3')) == 2: endyear = '20%s' % match.group('endyear3') else: endyear = match.group('endyear3') endmonth = match.group('endmonth3') endday = match.group('endday3') else: raise EventcalError('invalid_recur_until') recur_until = '%d/%02d/%02d' % (int(endyear), int(endmonth), int(endday)) else: raise EventcalError('invalid_recur_until') else: recur_until = '' else: raise EventcalError('invalid_recur') else: recur_freq = 0 recur_type = '' recur_until = '' # check validity of each fields if (starttime or endtime): if not endtime: endtime = starttime elif not starttime: raise EventcalError('need_starttime') # if no time, it's 1-day event if not enddate: enddate = startdate try: syear, smonth, sday = getdatefield(startdate) except (TypeError, ValueError): raise EventcalError('invalid_startdate') try: eyear, emonth, eday = getdatefield(enddate) except (TypeError, ValueError): raise EventcalError('invalid_enddate') if datetime.date(syear, smonth, sday) > datetime.date(eyear, emonth, eday): raise EventcalError('enddate_precede') # format date startdate = formatDate(syear, smonth, sday) enddate = formatDate(eyear, emonth, eday) if (starttime and endtime): try: shour, smin = gettimefield(starttime) except (TypeError, ValueError): raise EventcalError('invalid_starttime') try: ehour, emin = gettimefield(endtime) except (TypeError, ValueError): raise EventcalError('invalid_endtime') if startdate == enddate: if datetime.time(shour, smin) > datetime.time(ehour, emin): raise EventcalError('endtime_precede') # format time starttime = u'%02d%02d' %(shour, smin) endtime = u'%02d%02d' %(ehour, emin) # check recurrent data event_len = diffday(startdate, enddate) if recur_freq: if recur_type == 'day': if event_len > int(recur_freq): raise EventcalError('len_recur_int') elif recur_type == 'week': if event_len > int(recur_freq) * 7: raise EventcalError('len_recur_int') elif recur_type == 'weekday': if event_len > 25: raise EventcalError('len_recur_int') elif recur_type == 'month': if event_len > int(recur_freq) * 25: raise EventcalError('len_recur_int') elif recur_type == 'year': if event_len > int(recur_freq) * 365: raise EventcalError('len_recur_int') if recur_until: try: ryear, rmonth, rday = getdatefield(recur_until) except (TypeError, ValueError): raise EventcalError('invalid_recur_until') recur_until = formatDate(ryear, rmonth, rday) if int(recur_until) < int(enddate): raise EventcalError('recur_until_precede') return startdate, starttime, enddate, endtime, bgcolor, label, description, recur_freq, recur_type, recur_until def converttext(targettext): # Converts some special characters of html to plain-text style # What else to handle? targettext = targettext.replace(u'&', '&') targettext = targettext.replace(u'>', '>') targettext = targettext.replace(u'<', '<') targettext = targettext.replace(u'\n', '<br>') targettext = targettext.replace(u'"', '"') targettext = targettext.replace(u'\t', '    ') targettext = targettext.replace(u' ', '  ') return targettext # monthly view def showeventcalendar(year, month): debug('Show Calendar: Monthly View') request = Globs.request formatter = Globs.formatter _ = request.getText wkend = Globs.wkend months= Globs.months wkdays = Globs.wkdays # get the calendar monthcal = calendar.monthcalendar(year, month) # shows current year & month html_header_curyearmonth = calhead_yearmonth(year, month, 'head_yearmonth') r7 = range(7) # shows header of week days html_header_weekdays = [] for wkday in r7: wday = _(wkdays[wkday]) html_header_weekdays.append( calhead_weekday(wday, 'head_weekday') ) html_header_weekdays = ' <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_header_weekdays) # pending events for next row next_pending = [] # gets previous, next month day_delta = datetime.timedelta(days=-1) cur_month = datetime.date(year, month, 1) prev_month = cur_month + day_delta day_delta = datetime.timedelta(days=15) cur_month_end = datetime.date(year, month, 25) next_month = cur_month_end + day_delta prev_monthcal = calendar.monthcalendar(prev_month.year, prev_month.month) next_monthcal = calendar.monthcalendar(next_month.year, next_month.month) # shows days html_week_rows = [] # set ranges of events datefrom = u'%04d%02d21' % (prev_month.year, prev_month.month) dateto = u'%04d%02d06' % (next_month.year, next_month.month) # read all the events events, cal_events, labels = loadEvents(datefrom, dateto) #debug(u' events: %s' % events) #debug(u' cal_events: %s' % cal_events) for week in monthcal: # day head rows html_headday_cols = [] html_events_rows = [] for wkday in r7: day = week[wkday] if not day: if week == monthcal[0]: nb_day = prev_monthcal[-1][wkday] else: nb_day = next_monthcal[0][wkday] html_headday_cols.append( calhead_day_nbmonth(nb_day) ) else: html_headday_cols.append( calhead_day(year, month, day, wkday) ) html_headday_row = ' <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_headday_cols) html_week_rows.append(html_headday_row) # dummy rows html_headdummy_cols = [] for wkday in r7: day = week[wkday] if not day: html_headdummy_cols.append( calshow_blankbox('head_dummy_nbmonth') ) else: html_headdummy_cols.append( calshow_blankbox('head_dummy') ) html_headdummy_cols = u'\r\n'.join(html_headdummy_cols) html_week_rows.append(' <tr>\r\n%s </tr>\r\n' % html_headdummy_cols) # pending events for next row pending = next_pending next_pending = [] # show events while 1: event_left = 7 colspan = -1 html_events_cols = [] for wkday in r7: day = week[wkday] if not day: if week == monthcal[0]: cur_date = formatDate(prev_month.year, prev_month.month, prev_monthcal[-1][wkday]) else: cur_date = formatDate(next_month.year, next_month.month, next_monthcal[0][wkday]) else: cur_date = formatDate(year, month, day) # if an event is already displayed with colspan if colspan > 0: colspan -= 1 if cal_events.has_key(cur_date) and lastevent in cal_events[cur_date]: cal_events[cur_date].remove(lastevent) continue # if there is any event for this date if cal_events.has_key(cur_date): if len(cal_events[cur_date]) > 0: # if there is any pending event in the previous week if wkday == 0 and len(pending) > 0: todo_event_id = pending.pop(0) if todo_event_id in cal_events[cur_date]: cur_event = events[todo_event_id] temp_len = diffday(cur_date, cur_event['enddate']) + 1 # calculate colspan value if (7-wkday) < temp_len: colspan = 7 - wkday next_pending.append(cur_event['id']) html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append_pending', cur_date) ) else: colspan = temp_len html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append', cur_date) ) cal_events[cur_date].remove(todo_event_id) colspan -= 1 lastevent = todo_event_id else: debug('Warning: no such event in cal_events') continue # if there is no pending event in the previous week, start a new event event_found = 0 for e_id in cal_events[cur_date]: # if the start date of the event is current date if events[e_id]['startdate'] == cur_date: cur_event = events[cal_events[cur_date].pop(cal_events[cur_date].index(e_id))] # calculate colspan value if (7-wkday) < cur_event['date_len']: colspan = 7 - wkday next_pending.append(cur_event['id']) html_events_cols.append( calshow_eventbox(cur_event, colspan, 'pending', cur_date) ) else: colspan = cur_event['date_len'] html_events_cols.append( calshow_eventbox(cur_event, colspan, '', cur_date) ) colspan -= 1 lastevent = cur_event['id'] event_found = 1 break # if the start date of the event is NOT current date else: # pending event from previous month if wkday == 0 and week == monthcal[0]: cur_event = events[cal_events[cur_date].pop(0)] temp_len = diffday(cur_date, cur_event['enddate']) + 1 # calculate colspan value if (7-wkday) < temp_len: colspan = 7 - wkday next_pending.append(cur_event['id']) html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append_pending', cur_date) ) else: colspan = temp_len html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append', cur_date) ) colspan -= 1 lastevent = cur_event['id'] event_found = 1 break # if there is no event to start if not event_found: if not day: html_events_cols.append( calshow_blankbox('cal_nbmonth') ) else: html_events_cols.append( calshow_blankbox('cal_noevent') ) event_left -= 1 else: if not day: html_events_cols.append( calshow_blankbox('cal_nbmonth') ) else: html_events_cols.append( calshow_blankbox('cal_noevent') ) event_left -= 1 # if there is NO event for this date else: if not day: html_events_cols.append( calshow_blankbox('cal_nbmonth') ) else: html_events_cols.append( calshow_blankbox('cal_noevent') ) event_left -= 1 # if no event for this entry if not event_left: # ignore the previous entry break else: html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols)) # show dummy blank slots for week height left_blank_rows = 2 - len(html_events_rows) # remove the followings if left_blank_rows > 0 and 0: for i in range(left_blank_rows): html_events_cols = [] for wkday in r7: day = week[wkday] if not day: html_events_cols.append( calshow_blankbox('cal_nbmonth') ) else: html_events_cols.append( calshow_blankbox('cal_noevent') ) html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols)) # close the week slots html_events_cols = [] for wkday in r7: day = week[wkday] if not day: html_events_cols.append( calshow_blankbox('cal_last_nbmonth') ) else: html_events_cols.append( calshow_blankbox('cal_last_noevent') ) html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols)) html_events_rows = u'\r\n'.join(html_events_rows) html_week_rows.append(html_events_rows) html_calendar_rows = u'\r\n'.join(html_week_rows) html_cal_table = [ u'\r\n<div id="eventcalendar">', u'<table class="eventcalendar" %s>' % Params.monthlywidth, u'%s' % html_header_curyearmonth, u'%s' % html_header_weekdays, u'%s' % html_calendar_rows, u'</table>', u'</div>', ] html_cal_table = u'\r\n'.join(html_cal_table) return html_cal_table # daily view def showdailyeventcalendar(year, month, day): debug('Show Calendar: Daily View') request = Globs.request formatter = Globs.formatter _ = request.getText wkend = Globs.wkend months= Globs.months wkdays = Globs.wkdays cur_date = formatDate(year, month, day) # gets previous, next month day_delta = datetime.timedelta(days=-1) cur_month = datetime.date(year, month, 1) prev_month = cur_month + day_delta day_delta = datetime.timedelta(days=15) cur_month_end = datetime.date(year, month, 25) next_month = cur_month_end + day_delta # set ranges of events datefrom = u'%04d%02d21' % (prev_month.year, prev_month.month) dateto = u'%04d%02d06' % (next_month.year, next_month.month) # read all the events events, cal_events, labels = loadEvents(datefrom, dateto) #debug(u' events: %s' % events) #debug(u' cal_events: %s' % cal_events) # calculates hour_events hour_events = {} if cal_events.has_key(cur_date): for e_id in cal_events[cur_date]: cur_event = events[e_id] if cur_event['date_len'] == 1 and cur_event['time_len'] > 0: start_hour, start_min = gettimefield(cur_event['starttime']) if not hour_events.has_key(start_hour): hour_events[start_hour] = [] hour_events[start_hour].append(e_id) #debug(u'hour_events: %s' % hour_events) # in-day events html_calendar_rows = [] html_hour_cols = {} slot_pending = {} max_num_slots = 0 hour_max_slots = {} block_slots = [] start_hour_index = 0 r24 = range(24) for hour_index in r24: html_hour_cols[hour_index] = [] hour_max_slots[hour_index] = 1 html_hour_cols[hour_index].append ( calshow_daily_hourhead(hour_index) ) if len(slot_pending) > 0 or hour_events.has_key(hour_index): #debug('start: hour_index = %d, slot_pending = %s' % (hour_index, slot_pending)) if len(slot_pending) == 0: if max_num_slots < 1: max_num_slots = 1 for hour_lines in range(start_hour_index, hour_index): hour_max_slots[hour_lines] = max_num_slots #debug('block ended: %d ~ %d, max=%d' % (start_hour_index, hour_index-1, max_num_slots)) block_slots.append(max_num_slots) max_num_slots = 0 start_hour_index = hour_index for slot_index in range(max_num_slots): if slot_pending.has_key(slot_index) and slot_pending[slot_index] > 0: if slot_pending[slot_index] == 1: del slot_pending[slot_index] else: slot_pending[slot_index] -= 1 html_hour_cols[hour_index].append ( '' ) else: if hour_events.has_key(hour_index) and len(hour_events[hour_index]) > 0: e_id = hour_events[hour_index][0] cur_event = events[hour_events[hour_index].pop(hour_events[hour_index].index(e_id))] html_hour_cols[hour_index].append ( calshow_daily_eventbox(cur_event) ) slot_pending[slot_index] = cur_event['time_len'] - 1 else: if not ((len(slot_pending) > 0 and slot_index > max(slot_pending.keys())) or len(slot_pending) == 0): html_hour_cols[hour_index].append ( calshow_blankeventbox() ) if hour_events.has_key(hour_index): for tmp_cnt in range(len(hour_events[hour_index])): e_id = hour_events[hour_index][0] cur_event = events[hour_events[hour_index].pop(hour_events[hour_index].index(e_id))] html_hour_cols[hour_index].append ( calshow_daily_eventbox(cur_event) ) slot_pending[max_num_slots] = cur_event['time_len'] - 1 if slot_pending[max_num_slots] == 0: del slot_pending[max_num_slots] max_num_slots += 1 else: html_hour_cols[hour_index].append ( calshow_blankeventbox() ) #hour_max_slots[hour_index] = 1 if max_num_slots < 1: max_num_slots = 1 for hour_lines in range(start_hour_index, hour_index): hour_max_slots[hour_lines] = max_num_slots #debug('block ended: %d ~ %d, max=%d' % (start_hour_index, hour_index-1, max_num_slots)) block_slots.append(max_num_slots) max_num_slots = 0 start_hour_index = hour_index #debug('end: hour_index = %d, slot_pending = %s' % (hour_index, slot_pending)) if max_num_slots < 1: max_num_slots = 1 for hour_lines in range(start_hour_index, 24): hour_max_slots[hour_lines] = max_num_slots #debug('block ended: %d ~ %d, max=%d' % (start_hour_index, 23, max_num_slots)) block_slots.append(max_num_slots) #debug('hour_max_slots: %s' % hour_max_slots) # calculates global colspan if len(block_slots): global_colspan = LCM(block_slots) else: global_colspan = 1 for hour_index in r24: colspan = global_colspan / hour_max_slots[hour_index] width = 96 / hour_max_slots[hour_index] left_slots = hour_max_slots[hour_index] - (len(html_hour_cols[hour_index]) - 1) if left_slots > 0: #debug('appending left %d slots: %d' % (left_slots, hour_index)) html_hour_cols[hour_index].append ( calshow_blankeventbox2( left_slots * colspan, left_slots * width ) ) html_cols = u'\r\n'.join(html_hour_cols[hour_index]) % {'colspan': colspan, 'width': u'%d%%' % width} html_cols = u'<tr>%s</tr>\r\n' % html_cols html_calendar_rows.append (html_cols) html_calendar_rows = u'\r\n'.join(html_calendar_rows) # shows current year & month html_header_curyearmonthday = calhead_yearmonthday(year, month, day, 'head_yearmonth', global_colspan) # one-day long events html_oneday_rows = [] #debug('before cal_events[cur_date] = %s' % cal_events[cur_date]) if cal_events.has_key(cur_date): if len(cal_events[cur_date]) > 0: for e_id in cal_events[cur_date]: #debug('before cal_events[cur_date] = %s' % cal_events[cur_date]) #debug('test events[%s] = %s' % (e_id, events[e_id])) if events[e_id]['time_len'] <= 0 or events[e_id]['date_len'] > 1: #cur_event = events[cal_events[cur_date].pop(cal_events[cur_date].index(e_id))] cur_event = events[e_id] if cur_event['startdate'] == cur_date: if cur_event['enddate'] == cur_date: str_status = '' else: str_status = 'pending' else: if cur_event['enddate'] == cur_date: str_status = 'append' else: str_status = 'append_pending' tmp_html = u'<tr><td width="4%%" style="border-width: 0px; "> </td>%s</tr>' % calshow_daily_eventbox2(cur_event, global_colspan, str_status, cur_date) html_oneday_rows.append( tmp_html ) #debug('after cal_events[cur_date] = %s' % cal_events[cur_date]) else: tmp_html = u'<tr><td width="4%%" style="border-width: 0px; "> </td>%s</tr>' % calshow_blankbox2('cal_daily_noevent', global_colspan) html_oneday_rows.append( tmp_html ) #debug('after cal_events[cur_date] = %s' % cal_events[cur_date]) #debug('html_oneday_rows = %s' % html_oneday_rows) html_oneday_rows = u'\r\n'.join(html_oneday_rows) html_cal_table = [ u'\r\n<div id="eventcalendar">', u'<table class="eventcalendar" %s>' % Params.dailywidth, u'<table border="0">', u'%s' % html_header_curyearmonthday, u'%s' % html_oneday_rows, u'%s' % html_calendar_rows, u'</table>', u'</td></tr>', u'</div>', ] html_cal_table = u'\r\n'.join(html_cal_table) return html_cal_table # weekly view def showweeklyeventcalendar(year, month, day): debug('Show Calendar: Weekly View') request = Globs.request formatter = Globs.formatter _ = request.getText wkend = Globs.wkend months= Globs.months wkdays = Globs.wkdays cur_date = formatDate(year, month, day) # gets previous, next month day_delta = datetime.timedelta(days=-1) cur_month = datetime.date(year, month, 1) prev_month = cur_month + day_delta day_delta = datetime.timedelta(days=15) cur_month_end = datetime.date(year, month, 25) next_month = cur_month_end + day_delta # set ranges of events datefrom = u'%04d%02d21' % (prev_month.year, prev_month.month) dateto = u'%04d%02d06' % (next_month.year, next_month.month) # read all the events events, cal_events, labels = loadEvents(datefrom, dateto) #debug(u' events: %s' % events) #debug(u' cal_events: %s' % cal_events) # calculates hour_events hour_events = {} first_date_week = getFirstDateOfWeek(year, month, day) for dayindex in range(7): hour_events[dayindex] = {} cur_date = first_date_week + datetime.timedelta(dayindex) cur_date = formatDate(cur_date.year, cur_date.month, cur_date.day) if cal_events.has_key(cur_date): for e_id in cal_events[cur_date]: cur_event = events[e_id] if cur_event['date_len'] == 1 and cur_event['time_len'] > 0: start_hour, start_min = gettimefield(cur_event['starttime']) if not hour_events[dayindex].has_key(start_hour): hour_events[dayindex][start_hour] = [] hour_events[dayindex][start_hour].append(e_id) #debug(u'hour_events: %s' % hour_events) # in-day events html_calendar_rows = [] html_hour_cols = {} slot_pending = {} max_num_slots = {} hour_max_slots = {} block_slots = {} start_hour_index = {} r24 = range(24) for hour_index in r24: html_hour_cols[hour_index] = {} hour_max_slots[hour_index] = {} #html_hour_cols[hour_index].append ( calshow_daily_hourhead(hour_index) ) for dayindex in range(7): if not max_num_slots.has_key(dayindex): max_num_slots[dayindex] = 0 if not slot_pending.has_key(dayindex): slot_pending[dayindex] = {} if not start_hour_index.has_key(dayindex): start_hour_index[dayindex] = 0 if not block_slots.has_key(dayindex): block_slots[dayindex] = [] html_hour_cols[hour_index][dayindex] = [] hour_max_slots[hour_index][dayindex] = 1 if len(slot_pending[dayindex]) > 0 or hour_events[dayindex].has_key(hour_index): #debug('start: hour_index = %d, slot_pending = %s' % (hour_index, slot_pending[dayindex])) if len(slot_pending[dayindex]) == 0: if max_num_slots[dayindex] < 1: max_num_slots[dayindex] = 1 for hour_lines in range(start_hour_index[dayindex], hour_index): hour_max_slots[hour_lines][dayindex] = max_num_slots[dayindex] #debug('block ended: %d ~ %d, max=%d' % (start_hour_index[dayindex], hour_index-1, max_num_slots[dayindex])) block_slots[dayindex].append(max_num_slots[dayindex]) max_num_slots[dayindex] = 0 start_hour_index[dayindex] = hour_index for slot_index in range(max_num_slots[dayindex]): if slot_pending[dayindex].has_key(slot_index) and slot_pending[dayindex][slot_index] > 0: if slot_pending[dayindex][slot_index] == 1: del slot_pending[dayindex][slot_index] else: slot_pending[dayindex][slot_index] -= 1 html_hour_cols[hour_index][dayindex].append ( '' ) else: if hour_events[dayindex].has_key(hour_index) and len(hour_events[dayindex][hour_index]) > 0: e_id = hour_events[dayindex][hour_index][0] cur_event = events[hour_events[dayindex][hour_index].pop(hour_events[dayindex][hour_index].index(e_id))] html_hour_cols[hour_index][dayindex].append ( calshow_weekly_eventbox(cur_event) ) slot_pending[dayindex][slot_index] = cur_event['time_len'] - 1 else: if not ((len(slot_pending[dayindex]) > 0 and slot_index > max(slot_pending[dayindex].keys())) or len(slot_pending[dayindex]) == 0): html_hour_cols[hour_index][dayindex].append ( calshow_blankeventbox() ) if hour_events[dayindex].has_key(hour_index): for tmp_cnt in range(len(hour_events[dayindex][hour_index])): e_id = hour_events[dayindex][hour_index][0] cur_event = events[hour_events[dayindex][hour_index].pop(hour_events[dayindex][hour_index].index(e_id))] html_hour_cols[hour_index][dayindex].append ( calshow_weekly_eventbox(cur_event) ) slot_pending[dayindex][max_num_slots[dayindex]] = cur_event['time_len'] - 1 if slot_pending[dayindex][max_num_slots[dayindex]] == 0: del slot_pending[dayindex][max_num_slots[dayindex]] max_num_slots[dayindex] += 1 else: html_hour_cols[hour_index][dayindex].append ( calshow_blankeventbox() ) #hour_max_slots[hour_index][dayindex] = 1 if max_num_slots[dayindex] < 1: max_num_slots[dayindex] = 1 for hour_lines in range(start_hour_index[dayindex], hour_index): hour_max_slots[hour_lines][dayindex] = max_num_slots[dayindex] #debug('block ended: %d ~ %d, max=%d' % (start_hour_index[dayindex], hour_index-1, max_num_slots[dayindex])) block_slots[dayindex].append(max_num_slots[dayindex]) max_num_slots[dayindex] = 0 start_hour_index[dayindex] = hour_index global_colspan = {} header_colspan = 0 for dayindex in range(7): if max_num_slots[dayindex] < 1: max_num_slots[dayindex] = 1 for hour_lines in range(start_hour_index[dayindex], 24): hour_max_slots[hour_lines][dayindex] = max_num_slots[dayindex] block_slots[dayindex].append(max_num_slots[dayindex]) # calculates global colspan if len(block_slots[dayindex]): global_colspan[dayindex] = LCM(block_slots[dayindex]) else: global_colspan[dayindex] = 1 header_colspan += global_colspan[dayindex] for hour_index in r24: html_cols_days = [] for dayindex in range(7): colspan = global_colspan[dayindex] / hour_max_slots[hour_index][dayindex] width = (100 - 2) / 7 / hour_max_slots[hour_index][dayindex] left_slots = hour_max_slots[hour_index][dayindex] - len(html_hour_cols[hour_index][dayindex]) if left_slots > 0: #debug('appending left %d slots: %d' % (left_slots, hour_index)) html_hour_cols[hour_index][dayindex].append ( calshow_blankeventbox2( left_slots * colspan, left_slots * width ) ) html_cols = u'\r\n'.join(html_hour_cols[hour_index][dayindex]) % {'colspan': colspan, 'width': u'%d%%' % width} html_cols_days.append(html_cols) html_cols_collected = u'\r\n'.join(html_cols_days) html_cols = u'<tr>%s\r\n%s</tr>\r\n' % (calshow_weekly_hourhead(hour_index), html_cols_collected) html_calendar_rows.append (html_cols) html_calendar_rows = u'\r\n'.join(html_calendar_rows) # shows current year & month html_header_curyearmonthday = calhead_yearmonthday2(year, month, day, 'head_yearmonth', header_colspan) # one-day long events html_oneday_rows = {} #debug('before cal_events[cur_date] = %s' % cal_events[cur_date]) #first_date_week = getFirstDateOfWeek(year, month, day) html_oneday_rows = [] while 1: html_oneday_cols = [] cnt_blank_cols = 0 pending = -1 for dayindex in range(7): if pending > 0: pending -= 1 html_oneday_cols.append('') continue else: pending = -1 cur_date = first_date_week + datetime.timedelta(dayindex) cur_date = formatDate(cur_date.year, cur_date.month, cur_date.day) if cal_events.has_key(cur_date) and len(cal_events[cur_date]) > 0: tmpcount = len(cal_events[cur_date]) for tmp_index in range(tmpcount): cur_event = events[cal_events[cur_date].pop(0)] #debug('event poped out at %s: %s' % (cur_date, cur_event)) if (cur_event['startdate'] <= cur_date and dayindex == 0) or cur_event['startdate'] == cur_date: if cur_event['time_len'] <= 0 or cur_event['date_len'] > 1: temp_len = diffday(cur_date, cur_event['enddate']) + 1 if cur_event['startdate'] == cur_date: if temp_len <= 7 - dayindex: str_status = '' else: str_status = 'pending' else: if temp_len <= 7 - dayindex: str_status = 'append' else: str_status = 'append_pending' if temp_len > 7 - dayindex: temp_len = 7 - dayindex pending = temp_len - 1 tmp_global_colspan = 0 for tmp_index in range(dayindex, dayindex+temp_len): tmp_global_colspan += global_colspan[tmp_index] #debug('event appended at %s with pending=%d: %s' % (cur_date, pending, cur_event)) html_oneday_cols.append( calshow_weekly_eventbox2(cur_event, tmp_global_colspan, 14 * temp_len, str_status, cur_date) ) break if pending < 0: html_oneday_cols.append( calshow_blankbox2('cal_weekly_noevent', global_colspan[dayindex]) ) cnt_blank_cols += 1 else: html_oneday_cols.append( calshow_blankbox2('cal_weekly_noevent', global_colspan[dayindex]) ) cnt_blank_cols += 1 if cnt_blank_cols >= 7: if len(html_oneday_rows) == 0: html_oneday_cols = u'<tr><td width="2%%" style="border-width: 0px; "> </td>%s</tr>' % u'\r\n'.join(html_oneday_cols) html_oneday_rows.append (html_oneday_cols) break else: html_oneday_cols = u'<tr><td width="2%%" style="border-width: 0px; "> </td>%s</tr>' % u'\r\n'.join(html_oneday_cols) html_oneday_rows.append (html_oneday_cols) html_date_rows = [] for dayindex in range(7): cur_date = first_date_week + datetime.timedelta(dayindex) html_date_rows.append(calhead_weeklydate(cur_date.year, cur_date.month, cur_date.day, global_colspan[dayindex])) html_date_rows = u'<tr><td width="2%%" style="border-width: 0px; "> </td>%s</tr>' % u'\r\n'.join(html_date_rows) html_oneday_rows = u'\r\n'.join(html_oneday_rows) html_cal_table = [ u'\r\n<div id="eventcalendar">', u'<table class="eventcalendar" %s>' % Params.weeklywidth, u'<table border="0">', u'%s' % html_header_curyearmonthday, u'%s' % html_date_rows, u'%s' % html_oneday_rows, u'%s' % html_calendar_rows, u'</table>', u'</td></tr>', u'</div>', ] html_cal_table = u'\r\n'.join(html_cal_table) return html_cal_table # simple view def showsimpleeventcalendar(year, month): debug('Show Calendar: Simple View') request = Globs.request formatter = Globs.formatter _ = request.getText monthstyle_us = Globs.month_style_us wkend = Globs.wkend months= Globs.months wkdays = Globs.wkdays # get the calendar monthcal = calendar.monthcalendar(year, month) # shows current year & month html_header_curyearmonth = calhead_yearmonth(year, month, 'simple_yearmonth') r7 = range(7) # shows header of week days html_header_weekdays = [] for wkday in r7: wday = wkdays[wkday] html_header_weekdays.append( calhead_weekday(wday, 'simple_weekday') ) html_header_weekdays = ' <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_header_weekdays) # gets previous, next month day_delta = datetime.timedelta(days=-1) cur_month = datetime.date(year, month, 1) prev_month = cur_month + day_delta day_delta = datetime.timedelta(days=15) cur_month_end = datetime.date(year, month, 25) next_month = cur_month_end + day_delta prev_monthcal = calendar.monthcalendar(prev_month.year, prev_month.month) next_monthcal = calendar.monthcalendar(next_month.year, next_month.month) # shows days html_week_rows = [] # set ranges of events datefrom = u'%04d%02d21' % (prev_month.year, prev_month.month) dateto = u'%04d%02d06' % (next_month.year, next_month.month) # read all the events events, cal_events, labels = loadEvents(datefrom, dateto) maketip_js = [] for week in monthcal: # day head rows html_headday_cols = [] html_events_rows = [] for wkday in r7: day = week[wkday] if not day: if week == monthcal[0]: nb_day = prev_monthcal[-1][wkday] else: nb_day = next_monthcal[0][wkday] html_headday_cols.append( simple_eventbox(year, month, day, nb_day, 'simple_nb') ) else: cur_date = formatDate(year, month, day) if cal_events.has_key(cur_date): html_headday_cols.append( simple_eventbox(year, month, day, wkday, 'simple_event') ) if monthstyle_us: tiptitle = u'%s %d, %d' % (months[month-1], day, year) else: tiptitle = u'%d / %02d / %02d' % (year, month, day) date_today = datetime.date( year, month, day ) tiptitle = u'%s (%s)' % (tiptitle, _(wkdays[date_today.weekday() - calendar.firstweekday()])) tiptext = [] for e_id in cal_events[cur_date]: cur_event = events[e_id] if cur_event['starttime']: time_string = u'(%s:%s)' % (cur_event['starttime'][:2], cur_event['starttime'][2:]) else: time_string = '' title = wikiutil.escape(cur_event['title']).replace("'","\\'") description = wikiutil.escape(cur_event['description']).replace("'","\\'") tiptext.append( u'<b>%s</b>%s %s' % (title, time_string, description) ) tiptext = u'<br>'.join(tiptext) maketip_js.append("maketip('%s','%s','%s');" % (cur_date, tiptitle, tiptext)) else: html_headday_cols.append( simple_eventbox(year, month, day, wkday, 'simple_noevent') ) html_headday_row = ' <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_headday_cols) html_week_rows.append(html_headday_row) html_calendar_rows = u'\r\n'.join(html_week_rows) html_tooltip_result = """\ <script language="JavaScript" type="text/javascript" src="%s/common/js/infobox.js"></script> <div id="infodiv" style="position:absolute; visibility:hidden; z-index:20; top:-999em; left:0px;"></div> <script language="JavaScript" type="text/javascript"> <!-- %s // --> </script> """ % (request.cfg.url_prefix_static, "\n".join(maketip_js)) html_cal_table = [ u'\r\n<div id="eventcalendar">', u'%s' % html_tooltip_result, u'<table class="simplecalendar" %s>' % Params.simplewidth, u'%s' % html_header_curyearmonth, u'%s' % html_header_weekdays, u'%s' % html_calendar_rows, u'</table>', u'</div>', ] html_cal_table = u'\r\n'.join(html_cal_table) return html_cal_table # show calendar head (year & month) def calhead_yearmonth(year, month, headclass): request = Globs.request months = Globs.months monthstyle_us = Globs.month_style_us cal_action = Globs.cal_action page_name = Globs.pagename page_url = Globs.pageurl nextyear, nextmonth = yearmonthplusoffset(year, month, 1) prevyear, prevmonth = yearmonthplusoffset(year, month, -1) prevlink = u'%s?calaction=%s&caldate=%d%02d%s' % (page_url, cal_action, prevyear, prevmonth, getquerystring(['numcal']) ) nextlink = u'%s?calaction=%s&caldate=%d%02d%s' % (page_url, cal_action, nextyear, nextmonth, getquerystring(['numcal'])) curlink = u'%s?calaction=%s&caldate=%d%02d%s' % (page_url, cal_action, year, month, getquerystring(['numcal'])) if monthstyle_us: stryearmonth = u'%s %d' % (months[month-1], year) strnextmonth = u'%s %d' % (months[nextmonth-1], nextyear) strprevmonth = u'%s %d' % (months[prevmonth-1], prevyear) else: stryearmonth = u'%d / %02d' % (year, month) strnextmonth = u'%d / %02d' % (nextyear, nextmonth) strprevmonth = u'%d / %02d' % (prevyear, prevmonth) html = [ u' <tr>', u' <td class="%s"><a href="%s" title="%s"><</a></td>' % (headclass, prevlink, strprevmonth), u' <td colspan="5" class="%s"><a href="%s" title="Go/Refresh this month">%s</a></td>' % (headclass, curlink, stryearmonth), u' <td class="%s"><a href="%s" title="%s">></a></td>' % (headclass, nextlink, strnextmonth), u' </tr>', ] return u'\r\n'.join(html) # show calendar head (year & month & day) def calhead_yearmonthday(year, month, day, headclass, colspan): request = Globs.request _ = request.getText months = Globs.months monthstyle_us = Globs.month_style_us cal_action = Globs.cal_action page_name = Globs.pagename wkdays = Globs.wkdays page_url = Globs.pageurl date_today = datetime.date( year, month, day ) prevdate = date_today - datetime.timedelta(days=1) nextdate = date_today + datetime.timedelta(days=1) prevlink = u'%s?calaction=%s&caldate=%d%02d%02d%s' % (page_url, cal_action, prevdate.year, prevdate.month, prevdate.day, getquerystring(['numcal']) ) nextlink = u'%s?calaction=%s&caldate=%d%02d%02d%s' % (page_url, cal_action, nextdate.year, nextdate.month, nextdate.day, getquerystring(['numcal'])) curlink = u'%s?calaction=%s&caldate=%d%02d%02d%s' % (page_url, cal_action, year, month, day, getquerystring(['numcal'])) if monthstyle_us: stryearmonth = u'%s %d, %d' % (months[month-1], day, year) strnextmonth = u'%s %d, %d' % (months[nextdate.month-1], nextdate.day, nextdate.year) strprevmonth = u'%s %d, %d' % (months[prevdate.month-1], prevdate.day, prevdate.year) else: stryearmonth = u'%d / %02d / %02d' % (year, month, day) strnextmonth = u'%d / %02d / %02d' % (nextdate.year, nextdate.month, nextdate.day) strprevmonth = u'%d / %02d / %02d' % (prevdate.year, prevdate.month, prevdate.day) #stryearmonth = u'%s (%s)' % (stryearmonth, _(wkdays[date_today.weekday()])) stryearmonth = u'%s (%s)' % (stryearmonth, _(wkdays[date_today.weekday() - calendar.firstweekday()])) html = [ u'<tr><td width="4%" style="border: none;"> </td>', u'<td colspan="%d" style="border: none;">' % colspan, u'<table width="95%">', u' <tr>', u' <td class="%s"><a href="%s" title="%s"><</a></td>' % (headclass, prevlink, strprevmonth), u' <td class="%s"><a href="%s" title="Go/Refresh this day">%s</a></td>' % (headclass, curlink, stryearmonth), u' <td class="%s"><a href="%s" title="%s">></a></td>' % (headclass, nextlink, strnextmonth), u' </tr>', u'</table>', u'</td></tr>', ] return u'\r\n'.join(html) # show calendar head for weekly view (year & month & day) def calhead_yearmonthday2(year, month, day, headclass, colspan): request = Globs.request _ = request.getText months = Globs.months monthstyle_us = Globs.month_style_us cal_action = Globs.cal_action page_name = Globs.pagename wkdays = Globs.wkdays page_url = Globs.pageurl date_today = datetime.date( year, month, day ) prevdate = date_today - datetime.timedelta(days=7) nextdate = date_today + datetime.timedelta(days=7) first_date_week = getFirstDateOfWeek(year, month, day) prevdate_f = first_date_week - datetime.timedelta(days=7) nextdate_f = first_date_week + datetime.timedelta(days=7) last_date_week = first_date_week + datetime.timedelta(days=6) prevdate_l = last_date_week - datetime.timedelta(days=7) nextdate_l = last_date_week + datetime.timedelta(days=7) prevlink = u'%s?calaction=%s&caldate=%d%02d%02d%s' % (page_url, cal_action, prevdate.year, prevdate.month, prevdate.day, getquerystring(['numcal']) ) nextlink = u'%s?calaction=%s&caldate=%d%02d%02d%s' % (page_url, cal_action, nextdate.year, nextdate.month, nextdate.day, getquerystring(['numcal'])) curlink = u'%s?calaction=%s&caldate=%d%02d%02d%s' % (page_url, cal_action, year, month, day, getquerystring(['numcal'])) if monthstyle_us: stryearmonth = u'%s %d, %d ~ %s %d, %d' % (months[first_date_week.month-1], first_date_week.day, first_date_week.year, months[last_date_week.month-1], last_date_week.day, last_date_week.year) strnextmonth = u'%s %d, %d ~ %s %d, %d' % (months[nextdate_f.month-1], nextdate_f.day, nextdate_f.year, months[nextdate_l.month-1], nextdate_l.day, nextdate_l.year) strprevmonth = u'%s %d, %d ~ %s %d, %d' % (months[prevdate_f.month-1], prevdate_f.day, prevdate_f.year, months[prevdate_l.month-1], prevdate_l.day, prevdate_l.year) else: stryearmonth = u'%d / %02d / %02d ~ %d / %02d / %02d' % (first_date_week.year, first_date_week.month, first_date_week.day, last_date_week.year, last_date_week.month, last_date_week.day) strnextmonth = u'%d / %02d / %02d ~ %d / %02d / %02d' % (nextdate_f.year, nextdate_f.month, nextdate_f.day, nextdate_l.year, nextdate_l.month, nextdate_l.day) strprevmonth = u'%d / %02d / %02d ~ %d / %02d / %02d' % (prevdate_f.year, prevdate_f.month, prevdate_f.day, prevdate_l.year, prevdate_l.month, prevdate_l.day) #stryearmonth = u'%s (%s)' % (stryearmonth, _(wkdays[date_today.weekday() - calendar.firstweekday()])) html = [ u'<tr><td width="2%" style="border: none;"> </td>', u'<td colspan="%d" style="border: none;">' % colspan, u'<table width="95%">', u' <tr>', u' <td class="%s"><a href="%s" title="%s"><</a></td>' % (headclass, prevlink, strprevmonth), u' <td class="%s"><a href="%s" title="Go/Refresh this week">%s</a></td>' % (headclass, curlink, stryearmonth), u' <td class="%s"><a href="%s" title="%s">></a></td>' % (headclass, nextlink, strnextmonth), u' </tr>', u'</table>', u'</td></tr>', ] return u'\r\n'.join(html) # show calendar head for weekly view (the date) def calhead_weeklydate(year, month, day, colspan): request = Globs.request _ = request.getText months = Globs.months monthstyle_us = Globs.month_style_us cal_action = Globs.cal_action page_name = Globs.pagename wkdays = Globs.wkdays page_url = Globs.pageurl date_today = datetime.date( year, month, day ) if monthstyle_us: stryearmonth = u'%s %d' % (months[month-1], day) else: stryearmonth = u'%02d / %02d' % (month, day) stryearmonth = u'%s (%s)' % (stryearmonth, _(wkdays[date_today.weekday() - calendar.firstweekday()])) curlink = u'%s?calaction=daily&caldate=%d%02d%02d' % (page_url, year, month, day) cyear, cmonth, cday = gettodaydate() if cyear == year and cmonth == month and cday == day: bgcolor = 'background-color: #FFFFAA;' else: bgcolor = '' if not Params.changeview: curlink = '#' html = [ u'<td colspan="%d" style="border-width: 2px; text-align: center; font-size: 9pt; %s">' % (colspan, bgcolor), u'<a href="%s">%s</a>' % (curlink, stryearmonth), u'</td>', ] return u'\r\n'.join(html) # show days in simple def simple_eventbox(year, month, day, wkday, boxclass): wkend = Globs.wkend if wkday == wkend: html_text = u'<font color="#aa7744">%s</font>' % day else: html_text = u'%s' % day cyear, cmonth, cday = gettodaydate() page_url = Globs.pageurl linkkey = u'%d%02d%02d' % (year, month, day) curlink = u'%s?calaction=daily&caldate=%d%02d%02d' % (page_url, year, month, day) if not Params.changeview: curlink = '#' curlink = u'<a href="%s" onMouseOver="tip(\'%s\')" onMouseOut="untip()" >%s</a>' % (curlink, linkkey, html_text) if boxclass == 'simple_nb': html = u' <td class="%s"> </td>\r\n' % boxclass else: if cyear == year and cmonth == month and cday == day: html = u' <td class="%s_today">%s</td>\r\n' % (boxclass, curlink) else: html = u' <td class="%s">%s</td>\r\n' % (boxclass, curlink) return html # show weekday def calhead_weekday(wday, headclass): if headclass == 'simple_weekday': html = u' <td class="%s">%s</td>\r\n' % (headclass, wday[0]) else: html = u' <td class="%s">%s</td>\r\n' % (headclass, wday) return html # show days of current month def calhead_day(year, month, day, wkday): request = Globs.request page_name = Globs.pagename wkend = Globs.wkend if wkday == wkend: html_text = u'<font color="#FF3300">%s</font>' % day else: html_text = u'%s' % day page_url = Globs.pageurl html_text = u'<a href="%s?calaction=daily&caldate=%d%02d%02d">%s</a>' % (page_url, year, month, day, html_text) cyear, cmonth, cday = gettodaydate() if (not wkday) and Params.showweeknumber: html_text = u'%s <font size="1" color="#aaaaaa"><i>(%d)</i></font>' % (html_text, (int(datetime.date(year, month, day).isocalendar()[1]))) if cyear == year and cmonth == month and cday == day: html = u' <td class="head_day_today"> %s</td>\r\n' % html_text else: html = u' <td class="head_day"> %s</td>\r\n' % html_text return html # show days of previous or next month def calhead_day_nbmonth(day): html = u' <td class="head_day_nbmonth"> %s</td>\r\n' % day return html # show blank calendar box def calshow_blankbox(classname): html = u' <td class="%s"> </td>' % classname return html def calshow_blankbox2(classname, colspan): html = u' <td class="%s" colspan="%d"> </td>' % (classname, colspan) return html # show eventbox def calshow_eventbox(event, colspan, status, cur_date): if status: status = u'_%s' % status title = event['title'] eid = event['id'] startdate = event['startdate'] enddate = event['enddate'] starttime = event['starttime'] endtime = event['endtime'] description = event['description'] bgcolor = event['bgcolor'] if not bgcolor: if Globs.labels: labels = Globs.labels # for backward compatibility if event.has_key('label'): if labels.has_key(event['label']): bgcolor = labels[event['label']]['bgcolor'] year, month, day = getdatefield(cur_date) if bgcolor: bgcolor = 'background-color: %s;' % bgcolor else: bgcolor = 'background-color: %s;' % Params.bgcolor if (startdate == enddate) and starttime: shour, smin = gettimefield(starttime) link = [ u'<table width="100%" style="border-width: 0px; padding: 0px; margin: 0px;"><tr>\r\n', u'<td nowrap class="cal_eventbox_time">%02d:%02d </td>\r\n' % (shour, smin), u'<td class="cal_eventbox_time_event">', u'%s' % showReferPageParsed(event, 'title', 1), u'</td>\r\n</tr></table>', ] link = u''.join(link) else: link = u'%s' % showReferPageParsed(event, 'title', 1) html = [ u' <td class="cal_eventbox" colspan="%d"><table class="cal_event">' % colspan, u' <tr><td class="cal_event%s" style="%s">%s</td></tr>' % (status, bgcolor, link), u' </table></td>', ] return u'\r\n'.join(html) # show eventbox def calshow_daily_eventbox2(event, colspan, status, cur_date): if status: status = u'_%s' % status title = event['title'] eid = event['id'] startdate = event['startdate'] enddate = event['enddate'] starttime = event['starttime'] endtime = event['endtime'] description = event['description'] bgcolor = event['bgcolor'] if not bgcolor: labels = Globs.labels # for backward compatibility if event.has_key('label'): if labels.has_key(event['label']): bgcolor = labels[event['label']]['bgcolor'] year, month, day = getdatefield(cur_date) if bgcolor: bgcolor = 'background-color: %s;' % bgcolor else: bgcolor = 'background-color: %s;' % Params.bgcolor if (startdate == enddate) and starttime: shour, smin = gettimefield(starttime) link = [ u'<table width="100%" style="border-width: 0px; padding: 0px; margin: 0px;"><tr>\r\n', u'<td width="10" nowrap style="border-width: 0px; padding: 0px; margin: 0px; text-align: left; vertical-align: top; font-size: 7pt; color: #000000;">%02d:%02d </td>\r\n' % (shour, smin), u'<td style="border-width: 0px; padding: 0px; margin: 0px; text-align: left; vertical-align: top;font-size: 8pt;">', u'%s' % showReferPageParsed(event, 'title', 1), u'</td>\r\n</tr></table>', ] link = u''.join(link) else: link = u'%s' % showReferPageParsed(event, 'title', 1) html = [ u' <td colspan="%d" style="width: 96%%; border-width: 0px; line-height: 11px;"><table class="cal_event">' % colspan, u' <tr><td class="cal_event%s" style="%s">%s</td></tr>' % (status, bgcolor, link), u' </table></td>', ] return u'\r\n'.join(html) # show eventbox def calshow_daily_eventbox(event): title = event['title'] eid = event['id'] startdate = event['startdate'] enddate = event['enddate'] starttime = event['starttime'] endtime = event['endtime'] description = event['description'] bgcolor = event['bgcolor'] time_len = event['time_len'] if not bgcolor: labels = Globs.labels # for backward compatibility if event.has_key('label'): if labels.has_key(event['label']): bgcolor = labels[event['label']]['bgcolor'] if bgcolor: bgcolor = 'background-color: %s;' % bgcolor else: bgcolor = 'background-color: %s;' % Params.bgcolor shour, smin = gettimefield(starttime) ehour, emin = gettimefield(endtime) html = [ u' <td colspan="%(colspan)d"', u' style="%s border-width: 2px; border-color: #000000; vertical-align: top; font-size: 9pt; ' % bgcolor, u' width: %(width)s;" ', u' rowspan="%(rowspan)d">' % { 'rowspan': time_len }, u' %02d:%02d ~ %02d:%02d<br>%s' % (shour, smin, ehour, emin, showReferPageParsed(event, 'title', 1)), u' </td>', ] return u'\r\n'.join(html) # show eventbox def calshow_weekly_eventbox(event): title = event['title'] eid = event['id'] startdate = event['startdate'] enddate = event['enddate'] starttime = event['starttime'] endtime = event['endtime'] description = event['description'] bgcolor = event['bgcolor'] time_len = event['time_len'] if not bgcolor: labels = Globs.labels # for backward compatibility if event.has_key('label'): if labels.has_key(event['label']): bgcolor = labels[event['label']]['bgcolor'] if bgcolor: bgcolor = 'background-color: %s;' % bgcolor else: bgcolor = 'background-color: %s;' % Params.bgcolor shour, smin = gettimefield(starttime) ehour, emin = gettimefield(endtime) html = [ u' <td colspan="%(colspan)d"', u' style="%s;' % bgcolor, u' width: %(width)s;" ', u' rowspan="%(rowspan)d"' % { 'rowspan': time_len }, u' class="cal_weekly_eventbox">', u' %s' % showReferPageParsed(event, 'title', 1), u' </td>', ] return u'\r\n'.join(html) # show blank eventbox def calshow_blankeventbox(): html = [ u' <td colspan="%(colspan)d" style="width: %(width)s;" class="cal_blankeventbox"> </td>', ] return u'\r\n'.join(html) # show eventbox def calshow_weekly_eventbox2(event, colspan, width, status, cur_date): if status: status = u'_%s' % status title = event['title'] eid = event['id'] startdate = event['startdate'] enddate = event['enddate'] starttime = event['starttime'] endtime = event['endtime'] description = event['description'] bgcolor = event['bgcolor'] year, month, day = getdatefield(cur_date) if not bgcolor: labels = Globs.labels # for backward compatibility if event.has_key('label'): if labels.has_key(event['label']): bgcolor = labels[event['label']]['bgcolor'] if bgcolor: bgcolor = 'background-color: %s;' % bgcolor else: bgcolor = 'background-color: %s;' % Params.bgcolor link = u'%s' % showReferPageParsed(event, 'title', 1) html = [ u' <td colspan="%d" style="width: %d%%;" class="cal_weekly_eventbox2"><table class="cal_event">' % (colspan, width), u' <tr><td class="cal_event%s" style="%s">%s</td></tr>' % (status, bgcolor, link), u' </table></td>', ] return u'\r\n'.join(html) # show blank eventbox def calshow_blankeventbox2(colspan, width): html = [ u' <td colspan="%(colspan)d"' % { 'colspan': colspan }, u' style="width: %(width)s;" class="cal_blankeventbox"> </td>' % { 'width': '%d%%%%' % width }, ] return u'\r\n'.join(html) def calshow_daily_hourhead(hour): if hour >= Globs.dailystart and hour <= Globs.dailyend: bgcolor = "#ffffcc" else: bgcolor = "#ffeeee" html = [ u' <td class="cal_hourhead" style="background-color: %s; width: 4%%%%;">%02d</td>' % (bgcolor, hour), ] return u'\r\n'.join(html) def calshow_weekly_hourhead(hour): if hour >= Globs.dailystart and hour <= Globs.dailyend: bgcolor = "#ffffcc" else: bgcolor = "#ffeeee" html = [ u' <td class="cal_hourhead" style="width: 2%%%%; background-color: %s; ">%02d</td>' % (bgcolor, hour), ] return u'\r\n'.join(html) def insertcalevents(cal_events, datefrom, dateto, e_id, e_start_date, e_end_date): if not (int(e_start_date) > dateto or int(e_end_date) < datefrom): e_start_date = str(max(int(e_start_date), datefrom)) e_end_date = str(min(int(e_end_date), dateto)) day_delta = datetime.timedelta(days=1) e_start_year, e_start_month, e_start_day = getdatefield(e_start_date) cur_datetime = datetime.date(e_start_year, e_start_month, e_start_day) while 1: tmp_record_date = formatdateobject(cur_datetime) if not cal_events.has_key(tmp_record_date): cal_events[tmp_record_date] = [] cal_events[tmp_record_date].append(e_id) if tmp_record_date == e_end_date: break cur_datetime = cur_datetime + day_delta # date format should be like '20051004' for 2005, Oct., 04 def diffday(date1, date2): try: year1, month1, day1 = getdatefield(date1) year2, month2, day2 = getdatefield(date2) tmp_diff = datetime.date(year2, month2, day2) - datetime.date(year1, month1, day1) except (TypeError, ValueError): raise EventcalError('invalid_date') return tmp_diff.days # time format should be like '1700' for 05:00pm def difftime(time1, time2): try: hour1, min1 = gettimefield(time1) hour2, min2 = gettimefield(time2) except (TypeError, ValueError): raise EventcalError('invalid_time') if min2 == 0 and hour2 != 0 and hour1 != hour2: hour2 -= 1 tmp_diff = hour2 - hour1 return tmp_diff def formatDate(year, month, day): # returns like: '20051004' return u'%4d%02d%02d' % (year, month, day) def formatTime(hour, min): # returns like: '1700' return u'%2d%02d' % (hour, min) def formatdateobject(obj_date): return formatDate(obj_date.year, obj_date.month, obj_date.day) def formattimeobject(obj_time): return formatTime(obj_time.hour, obj_time.minute) def debug(astring): Globs.debugmsg += u'<li>%s\n' % astring def geterrormsg(errmsgcode, refer='', title='', hid=''): if errmsgcode == 'invalid_caldate': msg = 'Warning: Invalid value for "caldate" parameter. Shows today.' elif errmsgcode == 'invalid_curdate': msg = 'Warning: Invalid value for "curdate" parameter. Shows today.' elif errmsgcode == 'invalid_numcal': msg = 'Warning: Invalid value of "numcal" parameter. Shows one.' elif errmsgcode == 'invalid_startdate': msg = 'Error: Invalid startdate format. Not handled.' elif errmsgcode == 'invalid_enddate': msg = 'Error: Invalid enddate format. Not handled.' elif errmsgcode == 'invalid_start': msg = 'Error: Invalid start date or time format. Not handled.' elif errmsgcode == 'invalid_end': msg = 'Error: Invalid end date or time format. Not handled.' elif errmsgcode == 'invalid_date': msg = 'Error: Invalid date format. Not handled.' elif errmsgcode == 'enddate_precede': msg = 'Error: Startdate should be earlier than Enddate. Not handled.' elif errmsgcode == 'invalid_starttime': msg = 'Error: Invalid starttime format. Not handled.' elif errmsgcode == 'invalid_endtime': msg = 'Error: Invalid endtime format. Not handled.' elif errmsgcode == 'invalid_time': msg = 'Error: Invalid time format. Not handled.' elif errmsgcode == 'endtime_precede': msg = 'Error: Starttime should be earlier than Endtime. Not handled.' elif errmsgcode == 'len_recur_int': msg = 'Error: Event length should be smaller than recurrence interval. Not handled.' elif errmsgcode == 'invalid_bgcolor': msg = 'Warning: Invalid bgcolor format. Ignored.' elif errmsgcode == 'invalid_label': msg = 'Warning: Invalid label format. Ignored.' elif errmsgcode == 'invalid_recur': msg = 'Error: Invalid recurrence format. Not handled.' elif errmsgcode == 'invalid_recur_until': msg = 'Error: Invalid end date (until) format of the recurrence. Not handled.' elif errmsgcode == 'empty_description': msg = 'Warning: Empty description. Ignored.' elif errmsgcode == 'invalid_default_bgcolor': msg = 'Warning: Invalid default_bgcolor format. Ignored.' elif errmsgcode == 'empty_default_description': msg = 'Warning: Empty default_description. Ignored.' elif errmsgcode == 'redefined_label': msg = 'Warning: Redefined label. Ignored.' elif errmsgcode == 'empty_label_definition': msg = 'Warning: Invalid label definition. Ignored.' elif errmsgcode == 'need_starttime': msg = 'Error: Starttime should be specified. Not handled.' elif errmsgcode == 'recur_until_precede': msg = 'Error: Enddate should be earlier than the end date (until) of recurrence. Not handled.' else: msg = 'undefined: %s' % errmsgcode if refer: msg = '%s (%s)' % (msg, getReferLink(refer, title, hid)) return msg def errormsgcode(errmsgcode): errormsg(geterrormsg(errmsgcode)) def errormsg(astring): Globs.errormsg += u'<li>%s\n' % astring def yearmonthplusoffset(year, month, offset): month = month+offset # handle offset and under/overflows - quick and dirty, yes! while month < 1: month = month + 12 year = year - 1 while month > 12: month = month - 12 year = year + 1 return year, month def formatcfgdatetime(strdate, strtime=''): if not strdate: return '' request = Globs.request if request.user.date_fmt: date_fmt = request.user.date_fmt else: date_fmt = request.cfg.date_fmt if request.user.datetime_fmt: datetime_fmt = request.user.datetime_fmt else: datetime_fmt = request.cfg.datetime_fmt ## XXX HACK datetime_fmt = datetime_fmt.replace(':%S', '') date_fmt = str(date_fmt) datetime_fmt = str(datetime_fmt) year, month, day = getdatefield(str(strdate)) if strtime: hour, min = gettimefield(str(strtime)) objdatetime = datetime.datetime(year, month, day, hour, min) return objdatetime.strftime(datetime_fmt) else: objdate = getdatetimefromstring(strdate) return objdate.strftime(date_fmt) def getdatetimefromstring(strdate): year, month, day = getdatefield(str(strdate)) return datetime.date( year, month, day ) def searchPages(request, needle): # Search the pages and return the results query = search.QueryParser().parse_query(needle) results = search.searchPages(request, query) #results.sortByPagename() return results.hits html = [] for page in results.hits: html.append(page.page_name) html = u',<br>'.join(html) return u'%s<p>%s' % (Params.category, html) def getFirstDateOfWeek(year, month, day): orgday = datetime.date(year, month, day) yearBase, week, weekday = orgday.isocalendar() baseDate = datetime.date(yearBase, 2, 1) yearBase, weekBase, dayBase = baseDate.isocalendar() days = datetime.timedelta(1-dayBase+(week-weekBase)*7) theday = baseDate + days theday -= datetime.timedelta(7 - calendar.firstweekday()) if orgday - theday >= datetime.timedelta(7): theday += datetime.timedelta(7) return theday def gcd(a,b): """Return greatest common divisor using Euclid's Algorithm.""" while b: a, b = b, a % b return a def lcm(a,b): """ Return lowest common multiple.""" return (a*b)/gcd(a,b) def LCM(terms): "Return lcm of a list of numbers." return reduce(lambda a,b: lcm(a,b), terms) def getNumericalMonth(strMonth): months = Globs.months strMonth = strMonth.lower() index = 0 for monthitem in months: index += 1 if monthitem.lower().startswith(strMonth): return index return 0 def getReferLink(refer, title='', hid=''): request = Globs.request refer_url = '%s/%s' % (request.getScriptname(), wikiutil.quoteWikinameURL(refer)) if hid: refer_url += '#%s' % hid if title: refer = '%s: "%s"' % (refer, title) return '<a href="%s">%s</a>' % (refer_url, refer)