1 # -*- coding: iso-8859-1 -*- 2 """ 3 MoinMoin - EventAggregatorNewEvent Action 4 5 @copyright: 2008, 2009, 2010, 2011 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 from EventAggregatorSupport import * 17 18 try: 19 import pytz 20 except ImportError: 21 pytz = None 22 23 Dependencies = ['pages'] 24 25 # Action class and supporting functions. 26 27 class EventAggregatorNewEvent(ActionBase, ActionSupport): 28 29 "An event creation dialogue requesting various parameters." 30 31 def get_form_html(self, buttons_html): 32 _ = self._ 33 request = self.request 34 form = self.get_form() 35 36 # Handle advanced and basic forms, and enable/disable certain fields. 37 38 show_advanced = form.get("advanced") and not form.get("basic") 39 show_end_date = form.get("end-day") and not form.get("hide-end-date") or form.get("show-end-date") 40 show_times = (form.get("start-hour") or form.get("end-hour")) and not form.get("hide-times") or form.get("show-times") 41 42 show_zone_regime = form.get("regime") and not form.get("show-offsets") and \ 43 not form.get("hide-zone") or form.get("show-regime") 44 show_zone_offsets = form.get("start-offset") and not form.get("show-regime") and \ 45 not form.get("hide-zone") or form.get("show-offsets") 46 47 show_zones = show_zone_regime or show_zone_offsets 48 49 # Prepare the category list. 50 51 category_list = [] 52 category_pagenames = form.get("category", []) 53 54 for category_name, category_pagename in getCategoryMapping(getCategories(request), 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>' % ( 62 escattr(category_pagename), selected, escape(category_name))) 63 64 # In the basic view, use hidden fields. 65 66 elif selected: 67 category_list.append('<input value="%s" name="category" type="hidden" />' % escattr(category_pagename)) 68 69 # Prepare the topics list. 70 71 topics = form.get("topics", []) 72 73 if form.get("add-topic"): 74 topics.append("") 75 else: 76 for i in range(0, len(topics)): 77 if form.get("remove-topic-%d" % i): 78 del topics[i] 79 break 80 81 # Initialise month lists. 82 83 start_month_list, end_month_list = self.get_month_lists(default_as_current=1) 84 start_year_default, end_year_default = self.get_year_defaults(default_as_current=1) 85 86 # Initialise regime lists. 87 88 regime_list = [] 89 regime_list.append('<option value=""></option>') 90 91 regime = form.get("regime", [None])[0] 92 93 # Prepare regime lists, selecting specified regimes. 94 95 if pytz is not None: 96 for pytz_regime in pytz.common_timezones: 97 selected = self._get_selected(pytz_regime, regime) 98 regime_list.append('<option value="%s" %s>%s</option>' % (escattr(pytz_regime), selected, escape(pytz_regime))) 99 100 # Permitting configuration of the template name. 101 102 template_default = getattr(request.cfg, "event_aggregator_new_event_template", "EventTemplate") 103 104 d = { 105 "buttons_html" : buttons_html, 106 "category_label" : escape(_("Categories")), 107 "category_list" : "\n".join(category_list), 108 109 "start_month_list" : "\n".join(start_month_list), 110 "end_month_list" : "\n".join(end_month_list), 111 112 "regime_list" : "\n".join(regime_list), 113 "use_regime_label" : escape(_("Using local time")), 114 115 "show_end_date_label" : escape(_("Specify end date")), 116 "hide_end_date_label" : escape(_("End event on same day")), 117 118 "show_times_label" : escape(_("Specify times")), 119 "hide_times_label" : escape(_("No start and end times")), 120 121 "show_offsets_label" : escape(_("Specify UTC offsets")), 122 "show_regime_label" : escape(_("Specify location")), 123 "hide_zone_label" : escape(_("Make times apply everywhere")), 124 125 "start_label" : escape(_("Start date (day, month, year)")), 126 "start_day_default" : escattr(form.get("start-day", [""])[0]), 127 "start_year_default" : escattr(start_year_default), 128 "start_time_label" : escape(_("Start time (hour, minute, second)")), 129 "start_hour_default" : escattr(form.get("start-hour", [""])[0]), 130 "start_minute_default" : escattr(form.get("start-minute", [""])[0]), 131 "start_second_default" : escattr(form.get("start-second", [""])[0]), 132 "start_offset_default" : escattr(form.get("start-offset", [""])[0]), 133 134 "end_label" : escape(_("End date (day, month, year) - if different")), 135 "end_day_default" : escattr(form.get("end-day", [""])[0] or form.get("start-day", [""])[0]), 136 "end_year_default" : escattr(end_year_default), 137 "end_time_label" : escape(_("End time (hour, minute, second)")), 138 "end_hour_default" : escattr(form.get("end-hour", [""])[0]), 139 "end_minute_default" : escattr(form.get("end-minute", [""])[0]), 140 "end_second_default" : escattr(form.get("end-second", [""])[0]), 141 "end_offset_default" : escattr(form.get("end-offset", [""])[0] or form.get("start-offset", [""])[0]), 142 143 "title_label" : escape(_("Event title/summary")), 144 "title_default" : escattr(form.get("title", [""])[0]), 145 "description_label" : escape(_("Event description")), 146 "description_default" : escattr(form.get("description", [""])[0]), 147 "location_label" : escape(_("Event location")), 148 "location_default" : escattr(form.get("location", [""])[0]), 149 "link_label" : escape(_("Event URL")), 150 "link_default" : escattr(form.get("link", [""])[0]), 151 152 "topics_label" : escape(_("Topics")), 153 "add_topic_label" : escape(_("Add topic")), 154 "remove_topic_label" : escape(_("Remove topic")), 155 156 "template_label" : escape(_("Event template")), 157 "template_default" : escattr(form.get("template", [""])[0] or template_default), 158 "parent_label" : escape(_("Parent page")), 159 "parent_default" : escattr(form.get("parent", [""])[0]), 160 161 "advanced_label" : escape(_("Show advanced options")), 162 "basic_label" : escape(_("Hide advanced options")), 163 } 164 165 # Prepare the output HTML. 166 167 html = ''' 168 <table> 169 <tr> 170 <td class="label"><label>%(title_label)s</label></td> 171 <td colspan="2"> 172 <input name="title" type="text" size="40" value="%(title_default)s" /> 173 </td> 174 </tr> 175 <tr> 176 <td class="label"><label>%(start_label)s</label></td> 177 <td colspan="2" style="white-space: nowrap"> 178 <input name="start-day" type="text" value="%(start_day_default)s" size="2" /> 179 <select name="start-month"> 180 %(start_month_list)s 181 </select> 182 <input name="start-year" type="text" value="%(start_year_default)s" size="4" /> 183 </td> 184 </tr>''' % d 185 186 # End date controls. 187 188 if show_end_date: 189 html += ''' 190 <tr> 191 <td class="label"><label>%(end_label)s</label></td> 192 <td colspan="2" style="white-space: nowrap"> 193 <input name="end-day" type="text" value="%(end_day_default)s" size="2" /> 194 <select name="end-month"> 195 %(end_month_list)s 196 </select> 197 <input name="end-year" type="text" value="%(end_year_default)s" size="4" /> 198 </td> 199 </tr> 200 <tr> 201 <td class="label"> 202 <input name="hide-end-date" type="submit" value="%(hide_end_date_label)s" /> 203 </td> 204 </tr>''' % d 205 else: 206 html += ''' 207 <tr> 208 <td class="label"> 209 <input name="show-end-date" type="submit" value="%(show_end_date_label)s" /> 210 </td> 211 </tr>''' % d 212 213 # Generic time information. 214 215 if show_times: 216 217 # Start time controls. 218 219 html += ''' 220 <tr> 221 <td class="label"><label>%(start_time_label)s</label></td> 222 <td style="white-space: nowrap"> 223 <input name="start-hour" type="text" value="%(start_hour_default)s" size="2" maxlength="2" /> 224 <input name="start-minute" type="text" value="%(start_minute_default)s" size="2" maxlength="2" /> 225 <input name="start-second" type="text" value="%(start_second_default)s" size="2" maxlength="2" /> 226 </td>''' % d 227 228 # Offset information displayed. 229 230 if show_zone_offsets: 231 html += ''' 232 <td> 233 UTC <input name="start-offset" type="text" value="%(start_offset_default)s" size="6" maxlength="6" /> 234 </td>''' % d 235 236 # Regime information displayed. 237 238 elif show_zone_regime: 239 html += ''' 240 <td> 241 %(use_regime_label)s 242 </td>''' % d 243 244 html += ''' 245 </tr>''' 246 247 # End time controls. 248 249 html += ''' 250 <tr> 251 <td class="label"><label>%(end_time_label)s</label></td> 252 <td style="white-space: nowrap"> 253 <input name="end-hour" type="text" value="%(end_hour_default)s" size="2" maxlength="2" /> 254 <input name="end-minute" type="text" value="%(end_minute_default)s" size="2" maxlength="2" /> 255 <input name="end-second" type="text" value="%(end_second_default)s" size="2" maxlength="2" /> 256 </td>''' % d 257 258 # Offset information displayed. 259 260 if show_zone_offsets: 261 html += ''' 262 <td> 263 UTC <input name="end-offset" type="text" value="%(end_offset_default)s" size="6" maxlength="6" /> 264 </td>''' % d 265 266 # Regime information displayed. 267 268 elif show_zone_regime: 269 html += ''' 270 <td> 271 <select name="regime"> 272 %(regime_list)s 273 </select> 274 </td>''' % d 275 276 # Controls for removing times. 277 278 html += ''' 279 </tr> 280 <tr> 281 <td class="label"> 282 <input name="hide-times" type="submit" value="%(hide_times_label)s" /> 283 </td> 284 <td></td>''' % d 285 286 # Time zone controls. 287 288 if show_zones: 289 290 # Offset information displayed. 291 292 if show_zone_offsets: 293 html += ''' 294 <td> 295 <input name="show-regime" type="submit" value="%(show_regime_label)s" />''' % d 296 297 # Regime information displayed. 298 299 elif show_zone_regime: 300 html += ''' 301 <td> 302 <input name="show-offsets" type="submit" value="%(show_offsets_label)s" />''' % d 303 304 # To remove zone information. 305 306 html += ''' 307 <input name="hide-zone" type="submit" value="%(hide_zone_label)s" /> 308 </td>''' % d 309 310 # No time zone information shown. 311 312 else: 313 html += ''' 314 <td> 315 <input name="show-regime" type="submit" value="%(show_regime_label)s" /> 316 <input name="show-offsets" type="submit" value="%(show_offsets_label)s" /> 317 </td>''' % d 318 319 html += ''' 320 </tr>''' 321 322 # Controls for adding times. 323 324 else: 325 html += ''' 326 <tr> 327 <td class="label"> 328 <input name="show-times" type="submit" value="%(show_times_label)s" /> 329 </td> 330 </tr>''' % d 331 332 333 # Various basic controls. 334 335 html += ''' 336 <tr> 337 <td class="label"><label>%(description_label)s</label></td> 338 <td colspan="2"> 339 <input name="description" type="text" size="40" value="%(description_default)s" /> 340 </td> 341 </tr> 342 <tr> 343 <td class="label"><label>%(location_label)s</label></td> 344 <td colspan="2"> 345 <input name="location" type="text" size="40" value="%(location_default)s" /> 346 </td> 347 </tr> 348 <tr> 349 <td class="label"><label>%(link_label)s</label></td> 350 <td colspan="2"> 351 <input name="link" type="text" size="40" value="%(link_default)s" /> 352 </td> 353 </tr>''' % d 354 355 # Topics. 356 357 for i, topic in enumerate(topics): 358 d["topic"] = escattr(topic) 359 d["topic_number"] = i 360 html += ''' 361 <tr> 362 <td class="label"><label>%(topics_label)s</label></td> 363 <td colspan="2"> 364 <input name="topics" type="text" size="20" value="%(topic)s" /> 365 <input name="remove-topic-%(topic_number)s" type="submit" value="%(remove_topic_label)s" /> 366 </td> 367 </tr>''' % d 368 369 html += ''' 370 <tr> 371 <td></td> 372 <td colspan="2"> 373 <input name="add-topic" type="submit" value="%(add_topic_label)s" /> 374 </td> 375 </tr>''' % d 376 377 # Advanced options. 378 379 if show_advanced: 380 html += ''' 381 <tr> 382 <td></td> 383 <td colspan="2"> 384 <input name="basic" type="submit" value="%(basic_label)s" /> 385 <input name="advanced" type="hidden" value="true" /> 386 </td> 387 </tr> 388 <tr> 389 <td class="label"><label>%(category_label)s</label></td> 390 <td colspan="2" class="content"> 391 <select multiple="multiple" name="category"> 392 %(category_list)s 393 </select> 394 </td> 395 </tr> 396 <tr> 397 <td class="label"><label>%(template_label)s</label></td> 398 <td colspan="2"> 399 <input name="template" type="text" size="40" value="%(template_default)s" /> 400 </td> 401 </tr> 402 <tr> 403 <td class="label"><label>%(parent_label)s</label></td> 404 <td colspan="2"> 405 <input name="parent" type="text" size="40" value="%(parent_default)s" /> 406 </td> 407 </tr> 408 <tr> 409 <td></td> 410 <td colspan="2" class="buttons"> 411 %(buttons_html)s 412 </td> 413 </tr> 414 </table>''' % d 415 else: 416 html += ''' 417 <tr> 418 <td></td> 419 <td colspan="2"> 420 <input name="advanced" type="submit" value="%(advanced_label)s" /> 421 %(category_list)s 422 <input name="parent" type="hidden" value="%(parent_default)s" /> 423 <input name="template" type="hidden" value="%(template_default)s" /> 424 </td> 425 </tr> 426 <tr> 427 <td></td> 428 <td colspan="2" class="buttons"> 429 %(buttons_html)s 430 </td> 431 </tr> 432 </table>''' % d 433 434 return html 435 436 def do_action(self): 437 438 "Create the new event." 439 440 _ = self._ 441 form = self.get_form() 442 443 # If no title exists in the request, an error message is returned. 444 445 title = form.get("title", [None])[0] 446 template = form.get("template", [None])[0] 447 448 if not title: 449 return 0, _("No event title specified.") 450 451 if not template: 452 return 0, _("No page template specified.") 453 454 return self.create_event(self.request) 455 456 def render_success(self, msg, msgtype=None): 457 458 """ 459 Render neither 'msg' nor 'msgtype' since redirection should occur 460 instead. 461 NOTE: msgtype is optional because MoinMoin 1.5.x does not support it. 462 """ 463 464 pass 465 466 def create_event(self, request): 467 468 "Create an event page using the 'request'." 469 470 _ = request.getText 471 form = self.get_form() 472 473 category_pagenames = form.get("category", []) 474 description = form.get("description", [None])[0] 475 location = form.get("location", [None])[0] 476 link = form.get("link", [None])[0] 477 topics = form.get("topics", []) 478 479 regime = form.get("regime", [None])[0] 480 start_offset = form.get("start-offset", [None])[0] 481 end_offset = form.get("end-offset", [None])[0] 482 483 start_zone = regime or start_offset 484 end_zone = regime or end_offset 485 486 # Validate certain fields. 487 488 try: 489 title = form["title"][0] 490 template = form["template"][0] 491 parent = form["parent"][0] 492 except (KeyError, IndexError): 493 return 0, _("Event title or template missing.") 494 495 try: 496 start_day = self._get_input(form, "start-day") 497 start_month = self._get_input(form, "start-month") 498 start_year = self._get_input(form, "start-year") 499 500 if not start_day or not start_month or not start_year: 501 return 0, _("A start date must be specified.") 502 503 end_day = self._get_input(form, "end-day", start_day) 504 end_month = self._get_input(form, "end-month", start_month) 505 end_year = self._get_input(form, "end-year", start_year) 506 507 except (TypeError, ValueError): 508 return 0, _("Days and years must be numbers yielding a valid date!") 509 510 try: 511 start_hour = self._get_input(form, "start-hour") 512 start_minute = self._get_input(form, "start-minute") 513 start_second = self._get_input(form, "start-second") 514 515 end_hour = self._get_input(form, "end-hour") 516 end_minute = self._get_input(form, "end-minute") 517 end_second = self._get_input(form, "end-second") 518 519 except (TypeError, ValueError): 520 return 0, _("Hours, minutes and seconds must be numbers yielding a valid time!") 521 522 start_date = DateTime( 523 (start_year, start_month, start_day, start_hour, start_minute, start_second, start_zone) 524 ) 525 start_date.constrain() 526 527 end_date = DateTime( 528 (end_year, end_month, end_day, end_hour, end_minute, end_second, end_zone) 529 ) 530 end_date.constrain() 531 532 # An elementary date ordering check. 533 534 if (start_date.as_date() != end_date.as_date() or start_date.has_time() and end_date.has_time()) and start_date > end_date: 535 start_date, end_date = end_date, start_date 536 537 event_details = { 538 "start" : str(start_date), "end" : str(end_date), 539 "title" : title, "summary" : title, 540 "description" : description, "location" : location, "link" : link, 541 "topics" : [topic for topic in topics if topic] 542 } 543 544 # Copy the template. 545 546 template_page = PageEditor(request, template) 547 548 if not template_page.exists(): 549 return 0, _("Event template not available.") 550 551 # Use any parent page information. 552 553 full_title = getFullPageName(parent, title) 554 555 # Load the new page and replace the event details in the body. 556 557 new_page = PageEditor(request, full_title) 558 559 if new_page.exists(): 560 return 0, _("The specified page already exists. Please choose another name.") 561 562 # Complete the new page. 563 564 fillEventPageFromTemplate(template_page, new_page, event_details, category_pagenames) 565 566 # Redirect and return success. 567 568 query = {'action' : 'edit'} 569 request.http_redirect(new_page.url(request, query)) 570 return 1, None 571 572 # Action function. 573 574 def execute(pagename, request): 575 EventAggregatorNewEvent(pagename, request).render() 576 577 # vim: tabstop=4 expandtab shiftwidth=4