Refactor hosts TUI application: remove main entry point, enhance modal styles, and unify button classes
- Deleted the main entry point file for the hosts application. - Updated the Add Entry Modal to improve section titles and input styles. - Refactored HostsManagerApp layout to use common pane styles for left and right sections. - Enhanced Config, Delete Confirmation, and Help modals with consistent button labels and styles. - Improved Password Modal layout and removed unnecessary parameters. - Consolidated common CSS styles for buttons, inputs, and sections to ensure consistent styling across the application.
This commit is contained in:
		
							parent
							
								
									54a2e00e29
								
							
						
					
					
						commit
						502bbd87f3
					
				
					 10 changed files with 155 additions and 1218 deletions
				
			
		
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -1,17 +0,0 @@
 | 
			
		|||
"""
 | 
			
		||||
Main entry point for the hosts TUI application.
 | 
			
		||||
 | 
			
		||||
This module contains the main application entry point function.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from .tui.app import HostsManagerApp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    """Main entry point for the hosts application."""
 | 
			
		||||
    app = HostsManagerApp()
 | 
			
		||||
    app.run()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    main()
 | 
			
		||||
| 
						 | 
				
			
			@ -36,47 +36,48 @@ class AddEntryModal(ModalScreen):
 | 
			
		|||
        with Vertical(classes="add-entry-container"):
 | 
			
		||||
            yield Static("Add New Host Entry", classes="add-entry-title")
 | 
			
		||||
 | 
			
		||||
            with Vertical(classes="add-entry-section"):
 | 
			
		||||
                yield Label("IP Address:")
 | 
			
		||||
            with Vertical(classes="default-section") as ip_address:
 | 
			
		||||
                ip_address.border_title = "IP Address"
 | 
			
		||||
                yield Input(
 | 
			
		||||
                    placeholder="e.g., 192.168.1.1 or 2001:db8::1",
 | 
			
		||||
                    id="ip-address-input",
 | 
			
		||||
                    classes="add-entry-input",
 | 
			
		||||
                    classes="default-input",
 | 
			
		||||
                )
 | 
			
		||||
                yield Static("", id="ip-error", classes="validation-error")
 | 
			
		||||
 | 
			
		||||
            with Vertical(classes="add-entry-section"):
 | 
			
		||||
                yield Label("Hostnames (comma-separated):")
 | 
			
		||||
            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="add-entry-input",
 | 
			
		||||
                    classes="default-input",
 | 
			
		||||
                )
 | 
			
		||||
                yield Static("", id="hostnames-error", classes="validation-error")
 | 
			
		||||
 | 
			
		||||
            with Vertical(classes="add-entry-section"):
 | 
			
		||||
                yield Label("Comment (optional):")
 | 
			
		||||
            with Vertical(classes="default-section") as comment:
 | 
			
		||||
                comment.border_title = "Comment (optional)"
 | 
			
		||||
                yield Input(
 | 
			
		||||
                    placeholder="e.g., Development server",
 | 
			
		||||
                    id="comment-input",
 | 
			
		||||
                    classes="add-entry-input",
 | 
			
		||||
                    classes="default-input",
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            with Vertical(classes="add-entry-section"):
 | 
			
		||||
                yield Checkbox("Active (enabled)", value=True, id="active-checkbox")
 | 
			
		||||
            with Vertical(classes="default-section") as active:
 | 
			
		||||
                active.border_title = "Activate Entry"
 | 
			
		||||
                yield Checkbox("Active", value=True, id="active-checkbox", classes="default-checkbox")
 | 
			
		||||
 | 
			
		||||
            with Horizontal(classes="button-row"):
 | 
			
		||||
                yield Button(
 | 
			
		||||
                    "Add Entry",
 | 
			
		||||
                    "Add Entry (CTRL+S)",
 | 
			
		||||
                    variant="primary",
 | 
			
		||||
                    id="add-button",
 | 
			
		||||
                    classes="add-entry-button",
 | 
			
		||||
                    classes="default-button",
 | 
			
		||||
                )
 | 
			
		||||
                yield Button(
 | 
			
		||||
                    "Cancel",
 | 
			
		||||
                    "Cancel (ESC)",
 | 
			
		||||
                    variant="default",
 | 
			
		||||
                    id="cancel-button",
 | 
			
		||||
                    classes="add-entry-button",
 | 
			
		||||
                    classes="default-button",
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
    def on_mount(self) -> None:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,12 +82,12 @@ class HostsManagerApp(App):
 | 
			
		|||
 | 
			
		||||
        with Horizontal(classes="hosts-container"):
 | 
			
		||||
            # Left pane - entries table
 | 
			
		||||
            with Vertical(classes="left-pane") as left_pane:
 | 
			
		||||
            with Vertical(classes="common-pane left-pane") as left_pane:
 | 
			
		||||
                left_pane.border_title = "Host Entries"
 | 
			
		||||
                yield DataTable(id="entries-table")
 | 
			
		||||
 | 
			
		||||
            # Right pane - entry details or edit form
 | 
			
		||||
            with Vertical(classes="right-pane") as right_pane:
 | 
			
		||||
            with Vertical(classes="common-pane right-pane") as right_pane:
 | 
			
		||||
                right_pane.border_title = "Entry Details"
 | 
			
		||||
                yield DataTable(
 | 
			
		||||
                    id="entry-details-table",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,10 +51,10 @@ class ConfigModal(ModalScreen):
 | 
			
		|||
                    "Save", variant="primary", id="save-button", classes="config-button"
 | 
			
		||||
                )
 | 
			
		||||
                yield Button(
 | 
			
		||||
                    "Cancel",
 | 
			
		||||
                    "Cancel (ESC)",
 | 
			
		||||
                    variant="default",
 | 
			
		||||
                    id="cancel-button",
 | 
			
		||||
                    classes="config-button",
 | 
			
		||||
                    classes="default-button",
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
    def on_button_pressed(self, event: Button.Pressed) -> None:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,13 +55,13 @@ class DeleteConfirmationModal(ModalScreen):
 | 
			
		|||
                    "Delete",
 | 
			
		||||
                    variant="error",
 | 
			
		||||
                    id="delete-button",
 | 
			
		||||
                    classes="delete-button",
 | 
			
		||||
                    classes="default-button",
 | 
			
		||||
                )
 | 
			
		||||
                yield Button(
 | 
			
		||||
                    "Cancel",
 | 
			
		||||
                    "Cancel (ESC)",
 | 
			
		||||
                    variant="default",
 | 
			
		||||
                    id="cancel-button",
 | 
			
		||||
                    classes="delete-button",
 | 
			
		||||
                    classes="default-button",
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
    def on_mount(self) -> None:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,7 +32,6 @@ class HelpModal(ModalScreen):
 | 
			
		|||
        with Vertical(classes="help-container"):
 | 
			
		||||
            yield Static("/etc/hosts Manager - Help", classes="help-title")
 | 
			
		||||
 | 
			
		||||
            with ScrollableContainer(classes="help-content"):
 | 
			
		||||
            # Navigation section
 | 
			
		||||
            with Vertical(classes="help-section"):
 | 
			
		||||
                yield Static("Navigation", classes="help-section-title")
 | 
			
		||||
| 
						 | 
				
			
			@ -110,7 +109,7 @@ class HelpModal(ModalScreen):
 | 
			
		|||
 | 
			
		||||
            with Horizontal(classes="button-row"):
 | 
			
		||||
                yield Button(
 | 
			
		||||
                    "Close", variant="primary", id="close-button", classes="help-button"
 | 
			
		||||
                    "Close", variant="primary", id="close-button", classes="default-button"
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
    def on_mount(self) -> None:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ from textual.binding import Binding
 | 
			
		|||
HOSTS_MANAGER_BINDINGS = [
 | 
			
		||||
    Binding("q", "quit", "Quit"),
 | 
			
		||||
    Binding("r", "reload", "Reload"),
 | 
			
		||||
    Binding("h", "help", "Help"),
 | 
			
		||||
    Binding("question_mark", "help", "Help", key_display="?"),
 | 
			
		||||
    Binding("i", "sort_by_ip", "Sort by IP"),
 | 
			
		||||
    Binding("n", "sort_by_hostname", "Sort by Hostname"),
 | 
			
		||||
    Binding("c", "config", "Config"),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,38 +27,27 @@ class PasswordModal(ModalScreen):
 | 
			
		|||
        Binding("enter", "submit", "Submit"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    def __init__(self, message: str = "Enter your password for sudo access:"):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.message = message
 | 
			
		||||
        self.error_message = ""
 | 
			
		||||
 | 
			
		||||
    def compose(self) -> ComposeResult:
 | 
			
		||||
        """Create the password modal layout."""
 | 
			
		||||
        with Vertical(classes="password-container"):
 | 
			
		||||
            yield Static("Sudo Authentication", classes="password-title")
 | 
			
		||||
            yield Static(self.message, classes="password-message")
 | 
			
		||||
 | 
			
		||||
            with Vertical(classes="default-section") as password_input:
 | 
			
		||||
                password_input.border_title = "Enter sudo Password"
 | 
			
		||||
                yield Input(
 | 
			
		||||
                    placeholder="Password",
 | 
			
		||||
                    password=True,
 | 
			
		||||
                    id="password-input",
 | 
			
		||||
                classes="password-input",
 | 
			
		||||
                    classes="default-input",
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            # Error message placeholder (initially empty)
 | 
			
		||||
            yield Static("", id="error-message", classes="error-message")
 | 
			
		||||
 | 
			
		||||
            with Horizontal(classes="button-row"):
 | 
			
		||||
                yield Button(
 | 
			
		||||
                    "OK", variant="primary", id="ok-button", classes="password-button"
 | 
			
		||||
                )
 | 
			
		||||
                yield Button(
 | 
			
		||||
                    "Cancel",
 | 
			
		||||
                    variant="default",
 | 
			
		||||
                    id="cancel-button",
 | 
			
		||||
                    classes="password-button",
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
    def on_mount(self) -> None:
 | 
			
		||||
        """Focus the password input when modal opens."""
 | 
			
		||||
        password_input = self.query_one("#password-input", Input)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,8 +5,48 @@ This module contains all CSS definitions for consistent styling
 | 
			
		|||
across the application.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
# Common CSS classes shared across components
 | 
			
		||||
COMMON_CSS = """
 | 
			
		||||
.default-button {
 | 
			
		||||
    margin: 0 1;
 | 
			
		||||
    min-width: 10;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.default-checkbox {
 | 
			
		||||
    height: 1fr;
 | 
			
		||||
    margin: 0 2;
 | 
			
		||||
    border: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.default-input {
 | 
			
		||||
    height: 1fr;
 | 
			
		||||
    width: 1fr;
 | 
			
		||||
    margin: 0 2;
 | 
			
		||||
    border: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.default-section {
 | 
			
		||||
    border: round $primary;
 | 
			
		||||
    height: 3;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
    margin: 1 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button-row {
 | 
			
		||||
    margin-top: 2;
 | 
			
		||||
    height: 3;
 | 
			
		||||
    align: center middle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hidden {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
# CSS styles for the hosts manager application
 | 
			
		||||
HOSTS_MANAGER_CSS = """
 | 
			
		||||
HOSTS_MANAGER_CSS = (
 | 
			
		||||
    COMMON_CSS
 | 
			
		||||
    +"""
 | 
			
		||||
.search-container {
 | 
			
		||||
    border: round $primary;
 | 
			
		||||
    height: 3;
 | 
			
		||||
| 
						 | 
				
			
			@ -16,28 +56,27 @@ HOSTS_MANAGER_CSS = """
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
.search-input {
 | 
			
		||||
    height: 1fr;
 | 
			
		||||
    width: 1fr;
 | 
			
		||||
    height: 1;
 | 
			
		||||
    border: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hosts-container {
 | 
			
		||||
    # height: 1fr;
 | 
			
		||||
    height: 1fr;
 | 
			
		||||
    margin-top: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.common-pane {
 | 
			
		||||
    border: round $primary;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.left-pane {
 | 
			
		||||
    width: 60%;
 | 
			
		||||
    border: round $primary;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    padding: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.right-pane {
 | 
			
		||||
    width: 40%;
 | 
			
		||||
    border: round $primary;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    padding: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.entry-active {
 | 
			
		||||
| 
						 | 
				
			
			@ -128,18 +167,7 @@ Header.-tall {
 | 
			
		|||
    height: 1; /* Fix tall header also to height 1 */
 | 
			
		||||
}
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
# Common CSS classes shared across components
 | 
			
		||||
COMMON_CSS = """
 | 
			
		||||
.button-row {
 | 
			
		||||
    margin-top: 1;
 | 
			
		||||
    align: center middle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hidden {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
"""
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Help Modal CSS
 | 
			
		||||
HELP_MODAL_CSS = (
 | 
			
		||||
| 
						 | 
				
			
			@ -187,10 +215,6 @@ HelpModal {
 | 
			
		|||
    text-style: bold;
 | 
			
		||||
    color: $accent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.help-button {
 | 
			
		||||
    min-width: 10;
 | 
			
		||||
}
 | 
			
		||||
"""
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -204,7 +228,7 @@ AddEntryModal {
 | 
			
		|||
 | 
			
		||||
.add-entry-container {
 | 
			
		||||
    width: 80;
 | 
			
		||||
    height: 25;
 | 
			
		||||
    height: 26;
 | 
			
		||||
    background: $surface;
 | 
			
		||||
    border: thick $primary;
 | 
			
		||||
    padding: 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -217,25 +241,6 @@ AddEntryModal {
 | 
			
		|||
    margin-bottom: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.add-entry-section {
 | 
			
		||||
    margin: 1 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.add-entry-input {
 | 
			
		||||
    margin: 0 2;
 | 
			
		||||
    width: 1fr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button-row {
 | 
			
		||||
    margin-top: 2;
 | 
			
		||||
    align: center middle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.add-entry-button {
 | 
			
		||||
    margin: 0 1;
 | 
			
		||||
    min-width: 10;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.validation-error {
 | 
			
		||||
    color: $error;
 | 
			
		||||
    margin: 0 2;
 | 
			
		||||
| 
						 | 
				
			
			@ -254,7 +259,7 @@ DeleteConfirmationModal {
 | 
			
		|||
 | 
			
		||||
.delete-container {
 | 
			
		||||
    width: 60;
 | 
			
		||||
    height: 15;
 | 
			
		||||
    height: 16;
 | 
			
		||||
    background: $surface;
 | 
			
		||||
    border: thick $error;
 | 
			
		||||
    padding: 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -278,16 +283,6 @@ DeleteConfirmationModal {
 | 
			
		|||
    color: $primary;
 | 
			
		||||
    margin: 1 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button-row {
 | 
			
		||||
    margin-top: 2;
 | 
			
		||||
    align: center middle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.delete-button {
 | 
			
		||||
    margin: 0 1;
 | 
			
		||||
    min-width: 10;
 | 
			
		||||
}
 | 
			
		||||
"""
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -301,7 +296,7 @@ PasswordModal {
 | 
			
		|||
 | 
			
		||||
.password-container {
 | 
			
		||||
    width: 60;
 | 
			
		||||
    height: 12;
 | 
			
		||||
    height: 11;
 | 
			
		||||
    background: $surface;
 | 
			
		||||
    border: thick $primary;
 | 
			
		||||
    padding: 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -320,15 +315,6 @@ PasswordModal {
 | 
			
		|||
    margin-bottom: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.password-input {
 | 
			
		||||
    margin: 1 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.password-button {
 | 
			
		||||
    margin: 0 1;
 | 
			
		||||
    min-width: 10;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.error-message {
 | 
			
		||||
    color: $error;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
| 
						 | 
				
			
			@ -367,16 +353,6 @@ ConfigModal {
 | 
			
		|||
.config-option {
 | 
			
		||||
    margin: 0 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button-row {
 | 
			
		||||
    margin-top: 2;
 | 
			
		||||
    align: center middle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.config-button {
 | 
			
		||||
    margin: 0 1;
 | 
			
		||||
    min-width: 10;
 | 
			
		||||
}
 | 
			
		||||
"""
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -413,9 +389,5 @@ SaveConfirmationModal {
 | 
			
		|||
    margin: 0 1;
 | 
			
		||||
    min-width: 12;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.save-confirmation-button:focus {
 | 
			
		||||
    border: thick $accent;
 | 
			
		||||
}
 | 
			
		||||
"""
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue