diff --git a/src/aiidalab_qe/app/main.py b/src/aiidalab_qe/app/main.py index b1aad16c8..d24bfcbf9 100644 --- a/src/aiidalab_qe/app/main.py +++ b/src/aiidalab_qe/app/main.py @@ -114,6 +114,8 @@ def __init__(self, qe_auto_setup=True): self.new_workchain_button, self._process_loading_message, self._wizard_app_widget, + InAppGuide(identifier="post-guide", classes=["post-guide"]), + InAppGuide(children=[ipw.HTML("hello")], guide_id="general/basic"), ] ) diff --git a/src/aiidalab_qe/app/result/__init__.py b/src/aiidalab_qe/app/result/__init__.py index 1f07f1fcc..386f7cd0a 100644 --- a/src/aiidalab_qe/app/result/__init__.py +++ b/src/aiidalab_qe/app/result/__init__.py @@ -3,6 +3,7 @@ from aiida import orm from aiida.engine import ProcessState +from aiidalab_qe.common.infobox import InAppGuide from aiidalab_qe.common.widgets import LoadingWidget from aiidalab_widgets_base import ( ProcessMonitor, @@ -106,6 +107,7 @@ def render(self): ) self.children = [ + InAppGuide(identifier="results-step"), self.process_info, ipw.HBox( children=[ diff --git a/src/aiidalab_qe/app/static/styles/infobox.css b/src/aiidalab_qe/app/static/styles/infobox.css index 7d7b3ccc9..a66f0c773 100644 --- a/src/aiidalab_qe/app/static/styles/infobox.css +++ b/src/aiidalab_qe/app/static/styles/infobox.css @@ -22,6 +22,9 @@ border-color: #ffe4c4; margin-bottom: 1em; } +.post-guide { + margin: 1em 0; +} .in-app-guide .alert { color: black; margin: 10px 0; diff --git a/src/aiidalab_qe/common/infobox.py b/src/aiidalab_qe/common/infobox.py index bdf72e988..f315dcf8b 100644 --- a/src/aiidalab_qe/common/infobox.py +++ b/src/aiidalab_qe/common/infobox.py @@ -43,6 +43,7 @@ class InAppGuide(InfoBox): def __init__( self, children: list | None = None, + guide_id: str = "", identifier: str = "", classes: list[str] | None = None, **kwargs, @@ -51,8 +52,10 @@ def __init__( Parameters ---------- - children : `list`, optional + `children` : `list`, optional The content children of this guide section. + `guide_id` : `str`, optional + The associated guide id, required if providing children. `identifier` : `str`, optional If content `children` are not provided directly, the `identifier` is used to fetch the corresponding guide section from the guide @@ -73,12 +76,17 @@ def __init__( ) if children: + if not guide_id: + raise ValueError("Widget children provided but missing the guide id") + self.guide_id = guide_id self.children = children + self.identifier = None elif identifier: + self.guide_id = None self.children = [] self.identifier = identifier else: - raise ValueError("No content or path identifier provided") + raise ValueError("No widgets or path identifier provided") self.manager.observe( self._on_active_guide_change, @@ -96,10 +104,19 @@ def _on_active_guide_change(self, _): def _update_contents(self): """Update the contents of the guide section.""" - if hasattr(self, "identifier"): - html = self.manager.get_guide_section_by_id(self.identifier) - self.children = [ipw.HTML(str(html))] if html else [] + if not self.identifier: + return + html = self.manager.get_guide_section_by_id(self.identifier) + self.children = [ipw.HTML(str(html))] if html else [] def _toggle_guide(self): """Toggle the visibility of the guide section.""" - self.layout.display = "flex" if self.manager.has_guide else "none" + self.layout.display = ( + "flex" + if self.children + and ( + self.manager.active_guide == self.guide_id + or (self.identifier and self.manager.has_guide) + ) + else "none" + ) diff --git a/src/aiidalab_qe/guides/0_basic.html b/src/aiidalab_qe/guides/0_basic.html index e51f8763d..b2edb75b1 100644 --- a/src/aiidalab_qe/guides/0_basic.html +++ b/src/aiidalab_qe/guides/0_basic.html @@ -115,8 +115,50 @@

Tasks

Tasks

    -
  1. Select resources
  2. +
  3. Select computational resources
  4. +
  5. Add a description of the calculation
  6. Click Submit to proceed
+ +
+ In this step, we can monitor the calculation and view its results. A summary + of calculation parameters is also provided. Raw input and output files may be + downloaded, as well as an AiiDA archive containing the full calculation + provenance. +
+

Tasks

+
    +
  1. + In the process tree, click on the root QeAppWorkChain node +
  2. +
  3. (optional) review the calculation parameters
  4. +
  5. Click on the Final Geometry tab
  6. +
  7. + When the structure relaxation is finished, click on + Load results to view the final structure geometry +
  8. +
  9. + Repeat the last two steps for the Bands and PDOS tabs +
  10. +
+
+
+ +
+ This concludes the basic Quantum ESPRESSO in-app guide. +
+

Exercises

+
    +
  1. + Download the raw input and output files for further analysis +
  2. +
  3. + Download the AiiDA archive to store the full calculation + provenance +
  4. +
  5. Explore the AiiDA database to view the calculation history
  6. +
+
+
diff --git a/src/aiidalab_qe/guides/1_advanced.html b/src/aiidalab_qe/guides/1_advanced.html index 90c25128d..234d1fa55 100644 --- a/src/aiidalab_qe/guides/1_advanced.html +++ b/src/aiidalab_qe/guides/1_advanced.html @@ -8,3 +8,9 @@
Advanced example
Advanced example
+ +
Advanced example
+ +
+ This concludes the advanced Quantum ESPRESSO in-app guide. +
diff --git a/tests/test_infobox.py b/tests/test_infobox.py index 65651a4b4..374069d2f 100644 --- a/tests/test_infobox.py +++ b/tests/test_infobox.py @@ -22,7 +22,10 @@ def test_in_app_guide(): from aiidalab_qe.common.guide_manager import guide_manager from aiidalab_qe.common.infobox import InAppGuide - in_app_guide = InAppGuide(children=[ipw.HTML("Hello, World!")]) + in_app_guide = InAppGuide( + children=[ipw.HTML("Hello, World!")], + guide_id="general/basic", + ) assert all( css_class in in_app_guide._dom_classes for css_class in (