From 399c717734f2c761d14ef951fc751d49d58ca6f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Tue, 26 Nov 2019 13:59:57 +0100
Subject: [PATCH 2/6] remove support for agenda/events (#37967)

---
 auquotidien/auquotidien.py       |   4 -
 auquotidien/modules/admin.py     |  39 +--
 auquotidien/modules/agenda.py    | 307 -----------------------
 auquotidien/modules/events.py    | 234 -----------------
 auquotidien/modules/events_ui.py | 418 -------------------------------
 auquotidien/modules/root.py      |  23 +-
 auquotidien/modules/template.py  |   5 -
 7 files changed, 3 insertions(+), 1027 deletions(-)
 delete mode 100644 auquotidien/modules/agenda.py
 delete mode 100644 auquotidien/modules/events.py
 delete mode 100644 auquotidien/modules/events_ui.py

diff --git a/auquotidien/auquotidien.py b/auquotidien/auquotidien.py
index 551188e..81e6486 100644
--- a/auquotidien/auquotidien.py
+++ b/auquotidien/auquotidien.py
@@ -8,7 +8,6 @@ from modules import admin
 from modules import backoffice
 from modules import announces_ui
 from modules import categories_admin
-from modules import events_ui
 from modules import payments_ui
 from modules import strongbox_ui
 from modules import formpage
@@ -30,9 +29,6 @@ rdb.items = []
 rdb.register_directory('announces', announces_ui.AnnouncesDirectory())
 rdb.register_menu_item('announces/', _('Announces'))
 
-rdb.register_directory('events', events_ui.EventsDirectory())
-rdb.register_menu_item('events/', _('Events'))
-
 rdb.register_directory('payments', payments_ui.PaymentsDirectory())
 rdb.register_menu_item('payments/', _('Payments'))
 
diff --git a/auquotidien/modules/admin.py b/auquotidien/modules/admin.py
index 90202b7..4a490c7 100644
--- a/auquotidien/modules/admin.py
+++ b/auquotidien/modules/admin.py
@@ -17,13 +17,12 @@ from wcs.formdef import FormDef
 from wcs.categories import Category
 from wcs.qommon.backoffice.menu import html_top
 
-from .events import get_default_event_tags
 import re
 from .abelium_domino_ui import AbeliumDominoDirectory
 
 
 class PanelDirectory(Directory):
-    _q_exports = ['', 'update', 'announces', 'permissions', 'event_keywords',
+    _q_exports = ['', 'update', 'announces', 'permissions',
             'announce_themes', 'strongbox', 'clicrdv', 'domino']
     label = N_('Control Panel')
 
@@ -77,10 +76,6 @@ class PanelDirectory(Directory):
         form.add(SingleSelectWidget, 'forms', title = _('Admin role for forms'),
                 value = permissions_cfg.get('forms', None),
                 options = [(None, _('Nobody'), None)] + get_user_roles())
-        if get_publisher().has_site_option('auquotidien-events'):
-            form.add(SingleSelectWidget, 'events', title = _('Admin role for events'),
-                    value = permissions_cfg.get('events', None),
-                    options = [(None, _('Nobody'), None)] + get_user_roles())
         if get_publisher().has_site_option('auquotidien-announces'):
             form.add(SingleSelectWidget, 'announces', title = _('Admin role for announces'),
                     value = permissions_cfg.get('announces', None),
@@ -109,34 +104,7 @@ class PanelDirectory(Directory):
         else:
             from wcs.admin.settings import cfg_submit
             cfg_submit(form, 'aq-permissions',
-                        ('forms', 'events', 'announces', 'payments', 'strongbox'))
-            return redirect('..')
-
-    def event_keywords(self):
-        misc_cfg = get_cfg('misc', {})
-        form = Form(enctype='multipart/form-data')
-        form.add(WidgetList, 'event_tags', title = _('Event Keywords'),
-                value = misc_cfg.get('event_tags', get_default_event_tags()),
-                elemnt_type = StringWidget,
-                add_element_label = _('Add Keyword'),
-                element_kwargs = {str('render_br'): False, str('size'): 30})
-
-        form.add_submit('submit', _('Submit'))
-        form.add_submit('cancel', _('Cancel'))
-
-        if form.get_widget('cancel').parse():
-            return redirect('..')
-
-        if not form.is_submitted() or form.has_errors():
-            get_response().breadcrumb.append(('aq/event_keywords', _('Event Keywords')))
-            html_top('settings', _('Event Keywords'))
-            r = TemplateIO(html=True)
-            r += htmltext('<h2>%s</h2>') % _('Event Keywords')
-            r += form.render()
-            return r.getvalue()
-        else:
-            from wcs.admin.settings import cfg_submit
-            cfg_submit(form, 'misc', ('event_tags',))
+                        ('forms', 'announces', 'payments', 'strongbox'))
             return redirect('..')
 
     def announce_themes(self):
@@ -250,7 +218,6 @@ class PanelDirectory(Directory):
 class SettingsDirectory(wcs.admin.settings.SettingsDirectory):
     def _q_index(self):
         if not (get_publisher().has_site_option('auquotidien-announces') or
-                get_publisher().has_site_option('auquotidien-events') or
                 get_publisher().has_site_option('auquotidien-payments') or
                 get_publisher().has_site_option('auquotidien-strongvox')):
             return super(SettingsDirectory, self)._q_index()
@@ -263,8 +230,6 @@ class SettingsDirectory(wcs.admin.settings.SettingsDirectory):
         if get_publisher().has_site_option('auquotidien-announces'):
             r += htmltext('<li><a href="aq/announces">%s</a></li>') % _('Announces Options')
         r += htmltext('<li><a href="aq/permissions">%s</a></li>') % _('Permissions')
-        if get_publisher().has_site_option('auquotidien-events'):
-            r += htmltext('<li><a href="aq/event_keywords">%s</a></li>') % _('Event Keywords')
         if get_publisher().has_site_option('auquotidien-announces'):
             r += htmltext('<li><a href="aq/announce_themes">%s</a></li>') % _('Announce Themes')
         if get_publisher().has_site_option('strongbox'):
diff --git a/auquotidien/modules/agenda.py b/auquotidien/modules/agenda.py
deleted file mode 100644
index 5d9f56c..0000000
--- a/auquotidien/modules/agenda.py
+++ /dev/null
@@ -1,307 +0,0 @@
-import time
-import datetime
-from sets import Set
-
-from quixote.directory import Directory
-from quixote import get_publisher, get_request, redirect, get_session, get_response
-from quixote.html import htmltext, TemplateIO
-
-from wcs.qommon import _
-from wcs.qommon import misc, template, errors, get_cfg
-from wcs.qommon.form import *
-
-from .events import Event, RemoteCalendar, get_default_event_tags
-
-
-class TagDirectory(Directory):
-    def _q_lookup(self, component):
-        events = Event.select()
-        for remote_calendar in RemoteCalendar.select():
-            if remote_calendar.events:
-                events.extend(remote_calendar.events)
-        self.events = [x for x in events if component in (x.keywords or [])]
-        self.events.sort(lambda x,y: cmp(x.date_start, y.date_start))
-        self.tag = component
-        return self.display_events()
-
-    def display_events(self):
-        template.html_top(_('Agenda'))
-        r = TemplateIO(html=True)
-        if len(self.events) > 1:
-            r += htmltext('<p id="nb-events">')
-            r += _('%(nb)d events with %(keyword)s keyword') % {
-                    'nb': len(self.events),
-                    'keyword': self.tag
-            }
-            r += htmltext('</p>')
-
-        if self.events:
-            r += htmltext('<dl id="events">')
-            for ev in self.events:
-                r += htmltext(ev.as_html_dt_dd())
-            r += htmltext('</dl>')
-        else:
-            r += htmltext('<p id="nb-events">')
-            r += _('No event registered with the %s keyword.') % self.tag
-            r += htmltext('</p>')
-        return r.getvalue()
-
-
-class AgendaDirectory(Directory):
-    _q_exports = ['', 'icalendar', 'tag', 'atom', 'filter']
-
-    year = None
-    month = None
-
-    tag = TagDirectory()
-
-    def _q_traverse(self, path):
-        get_response().breadcrumb.append(('agenda/', _('Agenda')))
-        self.year, self.month = time.localtime()[:2]
-        if len(path) >= 1 and path[0].isdigit():
-            self.year, self.month = (None, None)
-            self.year = int(path[0])
-            get_response().breadcrumb.append(('%s/' % self.year, self.year))
-            path = path[1:]
-            if len(path) >= 1 and path[0] in [str(x) for x in range(1, 13)]:
-                self.month = int(path[0])
-                get_response().breadcrumb.append(('%s/' % self.month,
-                            misc.get_month_name(self.month)))
-                path = path[1:]
-            if len(path) == 0:
-                return redirect(get_request().get_path() + '/')
-        return Directory._q_traverse(self, path)
-
-    def _q_index(self):
-        if self.month:
-            r = TemplateIO(html=True)
-            r += htmltext(self.display_month_links())
-            r += htmltext(self.display_month())
-            return r.getvalue()
-        else:
-            return redirect('..')
-
-    def display_month(self):
-        template.html_top(_('Agenda'))
-        events = Event.select()
-        remote_cal = get_request().form.get('cal')
-        if remote_cal != 'local':
-            if remote_cal:
-                try:
-                    events = RemoteCalendar.get(remote_cal).events
-                except KeyError:
-                    raise errors.TraversalError()
-                if not events:
-                    events = []
-            else:
-                for remote_calendar in RemoteCalendar.select():
-                    if remote_calendar.events:
-                        events.extend(remote_calendar.events)
-        events = [x for x in events if x.in_month(self.year, self.month)]
-        events.sort(lambda x,y: cmp(x.date_start, y.date_start))
-
-        r = TemplateIO(html=True)
-        if events:
-            if len(events) > 1:
-                r += htmltext('<p id="nb-events">')
-                r += _('%(nb)d events for %(month_name)s %(year)s') % {
-                        'nb': len(events),
-                        'month_name': misc.get_month_name(self.month),
-                        'year': self.year}
-                r += htmltext('</p>')
-
-            r += htmltext('<dl id="events">')
-            for ev in events:
-                r += htmltext(ev.as_html_dt_dd())
-            r += htmltext('</dl>')
-        else:
-            r += htmltext('<p id="nb-events">')
-            r += _('No event registered for the month of %s.') % '%s %s' % (
-                    misc.get_month_name(self.month), self.year)
-            r += htmltext('</p>')
-
-        root_url = get_publisher().get_root_url()
-        r += htmltext('<div id="agenda-subs">')
-        r += htmltext('<p>')
-        r += _('You can subscribe to this calendar:')
-        r += htmltext('</p>')
-        r += htmltext('<ul>')
-        r += htmltext('  <li><a href="%sagenda/icalendar" id="par_ical">%s</a></li>') % (
-                root_url, _('iCalendar'))
-        r += htmltext('  <li><a href="%sagenda/atom" id="par_rss">%s</a></li>') % (
-                root_url, _('Feed'))
-        r += htmltext('</ul>')
-        r += htmltext('</div>')
-        return r.getvalue()
-
-    def display_month_links(self):
-        today = datetime.date(*(time.localtime()[:2] + (1,)))
-        r = TemplateIO(html=True)
-        r += htmltext('<ul id="month-links">')
-        for i in range(12):
-            r += htmltext('<li>')
-            if (today.year, today.month) == (self.year, self.month):
-                r += htmltext('<strong>')
-                r += '%s %s' % (misc.get_month_name(today.month), today.year)
-                r += htmltext('</strong>')
-            else:
-                root_url = get_publisher().get_root_url()
-                r += htmltext('<a href="%sagenda/%s/%s/">') % (root_url, today.year, today.month)
-                r += '%s %s' % (misc.get_month_name(today.month), today.year)
-                r += htmltext('</a>')
-            r += htmltext('</li>')
-            today += datetime.timedelta(31)
-        r += htmltext('</ul>')
-        return r.getvalue()
-
-    def display_remote_calendars(self):
-        r = TemplateIO(html=True)
-        remote_calendars = [x for x in RemoteCalendar.select() if x.label]
-        if not remote_calendars:
-            return
-        remote_calendars.sort(lambda x,y: cmp(x.label, y.label))
-        r += htmltext('<p class="tags">')
-        remote_cal = get_request().form.get('cal')
-        agenda_root_url = get_publisher().get_root_url() + 'agenda/'
-        if remote_cal:
-            r += htmltext('<a href="%s">%s</a> ') % (agenda_root_url, _('All'))
-        else:
-            r += htmltext('<strong><a href="%s">%s</a></strong> ') % (agenda_root_url, _('All'))
-        if remote_cal != 'local':
-            r += htmltext('<a href="%s?cal=local">%s</a> ') % (agenda_root_url, _('Local'))
-        else:
-            r += htmltext('<strong><a href="%s?cal=local">%s</a></strong> ') % (agenda_root_url, _('Local'))
-        for cal in remote_calendars:
-            if remote_cal == str(cal.id):
-                r += htmltext('<strong><a href="%s?cal=%s">%s</a></strong> ') % (
-                        agenda_root_url, cal.id, cal.label)
-            else:
-                r += htmltext('<a href="%s?cal=%s">%s</a> ') % (agenda_root_url, cal.id, cal.label)
-        r += htmltext('</p>')
-        return r.getvalue()
-
-    def icalendar(self):
-        if not Event.keys():
-            raise errors.TraversalError()
-        response = get_response()
-        response.set_content_type('text/calendar', 'utf-8')
-        vcal = Event.as_vcalendar()
-        if type(vcal) is unicode:
-            return vcal.encode('utf-8')
-        else:
-            return vcal
-
-    def atom(self):
-        response = get_response()
-        response.set_content_type('application/atom+xml')
-
-        from pyatom import pyatom
-        xmldoc = pyatom.XMLDoc()
-        feed = pyatom.Feed()
-        xmldoc.root_element = feed
-        feed.title = get_cfg('misc', {}).get('sitename', 'Publik') + ' - ' + _('Agenda')
-        feed.id = get_request().get_url()
-
-        author_email = get_cfg('emails', {}).get('reply_to')
-        if not author_email:
-            author_email = get_cfg('emails', {}).get('from')
-        if author_email:
-            feed.authors.append(pyatom.Author(author_email))
-
-        feed.links.append(pyatom.Link(get_request().get_url(1) + '/'))
-
-        year, month = time.localtime()[:2]
-        nyear, nmonth = year, month+1
-        if nmonth > 12:
-            nyear, nmonth = nyear+1, 1
-
-        events = [x for x in Event.select() if x.in_month(year, month) or x.in_month(nyear, nmonth)]
-        events.sort(lambda x,y: cmp(x.date_start, y.date_start))
-        events.reverse()
-
-        for item in events:
-            entry = item.get_atom_entry()
-            if entry is not None:
-                feed.entries.append(entry)
-
-        return str(feed)
-
-    def filter(self, no_event=False):
-        template.html_top(_('Agenda'))
-        tags = get_cfg('misc', {}).get('event_tags')
-        if not tags:
-            tags = get_default_event_tags()
-        remote_calendars = [x for x in RemoteCalendar.select() if x.label]
-
-        form = Form(enctype='multipart/form-data')
-        if tags and remote_calendars:
-            form.widgets.append(HtmlWidget('<table id="agenda-filter"><tr><td>'))
-        if tags:
-            form.add(CheckboxesWidget, 'tags', title=_('Tags'),
-                    options=[(x,x) for x in tags],
-                    inline=False)
-        if tags and remote_calendars:
-            form.widgets.append(HtmlWidget('</td><td>'))
-        if remote_calendars:
-            remote_calendars.sort(lambda x,y: cmp(x.label, y.label))
-            form.add(CheckboxesWidget, 'calendars', title=_('Calendars'),
-                    options=[('local', _('Local'))] + [(x.id, x.label) for x in remote_calendars],
-                    inline=False)
-        if tags and remote_calendars:
-            form.widgets.append(HtmlWidget('</td></tr></table>'))
-
-        form.add_submit('submit', _('Submit'))
-        form.add_submit('cancel', _('Cancel'))
-        if form.get_widget('cancel').parse():
-            return redirect('.')
-
-        if no_event or not form.is_submitted():
-            r = TemplateIO(html=True)
-            if no_event:
-                r += htmltext('<p id="nb-events">')
-                r += _('No events matching the filter.')
-                r += htmltext('</p>')
-            r += form.render()
-            return r.getvalue()
-        else:
-            return self.filter_submitted(form, tags, remote_calendars)
-
-    def filter_submitted(self, form, tags, remote_calendars):
-        if remote_calendars:
-            selected_remote_calendars = form.get_widget('calendars').parse()
-            events = []
-            for remote_calendar in selected_remote_calendars:
-                if remote_calendar == 'local':
-                    events.extend(Event.select())
-                else:
-                    try:
-                        events.extend(RemoteCalendar.get(remote_calendar).events)
-                    except KeyError:
-                        pass
-        else:
-            events = Event.select()
-
-        events = [x for x in events if x.after_today()]
-
-        if tags:
-            selected_tags = Set(form.get_widget('tags').parse())
-            if selected_tags and len(selected_tags) != len(tags):
-                events = [x for x in events if Set(x.keywords).intersection(selected_tags)]
-
-        events.sort(lambda x,y: cmp(x.date_start, y.date_start))
-
-        r = TemplateIO(html=True)
-
-        if len(events) > 1:
-            r += htmltext('<p id="nb-events">')
-            r += htmltext(_('%(nb)d events')) % {'nb': len(events)}
-            r += htmltext('</p>')
-
-        if events:
-            r += htmltext('<dl id="events">')
-            for ev in events:
-                r += htmltext(ev.as_html_dt_dd())
-            r += htmltext('</dl>')
-            return r.getvalue()
-        else:
-            return self.filter(no_event=True)
diff --git a/auquotidien/modules/events.py b/auquotidien/modules/events.py
deleted file mode 100644
index 6ab27e7..0000000
--- a/auquotidien/modules/events.py
+++ /dev/null
@@ -1,234 +0,0 @@
-import time
-import datetime
-import urllib2
-import vobject
-
-from quixote import get_request, get_publisher, get_response
-from quixote.html import htmltext, TemplateIO, htmlescape
-
-from wcs.qommon import _
-from wcs.qommon.publisher import get_publisher_class
-from wcs.qommon.storage import StorableObject
-from wcs.qommon.cron import CronJob
-from wcs.qommon import misc
-
-class Event(StorableObject):
-    _names = 'events'
-
-    title = None
-    description = None
-    url = None
-    date_start = None
-    date_end = None
-    location = None
-    organizer = None
-    more_infos = None
-    keywords = None
-
-    def in_month(self, year, month):
-        if not self.date_end: # a single date
-            return tuple(self.date_start[:2]) == (year, month)
-        else:
-            # an interval
-            if tuple(self.date_start[:2]) > (year, month): # start later
-                return False
-            if tuple(self.date_end[:2]) < (year, month): # ended before
-                return False
-        return True
-
-    def after_today(self):
-        today = time.localtime()[:3]
-        if not self.date_end:
-            return tuple(self.date_start[:3]) > today
-        return tuple(self.date_end[:3]) > today
-
-    def format_date(self):
-        d = {
-            'year_start': self.date_start[0],
-            'month_start': misc.get_month_name(self.date_start[1]),
-            'day_start': self.date_start[2]
-            }
-        if self.date_end and self.date_start[:3] != self.date_end[:3]:
-            d.update({
-                'year_end': self.date_end[0],
-                'month_end': misc.get_month_name(self.date_end[1]),
-                'day_end': self.date_end[2]
-                })
-            d2 = datetime.date(*self.date_start[:3]) + datetime.timedelta(days=1)
-            if tuple(self.date_end[:3]) == (d2.year, d2.month, d2.day):
-                # two consecutive days
-                if self.date_start[1] == self.date_end[1]:
-                    return _('On %(month_start)s %(day_start)s and %(day_end)s') % d
-                else:
-                    return _('On %(month_start)s %(day_start)s and %(month_end)s %(day_end)s') % d
-            else:
-                if self.date_start[0] == self.date_end[0]: # same year
-                    if self.date_start[1] == self.date_end[1]: # same month
-                        return _('From %(month_start)s %(day_start)s to %(day_end)s') % d
-                    else:
-                        return _('From %(month_start)s %(day_start)s '
-                                 'to %(month_end)s %(day_end)s') % d
-                else:
-                    return _('From %(month_start)s %(day_start)s %(year_start)s '
-                             'to %(month_end)s %(day_end)s %(year_end)s') % d
-        else:
-            return _('On %(month_start)s %(day_start)s') % d
-
-    def as_vevent(self):
-        vevent = vobject.newFromBehavior('vevent')
-        site_charset = get_publisher().site_charset
-        vevent.add('uid').value = '%04d%02d%02d-%s@%s' % (self.date_start[:3] + (self.id,
-            get_request().get_server().lower().split(':')[0].rstrip('.')))
-        vevent.add('summary').value = unicode(self.title, site_charset)
-        vevent.add('dtstart').value = datetime.date(*self.date_start[:3])
-        vevent.dtstart.value_param = 'DATE'
-        if self.date_end:
-            vevent.add('dtend').value = datetime.date(*self.date_end[:3])
-            vevent.dtend.value_param = 'DATE'
-        if self.description:
-            vevent.add('description').value = unicode(self.description.strip(), site_charset)
-        if self.url:
-            vevent.add('url').value = unicode(self.url, site_charset)
-        if self.location:
-            vevent.add('location').value = unicode(self.location, site_charset)
-        if self.organizer:
-            vevent.add('organizer').value = unicode(self.organizer, site_charset)
-        if self.keywords:
-            vevent.add('categories').value = [unicode(x, site_charset) for x in self.keywords]
-        vevent.add('class').value = 'PUBLIC'
-        return vevent
-
-    def as_vcalendar(cls):
-        cal = vobject.iCalendar()
-        cal.add('prodid').value = '-//Entr\'ouvert//NON SGML Publik'
-        for x in cls.select():
-            cal.add(x.as_vevent())
-        return cal.serialize()
-    as_vcalendar = classmethod(as_vcalendar)
-    
-    def as_html_dt_dd(self):
-        root_url = get_publisher().get_root_url()
-        r = TemplateIO(html=True)
-        r += htmltext('<dt>')
-        r += self.format_date()
-        r += htmltext('</dt>')
-        r += htmltext('<p><dd><strong>%s</strong>') % self.title
-        if self.description:
-            r += ' - ' + self.description
-        r += htmltext('</p>')
-        if (self.location or self.organizer or self.more_infos or self.keywords):
-            r += htmltext('<ul>')
-            if self.location:
-                r += htmltext('<li>%s: %s</li>') % (_('Location'), self.location)
-            if self.organizer:
-                r += htmltext('<li>%s: %s</li>') % (_('Organizer'), self.organizer)
-            if self.more_infos:
-                r += htmltext('<li>%s</li>') % self.more_infos
-            if self.keywords:
-                r += htmltext('<li>')
-                for k in self.keywords:
-                    r += htmltext('<a class="tag" href="%sagenda/tag/%s">%s</a> ') % (root_url, k, k)
-                r += htmltext('</li>')
-            r += htmltext('</ul>')
-
-        if self.url:
-            r += htmltext('<a class="external" href="%s">%s</a>') % (
-                        self.url, _('More information'))
-        r += htmltext('</dd>')
-        return r.getvalue()
-
-    def get_url(self):
-        return '%s/agenda/events/%s/' % (get_publisher().get_frontoffice_url(), self.id)
-
-    def get_atom_entry(self):
-        from pyatom import pyatom
-        entry = pyatom.Entry()
-        entry.id = self.get_url()
-        entry.title = self.title
-
-        entry.content.attrs['type'] = 'html'
-        entry.content.text = str('<p>' + htmlescape(
-                    unicode(self.description, get_publisher().site_charset).encode('utf-8')) + '</p>')
-
-        return entry
-
-
-class RemoteCalendar(StorableObject):
-    _names = 'remote_calendars'
-
-    label = None
-    url = None
-    content = None
-    events = None
-    error = None  # (time, string, params)
-
-    def download_and_parse(self, job=None):
-        old_content = self.content
-
-        try:
-            self.content = urllib2.urlopen(self.url).read()
-        except urllib2.HTTPError, e:
-            self.error = (time.localtime(), N_('HTTP Error %s on download'), (e.code,))
-            self.store()
-            return
-        except urllib2.URLError, e:
-            self.error = (time.localtime(), N_('Error on download'), ())
-            self.store()
-            return
-
-        if self.error:
-            self.error = None
-            self.store()
-
-        if self.content == old_content:
-            return
-
-        self.events = []
-        try:
-            parsed_cal = vobject.readOne(self.content)
-        except vobject.base.ParseError:
-            self.error = (time.localtime(), N_('Failed to parse file'), ())
-            self.store()
-            return
-
-        site_charset = get_publisher().site_charset
-        for vevent in parsed_cal.vevent_list:
-            ev = Event()
-            ev.title = vevent.summary.value.encode(site_charset, 'replace')
-            try:
-                ev.url = vevent.url.value.encode(site_charset, 'replace')
-            except AttributeError:
-                pass
-            ev.date_start = vevent.dtstart.value.timetuple()
-            try:
-                ev.date_end = vevent.dtend.value.timetuple()
-            except AttributeError:
-                pass
-            try:
-                ev.description = vevent.description.value.encode(site_charset, 'replace')
-            except AttributeError:
-                pass
-            try:
-                ev.keywords = [x.encode(site_charset) for x in vevent.categories.value]
-            except AttributeError:
-                pass
-            self.events.append(ev)
-        self.store()
-
-        
-    def get_error_message(self):
-        if not self.error:
-            return None
-        return '(%s) %s' % (misc.localstrftime(self.error[0]),
-                _(self.error[1]) % self.error[2])
-
-
-def update_remote_calendars(publisher):
-    for source in RemoteCalendar.select():
-        source.download_and_parse()
-
-def get_default_event_tags():
-    return [_('All Public'), _('Adults'), _('Children'), _('Free')]
-
-get_publisher_class().register_cronjob(CronJob(update_remote_calendars, minutes = [0]))
-
diff --git a/auquotidien/modules/events_ui.py b/auquotidien/modules/events_ui.py
deleted file mode 100644
index 8e87b4d..0000000
--- a/auquotidien/modules/events_ui.py
+++ /dev/null
@@ -1,418 +0,0 @@
-import time
-
-from quixote import get_request, get_response, get_session, redirect
-from quixote.directory import Directory, AccessControlled
-from quixote.html import TemplateIO, htmltext
-
-import wcs
-import wcs.admin.root
-
-from wcs.qommon import _
-from wcs.qommon.backoffice.menu import html_top
-from wcs.qommon.admin.menu import command_icon
-from wcs.qommon import get_cfg
-from wcs.qommon import errors, misc
-from wcs.qommon.form import *
-from wcs.qommon.misc import strftime
-
-from .events import Event, RemoteCalendar, get_default_event_tags
-
-
-
-class RemoteCalendarDirectory(Directory):
-    _q_exports = ['', 'edit', 'delete', 'update']
-
-    def __init__(self, calendar):
-        self.calendar = calendar
-
-    def _q_index(self):
-        form = Form(enctype='multipart/form-data')
-        form.add_submit('edit', _('Edit'))
-        form.add_submit('delete', _('Delete'))
-        form.add_submit('update', _('Update'))
-        form.add_submit('back', _('Back'))
-
-        if form.get_submit() == 'edit':
-            return redirect('edit')
-        if form.get_submit() == 'update':
-            return redirect('update')
-        if form.get_submit() == 'delete':
-            return redirect('delete')
-        if form.get_submit() == 'back':
-            return redirect('..')
-
-        html_top('events', title = _('Remote Calendar: %s') % self.calendar.label)
-        r = TemplateIO(html=True)
-        r += htmltext('<h2>%s</h2>') % _('Remote Calendar: %s') % self.calendar.label
-
-        r += get_session().display_message()
-
-        r += htmltext('<p>')
-        self.calendar.url
-        if self.calendar.error:
-            r += htmltext(' - <span class="error-message">%s</span>') % self.calendar.get_error_message()
-        r += htmltext('</p>')
-
-        if not self.calendar.content:
-            r += htmltext('<p>')
-            r += _('No content has been retrieved yet.')
-            r += htmltext('</p>')
-        else:
-            r += htmltext('<ul>')
-            for ev in sorted(self.calendar.events, lambda x,y: cmp(x.date_start, y.date_start)):
-                r += htmltext('<li>')
-                if ev.date_start:
-                    r += strftime(misc.date_format(), ev.date_start)
-                if ev.date_end and ev.date_start[:3] != ev.date_end[:3]:
-                    r += ' - '
-                    r += strftime(misc.date_format(), ev.date_start)
-
-                r += ' : '
-                if ev.url:
-                    r += htmltext('<a href="%s">%s</a>') % (ev.url, ev.title)
-                else:
-                    r += ev.title
-                r += htmltext('</li>')
-            r += htmltext('</ul>')
-
-        r += form.render()
-        return r.getvalue()
-
-    def edit(self):
-        form = self.form()
-        if form.get_submit() == 'cancel':
-            return redirect('.')
-
-        if form.is_submitted() and not form.has_errors():
-            self.submit(form)
-            return redirect('..')
-
-        html_top('events', title = _('Edit Remote Calendar: %s') % self.calendar.label)
-        r = TemplateIO(html=True)
-        r += htmltext('<h2>%s</h2>') % _('Edit Remote Calendar: %s') % self.calendar.label
-        r += form.render()
-        return r.getvalue()
-
-    def form(self):
-        form = Form(enctype='multipart/form-data')
-        form.add(StringWidget, 'label', title = _('Label'), required = True,
-                value = self.calendar.label)
-        form.add(StringWidget, 'url', title = _('URL'), required = True,
-                value = self.calendar.url, size = 40)
-        form.add_submit('submit', _('Submit'))
-        form.add_submit('cancel', _('Cancel'))
-        return form
-
-    def submit(self, form):
-        for k in ('label', 'url'):
-            widget = form.get_widget(k)
-            if widget:
-                setattr(self.calendar, k, widget.parse())
-        self.calendar.store()
-
-    def delete(self):
-        form = Form(enctype='multipart/form-data')
-        form.widgets.append(HtmlWidget('<p>%s</p>' % _(
-                        'You are about to irrevocably delete this remote calendar.')))
-        form.add_submit('submit', _('Submit'))
-        form.add_submit('cancel', _('Cancel'))
-        if form.get_submit() == 'cancel':
-            return redirect('..')
-        if not form.is_submitted() or form.has_errors():
-            get_response().breadcrumb.append(('delete', _('Delete')))
-            html_top('events', title = _('Delete Remote Calendar'))
-            r = TemplateIO(html=True)
-            r += htmltext('<h2>%s</h2>') % _('Deleting Remote Calendar: %s') % self.calendar.label
-            r += form.render()
-            return r.getvalue()
-        else:
-            self.calendar.remove_self()
-            return redirect('..')
-
-    def update(self):
-        get_session().message = ('info',
-                _('Calendar update has been requested, reload in a few moments'))
-        get_response().add_after_job('updating remote calendar',
-                self.calendar.download_and_parse,
-                fire_and_forget = True)
-        return redirect('.')
-
-
-
-class RemoteCalendarsDirectory(Directory):
-    _q_exports = ['', 'new']
-
-    def _q_traverse(self, path):
-        get_response().breadcrumb.append(('remote/', _('Remote Calendars')))
-        return Directory._q_traverse(self, path)
-
-    def _q_index(self):
-        return redirect('..')
-
-    def new(self):
-        calendar_ui = RemoteCalendarDirectory(RemoteCalendar())
-
-        form = calendar_ui.form()
-        if form.get_submit() == 'cancel':
-            return redirect('.')
-
-        if form.is_submitted() and not form.has_errors():
-            calendar_ui.submit(form)
-            return redirect('%s/' % calendar_ui.calendar.id)
-
-        get_response().breadcrumb.append(('new', _('New Remote Calendar')))
-        html_top('events', title = _('New Remote Calendar'))
-        r = TemplateIO(html=True)
-        r += htmltext('<h2>%s</h2>') % _('New Remote Calendar')
-        r += form.render()
-        return r.getvalue()
-
-    def _q_lookup(self, component):
-        try:
-            event = RemoteCalendar.get(component)
-        except KeyError:
-            raise errors.TraversalError()
-        get_response().breadcrumb.append((str(event.id), event.label))
-        return RemoteCalendarDirectory(event)
-
-
-class EventDirectory(Directory):
-    _q_exports = ['', 'edit', 'delete']
-
-    def __init__(self, event):
-        self.event = event
-
-    def _q_index(self):
-        form = Form(enctype='multipart/form-data')
-        form.add_submit('edit', _('Edit'))
-        form.add_submit('delete', _('Delete'))
-        form.add_submit('back', _('Back'))
-
-        if form.get_submit() == 'edit':
-            return redirect('edit')
-        if form.get_submit() == 'delete':
-            return redirect('delete')
-        if form.get_submit() == 'back':
-            return redirect('..')
-
-        html_top('events', title = _('Event: %s') % self.event.title)
-        r = TemplateIO(html=True)
-        r += htmltext('<h2>%s</h2>') % _('Event: %s') % self.event.title
-        r += htmltext('<p>')
-        r += self.event.description
-        r += htmltext('</p>')
-        r += htmltext('<ul>')
-        if self.event.location:
-            r += htmltext('<li>%s: %s</li>') % (_('Location'), self.event.location)
-        if self.event.organizer:
-            r += htmltext('<li>%s: %s</li>') % (_('Organizer'), self.event.organizer)
-        if self.event.url:
-            r += htmltext('<li>%s: <a href="%s">%s</a></li>') % (_('URL'), self.event.url, self.event.url)
-        r += htmltext('</ul>')
-
-        if self.event.more_infos:
-            r += htmltext('<p>')
-            r += self.event.more_infos
-            r += htmltext('</p>')
-
-        r += form.render()
-        return r.getvalue()
-
-    def edit(self):
-        form = self.form()
-        if form.get_submit() == 'cancel':
-            return redirect('.')
-
-        if form.is_submitted() and not form.has_errors():
-            self.submit(form)
-            return redirect('..')
-
-        html_top('events', title = _('Edit Event: %s') % self.event.title)
-        r = TemplateIO(html=True)
-        r += htmltext('<h2>%s</h2>') % _('Edit Event: %s') % self.event.title
-        r += form.render()
-        return r.getvalue()
-
-    def form(self):
-        form = Form(enctype='multipart/form-data')
-        form.add(StringWidget, 'title', title = _('Title'), required = True,
-                value = self.event.title)
-        form.add(TextWidget, 'description', title = _('Description'),
-                cols = 70, rows = 10,
-                required = True, value = self.event.description)
-        form.add(StringWidget, 'url', title = _('URL'), required = False,
-                value = self.event.url, size = 40)
-        form.add(DateWidget, 'date_start', title = _('Start Date'), required = True,
-                value = strftime(misc.date_format(), self.event.date_start))
-        form.add(DateWidget, 'date_end', title = _('End Date'), required = False,
-                value = strftime(misc.date_format(), self.event.date_end))
-        form.add(TextWidget, 'location', title = _('Location'),
-                cols = 70, rows = 4,
-                required = False, value = self.event.location)
-        form.add(StringWidget, 'organizer', title = _('Organizer'), required = False,
-                value = self.event.organizer, size = 40)
-        form.add(TextWidget, 'more_infos', title = _('More informations'),
-                cols = 70, rows = 10,
-                required = False, value = self.event.more_infos)
-        form.add(TagsWidget, 'keywords', title = _('Keywords'),
-                value = self.event.keywords, size = 50,
-                known_tags = get_cfg('misc', {}).get('event_tags', get_default_event_tags()))
-        form.add_submit('submit', _('Submit'))
-        form.add_submit('cancel', _('Cancel'))
-        return form
-
-    def submit(self, form):
-        for k in ('title', 'description', 'url', 'date_start', 'date_end',
-                    'organizer', 'location', 'more_infos', 'keywords'):
-            widget = form.get_widget(k)
-            if widget:
-                if k in ('date_start', 'date_end'):
-                    # convert dates to 9-item tuples
-                    v = widget.parse()
-                    if v:
-                        setattr(self.event, k, time.strptime(v, misc.date_format()))
-                    else:
-                        setattr(self.event, k, None)
-                else:
-                    setattr(self.event, k, widget.parse())
-        self.event.store()
-
-    def delete(self):
-        form = Form(enctype='multipart/form-data')
-        form.widgets.append(HtmlWidget('<p>%s</p>' % _(
-                        'You are about to irrevocably delete this event.')))
-        form.add_submit('submit', _('Submit'))
-        form.add_submit('cancel', _('Cancel'))
-        if form.get_submit() == 'cancel':
-            return redirect('..')
-        if not form.is_submitted() or form.has_errors():
-            get_response().breadcrumb.append(('delete', _('Delete')))
-            html_top('events', title = _('Delete Event'))
-            r = TemplateIO(html=True)
-            r += htmltext('<h2>%s</h2>') % _('Deleting Event: %s') % self.event.title
-            r += form.render()
-            return r.getvalue()
-        else:
-            self.event.remove_self()
-            return redirect('..')
-
-
-
-
-class EventsDirectory(AccessControlled, Directory):
-    _q_exports = ['', 'new', 'listing', 'remote']
-    label = N_('Events')
-
-    remote = RemoteCalendarsDirectory()
-
-    def is_accessible(self, user):
-        from .backoffice import check_visibility
-        return check_visibility('events', user)
-
-    def _q_access(self):
-        user = get_request().user
-        if not user:
-            raise errors.AccessUnauthorizedError()
-
-        if not self.is_accessible(user):
-            raise errors.AccessForbiddenError(
-                    public_msg = _('You are not allowed to access Events Management'),
-                    location_hint = 'backoffice')
-
-        get_response().breadcrumb.append(('events/', _('Events')))
-
-
-    def _q_index(self):
-        html_top('events', _('Events'))
-        r = TemplateIO(html=True)
-
-        get_response().filter['sidebar'] = self.get_sidebar()
-
-        r += htmltext('<div class="splitcontent-left">')
-
-        r += htmltext('<div class="bo-block">')
-        events = Event.select()
-        r += htmltext('<h2>%s</h2>') % _('Events')
-        if not events:
-            r += htmltext('<p>')
-            r += _('There is no event defined at the moment.')
-            r += htmltext('</p>')
-        r += htmltext('<ul class="biglist" id="events-list">')
-        for l in events:
-            event_id = l.id
-            r += htmltext('<li class="biglistitem" id="itemId_%s">') % event_id
-            r += htmltext('<strong class="label"><a href="%s/">%s</a></strong>') % (event_id, l.title)
-            r += ' - '
-            r += l.format_date()
-            r += htmltext('<p class="commands">')
-            r += command_icon('%s/edit' % event_id, 'edit')
-            r += command_icon('%s/delete' % event_id, 'remove')
-            r += htmltext('</p></li>')
-        r += htmltext('</ul>')
-        r += htmltext('</div>')
-        r += htmltext('</div>')
-
-        r += htmltext('<div class="splitcontent-right">')
-        r += htmltext('<div class="bo-block">')
-        rcalendars = RemoteCalendar.select()
-        r += htmltext('<h2>%s</h2>') % _('Remote Calendars')
-        if not rcalendars:
-            r += htmltext('<p>')
-            r += _('There is no remote calendars defined at the moment.')
-            r += htmltext('</p>')
-
-        r += htmltext('<ul class="biglist" id="events-list">')
-        for l in rcalendars:
-            rcal_id = l.id
-            r += htmltext('<li class="biglistitem" id="itemId_%s">') % rcal_id
-            r += htmltext('<strong class="label"><a href="remote/%s/">%s</a></strong>') % (rcal_id, l.label)
-            r += htmltext('<p class="details">')
-            r += l.url
-            if l.error:
-                r += htmltext('<br /><span class="error-message">%s</span>') % l.get_error_message()
-            r += htmltext('</p>')
-            r += htmltext('<p class="commands">')
-            r += command_icon('remote/%s/edit' % rcal_id, 'edit')
-            r += command_icon('remote/%s/delete' % rcal_id, 'remove')
-            r += htmltext('</p></li>')
-        r += htmltext('</ul>')
-        r += htmltext('</div>')
-        r += htmltext('</div>')
-        return r.getvalue()
-
-    def get_sidebar(self):
-        r = TemplateIO(html=True)
-        r += htmltext('<ul id="sidebar-actions">')
-        r += htmltext('  <li><a class="new-item" href="new">%s</a></li>') % _('New Event')
-        r += htmltext('  <li><a class="new-item" href="remote/new">%s</a></li>') % _('New Remote Calendar')
-        r += htmltext('</ul>')
-        return r.getvalue()
-
-    def new(self):
-        event_ui = EventDirectory(Event())
-
-        form = event_ui.form()
-        if form.get_submit() == 'cancel':
-            return redirect('.')
-
-        if form.is_submitted() and not form.has_errors():
-            event_ui.submit(form)
-            return redirect('%s/' % event_ui.event.id)
-
-        get_response().breadcrumb.append(('new', _('New Event')))
-        html_top('events', title = _('New Event'))
-        r = TemplateIO(html=True)
-        r += htmltext('<h2>%s</h2>') % _('New Event')
-        r += form.render()
-        return r.getvalue()
-
-    def _q_lookup(self, component):
-        try:
-            event = Event.get(component)
-        except KeyError:
-            raise errors.TraversalError()
-        get_response().breadcrumb.append((str(event.id), event.title))
-        return EventDirectory(event)
-
-    def listing(self):
-        return redirect('.')
diff --git a/auquotidien/modules/root.py b/auquotidien/modules/root.py
index d6664d7..253d36b 100644
--- a/auquotidien/modules/root.py
+++ b/auquotidien/modules/root.py
@@ -36,8 +36,6 @@ from wcs.qommon.admin.texts import TextsDirectory
 
 from .announces import Announce, AnnounceSubscription
 from .myspace import MyspaceDirectory
-from .agenda import AgendaDirectory
-from .events import Event, get_default_event_tags
 from .payments import PublicPaymentDirectory
 from .payments_ui import InvoicesDirectory
 
@@ -760,7 +758,7 @@ class AlternateRootDirectory(OldRootDirectory):
             'saml', 'register', 'ident', 'afterjobs',
             ('informations-editeur', 'informations_editeur'),
             ('announces', 'announces_dir'),
-            'myspace', 'services', 'agenda', 'categories', 'user',
+            'myspace', 'services', 'categories', 'user',
             ('tmp-upload', 'tmp_upload'), 'json', '__version__',
             'themes', 'pages', 'payment', 'invoices', 'roles',
             'api', 'code', 'fargo', 'tryauth', 'auth', 'preview',
@@ -772,7 +770,6 @@ class AlternateRootDirectory(OldRootDirectory):
     login = AlternateLoginDirectory()
     ident = AlternateIdentDirectory()
     myspace = MyspaceDirectory()
-    agenda = AgendaDirectory()
     saml = Saml2Directory()
     payment = PublicPaymentDirectory()
     invoices = InvoicesDirectory()
@@ -1095,24 +1092,6 @@ class AlternateRootDirectory(OldRootDirectory):
             r += htmltext('</ul>')
             r += htmltext('</div>')
 
-        if get_cfg('aq-permissions', {}).get('events') and Event.keys():
-            # if there are events, add a link to the agenda
-            tags = get_cfg('misc', {}).get('event_tags')
-            if not tags:
-                tags = get_default_event_tags()
-            r += htmltext('<h3 id="agenda-link"><a href="%sagenda/">%s</a></h3>') % (root_url, _('Agenda'))
-
-            if path and path[0] == 'agenda':
-                r += htmltext('<p class="tags">')
-                for tag in tags:
-                    r += htmltext('<a href="%sagenda/tag/%s">%s</a> ') % (root_url, tag, tag)
-                r += htmltext('</p>')
-                r += self.agenda.display_remote_calendars()
-
-                r += htmltext('<p>')
-                r += htmltext('  <a href="%sagenda/filter">%s</a>') % (root_url, _('Advanced Filter'))
-                r += htmltext('</p>')
-
         v = r.getvalue()
         if v:
             r = TemplateIO(html=True)
diff --git a/auquotidien/modules/template.py b/auquotidien/modules/template.py
index 8ab097e..3b2a3c9 100644
--- a/auquotidien/modules/template.py
+++ b/auquotidien/modules/template.py
@@ -48,11 +48,6 @@ def render_response(publisher, body):
         section_title = '<h2 id="announces">%s</h2>\n' % _('Announces to citizens')
         if page_title == _('Announces to citizens'):
             page_title = ''
-    elif section == 'agenda':
-        response.filter['bigdiv'] = 'rub_agenda'
-        section_title = '<h2 id="agenda">%s</h2>\n' % _('Agenda')
-        if page_title == _('Agenda'):
-            page_title = ''
     elif section and len(section) > 1:
         # XXX: this works but is not efficient
         if Category.has_urlname(section):
-- 
2.24.0

