Project

General

Profile

Download (10.4 KB) Statistics
| Branch: | Tag: | Revision:

root / extra / modules / agenda.ptl @ 2750dbae

1
import time
2
import datetime
3
from sets import Set
4

    
5
from quixote.directory import Directory
6
from quixote import get_publisher, get_request, redirect, get_session, get_response
7

    
8
from qommon import misc, template, errors, get_cfg
9
from qommon.form import *
10

    
11
from events import Event, RemoteCalendar, get_default_event_tags
12

    
13

    
14
class TagDirectory(Directory):
15
    def _q_lookup(self, component):
16
        events = Event.select()
17
        for remote_calendar in RemoteCalendar.select():
18
            if remote_calendar.events:
19
                events.extend(remote_calendar.events)
20
        self.events = [x for x in events if component in (x.keywords or [])]
21
        self.events.sort(lambda x,y: cmp(x.date_start, y.date_start))
22
        self.tag = component
23
        return self.display_events()
24

    
25
    def display_events [html] (self):
26
        template.html_top(_('Agenda'))
27
        if len(self.events) > 1:
28
            '<p id="nb-events">'
29
            _('%(nb)d events with %(keyword)s keyword') % {
30
                    'nb': len(self.events),
31
                    'keyword': self.tag
32
            }
33
            '</p>'
34

    
35
        if self.events:
36
            '<dl id="events">'
37
            for ev in self.events:
38
                ev.as_html_dt_dd()
39
            '</dl>'
40
        else:
41
            '<p id="nb-events">'
42
            _('No event registered with the %s keyword.') % self.tag
43
            '</p>'
44

    
45

    
46
class AgendaDirectory(Directory):
47
    _q_exports = ['', 'icalendar', 'tag', 'atom', 'filter']
48

    
49
    year = None
50
    month = None
51

    
52
    tag = TagDirectory()
53

    
54
    def _q_traverse(self, path):
55
        get_response().breadcrumb.append(('agenda/', _('Agenda')))
56
        self.year, self.month = time.localtime()[:2]
57
        if len(path) >= 1 and path[0].isdigit():
58
            self.year, self.month = (None, None)
59
            self.year = int(path[0])
60
            get_response().breadcrumb.append(('%s/' % self.year, self.year))
61
            path = path[1:]
62
            if len(path) >= 1 and path[0] in [str(x) for x in range(1, 13)]:
63
                self.month = int(path[0])
64
                get_response().breadcrumb.append(('%s/' % self.month,
65
                            misc.get_month_name(self.month)))
66
                path = path[1:]
67
            if len(path) == 0:
68
                return redirect(get_request().get_path() + '/')
69
        return Directory._q_traverse(self, path)
70

    
71
    def _q_index [html] (self):
72
        if self.month:
73
            self.display_month_links()
74
            self.display_month()
75
        else:
76
            return redirect('..')
77

    
78
    def display_month [html] (self):
79
        template.html_top(_('Agenda'))
80
        events = Event.select()
81
        remote_cal = get_request().form.get('cal')
82
        if remote_cal != 'local':
83
            if remote_cal:
84
                try:
85
                    events = RemoteCalendar.get(remote_cal).events
86
                except KeyError:
87
                    raise errors.TraversalError()
88
                if not events:
89
                    events = []
90
            else:
91
                for remote_calendar in RemoteCalendar.select():
92
                    if remote_calendar.events:
93
                        events.extend(remote_calendar.events)
94
        events = [x for x in events if x.in_month(self.year, self.month)]
95
        events.sort(lambda x,y: cmp(x.date_start, y.date_start))
96

    
97
        if events:
98
            if len(events) > 1:
99
                '<p id="nb-events">'
100
                _('%(nb)d events for %(month_name)s %(year)s') % {
101
                        'nb': len(events),
102
                        'month_name': misc.get_month_name(self.month),
103
                        'year': self.year}
104
                '</p>'
105

    
106
            '<dl id="events">'
107
            for ev in events:
108
                ev.as_html_dt_dd()
109
            '</dl>'
110
        else:
111
            '<p id="nb-events">'
112
            _('No event registered for the month of %s.') % '%s %s' % (
113
                    misc.get_month_name(self.month), self.year)
114
            '</p>'
115

    
116
        root_url = get_publisher().get_root_url()
117
        '<div id="agenda-subs">'
118
        '<p>'
119
        _('You can subscribe to this calendar:')
120
        '</p>'
121
        '<ul>'
122
        '  <li><a href="%sagenda/icalendar" id="par_ical">%s</a></li>' % (root_url, _('iCalendar'))
123
        '  <li><a href="%sagenda/atom" id="par_rss">%s</a></li>' % (root_url, _('Feed'))
124
        '</ul>'
125
        '</div>'
126

    
127
    def display_month_links [html] (self):
128
        today = datetime.date(*(time.localtime()[:2] + (1,)))
129
        '<ul id="month-links">'
130
        for i in range(12):
131
            '<li>'
132
            if (today.year, today.month) == (self.year, self.month):
133
                '<strong>'
134
                '%s %s' % (misc.get_month_name(today.month), today.year)
135
                '</strong>'
136
            else:
137
                root_url = get_publisher().get_root_url()
138
                '<a href="%sagenda/%s/%s/">' % (root_url, today.year, today.month)
139
                '%s %s' % (misc.get_month_name(today.month), today.year)
140
                '</a>'
141
            '</li>'
142
            today += datetime.timedelta(31)
143
        '</ul>'
144

    
145
    def display_remote_calendars [html] (self):
146
        remote_calendars = [x for x in RemoteCalendar.select() if x.label]
147
        if not remote_calendars:
148
            return
149
        remote_calendars.sort(lambda x,y: cmp(x.label, y.label))
150
        '<p class="tags">'
151
        remote_cal = get_request().form.get('cal')
152
        agenda_root_url = get_publisher().get_root_url() + 'agenda/'
153
        if remote_cal:
154
            '<a href="%s">%s</a> ' % (agenda_root_url, _('All'))
155
        else:
156
            '<strong><a href="%s">%s</a></strong> ' % (agenda_root_url, _('All'))
157
        if remote_cal != 'local':
158
            '<a href="%s?cal=local">%s</a> ' % (agenda_root_url, _('Local'))
159
        else:
160
            '<strong><a href="%s?cal=local">%s</a></strong> ' % (agenda_root_url, _('Local'))
161
        for cal in remote_calendars:
162
            if remote_cal == str(cal.id):
163
                '<strong><a href="%s?cal=%s">%s</a></strong> ' % (agenda_root_url, cal.id, cal.label)
164
            else:
165
                '<a href="%s?cal=%s">%s</a> ' % (agenda_root_url, cal.id, cal.label)
166
        '</p>'
167

    
168
    def icalendar(self):
169
        if not Event.keys():
170
            raise errors.TraversalError()
171
        response = get_response()
172
        response.set_content_type('text/calendar', 'utf-8')
173
        vcal = Event.as_vcalendar()
174
        if type(vcal) is unicode:
175
            return vcal.encode('utf-8')
176
        else:
177
            return vcal
178

    
179
    def atom [plain] (self):
180
        response = get_response()
181
        response.set_content_type('application/atom+xml')
182

    
183
        from pyatom import pyatom
184
        xmldoc = pyatom.XMLDoc()
185
        feed = pyatom.Feed()
186
        xmldoc.root_element = feed
187
        feed.title = get_cfg('misc', {}).get('sitename', 'Au Quotidien') + ' - ' + _('Agenda')
188
        feed.id = get_request().get_url()
189

    
190
        author_email = get_cfg('emails', {}).get('reply_to')
191
        if not author_email:
192
            author_email = get_cfg('emails', {}).get('from')
193
        if author_email:
194
            feed.authors.append(pyatom.Author(author_email))
195

    
196
        feed.links.append(pyatom.Link(get_request().get_url(1) + '/'))
197

    
198
        year, month = time.localtime()[:2]
199
        nyear, nmonth = year, month+1
200
        if nmonth > 12:
201
            nyear, nmonth = nyear+1, 1
202

    
203
        events = [x for x in Event.select() if x.in_month(year, month) or x.in_month(nyear, nmonth)]
204
        events.sort(lambda x,y: cmp(x.date_start, y.date_start))
205
        events.reverse()
206

    
207
        for item in events:
208
            entry = item.get_atom_entry()
209
            if entry is not None:
210
                feed.entries.append(entry)
211

    
212
        str(feed)
213

    
214
    def filter [html] (self, no_event=False):
215
        template.html_top(_('Agenda'))
216
        tags = get_cfg('misc', {}).get('event_tags')
217
        if not tags:
218
            tags = get_default_event_tags()
219
        remote_calendars = [x for x in RemoteCalendar.select() if x.label]
220

    
221
        form = Form(enctype='multipart/form-data')
222
        if tags and remote_calendars:
223
            form.widgets.append(HtmlWidget('<table id="agenda-filter"><tr><td>'))
224
        if tags:
225
            form.add(CheckboxesWidget, 'tags', title = _('Tags'),
226
                    elements = [(x,x) for x in tags],
227
                    inline = False)
228
        if tags and remote_calendars:
229
            form.widgets.append(HtmlWidget('</td><td>'))
230
        if remote_calendars:
231
            remote_calendars.sort(lambda x,y: cmp(x.label, y.label))
232
            form.add(CheckboxesWidget, 'calendars', title = _('Calendars'),
233
                    elements = [('local', _('Local'))] + [(x.id, x.label) for x in remote_calendars],
234
                    inline = False)
235
        if tags and remote_calendars:
236
            form.widgets.append(HtmlWidget('</td></tr></table>'))
237

    
238
        form.add_submit('submit', _('Submit'))
239
        form.add_submit('cancel', _('Cancel'))
240
        if form.get_widget('cancel').parse():
241
            return redirect('.')
242

    
243
        if no_event or not form.is_submitted():
244
            if no_event:
245
                '<p id="nb-events">'
246
                _('No events matching the filter.')
247
                '</p>'
248
            form.render()
249
        else:
250
            return self.filter_submitted(form, tags, remote_calendars)
251

    
252
    def filter_submitted [html] (self, form, tags, remote_calendars):
253
        if remote_calendars:
254
            selected_remote_calendars = form.get_widget('calendars').parse()
255
            events = []
256
            for remote_calendar in selected_remote_calendars:
257
                if remote_calendar == 'local':
258
                    events.extend(Event.select())
259
                else:
260
                    try:
261
                        events.extend(RemoteCalendar.get(remote_calendar).events)
262
                    except KeyError:
263
                        pass
264
        else:
265
            events = Event.select()
266

    
267
        events = [x for x in events if x.after_today()]
268

    
269
        if tags:
270
            selected_tags = Set(form.get_widget('tags').parse())
271
            if selected_tags and len(selected_tags) != len(tags):
272
                events = [x for x in events if Set(x.keywords).intersection(selected_tags)]
273

    
274
        events.sort(lambda x,y: cmp(x.date_start, y.date_start))
275

    
276
        if len(events) > 1:
277
            '<p id="nb-events">'
278
            _('%(nb)d events') % {'nb': len(events)}
279
            '</p>'
280

    
281
        if events:
282
            '<dl id="events">'
283
            for ev in events:
284
                ev.as_html_dt_dd()
285
            '</dl>'
286
        else:
287
            return self.filter(no_event=True)
(3-3/26)