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     changes for moin 1.2 Copyright (c) 2004 by Oliver Graf <ograf@bitart.de>
  11     Licensed under GNU GPL - see COPYING for details.
  12 
  13 ----
  14     
  15     Revisions:
  16     * first revision without a number (=1.0):
  17         * was only online for a few hours and then replaced by 1.1
  18     * 1.1:
  19         * changed name to MonthCalendar to avoid conflict with "calendar" under case-insensitive OSes like Win32
  20         * days as subpages
  21         * basepage argument
  22         * change order of year/month argument
  23         * browsing links to prev/next month/year
  24         * current limitation: you can only browse one calendar on the same
  25           page/url, if you try to browse another calendar on the same page,
  26           the first one jumps back to its original display
  27         * show basepage in calendar header if basepage<>currentpage
  28     * 1.2:
  29         * minor fixes in argument parsing
  30         * cosmetic fix for netscape, other cosmetic changes, changed css
  31         * i18n support (weekday short names)
  32     * 1.3:
  33         * fixes to run with MoinMoin 0.11, thanks to JuergenHermann
  34         * fix: withspace before "," allowed in argument list
  35         * BasePage in calendar header (if present) is a link now
  36         * more i18n
  37         * HTML cleanup, generating code avoids bracketing errors
  38         * colour cosmetics
  39     * 1.4:
  40         * new parameter for enabling fixed height of 6 "calendar weeks",
  41           if you want to show a whole year's calendar, this just looks
  42           better than having some months with 4, some with 5 and some with 6.
  43         * group calendaring functions:
  44           * you can give mutliple BasePages UserName1*UserName2*UserName3
  45           * first BasePage is considered "your" Basepage,
  46             used days are bright red
  47           * 2nd and all other BasePages are considered "others" BasePages
  48             and lead to an increasing green component the more "used" days
  49             the others have. So white gets greener and red gets more yellowish.
  50           * in the head part of the calendar, you can click on each name
  51             to get to the Page of the same name
  52           * colouring of my and others BasePage is done in a way to show
  53             the colouring used in the calendar:
  54             * others use green colouring (increasingly green if multiply used)
  55             * I use red colouring, which gets more and more yellowish as
  56               the day is used by more and more others, too
  57     * 1.5:
  58         * fixed username colouring when using a BasePage
  59         * fixed navigation header of MonthCalendar not to get broken into
  60           multiple lines
  61         * fixed SubPage handling (please do not use relative SubPages like
  62           /SubPage yet. Use MyName/SubPage.)
  63     * 1.6:
  64         * syntactic cleanup
  65         * removed i18n compatibility for moin<1.1 or cvs<2003-06-10
  66         * integrated Scott Chapman's changes:
  67             * Made it configurable for Sunday or Monday as the first day of the week.
  68               Search for 'change here'.
  69             * Made it so weekend dates have different color.
  70 
  71 TODO:
  72     * integrate patch for including day page contents directly into cal
  73      * still thinking over: does this make sense in a MonthCalendar?
  74      * it would be definitely nice in a week or day calendar (more space to
  75        burn)
  76     * integr. daycal -link-> monthcal
  77 
  78 ----
  79 
  80     Usage:
  81         [[MonthCalendar(BasePage,year,month,monthoffset,monthoffset2,height6)]]
  82 
  83         each parameter can be empty and then defaults to currentpage or currentdate or monthoffset=0
  84 
  85     Samples (paste that to one of your pages for a first try):
  86 
  87 Calendar of current month for current page:
  88 [[MonthCalendar]]
  89 
  90 Calendar of last month:
  91 [[MonthCalendar(,,,-1)]]
  92 
  93 Calendar of next month:
  94 [[MonthCalendar(,,,+1)]]
  95 
  96 Calendar of Page SampleUser, this years december:
  97 [[MonthCalendar(SampleUser,,12)]]
  98 
  99 Calendar of current Page, this years december:
 100 [[MonthCalendar(,,12)]]
 101 
 102 Calendar of December, 2001:
 103 [[MonthCalendar(,2001,12)]]
 104 
 105 Calendar of the month two months after December, 2001
 106 (maybe doesn't make much sense, but is possible)
 107 [[MonthCalendar(,2001,12,+2)]]
 108 
 109 Calendar of year 2002 (every month padded to height of 6):
 110 ||||||Year 2002||
 111 ||[[MonthCalendar(,2002,1,,,1)]]||[[MonthCalendar(,2002,2,,,1)]]||[[MonthCalendar(,2002,3,,,1)]]||
 112 ||[[MonthCalendar(,2002,4,,,1)]]||[[MonthCalendar(,2002,5,,,1)]]||[[MonthCalendar(,2002,6,,,1)]]||
 113 ||[[MonthCalendar(,2002,7,,,1)]]||[[MonthCalendar(,2002,8,,,1)]]||[[MonthCalendar(,2002,9,,,1)]]||
 114 ||[[MonthCalendar(,2002,10,,,1)]]||[[MonthCalendar(,2002,11,,,1)]]||[[MonthCalendar(,2002,12,,,1)]]||
 115 
 116 Current calendar of me, also showing entries of A and B:
 117 [[MonthCalendar(MyPage*TestUserA*TestUserB)]]
 118 
 119 SubPage calendars:
 120 [[MonthCalendar(MyName/CalPrivate)]]
 121 [[MonthCalendar(MyName/CalBusiness)]]
 122 [[MonthCalendar(MyName/CalBusiness*MyName/CalPrivate)]]
 123 
 124 ----
 125 
 126     You need to have some stylesheet entries like the following.
 127     Paste that to  default.css / moinmoin.css:
 128     
 129 /* begin css for MonthCalendar macro */
 130 /* calendar table */
 131 table.cal-table {
 132         border: none;
 133         padding: 2px;
 134         spacing: 2px;
 135 }
 136 
 137 table.cal-table td {
 138         border: none;
 139 }
 140 
 141 /* days without and with pages linked to them */
 142 a.cal-emptyday {
 143         color: #5A5A5A;
 144         text-align: center;
 145         text-decoration: none;
 146 }
 147 a.cal-usedday {
 148         font-weight: bold;
 149         color: #222200;
 150         text-align: center;
 151         text-decoration: none;
 152 }
 153 /* multi page calendars */
 154 a.cal-thispage {
 155     color: #777777;
 156     text-align: center;
 157     text-decoration: none;
 158 }
 159 a.cal-otherpage {
 160     font-weight: bold;
 161     color: #000000;
 162     text-align: center;
 163 }
 164 /* general stuff: workdays, weekend, today */
 165 .cal-cell {
 166         width: 2em;
 167         height: 1.5em;
 168 }
 169 
 170 td.cal-workday {
 171     background-color: #DDDDFF;
 172     text-align: center;
 173 }
 174 td.cal-weekend {
 175     background-color: #FFDDDD;
 176     text-align: center;
 177 }
 178 td.cal-today {
 179     background-color: #CCFFCC;
 180     text-align: center;
 181 }
 182 /* invalid places on the monthly calendar sheet */
 183 td.cal-invalidday {
 184     background-color: #DDDDFF;
 185     text-align: center;
 186 }
 187 /* links to prev/next month/year */
 188 a.cal-link {
 189     color: #000000;
 190     text-decoration: none;
 191 }
 192 th.cal-header {
 193     background-color: #DDBBFF;
 194     text-align: center;
 195 }
 196 /* end css for MonthCalendar macro */
 197 
 198 ----
 199 
 200     If you want translated (german) messages, add something like this to
 201     i18n/de.py (if you have >=0.11, the weekday translation might be already
 202     there):
 203     
 204 'Mon':'Mo','Tue':'Di','Wed':'Mi','Thu':'Do','Fri':'Fr','Sat':'Sa','Sun':'So',
 205     
 206 'Invalid MonthCalendar calparms "%s"!':
 207 'Ung\366ltige MonthCalendar calparms "%s"!',
 208 
 209 'Invalid MonthCalendar arguments "%s"!':
 210 'Ung\366ltige MonthCalendar Argumente "%s"!',
 211 
 212 """
 213 
 214 # Imports
 215 from MoinMoin import config, user, wikiutil
 216 from MoinMoin.Page import Page
 217 import sys, re, calendar, time, string
 218 
 219 # The following line sets the calendar to have either Sunday or Monday as
 220 # the first day of the week. Only SUNDAY or MONDAY (case sensitive) are
 221 # valid here.  All other values will not make good calendars.
 222 # If set to Sunday, the calendar is displayed at "March 2003" vs. "2003 / 3" also.
 223 # XXX change here ----------------vvvvvv
 224 calendar.setfirstweekday(calendar.MONDAY)
 225 
 226 def yearmonthplusoffset(year, month, offset):
 227     month = month+offset
 228     # handle offset and under/overflows - quick and dirty, yes!
 229     while month < 1:
 230         month = month+12
 231         year = year-1
 232     while month > 12:
 233         month = month-12
 234         year = year+1
 235     return year, month
 236 
 237 def parseargs(args, defpagename, defyear, defmonth, defoffset, defoffset2, defheight6):
 238     strpagename = args.group('basepage')
 239     if strpagename:
 240         parmpagename = strpagename
 241     else:
 242         parmpagename = defpagename
 243     # multiple pagenames separated by "*" - split into list of pagenames
 244     parmpagename = re.split(r'\*', parmpagename)
 245 
 246     stryear = args.group('year')
 247     if stryear:
 248         parmyear = int(stryear)
 249     else:
 250         parmyear = defyear
 251 
 252     strmonth = args.group('month')
 253     if strmonth:
 254         parmmonth = int(strmonth)
 255     else:
 256         parmmonth = defmonth
 257     
 258     stroffset = args.group('offset')
 259     if stroffset:
 260         parmoffset = int(stroffset)
 261     else:
 262         parmoffset = defoffset
 263 
 264     stroffset2 = args.group('offset2')
 265     if stroffset2:
 266         parmoffset2 = int(stroffset2)
 267     else:
 268         parmoffset2 = defoffset2
 269 
 270     strheight6 = args.group('height6')
 271     if strheight6:
 272         parmheight6 = int(strheight6)
 273     else:
 274         parmheight6 = defheight6
 275 
 276     return parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6
 277         
 278 # FIXME:                          vvvvvv is there a better way for matching a pagename ?
 279 _arg_basepage = r'\s*(?P<basepage>[^, ]+)?\s*'
 280 _arg_year = r',\s*(?P<year>\d+)?\s*'
 281 _arg_month = r',\s*(?P<month>\d+)?\s*'
 282 _arg_offset = r',\s*(?P<offset>[+-]?\d+)?\s*'
 283 _arg_offset2 = r',\s*(?P<offset2>[+-]?\d+)?\s*'
 284 _arg_height6 = r',\s*(?P<height6>[+-]?\d+)?\s*'
 285 _args_re_pattern = r'^(%s)?(%s)?(%s)?(%s)?(%s)?(%s)?$' % \
 286                    (_arg_basepage,_arg_year,_arg_month, \
 287                     _arg_offset,_arg_offset2,_arg_height6)
 288 
 289 
 290 def execute(macro, text):
 291     _ = macro.request.getText
 292 
 293     # return immediately if getting links for the current page
 294     if macro.request.mode_getpagelinks:
 295         return ''
 296 
 297     args_re=re.compile(_args_re_pattern)
 298 
 299     currentyear, currentmonth, currentday, h, m, s, wd, yd, ds = time.localtime(time.time())
 300     thispage = macro.formatter.page.page_name
 301     # does the url have calendar params (= somebody has clicked on prev/next links in calendar) ?
 302     if macro.form.has_key('calparms'):
 303         text2 = macro.form['calparms'][0]
 304         args2 = args_re.match(text2)
 305         if not args2:
 306             return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar calparms "%s"!')) % (text2,)
 307         else:
 308             has_calparms = 1 # yes!
 309             cparmpagename, cparmyear, cparmmonth, cparmoffset, cparmoffset2, cparmheight6 = \
 310                            parseargs(args2, thispage, currentyear, currentmonth, 0, 0, 0)
 311     else:
 312         has_calparms = 0
 313 
 314     if text is None: # macro call without parameters
 315         parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6 = \
 316             [thispage], currentyear, currentmonth, 0, 0, 0
 317     else:
 318         # parse and check arguments
 319         args = args_re.match(text)
 320         if not args:
 321             return ('<p><strong class="error">%s</strong></p>' % _('Invalid MonthCalendar arguments "%s"!')) % (text,)
 322         else:
 323             parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6 = \
 324                           parseargs(args, thispage, currentyear, currentmonth, 0, 0, 0)
 325 
 326     # does url have calendar params and is THIS the right calendar to modify (we can have multiple
 327     # calendars on the same page)?
 328     if has_calparms and cparmpagename == parmpagename:
 329         year,month = yearmonthplusoffset(parmyear, parmmonth, parmoffset + cparmoffset2)
 330         parmoffset2 = cparmoffset2
 331     else:
 332         year,month = yearmonthplusoffset(parmyear, parmmonth, parmoffset)
 333 
 334     if not has_calparms:
 335         cparmpagename = parmpagename[0]
 336 
 337     # get the calendar
 338     monthcal = calendar.monthcalendar(year, month)
 339 
 340     # european / US differences
 341     months = ('January','February','March','April','May','June','July','August','September','October','November','December')
 342     # Set things up for Monday or Sunday as the first day of the week
 343     if calendar.firstweekday() == calendar.MONDAY:
 344         wkend = (5, 6)
 345         wkdays = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
 346     if calendar.firstweekday() == calendar.SUNDAY:
 347         wkend = (0, 6)
 348         wkdays = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
 349 
 350     p = Page(thispage)
 351     querystr = "calparms=%s,%d,%d,%d,%%d" % (string.join(parmpagename,'*'), parmyear, parmmonth, parmoffset)
 352     prevlink  = p.url(macro.request, querystr % (parmoffset2 - 1))
 353     nextlink  = p.url(macro.request, querystr % (parmoffset2 + 1))
 354     prevylink = p.url(macro.request, querystr % (parmoffset2 - 12))
 355     nextylink = p.url(macro.request, querystr % (parmoffset2 + 12))
 356     prevmonth = macro.formatter.url(prevlink, '&lt;-', 'cal-link')
 357     nextmonth = macro.formatter.url(nextlink, '-&gt;', 'cal-link')
 358     prevyear  = macro.formatter.url(prevylink, '&lt;&lt;-', 'cal-link')
 359     nextyear  = macro.formatter.url(nextylink, '-&gt;&gt;', 'cal-link')
 360 
 361     # multiple base pages?
 362     if parmpagename <> [thispage]:
 363         pagelinks = []
 364         for page in parmpagename:
 365             daypage=Page(page)
 366             if page == cparmpagename:
 367                 csslink = "cal-thispage"
 368             else:
 369                 csslink = "cal-otherpage"
 370             pagelinks.append('<a class="%s" href="%s">%s</a>' % (csslink, daypage.url(macro.request), page))
 371             del daypage
 372         showpagename = '   %s<BR>\n' % '*'.join(pagelinks)
 373     else:
 374         showpagename = ''
 375     if calendar.firstweekday() == calendar.SUNDAY:
 376         resth1 = '  <th colspan="7" class="cal-header">\n' \
 377                  '%s' \
 378                  '   %s&nbsp;%s&nbsp;<b>&nbsp;%s&nbsp;%s</b>&nbsp;%s&nbsp;%s\n' \
 379                  '  </th>\n' % (showpagename, prevyear, prevmonth, months[month-1], str(year), nextmonth, nextyear)
 380     if calendar.firstweekday() == calendar.MONDAY:
 381         resth1 = '  <th colspan="7" class="cal-header">\n' \
 382                  '%s' \
 383                  '   %s&nbsp;%s&nbsp;<b>&nbsp;%s&nbsp;/&nbsp;%s</b>&nbsp;%s&nbsp;%s\n' \
 384                  '  </th>\n' % (showpagename, prevyear, prevmonth, str(year), month, nextmonth, nextyear)
 385     restr1 = ' <tr>\n%s </tr>\n' % resth1
 386 
 387     r7 = range(7)
 388     restd2 = []
 389     for wkday in r7:
 390         wday = _(wkdays[wkday])
 391         if wkday in wkend:
 392             cssday = "cal-weekend"
 393         else:
 394             cssday = "cal-workday"
 395         restd2.append('  <td class="%s cal-cell">%s</td>\n' % (cssday, wday))
 396     restr2 = ' <tr>\n%s </tr>\n' % "".join(restd2)
 397 
 398     if parmheight6:
 399         while len(monthcal) < 6:
 400             monthcal = monthcal + [[0,0,0,0,0,0,0]]
 401 
 402     restrn = []
 403     for week in monthcal:
 404         restdn = []
 405         for wkday in r7:
 406             day = week[wkday]
 407             if not day:
 408                 restdn.append('  <td class="cal-invalidday cal-cell">&nbsp;</td>\n')
 409             else:
 410                 csslink = "cal-emptyday"
 411                 page = parmpagename[0]
 412                 link = "%s/%4d-%02d-%02d" % (page, year, month, day)
 413                 daypage = Page(link)
 414                 if daypage.exists():
 415                     csslink = "cal-usedday"
 416                 for otherpage in parmpagename[1:]:
 417                     otherlink = "%s/%4d-%02d-%02d" % (otherpage, year, month, day)
 418                     otherdaypage = Page(otherlink)
 419                     if otherdaypage.exists():
 420                         csslink = "cal-usedday"
 421                 fmtlink = macro.formatter.url(daypage.url(macro.request), str(day), csslink)
 422                 if day == currentday and month == currentmonth and year == currentyear:
 423                     cssday = "cal-today"
 424                 else:
 425                     if wkday in wkend:
 426                         cssday = "cal-weekend"
 427                     else:
 428                         cssday = "cal-workday"
 429                 restdn.append('  <td class="%s cal-cell">%s</td>\n' % (cssday, fmtlink))
 430         restrn.append(' <tr>\n%s </tr>\n' % "".join(restdn))
 431 
 432     restable = '<table class="cal-table">\n%s%s%s</table>\n'
 433     result = restable % (restr1, restr2, "".join(restrn))
 434     return macro.formatter.rawHTML(result)
 435 
 436 # 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-02-02 13:40:47, 15.6 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.