diff --git a/modoboa/core/views/admin.py b/modoboa/core/views/admin.py
index 8b22b4923..911544e8b 100644
--- a/modoboa/core/views/admin.py
+++ b/modoboa/core/views/admin.py
@@ -143,7 +143,7 @@ def logs_page(request, tplname="core/logs_page.html"):
else:
context = {
"rows": render_to_string(tplname, {"logs": page.object_list}),
- "page": page.number
+ "pages": [page.number]
}
return render_to_json_response(context)
diff --git a/modoboa/extensions/admin/views/domain.py b/modoboa/extensions/admin/views/domain.py
index bbcdfbff0..64ddfd807 100644
--- a/modoboa/extensions/admin/views/domain.py
+++ b/modoboa/extensions/admin/views/domain.py
@@ -71,7 +71,7 @@ def _domains(request):
'domains': page.object_list,
}
)
- context["page"] = page.number
+ context["pages"] = [page.number]
return render_to_json_response(context)
diff --git a/modoboa/extensions/admin/views/identity.py b/modoboa/extensions/admin/views/identity.py
index ef4498aee..73a3eb8f3 100644
--- a/modoboa/extensions/admin/views/identity.py
+++ b/modoboa/extensions/admin/views/identity.py
@@ -60,7 +60,7 @@ def _identities(request):
"identities": page.object_list
}
)
- context["page"] = page.number
+ context["pages"] = [page.number]
return render_to_json_response(context)
diff --git a/modoboa/extensions/amavis/static/amavis/js/quarantine.js b/modoboa/extensions/amavis/static/amavis/js/quarantine.js
index dbb3506e4..3ca47ad36 100644
--- a/modoboa/extensions/amavis/static/amavis/js/quarantine.js
+++ b/modoboa/extensions/amavis/static/amavis/js/quarantine.js
@@ -83,7 +83,6 @@ Quarantine.prototype = {
$(this.options.scroll_container).scrollTop(10);
} else {
this.update_listing(data, false);
- $(this.options.scroll_container).infinite_scroll("pause");
}
},
diff --git a/modoboa/extensions/amavis/views.py b/modoboa/extensions/amavis/views.py
index a7f3c937e..13e194f42 100644
--- a/modoboa/extensions/amavis/views.py
+++ b/modoboa/extensions/amavis/views.py
@@ -27,15 +27,15 @@ from .sql_connector import get_connector
from .sql_listing import SQLemail
-def empty_quarantine(request):
+def empty_quarantine():
"""Shortcut to use when no content can be displayed."""
content = "
%s
" % _("Empty quarantine")
ctx = getctx("ok", level=2, listing=content)
return render_to_json_response(ctx)
-def get_listing_page(request, connector):
- """."""
+def get_listing_pages(request, connector):
+ """Return listing pages."""
paginator = Paginator(
connector.messages_count(),
int(parameters.get_user(request.user, "MESSAGES_PER_PAGE"))
@@ -44,7 +44,13 @@ def get_listing_page(request, connector):
page = paginator.getpage(page_id)
if not page:
return None
- return page
+ pages = [page]
+ if not page.has_next and page.has_previous and page.items < 40:
+ pages = [paginator.getpage(page_id - 1)] + pages
+ email_list = []
+ for page in pages:
+ email_list += connector.fetch(page.id_start, page.id_stop)
+ return {"pages": [page.number for page in pages], "rows": email_list}
@login_required
@@ -55,42 +61,42 @@ def listing_page(request):
navparams.store()
connector = get_connector(user=request.user, navparams=navparams)
- page = get_listing_page(request, connector)
- if page is None:
+ context = get_listing_pages(request, connector)
+ if context is None:
context = {"length": 0}
navparams["page"] = previous_page_id
else:
- context = {
- "rows": _render_to_string(request, "amavis/emails_page.html", {
- "email_list": connector.fetch(page.id_start, page.id_stop)
- }),
- "page": page.number
- }
+ context["rows"] = _render_to_string(
+ request, "amavis/emails_page.html", {"email_list": context["rows"]}
+ )
return render_to_json_response(context)
@login_required
def _listing(request):
+ """Listing initial view.
+
+ Called the first time the listing page is displayed.
+ """
if not request.user.is_superuser and request.user.group != 'SimpleUsers':
if not Domain.objects.get_for_admin(request.user).count():
- return empty_quarantine(request)
+ return empty_quarantine()
navparams = QuarantineNavigationParameters(request)
navparams.store()
connector = get_connector(user=request.user, navparams=navparams)
- page = get_listing_page(request, connector)
- if page is None:
- return empty_quarantine(request)
-
- content = _render_to_string(request, "amavis/email_list.html", {
- "email_list": connector.fetch(page.id_start, page.id_stop),
- })
- ctx = getctx("ok", listing=content, page=page.number)
+ context = get_listing_pages(request, connector)
+ if context is None:
+ return empty_quarantine()
+ context["listing"] = _render_to_string(
+ request, "amavis/email_list.html", {"email_list": context["rows"]}
+ )
+ del context["rows"]
if request.session.get('location', 'listing') != 'listing':
- ctx['menu'] = quar_menu()
- request.session['location'] = 'listing'
- return render_to_json_response(ctx)
+ context["menu"] = quar_menu()
+ request.session["location"] = "listingx"
+ return render_to_json_response(context)
@login_required
diff --git a/modoboa/extensions/webmail/lib/imaputils.py b/modoboa/extensions/webmail/lib/imaputils.py
index d087306f4..f5d735282 100644
--- a/modoboa/extensions/webmail/lib/imaputils.py
+++ b/modoboa/extensions/webmail/lib/imaputils.py
@@ -664,7 +664,7 @@ class IMAPconnector(object):
attdef = bs.find_attachment(partnum)
return attdef, data[int(uid)]["BODY[%s]" % partnum]
- def fetch(self, start, stop=None, mbox=None, **kwargs):
+ def fetch(self, start, stop=None, mbox=None):
"""Retrieve information about messages from the server
Issue a FETCH command to retrieve information about one or
@@ -685,7 +685,9 @@ class IMAPconnector(object):
data = self._cmd("FETCH", range, query)
result = []
for uid in submessages:
- msg = email.message_from_string(data[int(uid)]['BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)]'])
+ msg = email.message_from_string(
+ data[int(uid)]['BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)]']
+ )
msg['imapid'] = uid
if not r'\Seen' in data[int(uid)]['FLAGS']:
msg['style'] = 'unseen'
diff --git a/modoboa/extensions/webmail/static/webmail/js/webmail.js b/modoboa/extensions/webmail/static/webmail/js/webmail.js
index 6a356f39f..ce737b638 100644
--- a/modoboa/extensions/webmail/static/webmail/js/webmail.js
+++ b/modoboa/extensions/webmail/static/webmail/js/webmail.js
@@ -172,15 +172,16 @@ Webmail.prototype = {
var that = this;
if ($container.data("infinite-scroll") !== undefined) {
- $container.scrollTop(10);
- $container.infinite_scroll(
- "reset_loaded_pages", parseInt(data.page));
+ if (data.pages && data.pages[0] != 1) {
+ $container.scrollTop(10);
+ }
+ $container.infinite_scroll("reset_loaded_pages", data.pages);
$container.infinite_scroll("resume");
return;
}
$container.infinite_scroll({
- initial_page: parseInt(data.page),
+ initial_pages: data.pages,
url: this.options.listing_url,
calculate_bottom: function($element) {
return $("#emails").height() - $element.height();
diff --git a/modoboa/extensions/webmail/views.py b/modoboa/extensions/webmail/views.py
index c99d84334..96e0710e0 100644
--- a/modoboa/extensions/webmail/views.py
+++ b/modoboa/extensions/webmail/views.py
@@ -127,7 +127,7 @@ def empty(request):
get_imapconnector(request).empty(name)
content = "%s
" % _("Empty mailbox")
return render_to_json_response({
- 'listing': content, 'mailbox': name
+ 'listing': content, 'mailbox': name, 'pages': [1]
})
@@ -357,11 +357,9 @@ def listmailbox(request, defmailbox="INBOX", update_session=True):
int(parameters.get_user(request.user, "MESSAGES_PER_PAGE"))
)
page = paginator.getpage(page_id)
-
+ content = ""
if page is not None:
- email_list = mbc.fetch(
- page.id_start, page.id_stop, mbox, nbelems=page.items
- )
+ email_list = mbc.fetch(page.id_start, page.id_stop, mbox)
content = _render_to_string(request, "webmail/email_list.html", {
"email_list": email_list,
"page": page_id,
@@ -369,12 +367,13 @@ def listmailbox(request, defmailbox="INBOX", update_session=True):
})
length = len(content)
else:
- content = "{}
".format(
- _("Empty mailbox")
- )
+ if page_id == 1:
+ content = "{}
".format(
+ _("Empty mailbox")
+ )
length = 0
navparams["page"] = previous_page_id
- return {"listing": content, "length": length, "page": page_id}
+ return {"listing": content, "length": length, "pages": [page_id]}
def render_compose(request, form, posturl, email=None, insert_signature=False):
diff --git a/modoboa/lib/paginator.py b/modoboa/lib/paginator.py
index 6ba5dab20..79ecf94dd 100644
--- a/modoboa/lib/paginator.py
+++ b/modoboa/lib/paginator.py
@@ -25,8 +25,8 @@ class Page(object):
@property
def items(self):
- """The total number of items. (shortcut)"""
- return self.paginator.total
+ """The number of items in this page."""
+ return self.id_stop - self.id_start
@property
def has_previous(self):
@@ -61,10 +61,10 @@ class Page(object):
@property
def last_page(self):
"""Retrieve the id of the last page."""
- lid = self.items / self.items_per_page
+ lid = self.paginator.total / self.items_per_page
if not lid:
return 1
- if self.items % self.items_per_page:
+ if self.paginator.total % self.items_per_page:
lid += 1
return lid
diff --git a/modoboa/static/js/jquery.infinitescroll.js b/modoboa/static/js/jquery.infinitescroll.js
index 0d590dddd..23de4b23e 100644
--- a/modoboa/static/js/jquery.infinitescroll.js
+++ b/modoboa/static/js/jquery.infinitescroll.js
@@ -20,10 +20,14 @@
this.$options = options;
this.executing = false;
this.end_of_results = false;
- this.current_page = (isNaN(this.$options.initial_page)) ?
- 1 : this.$options.initial_page;
- this.loaded_pages = [this.current_page];
-
+ if (this.$options.initial_pages !== undefined &&
+ this.$options.initial_pages.length > 0) {
+ this.current_page = this.$options.initial_pages[0];
+ this.loaded_pages = this.$options.initial_pages;
+ } else {
+ this.current_page = 1;
+ this.loaded_pages = [this.current_page];
+ }
this.resume();
};
@@ -38,7 +42,7 @@
on_scroll: function() {
var bottom = this.$options.calculate_bottom(this.$element);
- if (bottom === undefined) {
+ if (bottom === undefined || bottom < 0) {
return;
}
if (this.$element.scrollTop() >= bottom) {
@@ -128,11 +132,11 @@
* Reset the loaded pages cache.
*
* @this InfiniteScroll
- * @param {Array} current_page - the new current_page
+ * @param {Array} new_pages - the new loaded pages
*/
- reset_loaded_pages: function(current_page) {
- this.current_page = current_page;
- this.loaded_pages = [this.current_page];
+ reset_loaded_pages: function(new_pages) {
+ this.current_page = new_pages[0];
+ this.loaded_pages = new_pages;
this.end_of_results = false;
},
diff --git a/modoboa/static/js/listing.js b/modoboa/static/js/listing.js
index fba3c774e..5a9546fc9 100644
--- a/modoboa/static/js/listing.js
+++ b/modoboa/static/js/listing.js
@@ -136,7 +136,7 @@ Listing.prototype = {
*/
end_of_list_reached: function(element) {
$("#" + this.options.main_table_id).after(
- $("{0}
".format(
+ $("{0}
".format(
this.options.eor_message
))
);
@@ -156,10 +156,11 @@ Listing.prototype = {
$scroll_container.scrollTop(0);
if (with_infinite_scroll || with_infinite_scroll === undefined) {
if ($scroll_container.data("infinite-scroll") !== undefined) {
- $scroll_container.infinite_scroll("reset_loaded_pages", data.page);
+ $scroll_container.infinite_scroll("reset_loaded_pages", data.pages);
$scroll_container.infinite_scroll("resume");
} else {
$scroll_container.infinite_scroll({
+ initial_pages: data.pages,
url: this.options.load_page_url,
get_args: $.proxy(this.get_load_page_args, this),
calculate_bottom: $.proxy(this.calculate_bottom, this),