Attachment 'MonthCalendarHack-1.1.py'
Download 1 """
2 MoinMoin - MonthCalendarHack Macro
3
4 This macro is a hack of the MonthCalendar one delivered with MoinMoin, to enable subpages titles in form
5
6 = title =
7
8 or
9
10 '''title'''
11
12 You can use this macro to put a month's calendar page on a Wiki page.
13
14 The days are links to Wiki pages following this naming convention:
15 BasePageName/year-month-day
16
17 @copyright: 2002-2005 by Thomas Waldmann <ThomasWaldmann@gmx.de>
18 @copyright: 2007- by Eric Veiras Galisson
19 @license: GNU GPL - see http://www.gnu.org/licenses/old-licenses/gpl-1.0.txt for details.
20
21 Revisions:
22 * first revision without a number (=1.0):
23 * work with MoinMoin 1.5
24 * 1.1:
25 * adaptation to MoinMoin 1.6
26
27 Usage:
28 <<MonthCalendarHack(BasePage,year,month,monthoffset,monthoffset2,height6)>>
29
30 each parameter can be empty and then defaults to currentpage or currentdate or monthoffset=0
31
32 Samples (paste that to one of your pages for a first try):
33
34 Calendar of current month for current page:
35 <<MonthCalendar>>
36
37 Calendar of last month:
38 <<MonthCalendarHack(,,,-1)>>
39
40 Calendar of next month:
41 <<MonthCalendarHack(,,,+1)>>
42
43 Calendar of Page SampleUser, this years december:
44 <<MonthCalendarHack(SampleUser,,12)>>
45
46 Calendar of current Page, this years december:
47 <<MonthCalendarHack(,,12)>>
48
49 Calendar of December, 2001:
50 <<MonthCalendarHack(,2001,12)>>
51
52 Calendar of the month two months after December, 2001
53 (maybe doesn't make much sense, but is possible)
54 <<MonthCalendarHack(,2001,12,+2)>>
55
56 Calendar of year 2002 (every month padded to height of 6):
57 ||||||Year 2002||
58 ||<<MonthCalendarHack(,2002,1,,,1)>>||<<MonthCalendarHack(,2002,2,,,1)>>||<<MonthCalendarHack(,2002,3,,,1)>>||
59 ||<<MonthCalendarHack(,2002,4,,,1)>>||<<MonthCalendarHack(,2002,5,,,1)>>||<<MonthCalendarHack(,2002,6,,,1)>>||
60 ||<<MonthCalendarHack(,2002,7,,,1)>>||<<MonthCalendarHack(,2002,8,,,1)>>||<<MonthCalendarHack(,2002,9,,,1)>>||
61 ||<<MonthCalendarHack(,2002,10,,,1)>>||<<MonthCalendarHack(,2002,11,,,1)>>||<<MonthCalendarHack(,2002,12,,,1)>>||
62
63 Current calendar of me, also showing entries of A and B:
64 <<MonthCalendarHack(MyPage*TestUserA*TestUserB)>>
65
66 SubPage calendars:
67 <<MonthCalendarHack(MyName/CalPrivate)>>
68 <<MonthCalendarHack(MyName/CalBusiness)>>
69 <<MonthCalendarHack(MyName/CalBusiness*MyName/CalPrivate)>>
70
71
72 Anniversary Calendars: (no year data)
73 <<MonthCalendarHack(Yearly,,,+1,,6,1)>>
74
75 This creates calendars of the format Yearly/MM-DD
76 By leaving out the year, you can set birthdays, and anniversaries in this
77 calendar and not have to re-enter each year.
78
79 This creates a calendar which uses MonthCalendarTemplate for directly editing
80 nonexisting day pages:
81 <<MonthCalendarHack(,,,,,,MonthCalendarTemplate)>>
82 """
83
84 Dependencies = ['namespace', 'time', ]
85
86 import re, calendar, time
87
88 from MoinMoin import wikiutil
89 from MoinMoin.Page import Page
90
91 # The following line sets the calendar to have either Sunday or Monday as
92 # the first day of the week. Only SUNDAY or MONDAY (case sensitive) are
93 # valid here. All other values will not make good calendars.
94 # If set to Sunday, the calendar is displayed at "March 2003" vs. "2003 / 3" also.
95 # XXX change here ----------------vvvvvv
96 calendar.setfirstweekday(calendar.MONDAY)
97
98 def cliprgb(r, g, b):
99 """ clip r,g,b values into range 0..254 """
100 def clip(x):
101 """ clip x value into range 0..254 """
102 if x < 0:
103 x = 0
104 elif x > 254:
105 x = 254
106 return x
107 return clip(r), clip(g), clip(b)
108
109 def yearmonthplusoffset(year, month, offset):
110 """ calculate new year/month from year/month and offset """
111 month += offset
112 # handle offset and under/overflows - quick and dirty, yes!
113 while month < 1:
114 month += 12
115 year -= 1
116 while month > 12:
117 month -= 12
118 year += 1
119 return year, month
120
121 def parseargs(args, defpagename, defyear, defmonth, defoffset, defoffset2, defheight6, defanniversary, deftemplate):
122 """ parse macro arguments """
123 strpagename = args.group('basepage')
124 if strpagename:
125 parmpagename = wikiutil.unquoteWikiname(strpagename)
126 else:
127 parmpagename = defpagename
128 # multiple pagenames separated by "*" - split into list of pagenames
129 parmpagename = re.split(r'\*', parmpagename)
130
131 strtemplate = args.group('template')
132 if strtemplate:
133 parmtemplate = wikiutil.unquoteWikiname(strtemplate)
134 else:
135 parmtemplate = deftemplate
136
137 def getint(args, name, default):
138 s = args.group(name)
139 i = default
140 if s:
141 try:
142 i = int(s)
143 except:
144 pass
145 return i
146
147 parmyear = getint(args, 'year', defyear)
148 parmmonth = getint(args, 'month', defmonth)
149 parmoffset = getint(args, 'offset', defoffset)
150 parmoffset2 = getint(args, 'offset2', defoffset2)
151 parmheight6 = getint(args, 'height6', defheight6)
152 parmanniversary = getint(args, 'anniversary', defanniversary)
153
154 return parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6, parmanniversary, parmtemplate
155
156 # FIXME: vvvvvv is there a better way for matching a pagename ?
157 _arg_basepage = r'\s*(?P<basepage>[^, ]+)?\s*'
158 _arg_year = r',\s*(?P<year>\d+)?\s*'
159 _arg_month = r',\s*(?P<month>\d+)?\s*'
160 _arg_offset = r',\s*(?P<offset>[+-]?\d+)?\s*'
161 _arg_offset2 = r',\s*(?P<offset2>[+-]?\d+)?\s*'
162 _arg_height6 = r',\s*(?P<height6>[+-]?\d+)?\s*'
163 _arg_anniversary = r',\s*(?P<anniversary>[+-]?\d+)?\s*'
164 _arg_template = r',\s*(?P<template>[^, ]+)?\s*' # XXX see basepage comment
165 _args_re_pattern = r'^(%s)?(%s)?(%s)?(%s)?(%s)?(%s)?(%s)?(%s)?$' % \
166 (_arg_basepage, _arg_year, _arg_month,
167 _arg_offset, _arg_offset2, _arg_height6, _arg_anniversary, _arg_template)
168
169
170 def execute(macro, text):
171 request = macro.request
172 formatter = macro.formatter
173 _ = request.getText
174
175 # return immediately if getting links for the current page
176 if request.mode_getpagelinks:
177 return ''
178
179 args_re = re.compile(_args_re_pattern)
180
181 currentyear, currentmonth, currentday, h, m, s, wd, yd, ds = request.user.getTime(time.time())
182 thispage = formatter.page.page_name
183 # does the url have calendar params (= somebody has clicked on prev/next links in calendar) ?
184 if 'calparms' in macro.form:
185 text2 = macro.form['calparms'][0]
186 args2 = args_re.match(text2)
187 if not args2:
188 return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar calparms "%s"!', formatted=False)) % (text2,)
189 else:
190 has_calparms = 1 # yes!
191 cparmpagename, cparmyear, cparmmonth, cparmoffset, cparmoffset2, cparmheight6, cparmanniversary, cparmtemplate = \
192 parseargs(args2, thispage, currentyear, currentmonth, 0, 0, 0, 0, '')
193 else:
194 has_calparms = 0
195
196 if text is None: # macro call without parameters
197 parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6, anniversary, parmtemplate = \
198 [thispage], currentyear, currentmonth, 0, 0, 0, 0, ''
199 else:
200 # parse and check arguments
201 args = args_re.match(text)
202 if not args:
203 return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar arguments "%s"!', formatted=False)) % (text,)
204 else:
205 parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6, anniversary, parmtemplate = \
206 parseargs(args, thispage, currentyear, currentmonth, 0, 0, 0, 0, '')
207
208 # does url have calendar params and is THIS the right calendar to modify (we can have multiple
209 # calendars on the same page)?
210 #if has_calparms and (cparmpagename,cparmyear,cparmmonth,cparmoffset) == (parmpagename,parmyear,parmmonth,parmoffset):
211
212 # move all calendars when using the navigation:
213 if has_calparms and cparmpagename == parmpagename:
214 year, month = yearmonthplusoffset(parmyear, parmmonth, parmoffset + cparmoffset2)
215 parmoffset2 = cparmoffset2
216 parmtemplate = cparmtemplate
217 else:
218 year, month = yearmonthplusoffset(parmyear, parmmonth, parmoffset)
219
220 if request.isSpiderAgent and abs(currentyear - year) > 1:
221 return '' # this is a bot and it didn't follow the rules (see below)
222 if currentyear == year:
223 attrs = {}
224 else:
225 attrs = {'rel': 'nofollow' } # otherwise even well-behaved bots will index forever
226
227 # get the calendar
228 monthcal = calendar.monthcalendar(year, month)
229
230 # european / US differences
231 months = ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
232 # Set things up for Monday or Sunday as the first day of the week
233 if calendar.firstweekday() == calendar.MONDAY:
234 wkend = (5, 6)
235 wkdays = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
236 if calendar.firstweekday() == calendar.SUNDAY:
237 wkend = (0, 6)
238 wkdays = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
239
240 colorstep = 85
241 p = Page(request, thispage)
242 qpagenames = '*'.join([wikiutil.quoteWikinameURL(pn) for pn in parmpagename])
243 qtemplate = wikiutil.quoteWikinameURL(parmtemplate)
244 querystr = "calparms=%%s,%d,%d,%d,%%d,%%s" % (parmyear, parmmonth, parmoffset)
245 prevlink = p.url(request, querystr % (qpagenames, parmoffset2 - 1, qtemplate), relative=False)
246 nextlink = p.url(request, querystr % (qpagenames, parmoffset2 + 1, qtemplate), relative=False)
247 prevylink = p.url(request, querystr % (qpagenames, parmoffset2 - 12, qtemplate), relative=False)
248 nextylink = p.url(request, querystr % (qpagenames, parmoffset2 + 12, qtemplate), relative=False)
249
250 prevmonth = formatter.url(1, prevlink, 'cal-link', **attrs) + '<' + formatter.url(0)
251 nextmonth = formatter.url(1, nextlink, 'cal-link', **attrs) + '>' + formatter.url(0)
252 prevyear = formatter.url(1, prevylink, 'cal-link', **attrs) + '<<' + formatter.url(0)
253 nextyear = formatter.url(1, nextylink, 'cal-link', **attrs) + '>>' + formatter.url(0)
254
255 if parmpagename != [thispage]:
256 pagelinks = ''
257 r, g, b = (255, 0, 0)
258 l = len(parmpagename[0])
259 steps = len(parmpagename)
260 maxsteps = (255 / colorstep)
261 if steps > maxsteps:
262 steps = maxsteps
263 chstep = int(l / steps)
264 st = 0
265 while st < l:
266 ch = parmpagename[0][st:st+chstep]
267 r, g, b = cliprgb(r, g, b)
268 link = Page(request, parmpagename[0]).link_to(request, ch,
269 rel='nofollow',
270 style='background-color:#%02x%02x%02x;color:#000000;text-decoration:none' % (r, g, b))
271 pagelinks = pagelinks + link
272 r, g, b = (r, g+colorstep, b)
273 st = st + chstep
274 r, g, b = (255-colorstep, 255, 255-colorstep)
275 for page in parmpagename[1:]:
276 link = Page(request, page).link_to(request, page,
277 rel='nofollow',
278 style='background-color:#%02x%02x%02x;color:#000000;text-decoration:none' % (r, g, b))
279 pagelinks = pagelinks + '*' + link
280 showpagename = ' %s<BR>\n' % pagelinks
281 else:
282 showpagename = ''
283 if calendar.firstweekday() == calendar.SUNDAY:
284 resth1 = ' <th colspan="7" class="cal-header">\n' \
285 '%s' \
286 ' %s %s <b> %s %s</b> %s\n %s\n' \
287 ' </th>\n' % (showpagename, prevyear, prevmonth, months[month-1], str(year), nextmonth, nextyear)
288 if calendar.firstweekday() == calendar.MONDAY:
289 resth1 = ' <th colspan="7" class="cal-header">\n' \
290 '%s' \
291 ' %s %s <b> %s / %s</b> %s\n %s\n' \
292 ' </th>\n' % (showpagename, prevyear, prevmonth, str(year), month, nextmonth, nextyear)
293 restr1 = ' <tr>\n%s </tr>\n' % resth1
294
295 r7 = range(7)
296 restd2 = []
297 for wkday in r7:
298 wday = _(wkdays[wkday], formatted=False)
299 if wkday in wkend:
300 cssday = "cal-weekend"
301 else:
302 cssday = "cal-workday"
303 restd2.append(' <td class="%s" width="14%%">%s</td>\n' % (cssday, wday))
304 restr2 = ' <tr>\n%s </tr>\n' % "".join(restd2)
305
306 if parmheight6:
307 while len(monthcal) < 6:
308 monthcal = monthcal + [[0, 0, 0, 0, 0, 0, 0]]
309
310 maketip_js = []
311 restrn = []
312 for week in monthcal:
313 restdn = []
314 for wkday in r7:
315 day = week[wkday]
316 if not day:
317 restdn.append(' <td class="cal-invalidday"> </td>\n')
318 else:
319 page = parmpagename[0]
320 if anniversary:
321 link = "%s/%02d-%02d" % (page, month, day)
322 else:
323 link = "%s/%4d-%02d-%02d" % (page, year, month, day)
324 daypage = Page(request, link)
325 if daypage.exists() and request.user.may.read(link):
326 csslink = "cal-usedday"
327 query = {}
328 r, g, b, u = (255, 0, 0, 1)
329 daycontent = daypage.get_raw_body()
330 header1_re = re.compile(r"^\s*('''\s*(.*)\s*'''|=\s+(.*)\s+=)\s*$", re.MULTILINE) # re.UNICODE
331 titletext = []
332 for match in header1_re.finditer(daycontent):
333 if match:
334 if match.group(2) == None:
335 title = match.group(3)
336 else:
337 title = match.group(2)
338 title = wikiutil.escape(title).replace("'", "\\'")
339 titletext.append(title)
340 tipname = link
341 tiptitle = link
342 tiptext = '<br>'.join(titletext)
343 maketip_js.append("maketip('%s','%s','%s');" % (tipname, tiptitle, tiptext))
344 attrs = {'onMouseOver': "tip('%s')" % tipname,
345 'onMouseOut': "untip()"}
346 else:
347 csslink = "cal-emptyday"
348 if parmtemplate:
349 query = {'action': 'edit', 'template': parmtemplate}
350 else:
351 query = {}
352 r, g, b, u = (255, 255, 255, 0)
353 if wkday in wkend:
354 csslink = "cal-weekend"
355 attrs = {'rel': 'nofollow'}
356 for otherpage in parmpagename[1:]:
357 otherlink = "%s/%4d-%02d-%02d" % (otherpage, year, month, day)
358 otherdaypage = Page(request, otherlink)
359 if otherdaypage.exists():
360 csslink = "cal-usedday"
361 if u == 0:
362 r, g, b = (r-colorstep, g, b-colorstep)
363 else:
364 r, g, b = (r, g+colorstep, b)
365 r, g, b = cliprgb(r, g, b)
366 style = 'background-color:#%02x%02x%02x' % (r, g, b)
367 fmtlink = formatter.url(1, daypage.url(request, query, relative=False), csslink, **attrs) + str(day) + formatter.url(0)
368 if day == currentday and month == currentmonth and year == currentyear:
369 cssday = "cal-today"
370 fmtlink = "<b>%s</b>" % fmtlink # for browser with CSS probs
371 else:
372 cssday = "cal-nottoday"
373 restdn.append(' <td style="%s" class="%s">%s</td>\n' % (style, cssday, fmtlink))
374 restrn.append(' <tr>\n%s </tr>\n' % "".join(restdn))
375
376 restable = '<table border="2" cellspacing="2" cellpadding="2">\n%s%s%s</table>\n'
377 restable = restable % (restr1, restr2, "".join(restrn))
378
379 result = """\
380 <script language="JavaScript" type="text/javascript" src="%s/common/js/infobox.js"></script>
381 <div id="infodiv" style="position:absolute; visibility:hidden; z-index:20; top:-999em; left:0px;"></div>
382 <script language="JavaScript" type="text/javascript">
383 <!--
384 %s
385 // -->
386 </script>
387 %s
388 """ % (request.cfg.url_prefix_static, "\n".join(maketip_js), restable)
389 return formatter.rawHTML(result)
390
391 # 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.