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