comparison data/plugin/parser/text_x_fullcalendar.py @ 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
children 127da830be6c
comparison
equal deleted inserted replaced
629:23bf696cf294 630:f3676743483d
1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - fullcalendar
4
5 This parser is used to visualize icals date entries by fullcalendar
6 http://www.fullcalendar.io
7
8 You may want to add to your wikiconfig.py something like
9 html_head = '''
10 <link rel="stylesheet" type="text/css" charset="utf-8" href="%(url_prefix_static)s/fullcalendar/fullcalendar.css">
11 <link rel="stylesheet" type="text/css" charset="utf-8" media="print" href="%(url_prefix_static)s/fullcalendar/fullcalendar.print.css">
12 <script src='%(url_prefix_static)s/fullcalendar/lib/moment.min.js'></script>
13 <script src='%(url_prefix_static)s/fullcalendar/lib/jquery.min.js'></script>
14 <script src='%(url_prefix_static)s/fullcalendar/fullcalendar.min.js'></script>
15 ''' % {"url_prefix_static": url_prefix_static}
16
17
18 Usage:
19
20 #format fullcalendar maxwidth=400px, week_numbers=1, left=today
21
22 @copyright: 2014 by MoinMoin:ReimarBauer
23 @license: GNU GPL, see COPYING for details.
24 """
25
26 try:
27 import icalendar
28 except ImportError:
29 icalendar = None
30
31 import os
32 import json
33 import datetime
34 from MoinMoin import config, wikiutil
35 from MoinMoin.action import AttachFile
36
37
38 def fullcalendar_settings(attachfile=u'default.ics', editable=0, default_date=u'',
39 week_numbers=0,
40 left=u'prev,next,today', right=u'month,agendaWeek,agendaDay',
41 title=u'title',
42 maxwidth=u'900px'):
43 """
44 dummy function to initialize all default parameters for fullcalendar.
45 The parameters are checked for wrong input.
46 @param attachfile: name of attachmet to read ical data from and convert to json
47 @param editable: default false
48 @param default_date: default current day
49 @param week_numbers: default false, determines if week numbers should be displayed on the calendar.
50 @param left: default: 'prev,next,today'
51 prev: button for moving the calendar back one month/week/day,
52 next: button for moving the calendar forward one month/week/day
53 today: button for moving the calendar to the current month/week/day
54 @param right: default: month,agendaWeek,agendaDay'
55 month: view month
56 agendaWeek: view week
57 agendaDay: view day
58 @param title: default title,text containing the current month/week/day
59 @param maxwidth: width used default 900px
60 """
61 return locals()
62
63 Dependencies = ["page"]
64
65 class Parser:
66 """ fullcalendar parser """
67 extensions = '*.ics'
68 def __init__(self, raw, request, **kw):
69 self.pagename = request.page.page_name
70 self.raw = raw.strip('\n')
71 self.request = request
72 self.formatter = request.formatter
73 self.form = None
74 self.ical_data = None
75 self.json_data = u""
76 self.attachfile = u"default.ical"
77 self.editable = 0
78 self.default_date = u''
79 self.week_numbers = 0
80 self.left = u'prev,next,today'
81 self.right = u'month,agendaWeek,agendaDay'
82 self.title = u'title'
83 self.maxwidth = u'900px'
84 self._ = request.getText
85
86
87 args = kw.get('format_args', '')
88 self.init_settings = False
89 try:
90 settings = wikiutil.invoke_extension_function(request, fullcalendar_settings, args)
91 for key, value in settings.items():
92 setattr(self, key, value)
93 # saves the state of valid input
94 self.init_settings = True
95 except ValueError, err:
96 msg = u"fullcalendar: %s" % err.args[0]
97 request.write(self.formatter.text(msg))
98
99 def render(self, formatter):
100 """ renders calendar """
101
102 _ = self._
103
104 # checks if initializing of all attributes in __init__ was done
105 if self.init_settings:
106 # reads in datafile if exists and converts it to json
107 self.ical2json()
108 editable = 'false'
109 if self.editable == 1:
110 editable = 'true'
111 default_date = self.default_date
112 if default_date == u'':
113 default_date = datetime.datetime.now().date().isoformat()
114 week_numbers = 'false'
115 if self.week_numbers == 1:
116 week_numbers = 'true'
117
118
119 html_text = """
120 <script>
121
122 $(document).ready(function() {
123
124
125 $('#calendar').fullCalendar({
126 header: {
127 left: '%(left)s',
128 center: '%(title)s',
129 right: '%(right)s'
130 },
131 defaultDate: '%(default_date)s',
132 editable: %(editable)s,
133 eventLimit: true, // allow "more" link when too many events
134 weekNumbers: %(week_numbers)s,
135 events:
136 %(json)s
137 });
138
139 });
140
141 </script>
142 <style>
143
144 #calendar {
145 max-width: %(maxwidth)s;
146 margin: 0 auto;
147 }
148
149 </style>
150 <div id='calendar'></div>
151
152 """
153 return html_text % {"left": self.left,
154 "title": self.title,
155 "right": self.right,
156 "default_date": default_date,
157 "editable": editable,
158 "week_numbers": week_numbers,
159 "json": self.json_data,
160 "maxwidth": self.maxwidth,
161 }
162
163 def get_ical_data(self):
164 """
165 reads ical attachfile
166 """
167 if icalendar is None:
168 return
169
170 if self.request.user.may.read(self.pagename) and AttachFile.exists(self.request, self.pagename, self.attachfile):
171 ical_file = os.path.join(AttachFile.getAttachDir(self.request, self.pagename), self.attachfile).encode(config.charset)
172 with open(ical_file, 'rb') as fhandler:
173 self.ical_data = icalendar.Calendar.from_ical(fhandler.read())
174
175 def ical2json(self):
176 """
177 comverts ical data to json
178 This routine was inspired by this blog article
179 http://www.thogan.com/blog/sogo-ical-and-fullcalendar/
180 """
181 self.get_ical_data()
182 events = []
183 if self.ical_data is not None:
184 for item in self.ical_data.walk():
185 if item.name == 'VEVENT':
186 new_event = {'editable': False,
187 'allDay': False}
188 new_event['title'] = item.get('summary')
189 new_event['start'] = item.get('dtstart').dt.isoformat()
190 new_event['end'] = item.get('dtend').dt.isoformat()
191 if item.get('location'):
192 new_event['url'] = item.get('location')
193 events.append(new_event)
194 self.json_data = json.dumps(events, indent=4)
195
196 def format(self, formatter):
197 """ parser output """
198 # checks if initializing of all attributes in __init__ was done
199 if self.init_settings:
200 self.request.write(self.formatter.div(1, css_class="fullcalendar"))
201 self.request.write(self.render(formatter))
202 self.request.write(self.formatter.div(0))