Attachment 'MonthCalendar.py'
Download 1 """
2 MoinMoin - MonthCalendar Macro
3
4 You can use this macro to put a months calendar page on a Wiki page.
5
6 The days are links to Wiki pages following this naming convention:
7 BasePageName/year-month-day
8
9 Copyright (c) 2002 by Thomas Waldmann <ThomasWaldmann@gmx.de>
10 changes for moin 1.2 Copyright (c) 2004 by Oliver Graf <ograf@bitart.de>
11 Licensed under GNU GPL - see COPYING for details.
12
13 ----
14
15 Revisions:
16 * first revision without a number (=1.0):
17 * was only online for a few hours and then replaced by 1.1
18 * 1.1:
19 * changed name to MonthCalendar to avoid conflict with "calendar" under case-insensitive OSes like Win32
20 * days as subpages
21 * basepage argument
22 * change order of year/month argument
23 * browsing links to prev/next month/year
24 * current limitation: you can only browse one calendar on the same
25 page/url, if you try to browse another calendar on the same page,
26 the first one jumps back to its original display
27 * show basepage in calendar header if basepage<>currentpage
28 * 1.2:
29 * minor fixes in argument parsing
30 * cosmetic fix for netscape, other cosmetic changes, changed css
31 * i18n support (weekday short names)
32 * 1.3:
33 * fixes to run with MoinMoin 0.11, thanks to JuergenHermann
34 * fix: withspace before "," allowed in argument list
35 * BasePage in calendar header (if present) is a link now
36 * more i18n
37 * HTML cleanup, generating code avoids bracketing errors
38 * colour cosmetics
39 * 1.4:
40 * new parameter for enabling fixed height of 6 "calendar weeks",
41 if you want to show a whole year's calendar, this just looks
42 better than having some months with 4, some with 5 and some with 6.
43 * group calendaring functions:
44 * you can give mutliple BasePages UserName1*UserName2*UserName3
45 * first BasePage is considered "your" Basepage,
46 used days are bright red
47 * 2nd and all other BasePages are considered "others" BasePages
48 and lead to an increasing green component the more "used" days
49 the others have. So white gets greener and red gets more yellowish.
50 * in the head part of the calendar, you can click on each name
51 to get to the Page of the same name
52 * colouring of my and others BasePage is done in a way to show
53 the colouring used in the calendar:
54 * others use green colouring (increasingly green if multiply used)
55 * I use red colouring, which gets more and more yellowish as
56 the day is used by more and more others, too
57 * 1.5:
58 * fixed username colouring when using a BasePage
59 * fixed navigation header of MonthCalendar not to get broken into
60 multiple lines
61 * fixed SubPage handling (please do not use relative SubPages like
62 /SubPage yet. Use MyName/SubPage.)
63 * 1.6:
64 * syntactic cleanup
65 * removed i18n compatibility for moin<1.1 or cvs<2003-06-10
66 * integrated Scott Chapman's changes:
67 * Made it configurable for Sunday or Monday as the first day of the week.
68 Search for 'change here'.
69 * Made it so weekend dates have different color.
70
71 TODO:
72 * integrate patch for including day page contents directly into cal
73 * still thinking over: does this make sense in a MonthCalendar?
74 * it would be definitely nice in a week or day calendar (more space to
75 burn)
76 * integr. daycal -link-> monthcal
77
78 ----
79
80 Usage:
81 [[MonthCalendar(BasePage,year,month,monthoffset,monthoffset2,height6)]]
82
83 each parameter can be empty and then defaults to currentpage or currentdate or monthoffset=0
84
85 Samples (paste that to one of your pages for a first try):
86
87 Calendar of current month for current page:
88 [[MonthCalendar]]
89
90 Calendar of last month:
91 [[MonthCalendar(,,,-1)]]
92
93 Calendar of next month:
94 [[MonthCalendar(,,,+1)]]
95
96 Calendar of Page SampleUser, this years december:
97 [[MonthCalendar(SampleUser,,12)]]
98
99 Calendar of current Page, this years december:
100 [[MonthCalendar(,,12)]]
101
102 Calendar of December, 2001:
103 [[MonthCalendar(,2001,12)]]
104
105 Calendar of the month two months after December, 2001
106 (maybe doesn't make much sense, but is possible)
107 [[MonthCalendar(,2001,12,+2)]]
108
109 Calendar of year 2002 (every month padded to height of 6):
110 ||||||Year 2002||
111 ||[[MonthCalendar(,2002,1,,,1)]]||[[MonthCalendar(,2002,2,,,1)]]||[[MonthCalendar(,2002,3,,,1)]]||
112 ||[[MonthCalendar(,2002,4,,,1)]]||[[MonthCalendar(,2002,5,,,1)]]||[[MonthCalendar(,2002,6,,,1)]]||
113 ||[[MonthCalendar(,2002,7,,,1)]]||[[MonthCalendar(,2002,8,,,1)]]||[[MonthCalendar(,2002,9,,,1)]]||
114 ||[[MonthCalendar(,2002,10,,,1)]]||[[MonthCalendar(,2002,11,,,1)]]||[[MonthCalendar(,2002,12,,,1)]]||
115
116 Current calendar of me, also showing entries of A and B:
117 [[MonthCalendar(MyPage*TestUserA*TestUserB)]]
118
119 SubPage calendars:
120 [[MonthCalendar(MyName/CalPrivate)]]
121 [[MonthCalendar(MyName/CalBusiness)]]
122 [[MonthCalendar(MyName/CalBusiness*MyName/CalPrivate)]]
123
124 ----
125
126 You need to have some stylesheet entries like the following.
127 Paste that to default.css / moinmoin.css:
128
129 /* begin css for MonthCalendar macro */
130 /* calendar table */
131 table.cal-table {
132 border: none;
133 padding: 2px;
134 spacing: 2px;
135 }
136
137 table.cal-table td {
138 border: none;
139 }
140
141 /* days without and with pages linked to them */
142 a.cal-emptyday {
143 color: #5A5A5A;
144 text-align: center;
145 text-decoration: none;
146 }
147 a.cal-usedday {
148 font-weight: bold;
149 color: #222200;
150 text-align: center;
151 text-decoration: none;
152 }
153 /* multi page calendars */
154 a.cal-thispage {
155 color: #777777;
156 text-align: center;
157 text-decoration: none;
158 }
159 a.cal-otherpage {
160 font-weight: bold;
161 color: #000000;
162 text-align: center;
163 }
164 /* general stuff: workdays, weekend, today */
165 .cal-cell {
166 width: 2em;
167 height: 1.5em;
168 }
169
170 td.cal-workday {
171 background-color: #DDDDFF;
172 text-align: center;
173 }
174 td.cal-weekend {
175 background-color: #FFDDDD;
176 text-align: center;
177 }
178 td.cal-today {
179 background-color: #CCFFCC;
180 text-align: center;
181 }
182 /* invalid places on the monthly calendar sheet */
183 td.cal-invalidday {
184 background-color: #DDDDFF;
185 text-align: center;
186 }
187 /* links to prev/next month/year */
188 a.cal-link {
189 color: #000000;
190 text-decoration: none;
191 }
192 th.cal-header {
193 background-color: #DDBBFF;
194 text-align: center;
195 }
196 /* end css for MonthCalendar macro */
197
198 ----
199
200 If you want translated (german) messages, add something like this to
201 i18n/de.py (if you have >=0.11, the weekday translation might be already
202 there):
203
204 'Mon':'Mo','Tue':'Di','Wed':'Mi','Thu':'Do','Fri':'Fr','Sat':'Sa','Sun':'So',
205
206 'Invalid MonthCalendar calparms "%s"!':
207 'Ung\366ltige MonthCalendar calparms "%s"!',
208
209 'Invalid MonthCalendar arguments "%s"!':
210 'Ung\366ltige MonthCalendar Argumente "%s"!',
211
212 """
213
214 # Imports
215 from MoinMoin import config, user, wikiutil
216 from MoinMoin.Page import Page
217 import sys, re, calendar, time, string
218
219 # The following line sets the calendar to have either Sunday or Monday as
220 # the first day of the week. Only SUNDAY or MONDAY (case sensitive) are
221 # valid here. All other values will not make good calendars.
222 # If set to Sunday, the calendar is displayed at "March 2003" vs. "2003 / 3" also.
223 # XXX change here ----------------vvvvvv
224 calendar.setfirstweekday(calendar.MONDAY)
225
226 def yearmonthplusoffset(year, month, offset):
227 month = month+offset
228 # handle offset and under/overflows - quick and dirty, yes!
229 while month < 1:
230 month = month+12
231 year = year-1
232 while month > 12:
233 month = month-12
234 year = year+1
235 return year, month
236
237 def parseargs(args, defpagename, defyear, defmonth, defoffset, defoffset2, defheight6):
238 strpagename = args.group('basepage')
239 if strpagename:
240 parmpagename = strpagename
241 else:
242 parmpagename = defpagename
243 # multiple pagenames separated by "*" - split into list of pagenames
244 parmpagename = re.split(r'\*', parmpagename)
245
246 stryear = args.group('year')
247 if stryear:
248 parmyear = int(stryear)
249 else:
250 parmyear = defyear
251
252 strmonth = args.group('month')
253 if strmonth:
254 parmmonth = int(strmonth)
255 else:
256 parmmonth = defmonth
257
258 stroffset = args.group('offset')
259 if stroffset:
260 parmoffset = int(stroffset)
261 else:
262 parmoffset = defoffset
263
264 stroffset2 = args.group('offset2')
265 if stroffset2:
266 parmoffset2 = int(stroffset2)
267 else:
268 parmoffset2 = defoffset2
269
270 strheight6 = args.group('height6')
271 if strheight6:
272 parmheight6 = int(strheight6)
273 else:
274 parmheight6 = defheight6
275
276 return parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6
277
278 # FIXME: vvvvvv is there a better way for matching a pagename ?
279 _arg_basepage = r'\s*(?P<basepage>[^, ]+)?\s*'
280 _arg_year = r',\s*(?P<year>\d+)?\s*'
281 _arg_month = r',\s*(?P<month>\d+)?\s*'
282 _arg_offset = r',\s*(?P<offset>[+-]?\d+)?\s*'
283 _arg_offset2 = r',\s*(?P<offset2>[+-]?\d+)?\s*'
284 _arg_height6 = r',\s*(?P<height6>[+-]?\d+)?\s*'
285 _args_re_pattern = r'^(%s)?(%s)?(%s)?(%s)?(%s)?(%s)?$' % \
286 (_arg_basepage,_arg_year,_arg_month, \
287 _arg_offset,_arg_offset2,_arg_height6)
288
289
290 def execute(macro, text):
291 _ = macro.request.getText
292
293 # return immediately if getting links for the current page
294 if macro.request.mode_getpagelinks:
295 return ''
296
297 args_re=re.compile(_args_re_pattern)
298
299 currentyear, currentmonth, currentday, h, m, s, wd, yd, ds = time.localtime(time.time())
300 thispage = macro.formatter.page.page_name
301 # does the url have calendar params (= somebody has clicked on prev/next links in calendar) ?
302 if macro.form.has_key('calparms'):
303 text2 = macro.form['calparms'][0]
304 args2 = args_re.match(text2)
305 if not args2:
306 return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar calparms "%s"!')) % (text2,)
307 else:
308 has_calparms = 1 # yes!
309 cparmpagename, cparmyear, cparmmonth, cparmoffset, cparmoffset2, cparmheight6 = \
310 parseargs(args2, thispage, currentyear, currentmonth, 0, 0, 0)
311 else:
312 has_calparms = 0
313
314 if text is None: # macro call without parameters
315 parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6 = \
316 [thispage], currentyear, currentmonth, 0, 0, 0
317 else:
318 # parse and check arguments
319 args = args_re.match(text)
320 if not args:
321 return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar arguments "%s"!')) % (text,)
322 else:
323 parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6 = \
324 parseargs(args, thispage, currentyear, currentmonth, 0, 0, 0)
325
326 # does url have calendar params and is THIS the right calendar to modify (we can have multiple
327 # calendars on the same page)?
328 if has_calparms and cparmpagename == parmpagename:
329 year,month = yearmonthplusoffset(parmyear, parmmonth, parmoffset + cparmoffset2)
330 parmoffset2 = cparmoffset2
331 else:
332 year,month = yearmonthplusoffset(parmyear, parmmonth, parmoffset)
333
334 if not has_calparms:
335 cparmpagename = parmpagename[0]
336
337 # get the calendar
338 monthcal = calendar.monthcalendar(year, month)
339
340 # european / US differences
341 months = ('January','February','March','April','May','June','July','August','September','October','November','December')
342 # Set things up for Monday or Sunday as the first day of the week
343 if calendar.firstweekday() == calendar.MONDAY:
344 wkend = (5, 6)
345 wkdays = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
346 if calendar.firstweekday() == calendar.SUNDAY:
347 wkend = (0, 6)
348 wkdays = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
349
350 p = Page(thispage)
351 querystr = "calparms=%s,%d,%d,%d,%%d" % (string.join(parmpagename,'*'), parmyear, parmmonth, parmoffset)
352 prevlink = p.url(macro.request, querystr % (parmoffset2 - 1))
353 nextlink = p.url(macro.request, querystr % (parmoffset2 + 1))
354 prevylink = p.url(macro.request, querystr % (parmoffset2 - 12))
355 nextylink = p.url(macro.request, querystr % (parmoffset2 + 12))
356 prevmonth = macro.formatter.url(prevlink, '<-', 'cal-link')
357 nextmonth = macro.formatter.url(nextlink, '->', 'cal-link')
358 prevyear = macro.formatter.url(prevylink, '<<-', 'cal-link')
359 nextyear = macro.formatter.url(nextylink, '->>', 'cal-link')
360
361 # multiple base pages?
362 if parmpagename <> [thispage]:
363 pagelinks = []
364 for page in parmpagename:
365 daypage=Page(page)
366 if page == cparmpagename:
367 csslink = "cal-thispage"
368 else:
369 csslink = "cal-otherpage"
370 pagelinks.append('<a class="%s" href="%s">%s</a>' % (csslink, daypage.url(macro.request), page))
371 del daypage
372 showpagename = ' %s<BR>\n' % '*'.join(pagelinks)
373 else:
374 showpagename = ''
375 if calendar.firstweekday() == calendar.SUNDAY:
376 resth1 = ' <th colspan="7" class="cal-header">\n' \
377 '%s' \
378 ' %s %s <b> %s %s</b> %s %s\n' \
379 ' </th>\n' % (showpagename, prevyear, prevmonth, months[month-1], str(year), nextmonth, nextyear)
380 if calendar.firstweekday() == calendar.MONDAY:
381 resth1 = ' <th colspan="7" class="cal-header">\n' \
382 '%s' \
383 ' %s %s <b> %s / %s</b> %s %s\n' \
384 ' </th>\n' % (showpagename, prevyear, prevmonth, str(year), month, nextmonth, nextyear)
385 restr1 = ' <tr>\n%s </tr>\n' % resth1
386
387 r7 = range(7)
388 restd2 = []
389 for wkday in r7:
390 wday = _(wkdays[wkday])
391 if wkday in wkend:
392 cssday = "cal-weekend"
393 else:
394 cssday = "cal-workday"
395 restd2.append(' <td class="%s cal-cell">%s</td>\n' % (cssday, wday))
396 restr2 = ' <tr>\n%s </tr>\n' % "".join(restd2)
397
398 if parmheight6:
399 while len(monthcal) < 6:
400 monthcal = monthcal + [[0,0,0,0,0,0,0]]
401
402 restrn = []
403 for week in monthcal:
404 restdn = []
405 for wkday in r7:
406 day = week[wkday]
407 if not day:
408 restdn.append(' <td class="cal-invalidday cal-cell"> </td>\n')
409 else:
410 csslink = "cal-emptyday"
411 page = parmpagename[0]
412 link = "%s/%4d-%02d-%02d" % (page, year, month, day)
413 daypage = Page(link)
414 if daypage.exists():
415 csslink = "cal-usedday"
416 for otherpage in parmpagename[1:]:
417 otherlink = "%s/%4d-%02d-%02d" % (otherpage, year, month, day)
418 otherdaypage = Page(otherlink)
419 if otherdaypage.exists():
420 csslink = "cal-usedday"
421 fmtlink = macro.formatter.url(daypage.url(macro.request), str(day), csslink)
422 if day == currentday and month == currentmonth and year == currentyear:
423 cssday = "cal-today"
424 else:
425 if wkday in wkend:
426 cssday = "cal-weekend"
427 else:
428 cssday = "cal-workday"
429 restdn.append(' <td class="%s cal-cell">%s</td>\n' % (cssday, fmtlink))
430 restrn.append(' <tr>\n%s </tr>\n' % "".join(restdn))
431
432 restable = '<table class="cal-table">\n%s%s%s</table>\n'
433 result = restable % (restr1, restr2, "".join(restrn))
434 return macro.formatter.rawHTML(result)
435
436 # EOF
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.