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

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 

11 

12from events.decorators import organiser_only 

13from events.models import Event 

14 

15from .forms import EventMessageForm 

16from .models import Category, Device, Message, ScheduledMessage 

17 

18 

19class MessageSentFilter(admin.SimpleListFilter): 

20 """Filter the push notifications on whether they are sent or not.""" 

21 

22 title = _("sent") 

23 parameter_name = "is_sent" 

24 

25 def lookups(self, request, model_admin): 

26 queryset = model_admin.get_queryset(request) 

27 values = [] 

28 

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"))) 

33 

34 return values 

35 

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 

42 

43 

44@admin.register(Device) 

45class DeviceAdmin(admin.ModelAdmin): 

46 """Manage the devices.""" 

47 

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 ) 

58 

59 def enable(self, request, queryset): 

60 queryset.update(active=True) 

61 

62 enable.short_description = _("Enable selected devices") 

63 

64 def disable(self, request, queryset): 

65 queryset.update(active=False) 

66 

67 disable.short_description = _("Disable selected devices") 

68 

69 def name(self, obj): 

70 return f"{obj.user.get_full_name()} ({obj.user.username})" 

71 

72 name.short_description = _("Name") 

73 name.admin_order_field = "user__first_name" 

74 

75 

76@admin.register(Message) 

77class MessageAdmin(ModelAdmin): 

78 """Manage normal messages.""" 

79 

80 list_display = ("title", "body", "category", "url", "sent", "success", "failure") 

81 filter_horizontal = ("users",) 

82 list_filter = (MessageSentFilter, "category") 

83 date_hierarchy = "sent" 

84 

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 ) 

104 

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) 

118 

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}) 

122 

123 

124@admin.register(ScheduledMessage) 

125class ScheduledMessageAdmin(ModelAdmin): 

126 """Manage scheduled messages.""" 

127 

128 list_display = ("title", "body", "time", "category", "sent", "success", "failure") 

129 date_hierarchy = "time" 

130 filter_horizontal = ("users",) 

131 list_filter = (MessageSentFilter, "category") 

132 

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 ) 

155 

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",) 

171 

172 

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.""" 

177 

178 form_class = EventMessageForm 

179 template_name = "admin/pushnotifications/event_message_form.html" 

180 admin = None 

181 event = None 

182 

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 

213 

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()}" 

218 

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() 

228 

229 messages.success(self.request, _("Message sent successfully.")) 

230 

231 if "_save" in self.request.POST: 

232 return redirect("admin:events_event_details", self.event.pk) 

233 return super().form_valid(form) 

234 

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) 

238 

239 

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 

245 

246 

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 

258 

259 

260# Unregister the original EventAdmin and register 

261# the new one with pushnotifications functionality. 

262admin.site.unregister(Event) 

263admin.site.register(Event, EventAdmin)