Notification emails #80
@ -39,6 +39,7 @@ urlpatterns = [
|
|||||||
path('', include('users.urls')),
|
path('', include('users.urls')),
|
||||||
path('', include('teams.urls')),
|
path('', include('teams.urls')),
|
||||||
path('', include('reviewers.urls')),
|
path('', include('reviewers.urls')),
|
||||||
|
path('', include('notifications.urls')),
|
||||||
path('api/swagger/', RedirectView.as_view(url='/api/v1/swagger/')),
|
path('api/swagger/', RedirectView.as_view(url='/api/v1/swagger/')),
|
||||||
path('api/v1/', SpectacularAPIView.as_view(), name='schema_v1'),
|
path('api/v1/', SpectacularAPIView.as_view(), name='schema_v1'),
|
||||||
path('api/v1/swagger/', SpectacularSwaggerView.as_view(url_name='schema_v1'), name='swagger'),
|
path('api/v1/swagger/', SpectacularSwaggerView.as_view(url_name='schema_v1'), name='swagger'),
|
||||||
|
22
notifications/templates/notifications/notification_list.html
Normal file
22
notifications/templates/notifications/notification_list.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{% extends "common/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block page_title %}{% blocktranslate %}Notifications{% endblocktranslate %}{% endblock page_title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% if notification_list %}
|
||||||
|
{% for notification in notification_list %}
|
||||||
|
<div class="row">
|
||||||
|
{{ notification.action }}
|
||||||
|
{% if notification.read_at %}
|
||||||
|
{% else %}
|
||||||
|
{% blocktranslate %}Mark as read{% endblocktranslate %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<p>
|
||||||
|
{% blocktranslate %}You have no notifications{% endblocktranslate %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock content %}
|
25
notifications/urls.py
Normal file
25
notifications/urls.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from django.urls import path, include
|
||||||
|
|
||||||
|
import notifications.views as views
|
||||||
|
|
||||||
|
app_name = 'notifications'
|
||||||
|
urlpatterns = [
|
||||||
|
path(
|
||||||
|
'notifications/',
|
||||||
|
include(
|
||||||
|
[
|
||||||
|
path('', views.NotificationsView.as_view(), name='notifications'),
|
||||||
|
path(
|
||||||
|
'mark-read-all/',
|
||||||
|
views.MarkReadAllView.as_view(),
|
||||||
|
name='notifications-mark-read-all',
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
'<int:pk>/mark-read/',
|
||||||
|
views.MarkReadView.as_view(),
|
||||||
|
name='notifications-mark-read',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
49
notifications/views.py
Normal file
49
notifications/views.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
"""Notifications pages."""
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.http import HttpResponseForbidden
|
||||||
|
from django.http.response import JsonResponse
|
||||||
|
from django.utils import timezone
|
||||||
|
from django.views.generic import ListView
|
||||||
|
from django.views.generic.detail import SingleObjectMixin
|
||||||
|
from django.views.generic.edit import FormView
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
|
from notifications.models import Notification
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationsView(LoginRequiredMixin, ListView):
|
||||||
|
model = Notification
|
||||||
|
ordering = None # FIXME
|
||||||
|
paginate_by = 10
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return Notification.objects.filter(recipient=self.request.user)
|
||||||
|
|
||||||
|
|
||||||
|
class MarkReadAllView(LoginRequiredMixin, FormView):
|
||||||
|
model = Notification
|
||||||
|
raise_exception = True
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
"""Mark all previously unread notifications as read."""
|
||||||
|
unread = self.model.objects.filter(recipient=request.user, read_at__isnull=True)
|
||||||
|
now = timezone.now()
|
||||||
|
for notification in unread:
|
||||||
|
notification.read_at = now
|
||||||
|
|
||||||
|
Notification.objects.bulk_update(unread, ['read_at'])
|
||||||
|
|
||||||
|
return JsonResponse({})
|
||||||
|
|
||||||
|
|
||||||
|
class MarkReadView(LoginRequiredMixin, SingleObjectMixin, View):
|
||||||
|
model = Notification
|
||||||
|
raise_exception = True
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
notification = self.get_object()
|
||||||
|
if notification.recipient != request.user:
|
||||||
|
return HttpResponseForbidden()
|
||||||
|
notification.read_at = timezone.now()
|
||||||
|
notification.save(update_fields=['read_at'])
|
||||||
|
return JsonResponse({})
|
Loading…
Reference in New Issue
Block a user