2.1 --- a/imip_manager.py Sat Jan 31 22:28:33 2015 +0100
2.2 +++ b/imip_manager.py Sat Jan 31 22:34:12 2015 +0100
2.3 @@ -53,7 +53,8 @@
2.4
2.5 "A CGI-compatible environment."
2.6
2.7 - def __init__(self):
2.8 + def __init__(self, charset=None):
2.9 + self.charset = charset
2.10 self.args = None
2.11 self.method = None
2.12 self.path = None
2.13 @@ -64,7 +65,15 @@
2.14 if self.args is None:
2.15 if self.get_method() != "POST":
2.16 setenv("QUERY_STRING", "")
2.17 - self.args = cgi.parse(keep_blank_values=True)
2.18 + args = cgi.parse(keep_blank_values=True)
2.19 +
2.20 + if not self.charset:
2.21 + self.args = args
2.22 + else:
2.23 + self.args = {}
2.24 + for key, values in args.items():
2.25 + self.args[key] = [unicode(value, self.charset) for value in values]
2.26 +
2.27 return self.args
2.28
2.29 def get_method(self):
2.30 @@ -196,7 +205,9 @@
2.31 def __init__(self, messenger=None):
2.32 self.messenger = messenger or Messenger()
2.33
2.34 - self.env = CGIEnvironment()
2.35 + self.encoding = "utf-8"
2.36 + self.env = CGIEnvironment(self.encoding)
2.37 +
2.38 user = self.env.get_user()
2.39 self.user = user and get_uri(user) or None
2.40 self.preferences = None
2.41 @@ -205,7 +216,6 @@
2.42
2.43 self.out = self.env.get_output()
2.44 self.page = markup.page()
2.45 - self.encoding = "utf-8"
2.46
2.47 self.store = imip_store.FileStore()
2.48 self.objects = {}
2.49 @@ -381,10 +391,10 @@
2.50
2.51 self.redirect(self.env.new_url(uid))
2.52
2.53 - def handle_request(self, uid, request, queued):
2.54 + def handle_request(self, uid, obj, queued):
2.55
2.56 """
2.57 - Handle actions involving the given 'uid' and 'request' object, where
2.58 + Handle actions involving the given 'uid' and 'obj' object, where
2.59 'queued' indicates that the object has not yet been handled.
2.60 """
2.61
2.62 @@ -393,6 +403,14 @@
2.63 args = self.env.get_args()
2.64 handled = True
2.65
2.66 + # Update the object.
2.67 +
2.68 + if args.has_key("summary"):
2.69 + details = self._get_details(obj)
2.70 + details["SUMMARY"] = [(args["summary"][0], {})]
2.71 +
2.72 + # Process any action.
2.73 +
2.74 accept = args.has_key("accept")
2.75 decline = args.has_key("decline")
2.76 invite = args.has_key("invite")
2.77 @@ -400,9 +418,9 @@
2.78
2.79 if accept or decline or invite:
2.80
2.81 - handler = ManagerHandler(request, self.user, self.messenger)
2.82 + handler = ManagerHandler(obj, self.user, self.messenger)
2.83
2.84 - # Process the request and remove it from the list.
2.85 + # Process the object and remove it from the list of requests.
2.86
2.87 if (accept or decline) and handler.process_received_request(accept, update) or \
2.88 invite and handler.process_created_request(update):
2.89 @@ -418,20 +436,23 @@
2.90 else:
2.91 handled = False
2.92
2.93 + # Upon handling an action, redirect to the main page.
2.94 +
2.95 if handled:
2.96 self.redirect(self.env.get_path())
2.97
2.98 return handled
2.99
2.100 - def show_request_form(self, obj, needs_action):
2.101 + def show_request_controls(self, obj, needs_action):
2.102
2.103 """
2.104 - Show a form for a request concerning 'obj', indicating whether action is
2.105 - needed if 'needs_action' is specified as a true value.
2.106 + Show form controls for a request concerning 'obj', indicating whether
2.107 + action is needed if 'needs_action' is specified as a true value.
2.108 """
2.109
2.110 + page = self.page
2.111 +
2.112 details = self._get_details(obj)
2.113 -
2.114 is_organiser = get_value(details, "ORGANIZER") == self.user
2.115
2.116 if not is_organiser:
2.117 @@ -441,39 +462,37 @@
2.118 if attendee_attr:
2.119 partstat = attendee_attr.get("PARTSTAT")
2.120 if partstat == "ACCEPTED":
2.121 - self.page.p("This request has been accepted.")
2.122 + page.p("This request has been accepted.")
2.123 elif partstat == "DECLINED":
2.124 - self.page.p("This request has been declined.")
2.125 + page.p("This request has been declined.")
2.126 else:
2.127 - self.page.p("This request has not yet been dealt with.")
2.128 + page.p("This request has not yet been dealt with.")
2.129
2.130 if needs_action:
2.131 - self.page.p("An action is required for this request:")
2.132 + page.p("An action is required for this request:")
2.133 else:
2.134 - self.page.p("This request can be updated as follows:")
2.135 + page.p("This request can be updated as follows:")
2.136
2.137 - self.page.form(method="POST")
2.138 - self.page.p()
2.139 + page.p()
2.140
2.141 # Show appropriate options depending on the role of the user.
2.142
2.143 if is_organiser:
2.144 - self.page.input(name="invite", type="submit", value="Invite")
2.145 + page.input(name="invite", type="submit", value="Invite")
2.146 else:
2.147 - self.page.input(name="accept", type="submit", value="Accept")
2.148 - self.page.add(" ")
2.149 - self.page.input(name="decline", type="submit", value="Decline")
2.150 + page.input(name="accept", type="submit", value="Accept")
2.151 + page.add(" ")
2.152 + page.input(name="decline", type="submit", value="Decline")
2.153
2.154 - self.page.add(" ")
2.155 - self.page.input(name="discard", type="submit", value="Discard")
2.156 + page.add(" ")
2.157 + page.input(name="discard", type="submit", value="Discard")
2.158
2.159 # Updated objects need to have details updated upon sending.
2.160
2.161 if not needs_action:
2.162 - self.page.input(name="update", type="hidden", value="true")
2.163 + page.input(name="update", type="hidden", value="true")
2.164
2.165 - self.page.p.close()
2.166 - self.page.form.close()
2.167 + page.p.close()
2.168
2.169 object_labels = {
2.170 "SUMMARY" : "Summary",
2.171 @@ -483,7 +502,7 @@
2.172 "ATTENDEE" : "Attendee",
2.173 }
2.174
2.175 - def show_object_on_page(self, uid, obj):
2.176 + def show_object_on_page(self, uid, obj, needs_action):
2.177
2.178 """
2.179 Show the calendar object with the given 'uid' and representation 'obj'
2.180 @@ -491,6 +510,7 @@
2.181 """
2.182
2.183 page = self.page
2.184 + page.form(method="POST")
2.185
2.186 # Obtain the user's timezone.
2.187
2.188 @@ -501,7 +521,13 @@
2.189
2.190 details = self._get_details(obj)
2.191
2.192 - page.table(cellspacing=5, cellpadding=5)
2.193 + page.table(id="object", cellspacing=5, cellpadding=5)
2.194 + page.thead()
2.195 + page.tr()
2.196 + page.th("Event", class_="mainheading", colspan=2)
2.197 + page.tr.close()
2.198 + page.thead.close()
2.199 + page.tbody()
2.200
2.201 for name in ["SUMMARY", "DTSTART", "DTEND", "ORGANIZER", "ATTENDEE"]:
2.202 page.tr()
2.203 @@ -518,6 +544,16 @@
2.204 page.td(value)
2.205 page.tr.close()
2.206
2.207 + # Handle the summary specially.
2.208 +
2.209 + elif name == "SUMMARY":
2.210 + value = get_value(details, name)
2.211 + page.th(label, class_="objectheading")
2.212 + page.td()
2.213 + page.input(name="summary", type="text", value=value, size=80)
2.214 + page.td.close()
2.215 + page.tr.close()
2.216 +
2.217 # Handle potentially many values.
2.218
2.219 else:
2.220 @@ -543,6 +579,7 @@
2.221 page.td.close()
2.222 page.tr.close()
2.223
2.224 + page.tbody.close()
2.225 page.table.close()
2.226
2.227 dtstart = format_datetime(get_utc_datetime(details, "DTSTART"))
2.228 @@ -578,6 +615,9 @@
2.229 found_details = self._get_details(found_obj)
2.230 page.a(get_value(found_details, "SUMMARY"), href=self.env.new_url(found_uid))
2.231
2.232 + self.show_request_controls(obj, needs_action)
2.233 + page.form.close()
2.234 +
2.235 def show_requests_on_page(self):
2.236
2.237 "Show requests for the current user."
2.238 @@ -671,10 +711,7 @@
2.239 return True
2.240
2.241 self.new_page(title="Event")
2.242 -
2.243 - self.show_object_on_page(uid, obj)
2.244 -
2.245 - self.show_request_form(obj, is_request and not handled)
2.246 + self.show_object_on_page(uid, obj, is_request and not handled)
2.247
2.248 return True
2.249