1.1 --- a/imipweb/event.py Sat Oct 07 00:37:47 2017 +0200
1.2 +++ b/imipweb/event.py Sat Oct 07 22:08:13 2017 +0200
1.3 @@ -28,7 +28,7 @@
1.4 classify_periods, filter_duplicates, \
1.5 remove_from_collection, \
1.6 get_period_control_values, \
1.7 - PeriodError
1.8 + PeriodError, State
1.9 from imipweb.resource import DateTimeFormUtilities, FormUtilities, ResourceClientForObject
1.10
1.11 # Fake gettext method for strings to be translated later.
1.12 @@ -39,8 +39,18 @@
1.13
1.14 "A resource presenting the details of an event."
1.15
1.16 - def __init__(self, resource=None):
1.17 - ResourceClientForObject.__init__(self, resource)
1.18 + def __init__(self, resource=None, messenger=None):
1.19 + ResourceClientForObject.__init__(self, resource, messenger or Messenger())
1.20 +
1.21 + # Manage editing state.
1.22 +
1.23 + self.state = State({
1.24 + "attendees" : self.get_current_attendees,
1.25 + "main" : self.get_current_main_period,
1.26 + "recurrences" : self.get_current_recurrences,
1.27 + "recur-remove" : list,
1.28 + "remove" : list,
1.29 + })
1.30
1.31 # Various property values and labels.
1.32
1.33 @@ -152,7 +162,7 @@
1.34
1.35 page = self.page
1.36
1.37 - attendees = uri_values(self.get_current_attendees())
1.38 + attendees = uri_values(self.state.get("attendees"))
1.39 is_attendee = self.user in attendees
1.40
1.41 if not self.obj.is_shared():
1.42 @@ -214,8 +224,8 @@
1.43
1.44 # Obtain basic event information, generating any necessary editing controls.
1.45
1.46 - attendees = self.get_current_attendees()
1.47 - period = self.get_current_main_period()
1.48 + attendees = self.state.get("attendees")
1.49 + period = self.state.get("main")
1.50 stored_period = self.get_stored_main_period()
1.51 self.show_object_datetime_controls(period)
1.52
1.53 @@ -417,7 +427,7 @@
1.54
1.55 remove_type = self.can_remove_attendee(attendee_uri) and "submit" or "checkbox"
1.56 self.control("remove", remove_type, str(i),
1.57 - attendee in self.get_state("remove", list),
1.58 + attendee in self.state.get("remove"),
1.59 id="remove-%d" % i, class_="remove")
1.60
1.61 page.label(_("Remove"), for_="remove-%d" % i, class_="remove")
1.62 @@ -452,7 +462,7 @@
1.63
1.64 # Obtain the periods associated with the event.
1.65
1.66 - recurrences = self.get_current_recurrences()
1.67 + recurrences = self.state.get("recurrences")
1.68
1.69 if len(recurrences) < 1:
1.70 return
1.71 @@ -515,7 +525,7 @@
1.72 remove_type = self.can_remove_recurrence(period) and "submit" or "checkbox"
1.73
1.74 self.control("recur-remove", remove_type, str(index),
1.75 - period in self.get_state("recur-remove", list),
1.76 + period in self.state.get("recur-remove"),
1.77 id="recur-remove-%d" % index, class_="remove")
1.78
1.79 page.label(_("Remove"), for_="recur-remove-%d" % index, class_="remove")
1.80 @@ -549,7 +559,7 @@
1.81 return
1.82
1.83 attendees = self.get_verbose_attendees(attendees)
1.84 - current_attendees = [uri for (name, uri) in uri_parts(self.get_current_attendees())]
1.85 + current_attendees = [uri for (name, uri) in uri_parts(self.state.get("attendees"))]
1.86 current_periods = set(self.get_periods(self.obj))
1.87
1.88 # Get suggestions. Attendees are aggregated and reference the existing
1.89 @@ -687,7 +697,7 @@
1.90 conflicts = set()
1.91 attendee_map = uri_dict(self.obj.get_value_map("ATTENDEE"))
1.92
1.93 - for name, participant in uri_parts(self.get_current_attendees()):
1.94 + for name, participant in uri_parts(self.state.get("attendees")):
1.95 if participant == self.user:
1.96 freebusy = self.store.get_freebusy(participant)
1.97 elif participant:
1.98 @@ -771,9 +781,6 @@
1.99
1.100 "A request handler for the event page."
1.101
1.102 - def __init__(self, resource=None, messenger=None):
1.103 - ResourceClientForObject.__init__(self, resource, messenger or Messenger())
1.104 -
1.105 def link_to(self, uid=None, recurrenceid=None):
1.106 args = self.env.get_query()
1.107 d = {}
1.108 @@ -886,8 +893,8 @@
1.109
1.110 # Obtain any new participants and those to be removed.
1.111
1.112 - attendees = self.get_current_attendees()
1.113 - removed = self.get_removed_attendees()
1.114 + attendees = self.state.get("attendees")
1.115 + removed = self.state.get("remove")
1.116
1.117 added, to_cancel = self.update_attendees(attendees, removed)
1.118 single_user = not attendees or uri_values(attendees) == [self.user]
1.119 @@ -1000,14 +1007,14 @@
1.120
1.121 "Return period details for the main start/end period in an event."
1.122
1.123 - return self.get_current_main_period().as_event_period()
1.124 + return self.state.get("main").as_event_period()
1.125
1.126 def handle_recurrence_periods(self):
1.127
1.128 "Return period details for the recurrences specified for an event."
1.129
1.130 periods = []
1.131 - for i, p in enumerate(self.get_current_recurrences()):
1.132 + for i, p in enumerate(self.state.get("recurrences")):
1.133 periods.append(p.as_event_period(i))
1.134 return periods
1.135
1.136 @@ -1052,7 +1059,7 @@
1.137 # Get remaining periods and those whose removal is deferred.
1.138
1.139 new, changed, unchanged, replaced, to_remove = classify_periods(periods,
1.140 - self.get_state("recur-remove", list))
1.141 + self.state.get("recur-remove"))
1.142
1.143 return new + unchanged, changed, to_remove
1.144
1.145 @@ -1114,7 +1121,7 @@
1.146 if remove:
1.147 still_to_remove = remove_from_collection(attendees,
1.148 args["remove"], self.can_remove_attendee)
1.149 - self.set_state("remove", still_to_remove)
1.150 + self.state.set("remove", still_to_remove)
1.151
1.152 if add or add_suggested or remove:
1.153 attendees = filter_duplicates(attendees)
1.154 @@ -1132,7 +1139,7 @@
1.155 add = args.has_key("recur-add")
1.156
1.157 if add:
1.158 - period = self.get_current_main_period().as_form_period()
1.159 + period = self.state.get("main").as_form_period()
1.160 period.origin = "RDATE"
1.161 recurrences.append(period)
1.162
1.163 @@ -1144,33 +1151,12 @@
1.164 if remove:
1.165 still_to_remove = remove_from_collection(recurrences,
1.166 args["recur-remove"], self.can_remove_recurrence)
1.167 - self.set_state("recur-remove", still_to_remove)
1.168 + self.state.set("recur-remove", still_to_remove)
1.169
1.170 return recurrences
1.171
1.172 # Access to current object information.
1.173
1.174 - def get_state(self, key, fn, overwrite=False):
1.175 -
1.176 - """
1.177 - Return state for the given 'key', using 'fn' if no state exists to
1.178 - compute and set the state. If 'overwrite' is set to a true value,
1.179 - compute and return the state using 'fn' regardless of existing state.
1.180 - """
1.181 -
1.182 - if overwrite or not self.state.has_key(key):
1.183 - self.state[key] = fn()
1.184 - return self.state[key]
1.185 -
1.186 - def set_state(self, key, value):
1.187 -
1.188 - """
1.189 - Set state for the given 'key', establishing new state or replacing any
1.190 - existing state with the given 'value'.
1.191 - """
1.192 -
1.193 - self.state[key] = value
1.194 -
1.195 def get_current_main_period(self):
1.196
1.197 """
1.198 @@ -1178,8 +1164,10 @@
1.199 on whether editing has begun or whether the object has just been loaded.
1.200 """
1.201
1.202 - return self.get_state("main", self.is_initial_load() and
1.203 - self.get_stored_main_period or self.get_main_period_from_page)
1.204 + if self.is_initial_load():
1.205 + return self.get_stored_main_period()
1.206 + else:
1.207 + return self.get_main_period_from_page()
1.208
1.209 def get_current_recurrences(self):
1.210
1.211 @@ -1188,16 +1176,22 @@
1.212 details where no editing is in progress, using form data otherwise.
1.213 """
1.214
1.215 - return self.get_state("recurrences", self.is_initial_load() and
1.216 - self.get_stored_recurrences or self.get_recurrences_from_page)
1.217 + if self.is_initial_load():
1.218 + return self.get_stored_recurrences()
1.219 + else:
1.220 + return self.get_recurrences_from_page()
1.221
1.222 def update_current_recurrences(self):
1.223
1.224 "Return an updated collection of recurrences for the current object."
1.225
1.226 - return self.get_state("recurrences", self.is_initial_load() and
1.227 - self.get_stored_recurrences or self.update_recurrences_from_page,
1.228 - overwrite=True)
1.229 + if self.is_initial_load():
1.230 + l = self.get_stored_recurrences()
1.231 + else:
1.232 + l = self.update_recurrences_from_page()
1.233 +
1.234 + self.state.set("recurrences", l)
1.235 + return l
1.236
1.237 def get_current_attendees(self):
1.238
1.239 @@ -1207,25 +1201,22 @@
1.240 form.
1.241 """
1.242
1.243 - return self.get_state("attendees", self.is_initial_load() and
1.244 - self.get_stored_attendees or self.get_attendees_from_page)
1.245 + if self.is_initial_load():
1.246 + return self.get_stored_attendees()
1.247 + else:
1.248 + return self.get_attendees_from_page()
1.249
1.250 def update_current_attendees(self):
1.251
1.252 "Return an updated collection of attendees for the current object."
1.253
1.254 - return self.get_state("attendees", self.is_initial_load() and
1.255 - self.get_stored_attendees or self.update_attendees_from_page,
1.256 - overwrite=True)
1.257 -
1.258 - def get_removed_attendees(self):
1.259 + if self.is_initial_load():
1.260 + l = self.get_stored_attendees()
1.261 + else:
1.262 + l = self.update_attendees_from_page()
1.263
1.264 - """
1.265 - Return details of attendees to be removed according to previously
1.266 - determined removal information.
1.267 - """
1.268 -
1.269 - return self.get_state("remove", list)
1.270 + self.state.set("attendees", l)
1.271 + return l
1.272
1.273 # Full page output methods.
1.274