# HG changeset patch # User Paul Boddie # Date 1428273591 -7200 # Node ID 626175542bdca78ca75c516c472362e08d235cdd # Parent 157844c5e8f55099f7f794f2f08999474cc723d5 Added attribute details to recurring event periods so that time zone details are loaded and shown correctly in the event editor. Split main and recurring event period handling into separate methods. diff -r 157844c5e8f5 -r 626175542bdc imiptools/data.py --- a/imiptools/data.py Mon Apr 06 00:38:24 2015 +0200 +++ b/imiptools/data.py Mon Apr 06 00:39:51 2015 +0200 @@ -377,15 +377,17 @@ "A period with origin information from the object." - def __init__(self, start, end, origin): + def __init__(self, start, end, origin, start_attr=None, end_attr=None): Period.__init__(self, start, end) self.origin = origin + self.start_attr = start_attr + self.end_attr = end_attr def as_tuple(self): - return self.start, self.end, self.origin + return self.start, self.end, self.origin, self.start_attr, self.end_attr def __repr__(self): - return "RecurringPeriod(%r, %r, %r)" % (self.start, self.end, self.origin) + return "RecurringPeriod(%r, %r, %r, %r, %r)" % (self.start, self.end, self.origin, self.start_attr, self.end_attr) def get_periods(obj, tzid, window_end, inclusive=False): @@ -414,7 +416,7 @@ tzid = get_tzid(dtstart_attr, dtend_attr) or tzid if not rrule: - periods = [RecurringPeriod(dtstart, dtend, "DTSTART")] + periods = [RecurringPeriod(dtstart, dtend, "DTSTART", dtstart_attr, dtend_attr)] else: # Recurrence rules create multiple instances to be checked. # Conflicts may only be assessed within a period defined by policy @@ -432,19 +434,17 @@ # Add recurrence dates. - periods = set(periods) - rdates = obj.get_date_values("RDATE", tzid) + rdates = obj.get_date_value_items("RDATE", tzid) if rdates: - for rdate in rdates: + for rdate, rdate_attr in rdates: if isinstance(rdate, tuple): - periods.add(RecurringPeriod(rdate[0], rdate[1], "RDATE")) + periods.append(RecurringPeriod(rdate[0], rdate[1], "RDATE", rdate_attr)) else: - periods.add(RecurringPeriod(rdate, rdate + duration, "RDATE")) + periods.append(RecurringPeriod(rdate, rdate + duration, "RDATE", rdate_attr)) # Return a sorted list of the periods. - periods = list(periods) periods.sort(cmp=compare_periods(tzid)) # Exclude exception dates. diff -r 157844c5e8f5 -r 626175542bdc imipweb/event.py --- a/imipweb/event.py Mon Apr 06 00:38:24 2015 +0200 +++ b/imipweb/event.py Mon Apr 06 00:39:51 2015 +0200 @@ -182,16 +182,25 @@ def handle_all_period_controls(self): """ - Handle datetime controls for a particular period, where 'index' may be - used to indicate a recurring period, or the main start and end datetimes - are handled. + Handle datetime controls for all periods, including the main period for + an event as well as any recurring periods. """ - args = self.env.get_args() + period, errors = self.handle_main_period_controls() + if errors: + return None, errors + + periods, errors = self.handle_recurrence_period_controls() + if errors: + return None, errors - periods = [] + return ([period] + periods), None + + def handle_main_period_controls(self): - # Get the main period details. + "Return period details for the main start/end period in an event." + + args = self.env.get_args() dtend_enabled = args.get("dtend-control", [None])[0] dttimes_enabled = args.get("dttimes-control", [None])[0] @@ -202,16 +211,22 @@ if errors: return None, errors + else: + return period, errors - periods.append(period) + def handle_recurrence_period_controls(self): - # Get the recurring period details. + "Return period details for the recurrences specified for an event." + + args = self.env.get_args() all_dtend_enabled = args.get("dtend-control-recur", []) all_dttimes_enabled = args.get("dttimes-control-recur", []) all_start_values = self.get_date_control_values("dtstart-recur", multiple=True) all_end_values = self.get_date_control_values("dtend-recur", multiple=True, tzid_name="dtstart-recur") + periods = [] + for index, (start_values, end_values, dtend_enabled, dttimes_enabled) in \ enumerate(map(None, all_start_values, all_end_values, all_dtend_enabled, all_dttimes_enabled)): @@ -467,17 +482,15 @@ if args.has_key("add"): attendees.append("") - # Only actually remove attendees if the event is unsent or if it is the - # current user being removed. + # Only actually remove attendees if the event is unsent, if the attendee + # is new, or if it is the current user being removed. if args.has_key("remove"): for i in args["remove"]: attendee = attendees[int(i)] existing = attendee in existing_attendees - if attendee in attendees and \ - (not existing or sequence is None or attendee == self.user): - + if not existing or sequence is None or attendee == self.user: attendees.remove(attendee) return attendees @@ -806,12 +819,12 @@ page.tr() error = errors and ("dtstart", index) in errors and " error" or "" page.th("Start", class_="objectheading start%s" % error) - self.show_recurrence_controls(obj, index, p.start, p.end, p.origin, recurrenceid, recurrenceids, True) + self.show_recurrence_controls(obj, index, p, recurrenceid, recurrenceids, True) page.tr.close() page.tr() error = errors and ("dtend", index) in errors and " error" or "" page.th("End", class_="objectheading end%s" % error) - self.show_recurrence_controls(obj, index, p.start, p.end, p.origin, recurrenceid, recurrenceids, False) + self.show_recurrence_controls(obj, index, p, recurrenceid, recurrenceids, False) page.tr.close() page.tbody.close() page.table.close() @@ -836,8 +849,8 @@ for index, p in enumerate(self.is_organiser(obj) and periods[1:] or periods): page.tr() - self.show_recurrence_controls(obj, index, p.start, p.end, p.origin, recurrenceid, recurrenceids, True) - self.show_recurrence_controls(obj, index, p.start, p.end, p.origin, recurrenceid, recurrenceids, False) + self.show_recurrence_controls(obj, index, p, recurrenceid, recurrenceids, True) + self.show_recurrence_controls(obj, index, p, recurrenceid, recurrenceids, False) page.tr.close() page.tbody.close() @@ -1032,14 +1045,14 @@ else: page.td(self.format_datetime(dt, "full")) - def show_recurrence_controls(self, obj, index, start, end, origin, recurrenceid, recurrenceids, show_start): + def show_recurrence_controls(self, obj, index, period, recurrenceid, recurrenceids, show_start): """ Show datetime details from the given 'obj' for the recurrence having the - given 'index', with the recurrence period described by the datetimes - 'start' and 'end', indicating the 'origin' of the period from the event - details, employing any 'recurrenceid' and 'recurrenceids' for the object - to configure the displayed information. + given 'index', with the recurrence period described by 'period', + indicating a start, end and origin of the period from the event details, + employing any 'recurrenceid' and 'recurrenceids' for the object to + configure the displayed information. If 'show_start' is set to a true value, the start details will be shown; otherwise, the end details will be shown. @@ -1048,14 +1061,15 @@ page = self.page sn = self._suffixed_name ssn = self._simple_suffixed_name + p = period # Change end dates to refer to the actual dates, not the iCalendar # "next day" dates. - if not isinstance(end, datetime): - end -= timedelta(1) + if not isinstance(p.end, datetime): + p.end -= timedelta(1) - start_utc = format_datetime(to_timezone(start, "UTC")) + start_utc = format_datetime(to_timezone(p.start, "UTC")) replaced = recurrenceids and start_utc in recurrenceids and "replaced" or "" css = " ".join([ replaced, @@ -1064,12 +1078,12 @@ # Show controls for editing as organiser. - if self.is_organiser(obj) and not replaced and origin != "RRULE": + if self.is_organiser(obj) and not replaced and p.origin != "RRULE": page.td(class_="objectvalue dt%s" % (show_start and "start" or "end")) if show_start: page.div(class_="dt enabled") - self._show_date_controls(ssn("dtstart", "recur", index), start, index=index) + self._show_date_controls(ssn("dtstart", "recur", index), p.start, p.start_attr.get("TZID"), index=index) page.br() page.label("Specify times", for_=sn("dttimes-enable", index), class_="time disabled enable") page.label("Specify dates only", for_=sn("dttimes-enable", index), class_="time enabled disable") @@ -1080,7 +1094,7 @@ page.label("Specify end date", for_=sn("dtend-enable", index), class_="enable") page.div.close() page.div(class_="dt enabled") - self._show_date_controls(ssn("dtend", "recur", index), end, index=index, show_tzid=False) + self._show_date_controls(ssn("dtend", "recur", index), p.end, index=index, show_tzid=False) page.br() page.label("End on same day", for_=sn("dtend-enable", index), class_="disable") page.div.close() @@ -1090,7 +1104,7 @@ # Show label as attendee. else: - page.td(self.format_datetime(show_start and start or end, "long"), class_=css) + page.td(self.format_datetime(show_start and p.start or p.end, "long"), class_=css) # Full page output methods.