Export activites as an ICS Calendar

This commit is contained in:
Yohann D'ANELLO 2020-09-04 18:36:20 +02:00
parent 5c7fe716ad
commit 70e1a611dd
3 changed files with 346 additions and 287 deletions

View File

@ -14,4 +14,5 @@ urlpatterns = [
path('<int:pk>/entry/', views.ActivityEntryView.as_view(), name='activity_entry'),
path('<int:pk>/update/', views.ActivityUpdateView.as_view(), name='activity_update'),
path('new/', views.ActivityCreateView.as_view(), name='activity_create'),
path('calendar.ics', views.CalendarView.as_view(), name='calendar_ics'),
]

View File

@ -1,14 +1,17 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from hashlib import md5
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
from django.db.models import F, Q
from django.http import HttpResponse
from django.urls import reverse_lazy
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.views import View
from django.views.generic import DetailView, TemplateView, UpdateView
from django_tables2.views import SingleTableView
from note.models import Alias, NoteSpecial, NoteUser
@ -281,3 +284,61 @@ class ActivityEntryView(LoginRequiredMixin, TemplateView):
Entry(activity=a, note=self.request.user.note,))]
return context
class CalendarView(View):
"""
Render an ICS calendar with all valid activities.
"""
def multilines(self, string, maxlength, offset=0):
newstring = string[:maxlength - offset]
string = string[maxlength - offset:]
while string:
newstring += "\r\n "
newstring += string[:maxlength - 1]
string = string[maxlength - 1:]
return newstring
def get(self, request, *args, **kwargs):
ics = """BEGIN:VCALENDAR
VERSION: 2.0
PRODID:Note Kfet 2020
X-WR-CALNAME:Kfet Calendar
NAME:Kfet Calendar
CALSCALE:GREGORIAN
BEGIN:VTIMEZONE
TZID:Europe/Berlin
TZURL:http://tzurl.org/zoneinfo-outlook/Europe/Berlin
X-LIC-LOCATION:Europe/Berlin
BEGIN:DAYLIGHT
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
TZNAME:CEST
DTSTART:19700329T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
TZNAME:CET
DTSTART:19701025T030000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
END:STANDARD
END:VTIMEZONE
"""
for activity in Activity.objects.filter(valid=True).order_by("-date_start").all():
ics += f"""BEGIN:VEVENT
DTSTAMP:{"{:%Y%m%dT%H%M%S}".format(activity.date_start)}Z
UID:{activity.id}
SUMMARY;CHARSET=UTF-8:{self.multilines(activity.name, 75, 22)}
DTSTART;TZID=Europe/Berlin:{"{:%Y%m%dT%H%M%S}".format(activity.date_start)}
DTEND;TZID=Europe/Berlin:{"{:%Y%m%dT%H%M%S}".format(activity.date_end)}
LOCATION:{self.multilines(activity.location, 75, 9) if activity.location else "Kfet"}
DESCRIPTION;CHARSET=UTF-8:{self.multilines(activity.description, 75, 26)}
-- {activity.organizer.name}
END:VEVENT
"""
ics += "END:VCALENDAR"
ics = ics.replace("\r", "").replace("\n", "\r\n")
return HttpResponse(ics, content_type="text/calendar; charset=UTF-8")

View File

@ -117,10 +117,7 @@ def delete_object(sender, instance, **kwargs):
Each time a model is deleted, an entry in the table `Changelog` is added in the database
"""
# noinspection PyProtectedMember
if instance._meta.label_lower in EXCLUDED:
return
if hasattr(instance, "_no_log"):
if instance._meta.label_lower in EXCLUDED or hasattr(instance, "_no_log"):
return
# Si un utilisateur est connecté, on récupère l'utilisateur courant ainsi que son adresse IP