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 %} - - - - - {% if with_owner %}{% endif %} - - - - - - - {% for cal in calendars %} - - - {% if with_owner %}{% endif %} - - - - - {% endfor %} - -
{% trans "Name" %}{% trans "Owner" %}{% trans "Tags" %}{% trans "Address" %}{% trans "Actions" %}
{% calendar_modify_link cal %}{{ cal.owner }}{% render_tags cal.tags %}{{ cal.url }}{% calendar_actions cal %}
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() { -
+
+ + + + + {% if with_owner %}{% endif %} + + + + + + + + +
{% trans "Name" %}{% trans "Owner" %}{% 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);