Refactoring: on sépare la partie calendrier
This commit is contained in:
parent
9daf35b4aa
commit
2a50c04352
158
src/agenda_culturel/calendar.py
Normal file
158
src/agenda_culturel/calendar.py
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
from datetime import datetime, timedelta, date, time
|
||||||
|
import calendar
|
||||||
|
|
||||||
|
|
||||||
|
def daterange(start, end, step=timedelta(1)):
|
||||||
|
if end is None:
|
||||||
|
yield start
|
||||||
|
else:
|
||||||
|
curr = start
|
||||||
|
while curr <= end:
|
||||||
|
yield curr
|
||||||
|
curr += step
|
||||||
|
|
||||||
|
|
||||||
|
class CalendarDay:
|
||||||
|
midnight = time(23, 59, 59)
|
||||||
|
|
||||||
|
def __init__(self, d, on_requested_interval = True):
|
||||||
|
self.date = d
|
||||||
|
now = date.today()
|
||||||
|
self.week = d.isocalendar()[1]
|
||||||
|
|
||||||
|
self.in_past = d < now
|
||||||
|
self.today = d == now
|
||||||
|
self.events = []
|
||||||
|
self.on_requested_interval = on_requested_interval
|
||||||
|
|
||||||
|
self.events_by_category = {}
|
||||||
|
|
||||||
|
def is_in_past(self):
|
||||||
|
return self.in_past
|
||||||
|
def is_today(self):
|
||||||
|
return self.today
|
||||||
|
|
||||||
|
def is_event_finishing_early_in_this_day(self, event):
|
||||||
|
if event.end_day is None or event.end_time is None:
|
||||||
|
return False
|
||||||
|
if event.start_day == event.end_day:
|
||||||
|
return False
|
||||||
|
return event.end_day == self.date and event.end_time < time(8)
|
||||||
|
|
||||||
|
def add_event(self, event):
|
||||||
|
if not self.is_event_finishing_early_in_this_day(event):
|
||||||
|
self.events.append(event)
|
||||||
|
if event.category is None:
|
||||||
|
if not "" in self.events_by_category:
|
||||||
|
self.events_by_category[""] = []
|
||||||
|
self.events_by_category[""].append(event)
|
||||||
|
else:
|
||||||
|
if not event.category.name in self.events_by_category:
|
||||||
|
self.events_by_category[event.category.name] = []
|
||||||
|
self.events_by_category[event.category.name].append(event)
|
||||||
|
|
||||||
|
def filter_events(self):
|
||||||
|
self.events.sort(key=lambda e: CalendarDay.midnight if e.start_time is None else e.start_time)
|
||||||
|
|
||||||
|
|
||||||
|
class CalendarList:
|
||||||
|
|
||||||
|
def __init__(self, firstdate, lastdate, filter):
|
||||||
|
self.firstdate = firstdate
|
||||||
|
self.lastdate = lastdate
|
||||||
|
self.now = date.today()
|
||||||
|
self.filter = filter
|
||||||
|
|
||||||
|
# start the first day of the first week
|
||||||
|
self.c_firstdate = firstdate + timedelta(days=-firstdate.weekday())
|
||||||
|
# end the last day of the last week
|
||||||
|
self.c_lastdate = lastdate + timedelta(days=6-lastdate.weekday())
|
||||||
|
|
||||||
|
|
||||||
|
# create a list of CalendarDays
|
||||||
|
self.create_calendar_days()
|
||||||
|
|
||||||
|
# fill CalendarDays with events
|
||||||
|
self.fill_calendar_days()
|
||||||
|
|
||||||
|
# finally, sort each CalendarDay
|
||||||
|
for i, c in self.calendar_days.items():
|
||||||
|
c.filter_events()
|
||||||
|
|
||||||
|
|
||||||
|
def today_in_calendar(self):
|
||||||
|
return self.firstdate <= self.now and self.lastdate >= self.now
|
||||||
|
|
||||||
|
def all_in_past(self):
|
||||||
|
return self.lastdate < self.now
|
||||||
|
|
||||||
|
def fill_calendar_days(self):
|
||||||
|
if self.filter is None:
|
||||||
|
qs = Event.objects()
|
||||||
|
else:
|
||||||
|
qs = self.filter.qs
|
||||||
|
self.events = qs.filter(start_day__lte=self.c_lastdate, start_day__gte=self.c_firstdate).order_by("start_day", "start_time")
|
||||||
|
|
||||||
|
for e in self.events:
|
||||||
|
for d in daterange(e.start_day, e.end_day):
|
||||||
|
if d.__str__() in self.calendar_days:
|
||||||
|
self.calendar_days[d.__str__()].add_event(e)
|
||||||
|
|
||||||
|
|
||||||
|
def create_calendar_days(self):
|
||||||
|
# create daylist
|
||||||
|
self.calendar_days = {}
|
||||||
|
for d in daterange(self.c_firstdate, self.c_lastdate):
|
||||||
|
self.calendar_days[d.strftime("%Y-%m-%d")] = CalendarDay(d, d >= self.firstdate and d <= self.lastdate)
|
||||||
|
|
||||||
|
|
||||||
|
def is_single_week(self):
|
||||||
|
return hasattr(self, "week")
|
||||||
|
|
||||||
|
|
||||||
|
def is_full_month(self):
|
||||||
|
return hasattr(self, "month")
|
||||||
|
|
||||||
|
|
||||||
|
def calendar_days_list(self):
|
||||||
|
return list(self.calendar_days.values())
|
||||||
|
|
||||||
|
class CalendarMonth(CalendarList):
|
||||||
|
|
||||||
|
def __init__(self, year, month, filter):
|
||||||
|
self.year = year
|
||||||
|
self.month = month
|
||||||
|
r = calendar.monthrange(year, month)
|
||||||
|
|
||||||
|
first = date(year, month, 1)
|
||||||
|
last = date(year, month, r[1])
|
||||||
|
|
||||||
|
super().__init__(first, last, filter)
|
||||||
|
|
||||||
|
def get_month_name(self):
|
||||||
|
return self.firstdate.strftime("%B")
|
||||||
|
|
||||||
|
def next_month(self):
|
||||||
|
return self.lastdate + timedelta(days=7)
|
||||||
|
|
||||||
|
def previous_month(self):
|
||||||
|
return self.firstdate + timedelta(days=-7)
|
||||||
|
|
||||||
|
|
||||||
|
class CalendarWeek(CalendarList):
|
||||||
|
|
||||||
|
def __init__(self, year, week, filter):
|
||||||
|
self.year = year
|
||||||
|
self.week = week
|
||||||
|
|
||||||
|
first = date.fromisocalendar(self.year, self.week, 1)
|
||||||
|
last = date.fromisocalendar(self.year, self.week, 7)
|
||||||
|
|
||||||
|
super().__init__(first, last, filter)
|
||||||
|
|
||||||
|
def next_week(self):
|
||||||
|
return self.firstdate + timedelta(days=7)
|
||||||
|
|
||||||
|
def previous_week(self):
|
||||||
|
return self.firstdate + timedelta(days=-7)
|
||||||
|
|
@ -14,8 +14,7 @@ from .celery import create_event_from_submission
|
|||||||
from .models import Event, Category, StaticContent
|
from .models import Event, Category, StaticContent
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from enum import StrEnum
|
from enum import StrEnum
|
||||||
from datetime import datetime, timedelta, date, time
|
from datetime import date
|
||||||
import calendar
|
|
||||||
from django.db.models import Q, F
|
from django.db.models import Q, F
|
||||||
|
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
@ -28,6 +27,8 @@ from django.contrib.auth.decorators import login_required
|
|||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.messages.views import SuccessMessageMixin
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
|
|
||||||
|
from .calendar import CalendarMonth, CalendarWeek
|
||||||
|
|
||||||
import unicodedata
|
import unicodedata
|
||||||
|
|
||||||
|
|
||||||
@ -38,159 +39,6 @@ def get_event_qs(request):
|
|||||||
return Event.objects.filter(status=Event.STATUS.PUBLISHED)
|
return Event.objects.filter(status=Event.STATUS.PUBLISHED)
|
||||||
|
|
||||||
|
|
||||||
def daterange(start, end, step=timedelta(1)):
|
|
||||||
if end is None:
|
|
||||||
yield start
|
|
||||||
else:
|
|
||||||
curr = start
|
|
||||||
while curr <= end:
|
|
||||||
yield curr
|
|
||||||
curr += step
|
|
||||||
|
|
||||||
|
|
||||||
class CalendarDay:
|
|
||||||
midnight = time(23, 59, 59)
|
|
||||||
|
|
||||||
def __init__(self, d, on_requested_interval = True):
|
|
||||||
self.date = d
|
|
||||||
now = date.today()
|
|
||||||
self.week = d.isocalendar()[1]
|
|
||||||
|
|
||||||
self.in_past = d < now
|
|
||||||
self.today = d == now
|
|
||||||
self.events = []
|
|
||||||
self.on_requested_interval = on_requested_interval
|
|
||||||
|
|
||||||
self.events_by_category = {}
|
|
||||||
|
|
||||||
def is_in_past(self):
|
|
||||||
return self.in_past
|
|
||||||
def is_today(self):
|
|
||||||
return self.today
|
|
||||||
|
|
||||||
def is_event_finishing_early_in_this_day(self, event):
|
|
||||||
if event.end_day is None or event.end_time is None:
|
|
||||||
return False
|
|
||||||
if event.start_day == event.end_day:
|
|
||||||
return False
|
|
||||||
return event.end_day == self.date and event.end_time < time(8)
|
|
||||||
|
|
||||||
def add_event(self, event):
|
|
||||||
if not self.is_event_finishing_early_in_this_day(event):
|
|
||||||
self.events.append(event)
|
|
||||||
if event.category is None:
|
|
||||||
if not "" in self.events_by_category:
|
|
||||||
self.events_by_category[""] = []
|
|
||||||
self.events_by_category[""].append(event)
|
|
||||||
else:
|
|
||||||
if not event.category.name in self.events_by_category:
|
|
||||||
self.events_by_category[event.category.name] = []
|
|
||||||
self.events_by_category[event.category.name].append(event)
|
|
||||||
|
|
||||||
def filter_events(self):
|
|
||||||
self.events.sort(key=lambda e: CalendarDay.midnight if e.start_time is None else e.start_time)
|
|
||||||
|
|
||||||
|
|
||||||
class CalendarList:
|
|
||||||
|
|
||||||
def __init__(self, firstdate, lastdate, filter):
|
|
||||||
self.firstdate = firstdate
|
|
||||||
self.lastdate = lastdate
|
|
||||||
self.now = date.today()
|
|
||||||
self.filter = filter
|
|
||||||
|
|
||||||
# start the first day of the first week
|
|
||||||
self.c_firstdate = firstdate + timedelta(days=-firstdate.weekday())
|
|
||||||
# end the last day of the last week
|
|
||||||
self.c_lastdate = lastdate + timedelta(days=6-lastdate.weekday())
|
|
||||||
|
|
||||||
|
|
||||||
# create a list of CalendarDays
|
|
||||||
self.create_calendar_days()
|
|
||||||
|
|
||||||
# fill CalendarDays with events
|
|
||||||
self.fill_calendar_days()
|
|
||||||
|
|
||||||
# finally, sort each CalendarDay
|
|
||||||
for i, c in self.calendar_days.items():
|
|
||||||
c.filter_events()
|
|
||||||
|
|
||||||
|
|
||||||
def today_in_calendar(self):
|
|
||||||
return self.firstdate <= self.now and self.lastdate >= self.now
|
|
||||||
|
|
||||||
def all_in_past(self):
|
|
||||||
return self.lastdate < self.now
|
|
||||||
|
|
||||||
def fill_calendar_days(self):
|
|
||||||
if self.filter is None:
|
|
||||||
qs = Event.objects()
|
|
||||||
else:
|
|
||||||
qs = self.filter.qs
|
|
||||||
self.events = qs.filter(start_day__lte=self.c_lastdate, start_day__gte=self.c_firstdate).order_by("start_day", "start_time")
|
|
||||||
|
|
||||||
for e in self.events:
|
|
||||||
for d in daterange(e.start_day, e.end_day):
|
|
||||||
if d.__str__() in self.calendar_days:
|
|
||||||
self.calendar_days[d.__str__()].add_event(e)
|
|
||||||
|
|
||||||
|
|
||||||
def create_calendar_days(self):
|
|
||||||
# create daylist
|
|
||||||
self.calendar_days = {}
|
|
||||||
for d in daterange(self.c_firstdate, self.c_lastdate):
|
|
||||||
self.calendar_days[d.strftime("%Y-%m-%d")] = CalendarDay(d, d >= self.firstdate and d <= self.lastdate)
|
|
||||||
|
|
||||||
|
|
||||||
def is_single_week(self):
|
|
||||||
return hasattr(self, "week")
|
|
||||||
|
|
||||||
|
|
||||||
def is_full_month(self):
|
|
||||||
return hasattr(self, "month")
|
|
||||||
|
|
||||||
|
|
||||||
def calendar_days_list(self):
|
|
||||||
return list(self.calendar_days.values())
|
|
||||||
|
|
||||||
class CalendarMonth(CalendarList):
|
|
||||||
|
|
||||||
def __init__(self, year, month, filter):
|
|
||||||
self.year = year
|
|
||||||
self.month = month
|
|
||||||
r = calendar.monthrange(year, month)
|
|
||||||
|
|
||||||
first = date(year, month, 1)
|
|
||||||
last = date(year, month, r[1])
|
|
||||||
|
|
||||||
super().__init__(first, last, filter)
|
|
||||||
|
|
||||||
def get_month_name(self):
|
|
||||||
return self.firstdate.strftime("%B")
|
|
||||||
|
|
||||||
def next_month(self):
|
|
||||||
return self.lastdate + timedelta(days=7)
|
|
||||||
|
|
||||||
def previous_month(self):
|
|
||||||
return self.firstdate + timedelta(days=-7)
|
|
||||||
|
|
||||||
|
|
||||||
class CalendarWeek(CalendarList):
|
|
||||||
|
|
||||||
def __init__(self, year, week, filter):
|
|
||||||
self.year = year
|
|
||||||
self.week = week
|
|
||||||
|
|
||||||
first = date.fromisocalendar(self.year, self.week, 1)
|
|
||||||
last = date.fromisocalendar(self.year, self.week, 7)
|
|
||||||
|
|
||||||
super().__init__(first, last, filter)
|
|
||||||
|
|
||||||
def next_week(self):
|
|
||||||
return self.firstdate + timedelta(days=7)
|
|
||||||
|
|
||||||
def previous_week(self):
|
|
||||||
return self.firstdate + timedelta(days=-7)
|
|
||||||
|
|
||||||
|
|
||||||
class CategoryCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
|
class CategoryCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
|
||||||
|
Loading…
Reference in New Issue
Block a user