paul@10 | 1 | # -*- coding: iso-8859-1 -*- |
paul@10 | 2 | """ |
paul@10 | 3 | MoinMoin - EventAggregatorSummary Action |
paul@10 | 4 | |
paul@10 | 5 | @copyright: 2008, 2009 by Paul Boddie <paul@boddie.org.uk> |
paul@10 | 6 | @copyright: 2000-2004 Juergen Hermann <jh@web.de>, |
paul@24 | 7 | 2003-2008 MoinMoin:ThomasWaldmann, |
paul@24 | 8 | 2004-2006 MoinMoin:AlexanderSchremmer, |
paul@19 | 9 | 2007 MoinMoin:ReimarBauer. |
paul@10 | 10 | @license: GNU GPL (v2 or later), see COPYING.txt for details. |
paul@10 | 11 | """ |
paul@10 | 12 | |
paul@19 | 13 | from MoinMoin.action import ActionBase |
paul@10 | 14 | from MoinMoin import config |
paul@24 | 15 | from MoinMoin.Page import Page |
paul@27 | 16 | import MoinMoin.util # for MoinMoin 1.5.x |
paul@10 | 17 | import EventAggregatorSupport |
paul@10 | 18 | |
paul@10 | 19 | Dependencies = ['pages'] |
paul@10 | 20 | |
paul@19 | 21 | # Action class and supporting functions. |
paul@19 | 22 | |
paul@19 | 23 | class EventAggregatorSummary(ActionBase): |
paul@19 | 24 | |
paul@19 | 25 | "A summary dialogue requesting various parameters." |
paul@19 | 26 | |
paul@19 | 27 | def get_form_html(self, buttons_html): |
paul@19 | 28 | _ = self._ |
paul@19 | 29 | request = self.request |
paul@19 | 30 | |
paul@19 | 31 | category_list = [] |
paul@19 | 32 | |
paul@19 | 33 | for category_name, category_pagename in \ |
paul@19 | 34 | EventAggregatorSupport.getCategoryMapping( |
paul@19 | 35 | EventAggregatorSupport.getCategories(request), |
paul@19 | 36 | request): |
paul@19 | 37 | |
paul@19 | 38 | category_list.append('<option value="%s">%s</option>' % (category_pagename, category_name)) |
paul@19 | 39 | |
paul@23 | 40 | month_list = [] |
paul@23 | 41 | month_list.append('<option value=""></option>') |
paul@23 | 42 | |
paul@23 | 43 | for month in range(1, 13): |
paul@23 | 44 | month_label = _(EventAggregatorSupport.getMonthLabel(month)) |
paul@23 | 45 | month_list.append('<option value="%02d">%s</option>' % (month, month_label)) |
paul@23 | 46 | |
paul@23 | 47 | year_label = [] |
paul@23 | 48 | |
paul@19 | 49 | d = { |
paul@19 | 50 | "buttons_html" : buttons_html, |
paul@19 | 51 | "category_label" : _("Categories"), |
paul@19 | 52 | "category_list" : "\n".join(category_list), |
paul@23 | 53 | "month_list" : "\n".join(month_list), |
paul@19 | 54 | "start_label" : _("Start year and month"), |
paul@23 | 55 | "start_year_default" : "", |
paul@19 | 56 | "end_label" : _("End year and month"), |
paul@23 | 57 | "end_year_default" : "", |
paul@19 | 58 | } |
paul@10 | 59 | |
paul@19 | 60 | return ''' |
paul@19 | 61 | <table> |
paul@19 | 62 | <tr> |
paul@19 | 63 | <td class="label"><label>%(category_label)s</label></td> |
paul@19 | 64 | <td class="content"> |
paul@19 | 65 | <select multiple="multiple" name="category"> |
paul@19 | 66 | %(category_list)s |
paul@19 | 67 | </select> |
paul@19 | 68 | </td> |
paul@19 | 69 | </tr> |
paul@19 | 70 | <tr> |
paul@19 | 71 | <td class="label"><label>%(start_label)s</label></td> |
paul@22 | 72 | <td> |
paul@23 | 73 | <select name="start-month"> |
paul@23 | 74 | %(month_list)s |
paul@23 | 75 | </select> |
paul@23 | 76 | <input name="start-year" type="text" value="%(start_year_default)s" size="4" /> |
paul@19 | 77 | </td> |
paul@19 | 78 | </tr> |
paul@19 | 79 | <tr> |
paul@19 | 80 | <td class="label"><label>%(end_label)s</label></td> |
paul@22 | 81 | <td> |
paul@23 | 82 | <select name="end-month"> |
paul@23 | 83 | %(month_list)s |
paul@23 | 84 | </select> |
paul@23 | 85 | <input name="end-year" type="text" value="%(end_year_default)s" size="4" /> |
paul@19 | 86 | </td> |
paul@19 | 87 | </tr> |
paul@19 | 88 | <tr> |
paul@19 | 89 | <td></td> |
paul@19 | 90 | <td class="buttons"> |
paul@19 | 91 | %(buttons_html)s |
paul@19 | 92 | </td> |
paul@19 | 93 | </tr> |
paul@19 | 94 | </table> |
paul@19 | 95 | ''' % d |
paul@19 | 96 | |
paul@19 | 97 | def do_action(self): |
paul@19 | 98 | |
paul@19 | 99 | "Write the iCalendar resource." |
paul@19 | 100 | |
paul@19 | 101 | _ = self._ |
paul@23 | 102 | form = self.request.form |
paul@19 | 103 | |
paul@19 | 104 | # If no category names exist in the request, an error message is |
paul@19 | 105 | # returned. |
paul@19 | 106 | |
paul@23 | 107 | category_names = form.get("category", []) |
paul@19 | 108 | |
paul@19 | 109 | if not category_names: |
paul@19 | 110 | return 0, _("No categories specified.") |
paul@19 | 111 | |
paul@19 | 112 | write_resource(self.request) |
paul@19 | 113 | return 1, None |
paul@19 | 114 | |
paul@27 | 115 | def render_success(self, msg, msgtype=None): |
paul@19 | 116 | |
paul@19 | 117 | """ |
paul@19 | 118 | Render neither 'msg' nor 'msgtype' since a resource has already been |
paul@19 | 119 | produced. |
paul@27 | 120 | NOTE: msgtype is optional because MoinMoin 1.5.x does not support it. |
paul@19 | 121 | """ |
paul@19 | 122 | |
paul@19 | 123 | pass |
paul@19 | 124 | |
paul@24 | 125 | def getQuotedText(text): |
paul@24 | 126 | |
paul@24 | 127 | "Return the 'text' quoted for iCalendar purposes." |
paul@24 | 128 | |
paul@24 | 129 | return text.replace(";", r"\;").replace(",", r"\,") |
paul@24 | 130 | |
paul@19 | 131 | def write_resource(request): |
paul@10 | 132 | |
paul@10 | 133 | """ |
paul@19 | 134 | For the given 'request', write an iCalendar summary of the event data found |
paul@19 | 135 | in the categories specified via the "category" request parameter, using the |
paul@19 | 136 | "start" and "end" parameters (if specified). Multiple "category" parameters |
paul@19 | 137 | can be specified. |
paul@10 | 138 | """ |
paul@10 | 139 | |
paul@10 | 140 | category_names = request.form.get("category", []) |
paul@10 | 141 | |
paul@19 | 142 | # Otherwise, produce an iCalendar resource. |
paul@10 | 143 | |
paul@19 | 144 | calendar_start = EventAggregatorSupport.getFormMonth(request, None, "start") |
paul@19 | 145 | calendar_end = EventAggregatorSupport.getFormMonth(request, None, "end") |
paul@10 | 146 | |
paul@23 | 147 | # Look for separate start and end years and months. |
paul@23 | 148 | |
paul@23 | 149 | form = request.form |
paul@23 | 150 | |
paul@23 | 151 | if calendar_start is None: |
paul@23 | 152 | calendar_start = EventAggregatorSupport.getFormMonthPair(request, "start-year", "start-month") |
paul@23 | 153 | |
paul@23 | 154 | if calendar_end is None: |
paul@23 | 155 | calendar_end = EventAggregatorSupport.getFormMonthPair(request, "end-year", "end-month") |
paul@23 | 156 | |
paul@10 | 157 | events, shown_events, all_shown_events, earliest, latest = \ |
paul@10 | 158 | EventAggregatorSupport.getEvents(request, category_names, calendar_start, calendar_end) |
paul@10 | 159 | |
paul@10 | 160 | # Output iCalendar data... |
paul@10 | 161 | |
paul@27 | 162 | if EventAggregatorSupport.isMoin15(): |
paul@27 | 163 | send_headers = request.http_headers |
paul@27 | 164 | else: |
paul@27 | 165 | send_headers = request.emit_http_headers |
paul@27 | 166 | |
paul@27 | 167 | send_headers(["Content-Type: text/calendar; charset=%s" % config.charset]) |
paul@10 | 168 | |
paul@10 | 169 | request.write("BEGIN:VCALENDAR\r\n") |
paul@10 | 170 | request.write("PRODID:-//MoinMoin//EventAggregatorSummary\r\n") |
paul@10 | 171 | request.write("VERSION:2.0\r\n") |
paul@10 | 172 | |
paul@10 | 173 | for event_page, event_details in all_shown_events: |
paul@10 | 174 | |
paul@24 | 175 | # Get the summary and timestamp details. |
paul@24 | 176 | |
paul@19 | 177 | event_summary = EventAggregatorSupport.getEventSummary(event_page, event_details) |
paul@10 | 178 | |
paul@24 | 179 | # Get the initial revision of the page. |
paul@24 | 180 | |
paul@24 | 181 | revisions = event_page.getRevList() |
paul@24 | 182 | event_page_initial = Page(request, event_page.page_name, rev=revisions[-1]) |
paul@24 | 183 | |
paul@24 | 184 | # Get the created and last modified times. |
paul@24 | 185 | |
paul@24 | 186 | created = EventAggregatorSupport.getPageDate(event_page_initial) |
paul@24 | 187 | last_modified = EventAggregatorSupport.getPageDate(event_page) |
paul@24 | 188 | sequence = len(revisions) - 1 |
paul@24 | 189 | |
paul@10 | 190 | # Output the event details. |
paul@10 | 191 | |
paul@10 | 192 | request.write("BEGIN:VEVENT\r\n") |
paul@10 | 193 | request.write("UID:%s\r\n" % request.getQualifiedURL(event_page.url(request))) |
paul@10 | 194 | request.write("URL:%s\r\n" % request.getQualifiedURL(event_page.url(request))) |
paul@24 | 195 | request.write("DTSTAMP:%04d%02d%02dT%02d%02d%02dZ\r\n" % created[:6]) |
paul@24 | 196 | request.write("LAST-MODIFIED:%04d%02d%02dT%02d%02d%02dZ\r\n" % last_modified[:6]) |
paul@24 | 197 | request.write("SEQUENCE:%d\r\n" % sequence) |
paul@10 | 198 | request.write("DTSTART;VALUE=DATE:%04d%02d%02d\r\n" % event_details["start"]) |
paul@10 | 199 | request.write("DTEND;VALUE=DATE:%04d%02d%02d\r\n" % EventAggregatorSupport.nextdate(event_details["end"])) |
paul@24 | 200 | request.write("SUMMARY:%s\r\n" % getQuotedText(event_summary)) |
paul@24 | 201 | |
paul@24 | 202 | # Optional details. |
paul@24 | 203 | |
paul@24 | 204 | if event_details.has_key("topics") or event_details.has_key("categories"): |
paul@24 | 205 | request.write("CATEGORIES:%s\r\n" % ",".join( |
paul@24 | 206 | [getQuotedText(topic) for topic in event_details.get("topics") or event_details.get("categories")] |
paul@24 | 207 | )) |
paul@24 | 208 | if event_details.has_key("location"): |
paul@24 | 209 | request.write("LOCATION:%s\r\n" % getQuotedText(event_details["location"])) |
paul@24 | 210 | |
paul@10 | 211 | request.write("END:VEVENT\r\n") |
paul@10 | 212 | |
paul@10 | 213 | request.write("END:VCALENDAR\r\n") |
paul@10 | 214 | |
paul@27 | 215 | if EventAggregatorSupport.isMoin15(): |
paul@27 | 216 | raise MoinMoin.util.MoinMoinNoFooter |
paul@27 | 217 | |
paul@19 | 218 | # Action function. |
paul@19 | 219 | |
paul@19 | 220 | def execute(pagename, request): |
paul@19 | 221 | EventAggregatorSummary(pagename, request).render() |
paul@19 | 222 | |
paul@10 | 223 | # vim: tabstop=4 expandtab shiftwidth=4 |