Attachment 'MonthCalendar-moin12.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 /* end css for MonthCalendar macro */
 176 
 177 ----
 178 
 179     If you want translated (german) messages, add something like this to
 180     i18n/de.py (if you have >=0.11, the weekday translation might be already
 181     there):
 182     
 183 'Mon':'Mo','Tue':'Di','Wed':'Mi','Thu':'Do','Fri':'Fr','Sat':'Sa','Sun':'So',
 184     
 185 'Invalid MonthCalendar calparms "%s"!':
 186 'Ung\366ltige MonthCalendar calparms "%s"!',
 187 
 188 'Invalid MonthCalendar arguments "%s"!':
 189 'Ung\366ltige MonthCalendar Argumente "%s"!',
 190 
 191 """
 192 
 193 # Imports
 194 from MoinMoin import config, user, wikiutil
 195 from MoinMoin.Page import Page
 196 import sys, re, calendar, time, string
 197 
 198 # The following line sets the calendar to have either Sunday or Monday as
 199 # the first day of the week. Only SUNDAY or MONDAY (case sensitive) are
 200 # valid here.  All other values will not make good calendars.
 201 # If set to Sunday, the calendar is displayed at "March 2003" vs. "2003 / 3" also.
 202 # XXX change here ----------------vvvvvv
 203 calendar.setfirstweekday(calendar.MONDAY)
 204 
 205 def cliprgb(r,g,b): # don't use 255!
 206     if r < 0:   r=0
 207     if r > 254: r=254
 208     if b < 0:   b=0
 209     if b > 254: b=254
 210     if g < 0:   g=0
 211     if g > 254: g=254
 212     return r, g, b
 213 
 214 def yearmonthplusoffset(year, month, offset):
 215     month = month+offset
 216     # handle offset and under/overflows - quick and dirty, yes!
 217     while month < 1:
 218         month = month+12
 219         year = year-1
 220     while month > 12:
 221         month = month-12
 222         year = year+1
 223     return year, month
 224 
 225 def parseargs(args, defpagename, defyear, defmonth, defoffset, defoffset2, defheight6):
 226     strpagename = args.group('basepage')
 227     if strpagename:
 228         parmpagename = strpagename
 229     else:
 230         parmpagename = defpagename
 231     # multiple pagenames separated by "*" - split into list of pagenames
 232     parmpagename = re.split(r'\*', parmpagename)
 233 
 234     stryear = args.group('year')
 235     if stryear:
 236         parmyear = int(stryear)
 237     else:
 238         parmyear = defyear
 239 
 240     strmonth = args.group('month')
 241     if strmonth:
 242         parmmonth = int(strmonth)
 243     else:
 244         parmmonth = defmonth
 245     
 246     stroffset = args.group('offset')
 247     if stroffset:
 248         parmoffset = int(stroffset)
 249     else:
 250         parmoffset = defoffset
 251 
 252     stroffset2 = args.group('offset2')
 253     if stroffset2:
 254         parmoffset2 = int(stroffset2)
 255     else:
 256         parmoffset2 = defoffset2
 257 
 258     strheight6 = args.group('height6')
 259     if strheight6:
 260         parmheight6 = int(strheight6)
 261     else:
 262         parmheight6 = defheight6
 263 
 264     return parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6
 265         
 266 # FIXME:                          vvvvvv is there a better way for matching a pagename ?
 267 _arg_basepage = r'\s*(?P<basepage>[^, ]+)?\s*'
 268 _arg_year = r',\s*(?P<year>\d+)?\s*'
 269 _arg_month = r',\s*(?P<month>\d+)?\s*'
 270 _arg_offset = r',\s*(?P<offset>[+-]?\d+)?\s*'
 271 _arg_offset2 = r',\s*(?P<offset2>[+-]?\d+)?\s*'
 272 _arg_height6 = r',\s*(?P<height6>[+-]?\d+)?\s*'
 273 _args_re_pattern = r'^(%s)?(%s)?(%s)?(%s)?(%s)?(%s)?$' % \
 274                    (_arg_basepage,_arg_year,_arg_month, \
 275 		    _arg_offset,_arg_offset2,_arg_height6)
 276 
 277 
 278 def execute(macro, text):
 279     _ = macro.request.getText
 280 
 281     # return immediately if getting links for the current page
 282     if macro.request.mode_getpagelinks:
 283         return ''
 284 
 285     args_re=re.compile(_args_re_pattern)
 286     
 287     currentyear, currentmonth, currentday, h, m, s, wd, yd, ds = time.localtime(time.time())
 288     thispage = macro.formatter.page.page_name
 289     # does the url have calendar params (= somebody has clicked on prev/next links in calendar) ?
 290     if macro.form.has_key('calparms'):
 291         text2 = macro.form['calparms'][0]
 292         args2 = args_re.match(text2)
 293         if not args2:
 294             return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar calparms "%s"!')) % (text2,)
 295         else:
 296 	    has_calparms = 1 # yes!
 297 	    cparmpagename, cparmyear, cparmmonth, cparmoffset, cparmoffset2, cparmheight6 = \
 298                 parseargs(args2, thispage, currentyear, currentmonth, 0, 0, 0)
 299     else:
 300         has_calparms = 0
 301 	
 302     if text is None: # macro call without parameters
 303         parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6 = \
 304 	    [thispage], currentyear, currentmonth, 0, 0, 0
 305     else:
 306         # parse and check arguments
 307         args = args_re.match(text)
 308         if not args:
 309             return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar arguments "%s"!')) % (text,)
 310         else:
 311 	    parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6 = \
 312 	        parseargs(args, thispage, currentyear, currentmonth, 0, 0, 0)
 313 
 314     # does url have calendar params and is THIS the right calendar to modify (we can have multiple
 315     # calendars on the same page)?
 316     if has_calparms and (cparmpagename,cparmyear,cparmmonth,cparmoffset) == (parmpagename,parmyear,parmmonth,parmoffset):
 317         year,month = yearmonthplusoffset(parmyear, parmmonth, parmoffset + cparmoffset2)
 318 	parmoffset2 = cparmoffset2
 319     else:
 320         year,month = yearmonthplusoffset(parmyear, parmmonth, parmoffset)
 321 
 322     # get the calendar
 323     monthcal = calendar.monthcalendar(year, month)
 324 
 325     # european / US differences
 326     months = ('January','February','March','April','May','June','July','August','September','October','November','December')
 327     # Set things up for Monday or Sunday as the first day of the week
 328     if calendar.firstweekday() == calendar.MONDAY:
 329         wkend = (5, 6)
 330         wkdays = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
 331     if calendar.firstweekday() == calendar.SUNDAY:
 332         wkend = (0, 6)
 333         wkdays = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
 334 
 335     colorstep = 85
 336     p = Page(thispage)
 337     querystr = "calparms=%s,%d,%d,%d,%%d" % (string.join(parmpagename,'*'), parmyear, parmmonth, parmoffset)
 338     prevlink  = p.url(macro.request, querystr % (parmoffset2 - 1))
 339     nextlink  = p.url(macro.request, querystr % (parmoffset2 + 1))
 340     prevylink = p.url(macro.request, querystr % (parmoffset2 - 12))
 341     nextylink = p.url(macro.request, querystr % (parmoffset2 + 12))
 342     prevmonth = macro.formatter.url(prevlink, '&lt;-', 'cal-link')
 343     nextmonth = macro.formatter.url(nextlink, '-&gt;', 'cal-link')
 344     prevyear  = macro.formatter.url(prevylink, '&lt;&lt;-', 'cal-link')
 345     nextyear  = macro.formatter.url(nextylink, '-&gt;&gt;', 'cal-link')
 346     
 347     if parmpagename <> [thispage]:
 348         pagelinks = ''
 349         r,g,b = (255, 0, 0)
 350 	l = len(parmpagename[0])
 351         steps = len(parmpagename)
 352 	maxsteps = (255 / colorstep)
 353 	if steps > maxsteps:
 354 	    steps = maxsteps
 355 	chstep = int(l / steps)
 356 	st = 0
 357 	while st < l:
 358 	    ch = parmpagename[0][st:st+chstep]
 359 	    r, g, b = cliprgb(r, g, b)
 360 	    pagelinks = pagelinks + '<a style="%s" href="%s">%s</a>' % \
 361                 ('background-color:#%02x%02x%02x;color:#000000;text-decoration:none' % \
 362                     (r,g,b), Page(parmpagename[0]).url(macro.request), ch)
 363 	    r, g, b = (r, g+colorstep, b)
 364 	    st = st + chstep
 365         r, g, b = (255-colorstep, 255, 255-colorstep)
 366         for page in parmpagename[1:]:
 367 	    pagelinks = pagelinks + '*<a style="%s" href="%s">%s</a>' % \
 368 	                    ('background-color:#%02x%02x%02x;color:#000000;text-decoration:none' % \
 369                                 (r,g,b), Page(page).url(macro.request), page)
 370         showpagename = '   %s<BR>\n' % pagelinks
 371     else:
 372         showpagename = ''
 373     if calendar.firstweekday() == calendar.SUNDAY:
 374         resth1 = '  <th colspan="7" class="cal-header">\n' \
 375                  '%s' \
 376                  '   %s&nbsp;%s&nbsp;<b>&nbsp;%s&nbsp;%s</b>&nbsp;%s\n&nbsp;%s\n' \
 377                  '  </th>\n' % (showpagename, prevyear, prevmonth, months[month-1], str(year), nextmonth, nextyear)
 378     if calendar.firstweekday() == calendar.MONDAY:
 379         resth1 = '  <th colspan="7" class="cal-header">\n' \
 380                  '%s' \
 381 	         '   %s&nbsp;%s&nbsp;<b>&nbsp;%s&nbsp;/&nbsp;%s</b>&nbsp;%s\n&nbsp;%s\n' \
 382                  '  </th>\n' % (showpagename, prevyear, prevmonth, str(year), month, nextmonth, nextyear)
 383     restr1 = ' <tr>\n%s </tr>\n' % resth1
 384 
 385     r7 = range(7)
 386     restd2 = []
 387     for wkday in r7:
 388         wday = _(wkdays[wkday])
 389         if wkday in wkend:
 390             cssday = "cal-weekend"
 391         else:
 392             cssday = "cal-workday"
 393         restd2.append('  <td class="%s" width="14%%">%s</td>\n' % (cssday, wday))
 394     restr2 = ' <tr>\n%s </tr>\n' % "".join(restd2)
 395  
 396     if parmheight6:
 397         while len(monthcal) < 6:
 398             monthcal = monthcal + [[0,0,0,0,0,0,0]]
 399 	
 400     restrn = []
 401     for week in monthcal:
 402 	restdn = []
 403         for wkday in r7:
 404             day = week[wkday]
 405             if not day:
 406                 restdn.append('  <td class="cal-invalidday">&nbsp;</td>\n')
 407             else:
 408 	        csslink = "cal-emptyday"
 409 		r, g, b, u = (255, 255, 255, 0)
 410 		page = parmpagename[0]
 411                 link = "%s/%4d-%02d-%02d" % (page, year, month, day)
 412 	        daypage = Page(link)
 413 	        if daypage.exists():
 414     	            csslink = "cal-usedday"
 415 		    r, g, b, u = (255, 0, 0, 1)
 416 		else:
 417                     if wkday in wkend:
 418                         csslink = "cal-weekend"
 419                 for otherpage in parmpagename[1:]:
 420                     otherlink = "%s/%4d-%02d-%02d" % (otherpage, year, month, day)
 421 	            otherdaypage = Page(otherlink)
 422 	            if otherdaypage.exists():
 423     	                csslink = "cal-usedday"
 424 			if u == 0:
 425 			    r, g, b = (r-colorstep, g, b-colorstep)
 426 			else:
 427 			    r, g, b = (r, g+colorstep, b)
 428 		r, g, b = cliprgb(r, g, b)
 429 		style = 'background-color:#%02x%02x%02x' % (r, g, b)
 430 	        fmtlink = macro.formatter.url(daypage.url(macro.request), str(day), csslink)
 431 	        if day == currentday and month == currentmonth and year == currentyear:
 432 	            cssday = "cal-today"
 433                     fmtlink = "<b>%s</b>" % fmtlink # for browser with CSS probs
 434 		else:
 435 		    cssday = "cal-nottoday"
 436 	        restdn.append('  <td style="%s" class="%s">%s</td>\n' % (style, cssday, fmtlink))
 437         restrn.append(' <tr>\n%s </tr>\n' % "".join(restdn))
 438 
 439     restable = '<table border="2" cellspacing="2" cellpadding="2">\n%s%s%s</table>\n'
 440     result = restable % (restr1, restr2, "".join(restrn))
 441     return macro.formatter.rawHTML(result)
 442 
 443 # 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.
  • [get | view] (2004-03-04 13:15:01, 16.2 KB) [[attachment:MonthCalendar-moin12.py]]
  • [get | view] (2004-11-15 00:39:12, 16.9 KB) [[attachment:MonthCalendar-moin13.py]]
  • [get | view] (2003-12-07 18:15:54, 15.8 KB) [[attachment:MonthCalendar.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.