--- a/web/views/calendar.py Thu May 20 20:47:13 2010 +0200
+++ b/web/views/calendar.py Thu May 20 20:47:55 2010 +0200
@@ -15,20 +15,36 @@
#
# You should have received a copy of the GNU Lesser General Public License along
# with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
-"""html calendar views
+"""html calendar views"""
-"""
__docformat__ = "restructuredtext en"
_ = unicode
from datetime import datetime, date, timedelta
from logilab.mtconverter import xml_escape
-from logilab.common.date import strptime, date_range, todate, todatetime
+from logilab.common.date import ONEDAY, strptime, date_range, todate, todatetime
from cubicweb.interfaces import ICalendarable
-from cubicweb.selectors import implements
-from cubicweb.view import EntityView
+from cubicweb.selectors import implements, adaptable
+from cubicweb.view import EntityView, EntityAdapter, implements_adapter_compat
+
+
+class ICalendarableAdapter(EntityAdapter):
+ __regid__ = 'ICalendarable'
+ __select__ = implements(ICalendarable) # XXX for bw compat, should be abstract
+
+ @property
+ @implements_adapter_compat('ICalendarable')
+ def start(self):
+ """return start date"""
+ raise NotImplementedError
+
+ @property
+ @implements_adapter_compat('ICalendarable')
+ def stop(self):
+ """return stop state"""
+ raise NotImplementedError
# useful constants & functions ################################################
@@ -52,7 +68,7 @@
Does apply to ICalendarable compatible entities
"""
- __select__ = implements(ICalendarable)
+ __select__ = adaptable('ICalendarable')
paginable = False
content_type = 'text/calendar'
title = _('iCalendar')
@@ -66,10 +82,11 @@
event = ical.add('vevent')
event.add('summary').value = task.dc_title()
event.add('description').value = task.dc_description()
- if task.start:
- event.add('dtstart').value = task.start
- if task.stop:
- event.add('dtend').value = task.stop
+ icalendarable = task.cw_adapt_to('ICalendarable')
+ if icalendarable.start:
+ event.add('dtstart').value = icalendarable.start
+ if icalendarable.stop:
+ event.add('dtend').value = icalendarable.stop
buff = ical.serialize()
if not isinstance(buff, unicode):
@@ -85,7 +102,7 @@
Does apply to ICalendarable compatible entities
"""
__regid__ = 'hcal'
- __select__ = implements(ICalendarable)
+ __select__ = adaptable('ICalendarable')
paginable = False
title = _('hCalendar')
#templatable = False
@@ -98,10 +115,15 @@
self.w(u'<h3 class="summary">%s</h3>' % xml_escape(task.dc_title()))
self.w(u'<div class="description">%s</div>'
% task.dc_description(format='text/html'))
- if task.start:
- self.w(u'<abbr class="dtstart" title="%s">%s</abbr>' % (task.start.isoformat(), self._cw.format_date(task.start)))
- if task.stop:
- self.w(u'<abbr class="dtstop" title="%s">%s</abbr>' % (task.stop.isoformat(), self._cw.format_date(task.stop)))
+ icalendarable = task.cw_adapt_to('ICalendarable')
+ if icalendarable.start:
+ self.w(u'<abbr class="dtstart" title="%s">%s</abbr>'
+ % (icalendarable.start.isoformat(),
+ self._cw.format_date(icalendarable.start)))
+ if icalendarable.stop:
+ self.w(u'<abbr class="dtstop" title="%s">%s</abbr>'
+ % (icalendarable.stop.isoformat(),
+ self._cw.format_date(icalendarable.stop)))
self.w(u'</div>')
self.w(u'</div>')
@@ -113,10 +135,15 @@
task = self.cw_rset.complete_entity(row, 0)
task.view('oneline', w=self.w)
if dates:
- if task.start and task.stop:
- self.w('<br/>' % self._cw._('from %(date)s' % {'date': self._cw.format_date(task.start)}))
- self.w('<br/>' % self._cw._('to %(date)s' % {'date': self._cw.format_date(task.stop)}))
- self.w('<br/>to %s'%self._cw.format_date(task.stop))
+ icalendarable = task.cw_adapt_to('ICalendarable')
+ if icalendarable.start and icalendarable.stop:
+ self.w('<br/> %s' % self._cw._('from %(date)s')
+ % {'date': self._cw.format_date(icalendarable.start)})
+ self.w('<br/> %s' % self._cw._('to %(date)s')
+ % {'date': self._cw.format_date(icalendarable.stop)})
+ else:
+ self.w('<br/>%s'%self._cw.format_date(icalendarable.start
+ or icalendarable.stop))
class CalendarLargeItemView(CalendarItemView):
__regid__ = 'calendarlargeitem'
@@ -128,22 +155,25 @@
self.color = color
self.index = index
self.length = 1
+ icalendarable = task.cw_adapt_to('ICalendarable')
+ self.start = icalendarable.start
+ self.stop = icalendarable.stop
def in_working_hours(self):
"""predicate returning True is the task is in working hours"""
- if todatetime(self.task.start).hour > 7 and todatetime(self.task.stop).hour < 20:
+ if todatetime(self.start).hour > 7 and todatetime(self.stop).hour < 20:
return True
return False
def is_one_day_task(self):
- task = self.task
- return task.start and task.stop and task.start.isocalendar() == task.stop.isocalendar()
+ return self.start and self.stop and self.start.isocalendar() == self.stop.isocalendar()
class OneMonthCal(EntityView):
"""At some point, this view will probably replace ampm calendars"""
__regid__ = 'onemonthcal'
- __select__ = implements(ICalendarable)
+ __select__ = adaptable('ICalendarable')
+
paginable = False
title = _('one month')
@@ -181,13 +211,14 @@
else:
user = None
the_dates = []
- tstart = task.start
+ icalendarable = task.cw_adapt_to('ICalendarable')
+ tstart = icalendarable.start
if tstart:
- tstart = todate(task.start)
+ tstart = todate(icalendarable.start)
if tstart > lastday:
continue
the_dates = [tstart]
- tstop = task.stop
+ tstop = icalendarable.stop
if tstop:
tstop = todate(tstop)
if tstop < firstday:
@@ -199,7 +230,7 @@
the_dates = [tstart]
else:
the_dates = date_range(max(tstart, firstday),
- min(tstop, lastday))
+ min(tstop + ONEDAY, lastday))
if not the_dates:
continue
@@ -335,7 +366,8 @@
class OneWeekCal(EntityView):
"""At some point, this view will probably replace ampm calendars"""
__regid__ = 'oneweekcal'
- __select__ = implements(ICalendarable)
+ __select__ = adaptable('ICalendarable')
+
paginable = False
title = _('one week')
@@ -368,8 +400,9 @@
continue
done_tasks.append(task)
the_dates = []
- tstart = task.start
- tstop = task.stop
+ icalendarable = task.cw_adapt_to('ICalendarable')
+ tstart = icalendarable.start
+ tstop = icalendarable.stop
if tstart:
tstart = todate(tstart)
if tstart > lastday:
@@ -382,7 +415,7 @@
the_dates = [tstop]
if tstart and tstop:
the_dates = date_range(max(tstart, firstday),
- min(tstop, lastday))
+ min(tstop + ONEDAY, lastday))
if not the_dates:
continue
@@ -462,7 +495,7 @@
def _build_calendar_cell(self, date, task_descrs):
inday_tasks = [t for t in task_descrs if t.is_one_day_task() and t.in_working_hours()]
wholeday_tasks = [t for t in task_descrs if not t.is_one_day_task()]
- inday_tasks.sort(key=lambda t:t.task.start)
+ inday_tasks.sort(key=lambda t:t.start)
sorted_tasks = []
for i, t in enumerate(wholeday_tasks):
t.index = i
@@ -470,7 +503,7 @@
while inday_tasks:
t = inday_tasks.pop(0)
for i, c in enumerate(sorted_tasks):
- if not c or c[-1].task.stop <= t.task.start:
+ if not c or c[-1].stop <= t.start:
c.append(t)
t.index = i+ncols
break
@@ -491,15 +524,15 @@
start_min = 0
stop_hour = 20
stop_min = 0
- if task.start:
- if date < todate(task.start) < date + ONEDAY:
- start_hour = max(8, task.start.hour)
- start_min = task.start.minute
- if task.stop:
- if date < todate(task.stop) < date + ONEDAY:
- stop_hour = min(20, task.stop.hour)
+ if task_desc.start:
+ if date < todate(task_desc.start) < date + ONEDAY:
+ start_hour = max(8, task_desc.start.hour)
+ start_min = task_desc.start.minute
+ if task_desc.stop:
+ if date < todate(task_desc.stop) < date + ONEDAY:
+ stop_hour = min(20, task_desc.stop.hour)
if stop_hour < 20:
- stop_min = task.stop.minute
+ stop_min = task_desc.stop.minute
height = 100.0*(stop_hour+stop_min/60.0-start_hour-start_min/60.0)/(20-8)
top = 100.0*(start_hour+start_min/60.0-8)/(20-8)
@@ -518,7 +551,7 @@
self.w(u'<div class="tooltip" ondblclick="stopPropagation(event); window.location.assign(\'%s\'); return false;">' % xml_escape(url))
task.view('tooltip', w=self.w)
self.w(u'</div>')
- if task.start is None:
+ if task_desc.start is None:
self.w(u'<div class="bottommarker">')
self.w(u'<div class="bottommarkerline" style="margin: 0px 3px 0px 3px; height: 1px;">')
self.w(u'</div>')