diff --git a/misago/__init__.py b/misago/__init__.py
index 262ae39f9d..e584347d0d 100644
--- a/misago/__init__.py
+++ b/misago/__init__.py
@@ -1,5 +1,5 @@
from .plugins.pluginlist import load_plugin_list_if_exists
-__version__ = "0.39.0"
-__released__ = False
+__version__ = "0.38.1"
+__released__ = True
diff --git a/misago/admin/forms.py b/misago/admin/forms.py
index 486d83cc38..8f108af775 100644
--- a/misago/admin/forms.py
+++ b/misago/admin/forms.py
@@ -2,9 +2,7 @@
from django.forms import (
CharField,
- ClearableFileInput,
DateTimeField,
- FileField,
RadioSelect,
TypedChoiceField,
ValidationError,
diff --git a/misago/admin/templatetags/misago_admin_form.py b/misago/admin/templatetags/misago_admin_form.py
index 0032774db9..8802a7b5ae 100644
--- a/misago/admin/templatetags/misago_admin_form.py
+++ b/misago/admin/templatetags/misago_admin_form.py
@@ -88,10 +88,12 @@ def is_select_field(field):
return isinstance(field.field.widget, forms.Select)
+MULTIPLE_CHOICE_WIDGETS = (forms.CheckboxSelectMultiple, forms.SelectMultiple)
+
+
@register.filter
def is_multiple_choice_field(field):
- multichoice_widgets = (forms.CheckboxSelectMultiple, forms.SelectMultiple)
- return isinstance(field.field.widget, multichoice_widgets)
+ return isinstance(field.field.widget, MULTIPLE_CHOICE_WIDGETS)
@register.filter
diff --git a/misago/admin/tests/__snapshots__/test_admin_form_templatetags.ambr b/misago/admin/tests/__snapshots__/test_admin_form_templatetags.ambr
new file mode 100644
index 0000000000..33d4991b5a
--- /dev/null
+++ b/misago/admin/tests/__snapshots__/test_admin_form_templatetags.ambr
@@ -0,0 +1,349 @@
+# serializer version: 1
+# name: test_image_row_with_value_renders_help_text
+ '''
+
+ '''
+# ---
+# name: test_image_row_with_value_renders_image_preview
+ '''
+
+ '''
+# ---
+# name: test_image_row_with_value_renders_input
+ '''
+
+ '''
+# ---
+# name: test_image_row_with_value_renders_input_and_field_css_class
+ '''
+
+ '''
+# ---
+# name: test_image_row_with_value_renders_input_and_label_and_field_css_classes
+ '''
+
+ '''
+# ---
+# name: test_image_row_with_value_renders_input_and_label_css_class
+ '''
+
+ '''
+# ---
+# name: test_image_row_with_value_renders_label
+ '''
+
+ '''
+# ---
+# name: test_row_with_checkbox_select_field_is_rendered
+ '''
+
+ '''
+# ---
+# name: test_row_with_radio_select_field_is_rendered
+ '''
+
+ '''
+# ---
+# name: test_row_with_select_field_is_rendered
+ '''
+
+ '''
+# ---
+# name: test_row_with_select_multiple_field_is_rendered
+ '''
+
+ '''
+# ---
+# name: test_row_with_textarea_field_is_rendered
+ '''
+
+ '''
+# ---
+# name: test_row_with_yes_no_field_is_rendered
+ '''
+
+ '''
+# ---
diff --git a/misago/admin/tests/test_admin_form_templatetags.py b/misago/admin/tests/test_admin_form_templatetags.py
index 01f29a285d..f62a659246 100644
--- a/misago/admin/tests/test_admin_form_templatetags.py
+++ b/misago/admin/tests/test_admin_form_templatetags.py
@@ -27,6 +27,11 @@ class Form(forms.Form):
select_field = forms.ChoiceField(
label="Choice", choices=(("y", "Yes"), ("n", "No"))
)
+ ratio_select_field = forms.ChoiceField(
+ label="Choice",
+ choices=(("y", "Yes"), ("n", "No")),
+ widget=forms.RadioSelect,
+ )
checkbox_select_field = forms.MultipleChoiceField(
label="Color",
choices=(("r", "Red"), ("g", "Green"), ("b", "Blue")),
@@ -127,6 +132,9 @@ def test_image_field_help_text_is_rendered():
class TestImage:
url = "test-image.png"
+ def __str__(self):
+ return self.url
+
def render_image(template_str):
base_template = "{%% load misago_admin_form %%} %s"
@@ -135,43 +143,48 @@ def render_image(template_str):
return template.render(context).strip()
-def test_image_row_with_value_renders_label():
+def test_image_row_with_value_renders_label(snapshot):
html = render_image("{% form_image_row form.image_field %}")
- assert "Image!" in html
+ assert snapshot == html
-def test_image_row_with_value_renders_help_text():
+def test_image_row_with_value_renders_help_text(snapshot):
html = render_image("{% form_image_row form.image_field %}")
- assert "I am a help text." in html
+ assert snapshot == html
-def test_image_row_with_value_renders_image_preview():
+def test_image_row_with_value_renders_image_preview(snapshot):
html = render_image("{% form_image_row form.image_field %}")
assert ('src="%s"' % TestImage.url) in html
+ assert snapshot == html
-def test_image_row_with_value_renders_input():
+def test_image_row_with_value_renders_input(snapshot):
html = render_image("{% form_image_row form.image_field %}")
assert "id_image_field" in html
+ assert snapshot == html
-def test_image_row_with_value_renders_input_and_label_css_class():
+def test_image_row_with_value_renders_input_and_label_css_class(snapshot):
html = render_image('{% form_image_row form.image_field label_class="col-md-3" %}')
assert "id_image_field" in html
assert "col-md-3" in html
+ assert snapshot == html
-def test_image_row_with_value_renders_input_and_field_css_class():
+def test_image_row_with_value_renders_input_and_field_css_class(snapshot):
html = render_image('{% form_image_row form.image_field field_class="col-md-9" %}')
assert "id_image_field" in html
assert "col-md-9" in html
+ assert snapshot == html
-def test_image_row_with_value_renders_input_and_label_and_field_css_classes():
+def test_image_row_with_value_renders_input_and_label_and_field_css_classes(snapshot):
html = render_image('{% form_image_row form.image_field "col-md-3" "col-md-9" %}')
assert "id_image_field" in html
assert "col-md-3" in html
assert "col-md-9" in html
+ assert snapshot == html
def test_image_tag_without_field_raises_exception():
@@ -180,13 +193,18 @@ def test_image_tag_without_field_raises_exception():
def test_for_field_with_radio_select_widget_filter_returns_true(form):
- assert is_radio_select_field(form["yesno_field"])
+ assert is_radio_select_field(form["ratio_select_field"])
def test_for_field_without_radio_select_widget_filter_returns_false(form):
assert not is_radio_select_field(form["text_field"])
+def test_row_with_radio_select_field_is_rendered(snapshot):
+ html = render_image("{% form_image_row form.ratio_select_field %}")
+ assert snapshot == html
+
+
def test_for_field_with_select_widget_filter_returns_true(form):
assert is_select_field(form["select_field"])
@@ -195,6 +213,11 @@ def teste_for_field_without_select_widget_filter_returns_false(form):
assert not is_select_field(form["text_field"])
+def test_row_with_select_field_is_rendered(snapshot):
+ html = render_image("{% form_image_row form.select_field %}")
+ assert snapshot == html
+
+
def test_for_field_with_checkbox_select_widget_filter_returns_true(form):
assert is_multiple_choice_field(form["checkbox_select_field"])
@@ -203,6 +226,11 @@ def test_for_field_without_checkbox_select_widget_filter_returns_false(form):
assert not is_multiple_choice_field(form["text_field"])
+def test_row_with_checkbox_select_field_is_rendered(snapshot):
+ html = render_image("{% form_image_row form.checkbox_select_field %}")
+ assert snapshot == html
+
+
def test_for_field_with_multiple_select_widget_filter_returns_true(form):
assert is_multiple_choice_field(form["multiple_select_field"])
@@ -211,6 +239,11 @@ def test_for_field_without_multiple_select_widget_filter_returns_false(form):
assert not is_multiple_choice_field(form["text_field"])
+def test_row_with_select_multiple_field_is_rendered(snapshot):
+ html = render_image("{% form_image_row form.multiple_select_field %}")
+ assert snapshot == html
+
+
def test_for_field_with_textarea_widget_filter_returns_true(form):
assert is_textarea_field(form["textarea_field"])
@@ -219,6 +252,11 @@ def test_for_field_without_textarea_widget_filter_returns_false(form):
assert not is_textarea_field(form["text_field"])
+def test_row_with_textarea_field_is_rendered(snapshot):
+ html = render_image("{% form_image_row form.textarea_field %}")
+ assert snapshot == html
+
+
def test_for_yes_no_field_filter_returns_true(form):
assert is_yesno_switch_field(form["yesno_field"])
@@ -227,6 +265,11 @@ def test_for_non_yes_no_field_filter_returns_false(form):
assert not is_yesno_switch_field(form["text_field"])
+def test_row_with_yes_no_field_is_rendered(snapshot):
+ html = render_image("{% form_image_row form.yesno_field %}")
+ assert snapshot == html
+
+
def test_specified_class_name_is_rendered():
result = render_attrs({"attrs": {}}, class_name="form-control")
assert result == 'class="form-control"'
diff --git a/misago/templates/misago/admin/form/input.html b/misago/templates/misago/admin/form/input.html
index 2fc7268ac3..2397e3bea6 100644
--- a/misago/templates/misago/admin/form/input.html
+++ b/misago/templates/misago/admin/form/input.html
@@ -1,10 +1,10 @@
{% load misago_admin_form %}
-{% if field|is_radio_select_field %}
+{% if field|is_multiple_choice_field %}
+ {% include "misago/admin/form/multiple_choice.html" %}
+{% elif field|is_radio_select_field %}
{% include "misago/admin/form/radio_select.html" %}
{% elif field|is_select_field %}
{% include "misago/admin/form/select.html" %}
-{% elif field|is_multiple_choice_field %}
- {% include "misago/admin/form/multiple_choice.html" %}
{% elif field|is_textarea_field %}
{% else %}