From c34b5eb03df8d4287797704ef48b31192f73d949 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Thu, 24 May 2018 12:45:09 +0200 Subject: Wizards - JSON fields: Manage dynamic list - list existing + dynamic add (refs #4089) --- ishtar_common/widgets.py | 87 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 10 deletions(-) (limited to 'ishtar_common/widgets.py') diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index 442f12b9a..a20d33fc3 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -23,6 +23,7 @@ import logging from django import forms from django.conf import settings +from django.core.exceptions import ValidationError from django.core.files import File from django.core.urlresolvers import reverse, NoReverseMatch from django.db.models import fields @@ -101,18 +102,10 @@ class SelectReadonlyField(forms.ChoiceField): return bool(self.get_q().filter(pk=value).count()) -class Select2Multiple(forms.SelectMultiple): - def __init__(self, attrs=None, choices=(), remote=None, model=None, - new=None, available=None): - super(Select2Multiple, self).__init__(attrs, choices) - self.remote = remote - self.available = available - self.model = model - self.new = new - +class Select2Media(object): @property def media(self): - media = super(Select2Multiple, self).media + media = super(Select2Media, self).media css = { 'all': ('select2/css/select2.css',) } @@ -123,6 +116,80 @@ class Select2Multiple(forms.SelectMultiple): media.add_js(js) return media + +class Select2Dynamic(Select2Media, forms.Select): + """ + Select input using select, allowing dynamic creation. + """ + + def render(self, name, value, attrs=None, choices=()): + choices = choices or getattr(self, 'choices', []) + if value and value not in [key for key, v in choices]: + choices.insert(1, (value, value)) + self.choices = choices + klass = attrs and attrs.get('class') or '' + klass += ' ' if klass else '' + 'js-select2' + if not attrs: + attrs = {} + attrs['class'] = klass + if 'style' not in attrs: + if attrs.get('full-width', None): + attrs['style'] = "width: calc(100% - 60px)" + else: + attrs['style'] = "width: 370px" + options = [ + u"tags: true", + ] + ''' + msg = unicode( + _(u"Are you sure you want to add this term? (the addition is " + u"effective after registration of the element)") + ) + options.append(u"""createTag: function (params) {{ + return confirm("{}"); + }}""".format(msg)) + ''' + if attrs.get('full-width', None): + options.append(u"containerCssClass: 'full-width'") + + html = super(Select2Dynamic, self).render(name, value, attrs) + html += """ + """.format(name, u", ".join(options)) + return mark_safe(html) + + +class Select2DynamicField(forms.ChoiceField): + widget = Select2Dynamic + + def validate(self, value): + """ + Key can be added dynamically. Only check that the character " is not + used. + """ + if value and u'"' in value: + raise ValidationError( + _(u"The character \" is not accepted.") + ) + + def to_python(self, value): + """ + Strip value + """ + return super(Select2DynamicField, self).to_python(value).strip() + + +class Select2Multiple(Select2Media, forms.SelectMultiple): + def __init__(self, attrs=None, choices=(), remote=None, model=None, + new=None, available=None): + super(Select2Multiple, self).__init__(attrs, choices) + self.remote = remote + self.available = available + self.model = model + self.new = new + def get_q(self): q = self.model.objects if self.available: -- cgit v1.2.3