Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 482af69
Author: Christophe Gabard <[email protected]>
Date:   Tue Nov 22 20:58:21 2016 +0100

    Disable ping

commit 21f2d59
Author: Christophe Gabard <[email protected]>
Date:   Tue Nov 22 20:50:53 2016 +0100

    Update markdown version

commit 58e9802
Author: Christophe Gabard <[email protected]>
Date:   Sun Nov 20 17:06:04 2016 +0100

    fix test

commit 541b0c7
Author: Christophe Gabard <[email protected]>
Date:   Sun Nov 20 16:34:09 2016 +0100

    fix test

commit 7e0d0e2
Author: Christophe Gabard <[email protected]>
Date:   Sun Nov 20 16:08:44 2016 +0100

    fix test

commit 87d51a0
Author: Christophe Gabard <[email protected]>
Date:   Sun Nov 20 13:37:25 2016 +0100

    fix according to @vhr comments

commit 1cb9515
Author: Gérard Paligot <[email protected]>
Date:   Sun Nov 20 13:04:28 2016 +0100

    Corrige les retours de @vhf (#2)

    * feat: Ajoute une limite de pings sur les messages.

    * style: Change " en ' dans zds/notification/models.py.

    * feat: Ajoute des asserts dans answer_comment_event.

    * fix: Marque les notifs comme lues pour les user connectes.

    * refactor: Evite de gerer le mail dans answer_comment_event.

    * fix: Gere le save dans Comment#update_content.

commit fc52a8a
Author: Christophe Gabard <[email protected]>
Date:   Mon Nov 14 21:11:17 2016 +0100

    Mise a jour de zmarkdown

commit 3f01e1e
Author: GerardPaligot <[email protected]>
Date:   Sat Nov 12 19:05:41 2016 +0100

    feat: Genere des notifications pour les ping.

commit 3a1306f
Author: GerardPaligot <[email protected]>
Date:   Sat Nov 12 19:26:45 2016 +0100

    refactor: Ajoute l'objet markdown a render_markdown.

commit 436192d
Author: GerardPaligot <[email protected]>
Date:   Sat Nov 12 18:16:36 2016 +0100

    fix: Corrige la signature de render_markdown.

commit 5f03cd4
Author: Christophe Gabard <[email protected]>
Date:   Wed Nov 9 21:03:09 2016 +0100

    Update with new ping version

commit 0efbaea
Author: Christophe Gabard <[email protected]>
Date:   Mon Nov 7 10:54:05 2016 +0100

    fix flake8

commit e844104
Author: Christophe Gabard <[email protected]>
Date:   Mon Nov 7 00:10:38 2016 +0100

    fix for inline

commit d7d9649
Author: Christophe Gabard <[email protected]>
Date:   Sun Nov 6 23:53:09 2016 +0100

    restore decale_header

commit 0e70a68
Author: Christophe Gabard <[email protected]>
Date:   Sun Nov 6 23:49:45 2016 +0100

    add ping processing

commit 7f8fba3
Author: Christophe Gabard <[email protected]>
Date:   Sun Nov 6 23:43:23 2016 +0100

    v13 (ping)

commit 63d6228
Author: Christophe Gabard <[email protected]>
Date:   Sun Nov 6 23:42:26 2016 +0100

    Ping support

commit 41bac94
Author: Christophe Gabard <[email protected]>
Date:   Sun Nov 6 22:20:13 2016 +0100

    Nouvelle version markdown
  • Loading branch information
vhf committed Nov 29, 2016
1 parent 913be09 commit 9709f1b
Show file tree
Hide file tree
Showing 16 changed files with 150 additions and 41 deletions.
12 changes: 12 additions & 0 deletions assets/scss/layout/_content.scss
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,18 @@
padding: 0 5px;
}

// @ping
.ping {
color: inherit;
font-weight: bold;
text-decoration: none;

&:hover,
&:focus {
text-decoration: underline;
}
}

.mathjax-wrapper {
max-width: 100%;
overflow: auto;
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ factory-boy==2.7.0
pygeoip==0.3.2
pillow==3.2.0
gitpython==1.0.1
https://github.com/zestedesavoir/Python-ZMarkdown/archive/2.6.0-zds.11.zip
https://github.com/zestedesavoir/Python-ZMarkdown/archive/2.6.0-zds.16.zip
easy-thumbnails==2.3
CairoSVG==1.0.20
beautifulsoup4==4.4.1
Expand Down
3 changes: 3 additions & 0 deletions zds/forum/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,9 @@ def get_absolute_url(self):
page,
self.pk)

def get_notification_title(self):
return self.topic.title


class TopicRead(models.Model):
"""
Expand Down
7 changes: 6 additions & 1 deletion zds/forum/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from zds.forum.forms import TopicForm, PostForm, MoveTopicForm
from zds.forum.models import Category, Forum, Topic, Post, is_read, mark_read, TopicRead
from zds.member.decorator import can_write_and_read_now
from zds.notification import signals
from zds.notification.models import NewTopicSubscription, TopicAnswerSubscription
from zds.utils import slugify
from zds.utils.forums import create_topic, send_post, CreatePostView
Expand Down Expand Up @@ -156,9 +157,11 @@ def get_context_data(self, **kwargs):
context = super(TopicPostsListView, self).get_context_data(**kwargs)
form = PostForm(self.object, self.request.user)
form.helper.form_action = reverse('post-new') + '?sujet=' + str(self.object.pk)

posts = self.build_list_with_previous_item(context['object_list'])
context.update({
'topic': self.object,
'posts': self.build_list_with_previous_item(context['object_list']),
'posts': posts,
'last_post_pk': self.object.last_message.pk,
'form': form,
'form_move': MoveTopicForm(topic=self.object),
Expand All @@ -181,6 +184,8 @@ def get_context_data(self, **kwargs):
context['user_can_modify'] = [post.pk for post in context['posts'] if post.author == self.request.user]

if self.request.user.is_authenticated():
for post in posts:
signals.content_read.send(sender=post.__class__, instance=post, user=self.request.user)
if not is_read(self.object):
mark_read(self.object)
return context
Expand Down
2 changes: 1 addition & 1 deletion zds/mp/tests/tests_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ def test_success_answer(self):

self.assertEqual(200, response.status_code)
self.assertEqual(3, PrivatePost.objects.all().count())
self.assertContains(response, 'Luc !?')
self.assertContains(response, 'Luc&#x202F;!?')

def test_fail_answer_with_no_right(self):

Expand Down
22 changes: 22 additions & 0 deletions zds/notification/migrations/0014_pingsubscription.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
import zds.notification.models


class Migration(migrations.Migration):

dependencies = [
('notification', '0013_clean_notifications'),
]

operations = [
migrations.CreateModel(
name='PingSubscription',
fields=[
('answersubscription_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='notification.AnswerSubscription')),
],
bases=('notification.answersubscription', zds.notification.models.MultipleNotificationsMixin),
),
]
42 changes: 36 additions & 6 deletions zds/notification/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
from django.contrib.auth.models import User
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
from django.core.mail import EmailMultiAlternatives
from django.db import models
from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _

from zds import settings
from zds.forum.models import Topic
from zds.member.models import Profile
from zds.notification.managers import NotificationManager, SubscriptionManager, TopicFollowedManager, \
TopicAnswerSubscriptionManager
from zds.utils.misc import convert_camel_to_underscore
Expand Down Expand Up @@ -126,6 +128,7 @@ class SingleNotificationMixin(object):
"""
Mixin for the subscription that can only have one active notification at a time
"""

def send_notification(self, content=None, send_email=True, sender=None):
"""
Sends the notification about the given content
Expand Down Expand Up @@ -175,7 +178,6 @@ def mark_notification_read(self):


class MultipleNotificationsMixin(object):

def send_notification(self, content=None, send_email=True, sender=None):
"""
Sends the notification about the given content
Expand Down Expand Up @@ -232,8 +234,9 @@ class AnswerSubscription(Subscription):
Subscription to new answer, either in a topic, a article or a tutorial
NOT used directly, use one of its subtype
"""

def __unicode__(self):
return _(u'<Abonnement du membre "{0}" aux réponses au {1} #{2}>')\
return _(u'<Abonnement du membre "{0}" aux réponses au {1} #{2}>') \
.format(self.user.username, self.content_type, self.object_id)

def get_notification_url(self, answer):
Expand All @@ -251,7 +254,7 @@ class TopicAnswerSubscription(AnswerSubscription, SingleNotificationMixin):
objects = TopicAnswerSubscriptionManager()

def __unicode__(self):
return _(u'<Abonnement du membre "{0}" aux réponses au sujet #{1}>')\
return _(u'<Abonnement du membre "{0}" aux réponses au sujet #{1}>') \
.format(self.user.username, self.object_id)


Expand All @@ -263,7 +266,7 @@ class PrivateTopicAnswerSubscription(AnswerSubscription, SingleNotificationMixin
objects = SubscriptionManager()

def __unicode__(self):
return _(u'<Abonnement du membre "{0}" aux réponses à la conversation privée #{1}>')\
return _(u'<Abonnement du membre "{0}" aux réponses à la conversation privée #{1}>') \
.format(self.user.username, self.object_id)


Expand All @@ -275,7 +278,7 @@ class ContentReactionAnswerSubscription(AnswerSubscription, SingleNotificationMi
objects = SubscriptionManager()

def __unicode__(self):
return _(u'<Abonnement du membre "{0}" aux réponses du contenu #{1}>')\
return _(u'<Abonnement du membre "{0}" aux réponses du contenu #{1}>') \
.format(self.user.username, self.object_id)


Expand All @@ -287,7 +290,7 @@ class NewTopicSubscription(Subscription, MultipleNotificationsMixin):
objects = SubscriptionManager()

def __unicode__(self):
return _(u'<Abonnement du membre "{0}" aux nouveaux sujets du {1} #{2}>')\
return _(u'<Abonnement du membre "{0}" aux nouveaux sujets du {1} #{2}>') \
.format(self.user.username, self.content_type, self.object_id)

def get_notification_url(self, topic):
Expand Down Expand Up @@ -315,11 +318,37 @@ def get_notification_title(self, content):
return content.title


@python_2_unicode_compatible
class PingSubscription(AnswerSubscription, MultipleNotificationsMixin):
"""
Subscription to ping of a user
"""
module = _(u'Ping')
objects = SubscriptionManager()

def __str__(self):
return _(u'<Abonnement du membre "{0}" aux mentions>').format(self.profile, self.object_id)

def get_notification_title(self, answer):
assert hasattr(answer, 'author')
assert hasattr(answer, 'get_notification_title')

return _(u'{0} vous a mentionné sur {1}.').format(answer.author, answer.get_notification_title())


def ping_url(user=None):
try:
return Profile.objects.get(user__username=user).get_absolute_url()
except ObjectDoesNotExist:
pass


@python_2_unicode_compatible
class Notification(models.Model):
"""
A notification
"""

class Meta:
verbose_name = _(u'Notification')
verbose_name_plural = _(u'Notifications')
Expand Down Expand Up @@ -374,6 +403,7 @@ def __unicode__(self):
return u'<Sujet "{0}" suivi par {1}>'.format(self.topic.title,
self.user.username)


# used to fix Django 1.9 Warning
# https://github.com/zestedesavoir/zds-site/issues/3451
import receivers # noqa
28 changes: 27 additions & 1 deletion zds/notification/receivers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
from zds.forum.models import Topic, Post
from zds.mp.models import PrivateTopic, PrivatePost
from zds.notification.models import TopicAnswerSubscription, ContentReactionAnswerSubscription, \
PrivateTopicAnswerSubscription, Subscription, Notification, NewTopicSubscription, NewPublicationSubscription
PrivateTopicAnswerSubscription, Subscription, Notification, NewTopicSubscription, NewPublicationSubscription, \
PingSubscription
from zds.notification.signals import answer_unread, content_read, new_content, edit_content
from zds.tutorialv2.models.models_database import PublishableContent, ContentReaction

Expand Down Expand Up @@ -125,6 +126,17 @@ def mark_pm_reactions_read(sender, **kwargs):
subscription.mark_notification_read()


@receiver(content_read, sender=ContentReaction)
@receiver(content_read, sender=Post)
def mark_comment_read(sender, **kwargs):
comment = kwargs.get('instance')
user = kwargs.get('user')

subscription = PingSubscription.objects.get_existing(user, comment, is_active=True)
if subscription:
subscription.mark_notification_read(comment)


@receiver(edit_content, sender=Topic)
def edit_topic_event(sender, **kwargs):
"""
Expand Down Expand Up @@ -243,6 +255,20 @@ def content_published_event(sender, **kwargs):
subscription.send_notification(content=content, sender=user, send_email=by_email)


@receiver(new_content, sender=ContentReaction)
@receiver(new_content, sender=Post)
@disable_for_loaddata
def answer_comment_event(sender, **kwargs):
comment = kwargs.get('instance')
user = kwargs.get('user')

assert comment is not None
assert user is not None

subscription = PingSubscription.objects.get_or_create_active(user, comment)
subscription.send_notification(content=comment, sender=comment.author, send_email=False)


@receiver(new_content, sender=PrivatePost)
@disable_for_loaddata
def answer_private_topic_event(sender, **kwargs):
Expand Down
2 changes: 1 addition & 1 deletion zds/notification/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
answer_unread = Signal(providing_args=['instance', 'user'])

# is sent whenever a resource is created.
new_content = Signal(providing_args=['instance', 'by_email'])
new_content = Signal(providing_args=['instance', 'user', 'by_email'])

# is sent whenever a content is edited.
edit_content = Signal(providing_args=['instance', 'action'])
Expand Down
4 changes: 4 additions & 0 deletions zds/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,10 @@
'topic': {
'home_number': 6,
},
'comment': {
'max_pings': 15,
'enable_pings': False,
},
'featured_resource': {
'featured_per_page': 100,
'home_number': 5,
Expand Down
3 changes: 3 additions & 0 deletions zds/tutorialv2/models/models_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,9 @@ def get_absolute_url(self):
page = int(ceil(float(self.position) / settings.ZDS_APP["content"]["notes_per_page"]))
return '{0}?page={1}#p{2}'.format(self.related_content.get_absolute_url_online(), page, self.pk)

def get_notification_title(self):
return self.related_content.title


class ContentRead(models.Model):
"""
Expand Down
6 changes: 3 additions & 3 deletions zds/tutorialv2/tests/tests_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4240,7 +4240,7 @@ def test_public_access(self):

def test_add_note(self):

message_to_post = u'la ZEP-12, c\'est énorme ! (CMB)'
message_to_post = u'la ZEP-12'

self.assertEqual(
self.client.login(
Expand Down Expand Up @@ -4941,8 +4941,8 @@ def test_cant_edit_not_owned_note(self):
article = PublishedContentFactory(author_list=[self.user_author], type="ARTICLE")
new_user = ProfileFactory().user
new_reaction = ContentReaction(related_content=article, position=1)
new_reaction.update_content("I will find you. And I will Kill you.")
new_reaction.author = self.user_guest
new_reaction.update_content("I will find you. And I will Kill you.")

new_reaction.save()
self.assertEqual(
Expand Down Expand Up @@ -4970,8 +4970,8 @@ def test_quote_note(self):

# add note :
reaction = ContentReaction(related_content=tuto, position=1)
reaction.update_content(text)
reaction.author = self.user_guest
reaction.update_content(text)
reaction.save()

self.assertEqual(
Expand Down
3 changes: 2 additions & 1 deletion zds/tutorialv2/views/views_published.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,10 @@ def get_context_data(self, **kwargs):
context['subscriber_count'] = ContentReactionAnswerSubscription.objects.get_subscriptions(self.object).count()

if self.request.user.is_authenticated():
for reaction in context['reactions']:
signals.content_read.send(sender=reaction.__class__, instance=reaction, user=self.request.user)
signals.content_read.send(
sender=self.object.__class__, instance=self.object, user=self.request.user, target=PublishableContent)
# handle reactions:
if last_participation_is_old(self.object, self.request.user):
mark_read(self.object, self.request.user)

Expand Down
2 changes: 1 addition & 1 deletion zds/utils/forums.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,12 @@ def send_post(request, topic, author, text,):
post = Post()
post.topic = topic
post.author = author
post.update_content(text)
post.pubdate = datetime.now()
if topic.last_message is not None:
post.position = topic.last_message.position + 1
else:
post.position = 1
post.update_content(text)
post.ip_address = get_client_ip(request)
post.save()

Expand Down
12 changes: 10 additions & 2 deletions zds/utils/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
import string
import uuid

from django.conf import settings

from django.contrib.auth.models import User
Expand All @@ -14,11 +15,12 @@

from easy_thumbnails.fields import ThumbnailerImageField

from zds.notification import signals
from zds.mp.models import PrivateTopic
from zds.tutorialv2.models import TYPE_CHOICES
from zds.utils.mps import send_mp
from zds.utils import slugify
from zds.utils.templatetags.emarkdown import emarkdown
from zds.utils.templatetags.emarkdown import get_markdown_instance, render_markdown

from model_utils.managers import InheritanceManager

Expand Down Expand Up @@ -177,8 +179,14 @@ class Meta:
default='')

def update_content(self, text):
from zds.notification.models import ping_url

self.text = text
self.text_html = emarkdown(self.text)
md_instance = get_markdown_instance(ping_url=ping_url)
self.text_html = render_markdown(md_instance, self.text)
self.save()
for username in list(md_instance.metadata.get('ping', []))[:settings.ZDS_APP['comment']['max_pings']]:
signals.new_content.send(sender=self.__class__, instance=self, user=User.objects.get(username=username))

def hide_comment_by_user(self, user, text_hidden):
"""Hide a comment and save it
Expand Down
Loading

0 comments on commit 9709f1b

Please sign in to comment.