2.1 --- a/imipweb/event.py Mon Sep 11 22:31:35 2017 +0200
2.2 +++ b/imipweb/event.py Mon Sep 11 22:50:42 2017 +0200
2.3 @@ -24,7 +24,7 @@
2.4 from imiptools.dates import format_datetime, to_timezone
2.5 from imiptools.mail import Messenger
2.6 from imipweb.data import EventPeriod, event_period_from_period, \
2.7 - get_period_control_values, set_period_control_values, \
2.8 + get_period_control_values, \
2.9 PeriodError
2.10 from imipweb.resource import DateTimeFormUtilities, FormUtilities, ResourceClientForObject
2.11
2.12 @@ -146,7 +146,6 @@
2.13 _ = self.get_translator()
2.14
2.15 page = self.page
2.16 - args = self.env.get_args()
2.17
2.18 attendees = uri_values(self.get_current_attendees())
2.19 is_attendee = self.user in attendees
2.20 @@ -367,7 +366,6 @@
2.21 _ = self.get_translator()
2.22
2.23 page = self.page
2.24 - args = self.env.get_args()
2.25
2.26 attendee_uri = get_uri(attendee)
2.27 partstat = attendee_attr and attendee_attr.get("PARTSTAT")
2.28 @@ -413,7 +411,9 @@
2.29 # Permit the removal of newly-added attendees.
2.30
2.31 remove_type = self.can_remove_attendee(attendee_uri) and "submit" or "checkbox"
2.32 - self.control("remove", remove_type, str(i), str(i) in args.get("remove", []), id="remove-%d" % i, class_="remove")
2.33 + self.control("remove", remove_type, str(i),
2.34 + str(i) in self.get_state("remove", list),
2.35 + id="remove-%d" % i, class_="remove")
2.36
2.37 page.label(_("Remove"), for_="remove-%d" % i, class_="remove")
2.38 page.label(for_="remove-%d" % i, class_="removed")
2.39 @@ -474,7 +474,6 @@
2.40 _ = self.get_translator()
2.41
2.42 page = self.page
2.43 - args = self.env.get_args()
2.44
2.45 # Isolate the controls from neighbouring tables.
2.46
2.47 @@ -511,7 +510,7 @@
2.48 remove_type = self.can_remove_recurrence(period) and "submit" or "checkbox"
2.49
2.50 self.control("recur-remove", remove_type, str(index),
2.51 - str(index) in args.get("recur-remove", []),
2.52 + str(index) in self.get_state("recur-remove", list),
2.53 id="recur-remove-%d" % index, class_="remove")
2.54
2.55 page.label(_("Remove"), for_="recur-remove-%d" % index, class_="remove")
2.56 @@ -797,6 +796,11 @@
2.57
2.58 args = self.env.get_args()
2.59
2.60 + # Update mutable state.
2.61 +
2.62 + self.update_current_attendees()
2.63 + self.update_current_recurrences()
2.64 +
2.65 # Get the possible actions.
2.66
2.67 reply = args.has_key("reply")
2.68 @@ -874,8 +878,9 @@
2.69
2.70 # Obtain any new participants and those to be removed.
2.71
2.72 - attendees = self.get_attendees_from_page()
2.73 - removed = [attendees[int(i)] for i in args.get("remove", [])]
2.74 + attendees = self.get_current_attendees()
2.75 + removed = self.get_removed_attendees(attendees)
2.76 +
2.77 added, to_cancel = self.update_attendees(attendees, removed)
2.78 single_user = not attendees or uri_values(attendees) == [self.user]
2.79 changed = added or changed
2.80 @@ -987,13 +992,16 @@
2.81
2.82 "Return period details for the main start/end period in an event."
2.83
2.84 - return self.get_main_period_from_page().as_event_period()
2.85 + return self.get_current_main_period().as_event_period()
2.86
2.87 def handle_recurrence_periods(self):
2.88
2.89 "Return period details for the recurrences specified for an event."
2.90
2.91 - return [p.as_event_period(i) for i, p in enumerate(self.get_recurrences_from_page())]
2.92 + periods = []
2.93 + for i, p in enumerate(self.get_current_recurrences()):
2.94 + periods.append(p.as_event_period(i))
2.95 + return periods
2.96
2.97 # Access to form-originating object information.
2.98
2.99 @@ -1024,40 +1032,6 @@
2.100 origin_name="recur-origin", replaced_name="recur-replaced",
2.101 tzid=self.get_tzid())
2.102
2.103 - def set_recurrences_in_page(self, recurrences):
2.104 -
2.105 - "Set the recurrences defined in the event form."
2.106 -
2.107 - set_period_control_values(recurrences, self.env.get_args(),
2.108 - "dtstart-recur", "dtend-recur",
2.109 - "dtend-control-recur", "dttimes-control-recur",
2.110 - "recur-origin", "recur-replaced")
2.111 -
2.112 - def get_removed_periods(self, periods):
2.113 -
2.114 - """
2.115 - Return those from the recurrence 'periods' to remove upon updating an
2.116 - event along with those to exclude in a tuple of the form (unscheduled,
2.117 - excluded).
2.118 - """
2.119 -
2.120 - args = self.env.get_args()
2.121 - to_unschedule = []
2.122 - to_exclude = []
2.123 -
2.124 - for i in args.get("recur-remove", []):
2.125 - try:
2.126 - period = periods[int(i)]
2.127 - except (IndexError, ValueError):
2.128 - continue
2.129 -
2.130 - if not self.can_edit_recurrence(period) and self.is_organiser():
2.131 - to_unschedule.append(period)
2.132 - else:
2.133 - to_exclude.append(period)
2.134 -
2.135 - return to_unschedule, to_exclude
2.136 -
2.137 def get_attendees_from_page(self):
2.138
2.139 """
2.140 @@ -1121,9 +1095,8 @@
2.141 else:
2.142 still_to_remove.append(str(i))
2.143
2.144 - args["remove"] = still_to_remove
2.145 + self.set_state("remove", still_to_remove)
2.146
2.147 - args["attendee"] = attendees
2.148 return attendees
2.149
2.150 def update_recurrences_from_page(self):
2.151 @@ -1159,13 +1132,34 @@
2.152 else:
2.153 still_to_remove.append(str(i))
2.154
2.155 - args["recur-remove"] = still_to_remove
2.156 + self.set_state("recur-remove", still_to_remove)
2.157
2.158 - self.set_recurrences_in_page(recurrences)
2.159 return recurrences
2.160
2.161 # Access to current object information.
2.162
2.163 + def get_state(self, key, fn, overwrite=False):
2.164 +
2.165 + """
2.166 + Return state for the given 'key', using 'fn' if no state exists to
2.167 + compute and set the state. If 'overwrite' is set to a true value,
2.168 + compute and return the state using 'fn' regardless of existing state.
2.169 + """
2.170 +
2.171 + state = self.env.get_state()
2.172 + if overwrite or not state.has_key(key):
2.173 + state[key] = fn()
2.174 + return state[key]
2.175 +
2.176 + def set_state(self, key, value):
2.177 +
2.178 + """
2.179 + Set state for the given 'key', establishing new state or replacing any
2.180 + existing state with the given 'value'.
2.181 + """
2.182 +
2.183 + self.env.get_state()[key] = value
2.184 +
2.185 def get_current_main_period(self):
2.186
2.187 """
2.188 @@ -1173,10 +1167,8 @@
2.189 on whether editing has begun or whether the object has just been loaded.
2.190 """
2.191
2.192 - if self.is_initial_load():
2.193 - return self.get_stored_main_period()
2.194 - else:
2.195 - return self.get_main_period_from_page()
2.196 + return self.get_state("main", self.is_initial_load() and
2.197 + self.get_stored_main_period or self.get_main_period_from_page)
2.198
2.199 def get_current_recurrences(self):
2.200
2.201 @@ -1185,19 +1177,16 @@
2.202 details where no editing is in progress, using form data otherwise.
2.203 """
2.204
2.205 - if self.is_initial_load():
2.206 - return self.get_stored_recurrences()
2.207 - else:
2.208 - return self.get_recurrences_from_page()
2.209 + return self.get_state("recurrences", self.is_initial_load() and
2.210 + self.get_stored_recurrences or self.get_recurrences_from_page)
2.211
2.212 def update_current_recurrences(self):
2.213
2.214 "Return an updated collection of recurrences for the current object."
2.215
2.216 - if self.is_initial_load():
2.217 - return self.get_stored_recurrences()
2.218 - else:
2.219 - return self.update_recurrences_from_page()
2.220 + return self.get_state("recurrences", self.is_initial_load() and
2.221 + self.get_stored_recurrences or self.update_recurrences_from_page,
2.222 + overwrite=True)
2.223
2.224 def get_current_attendees(self):
2.225
2.226 @@ -1207,19 +1196,52 @@
2.227 form.
2.228 """
2.229
2.230 - if self.is_initial_load():
2.231 - return self.get_stored_attendees()
2.232 - else:
2.233 - return self.get_attendees_from_page()
2.234 + return self.get_state("attendees", self.is_initial_load() and
2.235 + self.get_stored_attendees or self.get_attendees_from_page)
2.236
2.237 def update_current_attendees(self):
2.238
2.239 "Return an updated collection of attendees for the current object."
2.240
2.241 - if self.is_initial_load():
2.242 - return self.get_stored_attendees()
2.243 - else:
2.244 - return self.update_attendees_from_page()
2.245 + return self.get_state("attendees", self.is_initial_load() and
2.246 + self.get_stored_attendees or self.update_attendees_from_page,
2.247 + overwrite=True)
2.248 +
2.249 + def get_removed_attendees(self, attendees):
2.250 +
2.251 + """
2.252 + Return details of 'attendees' to be removed according to previously
2.253 + determined removal information.
2.254 + """
2.255 +
2.256 + removed = []
2.257 + for i in self.get_state("remove", list):
2.258 + removed.append(attendees[int(i)])
2.259 + return removed
2.260 +
2.261 + def get_removed_periods(self, periods):
2.262 +
2.263 + """
2.264 + Return those from the recurrence 'periods' to remove upon updating an
2.265 + event along with those to exclude in a tuple of the form (unscheduled,
2.266 + excluded).
2.267 + """
2.268 +
2.269 + to_unschedule = []
2.270 + to_exclude = []
2.271 +
2.272 + for i in self.get_state("recur-remove", list):
2.273 + try:
2.274 + period = periods[int(i)]
2.275 + except (IndexError, ValueError):
2.276 + continue
2.277 +
2.278 + if not self.can_edit_recurrence(period) and self.is_organiser():
2.279 + to_unschedule.append(period)
2.280 + else:
2.281 + to_exclude.append(period)
2.282 +
2.283 + return to_unschedule, to_exclude
2.284
2.285 # Full page output methods.
2.286
2.287 @@ -1239,9 +1261,6 @@
2.288 if not errors:
2.289 return True
2.290
2.291 - self.update_current_attendees()
2.292 - self.update_current_recurrences()
2.293 -
2.294 _ = self.get_translator()
2.295
2.296 self.new_page(title=_("Event"))