James S
James S

Reputation: 47

Report of Customer List that has all Defect based on the User Story's Release

I would like to get a report or custom list that displays all the defects where the defect environment is Production and the parent/associated User Story's release matches the release drop-down on the custom screen.

I found this story and it's close I think, but not sure how to link it to the release drop-down and also not sure how to display the User Story the defect is related to.

RALLY: Determine a parent User Story's release

The output should be the user story ID and Name along with the Defect ID and Name and possibly a few more columns.

I know I could do this via the API, but was trying to see if there is another way inside the existing Rally tools.

Thanks in advance for any help!

Upvotes: 1

Views: 319

Answers (1)

Kyle Morse
Kyle Morse

Reputation: 8400

You're in luck! I don't get to write apps as much as I'd like and I had some free time this afternoon so I whipped something up for you. Just create a release scoped custom page and add this code to a Custom HTML app on that page.

The app includes a field picker to change the displayed set of fields. I made a best guess at some useful ones to start with. It also includes a control to enable printing and exporting.

<!DOCTYPE html>
<html>
<head>
<title>DefectsByStoryInRelease</title>

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

<script type="text/javascript">
    Rally.onReady(function () {
        Ext.define('DefectsByStoryInRelease', {
            extend: 'Rally.app.TimeboxScopedApp',
            componentCls: 'app',

            scopeType: 'release',

            onScopeChange: function () {
                Ext.create('Rally.data.wsapi.TreeStoreBuilder').build({
                    models: ['defect'],
                    autoLoad: true,
                    enableHierarchy: true,
                    filters: this._getFilters()
                }).then({
                    success: this._onStoreBuilt,
                    scope: this
                });
            },

            _onStoreBuilt: function (store) {
                var modelNames = ['defect'],
                        context = this.getContext(),
                        gridBoard = this.down('rallygridboard');

                if (gridBoard) {
                    gridBoard.destroy();
                }

                this.add({
                    xtype: 'rallygridboard',
                    height: this.getHeight() - ((this.getHeader() && this.getHeader().getHeight()) || 0),
                    context: context,
                    modelNames: modelNames,
                    toggleState: 'grid',
                    stateful: false,
                    plugins: [
                        {
                            ptype: 'rallygridboardfieldpicker',
                            headerPosition: 'left',
                            modelNames: modelNames,
                            stateful: true,
                            stateId: context.getScopedStateId('fields')
                        },
                        {
                            ptype: 'rallygridboardactionsmenu',
                            menuItems: [
                                {
                                    text: 'Export...',
                                    handler: function () {
                                        window.location = Rally.ui.grid.GridCsvExport.buildCsvExportUrl(
                                                this.down('rallygridboard').getGridOrBoard());
                                    },
                                    scope: this
                                },
                                {
                                    text: 'Print...',
                                    handler: function () {
                                        Ext.create('Rally.ui.grid.TreeGridPrintDialog', {
                                            grid: this.down('rallygridboard').getGridOrBoard(),
                                            treeGridPrinterConfig: {
                                                largeHeaderText: 'Defects'
                                            }
                                        });
                                    },
                                    scope: this
                                }
                            ],
                            buttonConfig: {
                                iconCls: 'icon-export'
                            }
                        }
                    ],
                    gridConfig: {
                        store: store,
                        columnCfgs: [
                            'Name',
                            'Requirement',
                            'State',
                            'Priority',
                            'Severity'
                        ]
                    }
                });
            },

            _getFilters: function () {
                var scope = this.getContext().getTimeboxScope(),
                        release = scope.getRecord(),
                        filters = [{
                            property: 'Environment',
                            value: 'Production'
                        }];

                if (release) {
                    filters = filters.concat([

                        {
                            property: 'Requirement.Release.Name',
                            value: release.get('Name')
                        },
                        {
                            property: 'Requirement.Release.ReleaseStartDate',
                            value: release.get('ReleaseStartDate')
                        },
                        {
                            property: 'Requirement.Release.ReleaseDate',
                            value: release.get('ReleaseDate')
                        }
                    ]);
                } else {
                    filters.push({
                        property: 'Requirement.Release',
                        value: null
                    });
                }

                return filters;
            }
        });


        Rally.launchApp('DefectsByStoryInRelease', {
            name: "DefectsByStoryInRelease",
            parentRepos: ""
        });

    });
</script>


<style type="text/css">
    .app {
        /* Add app styles here */
    }

</style>

Upvotes: 1

Related Questions