Enhance status messages and layout in HostsManagerApp; improve error handling and testing for status updates
This commit is contained in:
parent
02423fe4f2
commit
d477328bea
3 changed files with 56 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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."""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue