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

View File

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