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) + '&lt;' + formatter.url(0)
 251     nextmonth = formatter.url(1, nextlink, 'cal-link', **attrs) + '&gt;' + formatter.url(0)
 252     prevyear = formatter.url(1, prevylink, 'cal-link', **attrs) + '&lt;&lt;' + formatter.url(0)
 253     nextyear = formatter.url(1, nextylink, 'cal-link', **attrs) + '&gt;&gt;' + 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&nbsp;%s&nbsp;<b>&nbsp;%s&nbsp;%s</b>&nbsp;%s\n&nbsp;%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&nbsp;%s&nbsp;<b>&nbsp;%s&nbsp;/&nbsp;%s</b>&nbsp;%s\n&nbsp;%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">&nbsp;</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.
  • [get | view] (2008-04-07 12:31:18, 15.6 KB) [[attachment:MonthCalendarHack-1.0.py]]
  • [get | view] (2008-04-07 12:31:49, 15.9 KB) [[attachment:MonthCalendarHack-1.1.py]]
 All files | Selected Files: delete move to page copy to page

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