Repository: svthalia/concrexit

Issue:
Clarify calendar colors
### Describe the bug
It's not always clear what the calendar colors mean for events.

### How to reproduce
Steps to reproduce the behaviour:
1. Go to calendar
2. See half-transparent event
3. Confused about whether it's unpublished/closed for registrations/hidden

### Expected behaviour
Some kind of help text to remind you what the colors mean. Maybe a legend or text on the event block in the calendar.

### Screenshots
Current state (the first two events will open registrations soon):
![image](https://user-images.githubusercontent.com/1576660/132332512-eb98bfad-78d7-4f56-8c6c-0da7073dd4fa.png)

Example fix with text in the calendar block:

![image](https://user-images.githubusercontent.com/1576660/132349861-a2e99c20-a5c9-45f9-96d1-b41e9e60fc15.png)



Discussion:
Oh nice, I like that status text

Resolving patch:
diff --git a/website/events/api/calendarjs/serializers.py b/website/events/api/calendarjs/serializers.py
--- a/website/events/api/calendarjs/serializers.py
+++ b/website/events/api/calendarjs/serializers.py
@@ -1,3 +1,9 @@
+from datetime import timedelta
+
+from django.contrib.humanize.templatetags.humanize import naturaltime
+from django.template.defaultfilters import date
+from django.utils import timezone
+from django.utils.translation import gettext_lazy as _
 from rest_framework.reverse import reverse
 
 from events import services
@@ -26,6 +32,38 @@ def _class_names(self, instance):
             # I think this handles the case that registration is needed, but not yet possible
             return ["regular-event-registration-closed"]
 
+    def _registration_info(self, instance: Event):
+        if self.context["member"] and services.is_user_registered(
+            self.context["member"], instance
+        ):
+            queue_pos = services.user_registration_pending(
+                self.context["member"], instance
+            )
+            if isinstance(queue_pos, int):
+                return _("In waiting list at position {queue_pos}").format(
+                    queue_pos=queue_pos
+                )
+            else:
+                return _("You are registered for this event")
+        elif instance.optional_registration_allowed:
+            return _("You can optionally register for this event")
+        elif instance.reached_participants_limit:
+            return _("You can put yourself on the waiting list for this event")
+        elif instance.registration_allowed:
+            return _("You can register for this event")
+        elif instance.registration_end:
+            now = timezone.now()
+            if instance.registration_end < now:
+                return _("Registrations have been closed")
+            elif instance.registration_end <= now + timedelta(days=2):
+                return _("You can register {at_time}").format(
+                    at_time=naturaltime(instance.registration_end)
+                )
+            else:
+                return _("You can register on {date}").format(
+                    date=date(instance.registration_end)
+                )
+
 
 class UnpublishedEventsCalenderJSSerializer(CalenderJSSerializer):
     """See CalenderJSSerializer, customised classes."""
@@ -38,3 +76,6 @@ def _class_names(self, instance):
 
     def _url(self, instance):
         return reverse("admin:events_event_details", kwargs={"pk": instance.id})
+
+    def _registration_info(self, instance):
+        return "Unpublished event"
diff --git a/website/events/services.py b/website/events/services.py
--- a/website/events/services.py
+++ b/website/events/services.py
@@ -37,8 +37,13 @@ def user_registration_pending(member, event):
     if not member.is_authenticated:
         return None
 
-    reg = event.registrations.filter(member=member, date_cancelled=None)
-    return len(list(filter(lambda r: r.queue_position, reg))) > 0
+    try:
+        registration = event.registrations.get(member=member, date_cancelled=None)
+        if registration.queue_position:
+            return registration.queue_position
+        return False
+    except EventRegistration.DoesNotExist:
+        return False
 
 
 def is_user_present(member, event):
diff --git a/website/thaliawebsite/api/calendarjs/serializers.py b/website/thaliawebsite/api/calendarjs/serializers.py
--- a/website/thaliawebsite/api/calendarjs/serializers.py
+++ b/website/thaliawebsite/api/calendarjs/serializers.py
@@ -19,6 +19,7 @@ class Meta:
             "description",
             "classNames",
             "blank",
+            "registration_info",
         )
 
     start = serializers.SerializerMethodField("_start")
@@ -30,6 +31,7 @@ class Meta:
     description = serializers.SerializerMethodField("_description")
     classNames = serializers.SerializerMethodField("_class_names")
     blank = serializers.SerializerMethodField("_target_blank")
+    registration_info = serializers.SerializerMethodField("_registration_info")
 
     def _start(self, instance):
         return timezone.localtime(instance.start)
@@ -57,3 +59,6 @@ def _class_names(self, instance):
 
     def _target_blank(self, instance):
         return False
+
+    def _registration_info(self, instance):
+        return ""


Test patch: