集会:从史诗般的故事的目标中检索特征

时间:2014-02-07 21:42:51

标签: rally

所以我尝试将Feature的自定义字段与其子故事(epic)的自定义字段值同步。

将值写入epic的自定义字段后,我需要调用一个函数,该函数将相同的值写入Feature的自定义字段。我需要帮助根据史诗故事的objectid检索功能的ObjectID。

另外,我使用的是Rally SDK 2.0p5。

1 个答案:

答案 0 :(得分:1)

以下是更新故事的自定义字段,然后更新其父要素的自定义字段的示例。在此代码中,首先创建一个新故事,并将其PortfolioItem属性设置为从工作区中存在的功能填充的组合框中选择的功能。请注意,在WS API中,HierarchicalRequirement对象具有Feature属性和PortfolioItem属性,但前者是只读的,因此后者必须用于更新故事的父PI / Feature。创建故事并设置其父功能后,将更新其自定义字段,最后更新父功能的自定义字段。

您可以在this github repo中看到html文件。

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'));
                                }
                            }
                         })
                    }
                })

            }
        });
    }
});

我们鼓励使用最新版本的AppSDK2,目前是rc2。 AppSDK2尚未在GA中使用,其中较早的候选版本(例如p5)与当前版本的WS API v2.0不兼容。与WS API的v2.0兼容的AppSDK2的第一个候选版本是rc1。我们不保证向后兼容p5,在某些方面它们肯定不兼容。例如,在v2.0中,出于性能原因,我们删除了在同一响应中返回子集合的功能。在v2.0中,获取集合将返回一个带有count的对象和从中获取集合数据的url。 WS API。 在旧版本的WS API中,某些提取列表会创建大量递归调用,并且提取中包含的所有集合都会使调用非常昂贵。这是使用p5时的一个考虑因素 - 随着现有代码的进一步发展,重新编写它以使其与WS API v2.0以及更新的AppcK2 rc保持一致。

就你的第二个问题的答案而言,如果儿童故事的record.get('PortfolioItem')也会提取实际上是史诗的父级的功能,则以下是测试的详细信息: 假设你有一个用户故事“史诗777”,它有一个功能父母,还有一个孩子“故事777”。

对用户故事“story 777”的此查询将返回一个空的PortfolioItem属性,但Feature属性将引用史诗故事的Feature父级:

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

这是结果的一个片段。 PortfolioItem为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"

关于“史诗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

将显示指向同一对象的PortfolioItem和Feature:

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"
},