Interface Management initial (2/2)

This commit is contained in:
RFNexus 2025-04-20 09:18:56 -04:00
parent c415345f59
commit dfa7adc21e
5 changed files with 1016 additions and 211 deletions

View file

@ -279,5 +279,260 @@ class FormMultiList(urwid.Pile, FormField):
self.error = "At least one entry is required"
break
self.error_widget.set_text(("error", self.error or ""))
return self.error is None
class FormMultiTable(urwid.Pile, FormField):
def __init__(self, config_key, fields, validation_types=None, transform=None, **kwargs):
self.entries = []
self.fields = fields
self.error_widget = urwid.Text("")
self.error = None
self.validation_types = validation_types or []
header_columns = [('weight', 3, urwid.Text(("list_focus", "Name")))]
for field_key, field_config in self.fields.items():
header_columns.append(('weight', 2, urwid.Text(("list_focus", field_config.get("label", field_key)))))
header_columns.append((4, urwid.Text(("list_focus", ""))))
self.header_row = urwid.Columns(header_columns)
first_entry = self.create_entry_row()
self.entries.append(first_entry)
self.add_button = urwid.Button("+ Add ", on_press=self.add_entry)
add_button_padded = urwid.Padding(self.add_button, left=2, right=2)
pile_widgets = [
self.header_row,
urwid.Divider("-"),
first_entry,
add_button_padded
]
urwid.Pile.__init__(self, pile_widgets)
FormField.__init__(self, config_key, transform)
def create_entry_row(self, name="", values=None):
if values is None:
values = {}
name_edit = urwid.Edit("", name)
columns = [('weight', 3, name_edit)]
field_widgets = {}
for field_key, field_config in self.fields.items():
field_value = values.get(field_key, "")
if field_config.get("type") == "checkbox":
widget = urwid.CheckBox("", state=bool(field_value))
elif field_config.get("type") == "dropdown":
# TODO: dropdown in MultiTable
widget = urwid.Edit("", str(field_value))
else:
widget = urwid.Edit("", str(field_value))
field_widgets[field_key] = widget
columns.append(('weight', 2, widget))
remove_button = urwid.Button("×", on_press=lambda button: self.remove_entry(button, entry_row))
columns.append((4, remove_button))
entry_row = urwid.Columns(columns)
entry_row.name_edit = name_edit
entry_row.field_widgets = field_widgets
return entry_row
def remove_entry(self, button, entry_row):
if len(self.entries) > 1:
self.entries.remove(entry_row)
self.contents = [(w, self.options()) for w in self.get_pile_widgets()]
def add_entry(self, button):
new_entry = self.create_entry_row()
self.entries.append(new_entry)
self.contents = [(w, self.options()) for w in self.get_pile_widgets()]
def get_pile_widgets(self):
return [
self.header_row,
urwid.Divider("-")
] + self.entries + [
urwid.Padding(self.add_button, left=2, right=2)
]
def get_value(self):
values = {}
for entry in self.entries:
name = entry.name_edit.edit_text.strip()
if name:
subinterface = {}
subinterface["interface_enabled"] = True
for field_key, widget in entry.field_widgets.items():
field_config = self.fields.get(field_key, {})
if hasattr(widget, "get_state"):
value = widget.get_state()
elif hasattr(widget, "edit_text"):
value = widget.edit_text.strip()
transform = field_config.get("transform")
if transform and value:
try:
value = transform(value)
except (ValueError, TypeError):
pass
value = ""
if value:
subinterface[field_key] = value
values[name] = subinterface
return self.transform(values) if self.transform else values
def set_value(self, value):
self.entries = []
if not value:
self.entries.append(self.create_entry_row())
else:
for name, config in value.items():
self.entries.append(self.create_entry_row(name=name, values=config))
self.contents = [(w, self.options()) for w in self.get_pile_widgets()]
def validate(self):
values = self.get_value()
self.error = None
for validation in self.validation_types:
if validation == "required" and not values:
self.error = "At least one subinterface is required"
break
self.error_widget.set_text(("error", self.error or ""))
return self.error is None
class FormKeyValuePairs(urwid.Pile, FormField):
def __init__(self, config_key, validation_types=None, transform=None, **kwargs):
self.entries = []
self.error_widget = urwid.Text("")
self.error = None
self.validation_types = validation_types or []
header_columns = [
('weight', 1, urwid.AttrMap(urwid.Text("Parameter Key"), "multitable_header")),
('weight', 1, urwid.AttrMap(urwid.Text("Parameter Value"), "multitable_header")),
(4, urwid.AttrMap(urwid.Text("Action"), "multitable_header"))
]
self.header_row = urwid.AttrMap(urwid.Columns(header_columns), "multitable_header")
first_entry = self.create_entry_row()
self.entries.append(first_entry)
self.add_button = urwid.Button("+ Add Parameter", on_press=self.add_entry)
add_button_padded = urwid.Padding(self.add_button, left=2, right=2)
pile_widgets = [
self.header_row,
urwid.Divider("-"),
first_entry,
add_button_padded
]
urwid.Pile.__init__(self, pile_widgets)
FormField.__init__(self, config_key, transform)
def create_entry_row(self, key="", value=""):
key_edit = urwid.Edit("", key)
value_edit = urwid.Edit("", value)
remove_button = urwid.Button("×", on_press=lambda button: self.remove_entry(button, entry_row))
entry_row = urwid.Columns([
('weight', 1, key_edit),
('weight', 1, value_edit),
(4, remove_button)
])
entry_row.key_edit = key_edit
entry_row.value_edit = value_edit
return entry_row
def remove_entry(self, button, entry_row):
if len(self.entries) > 1:
self.entries.remove(entry_row)
self.contents = [(w, self.options()) for w in self.get_pile_widgets()]
def add_entry(self, button):
new_entry = self.create_entry_row()
self.entries.append(new_entry)
self.contents = [(w, self.options()) for w in self.get_pile_widgets()]
def get_pile_widgets(self):
return [
self.header_row,
urwid.Divider("-")
] + self.entries + [
urwid.Padding(self.add_button, left=2, right=2)
]
def get_value(self):
values = {}
for entry in self.entries:
key = entry.key_edit.edit_text.strip()
value = entry.value_edit.edit_text.strip()
if key:
if value.isdigit():
values[key] = int(value)
elif value.replace('.', '', 1).isdigit() and value.count('.') <= 1:
values[key] = float(value)
elif value.lower() == 'true':
values[key] = True
elif value.lower() == 'false':
values[key] = False
else:
values[key] = value
return self.transform(values) if self.transform else values
def set_value(self, value):
self.entries = []
if not value or not isinstance(value, dict):
self.entries.append(self.create_entry_row())
else:
for key, val in value.items():
self.entries.append(self.create_entry_row(key=key, value=str(val)))
self.contents = [(w, self.options()) for w in self.get_pile_widgets()]
def validate(self):
values = self.get_value()
self.error = None
keys = [entry.key_edit.edit_text.strip() for entry in self.entries
if entry.key_edit.edit_text.strip()]
if len(keys) != len(set(keys)):
self.error = "Duplicate keys are not allowed"
self.error_widget.set_text(("error", self.error))
return False
for validation in self.validation_types:
if validation == "required" and not values:
self.error = "Atleast one parameter is required"
break
self.error_widget.set_text(("error", self.error or ""))
return self.error is None