1.1 --- a/imipweb/resource.py Thu Sep 24 19:40:03 2015 +0200
1.2 +++ b/imipweb/resource.py Thu Sep 24 20:41:58 2015 +0200
1.3 @@ -19,15 +19,16 @@
1.4 this program. If not, see <http://www.gnu.org/licenses/>.
1.5 """
1.6
1.7 -from datetime import datetime
1.8 +from datetime import datetime, timedelta
1.9 from imiptools.client import Client, ClientForObject
1.10 from imiptools.data import get_uri, uri_values
1.11 -from imiptools.dates import get_recurrence_start_point
1.12 +from imiptools.dates import format_datetime, get_recurrence_start_point, to_date
1.13 from imiptools.period import remove_period, remove_affected_period
1.14 from imipweb.env import CGIEnvironment
1.15 import babel.dates
1.16 import imip_store
1.17 import markup
1.18 +import pytz
1.19
1.20 class Resource:
1.21
1.22 @@ -212,4 +213,132 @@
1.23 user = self.env.get_user()
1.24 ClientForObject.__init__(self, None, user and get_uri(user) or None)
1.25
1.26 +class FormUtilities:
1.27 +
1.28 + "Utility methods."
1.29 +
1.30 + def control(self, name, type, value, selected=False, **kw):
1.31 +
1.32 + """
1.33 + Show a control with the given 'name', 'type' and 'value', with
1.34 + 'selected' indicating whether it should be selected (checked or
1.35 + equivalent), and with keyword arguments setting other properties.
1.36 + """
1.37 +
1.38 + page = self.page
1.39 + if selected:
1.40 + page.input(name=name, type=type, value=value, checked=selected, **kw)
1.41 + else:
1.42 + page.input(name=name, type=type, value=value, **kw)
1.43 +
1.44 + def menu(self, name, default, items, class_="", index=None):
1.45 +
1.46 + """
1.47 + Show a select menu having the given 'name', set to the given 'default',
1.48 + providing the given (value, label) 'items', and employing the given CSS
1.49 + 'class_' if specified.
1.50 + """
1.51 +
1.52 + page = self.page
1.53 + values = self.env.get_args().get(name, [default])
1.54 + if index is not None:
1.55 + values = values[index:]
1.56 + values = values and values[0:1] or [default]
1.57 +
1.58 + page.select(name=name, class_=class_)
1.59 + for v, label in items:
1.60 + if v is None:
1.61 + continue
1.62 + if v in values:
1.63 + page.option(label, value=v, selected="selected")
1.64 + else:
1.65 + page.option(label, value=v)
1.66 + page.select.close()
1.67 +
1.68 + def date_controls(self, name, default, index=None, show_tzid=True, read_only=False):
1.69 +
1.70 + """
1.71 + Show date controls for a field with the given 'name' and 'default' form
1.72 + date value.
1.73 +
1.74 + If 'index' is specified, default field values will be overridden by the
1.75 + element from a collection of existing form values with the specified
1.76 + index; otherwise, field values will be overridden by a single form
1.77 + value.
1.78 +
1.79 + If 'show_tzid' is set to a false value, the time zone menu will not be
1.80 + provided.
1.81 +
1.82 + If 'read_only' is set to a true value, the controls will be hidden and
1.83 + labels will be employed instead.
1.84 + """
1.85 +
1.86 + page = self.page
1.87 +
1.88 + # Show dates for up to one week around the current date.
1.89 +
1.90 + dt = default.as_datetime()
1.91 + if not dt:
1.92 + dt = date.today()
1.93 +
1.94 + base = to_date(dt)
1.95 +
1.96 + # Show a date label with a hidden field if read-only.
1.97 +
1.98 + if read_only:
1.99 + self.control("%s-date" % name, "hidden", format_datetime(base))
1.100 + page.span(self.format_date(base, "long"))
1.101 +
1.102 + # Show dates for up to one week around the current date.
1.103 + # NOTE: Support paging to other dates.
1.104 +
1.105 + else:
1.106 + items = []
1.107 + for i in range(-7, 8):
1.108 + d = base + timedelta(i)
1.109 + items.append((format_datetime(d), self.format_date(d, "full")))
1.110 + self.menu("%s-date" % name, format_datetime(base), items, index=index)
1.111 +
1.112 + # Show time details.
1.113 +
1.114 + page.span(class_="time enabled")
1.115 +
1.116 + if read_only:
1.117 + page.span("%s:%s:%s" % (default.get_hour(), default.get_minute(), default.get_second()))
1.118 + self.control("%s-hour" % name, "hidden", default.get_hour())
1.119 + self.control("%s-minute" % name, "hidden", default.get_minute())
1.120 + self.control("%s-second" % name, "hidden", default.get_second())
1.121 + else:
1.122 + self.control("%s-hour" % name, "text", default.get_hour(), maxlength=2, size=2)
1.123 + page.add(":")
1.124 + self.control("%s-minute" % name, "text", default.get_minute(), maxlength=2, size=2)
1.125 + page.add(":")
1.126 + self.control("%s-second" % name, "text", default.get_second(), maxlength=2, size=2)
1.127 +
1.128 + # Show time zone details.
1.129 +
1.130 + if show_tzid:
1.131 + page.add(" ")
1.132 + tzid = default.get_tzid() or self.get_tzid()
1.133 +
1.134 + # Show a label if read-only or a menu otherwise.
1.135 +
1.136 + if read_only:
1.137 + self.control("%s-tzid" % name, "hidden", tzid)
1.138 + page.span(tzid)
1.139 + else:
1.140 + self.timezone_menu("%s-tzid" % name, tzid, index)
1.141 +
1.142 + page.span.close()
1.143 +
1.144 + def timezone_menu(self, name, default, index=None):
1.145 +
1.146 + """
1.147 + Show timezone controls using a menu with the given 'name', set to the
1.148 + given 'default' unless a field of the given 'name' provides a value.
1.149 + """
1.150 +
1.151 + entries = [(tzid, tzid) for tzid in pytz.all_timezones]
1.152 + self.menu(name, default, entries, index=index)
1.153 +
1.154 # vim: tabstop=4 expandtab shiftwidth=4