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') + '&lt;-' + formatter.url(0)
 349     nextmonth = formatter.url(1, nextlink, 'cal-link') + '-&gt;' + formatter.url(0)
 350     prevyear  = formatter.url(1, prevylink, 'cal-link') + '&lt;&lt;-' + formatter.url(0)
 351     nextyear  = formatter.url(1, nextylink, 'cal-link') + '-&gt;&gt;' + 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&nbsp;%s&nbsp;<b>&nbsp;%s&nbsp;%s</b>&nbsp;%s\n&nbsp;%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&nbsp;%s&nbsp;<b>&nbsp;%s&nbsp;/&nbsp;%s</b>&nbsp;%s\n&nbsp;%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">&nbsp;</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.
  • [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.