Workflow support

The Haplo Platform provides basic workflow support for guiding users through processes, but doesn’t provide any implementation for the actual processes. The implementation is provided by plugins.

Because the platform features are deliberately limited, a standard Workflow plugin is layered on top to implement comprehensive workflow systems with minimal code. Unless you’re doing something very special, prefer to use the Workflow plugin instead of the platform directly.

The platform provides:

  • Underlying representation of a unit of work, with WorkUnit objects
  • User interface
    • Current open work units icon in menu bar on every page
    • Work list, with current and future task listings
    • Displaying work units attached to store objects on their pages
  • Hooks for plugins to implement work flow using WorkUnit objects.

The Workflow plugin extends this with many more features.

Plugin state

The platform provides three basic states for a work unit:

  • Future (openedAt date not yet reached)
  • Open (openedAt date is in the past, but it is not yet closed)
  • Closed (closedAt date is set)

These are the minimum states required for the user interface. Open work units show in the work indicator and main work list. Future work units show in the future work list. Closed work units are only shown on the store objects, if they’re attached to one.

Actionable work units

A plugin can be ‘actioned’ by a user if the actionableBy property is set to this user, or a group to which the user belongs.

Only actionable work units are shown in task lists.

Visibility

Work units have a visible property which controls whether they are shown in the various listings on the Tasks page and on object pages.

If the autoVisible property is true, which it is by default, open work units have their visibility changed:

  • when the associated object is updated or relabelled, if the work unit is actionable by a group, it is set to visible. If it’s actionable by a user, the visibility is set to match whether the user has read permissions on the object.
  • if the actionable user is changed, the work unit is automatically set to visible regardless of permissions on any associated object.

These auto-visibility rules are intended to 1) have minimal unexpected behaviour, but 2) generally, when a work unit is actionable by a user, the visibility of the work unit matches the visibility of the associated object.

Plugin implementation

Plugins create WorkUnit objects with O.work.create(). Work units can be created in response to hooks, or to user interface added elsewhere.

Work units are displayed in the Task listing, and on object pages. Use workUnit() function on your Plugin object to define a renderer function which generates the HTML for the work unit. The rendered work units should show the process state and link to the user interface for performing tasks or changing state, implemented by your plugin.

Process state is stored in the data property of the work units, which stores arbitrary JSON serialisable data structures. The plugin should use this to store data and note the state of the process.

Example renderer function

To implement the rendering for work units with an actionType of example_plugin:action, a plugin might use an implementation such as:

P.workUnit({
    workType: "action",
    description: "Simple test work unit",
    render: function(W) {
        W.render({
            fullInfo: '/do/example/action/'+W.workUnit.id,
            fullInfoText: "Perform action...",
            actionName: W.workUnit.data.actionName
        });
    }
});

W is a PluginWorkUnitRenderer object generated by the framework. The render() function is called to generate the HTML, which, since an explicit template name is not passed as a second argument, uses the action template.

The actionName property is part of the view for the template. The template/action.html file might contain the HTML:

    Example action {{actionName}}.

It’ll be surrounded by a border automatically. The fullInfo and fullInfoText properties specify the link and text respectively. If the latter was omitted, the link would be captioned “Full info…”.

If the W.render() function is not called, then the work unit will not be displayed on the page. While this would be confusing for the Tasks list, it can be useful to omit irrelevant work units from an object page. You can tell the difference with the context property.