-
Notifications
You must be signed in to change notification settings - Fork 0
feat: define initial ui and project structure #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR establishes the initial project structure for a Docker logs monitoring application, creating organized folders and base UI components for better maintainability.
- Introduces a modular structure with separate packages for widgets, screens, services, and utilities
- Creates foundational UI components including header, footer, controls, and metrics widgets
- Sets up placeholder files for Docker services and configuration utilities
Reviewed Changes
Copilot reviewed 12 out of 17 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/docker_logs/widgets/metrics_widget.py | Implements real-time metrics display widget with reactive properties for thread count, container count, and monitoring status |
| src/docker_logs/widgets/header.py | Creates custom header widget extending Textual's Header with app title and dynamic status display |
| src/docker_logs/widgets/footer.py | Defines basic footer widget extending Textual's Footer for keybindings display |
| src/docker_logs/widgets/controls_widget.py | Implements control panel with start/stop/refresh/clear buttons and corresponding message classes |
| src/docker_logs/widgets/init.py | Package initialization file with widget imports and exports |
| src/docker_logs/utils/config.py | Placeholder file for configuration utilities |
| src/docker_logs/utils/colors.py | Color management utility for assigning random colors to Docker containers |
| src/docker_logs/services/docker_services.py | Placeholder file for Docker-related services |
| src/docker_logs/screens/main_screen.py | Placeholder file for the main log viewer screen |
| src/docker_logs/screens/init.py | Package initialization file for screens module |
| src/docker_logs/dockerLog.py | Updated main app file with documentation header |
| layout.py | Example layout file demonstrating Textual app structure |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
src/docker_logs/widgets/__init__.py
Outdated
| from ..widgets import Header, Footer, MetricsWidget, ControlsWidget, LogViewerWidget | ||
|
|
||
| __all__ = [ | ||
| "Header", | ||
| "Footer", | ||
| "MetricsWidget", | ||
| "ControlsWidget", | ||
| "LogViewerWidget" |
Copilot
AI
Oct 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import statement references 'LogViewerWidget' which doesn't exist in any of the created files. This will cause an ImportError.
| from ..widgets import Header, Footer, MetricsWidget, ControlsWidget, LogViewerWidget | |
| __all__ = [ | |
| "Header", | |
| "Footer", | |
| "MetricsWidget", | |
| "ControlsWidget", | |
| "LogViewerWidget" | |
| from ..widgets import Header, Footer, MetricsWidget, ControlsWidget | |
| __all__ = [ | |
| "Header", | |
| "Footer", | |
| "MetricsWidget", | |
| "ControlsWidget", |
| from .main_screen import MainScreen | ||
|
|
||
| __all__ = ["MainScreen"] No newline at end of file |
Copilot
AI
Oct 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import statement references 'MainScreen' class which doesn't exist in main_screen.py. The file only contains an import of textual.app.App.
| from .main_screen import MainScreen | |
| __all__ = ["MainScreen"] | |
| __all__ = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 14 out of 19 changed files in this pull request and generated 9 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| from textual.widget import static | ||
| from textual.reactive import reactive | ||
| from threading import active_count | ||
|
|
||
| class MetricsWidget(static): |
Copilot
AI
Oct 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import statement is incorrect. Textual's Static widget should be imported with a capital 'S': from textual.widgets import Static. The current lowercase 'static' will cause an ImportError.
| from textual.widget import static | |
| from textual.reactive import reactive | |
| from threading import active_count | |
| class MetricsWidget(static): | |
| from textual.widgets import Static | |
| from textual.reactive import reactive | |
| from threading import active_count | |
| class MetricsWidget(Static): |
| from textual.widget import static | ||
| from textual.reactive import reactive | ||
| from threading import active_count | ||
|
|
||
| class MetricsWidget(static): |
Copilot
AI
Oct 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The class inherits from 'static' (lowercase), but should inherit from 'Static' (capitalized). This is a consequence of the incorrect import on line 3 and will cause a NameError.
| from textual.widget import static | |
| from textual.reactive import reactive | |
| from threading import active_count | |
| class MetricsWidget(static): | |
| from textual.widget import Static | |
| from textual.reactive import reactive | |
| from threading import active_count | |
| class MetricsWidget(Static): |
| super().__init__(max_lines=max_lines) | ||
| self.max_lines = max_lines | ||
|
|
||
| def write_log(self, container_name: str, message: str, color:str) -> None: |
Copilot
AI
Oct 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing space after colon in the type annotation for 'color' parameter. Should be 'color: str' to conform to PEP 8 style guidelines.
| def write_log(self, container_name: str, message: str, color:str) -> None: | |
| def write_log(self, container_name: str, message: str, color: str) -> None: |
| @@ -0,0 +1,21 @@ | |||
| """Log viewer widget.""" | |||
|
|
|||
| from textual.widget import RichLog | |||
Copilot
AI
Oct 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect import path for RichLog. The correct import should be from textual.widgets import RichLog (plural 'widgets', not singular 'widget').
| from textual.widget import RichLog | |
| from textual.widgets import RichLog |
| class StartMonitoring: | ||
| pass | ||
|
|
||
| class StopMonitoring: | ||
| pass | ||
|
|
||
| class ClearLogs: | ||
| pass | ||
|
|
||
| class RefreshContainers: | ||
| pass No newline at end of file |
Copilot
AI
Oct 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These message classes don't inherit from textual.message.Message. They should inherit from Message to work properly with Textual's message handling system, similar to how they're defined in ControlsWidget.
| from textual import on | ||
|
|
||
| from .screens.main_screen import MainScreen | ||
| from .services.docker_service import DockerService |
Copilot
AI
Oct 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attempting to import DockerService from a file that only contains a docstring comment. The docker_service.py file needs to implement the DockerService class before this import will work.
| from .utils.config import config | ||
|
|
Copilot
AI
Oct 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attempting to import config from a file that only contains a docstring comment. The config.py file needs to define the config object with attributes like 'default_colors' and 'update_interval' before this import will work.
| from .utils.config import config | |
| try: | |
| from .utils.config import config | |
| except ImportError: | |
| from types import SimpleNamespace | |
| config = SimpleNamespace( | |
| default_colors=["red", "green", "blue", "yellow", "magenta", "cyan"], | |
| update_interval=1.0 | |
| ) |
| container_count = self.docker_service.get_container_count() | ||
| monitoring = self.docker_service.is_monitoring() | ||
|
|
||
| self.main_screen.refresh_metrics(container_count, monitoring) |
Copilot
AI
Oct 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The MainScreen class doesn't have a 'refresh_metrics' method. Based on the structure, this should likely call 'self.main_screen.metrics.refresh_metrics(container_count, monitoring)'.
| self.main_screen.refresh_metrics(container_count, monitoring) | |
| self.main_screen.metrics.refresh_metrics(container_count, monitoring) |
| def action_clear_logs(self) -> None: | ||
| self.main_screen.log_viewer.clear_logs() | ||
| logger.info("Cleared logs") | ||
|
|
Copilot
AI
Oct 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method calls 'self.handle_refresh_containers()' which is not defined in this class. The method should either be implemented or this should post a RefreshContainers message.
| def handle_refresh_containers(self) -> None: | |
| """Refresh the list of containers and update the UI.""" | |
| containers = self.docker_service.get_containers() | |
| self.main_screen.refresh_container_list(containers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 14 out of 19 changed files in this pull request and generated 10 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
|
|
||
| __all__ = [ | ||
| "Header", | ||
| "Footer", |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trailing whitespace after 'Footer', - this line has inconsistent whitespace compared to other entries in the list.
| "Footer", | |
| "Footer", |
| from .screens.main_screen import MainScreen | ||
| from .services.docker_service import DockerService | ||
| from .utils.colors import ColorManager | ||
| from .utils.config import config |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Importing config from config.py, but that file only contains a docstring with no config object defined. This will result in an ImportError.
| def __init__(self): | ||
| super().__init__() | ||
| self.docker_service = DockerService() | ||
| self.color_manager = ColorManager(config.default_colors) |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attempting to access config.default_colors, but config is not defined in utils/config.py. This will cause an AttributeError at runtime.
| def on_mount(self) -> None: | ||
| """Called when the app starts""" | ||
| self.push_screen(self.main_screen) | ||
| self.set_interval(config.update_interval, self._update_metrics) |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attempting to access config.update_interval, but config is not defined in utils/config.py. This will cause an AttributeError at runtime.
| container_count = self.docker_service.get_container_count() | ||
| monitoring = self.docker_service.is_monitoring() |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling methods on docker_service, but DockerService class is not defined. These method calls will fail at runtime.
| container_count = self.docker_service.get_container_count() | ||
| monitoring = self.docker_service.is_monitoring() | ||
|
|
||
| self.main_screen.refresh_metrics(container_count, monitoring) |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling refresh_metrics on main_screen, but MainScreen class has no such method defined. This will result in an AttributeError.
|
|
||
| def _process_logs(self) -> None: | ||
| """ Process the incoming log messages""" | ||
| for container_name, message in self.docker_service.get_log_messages(): |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling get_log_messages on docker_service, but this method is not defined in the DockerService class. This will fail at runtime.
| # Setup event handlers | ||
| @on(MainScreen.StartMonitoring) | ||
| def handle_start_monitoring(self) -> None: | ||
| if self.docker_service.start_monitoring(): |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling start_monitoring on docker_service, but this method is not defined. This will fail at runtime.
|
|
||
| @on(MainScreen.StopMonitoring) | ||
| def handle_stop_monitoring(self) -> None: | ||
| self.docker_service.stop_monitoring() |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling stop_monitoring on docker_service, but this method is not defined. This will fail at runtime.
| def action_refresh(self) -> None: | ||
| self.handle_refresh_containers() |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Method handle_refresh_containers is called but not defined in the DockerLogsApp class. This will result in an AttributeError.
📝 Description
Adding the initial project structure with UI folders and other folders
What does this PR do?
Structuring this project for better maintainability.
Why is this change necessary?
With more features and additions to the project, it will need to be structured better
🔄 Type of Change
🧪 Testing
Test Environment
How Has This Been Tested?
Test Commands
# Commands used to test the changes python dockerLog.py📋 Checklist
📸 Screenshots/Output
Before
After
🔗 Related Issues
Closes #
Related to #
📝 Additional Notes
🔍 Reviewer Notes