[Freeipa-devel] webUI code restructuring [wall of text, diagrams, ... you've been warned!]

Pavel Zuna pzuna at redhat.com
Tue Sep 7 12:45:49 UTC 2010


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.

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.

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.


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');

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, ...).


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.


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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pzuna_ipa_webui_module_diagram.png
Type: image/png
Size: 92829 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/freeipa-devel/attachments/20100907/c1dee52d/attachment.png>


More information about the Freeipa-devel mailing list