Remove search functionality and related modal from the TUI application to streamline the user interface.

This commit is contained in:
Philip Henning 2025-08-14 20:41:12 +02:00
parent 8d884aeb65
commit c84c1aac2a
4 changed files with 2 additions and 286 deletions

View file

@ -460,11 +460,6 @@ class HostsManagerApp(App):
self.push_screen(DeleteConfirmationModal(entry), handle_delete_confirmation) self.push_screen(DeleteConfirmationModal(entry), handle_delete_confirmation)
def action_search(self) -> None:
"""Focus the search bar for filtering entries."""
search_input = self.query_one("#search-input", Input)
search_input.focus()
self.update_status("Use the search bar to filter entries")
def action_quit(self) -> None: def action_quit(self) -> None:
"""Quit the application.""" """Quit the application."""

View file

@ -94,7 +94,7 @@ class HelpModal(ModalScreen):
with Vertical(classes="help-section"): with Vertical(classes="help-section"):
yield Static("Main Commands", classes="help-section-title") yield Static("Main Commands", classes="help-section-title")
yield Static( yield Static(
"[bold]r[/bold] Reload [bold]h[/bold] Help [bold]c[/bold] Config [bold]Ctrl+F[/bold] Search [bold]q[/bold] Quit", "[bold]r[/bold] Reload [bold]h[/bold] Help [bold]c[/bold] Config [bold]q[/bold] Quit",
classes="help-item", classes="help-item",
) )
yield Static( yield Static(
@ -134,7 +134,7 @@ class HelpModal(ModalScreen):
"Special Dialog Commands", classes="help-section-title" "Special Dialog Commands", classes="help-section-title"
) )
yield Static( yield Static(
"[bold]F3[/bold] Search in search dialog [bold]s[/bold] Save changes [bold]d[/bold] Discard changes", "[bold]s[/bold] Save changes [bold]d[/bold] Discard changes",
classes="help-item", classes="help-item",
) )

View file

@ -15,7 +15,6 @@ HOSTS_MANAGER_BINDINGS = [
Binding("i", "sort_by_ip", "Sort by IP"), Binding("i", "sort_by_ip", "Sort by IP"),
Binding("n", "sort_by_hostname", "Sort by Hostname"), Binding("n", "sort_by_hostname", "Sort by Hostname"),
Binding("c", "config", "Config"), Binding("c", "config", "Config"),
Binding("ctrl+f", "search", "Focus Search"),
Binding("ctrl+e", "toggle_edit_mode", "Edit Mode"), Binding("ctrl+e", "toggle_edit_mode", "Edit Mode"),
Binding("a", "add_entry", "Add Entry", show=False), Binding("a", "add_entry", "Add Entry", show=False),
Binding("d", "delete_entry", "Delete Entry", show=False), Binding("d", "delete_entry", "Delete Entry", show=False),

View file

@ -1,278 +0,0 @@
"""
Search modal window for the hosts TUI application.
This module provides a floating search window for finding entries by hostname or IP address.
"""
from textual.app import ComposeResult
from textual.containers import Vertical, Horizontal
from textual.widgets import Static, Button, Input, DataTable, Label
from textual.screen import ModalScreen
from textual.binding import Binding
from ..core.models import HostEntry
class SearchModal(ModalScreen):
"""
Modal screen for searching host entries.
Provides a search interface and displays matching results.
"""
CSS = """
SearchModal {
align: center middle;
}
.search-container {
width: 90;
height: 30;
background: $surface;
border: thick $primary;
padding: 1;
}
.search-title {
text-align: center;
text-style: bold;
color: $primary;
margin-bottom: 1;
}
.search-section {
margin: 1 0;
}
.search-input {
margin: 0 2;
width: 1fr;
}
.results-section {
margin: 1 0;
height: 15;
}
.search-results {
margin: 0 2;
height: 13;
}
.button-row {
margin-top: 1;
align: center middle;
}
.search-button {
margin: 0 1;
min-width: 10;
}
.results-info {
margin: 0 2;
color: $text-muted;
text-style: italic;
}
"""
BINDINGS = [
Binding("escape", "cancel", "Cancel"),
Binding("enter", "select", "Select"),
Binding("f3", "search", "Search"),
]
def __init__(self, entries):
super().__init__()
self.entries = entries
self.search_results = []
def compose(self) -> ComposeResult:
"""Create the search modal layout."""
with Vertical(classes="search-container"):
yield Static("Search Host Entries", classes="search-title")
with Vertical(classes="search-section"):
yield Label("Search term (hostname or IP address):")
yield Input(
placeholder="e.g., example.com or 192.168.1.1",
id="search-input",
classes="search-input",
)
with Vertical(classes="results-section"):
yield Static("Search Results:", classes="results-info")
yield DataTable(
id="search-results-table",
classes="search-results",
show_header=True,
zebra_stripes=True,
)
with Horizontal(classes="button-row"):
yield Button(
"Search",
variant="primary",
id="search-button",
classes="search-button",
)
yield Button(
"Select",
variant="success",
id="select-button",
classes="search-button",
)
yield Button(
"Close",
variant="default",
id="close-button",
classes="search-button",
)
def on_mount(self) -> None:
"""Initialize the search results table and focus search input."""
# Set up the results table
results_table = self.query_one("#search-results-table", DataTable)
results_table.add_column("IP Address", key="ip")
results_table.add_column("Canonical Hostname", key="hostname")
results_table.add_column("Status", key="status")
results_table.add_column("Comment", key="comment")
# Focus search input
search_input = self.query_one("#search-input", Input)
search_input.focus()
# Disable select button initially
select_button = self.query_one("#select-button", Button)
select_button.disabled = True
def on_button_pressed(self, event: Button.Pressed) -> None:
"""Handle button presses."""
if event.button.id == "search-button":
self.action_search()
elif event.button.id == "select-button":
self.action_select()
elif event.button.id == "close-button":
self.action_cancel()
def on_input_submitted(self, event: Input.Submitted) -> None:
"""Handle enter key in search input."""
if event.input.id == "search-input":
self.action_search()
def on_data_table_row_selected(self, event: DataTable.RowSelected) -> None:
"""Handle row selection in results table."""
if event.data_table.id == "search-results-table":
# Enable select button when a row is selected
select_button = self.query_one("#select-button", Button)
select_button.disabled = False
def action_search(self) -> None:
"""Perform search based on input."""
search_input = self.query_one("#search-input", Input)
search_term = search_input.value.strip().lower()
if not search_term:
self._update_results_info("Please enter a search term")
return
# Perform search
self.search_results = self._search_entries(search_term)
# Update results table
results_table = self.query_one("#search-results-table", DataTable)
results_table.clear()
if not self.search_results:
self._update_results_info(f"No entries found matching '{search_term}'")
select_button = self.query_one("#select-button", Button)
select_button.disabled = True
return
# Add results to table
for entry in self.search_results:
status = "✓ Active" if entry.is_active else "✗ Inactive"
comment = entry.comment or ""
results_table.add_row(
entry.ip_address,
entry.canonical_hostname,
status,
comment,
key=str(id(entry)),
)
self._update_results_info(f"Found {len(self.search_results)} matching entries")
def action_select(self) -> None:
"""Select the currently highlighted entry and close modal."""
results_table = self.query_one("#search-results-table", DataTable)
if results_table.cursor_row is None or not self.search_results:
return
# Get the selected entry
cursor_row = results_table.cursor_row
if 0 <= cursor_row < len(self.search_results):
selected_entry = self.search_results[cursor_row]
# Find the original index of this entry
original_index = self._find_entry_index(selected_entry)
self.dismiss(original_index)
else:
self.dismiss(None)
def action_cancel(self) -> None:
"""Cancel search and close modal."""
self.dismiss(None)
def _search_entries(self, search_term: str) -> list[HostEntry]:
"""
Search entries by hostname or IP address.
Args:
search_term: The search term to match against
Returns:
List of matching entries
"""
results = []
for entry in self.entries:
# Search in IP address
if search_term in entry.ip_address.lower():
results.append(entry)
continue
# Search in hostnames
for hostname in entry.hostnames:
if search_term in hostname.lower():
results.append(entry)
break
else:
# Search in comment
if entry.comment and search_term in entry.comment.lower():
results.append(entry)
return results
def _find_entry_index(self, target_entry: HostEntry) -> int:
"""
Find the index of an entry in the original entries list.
Args:
target_entry: Entry to find
Returns:
Index of the entry, or -1 if not found
"""
for i, entry in enumerate(self.entries):
if entry is target_entry:
return i
return -1
def _update_results_info(self, message: str) -> None:
"""Update the results info label."""
try:
results_info = self.query_one(".results-info", Static)
results_info.update(message)
except Exception:
pass