From 8e9525a0d7dfdea9f2db86dbd0bc309d782afe49 Mon Sep 17 00:00:00 2001 From: Daniel Hollas Date: Tue, 5 Mar 2024 19:50:18 +0000 Subject: [PATCH 1/3] Add kill workflow button --- aiidalab_ispg/app/steps.py | 65 ++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/aiidalab_ispg/app/steps.py b/aiidalab_ispg/app/steps.py index 8790032..d51c12e 100644 --- a/aiidalab_ispg/app/steps.py +++ b/aiidalab_ispg/app/steps.py @@ -1,8 +1,8 @@ -"""Common Steps for AiiDAlab workflows. +"""Common/Base Steps for AiiDAlab workflows. Code inspired by the QeApp. Authors: - * Daniel Hollas + * Daniel Hollas """ import re @@ -135,7 +135,7 @@ class ViewWorkChainStatusStep(ipw.VBox, WizardAppWidgetStep): process_uuid = traitlets.Unicode(allow_none=True) - def __init__(self, progress_bar=None, children=None, **kwargs): + def __init__(self, progress_bar, children=None, **kwargs): if children is None: children = [] self.process_tree = ISPGProcessNodesTreeWidget() @@ -168,13 +168,29 @@ def __init__(self, progress_bar=None, children=None, **kwargs): ) ipw.dlink((self, "process_uuid"), (self.process_monitor, "value")) - if progress_bar is not None: - workflow_state = ipw.VBox([progress_bar, self.tree_toggle]) - else: - workflow_state = ipw.VBox([self.tree_toggle]) - workflow_state.layout.width = "60%" + self.kill_button = ipw.Button( + description="Kill workflow", + tooltip="Stop the running workflow", + button_style="danger", + icon="times-circle", + disabled=True, + # layout=ipw.Layout(width="120px", height="40px"), + ) + self.kill_button.on_click(self._on_click_kill_button) + + workflow_header = ipw.VBox([progress_bar, self.tree_toggle]) + workflow_header.layout.width = "70%" + + workflow_box = ipw.HBox( + [ + workflow_header, + self.kill_button, + ] + ) + workflow_header.layout.width = "85%" + super().__init__( - children=[workflow_state, self.process_tree, self.node_view, *children], + children=[workflow_box, self.process_tree, self.node_view, *children], **kwargs, ) @@ -225,6 +241,7 @@ def _observe_process(self, change): self.tree_toggle.disabled = False self._update_step_state() self._update_workflow_state() + self._update_kill_button_layout() def _observe_tree_toggle(self, change): if change["new"] == change["old"]: @@ -242,6 +259,36 @@ def _observe_tree_toggle(self, change): self.process_tree.value = None self.tree_toggle.icon = "folder" + def _update_kill_button_layout(self): + """Update the layout of the kill button.""" + # If no process is selected, hide the button. + if self.process_uuid is None: + self.kill_button.layout.display = "none" + else: + self.kill_button.layout.display = "block" + + # Enable the button only if the process is still running + if self.state is self.State.ACTIVE: + self.kill_button.disabled = False + else: + self.kill_button.disabled = True + + def _on_click_kill_button(self, _=None): + """Callback for the kill button. + + First kill the process, then update the kill button layout. + """ + from aiida.engine.processes.control import kill_processes + + self.kill_button.disabled = True + + workchain = [load_node(self.process_uuid)] + # TODO: Wait for a bit here + kill_processes(workchain, wait=False) + + # update the kill button layout + self._update_kill_button_layout() + class ViewSpectrumStep(ipw.VBox, WizardAppWidgetStep): """Step for displaying UV/vis spectrum""" From 7b9d3b17dacd825be280593c5e0dd4acd6996a19 Mon Sep 17 00:00:00 2001 From: Daniel Hollas Date: Wed, 24 Jul 2024 15:19:00 +0000 Subject: [PATCH 2/3] Tweak layout --- aiidalab_ispg/app/steps.py | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/aiidalab_ispg/app/steps.py b/aiidalab_ispg/app/steps.py index d51c12e..2510519 100644 --- a/aiidalab_ispg/app/steps.py +++ b/aiidalab_ispg/app/steps.py @@ -178,19 +178,11 @@ def __init__(self, progress_bar, children=None, **kwargs): ) self.kill_button.on_click(self._on_click_kill_button) - workflow_header = ipw.VBox([progress_bar, self.tree_toggle]) - workflow_header.layout.width = "70%" - - workflow_box = ipw.HBox( - [ - workflow_header, - self.kill_button, - ] - ) - workflow_header.layout.width = "85%" + workflow_btns = ipw.HBox([self.tree_toggle, self.kill_button]) + self.tree_toggle.layout.width = "70%" super().__init__( - children=[workflow_box, self.process_tree, self.node_view, *children], + children=[progress_bar, workflow_btns, self.process_tree, self.node_view, *children], **kwargs, ) @@ -241,7 +233,7 @@ def _observe_process(self, change): self.tree_toggle.disabled = False self._update_step_state() self._update_workflow_state() - self._update_kill_button_layout() + self._update_kill_button() def _observe_tree_toggle(self, change): if change["new"] == change["old"]: @@ -259,19 +251,15 @@ def _observe_tree_toggle(self, change): self.process_tree.value = None self.tree_toggle.icon = "folder" - def _update_kill_button_layout(self): + def _update_kill_button(self): """Update the layout of the kill button.""" - # If no process is selected, hide the button. - if self.process_uuid is None: + # Show the button only when the process is running + if self.process_uuid is None or self.state is not self.State.ACTIVE: self.kill_button.layout.display = "none" + self.kill_button.disabled = True else: self.kill_button.layout.display = "block" - - # Enable the button only if the process is still running - if self.state is self.State.ACTIVE: self.kill_button.disabled = False - else: - self.kill_button.disabled = True def _on_click_kill_button(self, _=None): """Callback for the kill button. @@ -287,7 +275,7 @@ def _on_click_kill_button(self, _=None): kill_processes(workchain, wait=False) # update the kill button layout - self._update_kill_button_layout() + self._update_kill_button() class ViewSpectrumStep(ipw.VBox, WizardAppWidgetStep): From d74908c35632a4eb47ae877d021b9d3c7c0566cd Mon Sep 17 00:00:00 2001 From: Daniel Hollas Date: Wed, 24 Jul 2024 16:34:51 +0100 Subject: [PATCH 3/3] Fix pre-commit --- aiidalab_ispg/app/steps.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/aiidalab_ispg/app/steps.py b/aiidalab_ispg/app/steps.py index 2510519..f373d1c 100644 --- a/aiidalab_ispg/app/steps.py +++ b/aiidalab_ispg/app/steps.py @@ -174,7 +174,6 @@ def __init__(self, progress_bar, children=None, **kwargs): button_style="danger", icon="times-circle", disabled=True, - # layout=ipw.Layout(width="120px", height="40px"), ) self.kill_button.on_click(self._on_click_kill_button) @@ -182,7 +181,13 @@ def __init__(self, progress_bar, children=None, **kwargs): self.tree_toggle.layout.width = "70%" super().__init__( - children=[progress_bar, workflow_btns, self.process_tree, self.node_view, *children], + children=[ + progress_bar, + workflow_btns, + self.process_tree, + self.node_view, + *children, + ], **kwargs, ) @@ -252,14 +257,16 @@ def _observe_tree_toggle(self, change): self.tree_toggle.icon = "folder" def _update_kill_button(self): - """Update the layout of the kill button.""" - # Show the button only when the process is running - if self.process_uuid is None or self.state is not self.State.ACTIVE: - self.kill_button.layout.display = "none" - self.kill_button.disabled = True - else: + """Update the layout of the kill button. + + Show the button only when the process is running + """ + if self.process_uuid is not None and self.state is self.State.ACTIVE: self.kill_button.layout.display = "block" self.kill_button.disabled = False + else: + self.kill_button.layout.display = "none" + self.kill_button.disabled = True def _on_click_kill_button(self, _=None): """Callback for the kill button.