1.1 --- a/imipweb/event.py Wed Apr 01 00:00:16 2015 +0200
1.2 +++ b/imipweb/event.py Wed Apr 01 01:31:39 2015 +0200
1.3 @@ -20,7 +20,7 @@
1.4 """
1.5
1.6 from datetime import datetime, timedelta
1.7 -from imiptools.client import update_attendees
1.8 +from imiptools.client import update_attendees, update_participation
1.9 from imiptools.data import get_uri, uri_dict, uri_values
1.10 from imiptools.dates import format_datetime, to_date, get_datetime, \
1.11 get_datetime_item, get_period_item, \
1.12 @@ -89,31 +89,31 @@
1.13
1.14 if reply or invite or cancel or save:
1.15
1.16 - # Update time periods (main and recurring).
1.17 + # Update principal event details if organiser.
1.18 +
1.19 + if is_organiser:
1.20 +
1.21 + # Update time periods (main and recurring).
1.22 +
1.23 + if periods:
1.24 + self.set_period_in_object(obj, periods[0])
1.25 + self.set_periods_in_object(obj, periods[1:])
1.26
1.27 - if periods:
1.28 - self.set_period_in_object(obj, periods[0])
1.29 - self.set_periods_in_object(obj, periods[1:])
1.30 + # Update summary.
1.31 +
1.32 + if args.has_key("summary"):
1.33 + obj["SUMMARY"] = [(args["summary"][0], {})]
1.34
1.35 - # Update summary.
1.36 + # Obtain any participants and those to be removed.
1.37
1.38 - if args.has_key("summary"):
1.39 - obj["SUMMARY"] = [(args["summary"][0], {})]
1.40 + attendees = args.get("attendee")
1.41 + removed = args.get("remove")
1.42 + to_cancel = update_attendees(obj, attendees, removed)
1.43
1.44 # Update attendee participation.
1.45
1.46 - attendees = uri_dict(obj.get_value_map("ATTENDEE"))
1.47 -
1.48 if args.has_key("partstat"):
1.49 - if attendees.has_key(self.user):
1.50 - attendees[self.user]["PARTSTAT"] = args["partstat"][0]
1.51 - if attendees[self.user].has_key("RSVP"):
1.52 - del attendees[self.user]["RSVP"]
1.53 -
1.54 - # Obtain any participants to be added or removed.
1.55 -
1.56 - removed = args.get("remove")
1.57 - added = args.get("added")
1.58 + update_participation(obj, self.user, args["partstat"][0])
1.59
1.60 # Process any action.
1.61
1.62 @@ -125,16 +125,19 @@
1.63
1.64 # Process the object and remove it from the list of requests.
1.65
1.66 - if reply and handler.process_received_request(update) or \
1.67 - is_organiser and (invite or cancel) and \
1.68 - handler.process_created_request(invite and "REQUEST" or "CANCEL", update, removed, added):
1.69 + if reply and handler.process_received_request(update):
1.70 + self.remove_request(uid, recurrenceid)
1.71 +
1.72 + elif is_organiser and (invite or cancel):
1.73
1.74 - self.remove_request(uid, recurrenceid)
1.75 + if handler.process_created_request(
1.76 + invite and "REQUEST" or "CANCEL", update, to_cancel):
1.77 +
1.78 + self.remove_request(uid, recurrenceid)
1.79
1.80 # Save single user events.
1.81
1.82 elif save:
1.83 - to_cancel = update_attendees(obj, added, removed)
1.84 self.store.set_event(self.user, uid, recurrenceid, node=obj.to_node())
1.85 self.update_freebusy(uid, recurrenceid, obj)
1.86 self.remove_request(uid, recurrenceid)
1.87 @@ -367,29 +370,23 @@
1.88
1.89 return False
1.90
1.91 - def handle_new_attendees(self, obj):
1.92 + def handle_attendees(self, obj):
1.93
1.94 - "Add or remove new attendees. This does not affect the stored object."
1.95 + "Add or remove attendees. This does not affect the stored object."
1.96
1.97 args = self.env.get_args()
1.98
1.99 - existing_attendees = uri_values(obj.get_values("ATTENDEE") or [])
1.100 - new_attendees = args.get("added", [])
1.101 - new_attendee = args.get("attendee", [""])[0]
1.102 + attendees = args.get("attendee", [])
1.103
1.104 if args.has_key("add"):
1.105 - if new_attendee.strip():
1.106 - new_attendee = get_uri(new_attendee.strip())
1.107 - if new_attendee not in new_attendees and new_attendee not in existing_attendees:
1.108 - new_attendees.append(new_attendee)
1.109 - new_attendee = ""
1.110 + attendees.append("")
1.111
1.112 - if args.has_key("removenew"):
1.113 - removed_attendee = args["removenew"][0]
1.114 - if removed_attendee in new_attendees:
1.115 - new_attendees.remove(removed_attendee)
1.116 + if args.has_key("remove"):
1.117 + removed_attendee = args["remove"][0]
1.118 + if removed_attendee in attendees:
1.119 + attendees.remove(removed_attendee)
1.120
1.121 - return new_attendees, new_attendee
1.122 + return attendees
1.123
1.124 def get_event_period(self, obj):
1.125
1.126 @@ -501,12 +498,10 @@
1.127 # Obtain basic event information, showing any necessary editing controls.
1.128
1.129 is_organiser = get_uri(obj.get_value("ORGANIZER")) == self.user
1.130 + initial_load = not args.has_key("editing")
1.131
1.132 - if is_organiser:
1.133 - new_attendees, new_attendee = self.handle_new_attendees(obj)
1.134 - else:
1.135 - new_attendees = []
1.136 - new_attendee = ""
1.137 + attendees = is_organiser and self.handle_attendees(obj) or \
1.138 + (initial_load or not is_organiser) and uri_values(obj.get_values("ATTENDEE")) or []
1.139
1.140 (dtstart, dtstart_attr), (dtend, dtend_attr) = self.get_event_period(obj)
1.141 self.show_object_datetime_controls(dtstart, dtend)
1.142 @@ -528,7 +523,7 @@
1.143 rowspan = len(items)
1.144
1.145 if name == "ATTENDEE":
1.146 - rowspan += len(new_attendees) + 1
1.147 + rowspan = len(attendees) + 1 # for the add button
1.148 elif not items:
1.149 continue
1.150
1.151 @@ -568,7 +563,83 @@
1.152 page.td.close()
1.153 page.tr.close()
1.154
1.155 - # Handle potentially many values.
1.156 + # Handle attendees specially.
1.157 +
1.158 + elif name == "ATTENDEE":
1.159 + attendee_map = dict(items)
1.160 + first = True
1.161 +
1.162 + for i, value in enumerate(attendees):
1.163 + if not first:
1.164 + page.tr()
1.165 + else:
1.166 + first = False
1.167 +
1.168 + page.td(class_="objectvalue")
1.169 +
1.170 + # Obtain details of existing attendees.
1.171 +
1.172 + attr = attendee_map.get(value)
1.173 + partstat = attr and attr.get("PARTSTAT")
1.174 +
1.175 + # Show a form control as organiser for new attendees.
1.176 +
1.177 + if is_organiser and not partstat:
1.178 + page.input(name="attendee", type="value", value=value, size="40")
1.179 + else:
1.180 + page.input(name="attendee", type="hidden", value=value)
1.181 + page.add(value)
1.182 + page.add(" ")
1.183 +
1.184 + # Show participation status, editable for the current user.
1.185 +
1.186 + if value == self.user:
1.187 + self._show_menu("partstat", partstat, self.partstat_items, "partstat")
1.188 +
1.189 + # Allow the participation indicator to act as a submit
1.190 + # button in order to refresh the page and show a control for
1.191 + # the current user, if indicated.
1.192 +
1.193 + elif is_organiser:
1.194 + page.input(name="partstat-refresh", type="submit", value="refresh", id="partstat-%d" % i, class_="refresh")
1.195 + page.label(dict(self.partstat_items).get(partstat, ""), for_="partstat-%s" % i, class_="partstat")
1.196 + else:
1.197 + page.span(dict(self.partstat_items).get(partstat, ""), class_="partstat")
1.198 +
1.199 + # Permit organisers to remove attendees.
1.200 +
1.201 + if is_organiser:
1.202 +
1.203 + # Permit the removal of newly-added attendees.
1.204 +
1.205 + remove_type = partstat and "checkbox" or "submit"
1.206 +
1.207 + if value in args.get("remove", []):
1.208 + page.input(name="remove", type=remove_type, value=value, id="remove-%d" % i, class_="remove", checked="checked")
1.209 + else:
1.210 + page.input(name="remove", type=remove_type, value=value, id="remove-%d" % i, class_="remove")
1.211 +
1.212 + page.label("Remove", for_="remove-%d" % i, class_="remove")
1.213 + page.label("Uninvited", for_="remove-%d" % i, class_="removed")
1.214 +
1.215 + page.td.close()
1.216 + page.tr.close()
1.217 +
1.218 + # Allow more attendees to be specified.
1.219 +
1.220 + if is_organiser:
1.221 + i = len(attendees)
1.222 +
1.223 + if not first:
1.224 + page.tr()
1.225 +
1.226 + page.td()
1.227 + page.input(name="add", type="submit", value="add", id="add-%d" % i, class_="add")
1.228 + page.label("Add attendee", for_="add-%d" % i, class_="add")
1.229 + page.td.close()
1.230 + page.tr.close()
1.231 +
1.232 + # Handle potentially many values of other kinds.
1.233
1.234 else:
1.235 first = True
1.236 @@ -579,57 +650,8 @@
1.237 else:
1.238 first = False
1.239
1.240 - if name == "ATTENDEE":
1.241 - value = get_uri(value)
1.242 -
1.243 - page.td(class_="objectvalue")
1.244 - page.add(value)
1.245 - page.add(" ")
1.246 -
1.247 - partstat = attr.get("PARTSTAT")
1.248 - if value == self.user:
1.249 - self._show_menu("partstat", partstat, self.partstat_items, "partstat")
1.250 - else:
1.251 - page.span(dict(self.partstat_items).get(partstat, ""), class_="partstat")
1.252 -
1.253 - if is_organiser:
1.254 - if value in args.get("remove", []):
1.255 - page.input(name="remove", type="checkbox", value=value, id="remove-%d" % i, class_="remove", checked="checked")
1.256 - else:
1.257 - page.input(name="remove", type="checkbox", value=value, id="remove-%d" % i, class_="remove")
1.258 - page.label("Remove", for_="remove-%d" % i, class_="remove")
1.259 - page.label("Uninvited", for_="remove-%d" % i, class_="removed")
1.260 -
1.261 - else:
1.262 - page.td(class_="objectvalue")
1.263 - page.add(value)
1.264 -
1.265 - page.td.close()
1.266 - page.tr.close()
1.267 -
1.268 - # Allow more attendees to be specified.
1.269 -
1.270 - if is_organiser and name == "ATTENDEE":
1.271 - for i, attendee in enumerate(new_attendees):
1.272 - if not first:
1.273 - page.tr()
1.274 - else:
1.275 - first = False
1.276 -
1.277 - page.td()
1.278 - page.input(name="added", type="value", value=attendee, size="40")
1.279 - page.input(name="removenew", type="submit", value=attendee, id="removenew-%d" % i, class_="remove")
1.280 - page.label("Remove", for_="removenew-%d" % i, class_="remove")
1.281 - page.td.close()
1.282 - page.tr.close()
1.283 -
1.284 - if not first:
1.285 - page.tr()
1.286 -
1.287 - page.td()
1.288 - page.input(name="attendee", type="value", value=new_attendee, size="40")
1.289 - page.input(name="add", type="submit", value="add", id="add-%d" % i, class_="add")
1.290 - page.label("Add", for_="add-%d" % i, class_="add")
1.291 + page.td(class_="objectvalue")
1.292 + page.add(value)
1.293 page.td.close()
1.294 page.tr.close()
1.295