rafalp 6 лет назад
Родитель
Сommit
f976b8af3f

+ 20 - 155
misago/conf/admin/forms.py

@@ -1,164 +1,29 @@
 from django import forms
-from django.utils.translation import gettext as _
-from django.utils.translation import ngettext
 
-from ...admin.forms import YesNoSwitch
+from ..cache import clear_settings_cache
 
-__all__ = ["ChangeSettingsForm"]
 
+class ChangeSettingsForm(forms.Form):
+    settings = []
+    files = []
 
-class ValidateChoicesNum:
-    def __init__(self, min_choices=0, max_choices=0):
-        self.min_choices = min_choices
-        self.max_choices = max_choices
+    def save(self, settings_dict):
+        self.save_settings(settings_dict)
+        self.clear_cache()
 
-    def __call__(self, data):
-        data_len = len(data)
-
-        if self.min_choices and self.min_choices > data_len:
-            message = ngettext(
-                "You have to select at least %(choices)d option.",
-                "You have to select at least %(choices)d options.",
-                self.min_choices,
-            )
-            raise forms.ValidationError(message % {"choices": self.min_choices})
-
-        if self.max_choices and self.max_choices < data_len:
-            message = ngettext(
-                "You cannot select more than %(choices)d option.",
-                "You cannot select more than %(choices)d options.",
-                self.max_choices,
-            )
-            raise forms.ValidationError(message % {"choices": self.max_choices})
-
-        return data
-
-
-def basic_kwargs(setting, extra):
-    kwargs = {
-        "label": _(setting.name),
-        "initial": setting.value,
-        "required": extra.get("min_length") or extra.get("min"),
-    }
-
-    if setting.description:
-        kwargs["help_text"] = _(setting.description)
-
-    if setting.form_field == "yesno":
-        # YesNoSwitch is int-base and setting is bool based
-        # this means we need to do quick conversion
-        kwargs["initial"] = 1 if kwargs["initial"] else 0
-
-    if kwargs["required"]:
-        if kwargs.get("help_text"):
-            help_text = {"help_text": kwargs["help_text"]}
-            kwargs["help_text"] = _("Required. %(help_text)s") % help_text
-        else:
-            kwargs["help_text"] = _("This field is required.")
-
-    return kwargs
-
-
-def localise_choices(extra):
-    return [(v, _(l)) for v, l in extra.get("choices", [])]
-
-
-def create_checkbox(setting, kwargs, extra):
-    kwargs["widget"] = forms.CheckboxSelectMultiple()
-    kwargs["choices"] = localise_choices(extra)
-
-    if extra.get("min") or extra.get("max"):
-        kwargs["validators"] = [
-            ValidateChoicesNum(extra.pop("min", 0), extra.pop("max", 0))
-        ]
-
-    if setting.python_type == "int":
-        return forms.TypedMultipleChoiceField(coerce="int", **kwargs)
-    return forms.MultipleChoiceField(**kwargs)
-
-
-def create_choice(setting, kwargs, extra):
-    if setting.form_field == "choice":
-        kwargs["widget"] = forms.RadioSelect()
-    else:
-        kwargs["widget"] = forms.Select()
-
-    kwargs["choices"] = localise_choices(extra)
-
-    if setting.python_type == "int":
-        return forms.TypedChoiceField(coerce="int", **kwargs)
-    return forms.ChoiceField(**kwargs)
-
-
-def create_text(setting, kwargs, extra):
-    kwargs.update(extra)
-    if setting.python_type == "int":
-        return forms.IntegerField(**kwargs)
-    return forms.CharField(**kwargs)
-
-
-def create_textarea(setting, kwargs, extra):
-    widget_kwargs = {}
-    if extra.get("min_length", 0) == 0:
-        kwargs["required"] = False
-    if extra.get("rows", 0):
-        widget_kwargs["attrs"] = {"rows": extra.pop("rows")}
-
-    kwargs["widget"] = forms.Textarea(**widget_kwargs)
-    return forms.CharField(**kwargs)
-
-
-def create_yesno(setting, kwargs, extra):
-    return YesNoSwitch(**kwargs)
-
-
-FIELD_STYPES = {
-    "checkbox": create_checkbox,
-    "radio": create_choice,
-    "select": create_choice,
-    "text": create_text,
-    "textarea": create_textarea,
-    "yesno": create_yesno,
-}
-
-
-def setting_field(FormType, setting):
-    field_factory = FIELD_STYPES[setting.form_field]
-    field_extra = setting.field_extra
-
-    form_field = field_factory(setting, basic_kwargs(setting, field_extra), field_extra)
-
-    FormType = type(
-        "FormType%s" % setting.pk, (FormType,), {setting.setting: form_field}
-    )
-
-    return FormType
-
-
-def ChangeSettingsForm(data=None, group=None):
-    """factory method that builds valid form for settings group"""
-
-    class FormType(forms.Form):
-        pass
-
-    fieldsets = []
-
-    fieldset_legend = None
-    fieldset_form = FormType
-    fieldset_fields = False
-    for setting in group.setting_set.order_by("order"):
-        if setting.legend and setting.legend != fieldset_legend:
-            if fieldset_fields:
-                fieldsets.append(
-                    {"legend": fieldset_legend, "form": fieldset_form(data)}
+    def save_settings(self, settings_dict):
+        for setting in self.settings:
+            setting_obj = settings_dict.get(setting)
+            if not setting_obj:
+                raise ValueError(
+                    "ChangeSettingsForm.save() was called with dict that was missing "
+                    "setting instance for %s" % setting
                 )
-            fieldset_legend = setting.legend
-            fieldset_form = FormType
-            fieldset_fields = False
-        fieldset_fields = True
-        fieldset_form = setting_field(fieldset_form, setting)
+            self.save_setting(setting_obj, self.cleaned_data.get(setting))
 
-    if fieldset_fields:
-        fieldsets.append({"legend": fieldset_legend, "form": fieldset_form(data)})
+    def save_setting(self, setting, value):
+        setting.value = value
+        setting.save()
 
-    return fieldsets
+    def clear_cache(self):
+        clear_settings_cache()

+ 21 - 3
misago/conf/admin/views.py

@@ -1,8 +1,17 @@
+from django.contrib import messages
+from django.shortcuts import redirect
+from django.utils.translation import gettext as _
+
+from ...admin.views import render
 from ...admin.views.generic import AdminView
 from ..models import Setting
 
 
-class ChangeConfigView(AdminView):
+def index(request):
+    return render(request, "misago/admin/conf/index.html")
+
+
+class ChangeSettingsView(AdminView):
     root_link = None  # Unused by change config views
     template_name = None
     form = None
@@ -12,14 +21,20 @@ class ChangeConfigView(AdminView):
 
     def dispatch(self, request, *args, **kwargs):
         settings = self.get_settings(self.form.settings)
-        initial = {key: setting.value for key, setting in settings.items()}
+        initial = self.get_initial_form_data(settings)
         form = self.form(initial=initial)
+        if request.method == "POST":
+            form = self.form(request.POST, request.FILES, initial=initial)
+            if form.is_valid():
+                form.save(settings)
+                messages.success(request, _("Changes in settings have been saved!"))
+                return redirect(request.path_info)
         return self.render(request, {"form": form})
 
     def get_settings(self, settings):
         settings_dict = {}
         for setting in Setting.objects.filter(setting__in=settings):
-            settings_dict[setting.name] = setting
+            settings_dict[setting.setting] = setting
         if len(settings_dict) != len(settings):
             not_found_settings = list(set(settings_dict.keys()) - set(settings))
             raise ValueError(
@@ -27,3 +42,6 @@ class ChangeConfigView(AdminView):
                 ", ".join(not_found_settings)
             )
         return settings_dict
+    
+    def get_initial_form_data(self, settings):
+        return {key: setting.value for key, setting in settings.items()}

+ 3 - 4
misago/core/admin/__init__.py

@@ -1,21 +1,20 @@
 from django.conf.urls import url
 from django.utils.translation import gettext_lazy as _
 
-from .views import ChangeGeneralConfigView
+from .views import ChangeGeneralSettingsView
 
 
 class MisagoAdminExtension:
     def register_urlpatterns(self, urlpatterns):
         urlpatterns.single_pattern(
-            r"^general/", "general", "settings", ChangeGeneralConfigView.as_view()
+            r"^general/", "general", "settings", ChangeGeneralSettingsView.as_view()
         )
 
     def register_navigation_nodes(self, site):
         site.add_node(
             name=_("General"),
             description=_(
-                "Those settings control most basic properties "
-                "of your forum like its name or description."
+                "Change forum details like name, description or footer."
             ),
             parent="settings",
             namespace="general",

+ 47 - 0
misago/core/admin/forms.py

@@ -0,0 +1,47 @@
+from django import forms
+from django.utils.translation import gettext_lazy as _
+
+from ...admin.forms import YesNoSwitch
+from ...conf.admin.forms import ChangeSettingsForm
+
+
+class ChangeGeneralSettingsForm(ChangeSettingsForm):
+    settings = [
+        "forum_name",
+        "forum_index_title",
+        "forum_index_meta_description",
+        "forum_branding_display",
+        "forum_branding_text",
+        "email_footer",
+    ]
+
+    forum_name = forms.CharField(label=_("Forum name"), min_length=2, max_length=255)
+    forum_index_title = forms.CharField(
+        label=_("Title"),
+        help_text=_("You may set a custom title on forum index by typing it here."),
+        max_length=255,
+        required=False,
+    )
+    forum_index_meta_description = forms.CharField(
+        label=_("Meta Description"),
+        help_text=_("Short description of your forum for internet crawlers."),
+        max_length=255,
+        required=False,
+    )
+    forum_branding_display = YesNoSwitch(
+        label=_("Display branding"),
+        help_text=_("Switch branding in forum's navbar."),
+    )
+    forum_branding_text = forms.CharField(
+        label=_("Branding text"),
+        help_text=_("Optional text displayed besides brand image in navbar."),
+        max_length=255,
+        required=False,
+    )
+    email_footer = forms.CharField(
+        label=_("E-mails footer"),
+        help_text=_("Optional short message included at the end of e-mails sent by forum."),
+        max_length=255,
+        required=False,
+    )
+

+ 4 - 18
misago/core/admin/views.py

@@ -1,21 +1,7 @@
-from django import forms
-from django.utils.translation import gettext_lazy as _
+from ...conf.admin.views import ChangeSettingsView
+from .forms import ChangeGeneralSettingsForm
 
-from ...conf.admin.views import ChangeConfigView
 
-
-class ChangeGeneralConfigForm(forms.Form):
-    settings = ["forum_name", "forum_index_title"]
-
-    forum_name = forms.CharField(label=_("Forum name"), min_length=2, max_length=255)
-    forum_index_title = forms.CharField(
-        label=_("Index title"),
-        help_text=_("You may set custon title on forum index by typing it here."),
-        min_length=2,
-        max_length=255,
-    )
-
-
-class ChangeGeneralConfigView(ChangeConfigView):
-    form = ChangeGeneralConfigForm
+class ChangeGeneralSettingsView(ChangeSettingsView):
+    form = ChangeGeneralSettingsForm
     template_name = "misago/admin/core/general_conf.html"

+ 1 - 1
misago/templates/misago/admin/conf/form.html

@@ -9,7 +9,7 @@
 
 {% block view %}
 <div class="card card-admin-form">
-  <form role="form" method="post">
+  <form role="form" method="post" enctype="multipart/form-data">
     {% csrf_token %}
 
     <h5 class="card-header">

+ 35 - 1
misago/templates/misago/admin/core/general_conf.html

@@ -1,6 +1,40 @@
 {% extends "misago/admin/conf/form.html" %}
+{% load i18n misago_admin_form %}
 
 
 {% block form-body %}
-HELLO!
+<div class="form-fieldset">
+  <fieldset>
+    <legend>{% trans "Site details" %}</legend>
+
+    {% form_row form.forum_name %}
+
+  </fieldset>
+</div>
+<div class="form-fieldset">
+  <fieldset>
+    <legend>{% trans "Forum index" %}</legend>
+
+    {% form_row form.forum_index_title %}
+    {% form_row form.forum_index_meta_description %}
+
+  </fieldset>
+</div>
+<div class="form-fieldset">
+  <fieldset>
+    <legend>{% trans "Branding" %}</legend>
+
+    {% form_row form.forum_branding_display %}
+    {% form_row form.forum_branding_text %}
+
+  </fieldset>
+</div>
+<div class="form-fieldset">
+  <fieldset>
+    <legend>{% trans "Forum e-mails" %}</legend>
+
+    {% form_row form.email_footer %}
+
+  </fieldset>
+</div>
 {% endblock form-body %}