--- a/svv/cal.py Sun Jan 09 15:52:28 2011 +0200
+++ b/svv/cal.py Sun Jan 09 17:49:15 2011 +0200
@@ -118,7 +118,7 @@
def get_events_for_interval (self, start, end) :
"""
- Returns list of Order objects for given interval, ordered by start time.
+ Return full list of all Orders taking place during the given datetime interval, ordered by start time
"""
# XXX: bad imports
@@ -130,6 +130,37 @@
| (db.between(start, Order.event_start, Order.event_end))
).order_by(Order.event_start).all()
+ def interval_for_dates (self, dates) :
+ """
+ Returns a datetime (start, end) interval encompassing all of the given dates
+ """
+
+ # a day is 00:00:00 - 23:59:59
+ start = datetime.datetime.combine(min(dates), datetime.time(0, 0, 0))
+ end = datetime.datetime.combine(max(dates), datetime.time(23, 59, 59))
+
+ return start, end
+
+ def hours_from_day_start (self, dt) :
+ """
+ Return the number of hours from the start of the day to the given datetime, as a float.
+ """
+
+ HOUR = float(60 * 60)
+
+ # dt - 00:00:00
+ return (dt - dt.replace(hour=0, minute=0, second=0)).seconds / HOUR
+
+ def hours_to_day_end (self, dt) :
+ """
+ Return the number of hours from the given datetime to the day's end, as a float.
+ """
+
+ HOUR = float(60 * 60)
+
+ # 23:59:59 - dt
+ return (dt.replace(hour=23, minute=59, second=59) - dt).seconds / HOUR
+
def render_week (self, month, week) :
"""
Render day rows for given week.
@@ -138,50 +169,74 @@
# XXX: nasty
from svv import urls
- # load events for week
- week_start = datetime.datetime.combine(min(week), datetime.time(0, 0, 0))
- week_end = datetime.datetime.combine(max(week), datetime.time(23, 59, 59))
-
+ # week as datetime interval
+ week_start, week_end = self.interval_for_dates(week)
+
+ # all orders for week
orders = self.get_events_for_interval(week_start, week_end)
- log.debug("Render week %r -> %r: %d", week_start, week_end, len(orders))
-
# day headers
yield tags.tr(class_='week-header')(
self.render_day_header(month, date) for date in week
)
- # each even on its own row for now
+ # each event on its own row for now
for order in orders :
# start/end date for this week
- start = min(date for date in week if order.on_date(date))
- end = max(date for date in week if order.on_date(date))
+ start_day = min(date for date in week if order.on_date(date))
+ end_day = max(date for date in week if order.on_date(date))
# as vector into week
- leading = (start - min(week)).days
- length = (end - start).days + 1
- trailing = (max(week) - end).days
+ leading_days = (start_day - min(week)).days
+ length_days = (end_day - start_day).days + 1
+ trailing_days = (max(week) - end_day).days
- # continues prev/next?
- prev = (start > order.event_start.date())
- next = (end < order.event_end.date())
+ # continues prev/next week?
+ prev_week = (start_day > order.event_start.date())
+ next_week = (end_day < order.event_end.date())
- log.debug("Event %r from %r -> %r", order.event_name, start, end)
+ log.debug("Event %r from %r -> %r", order.event_name, start_day, end_day)
+
+ # spec class
+ classes = ' '.join(cls for cls in (
+ 'event',
+ 'continues-prev' if prev_week else None,
+ 'continues-next' if next_week else None,
+ ) if cls)
+
+ # compute dynamic styles
+ styles = []
+
+ # width of each hour in the event's span this week, as a percentage
+ hour_width = 100.0 / (length_days * 24)
+
+ # margin for start hour offset
+ if not prev_week :
+ # starts on this week, so calc how many hours into day
+ styles.append('margin-left: %d%%' % int(hour_width * self.hours_from_day_start(order.event_start)))
+
+ # margin for end hour offset
+ if not next_week :
+ # ends on this week, se calc how many hours until day end
+ styles.append('margin-right: %d%%' % int(hour_width * self.hours_to_day_end(order.event_end)))
+
+ # style spec
+ if styles :
+ style = '; '.join(styles)
+
+ else :
+ style = None
yield tags.tr(class_='week-data')(
- [tags.td("")] * leading,
- tags.td(colspan=length, class_=(' '.join(cls for cls in (
- 'event',
- 'continues-prev' if prev else None,
- 'continues-next' if next else None,
- ) if cls)))(
- tags.a(href=self.url_for(urls.OrderView, id=order.id))(
- tags.div(class_='arrow-left')("") if prev else None,
+ tags.td("", colspan=leading_days) if leading_days else None,
+ tags.td(colspan=length_days, class_=classes)(
+ tags.a(href=self.url_for(urls.OrderView, id=order.id), style=style)(
+ tags.div(class_='arrow-left')("") if prev_week else None,
order.event_name,
- tags.div(class_='arrow-right')("") if next else None,
+ tags.div(class_='arrow-right')("") if next_week else None,
)
),
- [tags.td("")] * trailing,
+ tags.td("", colspan=trailing_days) if trailing_days else None,
)
def render_calendar (self, month) :