On 09/07/2010 08:45 AM, Pavel Zuna wrote:
Last week I started working on integrating the jQuery UI and jQuery
BBQ libraries into the project. I played around with them a little bit
and it turned out, that they are really great and bring a lot of value.
jQuery UI is a library of widgets like tabs, dialogs, tree views and a
lots of other cool stuff.
jQuery BBQ is a plugin for URL query string manipulation. It's main
advantage to us, is that it enables to get/push states (URL fragment
changes). This means that we don't have to reconstruct the whole state
every time. It is also friendly to the Back button and other standard
features of internet browsers.
Both libraries are mature and easy to use.
At first, I though "OK, that's cool! I'll just rewrite the navigation
file and we're set." In the end, I had to rewrite almost everything
due to not very well defined interfaces and dependencies. It took me
more than a week including the week-end, but I had one of those
creative blasts and I had fun doing it. :)
I thought this is a good opportunity to restructure the webUI code. We
are at the point were we've identified a great deal of emerging
patterns in the code and we aren't too far yet. It was only about 2000
lines or so.
Since I'm probably going back to IPA backend work with Rob in the
upcoming weeks, I thought it would be nice to reach a certain
milestone in the webUI. This is my shot at it.
Anyway, here's the design I propose (and have already implemented, so
that you can see the benefits for yourselves):
Take a look at the diagram I attached to this mail.
Looks dead on. Those were roughly the splits I was thinking about. I'm
not surpruised it took you this long: I've put off making changes like
these due to the time commitment and the need top keep showing
features. Well done.
Basically I split the code into two parts. One specific to our project
and one with re-usable code, that goes on top the of IPA framework
(ipalib; plugable architecture and all that). Module dependencies
(arrows with holes in them) and roles are now clearly defined.
I'm going to create another diagram depicting the code flow for better
understanding.
That will be useful. Once we push this patch, we should post these on
the site.
I'm also going to privately send everyone on the team a link to a live
demo. I don't feel like it should be on this public list. You can of
course checkout the whole code there.
Now, how does the code work and how do we use/modify it for feature XYZ?
------------------------------------------------------------------------
Everything is tied together in the webui.js file. This file includes
basically only two functions and a definition list used to generate
tabs. The functions are the application entry point (the document
ready event handler), where all initialization is performed, and the
"main loop" (the document hashchange event handler) used to track
changes in the state of the webUI. The definition list contains a list
of tabs and callbacks to generate their content.
Callback for generating tab content take only one parameter: the div
that represent the tab content. They shouldn't care about anything
else than their own tab! The div should be enough to identify
everything, that's required (for example what kind of IPA business
object is handled there).
The only callback currently used is the `ipa_entity_setup` function
from entity.js. It is a generic wrapper, that takes information from
entity specific files (user.js, group.js, ...) + metadata and uses it
to create facets. It basically glues functionality of all CRUD widgets
files.
The entity specific files are the place to make modifications like
adding/removing attributes to an object, change the order of
attributes, change what attributes are listed in a search, generate
special input elements for attributes that require them (attribute
callbacks).
Some examples:
* We need a new attribute for object X, that displays a calendar for
selecting dates.
=> add attribute to details definition list of object X, define
attribute callback to generate the calendar
* We need a new field to be displayed in the dialog when adding object Y.
=> add attribute to add definition list of object Y, define attribute
callback
to generate the field if it has some special requirements
* We need to handle a new state in the webUI
=> Modify the "main loop" in webui.js
* We need a whole new tab with something different that what we have now
=> add tab to navigation definition list in webui.js, create a
callback, that
generates what's supposed to be the tabs content
And so on...
Everything is customizable, but the defaults are good enough for 90%
of cases.
This should be the tagline of the UI code.
What is a webUI state?
----------------------
It's a certain combination of values in the URL fragment (that's the
portion of URLs after the # sign). Using the URL fragment saves us
from reloading the web pages (and all those bulky javascript files)
every time the user does something. We're going fully AJAX.
How to change a webUI state in the code?
----------------------------------------
Before we always had to reconstruct the whole URL. Doing ugly things
like:
document.location = document.location - fragmet + something +
'&thisandthat=' something_else + // and more
Now we can just do:
$.bbq.pushState({something: somevalue});
And to retrieve:
something = $.bbq.getState('something');
You'll have to explain how it keeps everything straight and separate.
Much nicer and we don't have to worry about overwriting states by
mistake.
How does this whole thing integrate with what we have in master?
----------------------------------------------------------------
If we decide to adopt it, I'm going to create a patch that goes over
the current master branch. It shouldn't be a big problem; a matter of
2-3 hours of work.
I already integrated some of Adam's latest patches (associations,
automatic sampledata retrieval, ...).
Should I commit the associations patch first?
So is this just code restructuring or does it have some new features?
---------------------------------------------------------------------
It has better transisions between webUI states. All the advantages of
jQuery UI and jQuery BBQ.
We have nice dialogs for adding new objects.
The content of different tabs is independent. You can click on Group,
check something and click back to user without loosing the user tab
state.
All webUI states are bookmarkable! You can save your session by simply
creating a bookmark.
Nice!
What to do, if this is adopted?
-------------------------------
I think there will be 4 main areas, where most work will be distributed.
- It's almost time to add CSS styles to make the UI look usable
- Callbacks for all kinds of special attributes and adding new IPA
objects to the UI
- Maintenance of core scripts
- Adding completely new features like work-flows, wizards,
localization, ...
If I'm to go back to IPA backend work with Rob in the upcoming weeks.
I suggest we let Andy handle the CSS, callbacks and adding new objects
(at least for now). Adam could work closely with the UXD team on new
features. I don't want to drop the UI work completely, so I could take
maintenance and helping out with whatever is needed.
This is just a suggestion btw.
Enough text. Waiting for comments. :)
Pavel
I'm impressed. I had hoped that this would be the end state. Thanks
for seeing it through. I'll review the patch top priority.
_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel