]> git.parisson.com Git - django-postman.git/commitdiff
Adjustments for integration with version 1.2.x of django-ajax-selects, in addition...
authorPatrick Samson <pk.samson@gmail.com>
Mon, 13 Aug 2012 19:53:12 +0000 (21:53 +0200)
committerPatrick Samson <pk.samson@gmail.com>
Mon, 13 Aug 2012 19:53:12 +0000 (21:53 +0200)
postman/fields.py
postman/templates/autocomplete_postman_multiple.html [deleted file]
postman/templates/autocomplete_postman_multiple_as1-1.html [new file with mode: 0644]
postman/templates/autocomplete_postman_single.html [deleted file]
postman/templates/autocomplete_postman_single_as1-1.html [new file with mode: 0644]
postman/templates/postman/base_write.html
postman/test_urls.py
postman/tests.py
postman/views.py

index c2c70a8fc70922f41f2255fbb0b3068a48103f31..9fd250c6d1dbb0a759eb9ca59bb52c029cef5fe0 100644 (file)
@@ -97,10 +97,13 @@ field_name = d.get('field', 'AutoCompleteField')
 arg_name = d.get('arg_name', 'channel')
 arg_default = d.get('arg_default') # the minimum to declare to enable the feature
 
+autocompleter_app = {}
 if app_name in settings.INSTALLED_APPS and arg_default:
+    autocompleter_app['is_active'] = True
+    autocompleter_app['name'] = app_name
+    autocompleter_app['version'] = getattr(__import__(app_name, globals(), locals(), ['__version__']), '__version__', None)
     # does something like "from ajax_select.fields import AutoCompleteField"
     auto_complete_field = getattr(__import__(app_name + '.fields', globals(), locals(), [field_name]), field_name)
-    is_autocompleted = True
 
     class CommaSeparatedUserField(BasicCommaSeparatedUserField, auto_complete_field):
         def __init__(self, *args, **kwargs):
@@ -116,5 +119,5 @@ if app_name in settings.INSTALLED_APPS and arg_default:
                 setattr(self.widget, arg_name, value)
 
 else:
+    autocompleter_app['is_active'] = False
     CommaSeparatedUserField = BasicCommaSeparatedUserField
-    is_autocompleted = False
diff --git a/postman/templates/autocomplete_postman_multiple.html b/postman/templates/autocomplete_postman_multiple.html
deleted file mode 100644 (file)
index 798c7c4..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{% extends "autocomplete.html" %}
-{% block script %}
-       $('#{{ html_id }}').autocomplete('{{ lookup_url }}', {
-               width: 320,
-               formatItem: function(row) { return row[1]; },
-               formatResult: function(row) { return row[2]; },
-               multiple: true,
-               dataType: "text"
-       })
-       $('#{{ html_id }}').result(function(event, data, formatted) {
-               $('#{{ html_id }}').trigger("added");
-       })
-{% endblock %}
\ No newline at end of file
diff --git a/postman/templates/autocomplete_postman_multiple_as1-1.html b/postman/templates/autocomplete_postman_multiple_as1-1.html
new file mode 100644 (file)
index 0000000..d9d2930
--- /dev/null
@@ -0,0 +1,26 @@
+{% extends "autocomplete.html" %}{% comment %}
+This is a custom template for django-ajax-selects version 1.1.4/5 (not for 1.2+).
+Channel:               postman_multiple_as1-1
+Form Field:            AutoCompleteField
+Usage:                 Entering of multiple values.
+
+There is no such template provided in the django-ajax-selects application.
+Differences with the default template:
+- it uses the "multiple: true" option of the jquery-plugin-autocomplete
+- it fixes the issue http://code.google.com/p/django-ajax-selects/issues/detail?id=57
+Note: this template is also used in the test suite.
+
+{% endcomment %}
+{% block script %}
+       $('#{{ html_id }}').autocomplete('{{ lookup_url }}', {
+               width: 320,
+               formatItem: function(row) { return row[1]; },
+               formatResult: function(row) { return row[2]; },
+               multiple: true,
+               dataType: "text"
+       })
+       $('#{{ html_id }}').result(function(event, data, formatted) {
+               $('#{{ html_id }}').trigger("added");
+       })
+{% block extra_script %}{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/postman/templates/autocomplete_postman_single.html b/postman/templates/autocomplete_postman_single.html
deleted file mode 100644 (file)
index 979e068..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{% extends "autocomplete.html" %}
-{% block script %}
-       $('#{{ html_id }}').autocomplete('{{ lookup_url }}', {
-               width: 320,
-               formatItem: function(row) { return row[1]; },
-               formatResult: function(row) { return row[2]; },
-               dataType: "text"
-       })
-       $('#{{ html_id }}').result(function(event, data, formatted) {
-               $('#{{ html_id }}').trigger("added");
-       })
-{% endblock %}
\ No newline at end of file
diff --git a/postman/templates/autocomplete_postman_single_as1-1.html b/postman/templates/autocomplete_postman_single_as1-1.html
new file mode 100644 (file)
index 0000000..2b5dc0c
--- /dev/null
@@ -0,0 +1,23 @@
+{% extends "autocomplete.html" %}{% comment %}
+This is a custom template for django-ajax-selects version 1.1.4/5 (not for 1.2+).
+Channel:               postman_single_as1-1
+Form Field:            AutoCompleteField
+Usage:                 Basic entering of a single value.
+
+It is the same as the default template, except that it fixes the issue:
+http://code.google.com/p/django-ajax-selects/issues/detail?id=57
+Note: this template is also used in the test suite.
+
+{% endcomment %}
+{% block script %}
+       $('#{{ html_id }}').autocomplete('{{ lookup_url }}', {
+               width: 320,
+               formatItem: function(row) { return row[1]; },
+               formatResult: function(row) { return row[2]; },
+               dataType: "text"
+       })
+       $('#{{ html_id }}').result(function(event, data, formatted) {
+               $('#{{ html_id }}').trigger("added");
+       })
+{% block extra_script %}{% endblock %}
+{% endblock %}
\ No newline at end of file
index e188e4821d2c13d5be8e638e5e47fa0907737ba4..4a30c38de4c566da6d2625c0a2e7d92fe7d0fede 100644 (file)
@@ -1,13 +1,25 @@
 {% extends "postman/base.html" %}
 {% load i18n %}
 {% block extrahead %}{{ block.super }}
-{% if is_autocompleted %}
-{# using the available admin jQuery is enough #}
-{# dj v1.4 #}{% load static %}<script type="text/javascript" src="{% static 'admin/js/jquery.min.js' %}"></script>
-{# dj v1.3 #}{# <script type="text/javascript" src="{% load adminmedia %}{% admin_media_prefix %}js/jquery.min.js"></script> #}
-{# <script type="text/javascript" src="{{ MEDIA_URL }}js/jquery.min.js"></script> #}
-<script type="text/javascript" src="{{ MEDIA_URL }}js/jquery.autocomplete.min.js"></script>
-<link href="{{ MEDIA_URL }}css/jquery.autocomplete.css" type="text/css" media="all" rel="stylesheet" />
+{% if autocompleter_app.is_active %}
+{# dj v1.4 #}{# {% load static %} #}
+<script type="text/javascript"src="
+{# using the available admin jQuery is enough: #}
+ {# dj v1.4 #}{# {% static 'admin/js/jquery.min.js' %} #}
+ {# dj v1.2/3 #}{% load adminmedia %}{% admin_media_prefix %}js/jquery.min.js
+{# unless you really want your own: #}
+ {# dj v1.2 #}{# {{ MEDIA_URL }}js/jquery.min.js #}
+"></script>
+{% if autocompleter_app.name == "ajax_select" %}{% if autocompleter_app.version == "1.1.4" or autocompleter_app.version == "1.1.5" %}<script type="text/javascript" src="
+{# dj v1.4 #}{# {% static 'js/jquery.autocomplete.min.js' %} #}
+{# dj v1.3 #}{# {{ STATIC_URL }}js/jquery.autocomplete.min.js #}
+{# dj v1.2 #}{{ MEDIA_URL }}js/jquery.autocomplete.min.js
+"></script>
+<link type="text/css" media="all" rel="stylesheet" href="
+{# dj v1.4 #}{# {% static 'css/jquery.autocomplete.css' %} #}
+{# dj v1.3 #}{# {{ STATIC_URL }}css/jquery.autocomplete.css #}
+{# dj v1.2 #}{{ MEDIA_URL }}css/jquery.autocomplete.css
+" />{# else: for version 1.2.x use AJAX_SELECT_BOOTSTRAP + AJAX_SELECT_INLINES or arrange to include jqueryUI/js/css #}{% endif %}{% endif %}
 {% endif %}
 {% endblock %}
 {% block content %}
index 611014c3fe4b484407a629aeae032502db3c75a9..f47bb02342ec569a4f17e9df8e0f9c85316de20a 100644 (file)
@@ -6,7 +6,7 @@ from django.conf import settings
 try:
     from django.conf.urls import patterns, include, url # django 1.4
 except ImportError:
-    from django.conf.urls.defaults import patterns, include, url # django 1.3
+    from django.conf.urls.defaults import * # "patterns, include, url" is enough for django 1.3, "*" for django 1.2
 from django.forms import ValidationError
 from django.views.generic.simple import redirect_to
 
@@ -101,8 +101,8 @@ postman_patterns = patterns('postman.views',
     url(r'^reply_formatters/(?P<message_id>[\d]+)/$', 'reply', {'formatters': (format_subject,format_body)}, name='postman_reply_formatters'),
     url(r'^view_formatters/(?P<message_id>[\d]+)/$', 'view', {'formatters': (format_subject,format_body)}, name='postman_view_formatters'),
     # auto-complete
-    url(r'^write_ac/(?:(?P<recipients>[\w.@+-:]+)/)?$', 'write', {'autocomplete_channels': ('postman_multiple', None)}, name='postman_write_auto_complete'),
-    url(r'^reply_ac/(?P<message_id>[\d]+)/$', 'reply', {'autocomplete_channel': 'postman_multiple'}, name='postman_reply_auto_complete'),
+    url(r'^write_ac/(?:(?P<recipients>[\w.@+-:]+)/)?$', 'write', {'autocomplete_channels': ('postman_multiple_as1-1', None)}, name='postman_write_auto_complete'),
+    url(r'^reply_ac/(?P<message_id>[\d]+)/$', 'reply', {'autocomplete_channel': 'postman_multiple_as1-1'}, name='postman_reply_auto_complete'),
     # 'template_name'
     url(r'^inbox_template/(?:(?P<option>'+OPTIONS+')/)?$', 'inbox', {'template_name': 'postman/fake.html'}, name='postman_inbox_template'),
     url(r'^sent_template/(?:(?P<option>'+OPTIONS+')/)?$', 'sent', {'template_name': 'postman/fake.html'}, name='postman_sent_template'),
index ed96f4c2f69dbdeb938cf2f6d3bf4d93b98ef2fd..03e9bb4dc63119c0cfeebdd323cbd1f833676e2c 100644 (file)
@@ -98,7 +98,7 @@ class BaseTest(TestCase):
                 delattr(settings, a)
         settings.POSTMAN_MAILER_APP = None
         settings.POSTMAN_AUTOCOMPLETER_APP = {
-            'arg_default': 'postman_single', # no default, mandatory to enable the feature
+            'arg_default': 'postman_single_as1-1', # no default, mandatory to enable the feature
         }
         self.reload_modules()
 
@@ -285,13 +285,13 @@ class ViewTest(BaseTest):
         response = self.client.get(url)
         f = response.context['form'].fields['recipients']
         if hasattr(f, 'channel'): # app may not be in INSTALLED_APPS
-            self.assertEqual(f.channel, 'postman_single')
+            self.assertEqual(f.channel, 'postman_single_as1-1')
         # authenticated
         self.assert_(self.client.login(username='foo', password='pass'))
         response = self.client.get(url)
         f = response.context['form'].fields['recipients']
         if hasattr(f, 'channel'):
-            self.assertEqual(f.channel, 'postman_multiple')
+            self.assertEqual(f.channel, 'postman_multiple_as1-1')
 
     def check_init_by_query_string(self, action, args=[]):
         template = "postman/{0}.html".format(action)
@@ -460,7 +460,7 @@ class ViewTest(BaseTest):
         response = self.client.get(url)
         f = response.context['form'].fields['recipients']
         if hasattr(f, 'channel'):
-            self.assertEqual(f.channel, 'postman_multiple')
+            self.assertEqual(f.channel, 'postman_multiple_as1-1')
 
     def check_404(self, view_name, pk):
         "Return is a 404 page."
@@ -1585,3 +1585,66 @@ class UtilsTest(BaseTest):
         self.assertEqual(format_subject("foo bar"), "Re: foo bar")
         self.assertEqual(format_subject("Re: foo bar"), "Re: foo bar")
         self.assertEqual(format_subject("rE: foo bar"), "rE: foo bar")
+
+from postman.api import pm_broadcast, pm_write
+class ApiTest(BaseTest):
+    """
+    Test the API functions.
+    """
+    def check_message(self, m, subject='s', body='b', recipient_username='bar'):
+        "Check some message properties."
+        self.assertEqual(m.subject, subject)
+        self.assertEqual(m.body, body)
+        self.assertEqual(m.email, '')
+        self.assertEqual(m.sender, self.user1)
+        self.assertEqual(m.recipient.username, recipient_username)
+
+    def test_pm_broadcast(self):
+        "Test the case of a single recipient."
+        pm_broadcast(sender=self.user1, recipients=self.user2, subject='s', body='b')
+        m = Message.objects.get()
+        self.check_status(m, status=STATUS_ACCEPTED, moderation_date=True,
+            sender_archived=True, sender_deleted_at=True)
+        self.check_now(m.sender_deleted_at)
+        self.check_now(m.moderation_date)
+        self.check_message(m)
+        self.assertEqual(len(mail.outbox), 1)
+
+    def test_pm_broadcast_skip_notification(self):
+        "Test the notification skipping."
+        pm_broadcast(sender=self.user1, recipients=self.user2, subject='s', skip_notification=True)
+        self.assertEqual(len(mail.outbox), 0)
+
+    def test_pm_broadcast_multi(self):
+        "Test the case of more than a single recipient."
+        pm_broadcast(sender=self.user1, recipients=[self.user2, self.user3], subject='s', body='b')
+        msgs = list(Message.objects.all())
+        self.check_message(msgs[0], recipient_username='baz')
+        self.check_message(msgs[1])
+
+    def test_pm_write(self):
+        "Test the basic minimal use."
+        pm_write(sender=self.user1, recipient=self.user2, subject='s', body='b')
+        m = Message.objects.get()
+        self.check_status(m, status=STATUS_ACCEPTED, moderation_date=True)
+        self.check_now(m.moderation_date)
+        self.check_message(m)
+        self.assertEqual(len(mail.outbox), 1)
+
+    def test_pm_write_skip_notification(self):
+        "Test the notification skipping."
+        pm_write(sender=self.user1, recipient=self.user2, subject='s', skip_notification=True)
+        self.assertEqual(len(mail.outbox), 0)
+
+    def test_pm_write_auto_archive(self):
+        "Test the auto_archive parameter."
+        pm_write(sender=self.user1, recipient=self.user2, subject='s', auto_archive=True)
+        m = Message.objects.get()
+        self.check_status(m, status=STATUS_ACCEPTED, moderation_date=True, sender_archived=True)
+
+    def test_pm_write_auto_delete(self):
+        "Test the auto_delete parameter."
+        pm_write(sender=self.user1, recipient=self.user2, subject='s', auto_delete=True)
+        m = Message.objects.get()
+        self.check_status(m, status=STATUS_ACCEPTED, moderation_date=True, sender_deleted_at=True)
+        self.check_now(m.sender_deleted_at)
index dd42f1ee818bc2e9daf5f2f78c92bd7fbd888798..f135f14b822f1ff384d35e0325db591d7d9b08b2 100644 (file)
@@ -16,7 +16,7 @@ except ImportError:
     from datetime import datetime
     now = datetime.now
 
-from postman.fields import is_autocompleted
+from postman.fields import autocompleter_app
 from postman.forms import WriteForm, AnonymousWriteForm, QuickReplyForm, FullReplyForm
 from postman.models import Message, get_order_by
 from postman.urls import OPTION_MESSAGES
@@ -148,7 +148,7 @@ def write(request, recipients=None, form_classes=(WriteForm, AnonymousWriteForm)
         form = form_class(initial=initial, channel=channel)
     return render_to_response(template_name, {
         'form': form,
-        'is_autocompleted': is_autocompleted,
+        'autocompleter_app': autocompleter_app,
         'next_url': request.GET.get('next', next_url),
         }, context_instance=RequestContext(request))
 if getattr(settings, 'POSTMAN_DISALLOW_ANONYMOUS', False):
@@ -200,7 +200,7 @@ def reply(request, message_id, form_class=FullReplyForm, formatters=(format_subj
     return render_to_response(template_name, {
         'form': form,
         'recipient': parent.obfuscated_sender,
-        'is_autocompleted': is_autocompleted,
+        'autocompleter_app': autocompleter_app,
         'next_url': request.GET.get('next', next_url),
         }, context_instance=RequestContext(request))