How to set attributes before a workItemProxy.storeWorkItem() call? (RTC/EWM) (javascript)
Hello,
We have JavaScript code that creates a new work item but we are unable to set any attribute values before the creation. Our current workaround is to create the "empty" work item and then with JavaScript modify the work item. Ideally, we want to set the attribute values before the creation.
This posted forum question from 2015 shows an example in how you would do that above in (maybe) RTC 5.x:
But with EWM 7.0 this type of code does not work for us - it does not set the Summary value:
var newProxy = WorkItemProxyFactory.getWorkItemProxy({createIfNeeded: true});
newProxy.initialize(...);
newProxy.initialize(...);
newProxy.object.attributes.summary.content = "Testing 123"; // this does not work for us
newProxy.storeWorkItem(...);
And this appears in console debug output:
Legacy bindings should not convert new work items
ItemProxy error notifying: attributes,applications. The page may have been unloaded.
Legacy bindings should not convert new work items
ItemProxy error notifying: attributes,applications. The page may have been unloaded.
The attribute is created but Summary is not set.
Please advise on how to set attribute before (or upon) creation.
Thanks,
Kevin
2 answers
As Ralph says above, this is an undocumented internal API and likely to change, but I had to do this for a client and this code works in 6.x and appears to still work in 7.x but I need to more thoroughly test in the later releases.
This code is used to create a child review task on a work item at a certain point in the workflow, and assign a SME and due date, so it shows creating the item, setting various built in and custom attributes, and creating parent/child link.
Because of the callbacks, it's a bit difficult to read but basically a proxy is created for a new work item, then the settings and values for the content are set up in a params object, including code that sets the values and saves the work item if it's successfully initialised. Finally the initialise is called with the params to kick off the whole create and save:
var WorkItemAttributes = com.ibm.team.workitem.api.common.WorkItemAttributes;
var WorkItemProxyFactory = com.ibm.team.workitem.web.cache.internal.WorkItemProxyFactory;
var valueObject = function(workItem, attr, val) {
var vo = {
attributeId : attr,
path : [ 'attributes', attr, workItem._getIdSegment(attr) ],
value : val
};
return vo;
};
var addReview = function(workItem, category, owner) {
console.log('addReview');
var newProxy = WorkItemProxyFactory.getWorkItemProxy({
id : -1,
createIfNeeded : true,
doNotGetFromCache : true,
doNotCache : true
});
var params = {
var WorkItemProxyFactory = com.ibm.team.workitem.web.cache.internal.WorkItemProxyFactory;
var valueObject = function(workItem, attr, val) {
var vo = {
attributeId : attr,
path : [ 'attributes', attr, workItem._getIdSegment(attr) ],
value : val
};
return vo;
};
var addReview = function(workItem, category, owner) {
console.log('addReview');
var newProxy = WorkItemProxyFactory.getWorkItemProxy({
id : -1,
createIfNeeded : true,
doNotGetFromCache : true,
doNotCache : true
});
var params = {
newWorkItem : true,
type : "review",
fetchEditorPresentation : false,
fetchInlinePresentation : false,
projectAreaItemId : workItem.getValue(WorkItemAttributes.PROJECT_AREA),
onSuccess : function() {
console.log('WI Initialisation Success');
newProxy.setValue(valueObject(workItem, WorkItemAttributes.SUMMARY, category.name + ': '
+ workItem.getValue(WorkItemAttributes.SUMMARY)));
newProxy.setValue(valueObject(workItem, 'cpfSummary', workItem.getValue(WorkItemAttributes.SUMMARY)));
newProxy.setValue(valueObject(workItem, WorkItemAttributes.OWNER, owner));
newProxy.setValue(valueObject(workItem, WorkItemAttributes.FILED_AGAINST, category.id));
var dueDate = workItem.getValue(WorkItemAttributes.DUE_DATE);
if (dueDate === null) {
dueDate = new Date();
dueDate = dueDate.setDate(dueDate.getDate() + 2);
}
newProxy.setValue(valueObject(workItem, WorkItemAttributes.DUE_DATE, dueDate));
var linkparam = {
isNew : true,
addLinkType : "com.ibm.team.workitem.linktype.parentworkitem",
addLinkIsSource : "false",
addLinkedProjectAreaItemId : workItem.getValue(WorkItemAttributes.PROJECT_AREA),
addLinkedItemId : workItem.getWorkItemItemId()
};
newProxy.addLinkTarget(linkparam);
var saveparam = {
self : this,
operationMsg : "Saving",
applyDelta : true,
onSuccess : function(param) {
console.log('WI Save Success');
},
fetchEditorPresentation : false,
fetchInlinePresentation : false,
projectAreaItemId : workItem.getValue(WorkItemAttributes.PROJECT_AREA),
onSuccess : function() {
console.log('WI Initialisation Success');
newProxy.setValue(valueObject(workItem, WorkItemAttributes.SUMMARY, category.name + ': '
+ workItem.getValue(WorkItemAttributes.SUMMARY)));
newProxy.setValue(valueObject(workItem, 'cpfSummary', workItem.getValue(WorkItemAttributes.SUMMARY)));
newProxy.setValue(valueObject(workItem, WorkItemAttributes.OWNER, owner));
newProxy.setValue(valueObject(workItem, WorkItemAttributes.FILED_AGAINST, category.id));
var dueDate = workItem.getValue(WorkItemAttributes.DUE_DATE);
if (dueDate === null) {
dueDate = new Date();
dueDate = dueDate.setDate(dueDate.getDate() + 2);
}
newProxy.setValue(valueObject(workItem, WorkItemAttributes.DUE_DATE, dueDate));
var linkparam = {
isNew : true,
addLinkType : "com.ibm.team.workitem.linktype.parentworkitem",
addLinkIsSource : "false",
addLinkedProjectAreaItemId : workItem.getValue(WorkItemAttributes.PROJECT_AREA),
addLinkedItemId : workItem.getWorkItemItemId()
};
newProxy.addLinkTarget(linkparam);
var saveparam = {
self : this,
operationMsg : "Saving",
applyDelta : true,
onSuccess : function(param) {
console.log('WI Save Success');
},
onError : function(err) {
console.log('WI Save Error');
console.log('WI Save Error');
console.log(err);
}
};
newProxy.storeWorkItem(saveparam);
},
onError : function(err) {
console.log('WI Initialise Error');
console.log(err);
}
};
newProxy.initialize(params);
};
newProxy.storeWorkItem(saveparam);
},
onError : function(err) {
console.log('WI Initialise Error');
console.log(err);
}
};
newProxy.initialize(params);
};
Comments
Hello Davyd,
Thank you. This looks promising.
Within "var params = {... }" it looks like variable workItem is the parent work item of the child review task. You call "newProxy.setValue(valueObject(workItem,...)" a few times. Is the call to valueObject getting the value of the parent work item attribute and then you are copying/setting the attribute of the child review task with the parent's value?
I'm trying to figure out what workItem._getIdSegment(attr) does. If I do not have a parent WI to copy the attribute from then how would I change valueObject/
Thanks!
-Kevin
Ran out of space in the comment - see below
The valueObject function simply converts an attribute or link into the required internal format the work item uses during storage - it's a Java script object that consists of the attribute name, value and its 'path' which is the internal hierarchy its stored under.
The _getIdSegment() function returns this path.
As mentioned before, this snippet was created to create a SME Review child work item at a particular point in the overall workflow of the parent. The SME review data was derived completely from the parent's content so you're correct, but you could use any data you like, passed in any way you like. In this example:
newProxy.setValue(valueObject(workItem, WorkItemAttributes.SUMMARY, category.name + ': ' + workItem.getValue(WorkItemAttributes.SUMMARY)));
sets the Review's Summary to a string made up of the review category (category is externally derived - it's an object, so this is one example of passing in your own data) plus the parent's Summary attribute
newProxy.setValue(valueObject(workItem, 'cpfSummary', workItem.getValue(WorkItemAttributes.SUMMARY)));
sets a custom attribute to the parent's Summary
newProxy.setValue(valueObject(workItem, WorkItemAttributes.OWNER, owner));
sets the Review's Owner attribute to the owner variable, which is passed in
newProxy.setValue(valueObject(workItem, WorkItemAttributes.FILED_AGAINST, category.id));
sets the Filed Against attribute to the category passed in
var dueDate = workItem.getValue(WorkItemAttributes.DUE_DATE);
if (dueDate === null) {
dueDate = new Date();
dueDate = dueDate.setDate(dueDate.getDate() + 2);
}
newProxy.setValue(valueObject(workItem, WorkItemAttributes.DUE_DATE, dueDate));
if (dueDate === null) {
dueDate = new Date();
dueDate = dueDate.setDate(dueDate.getDate() + 2);
}
newProxy.setValue(valueObject(workItem, WorkItemAttributes.DUE_DATE, dueDate));
sets the Due Date of the Review to either be the same as the parent work item, or two days from the current date if no due date was set on the parent
var linkparam = {
isNew : true,
addLinkType : "com.ibm.team.workitem.linktype.parentworkitem",
addLinkIsSource : "false",
addLinkedProjectAreaItemId : workItem.getValue(WorkItemAttributes.PROJECT_AREA),
addLinkedItemId : workItem.getWorkItemItemId()
};
newProxy.addLinkTarget(linkparam);
isNew : true,
addLinkType : "com.ibm.team.workitem.linktype.parentworkitem",
addLinkIsSource : "false",
addLinkedProjectAreaItemId : workItem.getValue(WorkItemAttributes.PROJECT_AREA),
addLinkedItemId : workItem.getWorkItemItemId()
};
newProxy.addLinkTarget(linkparam);
creates and adds a new Parent link back up to the parent work item
Comments
Davyd,
Thank you. One more question.
What is variable workItem? For example:
newProxy.setValue(valueObject( workItem, WorkItemAttributes.OWNER, owner ));
When I try workItem._getIdSegment(attr) I get on my console: _getIdSegment is not a function. I cannot find _getIdSegment anywhere. I was thinking workItem is this.workItem while in the context of my JavaScript.
This function runs in the context of an attribute customisation or condition, and every one of those functions is passed in a parameter called workitem, which is the current work item that has triggered the function
Davyd,
Yes, in my attribute presentation customization code I am grabbing parameters.workItem from my constructor. And parameters.workItem has all my attributes, id, itemId, locationUri, etc. but no function called _getIdSegment().
I am running EWM 7.0.1.
-Kevin
Carefully read the answer Davyd gave. The parameter workItem is available in JavaScript (or Java) Attribute Customization see https://jazz.net/wiki/bin/view/Main/AttributeCustomization. If you are talking about a custom editor presentation, that information might or might not be available or available in a different way.
Comments
Ralph Schoon
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER Apr 07 '21, 2:48 p.m.Kevin Johnson
Apr 09 '21, 4:08 p.m.