1.1 --- a/imipweb/data.py Sun Oct 15 21:34:23 2017 +0200
1.2 +++ b/imipweb/data.py Sun Oct 15 22:16:05 2017 +0200
1.3 @@ -412,8 +412,9 @@
1.4 "Return whether an update can be prepared and sent."
1.5
1.6 return not self.is_organiser() or \
1.7 + not self.obj.is_shared() or \
1.8 self.obj.is_shared() and self.state.get("changed") and \
1.9 - self.have_other_attendees()
1.10 + self.have_other_attendees()
1.11
1.12 def have_other_attendees(self):
1.13
1.14 @@ -471,7 +472,7 @@
1.15 "Add a blank attendee."
1.16
1.17 attendees = self.state.get("attendees")
1.18 - attendees[uri or ""] = {}
1.19 + attendees[uri or ""] = {"PARTSTAT" : "NEEDS-ACTION"}
1.20
1.21 def add_suggested_attendee(self, index):
1.22
1.23 @@ -511,9 +512,9 @@
1.24 # Cancel any removed periods.
1.25
1.26 if operation == "remove":
1.27 - for p in current:
1.28 + for index, p in enumerate(current):
1.29 if p == period:
1.30 - p.cancelled = True
1.31 + self.cancel_periods([index])
1.32 break
1.33
1.34 # Add or replace any other suggestions.
1.35 @@ -573,6 +574,12 @@
1.36 for index in to_remove:
1.37 del periods[index]
1.38
1.39 + def can_edit_attendance(self):
1.40 +
1.41 + "Return whether the organiser's attendance can be edited."
1.42 +
1.43 + return self.state.get("attendees").has_key(self.user)
1.44 +
1.45 def edit_attendance(self, partstat):
1.46
1.47 "Set the 'partstat' of the current user, if attending."
1.48 @@ -580,7 +587,9 @@
1.49 attendees = self.state.get("attendees")
1.50 attr = attendees.get(self.user)
1.51
1.52 - if attr:
1.53 + # Set the attendance for the user, if attending.
1.54 +
1.55 + if attr is not None:
1.56 new_attr = {}
1.57 new_attr.update(attr)
1.58 new_attr["PARTSTAT"] = partstat
1.59 @@ -1287,6 +1296,14 @@
1.60
1.61 cancelled_removed = select_recurrences(cancelled, removed).values()
1.62
1.63 + # Cancelled periods originating from rules must be excluded since there are
1.64 + # no explicit instances to be deleted.
1.65 +
1.66 + cancelled_rule = []
1.67 + for p in cancelled_removed:
1.68 + if p.origin == "RRULE":
1.69 + cancelled_rule.append(p)
1.70 +
1.71 # Reinstated periods are previously-cancelled periods that are now modified
1.72 # periods, and they appear in updates.
1.73
1.74 @@ -1300,7 +1317,6 @@
1.75 # As organiser...
1.76
1.77 if is_organiser:
1.78 - to_exclude = []
1.79
1.80 # For unshared events...
1.81 # All modifications redefine the event.
1.82 @@ -1309,9 +1325,11 @@
1.83 # New periods should cause the event to be redefined.
1.84 # Other changes should also cause event redefinition.
1.85 # Event redefinition should only occur if no replacement periods exist.
1.86 + # Cancelled rule-originating periods must be excluded.
1.87
1.88 if not is_shared or new and not replaced:
1.89 to_set = active_periods
1.90 + to_exclude = cancelled_rule
1.91 to_unschedule = []
1.92 to_reschedule = []
1.93 to_add = []
1.94 @@ -1323,6 +1341,7 @@
1.95
1.96 else:
1.97 to_set = []
1.98 + to_exclude = []
1.99 to_unschedule = cancelled_removed
1.100 to_reschedule = list(chain(replaced_modified, retained_modified, reinstated))
1.101 to_add = new