0

I want a list of all the people who have revised the given user story in addition to other data.

I'm querying the Rally Lookback REST API with the following JSON data:

{ 
    "find" : { "FormattedID": "$STORY" }, 
    "fields" : ["ObjectID", "_ValidFrom", "_ValidTo", "Blocked", "c_KanbanState", "Owner"],
    "compress" : true 
}

With this query, I get the Owner's OID, like so:

{
  "_ValidFrom": "2014-05-09T15:18:29.912Z",
  "_ValidTo": "9999-01-01T00:00:00.000Z",
  "ObjectID": 18326652440,
  "Blocked": false,
  "Owner": 13786838413,
  "c_KanbanState": "Accepted"
}

Is there a way to hydrate that Owner field? I'd like to see "John Smith", but I'd settle for "jsmith@example.com".

If I have to use the WSAPI for this, is there a way to query for a group of Owner OIDs at once -- if so, a sample would be helpful -- or will I need to loop through the collection of values and query each Owner individually?

neontapir
  • 4,698
  • 3
  • 37
  • 52

3 Answers3

1

Unfortunately, per the documentation -

It is not possible to hydrate some field types (e.g. User).

See the hydration section of the documentation

Trever Shick
  • 1,734
  • 16
  • 17
1

As Trever said, in Lookback API user fields cannot be hydrated.

As far as an example that hydrates user fields using wsapi, the code below uses shapshotstore to get snapshots where '_PreviousValues.Blocked' : {$exists: true}, and then uses Rally.data.ModelFactory to get the DisplayName of owner in each snapshot.

Ext.define('CustomApp', {
    extend: 'Rally.app.App',
    componentCls: 'app',
    scopeType: 'iteration',
    comboboxConfig: {
        labelWidth: 100,
        width: 300
    },
    launch: function() {
        var that = this;
        var iterationComboBox = Ext.create('Rally.ui.combobox.IterationComboBox',{
        listeners:{
            ready: function(combobox){
                                var iterationOid = combobox.getRecord().get('ObjectID'); 
                                that._loadStories(iterationOid);
            },
            select: function(combobox){
                                var iterationOid = combobox.getRecord().get('ObjectID'); 
                                this._loadStories(iterationOid);
            },
            scope: this  
        }
    });
        this.add(iterationComboBox);
    },

    _loadStories:function(iterationOid){
        var that = this;
        var snapshotStore = Ext.create('Rally.data.lookback.SnapshotStore', {
            autoLoad:true,
            find: {
                '_TypeHierarchy': 'HierarchicalRequirement',
                '_ProjectHierarchy': 12352608219,    
                '_PreviousValues.Blocked' : {$exists: true},
                'Iteration': iterationOid

            },
            fetch: ['Name','FormattedID','ScheduleState','Blocked','_ValidFrom','_ValidTo', 'BlockedReason','Owner'], 
            order: 'OpenedDate DESC',
            hydrate: ['Blocked','ScheduleState'],
            compress: true,
            listeners: {
        load: function(store,records,success){
            console.log("loaded %i records", records.length);
                    that._onStoriesLoaded(snapshotStore, records);
        },
        scope:this
        }
        });        
    },
    _onStoriesLoaded:function(store, records){
         var that = this;
        var promises = [];
         _.each(records, function(story) {
            promises.push(that._hydrateOwner(story, that));
        });

        Deft.Promise.all(promises).then({
            success: function(results) {
                that._stories = results;
                console.log('that._stories', that._stories);
                that._makeGrid();
            }
        });
    },
    _hydrateOwner:function(story, scope){
        var deferred = Ext.create('Deft.Deferred');
        var that = scope;
        var  ownerDisplayName = null;
        var userOid = story.get('Owner');

        var storyBlocked = story.get('Blocked');
        Rally.data.ModelFactory.getModel({
            type: 'User',
            scope: this,
            success: function(model, operation) {
                fetch: ['UserName', 'DisplayName'],
                model.load(userOid, {
                    scope: this,
                    success: function(record, operation) {
                        owner = record.get('DisplayName');
                        var fid = story.get('FormattedID');
                        var state = story.get('ScheduleState');
                        var name  = story.get('Name');
                        var blocked = story.get('Blocked');

                        result = {
                                    "fid"       : fid,
                                    "name"      : name,
                                    "state"     : state,
                                    "blocked"   : blocked,
                                    "owner"     : owner    
                                };

                        deferred.resolve(result);    
                    }
                });
            }
        });

        return deferred;
    },

        _makeGrid: function() {

        if (this.down('#grid')) {
            this.down('#grid').destroy();
        }

        var gridStore = Ext.create('Rally.data.custom.Store', {
            data: this._stories
        });

        var _grid = Ext.create('Rally.ui.grid.Grid', {
            itemId: 'grid',
            store: gridStore,
            columnCfgs: [
                {
                    text: 'Name', dataIndex: 'name'
                },
                {
                    text: 'FormattedID', dataIndex: 'fid'
                },
                {
                    text: 'ScheduleState', dataIndex: 'state'
                },
                {
                    text: 'Blocked', dataIndex: 'blocked'
                },
                {
                    text: 'Owner', dataIndex: 'owner'
                }

            ]
        });

        this.add(_grid);
        this._grid.reconfigure(gridStore);
    }
});
nickm
  • 5,936
  • 1
  • 13
  • 14
  • I'm doing this as a standalone application that queries the Rally API, but this post pointed me in the right direction. – neontapir May 12 '14 at 19:56
1

And to add to what Nick and Trever have said, if you want to know who has revised a given story, the field you're looking for is "_User". Owner is the owner, _User is who created the revision. Nick's example code can be tweaked to hydrate the _User, since it's just an OID like Owner.

A caveat: if someone changed Only a big text field (like the Description), that doesn't create a snapshot so won't be returned.

Joel Sherriff
  • 478
  • 2
  • 6