summaryrefslogtreecommitdiffstats
path: root/users/views/settings_system.py
blob: 52ba349a06fc62a62d7fda65357f98f275cecfad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
from functools import partial
from typing import ClassVar, Dict

from django import forms
from django.shortcuts import redirect
from django.utils.decorators import method_decorator
from django.views.generic import FormView, RedirectView

from core.models import Config
from users.decorators import identity_required


@method_decorator(identity_required, name="dispatch")
class SystemSettingsRoot(RedirectView):
    url = "/settings/system/basic/"


@method_decorator(identity_required, name="dispatch")
class SystemSettingsPage(FormView):
    """
    Shows a settings page dynamically created from our settings layout
    at the bottom of the page. Don't add this to a URL directly - subclass!
    """

    template_name = "settings/settings_system.html"
    options_class = Config.SystemOptions
    section: ClassVar[str]
    options: Dict[str, Dict[str, str]]

    def get_form_class(self):
        # Create the fields dict from the config object
        fields = {}
        for key, details in self.options.items():
            config_field = self.options_class.__fields__[key]
            if config_field.type_ is bool:
                form_field = partial(
                    forms.BooleanField,
                    widget=forms.Select(
                        choices=[(True, "Enabled"), (False, "Disabled")]
                    ),
                )
            elif config_field.type_ is str:
                form_field = forms.CharField
            else:
                raise ValueError(f"Cannot render settings type {config_field.type_}")
            fields[key] = form_field(
                label=details["title"],
                help_text=details.get("help_text", ""),
                required=details.get("required", False),
            )
        # Create a form class dynamically (yeah, right?) and return that
        return type("SettingsForm", (forms.Form,), fields)

    def load_config(self):
        return Config.load_system()

    def save_config(self, key, value):
        Config.set_system(key, value)

    def get_initial(self):
        config = self.load_config()
        initial = {}
        for key in self.options.keys():
            initial[key] = getattr(config, key)
        return initial

    def get_context_data(self):
        context = super().get_context_data()
        context["section"] = self.section
        return context

    def form_valid(self, form):
        # Save each key
        for field in form:
            self.save_config(
                field.name,
                form.cleaned_data[field.name],
            )
        return redirect(".")


class BasicPage(SystemSettingsPage):

    section = "basic"

    options = {
        "site_name": {
            "title": "Site Name",
            "help_text": "Shown in the top-left of the page, and titles",
        },
        "highlight_color": {
            "title": "Highlight Color",
            "help_text": "Used for logo background and other highlights",
        },
    }