From 5604b3083fd8b14c655fec0b1bd0d3de9a96e51b Mon Sep 17 00:00:00 2001
From: Maksudul Haque
Date: Tue, 25 Oct 2022 22:19:11 +0600
Subject: [PATCH 1/3] Display Ongoing Events on the Events Page
---
.gitignore | 1 +
events/models.py | 45 +++++++++++++++++-
events/tests/test_models.py | 78 ++++++++++++++++++++++++++++++++
events/views.py | 7 ++-
templates/events/event_list.html | 20 ++++++++
5 files changed, 149 insertions(+), 2 deletions(-)
diff --git a/.gitignore b/.gitignore
index 60836490f..954ff2401 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,4 @@ __pycache__
.env
.DS_Store
.envrc
+.state/
diff --git a/events/models.py b/events/models.py
index 3334ca326..457e77aea 100644
--- a/events/models.py
+++ b/events/models.py
@@ -93,6 +93,16 @@ def for_datetime(self, dt=None):
dt = convert_dt_to_aware(dt)
return self.filter(Q(occurring_rule__dt_start__gt=dt) | Q(recurring_rules__finish__gt=dt))
+ def ongoing_datetime(self, dt=None):
+ if dt is None:
+ dt = timezone.now()
+ else:
+ dt = convert_dt_to_aware(dt)
+ return self.filter(
+ (Q(occurring_rule__dt_start__lt=dt) & Q(occurring_rule__dt_end__gt=dt))
+ | (Q(recurring_rules__begin__lt=dt) & Q(recurring_rules__finish__gt=dt))
+ )
+
def until_datetime(self, dt=None):
if dt is None:
dt = timezone.now()
@@ -181,6 +191,39 @@ def next_time(self):
except IndexError:
return None
+ @property
+ def present_time(self):
+ """
+ Return the OccurringRule or RecurringRule that are ongoing now.
+ """
+ now = timezone.now()
+ recurring_start = occurring_start = None
+
+ try:
+ occurring_rule = self.occurring_rule
+ except OccurringRule.DoesNotExist:
+ pass
+ else:
+ if occurring_rule and occurring_rule.dt_start < now and occurring_rule.dt_end > now:
+ occurring_start = (occurring_rule.dt_start, occurring_rule)
+
+ rrules = self.recurring_rules.filter(begin__lt=now, finish__gt=now)
+ recurring_starts = [(rule.dt_start, rule) for rule in rrules if rule.dt_start is not None]
+ recurring_starts.sort(key=itemgetter(0))
+
+ try:
+ recurring_start = recurring_starts[0]
+ except IndexError:
+ pass
+
+ starts = [i for i in (recurring_start, occurring_start) if i is not None]
+ starts.sort(key=itemgetter(0))
+
+ try:
+ return starts[0][1]
+ except IndexError:
+ return None
+
@property
def previous_time(self):
now = timezone.now()
@@ -216,7 +259,7 @@ def next_or_previous_time(self):
@property
def is_past(self):
- return self.next_time is None
+ return self.next_time is None and self.present_time is None
class RuleMixin:
diff --git a/events/tests/test_models.py b/events/tests/test_models.py
index 0f3bafe76..855436408 100644
--- a/events/tests/test_models.py
+++ b/events/tests/test_models.py
@@ -47,6 +47,47 @@ def test_occurring_event(self):
self.assertEqual(self.event.next_time, None)
self.assertTrue(self.event.is_past)
+ def test_ongoing_occurring_event(self):
+ now = seconds_resolution(timezone.now())
+
+ # Starts before and ends after now
+ occurring_time_dtstart = now - datetime.timedelta(days=3)
+ occurring_time_dtend = occurring_time_dtstart + datetime.timedelta(days=5)
+
+ ot = OccurringRule.objects.create(
+ event=self.event,
+ dt_start=occurring_time_dtstart,
+ dt_end=occurring_time_dtend,
+ )
+
+ self.assertEqual(Event.objects.ongoing_datetime().count(), 1)
+ self.assertIsNone(self.event.next_time)
+ self.assertIsNone(self.event.previous_time)
+ self.assertIsNotNone(self.event.present_time)
+ self.assertEqual(self.event.present_time.dt_start, occurring_time_dtstart)
+ self.assertEqual(self.event.present_time.dt_end, occurring_time_dtend)
+ self.assertFalse(self.event.is_past)
+
+ # Starts before and ends before now
+ ot.dt_start = now - datetime.timedelta(days=5)
+ ot.dt_end = now - datetime.timedelta(days=3)
+ ot.save()
+
+ event = Event.objects.get(pk=self.event.pk)
+ self.assertEqual(Event.objects.ongoing_datetime().count(), 0)
+ self.assertIsNone(event.present_time)
+ self.assertTrue(event.is_past)
+
+ # Starts after and ends after now
+ ot.dt_start = now + datetime.timedelta(days=3)
+ ot.dt_end = now + datetime.timedelta(days=5)
+ ot.save()
+
+ event = Event.objects.get(pk=self.event.pk)
+ self.assertEqual(Event.objects.ongoing_datetime().count(), 0)
+ self.assertIsNone(event.present_time)
+ self.assertFalse(event.is_past)
+
def test_recurring_event(self):
now = seconds_resolution(timezone.now())
@@ -71,6 +112,43 @@ def test_recurring_event(self):
self.assertEqual(event.next_time, None)
self.assertEqual(Event.objects.for_datetime().count(), 0)
+ def test_ongoing_recurring_event(self):
+ now = seconds_resolution(timezone.now())
+
+ # Starts before and ends after now
+ recurring_time_dtstart = now - datetime.timedelta(days=3)
+ recurring_time_dtend = recurring_time_dtstart + datetime.timedelta(days=5)
+
+ rt = RecurringRule.objects.create(
+ event=self.event,
+ begin=recurring_time_dtstart,
+ finish=recurring_time_dtend,
+ )
+ self.assertEqual(Event.objects.ongoing_datetime().count(), 1)
+ self.assertGreater(self.event.present_time.dt_start, recurring_time_dtstart)
+ self.assertTrue(rt.valid_dt_end())
+ self.assertFalse(self.event.is_past)
+
+ # Starts before and ends before now
+ rt.begin = now - datetime.timedelta(days=5)
+ rt.finish = now - datetime.timedelta(days=3)
+ rt.save()
+
+ event = Event.objects.get(pk=self.event.pk)
+ self.assertEqual(Event.objects.ongoing_datetime().count(), 0)
+ self.assertIsNone(event.present_time)
+ self.assertTrue(event.is_past)
+
+ # Starts after and ends after now
+ rt.begin = now + datetime.timedelta(days=3)
+ rt.finish = now + datetime.timedelta(days=5)
+ rt.save()
+
+ event = Event.objects.get(pk=self.event.pk)
+ self.assertEqual(Event.objects.ongoing_datetime().count(), 0)
+ self.assertIsNone(event.present_time)
+ self.assertFalse(event.is_past)
+
def test_rrule(self):
now = seconds_resolution(timezone.now())
diff --git a/events/views.py b/events/views.py
index 2490626e3..7356daa20 100644
--- a/events/views.py
+++ b/events/views.py
@@ -72,7 +72,12 @@ def get_queryset(self):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
- context['events_today'] = Event.objects.until_datetime(timezone.now()).filter(calendar__slug=self.kwargs['calendar_slug'])[:2]
+ context['events_today'] = Event.objects.until_datetime(timezone.now()).filter(
+ calendar__slug=self.kwargs['calendar_slug']
+ )[:5]
+ context['events_ongoing'] = Event.objects.ongoing_datetime(timezone.now()).filter(
+ calendar__slug=self.kwargs['calendar_slug']
+ )
context['calendar'] = get_object_or_404(Calendar, slug=self.kwargs['calendar_slug'])
return context
diff --git a/templates/events/event_list.html b/templates/events/event_list.html
index bbfb764d2..15a9967b9 100644
--- a/templates/events/event_list.html
+++ b/templates/events/event_list.html
@@ -57,6 +57,26 @@
+
{% endfor %}
{% endif %}
From 7cb09e71e31ee575e3552bc99c3448728e45ae63 Mon Sep 17 00:00:00 2001
From: Maksudul Haque
Date: Tue, 25 Oct 2022 23:04:31 +0600
Subject: [PATCH 3/3] Fix html lint
---
templates/events/event_list.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/templates/events/event_list.html b/templates/events/event_list.html
index 474344909..b3e951a44 100644
--- a/templates/events/event_list.html
+++ b/templates/events/event_list.html
@@ -57,7 +57,7 @@ {{ object.title|
- {% if events_ongoing %}
+ {% if events_ongoing %}
Ongoing Events