Thursday, 12 April 2012

Opening a Seaside view from VW

I spend a good chunk of my time working on adding web interfaces to legacy Smalltalk applications, both in VW and VA. The larger project is in VW and is built with a big in-house framework. A couple of years ago I wrote a VW windowSpec to Seaside component builder which used the framework metadata to bind Seaside components to domain objects. It worked, but required too much of an investment to fully deploy.

So, we took another look at what clients needed from a web interface and decided that a 'portal' model was a better fit: a limited access web site useful to a subset of users. It is implemented with a Seaside image that has no domain objects, just parsed XML data from a RESTful GS interface. Seaside sessions share one GemStone session and rely on the application framework for login and security. It works nicely.

One of the views is table display of competitors by project, showing who is bidding on which section of the project, their bid status (won / lost / undecided), the estimated bid amount, and so on. This particular display was a challenge to do in the VW framework because it only supports a fixed number of columns in a table, and does not allow for in-cell editing (there may one day be support for the dataset widget).

We still wanted to make this display available to the VW users and the Seaside table looked nice. The solution was to launch a browser showing the selected table from a VW button press. This hybrid user interface (VW + web browser) may allow for a smoother incremental deployment of a full web based interface vs. an expensive and disruptive big bang approach.

When the 'Show table' button is pressed, a session token is saved on the logged in 'user' object in GemStone (each user has their own 'user' instance which handles things like application login and security). The oop of the saved session token is passed as a URL parameter (ExternalWebBrowser open: '...?start=12345678), and the token contents (user oop and timestamp) are checked to see if it is valid: oop of the user object must match the user object that contains the token & the timestamp of the token must be within a few seconds. If it matches, the token is cleared and a Seaside session is established. Each token can only be used once, for a short time and to access an internal web site; seems reasonably safe.

The token also contains display information which the Seaside image uses to build the table; a user presses a button and a browser opens on the expected table. Changes are stored in GemStone, so both the browser and the VW client see the same data.

Flyover components are rendered to display attributes and allow for updates. Users can change the status of a bid by pressing 'won', 'lost' or 'unknown' buttons in the flyover component. This is a quick way to edit the bid state vs. the VW based multi-window, multi-click sequence. I tried to use Seaside's jQuery tools to build the onMouseOver and onMouseOut scripts, but I found it simpler to just write the few lines I needed.

This script, as passed to table data's #onMouseOver: , positions the hidden flyover component (aFlyoverId) to the left and top of the cell under the mouse (aCellId), and then shows it. I was able to do this with Seaside jQuery code, but I could not figure out how to add the cell width to the flyover's 'left' position.

onMouseOverFlyoverId: aFlyoverId cellId: aCellId
$("#', aFlyoverId ,'").css("top",$("#', aCellId ,'").position().top);
$("#', aFlyoverId ,'").css("left",$("#', aCellId ,'").position().left + $("#', aCellId ,'").width() + 8);
$("#', aFlyoverId ,'").show();
$("#', aCellId ,'").css("background-color","#F2F7FA");

The flyover component has its own #onMouseOver: script to keep it visible when the mouse moves away from the cell and over the flyover component.

Views that show a consolidated view of objects, like the competitor table, are good candidates for the initial web interface. The XML based data gathering from GS is quick, since no domain objects are faulted to the client, and the display options are more flexible. Whereas VW fat client's detailed object level views are better for fine grain data.

The next step is to merge the windowSpec Seaside component builder with the RESTful web portal. Not hard to do, but we'll need to see if there is client interest.

Simple things should be simple. Complex things should be possible.