Attachment 'EventCalendar-080.py'

Download

   1 """
   2     EventCalendar.py  Version 0.80  2005. 10. 31.
   3                                                                                                            
   4     This macro gives a list of the events recorded in the sub-pages in the form of monthly view and list view.
   5                                                                                                            
   6     @copyright: 2005 by Seungik Lee <seungiklee<at>gmail.com>  http://cds.icu.ac.kr/~silee/
   7     @license: GPL
   8 
   9     Usage: 
  10         To list the events in a page, just insert [[EventCalendar]]
  11         To insert an event, enclose the information about ONE event with 'eventcal' in the page or its subpages.
  12         
  13             E.g., 
  14                 {{{#!eventcal
  15                     = [Title] =
  16                     [Start Date] ... [End Date]
  17                     [Start Time] ... [End Time]
  18                 }}}
  19             
  20             [Title] should be enclosed with heading marker ('='), double quatation mark ("), wiki italic or bold ('', ''')
  21                 Title can be omitted and it will be titled as 'No Title'
  22                 e.g., == Title ==, === Title ===, "Title", ''Title'', '''Title'''
  23             
  24             [Start|End Date] should be in YYYY/MM/DD or YYYY-MM-DD. End date can be omitted.
  25                 e.g, 2005/10/20, 2005-10-20
  26             
  27             [Start|End Time] should be in HH:MM in 24-hour format. Both of start|end Time can be omitted but not either of them.
  28                 e.g., 08:00, 12:00, 18:00
  29             
  30             In the parsing block of eventcal, it pops out first two date formatted text (startdate and enddate), 
  31             two time formatted text (starttime, endtime), and quoted or heading titie. 
  32             
  33             It ignores further occurrence of the targeted string. 
  34             The order of each fields (date, time, title) does not matter .
  35             The start date|time should precede the end date|time in the occurrence respectively.
  36         
  37         Use 'eventcal.py' to get a parsed format of the event which will be shown at the EventCalendar macro.
  38         To insert an administrative event, just click the [New Event] and input the information. It will be stored in a text file.
  39 
  40         There is no input parameter yet.
  41 
  42     Features:
  43         Monthly, List, Item view of events 
  44         Handles daily and timely events 
  45         Uses text files for storing administrative event data
  46         Uses wiki subpages for storing normal event data 
  47         Add/edit/remove events (in text files only)
  48         Fields included: Title, Start/End Date/Time, Reference Page in wiki 
  49 
  50     Change Log:
  51         Oct. 31, 2005 - Version 0.80 
  52             - The initial version is released.
  53 
  54     To do list:
  55         Clean the ugly codes!!! (need help)
  56             raw html codes
  57         Daily view of events 
  58         Weekly view of events (is it useful?)
  59         Date/time Format customization (e.g., 2005/10, Oct. 2005, 18:00, 06:00pm)
  60         Custom background color per event 
  61         Custom icon per event 
  62         Upcoming event list 
  63         More input parameters
  64         Parsing description field
  65         Using page cache
  66         Update page log at add/edit/remove event in the text data file
  67         Sort events by various options in list view
  68         Load partial events only in the specified date range
  69 
  70     Notes:
  71         'MonthCalendar.py' developed by Thomas Waldmann <ThomasWaldmann@gmx.de> has inspired this macro.
  72         Much buggy.. :please report bugs and suggest your ideas.
  73         If you missed to add css for EventCalender, monthly view may not readable.
  74             Insert the EventCalendar css classes into the common.css of appropriate theme.
  75 
  76 """
  77 
  78 from MoinMoin import wikiutil, config
  79 from MoinMoin.Page import Page
  80 import re, calendar, time, datetime
  81 import codecs, os, urllib
  82 
  83 # The following line sets the calendar to have either Sunday or Monday as
  84 # the first day of the week. Only SUNDAY or MONDAY (case sensitive) are
  85 # valid here.  All other values will not make good calendars.
  86 # XXX change here ----------------vvvvvv
  87 calendar.setfirstweekday(calendar.SUNDAY)
  88 
  89 class Globs:
  90     month_style_us = 1  # 1: October 2005; 2: 2005 / 10
  91     adminmsg=''
  92     datafiledir=''
  93     pagename=''
  94     pagepath = ''
  95     admin=''
  96     baseurl=''
  97     subname=''
  98     cal_delimeter = ''
  99     wkend = ''
 100     months = ''
 101     wkdays = ''
 102     today = ''
 103     lastaction = ''
 104     depth=1 # depth of sub-pages to read
 105     request=''
 106     out_fname=''
 107     inx_fname=''
 108 
 109 def execute(macro, args):
 110     
 111     # INITIALIZATION ----------------------------------------
 112     setglobalvalues(macro)
 113     
 114     # allowed actions to guests
 115     guest_allowed_action = ['calshow', 'evtlist', 'evtview']
 116     guest_default_action = 'calshow'
 117     
 118     # Internal variables
 119     cal_action = ''
 120     form_vals = {}
 121 
 122     # PROCESSING ARGUEMENTS ----------------------------------------
 123     if args:
 124         args=macro.request.getText(args)
 125 
 126     for item in macro.form.items():
 127         if not form_vals.has_key(item[0]):
 128 	    try:
 129 		    form_vals[item[0]]=item[1][0]
 130 	    except AttributeError:
 131 	        pass
 132     
 133     # PROCESSING ACTIONS ----------------------------------------
 134     cal_action = form_vals.get('calaction', guest_default_action)
 135     form_vals['calaction'] = cal_action
 136 
 137     # CONTROL FUNCTIONS ----------------------------------------
 138     
 139     html = []
 140     html_result = ''
 141     
 142     request = macro.request
 143     formatter = macro.formatter
 144     
 145     # check previlege
 146     if (not Globs.admin) and (not cal_action in guest_allowed_action):
 147         message('You have no previlege for this action')
 148         cal_action = guest_default_action
 149     
 150     # redirect to the appropriate view
 151     if cal_action == 'calshow':
 152         html_result = showcalendar(macro, form_vals)
 153         
 154     if cal_action == 'evtlist':
 155         html_result = showeventlist(macro, form_vals)
 156         
 157     if cal_action == 'evtadd':
 158         html_result = addeventform(macro, form_vals)
 159 
 160     if cal_action == 'evtaddnow':
 161         html_result = addevent(macro, form_vals)
 162         
 163     if cal_action == 'evtdel':
 164         html_result = deleteevent(macro, form_vals)
 165     
 166     if cal_action == 'evtedit':
 167         html_result = editevent(macro, form_vals)
 168         
 169     if cal_action == 'evteditnow':
 170         html_result = updateevent(macro, form_vals)
 171         
 172     if cal_action == 'evtview':
 173         html_result = viewevent(macro, form_vals)
 174     
 175     # format output
 176     html.append( showmessage() )
 177     html.append( html_result )
 178     html.append( showmenubar(form_vals) )
 179     
 180     return formatter.rawHTML(u''.join(html))
 181 
 182 
 183 def setglobalvalues(macro):
 184     
 185     request = macro.request
 186     
 187     # Useful variables
 188     Globs.baseurl = macro.request.getBaseURL() + '/'
 189     Globs.pagename = macro.formatter.page.page_name
 190     Globs.request = request
 191     
 192     # This fixes the subpages bug. subname is now used instead of pagename when creating certain urls
 193     Globs.subname = Globs.pagename.split('/')[-1]
 194 
 195     pagepath = macro.formatter.page.getPagePath()
 196     Globs.datafiledir = pagepath + '/eventcalendardata'
 197     Globs.pagepath = macro.formatter.page.getPagePath()
 198     Globs.cal_delimeter = u'\t'
 199     
 200     Globs.inx_fname = os.path.join(Globs.datafiledir, 'eventindex.txt')
 201     Globs.out_fname = os.path.join(Globs.datafiledir, 'events.txt')
 202     
 203     # Figure out if we have delete privs
 204     try:
 205         # If a user can delete the page containing the EventCalendar, then they are considered a EventCalendar administrator
 206         if macro.request.user.may.delete(macro.formatter.page.page_name):
 207             Globs.admin = 'true'
 208     except AttributeError:
 209         pass
 210     
 211     # european / US differences
 212     months = ('January','February','March','April','May','June','July','August','September','October','November','December')
 213     
 214     # Set things up for Monday or Sunday as the first day of the week
 215     if calendar.firstweekday() == calendar.MONDAY:
 216         wkend = 6
 217         wkdays = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
 218     elif calendar.firstweekday() == calendar.SUNDAY:
 219         wkend = 0
 220         wkdays = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
 221     
 222     Globs.months = months
 223     Globs.wkdays = wkdays
 224     Globs.wkend = wkend
 225 
 226     year, month, day, h, m, s, wd, yd, ds = request.user.getTime(time.time())
 227     Globs.today = datetime.date(year, month, day)
 228 
 229 def deleteevent(macro, form_vals):
 230     
 231     Globs.lastaction = 'evtdel'
 232     request = macro.request
 233     
 234     required_fields = {'id': 'Event ID'}
 235     
 236     missing_fields = []
 237     for field in required_fields.keys():
 238         if not form_vals.has_key(field):
 239             missing_fields.append(required_fields[field])
 240 
 241     if missing_fields:
 242         message('Failed to delete the event (insufficient input: %s)' % u','.join(missing_fields) )
 243         return redirectPreviousAction(macro, form_vals)
 244 
 245     eid = form_vals['id']
 246     
 247     return deleteeventnow(macro, form_vals, eid)
 248     
 249 
 250 def editevent(macro, form_vals):
 251     
 252     Globs.lastaction = 'evtedit'
 253     request = macro.request
 254     
 255     required_fields = {'id': 'Event ID'}
 256     
 257     missing_fields = []
 258     for field in required_fields.keys():
 259         if not form_vals.has_key(field):
 260             missing_fields.append(required_fields[field])
 261 
 262     if missing_fields:
 263         message('Failed to edit the event (insufficient input: %s)' % u','.join(missing_fields) )
 264         return redirectPreviousAction(macro, form_vals)
 265 
 266     try:
 267         eid = form_vals['id']
 268         event = getEventById(macro, eid)
 269     except KeyError:
 270         message('Failed to edit the event (no such event, id: %s)' % eid )
 271         return redirectPreviousAction(macro, form_vals)
 272         
 273     return editeventform(macro, form_vals, event)
 274     
 275 # input form to edit events
 276 def editeventform(macro, form_vals, event):
 277     
 278     Globs.lastaction = 'evtedit'
 279     prev_calaction = ''
 280     cal_date = ''
 281     cal_action = ''
 282     
 283     request = macro.request
 284     formatter = macro.formatter
 285     
 286     form_fields = ('id', 'title', 'startdate', 'enddate', 'starttime', 'endtime', 'description', 'refer')
 287     event_form = {}
 288     event_form = event_form.fromkeys(form_fields, '')
 289 
 290     if form_vals.has_key('calaction'):
 291         cal_action = form_vals['calaction']
 292         
 293     if cal_action == 'evteditnow' or (not event):
 294         for field in event_form.keys():
 295             if form_vals.has_key(field):
 296                 event_form[field] = form_vals[field]
 297 
 298     else:
 299         for field in event_form.keys():
 300             if event.has_key(field):
 301                 event_form[field] = event[field]
 302                 
 303     prev_calaction = form_vals.get('prevcalaction', '')
 304     cal_date = form_vals.get('caldate', '')
 305 
 306     html = [
 307         u'<div id="editeventform">',
 308         u'<table id="editeventform" width="90%%">',
 309         u'<form action="%s" name="editeventform" METHOD="POST">' % Globs.subname,
 310 
 311 		u'<tr><td><b>Title</b></td><td><input type="text" size="30" maxlength="100" name="title" value="%s"></td></tr>' % converttext(event_form['title']),
 312 		u'<tr><td><b>Start Date</b></td><td><input type="text" size="8" maxlength="8" name="startdate" value="%s"> (YYYYMMDD)</td></tr>' % event_form['startdate'],
 313 		u'<tr><td>Start Time</td><td><input type="text" size="4" maxlength="4" name="starttime" value="%s"> (HHMM)</td></tr>' % event_form['starttime'],
 314 		u'<tr><td><b>End Date</b></td><td><input type="text" size="8" maxlength="8" name="enddate" value="%s"> (YYYYMMDD)</td></tr>' % event_form['enddate'],
 315 		u'<tr><td>End Time</td><td><input type="text" size="4" maxlength="4" name="endtime" value="%s"> (HHMM)</td></tr>' % event_form['endtime'],
 316 		
 317 		u'<tr><td>Description</td><td><input type="text" size="50" maxlength="255" name="description" value="%s"></td></tr>' % converttext(event_form['description']),
 318 		#u'<tr><td>Reference</td><td><input type="text" size="50" maxlength="255" name="refer" value="%s"> (ReferPageName)</td></tr>' % converttext(event_form['refer']),
 319 		
 320 		u'<tr><td colspan="2" align="right"><input type="submit" value="POST" class="postbutton"></td></tr>',
 321 		u'<input type="hidden" value="%s" name="id">' % event_form['id'],
 322 		u'<input type="hidden" value="evteditnow" name="calaction">',
 323 		u'<input type="hidden" value="%s" name="prevcalaction">' % prev_calaction,
 324 		u'<input type="hidden" value="%s" name="caldate">' % cal_date,
 325 		u'</form>',
 326 		u'</table>',
 327 		u'</div>',
 328         ]
 329     
 330     return u'\r\n'.join(html)
 331 
 332 
 333 def viewevent(macro, form_vals):
 334     
 335     Globs.lastaction = 'evtview'
 336     
 337     request = macro.request
 338 
 339     required_fields = {'id': 'Event ID'}
 340     
 341     missing_fields = []
 342     for field in required_fields.keys():
 343         if not form_vals.has_key(field):
 344             missing_fields.append(required_fields[field])
 345 
 346     if missing_fields:
 347         message('Failed to view the event (insufficient input: %s)' % u','.join(missing_fields) )
 348         return redirectPreviousAction(macro, form_vals)
 349 
 350     try:
 351         eid = form_vals['id']
 352         event = getEventById(macro, eid)
 353     except KeyError:
 354         message('Failed to view the event (no such event, id: %s)' % eid )
 355         return redirectPreviousAction(macro, form_vals)
 356     
 357     return showeventdetail(event, form_vals)
 358     
 359 
 360 def showeventdetail(event, form_vals):
 361     Globs.lastaction = 'evtview'
 362     
 363     html = [
 364         u'<div id="viewevent">',
 365         u'<table id="viewevent" width="90%%">',
 366         u'<tr><td width="20%%">Title</td><td>%s</td></tr>' % converttext(event['title']),
 367 		u'<tr><td>Start Date</td><td>%s</td></tr>' % event['startdate'],
 368 		u'<tr><td>Start Time</td><td>%s</td></tr>' % event['starttime'],
 369 		u'<tr><td>End Date</td><td>%s</td></tr>' % event['enddate'],
 370 		u'<tr><td>End Time</td><td>%s</td></tr>' % event['endtime'],
 371 		u'<tr><td>Description</td><td>%s</td></tr>' % converttext(event['description']),
 372 		u'<tr><td>Reference</td><td>%s</td></tr>' % showReferPageParsed(event),
 373 		u'</table>',
 374 		u'</div>',
 375         ]
 376     
 377     return u'\r\n'.join(html)
 378 
 379 
 380 def showReferPageParsed(event):
 381     request = Globs.request
 382     pagename = Globs.pagename
 383     
 384     refer = event['refer']
 385     title = event['title']
 386     startdate = event['startdate']
 387     
 388     bookmark = u'%s%s' % (title.replace(' ', ''), startdate)
 389     bookmark = urllib.quote_plus(bookmark.encode(config.charset))
 390     targetlink = Page(request, refer).link_to(request, text=refer, querystr='action=show', anchor=bookmark)
 391     
 392     return targetlink
 393 
 394 
 395 def redirectPreviousAction(macro, form_vals):
 396 
 397     prev_calaction = form_vals.get('prevcalaction', 'calshow')
 398 
 399     if prev_calaction == 'evtlist':
 400         return showeventlist(macro, form_vals)
 401     else:
 402         return showcalendar(macro, form_vals)
 403 
 404 
 405 def getquerystring(form_vals, req_fields):
 406     
 407     m_query = []
 408     tmp_form_vals = form_vals
 409     
 410     # format querystring
 411     # action should be poped out
 412     for field in req_fields:
 413         if tmp_form_vals.has_key(field):
 414             m_query.append(u'%s=%s' % (field, tmp_form_vals[field]) )
 415     
 416     if 'prevcalaction' in req_fields:
 417         if not tmp_form_vals.has_key('prevcalaction'):
 418             m_query.append(u'%s=%s' % ('prevcalaction', tmp_form_vals['calaction']) )
 419             
 420     m_query = u'&'.join(m_query)
 421     return m_query
 422 
 423 # bottom menu bar
 424 def showmenubar(form_vals):
 425     
 426     lastaction = Globs.lastaction
 427     
 428     left_menu_selected = []
 429     right_menu_selected = []
 430     
 431     # New Event
 432     mnu_newevent = u'<a href="?calaction=evtadd&%s">[New Event]</a>' % getquerystring(form_vals, ['prevcalaction', 'caldate'])
 433     
 434     # Go Today
 435     year, month, day = gettodaydate()
 436     mnu_curmonthcal = u'<a href="?calaction=calshow&caldate=%d%02d">[Go Today]</a>' % (year, month)
 437     
 438     # View Event
 439     mnu_viewevent = u'<a href="?calaction=evtview&%s">[View Event]</a>' % getquerystring(form_vals, ['prevcalaction', 'caldate', 'id'])
 440     
 441     # Edit Event
 442     mnu_editevent = u'<a href="?calaction=evtedit&%s">[Edit Event]</a>' % getquerystring(form_vals, ['prevcalaction', 'caldate', 'id'])
 443     
 444     # Delete Event
 445     mnu_deleteevent = u'<a href="?calaction=evtdel&%s" onClick="return confirm(\'Are you sure to delete?\');">[Delete Event]</a>' % getquerystring(form_vals, ['prevcalaction', 'caldate', 'id'])
 446     
 447     # List View
 448     mnu_listview = u'<a href="?calaction=evtlist">[List View]</a>'
 449     
 450     # Monthly View
 451     mnu_monthview = u'<a href="?calaction=calshow&%s">[Monthly View]</a>' % getquerystring(form_vals, ['caldate'])
 452     
 453     html = [
 454         u'\r\n',
 455         u'<table class="eventcalendar_menubar" width="90%%" align="center">',
 456         u'  <tr>',
 457         u'  <td class="eventcalendar_menubar" align="left">%s</td>',
 458         u'  <td class="eventcalendar_menubar" align="right">%s</td>',
 459         u'  </tr>',
 460         u'</table>',
 461         ]
 462         
 463     if lastaction == 'evtview':
 464         if form_vals.has_key('id') and form_vals['id'].startswith('w'):
 465             left_menu_selected.append(mnu_monthview)
 466             left_menu_selected.append(mnu_listview)
 467             left_menu_selected.append(mnu_curmonthcal)
 468                    
 469             right_menu_selected.append(mnu_newevent)
 470         else:
 471             left_menu_selected.append(mnu_monthview)
 472             left_menu_selected.append(mnu_listview)
 473             left_menu_selected.append(mnu_curmonthcal)
 474                    
 475             if Globs.admin:
 476                 right_menu_selected.append(mnu_editevent)
 477                 right_menu_selected.append(mnu_deleteevent)
 478             
 479             if Globs.admin:
 480                 right_menu_selected.append(mnu_newevent)
 481 
 482     elif lastaction == 'evtedit':
 483         left_menu_selected.append(mnu_monthview)
 484         left_menu_selected.append(mnu_listview)
 485         left_menu_selected.append(mnu_curmonthcal)
 486                
 487         right_menu_selected.append(mnu_viewevent)
 488         
 489         if Globs.admin:
 490             right_menu_selected.append(mnu_deleteevent)
 491             right_menu_selected.append(mnu_newevent)
 492         
 493     elif lastaction == 'evtlist':
 494         left_menu_selected.append(mnu_monthview)
 495         left_menu_selected.append(mnu_curmonthcal)
 496                
 497         if Globs.admin:
 498             right_menu_selected.append(mnu_newevent)
 499         
 500     elif lastaction == 'evtadd':
 501         left_menu_selected.append(mnu_monthview)
 502         left_menu_selected.append(mnu_listview)
 503         left_menu_selected.append(mnu_curmonthcal)
 504 
 505     else:
 506         left_menu_selected.append(mnu_listview)
 507         left_menu_selected.append(mnu_curmonthcal)
 508         
 509         if Globs.admin:       
 510             right_menu_selected.append(mnu_newevent)
 511 
 512     left_menu_selected = u'\r\n'.join(left_menu_selected)
 513     right_menu_selected = u'\r\n'.join(right_menu_selected)
 514     
 515     html = u'\r\n'.join(html)
 516     html = html % (left_menu_selected, right_menu_selected)
 517 
 518     return html
 519         
 520 
 521 def getdatefield(str_date):
 522     str_year = ''
 523     str_month = ''
 524     str_day = ''
 525     
 526     if len(str_date) == 6:
 527         # year+month
 528         str_year = str_date[:4]
 529         str_month = str_date[4:]
 530         str_day = '1'
 531 
 532     elif len(str_date) == 8:
 533         # year+month+day
 534         str_year = str_date[:4]
 535         str_month = str_date[4:6]
 536         str_day = str_date[6:]
 537     
 538     elif len(str_date) == 10:
 539         # year+?+month+?+day
 540         str_year = str_date[:4]
 541         str_month = str_date[5:7]
 542         str_day = str_date[8:]
 543     
 544     else:
 545         raise ValueError
 546     
 547     # It raises exception if the input date is incorrect
 548     temp = datetime.date(int(str_year), int(str_month), int(str_day))
 549 
 550     return temp.year, temp.month, temp.day
 551 
 552 
 553 def gettimefield(str_time):
 554     str_hour = ''
 555     str_min = ''
 556     
 557     if len(str_time) == 4:
 558         # hour+minute
 559         str_hour = str_time[:2]
 560         str_min = str_time[2:]
 561     
 562     elif len(str_time) == 5:
 563         # hour+?+minute
 564         str_hour = str_time[:2]
 565         str_min = str_time[3:]
 566         
 567     else:
 568         raise ValueError
 569     
 570     # It raises exception if the input date is incorrect
 571     temp = datetime.time(int(str_hour), int(str_min))
 572 
 573     return temp.hour, temp.minute
 574 
 575 def showmessage():
 576     if Globs.adminmsg:
 577         return u'<table class="eventcalendar_msg" align="center"><tr><td class="eventcalendar_msg">%s</td></tr></table>' % Globs.adminmsg
 578     else:
 579         return ''
 580 
 581 def gettodaydate():
 582     today = Globs.today
 583     return today.year, today.month, today.day    
 584 
 585 
 586 def cal_listhead():
 587 
 588     html = [
 589         u'  <tr>',
 590         u'      <td class="list_head">Title</td>',
 591         u'      <td class="list_head">Start Date</td>',
 592         u'      <td class="list_head">Start Time</td>',
 593         u'      <td class="list_head">End Date</td>',
 594         u'      <td class="list_head">End Time</td>',
 595         u'      <td class="list_head">Description</td>',
 596         u'      <td class="list_head">Reference</td>',
 597         u'      <td class="list_head">Action</td>',
 598         u'  </tr>',
 599         ]
 600         
 601     return u'\r\n'.join(html)
 602 
 603 
 604 def showeventlist(macro, form_vals):
 605     Globs.lastaction = 'evtlist'
 606     
 607     request = macro.request
 608     formatter = macro.formatter
 609     
 610     html_event_rows = []
 611     html_list_header = cal_listhead()
 612     
 613     # read all the events from data file
 614     events, cal_events = loadEvents(macro, 1)
 615     
 616     # sort events
 617     sorted_eventids = events.keys()
 618     sorted_eventids.sort(cmp=lambda x,y: cmp(events[x]['startdate'], events[y]['startdate']))
 619     
 620     for eid in sorted_eventids:
 621         html_event_rows.append( listshow_event(events[eid], form_vals) )
 622     
 623     html_event_rows = u'\r\n'.join(html_event_rows)
 624     
 625     html_list_table = [
 626         u'\r\n<div id="eventlist">',
 627         u'<table width="90%%" align="center">',
 628         u'%s' % html_list_header,
 629         u'%s' % html_event_rows,
 630         u'</table>',
 631         u'</div>',
 632         ]
 633     html_list_table = u'\r\n'.join(html_list_table)
 634         
 635     return html_list_table
 636         
 637 
 638 def listshow_event(event, form_vals):
 639     
 640     if event['id'][0] != 'w':
 641         html_editlink = u'  <a href="?calaction=evtedit&id=%s&prevcalaction=evtlist">[Edit]</a>' % event['id']
 642         html_dellink = u'  <a href="?calaction=evtdel&id=%s&prevcalaction=evtlist" onClick="return confirm(\'Are you sure to delete?\');">[Delete]</a>' % event['id']
 643     else:
 644         html_editlink = ''
 645         html_dellink = ''
 646         
 647     syear, smonth, sday = getdatefield(event['startdate'])
 648     eyear, emonth, eday = getdatefield(event['enddate'])
 649     
 650     time_info = 1
 651     try:
 652         shour, smin = gettimefield(event['starttime'])
 653         ehour, emin = gettimefield(event['endtime'])
 654     except ValueError:
 655         time_info = 0
 656     
 657     if time_info:
 658         html = [
 659             u'  <tr>',
 660             u'  <td class="list_entry">%s</td>' % converttext(event['title']),
 661             u'  <td class="list_entry">%d %02d/%02d</td>' % (syear, smonth, sday),
 662             u'  <td class="list_entry">%02d:%02d</td>' % (shour, smin),
 663             u'  <td class="list_entry">%d %02d/%02d</td>' % (eyear, emonth, eday),
 664             u'  <td class="list_entry">%02d:%02d</td>' % (ehour, emin),
 665             u'  <td class="list_entry">%s</td>' % converttext(event['description']),
 666             u'  <td class="list_entry">%s</td>' % showReferPageParsed(event),
 667             u'  <td class="list_entry">%s%s</td>' % (html_editlink, html_dellink),
 668             u'  </tr>',
 669             ]
 670     
 671     else:
 672         html = [
 673             u'  <tr>',
 674             u'  <td class="list_entry">%s</td>' % converttext(event['title']),
 675             u'  <td class="list_entry">%d %02d/%02d</td>' % (syear, smonth, sday),
 676             u'  <td class="list_entry">&nbsp;</td>',
 677             u'  <td class="list_entry">%d %02d/%02d</td>' % (eyear, emonth, eday),
 678             u'  <td class="list_entry">&nbsp;</td>',
 679             u'  <td class="list_entry">%s</td>' % converttext(event['description']),
 680             u'  <td class="list_entry">%s</td>' % showReferPageParsed(event),
 681             u'  <td class="list_entry">%s%s</td>' % (html_editlink, html_dellink),
 682             u'  </tr>',
 683             ]
 684         
 685     return u'\r\n'.join(html)
 686 
 687 def showcalendar(macro, form_vals):
 688     Globs.lastaction = 'calshow'
 689     
 690     request = macro.request
 691     formatter = macro.formatter
 692     
 693     if form_vals.has_key('caldate'):
 694         try:
 695             year, month, str_temp = getdatefield(form_vals['caldate'])
 696         except ValueError:
 697             message('Invalid target date: e.g., "200510"')
 698             year, month, dy = gettodaydate()
 699     else:
 700         year, month, dy = gettodaydate()
 701     
 702     html = showeventcalendar(macro, year, month)
 703     
 704     return u''.join(html)
 705 
 706 def getEventById(macro, e_id):
 707 
 708     events, cal_events = loadEvents(macro, 1)
 709         
 710     return events[e_id]
 711 
 712 # load events from text files and wiki pages
 713 def loadEvents(macro, readsubpages=1):
 714     
 715     events, cal_events = loadEventsFromTextFile(macro)
 716     
 717     if readsubpages:
 718         # reads events from child pages----------------------
 719         events, cal_events = loadEventsFromWikiPage(macro, events, cal_events)
 720     
 721     Globs.events = events
 722     Globs.cal_events = cal_events
 723     
 724     return events, cal_events
 725 
 726 # sort cal_events by length of days
 727 def comp_cal_events(xid, yid):
 728     events = Globs.events
 729     
 730     if events[xid]['date_len'] > events[yid]['date_len']:
 731         return -1
 732     elif events[xid]['date_len'] == events[yid]['date_len']:
 733         if events[xid]['date_len'] == 1:
 734             return cmp(events[xid]['starttime'], events[yid]['starttime'])
 735         else:
 736             return 0
 737     else:
 738         return 1
 739         
 740 # load events from text files
 741 def loadEventsFromTextFile(macro):
 742 
 743     # delimeter
 744     cal_delimeter = Globs.cal_delimeter
 745     
 746     # event information
 747     events = {}
 748     
 749     # event information per date
 750     cal_events = {}
 751     
 752     if not os.path.isfile(Globs.out_fname):
 753         # message('Failed to load event data file (no event or data file is removed)')
 754         return events, cal_events
 755 
 756     try:
 757         event_file = codecs.open(Globs.out_fname,'r', encoding='utf-8')
 758     except IOError:
 759         message('Failed to load event data file (unable to read data file)')
 760         return events, cal_events
 761     
 762     while 1:
 763         in_line = event_file.readline()
 764                 
 765         if not in_line:
 766             break
 767         
 768         if in_line == '\r\n':
 769             continue
 770         
 771         try:
 772             [e_id, e_start_date, e_start_time, e_end_date, e_end_time, e_title, e_description, e_ref] = in_line.split(cal_delimeter)
 773         except ValueError:
 774             message('Failed to parse the events (the data file may be corrupt)')
 775             return events, cal_events
 776         
 777         try:
 778             e_start_year, e_start_month, e_start_day = getdatefield(e_start_date)
 779             e_end_year, e_end_month, e_end_day = getdatefield(e_end_date)
 780         except ValueError:
 781             message('An event data is corrupted: invalid date format')
 782 
 783         if e_start_time and e_end_time:
 784 	        try:
 785 	            e_start_time_hour, e_start_time_min = gettimefield(e_start_time)
 786 	            e_end_time_min, e_end_time_min = gettimefield(e_end_time)
 787 	        except ValueError:
 788 	            message('An event data is corrupted: invalid time format')
 789         
 790         # store event information
 791         events[e_id] = {}
 792         events[e_id]['id'] = e_id
 793         events[e_id]['startdate'] = e_start_date
 794         events[e_id]['starttime'] = e_start_time
 795         events[e_id]['enddate'] = e_end_date
 796         events[e_id]['endtime'] = e_end_time
 797         events[e_id]['title'] = e_title
 798         events[e_id]['description'] = e_description
 799         events[e_id]['refer'] = e_ref
 800         events[e_id]['date_len'] = diffday(e_start_date, e_end_date) + 1
 801 
 802         # records event information for each date b/w start and end
 803         tmp_record_date = e_start_date
 804         cur_datetime = datetime.date(e_start_year, e_start_month, e_start_day)
 805         offset = 1
 806         
 807         while 1:
 808             if not cal_events.has_key(tmp_record_date):
 809                 cal_events[tmp_record_date] = []
 810             cal_events[tmp_record_date].append(e_id)
 811             
 812             if tmp_record_date == e_end_date:
 813                 break
 814             
 815             day_delta = datetime.timedelta(days=offset)
 816             tmp_datetime = cur_datetime + day_delta
 817             
 818             tmp_record_date = formatDate(tmp_datetime.year, tmp_datetime.month, tmp_datetime.day)
 819             offset += 1
 820     
 821     event_file.close()
 822 
 823     return events, cal_events
 824 
 825 def loadEventsFromWikiPage(macro, events, cal_events):
 826 
 827     request = macro.request
 828     depth = Globs.depth
 829     parent = Globs.pagename
 830     
 831     # reads events from child pages
 832     children = getPages(request, '^%s/' % parent)
 833     
 834     # append the page itself
 835     children.append(parent)
 836     
 837     id = 0
 838     for child in children:
 839         shortname = child[len(parent):]
 840         # possibly limit depth
 841         if depth and shortname.count('/') > depth:
 842             continue
 843         
 844         p = Page(request, child)
 845         page_content = p.get_raw_body()
 846         
 847         for lines in getEventListFromPage(page_content):
 848             try:
 849                 e_start_date, e_start_time, e_end_date, e_end_time, e_title, e_description = geteventfield(lines)
 850             except ValueError:
 851                 # message('An event data is corrupted: invalid event format')
 852                 continue
 853             
 854             try:
 855                 e_start_year, e_start_month, e_start_day = getdatefield(e_start_date)
 856                 e_end_year, e_end_month, e_end_day = getdatefield(e_end_date)
 857             except ValueError:
 858                 # message('An event data is corrupted: invalid date format')
 859                 continue
 860             
 861             if e_start_time and e_end_time:
 862                 try:
 863                     e_start_time_hour, e_start_time_min = gettimefield(e_start_time)
 864                     e_end_time_min, e_end_time_min = gettimefield(e_end_time)
 865                 except ValueError:
 866                     # message('An event data is corrupted: invalid time format')
 867                     continue
 868             
 869             e_ref = p.page_name
 870             
 871             if not e_start_date:
 872                 # message('An event data is corrupted: invalid time format')
 873                 continue
 874             
 875             id += 1
 876             e_id = u'w%d' % id
 877             
 878             # store event information
 879             events[e_id] = {}
 880             events[e_id]['id'] = e_id
 881             events[e_id]['startdate'] = e_start_date
 882             events[e_id]['starttime'] = e_start_time
 883             events[e_id]['enddate'] = e_end_date
 884             events[e_id]['endtime'] = e_end_time
 885             events[e_id]['title'] = e_title
 886             events[e_id]['description'] = e_description
 887             events[e_id]['refer'] = e_ref
 888             events[e_id]['date_len'] = diffday(e_start_date, e_end_date) + 1
 889             
 890             # message('event %s: %s' % (e_id, events[e_id]))
 891             
 892             # records event information for each date b/w start and end
 893             tmp_record_date = e_start_date
 894             cur_datetime = datetime.date(e_start_year, e_start_month, e_start_day)
 895             offset = 1
 896             
 897             while 1:
 898                 if not cal_events.has_key(tmp_record_date):
 899                     cal_events[tmp_record_date] = []
 900                 cal_events[tmp_record_date].append(e_id)
 901                 
 902                 if tmp_record_date == e_end_date:
 903                     break
 904                 
 905                 day_delta = datetime.timedelta(days=offset)
 906                 tmp_datetime = cur_datetime + day_delta
 907                 
 908                 tmp_record_date = formatDate(tmp_datetime.year, tmp_datetime.month, tmp_datetime.day)
 909                 offset += 1
 910     
 911     return events, cal_events
 912 
 913 
 914 def getEventListFromPage(lines):
 915     regex_eventcal = r'[\{]{3}#!eventcal(\s*.*?[^}]+)[\}]{3}'
 916     
 917     pattern = re.compile(regex_eventcal, re.UNICODE + re.MULTILINE)
 918     match = pattern.findall(lines)
 919     return match
 920 
 921 def geteventfield(lines):
 922     # need help on regular expressions for more efficient/flexible form
 923     regex_date = r'(\d{4}[/-]\d{2}[/-]\d{2})'
 924     regex_time = r'(\d{2}[:]\d{2})'
 925     # regex_title = r'["\'=-]+(\s*.*[^"\'=-]+)["\'=-]+'
 926     regex_title = r'["]+(\s*.*?)["]+|[\']{2,}(\s*.*?)[\']{2,}|[=]+(\s*.*?)[=]+' 
 927     
 928     # retrieve date
 929     pattern = re.compile(regex_date, re.UNICODE + re.MULTILINE)
 930     
 931     match = pattern.findall(lines)
 932     
 933     if not len(match):
 934         # message('at least one date field should be specified')
 935         # self.printoutput('Parse Error', msg, '')
 936         # ERROR
 937         return '','','','','',''
 938     
 939     # month, day only should be handled
 940     
 941     startdate = match[0]
 942     if len(match) > 1:
 943         enddate = match[1]
 944     else:
 945         enddate = ''
 946     
 947     # retrieve time
 948     pattern = re.compile(regex_time, re.UNICODE + re.MULTILINE)
 949     
 950     match = pattern.findall(lines)
 951     
 952     if len(match) >= 2:
 953         starttime = match[0]
 954         endtime = match[1]
 955     elif len(match) == 0:
 956         starttime = ''
 957         endtime = ''
 958     else:
 959         # message('no or 2 time field should be specified')
 960         # ERROR
 961         return '','','','','',''
 962         
 963     # retrieve title
 964     pattern = re.compile(regex_title, re.UNICODE + re.MULTILINE + re.DOTALL)
 965     
 966     match = pattern.search(lines)
 967     
 968     if not match:
 969         title = 'No title'
 970     else:
 971         for item in match.groups():
 972             if item:
 973                 title = item
 974                 break
 975     
 976     # if no time, it's 1-day event
 977     if not enddate:
 978         enddate = startdate
 979     
 980     # check the validity of date/time
 981     try:
 982         syear, smonth, sday = getdatefield(startdate)
 983         eyear, emonth, eday = getdatefield(enddate)
 984     except ValueError:
 985         # message('invalid date format: %s, %s' % (startdate, enddate))
 986         return '','','','','',''
 987     
 988     if startdate and enddate:
 989         if datetime.date(syear, smonth, sday) > datetime.date(eyear, emonth, eday):
 990             # message('startdate should precede enddate')
 991             return '','','','','',''
 992     
 993     # format date
 994     startdate = u'%4d%02d%02d' %(syear, smonth, sday)
 995     enddate = u'%4d%02d%02d' %(eyear, emonth, eday)
 996     
 997     if (starttime and endtime):
 998         try:
 999             shour, smin = gettimefield(starttime)
1000             ehour, emin = gettimefield(endtime)
1001         except ValueError:
1002             # message('invalid time format: %s, %s' % (startdate, enddate))
1003             return '','','','','',''
1004         
1005         if startdate == enddate:
1006             if datetime.time(shour, smin) > datetime.time(ehour, emin):
1007                 # message('starttime should precede endtime')
1008                 return '','','','','',''
1009                 
1010         # format time
1011         starttime = u'%02d%02d' %(shour, smin)
1012         endtime = u'%02d%02d' %(ehour, emin)
1013     
1014     return startdate, starttime, enddate, endtime, title, ''
1015 
1016 
1017 def addevent(macro, form_vals):
1018     Globs.lastaction = 'evtadd'
1019     
1020     request = macro.request
1021     formatter = macro.formatter
1022         
1023     form_fields = ('title', 'startdate', 'starttime', 'enddate', 'endtime', 'description', 'refer')
1024     required_fields = {'title': 'Title', 'startdate': 'Start Date', 'enddate': 'End Date'}
1025     
1026     event_form = {}
1027     event_form = event_form.fromkeys(form_fields, '')
1028     
1029     for field in event_form.keys():
1030         if form_vals.has_key(field):
1031             event_form[field] = form_vals[field]
1032             
1033     missing_fields = []
1034     for field in required_fields.keys():
1035         if not event_form[field]:
1036             missing_fields.append(required_fields[field])
1037             
1038     if missing_fields:
1039         message('Failed to add the event (insufficient input: %s)' % u','.join(missing_fields) )
1040         return addeventform(macro, form_vals)
1041         
1042     if (event_form['starttime'] and (not event_form['endtime'])) or (not event_form['starttime'] and event_form['endtime']):
1043         message('Failed to add the event (insufficient input: start/end time)' )
1044         return addeventform(macro, form_vals)
1045     
1046     else:
1047         if (event_form['starttime'] and event_form['endtime']):
1048 	        try:
1049 	            hour, min = gettimefield( event_form['starttime'] )
1050 	            hour, min = gettimefield( event_form['endtime'] )
1051 	        except ValueError:
1052 	            message('Failed to add the event (invalid time format)' )
1053 	            return addeventform(macro, form_vals)
1054     
1055     try:
1056         year, month, day = getdatefield( event_form['startdate'] )
1057         year, month, day = getdatefield( event_form['enddate'] )
1058     
1059     except ValueError:
1060         message('Failed to add the event (invalid date format)' )
1061         return addeventform(macro, form_vals)
1062     
1063     return addeventnow(macro, event_form, form_vals)
1064 
1065 
1066 def updateevent(macro, form_vals):
1067     Globs.lastaction = 'evtedit'
1068     
1069     request = macro.request
1070     formatter = macro.formatter
1071     
1072     form_fields = ('id', 'title', 'startdate', 'starttime', 'enddate', 'endtime', 'description', 'refer')
1073     required_fields = {'id': 'Event ID', 'title': 'Title', 'startdate': 'Start Date', 'enddate': 'End Date'}
1074     
1075     event_form = {}
1076     event_form = event_form.fromkeys(form_fields, '')
1077     
1078     for field in event_form.keys():
1079         if form_vals.has_key(field):
1080             event_form[field] = form_vals[field]
1081             
1082     missing_fields = []
1083     for field in required_fields.keys():
1084         if not event_form[field]:
1085             missing_fields.append(required_fields[field])
1086             
1087     if missing_fields:
1088         message('Failed to update the event (insufficient input: %s)' % u','.join(missing_fields) )
1089         return editeventform(macro, form_vals, event_form)
1090         
1091     if (event_form['starttime'] and (not event_form['endtime'])) or (not event_form['starttime'] and event_form['endtime']):
1092         message('Failed to update the event (insufficient input: start/end time)' )
1093         return addeventform(macro, form_vals)
1094 
1095     else:
1096         if event_form['starttime'] and event_form['endtime']:
1097             try:
1098                 hour, min = gettimefield( event_form['starttime'] )
1099                 hour, min = gettimefield( event_form['endtime'] )
1100             except ValueError:
1101                 message('Failed to update the event (invalid time format)' )
1102                 return editeventform(macro, form_vals, event_form)
1103     try:
1104         year, month, day = getdatefield( event_form['startdate'] )
1105         year, month, day = getdatefield( event_form['enddate'] )
1106     
1107     except ValueError:
1108         message('Failed to update the event (invalid date format)' )
1109         return editeventform(macro, form_vals, event_form)
1110     
1111     try:
1112         tempid = int(event_form['id']) + 1
1113     except ValueError:
1114         message('Failed to update the event (invalid id format)' )
1115         return editeventform(macro, form_vals, event_form)
1116     
1117     return updateeventnow(macro, event_form, form_vals)
1118 
1119 # input form to add events
1120 def addeventform(macro, form_vals):
1121     Globs.lastaction = 'evtadd'
1122     prev_calaction = ''
1123     cal_date = ''
1124     
1125     request = macro.request
1126     formatter = macro.formatter
1127     
1128     form_fields = ('title', 'startdate', 'enddate', 'starttime', 'endtime', 'description', 'refer')
1129     event_form = {}
1130     event_form = event_form.fromkeys(form_fields, '')
1131     
1132     for field in event_form.keys():
1133         if form_vals.has_key(field):
1134             event_form[field] = form_vals[field]
1135     
1136     if form_vals.has_key('prevcalaction'):
1137         prev_calaction = form_vals['prevcalaction']
1138     
1139     if form_vals.has_key('caldate'):
1140         cal_date = form_vals['caldate']
1141     
1142     year, month, day = gettodaydate()
1143     syear = 0
1144 
1145     if cal_date:
1146         try:
1147             syear, smonth, sday = getdatefield(cal_date)
1148         except  ValueError:
1149             message('Invalid target date: e.g., "200510"')
1150         
1151         if syear == year and smonth == month:
1152             sday = day
1153 
1154     if not event_form['startdate']:
1155         if syear:
1156             event_form['startdate'] = u'%d%02d%02d' % (syear, smonth, sday)
1157         else:
1158             event_form['startdate'] = u'%d%02d%02d' % (year, month, day)
1159 
1160     if not event_form['enddate']:
1161         if syear:
1162             event_form['enddate'] = u'%d%02d%02d' % (syear, smonth, sday)
1163         else:
1164             event_form['enddate'] = u'%d%02d%02d' % (year, month, day)
1165     
1166     if not event_form['starttime']:
1167         event_form['starttime'] = u'0900'
1168         
1169     if not event_form['endtime']:
1170         event_form['endtime'] = u'1800'
1171     
1172     html = [
1173         u'<div id=addeventform>',
1174         u'<table id=addeventform width=90%%>',
1175         u'<form action="%s" name=a"ddeventform" METHOD=POST>' % Globs.subname,
1176 
1177 		u'<tr><td><b>Title</b></td><td><input type="text" size="30" maxlength="100" name="title" value="%s"></td></tr>' % event_form['title'],
1178 		u'<tr><td><b>Start Date</b></td><td><input type="text" size="8" maxlength="8" name="startdate" value="%s"> (YYYYMMDD)</td></tr>' % event_form['startdate'],
1179 		u'<tr><td>Start Time</td><td><input type="text" size="4" maxlength="4" name="starttime" value="%s"> (HHMM)</td></tr>' % event_form['starttime'],
1180 		u'<tr><td><b>End Date</b></td><td><input type="text" size="8" maxlength="8" name="enddate" value="%s"> (YYYYMMDD)</td></tr>' % event_form['enddate'],
1181 		u'<tr><td>End Time</td><td><input type="text" size="4" maxlength="4" name="endtime" value="%s"> (HHMM)</td></tr>' % event_form['endtime'],
1182 		
1183 		u'<tr><td>Description</td><td><input type="text" size="50" maxlength="255" name="description" value="%s"></td></tr>' % event_form['description'],
1184 		#u'<tr><td>Reference</td><td><input type="text" size="50" maxlength="255" name="refer" value="%s"> (ReferPageName)</td></tr>' % event_form['refer'],
1185 		
1186 		u'<tr><td colspan="2" align="right"><input type="submit" value="POST" class="postbutton"></td></tr>',
1187 		u'<input type="hidden" value="evtaddnow" name="calaction">',
1188 		u'<input type="hidden" value="%s" name="prevcalaction">' % prev_calaction,
1189 		u'<input type="hidden" value="%s" name="caldate">' % cal_date,
1190 		u'</form>',
1191 		u'</table>',
1192 		u'</div>',
1193         ]
1194 
1195     
1196     return u'\r\n'.join(html)
1197 
1198 def addeventnow(macro, event_form, form_vals):
1199     Globs.lastaction = 'evtadd'
1200     
1201     # Add an event with inputs
1202     
1203     request = macro.request
1204     formatter = macro.formatter
1205     
1206     cal_delimeter = Globs.cal_delimeter
1207     
1208     try:
1209         # If the data file exists
1210         inx_file = codecs.open(Globs.inx_fname,'r+',encoding='utf-8')
1211     except IOError:
1212         try:
1213             # If the directory does not exist
1214             if not os.path.isdir(Globs.datafiledir):
1215                 # Create a attachments directory first
1216                 # Is conflict with moinmoin?
1217                 os.mkdir(Globs.datafiledir)
1218             
1219             inx_file = codecs.open(Globs.inx_fname,'w',encoding='utf-8')
1220 
1221         except IOError:
1222             message('Failed to add the event (unable to create an index file)')
1223             return addeventform(macro, form_vals)
1224     
1225     try:
1226         cur_index = inx_file.readline()
1227         cur_index = int(cur_index)
1228     except ValueError:
1229         cur_index = 0
1230 
1231     cur_index = cur_index + 1
1232     cur_index = str(cur_index)
1233     
1234     try:
1235         out_file = codecs.open(Globs.out_fname,'a+',encoding='utf-8')
1236     except IOError:
1237         message('Failed to add the event (unable to create a data file)')
1238         return addeventform(macro, form_vals)
1239     
1240     eventitem = [
1241         cur_index,
1242         cal_delimeter,
1243         event_form['startdate'],
1244         cal_delimeter,
1245         event_form['starttime'],
1246         cal_delimeter,
1247         event_form['enddate'], 
1248         cal_delimeter,
1249         event_form['endtime'],
1250         cal_delimeter,
1251         convertdelimiter(event_form['title']),
1252         cal_delimeter,
1253         convertdelimiter(event_form['description']),
1254         cal_delimeter,
1255         convertdelimiter(event_form['refer']),
1256         ]
1257     
1258     eventitem = u''.join(eventitem)
1259     
1260     out_file.write(eventitem + u'\r\n')
1261     out_file.close()
1262     
1263     inx_file.seek(0)
1264     inx_file.write(cur_index)
1265     inx_file.close()
1266     
1267     # add log entry
1268     # addLogEntry(macro.request, 'EVTNEW', Globs.pagename, 'titled \'%s\'' % event_form['title'])
1269     
1270     message('The event is added')
1271     return redirectPreviousAction(macro, form_vals)
1272 
1273 
1274 def updateeventnow(macro, event_form, form_vals):
1275     Globs.lastaction = 'evtedit'
1276     
1277     # Update an event with inputs
1278     
1279     request = macro.request
1280     formatter = macro.formatter
1281     
1282     cal_delimeter = Globs.cal_delimeter
1283     
1284     # read all the events from data file
1285     events, cal_events = loadEvents(macro, 0)
1286     
1287     # update the selected event item
1288     try:
1289         events[event_form['id']].update(event_form.items())
1290     except KeyError:
1291         message('Failed to update the event (no such event)')
1292         return editeventform(macro, form_vals, event_form)
1293     
1294     # format the data fit to data file
1295     event_items = []
1296     for eid in events.keys():
1297         eventitem = [
1298             eid,
1299             cal_delimeter,
1300             events[eid]['startdate'],
1301             cal_delimeter,
1302             events[eid]['starttime'],
1303             cal_delimeter,
1304             events[eid]['enddate'],
1305             cal_delimeter,
1306             events[eid]['endtime'],
1307             cal_delimeter,
1308             convertdelimiter(events[eid]['title']),
1309             cal_delimeter,
1310             convertdelimiter(events[eid]['description']),
1311             cal_delimeter,
1312             convertdelimiter(events[eid]['refer']),
1313             ]
1314     
1315         eventitem = u''.join(eventitem)
1316         event_items.append(eventitem)
1317     
1318     event_items = u'\r\n'.join(event_items) + u'\r\n'
1319 
1320     # writes the data file back
1321     try:
1322         out_file = codecs.open(Globs.out_fname,'w',encoding='utf-8')
1323     except IOError:
1324         message('Failed to update the event (unable to open a data file)')
1325         return editeventform(macro, form_vals, event_form)
1326         
1327     out_file.writelines(event_items)
1328     out_file.close()
1329     
1330     # add log entry
1331     # addLogEntry(macro.request, 'EVTUPD', Globs.pagename, 'titled \'%s\'' % events[eid]['title'])
1332     
1333     message('The event is updated')
1334     return redirectPreviousAction(macro, form_vals)
1335 
1336 def deleteeventnow(macro, form_vals, eid):
1337     
1338     # Remove an event with inputs
1339     
1340     request = macro.request
1341     formatter = macro.formatter
1342     
1343     cal_delimeter = Globs.cal_delimeter
1344     
1345     # read all the events from data file
1346     events, cal_events = loadEvents(macro, 0)
1347     
1348     # remove the selected event item
1349     try:
1350         deletedevent = events.pop(eid)
1351     except KeyError:
1352         message('Failed to delete the event (no such event, id: %s)' % eid )
1353         return redirectPreviousAction(macro, form_vals)
1354     
1355     # format the data fit to data file
1356     event_items = []
1357     for eid in events.keys():
1358         eventitem = [
1359             eid,
1360             cal_delimeter,
1361             events[eid]['startdate'], 
1362             cal_delimeter,
1363             events[eid]['starttime'],
1364             cal_delimeter,
1365             events[eid]['enddate'], 
1366             cal_delimeter,
1367             events[eid]['endtime'],
1368             cal_delimeter,
1369             convertdelimiter(events[eid]['title']),
1370             cal_delimeter,
1371             convertdelimiter(events[eid]['description']),
1372             cal_delimeter,
1373             convertdelimiter(events[eid]['refer']),
1374             ]
1375             
1376         eventitem = u''.join(eventitem)
1377         event_items.append(eventitem)
1378     
1379     if event_items:
1380         event_items = u'\r\n'.join(event_items) + u'\r\n'
1381     else:
1382         event_items = u'\r\n'.join(event_items)
1383     
1384     # writes the data file back
1385     try:
1386         out_file = codecs.open(Globs.out_fname,'w',encoding='utf-8')
1387     except IOError:
1388         message('Failed to delete the event (unable to open a data file)')
1389         return editeventform(macro, form_vals, event_form)
1390         
1391     out_file.writelines(event_items)
1392     out_file.close()
1393     
1394     # add log entry
1395     # addLogEntry(macro.request, 'EVTDEL', Globs.pagename, 'titled \'%s\'' % events[eid]['title'])
1396     
1397     message('The event is deleted')
1398     return redirectPreviousAction(macro, form_vals)
1399 
1400 
1401 def converttext(targettext):
1402     # Converts some special characters of html to plain-text style
1403     # What else to handle?
1404 
1405     targettext = targettext.replace(u'&', '&amp')
1406     targettext = targettext.replace(u'>', '&gt;')
1407     targettext = targettext.replace(u'<', '&lt;')
1408     targettext = targettext.replace(u'\n', '<br>')
1409     targettext = targettext.replace(u'"', '&quot;')
1410     targettext = targettext.replace(u'\t', '&nbsp;&nbsp;&nbsp;&nbsp')
1411     targettext = targettext.replace(u'  ', '&nbsp;&nbsp;')
1412         
1413     return targettext
1414 
1415 def convertdelimiter(targettext):
1416     # Converts delimeter to other string to avoid a crash
1417     
1418     targettext = targettext.replace(Globs.cal_delimeter, '    ')
1419     
1420     return targettext
1421 
1422 
1423 
1424 def showeventcalendar(macro, year, month):
1425     Globs.lastaction = 'calshow'
1426     
1427     request = macro.request
1428     formatter = macro.formatter
1429     _ = request.getText
1430     
1431     wkend = Globs.wkend
1432     months= Globs.months
1433     wkdays = Globs.wkdays
1434     
1435     # get the calendar
1436     monthcal = calendar.monthcalendar(year, month)
1437 
1438     # shows current year & month
1439     html_header_curyearmonth = calhead_yearmonth(year, month)
1440     
1441     r7 = range(7)
1442     
1443     # shows header of week days
1444     html_header_weekdays = []
1445     
1446     for wkday in r7:
1447         wday = _(wkdays[wkday])
1448         html_header_weekdays.append( calhead_weekday(wday) )
1449     html_header_weekdays = '    <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_header_weekdays)
1450  
1451     # read all the events from data file
1452     events, cal_events = loadEvents(macro, 1)
1453     # message(u'total # of events: %d' % len(events))
1454     
1455     # sort cal_events
1456     for eachdate in cal_events.keys():
1457         # cal_events[eachdate].sort(cmp=lambda x,y: cmp(events[y]['date_len'], events[x]['date_len']))
1458         cal_events[eachdate].sort(comp_cal_events)
1459             
1460     # pending events for next row
1461     next_pending = []
1462     
1463     # gets previous, next month
1464     day_delta = datetime.timedelta(days=-1)
1465     cur_month = datetime.date(year, month, 1)
1466     prev_month = cur_month + day_delta
1467     
1468     day_delta = datetime.timedelta(days=15)
1469     cur_month_end = datetime.date(year, month, 25)
1470     next_month = cur_month_end + day_delta
1471     
1472     prev_monthcal = calendar.monthcalendar(prev_month.year, prev_month.month)
1473     next_monthcal = calendar.monthcalendar(next_month.year, next_month.month)
1474     
1475     # shows days
1476     html_week_rows = []
1477     
1478     for week in monthcal:
1479         
1480         # day head rows
1481         html_headday_cols = []
1482         html_events_rows = []
1483         
1484         for wkday in r7:
1485              
1486             day = week[wkday]
1487             
1488             if not day:
1489                 if week == monthcal[0]:
1490                     nb_day = prev_monthcal[-1][wkday]
1491                 else:
1492                     nb_day = next_monthcal[0][wkday]
1493                     
1494                 html_headday_cols.append( calhead_day_nbmonth(nb_day) )
1495             else:
1496                 html_headday_cols.append( calhead_day(year, month, day, wkday) )
1497         
1498         html_headday_row = '    <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_headday_cols)
1499         html_week_rows.append(html_headday_row)
1500         
1501         # dummy rows
1502         html_headdummy_cols = []
1503         
1504         for wkday in r7:
1505             day = week[wkday]
1506             if not day:
1507                 html_headdummy_cols.append( calshow_blankbox('head_dummy_nbmonth') )
1508             else:
1509                 html_headdummy_cols.append( calshow_blankbox('head_dummy') )
1510         
1511         html_headdummy_cols = u'\r\n'.join(html_headdummy_cols)
1512         html_week_rows.append(' <tr>\r\n%s </tr>\r\n' % html_headdummy_cols)
1513         
1514         # pending events for next row
1515         pending = next_pending
1516         next_pending = []
1517         
1518         # show events
1519         while 1: 
1520             event_left = 7
1521             colspan = -1
1522             html_events_cols = []
1523 
1524             for wkday in r7:
1525              
1526                 day = week[wkday]
1527                 
1528                 if not day:
1529                     if week == monthcal[0]:
1530                         cur_date = formatDate(prev_month.year, prev_month.month, prev_monthcal[-1][wkday])
1531                     else:
1532                         cur_date = formatDate(next_month.year, next_month.month, next_monthcal[0][wkday])
1533                 else:
1534                     cur_date = formatDate(year, month, day)
1535 
1536                 # if an event is already displayed with colspan
1537                 if colspan > 0:
1538                     colspan -= 1
1539                     if cal_events.has_key(cur_date) and lastevent in cal_events[cur_date]:
1540                         cal_events[cur_date].remove(lastevent)
1541                     
1542                     continue
1543                     
1544                 # if there is any event for this date
1545                 if cal_events.has_key(cur_date):
1546                     if len(cal_events[cur_date]) > 0:
1547                         
1548                         if wkday == 0 and len(pending) > 0:
1549                             todo_event_id = pending.pop(0)
1550                             if todo_event_id in cal_events[cur_date]:
1551                                 cur_event = events[todo_event_id]
1552                                 temp_len = diffday(cur_date, cur_event['enddate']) + 1
1553                                 
1554                                 # calculate colspan value
1555                                 if (7-wkday) < temp_len:
1556                                     colspan = 7 - wkday
1557                                     next_pending.append(cur_event['id'])
1558                                     html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append_pending', cur_date) )
1559 
1560                                 else:
1561                                     colspan = temp_len
1562                                     html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append', cur_date) )
1563                                 
1564                                 
1565                                 cal_events[cur_date].remove(todo_event_id)
1566 
1567                                 colspan -= 1
1568                                 lastevent = todo_event_id
1569                             else:
1570                                 message('FATAL ERROR')
1571                             continue
1572                             
1573                         # if the start date of the event is current date    
1574                         
1575                         for e_id in cal_events[cur_date]:
1576                             if events[e_id]['startdate'] == cur_date:
1577                                 cur_event = events[cal_events[cur_date].pop(cal_events[cur_date].index(e_id))]
1578                                 
1579                                 # calculate colspan value
1580                                 if (7-wkday) < cur_event['date_len']:
1581                                     colspan = 7 - wkday
1582                                     next_pending.append(cur_event['id'])
1583                                     html_events_cols.append( calshow_eventbox(cur_event, colspan, 'pending', cur_date) )
1584 
1585                                 else:
1586                                     colspan = cur_event['date_len']
1587                                     html_events_cols.append( calshow_eventbox(cur_event, colspan, '', cur_date) )
1588                                 
1589                                 colspan -= 1
1590                                 lastevent = cur_event['id']
1591                                 break
1592                             
1593                         # if the start date of the event is NOT current date
1594                         else:
1595                             if day == 0 and wkday == 0 and week == monthcal[0]:
1596                                 cur_event = events[cal_events[cur_date].pop(0)]
1597                                 temp_len = diffday(cur_date, cur_event['enddate']) + 1
1598                                 
1599                                 # calculate colspan value
1600                                 if (7-wkday) < temp_len:
1601                                     colspan = 7 - wkday
1602                                     next_pending.append(cur_event['id'])
1603                                     html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append_pending', cur_date) )
1604                                 else:
1605                                     colspan = temp_len
1606                                     html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append', cur_date) )
1607                                 
1608                                 
1609                                 colspan -= 1
1610                                 lastevent = cur_event['id']
1611                             else:
1612                                 if not day:
1613                                     html_events_cols.append( calshow_blankbox('cal_nbmonth') )
1614                                 else:
1615                                     html_events_cols.append( calshow_blankbox('cal_noevent') )
1616                                 event_left -= 1
1617                                 
1618                     else:
1619                         if not day:
1620                             html_events_cols.append( calshow_blankbox('cal_nbmonth') )
1621                         else:
1622                             html_events_cols.append( calshow_blankbox('cal_noevent') )
1623                         
1624                         event_left -= 1        
1625                 
1626                 # if there is NO event for this date
1627                 else:
1628                     if not day:
1629                         html_events_cols.append( calshow_blankbox('cal_nbmonth') )
1630                     else:
1631                         html_events_cols.append( calshow_blankbox('cal_noevent') )
1632                         
1633                     event_left -= 1
1634             
1635             # if no event for this entry
1636             if not event_left:
1637                 # ignore the previous entry
1638                 break
1639             else:
1640                 html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols))
1641             
1642         # show dummy blank slots for week height
1643         left_blank_rows = 2 - len(html_events_rows)
1644         
1645         # message('%d: left_blank_rows=%d' % (day, left_blank_rows))
1646         
1647         if left_blank_rows > 0:
1648             for i in range(left_blank_rows):
1649                 html_events_cols = []
1650                 for wkday in r7:
1651                     day = week[wkday]
1652                     if not day:
1653                         html_events_cols.append( calshow_blankbox('cal_nbmonth') )
1654                     else:
1655                         html_events_cols.append( calshow_blankbox('cal_noevent') )
1656                 
1657                 html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols))
1658         
1659         
1660         # close the week slots
1661         html_events_cols = []
1662         for wkday in r7:
1663             day = week[wkday]
1664             if not day:
1665                 html_events_cols.append( calshow_blankbox('cal_last_nbmonth') )
1666             else:
1667                 html_events_cols.append( calshow_blankbox('cal_last_noevent') )
1668     
1669         html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols))
1670         
1671         html_events_rows = u'\r\n'.join(html_events_rows)
1672         html_week_rows.append(html_events_rows)
1673             
1674     html_calendar_rows = u'\r\n'.join(html_week_rows)
1675     
1676     html_cal_table = [
1677         u'\r\n<div id="eventcalendar">',
1678         u'<table width="90%%" class="eventcalendar">',
1679         u'%s' % html_header_curyearmonth,
1680         u'%s' % html_header_weekdays,
1681         u'%s' % html_calendar_rows,
1682         u'</table>',
1683         u'</div>',
1684         ]
1685     html_cal_table = u'\r\n'.join(html_cal_table)
1686         
1687     return html_cal_table
1688 
1689 # show weekday
1690 def calhead_yearmonth(year, month):
1691     
1692     months = Globs.months
1693     monthstyle_us = Globs.month_style_us
1694     
1695     nextyear, nextmonth = yearmonthplusoffset(year, month, 1)
1696     prevyear, prevmonth = yearmonthplusoffset(year, month, -1)
1697     
1698     prevlink = u'?calaction=calshow&caldate=%d%02d' % (prevyear, prevmonth)
1699     nextlink = u'?calaction=calshow&caldate=%d%02d' % (nextyear, nextmonth)
1700     
1701     if monthstyle_us:
1702         stryearmonth = u'%s %d' % (months[month-1], year)
1703     else:
1704         stryearmonth = u'%d / %02d' % (year, month)
1705     
1706     html = [
1707         u'  <tr>',
1708         u'      <td class="head_yearmonth"><a href="%s">&lt;</a></td>' % prevlink,
1709         u'      <td colspan="5" class="head_yearmonth">%s</td>' % stryearmonth,
1710         u'      <td class="head_yearmonth"><a href="%s">&gt;</a></td>' % nextlink,
1711         u'  </tr>',
1712         ]
1713         
1714     return u'\r\n'.join(html)
1715 
1716 
1717 # show weekday
1718 def calhead_weekday(wday):
1719     html = u'       <td class="head_weekday">%s</td>\r\n' % wday
1720     return html
1721 
1722 
1723 # show days of current month
1724 def calhead_day(year, month, day, wkday):
1725     wkend = Globs.wkend
1726     if wkday == wkend:
1727         html_text = u'<font color="#FF3300">%s</font>' % day
1728     else:
1729         html_text = u'%s' % day
1730     
1731     cyear, cmonth, cday = gettodaydate()
1732     
1733     if cyear == year and cmonth == month and cday == day:
1734         html = u'  <td class="head_day_today">&nbsp;%s</td>\r\n' % html_text
1735     else:
1736         html = u'  <td class="head_day">&nbsp;%s</td>\r\n' % html_text
1737        
1738     return html
1739 
1740 
1741 # show days of previous or next month
1742 def calhead_day_nbmonth(day):
1743     html = u'  <td class="head_day_nbmonth">&nbsp;%s</td>\r\n' % day
1744     return html
1745 
1746     
1747 # show blank calendar box
1748 def calshow_blankbox(classname):
1749     html = u'  <td class="%s">&nbsp;</td>' % classname
1750     return html
1751 
1752 # show eventbox
1753 def calshow_eventbox(event, colspan, status, cur_date):
1754     if status:
1755         status = u'_%s' % status
1756     
1757     title = event['title']
1758     eid = event['id']
1759     startdate = event['startdate']
1760     enddate = event['enddate']
1761     starttime = event['starttime']
1762     endtime = event['endtime']
1763     description = event['description']
1764     
1765     year, month, day = getdatefield(cur_date)
1766     
1767     if eid[0] == 'w':
1768         eventfromsubpage = 'background-color: #ddffdd;'
1769     else:
1770         eventfromsubpage = ''
1771     
1772     if (startdate == enddate) and starttime:
1773         shour, smin = gettimefield(starttime)
1774         
1775         link = [
1776             u'<table width="100%%" style="border-width: 0px; padding: 0px; margin: 0px;"><tr>\r\n',
1777             u'<td width="10" nowrap style="border-width: 0px; padding: 0px; margin: 0px; text-align: left; vertical-align: top; font-size: 7pt; color: #000000;">%02d:%02d&nbsp;</td>\r\n' % (shour, smin),
1778             # u'<td>&nbsp;</td>',
1779             u'<td style="border-width: 0px; padding: 0px; margin: 0px; text-align: left; vertical-align: top;font-size: 8pt;">',
1780             u'<a href="?calaction=evtview&id=%s&caldate=%d%02d" title="%s">%s</a>' % (eid, year, month, converttext(description), converttext(title)),
1781             u'</td>\r\n</tr></table>',
1782             ]
1783         link = u''.join(link)
1784     else:
1785         link = u'<a href="?calaction=evtview&id=%s&caldate=%d%02d" title="%s">%s</a>' % (eid, year, month, converttext(description), converttext(title))
1786     
1787     
1788     html = [
1789         u'  <td class="cal_eventbox" colspan="%d"><table class="cal_event">' % colspan,
1790         u'      <tr><td id="cal_event_%s" class="cal_event%s" style="%s">%s</td></tr>' % (eid, status, eventfromsubpage, link),
1791         u'      </table></td>',
1792         ]
1793         
1794     return u'\r\n'.join(html)
1795         
1796 
1797 
1798 # date format should be like '20051004' for 2005, Oct., 04
1799 def diffday(date1, date2):
1800     
1801     try:
1802         year1, month1, day1 = getdatefield(date1)
1803         year2, month2, day2 = getdatefield(date2)
1804         tmp_diff = datetime.date(year2, month2, day2) - datetime.date(year1, month1, day1)
1805     except ValueError:
1806         message('An event data is corrupted: invalid date format')
1807         return 0
1808 
1809     return tmp_diff.days
1810 
1811 
1812 def formatDate(year, month, day):
1813     # returns like: '20051004'
1814     return u'%4d%02d%02d' % (year, month, day)
1815 
1816 def cliprgb(r,g,b): # don't use 255!
1817     if r < 0:   r=0
1818     if r > 254: r=254
1819     if b < 0:   b=0
1820     if b > 254: b=254
1821     if g < 0:   g=0
1822     if g > 254: g=254
1823     return r, g, b
1824 
1825 
1826 def message(astring):
1827     Globs.adminmsg += u'%s<br>\r\n' % astring
1828 
1829 def yearmonthplusoffset(year, month, offset):
1830     month = month+offset
1831     # handle offset and under/overflows - quick and dirty, yes!
1832     while month < 1:
1833         month = month + 12
1834         year = year - 1
1835     while month > 12:
1836         month = month - 12
1837         year = year + 1
1838     return year, month
1839 
1840 def getPages(request, filter_regex=None):
1841     """ Return a (filtered) list of pages names.
1842     """
1843     filter = None
1844     if filter_regex:
1845         filter = re.compile(filter_regex).match
1846     pages = request.rootpage.getPageList(filter=filter)
1847     return pages
1848     
1849     
1850 def cutstring(strcut, intlen):
1851     if len(strcut) > intlen:
1852         newlen = intlen - 3
1853         strtemp = strcut[:newlen] + '...'
1854     else:
1855         strtemp = strcut
1856         
1857     return strtemp

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2005-10-31 18:42:02, 65.4 KB) [[attachment:EventCalendar-080.py]]
  • [get | view] (2005-11-22 17:40:26, 55.4 KB) [[attachment:EventCalendar-090.py]]
  • [get | view] (2006-01-15 16:25:08, 57.2 KB) [[attachment:EventCalendar-091.py]]
  • [get | view] (2006-01-17 08:02:06, 75.4 KB) [[attachment:EventCalendar-092.py]]
  • [get | view] (2006-01-18 03:54:33, 75.6 KB) [[attachment:EventCalendar-093.py]]
  • [get | view] (2006-02-25 09:00:17, 74.8 KB) [[attachment:EventCalendar-094-easytime.py]]
  • [get | view] (2006-02-06 04:39:13, 76.2 KB) [[attachment:EventCalendar-094.py]]
  • [get | view] (2006-04-17 13:21:03, 122.7 KB) [[attachment:EventCalendar-096.py]]
  • [get | view] (2006-05-12 15:26:40, 150.6 KB) [[attachment:EventCalendar-098.py]]
  • [get | view] (2008-11-05 16:58:27, 3.2 KB) [[attachment:EventCalendar-099-01.py.patch]]
  • [get | view] (2006-05-23 09:50:33, 152.3 KB) [[attachment:EventCalendar-099.py]]
  • [get | view] (2008-02-14 05:18:57, 1.0 KB) [[attachment:EventCalendar-099.py.patch]]
  • [get | view] (2009-07-15 23:35:13, 151.1 KB) [[attachment:EventCalendar-099a.py]]
  • [get | view] (2013-01-21 02:05:25, 152.4 KB) [[attachment:EventCalendar-099b.py]]
  • [get | view] (2006-11-30 15:51:59, 1.8 KB) [[attachment:defaults-099-01.patch]]
  • [get | view] (2005-10-31 18:35:06, 5.0 KB) [[attachment:eventcal-080.css]]
  • [get | view] (2005-10-31 18:35:01, 11.3 KB) [[attachment:eventcal-080.py]]
  • [get | view] (2005-11-22 17:40:51, 6.8 KB) [[attachment:eventcal-090.css]]
  • [get | view] (2005-11-22 17:40:40, 18.1 KB) [[attachment:eventcal-090.py]]
  • [get | view] (2006-04-17 13:22:09, 8.9 KB) [[attachment:eventcal-096.css]]
  • [get | view] (2006-02-08 02:31:50, 1.4 KB) [[attachment:eventcalendar-094-01.patch]]
  • [get | view] (2006-11-30 15:52:26, 12.2 KB) [[attachment:label_priority-099-01.patch]]
  • [get | view] (2006-11-16 17:06:28, 1.1 KB) [[attachment:pagelinks-099-01.patch]]
  • [get | view] (2006-11-16 17:06:52, 2.9 KB) [[attachment:pagelist-099-01.patch]]
  • [get | view] (2006-03-29 07:37:02, 118.7 KB) [[attachment:snap-daily.jpg]]
  • [get | view] (2006-01-18 03:52:49, 23.2 KB) [[attachment:snap-list.jpg]]
  • [get | view] (2006-01-18 03:52:40, 37.4 KB) [[attachment:snap-monthly.jpg]]
  • [get | view] (2006-03-29 07:35:54, 43.8 KB) [[attachment:snap-simple.jpg]]
  • [get | view] (2006-01-18 03:53:04, 29.4 KB) [[attachment:snap-upcoming.jpg]]
  • [get | view] (2006-03-29 07:36:43, 161.0 KB) [[attachment:snap-weekly.jpg]]
  • [get | view] (2007-06-12 19:51:39, 55.0 KB) [[attachment:time_bug.PNG]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.