wip: filter messages by type.

Initial work.

see #376
This commit is contained in:
Antoine Nguyen
2013-11-07 21:52:27 +01:00
parent 5dd3a4c8bc
commit 8a4af08bea
15 changed files with 112 additions and 28 deletions
+1
View File
@@ -87,6 +87,7 @@ class QuarantineNavigationParameters(NavigationParameters):
super(QuarantineNavigationParameters, self).__init__(
request, 'quarantine_navparams'
)
self.parameters += [('msgtype', None, False)]
def back_to_listing(self):
"""Return the current listing URL.
+8 -1
View File
@@ -19,7 +19,7 @@ class Qtable(tables.Table):
idkey = "mailid"
type = tables.Column(
"type", align="center", width="30px", sort_order="type"
"type", align="center", width="30px", sort_order="type", safe=True
)
score = tables.Column("score", label=ugettext_lazy("Score"), limit=6,
sort_order="score")
@@ -33,6 +33,13 @@ class Qtable(tables.Table):
cols_order = []
def parse_type(self, value):
if value in ['S', 'V']:
color = 'important'
else:
color = 'warning'
return '<span class="label label-%s">%s</span>' % (color, value)
def parse_date(self, value):
return datetime.fromtimestamp(value)
@@ -27,11 +27,20 @@
color: #0088cc;
}
#filters_bar {
/*padding-top: 5px;*/
padding-left: 15px;
}
thead tr {
position: relative;
z-index: 1;
}
td[name=type] span {
cursor: pointer;
}
td.unseen {
font-weight: bold;
}
@@ -17,6 +17,25 @@ Quarantine.prototype = {
this.register_navcallbacks();
this.listen();
this.set_msgtype();
$("#searchfield").searchbar({navobj: this.navobj});
},
/*
* Activate the button corresponding to the current message type
* filter. If no message type is found, the 'All' button is
* selected.
*/
set_msgtype: function() {
var msgtype = this.navobj.getparam('msgtype');
$("button[name*=msgtype]").removeClass('active');
if (msgtype != undefined) {
$("button[name=msgtype_" + msgtype + "]").addClass('active');
} else {
$("button[name=msgtype_all]").addClass('active');
}
},
update_page: function(data) {
@@ -47,11 +66,13 @@ Quarantine.prototype = {
$(document).on("click", "a[name=release]", $.proxy(this.release, this));
$(document).on("click", "a[name=delete]", $.proxy(this.delete, this));
$(document).on("click", "a[name=headers]", $.proxy(this.headers, this));
$(document).on("click", "td[name=type] span", $.proxy(this.filter_by_type, this));
$(document).on("click", "#filters button", $.proxy(this.filter_by_type, this));
},
load_page: function(e) {
Listing.prototype.load_page.apply(this, arguments);
this.navobj.delparam("rcpt");
this.navobj.delparam("rcpt").update();
},
view_requests: function(e) {
@@ -81,12 +102,26 @@ Quarantine.prototype = {
}
$("td[name=type]").each(function() {
var $this = $(this);
if ($this.html().trim() == type) {
if ($this.find('span').html().trim() == type) {
$("#emails").htmltable("select_row", $this.parent());
}
});
},
/*
* Filter listing by message type (spam, virus, etc.)
*/
filter_by_type: function(evt) {
var msgtype = $(evt.target).html().trim();
if (msgtype != 'All') {
this.navobj.setparam('msgtype', msgtype);
} else {
this.navobj.delparam('msgtype');
}
this.navobj.update();
},
_send_selection: function(e, name, message) {
var $link = $(e.target);
@@ -194,6 +229,8 @@ Quarantine.prototype = {
listing_cb: function(data) {
this.update_page(data);
this.navobj.delparam("rcpt").update();
this.set_msgtype();
$("#emails").htmltable();
this.htmltable = $("#emails").data("htmltable");
},
@@ -1,4 +1,4 @@
{% extends "fixed.html" %}{% load i18n %}
{% extends "fixed.html" %}{% load i18n amavis_tags %}
{% block pagetitle %}{% trans "Quarantine management" %}{% endblock %}
{% block html_head %}
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}amavis/css/quarantine.css" />
@@ -19,6 +19,6 @@ $(document).ready(function() {
</script>
{% endblock %}
{% block fixed_content %}
<div id="menubar"></div>
<div id="menubar">{% quar_menu user %}</div>
<div id="listing"></div>
{% endblock %}
@@ -0,0 +1,13 @@
{% extends "common/buttons_list.html" %}{% load i18n %}
{% block extracontent %}{% include "common/email_searchbar.html" with extraopts=extraopts %}
</div>
<div id="filters_bar" class="btn-toolbar pull-right">
<div id="filters" class="btn-group" data-toggle="buttons-radio">
<button name="msgtype_all" class="btn btn">{% trans "All" %}</button>
<button name="msgtype_S" class="btn btn btn-danger">S</button>
<button name="msgtype_V" class="btn btn btn-danger">V</button>
<button name="msgtype_H" class="btn btn btn-warning">H</button>
<button name="msgtype_M" class="btn btn btn-warning">M</button>
<button name="msgtype_B" class="btn btn btn-warning">B</button>
</div>
{% endblock %}
@@ -3,6 +3,7 @@ from django.template.loader import render_to_string
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
from django.conf import settings
from modoboa.lib.webutils import _render_to_string
register = template.Library()
@@ -103,11 +104,8 @@ def quar_menu(user):
extraopts = [{"name": "to", "label": _("To")}]
else:
extraopts = []
extracontent = render_to_string('common/email_searchbar.html', {
"STATIC_URL": settings.STATIC_URL,
"extraopts": extraopts
return render_to_string('amavis/main_action_bar.html', {
'entries': entries, 'extraopts': extraopts,
'STATIC_URL': settings.STATIC_URL, 'extraclasses': 'pull-left'
})
return render_to_string('common/buttons_list.html', dict(
entries=entries, extracontent=extracontent
))
+11 -4
View File
@@ -26,8 +26,7 @@ from .models import Msgrcpt
def empty_quarantine(request):
content = "<div class='alert alert-info'>%s</div>" % _("Empty quarantine")
ctx = getctx("ok", level=2, listing=content, paginbar="",
menu=quar_menu(request.user))
ctx = getctx("ok", level=2, listing=content, paginbar="")
return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
@@ -60,6 +59,11 @@ def _listing(request):
raise Exception("unsupported search criteria %s" % c)
flt = nfilter if flt is None else flt | nfilter
msgtype = navparams.get('msgtype', None)
if msgtype is not None:
nfilter = Q(mail__msgrcpt__content=msgtype)
flt = flt | nfilter if flt is not None else nfilter
msgs = get_wrapper().get_mails(request, rcptfilter)
page = navparams.get('page')
lst = SQLlisting(
@@ -73,8 +77,10 @@ def _listing(request):
content = lst.fetch(request, page.id_start, page.id_stop)
paginbar = pagination_bar(page)
ctx = getctx("ok", listing=content, paginbar=paginbar, page=page.number,
menu=quar_menu(request.user))
ctx = getctx("ok", listing=content, paginbar=paginbar, page=page.number)
if request.session.get('location', 'listing') != 'listing':
ctx['menu'] = quar_menu(request.user)
request.session['location'] = 'listing'
return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
@@ -147,6 +153,7 @@ def viewmail(request, mail_id):
""").render(Context({"url": reverse(getmailcontent, args=[mail_id])}))
menu = viewm_menu(request.user, mail_id, rcpt)
ctx = getctx("ok", menu=menu, listing=content)
request.session['location'] = 'viewmail'
return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
+1 -1
View File
@@ -756,4 +756,4 @@ class WebmailNavigationParameters(NavigationParameters):
request, 'webmail_navparams'
)
if defmailbox is not None:
self.parameters += [('mbox', defmailbox)]
self.parameters += [('mbox', defmailbox, False)]
@@ -0,0 +1,3 @@
{% extends "common/buttons_list.html" %}{% load i18n %}
{% block extracontent %}{% include "common/email_searchbar.html" with extraopts=extraopts %}
{% endblock %}
@@ -114,13 +114,10 @@ def listmailbox_menu(selection, folder, user):
"label": _("Empty folder"),
"url": reverse(webmail.views.empty, args=[folder])}
]
searchbar = render_to_string('common/email_searchbar.html', {
"STATIC_URL": settings.STATIC_URL
return render_to_string('webmail/main_action_bar.html', {
'selection': selection, 'entries': entries, 'user': user, 'css': "nav",
'STATIC_URL': settings.STATIC_URL
})
return render_to_string('common/buttons_list.html', dict(
selection=selection, entries=entries, extracontent=searchbar,
user=user, css="nav"
))
@register.simple_tag
+9 -3
View File
@@ -172,7 +172,8 @@ class NavigationParameters(object):
def __init__(self, request, sessionkey):
self.request = request
self.sessionkey = sessionkey
self.parameters = [('pattern', ''), ('criteria', 'from_addr')]
self.parameters = [('pattern', '', True),
('criteria', 'from_addr', False)]
def store(self):
"""Store navigation parameters into session.
@@ -182,8 +183,13 @@ class NavigationParameters(object):
navparams = self.request.session[self.sessionkey]
navparams["order"] = self.request.GET.get("sort_order", "-date")
navparams["page"] = int(self.request.GET.get("page", 1))
for param, defvalue in self.parameters:
navparams[param] = re.escape(self.request.GET.get(param, defvalue))
for param, defvalue, escape in self.parameters:
value = self.request.GET.get(param, defvalue)
if value is None:
if param in navparams:
del navparams[param]
continue
navparams[param] = re.escape(value) if escape else value
def get(self, param, default_value=None):
"""Retrieve a navigation parameter.
+5
View File
@@ -116,3 +116,8 @@ body {
.table-fixed {
table-layout: fixed;
}
.menubar-text {
display: inline;
vertical-align: middle;
}
+1 -1
View File
@@ -30,7 +30,7 @@ Listing.prototype = {
e.preventDefault();
});
}
if (data.page != this.navobj.getparam("page")) {
if (data.page && data.page != this.navobj.getparam("page")) {
this.navobj.setparam("page", data.page).update(false, true);
}
var $sortables = $(this.options.sortable_selector);
+2 -1
View File
@@ -7,5 +7,6 @@
{% endfor %}</ul>
{% else %}{% render_link entry "btn" %}{% endif %}
</div>
{% endfor %}{{ extracontent }}</div>
{% endfor %}{% block extracontent %}{% endblock %}
</div>