Reputation: 1265
So I am trying to synchronize a custom field for Feature with its child story's (epic's) custom field value.
After writing the value to the epic's custom field, I need to call a function that will write the same value to the Feature's custom field. I need help retrieving the Feature's ObjectID based on the epic story's objectid.
Also, I am using Rally SDK 2.0p5.
Upvotes: 2
Views: 964
Reputation: 5966
Here is an example where a story's custom field is updated, and then its parent feature's custom field is updated. In this code a new story is created first, and its PortfolioItem attribute is set to the feature selected from a combobox populated by features that exist in your workspace. Note that in WS API HierarchicalRequirement object has Feature attribute and PortfolioItem attribute, but the former is read-only, so the latter must be used to update the story's parent PI/Feature. After a story is created and its parent feature is set, its custom field is updated and finally the parent feature's custom field is updated.
You may see the html file in this github repo.
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
if (this.down('#features')) {
this.down('#features').destroy();
}
var features = Ext.create('Rally.ui.combobox.ComboBox',{
id: 'features',
storeConfig: {
model: 'PortfolioItem/Feature',
fetch: ['FormattedID','Name', 'UserStories'],
pageSize: 100,
autoLoad: true,
},
fieldLabel: 'select Feature',
listeners:{
ready: function(combobox){
if (combobox.getRecord()) {
this._onFeatureSelected(combobox.getRecord());
}
},
select: function(combobox){
if (combobox.getRecord()) {
this._onFeatureSelected(combobox.getRecord());
}
},
scope: this
}
});
this.add(features);
},
_onFeatureSelected: function(feature){
var that = this;
if (this.down('#b')) {
this.down('#b').destroy();
}
var cb = Ext.create('Ext.Container', {
items: [
{
xtype : 'rallybutton',
text : 'create',
itemId: 'b',
handler: function() {
that._getModel(feature);
}
}
]
});
this.add(cb);
},
_getModel: function(feature){
var that = this;
Rally.data.ModelFactory.getModel({
type: 'UserStory',
success: function(model) {
that._model = model;
var story = Ext.create(model, {
Name: 'story 777',
Description: 'created via appsdk2'
});
story.save({
callback: function(result, operation) {
if(operation.wasSuccessful()) {
console.log("_ref",result.get('_ref'), ' ', result.get('Name'));
that._record = result;
that._readAndUpdateStory(feature);
}
else{
console.log("?");
}
}
});
}
});
},
_readAndUpdateStory:function(feature){
var that = this;
var id = this._record.get('ObjectID');
this._model.load(id,{
fetch: ['Name', 'FormattedID', 'ScheduleState', 'PortfolioItem', 'StoryCustomField'],
callback: function(record, operation){
console.log('ScheduleState prior to update:', record.get('ScheduleState'));
record.set('ScheduleState','In-Progress');
record.set('PortfolioItem', feature.get("_ref"));
record.set('Project', '/project/12352608219');
record.set('StoryCustomField', 'one');
record.save({
callback: function(record, operation) {
if(operation.wasSuccessful()) {
console.log('ScheduleState after update..', record.get('ScheduleState'));
console.log('StoryCustomField after update..', record.get('StoryCustomField'));
console.log('The Feature parent of this story after update..', record.get('PortfolioItem'));
that._readAndUpdateFeature(feature);
}
else{
console.log("?");
}
}
});
}
})
},
_readAndUpdateFeature:function(feature){
var id = feature.get('ObjectID');
Rally.data.ModelFactory.getModel({
type: 'PortfolioItem/Feature',
success: function(model) {
model.load(id,{
fetch: ['Name', 'FormattedID', 'FeatureCustomField'],
callback: function(record, operation){
console.log('FeatureCustomField prior to update...', record.get('FeatureCustomField'));
record.set('FeatureCustomField', 'one');
record.save({
callback: function(record, operation) {
if(operation.wasSuccessful()) {
console.log('FeatureCustomField after update..', record.get('FeatureCustomField'));
}
}
})
}
})
}
});
}
});
We encourage using the latest release of AppSDK2, which is currently rc2. AppSDK2 is not in a GA yet, and the older release candidates of them such as p5 are not compatible with the current version of WS API v2.0. The first release candidate of AppSDK2 compatible with v2.0 of WS API was rc1. We do not guarantee backwards compatibility with p5 and in some areas they are certainly not compatible. For example, In v2.0 we removed the ability to return child collections in the same response for performance reasons. In v2.0 fetching a collection will return an object with the count and the url from which to get the collection data. of WS API. In the older versions of WS API certain fetch lists create a lot of recursive calls, and all the collections included in the fetch make the call quite expensive. This is a consideration when using p5 - the further along you go with the existing code the harder it will be to re-write it to be aligned with WS API v2.0 and with newer rc of AppSDK2.
As far as the answer to your second question, if record.get('PortfolioItem')
for a child story will also pull up the feature that is actually parent of the epic, here are the details of a test:
Let's say you have a user story "epic 777" that has a Feature parent, and also a child "story 777".
This query on a user story "story 777" will return an empty PortfolioItem attribute, but the Feature attribute will reference the Feature parent of the epic story:
https://rally1.rallydev.com/slm/webservice/v2.0/hierarchicalrequirement?workspace=https://rally1.rallydev.com/slm/webservice/v2.0/workspace/12352608129&query=(Name = "story 777bbb")&fetch=PortfolioItem,Feature
Here is a fragment of result. PortfolioItem is null:
Feature: {
_rallyAPIMajor: "2",
_rallyAPIMinor: "0",
_ref: "https://rally1.rallydev.com/slm/webservice/v2.0/portfolioitem/feature/12483739639",
_refObjectUUID: "70c2a212-ae63-4a21-ae0b-2dcbbc25206c",
_objectVersion: "66",
_refObjectName: "f1",
_type: "PortfolioItem/Feature"
},
PortfolioItem: null,
_type: "HierarchicalRequirement"
A similar query on "epic 777":
https://rally1.rallydev.com/slm/webservice/v2.0/hierarchicalrequirement?workspace=https://rally1.rallydev.com/slm/webservice/v2.0/workspace/12352608129&query=(Name = "epic 777")&fetch=PortfolioItem,Feature
will show both PortfolioItem and Feature pointing to the same object:
Feature: {
_rallyAPIMajor: "2",
_rallyAPIMinor: "0",
_ref: "https://rally1.rallydev.com/slm/webservice/v2.0/portfolioitem/feature/12483739639",
_refObjectUUID: "70c2a212-ae63-4a21-ae0b-2dcbbc25206c",
_objectVersion: "66",
_refObjectName: "f1",
_type: "PortfolioItem/Feature"
},
PortfolioItem: {
_rallyAPIMajor: "2",
_rallyAPIMinor: "0",
_ref: "https://rally1.rallydev.com/slm/webservice/v2.0/portfolioitem/feature/12483739639",
_refObjectUUID: "70c2a212-ae63-4a21-ae0b-2dcbbc25206c",
_objectVersion: "66",
_refObjectName: "f1",
_type: "PortfolioItem/Feature"
},
Upvotes: 1