From e7f332107b32edfb2f22b3220104b1f4ab31cd55 Mon Sep 17 00:00:00 2001 From: Julien Mercier-Rojas Date: Thu, 31 Oct 2024 17:54:53 +0100 Subject: [PATCH] Setup project custom action group --- src/models/project.py | 3 +- src/presentation/__init__.py | 13 +++++- .../component/action_option_list.py | 37 +++++++++++++++ src/presentation/component/message.py | 14 ++++++ src/presentation/component/sidebar.py | 11 ++++- .../composer/composer_container.py | 3 -- src/presentation/docker/__init__.py | 4 ++ src/presentation/docker/container_select.py | 7 +++ src/presentation/summary/__init__.py | 46 +------------------ 9 files changed, 86 insertions(+), 52 deletions(-) create mode 100644 src/presentation/component/action_option_list.py create mode 100644 src/presentation/component/message.py diff --git a/src/models/project.py b/src/models/project.py index f58e26b..30796b9 100644 --- a/src/models/project.py +++ b/src/models/project.py @@ -19,8 +19,7 @@ class Project(BaseModel): composer: Optional[bool] = Field(default=False) composer_cmd: list[str] = ["composer"] docker_composer_cmd: list[str] = ["docker", "compose"] - actions: list[ProjectAction] = [] - # actions: dict[str, str] = {} + actions: Optional[dict[str, list[ProjectAction]]] = None @classmethod def from_json(cls, json_path: str): diff --git a/src/presentation/__init__.py b/src/presentation/__init__.py index da011b9..b79b7c9 100644 --- a/src/presentation/__init__.py +++ b/src/presentation/__init__.py @@ -4,6 +4,7 @@ from textual.containers import Container from models import Project +from .component.message import TerminalCommandRequested from .composer import ComposerContainer, ComposerCommandRequested from .docker import DockerContainer @@ -48,7 +49,7 @@ def action_toggle_sidebar(self) -> None: self.query_one(Sidebar).toggle_class("-hidden") @on(ComposerCommandRequested) - def action_composer_script(self, event: ComposerCommandRequested): + def action_composer_script(self, event: ComposerCommandRequested) -> None: def refresh_composer(result: bool | None): if event.refresh_composer_on_success and result: self.query_one(ComposerContainer).action_refresh() @@ -64,3 +65,13 @@ def refresh_composer(result: bool | None): ), refresh_composer, ) + + @on(TerminalCommandRequested) + def action_terminal_command(self, event: TerminalCommandRequested) -> None: + self.query_one(Sidebar).add_class("-hidden") + self.app.push_screen( + TerminalModal( + command=event.command, + allow_rerun=event.allow_rerun, + ) + ) diff --git a/src/presentation/component/action_option_list.py b/src/presentation/component/action_option_list.py new file mode 100644 index 0000000..bf27614 --- /dev/null +++ b/src/presentation/component/action_option_list.py @@ -0,0 +1,37 @@ +from textual import on +from textual.widgets import OptionList +from textual.widgets.option_list import Option + +from models import Project +from models.project import ProjectAction +from .terminal import ShellCommand, NonShellCommand, CommandType +from .message import TerminalCommandRequested + + +class ActionOptionList(OptionList): + # BORDER_TITLE = "Commands" + + # def __init__(self, project: Project, **kwargs): + def __init__( + self, + project: Project, + actions: list[ProjectAction], + group_name: str = "Commands", + **kwargs + ): + self._project: Project = project + self._actions: list[ProjectAction] = actions + super().__init__(*(Option(action.label) for action in self._actions), **kwargs) + self.border_title = group_name + + @on(OptionList.OptionSelected) + def on_script_selected(self, event: OptionList.OptionSelected) -> None: + action = self._actions[event.option_index] + command: CommandType = ( + ShellCommand(path=self._project.path, command=action.command) + if action.use_shell + else NonShellCommand( + path=self._project.path, command=action.command.split(" ") + ) + ) + self.post_message(TerminalCommandRequested(command=command)) diff --git a/src/presentation/component/message.py b/src/presentation/component/message.py new file mode 100644 index 0000000..9226db5 --- /dev/null +++ b/src/presentation/component/message.py @@ -0,0 +1,14 @@ +from textual.message import Message + +from .terminal import CommandType + + +class TerminalCommandRequested(Message): + def __init__( + self, + command: CommandType, + allow_rerun: bool = True, + ): + self.command = command + self.allow_rerun = allow_rerun + super().__init__() diff --git a/src/presentation/component/sidebar.py b/src/presentation/component/sidebar.py index cf3e60f..4cf4f1b 100644 --- a/src/presentation/component/sidebar.py +++ b/src/presentation/component/sidebar.py @@ -5,6 +5,7 @@ from models import Project +from presentation.component.action_option_list import ActionOptionList from presentation.composer.composer_script_option_list import ComposerScriptOptionList from service_locator import ServiceContainer @@ -33,5 +34,11 @@ def compose(self) -> ComposeResult: if len(ServiceContainer.composer_client().scripts(self.project)) > 0: yield ComposerScriptOptionList(self.project) - - yield OptionList(*(Option(action.label) for action in self.project.actions)) + if self.project.actions is None: + return + for action_group, actions in self.project.actions.items(): + if len(actions) > 0: + yield ActionOptionList( + project=self.project, actions=actions, group_name=action_group + ) + # yield ActionOptionList(project=self.project) diff --git a/src/presentation/composer/composer_container.py b/src/presentation/composer/composer_container.py index a0ee6a4..2b412ab 100644 --- a/src/presentation/composer/composer_container.py +++ b/src/presentation/composer/composer_container.py @@ -13,9 +13,6 @@ class ComposerContainer(Container): - BINDINGS = [ - ("ctrl+r", "refresh", "Refresh"), - ] DEFAULT_CSS = """ ComposerContainer { Container { diff --git a/src/presentation/docker/__init__.py b/src/presentation/docker/__init__.py index 27b4bc1..614d36d 100644 --- a/src/presentation/docker/__init__.py +++ b/src/presentation/docker/__init__.py @@ -26,3 +26,7 @@ def compose(self) -> ComposeResult: @on(Select.Changed) def select_changed(self, event: Select.Changed) -> None: self.docker_logs.stream_logs(event.value) + + @on(Button.Pressed, "#docker_refresh") + def refresh_container_list(self): + self.query_one(ContainerSelect).refresh_container_list() diff --git a/src/presentation/docker/container_select.py b/src/presentation/docker/container_select.py index 38e4b44..b26a2f2 100644 --- a/src/presentation/docker/container_select.py +++ b/src/presentation/docker/container_select.py @@ -12,3 +12,10 @@ def __init__(self, **kargs): ), **kargs ) + + def refresh_container_list(self): + self.clear() + self.set_options( + (docker_container.name, docker_container.id) + for docker_container in ServiceContainer.docker_client().get_running_containers() + ) diff --git a/src/presentation/summary/__init__.py b/src/presentation/summary/__init__.py index 4a28215..c110997 100644 --- a/src/presentation/summary/__init__.py +++ b/src/presentation/summary/__init__.py @@ -1,15 +1,7 @@ -from textual.containers import Container, Horizontal -from textual.widgets import Markdown, Button -from textual import on +from textual.containers import Container +from textual.widgets import Markdown from models import Project -from models.project import ProjectAction -from presentation.component import ( - TerminalModal, - Terminal, - ShellCommand, - NonShellCommand, -) # service: Service = Provide[Container.service] @@ -23,10 +15,6 @@ class ProjectSummaryContainer(Container): Markdown { height: auto; } - - #summary-actions { - height: 3; - } } """ @@ -40,33 +28,3 @@ def compose(self): # Project : {self.project.project_name} """ ) - if len(self.project.actions) > 0: - with Horizontal(id="summary-actions"): - for action in self.project.actions: - yield ProjectActionButton(action) - - @on(Button.Pressed) - def on_pressed(self, event: Button.Pressed) -> None: - if not isinstance(event.button, ProjectActionButton): - return - action = event.button.action - if action.use_shell: - self.app.push_screen( - TerminalModal( - command=ShellCommand(path=self.project.path, command=action.command) - ) - ) - else: - self.app.push_screen( - TerminalModal( - command=NonShellCommand( - self.project.path, action.command.split(" ") - ) - ) - ) - - -class ProjectActionButton(Button): - def __init__(self, action: ProjectAction, **kwargs): - self.action = action - super().__init__(label=action.label, name=action.label, **kwargs)