How should the RHQ GUI deal with a user clicking to navigate to view X
and then quickly clicking to navigate to view Y before X has finished
loading?
This is a situation which we currently do not handle for the most part
in our GUI. There are a few places where when the user clicks on a
button on a list view, we disable the other buttons on the view until
the action for the clicked button completes. But, aside from this, the
user could still click on other links or buttons in the GUI either while
a server-side call is in progress or when the current view is still
being loaded/drawn. An easy way to see the variety of errors that can
occur as a result of such scenarios is to go to a Resource view and
quickly click on nodes in the tree and/or tabs or subtabs (a number of
BZs have recently been reported with such reproduction steps). Our
navigation infrastructure is simply not built to handle this. For
example, we have views that parse the current history token and assume
that token represents themselves, but if the user had already quickly
clicked on a link to go to another view, that assumption could be wrong
and a parse exception would occur.
There are a few ways we could deal with this issue:
1) ignore it, assuming that most of the time users will not click
something until the current view is fully rendered - this is bad because
users are used to being able to click something else if they change
their mind, and if a link or button is enabled, they assume they can
click it without causing application errors; such errors make RHQ not
look like a robust professional app
2) when a user clicks something, disable all other links and buttons on
the page until the action(s) initiated by the click have completed -
this would be very tedious to implement, and would probably require
adding a global handler that all links and buttons need to register
with; it could also annoy and frustrate users, because they would be
powerless to do anything else until the previously initiated action had
completed
3) when a user clicks something that will take them to another view,
display a "Loading..." message on the panel about to be updated, do all
of the drawing of the view off-screen, and only make it visible in the
panel once everything is fully loaded and drawn *and* a check that the
user hasn't navigated somewhere else succeeds; if the user clicks
something else, set some state to to tell other views that may still be
loading to not flip themselves to visible when they're done loading -
this would require a lot of refactoring across all our views, but at
least allows users to freely click around; it would also prevent them
from clicking on anything in the part of the page being updated until it
is fully drawn (this is similar to how SmartGWT ListGrids work - they
show a "Loading data..." message until the data is done loading and only
render the rows in the grid once the data is done loading)
4) re-architect coregui to use the MVP (Model-View-Presenter) pattern;
GWT 2.1 and later include the Activity and Place API which can be used
to do MVP-based navigation and bookmarking (see
http://code.google.com/webtoolkit/doc/latest/DevGuideMvpActivitiesAndPlac...);
the API provides a clear separation between code that performs
navigation or some other action and code that actually draws a
widget/view, which allows something like 3) to be done easily and more
robustly
I think 4) is the best solution, because MVP is a pattern specifically
intended for large complex GWT apps like ours and would provide many
other benefits besides solving the issue at hand. The drawback is that
it would take a significant amount of work to rewrite the entire GUI
using MVP (I'm guessing 400-600 engineering hours). However, I think it
will save time in the long run, because it will make the app more robust
and maintainable. So I recommend we take the plunge. I think it could be
done as a new coregui2.war webapp within rhq.ear. This would allow the
latest business logic to gradually be pulled over from coregui.war as
parallel development goes on in coregui.war. Once coregui2.war is done,
coregui.war could be deprecated or deleted, and coregui2.war would take
its place.
If we decide we can't devote the resources to take on 4), I think 3)
would be the best option, but 3) would still be a lot of work (perhaps
200-300 engineering hours) and if we eventually do 4), it would all get
thrown away. If we don't want to do 4) or 3), then I would just go with
1), since I'm not a fan of 2).
Please give your thoughts on this. Which of the options do you think we
should take short term? long term? Are there are any other options you
can think of?
For a detailed description of the MVP pattern, read the two-part article
linked at the top of
http://code.google.com/webtoolkit/doc/latest/DevGuideMvpActivitiesAndPlac....
Thanks,
Ian