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"> </td>',
677 u' <td class="list_entry">%d %02d/%02d</td>' % (eyear, emonth, eday),
678 u' <td class="list_entry"> </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'&', '&')
1406 targettext = targettext.replace(u'>', '>')
1407 targettext = targettext.replace(u'<', '<')
1408 targettext = targettext.replace(u'\n', '<br>')
1409 targettext = targettext.replace(u'"', '"')
1410 targettext = targettext.replace(u'\t', '  ')
1411 targettext = targettext.replace(u' ', ' ')
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"><</a></td>' % prevlink,
1709 u' <td colspan="5" class="head_yearmonth">%s</td>' % stryearmonth,
1710 u' <td class="head_yearmonth"><a href="%s">></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"> %s</td>\r\n' % html_text
1735 else:
1736 html = u' <td class="head_day"> %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"> %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"> </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 </td>\r\n' % (shour, smin),
1778 # u'<td> </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.You are not allowed to attach a file to this page.