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 18 Dependencies = ['pages'] 19 20 # Action class and supporting functions. 21 22 class EventAggregatorNewEvent(ActionBase): 23 24 "An event creation dialogue requesting various parameters." 25 26 def _get_selected(self, value, input_value): 27 return input_value is not None and value == input_value and 'selected="selected"' or '' 28 29 def _get_selected_for_list(self, value, input_values): 30 return value in input_values and 'selected="selected"' or '' 31 32 def _get_input(self, form, name, default=None): 33 value = form.get(name, [None])[0] 34 if not value: # true if 0 obtained 35 return default 36 else: 37 return int(value) 38 39 def get_form_html(self, buttons_html): 40 _ = self._ 41 request = self.request 42 form = request.form 43 44 # Handle advanced and basic forms. 45 46 show_advanced = form.get("advanced") and not form.get("basic") 47 48 # Prepare the category list. 49 50 category_list = [] 51 category_pagenames = form.get("category", []) 52 53 for category_name, category_pagename in \ 54 EventAggregatorSupport.getCategoryMapping( 55 EventAggregatorSupport.getCategories(request), 56 request): 57 58 selected = self._get_selected_for_list(category_pagename, category_pagenames) 59 60 # In the advanced view, populate a menu. 61 62 if show_advanced: 63 category_list.append('<option value="%s" %s>%s</option>' % (category_pagename, selected, category_name)) 64 65 # In the basic view, use hidden fields. 66 67 elif selected: 68 category_list.append('<input value="%s" name="category" type="hidden" />' % category_pagename) 69 70 # Prepare the topics list. 71 72 topics = form.get("topics", []) 73 74 if form.get("add-topic"): 75 topics.append("") 76 else: 77 for i in range(0, len(topics)): 78 if form.get("remove-topic-%d" % i): 79 del topics[i] 80 break 81 82 # Initialise hour and minute lists. 83 84 start_hour_list = [] 85 start_hour_list.append('<option value=""></option>') 86 start_minute_list = [] 87 start_minute_list.append('<option value=""></option>') 88 end_hour_list = [] 89 end_hour_list.append('<option value=""></option>') 90 end_minute_list = [] 91 end_minute_list.append('<option value=""></option>') 92 93 start_hour = self._get_input(form, "start-hour") 94 end_hour = self._get_input(form, "end-hour") 95 start_minute = self._get_input(form, "start-minute") 96 end_minute = self._get_input(form, "end-minute") 97 98 # Prepare hour and minute lists, selecting specified values. 99 100 for hour in range(0, 24): 101 selected = self._get_selected(hour, start_hour) 102 start_hour_list.append('<option value="%02d" %s>%02d</option>' % (hour, selected, hour)) 103 selected = self._get_selected(hour, end_hour) 104 end_hour_list.append('<option value="%02d" %s>%02d</option>' % (hour, selected, hour)) 105 106 for minute in range(0, 60): 107 selected = self._get_selected(minute, start_minute) 108 start_minute_list.append('<option value="%02d" %s>%02d</option>' % (minute, selected, minute)) 109 selected = self._get_selected(minute, end_minute) 110 end_minute_list.append('<option value="%02d" %s>%02d</option>' % (minute, selected, minute)) 111 112 # Initialise month lists. 113 114 start_month_list = [] 115 start_month_list.append('<option value=""></option>') 116 end_month_list = [] 117 end_month_list.append('<option value=""></option>') 118 119 start_month = self._get_input(form, "start-month", 0) 120 end_month = self._get_input(form, "end-month", 0) 121 122 # Prepare month lists, selecting specified months. 123 124 for month in range(1, 13): 125 month_label = _(EventAggregatorSupport.getMonthLabel(month)) 126 selected = self._get_selected(month, start_month) 127 start_month_list.append('<option value="%02d" %s>%s</option>' % (month, selected, month_label)) 128 selected = self._get_selected(month, end_month) 129 end_month_list.append('<option value="%02d" %s>%s</option>' % (month, selected, month_label)) 130 131 # Permitting configuration of the template name. 132 133 template_default = getattr(request.cfg, "event_aggregator_new_event_template", "EventTemplate") 134 135 d = { 136 "buttons_html" : buttons_html, 137 "category_label" : _("Categories"), 138 "category_list" : "\n".join(category_list), 139 140 "start_month_list" : "\n".join(start_month_list), 141 "start_hour_list" : "\n".join(start_hour_list), 142 "start_minute_list" : "\n".join(start_minute_list), 143 144 "end_month_list" : "\n".join(end_month_list), 145 "end_hour_list" : "\n".join(end_hour_list), 146 "end_minute_list" : "\n".join(end_minute_list), 147 148 "start_label" : _("Start date (day, month, year)"), 149 "start_day_default" : form.get("start-day", [""])[0], 150 "start_year_default" : form.get("start-year", [""])[0] or EventAggregatorSupport.getCurrentYear(), 151 "start_time_label" : _("Start time (hour, minute, second)"), 152 "start_second_default" : form.get("start-second", [""])[0], 153 154 "end_label" : _("End date (day, month, year) - if different"), 155 "end_day_default" : form.get("end-day", [""])[0], 156 "end_year_default" : form.get("end-year", [""])[0], 157 "end_time_label" : _("End time (hour, minute, second)"), 158 "end_second_default" : form.get("end-second", [""])[0], 159 160 "title_label" : _("Event title/summary"), 161 "title_default" : form.get("title", [""])[0], 162 "description_label" : _("Event description"), 163 "description_default" : form.get("description", [""])[0], 164 "location_label" : _("Event location"), 165 "location_default" : form.get("location", [""])[0], 166 "link_label" : _("Event URL"), 167 "link_default" : form.get("link", [""])[0], 168 169 "topics_label" : _("Topics"), 170 "add_topic_label" : _("Add topic"), 171 "remove_topic_label" : _("Remove topic"), 172 173 "template_label" : _("Event template"), 174 "template_default" : form.get("template", [""])[0] or template_default, 175 "parent_label" : _("Parent page"), 176 "parent_default" : form.get("parent", [""])[0], 177 178 "advanced_label" : _("Show advanced options"), 179 "basic_label" : _("Show basic options"), 180 } 181 182 # Prepare the output HTML. 183 184 html = ''' 185 <table> 186 <tr> 187 <td class="label"><label>%(title_label)s</label></td> 188 <td> 189 <input name="title" type="text" size="40" value="%(title_default)s" /> 190 </td> 191 </tr> 192 <tr> 193 <td class="label"><label>%(start_label)s</label></td> 194 <td> 195 <input name="start-day" type="text" value="%(start_day_default)s" size="2" /> 196 <select name="start-month"> 197 %(start_month_list)s 198 </select> 199 <input name="start-year" type="text" value="%(start_year_default)s" size="4" /> 200 </td> 201 </tr> 202 <tr> 203 <td class="label"><label>%(start_time_label)s</label></td> 204 <td> 205 <select name="start-hour"> 206 %(start_hour_list)s 207 </select> 208 <select name="start-minute"> 209 %(start_minute_list)s 210 </select> 211 <input name="start-second" type="text" value="%(start_second_default)s" size="2" /> 212 </td> 213 </tr> 214 <tr> 215 <td class="label"><label>%(end_label)s</label></td> 216 <td> 217 <input name="end-day" type="text" value="%(end_day_default)s" size="2" /> 218 <select name="end-month"> 219 %(end_month_list)s 220 </select> 221 <input name="end-year" type="text" value="%(end_year_default)s" size="4" /> 222 </td> 223 </tr> 224 <tr> 225 <td class="label"><label>%(end_time_label)s</label></td> 226 <td> 227 <select name="end-hour"> 228 %(end_hour_list)s 229 </select> 230 <select name="end-minute"> 231 %(end_minute_list)s 232 </select> 233 <input name="end-second" type="text" value="%(end_second_default)s" size="2" /> 234 </td> 235 </tr> 236 <tr> 237 <td class="label"><label>%(description_label)s</label></td> 238 <td> 239 <input name="description" type="text" size="40" value="%(description_default)s" /> 240 </td> 241 </tr> 242 <tr> 243 <td class="label"><label>%(location_label)s</label></td> 244 <td> 245 <input name="location" type="text" size="40" value="%(location_default)s" /> 246 </td> 247 </tr> 248 <tr> 249 <tr> 250 <td class="label"><label>%(link_label)s</label></td> 251 <td> 252 <input name="link" type="text" size="40" value="%(link_default)s" /> 253 </td> 254 </tr>''' % d 255 256 # Topics. 257 258 for i, topic in enumerate(topics): 259 d["topic"] = topic 260 d["topic_number"] = i 261 html += ''' 262 <tr> 263 <td class="label"><label>%(topics_label)s</label></td> 264 <td> 265 <input name="topics" type="text" size="20" value="%(topic)s" /> 266 <input name="remove-topic-%(topic_number)s" type="submit" value="%(remove_topic_label)s" /> 267 </td> 268 </tr>''' % d 269 270 html += ''' 271 <tr> 272 <td></td> 273 <td> 274 <input name="add-topic" type="submit" value="%(add_topic_label)s" /> 275 </td> 276 </tr>''' % d 277 278 # Advanced options. 279 280 if show_advanced: 281 html += ''' 282 <tr> 283 <td></td> 284 <td> 285 <input name="basic" type="submit" value="%(basic_label)s" /> 286 <input name="advanced" type="hidden" value="true" /> 287 </td> 288 </tr> 289 <tr> 290 <td class="label"><label>%(category_label)s</label></td> 291 <td class="content"> 292 <select multiple="multiple" name="category"> 293 %(category_list)s 294 </select> 295 </td> 296 </tr> 297 <tr> 298 <td class="label"><label>%(template_label)s</label></td> 299 <td> 300 <input name="template" type="text" size="40" value="%(template_default)s" /> 301 </td> 302 </tr> 303 <tr> 304 <td class="label"><label>%(parent_label)s</label></td> 305 <td> 306 <input name="parent" type="text" size="40" value="%(parent_default)s" /> 307 </td> 308 </tr> 309 <tr> 310 <td></td> 311 <td class="buttons"> 312 %(buttons_html)s 313 </td> 314 </tr> 315 </table>''' % d 316 else: 317 html += ''' 318 <tr> 319 <td></td> 320 <td> 321 <input name="advanced" type="submit" value="%(advanced_label)s" /> 322 %(category_list)s 323 <input name="parent" type="hidden" value="%(parent_default)s" /> 324 <input name="template" type="hidden" value="%(template_default)s" /> 325 </td> 326 </tr> 327 <tr> 328 <td></td> 329 <td class="buttons"> 330 %(buttons_html)s 331 </td> 332 </tr> 333 </table>''' % d 334 335 return html 336 337 def do_action(self): 338 339 "Create the new event." 340 341 _ = self._ 342 form = self.request.form 343 344 # If no title exists in the request, an error message is returned. 345 346 title = form.get("title", [None])[0] 347 template = form.get("template", [None])[0] 348 349 if not title: 350 return 0, _("No event title specified.") 351 352 if not template: 353 return 0, _("No page template specified.") 354 355 return self.create_event(self.request) 356 357 def render_success(self, msg, msgtype=None): 358 359 """ 360 Render neither 'msg' nor 'msgtype' since redirection should occur 361 instead. 362 NOTE: msgtype is optional because MoinMoin 1.5.x does not support it. 363 """ 364 365 pass 366 367 def create_event(self, request): 368 369 "Create an event page using the 'request'." 370 371 _ = request.getText 372 form = request.form 373 374 category_pagenames = form.get("category", []) 375 description = form.get("description", [None])[0] 376 location = form.get("location", [None])[0] 377 link = form.get("link", [None])[0] 378 topics = form.get("topics", []) 379 380 start_zone = form.get("start-zone", [None])[0] 381 end_zone = form.get("end-zone", [None])[0] 382 383 # Validate certain fields. 384 385 try: 386 title = form["title"][0] 387 template = form["template"][0] 388 parent = form["parent"][0] 389 except (KeyError, IndexError): 390 return 0, _("Event title or template missing.") 391 392 try: 393 start_day = self._get_input(form, "start-day") 394 start_month = self._get_input(form, "start-month") 395 start_year = self._get_input(form, "start-year") 396 397 if not start_day or not start_month or not start_year: 398 return 0, _("A start date must be specified.") 399 400 end_day = self._get_input(form, "end-day", start_day) 401 end_month = self._get_input(form, "end-month", start_month) 402 end_year = self._get_input(form, "end-year", start_year) 403 404 except (TypeError, ValueError): 405 return 0, _("Days and years must be numbers yielding a valid date!") 406 407 try: 408 start_hour = self._get_input(form, "start-hour") 409 start_minute = self._get_input(form, "start-minute") 410 start_second = self._get_input(form, "start-second") 411 412 end_hour = self._get_input(form, "end-hour") 413 end_minute = self._get_input(form, "end-minute") 414 end_second = self._get_input(form, "end-second") 415 416 except (TypeError, ValueError): 417 return 0, _("Hours, minutes and seconds must be numbers yielding a valid time!") 418 419 start_date = EventAggregatorSupport.DateTime( 420 (start_year, start_month, start_day, start_hour, start_minute, start_second, start_zone) 421 ) 422 start_date.constrain() 423 424 end_date = EventAggregatorSupport.DateTime( 425 (end_year, end_month, end_day, end_hour, end_minute, end_second, end_zone) 426 ) 427 end_date.constrain() 428 429 # An elementary date ordering check. 430 431 if (start_date.as_date() != end_date.as_date() or start_date.has_time() and end_date.has_time()) and start_date > end_date: 432 start_date, end_date = end_date, start_date 433 434 event_details = { 435 "start" : str(start_date), "end" : str(end_date), 436 "title" : title, "summary" : title, 437 "description" : description, "location" : location, "link" : link, 438 "topics" : [topic for topic in topics if topic] 439 } 440 441 # Copy the template. 442 443 template_page = PageEditor(request, template) 444 445 if not template_page.exists(): 446 return 0, _("Event template not available.") 447 448 # Use any parent page information. 449 450 full_title = EventAggregatorSupport.getFullPageName(parent, title) 451 452 # Load the new page and replace the event details in the body. 453 454 new_page = PageEditor(request, full_title) 455 456 if new_page.exists(): 457 return 0, _("The specified page already exists. Please choose another name.") 458 459 # Complete the new page. 460 461 EventAggregatorSupport.fillEventPageFromTemplate(template_page, 462 new_page, event_details, category_pagenames) 463 464 # Redirect and return success. 465 466 query = {'action' : 'edit'} 467 request.http_redirect(new_page.url(request, query)) 468 return 1, None 469 470 # Action function. 471 472 def execute(pagename, request): 473 EventAggregatorNewEvent(pagename, request).render() 474 475 # vim: tabstop=4 expandtab shiftwidth=4