Skip to content

Commit

Permalink
Signaler une faute dans un article
Browse files Browse the repository at this point in the history
  • Loading branch information
DevHugo committed Mar 21, 2015
1 parent afa9467 commit e13f8dc
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 3 deletions.
33 changes: 33 additions & 0 deletions templates/article/includes/warn_typo.part.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{% load i18n %}

{% if user.is_authenticated and on_line %}

{% if user not in authors.all and authors_reachable|length >= 1 %}

<a href="#warn-typo-modal" class="open-modal btn btn-grey ico-after edit blue">
{% trans "Signaler une faute dans l'article" %}
</a>
<form class="modal modal-big" id="warn-typo-modal" action="{% url "zds.article.views.warn_typo" article_pk=article.pk %}" method="post" >
<p>
{% trans "J'ai trouvé une faute dans l'article" %}
:
</p>
{% csrf_token %}
<p>
<textarea name="explication" placeholder="{% blocktrans %}Expliquez ici la faute{% endblocktrans %}" required="required"></textarea>
</p>
<p>
{% trans "Pas assez de place ?" %}
<a href="{% url 'mp-new' %}?title={% trans "Je voudrais signaler une faute dans l'article" %} &quot;{{ article.title }}&quot;{% for username in authors.all %}&amp;username={{ username }}{% endfor %}" >
{% trans "Envoyez un MP" %}
{% if tutorial.authors.all|length > 1 %}
{% trans "aux auteurs" %}
{% else %}
{% trans "à l'auteur" %}
{% endif %}
</a>
</p>
<button type="submit">{% trans "Envoyer" %}</button>
</form>
{% endif %}
{% endif %}
4 changes: 3 additions & 1 deletion templates/article/view.html
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,10 @@ <h2 class="subtitle">
{% block content %}
{{ article.txt|safe }}


{% include "article/includes/pager.part.html" %}

{% include "article/includes/warn_typo.part.html" with article=article authors=authors%}

{% endblock %}


Expand Down
116 changes: 115 additions & 1 deletion zds/article/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
import datetime
from zds.gallery.factories import ImageFactory, UserGalleryFactory, GalleryFactory

from django.contrib import messages
from django.contrib.auth.models import Group

try:
import ujson as json_reader
except:
Expand Down Expand Up @@ -38,7 +41,6 @@
class ArticleTests(TestCase):

def setUp(self):

settings.EMAIL_BACKEND = \
'django.core.mail.backends.locmem.EmailBackend'
self.mas = ProfileFactory().user
Expand Down Expand Up @@ -102,6 +104,9 @@ def setUp(self):
self.assertEquals(len(mail.outbox), 1)
mail.outbox = []

bot = Group(name=settings.ZDS_APP["member"]["bot_group"])
bot.save()

def test_delete_image_on_change(self):
"""test que l'image est bien supprimée quand on la change"""

Expand Down Expand Up @@ -878,6 +883,115 @@ def test_new_article(self):
self.assertEqual(result.status_code, 200)
self.assertEqual(Article.objects.filter(title='Create a new article test').count(), 1)

def test_warn_typo(self):
"""
Add a non-regression test about warning the author(s) of a typo in an article
"""

typo_text = u'T\'as fait une faute, t\'es nul'

# login with author
self.assertEqual(
self.client.login(
username=self.user_author.username,
password='hostel77'),
True)

# check if author get error when warning typo on its own tutorial
result = self.client.post(
reverse('zds.article.views.warn_typo', args=[self.article.pk]),
{
'explication': u'ceci est un test',
},
follow=True)
self.assertEqual(result.status_code, 200)

msgs = result.context['messages']
last = None
for msg in msgs:
last = msg
self.assertEqual(last.level, messages.ERROR)

# login with normal user
self.client.logout()

self.assertEqual(
self.client.login(
username=self.user.username,
password='hostel77'),
True)

# check if user can warn typo in tutorial
result = self.client.post(
reverse('zds.article.views.warn_typo', args=[self.article.pk]),
{
'explication': typo_text,
},
follow=True)
self.assertEqual(result.status_code, 200)

msgs = result.context['messages']
last = None
for msg in msgs:
last = msg
self.assertEqual(last.level, messages.SUCCESS)

# check PM :
sent_pm = PrivateTopic.objects.filter(author=self.user.pk).last()
self.assertIn(self.user_author, sent_pm.participants.all()) # author is in participants
self.assertIn(typo_text, sent_pm.last_message.text) # typo is in message
self.assertIn(self.article.get_absolute_url_online(), sent_pm.last_message.text) # public url is in message

# Check if we send a wrong pk key
result = self.client.post(
reverse('zds.article.views.warn_typo', args=["1111"]),
{
'explication': typo_text,
},
follow=False)
self.assertEqual(result.status_code, 404)

# Check if we send no explanation
result = self.client.post(
reverse('zds.article.views.warn_typo', args=[self.article.pk]),
{
'explication': '',
},
follow=True)
self.assertEqual(result.status_code, 200)

msgs = result.context['messages']
last = None
for msg in msgs:
last = msg
self.assertEqual(last.level, messages.ERROR)

# Check if we send an explanation with only space
result = self.client.post(
reverse('zds.article.views.warn_typo', args=[self.article.pk]),
{
'explication': ' ',
},
follow=True)
self.assertEqual(result.status_code, 200)

msgs = result.context['messages']
last = None
for msg in msgs:
last = msg
self.assertEqual(last.level, messages.ERROR)

# Check if a guest can not warn the author
self.client.logout()

result = self.client.post(
reverse('zds.article.views.warn_typo', args=[self.article.pk]),
{
'explication': typo_text,
},
follow=False)
self.assertEqual(result.status_code, 302)

def tearDown(self):
if os.path.isdir(settings.ZDS_APP['article']['repo_path']):
shutil.rmtree(settings.ZDS_APP['article']['repo_path'])
Expand Down
2 changes: 2 additions & 0 deletions zds/article/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,6 @@
'zds.article.views.like_reaction'),
url(r'^message/dislike/$',
'zds.article.views.dislike_reaction'),
url(r'^message/typo/article/(?P<article_pk>\d+)/$',
'zds.article.views.warn_typo'),
)
80 changes: 79 additions & 1 deletion zds/article/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from datetime import datetime
from operator import attrgetter
from zds.member.models import Profile

try:
import ujson as json_reader
except ImportError:
Expand Down Expand Up @@ -130,6 +132,7 @@ def view(request, article_pk, article_slug):
'validation': validation,
'is_js': is_js,
'formJs': form_js,
'on_line': False
})


Expand Down Expand Up @@ -165,6 +168,12 @@ def view_online(request, article_pk, article_slug):
.order_by('position')\
.all()

# Check if the author is reachable
authors_reachable_request = Profile.objects.contactable_members().filter(user__in=article.authors.all())
authors_reachable = []
for author in authors_reachable_request:
authors_reachable.append(author.user)

# Retrieve pk of the last reaction. If there aren't reactions
# for the article, we initialize this last reaction at 0.
last_reaction_pk = 0
Expand Down Expand Up @@ -211,10 +220,79 @@ def view_online(request, article_pk, article_slug):
'pages': paginator_range(page_nbr, paginator.num_pages),
'nb': page_nbr,
'last_reaction_pk': last_reaction_pk,
'form': form
'form': form,
'on_line': True,
'authors_reachable': authors_reachable
})


@login_required
@require_POST
def warn_typo(request, article_pk):
"""Warn author(s) about a mistake in its (their) article by sending him/her (them) a private message."""

# Need profile
profile = get_object_or_404(Profile, user=request.user)

# Get article
try:
article_pk = int(article_pk)
except (KeyError, ValueError):
raise Http404

article = get_object_or_404(Article, pk=article_pk)

# Check if the article is published
if article.sha_public is None:
raise Http404

# Check if authors are reachable
authors_reachable = Profile.objects.contactable_members().filter(user__in=article.authors.all())
authors = []
for author in authors_reachable:
authors.append(author.user)

if len(authors) == 0:
if article.authors.count() > 1:
messages.error(request, _(u"Les auteurs de l'article sont malheureusement injoignables"))
else:
messages.error(request, _(u"L'auteur de l'article est malheureusement injoignable"))
else:
# Fetch explanation
if 'explication' not in request.POST or not request.POST['explication'].strip():
messages.error(request, _(u'Votre proposition de correction est vide'))
else:
explanation = request.POST['explication']
explanation = '\n'.join(['> ' + line for line in explanation.split('\n')])

# Is the user trying to send PM to himself ?
if request.user in article.authors.all():
messages.error(request, _(u'Impossible d\'envoyer la correction car vous êtes l\'auteur '
u'de cet article !'))
else:
# Create message :
msg = _(u'[{}]({}) souhaite vous proposer une correction pour votre article [{}]({}).\n\n').format(
request.user.username,
settings.ZDS_APP['site']['url'] + profile.get_absolute_url(),
article.title,
settings.ZDS_APP['site']['url'] + article.get_absolute_url_online()
)

msg += _(u'Voici son message :\n\n{}').format(explanation)

# Send it
send_mp(request.user,
article.authors.all(),
_(u"Proposition de correction"),
article.title,
msg,
leave=False)
messages.success(request, _(u'Votre correction a bien été proposée !'))

# return to page :
return redirect(article.get_absolute_url_online())


@can_write_and_read_now
@login_required
def new(request):
Expand Down
3 changes: 3 additions & 0 deletions zds/member/tests/tests_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ def setUp(self):
position_in_category=1)
self.staff = StaffProfileFactory().user

bot = Group(name=settings.ZDS_APP["member"]["bot_group"])
bot.save()

def test_list_members(self):
"""
To test the listing of the members with and without page parameter.
Expand Down

0 comments on commit e13f8dc

Please sign in to comment.