from wtforms import Form from wtforms.fields import Field, StringField, BooleanField, SelectField, PasswordField, FormField from wtforms.validators import Regexp from wtforms.widgets import CheckboxInput from re import search class CheckboxSettingWidget(CheckboxInput): def __init__(self, error_class='has_errors'): super(CheckboxInput, self).__init__() self.error_class = error_class def __call__(self, field, **kwargs): kwargs.setdefault('id', field.id) kwargs.setdefault('name', field.name) kwargs.setdefault('type', 'checkbox') kwargs.setdefault('data-default-method', "mode" if kwargs['name'] in ('AUTOCONF_MODE', 'SWARM_MODE', 'KUBERNETES_MODE') else field.method if hasattr(field, 'method') else 'default') kwargs.setdefault('value', field.global_config_value) kwargs.setdefault('data-pattern', field.regex) kwargs.setdefault('checked', "") return f"""
class="relative mb-7 md:mb-0 z-10 "> {self.input(field, **kwargs)} {self.label(field, {"class": "sr-only", "for": kwargs['name']})}
""" class BWBooleanField(Field): widget = CheckboxSetting() false_values = (False, "false", "") def __init__(self, label=None, validators=None, false_values=None, **kwargs): super().__init__(label, validators, **kwargs) if false_values is not None: self.false_values = false_values def pre_validate(self, form): if isinstance(self.data, bool): self.data = "no" def process_data(self, value): self.data = value def process_formdata(self, valuelist): if not valuelist or valuelist[0] in self.false_values: self.data = False else: self.data = "yes" def _value(self): if self.raw_data: return str(self.raw_data[0]) return "yes" def number_from_setting_name(setting): res = search(r"_([0-9]+)$", setting) if res: return res.group(1) return "0" def settings_to_form(settings): class SettingsForm(Form): pass bw_multiple_forms = {} for setting, data in settings.items(): field_type = None field_data = dict( label=data["label"], validators=[Regexp(data["regex"])], description=data["help"], id=setting, default=data["default"], # widget=None, render_kw={ "custom-attributes-1": "custom-value-1", "custom-attributes-2": "custom-value-2", }, name=setting, # _form=None, # _prefix='', # _translations=None, # _meta=None ) if data["type"] == "text": field_type = StringField elif data["type"] == "check": field_type = BWBooleanField del field_data["default"] if data["default"] == "yes": field_data["default"] = "checked" field_data["render_kw"]["checked"] = "" field_data["false_values"] = ("no") elif data["type"] == "select": field_type = SelectField field_data["choices"] = data["select"] elif data["type"] == "password": field_type = PasswordField else: print(f"unsupported type {data['type']}") continue if "multiple" not in data: setattr( SettingsForm, setting, field_type( **field_data ) ) else: class BWMultipleForm(Form): pass multiple_key = f"{data['multiple']}-{number_from_setting_name(setting)}" if multiple_key not in bw_multiple_forms: bw_multiple_forms[multiple_key] = BWMultipleForm setattr( bw_multiple_forms[multiple_key], setting, field_type( **field_data ) ) for multiple, form in bw_multiple_forms.items(): setattr( SettingsForm, multiple, FormField(form) ) return SettingsForm def compute_form(client_form, request_form, settings): for key, value in request_form.items(): print(key) real_key = key res = search(r"([a-z\-]+\-[0-9]+\-).*_([0-9]+)$", key) if res: real_key = "_".join(key.replace(res.group(1), "").split("_")[:-1]) if real_key in settings and "multiple" in settings[real_key]: setattr( client_form, key, StringField( validators=[Regexp(settings[real_key]["regex"])] ) ) return client_form