Commits

Dejan Noveski  committed 2d6c8c8

Added model SkipInboxFolder, added relation from message to it, added views for creation, filtering by, moving to and from them, added logic for saving and filtering in Message model, template changes.

  • Participants
  • Parent commits 6b82b6d

Comments (0)

Files changed (8)

File postman/admin.py

 from django.db import transaction
 from django.utils.translation import ugettext, ugettext_lazy as _
 
-from postman.models import Message, PendingMessage
+from postman.models import Message, PendingMessage, SkipInboxFolder
 
 class MessageAdminForm(forms.ModelForm):
     class Meta:
     fieldsets = (
         (None, {'fields': (
             ('sender', 'recipient', 'email'),
-            'sent_at',
+            'sent_at', 'recipient_skip_inbox_folder',
             )}),
         (_('Message'), {'fields': (
             'subject',
         "Deleting is impossible"
         return False
 
+class SkipInboxMessageAdmin(admin.ModelAdmin):
+    search_fields = ('name', 'user')
+    list_display = ('name', 'user')
+
 admin.site.register(Message, MessageAdmin)
 admin.site.register(PendingMessage, PendingMessageAdmin)
+admin.site.register(SkipInboxFolder, SkipInboxMessageAdmin)

File postman/models.py

                 order_by_field = '-' + order_by_field
             return order_by_field
 
+
+class SkipInboxFolder(models.Model):
+    """
+    Defines a skip-inbox folder for messages. Folders can be user-specific or system-wide by setting user to None
+    """
+
+    name = models.CharField(_("name"), max_length = 150)
+    user = models.ForeignKey(User, related_name='own_folder', null=True, blank=True, verbose_name=_("user"))
+
+    def save(self, *args, **kwargs):
+        from django.core.exceptions import ValidationError
+        if self.user is None:
+            
+
+        system_folders = SkipInboxFolder.objects.filter(
+                models.Q(name = self.name), models.Q(models.Q(user=self.user) | models.Q(user=None))).count()
+
+        if system_folders > 0:
+            raise ValidationError('A system folder with that name already exists. Use that one, or change the name.')
+        return super(SkipInboxFolder, self).save(*args, **kwargs)
+
+    class Meta:
+        verbose_name = _("skip-inbox folder")
+        verbose_name_plural = _("skip-inbox folders")
+        unique_together = ("name", "user",)
+    
+    def __unicode__(self):
+        return self.name
+    
+    @models.permalink
+    def get_absolute_url(self):
+        return ('postman_folder', [self.name,])
+
+
 class MessageManager(models.Manager):
     """The manager for Message."""
 
             'recipient_archived': False,
             'recipient_deleted_at__isnull': True,
             'moderation_status': STATUS_ACCEPTED,
+            'recipient_skip_inbox_folder': None,
         }
         return self._folder(related, filters, **kwargs)
 
             'sender_deleted_at__isnull': False,
         })
         return self._folder(related, filters, **kwargs)
+    
+    def skip_inbox_folder(self, user, **kwargs):
+        """
+        Return messages belonging to a user, moved to another skip-inbox folder
+        """
+        related = ('recipient')
+        folder_name = kwargs.get("folder_name", None)
+        
+        if not folder_name:
+            return self.inbox(user, **kwargs)
+        else:
+            del kwargs["folder_name"]
+
+        folder = SkipInboxFolder.objects.filter(models.Q(name = folder_name), models.Q(models.Q(user=user) | models.Q(user=None)))
+        
+        if not folder:
+            return self.none()
+        
+        filters = ({
+            'recipient': user,
+            'recipient_archived': False,
+            'recipient_deleted_at__isnull': True,
+            'recipient_skip_inbox_folder': folder,
+            'moderation_status': STATUS_ACCEPTED,
+        },)
+        return self._folder(related, filters, **kwargs)
 
     def thread(self, user, filter):
         """
             read_at__isnull=True,
         ).update(read_at=datetime.datetime.now())
 
+
+
 class Message(models.Model):
     """
     A message between a User and another User or an AnonymousUser.
         null=True, blank=True, verbose_name=_("moderator"))
     moderation_date = models.DateTimeField(_("moderated at"), null=True, blank=True)
     moderation_reason = models.CharField(_("rejection reason"), max_length=120, blank=True)
+    sender_skip_inbox_folder = models.ForeignKey(SkipInboxFolder, verbose_name = _("skip-inbox folder"), related_name='received_moved_messages', null=True, blank=False,)
+    recipient_skip_inbox_folder = models.ForeignKey(SkipInboxFolder, verbose_name = _("skip-inbox folder"), related_name='sent_moved_messages', null=True, blank=False,)
 
     objects = MessageManager()
 

File postman/templates/postman/archives.html

 {% block pm_folder_title %}{% trans "Archived Messages" %}{% endblock %}
 {% block pm_archive_button %}{% endblock %}
 {% block pm_undelete_button %}{% endblock %}
+{% block pm_move_button %}{% endblock %}
 {% block pm_footer_info %}
 <p>{% trans "Messages in this folder will never be removed. You can use this folder for long term storage." %}</p>
 {% endblock %}

File postman/templates/postman/base.html

 {% block postman_menu %}
 <ul id="postman_menu">{% postman_unread as unread_count %}
  <li><a href="{% url postman_inbox %} ">&raquo;&nbsp;{% trans "Inbox" %}{% if unread_count %} <strong>({{ unread_count }})</strong>{% endif %}</a></li>
+ <li>
+  <ul>
+    {%for f in skip_inbox_folders%}
+      <li><a href="{% url postman_folder folder_name=f.name %} ">&raquo;&nbsp;{{f.name}}</a></li>  
+    {%endfor%}
+    <li>
+      <form action="{%url postman_create_folder%}" method="post">
+        <label for="postman_create_folder_name">{% trans "Create a folder"%}</label><input id="postman_create_folder_name" type="text" name="folder_name"/>
+        <input type="submit" value="{%trans 'Create'%}"/>
+      </form>
+    </li>
+  </ul>
+ </li> 
  <li><a href="{% url postman_sent %} ">&raquo;&nbsp;{% trans "Sent Messages" %}</a></li>
  <li><a href="{% url postman_write %} ">&raquo;&nbsp;{% trans "Write" %}</a></li>
  <li><a href="{% url postman_archives %} ">&raquo;&nbsp;{% trans "Archives" %}</a></li>

File postman/templates/postman/base_folder.html

 {% block pm_delete_button %}<button type="submit" onclick="this.form.action='{% url postman_delete %}'">{% trans "Delete" %}</button>{% endblock %}
 {% block pm_archive_button %}<button type="submit" onclick="this.form.action='{% url postman_archive %}'">{% trans "Archive" %}</button>{% endblock %}
 {% block pm_undelete_button %}<button type="submit" onclick="this.form.action='{% url postman_undelete %}'">{% trans "Undelete" %}</button>{% endblock %}
+{% block pm_move_button %}
+<select name="folder_id">
+    <option value="">{%trans "Inbox"%}</option>
+    {%for folder in skip_inbox_folders%}
+      <option value="{{folder.id}}">{{folder.name}}</option>
+    {%endfor%}
+</select><button type="submit" onclick="this.form.action='{% url postman_skip_inbox %}'">{% trans "Move" %}</button>
+{% endblock %}
 </span>{% endblock %}
 <table id="pm_messages">
  <thead>

File postman/templates/postman/trash.html

 {% block pm_folder_title %}{% trans "Deleted Messages" %}{% endblock %}
 {% block pm_delete_button %}{% endblock %}
 {% block pm_archive_button %}{% endblock %}
+{% block pm_move_button %}{% endblock %}
 {% block pm_subject %}{# no link #}
      {% include "postman/inc_subject_ex.html" %}
 {% endblock %}

File postman/urls.py

     url(r'^archive/$', 'archive', name='postman_archive'),
     url(r'^delete/$', 'delete', name='postman_delete'),
     url(r'^undelete/$', 'undelete', name='postman_undelete'),
+    url(r'^skip_inbox/$', 'skip_inbox', name='postman_skip_inbox'),
+    url(r'^create_folder/$', 'create_folder', name='postman_create_folder'),
+    url(r'^folder/(?P<folder_name>[^\/]+)/(?:(?P<option>'+OPTIONS+')/)?$', 'skip_inbox_folder', name='postman_folder'),
     (r'^$', redirect_to, {'url': 'inbox/'}),
 )

File postman/views.py

 
 from postman.fields import is_autocompleted
 from postman.forms import WriteForm, AnonymousWriteForm, QuickReplyForm, FullReplyForm
-from postman.models import Message, get_order_by
+from postman.models import Message, get_order_by, SkipInboxFolder
 from postman.urls import OPTION_MESSAGES
 from postman.utils import format_subject, format_body
 
         sr = urlparse.urlsplit(request.META['HTTP_REFERER'])
         return urlparse.urlunsplit(('','',sr.path,sr.query,sr.fragment))
 
+
+def _get_skip_inbox_folders(request):
+    """Return the skip-inbox folders"""
+    if request.user.is_authenticated():
+        return SkipInboxFolder.objects.filter(Q(user = request.user)|Q(user = None))
+    else:
+        return SkipInboxFolder.objects.filter(Q(user = None))
+
 ########
 # Views
 ########
         'by_message_url': reverse(view_name, args=[OPTION_MESSAGES]),
         'current_url': request.get_full_path(),
         'gets': request.GET, # useful to postman_order_by template tag
+        'skip_inbox_folders': _get_skip_inbox_folders(request),
         }, context_instance=RequestContext(request))
 
 @login_required
     """
     return _folder(request, 'trash', 'postman_trash', option, template_name)
 
+@login_required
+def skip_inbox_folder(request, folder_name, option=None, template_name='postman/inbox.html'):
+    """
+    Display the messages that skipped inbox to [folder_name]
+    """
+    kwargs = {}
+    if option:
+        kwargs.update(option=option)
+    order_by = get_order_by(request.GET)
+    if order_by:
+        kwargs.update(order_by=order_by)
+    kwargs.update(folder_name=folder_name)
+    msgs = getattr(Message.objects, 'skip_inbox_folder')(request.user, **kwargs)
+    return render_to_response(template_name, {
+        'pm_messages': msgs,    # avoid 'messages', already used by contrib.messages
+        'by_conversation': option is None,
+        'by_message': option == OPTION_MESSAGES,
+        'by_conversation_url': reverse("postman_folder", args=[folder_name]),
+        'by_message_url': reverse("postman_folder", args=[folder_name, OPTION_MESSAGES]),
+        'current_url': request.get_full_path(),
+        'gets': request.GET, # useful to postman_order_by template tag
+        'skip_inbox_folders': _get_skip_inbox_folders(request),
+        }, context_instance=RequestContext(request))
+
+
 def write(request, recipients=None, form_classes=(WriteForm, AnonymousWriteForm), autocomplete_channels=None,
         template_name='postman/write.html', success_url=None,
         user_filter=None, exchange_filter=None, max=None, auto_moderators=[]):
         'form': form,
         'is_autocompleted': is_autocompleted,
         'next_url': request.GET.get('next', next_url),
+        'skip_inbox_folders': _get_skip_inbox_folders(request),
         }, context_instance=RequestContext(request))
 if getattr(settings, 'POSTMAN_DISALLOW_ANONYMOUS', False):
     write = login_required(write)
         'recipient': parent.obfuscated_sender,
         'is_autocompleted': is_autocompleted,
         'next_url': request.GET.get('next', next_url),
+        'skip_inbox_folders': _get_skip_inbox_folders(request),
         }, context_instance=RequestContext(request))
 
 def _view(request, filter, form_class=QuickReplyForm, formatters=(format_subject,format_body),
             'reply_to_pk': received.pk if received else None,
             'form' : form_class(initial=received.quote(*formatters)) if received else None,
             'next_url': request.GET.get('next', reverse('postman_inbox')),
+            'skip_inbox_folders': _get_skip_inbox_folders(request),
             }, context_instance=RequestContext(request))
     raise Http404
 
 def undelete(request, *args, **kwargs):
     """Revert messages/conversations from marked as deleted."""
     return _update(request, 'deleted_at', _("Messages or conversations successfully recovered."), *args, **kwargs)
+
+@login_required
+def skip_inbox(request, *args, **kwargs):
+    """Revert messages/conversations from marked as deleted."""
+
+    folder_id = request.POST.get("folder_id", None)
+    folder = None
+    if folder_id:
+        try:
+            folder = SkipInboxFolder.objects.get(id=folder_id)
+        except SkipInboxFolder.DoesNotExist:
+            folder = None
+    else:
+        folder = None
+
+    return _update(request, 'skip_inbox_folder', _("Messages moved successfully."), folder, **kwargs)
+
+@login_required
+def create_folder(request, *args, **kwargs):
+    """ Create a skip-inbox folder. """
+    from django.core.exceptions import ValidationError
+    if not request.method == 'POST':
+        raise Http404
+    
+    next_url = _get_referer(request) or 'postman_inbox'
+    folder_name = request.POST.get("folder_name", None)
+    if folder_name:
+        try:
+            folder = SkipInboxFolder(name = folder_name, user = request.user)
+            folder.save()
+            messages.success(request, _("Folder successfully created."), fail_silently=True)
+            return redirect(next_url)
+        except ValidationError, e:
+            messages.warning(request, _("There's already a system folder with that name."), fail_silently=True)
+            return redirect(next_url)
+    else:
+        messages.warning(request, _("Please insert a folder name."), fail_silently=True)
+        return redirect(next_url)
+
+