Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

Also, before spending too much time drawing up a UI I'd like to get general approval from the community with regards to the functional aspects of the proposal. It would be wasted time to design a nice UI only to have it discarded because we decided to use a different approach to the problem. Once we are committed to this general approach then we would spend more time flushing out the UI design and discussing that specifically. The main point is that users would have a wysiwyg style UI for choosing widgets and organizing them in panels which would alleviate the need for direct template editing.

Design (Object and Data Model)

how are widgets represented in the code?

Similar to the way themes work now, widgets will be defined using a new Widget pojo which will describe all elements of a widget as defined by the widget XML descriptor as well as provide access to all resources defined in the widget. The Widget pojos would look something like ...

No Format

// Every widget configured in the system gets one instance of the Widget class to represent it
public class Widget {
  String id
  String name
  String description
  List templates
  List resources

  WidgetTemplate getTemplate("path/inside/widget");

  WidgetResource getResource("path/inside/widget");
}

// templates that are part of a Widget
public class WidgetTemplate {
  String id
  String name
  String description
  
  InputStream getInputStream();
}

// resource files that are part of a Widget
public class WidgetResource {
  String path

  InputStream getInputStream();
}

how are widgets associated with a weblog? how do panels fit in?

a weblog may define 0 or more Panels which are layout containers for widgets. to associate a widget with a weblog requires a Panel and to access a panel you would use a weblog such as, weblog.getPanels() or weblog.getPanel("name")

a Panel may contain 0 or more Widgets organized in some kind of layout. Most of the time it would be vertical, but we could also allow for other layout options such as horizontal, grid, etc. to access the widgets associated with a panel you would use panel.getWidgets()

The code would look something like ...

No Format

// A panel which is attached to a specific weblog
WeblogPanel {
  String id
  WebsiteData weblog
  String name
  String description
  String layout (some way to describe a layout)
  List widgets (reference to widgets configured in this panel)
}

// A WeblogWidget only represents the association between a real Widget
// and a WeblogPanel, it does not contain any actual Widget information
WeblogWidget {
  String id
  WeblogPanel panel (panel this is attached to)
  String widgetId (id of the actual widget this represents)
  int ordering (some way to order the widgets within the panel)
}


-- sql tables
roller_weblogpanels(
  varchar(48) panelid not null primary key, 
  varchar(48) weblogid not null,
  varchar(64) name not null,
  varchar(255) description,
  varchar(64) layout not null
);

roller_panelwidgets(
  varchar(48) id not null primary key,
  varchar(48) panelid not null, 
  varchar(64) widgetid not null, 
  integer position not null
);

Design (Rendering)

what actually happens to render a widget and insert it into a template?

...

  • some level of performance hit during rendering since you add in the overhead of going back through the rendering system, possibly multiple times. this could likely be negated by providing some decent caching for widgets, so that once a widget is rendered it can be reused multiple times without needing to be re-rendered.

A Walkthrough

1. Load Widget Library. a widget is imported into the system, either at runtime or was previously imported and is loaded at app init time. in this step some kind of WidgetManager would inspect all of the widget archive files, parse their XML descriptors, and construct Widget objects to represent them while the system is running.

2. Associate widgets to a weblog. to make use of widgets they need to be attached to a weblog via a panel. this is done either by a theme or directly by a weblog owner on the UI. the end result is that a WeblogPanel is defined and any number of WeblogWidgets is associated to the panel. The WeblogWidgets simply defines an association indicating that widget "foo" is attached to panel "sidebar" in weblog "myWeblog". The actual "foo" widget is maintained by the WidgetManager.

3. Rendering a widget. when a weblog page is being rendered it would indicate that it wants to render a specific panel using a macro call like #showPanel("sidebar"). that macro would perform the necessary logic to lookup the panel from the weblog, $model.weblog.getPanel("sidebar"), then render each widget in the panel using a loop over $panel.widgets. For each widget being rendered the process would be slightly different depending on the rendering approach chosen, but the outcome would be the same.

Issues

  • how to access widget resources? Roller takes the approach that all components used by a weblog should be accessed via that weblogs urls, but this creates some issues for resources that are meant to be shared across weblogs.
    • option 1, use the existing resource servlet the same way we do for theme resources.
    • option 2, pick a url location outside of the weblog url space (/roller-ui/) to use for accessing widget resources, such as /roller-ui/widgets/<widget>/