# HG changeset patch # User Paul Boddie # Date 1418081234 -3600 # Node ID 39f9ea9ec85a9c261ad67691fb692e14314ff311 # Parent f3102e4e82e7d931c7fefaf963cda9659d12f228 Changed the Web interface to show the calendar and pending requests together. Tidied object inspection. diff -r f3102e4e82e7 -r 39f9ea9ec85a imip_manager.py --- a/imip_manager.py Tue Dec 09 00:26:01 2014 +0100 +++ b/imip_manager.py Tue Dec 09 00:27:14 2014 +0100 @@ -65,11 +65,15 @@ class ManagerHandler(Handler): - "A content handler for use by the manager." + """ + A content handler for use by the manager, as opposed to operating within the + mail processing pipeline. + """ - def __init__(self, details, objtype, user, messenger): + def __init__(self, obj, user, messenger): + details, details_attr = obj.values()[0] Handler.__init__(self, details) - self.objtype = objtype + self.obj = obj self.user = user self.messenger = messenger @@ -84,7 +88,7 @@ given 'sender'. """ - node = to_node({self.objtype : [(self.details, {})]}) + node = to_node(self.obj) part = to_part("REPLY", [node]) message = self.messenger.make_message([part], self.organisers, sender=sender) self.messenger.sendmail(self.organisers, message.as_string(), sender=sender) @@ -125,6 +129,8 @@ self.env = CGIEnvironment() user = self.env.get_user() self.user = user and get_uri(user) or None + self.requests = None + self.out = self.env.get_output() self.page = markup.page() self.encoding = "utf-8" @@ -136,6 +142,9 @@ except OSError: self.publisher = None + def _get_uid(self, path_info): + return path_info.lstrip("/").split("/", 1)[0] + def _get_object(self, uid): f = uid and self.store.get_event(self.user, uid) or None @@ -147,8 +156,16 @@ if not obj: return None - objtype = obj.keys()[0] - return obj[objtype][0] + return obj + + def _get_details(self, obj): + details, details_attr = obj.values()[0] + return details + + def _get_requests(self): + if self.requests is None: + self.requests = self.store.get_requests(self.user) + return self.requests # Data management methods. @@ -173,16 +190,107 @@ self.new_page(title="Not Found") self.page.p("No page is provided at the given address.") - def show_requests(self): + # Request logic and page fragment methods. + + def handle_request(self, uid, request): + + "Handle actions involving the given 'uid' and 'request' object." + + # Handle a submitted form. + + args = self.env.get_args() + show_form = False + + accept = args.has_key("accept") + decline = args.has_key("decline") + + if accept or decline: + + handler = ManagerHandler(request, self.user, self.messenger) + + if handler.process_request(accept): + + # Remove the request from the list. + + self.remove_request(uid) + + elif args.has_key("ignore"): + + # Remove the request from the list. + + self.remove_request(uid) + + else: + show_form = True + + return show_form + + def show_request_form(self): + + "Show a form for a request." + + self.page.p("Action to take for this request:") + self.page.form(method="POST") + self.page.p() + self.page.input(name="accept", type="submit", value="Accept") + self.page.add(" ") + self.page.input(name="decline", type="submit", value="Decline") + self.page.add(" ") + self.page.input(name="ignore", type="submit", value="Ignore") + self.page.p.close() + self.page.form.close() + + def show_object_on_page(self, uid, obj): + + """ + Show the calendar object with the given 'uid' and representation 'obj' + on the current page. + """ + + details = self._get_details(obj) + + # Provide a summary of the object. + + self.page.dl() + + for name in ["SUMMARY", "DTSTART", "DTEND", "ORGANIZER", "ATTENDEE"]: + for value in get_values(details, name): + self.page.dt(name) + self.page.dd(value) + + self.page.dl.close() + + dtstart = format_datetime(get_utc_datetime(details, "DTSTART")) + dtend = format_datetime(get_utc_datetime(details, "DTEND")) + + # Indicate whether there are conflicting events. + + freebusy = self.store.get_freebusy(self.user) + + if freebusy: + + # Obtain any time zone details from the suggested event. + + _dtstart, attr = get_item(details, "DTSTART") + tzid = attr.get("TZID") + + # Show any conflicts. + + for t in have_conflict(freebusy, [(dtstart, dtend)], True): + start, end, found_uid = t[:3] + if uid != found_uid: + start = format_datetime(to_timezone(get_datetime(start), tzid)) + end = format_datetime(to_timezone(get_datetime(end), tzid)) + self.page.p("Event conflicts with another from %s to %s." % (start, end)) + + def show_requests_on_page(self): "Show requests for the current user." # NOTE: This list could be more informative, but it is envisaged that # NOTE: the requests would be visited directly anyway. - self.new_page(title="Pending Requests") - - requests = self.store.get_requests(self.user) + requests = self._get_requests() if requests: self.page.p("Pending requests:") @@ -199,93 +307,28 @@ else: self.page.p("There are no pending requests.") - def show_request(self, path_info): + # Full page output methods. - "Show a request using the given 'path_info' for the current user." + def show_object(self, path_info): - uid = path_info.lstrip("/").split("/", 1)[0] - request = self._get_object(uid) + "Show an object request using the given 'path_info' for the current user." - if not request: + uid = self._get_uid(path_info) + obj = self._get_object(uid) + + if not obj: return False - # Handle a submitted form. - - args = self.env.get_args() - show_form = False - - accept = args.has_key("accept") - decline = args.has_key("decline") - - if accept or decline: - - handler = ManagerHandler(request, objtype, self.user, self.messenger) - - if handler.process_request(accept): + self.new_page(title="Event") - # Remove the request from the list. - - self.remove_request(uid) - - elif args.has_key("ignore"): - - # Remove the request from the list. - - self.remove_request(uid) - - else: - show_form = True - - self.new_page(title="Request") - - # Provide a summary of the request. + is_request = uid in self._get_requests() - self.page.p("The following request was received:") - self.page.dl() - - for name in ["SUMMARY", "DTSTART", "DTEND", "ORGANIZER", "ATTENDEE"]: - for value in get_values(request, name): - self.page.dt(name) - self.page.dd(value) - - self.page.dl.close() - - dtstart = format_datetime(get_utc_datetime(request, "DTSTART")) - dtend = format_datetime(get_utc_datetime(request, "DTEND")) - - # Indicate whether there are conflicting events. - - freebusy = self.store.get_freebusy(self.user) + show_form = is_request and self.handle_request(uid, obj) - if freebusy: - - # Obtain any time zone details from the suggested event. - - _dtstart, attr = get_item(request, "DTSTART") - tzid = attr.get("TZID") - - # Show any conflicts. - - for t in have_conflict(freebusy, [(dtstart, dtend)], True): - start, end, found_uid = t[:3] - if uid != found_uid: - start = format_datetime(to_timezone(get_datetime(start), tzid)) - end = format_datetime(to_timezone(get_datetime(end), tzid)) - self.page.p("Event conflicts with another from %s to %s." % (start, end)) - - # Show a form if no action has just been taken. + self.show_object_on_page(uid, obj) if show_form: - self.page.p("Action to take for this request:") - self.page.form(method="POST") - self.page.p() - self.page.input(name="accept", type="submit", value="Accept") - self.page.add(" ") - self.page.input(name="decline", type="submit", value="Decline") - self.page.add(" ") - self.page.input(name="ignore", type="submit", value="Ignore") - self.page.p.close() - self.page.form.close() + self.show_request_form() return True @@ -294,6 +337,7 @@ "Show the calendar for the current user." self.new_page(title="Calendar") + self.show_requests_on_page() freebusy = self.store.get_freebusy(self.user) page = self.page @@ -335,7 +379,8 @@ page.td(class_="event", rowspan=span) obj = self._get_object(uid) if obj: - page.add(get_value(obj, "SUMMARY")) + details = self._get_details(obj) + page.a(get_value(details, "SUMMARY"), href="%s/%s" % (self.env.get_url().rstrip("/"), uid)) page.td.close() else: page.td(class_="empty") @@ -349,12 +394,11 @@ "Select the desired action and show the result." - path_info = self.env.get_path_info().rstrip("/") + path_info = self.env.get_path_info().strip("/") + if not path_info: - self.show_requests() - elif path_info.rsplit("/", 1)[-1] == "calendar": self.show_calendar() - elif self.show_request(path_info): + elif self.show_object(path_info): pass else: self.no_page()