2012-03-31 15:45:24 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
import time, calendar
|
|
|
|
from datetime import datetime, date, timedelta
|
|
|
|
from cStringIO import StringIO
|
|
|
|
|
|
|
|
from trac.wiki.api import WikiSystem
|
|
|
|
from trac.wiki.macros import WikiMacroBase
|
|
|
|
from trac.util import *
|
|
|
|
from trac.web.chrome import add_stylesheet
|
|
|
|
from trac.web import Href
|
|
|
|
from trac.util.datefmt import utc, to_timestamp
|
|
|
|
from trac.resource import get_resource_url
|
|
|
|
|
|
|
|
from tracrendezvous.event.model import Event
|
|
|
|
from ctdotools.utils import get_tz
|
|
|
|
|
|
|
|
__all__ = ['RendezVousesCalendarMacro',]
|
|
|
|
|
|
|
|
class EventHeaderMacro(WikiMacroBase):
|
|
|
|
def expand_macro(self, formatter, name, content):
|
|
|
|
try:
|
|
|
|
e_id = int(content)
|
|
|
|
except ValueError:
|
|
|
|
return ""
|
|
|
|
event = Event.fetch_one(self.env, e_id, show_all=True, days=60)
|
|
|
|
if not event or not event.periodic():
|
|
|
|
return ""
|
|
|
|
|
|
|
|
rows = []
|
|
|
|
rows.append("""<style type="text/css">
|
|
|
|
div.eventheader {text-align:center; min-width:5em; min-height:20em; float:right; clear:both; background:#ffedbc;}
|
|
|
|
a.existing_occurence, a.existing-occurence:visited {color:#00f;}
|
|
|
|
</style>""")
|
|
|
|
session_tzname, selected_tz = get_tz(formatter.req.session.get('tz', self.env.config.get("trac", "default_timezone") or None))
|
|
|
|
rows.append("<tr><td>%s</td></tr>" % event.rrules_explained)
|
|
|
|
if hasattr(event, "followups"):
|
|
|
|
l = []
|
|
|
|
for ev in event.followups:
|
2012-04-24 10:25:53 +00:00
|
|
|
local_time_begin = ev.time_begin.astimezone(selected_tz)
|
|
|
|
local_time_end = ev.time_end.astimezone(selected_tz)
|
2012-03-31 15:45:24 +00:00
|
|
|
link_label = "%s %s - %s %s" % (local_time_begin.strftime("%d.%m.%Y %H:%M"), local_time_begin.tzinfo.tzname(None), local_time_end.strftime("%d.%m.%Y %H:%M"), local_time_end.tzinfo.tzname(None))
|
|
|
|
link = "events/%s/%s" % (event.e_id, ev.time_begin.strftime("%Y-%m-%d"))
|
|
|
|
if WikiSystem(self.env).has_page(link):
|
|
|
|
row = '<li><a class="existing-occurence" href="%s">%s</a></li>' % (formatter.href.wiki(link) or formatter.href.event("createpage", event.e_id, ev.time_begin.strftime("%Y-%m-%d")), link_label)
|
|
|
|
else:
|
|
|
|
row = '<li><a href="%s">%s</a></li>' % (formatter.href.event("createpage", event.e_id, ev.time_begin.strftime("%Y-%m-%d")), link_label)
|
|
|
|
l.append(row)
|
|
|
|
rows.append("<tr><td><ul>%s</ul></td></tr>" % "".join(l))
|
|
|
|
return """<div class="eventheader"><h2><a href="%s">%s</a></h2><table class="eventheader"><tbody>%s<tr><td></td></tr></tbody></table></div>""" % (formatter.href.event(event.e_id), event.name, "".join(rows))
|
|
|
|
|
|
|
|
class RendezVousesCalendarMacro(WikiMacroBase):
|
|
|
|
"""Inserts a small calendar with scheduled RendezVouses with optional locations
|
|
|
|
constraint
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
{{{
|
|
|
|
[[WikiCalendar]]
|
|
|
|
[[WikiCalendar(location1,location2,foo_location)]]
|
|
|
|
}}}
|
|
|
|
"""
|
|
|
|
|
|
|
|
def expand_macro(self, formatter, name, content):
|
|
|
|
today = time.localtime()
|
|
|
|
http_param_year = formatter.req.args.get('year', '')
|
|
|
|
http_param_month = formatter.req.args.get('month', '')
|
|
|
|
if content:
|
|
|
|
args = content.split(',')
|
|
|
|
else:
|
|
|
|
args = []
|
|
|
|
|
|
|
|
if http_param_year == "":
|
|
|
|
# not clicked on a prev or next button
|
|
|
|
if len(args) >= 1 and args[0] <> "*":
|
|
|
|
# year given in macro parameters
|
|
|
|
year = int(args[0])
|
|
|
|
else:
|
|
|
|
# use current year
|
|
|
|
year = today.tm_year
|
|
|
|
else:
|
|
|
|
# year in http params (clicked by user) overrides everything
|
|
|
|
year = int(http_param_year)
|
|
|
|
|
|
|
|
if http_param_month == "":
|
|
|
|
# not clicked on a prev or next button
|
|
|
|
if len(args) >= 2 and args[1] <> "*":
|
|
|
|
# month given in macro parameters
|
|
|
|
month = int(args[1])
|
|
|
|
else:
|
|
|
|
# use current month
|
|
|
|
month = today.tm_mon
|
|
|
|
else:
|
|
|
|
# month in http params (clicked by user) overrides everything
|
|
|
|
month = int(http_param_month)
|
|
|
|
|
|
|
|
wiki_page_format = "%Y-%m-%d"
|
|
|
|
if len(args) >= 4:
|
|
|
|
wiki_page_format = args[3]
|
|
|
|
|
|
|
|
curr_day = None
|
|
|
|
if year == today.tm_year and month == today.tm_mon:
|
|
|
|
curr_day = today.tm_mday
|
|
|
|
|
|
|
|
thispageURL = Href(get_resource_url(self.env, formatter.resource, formatter.href))
|
|
|
|
# for the prev/next navigation links
|
|
|
|
prevMonth = month-1
|
|
|
|
prevYear = year
|
|
|
|
nextMonth = month+1
|
|
|
|
nextYear = year
|
|
|
|
# check for year change (KISS version)
|
|
|
|
if prevMonth == 0:
|
|
|
|
prevMonth = 12
|
|
|
|
prevYear -= 1
|
|
|
|
if nextMonth == 13:
|
|
|
|
nextMonth = 1
|
|
|
|
nextYear += 1
|
|
|
|
|
|
|
|
# 9-tuple for use with time.* functions requiring a struct_time
|
|
|
|
mydate = [0] * 8 + [-1] # AS: breaks Python 2.4
|
|
|
|
|
|
|
|
# building the output
|
|
|
|
buff = []
|
|
|
|
buff.append(u'''\
|
|
|
|
<style type="text/css">
|
|
|
|
<!--
|
|
|
|
div#wiki-calendar-block {margin:auto; display:inline-block; border:2px solid #000; padding:0; -khtml-border-radius: 17px;-moz-border-radius: 17px;}
|
|
|
|
table.wiki-calendar {margin:0px}
|
|
|
|
table.wiki-calendar caption {font-size: 120%; white-space: nowrap;}
|
|
|
|
table.wiki-calendar caption a {display: inline; margin: 0; border: 0; padding: 0; background-color: transparent; color: #b00; text-decoration: none;}
|
|
|
|
table.wiki-calendar caption a.prev {padding-right: 5px;}
|
|
|
|
table.wiki-calendar caption a.next {padding-left: 5px;}
|
|
|
|
table.wiki-calendar caption a:hover {background-color: #eee;background:transparent;border:0;}
|
|
|
|
table.wiki-calendar th {border: none; border-bottom: 2px solid #000; text-align: center; font-weight: bold;}
|
|
|
|
table.wiki-calendar td {border: none; text-align: center;padding:10px 10px;wrap:nowrap;}
|
|
|
|
table.wiki-calendar td.day {min-width: 2em; height: 100%; margin: 0; border: 2px solid #eee; background-color: #fff; color: #888; text-decoration: none; -khtml-border-radius: 17px;-moz-border-radius: 17px;}
|
|
|
|
table.wiki-calendar td.active {border-color: #eee; background:#0f0; color: #000;}
|
|
|
|
table.wiki-calendar td.active:hover {border-color: #eee; background:#afa; color: #000;}
|
|
|
|
table.wiki-calendar td.today {border-color: #b77 !important;}
|
|
|
|
table.wiki-calendar ul, table.wiki-calendar li {margin:0;padding:0;}
|
|
|
|
table.wiki-calendar td.adjacent_month {background-color: #333;}
|
|
|
|
table.wiki-calendar td.adjacent_month:hover {background-color: #333;color:#888}
|
|
|
|
table.wiki-calendar td.collision {background:#800;}
|
|
|
|
table.wiki-calendar a.byday {min-width:100px; border:1px solid #eee;padding:0px 10px; margin:0; font-weight:bold; -khtml-border-radius: 17px;-moz-border-radius: 17px;}
|
|
|
|
table.wiki-calendar a.byday:hover {background:#ccc;}
|
|
|
|
table.wiki-calendar td.adjacent_month a.byday {color: #ddd !important;}
|
|
|
|
table.wiki-calendar td.adjacent_month a.byday:hover {color: #000 !important;}
|
|
|
|
table.wiki-calendar :link,table.wiki-calendar :visited {color: #000 !important;font-size:1.2em;wrap:nowrap;}
|
|
|
|
|
|
|
|
//-->
|
|
|
|
</style>
|
|
|
|
<div id="wiki-calendar-block">
|
|
|
|
<table class="wiki-calendar"><caption>
|
|
|
|
''')
|
|
|
|
import locale
|
|
|
|
|
|
|
|
encoding = locale.getlocale()[1]
|
|
|
|
# prev year link
|
|
|
|
mydate[0:2] = [year-1, month]
|
|
|
|
mydate_label = time.strftime('%B %Y', tuple(mydate))
|
|
|
|
if encoding:
|
|
|
|
mydate_label = mydate_label.decode(encoding)
|
|
|
|
|
|
|
|
buff.append(u'<a class="prev" href="%s" title="%s"><<</a>' % (
|
|
|
|
thispageURL(month=month, year=year-1),
|
|
|
|
mydate_label
|
|
|
|
))
|
|
|
|
# prev month link
|
|
|
|
mydate[0:2] = [prevYear, prevMonth]
|
|
|
|
mydate_label = time.strftime('%B %Y', tuple(mydate))
|
|
|
|
if encoding:
|
|
|
|
mydate_label = mydate_label.decode(encoding)
|
|
|
|
buff.append(u'<a class="prev" href="%s" title="%s"><</a>' % (
|
|
|
|
thispageURL(month=prevMonth, year=prevYear),
|
|
|
|
mydate_label
|
|
|
|
))
|
|
|
|
|
|
|
|
# the caption
|
|
|
|
mydate[0:2] = [year, month]
|
|
|
|
mydate_label = time.strftime('%B %Y', tuple(mydate))
|
|
|
|
if encoding:
|
|
|
|
mydate_label = mydate_label.decode(encoding)
|
|
|
|
buff.append(mydate_label)
|
|
|
|
|
|
|
|
|
|
|
|
# next month link
|
|
|
|
mydate[0:2] = [nextYear, nextMonth]
|
|
|
|
mydate_label = time.strftime('%B %Y', tuple(mydate))
|
|
|
|
if encoding:
|
|
|
|
mydate_label = mydate_label.decode(encoding)
|
|
|
|
buff.append(u'<a class="next" href="%s" title="%s">></a>' % (
|
|
|
|
thispageURL(month=nextMonth, year=nextYear),
|
|
|
|
mydate_label))
|
|
|
|
# next year link
|
|
|
|
mydate[0:2] = [year+1, month]
|
|
|
|
mydate_label = time.strftime('%B %Y', tuple(mydate))
|
|
|
|
if encoding:
|
|
|
|
mydate_label = mydate_label.decode(encoding)
|
|
|
|
buff.append(u'<a class="next" href="%s" title="%s">>></a>' % (
|
|
|
|
thispageURL(month=month, year=year+1),
|
|
|
|
mydate))
|
|
|
|
|
|
|
|
buff.append(u'</caption>\n<thead>\n<tr>')
|
|
|
|
for day in calendar.weekheader(2).split():
|
|
|
|
buff.append(u'<th scope="col">%s</th>' % day)
|
|
|
|
buff.append(u'</tr>\n</thead>\n<tbody>')
|
|
|
|
|
|
|
|
last_week_prev_month = calendar.monthcalendar(prevYear, prevMonth)[-1];
|
|
|
|
first_week_next_month = calendar.monthcalendar(nextYear, nextMonth)[0];
|
|
|
|
w = -1
|
|
|
|
db = self.env.get_db_cnx()
|
|
|
|
cursor = db.cursor()
|
|
|
|
day_list = []
|
|
|
|
foo,last_day = calendar.monthrange(year, month)
|
|
|
|
start_dt = datetime(year, month, 1, tzinfo=utc)
|
|
|
|
end_dt = datetime(year, month, last_day, 23, 59, tzinfo=utc)
|
|
|
|
rts = Event.fetch_by_period_dict(self.env, start_dt, end_dt)
|
|
|
|
session_tzname, selected_tz = get_tz(formatter.req.session.get('tz', self.env.config.get("trac", "default_timezone") or None))
|
|
|
|
def _f(t):
|
|
|
|
assert type(t) == Event
|
2012-04-24 10:25:53 +00:00
|
|
|
real_begin = t.time_begin.astimezone(selected_tz)
|
|
|
|
real_end = t.time_end.astimezone(selected_tz)
|
2012-03-31 15:45:24 +00:00
|
|
|
return u'<li><a href="%s" title="%s - %s %s">%s:<br/>%s</a></li>' % (formatter.href.event(t.e_id), real_begin.strftime("%d.%m.%Y %H:%M"), real_end.strftime("%d.%m.%Y %H:%M"), real_begin.tzinfo.tzname(None), unicode(t.location.name), unicode(t.name))
|
|
|
|
for week in calendar.monthcalendar(year, month):
|
|
|
|
buff.append(u'\n<tr>')
|
|
|
|
w = w+1
|
|
|
|
d = -1
|
|
|
|
for day in week:
|
|
|
|
d = d+1
|
|
|
|
|
|
|
|
# calc date and update CSS classes
|
|
|
|
mydate[0:3] = [year, month, day]
|
|
|
|
classes = u'day'
|
|
|
|
title = u''
|
|
|
|
if not day:
|
|
|
|
classes += u' adjacent_month'
|
|
|
|
if w == 0:
|
|
|
|
day = last_week_prev_month[d]
|
|
|
|
mydate[0:3] = [prevYear, prevMonth, day]
|
|
|
|
else:
|
|
|
|
day = first_week_next_month[d]
|
|
|
|
mydate[0:3] = [nextYear, nextMonth, day]
|
|
|
|
else:
|
|
|
|
if day == curr_day:
|
|
|
|
classes += u' today'
|
|
|
|
title += u"Heute:"
|
|
|
|
wiki = time.strftime(wiki_page_format, tuple(mydate))
|
|
|
|
actual_date = date(mydate[0], mydate[1], mydate[2])
|
|
|
|
if rts and rts.has_key(actual_date):
|
|
|
|
rt = rts[actual_date]
|
|
|
|
for t in rt:
|
|
|
|
if actual_date.day != t.time_end.day:
|
|
|
|
tomorrow = actual_date + timedelta(1)
|
|
|
|
rts[tomorrow].append(t)
|
|
|
|
text = u"".join([_f(t) for t in rt])
|
|
|
|
classes += u" active"
|
|
|
|
title += u" %d Termin(e)" % len(rt)
|
|
|
|
daylink = unicode(formatter.href.event("by-day", "%d-%d-%d" % tuple(mydate[:3])))
|
|
|
|
#text = text.encode("utf8")
|
|
|
|
buff.append(u'\n<td class="%s"><a class="byday" href="%s" title="%s">%s</a><br/><ul>%s</ul></td>' % (classes.strip(), daylink, title, day, text))
|
|
|
|
else:
|
|
|
|
title += u"Noch keine Termine"
|
|
|
|
daylink = formatter.href.event("new", "%d-%d-%d" % tuple(mydate[:3]))
|
|
|
|
buff.append(u'\n<td class="%s"><a class="byday" href="%s" title="%s">%s</a></td>' % (classes, daylink, title, day))
|
|
|
|
buff.append(u'\n</tr>')
|
|
|
|
buff.append(u'\n</tbody>\n</table></div>\n')
|
|
|
|
table = u"".join(buff)
|
|
|
|
return table
|