Skip to content

Commit d1aae33

Browse files
Codify state icons in a separate module (#1186)
This PR defines process state icons in a separate common module and utilizes them throughout the app.
1 parent 7cdec52 commit d1aae33

File tree

6 files changed

+54
-40
lines changed

6 files changed

+54
-40
lines changed

src/aiidalab_qe/app/result/__init__.py

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from aiida.engine import ProcessState
55
from aiidalab_qe.common.infobox import InAppGuide
6+
from aiidalab_qe.common.process import STATE_ICONS
67
from aiidalab_qe.common.widgets import LoadingWidget
78
from aiidalab_qe.common.wizard import QeDependentWizardStep
89
from aiidalab_widgets_base import ProcessMonitor, WizardAppWidgetStep
@@ -13,19 +14,14 @@
1314
from .components.viewer import WorkChainResultsViewer, WorkChainResultsViewerModel
1415
from .model import ResultsStepModel
1516

16-
STATUS_TEMPLATE = "<h4>Workflow status: {}</h4"
17-
18-
STATUS_MAP = {
19-
ProcessState.EXCEPTED: "Excepted",
20-
ProcessState.KILLED: "Killed",
21-
}
22-
2317

2418
class ViewQeAppWorkChainStatusAndResultsStep(QeDependentWizardStep[ResultsStepModel]):
2519
missing_information_warning = (
2620
"No available results. Did you submit or load a calculation?"
2721
)
2822

23+
STATUS_TEMPLATE = "<h4>Workflow status: {}</h4"
24+
2925
def __init__(self, model: ResultsStepModel, **kwargs):
3026
self.log_widget = kwargs.pop("log_widget", None)
3127
super().__init__(model=model, **kwargs)
@@ -235,30 +231,42 @@ def _update_status(self):
235231
self._model.monitor_counter += 1
236232

237233
def _update_state(self):
238-
process_node = self._model.fetch_process_node()
239-
if not process_node:
234+
if not (process_node := self._model.fetch_process_node()):
240235
self.state = self.State.INIT
241-
elif process_node.process_state in (
242-
ProcessState.CREATED,
236+
self._update_controls()
237+
return
238+
239+
if process_state := process_node.process_state:
240+
status = self._get_process_status(process_state.value)
241+
else:
242+
status = "Unknown"
243+
244+
if process_state is ProcessState.CREATED:
245+
self.state = self.State.ACTIVE
246+
elif process_state in (
243247
ProcessState.RUNNING,
244248
ProcessState.WAITING,
245249
):
246250
self.state = self.State.ACTIVE
247-
self._model.process_info = STATUS_TEMPLATE.format("Running")
248-
elif (
249-
process_node.process_state
250-
in (
251-
ProcessState.EXCEPTED,
252-
ProcessState.KILLED,
253-
)
254-
or process_node.is_failed
251+
status = self._get_process_status("running") # overwrite status
252+
elif process_state in (
253+
ProcessState.EXCEPTED,
254+
ProcessState.KILLED,
255255
):
256256
self.state = self.State.FAIL
257-
status = STATUS_MAP.get(process_node.process_state, "Failed")
258-
self._model.process_info = STATUS_TEMPLATE.format(status)
257+
elif process_node.is_failed:
258+
self.state = self.State.FAIL
259259
elif process_node.is_finished_ok:
260260
self.state = self.State.SUCCESS
261-
self._model.process_info = STATUS_TEMPLATE.format("Completed successfully")
261+
262+
self._model.process_info = self.STATUS_TEMPLATE.format(status)
263+
264+
self._update_controls()
265+
266+
def _update_controls(self):
262267
if self.state in (self.State.SUCCESS, self.State.FAIL):
263268
self._update_kill_button_layout()
264269
self._update_clean_scratch_button_layout()
270+
271+
def _get_process_status(self, state: str):
272+
return f"{state.capitalize()} {STATE_ICONS[state]}"

src/aiidalab_qe/app/utils/search_jobs.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,9 @@
44
from table_widget import TableWidget
55

66
from aiida.orm import QueryBuilder, load_node
7+
from aiidalab_qe.common.process import STATE_ICONS
78
from aiidalab_qe.common.widgets import LoadingWidget
89

9-
STATE_ICONS = {
10-
"running": "⏳",
11-
"finished": "✅",
12-
"excepted": "⚠️",
13-
"killed": "❌",
14-
}
15-
1610

1711
def determine_state_icon(row):
1812
"""Attach an icon to the displayed job state."""

src/aiidalab_qe/common/mixins.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import typing as t
24

35
import traitlets as tl
@@ -107,9 +109,9 @@ def outputs(self):
107109
process_node = self.fetch_process_node()
108110
return process_node.outputs if process_node else []
109111

110-
def fetch_process_node(self):
112+
def fetch_process_node(self) -> orm.ProcessNode | None:
111113
try:
112-
return orm.load_node(self.process_uuid) if self.process_uuid else None
114+
return orm.load_node(self.process_uuid) if self.process_uuid else None # type: ignore
113115
except NotExistent:
114116
return None
115117

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
from .process import QeAppWorkChainSelector, WorkChainSelector
2+
from .state import STATE_ICONS
3+
from .tree import SimplifiedProcessTree, SimplifiedProcessTreeModel
24

35
__all__ = [
6+
"STATE_ICONS",
47
"QeAppWorkChainSelector",
8+
"SimplifiedProcessTree",
9+
"SimplifiedProcessTreeModel",
510
"WorkChainSelector",
611
]
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
STATE_ICONS = {
2+
"created": "🚀",
3+
"waiting": "⏳",
4+
"queued": "⏳",
5+
"paused": "⏸",
6+
"running": "▶️",
7+
"finished": "✅",
8+
"failed": "❌",
9+
"killed": "☠️",
10+
"excepted": "⚠️",
11+
}

src/aiidalab_qe/common/process/tree.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from aiidalab_qe.common.mvc import Model
1616
from aiidalab_qe.common.widgets import LoadingWidget
1717

18+
from .state import STATE_ICONS
19+
1820

1921
class SimplifiedProcessTreeModel(Model, HasProcess):
2022
clicked = tl.Unicode(None, allow_none=True)
@@ -186,15 +188,7 @@ def _get_indentation(self):
186188
return ipw.HTML(layout=ipw.Layout(width=f"{22 * self.level}px"))
187189

188190
def _get_emoji(self, state):
189-
return {
190-
"created": "🚀",
191-
"waiting": "💤",
192-
"running": "⏳",
193-
"finished": "✅",
194-
"failed": "❌",
195-
"killed": "💀",
196-
"excepted": "⚠️",
197-
}.get(state, "❓")
191+
return STATE_ICONS.get(state, "❓")
198192

199193
def _get_state(self):
200194
if not hasattr(self.node, "process_state"):

0 commit comments

Comments
 (0)