Notifications: unsubscribe from extension approval activity (#177) #207
@ -79,7 +79,27 @@
|
|||||||
{% block extension_activity %}
|
{% block extension_activity %}
|
||||||
<section id="activity" class="mt-4">
|
<section id="activity" class="mt-4">
|
||||||
<hr class="my-4">
|
<hr class="my-4">
|
||||||
<h2>Activity</h2>
|
<div class="align-items-center d-flex w-100">
|
||||||
|
<h2>Activity</h2>
|
||||||
|
{% if request.user.is_authenticated and not is_maintainer %}
|
||||||
|
<form class="d-flex flex-column flex-grow-1" method="post" action="{% url 'reviewers:approval-follow' extension.slug %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% if user_is_following %}
|
||||||
|
<button class="btn ms-auto" type="submit">
|
||||||
|
<i class="i-bell-off"></i> Unsubscribe
|
||||||
|
<input type="hidden" name="follow" value="" />
|
||||||
|
</button>
|
||||||
|
<small class="text-muted text-end">{% trans "You're receiving notifications because you're subscribed to this thread." %}</small>
|
||||||
|
{% else %}
|
||||||
|
<button class="btn ms-auto" type="submit">
|
||||||
|
<i class="i-bell"></i> Subscribe
|
||||||
|
<input type="hidden" name="follow" value="True" />
|
||||||
|
</button>
|
||||||
|
<small class="text-muted text-end">{% trans "You're not receiving notifications from this thread." %}</small>
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if review_activity %}
|
{% if review_activity %}
|
||||||
<ul class="activity-list">
|
<ul class="activity-list">
|
||||||
|
50
reviewers/tests/test_notifications.py
Normal file
50
reviewers/tests/test_notifications.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from common.tests.factories.extensions import create_version
|
||||||
|
from common.tests.factories.users import UserFactory
|
||||||
|
from notifications.models import Notification
|
||||||
|
from reviewers.models import ApprovalActivity
|
||||||
|
|
||||||
|
|
||||||
|
class TestNotifications(TestCase):
|
||||||
|
def test_unsubscribe(self):
|
||||||
|
version = create_version()
|
||||||
|
extension = version.extension
|
||||||
|
some_user = UserFactory()
|
||||||
|
some_user2 = UserFactory()
|
||||||
|
|
||||||
|
self.client.force_login(some_user)
|
||||||
|
url = reverse('reviewers:approval-comment', args=[extension.slug])
|
||||||
|
self.client.post(url, {'type': ApprovalActivity.ActivityType.COMMENT, 'message': 'lala'})
|
||||||
|
|
||||||
|
notification_nr = Notification.objects.filter(recipient=some_user).count()
|
||||||
|
self.client.force_login(some_user2)
|
||||||
|
url = reverse('reviewers:approval-comment', args=[extension.slug])
|
||||||
|
self.client.post(url, {'type': ApprovalActivity.ActivityType.COMMENT, 'message': 'lala2'})
|
||||||
|
new_notification_nr = Notification.objects.filter(recipient=some_user).count()
|
||||||
|
self.assertEqual(new_notification_nr, notification_nr + 1)
|
||||||
|
|
||||||
|
# unsubscribe and see what happens
|
||||||
|
self.client.force_login(some_user)
|
||||||
|
url = reverse('reviewers:approval-follow', args=[extension.slug])
|
||||||
|
self.client.post(url, {'follow': ''})
|
||||||
|
|
||||||
|
self.client.force_login(some_user2)
|
||||||
|
url = reverse('reviewers:approval-comment', args=[extension.slug])
|
||||||
|
self.client.post(url, {'type': ApprovalActivity.ActivityType.COMMENT, 'message': 'lala3'})
|
||||||
|
|
||||||
|
new_notification_nr2 = Notification.objects.filter(recipient=some_user).count()
|
||||||
|
self.assertEqual(new_notification_nr2, new_notification_nr)
|
||||||
|
|
||||||
|
# subscribe back
|
||||||
|
self.client.force_login(some_user)
|
||||||
|
url = reverse('reviewers:approval-follow', args=[extension.slug])
|
||||||
|
self.client.post(url, {'follow': '1'})
|
||||||
|
|
||||||
|
self.client.force_login(some_user2)
|
||||||
|
url = reverse('reviewers:approval-comment', args=[extension.slug])
|
||||||
|
self.client.post(url, {'type': ApprovalActivity.ActivityType.COMMENT, 'message': 'lala4'})
|
||||||
|
|
||||||
|
new_notification_nr3 = Notification.objects.filter(recipient=some_user).count()
|
||||||
|
self.assertEqual(new_notification_nr3, new_notification_nr2 + 1)
|
@ -15,4 +15,9 @@ urlpatterns = [
|
|||||||
views.ExtensionsApprovalFormView.as_view(),
|
views.ExtensionsApprovalFormView.as_view(),
|
||||||
name='approval-comment',
|
name='approval-comment',
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
'approval-queue-follow/<slug:slug>/',
|
||||||
|
views.ExtensionsApprovalFollowView.as_view(),
|
||||||
|
name='approval-follow',
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from actstream.actions import follow, is_following, unfollow
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.views.generic.list import ListView
|
from django.views.generic.list import ListView
|
||||||
from django.views.generic import DetailView, FormView
|
from django.views.generic import DetailView, FormView
|
||||||
from django.shortcuts import reverse
|
from django.shortcuts import redirect, reverse
|
||||||
import django.forms
|
import django.forms
|
||||||
|
|
||||||
|
from constants.activity import Flag
|
||||||
from extensions.models import Extension
|
from extensions.models import Extension
|
||||||
from reviewers.forms import CommentForm
|
from reviewers.forms import CommentForm
|
||||||
from reviewers.models import ApprovalActivity
|
from reviewers.models import ApprovalActivity
|
||||||
@ -134,6 +136,7 @@ class ExtensionsApprovalDetailView(DetailView):
|
|||||||
form.fields['type'].widget.choices = choices
|
form.fields['type'].widget.choices = choices
|
||||||
if len(choices) == 1:
|
if len(choices) == 1:
|
||||||
form.fields['type'].widget = django.forms.HiddenInput()
|
form.fields['type'].widget = django.forms.HiddenInput()
|
||||||
|
ctx['user_is_following'] = is_following(user, self.object, flag=Flag.REVIEWER)
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
@ -158,3 +161,16 @@ class ExtensionsApprovalFormView(LoginRequiredMixin, FormView):
|
|||||||
form.save()
|
form.save()
|
||||||
self.approve_if_allowed(form)
|
self.approve_if_allowed(form)
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
class ExtensionsApprovalFollowView(LoginRequiredMixin, DetailView):
|
||||||
|
model = Extension
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
extension = self.get_object()
|
||||||
|
user = request.user
|
||||||
|
if request.POST.get('follow'):
|
||||||
|
follow(user, extension, send_action=False, flag=Flag.REVIEWER)
|
||||||
|
else:
|
||||||
|
unfollow(user, extension, send_action=False, flag=Flag.REVIEWER)
|
||||||
|
return redirect(extension.get_review_url() + '#activity')
|
||||||
|
Loading…
Reference in New Issue
Block a user