# HG changeset patch # User Paul Boddie # Date 1445118568 -7200 # Node ID a15f4aa9f1fc2da50ab333cc09f1209b896ad9a1 # Parent 851df2f4cfed31706366c584e674448e0e804b31 Introduced a "replaced" flag to periods in the manager interface in order to be able to track existing and new periods and thus correctly restore periods after cancellation. As a consequence use of each object's recurrences list is reduced. diff -r 851df2f4cfed -r a15f4aa9f1fc imipweb/data.py --- a/imipweb/data.py Sat Oct 17 23:09:07 2015 +0200 +++ b/imipweb/data.py Sat Oct 17 23:49:28 2015 +0200 @@ -35,7 +35,7 @@ intended to represent information obtained from an iCalendar resource. """ - def __init__(self, start, end, tzid=None, origin=None, start_attr=None, end_attr=None, form_start=None, form_end=None): + def __init__(self, start, end, tzid=None, origin=None, start_attr=None, end_attr=None, form_start=None, form_end=None, replaced=False): """ Initialise a period with the given 'start' and 'end' datetimes, together @@ -47,9 +47,10 @@ RecurringPeriod.__init__(self, start, end, tzid, origin, start_attr, end_attr) self.form_start = form_start self.form_end = form_end + self.replaced = replaced def as_tuple(self): - return self.start, self.end, self.tzid, self.origin, self.start_attr, self.end_attr, self.form_start, self.form_end + return self.start, self.end, self.tzid, self.origin, self.start_attr, self.end_attr, self.form_start, self.form_end, self.replaced def __repr__(self): return "EventPeriod%r" % (self.as_tuple(),) @@ -82,7 +83,8 @@ isinstance(self.end, datetime) or self.get_start() != self.get_end() - timedelta(1), isinstance(self.start, datetime) or isinstance(self.end, datetime), self.tzid, - self.origin + self.origin, + self.replaced ) def get_form_date(self, dt, attr=None): @@ -99,16 +101,17 @@ "A period whose information originates from a form." - def __init__(self, start, end, end_enabled=True, times_enabled=True, tzid=None, origin=None): + def __init__(self, start, end, end_enabled=True, times_enabled=True, tzid=None, origin=None, replaced=False): self.start = start self.end = end self.end_enabled = end_enabled self.times_enabled = times_enabled self.tzid = tzid self.origin = origin + self.replaced = replaced def as_tuple(self): - return self.start, self.end, self.end_enabled, self.times_enabled, self.tzid, self.origin + return self.start, self.end, self.end_enabled, self.times_enabled, self.tzid, self.origin, self.replaced def __repr__(self): return "FormPeriod%r" % (self.as_tuple(),) @@ -135,7 +138,7 @@ index is not None and ("dtend", index) or "dtend" ]) - return EventPeriod(dtstart, end_date_to_calendar(dtend), self.tzid, self.origin, dtstart_attr, dtend_attr, self.start, self.end) + return EventPeriod(dtstart, end_date_to_calendar(dtend), self.tzid, self.origin, dtstart_attr, dtend_attr, self.start, self.end, self.replaced) # Period data methods. diff -r 851df2f4cfed -r a15f4aa9f1fc imipweb/event.py --- a/imipweb/event.py Sat Oct 17 23:09:07 2015 +0200 +++ b/imipweb/event.py Sat Oct 17 23:49:28 2015 +0200 @@ -112,8 +112,11 @@ "Return recurrences computed using the current object." + recurrenceids = self._get_recurrences(self.uid) recurrences = [] for period in self.get_periods(self.obj): + period = event_period_from_period(period) + period.replaced = period.is_replaced(recurrenceids) if period.origin != "DTSTART": recurrences.append(period) return recurrences @@ -204,7 +207,7 @@ # Obtain any separate recurrences for this event. - recurrenceids = self._get_active_recurrences(self.uid) + recurrenceids = self._get_recurrences(self.uid) replaced = not self.recurrenceid and period.is_replaced(recurrenceids) excluded = period == stored_period and period not in self.get_periods(self.obj) @@ -440,23 +443,20 @@ if len(recurrences) < 1: return - recurrenceids = self._get_recurrences(self.uid) - page.p("This event occurs on the following occasions within the next %d days:" % self.get_window_size()) # Show each recurrence in a separate table. for index, period in enumerate(recurrences): - self.show_recurrence(index, period, self.recurrenceid, recurrenceids, errors) + self.show_recurrence(index, period, self.recurrenceid, errors) - def show_recurrence(self, index, period, recurrenceid, recurrenceids, errors=None): + def show_recurrence(self, index, period, recurrenceid, errors=None): """ Show recurrence controls for a recurrence provided by the current object with the given 'index' position in the list of periods, the given 'period' details, where a 'recurrenceid' indicates any specific - recurrence, and where 'recurrenceids' indicates all known additional - recurrences for the object. + recurrence. If 'errors' is given, show a suitable message for the different errors provided. @@ -465,14 +465,6 @@ page = self.page args = self.env.get_args() - try: - p = event_period_from_period(period) - except PeriodError, exc: - replaced = False - errors = list(errors or []) + [exc.args] - else: - replaced = not recurrenceid and p.is_replaced(recurrenceids) - # Isolate the controls from neighbouring tables. page.div() @@ -486,17 +478,17 @@ page.tr() error = errors and ("dtstart", index) in errors and " error" or "" page.th("Start", class_="objectheading start%s" % error) - self.show_recurrence_controls(index, period, recurrenceid, recurrenceids, True) + self.show_recurrence_controls(index, period, recurrenceid, 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(index, period, recurrenceid, recurrenceids, False) + self.show_recurrence_controls(index, period, recurrenceid, False) page.tr.close() # Permit the removal of recurrences. - if not replaced: + if not period.replaced: page.tr() page.th("") page.td() @@ -833,7 +825,10 @@ changed = self.obj.set_period(period) or changed changed = self.obj.set_periods(periods) or changed changed = self.obj.update_exceptions(to_exclude) or changed - changed = self.revert_cancellations(periods) or changed + + # Assert periods restored after cancellation. + + changed = self.revert_cancellations([p for p in periods if not p.replaced]) or changed # Organiser-only changes... @@ -997,15 +992,18 @@ all_starts = self.get_date_control_values("dtstart-recur", multiple=True) all_ends = self.get_date_control_values("dtend-recur", multiple=True, tzid_name="dtstart-recur") all_origins = args.get("recur-origin", []) + all_replaced = args.get("recur-replaced", []) periods = [] - for index, (start, end, dtend_enabled, dttimes_enabled, origin) in \ - enumerate(map(None, all_starts, all_ends, all_dtend_enabled, all_dttimes_enabled, all_origins)): + for index, (start, end, origin) in \ + enumerate(map(None, all_starts, all_ends, all_origins)): dtend_enabled = str(index) in all_dtend_enabled dttimes_enabled = str(index) in all_dttimes_enabled - period = FormPeriod(start, end, dtend_enabled, dttimes_enabled, self.get_tzid(), origin) + replaced = str(index) in all_replaced + + period = FormPeriod(start, end, dtend_enabled, dttimes_enabled, self.get_tzid(), origin, replaced) periods.append(period) return periods @@ -1019,6 +1017,7 @@ args["dtend-control-recur"] = [] args["dttimes-control-recur"] = [] args["recur-origin"] = [] + args["recur-replaced"] = [] all_starts = [] all_ends = [] @@ -1028,6 +1027,8 @@ args["dtend-control-recur"].append(str(index)) if period.times_enabled: args["dttimes-control-recur"].append(str(index)) + if period.replaced: + args["recur-replaced"].append(str(index)) args["recur-origin"].append(period.origin or "") all_starts.append(period.get_form_start()) diff -r 851df2f4cfed -r a15f4aa9f1fc imipweb/resource.py --- a/imipweb/resource.py Sat Oct 17 23:09:07 2015 +0200 +++ b/imipweb/resource.py Sat Oct 17 23:49:28 2015 +0200 @@ -635,14 +635,14 @@ page.td.close() - def show_recurrence_controls(self, index, period, recurrenceid, recurrenceids, show_start): + def show_recurrence_controls(self, index, period, recurrenceid, show_start): """ Show datetime details from the current object for the recurrence having the 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. + employing any 'recurrenceid' 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. @@ -652,22 +652,12 @@ _id = self.element_identifier _name = self.element_name - try: - p = event_period_from_period(period) - except PeriodError, exc: - replaced = False - errors = exc.args - else: - replaced = not recurrenceid and p.is_replaced(recurrenceids) - errors = [] - period = form_period_from_period(period) # Show controls for editing. - if not replaced: - error = errors and (show_start and ("dtstart", index) in errors or not show_start and ("dtend", index) in errors) and " error" or "" - page.td(class_="objectvalue dt%s%s" % (show_start and "start" or "end", error)) + if not period.replaced: + page.td(class_="objectvalue dt%s" % (show_start and "start" or "end")) read_only = period.origin == "RRULE" @@ -683,6 +673,7 @@ # Put the origin somewhere. self.control("recur-origin", "hidden", period.origin or "") + self.control("recur-replaced", "hidden", period.replaced and str(index) or "") else: page.div(class_="dt disabled") @@ -701,15 +692,14 @@ # Show label as attendee. else: - self.show_recurrence_label(index, period, recurrenceid, recurrenceids, show_start) + self.show_recurrence_label(index, period, recurrenceid, show_start) - def show_recurrence_label(self, index, period, recurrenceid, recurrenceids, show_start): + def show_recurrence_label(self, index, period, recurrenceid, show_start): """ Show datetime details from the current object for the recurrence having the given 'index', for the given recurrence 'period', employing any - 'recurrenceid' and 'recurrenceids' for the object to configure the - displayed information. + 'recurrenceid' 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. @@ -721,18 +711,14 @@ try: p = event_period_from_period(period) except PeriodError, exc: - replaced = False affected = False - errors = exc.args else: - replaced = not recurrenceid and p.is_replaced(recurrenceids) affected = p.is_affected(recurrenceid) - errors = [] period = form_period_from_period(period) css = " ".join([ - replaced and "replaced" or "", + period.replaced and "replaced" or "", affected and "affected" or "" ]) @@ -743,6 +729,7 @@ if show_start: self.date_controls(_name("dtstart", "recur", index), period.get_form_start(), index=index, read_only=True) self.control("recur-origin", "hidden", period.origin or "") + self.control("recur-replaced", "hidden", period.replaced and str(index) or "") else: self.date_controls(_name("dtend", "recur", index), period.get_form_end(), index=index, show_tzid=False, read_only=True) page.td.close()