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 mx.DateTime import DateTime, RelativeDateTime, Date, Time, today, Sunday |
8 from datetime import date, time, timedelta |
9 |
9 |
10 from logilab.mtconverter import html_escape |
10 from logilab.mtconverter import html_escape |
11 |
11 |
12 from cubicweb.interfaces import ICalendarViews |
12 from cubicweb.interfaces import ICalendarViews |
13 from cubicweb.common.utils import date_range |
13 from cubicweb.utils import ONEDAY, ONEWEEK, date_range, first_day, last_day, previous_month, next_month, days_in_month |
14 from cubicweb.common.selectors import implement_interface |
14 from cubicweb.selectors import implements |
15 from cubicweb.common.registerers import priority_registerer |
15 from cubicweb.view import EntityView |
16 from cubicweb.common.view import EntityView |
16 |
17 |
17 # used by i18n tools |
18 # Define some useful constants |
|
19 ONE_MONTH = RelativeDateTime(months=1) |
|
20 TODAY = today() |
|
21 THIS_MONTH = TODAY.month |
|
22 THIS_YEAR = TODAY.year |
|
23 # mx.DateTime and ustrftime could be used to build WEEKDAYS |
|
24 WEEKDAYS = [_("monday"), _("tuesday"), _("wednesday"), _("thursday"), |
18 WEEKDAYS = [_("monday"), _("tuesday"), _("wednesday"), _("thursday"), |
25 _("friday"), _("saturday"), _("sunday")] |
19 _("friday"), _("saturday"), _("sunday")] |
26 |
|
27 # used by i18n tools |
|
28 MONTHNAMES = [ _('january'), _('february'), _('march'), _('april'), _('may'), |
20 MONTHNAMES = [ _('january'), _('february'), _('march'), _('april'), _('may'), |
29 _('june'), _('july'), _('august'), _('september'), _('october'), |
21 _('june'), _('july'), _('august'), _('september'), _('october'), |
30 _('november'), _('december') |
22 _('november'), _('december') |
31 ] |
23 ] |
32 |
24 |
33 class _CalendarView(EntityView): |
25 class _CalendarView(EntityView): |
34 """base calendar view containing helpful methods to build calendar views""" |
26 """base calendar view containing helpful methods to build calendar views""" |
35 __registerer__ = priority_registerer |
27 __select__ = implements(ICalendarViews,) |
36 __selectors__ = (implement_interface,) |
|
37 accepts_interfaces = (ICalendarViews,) |
|
38 need_navigation = False |
28 need_navigation = False |
39 |
29 |
40 # Navigation building methods / views #################################### |
30 # Navigation building methods / views #################################### |
41 |
31 |
42 PREV = u'<a href="%s"><<</a> <a href="%s"><</a>' |
32 PREV = u'<a href="%s"><<</a> <a href="%s"><</a>' |
43 NEXT = u'<a href="%s">></a> <a href="%s">>></a>' |
33 NEXT = u'<a href="%s">></a> <a href="%s">>></a>' |
44 NAV_HEADER = u"""<table class="calendarPageHeader"> |
34 NAV_HEADER = u"""<table class="calendarPageHeader"> |
45 <tr><td class="prev">%s</td><td class="next">%s</td></tr> |
35 <tr><td class="prev">%s</td><td class="next">%s</td></tr> |
46 </table> |
36 </table> |
47 """ % (PREV, NEXT) |
37 """ % (PREV, NEXT) |
48 |
38 |
49 def nav_header(self, date, smallshift=3, bigshift=9): |
39 def nav_header(self, date, smallshift=3, bigshift=9): |
50 """prints shortcut links to go to previous/next steps (month|week)""" |
40 """prints shortcut links to go to previous/next steps (month|week)""" |
51 prev1 = date - RelativeDateTime(months=smallshift) |
41 prev1 = next1 = prev2 = nex2 = date |
52 prev2 = date - RelativeDateTime(months=bigshift) |
42 prev1 = previous_month(date, smallshift) |
53 next1 = date + RelativeDateTime(months=smallshift) |
43 next1 = next_month(date, smallshift) |
54 next2 = date + RelativeDateTime(months=bigshift) |
44 prev2 = previous_month(date, bigshift) |
55 rql, vid = self.rset.printable_rql(), self.id |
45 next2 = next_month(date, bigshift) |
|
46 rql = self.rset.printable_rql() |
56 return self.NAV_HEADER % ( |
47 return self.NAV_HEADER % ( |
57 html_escape(self.build_url(rql=rql, vid=vid, year=prev2.year, month=prev2.month)), |
48 html_escape(self.build_url(rql=rql, vid=self.id, year=prev2.year, |
58 html_escape(self.build_url(rql=rql, vid=vid, year=prev1.year, month=prev1.month)), |
49 month=prev2.month)), |
59 html_escape(self.build_url(rql=rql, vid=vid, year=next1.year, month=next1.month)), |
50 html_escape(self.build_url(rql=rql, vid=self.id, year=prev1.year, |
60 html_escape(self.build_url(rql=rql, vid=vid, year=next2.year, month=next2.month))) |
51 month=prev1.month)), |
61 |
52 html_escape(self.build_url(rql=rql, vid=self.id, year=next1.year, |
62 |
53 month=next1.month)), |
|
54 html_escape(self.build_url(rql=rql, vid=self.id, year=next2.year, |
|
55 month=next2.month))) |
|
56 |
|
57 |
63 # Calendar building methods ############################################## |
58 # Calendar building methods ############################################## |
64 |
59 |
65 def build_calendars(self, schedule, begin, end): |
60 def build_calendars(self, schedule, begin, end): |
66 """build several HTML calendars at once, one for each month |
61 """build several HTML calendars at once, one for each month |
67 between begin and end |
62 between begin and end |
68 """ |
63 """ |
69 return [self.build_calendar(schedule, date) |
64 return [self.build_calendar(schedule, date) |
70 for date in date_range(begin, end, incr=ONE_MONTH)] |
65 for date in date_range(begin, end, incmonth=1)] |
71 |
66 |
72 def build_calendar(self, schedule, first_day): |
67 def build_calendar(self, schedule, first_day): |
73 """method responsible for building *one* HTML calendar""" |
68 """method responsible for building *one* HTML calendar""" |
74 # FIXME iterates between [first_day-first_day.day_of_week ; |
69 # FIXME iterates between [first_day-first_day.day_of_week ; |
75 # last_day+6-last_day.day_of_week] |
70 # last_day+6-last_day.day_of_week] |
76 umonth = self.format_date(first_day, '%B %Y') # localized month name |
71 umonth = self.format_date(first_day, '%B %Y') # localized month name |
77 rows = [] |
72 rows = [] |
78 current_row = [NO_CELL] * first_day.day_of_week |
73 current_row = [NO_CELL] * first_day.weekday() |
79 for daynum in xrange(0, first_day.days_in_month): |
74 for daynum in xrange(0, days_in_month(first_day)): |
80 # build cell day |
75 # build cell day |
81 day = first_day + daynum |
76 day = first_day + timedelta(daynum) |
82 events = schedule.get(day) |
77 events = schedule.get(day) |
83 if events: |
78 if events: |
84 events = [u'\n'.join(event) for event in events.values()] |
79 events = [u'\n'.join(event) for event in events.values()] |
85 current_row.append(CELL % (daynum+1, '\n'.join(events))) |
80 current_row.append(CELL % (daynum+1, '\n'.join(events))) |
86 else: |
81 else: |
87 current_row.append(EMPTY_CELL % (daynum+1)) |
82 current_row.append(EMPTY_CELL % (daynum+1)) |
88 # store & reset current row on Sundays |
83 # store & reset current row on Sundays |
89 if day.day_of_week == Sunday: |
84 if day.weekday() == 6: |
90 rows.append(u'<tr>%s%s</tr>' % (WEEKNUM_CELL % day.iso_week[1], ''.join(current_row))) |
85 rows.append(u'<tr>%s%s</tr>' % (WEEKNUM_CELL % day.isocalendar()[1], ''.join(current_row))) |
91 current_row = [] |
86 current_row = [] |
92 current_row.extend([NO_CELL] * (Sunday-day.day_of_week)) |
87 current_row.extend([NO_CELL] * (6-day.weekday())) |
93 rql = self.rset.printable_rql() |
88 rql = self.rset.printable_rql() |
94 if day.day_of_week != Sunday: |
89 if day.weekday() != 6: |
95 rows.append(u'<tr>%s%s</tr>' % (WEEKNUM_CELL % day.iso_week[1], ''.join(current_row))) |
90 rows.append(u'<tr>%s%s</tr>' % (WEEKNUM_CELL % day.isocalendar()[1], ''.join(current_row))) |
96 url = self.build_url(rql=rql, vid='calendarmonth', |
91 url = self.build_url(rql=rql, vid='calendarmonth', |
97 year=first_day.year, month=first_day.month) |
92 year=first_day.year, month=first_day.month) |
98 monthlink = u'<a href="%s">%s</a>' % (html_escape(url), umonth) |
93 monthlink = u'<a href="%s">%s</a>' % (html_escape(url), umonth) |
99 return CALENDAR(self.req) % (monthlink, '\n'.join(rows)) |
94 return CALENDAR(self.req) % (monthlink, '\n'.join(rows)) |
100 |
95 |
184 one column per month |
181 one column per month |
185 """ |
182 """ |
186 id = 'calendarsemester' |
183 id = 'calendarsemester' |
187 title = _('calendar (semester)') |
184 title = _('calendar (semester)') |
188 |
185 |
189 def call(self, year=THIS_YEAR, month=THIS_MONTH): |
186 def call(self, year=None, month=None): |
190 year = int(self.req.form.get('year', year)) |
187 year = year or int(self.req.form.get('year', date.today().year)) |
191 month = int(self.req.form.get('month', month)) |
188 month = month or int(self.req.form.get('month', date.today().month)) |
192 begin = DateTime(year, month) - RelativeDateTime(months=2) |
189 begin = previous_month(date(year, month, 1), 2) |
193 end = DateTime(year, month) + RelativeDateTime(months=3) |
190 end = next_month(date(year, month, 1), 3) |
194 schedule = self._mk_schedule(begin, end) |
191 schedule = self._mk_schedule(begin, end) |
195 self.w(self.nav_header(DateTime(year, month), 1, 6)) |
192 self.w(self.nav_header(date(year, month, 1), 1, 6)) |
196 self.w(u'<table class="semesterCalendar">') |
193 self.w(u'<table class="semesterCalendar">') |
197 self.build_calendars(schedule, begin, end) |
194 self.build_calendars(schedule, begin, end) |
198 self.w(u'</table>') |
195 self.w(u'</table>') |
199 self.w(self.nav_header(DateTime(year, month), 1, 6)) |
196 self.w(self.nav_header(date(year, month, 1), 1, 6)) |
200 |
197 |
201 def build_calendars(self, schedule, begin, end): |
198 def build_calendars(self, schedule, begin, end): |
202 self.w(u'<tr>') |
199 self.w(u'<tr>') |
203 rql = self.rset.printable_rql() |
200 rql = self.rset.printable_rql() |
204 for cur_month in date_range(begin, end, incr=ONE_MONTH): |
201 for cur_month in date_range(begin, end, incmonth=1): |
205 umonth = u'%s %s' % (self.format_date(cur_month, '%B'), cur_month.year) |
202 umonth = u'%s %s' % (self.format_date(cur_month, '%B'), cur_month.year) |
206 url = self.build_url(rql=rql, vid=self.id, |
203 url = self.build_url(rql=rql, vid=self.id, |
207 year=cur_month.year, month=cur_month.month) |
204 year=cur_month.year, month=cur_month.month) |
208 self.w(u'<th colspan="2"><a href="%s">%s</a></th>' % (html_escape(url), |
205 self.w(u'<th colspan="2"><a href="%s">%s</a></th>' % (html_escape(url), |
209 umonth)) |
206 umonth)) |
210 self.w(u'</tr>') |
207 self.w(u'</tr>') |
211 _ = self.req._ |
208 _ = self.req._ |
212 for day_num in xrange(31): |
209 for day_num in xrange(31): |
213 self.w(u'<tr>') |
210 self.w(u'<tr>') |
214 for cur_month in date_range(begin, end, incr=ONE_MONTH): |
211 for cur_month in date_range(begin, end, incmonth=1): |
215 if day_num >= cur_month.days_in_month: |
212 if day_num >= days_in_month(cur_month): |
216 self.w(u'%s%s' % (NO_CELL, NO_CELL)) |
213 self.w(u'%s%s' % (NO_CELL, NO_CELL)) |
217 else: |
214 else: |
218 day = DateTime(cur_month.year, cur_month.month, day_num+1) |
215 day = date(cur_month.year, cur_month.month, day_num+1) |
219 events = schedule.get(day) |
216 events = schedule.get(day) |
220 self.w(u'<td>%s %s</td>\n' % (_(WEEKDAYS[day.day_of_week])[0].upper(), day_num+1)) |
217 self.w(u'<td>%s %s</td>\n' % (_(WEEKDAYS[day.weekday()])[0].upper(), day_num+1)) |
221 self.format_day_events(day, events) |
218 self.format_day_events(day, events) |
222 self.w(u'</tr>') |
219 self.w(u'</tr>') |
223 |
220 |
224 def format_day_events(self, day, events): |
221 def format_day_events(self, day, events): |
225 if events: |
222 if events: |
226 events = ['\n'.join(event) for event in events.values()] |
223 events = ['\n'.join(event) for event in events.values()] |
227 self.w(WEEK_CELL % '\n'.join(events)) |
224 self.w(WEEK_CELL % '\n'.join(events)) |
228 else: |
225 else: |
229 self.w(WEEK_EMPTY_CELL) |
226 self.w(WEEK_EMPTY_CELL) |
230 |
227 |
231 |
228 |
232 class MonthCalendarView(_CalendarView): |
229 class MonthCalendarView(_CalendarView): |
233 """this view renders a 3x1 calendars' table""" |
230 """this view renders a 3x1 calendars' table""" |
234 id = 'calendarmonth' |
231 id = 'calendarmonth' |
235 title = _('calendar (month)') |
232 title = _('calendar (month)') |
236 |
233 |
237 def call(self, year=THIS_YEAR, month=THIS_MONTH): |
234 def call(self, year=None, month=None): |
238 year = int(self.req.form.get('year', year)) |
235 year = year or int(self.req.form.get('year', date.today().year)) |
239 month = int(self.req.form.get('month', month)) |
236 month = month or int(self.req.form.get('month', date.today().month)) |
240 center_date = DateTime(year, month) |
237 center_date = date(year, month, 1) |
241 begin, end = self.get_date_range(day=center_date, shift=1) |
238 begin, end = self.get_date_range(day=center_date, shift=1) |
242 schedule = self._mk_schedule(begin, end) |
239 schedule = self._mk_schedule(begin, end) |
243 calendars = self.build_calendars(schedule, begin, end) |
240 calendars = self.build_calendars(schedule, begin, end) |
244 self.w(self.nav_header(center_date, 1, 3)) |
241 self.w(self.nav_header(center_date, 1, 3)) |
245 self.w(BIG_CALENDARS_PAGE % tuple(calendars)) |
242 self.w(BIG_CALENDARS_PAGE % tuple(calendars)) |
246 self.w(self.nav_header(center_date, 1, 3)) |
243 self.w(self.nav_header(center_date, 1, 3)) |
247 |
244 |
248 |
245 |
249 class WeekCalendarView(_CalendarView): |
246 class WeekCalendarView(_CalendarView): |
250 """this view renders a calendar for week events""" |
247 """this view renders a calendar for week events""" |
251 id = 'calendarweek' |
248 id = 'calendarweek' |
252 title = _('calendar (week)') |
249 title = _('calendar (week)') |
253 |
250 |
254 def call(self, year=THIS_YEAR, week=TODAY.iso_week[1]): |
251 def call(self, year=None, week=None): |
255 year = int(self.req.form.get('year', year)) |
252 year = year or int(self.req.form.get('year', date.today().year)) |
256 week = int(self.req.form.get('week', week)) |
253 week = week or int(self.req.form.get('week', date.today().isocalendar()[1])) |
257 day0 = DateTime(year) |
254 day0 = date(year, 1, 1) |
258 first_day_of_week = (day0-day0.day_of_week) + 7*week |
255 first_day_of_week = day0 - day0.weekday()*ONEDAY + ONEWEEK |
259 begin, end = first_day_of_week-7, first_day_of_week+14 |
256 begin, end = first_day_of_week- ONEWEEK, first_day_of_week + 2*ONEWEEK |
260 schedule = self._mk_schedule(begin, end, itemvid='calendarlargeitem') |
257 schedule = self._mk_schedule(begin, end, itemvid='calendarlargeitem') |
261 self.w(self.nav_header(first_day_of_week)) |
258 self.w(self.nav_header(first_day_of_week)) |
262 self.w(u'<table class="weekCalendar">') |
259 self.w(u'<table class="weekCalendar">') |
263 _weeks = [(first_day_of_week-7, first_day_of_week-1), |
260 _weeks = [(first_day_of_week-ONEWEEK, first_day_of_week-ONEDAY), |
264 (first_day_of_week, first_day_of_week+6), |
261 (first_day_of_week, first_day_of_week+6*ONEDAY), |
265 (first_day_of_week+7, first_day_of_week+13)] |
262 (first_day_of_week+ONEWEEK, first_day_of_week+13*ONEDAY)] |
266 self.build_calendar(schedule, _weeks) |
263 self.build_calendar(schedule, _weeks) |
267 self.w(u'</table>') |
264 self.w(u'</table>') |
268 self.w(self.nav_header(first_day_of_week)) |
265 self.w(self.nav_header(first_day_of_week)) |
269 |
266 |
270 def build_calendar(self, schedule, weeks): |
267 def build_calendar(self, schedule, weeks): |
271 rql = self.rset.printable_rql() |
268 rql = self.rset.printable_rql() |
272 _ = self.req._ |
269 _ = self.req._ |
273 for monday, sunday in weeks: |
270 for monday, sunday in weeks: |
274 umonth = self.format_date(monday, '%B %Y') |
271 umonth = self.format_date(monday, '%B %Y') |
275 url = self.build_url(rql=rql, vid='calendarmonth', |
272 url = self.build_url(rql=rql, vid='calendarmonth', |
276 year=monday.year, month=monday.month) |
273 year=monday.year, month=monday.month) |
277 monthlink = '<a href="%s">%s</a>' % (html_escape(url), umonth) |
274 monthlink = '<a href="%s">%s</a>' % (html_escape(url), umonth) |
278 self.w(u'<tr><th colspan="3">%s %s (%s)</th></tr>' \ |
275 self.w(u'<tr><th colspan="3">%s %s (%s)</th></tr>' \ |
279 % (_('week'), monday.iso_week[1], monthlink)) |
276 % (_('week'), monday.isocalendar()[1], monthlink)) |
280 for day in date_range(monday, sunday): |
277 for day in date_range(monday, sunday): |
281 self.w(u'<tr>') |
278 self.w(u'<tr>') |
282 self.w(u'<td>%s</td>' % _(WEEKDAYS[day.day_of_week])) |
279 self.w(u'<td>%s</td>' % _(WEEKDAYS[day.weekday()])) |
283 self.w(u'<td>%s</td>' % (day.strftime('%Y-%m-%d'))) |
280 self.w(u'<td>%s</td>' % (day.strftime('%Y-%m-%d'))) |
284 events = schedule.get(day) |
281 events = schedule.get(day) |
285 if events: |
282 if events: |
286 events = ['\n'.join(event) for event in events.values()] |
283 events = ['\n'.join(event) for event in events.values()] |
287 self.w(WEEK_CELL % '\n'.join(events)) |
284 self.w(WEEK_CELL % '\n'.join(events)) |
288 else: |
285 else: |
289 self.w(WEEK_EMPTY_CELL) |
286 self.w(WEEK_EMPTY_CELL) |
290 self.w(u'</tr>') |
287 self.w(u'</tr>') |
291 |
288 |
292 def nav_header(self, date, smallshift=1, bigshift=3): |
289 def nav_header(self, date, smallshift=1, bigshift=3): |
293 """prints shortcut links to go to previous/next steps (month|week)""" |
290 """prints shortcut links to go to previous/next steps (month|week)""" |
294 prev1 = date - RelativeDateTime(weeks=smallshift) |
291 prev1 = date - ONEWEEK * smallshift |
295 prev2 = date - RelativeDateTime(weeks=bigshift) |
292 prev2 = date - ONEWEEK * bigshift |
296 next1 = date + RelativeDateTime(weeks=smallshift) |
293 next1 = date + ONEWEEK * smallshift |
297 next2 = date + RelativeDateTime(weeks=bigshift) |
294 next2 = date + ONEWEEK * bigshift |
298 rql, vid = self.rset.printable_rql(), self.id |
295 rql = self.rset.printable_rql() |
299 return self.NAV_HEADER % ( |
296 return self.NAV_HEADER % ( |
300 html_escape(self.build_url(rql=rql, vid=vid, year=prev2.year, week=prev2.iso_week[1])), |
297 html_escape(self.build_url(rql=rql, vid=self.id, year=prev2.year, week=prev2.isocalendar()[1])), |
301 html_escape(self.build_url(rql=rql, vid=vid, year=prev1.year, week=prev1.iso_week[1])), |
298 html_escape(self.build_url(rql=rql, vid=self.id, year=prev1.year, week=prev1.isocalendar()[1])), |
302 html_escape(self.build_url(rql=rql, vid=vid, year=next1.year, week=next1.iso_week[1])), |
299 html_escape(self.build_url(rql=rql, vid=self.id, year=next1.year, week=next1.isocalendar()[1])), |
303 html_escape(self.build_url(rql=rql, vid=vid, year=next2.year, week=next2.iso_week[1]))) |
300 html_escape(self.build_url(rql=rql, vid=self.id, year=next2.year, week=next2.isocalendar()[1]))) |
304 |
301 |
305 |
302 |
306 |
303 |
307 class AMPMYearCalendarView(YearCalendarView): |
304 class AMPMYearCalendarView(YearCalendarView): |
308 id = 'ampmcalendaryear' |
305 id = 'ampmcalendaryear' |
309 title = _('am/pm calendar (year)') |
306 title = _('am/pm calendar (year)') |
310 |
307 |
311 def build_calendar(self, schedule, first_day): |
308 def build_calendar(self, schedule, first_day): |
312 """method responsible for building *one* HTML calendar""" |
309 """method responsible for building *one* HTML calendar""" |
313 umonth = self.format_date(first_day, '%B %Y') # localized month name |
310 umonth = self.format_date(first_day, '%B %Y') # localized month name |
314 rows = [] # each row is: (am,pm), (am,pm) ... week_title |
311 rows = [] # each row is: (am,pm), (am,pm) ... week_title |
315 current_row = [(NO_CELL, NO_CELL, NO_CELL)] * first_day.day_of_week |
312 current_row = [(NO_CELL, NO_CELL, NO_CELL)] * first_day.weekday() |
316 rql = self.rset.printable_rql() |
313 rql = self.rset.printable_rql() |
317 for daynum in xrange(0, first_day.days_in_month): |
314 for daynum in xrange(0, days_in_month(first_day)): |
318 # build cells day |
315 # build cells day |
319 day = first_day + daynum |
316 day = first_day + timedelta(daynum) |
320 events = schedule.get(day) |
317 events = schedule.get(day) |
321 if events: |
318 if events: |
322 current_row.append((AMPM_DAY % (daynum+1),) + self._build_ampm_cells(daynum, events)) |
319 current_row.append((AMPM_DAY % (daynum+1),) + self._build_ampm_cells(daynum, events)) |
323 else: |
320 else: |
324 current_row.append((AMPM_DAY % (daynum+1), |
321 current_row.append((AMPM_DAY % (daynum+1), |
325 AMPM_EMPTY % ("amCell", "am"), |
322 AMPM_EMPTY % ("amCell", "am"), |
326 AMPM_EMPTY % ("pmCell", "pm"))) |
323 AMPM_EMPTY % ("pmCell", "pm"))) |
327 # store & reset current row on Sundays |
324 # store & reset current row on Sundays |
328 if day.day_of_week == Sunday: |
325 if day.weekday() == 6: |
329 url = self.build_url(rql=rql, vid='ampmcalendarweek', |
326 url = self.build_url(rql=rql, vid='ampmcalendarweek', |
330 year=day.year, week=day.iso_week[1]) |
327 year=day.year, week=day.isocalendar()[1]) |
331 weeklink = '<a href="%s">%s</a>' % (html_escape(url), |
328 weeklink = '<a href="%s">%s</a>' % (html_escape(url), |
332 day.iso_week[1]) |
329 day.isocalendar()[1]) |
333 current_row.append(WEEKNUM_CELL % weeklink) |
330 current_row.append(WEEKNUM_CELL % weeklink) |
334 rows.append(current_row) |
331 rows.append(current_row) |
335 current_row = [] |
332 current_row = [] |
336 current_row.extend([(NO_CELL, NO_CELL, NO_CELL)] * (Sunday-day.day_of_week)) |
333 current_row.extend([(NO_CELL, NO_CELL, NO_CELL)] * (6-day.weekday())) |
337 url = self.build_url(rql=rql, vid='ampmcalendarweek', |
334 url = self.build_url(rql=rql, vid='ampmcalendarweek', |
338 year=day.year, week=day.iso_week[1]) |
335 year=day.year, week=day.isocalendar()[1]) |
339 weeklink = '<a href="%s">%s</a>' % (html_escape(url), day.iso_week[1]) |
336 weeklink = '<a href="%s">%s</a>' % (html_escape(url), day.isocalendar()[1]) |
340 current_row.append(WEEKNUM_CELL % weeklink) |
337 current_row.append(WEEKNUM_CELL % weeklink) |
341 rows.append(current_row) |
338 rows.append(current_row) |
342 # build two rows for each week: am & pm |
339 # build two rows for each week: am & pm |
343 formatted_rows = [] |
340 formatted_rows = [] |
344 for row in rows: |
341 for row in rows: |
352 # tigh everything together |
349 # tigh everything together |
353 url = self.build_url(rql=rql, vid='ampmcalendarmonth', |
350 url = self.build_url(rql=rql, vid='ampmcalendarmonth', |
354 year=first_day.year, month=first_day.month) |
351 year=first_day.year, month=first_day.month) |
355 monthlink = '<a href="%s">%s</a>' % (html_escape(url), umonth) |
352 monthlink = '<a href="%s">%s</a>' % (html_escape(url), umonth) |
356 return CALENDAR(self.req) % (monthlink, '\n'.join(formatted_rows)) |
353 return CALENDAR(self.req) % (monthlink, '\n'.join(formatted_rows)) |
357 |
354 |
358 |
355 |
359 |
356 |
360 class AMPMSemesterCalendarView(SemesterCalendarView): |
357 class AMPMSemesterCalendarView(SemesterCalendarView): |
361 """this view renders a 3x1 calendars' table""" |
358 """this view renders a 3x1 calendars' table""" |
362 id = 'ampmcalendarsemester' |
359 id = 'ampmcalendarsemester' |
363 title = _('am/pm calendar (semester)') |
360 title = _('am/pm calendar (semester)') |
364 |
361 |
365 def build_calendars(self, schedule, begin, end): |
362 def build_calendars(self, schedule, begin, end): |
366 self.w(u'<tr>') |
363 self.w(u'<tr>') |
367 rql = self.rset.printable_rql() |
364 rql = self.rset.printable_rql() |
368 for cur_month in date_range(begin, end, incr=ONE_MONTH): |
365 for cur_month in date_range(begin, end, incmonth=1): |
369 umonth = u'%s %s' % (self.format_date(cur_month, '%B'), cur_month.year) |
366 umonth = u'%s %s' % (self.format_date(cur_month, '%B'), cur_month.year) |
370 url = self.build_url(rql=rql, vid=self.id, |
367 url = self.build_url(rql=rql, vid=self.id, |
371 year=cur_month.year, month=cur_month.month) |
368 year=cur_month.year, month=cur_month.month) |
372 self.w(u'<th colspan="3"><a href="%s">%s</a></th>' % (html_escape(url), |
369 self.w(u'<th colspan="3"><a href="%s">%s</a></th>' % (html_escape(url), |
373 umonth)) |
370 umonth)) |
374 self.w(u'</tr>') |
371 self.w(u'</tr>') |
375 _ = self.req._ |
372 _ = self.req._ |
376 for day_num in xrange(31): |
373 for day_num in xrange(31): |
377 self.w(u'<tr>') |
374 self.w(u'<tr>') |
378 for cur_month in date_range(begin, end, incr=ONE_MONTH): |
375 for cur_month in date_range(begin, end, incmonth=1): |
379 if day_num >= cur_month.days_in_month: |
376 if day_num >= days_in_month(cur_month): |
380 self.w(u'%s%s%s' % (NO_CELL, NO_CELL, NO_CELL)) |
377 self.w(u'%s%s%s' % (NO_CELL, NO_CELL, NO_CELL)) |
381 else: |
378 else: |
382 day = DateTime(cur_month.year, cur_month.month, day_num+1) |
379 day = date(cur_month.year, cur_month.month, day_num+1) |
383 events = schedule.get(day) |
380 events = schedule.get(day) |
384 self.w(u'<td>%s %s</td>\n' % (_(WEEKDAYS[day.day_of_week])[0].upper(), |
381 self.w(u'<td>%s %s</td>\n' % (_(WEEKDAYS[day.weekday()])[0].upper(), |
385 day_num+1)) |
382 day_num+1)) |
386 self.format_day_events(day, events) |
383 self.format_day_events(day, events) |
387 self.w(u'</tr>') |
384 self.w(u'</tr>') |
388 |
385 |
389 def format_day_events(self, day, events): |
386 def format_day_events(self, day, events): |
390 if events: |
387 if events: |
391 self.w(u'\n'.join(self._build_ampm_cells(day, events))) |
388 self.w(u'\n'.join(self._build_ampm_cells(day, events))) |
392 else: |
389 else: |
393 self.w(u'%s %s'% (AMPM_EMPTY % ("amCell", "am"), |
390 self.w(u'%s %s'% (AMPM_EMPTY % ("amCell", "am"), |
394 AMPM_EMPTY % ("pmCell", "pm"))) |
391 AMPM_EMPTY % ("pmCell", "pm"))) |
395 |
392 |
396 |
393 |
397 class AMPMMonthCalendarView(MonthCalendarView): |
394 class AMPMMonthCalendarView(MonthCalendarView): |
398 """this view renders a 3x1 calendars' table""" |
395 """this view renders a 3x1 calendars' table""" |
401 |
398 |
402 def build_calendar(self, schedule, first_day): |
399 def build_calendar(self, schedule, first_day): |
403 """method responsible for building *one* HTML calendar""" |
400 """method responsible for building *one* HTML calendar""" |
404 umonth = self.format_date(first_day, '%B %Y') # localized month name |
401 umonth = self.format_date(first_day, '%B %Y') # localized month name |
405 rows = [] # each row is: (am,pm), (am,pm) ... week_title |
402 rows = [] # each row is: (am,pm), (am,pm) ... week_title |
406 current_row = [(NO_CELL, NO_CELL, NO_CELL)] * first_day.day_of_week |
403 current_row = [(NO_CELL, NO_CELL, NO_CELL)] * first_day.weekday() |
407 rql = self.rset.printable_rql() |
404 rql = self.rset.printable_rql() |
408 for daynum in xrange(0, first_day.days_in_month): |
405 for daynum in xrange(0, days_in_month(first_day)): |
409 # build cells day |
406 # build cells day |
410 day = first_day + daynum |
407 day = first_day + timedelta(daynum) |
411 events = schedule.get(day) |
408 events = schedule.get(day) |
412 if events: |
409 if events: |
413 current_row.append((AMPM_DAY % (daynum+1),) + self._build_ampm_cells(daynum, events)) |
410 current_row.append((AMPM_DAY % (daynum+1),) + self._build_ampm_cells(daynum, events)) |
414 else: |
411 else: |
415 current_row.append((AMPM_DAY % (daynum+1), |
412 current_row.append((AMPM_DAY % (daynum+1), |
416 AMPM_EMPTY % ("amCell", "am"), |
413 AMPM_EMPTY % ("amCell", "am"), |
417 AMPM_EMPTY % ("pmCell", "pm"))) |
414 AMPM_EMPTY % ("pmCell", "pm"))) |
418 # store & reset current row on Sundays |
415 # store & reset current row on Sundays |
419 if day.day_of_week == Sunday: |
416 if day.weekday() == 6: |
420 url = self.build_url(rql=rql, vid='ampmcalendarweek', |
417 url = self.build_url(rql=rql, vid='ampmcalendarweek', |
421 year=day.year, week=day.iso_week[1]) |
418 year=day.year, week=day.isocalendar()[1]) |
422 weeklink = '<a href="%s">%s</a>' % (html_escape(url), |
419 weeklink = '<a href="%s">%s</a>' % (html_escape(url), |
423 day.iso_week[1]) |
420 day.isocalendar()[1]) |
424 current_row.append(WEEKNUM_CELL % weeklink) |
421 current_row.append(WEEKNUM_CELL % weeklink) |
425 rows.append(current_row) |
422 rows.append(current_row) |
426 current_row = [] |
423 current_row = [] |
427 current_row.extend([(NO_CELL, NO_CELL, NO_CELL)] * (Sunday-day.day_of_week)) |
424 current_row.extend([(NO_CELL, NO_CELL, NO_CELL)] * (6-day.weekday())) |
428 url = self.build_url(rql=rql, vid='ampmcalendarweek', |
425 url = self.build_url(rql=rql, vid='ampmcalendarweek', |
429 year=day.year, week=day.iso_week[1]) |
426 year=day.year, week=day.isocalendar()[1]) |
430 weeklink = '<a href="%s">%s</a>' % (html_escape(url), |
427 weeklink = '<a href="%s">%s</a>' % (html_escape(url), |
431 day.iso_week[1]) |
428 day.isocalendar()[1]) |
432 current_row.append(WEEKNUM_CELL % weeklink) |
429 current_row.append(WEEKNUM_CELL % weeklink) |
433 rows.append(current_row) |
430 rows.append(current_row) |
434 # build two rows for each week: am & pm |
431 # build two rows for each week: am & pm |
435 formatted_rows = [] |
432 formatted_rows = [] |
436 for row in rows: |
433 for row in rows: |