Enhance status messages and layout in HostsManagerApp; improve error handling and testing for status updates

This commit is contained in:
Philip Henning 2025-07-30 00:18:48 +02:00
parent 02423fe4f2
commit d477328bea
3 changed files with 56 additions and 20 deletions

View file

@ -58,6 +58,8 @@
- ✅ **Safe file operations**: Atomic file writing with rollback capability
- ✅ **Manager module**: Complete HostsManager class for edit operations
- ✅ **Error handling**: Comprehensive error handling with user feedback
- ✅ **Enhanced read-only error messages**: Clear, informative error messages with ❌ indicator and helpful instructions
- ✅ **Status bar positioning**: Fixed status bar layout to appear above footer for maximum visibility
- ✅ **Keyboard shortcuts**: All edit mode shortcuts implemented and tested
- ✅ **Live testing**: Manual testing confirms all functionality works correctly
- ✅ **Human-readable formatting**: Tab-based column alignment with proper spacing
@ -109,7 +111,8 @@
5. ✅ **Entry reordering**: Move entries up/down with Ctrl+Up/Down keyboard shortcuts
6. ✅ **Manager module**: Complete HostsManager class for all edit operations
7. ✅ **Safe file operations**: Atomic file writing with rollback capability
8. ✅ **Comprehensive testing**: 38 new tests for manager module (135 total tests)
8. ✅ **Enhanced error messages**: Professional read-only mode error messages with clear instructions
9. ✅ **Comprehensive testing**: 38 new tests for manager module (135 total tests)
### Recent Major Accomplishments
- ✅ **Complete Phase 3 implementation**: Full edit mode foundation with permission management

View file

@ -28,7 +28,7 @@ class HostsManagerApp(App):
CSS = """
.hosts-container {
height: 100%;
height: 1fr;
}
.left-pane {
@ -59,6 +59,16 @@ class HostsManagerApp(App):
color: $text;
height: 1;
padding: 0 1;
dock: bottom;
}
.status-error {
background: $error;
color: $text;
height: 1;
padding: 0 1;
text-style: bold;
dock: bottom;
}
/* DataTable styling to match background */
@ -115,6 +125,7 @@ class HostsManagerApp(App):
"""Create the application layout."""
yield Header()
with Vertical():
with Horizontal(classes="hosts-container"):
left_pane = Vertical(classes="left-pane")
left_pane.border_title = "Hosts Entries"
@ -129,6 +140,7 @@ class HostsManagerApp(App):
yield right_pane
yield Static("", classes="status-bar", id="status")
yield Footer()
def on_ready(self) -> None:
@ -367,8 +379,26 @@ class HostsManagerApp(App):
status_widget = self.query_one("#status", Static)
if message:
# Check if this is an error message (starts with ❌)
if message.startswith(""):
# Use error styling for error messages
status_widget.remove_class("status-bar")
status_widget.add_class("status-error")
status_widget.update(message)
# Auto-clear error message after 5 seconds
self.set_timer(5.0, lambda: self.update_status())
else:
# Use normal styling for regular messages
status_widget.remove_class("status-error")
status_widget.add_class("status-bar")
status_widget.update(message)
# Auto-clear regular message after 3 seconds
self.set_timer(3.0, lambda: self.update_status())
else:
# Reset to normal status display
status_widget.remove_class("status-error")
status_widget.add_class("status-bar")
mode = "Edit mode" if self.edit_mode else "Read-only mode"
entry_count = len(self.hosts_file.entries)
active_count = len(self.hosts_file.get_active_entries())
@ -485,7 +515,7 @@ class HostsManagerApp(App):
def action_toggle_entry(self) -> None:
"""Toggle the active state of the selected entry."""
if not self.edit_mode:
self.update_status("Not in edit mode - press 'Ctrl+E' to enable editing")
self.update_status("❌ Cannot toggle entry: Application is in read-only mode. Press 'Ctrl+E' to enable edit mode.")
return
if not self.hosts_file.entries:
@ -513,7 +543,7 @@ class HostsManagerApp(App):
def action_move_entry_up(self) -> None:
"""Move the selected entry up in the list."""
if not self.edit_mode:
self.update_status("Not in edit mode - press 'Ctrl+E' to enable editing")
self.update_status("❌ Cannot move entry: Application is in read-only mode. Press 'Ctrl+E' to enable edit mode.")
return
if not self.hosts_file.entries:
@ -544,7 +574,7 @@ class HostsManagerApp(App):
def action_move_entry_down(self) -> None:
"""Move the selected entry down in the list."""
if not self.edit_mode:
self.update_status("Not in edit mode - press 'Ctrl+E' to enable editing")
self.update_status("❌ Cannot move entry: Application is in read-only mode. Press 'Ctrl+E' to enable edit mode.")
return
if not self.hosts_file.entries:
@ -575,7 +605,7 @@ class HostsManagerApp(App):
def action_save_file(self) -> None:
"""Save the hosts file to disk."""
if not self.edit_mode:
self.update_status("Not in edit mode - no changes to save")
self.update_status("❌ Cannot save: Application is in read-only mode. No changes to save.")
return
success, message = self.manager.save_hosts_file(self.hosts_file)

View file

@ -243,14 +243,17 @@ class TestHostsManagerApp:
app = HostsManagerApp()
# Mock the query_one method
# Mock the query_one method and set_timer to avoid event loop issues
mock_status = Mock()
app.query_one = Mock(return_value=mock_status)
app.set_timer = Mock() # Mock the timer to avoid event loop issues
app.update_status("Custom status message")
# Verify status was updated with custom message
mock_status.update.assert_called_once_with("Custom status message")
# Verify timer was set for auto-clearing
app.set_timer.assert_called_once()
def test_action_reload(self):
"""Test reload action."""