RTC 5.0.1 using
Client for Eclipse 4.2.x IDE
Based on various combinations of attribute values, we need to prevent the user from selecting particular actions that result in transitions to certain states. We do not have the option of creating a plug-in and are limited to client-side scripting. The situation arises when the state machine (workflow) defined for the work item allows transitions from one state to more than one other state, but the valid transitions depend on combinations of attribute values. We are not permitted by the client to use roles, approvals, or any other approach to address this need.
The minimum we would like to do is to refuse to allow the user to save the work item if certain combinations of attribute values exist. (Providing a proper error message is a separate issue.)
I am trying to use the Attribute Customization for Conditions facility to supply the Javascript for execution and the Operation Behavior of "Required Attributes for Condition" for the Save Work Item (server) Operation facility to trigger the script. This works, except that a return value of false from the "matches" function implemented by the script does not prevent the work item from being saved.
I created a Sandbox project are to explore this potential solution with a simple work item and an associated workflow. For this exploration, only one attribute is used: "Category" with an enum with two values - "A" and "B". The state machine is simple: (I can't upload the diagram yet, due to lack of reputation points)
New => (via "Continue") => Stage 1
Stage 1 => (via "Submit A") => Branch A OR (via "Submit B") => Branch B
The Conditions script is:
dojo.provide("sandbox.stateMachine.ValidStateTransition");
dojo.require("com.ibm.team.workitem.api.common.WorkItemAttributes");
(function() {
var doDebug = true;
var WorkItemAttributes = com.ibm.team.workitem.api.common.WorkItemAttributes;
var scriptname = "sandbox.stateMachine.ValidStateTransition";
dojo.declare(scriptname, null, {
matches: function(workItem, configuration) {
debug("Start matches");
var returnResult = true;
var workFlowAction = configuration.getWorkflowAction();
var workFlowState = workItem.getValue(WorkItemAttributes.STATE);
debug("WorkflowState: " + workFlowState);
debug("Workflow Action: " + workFlowAction);
if (workFlowAction == null) {
debug("user has not selected an action - nothing to do...");
returnResult = true;
} else if (workFlowState == "sandbox.stateMachine.conditionalWorkflowAB.state.stage1") {
var selectedCategory = workItem.getValue("sandbox.stateMachine.category");
debug("Category: " + selectedCategory);
returnResult = false;
if ((selectedCategory == "categoryA") && (workFlowAction == "sandbox.stateMachine.conditionalWorkflowAB.action.submitA")) {
returnResult = true;
}
if ((selectedCategory == "categoryB") && (workFlowAction == "sandbox.stateMachine.conditionalWorkflowAB.action.submitB")) {
returnResult = true;
}
}
debug("matches result: " + returnResult);
debug("End matches"); console.log("***");
return returnResult;
function debug(display){if(doDebug) {console.log(scriptname + ": " + display);}}
}
});
})();
Here's the (annotated using "===") console output from the log file when I load an existing work item already in the Stage 1 state:
=== Open the work item
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 12:59:42.450
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Start matches'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 12:59:42.450
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: WorkflowState: sandbox.stateMachine.conditionalWorkflowAB.state.stage1'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 12:59:42.451
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Workflow Action: null'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 12:59:42.452
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: user has not selected an action - nothing to do...'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 12:59:42.452
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: matches result: true'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 12:59:42.452
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: End matches'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 12:59:42.452
!MESSAGE LOG: '***'
=== Category attribute is set to "A" and the "Submit B" action is selected
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:32.721
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Start matches'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:32.722
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: WorkflowState: sandbox.stateMachine.conditionalWorkflowAB.state.stage1'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:32.722
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Workflow Action: sandbox.stateMachine.conditionalWorkflowAB.action.submitB'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:32.722
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Category: categoryA'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:32.723
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: matches result: false'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:32.723
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: End matches'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:32.723
!MESSAGE LOG: '***'
=== Save is clicked
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:48.737
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Start matches'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:48.738
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: WorkflowState: sandbox.stateMachine.conditionalWorkflowAB.state.stage1'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:48.739
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Workflow Action: sandbox.stateMachine.conditionalWorkflowAB.action.submitB'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:48.740
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Category: categoryA'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:48.740
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: matches result: false'
=== Note result of "false", above
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:48.740
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: End matches'
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:48.740
!MESSAGE LOG: '***'
The work item is successfully saved with a state of "Branch B", even though the script returned false. Note: in assigning the script "ValidStateTransition", above, to "Condition" for "Required Attributes for Condition", it does not matter which attribute, if any, are selected for the Condition in the table - the result is the same.
Thanks,
-Paul Inman