Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ Persistent Messages has an extended API that will let you do some extra nice thi

This is the prototype of `add_message` in Persistent Messages.

def add_message(request, level, message, extra_tags='', fail_silently=False, subject='', user=None, email=False, from_user=None, expires=None, close_timeout=None):
def add_message(request, level, message, extra_tags='', fail_silently=False, subject='', user=None, email=False, from_user=None, parent_msg=None, expires=None, close_timeout=None):

#### Subject and email notifications ####

Expand Down
17 changes: 9 additions & 8 deletions persistent_messages/api.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
from persistent_messages import notify
from persistent_messages import constants

def add_message(request, level, message, extra_tags='', fail_silently=False, subject='', user=None, email=False, from_user=None, expires=None, close_timeout=None):
def add_message(request, level, message, extra_tags='', fail_silently=False, subject='', user=None, email=False, from_user=None, parent_msg=None, expires=None, close_timeout=None):
"""
"""
if email:
notify.email(level, message, extra_tags, subject, user, from_user)

return request._messages.add(level, message, extra_tags, subject, user, from_user, expires, close_timeout)
return request._messages.add(level, message, extra_tags, subject, user, from_user, parent_msg, expires, close_timeout)

def info(request, message, extra_tags='', fail_silently=False, subject='', user=None, email=False, from_user=None, expires=None, close_timeout=None):
def info(request, message, extra_tags='', fail_silently=False, subject='', user=None, email=False, from_user=None, parent_msg=None, expires=None, close_timeout=None):
"""
"""
level = constants.INFO
return add_message(request, level, message, extra_tags, fail_silently, subject, user, email, from_user, expires, close_timeout)
return add_message(request, level, message, extra_tags, fail_silently, subject, user, email, from_user, parent_msg, expires, close_timeout)

def warning(request, message, extra_tags='', fail_silently=False, subject='', user=None, email=False, from_user=None, expires=None, close_timeout=None):
def warning(request, message, extra_tags='', fail_silently=False, subject='', user=None, email=False, from_user=None, parent_msg=None, expires=None, close_timeout=None):
"""
"""
level = constants.WARNING
return add_message(request, level, message, extra_tags, fail_silently, subject, user, email, from_user, expires, close_timeout)
return add_message(request, level, message, extra_tags, fail_silently, subject, user, email, from_user, parent_msg, expires, close_timeout)

def debug(request, message, extra_tags='', fail_silently=False, subject='', user=None, email=False, from_user=None, expires=None, close_timeout=None):
def debug(request, message, extra_tags='', fail_silently=False, subject='', user=None, email=False, from_user=None, parent_msg=None, expires=None, close_timeout=None):
"""
"""
level = constants.DEBUG
return add_message(request, level, message, extra_tags, fail_silently, subject, user, email, from_user, expires, close_timeout)
return add_message(request, level, message, extra_tags, fail_silently, subject, user, email, from_user, parent_msg, expires, close_timeout)

def add_message_without_storage(to_user, from_user, level, message, extra_tags='', fail_silently=False, subject='', mail=False, expires=None, close_timeout=None):
"""
Use this method to add message without having to pass a `request.storage`
As we are not storing the message, there is no need to add `parent_msg`
"""
from models import Message
message = Message(user=to_user, level=level, message=message, extra_tags=extra_tags, subject=subject, from_user=from_user, expires=expires, close_timeout=close_timeout)
Expand Down
4 changes: 3 additions & 1 deletion persistent_messages/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
SUCCESS = 125
WARNING = 130
ERROR = 140
MESSAGE = 123

DEFAULT_TAGS = {
INFO: 'info',
SUCCESS: 'success',
WARNING: 'warning',
ERROR: 'error',
MESSAGE: 'message',
}

PERSISTENT_MESSAGE_LEVELS = (INFO, SUCCESS, WARNING, ERROR)
PERSISTENT_MESSAGE_LEVELS = (INFO, SUCCESS, WARNING, ERROR, MESSAGE)
38 changes: 38 additions & 0 deletions persistent_messages/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import datetime
from django import forms
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext_noop
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404

from persistent_messages.models import Message
from persistent_messages import constants

class ComposeForm(forms.Form):
"""
A simple default form for private messages.
"""
to_user = forms.CharField(label=_(u"Recipient"))
subject = forms.CharField(label=_(u"Subject"))
message = forms.CharField(label=_(u"Message"),
widget=forms.Textarea(attrs={'rows': '12', 'cols':'55'}))


def __init__(self, *args, **kwargs):
super(ComposeForm, self).__init__(*args, **kwargs)

def save(self, from_user, parent_msg=None):
subject = self.cleaned_data['subject']
message = self.cleaned_data['message']
to_user = get_object_or_404(User, username=self.cleaned_data['to_user'])
level = constants.MESSAGE

# Update the parent_msg `replied` field to true
if parent_msg is not None:
parent_msg.replied = True
parent_msg.save()


message = Message(user=to_user, level=level, message=message, subject=subject, from_user=from_user, parent_msg=parent_msg)
return message.save()
2 changes: 2 additions & 0 deletions persistent_messages/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
class Message(models.Model):
user = models.ForeignKey(User, blank=True, null=True)
from_user = models.ForeignKey(User, blank=True, null=True, related_name="from_user")
parent_msg = models.ForeignKey('self', null=True, blank=True, related_name="child_messages")
subject = models.CharField(max_length=255, blank=True, default='')
message = models.TextField()
LEVEL_CHOICES = (
Expand All @@ -32,6 +33,7 @@ class Message(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
read = models.BooleanField(default=False)
replied = models.BooleanField(default=False)
expires = models.DateTimeField(null=True, blank=True)
close_timeout = models.IntegerField(null=True, blank=True)

Expand Down
24 changes: 18 additions & 6 deletions persistent_messages/storage.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import datetime

from django.contrib import messages
from django.contrib import messages
from django.contrib.messages.storage.base import BaseStorage
from django.contrib.auth.models import AnonymousUser
from django.contrib.messages.storage.fallback import FallbackStorage
from django.db.models import Q
from django.conf import settings

# Try to use 1.4's tz utils. Else just use naive now.
try:
from django.utils.timezone import now
except ImportError:
from datetime import datetime
now = datetime.now

from persistent_messages.models import Message
from persistent_messages.constants import PERSISTENT_MESSAGE_LEVELS

Expand Down Expand Up @@ -41,7 +46,7 @@ def _message_queryset(self, exclude_read=None):
"""
Gets the messages from the model. If `exclude_unread` is set to True, read messages are excluded
"""
qs = Message.objects.filter(user=get_user(self.request)).filter(Q(expires=None) | Q(expires__gt=datetime.datetime.now()))
qs = Message.objects.filter(user=get_user(self.request)).filter(Q(expires=None) | Q(expires__gt=now()))

# If the function didn't get an exclude_read argument, we look for it in settings
if exclude_read is None:
Expand Down Expand Up @@ -179,7 +184,7 @@ def update(self, response):

return super(PersistentMessageStorage, self).update(response)

def add(self, level, message, extra_tags='', subject='', user=None, from_user=None, expires=None, close_timeout=None):
def add(self, level, message, extra_tags='', subject='', user=None, from_user=None, parent_msg=None, expires=None, close_timeout=None):
"""
Adds or queues a message to the storage

Expand All @@ -189,6 +194,7 @@ def add(self, level, message, extra_tags='', subject='', user=None, from_user=No
:param subject: Subject of the message
:param user: `auth.User` that receives the message
:param from_user: `auth.User` that sends the message
:param parent_msg: `persistent_messages.Message` that this message is in reply to
:param expires: Timestamp that indicates when the message expires
:param close_timeout: Integer

Expand All @@ -210,7 +216,13 @@ def add(self, level, message, extra_tags='', subject='', user=None, from_user=No

# Add the message
message = Message(user=to_user, level=level, message=message, extra_tags=extra_tags, subject=subject,
from_user=from_user, expires=expires, close_timeout=close_timeout)
from_user=from_user, parent_msg=parent_msg, expires=expires, close_timeout=close_timeout)

# Update the parent_msg `replied` field to true
if parent_msg is not None:
parent_msg.replied = True
parent_msg.save()


# Messages need a primary key when being displayed so that they can be closed/marked as read by the user.
# Hence, save it now instead of adding it to queue:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{% load i18n %}
<div id="message_{{ message.pk }}" {% if message.tags %} class="{{ message.tags }}"{% endif %}>
{% with 32 as max_words %}
{% if message.subject %}<strong>{{ message.subject }}</strong>{% endif %}
{% if message.message|wordcount > max_words %}
(<a class="message_more" id="{{ message.pk }}" href="{% url message_detail message.id %}">show more</a>)
{% endif %}
<br />
{% if jquery %}
<div id="message_text_{{ message.pk }}">
{{ message.message|linebreaksbr|truncatewords:max_words }}
</div>
{% else %}
{{ message|linebreaksbr }}
{% endif %}
{% if message.is_persistent or jquery %}
<a class="message_close icon" href="{% if message.is_persistent %}{% url message_mark_read message.pk %}{% else %}#{% endif %}"><span>{% trans "close" %}</span></a>
{% endif %}
{% endwith %}
</div>
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{% load i18n %}
{% if messages %}
<ul class="messages">
<div class="messages">
{% for message in messages %}
{% if not hide_persistent or not message.is_persistent %}
{% include "persistent_messages/message/includes/message_li.html" %}
{% endif %}
{% if message.is_persistent %}
{% include "persistent_messages/message/includes/message_div.html" %}
{% endif %}
{% endfor %}
</ul>
{% if close_all and messages|length > 1 %}
<a class="message-close-all icon" href="{% url message_mark_all_read %}"><span>{% trans "close all" %}</span></a>
{% endif %}
</div>
{% if close_all and messages|length > 1 %}
<a class="message_close_all icon" href="{% url message_mark_all_read %}"><span>{% trans "close all" %}</span></a>
{% endif %}
{% endif %}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
<script type="text/javascript">
//<![CDATA[
$(document).ready(function() {
var messageSelector = '.messages li';
var closeSelector = '.message-close';
var closeAllSelector = '.message-close-all';
var messageSelector = '.messages div';
var messageText = '.message_text';
var closeSelector = '.message_close';
var closeAllSelector = '.message_close_all';
var moreSelector = '.message_more';
var lessSelector = '.message_less';

$.fn.messageClose = function() {
$(this).fadeTo('fast', 0, function() {
$(this).hide('fast', function() {
Expand Down Expand Up @@ -44,10 +48,38 @@
$(this).messageClose();
$(messageSelector).messageClose();
});
$(moreSelector).click(function(event) {
event.preventDefault();
if ($(this).attr('href') != '#') {

if ($(this).attr('class') == 'message_more') {

url = $(this).attr('href');
var descriptor = "#message_text_" + $(this).attr('id');
$.get(url, function(data) {
var txt = $(descriptor).html();
$(descriptor).data({ content: txt }); //$(descriptor).html
$(descriptor).html(data);
});
$(this).text("show less");
$(this).removeClass('message_more').addClass('message_less');

}

else if ($(this).attr('class') == 'message_less') {

var descriptor = "#message_text_" + $(this).attr('id');
var txt = $(descriptor).data();
$(descriptor).html(txt.content);
$(this).text("show more");
$(this).removeClass('message_less').addClass('message_more');

}
}
});
{% for message in messages %}
{% if message.close_timeout %}
$('#message-{{ message.pk }}').messageCloseTimeout({{ message.close_timeout }});
$('#message_{{ message.pk }}').messageCloseTimeout({{ message.close_timeout }});
{% endif %}
{% endfor %}
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% load i18n %}
{% if messages %}
<div class="messages_pop">
{% for message in messages %}
{% comment %}AND has precedence over OR, i.e. (not read and not hide) or not persistent {% endcomment %}
{% if not message.read and not hide_persistent or not message.is_persistent %}
{% include "persistent_messages/message/includes/pop_div.html" %}
{% endif %}
{% endfor %}
{% if close_all and messages|length > 1 %}
<a class="message_pop_close_all icon" href="{% url message_mark_all_read %}"><span>{% trans "close all" %}</span></a>
{% endif %}
</div>
{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{% if messages %}
<script type="text/javascript">
//<![CDATA[
$(document).ready(function() {
var messageSelector = '.messages_pop div';
var closeSelector = '.message_pop_close';
var closeAllSelector = '.message_pop_close_all';
$.fn.messageClose = function() {
$(this).fadeTo('fast', 0, function() {
$(this).hide('fast', function() {
$(this).remove();
});
});
};
$.fn.messageCloseTimeout = function(interval) {
var _this = $(this);
setTimeout(function() {
_this.messageClose();
var close = _this.find(closeSelector);
if (close.attr('href') != '#') {
$.ajax({
url: $(this).attr('href')
})
}
}, interval)
};
$(closeSelector).click(function(event) {
event.preventDefault();
if ($(this).attr('href') != '#') {
$.ajax({
url: $(this).attr('href')
})
}
if ($(messageSelector).length <= 2) {
$(closeAllSelector).messageClose();
}
$(this).closest(messageSelector).messageClose();
});
$(closeAllSelector).click(function(event) {
event.preventDefault();
$.ajax({
url: $(this).attr('href')
})
$(this).messageClose();
$(messageSelector).messageClose();
});

{% for message in messages %}
{% if message.close_timeout %}
$('#message_pop_{{ message.pk }}').messageCloseTimeout({{ message.close_timeout }});
{% endif %}
{% endfor %}
});

//]]>
</script>
{% with 1 as jquery %}
{% include "persistent_messages/message/includes/pop.html" %}
{% endwith %}
{% endif %}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% load i18n %}
<li id="message-{{ message.pk }}" {% if message.tags %} class="{{ message.tags }}"{% endif %}>
<div id="message-{{ message.pk }}" {% if message.tags %} class="{{ message.tags }}"{% endif %}>
{% if message.subject %}<strong>{{ message.subject }}</strong><br />{% endif %}
{% if message.is_persistent or jquery %}
{% with 32 as max_words %}
Expand All @@ -9,6 +9,6 @@
{{ message }}
{% endif %}
{% if message.is_persistent or jquery %}
<a class="message-close icon" href="{% if message.is_persistent %}{% url message_mark_read message.pk %}{% else %}#{% endif %}"><span>{% trans "close" %}</span></a>
<a class="message_pop_close icon" href="{% if message.is_persistent %}{% url message_mark_read message.pk %}{% else %}#{% endif %}"><span>{% trans "close" %}</span></a>
{% endif %}
</li>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{% extends "site_base.html" %}
{% load i18n %}
{% block body %}
<h1>{% trans "Compose Message"%}</h1>
<form action="" method="post">{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="{% trans "Send" %} &raquo;"/>
</form>

{% endblock %}
Loading