diff --git a/modoboa/core/extensions.py b/modoboa/core/extensions.py
index 0db058b61..6ff68c88a 100644
--- a/modoboa/core/extensions.py
+++ b/modoboa/core/extensions.py
@@ -3,7 +3,7 @@ from django.conf.urls import include
class ModoExtension(object):
- """Base extension class
+ """Base extension class.
Each Modoboa extension must inherit from this class to be
considered as valid.
diff --git a/modoboa/extensions/admin/static/admin/js/admin.js b/modoboa/extensions/admin/static/admin/js/admin.js
index a3c245b82..c0c1a5b72 100644
--- a/modoboa/extensions/admin/static/admin/js/admin.js
+++ b/modoboa/extensions/admin/static/admin/js/admin.js
@@ -39,7 +39,6 @@ Admin.prototype = {
* Children must override this method.
*/
listen: function() {
- $(document).on("click", "a.filter", $.proxy(this.filter_by_tag, this));
},
importform_cb: function() {
diff --git a/modoboa/extensions/radicale/__init__.py b/modoboa/extensions/radicale/__init__.py
index d713a190b..2ca63a3e5 100644
--- a/modoboa/extensions/radicale/__init__.py
+++ b/modoboa/extensions/radicale/__init__.py
@@ -33,6 +33,7 @@ class Radicale(ModoExtension):
name = "radicale"
label = ugettext_lazy("Radicale frontend")
version = "1.0"
+ url = "calendars"
description = ugettext_lazy(
"Management frontend for Radicale, a simple calendar and contact server."
)
diff --git a/modoboa/extensions/radicale/static/radicale/js/radicale.js b/modoboa/extensions/radicale/static/radicale/js/radicale.js
index 9a6552ba7..a38393bcc 100644
--- a/modoboa/extensions/radicale/static/radicale/js/radicale.js
+++ b/modoboa/extensions/radicale/static/radicale/js/radicale.js
@@ -14,13 +14,16 @@ Radicale.prototype = {
constructor: Radicale,
defaults: {
- deflocation: "calendars/"
+ deflocation: "list/",
+ main_table_id: "calendar_table",
+ eor_message: gettext("No more calendar to show")
},
initialize: function(options) {
this.options = $.extend({}, this.defaults, options);
this.options.defcallback = $.proxy(this.list_cb, this);
Listing.prototype.initialize.call(this, this.options);
+ this.options.navigation_params.push("calfilter");
this.register_tag_handler("cal", this.generic_tag_handler);
$(document).on(
"click", "a[name=delcalendar]", $.proxy(this.del_calendar, this)
@@ -28,9 +31,8 @@ Radicale.prototype = {
},
list_cb: function(data) {
- $("#listing").html(data.table);
+ $("#{0} tbody".format(this.options.main_table_id)).html(data.rows);
this.update_listing(data);
- $("a.filter").click($.proxy(this.filter_by_tag, this));
},
/**
diff --git a/modoboa/extensions/radicale/templates/radicale/calendar_list.html b/modoboa/extensions/radicale/templates/radicale/calendar_list.html
deleted file mode 100644
index 3d87ac0b6..000000000
--- a/modoboa/extensions/radicale/templates/radicale/calendar_list.html
+++ /dev/null
@@ -1,23 +0,0 @@
-{% load i18n lib_tags radicale_tags %}
-
-
-
- | {% trans "Name" %} |
- {% if with_owner %}{% trans "Owner" %} | {% endif %}
- {% trans "Tags" %} |
- {% trans "Address" %} |
- {% trans "Actions" %} |
-
-
-
- {% for cal in calendars %}
-
- | {% calendar_modify_link cal %} |
- {% if with_owner %}{{ cal.owner }} | {% endif %}
- {% render_tags cal.tags %} |
- {{ cal.url }} |
- {% calendar_actions cal %} |
-
- {% endfor %}
-
-
diff --git a/modoboa/extensions/radicale/templates/radicale/calendars.html b/modoboa/extensions/radicale/templates/radicale/calendars.html
index c4010c5c3..99ac8864a 100644
--- a/modoboa/extensions/radicale/templates/radicale/calendars.html
+++ b/modoboa/extensions/radicale/templates/radicale/calendars.html
@@ -3,6 +3,7 @@
+
@@ -12,7 +13,8 @@
@@ -31,5 +33,20 @@ $(document).ready(function() {
-
+
+
+
+
+ | {% trans "Name" %} |
+ {% if with_owner %}{% trans "Owner" %} | {% endif %}
+ {% trans "Tags" %} |
+ {% trans "Address" %} |
+ {% trans "Actions" %} |
+
+
+
+
+
+
+
{% endblock %}
diff --git a/modoboa/extensions/radicale/templates/radicale/calendars_page.html b/modoboa/extensions/radicale/templates/radicale/calendars_page.html
new file mode 100644
index 000000000..a5876e4ff
--- /dev/null
+++ b/modoboa/extensions/radicale/templates/radicale/calendars_page.html
@@ -0,0 +1,10 @@
+{% load i18n lib_tags radicale_tags %}
+{% for cal in calendars %}
+
+ | {% calendar_modify_link cal %} |
+ {% if with_owner %}{{ cal.owner }} | {% endif %}
+ {% render_tags cal.tags %} |
+ {{ cal.url }} |
+ {% calendar_actions cal %} |
+
+{% endfor %}
diff --git a/modoboa/extensions/radicale/urls.py b/modoboa/extensions/radicale/urls.py
index 14f69e9f3..5904c1f76 100644
--- a/modoboa/extensions/radicale/urls.py
+++ b/modoboa/extensions/radicale/urls.py
@@ -4,13 +4,13 @@ urlpatterns = patterns(
'modoboa.extensions.radicale.views',
url(r'^$', 'index', name="index"),
- url(r'^calendars/$', 'calendars', name="calendar_list"),
- url(r'^usercalendar/$', 'new_user_calendar', name='user_calendar_add'),
- url(r'^usercalendar/(?P\d+)/$', 'user_calendar',
+ url(r'^list/$', 'calendars_page', name="calendars_page"),
+ url(r'^user/$', 'new_user_calendar', name='user_calendar_add'),
+ url(r'^user/(?P\d+)/$', 'user_calendar',
name='user_calendar'),
- url(r'^sharedcalendar/$', 'new_shared_calendar',
+ url(r'^shared/$', 'new_shared_calendar',
name='shared_calendar_add'),
- url(r'^sharedcalendar/(?P\d+)/$', 'shared_calendar',
+ url(r'^shared/(?P\d+)/$', 'shared_calendar',
name='shared_calendar'),
url(r'^usernames/$', 'username_list', name='username_list'),
)
diff --git a/modoboa/extensions/radicale/views.py b/modoboa/extensions/radicale/views.py
index 61ae77aab..081ac18b1 100644
--- a/modoboa/extensions/radicale/views.py
+++ b/modoboa/extensions/radicale/views.py
@@ -10,7 +10,7 @@ from django.contrib.auth.decorators import (
)
from django.utils.translation import ugettext as _
-from modoboa.lib.listing import get_sort_order
+from modoboa.lib.listing import get_sort_order, get_listing_page
from modoboa.lib.webutils import (
_render_to_string, render_to_json_response
)
@@ -24,27 +24,25 @@ from modoboa.extensions.radicale.models import UserCalendar, SharedCalendar
@login_required
def index(request):
+ """Calendar list entry point."""
return render(request, "radicale/calendars.html", {
- "selection": "radicale"
+ "selection": "radicale",
+ "with_owner": request.user.group != "SimpleUsers"
})
-@login_required
-def calendars(request, tplname="radicale/calendar_list.html"):
- """Display calendars list.
-
- The content depends on current user's role.
- """
+def get_calendar_page(request, page_id=None):
+ """Return a page containing calendars."""
sort_order, sort_dir = get_sort_order(request.GET, "name")
calfilter = request.GET.get("calfilter", None)
searchquery = request.GET.get("searchquery", None)
+ page_id = request.GET.get("page", 1)
if request.user.group == "SimpleUsers":
mbox = request.user.mailbox_set.all()[0]
cals = UserCalendar.objects.filter(mailbox=mbox)
if searchquery is not None:
cals = cals.filter(name__icontains=searchquery)
cals = cals.select_related().all()
- with_owner = False
else:
ucals = []
if calfilter is None or calfilter == "user":
@@ -57,15 +55,30 @@ def calendars(request, tplname="radicale/calendar_list.html"):
if searchquery is not None:
scals = scals.filter(name__icontains=searchquery)
cals = chain(ucals, scals)
- with_owner = True
cals = sorted(
cals, key=lambda c: getattr(c, sort_order), reverse=sort_dir == '-'
)
- return render_to_json_response({
- "table": _render_to_string(request, tplname, {
- "calendars": cals, "with_owner": with_owner
- })
- })
+ return get_listing_page(cals, page_id)
+
+
+@login_required
+def calendars_page(request, tplname="radicale/calendars_page.html"):
+ """Return a page of calendars.
+
+ The content depends on current user's role.
+ """
+ page = get_calendar_page(request)
+ if page is None:
+ context = {"length": 0}
+ else:
+ context = {
+ "rows": _render_to_string(request, tplname, {
+ "calendars": page.object_list,
+ "with_owner": request.user.group != "SimpleUsers"
+ }),
+ "page": page.number
+ }
+ return render_to_json_response(context)
@login_required
diff --git a/modoboa/static/js/listing.js b/modoboa/static/js/listing.js
index d887028bc..97a3a85b5 100644
--- a/modoboa/static/js/listing.js
+++ b/modoboa/static/js/listing.js
@@ -31,6 +31,7 @@ Listing.prototype = {
$.proxy(this.load_page, this));
$(document).on("click", this.options.presp_container + " a",
$.proxy(this.load_page, this));
+ $(document).on("click", "a.filter", $.proxy(this.filter_by_tag, this));
if (this.options.with_searchform) {
this.init_searchform();
}
@@ -131,6 +132,7 @@ Listing.prototype = {
update_listing: function(data, with_infinite_scroll) {
var $this = this;
+ $(window).scrollTop(0);
if (with_infinite_scroll || with_infinite_scroll === undefined) {
if ($(window).data("infinite-scroll") !== undefined) {
$(window).infinite_scroll("reset_loaded_pages", data.page);