Coverage for website/pushnotifications/admin.py: 51.09%
115 statements
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
1from django.apps import apps
2from django.conf import settings
3from django.contrib import admin, messages
4from django.contrib.admin import ModelAdmin, helpers
5from django.contrib.admin.views.decorators import staff_member_required
6from django.shortcuts import get_object_or_404, redirect
7from django.urls import path
8from django.utils.decorators import method_decorator
9from django.utils.translation import gettext_lazy as _
10from django.views.generic import FormView
12from events.decorators import organiser_only
13from events.models import Event
15from .forms import EventMessageForm
16from .models import Category, Device, Message, ScheduledMessage
19class MessageSentFilter(admin.SimpleListFilter):
20 """Filter the push notifications on whether they are sent or not."""
22 title = _("sent")
23 parameter_name = "is_sent"
25 def lookups(self, request, model_admin):
26 queryset = model_admin.get_queryset(request)
27 values = []
29 if queryset.filter(sent__isnull=False).exists():
30 values.append((1, _("Yes")))
31 if queryset.filter(sent__isnull=True).exists():
32 values.append((0, _("No")))
34 return values
36 def queryset(self, request, queryset):
37 if self.value() == "1":
38 return queryset.filter(sent__isnull=False)
39 if self.value() == "0":
40 return queryset.filter(sent__isnull=True)
41 return queryset
44@admin.register(Device)
45class DeviceAdmin(admin.ModelAdmin):
46 """Manage the devices."""
48 list_display = ("name", "type", "active", "date_created")
49 list_filter = ("active", "type")
50 actions = ("enable", "disable")
51 ordering = ("user__first_name",)
52 search_fields = (
53 "registration_id",
54 "user__username",
55 "user__first_name",
56 "user__last_name",
57 )
59 def enable(self, request, queryset):
60 queryset.update(active=True)
62 enable.short_description = _("Enable selected devices")
64 def disable(self, request, queryset):
65 queryset.update(active=False)
67 disable.short_description = _("Disable selected devices")
69 def name(self, obj):
70 return f"{obj.user.get_full_name()} ({obj.user.username})"
72 name.short_description = _("Name")
73 name.admin_order_field = "user__first_name"
76@admin.register(Message)
77class MessageAdmin(ModelAdmin):
78 """Manage normal messages."""
80 list_display = ("title", "body", "category", "url", "sent", "success", "failure")
81 filter_horizontal = ("users",)
82 list_filter = (MessageSentFilter, "category")
83 date_hierarchy = "sent"
85 def get_fields(self, request, obj=None):
86 if obj and obj.sent:
87 return (
88 "users",
89 "title",
90 "body",
91 "url",
92 "category",
93 "sent",
94 "success",
95 "failure",
96 )
97 return (
98 "users",
99 "title",
100 "body",
101 "url",
102 "category",
103 )
105 def get_readonly_fields(self, request, obj=None):
106 if obj and obj.sent:
107 return (
108 "users",
109 "title",
110 "body",
111 "url",
112 "category",
113 "sent",
114 "success",
115 "failure",
116 )
117 return super().get_readonly_fields(request, obj)
119 def change_view(self, request, object_id, form_url="", **kwargs):
120 obj = Message.objects.filter(id=object_id)[0]
121 return super().change_view(request, object_id, form_url, {"message": obj})
124@admin.register(ScheduledMessage)
125class ScheduledMessageAdmin(ModelAdmin):
126 """Manage scheduled messages."""
128 list_display = ("title", "body", "time", "category", "sent", "success", "failure")
129 date_hierarchy = "time"
130 filter_horizontal = ("users",)
131 list_filter = (MessageSentFilter, "category")
133 def get_fields(self, request, obj=None):
134 if obj and obj.sent:
135 return (
136 "users",
137 "title",
138 "body",
139 "url",
140 "category",
141 "sent",
142 "success",
143 "failure",
144 "time",
145 "executed",
146 )
147 return (
148 "users",
149 "title",
150 "body",
151 "url",
152 "category",
153 "time",
154 )
156 def get_readonly_fields(self, request, obj=None):
157 if obj and obj.sent:
158 return (
159 "users",
160 "title",
161 "body",
162 "url",
163 "category",
164 "sent",
165 "success",
166 "failure",
167 "time",
168 "executed",
169 )
170 return ("executed",)
173@method_decorator(staff_member_required, name="dispatch")
174@method_decorator(organiser_only, name="dispatch")
175class EventMessageView(FormView):
176 """View used to create a pushnotification for all users registered to an event."""
178 form_class = EventMessageForm
179 template_name = "admin/pushnotifications/event_message_form.html"
180 admin = None
181 event = None
183 def get_context_data(self, **kwargs):
184 context = super().get_context_data(**kwargs)
185 context.update(
186 {
187 **self.admin.admin_site.each_context(self.request),
188 "add": False,
189 "change": True,
190 "has_view_permission": True,
191 "has_add_permission": False,
192 "has_change_permission": self.request.user.has_perms(
193 ["events.change_event"]
194 ),
195 "has_delete_permission": False,
196 "has_editable_inline_admin_formsets": False,
197 "app_label": "events",
198 "opts": self.event._meta,
199 "is_popup": False,
200 "save_as": False,
201 "save_on_top": False,
202 "original": self.event,
203 "obj_id": self.event.pk,
204 "title": _("Send push notification"),
205 "adminform": helpers.AdminForm(
206 context["form"],
207 ((None, {"fields": context["form"].fields.keys()}),),
208 {},
209 ),
210 }
211 )
212 return context
214 def form_valid(self, form):
215 values = form.cleaned_data
216 if not values["url"]:
217 values["url"] = f"{settings.BASE_URL}{self.event.get_absolute_url()}"
219 message = Message(
220 title=values["title"],
221 body=values["body"],
222 url=values["url"],
223 category=Category.objects.get(key=Category.EVENT),
224 )
225 message.save()
226 message.users.set([r.member for r in self.event.participants if r.member])
227 message.send()
229 messages.success(self.request, _("Message sent successfully."))
231 if "_save" in self.request.POST:
232 return redirect("admin:events_event_details", self.event.pk)
233 return super().form_valid(form)
235 def dispatch(self, request, *args, **kwargs):
236 self.event = get_object_or_404(Event, pk=self.kwargs["pk"])
237 return super().dispatch(request, *args, **kwargs)
240# Announcements also overrides the EventAdmin. We need to override the latest.
241if apps.is_installed("announcements"): 241 ↛ 244line 241 didn't jump to line 244 because the condition on line 241 was always true
242 from announcements.admin import EventAdmin as BaseEventAdmin
243else:
244 from events.admin import EventAdmin as BaseEventAdmin
247class EventAdmin(BaseEventAdmin):
248 def get_urls(self):
249 urls = super().get_urls()
250 custom_urls = [
251 path(
252 "<int:pk>/message/",
253 self.admin_site.admin_view(EventMessageView.as_view(admin=self)),
254 name="events_event_message",
255 ),
256 ]
257 return custom_urls + urls
260# Unregister the original EventAdmin and register
261# the new one with pushnotifications functionality.
262admin.site.unregister(Event)
263admin.site.register(Event, EventAdmin)