1.1 --- a/imipweb/resource.py Thu Sep 24 20:41:58 2015 +0200
1.2 +++ b/imipweb/resource.py Thu Sep 24 23:41:47 2015 +0200
1.3 @@ -24,6 +24,7 @@
1.4 from imiptools.data import get_uri, uri_values
1.5 from imiptools.dates import format_datetime, get_recurrence_start_point, to_date
1.6 from imiptools.period import remove_period, remove_affected_period
1.7 +from imipweb.data import event_period_from_period, form_period_from_period, FormDate
1.8 from imipweb.env import CGIEnvironment
1.9 import babel.dates
1.10 import imip_store
1.11 @@ -215,7 +216,7 @@
1.12
1.13 class FormUtilities:
1.14
1.15 - "Utility methods."
1.16 + "Utility methods resource mix-in."
1.17
1.18 def control(self, name, type, value, selected=False, **kw):
1.19
1.20 @@ -341,4 +342,227 @@
1.21 entries = [(tzid, tzid) for tzid in pytz.all_timezones]
1.22 self.menu(name, default, entries, index=index)
1.23
1.24 +class DateTimeFormUtilities:
1.25 +
1.26 + "Date/time control methods resource mix-in."
1.27 +
1.28 + def show_object_datetime_controls(self, period, index=None):
1.29 +
1.30 + """
1.31 + Show datetime-related controls if already active or if an object needs
1.32 + them for the given 'period'. The given 'index' is used to parameterise
1.33 + individual controls for dynamic manipulation.
1.34 + """
1.35 +
1.36 + p = form_period_from_period(period)
1.37 +
1.38 + page = self.page
1.39 + args = self.env.get_args()
1.40 + _id = self.element_identifier
1.41 + _name = self.element_name
1.42 + _enable = self.element_enable
1.43 +
1.44 + # Add a dynamic stylesheet to permit the controls to modify the display.
1.45 + # NOTE: The style details need to be coordinated with the static
1.46 + # NOTE: stylesheet.
1.47 +
1.48 + if index is not None:
1.49 + page.style(type="text/css")
1.50 +
1.51 + # Unlike the rules for object properties, these affect recurrence
1.52 + # properties.
1.53 +
1.54 + page.add("""\
1.55 +input#dttimes-enable-%(index)d,
1.56 +input#dtend-enable-%(index)d,
1.57 +input#dttimes-enable-%(index)d:not(:checked) ~ .recurrence td.objectvalue .time.enabled,
1.58 +input#dttimes-enable-%(index)d:checked ~ .recurrence td.objectvalue .time.disabled,
1.59 +input#dtend-enable-%(index)d:not(:checked) ~ .recurrence td.objectvalue.dtend .dt.enabled,
1.60 +input#dtend-enable-%(index)d:checked ~ .recurrence td.objectvalue.dtend .dt.disabled {
1.61 + display: none;
1.62 +}""" % {"index" : index})
1.63 +
1.64 + page.style.close()
1.65 +
1.66 + self.control(
1.67 + _name("dtend-control", "recur", index), "checkbox",
1.68 + _enable(index), p.end_enabled,
1.69 + id=_id("dtend-enable", index)
1.70 + )
1.71 +
1.72 + self.control(
1.73 + _name("dttimes-control", "recur", index), "checkbox",
1.74 + _enable(index), p.times_enabled,
1.75 + id=_id("dttimes-enable", index)
1.76 + )
1.77 +
1.78 + def show_datetime_controls(self, formdate, show_start):
1.79 +
1.80 + """
1.81 + Show datetime details from the current object for the 'formdate',
1.82 + showing start details if 'show_start' is set to a true value. Details
1.83 + will appear as controls for organisers and labels for attendees.
1.84 + """
1.85 +
1.86 + page = self.page
1.87 +
1.88 + # Show controls for editing as organiser.
1.89 +
1.90 + if self.is_organiser():
1.91 + page.td(class_="objectvalue dt%s" % (show_start and "start" or "end"))
1.92 +
1.93 + if show_start:
1.94 + page.div(class_="dt enabled")
1.95 + self.date_controls("dtstart", formdate)
1.96 + page.br()
1.97 + page.label("Specify times", for_="dttimes-enable", class_="time disabled enable")
1.98 + page.label("Specify dates only", for_="dttimes-enable", class_="time enabled disable")
1.99 + page.div.close()
1.100 +
1.101 + else:
1.102 + page.div(class_="dt disabled")
1.103 + page.label("Specify end date", for_="dtend-enable", class_="enable")
1.104 + page.div.close()
1.105 + page.div(class_="dt enabled")
1.106 + self.date_controls("dtend", formdate)
1.107 + page.br()
1.108 + page.label("End on same day", for_="dtend-enable", class_="disable")
1.109 + page.div.close()
1.110 +
1.111 + page.td.close()
1.112 +
1.113 + # Show a label as attendee.
1.114 +
1.115 + else:
1.116 + dt = formdate.as_datetime()
1.117 + if dt:
1.118 + page.td(self.format_datetime(dt, "full"))
1.119 + else:
1.120 + page.td("(Unrecognised date)")
1.121 +
1.122 + def show_recurrence_controls(self, index, period, recurrenceid, recurrenceids, show_start):
1.123 +
1.124 + """
1.125 + Show datetime details from the current object for the recurrence having
1.126 + the given 'index', with the recurrence period described by 'period',
1.127 + indicating a start, end and origin of the period from the event details,
1.128 + employing any 'recurrenceid' and 'recurrenceids' for the object to
1.129 + configure the displayed information.
1.130 +
1.131 + If 'show_start' is set to a true value, the start details will be shown;
1.132 + otherwise, the end details will be shown.
1.133 + """
1.134 +
1.135 + page = self.page
1.136 + _id = self.element_identifier
1.137 + _name = self.element_name
1.138 +
1.139 + p = event_period_from_period(period)
1.140 + replaced = not recurrenceid and p.is_replaced(recurrenceids)
1.141 +
1.142 + # Show controls for editing as organiser.
1.143 +
1.144 + if self.is_organiser() and not replaced:
1.145 + page.td(class_="objectvalue dt%s" % (show_start and "start" or "end"))
1.146 +
1.147 + read_only = period.origin == "RRULE"
1.148 +
1.149 + if show_start:
1.150 + page.div(class_="dt enabled")
1.151 + self.date_controls(_name("dtstart", "recur", index), p.get_form_start(), index=index, read_only=read_only)
1.152 + if not read_only:
1.153 + page.br()
1.154 + page.label("Specify times", for_=_id("dttimes-enable", index), class_="time disabled enable")
1.155 + page.label("Specify dates only", for_=_id("dttimes-enable", index), class_="time enabled disable")
1.156 + page.div.close()
1.157 +
1.158 + # Put the origin somewhere.
1.159 +
1.160 + self.control("recur-origin", "hidden", p.origin or "")
1.161 +
1.162 + else:
1.163 + page.div(class_="dt disabled")
1.164 + if not read_only:
1.165 + page.label("Specify end date", for_=_id("dtend-enable", index), class_="enable")
1.166 + page.div.close()
1.167 + page.div(class_="dt enabled")
1.168 + self.date_controls(_name("dtend", "recur", index), p.get_form_end(), index=index, show_tzid=False, read_only=read_only)
1.169 + if not read_only:
1.170 + page.br()
1.171 + page.label("End on same day", for_=_id("dtend-enable", index), class_="disable")
1.172 + page.div.close()
1.173 +
1.174 + page.td.close()
1.175 +
1.176 + # Show label as attendee.
1.177 +
1.178 + else:
1.179 + self.show_recurrence_label(p, recurrenceid, recurrenceids, show_start)
1.180 +
1.181 + def show_recurrence_label(self, period, recurrenceid, recurrenceids, show_start):
1.182 +
1.183 + """
1.184 + Show datetime details for the given 'period', employing any
1.185 + 'recurrenceid' and 'recurrenceids' for the object to configure the
1.186 + displayed information.
1.187 +
1.188 + If 'show_start' is set to a true value, the start details will be shown;
1.189 + otherwise, the end details will be shown.
1.190 + """
1.191 +
1.192 + page = self.page
1.193 +
1.194 + p = event_period_from_period(period)
1.195 + replaced = not recurrenceid and p.is_replaced(recurrenceids)
1.196 +
1.197 + css = " ".join([
1.198 + replaced and "replaced" or "",
1.199 + p.is_affected(recurrenceid) and "affected" or ""
1.200 + ])
1.201 +
1.202 + formdate = show_start and p.get_form_start() or p.get_form_end()
1.203 + dt = formdate.as_datetime()
1.204 + if dt:
1.205 + page.td(self.format_datetime(dt, "long"), class_=css)
1.206 + else:
1.207 + page.td("(Unrecognised date)")
1.208 +
1.209 + def get_date_control_values(self, name, multiple=False, tzid_name=None):
1.210 +
1.211 + """
1.212 + Return a dictionary containing date, time and tzid entries for fields
1.213 + starting with 'name'. If 'multiple' is set to a true value, many
1.214 + dictionaries will be returned corresponding to a collection of
1.215 + datetimes. If 'tzid_name' is specified, the time zone information will
1.216 + be acquired from a field starting with 'tzid_name' instead of 'name'.
1.217 + """
1.218 +
1.219 + args = self.env.get_args()
1.220 +
1.221 + dates = args.get("%s-date" % name, [])
1.222 + hours = args.get("%s-hour" % name, [])
1.223 + minutes = args.get("%s-minute" % name, [])
1.224 + seconds = args.get("%s-second" % name, [])
1.225 + tzids = args.get("%s-tzid" % (tzid_name or name), [])
1.226 +
1.227 + # Handle absent values by employing None values.
1.228 +
1.229 + field_values = map(None, dates, hours, minutes, seconds, tzids)
1.230 +
1.231 + if not field_values and not multiple:
1.232 + all_values = FormDate()
1.233 + else:
1.234 + all_values = []
1.235 + for date, hour, minute, second, tzid in field_values:
1.236 + value = FormDate(date, hour, minute, second, tzid or self.get_tzid())
1.237 +
1.238 + # Return a single value or append to a collection of all values.
1.239 +
1.240 + if not multiple:
1.241 + return value
1.242 + else:
1.243 + all_values.append(value)
1.244 +
1.245 + return all_values
1.246 +
1.247 # vim: tabstop=4 expandtab shiftwidth=4