-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement path for in-app guides #763
base: main
Are you sure you want to change the base?
Conversation
6de6c08
to
d42aa7f
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #763 +/- ##
==========================================
+ Coverage 68.26% 68.53% +0.26%
==========================================
Files 110 111 +1
Lines 6211 6302 +91
==========================================
+ Hits 4240 4319 +79
- Misses 1971 1983 +12
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
d42aa7f
to
204914e
Compare
204914e
to
3c1c5e3
Compare
8d5dd19
to
722184f
Compare
3c3d3bf
to
e2281fd
Compare
503faae
to
4d177a5
Compare
Hi @edan-bainglass , is this PR ready for review? I like the design, and I am looking forward to having it in the APP. |
@superstar54 it is :) The failed tests are due to a chain of yet-to-be-merged PRs all the way back to aiidalab/aiidalab-widgets-base#624, which @danielhollas is reviewing. |
When reviewing this PR, do I need to switch aiidalab/aiidalab-widgets-base#624?. |
If you're testing locally, then yes. |
77926ab
to
8d5e19f
Compare
8d5e19f
to
648a084
Compare
Need to implement selenium tests to make sure the widget works properly |
648a084
to
0a650d6
Compare
0a650d6
to
d6ae1d4
Compare
@superstar54 @danielhollas rebased on top current state. Please give it a quick look. @superstar54 let me know if I can remove the blocked label. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a super quick thoughts.
Thanks on working on this @edan-bainglass looks super intriguing. Unfortunately this week is super busy and on Friday I am leaving for two week holiday. But I am looking forward to delving into this work once I get back.
src/aiidalab_qe/common/infobox.py
Outdated
|
||
Parameters | ||
---------- | ||
`guide_id` : `str` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is quide_id
currently used anywhere? What is its purpose?
The name of this is confusing, since below it is added to extra classes, so it's not really an id
in a CSS sense.
Also, how is the uniqueness enforced. Is it up to the programmer to ensure that these ids are unique in the whole app? Not sure if that is scalable (especially given that there are also external plugins that supposedly could use this as well perhaps?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The guide id class is used by JS code to toggle the guide. Suppose you were making a new guide for bands. You'd add these widgets all around with the guide id "bands". You would then add a new guide item in the guides list with the key "bands". Selecting the guide bands will toggle all InAppGuides with the bands id.
Now, regarding collisions with existing classes, I'd have to think about it. If someone introduced the bands class, it might override, or unintentionally add styles. Will think and let you know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naively, I'd enforce that the guide id to be of a certain "unique" format, but I suppose one could always think of a case where that may be accidently used. Not sure how realistic that assumption is. Happy to consider other suggestions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danielhollas back to this PR. Unfortunately, I am not sure at the moment how to handle this. It is actually not an id, so I'll be changing it to guide_class
. It needs to be a class (and not an id), because multiple widgets will share this guide class, such that they can be toggled in unison. I think it is okay for now.
As for uniqueness, I can maybe append -guide
to the guide class, so for example bands-guide-identifier
. This should help a bit. I can make it more unique of course, e.g. this-is-a-super-unique-guide-class-identifier-for-bands
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is actually not an id, so I'll be changing it to guide_class
Makes sense 👍
As for uniqueness, I can maybe append -guide to the guide class, so for example bands-guide-identifier.
I like the idea to append a string to make this a bit more unique to prevent random clashes in the DOM from outside this widget. Perhaps appending-in-app-guide
? That's less generic than just "guide" and is consistent with the classname that you're already adding.
However, my concern was more with how to ensure uniqueness within this class itself, e.g. how to prevent programmer from e.g. copy-pasting a snippet that creates an instance of InAppGuide
and forgetting to change the guide_class
? QeApp is large enough that one could imagine that making sure all instances of this widget have unique name is non-trivial (not to mention if we ultimately choose to move this widget to AWB).
Perhaps for this you could create a class variable to would hold a list of these guide_class
identifiers across all instances, and we could than error out in the __init__
if we detect a duplicate? Something like
class InAppGuide(InfoBox):
unique_class_names: set = {}
def __init__(self, guide_class: str, classes: list[str] | None = None, **kwargs):
if guide_class in unique_class_names:
raise ValueError()
unique_class_names.add(guide_class)
(just an idea, perhaps I am overthinking it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's interesting. Note that after some discussion, we've decided to pursue a plugin-based approach for these. So a guide for bands will be provided by the bands plugin (along its settings, results, codes, etc.). The guide radio buttons would then be autodetected from entry points. The guide itself would be limited to the components of the plugin. So for bands, the settings panel and results panel(s).
That said, uniqueness should be handled carefully. Will consider your comment 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @edan-bainglass , thanks for the nice work!
Could you add a section on how to add in-app guide in the docs?
@superstar54 will do 👍 |
7fff3c3
to
5ebeedc
Compare
5ebeedc
to
a5b7a3b
Compare
a5b7a3b
to
b8f7451
Compare
b8f7451
to
bb57f5c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice in-app guide! The style is also pretty. I added a few suggestions in the comments.
Could you also add a guide for step 4.
src/aiidalab_qe/guides/basic.html
Outdated
<div class="alert alert-success"> | ||
<h4>Tasks</h4> | ||
<ol> | ||
<li>Select resources</li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<li>Select resources</li> | |
<li>Select resources in the Global resources tab</li> |
src/aiidalab_qe/guides/basic.html
Outdated
<div class="alert alert-success"> | ||
<h4>Tasks</h4> | ||
<ol> | ||
<li>Select <b>Full geometry</b> relaxation</li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since "Full geometry" is the default, consider select "Atomic positions"
src/aiidalab_qe/guides/basic.html
Outdated
<div id="pdos-settings"> | ||
Here we configure the settings for computing the projected density of states, | ||
or PDOS. | ||
<div class="alert alert-success">???</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the advacned settings,
<div class="alert alert-success">???</div> | |
<div class="alert alert-success">In this walkthrough, we will not modify the pdos settings and proceed with the defaults.</div> |
<div class="alert alert-success"> | ||
<h4>Tasks</h4> | ||
<ol> | ||
<li>Select resources</li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe also add a description of the calculation before submitting.
Thanks @superstar54. Note that I will make no comments regarding the actual content of the guides, as the current content is only a draft to give @giovannipizzi and @cpignedoli a sense of how it works. I will work with them in an immediately following PR to iron out the actual content, at which point, we will also cover step 4 🙂 Since all your comments above ARE regarding content, I take it you approve of the mechanism itself. Per our discussion, I will update the PR to handle uniqueness as suggested in the PR description. |
LMK when you're done with that and I can have a final look (but feel free to merge anytime / don't feel block by me) |
bb33567
to
bfa4b02
Compare
@danielhollas ready to review. I implemented guide uniqueness in the last commit. Also in that commit is a mechanism for ensuring intended guide order by inspecting the HTML file name, which is now required to include a |
Based on #967
This PR adds a mechanism for adding in-app guides meant as example use-cases for users. The mechanism leverages a global instance of the
GuideManager
, which tracks the current selected guide in anactive_guide
traitlet, which is observed by allInAppGuide
instances. Instances are placed throughout the app with unique identifiers. Additional placeholders may be added by plugin developers within their defined panels.Usage
In-app guide widgets can be added anywhere as follows:
This defines the guide explicitly, providing hard-coded content, which is useful for generic guide sections that are useful for any guide. Children can be any widget supported by
ipywidgets
. This allows developers to customize the content of the guide as they wish.However, for specific guide content, a more flexible approach is
Here, the guide is defined from content fetched by an HTML
id
attribute from the currently loaded guide (HTML document) in the guide manager corresponding to the active (selected) guide. The HTML document is parsed using beautiful soup.In either case, CSS
classes
can be provided to theInAppGuide
constructor to override the behavior of theinfo-box
andin-app-guide
CSS classes.This allows developers to control top-level styles for the guide. Styles internal to the guide are more easily controlled directly in the guide HTML documents.
External guides
The app defines internal guides in
src/aiidalab_qe/guides
. External guides may be added by plugin developers using the same entry point system already used in plugins. Developers simply add aguides
key to their plugin definition with a value pointing at the path of theirguides
directory. The guide manager will pick these up on app start and add them to the list of available guides.Comments regarding external guides
Entry point
We may consider enforcing a structure here, specifying that external guides must be provided at the root level of the plugin.
guides
keyUniqueness
In the current implementation, there is a risk an external guide developer names a guide identically to an existing internal/external guide. To avoid this, the plugin identifier can be used as a prefix when storing guides in the manager. In the app, we could consider displaying guides by category. There are various means of achieving this cleanly. Open to discussion.