make more inputs display errors

This commit is contained in:
Jakob Ketterl 2021-03-25 14:48:09 +01:00
parent 383c08ed48
commit 69237c0bb4
2 changed files with 78 additions and 55 deletions

View File

@ -48,15 +48,15 @@ class Input(ABC):
else "",
)
def input_classes(self, error):
def input_classes(self, errors):
classes = ["form-control", "form-control-sm"]
if error:
if errors:
classes.append("is-invalid")
return " ".join(classes)
def input_properties(self, value, error):
def input_properties(self, value, errors):
props = {
"class": self.input_classes(error),
"class": self.input_classes(errors),
"id": self.id,
"name": self.id,
"placeholder": self.label,
@ -72,15 +72,22 @@ class Input(ABC):
def render_errors(self, errors):
return "".join("""<div class="invalid-feedback">{msg}</div>""".format(msg=e) for e in errors)
def render_input(self, value, errors):
return "<input {properties} />{errors}".format(
properties=self.render_input_properties(value, errors), errors=self.render_errors(errors)
def render_input_group(self, value, errors):
return """
{input}
{errors}
""".format(
input=self.render_input(value, errors),
errors=self.render_errors(errors)
)
def render_input(self, value, errors):
return "<input {properties} />".format(properties=self.render_input_properties(value, errors))
def render(self, config, errors):
value = config[self.id] if self.id in config else None
error = errors[self.id] if self.id in errors else []
return self.bootstrap_decorate(self.render_input(self.converter.convert_to_form(value), error))
return self.bootstrap_decorate(self.render_input_group(self.converter.convert_to_form(value), error))
def parse(self, data):
value = self.converter.convert_from_form(data[self.id][0])
@ -115,7 +122,7 @@ class NumberInput(Input):
props["step"] = self.step
return props
def render_input(self, value, errors):
def render_input_group(self, value, errors):
if self.append:
append = """
<div class="input-group-append">
@ -131,10 +138,12 @@ class NumberInput(Input):
<div class="input-group input-group-sm">
{input}
{append}
{errors}
</div>
""".format(
input=super().render_input(value, errors),
input=self.render_input(value, errors),
append=append,
errors=self.render_errors(errors)
)
@ -148,21 +157,26 @@ class FloatInput(NumberInput):
class LocationInput(Input):
def render_input(self, value, errors):
# TODO display errors
def render_input_group(self, value, errors):
return """
<div class="row">
<div class="row {rowclass}">
{inputs}
</div>
{errors}
<div class="row">
<div class="col map-input" data-key="{key}" for="{id}"></div>
</div>
""".format(
id=self.id,
inputs="".join(self.render_sub_input(value, id, errors) for id in ["lat", "lon"]),
rowclass="is-invalid" if errors else "",
inputs=self.render_input(value, errors),
errors=self.render_errors(errors),
key=Config.get()["google_maps_api_key"],
)
def render_input(self, value, errors):
return "".join(self.render_sub_input(value, id, errors) for id in ["lat", "lon"])
def render_sub_input(self, value, id, errors):
return """
<div class="col">
@ -185,13 +199,11 @@ class TextAreaInput(Input):
def render_input(self, value, errors):
return """
<textarea class="{classes}" id="{id}" name="{id}" style="height:200px;" {disabled}>{value}</textarea>
{errors}
""".format(
id=self.id,
classes=self.input_classes(errors),
value=value,
disabled="disabled" if self.disabled else "",
errors=self.render_errors(errors),
)
@ -208,7 +220,6 @@ class CheckboxInput(Input):
<label class="form-check-label" for="{id}">
{checkboxText}
</label>
{errors}
</div>
""".format(
id=self.id,
@ -216,7 +227,6 @@ class CheckboxInput(Input):
checked="checked" if value else "",
disabled="disabled" if self.disabled else "",
checkboxText=self.checkboxText,
errors=self.render_errors(errors)
)
def input_classes(self, error):
@ -247,7 +257,6 @@ class MultiCheckboxInput(Input):
self.options = options
def render_input(self, value, errors):
# TODO display errors
return "".join(self.render_checkbox(o, value, errors) for o in self.options)
def checkbox_id(self, option):
@ -317,13 +326,11 @@ class DropdownInput(Input):
def render_input(self, value, errors):
return """
<select class="{classes}" id="{id}" name="{id}" {disabled}>{options}</select>
{errors}
""".format(
classes=self.input_classes(errors),
id=self.id,
options=self.render_options(value),
disabled="disabled" if self.disabled else "",
errors=self.render_errors(errors),
)
def render_options(self, value):
@ -365,7 +372,7 @@ class ExponentialInput(Input):
props["step"] = "any"
return props
def render_input(self, value, errors):
def render_input_group(self, value, errors):
append = """
<div class="input-group-append">
<select class="input-group-text exponent" name="{id}-exponent" {disabled}>
@ -386,10 +393,12 @@ class ExponentialInput(Input):
<div class="input-group input-group-sm exponential-input">
{input}
{append}
{errors}
</div>
""".format(
input=super().render_input(value, errors),
input=self.render_input(value, errors),
append=append,
errors=self.render_errors(errors)
)
def parse(self, data):

View File

@ -11,23 +11,20 @@ class GainInput(Input):
self.gain_stages = gain_stages
def render_input(self, value, errors):
# TODO display errors
try:
display_value = float(value)
except (ValueError, TypeError):
display_value = "0.0"
return """
<div id="{id}">
<select class="{classes}" id="{id}-select" name="{id}-select" {disabled}>
{options}
</select>
<div class="option manual" style="display: none;">
<input type="number" id="{id}-manual" name="{id}-manual" value="{value}" class="{classes}"
placeholder="Manual device gain" step="any" {disabled}>
</div>
{stageoption}
<select class="{classes}" id="{id}-select" name="{id}-select" {disabled}>
{options}
</select>
<div class="option manual" style="display: none;">
<input type="number" id="{id}-manual" name="{id}-manual" value="{value}" class="{classes}"
placeholder="Manual device gain" step="any" {disabled}>
</div>
{stageoption}
""".format(
id=self.id,
classes=self.input_classes(errors),
@ -38,6 +35,18 @@ class GainInput(Input):
disabled="disabled" if self.disabled else "",
)
def render_input_group(self, value, errors):
return """
<div id="{id}">
{input}
{errors}
</div>
""".format(
id=self.id,
input=self.render_input(value, errors),
errors=self.render_errors(errors)
)
def render_options(self, value):
options = []
if self.has_agc:
@ -342,35 +351,40 @@ class SchedulerInput(Input):
class WaterfallLevelsInput(Input):
def render_input(self, value, errors):
# TODO display errors
def render_input_group(self, value, errors):
return """
<div class="row" id="{id}">
{inputs}
<div class="row {rowclass}" id="{id}">
{input}
</div>
{errors}
""".format(
rowclass="is-invalid" if errors else "",
id=self.id,
inputs="".join(
"""
<div class="col row">
<label class="col-3 col-form-label col-form-label-sm" for="{id}-{name}">{label}</label>
<div class="col-9 input-group input-group-sm">
<input type="number" step="any" class="{classes}" name="{id}-{name}" value="{value}" {disabled}>
<div class="input-group-append">
<span class="input-group-text">dBFS</span>
</div>
input=self.render_input(value, errors),
errors=self.render_errors(errors),
)
def render_input(self, value, errors):
return "".join(
"""
<div class="col row">
<label class="col-3 col-form-label col-form-label-sm" for="{id}-{name}">{label}</label>
<div class="col-9 input-group input-group-sm">
<input type="number" step="any" class="{classes}" name="{id}-{name}" value="{value}" {disabled}>
<div class="input-group-append">
<span class="input-group-text">dBFS</span>
</div>
</div>
""".format(
id=self.id,
name=name,
label=label,
value=value[name] if value and name in value else "0",
classes=self.input_classes(errors),
disabled="disabled" if self.disabled else "",
)
for name, label in [("min", "Minimum"), ("max", "Maximum")]
</div>
""".format(
id=self.id,
name=name,
label=label,
value=value[name] if value and name in value else "0",
classes=self.input_classes(errors),
disabled="disabled" if self.disabled else "",
)
for name, label in [("min", "Minimum"), ("max", "Maximum")]
)
def parse(self, data):