diff --git a/src/aiidalab_qe/app/wrapper.py b/src/aiidalab_qe/app/wrapper.py index ba7817e1..3193dcb1 100644 --- a/src/aiidalab_qe/app/wrapper.py +++ b/src/aiidalab_qe/app/wrapper.py @@ -2,7 +2,7 @@ import ipywidgets as ipw import traitlets as tl -from IPython.display import Javascript, display +from IPython.display import display from aiidalab_qe.common.widgets import LoadingWidget @@ -94,43 +94,10 @@ def _on_job_history_toggle(self, change: dict): self._view.main.children = self._old_view def _on_guide_select(self, change: dict): - """Toggle the guide section.""" - display( - Javascript(f""" - const addGuideObserver = (guideClass) => {{ - const observer = new MutationObserver(() => {{ - document.querySelectorAll( - `.qe-app-guide, .${{guideClass}}-guide` - ).forEach(guide => {{ - if (!guide.classList.contains("show")) {{ - guide.classList.add("show"); - }} - }}); - }}); - observer.observe(document.body, {{ childList: true, subtree: true }}); - }} - - const activeGuide = "{change["new"]}"; - console.log(activeGuide); - document.querySelectorAll( - `.qe-app-guide, .${{activeGuide}}-guide` - ).forEach(guide => {{ - guide.classList.remove("show"); - }}); - if (activeGuide !== "none") {{ - document.querySelectorAll( - `.qe-app-guide, .${{activeGuide}}-guide` - ).forEach(guide => {{ - guide.classList.add("show"); - }}); - addGuideObserver(activeGuide); - }} else {{ - document.querySelectorAll(".in-app-guide").forEach(guide => {{ - guide.classList.remove("show"); - }}); - }} - """) - ) + """Sets the current active guide.""" + from aiidalab_qe.common.infobox import guide_manager + + guide_manager.active_guide = change["new"] def _set_event_handlers(self) -> None: """Set up event handlers.""" diff --git a/src/aiidalab_qe/common/infobox.py b/src/aiidalab_qe/common/infobox.py index b569425a..a665991f 100644 --- a/src/aiidalab_qe/common/infobox.py +++ b/src/aiidalab_qe/common/infobox.py @@ -1,6 +1,7 @@ from __future__ import annotations import ipywidgets as ipw +import traitlets as tl class InfoBox(ipw.VBox): @@ -22,6 +23,13 @@ def __init__(self, classes: list[str] | None = None, **kwargs): self.add_class(custom_class) +class GuideManager(tl.HasTraits): + active_guide = tl.Unicode("none") + + +guide_manager = GuideManager() + + class InAppGuide(InfoBox): """The `InfoAppGuide` is used to set up in-app guides that may be toggle in unison.""" @@ -42,5 +50,33 @@ def __init__( One or more CSS classes. """ - classes = ["in-app-guide", *(classes or []), f"{guide_class}-guide"] - super().__init__(classes=classes, **kwargs) + self.guide_class = guide_class + + super().__init__( + classes=[ + "in-app-guide", + *(classes or []), + ], + **kwargs, + ) + + guide_manager.observe( + self._on_active_guide_change, + "active_guide", + ) + + # This manual toggle call is necessary because the guide + # may be contained in a component that was not yet rendered + # when a guide was selected. + self._toggle_guide() + + def _on_active_guide_change(self, _): + self._toggle_guide() + + def _toggle_guide(self): + active_guide = guide_manager.active_guide + not_generic = self.guide_class != "qe-app" + if active_guide == "none" or (not_generic and active_guide != self.guide_class): + self.layout.display = "none" + else: + self.layout.display = "flex"