This document contains the design for the MyOpenbravo (MyOB) functionality.
MyOB is the first tab in the multi-document interface. It is the starting page for a user when logging in. It contains widgets which provide information from different information sources (Openbravo, news feeds, igoogle gadgets etc.).
A user can configure the MyOB tab by creating and organizing widgets.
Widgets Key Aspects
Some key aspects:
- widgets can be anything from queries in the database which are then processed through a template, a news feed, an igoogle gadget, etc.
- widgets are defined by consultants, or more complex ones are implemented by developers
- widgets can be enabled by role and user
- widgets can have parameters which are settable (and stored) by user
- widgets have a refresh rate which determines how often de widget content is refreshed
- a user can organize the widgets available to him/her on the first tab, widgets can be hidden or resized, the widget organization is persisted so that it is restored when the user returns
MyOB and Widget Functionality
Widgets are shown in columns. Within a column widgets are vertically organized. For an example of a multi-column display see the Smartclient Portal example.
The number of columns can be set in the user preferences of MyOB (see the user preferences section below). Note: in a first release it is also acceptable to support a fixed set of 2 columns. Preferably in the underlying implementation a flexible number of columns should be taken into account.
Columns are horizontally resizable.
Remove and Add widgets
A user should be able to hide and show widgets. This means that there should be a global dialog which shows the available widgets to the user. The user can then drag/drop widgets to the desired column.
A user can remove a widget by opening a popup dialog and clicking 'delete this widget'. A widget can be re-added again from the list of available widgets on the left (see screenshot below).
Widgets can be parameterized, meaning that the user can enter values for these parameters and in this way influence the widget calculation/visualization. The parameter dialog can be opened from the widget header ('edit this widget').
The above screenshot also shows a widget in edit mode, see the RSS Feed widget in the bottom.
A widget can have any number of parameters. The parameter types are defined in the widget definition, the following is defined for each parameter:
- type: text, numeric, date, list (with list values)
- default value
A user can change a parameter through a dialog which can be accessed through the widget.
Widgets should be draggable:
- within one column, to re-order them
- from one column to the other with automatic resizing of other widgets which are located in the same column.
- widgets in one column are vertically resizable (the horizontal size is determined by the column size).
In addition a widget can be moved up/down, to the right or left, through the dialog which popups from the header (see screen shot above).
The widget organization is persisted when changes are made so that when the user returns the widget organization (column, size and location within the column) is restored.
Different types of widgets
URL based widget
The url widget loads its content from another website using an url. The url can be anything, the loaded content is not checked or converted, it is displayed as is within the widget.
The url of an url-widget can contain parameters which are substituted at runtime. The parameters can be taken from the user parameters (see previous section) of that widget or can be retrieved from the context (userid for example).
The query/templates widget is a widget which reads information from the database (or another data source) and displays the result to the user. The widget consists of 2 parts:
- a query or datasource to provide the widget with data from the system
- a template to process the data and create html which can be shown in the widget.
The widget parameters, set by the user, are passed on to the template so that it can make use of them when processing the data.
This type of widget is completely developed in java. It allows the developer to make use of the complete Openbravo system to compute the information (html) shown in the widget.
Multiple Widgets of the same Type
As widgets can be parameterized it is perfectly fine for a user to display the same widget (for example a sales order tracker) multiple times, as each widget instance can have different parameters.
Creating widgets at runtime
A user should be able to create a widget on the fly at runtime. The list of available widgets is shown on the left in MyOB (see screenshots above). The list is based on the widget role access table (see the data model section). The order in the list is based on the sortno column in the widget definition.
The user can create a new widget in two ways:
- drag the link (for example: add feed widget) to the correct location
- click the link, enter the mandatory parameters, then the widget is as a default created in the first column
In both cases the user needs to enter the information needed by the widget. This means that a widget needs like a creation dialog which makes it possible for the user to enter the required information (an url for a newsfeed for example).
Instead of supporting a custom (complex) creation dialog another approach can also be followed: use the concept of widget parameters. One or more parameters can be flagged as mandatory. When the user creates a widget the user must first fill in the mandatory parameters before the widget is actually created. For example, when a user drags a newsfeed widget in a column he/she needs to enter the url of the newsfeed.
Common widget instance information
When a user has created a widget in MyOB there are two fields he/she can set for the widget:
- refresh rate: determines how often the content of the widget is recreated/refreshed.
These are stored as parameters for the widget instance.
Default widget set by role/complete system
It should be possible to define a default set of widgets to show when a user logs in for the first time. It makes most sense to define this information on role level.
It should be possible to configure the set of visible widgets in detail (parameters, which widgets are shown in which column). To facilitate this the idea is that an authorized user can log in and store his/her current configuration for a specific role or on system level.
To support this the following needs to be supported:
- it should be possible to flag and identify that a user has the authorizations to store the widget configurations on role level.
- when a user is authorized then the MyOB tab should have an option to save the current configuration for a specific role (to be selected) or on system level.
- when saving the configuration on role level, the current MyOB widget definitions for that role should be removed.
- when a user logs in the system should check if there is a widget set defined for the user/role combination. If not then the system should check if there is a widget set for the role. If none is defined then the system should search for a widget set definition on client level (so without a user/role).
As indicated by the previous sections, somewhere in MyOB it should be possible to open a user preferences dialog which make it possible for the user:
- to set the number of columns to use in the visualization (minimum is 1)
- to drag/drop a widget which is available for the user (considering his/her role).
- to store the current widget configuration on role or client level (if the user is authorized)
When the user reduces the number of columns then the columns are removed first on the right side and the widgets in that column are removed (in a later version we can support automatically moving over widgets to other columns).
When increasing the number of columns, these are added to the right.
When changing the number of columns the system should use a practical/sensible approach for resizing the remaining/new columns.
Community versus Pro edition
The MyOB functionality will differ depending on if the Openbravo version is a community or a pro edition:
- the community edition will have an Openbravo news widget in the top-left which can't be removed by a user. If a user tries to remove it a message such as 'This is a community edition, do you want to upgrade?' should be displayed.
- the community edition will have less advanced standard widgets.
Other functionality aspects
Some other functionality aspects which need to be taken into account:
- the MyOB tab is not deletable
- it should be possible for widgets to enable a warning flag/icon in the MyOB tab header. When the user hovers over the icon one or more messages are displayed (provided by the widgets). Multiple widgets can set the 'alert' state of the MyOB tab, with multiple messages from each
This section discussed the main code components of the solution. It discusses both the client as well as a server side implementation.
Client side: MyOB Manager
The MyOB manager manages the complete MyOB tab. This object is responsible for creating the content of the MyOB tab:
- creating the options/buttons/dialogs to set the number of columns
- support column resizing
- support creating new widgets and dragging them to the correct column
- support an edit dialog for entering mandatory parameters for a widget.
When the user starts the application and the MyOB tab is shown then the MyOB manager goes through the following steps:
- read the MyOB configuration from the preferences: this includes the number of columns and their widths.
- read the current set of widgets for the user. The widget instances are either defined on user, on role or on client level.
- for each widget instance, create a client side representation and pass in the widget instance configuration (read from the database) and widget parameter values. The client side widget instance is then responsible for creating its content by calling the corresponding server side instance. The client side widget window is then created and placed within the MyOB tab.
Then at runtime the MyOB manager takes care of:
- support creating new widget instances: instantiating the correct client side class, storing the widget instance information on the server.
- column changes/resizes
- organize widget actions: re-order, drag, re-size, remove
The client side MyOB manager is responsible for both the client-side dialogs to support these functions as well as sending configuration changes to the server to persist them in the database.
When a widget has mandatory parameters then the user must set these before the widget can be instantiated/shown. For this the MyOB client manager must be capable of:
- detecting that a widget has mandatory parameters
- generate a parameter form which shows these parameters (see the section on the client side widget class below)
- store these parameters on the server, let the server create a new widget instance and get the widget id back (to create the widget)
The flow for creating a new widget is then as follows:
- the user selects a widget to create
- the MyOB client manager checks if there are mandatory parameters
- if so then these are used to create an input form
- the user enters the parameter values and presses save
- a request is send to the server to create a widget, the request also contains the mandatory parameter values
- the server creates the widget instance record and stores it in the database together with the parameter values
- the widget id (of the new record) is sent back to the client
- the MyOB manager receives the widget id and uses this to create the widget (this is the same approach as creating widgets when logging in)
- the widgets in the target column are re-ordered and resized to make room for the new widget
- the MyOB manager stores the new configuration (size and ordering of widgets) on the server.
There is a special scenario which should be covered by the client and server side MyOB manager. When a user logs in then it is possible that his/her widgets are not defined on user level but on role/client level. When the user however then changes the configuration (change columns, resize widgets, sets parameters) then the widget configuration (settings, instances, parameter values) should be stored on user level. So there is an initial situation where all the widget instances and their configurations are created for a user.
An alternative choice can be to copy the set of widgets from role/client level to the user level when a user logs in for the first time.
Client side: Widget Class/Widget Window
The client side widget class is responsible for creating a widget window and fill its content. When the widget class is instantiated it reads the widget definition from the server and then creates the widget window. The widget content is read from the server and displayed within the widget window.
A widget window has a common part which is the same for each widget. This part provides these functions:
- a small toolbar in the top of the window with:
- a refresh button: when clicked the content is refreshed
- help button: shows the widget help text. When clicked the help is displayed in a popup. The help consists of the help text of the element linked to the widget and the help text for each parameter. There should be a generic help text for a widget also and in addition help for the title and refresh rate parameters. The help texts are read from the element records which are linked to the widget and widget parameters (see data model later in this document).
- button to popup a display with these links:
- edit parameters: opens the edit parameters dialog
- move links: up/down/right/left, these links should take into account where the widget is (for example, if it is the bottom widget then 'move down' is not shown)
- when the user clicks the 'edit parameters' link a popup is shown to edit the parameters. Some specifics of the edit parameters dialog:
- the edit form is created/generated when the user clicks the 'edit parameters' link:
- it should support setting the title and refresh rate as the first parameters
- it should read the current parameter definitions for the widget:
- only the changeable parameters are shown in the parameter form
- each parameter definition is visualized as an input field
- initially only primitive types are supported, the types supported are: numeric, date, string, long text, boolean, enumerate/list
- current/default value should be placed in the form.
- the label is read from the parameter definition or from the linked element
- after changing/setting the parameters, the widget content needs to be re-computed.
- When the use clicks the 'delete this widget' link a confirmation should be asked. If the user confirms then the following is done:
- the widget is removed on the client
- other widgets in the same column are moved up/down or resized
- the widget instance record and related parameter values is removed in the database.
- widget instance id
- title, refresh rate
- parameter values
For visualizing the widget this class should create a window which:
- in the header has a title
- shows a small toolbar in the header with a: refresh button, configure button (which opens the popup with edit/move/delete links) and a help text button
- use a SmartClient HtmlPane to visualize the content, the widget calls the server to generate the content of the widget.
Note that a widget definition can define its own client side class to use for the widget. This custom widget class should in practice always extend the default widget class.
Server Side: Widget Class
The server side widget implementation class is specified in the widget definition in the widget table. The class should implement a specific interface defined by the to-be-defined abstract super class: Widget. The interface defines these methods:
- create widget instance record: this method is called when a user creates a new widget instance on the client. The call should include values for the mandatory parameters. The method creates the widget instance record and the widget parameter records. The widget instance id should be returned.
- get content: This method is called when the widget is displayed. The method gets the widget id and can use the widget parameters stored in the database to create the content. The widget class computes the content of the widget by executing widget specific actions. The content is a string consisting of valid html which can be directly shown in a SmartClient HtmlPane.
- store parameters: is called when a user changes parameters and sets their values. This method is also called to set the title and refresh rate of a widget.
- store widget preferences: this is mainly the widget size and widget location (column and sortno).
The above bullet mentions that the html generated by the widget is valid html. A choice can be made to always have a generic html part (the head for example) and let the widget only generate the body of the html.
Server Side: Widget Manager
On the server side there should also be a widget manager class which supports actions for the complete MyOB tab, for example:
- provide the client with the list of all widget instances which should be shown in the client for that user/role.
- storing the complete widget configuration in the database/preferences (incl. number of columns and column sizes).
- provide the client with the list of allowed widgets to be created by the user
- providing the client with the definition of a widget when the user creates a widget. This definition is used to build the client side form with the (mandatory) parameters.
Widget Data Model
This section describes the tables of the MyOB solution. All the tables require a maintenance window (in classic OB style for now).
The OBMYOB_Widget table stores the widget definition. Modules can provide their own implementation and additional parameters by adding child tables.
The OBMYOB_Widget table is a client/system table with the following columns:
- OBMYOB_Widget_id: primary key
- ad_module_id (mandatory)
- name (mandatory)
- description (non-mandatory)
- title (mandatory): displayed in the widget title bar if the element column is empty.
- sortno: defines the ordering in the 'add widget' list on the left in MyOB
- ad_element_id (non-mandatory): reference to an element for supporting translated titles and help text.
- widgetServerClass: the class name of the server side widget class implementing this widget. If empty then a default implementation is used which shows the widget parameter values.
- widgetClientClass: the class name of the client side implementation, can be empty, in this case the default widget implementation class is used.
- A record in the table may only be edited if the module is in development.
- When creating a new record then only modules in development maybe selected.
- There are no special unique constraints.
The widget parameters are stored in a table (OBMYOB_Widget_Parameter). This table has the following characteristics:
- system/client level.
- is a child of the Widget table
This table has the following columns:
- OBMYOB_Widget_Parameter_id: primary key
- obmyob_widget_id (mandatory, parent): foreign key to the parent table
- name (mandatory)
- ad_element_id: a widget parameter can refer to an element name to facilitate translation, i.e. if a widget parameter has an element then the element print text value is used as the display value for the end user, the help text is also retrieved from the element.
- ad_Reference_id and ad_reference_value_id (mandatory): the reference defines the type of the widget parameter. Initially only primitive types are supported. In a later release also foreign key types are supported. The ad_reference_id and ad_reference_value_id should work the same as in the column, so the ad_reference_value is set based on the value of the ad_reference_id column.
- sortno: defines the order in the edit parameters dialog.
- default: a text which denotes the default value for the parameter
- mandatory: if true then this parameter is part of the initial creation dialog when the user creates an instance of the widget.
- changeable: if the parameter is changeable and visible to the user to edit, if false then this parameter is not shown to the user in edit dialogs.
- a record in the table may only be edited if the module of the parent table is in development
The number of columns in MyOB is stored by user. This information is stored as a user preference in the preference table. There are client side utilities which facilitate getting and setting this preference:
A new list reference value should be created for the 'Property Configuration' reference. The name of this list reference value should be used when getting/setting this preference.
The OBMYOB_Widget_Instance table holds the instances which have been created for/by the user.
- OBMYOB_Widget_Instance_id: primary key
- ad_role_id (non-mandatory): foreign key to the role
- ad_user_id (non-mandatory): foreign key to the user
- columnno: the number of the column in which to place this widget
- sortno: the location in the column
- obmyob_widget_id (mandatory): foreign key to the widget table (not defined as the parent)
- settings: a json string which can hold widget specific settings such as the size of the window.
- title: the user can override the title of the widget, the overridden title is stored in this column
- refresh rate: holds the refresh rate of the widget
The role and user fields are used to support the concept of default widgets. If they are both null then this is a widget instance which is available for users which do not have widgets defined on user or role level.
The records in this table are typically created by the system and not through manual actions.
Widget instance parameter values
The OBMYOB_Widget_Param_Values stores the values entered by the user for the parameters of the widget. It has the following columns:
- OBMYOB_Widget_Param_Values_id: primary key
- ad_role_id (non-mandatory)
- ad_user_id (non-mandatory)
- obmyob_widget_instance_id (mandatory, parent): foreign key to the widget instance
- obmyob_widget_parameter_id (mandatory, parent): foreign key to the widget parameter
- value: column which holds the value of the parameter, must be able to hold longer textual values
The records in this table are typically created by the system and not through manual actions.
This is a client/system table.
Widget By Role
Widgets are enabled by role, so different roles have different widgets which can be created by a user. The content of this table defines which 'add' links are shown in the MyOB tab on the left.
To define which widgets are available for which role the table OBMYOB_Widget_Role_Access is introduced. This table has the following columns:
- OBMYOB_Widget_Role_Access_id: primary key
- ad_role_id (mandatory, parent): foreign key to the role
- obmyob_widget_id (mandatory, parent): foreign key to the widget definition
- This is a client/system table.
- it is a child of the obmyob_widget table and of the ad_role table
- When a new widget is created then automatically it should be enabled for all roles.
The widget by role window should be implemented as a child tab in the widget window.
Widget Types and the data model
This section describes how the different widget types are modeled in the above datamodel.
The url widget is a widget which reads the content of the widget from another website using an url. The url is defined as a mandatory widget parameter. This means that when a user creates the widget on the client that he/she needs to enter a url for it. The url can itself contain parameters which are substituted at runtime.
A specific widget implementation should be developed which resolves the parameters in the url and then create the url which is used to retrieve the content of the widget.
When implementing this widget class a choice should be made if the url is called from the client directly or that the server calls the url and sends the result to the widget.
Note that the newsfeed widget can be implemented using this same approach (defining a mandatory url parameter).
Query and Templated Widget
This widget consists of two main parts:
- Data source, this can be:
- a direct query which reads data from the database, the query can contain parameters which are read from context.
- a reference to a datasource
- a template (reference to the template table), see here for more information on the Openbravo templating concept.
The query/template widget specific information is stored in a child table of the widget table: OBMYOB_Templated_Widget.
This table has the following columns:
- OBMYOB_Templated_Widget_id: primary key
- obmyob_widget_id (mandatory, parent): foreign key to the parent table
- obserds_datasource_id: foreign key to a datasource
- query: a hql query which reads data from the database
- obclker_template_id (mandatory): foreign key to an instance of a template
- Either the obserds_datasource_id or the query must be set
The window of this table should be implemented as a child tab in the widget window.
The initial implementation of MyOB should contain a number of examples widgets:
- Alerts widget: showing alerts with a click through to open the relevant window in a separate tab
- Google iGadget: example of a google igadget widget
- RSS Feed: an example of a multi-tab rss feed wizard
- Openbravo News widget
- A query/template widget (to-be-defined in more detail, for example retrieving sales/purchase information)
- store widget instances in the database or as a user preference: the design proposes to store the widget instances in a table, another (light-weighter) option would be store the widget instances in a user preference. This however means less referential integrity.
- Store parameter values in the database or in preferences: the same discussion can be held for parameter values, these could also be stored in user preferences instead of in the database.
- A choice need to be made where to place the link to edit/set global information like number of columns. The most logical location seems to be on the left with a 'Configure MyOB' link.