rallyappsdk2

How to display ScheduleState and Blocked columns in custom Grid the way Rally's grid does


I'm trying to create a custom Rally app that displays data in a grid view. In another question Rally SDK App Using Grid with collapsible tree of children stories, nickm posted some sample code

Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
    var today = new Date().toISOString();
    Ext.create('Rally.data.wsapi.Store', {
            model: 'UserStory',
            fetch: ['ObjectID', 'FormattedID', 'Name', 'ScheduleState', 'Feature'],
            autoLoad: true,
            filters: [
                {
                    property: 'Iteration.StartDate',
                    operator: '<=',
                    value: today
                },
                {
                    property: 'Iteration.EndDate',
                    operator: '>=',
                    value: today
                },
                {
                    property: 'Feature',
                    operator: '!=',
                    value: null
                }
            ],
            listeners: {
                load: this._onDataLoaded,
                scope: this
            }
            });
},
_onDataLoaded: function(store, records){
    var that = this;
    var promises = [];
     _.each(records, function(story) {
        promises.push(that._getFeature(story, that));
    });

    Deft.Promise.all(promises).then({
        success: function(results) {
            that._stories = results;
            that._makeGrid();
        }
    });
},

_getFeature: function(story, scope) {
    var deferred = Ext.create('Deft.Deferred');
    var that = scope;
        var featureOid = story.get('Feature').ObjectID;
        Rally.data.ModelFactory.getModel({
        type: 'PortfolioItem/Feature',
        scope: this,
        success: function(model, operation) {
            fetch: ['State'],
            model.load(featureOid, {
                scope: this,
                success: function(record, operation) {
                    var featureState = record.get('State')._refObjectName;
                    var storyRef = story.get('_ref');
                    var storyOid  = story.get('ObjectID');
                    var storyFid = story.get('FormattedID');
                    var storyName  = story.get('Name');
                    var storyState = story.get('ScheduleState');
                    var feature = story.get('Feature');

                    result = {
                                "_ref"          : storyRef,
                                "ObjectID"      : storyOid,
                                "FormattedID"   : storyFid,
                                "Name"          : storyName,
                                "ScheduleState" : storyState,
                                "Feature"       : feature,
                                "FeatureState"  : featureState,
                                "FeatureID"     : featureOid   
                            };
                    deferred.resolve(result);    
                }
            });
        }
    });
    return deferred; 
},

_makeGrid: function() {
    var that = this;

    if (that._grid) {
        that._grid.destroy();
    }

    var gridStore = Ext.create('Rally.data.custom.Store', {
        data: that._stories,
        groupField: 'FeatureID',
        pageSize: 1000,
    });

    that._grid = Ext.create('Rally.ui.grid.Grid', {
        itemId: 'storyGrid',
        store: gridStore,
        features: [{ftype:'grouping'}],
        columnCfgs: [
            {
                text: 'Formatted ID', dataIndex: 'FormattedID', xtype: 'templatecolumn',
                tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate')
            },

            {
                text: 'Name', dataIndex: 'Name', 
            },
            {
                text: 'ScheduleState', dataIndex: 'ScheduleState', 
            },
            {
                text: 'Feature', dataIndex: 'Feature',
                renderer: function(val, meta, record) {
                    return '<a href="https://rally1.rallydev.com/#/detail/portfolioitem/feature/' + record.get('Feature').ObjectID + '" target="_blank">' + record.get('Feature').FormattedID + '</a>';
                }
            },
            {
                text: 'Feature State', dataIndex: 'FeatureState',
            }
        ]
    });

    that.add(that._grid);
    that._grid.reconfigure(gridStore);
}
});

I'd like to display the ScheduleState and Blocked columns the same way that the Rally Grid shows them (as graphic representations). I've tried to figure out how to use templatecolumn xtype by using the following in my columnCfgs block:

{   text: 'State', dataIndex: 'ScheduleState', xtype: 'templatecolumn',
                tpl: Ext.create('Rally.ui.renderer.template.ScheduleStateTemplate') }

This fails and causes a JS error in the sdk-debug.js:

Uncaught TypeError: Cannot read property 'getAllowedValueStore' of undefined sdk-debug.js:190539 Ext.define.loadStates

I get different errors with the Blocked column but I haven't been able to figure out how to get it to display as the red blocked icon.

This is what I'm trying to achieve


Solution

  • With some tweaking I expect this to work in the next release of AppSDK2, but right now the rendering of the ScheduleState and Blocked will only work with wsapi data store. Using

    tpl: Ext.create('Rally.ui.renderer.template.ScheduleStateTemplate')

    is not sufficient. Custom store has no access to the valid states.

    UPDATE

    Rendering of ScheduleState and Blocked works in the current x version of AppSDK2 as of the date of this update, 5/22

    <script type="text/javascript" src="/apps/x/sdk.js"></script>
    

    This fix will eventually make its way to the next official release of AppSDK2 but for now you may use it with x version of AppSDK2.

    Warning: x version of AppSDK is never stable - changes are made to it constantly.

    See full code example here.

    In x version of AppSDK you may do this:

    {
       text: 'ScheduleState', dataIndex: 'ScheduleState', xtype: 'templatecolumn',
          tpl: Ext.create('Rally.ui.renderer.template.ScheduleStateTemplate',
               {
                  states: ['Defined', 'In-Progress', 'Completed', 'Accepted'],
                  field: {name: 'ScheduleState' }
                })
    },
    {
       text: 'Blocked', dataIndex: 'Blocked', xtype: 'templatecolumn',
          tpl: Ext.create('Rally.ui.renderer.template.BlockedTemplate')
    }
    

    Also, for now, set this to false in the grid config:

    enableBlockedReasonPopover: false