1.1 --- a/macros/EventAggregator.py Sun Jan 16 19:30:01 2011 +0100
1.2 +++ b/macros/EventAggregator.py Mon Jan 17 02:26:17 2011 +0100
1.3 @@ -23,15 +23,19 @@
1.4 "A view of the event calendar."
1.5
1.6 def __init__(self, page, calendar_name, raw_calendar_start, raw_calendar_end,
1.7 - calendar_start, calendar_end, first, last, category_names, template_name,
1.8 - parent_name, mode, name_usage):
1.9 + original_calendar_start, original_calendar_end, calendar_start, calendar_end,
1.10 + first, last, category_names, template_name, parent_name, mode, name_usage):
1.11
1.12 """
1.13 Initialise the view with the current 'page', a 'calendar_name' (which
1.14 may be None), the 'raw_calendar_start' and 'raw_calendar_end' (which
1.15 are the actual start and end values provided by the request), the
1.16 - requested, calculated 'calendar_start' and 'calendar_end', and the
1.17 - 'first' and 'last' months of event coverage.
1.18 + calculated 'original_calendar_start' and 'original_calendar_end' (which
1.19 + are the result of calculating the calendar's limits from the raw start
1.20 + and end values), and the requested, calculated 'calendar_start' and
1.21 + 'calendar_end' (which may involve different start and end values due to
1.22 + navigation in the user interface), along with the 'first' and 'last'
1.23 + months of event coverage.
1.24
1.25 The additional 'category_names', 'template_name', 'parent_name' and
1.26 'mode' parameters are used to configure the links employed by the view.
1.27 @@ -44,6 +48,8 @@
1.28 self.calendar_name = calendar_name
1.29 self.raw_calendar_start = raw_calendar_start
1.30 self.raw_calendar_end = raw_calendar_end
1.31 + self.original_calendar_start = original_calendar_start
1.32 + self.original_calendar_end = original_calendar_end
1.33 self.calendar_start = calendar_start
1.34 self.calendar_end = calendar_end
1.35 self.template_name = template_name
1.36 @@ -153,8 +159,10 @@
1.37
1.38 # Generate the links.
1.39
1.40 - download_dialogue_link = "action=EventAggregatorSummary&parent=%s&%s" % (
1.41 - self.parent_name or "", self.category_name_parameters
1.42 + download_dialogue_link = "action=EventAggregatorSummary&parent=%s&resolution=%s&%s" % (
1.43 + self.parent_name or "",
1.44 + self.mode == "day" and "date" or "month",
1.45 + self.category_name_parameters
1.46 )
1.47 download_all_link = download_dialogue_link + "&doit=1"
1.48 download_link = download_all_link + ("&%s&%s" % (
1.49 @@ -197,6 +205,10 @@
1.50 get_label(self.calendar_start),
1.51 get_label(self.calendar_end)
1.52 )
1.53 + original_calendar_period = "%s - %s" % (
1.54 + get_label(self.original_calendar_start),
1.55 + get_label(self.original_calendar_end)
1.56 + )
1.57 raw_calendar_period = "%s - %s" % (self.raw_calendar_start, self.raw_calendar_end)
1.58
1.59 # Write the controls.
1.60 @@ -215,7 +227,7 @@
1.61 output.append(linkToPage(request, page, _("Download this calendar"), download_all_link))
1.62 output.append(fmt.span(on=1, css_class="event-download-popup"))
1.63 output.append(fmt.span(on=1, css_class="event-download-period"))
1.64 - output.append(fmt.text(calendar_period))
1.65 + output.append(fmt.text(original_calendar_period))
1.66 output.append(fmt.span(on=0))
1.67 output.append(fmt.span(on=1, css_class="event-download-period-raw"))
1.68 output.append(fmt.text(raw_calendar_period))
1.69 @@ -243,7 +255,7 @@
1.70 output.append(linkToPage(request, page, _("Subscribe to this calendar"), subscribe_all_link))
1.71 output.append(fmt.span(on=1, css_class="event-download-popup"))
1.72 output.append(fmt.span(on=1, css_class="event-download-period"))
1.73 - output.append(fmt.text(calendar_period))
1.74 + output.append(fmt.text(original_calendar_period))
1.75 output.append(fmt.span(on=0))
1.76 output.append(fmt.span(on=1, css_class="event-download-period-raw"))
1.77 output.append(fmt.text(raw_calendar_period))
1.78 @@ -808,15 +820,49 @@
1.79 # determine whether it provides content for each period.
1.80
1.81 scale = EventAggregatorSupport.getCoverageScale(full_coverage)
1.82 - period = None
1.83 +
1.84 + # Define a mapping of events to rowspans.
1.85 +
1.86 + rowspans = {}
1.87 +
1.88 + # Populate each period with event details, recording how many periods
1.89 + # each event populates.
1.90 +
1.91 + day_rows = []
1.92
1.93 for period in scale:
1.94
1.95 # Ignore timespans before this day.
1.96
1.97 - if not date in period:
1.98 + if period != date:
1.99 continue
1.100
1.101 + # Visit each slot corresponding to a location (or no location).
1.102 +
1.103 + day_row = []
1.104 +
1.105 + for location in locations:
1.106 +
1.107 + # Visit each coverage span, presenting the events in the span.
1.108 +
1.109 + for events in day_slots[location]:
1.110 + event = self.getActiveEvent(period, events)
1.111 + if event is not None:
1.112 + if not rowspans.has_key(event):
1.113 + rowspans[event] = 1
1.114 + else:
1.115 + rowspans[event] += 1
1.116 + day_row.append((location, event))
1.117 +
1.118 + day_rows.append((period, day_row))
1.119 +
1.120 + # Output the periods with event details.
1.121 +
1.122 + period = None
1.123 + events_written = set()
1.124 +
1.125 + for period, day_row in day_rows:
1.126 +
1.127 # Write an empty heading for the start of the day where the first
1.128 # applicable timespan starts before this day.
1.129
1.130 @@ -828,23 +874,22 @@
1.131
1.132 else:
1.133 output.append(fmt.table_row(on=1))
1.134 - output.append(self.writeDayScaleHeading(str(period.start)))
1.135 + output.append(self.writeDayScaleHeading(period.start.time_string()))
1.136
1.137 # Visit each slot corresponding to a location (or no location).
1.138
1.139 - for location in locations:
1.140 + for location, event in day_row:
1.141
1.142 - # Visit each coverage span, presenting the events in the span.
1.143 + # Add a spacer.
1.144
1.145 - for events in day_slots[location]:
1.146 + output.append(self.writeDaySpacer())
1.147
1.148 - # Add a spacer.
1.149 -
1.150 - output.append(self.writeDaySpacer())
1.151 + # Output each location slot's contribution.
1.152
1.153 - # Output each set's contribution to this period.
1.154 -
1.155 - output.append(self.writeDaySlot(period, events))
1.156 + if event is None or event not in events_written:
1.157 + output.append(self.writeDaySlot(period, event, event is None and 1 or rowspans[event]))
1.158 + if event is not None:
1.159 + events_written.add(event)
1.160
1.161 output.append(fmt.table_row(on=0))
1.162
1.163 @@ -853,12 +898,11 @@
1.164 if period is not None:
1.165 if period.end == date:
1.166 output.append(fmt.table_row(on=1))
1.167 - output.append(self.writeDayScaleHeading(str(period.end)))
1.168 + output.append(self.writeDayScaleHeading(period.end.time_string()))
1.169
1.170 - for location in locations:
1.171 - for events in day_slots[location]:
1.172 - output.append(self.writeDaySpacer())
1.173 - output.append(self.writeEmptyDaySlot())
1.174 + for slot in day_row:
1.175 + output.append(self.writeDaySpacer())
1.176 + output.append(self.writeEmptyDaySlot())
1.177
1.178 output.append(fmt.table_row(on=0))
1.179
1.180 @@ -875,26 +919,31 @@
1.181
1.182 return "".join(output)
1.183
1.184 - def writeDaySlot(self, period, events):
1.185 + def getActiveEvent(self, period, events):
1.186 + for event in events:
1.187 + if period not in event:
1.188 + continue
1.189 + return event
1.190 + else:
1.191 + return None
1.192 +
1.193 + def writeDaySlot(self, period, event, rowspan):
1.194 page = self.page
1.195 fmt = page.formatter
1.196
1.197 output = []
1.198
1.199 - for event in events:
1.200 - if period not in event:
1.201 - continue
1.202 -
1.203 + if event is not None:
1.204 event_summary = event.getSummary(self.parent_name)
1.205 style = self.getEventStyle(event_summary)
1.206
1.207 output.append(fmt.table_cell(on=1, attrs={
1.208 "class" : "event-timespan-content event-timespan-busy",
1.209 - "style" : style}))
1.210 + "style" : style,
1.211 + "rowspan" : str(rowspan)
1.212 + }))
1.213 output.append(self.writeEventSummaryBox(event))
1.214 output.append(fmt.table_cell(on=0))
1.215 - break
1.216 -
1.217 else:
1.218 output.append(self.writeEmptyDaySlot())
1.219
1.220 @@ -1042,8 +1091,8 @@
1.221
1.222 # Determine the limits of the calendar.
1.223
1.224 - calendar_start = get_date(raw_calendar_start)
1.225 - calendar_end = get_date(raw_calendar_end)
1.226 + original_calendar_start = calendar_start = get_date(raw_calendar_start)
1.227 + original_calendar_end = calendar_end = get_date(raw_calendar_end)
1.228
1.229 if calendar_name is not None:
1.230 calendar_start = get_form_date(request, calendar_name, "start") or calendar_start
1.231 @@ -1061,7 +1110,8 @@
1.232
1.233 # Define a view of the calendar, retaining useful navigational information.
1.234
1.235 - view = View(page, calendar_name, raw_calendar_start, raw_calendar_end, calendar_start, calendar_end,
1.236 + view = View(page, calendar_name, raw_calendar_start, raw_calendar_end,
1.237 + original_calendar_start, original_calendar_end, calendar_start, calendar_end,
1.238 first, last, category_names, template_name, parent_name, mode, name_usage)
1.239
1.240 # Make a calendar.