ctdo-trac/TracRendezVous/tracrendezvous/event/macros.py

268 lines
12 KiB
Python

# -*- 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:
local_time_begin = ev.time_begin.astimezone(selected_tz)
local_time_end = ev.time_end.astimezone(selected_tz)
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">&lt;&lt;</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">&lt;</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">&gt;</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">&gt;&gt;</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
real_begin = t.time_begin.astimezone(selected_tz)
real_end = t.time_end.astimezone(selected_tz)
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