diff --git a/layerindex/forms.py b/layerindex/forms.py index f96659d..d770d42 100644 --- a/layerindex/forms.py +++ b/layerindex/forms.py @@ -8,6 +8,7 @@ from layerindex.models import LayerItem, LayerMaintainer from django import forms from django.core.validators import URLValidator, RegexValidator, email_re from django.forms.models import inlineformset_factory +from widgets import TableCheckboxSelectMultiple import re @@ -40,7 +41,7 @@ LayerMaintainerFormSet = inlineformset_factory(LayerItem, LayerMaintainer, form= class SubmitLayerForm(forms.ModelForm): # Additional form fields - deps = forms.ModelMultipleChoiceField(label='Other layers this layer depends upon', queryset=LayerItem.objects.all(), required=False) + deps = forms.ModelMultipleChoiceField(label='Other layers this layer depends upon', queryset=LayerItem.objects.all(), required=False, widget=TableCheckboxSelectMultiple, initial=[l.pk for l in LayerItem.objects.filter(name='openembedded-core')]) class Meta: model = LayerItem @@ -58,6 +59,16 @@ class SubmitLayerForm(forms.ModelForm): raise forms.ValidationError("Name cannot contain consecutive dashes") return name + def clean_summary(self): + # Compress whitespace and use only spaces + summary = self.cleaned_data['summary'].strip() + summary = re.sub('\s+', ' ', summary) + return summary + + def clean_description(self): + description = self.cleaned_data['description'].strip() + return description + def clean_vcs_url(self): url = self.cleaned_data['vcs_url'].strip() val = RegexValidator(regex=r'[a-z]+://.*', message='Please enter a valid repository URL, e.g. git://server.name/path') diff --git a/layerindex/static/css/additional.css b/layerindex/static/css/additional.css index 4b96cd7..2a52942 100644 --- a/layerindex/static/css/additional.css +++ b/layerindex/static/css/additional.css @@ -54,3 +54,9 @@ textarea { h1 .btn { font-weight: normal; } + +.scrolling { +height: auto; +max-height: 120px; +overflow: auto; +} \ No newline at end of file diff --git a/layerindex/submitlayer.html b/layerindex/submitlayer.html index 11ccacb..7368fb6 100644 --- a/layerindex/submitlayer.html +++ b/layerindex/submitlayer.html @@ -28,7 +28,13 @@
{{ field.errors }} {{ field.label_tag }} - {{ field }} + {% if field.name = 'deps' %} +
+ {{ field }} +
+ {% else %} + {{ field }} + {% endif %} {{ field.help_text }}
{% endfor %} diff --git a/layerindex/widgets.py b/layerindex/widgets.py new file mode 100644 index 0000000..d0bd6d9 --- /dev/null +++ b/layerindex/widgets.py @@ -0,0 +1,69 @@ +# Based on parts of forms/widgets.py from Django +# +# Copyright (c) Django Software Foundation and individual contributors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of Django nor the names of its contributors may be used +# to endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +import django.forms +from django.forms.widgets import CheckboxInput +from django.utils.encoding import force_unicode +from django.utils.html import escape, conditional_escape +from django.utils.safestring import mark_safe +from itertools import chain + +# Reworked CheckboxSelectMultiple +class TableCheckboxSelectMultiple(django.forms.SelectMultiple): + def render(self, name, value, attrs=None, choices=()): + if value is None: value = [] + has_id = attrs and 'id' in attrs + final_attrs = self.build_attrs(attrs, name=name) + output = [u''] + # Normalize to strings + str_values = set([force_unicode(v) for v in value]) + for i, (option_value, option_label) in enumerate(chain(self.choices, choices)): + # If an ID attribute was given, add a numeric index as a suffix, + # so that the checkboxes don't all have the same ID attribute. + if has_id: + final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i)) + label_for = u' for="%s"' % final_attrs['id'] + else: + label_for = '' + + cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values) + option_value = force_unicode(option_value) + rendered_cb = cb.render(name, option_value) + option_label = conditional_escape(force_unicode(option_label)) + output.append(u'' % (rendered_cb, label_for, option_label)) + output.append(u'
%s%s
') + return mark_safe(u'\n'.join(output)) + + def id_for_label(self, id_): + # See the comment for RadioSelect.id_for_label() + if id_: + id_ += '_0' + return id_