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
72 TODO:
73 * integrate patch for including day page contents directly into cal
74 * still thinking over: does this make sense in a MonthCalendar?
75 * it would be definitely nice in a week or day calendar (more space to
76 burn)
77 * integr. daycal -link-> monthcal
78
79 ----
80
81 Usage:
82 [[MonthCalendar(BasePage,year,month,monthoffset,monthoffset2,height6)]]
83
84 each parameter can be empty and then defaults to currentpage or currentdate or monthoffset=0
85
86 Samples (paste that to one of your pages for a first try):
87
88 Calendar of current month for current page:
89 [[MonthCalendar]]
90
91 Calendar of last month:
92 [[MonthCalendar(,,,-1)]]
93
94 Calendar of next month:
95 [[MonthCalendar(,,,+1)]]
96
97 Calendar of Page SampleUser, this years december:
98 [[MonthCalendar(SampleUser,,12)]]
99
100 Calendar of current Page, this years december:
101 [[MonthCalendar(,,12)]]
102
103 Calendar of December, 2001:
104 [[MonthCalendar(,2001,12)]]
105
106 Calendar of the month two months after December, 2001
107 (maybe doesn't make much sense, but is possible)
108 [[MonthCalendar(,2001,12,+2)]]
109
110 Calendar of year 2002 (every month padded to height of 6):
111 ||||||Year 2002||
112 ||[[MonthCalendar(,2002,1,,,1)]]||[[MonthCalendar(,2002,2,,,1)]]||[[MonthCalendar(,2002,3,,,1)]]||
113 ||[[MonthCalendar(,2002,4,,,1)]]||[[MonthCalendar(,2002,5,,,1)]]||[[MonthCalendar(,2002,6,,,1)]]||
114 ||[[MonthCalendar(,2002,7,,,1)]]||[[MonthCalendar(,2002,8,,,1)]]||[[MonthCalendar(,2002,9,,,1)]]||
115 ||[[MonthCalendar(,2002,10,,,1)]]||[[MonthCalendar(,2002,11,,,1)]]||[[MonthCalendar(,2002,12,,,1)]]||
116
117 Current calendar of me, also showing entries of A and B:
118 [[MonthCalendar(MyPage*TestUserA*TestUserB)]]
119
120 SubPage calendars:
121 [[MonthCalendar(MyName/CalPrivate)]]
122 [[MonthCalendar(MyName/CalBusiness)]]
123 [[MonthCalendar(MyName/CalBusiness*MyName/CalPrivate)]]
124
125 ----
126
127 You need to have some stylesheet entries like the following.
128 Paste that to default.css / moinmoin.css:
129
130 /* begin css for MonthCalendar macro */
131 /* days without and with pages linked to them */
132 a.cal-emptyday {
133 color: #777777;
134 text-align: center;
135 }
136 a.cal-usedday {
137 font-weight: bold;
138 color: #000000;
139 text-align: center;
140 }
141 /* general stuff: workdays, weekend, today */
142 td.cal-workday {
143 background-color: #DDDDFF;
144 text-align: center;
145 }
146 td.cal-weekend {
147 background-color: #FFDDDD;
148 text-align: center;
149 }
150 td.cal-today {
151 background-color: #CCFFCC;
152 border-style: solid;
153 border-width: 2pt;
154 text-align: center;
155 }
156 /* invalid places on the monthly calendar sheet */
157 td.cal-invalidday {
158 background-color: #CCCCCC;
159 }
160 /* links to prev/next month/year */
161 a.cal-link {
162 color: #000000;
163 text-decoration: none;
164 }
165 th.cal-header {
166 background-color: #DDBBFF;
167 text-align: center;
168 }
169 /* end css for MonthCalendar macro */
170
171 ----
172
173 If you want translated (german) messages, add something like this to
174 i18n/de.py (if you have >=0.11, the weekday translation might be already
175 there):
176
177 'Mon':'Mo','Tue':'Di','Wed':'Mi','Thu':'Do','Fri':'Fr','Sat':'Sa','Sun':'So',
178
179 'Invalid MonthCalendar calparms "%s"!':
180 'Ung\366ltige MonthCalendar calparms "%s"!',
181
182 'Invalid MonthCalendar arguments "%s"!':
183 'Ung\366ltige MonthCalendar Argumente "%s"!',
184
185 """
186
187 # Imports
188 from MoinMoin import config, user, wikiutil
189 from MoinMoin.Page import Page
190 import sys, re, calendar, time, string
191
192 # The following line sets the calendar to have either Sunday or Monday as
193 # the first day of the week. Only SUNDAY or MONDAY (case sensitive) are
194 # valid here. All other values will not make good calendars.
195 # If set to Sunday, the calendar is displayed at "March 2003" vs. "2003 / 3" also.
196 # XXX change here ----------------vvvvvv
197 calendar.setfirstweekday(calendar.MONDAY)
198
199 def cliprgb(r,g,b): # don't use 255!
200 if r < 0: r=0
201 if r > 254: r=254
202 if b < 0: b=0
203 if b > 254: b=254
204 if g < 0: g=0
205 if g > 254: g=254
206 return r, g, b
207
208 def yearmonthplusoffset(year, month, offset):
209 month = month+offset
210 # handle offset and under/overflows - quick and dirty, yes!
211 while month < 1:
212 month = month+12
213 year = year-1
214 while month > 12:
215 month = month-12
216 year = year+1
217 return year, month
218
219 def parseargs(args, defpagename, defyear, defmonth, defoffset, defoffset2, defheight6):
220 strpagename = args.group('basepage')
221 if strpagename:
222 parmpagename = strpagename
223 else:
224 parmpagename = defpagename
225 # multiple pagenames separated by "*" - split into list of pagenames
226 parmpagename = re.split(r'\*', parmpagename)
227
228 stryear = args.group('year')
229 if stryear:
230 parmyear = int(stryear)
231 else:
232 parmyear = defyear
233
234 strmonth = args.group('month')
235 if strmonth:
236 parmmonth = int(strmonth)
237 else:
238 parmmonth = defmonth
239
240 stroffset = args.group('offset')
241 if stroffset:
242 parmoffset = int(stroffset)
243 else:
244 parmoffset = defoffset
245
246 stroffset2 = args.group('offset2')
247 if stroffset2:
248 parmoffset2 = int(stroffset2)
249 else:
250 parmoffset2 = defoffset2
251
252 strheight6 = args.group('height6')
253 if strheight6:
254 parmheight6 = int(strheight6)
255 else:
256 parmheight6 = defheight6
257
258 return parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6
259
260 # FIXME: vvvvvv is there a better way for matching a pagename ?
261 _arg_basepage = r'\s*(?P<basepage>[^, ]+)?\s*'
262 _arg_year = r',\s*(?P<year>\d+)?\s*'
263 _arg_month = r',\s*(?P<month>\d+)?\s*'
264 _arg_offset = r',\s*(?P<offset>[+-]?\d+)?\s*'
265 _arg_offset2 = r',\s*(?P<offset2>[+-]?\d+)?\s*'
266 _arg_height6 = r',\s*(?P<height6>[+-]?\d+)?\s*'
267 _args_re_pattern = r'^(%s)?(%s)?(%s)?(%s)?(%s)?(%s)?$' % \
268 (_arg_basepage,_arg_year,_arg_month, \
269 _arg_offset,_arg_offset2,_arg_height6)
270
271
272 def execute(macro, text):
273 _ = macro.request.getText
274
275 # return immediately if getting links for the current page
276 if macro.request.mode_getpagelinks:
277 return ''
278
279 args_re=re.compile(_args_re_pattern)
280
281 currentyear, currentmonth, currentday, h, m, s, wd, yd, ds = time.localtime(time.time())
282 thispage = macro.formatter.page.page_name
283 # does the url have calendar params (= somebody has clicked on prev/next links in calendar) ?
284 if macro.form.has_key('calparms'):
285 text2 = macro.form['calparms'].value
286 args2 = args_re.match(text2)
287 if not args2:
288 return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar calparms "%s"!')) % (text2,)
289 else:
290 has_calparms = 1 # yes!
291 cparmpagename, cparmyear, cparmmonth, cparmoffset, cparmoffset2, cparmheight6 = \
292 parseargs(args2, thispage, currentyear, currentmonth, 0, 0, 0)
293 else:
294 has_calparms = 0
295
296 if text is None: # macro call without parameters
297 parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6 = \
298 [thispage], currentyear, currentmonth, 0, 0, 0
299 else:
300 # parse and check arguments
301 args = args_re.match(text)
302 if not args:
303 return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar arguments "%s"!')) % (text,)
304 else:
305 parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6 = \
306 parseargs(args, thispage, currentyear, currentmonth, 0, 0, 0)
307
308 # does url have calendar params and is THIS the right calendar to modify (we can have multiple
309 # calendars on the same page)?
310 if has_calparms and (cparmpagename,cparmyear,cparmmonth,cparmoffset) == (parmpagename,parmyear,parmmonth,parmoffset):
311 year,month = yearmonthplusoffset(parmyear, parmmonth, parmoffset + cparmoffset2)
312 parmoffset2 = cparmoffset2
313 else:
314 year,month = yearmonthplusoffset(parmyear, parmmonth, parmoffset)
315
316 # get the calendar
317 monthcal = calendar.monthcalendar(year, month)
318
319 # european / US differences
320 months = ('January','February','March','April','May','June','July','August','September','October','November','December')
321 # Set things up for Monday or Sunday as the first day of the week
322 if calendar.firstweekday() == calendar.MONDAY:
323 wkend = (5, 6)
324 wkdays = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
325 if calendar.firstweekday() == calendar.SUNDAY:
326 wkend = (0, 6)
327 wkdays = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
328
329 colorstep = 85
330 p = Page(thispage)
331 querystr = "calparms=%s,%d,%d,%d,%%d" % (string.join(parmpagename,'*'), parmyear, parmmonth, parmoffset)
332 prevlink = p.url(querystr % (parmoffset2 - 1))
333 nextlink = p.url(querystr % (parmoffset2 + 1))
334 prevylink = p.url(querystr % (parmoffset2 - 12))
335 nextylink = p.url(querystr % (parmoffset2 + 12))
336 prevmonth = macro.formatter.url(prevlink, '<-', 'cal-link')
337 nextmonth = macro.formatter.url(nextlink, '->', 'cal-link')
338 prevyear = macro.formatter.url(prevylink, '<<-', 'cal-link')
339 nextyear = macro.formatter.url(nextylink, '->>', 'cal-link')
340
341 if parmpagename <> [thispage]:
342 pagelinks = ''
343 r,g,b = (255, 0, 0)
344 l = len(parmpagename[0])
345 steps = len(parmpagename)
346 maxsteps = (255 / colorstep)
347 if steps > maxsteps:
348 steps = maxsteps
349 chstep = int(l / steps)
350 st = 0
351 while st < l:
352 ch = parmpagename[0][st:st+chstep]
353 r, g, b = cliprgb(r, g, b)
354 pagelinks = pagelinks + '<a style="%s" href="%s">%s</a>' % \
355 ('background-color:#%02x%02x%02x;color:#000000;text-decoration:none' % \
356 (r,g,b), Page(parmpagename[0]).url(), ch)
357 r, g, b = (r, g+colorstep, b)
358 st = st + chstep
359 r, g, b = (255-colorstep, 255, 255-colorstep)
360 for page in parmpagename[1:]:
361 pagelinks = pagelinks + '*<a style="%s" href="%s">%s</a>' % \
362 ('background-color:#%02x%02x%02x;color:#000000;text-decoration:none' % \
363 (r,g,b), Page(page).url(), page)
364 showpagename = ' %s<BR>\n' % pagelinks
365 else:
366 showpagename = ''
367 if calendar.firstweekday() == calendar.SUNDAY:
368 resth1 = ' <th colspan="7" class="cal-header">\n' \
369 '%s' \
370 ' %s %s <b> %s %s</b> %s\n %s\n' \
371 ' </th>\n' % (showpagename, prevyear, prevmonth, months[month-1], str(year), nextmonth, nextyear)
372 if calendar.firstweekday() == calendar.MONDAY:
373 resth1 = ' <th colspan="7" class="cal-header">\n' \
374 '%s' \
375 ' %s %s <b> %s / %s</b> %s\n %s\n' \
376 ' </th>\n' % (showpagename, prevyear, prevmonth, str(year), month, nextmonth, nextyear)
377 restr1 = ' <tr>\n%s </tr>\n' % resth1
378
379 r7 = range(7)
380 restd2 = []
381 for wkday in r7:
382 wday = _(wkdays[wkday])
383 if wkday in wkend:
384 cssday = "cal-weekend"
385 else:
386 cssday = "cal-workday"
387 restd2.append(' <td class="%s" width="14%%">%s</td>\n' % (cssday, wday))
388 restr2 = ' <tr>\n%s </tr>\n' % "".join(restd2)
389
390 if parmheight6:
391 while len(monthcal) < 6:
392 monthcal = monthcal + [[0,0,0,0,0,0,0]]
393
394 restrn = []
395 for week in monthcal:
396 restdn = []
397 for wkday in r7:
398 day = week[wkday]
399 if not day:
400 restdn.append(' <td class="cal-invalidday"> </td>\n')
401 else:
402 csslink = "cal-emptyday"
403 r, g, b, u = (255, 255, 255, 0)
404 page = parmpagename[0]
405 link = "%s/%4d-%02d-%02d" % (page, year, month, day)
406 daypage = Page(link)
407 if daypage.exists():
408 csslink = "cal-usedday"
409 r, g, b, u = (255, 0, 0, 1)
410 else:
411 if wkday in wkend:
412 csslink = "cal-weekend"
413 for otherpage in parmpagename[1:]:
414 otherlink = "%s/%4d-%02d-%02d" % (otherpage, year, month, day)
415 otherdaypage = Page(otherlink)
416 if otherdaypage.exists():
417 csslink = "cal-usedday"
418 if u == 0:
419 r, g, b = (r-colorstep, g, b-colorstep)
420 else:
421 r, g, b = (r, g+colorstep, b)
422 r, g, b = cliprgb(r, g, b)
423 style = 'background-color:#%02x%02x%02x' % (r, g, b)
424 fmtlink = macro.formatter.url(daypage.url(), str(day), csslink)
425 if day == currentday and month == currentmonth and year == currentyear:
426 cssday = "cal-today"
427 fmtlink = "<b>%s</b>" % fmtlink # for browser with CSS probs
428 else:
429 cssday = "cal-nottoday"
430 restdn.append(' <td style="%s" class="%s">%s</td>\n' % (style, cssday, fmtlink))
431 restrn.append(' <tr>\n%s </tr>\n' % "".join(restdn))
432
433 restable = '<table border="2" cellspacing="2" cellpadding="2">\n%s%s%s</table>\n'
434 result = restable % (restr1, restr2, "".join(restrn))
435 return macro.formatter.rawHTML(result)
436
437 # 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.