1.1 --- a/imipweb/data.py Thu Sep 14 23:18:30 2017 +0200
1.2 +++ b/imipweb/data.py Fri Sep 15 00:03:38 2017 +0200
1.3 @@ -343,46 +343,80 @@
1.4
1.5 # Form period processing.
1.6
1.7 -def get_active_periods(periods):
1.8 +def get_existing_periods(periods, still_to_remove):
1.9
1.10 - "Return a mapping of non-replaced periods to counts, given 'periods'."
1.11 + """
1.12 + Find all periods that existed before editing, given 'periods', applying
1.13 + the periods in 'still_to_remove' and producing retained, replaced and
1.14 + to-remove collections containing these existing periods.
1.15 + """
1.16
1.17 - active_periods = {}
1.18 + retained = []
1.19 + replaced = []
1.20 + to_remove = []
1.21 +
1.22 for p in periods:
1.23 - if not p.replaced:
1.24 - if not active_periods.has_key(p):
1.25 - active_periods[p] = 1
1.26 + p = form_period_from_period(p)
1.27 + if p.recurrenceid:
1.28 + if p.replaced:
1.29 + replaced.append(p)
1.30 + elif p in still_to_remove:
1.31 + to_remove.append(p)
1.32 else:
1.33 - active_periods[p] += 1
1.34 - return active_periods
1.35 + retained.append(p)
1.36 +
1.37 + return retained, replaced, to_remove
1.38 +
1.39 +def get_new_periods(periods):
1.40 +
1.41 + "Return all periods introduced during editing, given 'periods'."
1.42 +
1.43 + new = []
1.44 + for p in periods:
1.45 + fp = form_period_from_period(p)
1.46 + if not fp.recurrenceid:
1.47 + new.append(p)
1.48 + return new
1.49
1.50 -def get_removed_periods(periods, still_to_remove):
1.51 +def get_changed_periods(periods):
1.52 +
1.53 + "Return changed and unchanged periods, given 'periods'."
1.54 +
1.55 + changed = []
1.56 + unchanged = []
1.57 +
1.58 + for p in periods:
1.59 + fp = form_period_from_period(p)
1.60 + if fp.is_changed():
1.61 + changed.append(p)
1.62 + else:
1.63 + unchanged.append(p)
1.64 +
1.65 + return changed, unchanged
1.66 +
1.67 +def classify_periods(periods, still_to_remove):
1.68
1.69 """
1.70 From the recurrence 'periods', given details of those 'still_to_remove',
1.71 - return the remaining active periods and the periods to unschedule or
1.72 - exclude, using a tuple of the form (active, unscheduled, excluded).
1.73 + return a tuple containing collections of new, changed, unchanged, replaced
1.74 + and to-be-removed periods.
1.75 """
1.76
1.77 - to_remove = set()
1.78 -
1.79 - # Get all periods that are not replaced.
1.80 + retained, replaced, to_remove = get_existing_periods(periods, still_to_remove)
1.81
1.82 - active_periods = get_active_periods(periods)
1.83 + # Filter new periods with the existing period information.
1.84
1.85 - for period in still_to_remove:
1.86 - active_periods[period] -= 1
1.87 - to_remove.add(period)
1.88 + new = set(get_new_periods(periods))
1.89
1.90 - # Determine whether some periods are both removed and added.
1.91 + new.difference_update(retained)
1.92 + new.difference_update(replaced)
1.93 + new.difference_update(to_remove)
1.94
1.95 - remaining = []
1.96 - for period, n in active_periods.items():
1.97 - if n > 0:
1.98 - remaining.append(period)
1.99 + # Divide retained periods into changed and unchanged collections.
1.100
1.101 - to_remove.difference_update(remaining)
1.102 - return remaining, to_remove
1.103 + changed, unchanged = get_changed_periods(retained)
1.104 +
1.105 + return list(new), changed, unchanged, replaced, to_remove
1.106
1.107
1.108
2.1 --- a/imipweb/event.py Thu Sep 14 23:18:30 2017 +0200
2.2 +++ b/imipweb/event.py Fri Sep 15 00:03:38 2017 +0200
2.3 @@ -25,8 +25,8 @@
2.4 from imiptools.mail import Messenger
2.5 from imipweb.data import EventPeriod, event_period_from_period, \
2.6 form_period_from_period, \
2.7 - filter_duplicates, get_active_periods, \
2.8 - get_removed_periods, remove_from_collection, \
2.9 + classify_periods, filter_duplicates, \
2.10 + remove_from_collection, \
2.11 get_period_control_values, \
2.12 PeriodError
2.13 from imipweb.resource import DateTimeFormUtilities, FormUtilities, ResourceClientForObject
2.14 @@ -857,7 +857,11 @@
2.15 # modified period information.
2.16 # NOTE: Currently, rules are not updated.
2.17
2.18 - active_periods, to_unschedule, to_exclude = self.get_removed_periods(periods)
2.19 + editable_periods, to_change, to_remove = self.classify_periods(periods)
2.20 +
2.21 + active_periods = editable_periods + to_change
2.22 + to_unschedule = self.is_organiser() and to_remove or []
2.23 + to_exclude = not self.is_organiser() and to_remove or []
2.24
2.25 periods = set(periods)
2.26 changed = self.obj.set_period(period) or changed
2.27 @@ -1037,32 +1041,20 @@
2.28 recurrenceid_name="recur-id",
2.29 tzid=self.get_tzid())
2.30
2.31 - def get_removed_periods(self, periods):
2.32 + def classify_periods(self, periods):
2.33
2.34 """
2.35 From the recurrence 'periods' and information provided in the request,
2.36 - return the remaining active periods, the periods to unschedule, and the
2.37 - periods to exclude, in a tuple of the form (active, unscheduled,
2.38 - excluded).
2.39 + return a tuple containing the new and unchanged periods, the changed
2.40 + periods, and the periods to be removed.
2.41 """
2.42
2.43 # Get remaining periods and those whose removal is deferred.
2.44
2.45 - remaining, to_remove = get_removed_periods(periods,
2.46 + new, changed, unchanged, replaced, to_remove = classify_periods(periods,
2.47 self.get_state("recur-remove", list))
2.48
2.49 - # Sort the deferred removal periods into categories.
2.50 -
2.51 - to_unschedule = set()
2.52 - to_exclude = set()
2.53 -
2.54 - for period in to_remove:
2.55 - if not self.can_edit_recurrence(period) and self.is_organiser():
2.56 - to_unschedule.add(period)
2.57 - else:
2.58 - to_exclude.add(period)
2.59 -
2.60 - return remaining, to_unschedule, to_exclude
2.61 + return new + unchanged, changed, to_remove
2.62
2.63 def get_attendees_from_page(self):
2.64