1 # -*- coding: iso-8859-1 -*- 2 """ 3 MoinMoin - EventAggregatorNewEvent Action 4 5 @copyright: 2008, 2009, 2010 by Paul Boddie <paul@boddie.org.uk> 6 @copyright: 2000-2004 Juergen Hermann <jh@web.de>, 7 2003-2008 MoinMoin:ThomasWaldmann, 8 2004-2006 MoinMoin:AlexanderSchremmer, 9 2007 MoinMoin:ReimarBauer. 10 @license: GNU GPL (v2 or later), see COPYING.txt for details. 11 """ 12 13 from MoinMoin.action import ActionBase 14 from MoinMoin.Page import Page 15 from MoinMoin.PageEditor import PageEditor 16 import EventAggregatorSupport 17 import calendar 18 import re 19 20 Dependencies = ['pages'] 21 22 # Action class and supporting functions. 23 24 class EventAggregatorNewEvent(ActionBase): 25 26 "An event creation dialogue requesting various parameters." 27 28 def _get_selected(self, value, input_value): 29 return input_value is not None and value == input_value and 'selected="selected"' or '' 30 31 def _get_selected_for_list(self, value, input_values): 32 return value in input_values and 'selected="selected"' or '' 33 34 def _get_input(self, form, name, default): 35 return int(form.get(name, [None])[0] or default) 36 37 def get_form_html(self, buttons_html): 38 _ = self._ 39 request = self.request 40 form = request.form 41 42 # Handle advanced and basic forms. 43 44 show_advanced = form.get("advanced") and not form.get("basic") 45 46 # Prepare the category list. 47 48 category_list = [] 49 category_pagenames = form.get("category", []) 50 51 for category_name, category_pagename in \ 52 EventAggregatorSupport.getCategoryMapping( 53 EventAggregatorSupport.getCategories(request), 54 request): 55 56 selected = self._get_selected_for_list(category_pagename, category_pagenames) 57 58 # In the advanced view, populate a menu. 59 60 if show_advanced: 61 category_list.append('<option value="%s" %s>%s</option>' % (category_pagename, selected, category_name)) 62 63 # In the basic view, use hidden fields. 64 65 elif selected: 66 category_list.append('<input value="%s" name="category" type="hidden" />' % category_pagename) 67 68 # Prepare the topics list. 69 70 topics = form.get("topics", []) 71 72 if form.get("add-topic"): 73 topics.append("") 74 else: 75 for i in range(0, len(topics)): 76 if form.get("remove-topic-%d" % i): 77 del topics[i] 78 break 79 80 # Initialise month lists. 81 82 start_month_list = [] 83 start_month_list.append('<option value=""></option>') 84 end_month_list = [] 85 end_month_list.append('<option value=""></option>') 86 87 start_month = self._get_input(form, "start-month", 0) 88 end_month = self._get_input(form, "end-month", 0) 89 90 # Prepare month lists, selecting specified months. 91 92 for month in range(1, 13): 93 month_label = _(EventAggregatorSupport.getMonthLabel(month)) 94 selected = self._get_selected(month, start_month) 95 start_month_list.append('<option value="%02d" %s>%s</option>' % (month, selected, month_label)) 96 selected = self._get_selected(month, end_month) 97 end_month_list.append('<option value="%02d" %s>%s</option>' % (month, selected, month_label)) 98 99 # Permitting configuration of the template name. 100 101 template_default = getattr(request.cfg, "event_aggregator_new_event_template", "EventTemplate") 102 103 d = { 104 "buttons_html" : buttons_html, 105 "category_label" : _("Categories"), 106 "category_list" : "\n".join(category_list), 107 "start_month_list" : "\n".join(start_month_list), 108 "end_month_list" : "\n".join(end_month_list), 109 "start_label" : _("Start date (day, month, year)"), 110 "start_day_default" : form.get("start-day", [""])[0], 111 "start_year_default" : form.get("start-year", [""])[0] or EventAggregatorSupport.getCurrentYear(), 112 "end_label" : _("End date (day, month, year) - if different"), 113 "end_day_default" : form.get("end-day", [""])[0], 114 "end_year_default" : form.get("end-year", [""])[0], 115 "title_label" : _("Event title/summary"), 116 "title_default" : form.get("title", [""])[0], 117 "description_label" : _("Event description"), 118 "description_default" : form.get("description", [""])[0], 119 "location_label" : _("Event location"), 120 "location_default" : form.get("location", [""])[0], 121 "link_label" : _("Event URL"), 122 "link_default" : form.get("link", [""])[0], 123 "topics_label" : _("Topics"), 124 "add_topic_label" : _("Add topic"), 125 "remove_topic_label" : _("Remove topic"), 126 "template_label" : _("Event template"), 127 "template_default" : form.get("template", [""])[0] or template_default, 128 "parent_label" : _("Parent page"), 129 "parent_default" : form.get("parent", [""])[0], 130 "advanced_label" : _("Show advanced options"), 131 "basic_label" : _("Show basic options"), 132 } 133 134 # Prepare the output HTML. 135 136 html = ''' 137 <table> 138 <tr> 139 <td class="label"><label>%(title_label)s</label></td> 140 <td> 141 <input name="title" type="text" size="40" value="%(title_default)s" /> 142 </td> 143 </tr> 144 <tr> 145 <td class="label"><label>%(start_label)s</label></td> 146 <td> 147 <input name="start-day" type="text" value="%(start_day_default)s" size="2" /> 148 <select name="start-month"> 149 %(start_month_list)s 150 </select> 151 <input name="start-year" type="text" value="%(start_year_default)s" size="4" /> 152 </td> 153 </tr> 154 <tr> 155 <td class="label"><label>%(end_label)s</label></td> 156 <td> 157 <input name="end-day" type="text" value="%(end_day_default)s" size="2" /> 158 <select name="end-month"> 159 %(end_month_list)s 160 </select> 161 <input name="end-year" type="text" value="%(end_year_default)s" size="4" /> 162 </td> 163 </tr> 164 <tr> 165 <td class="label"><label>%(description_label)s</label></td> 166 <td> 167 <input name="description" type="text" size="40" value="%(description_default)s" /> 168 </td> 169 </tr> 170 <tr> 171 <td class="label"><label>%(location_label)s</label></td> 172 <td> 173 <input name="location" type="text" size="40" value="%(location_default)s" /> 174 </td> 175 </tr> 176 <tr> 177 <tr> 178 <td class="label"><label>%(link_label)s</label></td> 179 <td> 180 <input name="link" type="text" size="40" value="%(link_default)s" /> 181 </td> 182 </tr>''' % d 183 184 # Topics. 185 186 for i, topic in enumerate(topics): 187 d["topic"] = topic 188 d["topic_number"] = i 189 html += ''' 190 <tr> 191 <td class="label"><label>%(topics_label)s</label></td> 192 <td> 193 <input name="topics" type="text" size="20" value="%(topic)s" /> 194 <input name="remove-topic-%(topic_number)s" type="submit" value="%(remove_topic_label)s" /> 195 </td> 196 </tr>''' % d 197 198 html += ''' 199 <tr> 200 <td></td> 201 <td> 202 <input name="add-topic" type="submit" value="%(add_topic_label)s" /> 203 </td> 204 </tr>''' % d 205 206 # Advanced options. 207 208 if show_advanced: 209 html += ''' 210 <tr> 211 <td></td> 212 <td> 213 <input name="basic" type="submit" value="%(basic_label)s" /> 214 <input name="advanced" type="hidden" value="true" /> 215 </td> 216 </tr> 217 <tr> 218 <td class="label"><label>%(category_label)s</label></td> 219 <td class="content"> 220 <select multiple="multiple" name="category"> 221 %(category_list)s 222 </select> 223 </td> 224 </tr> 225 <tr> 226 <td class="label"><label>%(template_label)s</label></td> 227 <td> 228 <input name="template" type="text" size="40" value="%(template_default)s" /> 229 </td> 230 </tr> 231 <tr> 232 <td class="label"><label>%(parent_label)s</label></td> 233 <td> 234 <input name="parent" type="text" size="40" value="%(parent_default)s" /> 235 </td> 236 </tr> 237 <tr> 238 <td></td> 239 <td class="buttons"> 240 %(buttons_html)s 241 </td> 242 </tr> 243 </table>''' % d 244 else: 245 html += ''' 246 <tr> 247 <td></td> 248 <td> 249 <input name="advanced" type="submit" value="%(advanced_label)s" /> 250 %(category_list)s 251 <input name="parent" type="hidden" value="%(parent_default)s" /> 252 <input name="template" type="hidden" value="%(template_default)s" /> 253 </td> 254 </tr> 255 <tr> 256 <td></td> 257 <td class="buttons"> 258 %(buttons_html)s 259 </td> 260 </tr> 261 </table>''' % d 262 263 return html 264 265 def do_action(self): 266 267 "Create the new event." 268 269 _ = self._ 270 form = self.request.form 271 272 # If no title exists in the request, an error message is returned. 273 274 title = form.get("title", [None])[0] 275 template = form.get("template", [None])[0] 276 277 if not title: 278 return 0, _("No event title specified.") 279 280 if not template: 281 return 0, _("No page template specified.") 282 283 return self.create_event(self.request) 284 285 def render_success(self, msg, msgtype=None): 286 287 """ 288 Render neither 'msg' nor 'msgtype' since redirection should occur 289 instead. 290 NOTE: msgtype is optional because MoinMoin 1.5.x does not support it. 291 """ 292 293 pass 294 295 def create_event(self, request): 296 297 "Create an event page using the 'request'." 298 299 _ = request.getText 300 form = request.form 301 302 category_pagenames = form.get("category", []) 303 description = form.get("description", [None])[0] 304 location = form.get("location", [None])[0] 305 link = form.get("link", [None])[0] 306 topics = form.get("topics", []) 307 308 # Validate certain fields. 309 310 try: 311 title = form["title"][0] 312 template = form["template"][0] 313 parent = form["parent"][0] 314 315 start_day = self._get_input(form, "start-day", 0) 316 start_month = self._get_input(form, "start-month", 0) 317 start_year = self._get_input(form, "start-year", 0) 318 end_day = self._get_input(form, "end-day", start_day) 319 end_month = self._get_input(form, "end-month", start_month) 320 end_year = self._get_input(form, "end-year", start_year) 321 322 start_year, start_month, start_day = self.constrain_date(start_year, start_month, start_day) 323 end_year, end_month, end_day = self.constrain_date(end_year, end_month, end_day) 324 325 except (TypeError, ValueError): 326 return 0, _("Days and years must be numbers yielding a valid date!") 327 328 except (KeyError, IndexError): 329 return 0, _("Event title or template missing.") 330 331 start_date = self.make_date_string(start_year, start_month, start_day) 332 end_date = self.make_date_string(end_year, end_month, end_day) 333 334 # An elementary date ordering check. 335 336 if start_date > end_date: 337 start_date, end_date = end_date, start_date 338 339 event_details = { 340 "start" : start_date, "end" : end_date, 341 "title" : title, "summary" : title, 342 "description" : description, "location" : location, "link" : link, 343 "topics" : [topic for topic in topics if topic] 344 } 345 346 # Copy the template. 347 348 template_page = PageEditor(request, template) 349 350 if not template_page.exists(): 351 return 0, _("Event template not available.") 352 353 # Use any parent page information. 354 355 full_title = EventAggregatorSupport.getFullPageName(parent, title) 356 357 # Load the new page and replace the event details in the body. 358 359 new_page = PageEditor(request, full_title) 360 361 if new_page.exists(): 362 return 0, _("The specified page already exists. Please choose another name.") 363 364 # Complete the new page. 365 366 EventAggregatorSupport.fillEventPageFromTemplate(template_page, 367 new_page, event_details, category_pagenames) 368 369 # Redirect and return success. 370 371 query = {'action' : 'edit'} 372 request.http_redirect(new_page.url(request, query)) 373 return 1, None 374 375 def make_date_string(self, year, month, day): 376 return "%s-%s-%s" % ( 377 year and ("%04d" % year) or "YYYY", 378 month and ("%02d" % month) or "MM", 379 day and ("%02d" % day) or "DD" 380 ) 381 382 def constrain_date(self, year, month, day): 383 if year and month and day: 384 wd, last_day = calendar.monthrange(year, month) 385 day = max(min(day, last_day), 1) 386 return year, month, day 387 388 # Action function. 389 390 def execute(pagename, request): 391 EventAggregatorNewEvent(pagename, request).render() 392 393 # vim: tabstop=4 expandtab shiftwidth=4