# HG changeset patch # User Paul Boddie # Date 1428174449 -7200 # Node ID 5acbb64fdc5ddd4a8a6f202f95a14ddb939df46b # Parent 4837e47eb5d6729efb9cd50b89e14c0cf2b0931f Moved various definitions around; added a method for checkbox generation. diff -r 4837e47eb5d6 -r 5acbb64fdc5d imipweb/event.py --- a/imipweb/event.py Wed Apr 01 01:31:39 2015 +0200 +++ b/imipweb/event.py Sat Apr 04 21:07:29 2015 +0200 @@ -39,6 +39,25 @@ Resource.__init__(self, resource) self.messenger = messenger or Messenger() + # Various property values and labels. + + property_items = [ + ("SUMMARY", "Summary"), + ("DTSTART", "Start"), + ("DTEND", "End"), + ("ORGANIZER", "Organiser"), + ("ATTENDEE", "Attendee"), + ] + + partstat_items = [ + ("NEEDS-ACTION", "Not confirmed"), + ("ACCEPTED", "Attending"), + ("TENTATIVE", "Tentatively attending"), + ("DECLINED", "Not attending"), + ("DELEGATED", "Delegated"), + (None, "Not indicated"), + ] + # Request logic methods. def handle_request(self, uid, recurrenceid, obj): @@ -460,23 +479,6 @@ page.input(name="ignore", type="submit", value="Do nothing for now") page.p.close() - property_items = [ - ("SUMMARY", "Summary"), - ("DTSTART", "Start"), - ("DTEND", "End"), - ("ORGANIZER", "Organiser"), - ("ATTENDEE", "Attendee"), - ] - - partstat_items = [ - ("NEEDS-ACTION", "Not confirmed"), - ("ACCEPTED", "Attending"), - ("TENTATIVE", "Tentatively attending"), - ("DECLINED", "Not attending"), - ("DELEGATED", "Delegated"), - (None, "Not indicated"), - ] - def show_object_on_page(self, uid, obj, error=None): """ @@ -614,10 +616,7 @@ remove_type = partstat and "checkbox" or "submit" - if value in args.get("remove", []): - page.input(name="remove", type=remove_type, value=value, id="remove-%d" % i, class_="remove", checked="checked") - else: - page.input(name="remove", type=remove_type, value=value, id="remove-%d" % i, class_="remove") + self._control("remove", remove_type, value, value in args.get("remove", []), id="remove-%d" % i, class_="remove") page.label("Remove", for_="remove-%d" % i, class_="remove") page.label("Uninvited", for_="remove-%d" % i, class_="removed") @@ -664,176 +663,6 @@ page.form.close() - def show_object_datetime_controls(self, start, end, index=None): - - """ - Show datetime-related controls if already active or if an object needs - them for the given 'start' to 'end' period. The given 'index' is used to - parameterise individual controls for dynamic manipulation. - """ - - page = self.page - args = self.env.get_args() - sn = self._suffixed_name - ssn = self._simple_suffixed_name - - # Add a dynamic stylesheet to permit the controls to modify the display. - # NOTE: The style details need to be coordinated with the static - # NOTE: stylesheet. - - if index is not None: - page.style(type="text/css") - - # Unlike the rules for object properties, these affect recurrence - # properties. - - page.add("""\ -input#dttimes-enable-%(index)d, -input#dtend-enable-%(index)d, -input#dttimes-enable-%(index)d:not(:checked) ~ .recurrence td.objectvalue .time.enabled, -input#dttimes-enable-%(index)d:checked ~ .recurrence td.objectvalue .time.disabled, -input#dtend-enable-%(index)d:not(:checked) ~ .recurrence td.objectvalue.dtend .dt.enabled, -input#dtend-enable-%(index)d:checked ~ .recurrence td.objectvalue.dtend .dt.disabled { - display: none; -}""" % {"index" : index}) - - page.style.close() - - dtend_control = args.get(ssn("dtend-control", "recur", index), []) - dttimes_control = args.get(ssn("dttimes-control", "recur", index), []) - - dtend_enabled = index is not None and str(index) in dtend_control or index is None and dtend_control - dttimes_enabled = index is not None and str(index) in dttimes_control or index is None and dttimes_control - - initial_load = not args.has_key("editing") - - dtend_enabled = dtend_enabled or initial_load and (isinstance(end, datetime) or start != end - timedelta(1)) - dttimes_enabled = dttimes_enabled or initial_load and (isinstance(start, datetime) or isinstance(end, datetime)) - - if dtend_enabled: - page.input(name=ssn("dtend-control", "recur", index), type="checkbox", - value=(index is not None and str(index) or "enable"), id=sn("dtend-enable", index), checked="checked") - else: - page.input(name=ssn("dtend-control", "recur", index), type="checkbox", - value=(index is not None and str(index) or "enable"), id=sn("dtend-enable", index)) - - if dttimes_enabled: - page.input(name=ssn("dttimes-control", "recur", index), type="checkbox", - value=(index is not None and str(index) or "enable"), id=sn("dttimes-enable", index), checked="checked") - else: - page.input(name=ssn("dttimes-control", "recur", index), type="checkbox", - value=(index is not None and str(index) or "enable"), id=sn("dttimes-enable", index)) - - def show_datetime_controls(self, obj, dt, attr, show_start): - - """ - Show datetime details from the given 'obj' for the datetime 'dt' and - attributes 'attr', showing start details if 'show_start' is set - to a true value. Details will appear as controls for organisers and - labels for attendees. - """ - - page = self.page - is_organiser = get_uri(obj.get_value("ORGANIZER")) == self.user - - # Change end dates to refer to the actual dates, not the iCalendar - # "next day" dates. - - if not show_start and not isinstance(dt, datetime): - dt -= timedelta(1) - - # Show controls for editing as organiser. - - if is_organiser: - page.td(class_="objectvalue dt%s" % (show_start and "start" or "end")) - - if show_start: - page.div(class_="dt enabled") - self._show_date_controls("dtstart", dt, attr.get("TZID")) - page.br() - page.label("Specify times", for_="dttimes-enable", class_="time disabled enable") - page.label("Specify dates only", for_="dttimes-enable", class_="time enabled disable") - page.div.close() - - else: - page.div(class_="dt disabled") - page.label("Specify end date", for_="dtend-enable", class_="enable") - page.div.close() - page.div(class_="dt enabled") - self._show_date_controls("dtend", dt, attr.get("TZID")) - page.br() - page.label("End on same day", for_="dtend-enable", class_="disable") - page.div.close() - - page.td.close() - - # Show a label as attendee. - - else: - page.td(self.format_datetime(dt, "full")) - - def show_recurrence_controls(self, obj, index, start, end, origin, recurrenceid, recurrenceids, show_start): - - """ - Show datetime details from the given 'obj' for the recurrence having the - given 'index', with the recurrence period described by the datetimes - 'start' and 'end', indicating the 'origin' of the period from the event - details, employing any 'recurrenceid' and 'recurrenceids' for the object - to configure the displayed information. - - If 'show_start' is set to a true value, the start details will be shown; - otherwise, the end details will be shown. - """ - - page = self.page - sn = self._suffixed_name - ssn = self._simple_suffixed_name - - is_organiser = get_uri(obj.get_value("ORGANIZER")) == self.user - - # Change end dates to refer to the actual dates, not the iCalendar - # "next day" dates. - - if not isinstance(end, datetime): - end -= timedelta(1) - - start_utc = format_datetime(to_timezone(start, "UTC")) - replaced = recurrenceids and start_utc in recurrenceids and "replaced" or "" - css = " ".join([ - replaced, - recurrenceid and start_utc == recurrenceid and "affected" or "" - ]) - - # Show controls for editing as organiser. - - if is_organiser and not replaced and origin != "RRULE": - page.td(class_="objectvalue dt%s" % (show_start and "start" or "end")) - - if show_start: - page.div(class_="dt enabled") - self._show_date_controls(ssn("dtstart", "recur", index), start, index=index) - page.br() - page.label("Specify times", for_=sn("dttimes-enable", index), class_="time disabled enable") - page.label("Specify dates only", for_=sn("dttimes-enable", index), class_="time enabled disable") - page.div.close() - - else: - page.div(class_="dt disabled") - page.label("Specify end date", for_=sn("dtend-enable", index), class_="enable") - page.div.close() - page.div(class_="dt enabled") - self._show_date_controls(ssn("dtend", "recur", index), end, index=index, show_tzid=False) - page.br() - page.label("End on same day", for_=sn("dtend-enable", index), class_="disable") - page.div.close() - - page.td.close() - - # Show label as attendee. - - else: - page.td(self.format_datetime(show_start and start or end, "long"), class_=css) - def show_recurrences(self, obj): "Show recurrences for the object having the given representation 'obj'." @@ -992,6 +821,176 @@ page.tbody.close() page.table.close() + # Generation of controls within page fragments. + + def show_object_datetime_controls(self, start, end, index=None): + + """ + Show datetime-related controls if already active or if an object needs + them for the given 'start' to 'end' period. The given 'index' is used to + parameterise individual controls for dynamic manipulation. + """ + + page = self.page + args = self.env.get_args() + sn = self._suffixed_name + ssn = self._simple_suffixed_name + + # Add a dynamic stylesheet to permit the controls to modify the display. + # NOTE: The style details need to be coordinated with the static + # NOTE: stylesheet. + + if index is not None: + page.style(type="text/css") + + # Unlike the rules for object properties, these affect recurrence + # properties. + + page.add("""\ +input#dttimes-enable-%(index)d, +input#dtend-enable-%(index)d, +input#dttimes-enable-%(index)d:not(:checked) ~ .recurrence td.objectvalue .time.enabled, +input#dttimes-enable-%(index)d:checked ~ .recurrence td.objectvalue .time.disabled, +input#dtend-enable-%(index)d:not(:checked) ~ .recurrence td.objectvalue.dtend .dt.enabled, +input#dtend-enable-%(index)d:checked ~ .recurrence td.objectvalue.dtend .dt.disabled { + display: none; +}""" % {"index" : index}) + + page.style.close() + + dtend_control = args.get(ssn("dtend-control", "recur", index), []) + dttimes_control = args.get(ssn("dttimes-control", "recur", index), []) + + dtend_enabled = index is not None and str(index) in dtend_control or index is None and dtend_control + dttimes_enabled = index is not None and str(index) in dttimes_control or index is None and dttimes_control + + initial_load = not args.has_key("editing") + + dtend_enabled = dtend_enabled or initial_load and (isinstance(end, datetime) or start != end - timedelta(1)) + dttimes_enabled = dttimes_enabled or initial_load and (isinstance(start, datetime) or isinstance(end, datetime)) + + self._control( + ssn("dtend-control", "recur", index), "checkbox", + index is not None and str(index) or "enable", dtend_enabled, + id=sn("dtend-enable", index) + ) + + self._control( + ssn("dttimes-control", "recur", index), "checkbox", + index is not None and str(index) or "enable", dttimes_enabled, + id=sn("dttimes-enable", index) + ) + + def show_datetime_controls(self, obj, dt, attr, show_start): + + """ + Show datetime details from the given 'obj' for the datetime 'dt' and + attributes 'attr', showing start details if 'show_start' is set + to a true value. Details will appear as controls for organisers and + labels for attendees. + """ + + page = self.page + is_organiser = get_uri(obj.get_value("ORGANIZER")) == self.user + + # Change end dates to refer to the actual dates, not the iCalendar + # "next day" dates. + + if not show_start and not isinstance(dt, datetime): + dt -= timedelta(1) + + # Show controls for editing as organiser. + + if is_organiser: + page.td(class_="objectvalue dt%s" % (show_start and "start" or "end")) + + if show_start: + page.div(class_="dt enabled") + self._show_date_controls("dtstart", dt, attr.get("TZID")) + page.br() + page.label("Specify times", for_="dttimes-enable", class_="time disabled enable") + page.label("Specify dates only", for_="dttimes-enable", class_="time enabled disable") + page.div.close() + + else: + page.div(class_="dt disabled") + page.label("Specify end date", for_="dtend-enable", class_="enable") + page.div.close() + page.div(class_="dt enabled") + self._show_date_controls("dtend", dt, attr.get("TZID")) + page.br() + page.label("End on same day", for_="dtend-enable", class_="disable") + page.div.close() + + page.td.close() + + # Show a label as attendee. + + else: + page.td(self.format_datetime(dt, "full")) + + def show_recurrence_controls(self, obj, index, start, end, origin, recurrenceid, recurrenceids, show_start): + + """ + Show datetime details from the given 'obj' for the recurrence having the + given 'index', with the recurrence period described by the datetimes + 'start' and 'end', indicating the 'origin' of the period from the event + details, employing any 'recurrenceid' and 'recurrenceids' for the object + to configure the displayed information. + + If 'show_start' is set to a true value, the start details will be shown; + otherwise, the end details will be shown. + """ + + page = self.page + sn = self._suffixed_name + ssn = self._simple_suffixed_name + + is_organiser = get_uri(obj.get_value("ORGANIZER")) == self.user + + # Change end dates to refer to the actual dates, not the iCalendar + # "next day" dates. + + if not isinstance(end, datetime): + end -= timedelta(1) + + start_utc = format_datetime(to_timezone(start, "UTC")) + replaced = recurrenceids and start_utc in recurrenceids and "replaced" or "" + css = " ".join([ + replaced, + recurrenceid and start_utc == recurrenceid and "affected" or "" + ]) + + # Show controls for editing as organiser. + + if is_organiser and not replaced and origin != "RRULE": + page.td(class_="objectvalue dt%s" % (show_start and "start" or "end")) + + if show_start: + page.div(class_="dt enabled") + self._show_date_controls(ssn("dtstart", "recur", index), start, index=index) + page.br() + page.label("Specify times", for_=sn("dttimes-enable", index), class_="time disabled enable") + page.label("Specify dates only", for_=sn("dttimes-enable", index), class_="time enabled disable") + page.div.close() + + else: + page.div(class_="dt disabled") + page.label("Specify end date", for_=sn("dtend-enable", index), class_="enable") + page.div.close() + page.div(class_="dt enabled") + self._show_date_controls(ssn("dtend", "recur", index), end, index=index, show_tzid=False) + page.br() + page.label("End on same day", for_=sn("dtend-enable", index), class_="disable") + page.div.close() + + page.td.close() + + # Show label as attendee. + + else: + page.td(self.format_datetime(show_start and start or end, "long"), class_=css) + # Full page output methods. def show(self, path_info): @@ -1016,6 +1015,20 @@ # Utility methods. + def _control(self, name, type, value, selected, **kw): + + """ + Show a control with the given 'name', 'type' and 'value', with + 'selected' indicating whether it should be selected (checked or + equivalent), and with keyword arguments setting other properties. + """ + + page = self.page + if selected: + page.input(name=name, type=type, value=value, checked=selected, **kw) + else: + page.input(name=name, type=type, value=value, **kw) + def _show_menu(self, name, default, items, class_="", index=None): """