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.


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


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

Reply via email to