mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
wip: radicale extension.
This commit is contained in:
@@ -25,7 +25,7 @@ Admin.prototype = {
|
||||
$(this).val("");
|
||||
}).blur($.proxy(function(e) {
|
||||
var $this = $(e.target);
|
||||
if ($this.val() == "") {
|
||||
if ($this.val() === "") {
|
||||
if (this.navobj.getparam("searchquery")) {
|
||||
$this.val(this.navobj.getparam("searchquery"));
|
||||
} else {
|
||||
@@ -33,7 +33,7 @@ Admin.prototype = {
|
||||
}
|
||||
}
|
||||
}, this));
|
||||
if (this.navobj.getparam("searchquery") != undefined) {
|
||||
if (this.navobj.getparam("searchquery") !== undefined) {
|
||||
$("#searchquery").val(this.navobj.getparam("searchquery"));
|
||||
}
|
||||
|
||||
@@ -52,14 +52,14 @@ Admin.prototype = {
|
||||
|
||||
register_tag_handler: function(name, handler) {
|
||||
this.tag_handlers[name] = handler;
|
||||
if (this.navobj.getparam(name + "filter") != undefined) {
|
||||
if (this.navobj.getparam(name + "filter") !== undefined) {
|
||||
var text = this.navobj.getparam(name + "filter");
|
||||
$("#searchform").parent().after(this.make_tag(text, name));
|
||||
}
|
||||
},
|
||||
|
||||
generic_tag_handler: function(tag, $link) {
|
||||
if (this.navobj.getparam(tag + "filter") == undefined && $link.hasClass(tag)) {
|
||||
if (this.navobj.getparam(tag + "filter") === undefined && $link.hasClass(tag)) {
|
||||
var text = $link.attr("name");
|
||||
this.navobj.setparam(tag + "filter", text).update();
|
||||
$("#searchform").parent().after(this.make_tag(text, tag));
|
||||
@@ -101,7 +101,7 @@ Admin.prototype = {
|
||||
do_search: function(e) {
|
||||
e.preventDefault();
|
||||
var squery = $("#searchquery").val();
|
||||
if (squery != "") {
|
||||
if (squery !== "") {
|
||||
this.navobj.setparam("searchquery", squery);
|
||||
} else {
|
||||
this.navobj.delparam("searchquery");
|
||||
@@ -112,7 +112,7 @@ Admin.prototype = {
|
||||
importform_cb: function() {
|
||||
$(".submit").one('click', function(e) {
|
||||
e.preventDefault();
|
||||
if ($("#id_sourcefile").val() == "") {
|
||||
if ($("#id_sourcefile").val() === "") {
|
||||
return;
|
||||
}
|
||||
$("#import_status").css("display", "block");
|
||||
@@ -305,13 +305,13 @@ Identities.prototype = {
|
||||
},
|
||||
|
||||
grp_tag_handler: function(tag, $link) {
|
||||
if (this.navobj.getparam(tag + "filter") == undefined && $link.hasClass(tag)) {
|
||||
if (this.navobj.getparam(tag + "filter") === undefined && $link.hasClass(tag)) {
|
||||
var text = $link.attr("name");
|
||||
this.navobj
|
||||
.setparam("idtfilter", "account")
|
||||
.setparam(tag + "filter", text)
|
||||
.update();
|
||||
if ($("a[name=idt]").length == 0) {
|
||||
if ($("a[name=idt]").length === 0) {
|
||||
$("#searchform").parent().after(this.make_tag("account", "idt"));
|
||||
}
|
||||
$("#searchform").parent().after(this.make_tag(text, tag));
|
||||
@@ -341,13 +341,13 @@ Identities.prototype = {
|
||||
var $this = $(e.target);
|
||||
var value = $this.val();
|
||||
|
||||
if (value == "SimpleUsers" || value == "") {
|
||||
if (value == "SimpleUsers" || value === "") {
|
||||
this.simpleuser_mode();
|
||||
} else {
|
||||
this.normal_mode();
|
||||
}
|
||||
}, this));
|
||||
if (notrigger != undefined && notrigger) {
|
||||
if (notrigger !== undefined && notrigger) {
|
||||
return;
|
||||
}
|
||||
$("#id_role").trigger("change");
|
||||
@@ -382,7 +382,7 @@ Identities.prototype = {
|
||||
|
||||
mailform_prefill: function() {
|
||||
var $role = $("#id_role");
|
||||
if (!$role.length || $role.val() == "" || $role.val() == "SimpleUsers") {
|
||||
if (!$role.length || $role.val() === "" || $role.val() == "SimpleUsers") {
|
||||
$("#id_email").val($("#id_username").val());
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ugettext_lazy
|
||||
from django import forms
|
||||
from modoboa.lib.parameters import AdminParametersForm, UserParametersForm
|
||||
from modoboa.lib.formutils import SeparatorField, YesNoField, InlineRadioSelect
|
||||
from modoboa.lib.parameters import AdminParametersForm
|
||||
|
||||
|
||||
class ParametersForm(AdminParametersForm):
|
||||
app = "radicale"
|
||||
|
||||
rights_file_path = forms.CharField(
|
||||
label=ugettext_lazy("Radicale rights file path"),
|
||||
initial="/etc/radicale/rights",
|
||||
help_text=ugettext_lazy("Path to file that contains rights definition")
|
||||
)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = ""
|
||||
|
||||
def handle(self, *args, **options):
|
||||
"""Command entry point.
|
||||
"""
|
||||
pass
|
||||
@@ -112,6 +112,8 @@ class SharedCalendar(Calendar):
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class AccessRule(models.Model):
|
||||
"""Access rules to user calendars
|
||||
"""
|
||||
mailbox = models.ForeignKey("admin.Mailbox")
|
||||
read = models.BooleanField(default=False)
|
||||
write = models.BooleanField(default=False)
|
||||
|
||||
@@ -47,8 +47,27 @@ Radicale.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve a list of username from the server.
|
||||
*/
|
||||
get_username_list: function() {
|
||||
var result;
|
||||
|
||||
$.ajax({
|
||||
url: this.options.username_list_url,
|
||||
dataType: "json",
|
||||
async: false
|
||||
}).done(function(data) {
|
||||
result = data;
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
edit_calendar_cb: function() {
|
||||
$("#original_row").dynamicrule();
|
||||
$("#id_username").autocompleter({
|
||||
choices: $.proxy(this.get_username_list, this)
|
||||
});
|
||||
$('.submit').on('click', $.proxy(function(e) {
|
||||
simple_ajax_form_post(e, {
|
||||
formid: "ucal_form",
|
||||
@@ -58,10 +77,10 @@ Radicale.prototype = {
|
||||
}, this));
|
||||
},
|
||||
|
||||
add_shared_calendar_cb: function() {
|
||||
shared_calendar_cb: function() {
|
||||
$('.submit').on('click', $.proxy(function(e) {
|
||||
simple_ajax_form_post(e, {
|
||||
formid: "newsharedcal_form",
|
||||
formid: "sharedcal_form",
|
||||
reload_on_success: false,
|
||||
success_cb: $.proxy(this.reload_listing, this)
|
||||
});
|
||||
|
||||
@@ -5,11 +5,14 @@
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}js/history.js"></script>
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}js/creation_wizard.js"></script>
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}js/listing.js"></script>
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}js/autocompleter.js"></script>
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}radicale/js/jquery.dynamicrule.js"></script>
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}radicale/js/radicale.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
radicale = new Radicale({});
|
||||
radicale = new Radicale({
|
||||
"username_list_url": "{% url 'usernames' %}"
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -33,7 +33,7 @@ def radicale_left_menu(user):
|
||||
"label": _("Add shared calendar"),
|
||||
"img": "icon-plus",
|
||||
"modal": True,
|
||||
"modalcb": "radicale.add_shared_calendar_cb",
|
||||
"modalcb": "radicale.shared_calendar_cb",
|
||||
"url": reverse("new_shared_calendar")},
|
||||
]
|
||||
return render_to_string('common/menulist.html', {
|
||||
@@ -56,6 +56,7 @@ def calendar_modify_link(calendar):
|
||||
linkdef["url"] = reverse(
|
||||
"shared_calendar", args=[calendar.pk]
|
||||
)
|
||||
linkdef["modalcb"] = "radicale.shared_calendar_cb"
|
||||
return render_link(linkdef)
|
||||
|
||||
|
||||
|
||||
@@ -10,4 +10,5 @@ urlpatterns = patterns(
|
||||
name='new_shared_calendar'),
|
||||
url(r'^sharedcalendar/(?P<pk>\d+)/$', 'shared_calendar',
|
||||
name='shared_calendar'),
|
||||
url(r'^usernames/$', 'username_list', name='usernames'),
|
||||
)
|
||||
|
||||
@@ -6,7 +6,7 @@ from itertools import chain
|
||||
from django.shortcuts import render
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.contrib.auth.decorators import (
|
||||
login_required
|
||||
login_required, permission_required, user_passes_test
|
||||
)
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
@@ -29,10 +29,13 @@ def index(request):
|
||||
|
||||
@login_required
|
||||
def calendars(request, tplname="radicale/calendar_list.html"):
|
||||
"""Display calendars list.
|
||||
|
||||
The content depends on current user's role.
|
||||
"""
|
||||
if request.user.group == "SimpleUsers":
|
||||
cals = UserCalendar.objects.filter(
|
||||
mailbox=request.user.mailbox_set.all()[0]
|
||||
)
|
||||
mbox = request.user.mailbox_set.all()[0]
|
||||
cals = UserCalendar.objects.filter(mailbox=mbox).select_related().all()
|
||||
else:
|
||||
cals = chain(
|
||||
UserCalendar.objects.get_for_admin(request.user),
|
||||
@@ -47,6 +50,8 @@ def calendars(request, tplname="radicale/calendar_list.html"):
|
||||
|
||||
@login_required
|
||||
def new_user_calendar(request):
|
||||
"""Calendar creation view.
|
||||
"""
|
||||
return UserCalendarWizard(request).process()
|
||||
|
||||
|
||||
@@ -67,7 +72,10 @@ def user_calendar(request, pk):
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required("radicale.add_sharedcalendar")
|
||||
def new_shared_calendar(request):
|
||||
"""Shared calendar creation view.
|
||||
"""
|
||||
if request.method == "POST":
|
||||
form = SharedCalendarForm(request.POST)
|
||||
if form.is_valid():
|
||||
@@ -79,7 +87,7 @@ def new_shared_calendar(request):
|
||||
form = SharedCalendarForm()
|
||||
return render(request, "common/generic_modal_form.html", {
|
||||
"form": form,
|
||||
"formid": "newsharedcal_form",
|
||||
"formid": "sharedcal_form",
|
||||
"title": _("New shared calendar"),
|
||||
"action": reverse("new_shared_calendar"),
|
||||
"action_classes": "submit",
|
||||
@@ -88,6 +96,11 @@ def new_shared_calendar(request):
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required("radicale.add_sharedcalendar")
|
||||
@user_passes_test(
|
||||
lambda u: u.has_perm("radicale.change_sharedcalendar")
|
||||
or u.has_perm("radicale.delete_sharedcalendar")
|
||||
)
|
||||
def shared_calendar(request, pk):
|
||||
"""
|
||||
"""
|
||||
@@ -100,4 +113,32 @@ def shared_calendar(request, pk):
|
||||
if request.method == "DELETE":
|
||||
scal.delete()
|
||||
return render_to_json_response(_("Calendar removed"))
|
||||
|
||||
if request.method == "POST":
|
||||
form = SharedCalendarForm(request.POST, instance=scal)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
return render_to_json_response(_("Calendar updated"))
|
||||
return render_to_json_response(
|
||||
{"form_errors": form.errors}, status=400
|
||||
)
|
||||
form = SharedCalendarForm(instance=scal)
|
||||
return render(request, "common/generic_modal_form.html", {
|
||||
"form": form,
|
||||
"formid": "sharedcal_form",
|
||||
"title": scal.name,
|
||||
"action": reverse("shared_calendar", args=[scal.pk]),
|
||||
"action_classes": "submit",
|
||||
"action_label": _("Submit")
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
def username_list(request):
|
||||
"""Get the list of username the current user can see.
|
||||
"""
|
||||
from modoboa.extensions.admin.models import Mailbox
|
||||
|
||||
result = []
|
||||
for mb in Mailbox.objects.prefetch_related("user").all():
|
||||
result.append(mb.user.username)
|
||||
return render_to_json_response(result)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
(function($) {
|
||||
"use strict";
|
||||
|
||||
var Autocompleter = function(element, options) {
|
||||
this.initialize(element, options);
|
||||
};
|
||||
@@ -9,13 +11,10 @@
|
||||
initialize: function(element, options) {
|
||||
this.$element = $(element);
|
||||
this.options = $.extend({}, $.fn.autocompleter.defaults, options);
|
||||
this.choices = {
|
||||
value: null
|
||||
};
|
||||
if (typeof this.options.choices === "function") {
|
||||
this.options.choices(this.choices);
|
||||
this.choices = this.options.choices();
|
||||
} else {
|
||||
this.choices.value = this.options.choices();
|
||||
this.choices = this.options.choices;
|
||||
}
|
||||
this.$menu =
|
||||
$('<ul class="dropdown-menu autocompleter" data-toggle="dropdown" />');
|
||||
@@ -54,10 +53,11 @@
|
||||
var exp = new RegExp("^" + pattern);
|
||||
|
||||
this.$menu.empty();
|
||||
$.each(this.choices.value, $.proxy(function(index, value) {
|
||||
$.each(this.choices, $.proxy(function(index, value) {
|
||||
if (exp.test(value)) {
|
||||
this.$menu.append($('<li><a href="#" name="' + value
|
||||
+ '">' + value + '</a></li>'));
|
||||
this.$menu.append(
|
||||
$('<li><a href="#" name="' + value + '">' + value + '</a></li>')
|
||||
);
|
||||
}
|
||||
}, this));
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
'z-index': 1051
|
||||
});
|
||||
if (this.$menu.children().length) {
|
||||
this.$menu.children().first().addClass("active");
|
||||
this.$menu.show();
|
||||
} else {
|
||||
this.$menu.hide();
|
||||
@@ -84,7 +85,7 @@
|
||||
select_entry: function(evt) {
|
||||
if (this.$menu.is(":visible")) {
|
||||
var $link;
|
||||
if (evt != undefined) {
|
||||
if (evt !== undefined) {
|
||||
evt.preventDefault();
|
||||
$link = $(evt.target);
|
||||
} else {
|
||||
@@ -92,7 +93,7 @@
|
||||
}
|
||||
var curvalue = this.$element.val();
|
||||
|
||||
if (curvalue == undefined || curvalue == "") {
|
||||
if (curvalue === undefined || curvalue === "") {
|
||||
if (this.options.empty_choice) {
|
||||
this.options.empty_choice();
|
||||
}
|
||||
@@ -111,19 +112,18 @@
|
||||
},
|
||||
|
||||
activate_next: function() {
|
||||
var active = this.$menu.find('.active').removeClass('active')
|
||||
, next = active.next();
|
||||
var active = this.$menu.find('.active').removeClass('active'),
|
||||
next = active.next();
|
||||
|
||||
if (!next.length) {
|
||||
next = $(this.$menu.find('li').first());
|
||||
}
|
||||
|
||||
next.addClass('active');
|
||||
},
|
||||
|
||||
activate_prev: function() {
|
||||
var active = this.$menu.find('.active').removeClass('active')
|
||||
, prev = active.prev();
|
||||
var active = this.$menu.find('.active').removeClass('active'),
|
||||
prev = active.prev();
|
||||
|
||||
if (!prev.length) {
|
||||
prev = this.$menu.find('li').last();
|
||||
@@ -170,7 +170,7 @@
|
||||
|
||||
default:
|
||||
this.check_user_input();
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -194,4 +194,4 @@
|
||||
'empty_choice' : null
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
})(jQuery);
|
||||
|
||||
Reference in New Issue
Block a user