1.1 --- a/imipweb/data.py Sat Oct 17 23:09:07 2015 +0200
1.2 +++ b/imipweb/data.py Sat Oct 17 23:49:28 2015 +0200
1.3 @@ -35,7 +35,7 @@
1.4 intended to represent information obtained from an iCalendar resource.
1.5 """
1.6
1.7 - def __init__(self, start, end, tzid=None, origin=None, start_attr=None, end_attr=None, form_start=None, form_end=None):
1.8 + def __init__(self, start, end, tzid=None, origin=None, start_attr=None, end_attr=None, form_start=None, form_end=None, replaced=False):
1.9
1.10 """
1.11 Initialise a period with the given 'start' and 'end' datetimes, together
1.12 @@ -47,9 +47,10 @@
1.13 RecurringPeriod.__init__(self, start, end, tzid, origin, start_attr, end_attr)
1.14 self.form_start = form_start
1.15 self.form_end = form_end
1.16 + self.replaced = replaced
1.17
1.18 def as_tuple(self):
1.19 - return self.start, self.end, self.tzid, self.origin, self.start_attr, self.end_attr, self.form_start, self.form_end
1.20 + return self.start, self.end, self.tzid, self.origin, self.start_attr, self.end_attr, self.form_start, self.form_end, self.replaced
1.21
1.22 def __repr__(self):
1.23 return "EventPeriod%r" % (self.as_tuple(),)
1.24 @@ -82,7 +83,8 @@
1.25 isinstance(self.end, datetime) or self.get_start() != self.get_end() - timedelta(1),
1.26 isinstance(self.start, datetime) or isinstance(self.end, datetime),
1.27 self.tzid,
1.28 - self.origin
1.29 + self.origin,
1.30 + self.replaced
1.31 )
1.32
1.33 def get_form_date(self, dt, attr=None):
1.34 @@ -99,16 +101,17 @@
1.35
1.36 "A period whose information originates from a form."
1.37
1.38 - def __init__(self, start, end, end_enabled=True, times_enabled=True, tzid=None, origin=None):
1.39 + def __init__(self, start, end, end_enabled=True, times_enabled=True, tzid=None, origin=None, replaced=False):
1.40 self.start = start
1.41 self.end = end
1.42 self.end_enabled = end_enabled
1.43 self.times_enabled = times_enabled
1.44 self.tzid = tzid
1.45 self.origin = origin
1.46 + self.replaced = replaced
1.47
1.48 def as_tuple(self):
1.49 - return self.start, self.end, self.end_enabled, self.times_enabled, self.tzid, self.origin
1.50 + return self.start, self.end, self.end_enabled, self.times_enabled, self.tzid, self.origin, self.replaced
1.51
1.52 def __repr__(self):
1.53 return "FormPeriod%r" % (self.as_tuple(),)
1.54 @@ -135,7 +138,7 @@
1.55 index is not None and ("dtend", index) or "dtend"
1.56 ])
1.57
1.58 - return EventPeriod(dtstart, end_date_to_calendar(dtend), self.tzid, self.origin, dtstart_attr, dtend_attr, self.start, self.end)
1.59 + return EventPeriod(dtstart, end_date_to_calendar(dtend), self.tzid, self.origin, dtstart_attr, dtend_attr, self.start, self.end, self.replaced)
1.60
1.61 # Period data methods.
1.62
2.1 --- a/imipweb/event.py Sat Oct 17 23:09:07 2015 +0200
2.2 +++ b/imipweb/event.py Sat Oct 17 23:49:28 2015 +0200
2.3 @@ -112,8 +112,11 @@
2.4
2.5 "Return recurrences computed using the current object."
2.6
2.7 + recurrenceids = self._get_recurrences(self.uid)
2.8 recurrences = []
2.9 for period in self.get_periods(self.obj):
2.10 + period = event_period_from_period(period)
2.11 + period.replaced = period.is_replaced(recurrenceids)
2.12 if period.origin != "DTSTART":
2.13 recurrences.append(period)
2.14 return recurrences
2.15 @@ -204,7 +207,7 @@
2.16
2.17 # Obtain any separate recurrences for this event.
2.18
2.19 - recurrenceids = self._get_active_recurrences(self.uid)
2.20 + recurrenceids = self._get_recurrences(self.uid)
2.21 replaced = not self.recurrenceid and period.is_replaced(recurrenceids)
2.22 excluded = period == stored_period and period not in self.get_periods(self.obj)
2.23
2.24 @@ -440,23 +443,20 @@
2.25 if len(recurrences) < 1:
2.26 return
2.27
2.28 - recurrenceids = self._get_recurrences(self.uid)
2.29 -
2.30 page.p("This event occurs on the following occasions within the next %d days:" % self.get_window_size())
2.31
2.32 # Show each recurrence in a separate table.
2.33
2.34 for index, period in enumerate(recurrences):
2.35 - self.show_recurrence(index, period, self.recurrenceid, recurrenceids, errors)
2.36 + self.show_recurrence(index, period, self.recurrenceid, errors)
2.37
2.38 - def show_recurrence(self, index, period, recurrenceid, recurrenceids, errors=None):
2.39 + def show_recurrence(self, index, period, recurrenceid, errors=None):
2.40
2.41 """
2.42 Show recurrence controls for a recurrence provided by the current object
2.43 with the given 'index' position in the list of periods, the given
2.44 'period' details, where a 'recurrenceid' indicates any specific
2.45 - recurrence, and where 'recurrenceids' indicates all known additional
2.46 - recurrences for the object.
2.47 + recurrence.
2.48
2.49 If 'errors' is given, show a suitable message for the different errors
2.50 provided.
2.51 @@ -465,14 +465,6 @@
2.52 page = self.page
2.53 args = self.env.get_args()
2.54
2.55 - try:
2.56 - p = event_period_from_period(period)
2.57 - except PeriodError, exc:
2.58 - replaced = False
2.59 - errors = list(errors or []) + [exc.args]
2.60 - else:
2.61 - replaced = not recurrenceid and p.is_replaced(recurrenceids)
2.62 -
2.63 # Isolate the controls from neighbouring tables.
2.64
2.65 page.div()
2.66 @@ -486,17 +478,17 @@
2.67 page.tr()
2.68 error = errors and ("dtstart", index) in errors and " error" or ""
2.69 page.th("Start", class_="objectheading start%s" % error)
2.70 - self.show_recurrence_controls(index, period, recurrenceid, recurrenceids, True)
2.71 + self.show_recurrence_controls(index, period, recurrenceid, True)
2.72 page.tr.close()
2.73 page.tr()
2.74 error = errors and ("dtend", index) in errors and " error" or ""
2.75 page.th("End", class_="objectheading end%s" % error)
2.76 - self.show_recurrence_controls(index, period, recurrenceid, recurrenceids, False)
2.77 + self.show_recurrence_controls(index, period, recurrenceid, False)
2.78 page.tr.close()
2.79
2.80 # Permit the removal of recurrences.
2.81
2.82 - if not replaced:
2.83 + if not period.replaced:
2.84 page.tr()
2.85 page.th("")
2.86 page.td()
2.87 @@ -833,7 +825,10 @@
2.88 changed = self.obj.set_period(period) or changed
2.89 changed = self.obj.set_periods(periods) or changed
2.90 changed = self.obj.update_exceptions(to_exclude) or changed
2.91 - changed = self.revert_cancellations(periods) or changed
2.92 +
2.93 + # Assert periods restored after cancellation.
2.94 +
2.95 + changed = self.revert_cancellations([p for p in periods if not p.replaced]) or changed
2.96
2.97 # Organiser-only changes...
2.98
2.99 @@ -997,15 +992,18 @@
2.100 all_starts = self.get_date_control_values("dtstart-recur", multiple=True)
2.101 all_ends = self.get_date_control_values("dtend-recur", multiple=True, tzid_name="dtstart-recur")
2.102 all_origins = args.get("recur-origin", [])
2.103 + all_replaced = args.get("recur-replaced", [])
2.104
2.105 periods = []
2.106
2.107 - for index, (start, end, dtend_enabled, dttimes_enabled, origin) in \
2.108 - enumerate(map(None, all_starts, all_ends, all_dtend_enabled, all_dttimes_enabled, all_origins)):
2.109 + for index, (start, end, origin) in \
2.110 + enumerate(map(None, all_starts, all_ends, all_origins)):
2.111
2.112 dtend_enabled = str(index) in all_dtend_enabled
2.113 dttimes_enabled = str(index) in all_dttimes_enabled
2.114 - period = FormPeriod(start, end, dtend_enabled, dttimes_enabled, self.get_tzid(), origin)
2.115 + replaced = str(index) in all_replaced
2.116 +
2.117 + period = FormPeriod(start, end, dtend_enabled, dttimes_enabled, self.get_tzid(), origin, replaced)
2.118 periods.append(period)
2.119
2.120 return periods
2.121 @@ -1019,6 +1017,7 @@
2.122 args["dtend-control-recur"] = []
2.123 args["dttimes-control-recur"] = []
2.124 args["recur-origin"] = []
2.125 + args["recur-replaced"] = []
2.126
2.127 all_starts = []
2.128 all_ends = []
2.129 @@ -1028,6 +1027,8 @@
2.130 args["dtend-control-recur"].append(str(index))
2.131 if period.times_enabled:
2.132 args["dttimes-control-recur"].append(str(index))
2.133 + if period.replaced:
2.134 + args["recur-replaced"].append(str(index))
2.135 args["recur-origin"].append(period.origin or "")
2.136
2.137 all_starts.append(period.get_form_start())
3.1 --- a/imipweb/resource.py Sat Oct 17 23:09:07 2015 +0200
3.2 +++ b/imipweb/resource.py Sat Oct 17 23:49:28 2015 +0200
3.3 @@ -635,14 +635,14 @@
3.4
3.5 page.td.close()
3.6
3.7 - def show_recurrence_controls(self, index, period, recurrenceid, recurrenceids, show_start):
3.8 + def show_recurrence_controls(self, index, period, recurrenceid, show_start):
3.9
3.10 """
3.11 Show datetime details from the current object for the recurrence having
3.12 the given 'index', with the recurrence period described by 'period',
3.13 indicating a start, end and origin of the period from the event details,
3.14 - employing any 'recurrenceid' and 'recurrenceids' for the object to
3.15 - configure the displayed information.
3.16 + employing any 'recurrenceid' for the object to configure the displayed
3.17 + information.
3.18
3.19 If 'show_start' is set to a true value, the start details will be shown;
3.20 otherwise, the end details will be shown.
3.21 @@ -652,22 +652,12 @@
3.22 _id = self.element_identifier
3.23 _name = self.element_name
3.24
3.25 - try:
3.26 - p = event_period_from_period(period)
3.27 - except PeriodError, exc:
3.28 - replaced = False
3.29 - errors = exc.args
3.30 - else:
3.31 - replaced = not recurrenceid and p.is_replaced(recurrenceids)
3.32 - errors = []
3.33 -
3.34 period = form_period_from_period(period)
3.35
3.36 # Show controls for editing.
3.37
3.38 - if not replaced:
3.39 - error = errors and (show_start and ("dtstart", index) in errors or not show_start and ("dtend", index) in errors) and " error" or ""
3.40 - page.td(class_="objectvalue dt%s%s" % (show_start and "start" or "end", error))
3.41 + if not period.replaced:
3.42 + page.td(class_="objectvalue dt%s" % (show_start and "start" or "end"))
3.43
3.44 read_only = period.origin == "RRULE"
3.45
3.46 @@ -683,6 +673,7 @@
3.47 # Put the origin somewhere.
3.48
3.49 self.control("recur-origin", "hidden", period.origin or "")
3.50 + self.control("recur-replaced", "hidden", period.replaced and str(index) or "")
3.51
3.52 else:
3.53 page.div(class_="dt disabled")
3.54 @@ -701,15 +692,14 @@
3.55 # Show label as attendee.
3.56
3.57 else:
3.58 - self.show_recurrence_label(index, period, recurrenceid, recurrenceids, show_start)
3.59 + self.show_recurrence_label(index, period, recurrenceid, show_start)
3.60
3.61 - def show_recurrence_label(self, index, period, recurrenceid, recurrenceids, show_start):
3.62 + def show_recurrence_label(self, index, period, recurrenceid, show_start):
3.63
3.64 """
3.65 Show datetime details from the current object for the recurrence having
3.66 the given 'index', for the given recurrence 'period', employing any
3.67 - 'recurrenceid' and 'recurrenceids' for the object to configure the
3.68 - displayed information.
3.69 + 'recurrenceid' for the object to configure the displayed information.
3.70
3.71 If 'show_start' is set to a true value, the start details will be shown;
3.72 otherwise, the end details will be shown.
3.73 @@ -721,18 +711,14 @@
3.74 try:
3.75 p = event_period_from_period(period)
3.76 except PeriodError, exc:
3.77 - replaced = False
3.78 affected = False
3.79 - errors = exc.args
3.80 else:
3.81 - replaced = not recurrenceid and p.is_replaced(recurrenceids)
3.82 affected = p.is_affected(recurrenceid)
3.83 - errors = []
3.84
3.85 period = form_period_from_period(period)
3.86
3.87 css = " ".join([
3.88 - replaced and "replaced" or "",
3.89 + period.replaced and "replaced" or "",
3.90 affected and "affected" or ""
3.91 ])
3.92
3.93 @@ -743,6 +729,7 @@
3.94 if show_start:
3.95 self.date_controls(_name("dtstart", "recur", index), period.get_form_start(), index=index, read_only=True)
3.96 self.control("recur-origin", "hidden", period.origin or "")
3.97 + self.control("recur-replaced", "hidden", period.replaced and str(index) or "")
3.98 else:
3.99 self.date_controls(_name("dtend", "recur", index), period.get_form_end(), index=index, show_tzid=False, read_only=True)
3.100 page.td.close()