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