13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
14 # details. |
14 # details. |
15 # |
15 # |
16 # You should have received a copy of the GNU Lesser General Public License along |
16 # You should have received a copy of the GNU Lesser General Public License along |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
18 """html calendar views |
18 """html calendar views""" |
19 |
|
20 """ |
|
21 |
19 |
22 from datetime import date, time, timedelta |
20 from datetime import date, time, timedelta |
23 |
21 |
24 from logilab.mtconverter import xml_escape |
22 from logilab.mtconverter import xml_escape |
25 from logilab.common.date import (ONEDAY, ONEWEEK, days_in_month, previous_month, |
23 from logilab.common.date import (ONEDAY, ONEWEEK, days_in_month, previous_month, |
26 next_month, first_day, last_day, date_range) |
24 next_month, first_day, last_day, date_range) |
27 |
25 |
28 from cubicweb.interfaces import ICalendarViews |
26 from cubicweb.interfaces import ICalendarViews |
29 from cubicweb.selectors import implements |
27 from cubicweb.selectors import implements, adaptable |
30 from cubicweb.view import EntityView |
28 from cubicweb.view import EntityView, EntityAdapter, implements_adapter_compat |
|
29 |
|
30 class ICalendarViewsAdapter(EntityAdapter): |
|
31 """calendar views interface""" |
|
32 __regid__ = 'ICalendarViews' |
|
33 __select__ = implements(ICalendarViews) # XXX for bw compat, should be abstract |
|
34 |
|
35 @implements_adapter_compat('ICalendarViews') |
|
36 def matching_dates(self, begin, end): |
|
37 """ |
|
38 :param begin: day considered as begin of the range (`DateTime`) |
|
39 :param end: day considered as end of the range (`DateTime`) |
|
40 |
|
41 :return: |
|
42 a list of dates (`DateTime`) in the range [`begin`, `end`] on which |
|
43 this entity apply |
|
44 """ |
|
45 raise NotImplementedError |
31 |
46 |
32 # used by i18n tools |
47 # used by i18n tools |
33 WEEKDAYS = [_("monday"), _("tuesday"), _("wednesday"), _("thursday"), |
48 WEEKDAYS = [_("monday"), _("tuesday"), _("wednesday"), _("thursday"), |
34 _("friday"), _("saturday"), _("sunday")] |
49 _("friday"), _("saturday"), _("sunday")] |
35 MONTHNAMES = [ _('january'), _('february'), _('march'), _('april'), _('may'), |
50 MONTHNAMES = [ _('january'), _('february'), _('march'), _('april'), _('may'), |
37 _('november'), _('december') |
52 _('november'), _('december') |
38 ] |
53 ] |
39 |
54 |
40 class _CalendarView(EntityView): |
55 class _CalendarView(EntityView): |
41 """base calendar view containing helpful methods to build calendar views""" |
56 """base calendar view containing helpful methods to build calendar views""" |
42 __select__ = implements(ICalendarViews,) |
57 __select__ = adaptable('ICalendarViews') |
43 paginable = False |
58 paginable = False |
44 |
59 |
45 # Navigation building methods / views #################################### |
60 # Navigation building methods / views #################################### |
46 |
61 |
47 PREV = u'<a href="%s"><<</a>  <a href="%s"><</a>' |
62 PREV = u'<a href="%s"><<</a>  <a href="%s"><</a>' |
124 for row in xrange(len(self.cw_rset.rows)): |
139 for row in xrange(len(self.cw_rset.rows)): |
125 entity = self.cw_rset.get_entity(row, 0) |
140 entity = self.cw_rset.get_entity(row, 0) |
126 infos = u'<div class="event">' |
141 infos = u'<div class="event">' |
127 infos += self._cw.view(itemvid, self.cw_rset, row=row) |
142 infos += self._cw.view(itemvid, self.cw_rset, row=row) |
128 infos += u'</div>' |
143 infos += u'</div>' |
129 for date_ in entity.matching_dates(begin, end): |
144 for date_ in entity.cw_adapt_to('ICalendarViews').matching_dates(begin, end): |
130 day = date(date_.year, date_.month, date_.day) |
145 day = date(date_.year, date_.month, date_.day) |
131 try: |
146 try: |
132 dt = time(date_.hour, date_.minute, date_.second) |
147 dt = time(date_.hour, date_.minute, date_.second) |
133 except AttributeError: |
148 except AttributeError: |
134 # date instance |
149 # date instance |
286 url = self._cw.build_url(rql=rql, vid='calendarmonth', |
301 url = self._cw.build_url(rql=rql, vid='calendarmonth', |
287 year=monday.year, month=monday.month) |
302 year=monday.year, month=monday.month) |
288 monthlink = '<a href="%s">%s</a>' % (xml_escape(url), umonth) |
303 monthlink = '<a href="%s">%s</a>' % (xml_escape(url), umonth) |
289 self.w(u'<tr><th colspan="3">%s %s (%s)</th></tr>' \ |
304 self.w(u'<tr><th colspan="3">%s %s (%s)</th></tr>' \ |
290 % (_('week'), monday.isocalendar()[1], monthlink)) |
305 % (_('week'), monday.isocalendar()[1], monthlink)) |
291 for day in date_range(monday, sunday): |
306 for day in date_range(monday, sunday+ONEDAY): |
292 self.w(u'<tr>') |
307 self.w(u'<tr>') |
293 self.w(u'<td>%s</td>' % _(WEEKDAYS[day.weekday()])) |
308 self.w(u'<td>%s</td>' % _(WEEKDAYS[day.weekday()])) |
294 self.w(u'<td>%s</td>' % (day.strftime('%Y-%m-%d'))) |
309 self.w(u'<td>%s</td>' % (day.strftime('%Y-%m-%d'))) |
295 events = schedule.get(day) |
310 events = schedule.get(day) |
296 if events: |
311 if events: |
476 year=monday.year, month=monday.month) |
491 year=monday.year, month=monday.month) |
477 monthlink = '<a href="%s">%s</a>' % (xml_escape(url), umonth) |
492 monthlink = '<a href="%s">%s</a>' % (xml_escape(url), umonth) |
478 w(u'<tr>%s</tr>' % ( |
493 w(u'<tr>%s</tr>' % ( |
479 WEEK_TITLE % (_('week'), monday.isocalendar()[1], monthlink))) |
494 WEEK_TITLE % (_('week'), monday.isocalendar()[1], monthlink))) |
480 w(u'<tr><th>%s</th><th> </th></tr>'% _(u'Date')) |
495 w(u'<tr><th>%s</th><th> </th></tr>'% _(u'Date')) |
481 for day in date_range(monday, sunday): |
496 for day in date_range(monday, sunday+ONEDAY): |
482 events = schedule.get(day) |
497 events = schedule.get(day) |
483 style = day.weekday() % 2 and "even" or "odd" |
498 style = day.weekday() % 2 and "even" or "odd" |
484 w(u'<tr class="%s">' % style) |
499 w(u'<tr class="%s">' % style) |
485 if events: |
500 if events: |
486 hours = events.keys() |
501 hours = events.keys() |