web/views/old_calendar.py
branchtls-sprint
changeset 1700 b5b323f8a05b
parent 1688 1f16db872f92
child 1707 71b55db64269
equal deleted inserted replaced
1699:f61402624f7b 1700:b5b323f8a05b
     1 """html calendar views
     1 """html calendar views
     2 
     2 
     3 :organization: Logilab
     3 :organization: Logilab
     4 :copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     4 :copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
     5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
     6 """
     6 """
     7 
     7 
     8 from datetime import datetime, date, time, timedelta
     8 from datetime import date, time, timedelta
     9 #from datetime import datetime, RelativeDateTime, date, time, Sunday
       
    10 
     9 
    11 from logilab.mtconverter import html_escape
    10 from logilab.mtconverter import html_escape
    12 
    11 
    13 from cubicweb.interfaces import ICalendarViews
    12 from cubicweb.interfaces import ICalendarViews
    14 from cubicweb.utils import date_range
    13 from cubicweb.utils import ONEDAY, ONEWEEK, date_range, previous_month, next_month
    15 from cubicweb.selectors import implements
    14 from cubicweb.selectors import implements
    16 from cubicweb.view import EntityView
    15 from cubicweb.view import EntityView
    17 
    16 
    18 # Define some useful constants
    17 # Define some useful constants
    19 #ONE_MONTH = RelativeDateTime(months=1)
    18 ONE_MONTH = timedelta(days=31) # XXX
    20 ONE_MONTH = timedelta(days=31)
    19 # used by i18n tools
    21 TODAY = date.today()
       
    22 THIS_MONTH = TODAY.month
       
    23 THIS_YEAR = TODAY.year
       
    24 # mx.DateTime and ustrftime could be used to build WEEKDAYS
       
    25 WEEKDAYS = [_("monday"), _("tuesday"), _("wednesday"), _("thursday"),
    20 WEEKDAYS = [_("monday"), _("tuesday"), _("wednesday"), _("thursday"),
    26             _("friday"), _("saturday"), _("sunday")]
    21             _("friday"), _("saturday"), _("sunday")]
    27 
       
    28 # used by i18n tools
       
    29 MONTHNAMES = [ _('january'), _('february'), _('march'), _('april'), _('may'),
    22 MONTHNAMES = [ _('january'), _('february'), _('march'), _('april'), _('may'),
    30                _('june'), _('july'), _('august'), _('september'), _('october'),
    23                _('june'), _('july'), _('august'), _('september'), _('october'),
    31                _('november'), _('december')
    24                _('november'), _('december')
    32                ]
    25                ]
    33 
    26 
    42     NEXT = u'<a href="%s">&gt;</a>&nbsp;&nbsp;<a href="%s">&gt;&gt;</a>'
    35     NEXT = u'<a href="%s">&gt;</a>&nbsp;&nbsp;<a href="%s">&gt;&gt;</a>'
    43     NAV_HEADER = u"""<table class="calendarPageHeader">
    36     NAV_HEADER = u"""<table class="calendarPageHeader">
    44 <tr><td class="prev">%s</td><td class="next">%s</td></tr>
    37 <tr><td class="prev">%s</td><td class="next">%s</td></tr>
    45 </table>
    38 </table>
    46 """ % (PREV, NEXT)
    39 """ % (PREV, NEXT)
    47     
    40 
    48     def nav_header(self, date, smallshift=3, bigshift=9):
    41     def nav_header(self, date, smallshift=3, bigshift=9):
    49         """prints shortcut links to go to previous/next steps (month|week)"""
    42         """prints shortcut links to go to previous/next steps (month|week)"""
    50         prev1 = date - RelativeDateTime(months=smallshift)
    43         prev1 = next1 = prev2 = nex2 = date
    51         prev2 = date - RelativeDateTime(months=bigshift)
    44         prev1 = previous_month(date, smallshift)
    52         next1 = date + RelativeDateTime(months=smallshift)
    45         next1 = next_month(date, smallshift)
    53         next2 = date + RelativeDateTime(months=bigshift)
    46         prev2 = previous_month(date, bigshift)
    54         rql, vid = self.rset.printable_rql(), self.id
    47         next2 = next_month(date, bigshift)
       
    48         rql = self.rset.printable_rql()
    55         return self.NAV_HEADER % (
    49         return self.NAV_HEADER % (
    56             html_escape(self.build_url(rql=rql, vid=vid, year=prev2.year, month=prev2.month)),
    50             html_escape(self.build_url(rql=rql, vid=self.id, year=prev2.year,
    57             html_escape(self.build_url(rql=rql, vid=vid, year=prev1.year, month=prev1.month)),
    51                                        month=prev2.month)),
    58             html_escape(self.build_url(rql=rql, vid=vid, year=next1.year, month=next1.month)),
    52             html_escape(self.build_url(rql=rql, vid=self.id, year=prev1.year,
    59             html_escape(self.build_url(rql=rql, vid=vid, year=next2.year, month=next2.month)))
    53                                        month=prev1.month)),
    60         
    54             html_escape(self.build_url(rql=rql, vid=self.id, year=next1.year,
    61     
    55                                        month=next1.month)),
       
    56             html_escape(self.build_url(rql=rql, vid=self.id, year=next2.year,
       
    57                                        month=next2.month)))
       
    58 
       
    59 
    62     # Calendar building methods ##############################################
    60     # Calendar building methods ##############################################
    63     
    61 
    64     def build_calendars(self, schedule, begin, end):
    62     def build_calendars(self, schedule, begin, end):
    65         """build several HTML calendars at once, one for each month
    63         """build several HTML calendars at once, one for each month
    66         between begin and end
    64         between begin and end
    67         """
    65         """
    68         return [self.build_calendar(schedule, date)
    66         return [self.build_calendar(schedule, date)
    69                 for date in date_range(begin, end, incr=ONE_MONTH)]
    67                 for date in date_range(begin, end, incr=ONE_MONTH)]
    70     
    68 
    71     def build_calendar(self, schedule, first_day):
    69     def build_calendar(self, schedule, first_day):
    72         """method responsible for building *one* HTML calendar"""
    70         """method responsible for building *one* HTML calendar"""
    73         # FIXME  iterates between [first_day-first_day.day_of_week ;
    71         # FIXME  iterates between [first_day-first_day.day_of_week ;
    74         #                          last_day+6-last_day.day_of_week]
    72         #                          last_day+6-last_day.day_of_week]
    75         umonth = self.format_date(first_day, '%B %Y') # localized month name
    73         umonth = self.format_date(first_day, '%B %Y') # localized month name
   106         :param itemvid: which view to call to render elements in cells
   104         :param itemvid: which view to call to render elements in cells
   107 
   105 
   108         returns { day1 : { hour : [views] },
   106         returns { day1 : { hour : [views] },
   109                   day2 : { hour : [views] } ... }
   107                   day2 : { hour : [views] } ... }
   110         """
   108         """
   111         # put this here since all sub views are calling this method        
   109         # put this here since all sub views are calling this method
   112         self.req.add_css('cubicweb.calendar.css') 
   110         self.req.add_css('cubicweb.calendar.css')
   113         schedule = {}
   111         schedule = {}
   114         for row in xrange(len(self.rset.rows)):
   112         for row in xrange(len(self.rset.rows)):
   115             entity = self.entity(row)
   113             entity = self.entity(row)
   116             infos = u'<div class="event">'
   114             infos = u'<div class="event">'
   117             infos += self.view(itemvid, self.rset, row=row)
   115             infos += self.view(itemvid, self.rset, row=row)
   118             infos += u'</div>'
   116             infos += u'</div>'
   119             for date in entity.matching_dates(begin, end):
   117             for date_ in entity.matching_dates(begin, end):
   120                 day = Date(date.year, date.month, date.day)
   118                 day = date(date_.year, date_.month, date_.day)
   121                 time = Time(date.hour, date.minute, date.second) 
   119                 try:
       
   120                     dt = time(date_.hour, date_.minute, date_.second)
       
   121                 except AttributeError:
       
   122                     # date instance
       
   123                     dt = time(0, 0, 0)
   122                 schedule.setdefault(day, {})
   124                 schedule.setdefault(day, {})
   123                 schedule[day].setdefault(time, []).append(infos)
   125                 schedule[day].setdefault(dt, []).append(infos)
   124         return schedule
   126         return schedule
   125         
   127 
   126 
   128 
   127     @staticmethod
   129     @staticmethod
   128     def get_date_range(day=TODAY, shift=4):
   130     def get_date_range(day, shift=4):
   129         """returns a couple (begin, end)
   131         """returns a couple (begin, end)
   130 
   132 
   131         <begin> is the first day of current_month - shift
   133         <begin> is the first day of current_month - shift
   132         <end> is the last day of current_month + (shift+1)
   134         <end> is the last day of current_month + (shift+1)
   133         """
   135         """
   134         first_day_in_month = DateTime(day.year, day.month, 1)
   136         begin = first_day(previous_month(day, shift))
   135         begin = first_day_in_month - RelativeDateTime(months=shift)
   137         end = last_day(next_month(day, shift))
   136         end = (first_day_in_month + RelativeDateTime(months=shift+1)) - 1
       
   137         return begin, end
   138         return begin, end
   138 
       
   139 
   139 
   140     def _build_ampm_cells(self, daynum, events):
   140     def _build_ampm_cells(self, daynum, events):
   141         """create a view without any hourly details.
   141         """create a view without any hourly details.
   142 
   142 
   143         :param daynum: day of the built cell
   143         :param daynum: day of the built cell
   164 
   164 
   165 class YearCalendarView(_CalendarView):
   165 class YearCalendarView(_CalendarView):
   166     id = 'calendaryear'
   166     id = 'calendaryear'
   167     title = _('calendar (year)')
   167     title = _('calendar (year)')
   168 
   168 
   169     def call(self, year=THIS_YEAR, month=THIS_MONTH):
   169     def call(self, year=None, month=None):
   170         """this view renders a 3x3 calendars' table"""
   170         """this view renders a 3x3 calendars' table"""
   171         year = int(self.req.form.get('year', year))
   171         year = year or int(self.req.form.get('year', date.today().year))
   172         month = int(self.req.form.get('month', month))
   172         month = month or int(self.req.form.get('month', date.today().month))
   173         center_date = DateTime(year, month)
   173         center_date = date(year, month, 1)
   174         begin, end = self.get_date_range(day=center_date)
   174         begin, end = self.get_date_range(day=center_date)
   175         schedule = self._mk_schedule(begin, end)
   175         schedule = self._mk_schedule(begin, end)
   176         self.w(self.nav_header(center_date))
   176         self.w(self.nav_header(center_date))
   177         calendars = tuple(self.build_calendars(schedule, begin, end))
   177         calendars = tuple(self.build_calendars(schedule, begin, end))
   178         self.w(SMALL_CALENDARS_PAGE % calendars)
   178         self.w(SMALL_CALENDARS_PAGE % calendars)
   183     one column per month
   183     one column per month
   184     """
   184     """
   185     id = 'calendarsemester'
   185     id = 'calendarsemester'
   186     title = _('calendar (semester)')
   186     title = _('calendar (semester)')
   187 
   187 
   188     def call(self, year=THIS_YEAR, month=THIS_MONTH):
   188     def call(self, year=None, month=None):
   189         year = int(self.req.form.get('year', year))
   189         year = year or int(self.req.form.get('year', date.today().year))
   190         month = int(self.req.form.get('month', month))
   190         month = month or int(self.req.form.get('month', date.today().month))
   191         begin = DateTime(year, month) - RelativeDateTime(months=2)
   191         begin = previous_month(date(year, month, 1), 2)
   192         end = DateTime(year, month) + RelativeDateTime(months=3)
   192         end = next_month(date(year, month, 1), 3)
   193         schedule = self._mk_schedule(begin, end)
   193         schedule = self._mk_schedule(begin, end)
   194         self.w(self.nav_header(DateTime(year, month), 1, 6))
   194         self.w(self.nav_header(date(year, month, 1), 1, 6))
   195         self.w(u'<table class="semesterCalendar">')
   195         self.w(u'<table class="semesterCalendar">')
   196         self.build_calendars(schedule, begin, end)
   196         self.build_calendars(schedule, begin, end)
   197         self.w(u'</table>')
   197         self.w(u'</table>')
   198         self.w(self.nav_header(DateTime(year, month), 1, 6))
   198         self.w(self.nav_header(date(year, month, 1), 1, 6))
   199 
   199 
   200     def build_calendars(self, schedule, begin, end):
   200     def build_calendars(self, schedule, begin, end):
   201         self.w(u'<tr>')
   201         self.w(u'<tr>')
   202         rql = self.rset.printable_rql()
   202         rql = self.rset.printable_rql()
   203         for cur_month in date_range(begin, end, incr=ONE_MONTH):
   203         for cur_month in date_range(begin, end, incr=ONE_MONTH):
   212             self.w(u'<tr>')
   212             self.w(u'<tr>')
   213             for cur_month in date_range(begin, end, incr=ONE_MONTH):
   213             for cur_month in date_range(begin, end, incr=ONE_MONTH):
   214                 if day_num >= cur_month.days_in_month:
   214                 if day_num >= cur_month.days_in_month:
   215                     self.w(u'%s%s' % (NO_CELL, NO_CELL))
   215                     self.w(u'%s%s' % (NO_CELL, NO_CELL))
   216                 else:
   216                 else:
   217                     day = DateTime(cur_month.year, cur_month.month, day_num+1)
   217                     day = date(cur_month.year, cur_month.month, day_num+1)
   218                     events = schedule.get(day)
   218                     events = schedule.get(day)
   219                     self.w(u'<td>%s&nbsp;%s</td>\n' % (_(WEEKDAYS[day.day_of_week])[0].upper(), day_num+1))
   219                     self.w(u'<td>%s&nbsp;%s</td>\n' % (_(WEEKDAYS[day.day_of_week])[0].upper(), day_num+1))
   220                     self.format_day_events(day, events)
   220                     self.format_day_events(day, events)
   221             self.w(u'</tr>')
   221             self.w(u'</tr>')
   222             
   222 
   223     def format_day_events(self, day, events):
   223     def format_day_events(self, day, events):
   224         if events:
   224         if events:
   225             events = ['\n'.join(event) for event in events.values()]
   225             events = ['\n'.join(event) for event in events.values()]
   226             self.w(WEEK_CELL % '\n'.join(events))
   226             self.w(WEEK_CELL % '\n'.join(events))
   227         else:
   227         else:
   228             self.w(WEEK_EMPTY_CELL)
   228             self.w(WEEK_EMPTY_CELL)
   229         
   229 
   230 
   230 
   231 class MonthCalendarView(_CalendarView):
   231 class MonthCalendarView(_CalendarView):
   232     """this view renders a 3x1 calendars' table"""
   232     """this view renders a 3x1 calendars' table"""
   233     id = 'calendarmonth'
   233     id = 'calendarmonth'
   234     title = _('calendar (month)')
   234     title = _('calendar (month)')
   235     
   235 
   236     def call(self, year=THIS_YEAR, month=THIS_MONTH):
   236     def call(self, year=None, month=None):
   237         year = int(self.req.form.get('year', year))
   237         year = year or int(self.req.form.get('year', date.today().year))
   238         month = int(self.req.form.get('month', month))
   238         month = month or int(self.req.form.get('month', date.today().month))
   239         center_date = DateTime(year, month)
   239         center_date = date(year, month, 1)
   240         begin, end = self.get_date_range(day=center_date, shift=1)
   240         begin, end = self.get_date_range(day=center_date, shift=1)
   241         schedule = self._mk_schedule(begin, end)
   241         schedule = self._mk_schedule(begin, end)
   242         calendars = self.build_calendars(schedule, begin, end)
   242         calendars = self.build_calendars(schedule, begin, end)
   243         self.w(self.nav_header(center_date, 1, 3))
   243         self.w(self.nav_header(center_date, 1, 3))
   244         self.w(BIG_CALENDARS_PAGE % tuple(calendars))
   244         self.w(BIG_CALENDARS_PAGE % tuple(calendars))
   245         self.w(self.nav_header(center_date, 1, 3))
   245         self.w(self.nav_header(center_date, 1, 3))
   246 
   246 
   247         
   247 
   248 class WeekCalendarView(_CalendarView):
   248 class WeekCalendarView(_CalendarView):
   249     """this view renders a calendar for week events"""
   249     """this view renders a calendar for week events"""
   250     id = 'calendarweek'
   250     id = 'calendarweek'
   251     title = _('calendar (week)')
   251     title = _('calendar (week)')
   252     
   252 
   253     def call(self, year=THIS_YEAR, week=TODAY.isocalendar()[1]):
   253     def call(self, year=None, week=None):
   254         year = int(self.req.form.get('year', year))
   254         year = year or int(self.req.form.get('year', date.today().year))
   255         week = int(self.req.form.get('week', week))
   255         week = week or int(self.req.form.get('week', week,
   256         day0 = DateTime(year)
   256                                              date.today().isocalendar()[1]))
   257         first_day_of_week = (day0-day0.day_of_week) + 7*week
   257         day0 = date(year, 1, 1)
   258         begin, end = first_day_of_week-7, first_day_of_week+14
   258         first_day_of_week = day0 - day0.day_of_week*ONEDAY + ONEWEEK
       
   259         begin, end = first_day_of_week- ONEWEEK, first_day_of_week + 2*ONEWEEK
   259         schedule = self._mk_schedule(begin, end, itemvid='calendarlargeitem')
   260         schedule = self._mk_schedule(begin, end, itemvid='calendarlargeitem')
   260         self.w(self.nav_header(first_day_of_week))
   261         self.w(self.nav_header(first_day_of_week))
   261         self.w(u'<table class="weekCalendar">')
   262         self.w(u'<table class="weekCalendar">')
   262         _weeks = [(first_day_of_week-7, first_day_of_week-1),
   263         _weeks = [(first_day_of_week-ONEWEEK, first_day_of_week-ONEDAY),
   263                   (first_day_of_week, first_day_of_week+6),
   264                   (first_day_of_week, first_day_of_week+6*ONEDAY),
   264                   (first_day_of_week+7, first_day_of_week+13)]
   265                   (first_day_of_week+ONEWEEK, first_day_of_week+13*ONEDAY)]
   265         self.build_calendar(schedule, _weeks)
   266         self.build_calendar(schedule, _weeks)
   266         self.w(u'</table>')
   267         self.w(u'</table>')
   267         self.w(self.nav_header(first_day_of_week))
   268         self.w(self.nav_header(first_day_of_week))
   268  
   269 
   269     def build_calendar(self, schedule, weeks):
   270     def build_calendar(self, schedule, weeks):
   270         rql = self.rset.printable_rql()
   271         rql = self.rset.printable_rql()
   271         _ = self.req._
   272         _ = self.req._
   272         for monday, sunday in weeks:            
   273         for monday, sunday in weeks:
   273             umonth = self.format_date(monday, '%B %Y')
   274             umonth = self.format_date(monday, '%B %Y')
   274             url = self.build_url(rql=rql, vid='calendarmonth',
   275             url = self.build_url(rql=rql, vid='calendarmonth',
   275                                  year=monday.year, month=monday.month)
   276                                  year=monday.year, month=monday.month)
   276             monthlink = '<a href="%s">%s</a>' % (html_escape(url), umonth)
   277             monthlink = '<a href="%s">%s</a>' % (html_escape(url), umonth)
   277             self.w(u'<tr><th colspan="3">%s %s (%s)</th></tr>' \
   278             self.w(u'<tr><th colspan="3">%s %s (%s)</th></tr>' \
   285                     events = ['\n'.join(event) for event in events.values()]
   286                     events = ['\n'.join(event) for event in events.values()]
   286                     self.w(WEEK_CELL % '\n'.join(events))
   287                     self.w(WEEK_CELL % '\n'.join(events))
   287                 else:
   288                 else:
   288                     self.w(WEEK_EMPTY_CELL)
   289                     self.w(WEEK_EMPTY_CELL)
   289                 self.w(u'</tr>')
   290                 self.w(u'</tr>')
   290         
   291 
   291     def nav_header(self, date, smallshift=1, bigshift=3):
   292     def nav_header(self, date, smallshift=1, bigshift=3):
   292         """prints shortcut links to go to previous/next steps (month|week)"""
   293         """prints shortcut links to go to previous/next steps (month|week)"""
   293         prev1 = date - RelativeDateTime(weeks=smallshift)
   294         prev1 = date - ONEWEEK * smallshift
   294         prev2 = date - RelativeDateTime(weeks=bigshift)
   295         prev2 = date - ONEWEEK * bigshift
   295         next1 = date + RelativeDateTime(weeks=smallshift)
   296         next1 = date + ONEWEEK * smallshift
   296         next2 = date + RelativeDateTime(weeks=bigshift)
   297         next2 = date + ONEWEEK * bigshift
   297         rql, vid = self.rset.printable_rql(), self.id
   298         rql = self.rset.printable_rql()
   298         return self.NAV_HEADER % (
   299         return self.NAV_HEADER % (
   299             html_escape(self.build_url(rql=rql, vid=vid, year=prev2.year, week=prev2.isocalendar()[1])),
   300             html_escape(self.build_url(rql=rql, vid=self.id, year=prev2.year, week=prev2.isocalendar()[1])),
   300             html_escape(self.build_url(rql=rql, vid=vid, year=prev1.year, week=prev1.isocalendar()[1])),
   301             html_escape(self.build_url(rql=rql, vid=self.id, year=prev1.year, week=prev1.isocalendar()[1])),
   301             html_escape(self.build_url(rql=rql, vid=vid, year=next1.year, week=next1.isocalendar()[1])),
   302             html_escape(self.build_url(rql=rql, vid=self.id, year=next1.year, week=next1.isocalendar()[1])),
   302             html_escape(self.build_url(rql=rql, vid=vid, year=next2.year, week=next2.isocalendar()[1])))
   303             html_escape(self.build_url(rql=rql, vid=self.id, year=next2.year, week=next2.isocalendar()[1])))
   303 
   304 
   304 
   305 
   305         
   306 
   306 class AMPMYearCalendarView(YearCalendarView):
   307 class AMPMYearCalendarView(YearCalendarView):
   307     id = 'ampmcalendaryear'
   308     id = 'ampmcalendaryear'
   308     title = _('am/pm calendar (year)')
   309     title = _('am/pm calendar (year)')
   309     
   310 
   310     def build_calendar(self, schedule, first_day):
   311     def build_calendar(self, schedule, first_day):
   311         """method responsible for building *one* HTML calendar"""
   312         """method responsible for building *one* HTML calendar"""
   312         umonth = self.format_date(first_day, '%B %Y') # localized month name
   313         umonth = self.format_date(first_day, '%B %Y') # localized month name
   313         rows = [] # each row is: (am,pm), (am,pm) ... week_title
   314         rows = [] # each row is: (am,pm), (am,pm) ... week_title
   314         current_row = [(NO_CELL, NO_CELL, NO_CELL)] * first_day.day_of_week
   315         current_row = [(NO_CELL, NO_CELL, NO_CELL)] * first_day.day_of_week
   351         # tigh everything together
   352         # tigh everything together
   352         url = self.build_url(rql=rql, vid='ampmcalendarmonth',
   353         url = self.build_url(rql=rql, vid='ampmcalendarmonth',
   353                              year=first_day.year, month=first_day.month)
   354                              year=first_day.year, month=first_day.month)
   354         monthlink = '<a href="%s">%s</a>' % (html_escape(url), umonth)
   355         monthlink = '<a href="%s">%s</a>' % (html_escape(url), umonth)
   355         return CALENDAR(self.req) % (monthlink, '\n'.join(formatted_rows))
   356         return CALENDAR(self.req) % (monthlink, '\n'.join(formatted_rows))
   356         
   357 
   357 
   358 
   358 
   359 
   359 class AMPMSemesterCalendarView(SemesterCalendarView):
   360 class AMPMSemesterCalendarView(SemesterCalendarView):
   360     """this view renders a 3x1 calendars' table"""
   361     """this view renders a 3x1 calendars' table"""
   361     id = 'ampmcalendarsemester'
   362     id = 'ampmcalendarsemester'
   376             self.w(u'<tr>')
   377             self.w(u'<tr>')
   377             for cur_month in date_range(begin, end, incr=ONE_MONTH):
   378             for cur_month in date_range(begin, end, incr=ONE_MONTH):
   378                 if day_num >= cur_month.days_in_month:
   379                 if day_num >= cur_month.days_in_month:
   379                     self.w(u'%s%s%s' % (NO_CELL, NO_CELL, NO_CELL))
   380                     self.w(u'%s%s%s' % (NO_CELL, NO_CELL, NO_CELL))
   380                 else:
   381                 else:
   381                     day = DateTime(cur_month.year, cur_month.month, day_num+1)
   382                     day = date(cur_month.year, cur_month.month, day_num+1)
   382                     events = schedule.get(day)
   383                     events = schedule.get(day)
   383                     self.w(u'<td>%s&nbsp;%s</td>\n' % (_(WEEKDAYS[day.day_of_week])[0].upper(),
   384                     self.w(u'<td>%s&nbsp;%s</td>\n' % (_(WEEKDAYS[day.day_of_week])[0].upper(),
   384                                                        day_num+1))
   385                                                        day_num+1))
   385                     self.format_day_events(day, events)
   386                     self.format_day_events(day, events)
   386             self.w(u'</tr>')
   387             self.w(u'</tr>')
   387     
   388 
   388     def format_day_events(self, day, events):
   389     def format_day_events(self, day, events):
   389         if events:
   390         if events:
   390             self.w(u'\n'.join(self._build_ampm_cells(day, events)))
   391             self.w(u'\n'.join(self._build_ampm_cells(day, events)))
   391         else:
   392         else:
   392             self.w(u'%s %s'% (AMPM_EMPTY % ("amCell", "am"), 
   393             self.w(u'%s %s'% (AMPM_EMPTY % ("amCell", "am"),
   393                               AMPM_EMPTY % ("pmCell", "pm")))
   394                               AMPM_EMPTY % ("pmCell", "pm")))
   394 
   395 
   395 
   396 
   396 class AMPMMonthCalendarView(MonthCalendarView):
   397 class AMPMMonthCalendarView(MonthCalendarView):
   397     """this view renders a 3x1 calendars' table"""
   398     """this view renders a 3x1 calendars' table"""
   443         # tigh everything together
   444         # tigh everything together
   444         url = self.build_url(rql=rql, vid='ampmcalendarmonth',
   445         url = self.build_url(rql=rql, vid='ampmcalendarmonth',
   445                              year=first_day.year, month=first_day.month)
   446                              year=first_day.year, month=first_day.month)
   446         monthlink = '<a href="%s">%s</a>' % (html_escape(url),
   447         monthlink = '<a href="%s">%s</a>' % (html_escape(url),
   447                                              umonth)
   448                                              umonth)
   448         return CALENDAR(self.req) % (monthlink, '\n'.join(formatted_rows))      
   449         return CALENDAR(self.req) % (monthlink, '\n'.join(formatted_rows))
   449     
   450 
   450 
   451 
   451     
   452 
   452 class AMPMWeekCalendarView(WeekCalendarView):
   453 class AMPMWeekCalendarView(WeekCalendarView):
   453     """this view renders a 3x1 calendars' table"""
   454     """this view renders a 3x1 calendars' table"""
   454     id = 'ampmcalendarweek'
   455     id = 'ampmcalendarweek'
   455     title = _('am/pm calendar (week)')
   456     title = _('am/pm calendar (week)')
   456 
   457