# HG changeset patch # User Paul Boddie # Date 1238358873 -7200 # Node ID 88b83d2632b3db12752f62fa6695f1ecbe320045 # Parent 59ece334903a07b0ac730e915185d1fd488b8e4c Added DTSTAMP and LAST-MODIFIED properties to iCalendar summaries, along with LOCATION support. Introduced text encoding/quoting in iCalendar summaries. Widened calendar tables in the CSS file for the macro. Added "categories" as a synonym for "topics" in the event descriptions. Introduced support for simple Wiki syntax in event topics. Expanded the macro documentation and added documentation for the action. Updated the copyright information. diff -r 59ece334903a -r 88b83d2632b3 EventAggregatorSupport.py --- a/EventAggregatorSupport.py Sun Mar 29 21:01:49 2009 +0200 +++ b/EventAggregatorSupport.py Sun Mar 29 22:34:33 2009 +0200 @@ -10,8 +10,10 @@ from MoinMoin.Page import Page from MoinMoin import search, version +from MoinMoin import wikiutil import calendar import datetime +import time import re __version__ = "0.1" @@ -86,6 +88,14 @@ mapping.sort() return mapping +def getPageDate(page): + + # From MoinMoin.xmlrpc... + + edit_info = page.edit_info() + mtime = wikiutil.version2timestamp(long(edit_info['timestamp'])) # must be long for py 2.2.x + return tuple(time.gmtime(mtime)) + # The main activity functions. def getPages(pagename, request): @@ -106,6 +116,18 @@ pages.append(page) return pages +def getSimpleWikiText(text): + + """ + Return the plain text representation of the given 'text' which may employ + certain Wiki syntax features, such as those providing verbatim or monospaced + text. + """ + + # NOTE: Re-implementing support for verbatim text and linking avoidance. + + return "".join([s for s in verbatim_regexp.split(text) if s is not None]) + def getEventDetails(page): "Return a dictionary of event details from the given 'page'." @@ -127,17 +149,15 @@ if term in ("start", "end"): desc = getDate(desc) - # Lists. + # Lists (whose elements may be quoted). - elif term in ("topics",): - desc = [value.strip() for value in desc.split(",")] + elif term in ("topics", "categories"): + desc = [getSimpleWikiText(value.strip()) for value in desc.split(",")] # Labels which may well be quoted. - # NOTE: Re-implementing support for verbatim text and linking - # NOTE: avoidance. elif term in ("title", "summary"): - desc = "".join([s for s in verbatim_regexp.split(desc) if s is not None]) + desc = getSimpleWikiText(desc) if desc is not None: event_details[term] = desc diff -r 59ece334903a -r 88b83d2632b3 README.txt --- a/README.txt Sun Mar 29 21:01:49 2009 +0200 +++ b/README.txt Sun Mar 29 22:34:33 2009 +0200 @@ -90,17 +90,9 @@ To obtain an iCalendar summary, the EventAggregatorSummary action can be selected from the actions menu on any page. Alternatively, a collection of -parameters can be specified in the URL of any Wiki page. For example: - - http://example.com/moin/FrontPage?action=EventAggregatorSummary&category=CategoryEvents&doit=1 +parameters can be specified in the URL of any Wiki page. -This should produce an iCalendar resource in response. By specifying 'start' -and 'end' parameters, a restricted view can be obtained. For example: - - http://example.com/moin/FrontPage?action=EventAggregatorSummary&category=CategoryEvents&start=2009-06&end=2009-07&doit=1 - -This would restrict the initial query to events occurring in the months of -June 2009 ('2009-06') and July 2009 ('2009-07'). +See pages/HelpOnEventAggregatorSummary for more detailed information. Recommended Software -------------------- diff -r 59ece334903a -r 88b83d2632b3 actions/EventAggregatorSummary.py --- a/actions/EventAggregatorSummary.py Sun Mar 29 21:01:49 2009 +0200 +++ b/actions/EventAggregatorSummary.py Sun Mar 29 22:34:33 2009 +0200 @@ -4,13 +4,15 @@ @copyright: 2008, 2009 by Paul Boddie @copyright: 2000-2004 Juergen Hermann , - 2005-2008 MoinMoin:ThomasWaldmann, + 2003-2008 MoinMoin:ThomasWaldmann, + 2004-2006 MoinMoin:AlexanderSchremmer, 2007 MoinMoin:ReimarBauer. @license: GNU GPL (v2 or later), see COPYING.txt for details. """ from MoinMoin.action import ActionBase from MoinMoin import config +from MoinMoin.Page import Page import EventAggregatorSupport Dependencies = ['pages'] @@ -118,6 +120,12 @@ pass +def getQuotedText(text): + + "Return the 'text' quoted for iCalendar purposes." + + return text.replace(";", r"\;").replace(",", r"\,") + def write_resource(request): """ @@ -157,18 +165,42 @@ for event_page, event_details in all_shown_events: + # Get the summary and timestamp details. + event_summary = EventAggregatorSupport.getEventSummary(event_page, event_details) + # Get the initial revision of the page. + + revisions = event_page.getRevList() + event_page_initial = Page(request, event_page.page_name, rev=revisions[-1]) + + # Get the created and last modified times. + + created = EventAggregatorSupport.getPageDate(event_page_initial) + last_modified = EventAggregatorSupport.getPageDate(event_page) + sequence = len(revisions) - 1 + # Output the event details. request.write("BEGIN:VEVENT\r\n") - request.write("SUMMARY:%s\r\n" % event_summary) request.write("UID:%s\r\n" % request.getQualifiedURL(event_page.url(request))) request.write("URL:%s\r\n" % request.getQualifiedURL(event_page.url(request))) + request.write("DTSTAMP:%04d%02d%02dT%02d%02d%02dZ\r\n" % created[:6]) + request.write("LAST-MODIFIED:%04d%02d%02dT%02d%02d%02dZ\r\n" % last_modified[:6]) + request.write("SEQUENCE:%d\r\n" % sequence) request.write("DTSTART;VALUE=DATE:%04d%02d%02d\r\n" % event_details["start"]) request.write("DTEND;VALUE=DATE:%04d%02d%02d\r\n" % EventAggregatorSupport.nextdate(event_details["end"])) - if event_details.has_key("topics"): - request.write("CATEGORIES:%s\r\n" % ",".join(event_details["topics"])) + request.write("SUMMARY:%s\r\n" % getQuotedText(event_summary)) + + # Optional details. + + if event_details.has_key("topics") or event_details.has_key("categories"): + request.write("CATEGORIES:%s\r\n" % ",".join( + [getQuotedText(topic) for topic in event_details.get("topics") or event_details.get("categories")] + )) + if event_details.has_key("location"): + request.write("LOCATION:%s\r\n" % getQuotedText(event_details["location"])) + request.write("END:VEVENT\r\n") request.write("END:VCALENDAR\r\n") diff -r 59ece334903a -r 88b83d2632b3 css/event-aggregator.css --- a/css/event-aggregator.css Sun Mar 29 21:01:49 2009 +0200 +++ b/css/event-aggregator.css Sun Mar 29 22:34:33 2009 +0200 @@ -12,7 +12,7 @@ /* Calendar view. */ .event-month { - width: 90%; + width: 98%; border-bottom: 1px solid #dddddd; } diff -r 59ece334903a -r 88b83d2632b3 docs/COPYING.txt --- a/docs/COPYING.txt Sun Mar 29 21:01:49 2009 +0200 +++ b/docs/COPYING.txt Sun Mar 29 22:34:33 2009 +0200 @@ -3,13 +3,15 @@ Copyright (C) 2008, 2009 Paul Boddie -Some pieces of MoinMoin code were used in this work - -specifically the category regular expression code from -MoinMoin.config.multiconfig - and are thus covered by the -following copyrights: +Some pieces of MoinMoin code were used in this work - typically +pieces which demonstrate how to perform certain common tasks +(as found in various macros and actions) - and are thus covered +by the following copyrights: Copyright (C) 2000-2004 Juergen Hermann -Copyright (C) 2005-2008 MoinMoin:ThomasWaldmann +Copyright (C) 2003-2008 MoinMoin:ThomasWaldmann +Copyright (C) 2004-2006 MoinMoin:AlexanderSchremmer +Copyright (C) 2007 MoinMoin:ReimarBauer This software is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff -r 59ece334903a -r 88b83d2632b3 pages/HelpOnEventAggregator --- a/pages/HelpOnEventAggregator Sun Mar 29 21:01:49 2009 +0200 +++ b/pages/HelpOnEventAggregator Sun Mar 29 22:34:33 2009 +0200 @@ -33,6 +33,25 @@ Obviously, duplicating the date information introduces a risk of this information becoming inconsistent, so beware! +=== Supported Event Properties === + +As well as the start and end dates of an event, the following properties are also recognised as being part of an event description: + + Title:: the preferred name of the event in the calendar + Summary:: a synonym for title + Topics:: a list of topics related to the event - use a comma (`,`) to separate topic names + Categories:: a synonym for topics + Location:: the location of the event + +These properties may be incorporated into representations or summaries of events. + +Textual properties can be quoted in a limited way using the verbatim or monospaced text Wiki syntax. For example: + +{{{ + Summary:: <> 2009 + Topics:: Python, <>, Zope +}}} + == Showing Event Calendars == To show a calendar, use the !EventAggregator macro with a list of event categories. For example: @@ -80,3 +99,7 @@ }}} The `list` value causes a list view to be employed; the `calendar` value causes the default calendar view to be employed. + +== See Also == + + * HelpOnEventAggregatorSummary - an action producing iCalendar event summaries diff -r 59ece334903a -r 88b83d2632b3 pages/HelpOnEventAggregatorSummary --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pages/HelpOnEventAggregatorSummary Sun Mar 29 22:34:33 2009 +0200 @@ -0,0 +1,41 @@ +##master-page:HelpTemplate +##master-date:Unknown-Date +#format wiki +#language en + +== EventAggregatorSummary == + +The !EventAggregatorSummary action provides iCalendar summaries of events whose details are recorded in pages belonging to specific categories (such as CategoryEvents). These summaries can then be imported into applications which understand the iCalendar format. + +Upon invoking the action, an iCalendar response will be produced. If the action is invoked in a browser, it is most likely that a dialogue box will appear asking you whether you would like to save the response to a file or to open the response in a suitable application. This behaviour is slightly different to many !MoinMoin actions. + +== Using the Actions Menu Entry == + +The action can be selected from the actions menu on any page; this will produce a form requesting values for the following items: + + * The names of categories known to the Wiki. + * The start (first month) of the summary (optional). + * The end (last month) of the summary (optional). + +Where no start or end values are specified, all events in the chosen categories are included in the summary. + +== Making Direct Requests to the Action == + +Alternatively, a collection of parameters can be specified in the URL of any Wiki page. For example: + +{{{ +http://example.com/moin/FrontPage?action=EventAggregatorSummary&category=CategoryEvents&doit=1 +}}} + +This should produce an iCalendar resource in response. By specifying `start` and `end` parameters, a restricted view can be obtained. For example: + +{{{ +http://example.com/moin/FrontPage?action=EventAggregatorSummary&category=CategoryEvents +&start=2009-06&end=2009-07&doit=1 +}}} + +This restricts the initial query to only retrieve events occurring in the months of June 2009 (`2009-06`) and July 2009 (`2009-07`). + +== See Also == + + * HelpOnEventAggregator - a macro producing event calendars and listings