Reputation: 47
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
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