mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-10-31 07:49:57 +01:00 
			
		
		
		
	Export activites as an ICS Calendar
This commit is contained in:
		| @@ -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'), | ||||
| ] | ||||
|   | ||||
| @@ -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") | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user