changeset 630:f3676743483d

initial version of an ical/ics data parser rendered by fullcalendar attachment default.ics is rendered on default requires python package icalendar and js libray fullcalendar (both on PyPi)
author Reimar Bauer <rb.proj AT googlemail DOT com>
date Tue, 02 Dec 2014 13:51:53 +0100
parents 23bf696cf294
children 6d6e3a8caa03
files data/plugin/parser/text_x_fullcalendar.py
diffstat 1 files changed, 202 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/data/plugin/parser/text_x_fullcalendar.py	Tue Dec 02 13:51:53 2014 +0100
@@ -0,0 +1,202 @@
+# -*- coding: iso-8859-1 -*-
+"""
+    MoinMoin - fullcalendar
+
+    This parser is used to visualize icals date entries by fullcalendar
+    http://www.fullcalendar.io
+
+    You may want to add to your wikiconfig.py something like
+    html_head = '''
+<link rel="stylesheet" type="text/css" charset="utf-8" href="%(url_prefix_static)s/fullcalendar/fullcalendar.css">
+<link rel="stylesheet" type="text/css" charset="utf-8" media="print" href="%(url_prefix_static)s/fullcalendar/fullcalendar.print.css">
+<script src='%(url_prefix_static)s/fullcalendar/lib/moment.min.js'></script>
+<script src='%(url_prefix_static)s/fullcalendar/lib/jquery.min.js'></script>
+<script src='%(url_prefix_static)s/fullcalendar/fullcalendar.min.js'></script>
+''' % {"url_prefix_static": url_prefix_static}
+
+
+    Usage:
+    
+    #format fullcalendar maxwidth=400px, week_numbers=1, left=today
+
+    @copyright: 2014 by MoinMoin:ReimarBauer
+    @license: GNU GPL, see COPYING for details.
+"""
+
+try:
+    import icalendar
+except ImportError:
+    icalendar = None
+
+import os
+import json
+import datetime
+from MoinMoin import config, wikiutil
+from MoinMoin.action import AttachFile
+
+
+def fullcalendar_settings(attachfile=u'default.ics', editable=0, default_date=u'',
+                          week_numbers=0,
+                          left=u'prev,next,today', right=u'month,agendaWeek,agendaDay',
+                          title=u'title',
+                          maxwidth=u'900px'):
+    """
+    dummy function to initialize all default parameters for fullcalendar.
+    The parameters are checked for wrong input.
+    @param attachfile: name of attachmet to read ical data from and convert to json
+    @param editable: default false
+    @param default_date: default current day
+    @param week_numbers: default false, determines if week numbers should be displayed on the calendar.
+    @param left: default: 'prev,next,today'
+           prev: button for moving the calendar back one month/week/day,
+           next: button for moving the calendar forward one month/week/day
+           today: button for moving the calendar to the current month/week/day
+    @param right: default: month,agendaWeek,agendaDay'
+           month: view month
+           agendaWeek: view week
+           agendaDay:  view day
+    @param title: default title,text containing the current month/week/day
+    @param maxwidth: width used default 900px
+    """
+    return locals()
+
+Dependencies = ["page"]
+
+class Parser:
+    """ fullcalendar parser """
+    extensions = '*.ics'
+    def __init__(self, raw, request, **kw):
+        self.pagename = request.page.page_name
+        self.raw = raw.strip('\n')
+        self.request = request
+        self.formatter = request.formatter
+        self.form = None
+        self.ical_data = None
+        self.json_data = u""
+        self.attachfile = u"default.ical"
+        self.editable = 0
+        self.default_date = u''
+        self.week_numbers = 0
+        self.left = u'prev,next,today'
+        self.right = u'month,agendaWeek,agendaDay'
+        self.title = u'title'
+        self.maxwidth = u'900px'
+        self._ = request.getText
+
+
+        args = kw.get('format_args', '')
+        self.init_settings = False
+        try:
+            settings = wikiutil.invoke_extension_function(request, fullcalendar_settings, args)
+            for key, value in settings.items():
+                setattr(self, key, value)
+            # saves the state of valid input
+            self.init_settings = True
+        except ValueError, err:
+            msg = u"fullcalendar: %s" % err.args[0]
+            request.write(self.formatter.text(msg))
+
+    def render(self, formatter):
+        """ renders calendar  """
+
+        _ = self._
+
+        # checks if initializing of all attributes in __init__ was done
+        if self.init_settings:
+            # reads in datafile if exists and converts it to json
+            self.ical2json()
+            editable = 'false'
+            if self.editable == 1:
+                editable = 'true'
+            default_date = self.default_date
+            if default_date == u'':
+                default_date = datetime.datetime.now().date().isoformat()
+            week_numbers = 'false'
+            if self.week_numbers == 1:
+                week_numbers = 'true'
+
+
+            html_text = """
+    <script>
+
+        $(document).ready(function() {
+
+
+            $('#calendar').fullCalendar({
+			header: {
+				left: '%(left)s',
+				center: '%(title)s',
+				right: '%(right)s'
+			},
+                defaultDate: '%(default_date)s',
+                editable: %(editable)s,
+                eventLimit: true, // allow "more" link when too many events
+                weekNumbers: %(week_numbers)s,
+                events:
+                    %(json)s
+            });
+
+        });
+
+    </script>
+    <style>
+
+        #calendar {
+            max-width: %(maxwidth)s;
+            margin: 0 auto;
+        }
+
+    </style>
+    <div id='calendar'></div>
+
+            """
+            return html_text % {"left": self.left,
+                                "title": self.title,
+                                "right": self.right,
+                                "default_date": default_date,
+                                "editable": editable,
+                                "week_numbers": week_numbers,
+                                "json": self.json_data,
+                                "maxwidth": self.maxwidth,
+                                }
+
+    def get_ical_data(self):
+        """
+        reads ical attachfile
+        """
+        if icalendar is None:
+            return
+
+        if self.request.user.may.read(self.pagename) and AttachFile.exists(self.request, self.pagename, self.attachfile):
+            ical_file = os.path.join(AttachFile.getAttachDir(self.request, self.pagename), self.attachfile).encode(config.charset)
+            with open(ical_file, 'rb') as fhandler:
+                self.ical_data = icalendar.Calendar.from_ical(fhandler.read())
+
+    def ical2json(self):
+        """
+        comverts ical data to json
+        This routine was inspired by this blog article
+        http://www.thogan.com/blog/sogo-ical-and-fullcalendar/
+        """
+        self.get_ical_data()
+        events = []
+        if self.ical_data is not None:
+            for item in self.ical_data.walk():
+                if item.name == 'VEVENT':
+                    new_event = {'editable': False,
+                                 'allDay': False}
+                    new_event['title'] = item.get('summary')
+                    new_event['start'] = item.get('dtstart').dt.isoformat()
+                    new_event['end'] = item.get('dtend').dt.isoformat()
+                    if item.get('location'):
+                        new_event['url'] = item.get('location')
+                    events.append(new_event)
+            self.json_data = json.dumps(events, indent=4)
+
+    def format(self, formatter):
+        """ parser output """
+        # checks if initializing of all attributes in __init__ was done
+        if self.init_settings:
+            self.request.write(self.formatter.div(1, css_class="fullcalendar"))
+            self.request.write(self.render(formatter))
+            self.request.write(self.formatter.div(0))
\ No newline at end of file