如何在 CA Agile Central (AKA Rally) 自定义应用程序中使用其 ObjectID 获取单个对象详细信息?

How to Fetch a single Object Details using its ObjectID in a CA Agile Central (AKA Rally) Custom App?

我有一个从 Lookback API 获取数据的应用程序。我在数据中获取了用户 ObjectID,但是我想获取用户的 DisplayName 而不是 ObjectID。 Rally Lookback API 不允许 Hydrate User 字段,因此我在加载 Lookback API 数据时不能有用户名。 我尝试使用用户对象 ID 过滤器创建存储以获取用户名,但在 Lookback API 数据加载完成之前我没有获取用户名。当 Lookback API 数据加载完成时,我的数据操作也已完成。所以在第一次加载后加载用户名是没有用的。我尝试将 Store 的异步 属性 设置为 false/true,但没有用。 有什么方法可以用 Rally SDK 2.0 来完成这个吗? 这是代码块 -

//Lookback call
_getStoriesByUser: function (user_story_ids, user_oids, user_story_state, users) {
    this.acceptedByTM = [];
    var scheduleStates = [];
    scheduleStates.push('Accepted');
    scheduleStates.push('Released to Prod');

    var deferred = Ext.create('Deft.Deferred');
    var me = this;
    console.time("FetchingLBData");
    var snapshotStore = Ext.create('Rally.data.lookback.SnapshotStore', {
        "context": this.getContext().getDataContext(),
        "fetch": ["ScheduleState", "_User", "_PreviousValues.ScheduleState"],
        "hydrate": ["ScheduleState"],
        "find": {
            "ObjectID": { "$in": user_story_ids },
            //"_User": { "$in": user_oids },
            "_TypeHierarchy": "HierarchicalRequirement",
            "ScheduleState": { "$in": scheduleStates },
            "_PreviousValues.ScheduleState": { "$ne": null },
            "Children": null
        },
        "sort": { "_ValidFrom": -1 }
    });

    snapshotStore.load({
        callback: function (records, operation) {
            if (operation.wasSuccessful()) {
                console.timeEnd("FetchingLBData");
                me.logger.log("LB US Count >>", records.length, records)
                var total_us_accepted_by_tm = 0;
                var tmAcceptedUS = 0;
                var nontmAcceptedUS = 0;
                var tm_accepted = [];
                Ext.Array.each(user_story_state, function (uss) {
                    Ext.Array.each(records, function (rec) {
                        if ((rec.get('ObjectID') == uss.ObjectID && rec.get('ScheduleState') == 'Accepted') && (uss.ScheduleState == 'Accepted' || uss.ScheduleState == 'Released to Prod')) {
                            total_us_accepted_by_tm += 1;
                            tm_accepted.push({ ObjectID: rec.get('ObjectID'), UserObjectID: rec.get('_User') });
                                var userName;
                                //userName = me._fetchUserName(rec.get('_User')).value;
                                me._fetchUserName(rec.get('_User')).then({
                                    success: function (records) {
                                        userName = records[0].get('DisplayName')
                                    },
                                    failure: function (error) {
                                        console.log('Error in Execution:', error)
                                    }
                                }).always(function() {
                                    console.log('Waiting for Update!');
                                });
                                //userName = rec.get('_User').DisplayName;
                                console.log('Accepted By Name: ', userName);

                                me.acceptedByTM.push({ ObjectID: rec.get('ObjectID'), UserObjectID: userName });
                                return false;

                        }
                    });

                });

                deferred.resolve(me.acceptedByTM);
            } else {
                deferred.reject('Problem querying lookback');
            }
        },
        scope: me
    });
    return deferred;
},

//Get User Details for a given user
_fetchUserName: function (userObjId) {
    var me = this;
    var userName;
    var userDetails;
    var deferred = Ext.create('Deft.Deferred');
    me.logger.log("Fetching User Information for User >>", userObjId);

    var userFilter = Ext.create('Rally.data.wsapi.Filter', {
        property: 'ObjectID',
        value: userObjId
    });

    userDetails = Ext.create('Rally.data.wsapi.Store', {
        model: 'User',
        fetch: ['ObjectID', 'DisplayName'],
        filters: userFilter,
        limit: 1,
        pageSize: 1
    });

    userDetails.load({
        scope: this,
        callback: function (records, operation, success) {
            console.log("Operation Status: ", operation.synchronous);
            if (success) {
                //userName = records[0].get('DisplayName');
                deferred.resolve(records);
            } else {
                deferred.reject(Ext.String.format("Error getting {0} count for {1}: {2}", 'User', userFilter.toString(), operation.error.errors.join(',')));
            }
        }
    });

    return deferred.promise;
}

为了简化事情,我可能只是预先从 WSAPI 加载所有用户并通过 objectid 构建他们的地图。这样您就已经拥有了所有数据,并且可以在处理回溯快照时直接进行查找。

像这样:

Ext.define('CustomApp', {
    extend: 'Rally.app.App',
    componentCls: 'app',
    launch: function () {
        this._loadUsersFromWsapi().then({
            success: function (users) { 
                this.usersByOid = _.indexBy(users, function(user) {
                    return user.getId();
                });
                this._loadSnapshotData();
            },
            scope: this
        });
    },

    _loadUsersFromWsapi: function () {
        return Ext.create('Rally.data.wsapi.Store', {
            model: 'user',
            limit: Infinity,
            pageSize: 2000,
            fetch: ['ObjectID']
        }).load();
    },

    _loadSnapshotData: function () { 
        //Now in here for any given snapshot you can get the user
        //information by looking it up in the this.usersByOid map
        var userName = this._usersByOid[userObjectID].get('_refObjectName');
    }
});