Index: openacs-4/packages/workflow/www/doc/developer-guide.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/www/doc/developer-guide.html,v diff -u -r1.1.2.2 -r1.1.2.3 --- openacs-4/packages/workflow/www/doc/developer-guide.html 15 Apr 2003 16:55:54 -0000 1.1.2.2 +++ openacs-4/packages/workflow/www/doc/developer-guide.html 22 Apr 2003 17:15:03 -0000 1.1.2.3 @@ -18,10 +18,17 @@ th { background-color: #ffcccc; } + th.header { + background-color: #eeeeee; + color: black; + font-size: 125%; + padding: 8px; + } tr { background-color: white; } table { + font-size: 85%; margin-left: 24px; background-color: #999999; } @@ -134,6 +141,28 @@ +

Finite State Machines (FSMs)

+ +

+ As mentioned, workflow is designed to support workflows based on any + model, however the only model currently implemented is the finite + state machine. +

+ +

+ The workflow API is designed so that whenver you're using features + that are specific to finite state machines, the procedure name will + include the letters "fsm" in the name, as in + workflow::case::fsm::get. That way you'll know when + you're hard-wiring a dependency on the particular workflow model. +

+ +

+ It's considered good practice to only use non-fsm API calls, but in + practice, it can be hard to create good user experiences without. So + feel free. +

+
Notation:

@@ -331,6 +360,9 @@ + + + @@ -402,6 +434,9 @@
Workflow Attributes
Attribute Description
+ + + @@ -428,6 +463,9 @@
Role Attributes
Attribute Description
+ + + @@ -463,6 +501,9 @@
Examples of States
Application States
+ + + @@ -547,6 +588,9 @@
State Attributes
Attribute Description
+ + + @@ -781,6 +825,9 @@
Action Attributes
Attribute Description
+ + + @@ -793,7 +840,8 @@ @@ -804,7 +852,8 @@ @@ -817,6 +866,12 @@ new assignee for a role. Could typically be used to limit the search to members of a particular group, organizers of a particular event, etc. +

+ Should return a subquery ready to be + included in the from-clause of a query, which will be used when + querying for users, for example '(select * from parties where + ...)', (sub-selects must be in parenthesis), or simply + 'cc_users' or 'parties'. Defaults to 'cc_users'.

@@ -827,7 +882,14 @@ @@ -839,6 +901,10 @@ Used to format the title of the case log. In bug-tracker, this is used to get the resolution code displayed in the case log as "Resolved (Fixed)" or "Resolved (Not Reproducable)". +

+ The implementation should return the text string that should go + into the parenthesis. The parenthesis are automatically added + if the returned string is non-empty.

@@ -849,29 +915,412 @@
Service contracts
Service Contract Applies To Description Used to get the default assignees for a role. Called for all roles when a case is started. Also called for roles with no - assignees, when that role is assigned to an action. + assignees, when that role is assigned to an action. Should return a + list of party_id's.
Used when the users wants to reassign a role to populate a drop-down list of the most likely users/groups to assign this role - to. Should return less than 25 users/groups. + to. Should return less than 25 users/groups. Should return a + list of party_id's.
This is executed whenever the given action is executed. If specified for the workflow, it will be executed whenever any - action is executed on the workflow. + action is executed on the workflow. For details about how to use + this in conjunction with log entry data and format log title, + see below. +

+ Side-effects are executed after the application object has been + updated, after the workflow state has been changed, after the + log entry has been crated, and roles assigned, but before + notifications have been sent out.

Allows the application to supply information about the case object for the notification. +

+ + Should return the notification information as a 4-element list + containing: +

    +
  1. url +
  2. one-line summary +
  3. details about the object in + the form of an array-list with label/value +
  4. tag for the notification subject (optional). If present, + it will be put inside brackets []. +

- $$$ service contract operations, input, output + All the service contracts have 3 operations each. The first two are + the same for all service contracts, and they really just act like + static variables:

+ + + + + + + + + + + + + + + + + + + + + + +
Common service contract operations
OperationInputOutputDescription
GetObjectType + None + + object_type:string + + Get the object type for which this implementation is valid. If + your implementation is valid for any object, return + 'acs_object', otherwise return the object type. +
GetPrettyName + None + + pretty_name:string + + Get the pretty name of this implementation. This will be used in + the user interface to let the workflow designer pick which + implementation to use. +
+

- $$$ linking implementations to object types. + The third operation is the one that does the real work. Here are the + inputs and outputs:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Specific service contract operations
ContractOperationInputOutput
+ Workflow.Role_DefaultAssignees + + GetAssignees + + case_id:integer
+ object_id:integer
+ role_id:integer +
+ party_ids:integer,multiple +
Workflow.Role_AssigneePickList + GetPickList + + case_id:integer
+ object_id:integer
+ role_id:integer +
+ party_ids:integer,multiple +
Workflow.Role_AssigneeSubQuery + GetSubquery + + case_id:integer
+ object_id:integer
+ role_id:integer +
+ subquery:string +
Workflow.Action_SideEffect + DoSideEffect + + case_id:integer + object_id:integer + action_id:integer + entry_id:integer + + None +
Workflow.ActivityLog_FormatTitle + GetTitle + + case_id:integer + object_id:integer + action_id:integer + entry_id:integer + data_arraylist:string,multiple + + title:string +
Workflow.NotificationInfo + GetNotificationInfo + + case_id:integer + object_id:integer + + info:string,multiple +
-

Installing and Instantiating

+

+ For the most up-to-date information about the service contracts, + your safest bet is to refer to the user-visible pages of the + acs-service-contract package itself, which will let you view your + currently installed contracts and implementations. +

+

Log Entry Data and Log Entry Titles

+ +

+ One noteworthy thing that side-effects can be used for, is to + record information about a log entry for use later in displaying a + more detailed log entry title, or can be used to e.g. tie a workflow + log entry to a particular content repository revision, etc. +

+ +

+ Using workflow::case::add_log_data, you can add arbitrary key/value + pairs to a log entry. These can the be retrieved later using + workflow::case::get_log_data_by_key, and workflow::case::get_log_data. +

+ + +

Installing and Instantiating (APM Tcl Callbacks)

+ +

+ Here are the workflow-related operations that you'll typically want + your application to do from the APM Tcl Callbacks: +

+ +
+
after-install
+
+
    +
  • Register service contract implementations +
  • Create default workflow (workflow::fsm::new_from_spec) +
+
+ +
before-uninstall
+
+
    +
  • Delete default workflow (workflow::delete) +
  • Unregister service contract implementations +
+
+ +
before-upgrade
+
+
    +
  • Add new service contract implementations +
  • Add new workflows +
  • Make changes to existing default workflows (if the installed + verison is not modified) (this isn't yet supported on the workflow API) +
+
+ +
after-instantiate
+
+
    +
  • + Clone default workflow to create a new workflow attached to + the instance (workflow::fsm::clone) +
  • +
+
+ +
before-uninstantiate
+
+
    +
  • + Delete the workflow attached to the instance (workflow::delete) +
  • +
+
+
+ +

+ To see what this could look like in practice, check out + packages/bug-tracker/tcl/install-procs.tcl. +

+ +

Integrating With Your Application's API

-

Integrating With Your Application's User Interface

+

+ Newer applications will define a namespace for each of the objects + it defines, which will contain procs like "get", "new", "delete", + etc., to manipulate these objects. +

+

+ Given such a setup, here are the procs that you want to integrate + workflow into for your workflow-integrated objects. For a real-life + example, see packages/bug-tracker/tcl/bug-procs.tcl and + search for "workflow::". +

+ +
+
get
+
+ In addition to your application's object data, you'll want to call + workflow::case::get_id to get the case_id for your + object, and then either workflow::case::get or + workflow::case::fsm::get in order to get state + information from workflow to include in the data set returned by + your API proc. +
+ +
new
+
+ When creating a new object, you should also start a new workflow + case for that object using workflow::case::new. +
+ +
edit
+
+ Editing an object should only happen through a workflow action, if + you want to have a complete audit log (workflow case log). Thus, + your edit proc should take the following arguments, in addition to + the object_id and the array containing the object data: +
+      -action_id:required
+      -comment:required
+      -comment_format:required
+      {-entry_id {}}
+    
+ (entry_id is for double-click protection). +

+ First, you should update your application object data as normal. + Then you'll probably want to use + workflow::case::get_id to find the case_id. If you + have assignment integrated in your form, you'll want to call + workflow::case::role::assign to pass these on to + workflow, and finally you'll say + workflow::case::action::execute to execute the + action, including state changes, side-effects, and notifications. +

+
+ +

Integrating With Your Application's User Interface

+ +

+ Usually, you'll want one page that lists all the objects in your + package instance, and another that lets the user view/edit one + object, called the object form page. This section is about the + object form page, the next section is about the object listing page. +

+ +

+ For a real-life example, look at + packages/bug-tracker/www/bug.tcl. You may want to have + that handy while reading through this. +

+ +

+ We're hoping to make some streamlining of both ad_form and workflow + to make this form page integration even easier at some point. But no promises. +

+ +

+ Use workflow::case::get_id to get the case_id. +

+ +

+ If you want buttons along the bottom of the form like bug-tracker, + use the new 'action' feature of the form builder. What you do is + pass a list of possible actions to the form builder as a + list-of-lists with { label value }. These will be + displayed as buttons at the bottom of the form. +

+ +

+ When one of these buttons are clicked, the form will be in + edit-mode, and you can use form get_action to get the + value of the action chosen. +

+ +

+ So up top, you'll want to ask the form if an action is in progress, + and which one it is, by saying set action_id [form get_action + form-id]. If no action is in progress this will return + the empty string. +

+ +

+ Then you should check that this action is currently available to + this user by saying + workflow::case::action::available_p. +

+ +

+ To get the currently available actions so you can offer them to the + user, use workflow::case::get_available_actions which + will return the action_id's, then workflow::action::get + to get the details about each of the actions. +

+ +

+ If you're using ad_form, and you want only one assignee + per role, and you want assignment integrated with your form, use + workflow::case::role::add_assignee_widgets to add the + widgets. It'll do an ad_form -extend, so they'll appear + at the point at which you call this proc. +

+ +

+ To set the editable fields as defined for the action, do this: +

+ +
+if { ![empty_string_p $action_id] } {
+    foreach field [workflow::action::get_element -action_id $action_id -element edit_fields] { 
+	element set_properties bug $field -mode edit 
+    }
+}
+
+ +

+ Similarly, on submit, you'll want to set the value of the editable fields. +

+ +

+ To populate values of the assignee widgets, use + workflow::case::role::set_assignee_values in your + on_request block. +

+ +

+ To add the case log to the comment field, use workflow::case::get_activity_html. +

+ + +

Integrating With Your Application's Queries

+
lars@pinds.com