# HG changeset patch # User Paul Boddie # Date 1423489041 -3600 # Node ID 8d0c013ef5277eb38d58bbe39c9febaec0c7cb00 # Parent b96e527e13d4f88c7a4c74b07305bf11b3a66b35 Added support for switching between date-only and date-plus-time event periods. diff -r b96e527e13d4 -r 8d0c013ef527 htdocs/styles.css --- a/htdocs/styles.css Sun Feb 08 22:52:37 2015 +0100 +++ b/htdocs/styles.css Mon Feb 09 14:37:21 2015 +0100 @@ -141,24 +141,36 @@ display: block; } -/* Hiding/showing end datetimes. */ +/* Hiding/showing end datetimes and start/end times. */ +input#dttimes-disable, +input#dttimes-enable, input#dtend-disable, input#dtend-enable, -input#dtend-enable:not(:checked) ~ .object td.objectvalue.dtend .enabled, -input#dtend-enable:checked ~ .object td.objectvalue.dtend .disabled { +input#dttimes-disable:checked ~ .object td.objectvalue .time.enabled, +input#dttimes-enable:checked ~ .object td.objectvalue .time.disabled, +input#dtend-disable:checked ~ .object td.objectvalue.dtend .dt.enabled, +input#dtend-enable:checked ~ .object td.objectvalue.dtend .dt.disabled { display: none; } /* Style the labels. */ -div.enabled label.disable { +.dt.disabled label, +.dt.enabled label, +label.hidebusy, +label.showdays { + color: #009; + text-decoration: underline; +} + +.dt.enabled label { display: block; margin-top: 0.25em; } -label.enable, -label.disable { +label.hidebusy, +label.showdays { padding-left: 0.25em; } diff -r b96e527e13d4 -r 8d0c013ef527 imip_manager.py --- a/imip_manager.py Sun Feb 08 22:52:37 2015 +0100 +++ b/imip_manager.py Mon Feb 09 14:37:21 2015 +0100 @@ -512,17 +512,20 @@ update = False if is_organiser: - t = self.handle_date_controls("dtstart") + dtend_enabled = args.get("dtend-control", [None])[0] == "enable" + dttimes_enabled = args.get("dttimes-control", [None])[0] == "enable" + + t = self.handle_date_controls("dtstart", dttimes_enabled) if t: dtstart, attr = t - update = self.set_datetime_in_object(dtstart, attr["TZID"], "DTSTART", obj) or update + update = self.set_datetime_in_object(dtstart, attr.get("TZID"), "DTSTART", obj) or update else: return ["dtstart"] # Handle specified end datetimes. - if args.get("dtend-control", [None])[0] == "enable": - t = self.handle_date_controls("dtend") + if dtend_enabled: + t = self.handle_date_controls("dtend", dttimes_enabled) if t: dtend, attr = t @@ -530,7 +533,7 @@ if not isinstance(dtend, datetime): dtend += timedelta(1) - update = self.set_datetime_in_object(dtend, attr["TZID"], "DTEND", obj) or update + update = self.set_datetime_in_object(dtend, attr.get("TZID"), "DTEND", obj) or update else: return ["dtend"] @@ -541,7 +544,7 @@ dtend = dtstart + timedelta(1) if isinstance(dtstart, datetime): dtend = get_start_of_day(dtend, attr["TZID"]) - update = self.set_datetime_in_object(dtend, attr["TZID"], "DTEND", obj) or update + update = self.set_datetime_in_object(dtend, attr.get("TZID"), "DTEND", obj) or update if dtstart >= dtend: return ["dtstart", "dtend"] @@ -585,7 +588,7 @@ return None - def handle_date_controls(self, name): + def handle_date_controls(self, name, with_time=True): """ Handle date control information for fields starting with 'name', @@ -594,19 +597,24 @@ """ args = self.env.get_args() - tzid = self.get_tzid() if args.has_key("%s-date" % name): date = args["%s-date" % name][0] - hour = args.get("%s-hour" % name, [None])[0] - minute = args.get("%s-minute" % name, [None])[0] - second = args.get("%s-second" % name, [None])[0] - tzid = args.get("%s-tzid" % name, [tzid])[0] + + if with_time: + hour = args.get("%s-hour" % name, [None])[0] + minute = args.get("%s-minute" % name, [None])[0] + second = args.get("%s-second" % name, [None])[0] + tzid = args.get("%s-tzid" % name, [self.get_tzid()])[0] - time = (hour or minute or second) and "T%s%s%s" % (hour, minute, second) or "" - value = "%s%s" % (date, time) - attr = {"TZID" : tzid} - dt = get_datetime(value, attr) + time = (hour or minute or second) and "T%s%s%s" % (hour, minute, second) or "" + value = "%s%s" % (date, time) + attr = {"TZID" : tzid, "VALUE" : "DATE-TIME"} + dt = get_datetime(value, attr) + else: + attr = {"VALUE" : "DATE"} + dt = get_datetime(date) + if dt: return dt, attr @@ -707,17 +715,18 @@ # Provide controls to change the displayed object. args = self.env.get_args() + dtend_control = args.get("dtend-control", [None])[0] + dttimes_control = args.get("dttimes-control", [None])[0] + with_time = dttimes_control == "enable" - t = self.handle_date_controls("dtstart") + t = self.handle_date_controls("dtstart", with_time) if t: dtstart, dtstart_attr = t else: dtstart, dtstart_attr = obj.get_datetime_item("DTSTART") - dtend_control = args.get("dtend-control", [None])[0] - if dtend_control == "enable": - t = self.handle_date_controls("dtend") + t = self.handle_date_controls("dtend", with_time) if t: dtend, dtend_attr = t else: @@ -736,15 +745,23 @@ # Show the end datetime controls if already active or if an object needs # them. - dtend_control = dtend_control or (isinstance(dtend, datetime) or dtstart != dtend) and "enable" or None + dtend_enabled = dtend_control == "enable" or isinstance(dtend, datetime) or dtstart != dtend + dttimes_enabled = dttimes_control == "enable" or isinstance(dtstart, datetime) or isinstance(dtend, datetime) - if dtend_control == "enable": + if dtend_enabled: page.input(name="dtend-control", type="radio", value="enable", id="dtend-enable", checked="checked") page.input(name="dtend-control", type="radio", value="disable", id="dtend-disable") else: page.input(name="dtend-control", type="radio", value="enable", id="dtend-enable") page.input(name="dtend-control", type="radio", value="disable", id="dtend-disable", checked="checked") + if dttimes_enabled: + page.input(name="dttimes-control", type="radio", value="enable", id="dttimes-enable", checked="checked") + page.input(name="dttimes-control", type="radio", value="disable", id="dttimes-disable") + else: + page.input(name="dttimes-control", type="radio", value="enable", id="dttimes-enable") + page.input(name="dttimes-control", type="radio", value="disable", id="dttimes-disable", checked="checked") + # Provide a summary of the object. page.table(class_="object", cellspacing=5, cellpadding=5) @@ -779,25 +796,32 @@ else: dt, attr, event_tzid = dtend or dtstart, dtend_attr or dtstart_attr, (dtend_attr or dtstart_attr).get("TZID", tzid) - strvalue = self.format_datetime(dt, "full") - value = format_datetime(dt) + # Show controls for editing as organiser. if is_organiser: + value = format_datetime(dt) + page.td(class_="objectvalue %s" % field) if name == "DTEND": - page.div(class_="disabled") + page.div(class_="dt disabled") page.label("Specify end date", for_="dtend-enable", class_="enable") page.div.close() - page.div(class_="enabled") + page.div(class_="dt enabled") self._show_date_controls(field, value, attr, tzid) - if name == "DTEND": + if name == "DTSTART": + page.label("Specify times", for_="dttimes-enable", class_="time disabled enable") + page.label("Specify dates only", for_="dttimes-disable", class_="time enabled disable") + elif name == "DTEND": page.label("End on same day", for_="dtend-disable", class_="disable") page.div.close() page.td.close() + + # Show a label as attendee. + else: - page.td(strvalue) + page.td(self.format_datetime(dt, "full")) page.tr.close() @@ -1478,21 +1502,23 @@ # Show time details. - if isinstance(dt, datetime): - hour = args.get("%s-hour" % name, "%02d" % dt.hour) - minute = args.get("%s-minute" % name, "%02d" % dt.minute) - second = args.get("%s-second" % name, "%02d" % dt.second) - page.add(" ") - page.input(name="%s-hour" % name, type="text", value=hour, maxlength=2, size=2) - page.add(":") - page.input(name="%s-minute" % name, type="text", value=minute, maxlength=2, size=2) - page.add(":") - page.input(name="%s-second" % name, type="text", value=second, maxlength=2, size=2) - page.add(" ") - self._show_menu("%s-tzid" % name, event_tzid, - [(event_tzid, event_tzid)] + ( - event_tzid != tzid and [(tzid, tzid)] or [] - )) + dt_time = isinstance(dt, datetime) and dt or None + hour = args.get("%s-hour" % name, "%02d" % (dt_time and dt_time.hour or 0)) + minute = args.get("%s-minute" % name, "%02d" % (dt_time and dt_time.minute or 0)) + second = args.get("%s-second" % name, "%02d" % (dt_time and dt_time.second or 0)) + + page.span(class_="time enabled") + page.input(name="%s-hour" % name, type="text", value=hour, maxlength=2, size=2) + page.add(":") + page.input(name="%s-minute" % name, type="text", value=minute, maxlength=2, size=2) + page.add(":") + page.input(name="%s-second" % name, type="text", value=second, maxlength=2, size=2) + page.add(" ") + self._show_menu("%s-tzid" % name, event_tzid, + [(event_tzid, event_tzid)] + ( + event_tzid != tzid and [(tzid, tzid)] or [] + )) + page.span.close() # Incoming HTTP request direction. diff -r b96e527e13d4 -r 8d0c013ef527 imiptools/dates.py --- a/imiptools/dates.py Sun Feb 08 22:52:37 2015 +0100 +++ b/imiptools/dates.py Mon Feb 09 14:37:21 2015 +0100 @@ -115,14 +115,19 @@ else: return None -def get_datetime_item(dt, tzid): +def get_datetime_item(dt, tzid=None): "Return an iCalendar-compatible string and attributes for 'dt' and 'tzid'." if not dt: return None, None value = format_datetime(dt) - attr = isinstance(dt, datetime) and {"TZID" : tzid, "VALUE" : "DATE-TIME"} or {"VALUE" : "DATE"} + if isinstance(dt, datetime): + attr = {"VALUE" : "DATE-TIME"} + if tzid: + attr["TZID"] = tzid + else: + attr = {"VALUE" : "DATE"} return value, attr def get_datetime(value, attr=None):