From 703e85fb1b173f3b68179c40ebec8d201d5f682c Mon Sep 17 00:00:00 2001 From: phg Date: Fri, 4 Sep 2026 18:43:39 +0200 Subject: [PATCH] Order hostnames first in new entry form --- src/hosts/tui/add_entry_modal.py | 36 +++++++++++++------------------- tests/test_add_entry_modal.py | 16 +++++++------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/src/hosts/tui/add_entry_modal.py b/src/hosts/tui/add_entry_modal.py index 21188b0..467c14f 100644 --- a/src/hosts/tui/add_entry_modal.py +++ b/src/hosts/tui/add_entry_modal.py @@ -45,7 +45,17 @@ class AddEntryModal(ModalScreen[HostEntry | None]): ) yield RadioButton("DNS Name Entry", id="dns-entry-radio") - # IP Address Section + # Hostnames Section + with Vertical(classes="default-section") as hostnames: + hostnames.border_title = "Hostnames" + yield Input( + placeholder="e.g., example.com, www.example.com", + id="hostnames-input", + classes="default-input", + ) + yield Static("", id="hostnames-error", classes="validation-error") + + # Address sections follow Hostnames in both visual and Tab order. with Vertical(classes="default-section", id="ip-section") as ip_address: ip_address.border_title = "IP Address" yield Input( @@ -55,7 +65,6 @@ class AddEntryModal(ModalScreen[HostEntry | None]): ) yield Static("", id="ip-error", classes="validation-error") - # DNS Name Section (initially hidden) with Vertical( classes="default-section hidden", id="dns-section" ) as dns_name: @@ -67,16 +76,6 @@ class AddEntryModal(ModalScreen[HostEntry | None]): ) yield Static("", id="dns-error", classes="validation-error") - # Hostnames Section - with Vertical(classes="default-section") as hostnames: - hostnames.border_title = "Hostnames" - yield Input( - placeholder="e.g., example.com, www.example.com", - id="hostnames-input", - classes="default-input", - ) - yield Static("", id="hostnames-error", classes="validation-error") - # Comment Section with Vertical(classes="default-section") as comment: comment.border_title = "Comment (optional)" @@ -112,9 +111,8 @@ class AddEntryModal(ModalScreen[HostEntry | None]): ) def on_mount(self) -> None: - """Focus IP address input when modal opens.""" - ip_input = self.query_one("#entry-type-radio", RadioSet) - ip_input.focus() + """Focus the entry type choice when the modal opens.""" + self.query_one("#entry-type-radio", RadioSet).focus() def on_radio_set_changed(self, event: RadioSet.Changed) -> None: """Handle entry type radio button changes.""" @@ -135,9 +133,7 @@ class AddEntryModal(ModalScreen[HostEntry | None]): if isinstance(active_section, Vertical): active_section.border_title = "Activate Entry" - # Focus IP input - ip_input = self.query_one("#ip-address-input", Input) - ip_input.focus() + self.query_one("#hostnames-input", Input).focus() elif pressed_radio and pressed_radio.id == "dns-entry-radio": # Show DNS section, hide IP section ip_section = self.query_one("#ip-section") @@ -155,9 +151,7 @@ class AddEntryModal(ModalScreen[HostEntry | None]): "Activate Entry (DNS entries activate after resolution)" ) - # Focus DNS input - dns_input = self.query_one("#dns-name-input", Input) - dns_input.focus() + self.query_one("#hostnames-input", Input).focus() def on_button_pressed(self, event: Button.Pressed) -> None: """Handle button presses.""" diff --git a/tests/test_add_entry_modal.py b/tests/test_add_entry_modal.py index 63c901e..313a0e1 100644 --- a/tests/test_add_entry_modal.py +++ b/tests/test_add_entry_modal.py @@ -193,15 +193,15 @@ class TestAddEntryModalRadioButtonLogic: # Mock the query_one method for sections and inputs mock_ip_section = Mock() mock_dns_section = Mock() - mock_ip_input = Mock(spec=Input) + mock_hostname_input = Mock(spec=Input) def mock_query_one(selector, widget_type=None): if selector == "#ip-section": return mock_ip_section elif selector == "#dns-section": return mock_dns_section - elif selector == "#ip-address-input": - return mock_ip_input + elif selector == "#hostnames-input": + return mock_hostname_input return Mock() self.modal.query_one = Mock(side_effect=mock_query_one) @@ -225,22 +225,22 @@ class TestAddEntryModalRadioButtonLogic: # Verify IP section is shown and DNS section is hidden mock_ip_section.remove_class.assert_called_with("hidden") mock_dns_section.add_class.assert_called_with("hidden") - mock_ip_input.focus.assert_called_once() + mock_hostname_input.focus.assert_called_once() def test_radio_button_change_to_dns_entry(self): """Test radio button change to DNS entry mode.""" # Mock the query_one method for sections and inputs mock_ip_section = Mock() mock_dns_section = Mock() - mock_dns_input = Mock(spec=Input) + mock_hostname_input = Mock(spec=Input) def mock_query_one(selector, widget_type=None): if selector == "#ip-section": return mock_ip_section elif selector == "#dns-section": return mock_dns_section - elif selector == "#dns-name-input": - return mock_dns_input + elif selector == "#hostnames-input": + return mock_hostname_input return Mock() self.modal.query_one = Mock(side_effect=mock_query_one) @@ -264,7 +264,7 @@ class TestAddEntryModalRadioButtonLogic: # Verify DNS section is shown and IP section is hidden mock_ip_section.add_class.assert_called_with("hidden") mock_dns_section.remove_class.assert_called_with("hidden") - mock_dns_input.focus.assert_called_once() + mock_hostname_input.focus.assert_called_once() class TestAddEntryModalSaveLogic: