Attachment 'MonthCalendar-moin13.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 to browse another calendar on the same page,
25 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 * 1.9:
78 * adapted to moin 1.3
79
80
81 TODO:
82 * integrate patch for including day page contents directly into cal
83 * still thinking over: does this make sense in a MonthCalendar?
84 * it would be definitely nice in a week or day calendar (more space to
85 burn)
86 * integr. daycal -link-> monthcal
87
88 ----
89
90 Usage:
91 [[MonthCalendar(BasePage,year,month,monthoffset,monthoffset2,height6)]]
92
93 each parameter can be empty and then defaults to currentpage or currentdate or monthoffset=0
94
95 Samples (paste that to one of your pages for a first try):
96
97 Calendar of current month for current page:
98 [[MonthCalendar]]
99
100 Calendar of last month:
101 [[MonthCalendar(,,,-1)]]
102
103 Calendar of next month:
104 [[MonthCalendar(,,,+1)]]
105
106 Calendar of Page SampleUser, this years december:
107 [[MonthCalendar(SampleUser,,12)]]
108
109 Calendar of current Page, this years december:
110 [[MonthCalendar(,,12)]]
111
112 Calendar of December, 2001:
113 [[MonthCalendar(,2001,12)]]
114
115 Calendar of the month two months after December, 2001
116 (maybe doesn't make much sense, but is possible)
117 [[MonthCalendar(,2001,12,+2)]]
118
119 Calendar of year 2002 (every month padded to height of 6):
120 ||||||Year 2002||
121 ||[[MonthCalendar(,2002,1,,,1)]]||[[MonthCalendar(,2002,2,,,1)]]||[[MonthCalendar(,2002,3,,,1)]]||
122 ||[[MonthCalendar(,2002,4,,,1)]]||[[MonthCalendar(,2002,5,,,1)]]||[[MonthCalendar(,2002,6,,,1)]]||
123 ||[[MonthCalendar(,2002,7,,,1)]]||[[MonthCalendar(,2002,8,,,1)]]||[[MonthCalendar(,2002,9,,,1)]]||
124 ||[[MonthCalendar(,2002,10,,,1)]]||[[MonthCalendar(,2002,11,,,1)]]||[[MonthCalendar(,2002,12,,,1)]]||
125
126 Current calendar of me, also showing entries of A and B:
127 [[MonthCalendar(MyPage*TestUserA*TestUserB)]]
128
129 SubPage calendars:
130 [[MonthCalendar(MyName/CalPrivate)]]
131 [[MonthCalendar(MyName/CalBusiness)]]
132 [[MonthCalendar(MyName/CalBusiness*MyName/CalPrivate)]]
133
134 ----
135
136 You need to have some stylesheet entries like the following.
137 Paste that to default.css / moinmoin.css:
138
139 /* begin css for MonthCalendar macro */
140 /* days without and with pages linked to them */
141 a.cal-emptyday {
142 color: #777777;
143 text-align: center;
144 }
145 a.cal-usedday {
146 font-weight: bold;
147 color: #000000;
148 text-align: center;
149 }
150 /* general stuff: workdays, weekend, today */
151 td.cal-workday {
152 background-color: #DDDDFF;
153 text-align: center;
154 }
155 td.cal-weekend {
156 background-color: #FFDDDD;
157 text-align: center;
158 }
159 td.cal-today {
160 background-color: #CCFFCC;
161 border-style: solid;
162 border-width: 2pt;
163 text-align: center;
164 }
165 /* invalid places on the monthly calendar sheet */
166 td.cal-invalidday {
167 background-color: #CCCCCC;
168 }
169 /* links to prev/next month/year */
170 a.cal-link {
171 color: #000000;
172 text-decoration: none;
173 }
174 th.cal-header {
175 background-color: #DDBBFF;
176 text-align: center;
177 }
178 /* end css for MonthCalendar macro */
179
180 ----
181
182 If you want translated (german) messages, add something like this to
183 i18n/de.py (if you have >=0.11, the weekday translation might be already
184 there):
185
186 'Mon':'Mo','Tue':'Di','Wed':'Mi','Thu':'Do','Fri':'Fr','Sat':'Sa','Sun':'So',
187
188 'Invalid MonthCalendar calparms "%s"!':
189 'Ung\366ltige MonthCalendar calparms "%s"!',
190
191 'Invalid MonthCalendar arguments "%s"!':
192 'Ung\366ltige MonthCalendar Argumente "%s"!',
193
194 """
195
196 Dependencies = ['namespace','time']
197
198 from MoinMoin import wikiutil
199 from MoinMoin.Page import Page
200 import re, calendar, time
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 request = macro.request
284 formatter = macro.formatter
285 _ = request.getText
286
287 # return immediately if getting links for the current page
288 if request.mode_getpagelinks:
289 return ''
290
291 args_re=re.compile(_args_re_pattern)
292
293 currentyear, currentmonth, currentday, h, m, s, wd, yd, ds = time.localtime(time.time())
294 thispage = formatter.page.page_name
295 # does the url have calendar params (= somebody has clicked on prev/next links in calendar) ?
296 if macro.form.has_key('calparms'):
297 text2 = macro.form['calparms'][0]
298 args2 = args_re.match(text2)
299 if not args2:
300 return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar calparms "%s"!')) % (text2,)
301 else:
302 has_calparms = 1 # yes!
303 cparmpagename, cparmyear, cparmmonth, cparmoffset, cparmoffset2, cparmheight6 = \
304 parseargs(args2, thispage, currentyear, currentmonth, 0, 0, 0)
305 else:
306 has_calparms = 0
307
308 if text is None: # macro call without parameters
309 parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6 = \
310 [thispage], currentyear, currentmonth, 0, 0, 0
311 else:
312 # parse and check arguments
313 args = args_re.match(text)
314 if not args:
315 return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar arguments "%s"!')) % (text,)
316 else:
317 parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6 = \
318 parseargs(args, thispage, currentyear, currentmonth, 0, 0, 0)
319
320 # does url have calendar params and is THIS the right calendar to modify (we can have multiple
321 # calendars on the same page)?
322 if has_calparms and (cparmpagename,cparmyear,cparmmonth,cparmoffset) == (parmpagename,parmyear,parmmonth,parmoffset):
323 year,month = yearmonthplusoffset(parmyear, parmmonth, parmoffset + cparmoffset2)
324 parmoffset2 = cparmoffset2
325 else:
326 year,month = yearmonthplusoffset(parmyear, parmmonth, parmoffset)
327
328 # get the calendar
329 monthcal = calendar.monthcalendar(year, month)
330
331 # european / US differences
332 months = ('January','February','March','April','May','June','July','August','September','October','November','December')
333 # Set things up for Monday or Sunday as the first day of the week
334 if calendar.firstweekday() == calendar.MONDAY:
335 wkend = (5, 6)
336 wkdays = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
337 if calendar.firstweekday() == calendar.SUNDAY:
338 wkend = (0, 6)
339 wkdays = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
340
341 colorstep = 85
342 p = Page(request, thispage)
343 querystr = "calparms=%s,%d,%d,%d,%%d" % ('*'.join(parmpagename), parmyear, parmmonth, parmoffset)
344 prevlink = p.url(request, querystr % (parmoffset2 - 1))
345 nextlink = p.url(request, querystr % (parmoffset2 + 1))
346 prevylink = p.url(request, querystr % (parmoffset2 - 12))
347 nextylink = p.url(request, querystr % (parmoffset2 + 12))
348 prevmonth = formatter.url(1, prevlink, 'cal-link') + '<-' + formatter.url(0)
349 nextmonth = formatter.url(1, nextlink, 'cal-link') + '->' + formatter.url(0)
350 prevyear = formatter.url(1, prevylink, 'cal-link') + '<<-' + formatter.url(0)
351 nextyear = formatter.url(1, nextylink, 'cal-link') + '->>' + formatter.url(0)
352
353 if parmpagename <> [thispage]:
354 pagelinks = ''
355 r,g,b = (255, 0, 0)
356 l = len(parmpagename[0])
357 steps = len(parmpagename)
358 maxsteps = (255 / colorstep)
359 if steps > maxsteps:
360 steps = maxsteps
361 chstep = int(l / steps)
362 st = 0
363 while st < l:
364 ch = parmpagename[0][st:st+chstep]
365 r, g, b = cliprgb(r, g, b)
366 pagelinks = pagelinks + '<a style="%s" href="%s">%s</a>' % \
367 ('background-color:#%02x%02x%02x;color:#000000;text-decoration:none' % \
368 (r,g,b), Page(request, parmpagename[0]).url(request), ch)
369 r, g, b = (r, g+colorstep, b)
370 st = st + chstep
371 r, g, b = (255-colorstep, 255, 255-colorstep)
372 for page in parmpagename[1:]:
373 pagelinks = pagelinks + '*<a style="%s" href="%s">%s</a>' % \
374 ('background-color:#%02x%02x%02x;color:#000000;text-decoration:none' % \
375 (r,g,b), Page(request, page).url(request), page)
376 showpagename = ' %s<BR>\n' % pagelinks
377 else:
378 showpagename = ''
379 if calendar.firstweekday() == calendar.SUNDAY:
380 resth1 = ' <th colspan="7" class="cal-header">\n' \
381 '%s' \
382 ' %s %s <b> %s %s</b> %s\n %s\n' \
383 ' </th>\n' % (showpagename, prevyear, prevmonth, months[month-1], str(year), nextmonth, nextyear)
384 if calendar.firstweekday() == calendar.MONDAY:
385 resth1 = ' <th colspan="7" class="cal-header">\n' \
386 '%s' \
387 ' %s %s <b> %s / %s</b> %s\n %s\n' \
388 ' </th>\n' % (showpagename, prevyear, prevmonth, str(year), month, nextmonth, nextyear)
389 restr1 = ' <tr>\n%s </tr>\n' % resth1
390
391 r7 = range(7)
392 restd2 = []
393 for wkday in r7:
394 wday = _(wkdays[wkday])
395 if wkday in wkend:
396 cssday = "cal-weekend"
397 else:
398 cssday = "cal-workday"
399 restd2.append(' <td class="%s" width="14%%">%s</td>\n' % (cssday, wday))
400 restr2 = ' <tr>\n%s </tr>\n' % "".join(restd2)
401
402 if parmheight6:
403 while len(monthcal) < 6:
404 monthcal = monthcal + [[0,0,0,0,0,0,0]]
405
406 restrn = []
407 for week in monthcal:
408 restdn = []
409 for wkday in r7:
410 day = week[wkday]
411 if not day:
412 restdn.append(' <td class="cal-invalidday"> </td>\n')
413 else:
414 csslink = "cal-emptyday"
415 r, g, b, u = (255, 255, 255, 0)
416 page = parmpagename[0]
417 link = "%s/%4d-%02d-%02d" % (page, year, month, day)
418 daypage = Page(request, link)
419 if daypage.exists():
420 csslink = "cal-usedday"
421 r, g, b, u = (255, 0, 0, 1)
422 else:
423 if wkday in wkend:
424 csslink = "cal-weekend"
425 for otherpage in parmpagename[1:]:
426 otherlink = "%s/%4d-%02d-%02d" % (otherpage, year, month, day)
427 otherdaypage = Page(request, otherlink)
428 if otherdaypage.exists():
429 csslink = "cal-usedday"
430 if u == 0:
431 r, g, b = (r-colorstep, g, b-colorstep)
432 else:
433 r, g, b = (r, g+colorstep, b)
434 r, g, b = cliprgb(r, g, b)
435 style = 'background-color:#%02x%02x%02x' % (r, g, b)
436 fmtlink = formatter.url(1, daypage.url(request), csslink) + str(day) + formatter.url(0)
437 if day == currentday and month == currentmonth and year == currentyear:
438 cssday = "cal-today"
439 fmtlink = "<b>%s</b>" % fmtlink # for browser with CSS probs
440 else:
441 cssday = "cal-nottoday"
442 restdn.append(' <td style="%s" class="%s">%s</td>\n' % (style, cssday, fmtlink))
443 restrn.append(' <tr>\n%s </tr>\n' % "".join(restdn))
444
445 restable = '<table border="2" cellspacing="2" cellpadding="2">\n%s%s%s</table>\n'
446 result = restable % (restr1, restr2, "".join(restrn))
447 return formatter.rawHTML(result)
448
449 # 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.