Getting Accepted Stories that have Tasks with TimeSpent

137 Views Asked by At

I'm writing an application that should load Accepted stories that have tasks with integer in the Time Spent field.

As I can see in some tests I made the task fields that are accessible through UserStory is: 'Tasks', 'TaskActualTotal', 'TaskEstimateTotal', 'TaskRemainingTotal' and 'TaskStatus'.

Tasks has a _ref attribute with a link to a JSON with all tasks for this story. How may I explore this since I'm using Rally API? Or Is there a better way to do this?

UPDATE:

So this is pretty much i have now.

var storiesCall = Ext.create('Rally.data.WsapiDataStore', {
                model: 'UserStory',
                fetch: ['Tasks']
            });
storiesCall.load().then({
                success: this.loadTasks,
                scope: this
            });


loadTasks: function(stories) {
        storiesCall = _.flatten(stories);
        console.log(stories.length);

        _.each(stories, function(story) {
            var tasks = story.get('Tasks');

            if(tasks.Count > 0) {
                tasks.store = story.getCollection('Tasks', {fetch: ['Name','FormattedID','Workproduct','Estimate','TimeSpent']});
                console.log(tasks.store.load().deferred);
            }
            else{
                console.log('no tasks');
            }
        });
}

tasks.store.load().deferred is returning the following object:

enter image description here

Note that we can see the task data on value[0] but when i try to wrap it out with tasks.store.load().deferred.value[0] its crashing.

Any thoughts?

1

There are 1 best solutions below

1
nickm On BEST ANSWER

Per WS API doc, TimeSpent field on Task object (which is populated automatically from entries in Rally Timesheet/Time Tracker module) cannot be used in queries, so something like this (TimeSpent > 0) will not work.

Also, a UserStory object (referred to as HierarchicalRequirement in WS API) does not have a field where child tasks' TimeSpent rolls up to the story similar to how child tasks' Estimate rolls up to TaskEstimateTotal on a story.

It is possible to get TimeSpent for each task and then add them up by accessing a story's Tasks collection as done in this app:

Ext.define('CustomApp', {
    extend: 'Rally.app.App',
    componentCls: 'app',
    launch: function() {
        var initiatives = Ext.create('Rally.data.wsapi.Store', {
            model: 'PortfolioItem/Initiative',
            fetch: ['Children']
        });
        initiatives.load().then({
            success: this.loadFeatures,
            scope: this
        }).then({                          
            success: this.loadParentStories,
            scope: this
        }).then({                          
            success: this.loadChildStories,
            scope: this
        }).then({                          
            success: this.loadTasks,
            failure: this.onFailure,
            scope: this
        }).then({
            success: function(results) {
                results = _.flatten(results);
                _.each(results, function(result){
                    console.log(result.data.FormattedID, 'Estimate: ', result.data.Estimate, 'WorkProduct:', result.data.WorkProduct.FormattedID, 'TimeSpent', result.data.TimeSpent );
                });
                this.makeGrid(results);
            },
            failure: function(error) {
                console.log('oh, noes!');
            },
            scope: this
        });
    },

    loadFeatures: function(initiatives) {
        var promises = [];
        _.each(initiatives, function(initiative) {
            var features = initiative.get('Children');
            if(features.Count > 0) {
                features.store = initiative.getCollection('Children',{fetch: ['Name','FormattedID','UserStories']});
                promises.push(features.store.load());
            }
        });
        return Deft.Promise.all(promises);
    },
    loadParentStories: function(features) {
        features = _.flatten(features);
        var promises = [];
        _.each(features, function(feature) {
            var stories = feature.get('UserStories');
            if(stories.Count > 0) {
                stories.store = feature.getCollection('UserStories', {fetch: ['Name','FormattedID','Children']});
                promises.push(stories.store.load());
            }
        });
        return Deft.Promise.all(promises);
    },
     loadChildStories: function(parentStories) {
        parentStories = _.flatten(parentStories);
        var promises = [];
        _.each(parentStories, function(parentStory) {
            var children = parentStory.get('Children');
            if(children.Count > 0) {
                children.store = parentStory.getCollection('Children', {fetch: ['Name','FormattedID','Tasks']});
                promises.push(children.store.load());
            }
        });
        return Deft.Promise.all(promises);
    },
    loadTasks: function(stories) {
        stories = _.flatten(stories);
        var promises = [];
        _.each(stories, function(story) {
            var tasks = story.get('Tasks');
            if(tasks.Count > 0) {
                tasks.store = story.getCollection('Tasks', {fetch: ['Name','FormattedID','Workproduct','Estimate','TimeSpent']});
                promises.push(tasks.store.load());
            }
            else{
                console.log('no tasks');
            }
        });
        return Deft.Promise.all(promises);
    },
    makeGrid:function(tasks){
        var data = [];
        _.each(tasks, function(task){
            data.push(task.data);
        });

        _.each(data, function(record){
            record.Story = record.WorkProduct.FormattedID + " " + record.WorkProduct.Name;
        });

        this.add({
            xtype: 'rallygrid',
            showPagingToolbar: true,
            showRowActionsColumn: true,
            editable: false,
            store: Ext.create('Rally.data.custom.Store', {
                data: data,
                groupField: 'Story'
            }),
            features: [{ftype:'groupingsummary'}],
            columnCfgs: [
                {
                    xtype: 'templatecolumn',text: 'ID',dataIndex: 'FormattedID',width: 100,
                    tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate'),
                    summaryRenderer: function() {
                        return "Totals"; 
                    }
                },
                {
                    text: 'Name',dataIndex: 'Name'
                },
                {
                    text: 'TimeSpent',dataIndex: 'TimeSpent',
                    summaryType: 'sum'
                },
                {
                    text: 'Estimate',dataIndex: 'Estimate',
                    summaryType: 'sum'
                }
            ]
        });

    }
});