Search code examples
javascriptrallyappsdk2

How to add a Release filter on the PortfolioItem/Feature object


Using AppSDK 2.0, how can I see the "Release" field in the PortfolioItem/Feature when I create a store?


Solution

  • Release needs to be among the fetched fields in WsapiDataStore:

    fetch: ['FormattedID','Name','UserStories','Release']
    

    But then in a Rally.data.custom.Store, to account for Features that are not assigned to a release, this condition is used:

    Release: (release && release.Name) || 'None'
    

    Here is the code:

    Ext.define('CustomApp', {
        extend: 'Rally.app.App',
        componentCls: 'app',
    
        launch: function() {
        Ext.create('Rally.data.WsapiDataStore', {
            model: 'PortfolioItem/Feature',
            fetch: ['FormattedID','Name','UserStories','Release'],
            pageSize: 100,
            autoLoad: true,
            listeners: {
            load: this._onDataLoaded,
            scope: this
            }
        });
        },
    
        _createGrid: function(features) {
         this.add({
            xtype: 'rallygrid',
            store: Ext.create('Rally.data.custom.Store', {
            data: features,
            pageSize: 100
            }),
    
            columnCfgs: [
            {
               text: 'Formatted ID', dataIndex: 'FormattedID', xtype: 'templatecolumn',
                tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate')
            },
            {
                text: 'Name', dataIndex: 'Name'
            },
            {
                text: 'Release', dataIndex: 'Release'
            },
            {
                text: 'Story Count', dataIndex: 'StoryCount'
            },
            {
                text: 'User Stories', dataIndex: 'UserStories', 
                renderer: function(value) {
                var html = [];
                Ext.Array.each(value, function(userstory){
                    html.push('<a href="' + Rally.nav.Manager.getDetailUrl(userstory) + '">' + userstory.FormattedID + '</a>')
                });
                return html.join(', ');
                }
            }
            ]
    
        });
        },
        _onDataLoaded: function(store, data){
            var features = [];
            var pendingstories = data.length;
            //debugger;
            Ext.Array.each(data, function(feature) {
                    var release = feature.get('Release');
                    var f  = {
                    FormattedID: feature.get('FormattedID'),
                    Name: feature.get('Name'),
                    Release: (release && release.Name) || 'None',                             
                    _ref: feature.get("_ref"),
                    StoryCount: feature.get('UserStories').Count,
                    UserStories: []
                    };
    
                    var stories = feature.getCollection('UserStories');
                   stories.load({
                    fetch: ['FormattedID'],
                    callback: function(records, operation, success){
                        Ext.Array.each(records, function(story){
                        var number = story.get('DirectChildrenCount');  
                        if (number == 0) {
                            f.UserStories.push({_ref: story.get('_ref'),
                                FormattedID: story.get('FormattedID')
                                });}
                        }, this);
    
                        --pendingstories;
                        if (pendingstories === 0) {
                        this._createGrid(features);
                        }
                    },
                    scope: this
                    });
                    features.push(f);
            }, this);
        }             
    });