<commit_before>Ext.define('Rally.apps.releasesummary.App', {
    extend: 'Rally.app.TimeboxScopedApp',
    componentCls: 'app',
    scopeType: 'release',

    addContent: function () {
        this.callParent(arguments);

        Rally.data.ModelFactory.getModels({
            types: ['UserStory', 'Defect'],
            success: function(models) {
                this.models = models;
                this._addContent();
            },
            scope: this
        });
    },

    _addContent: function() {
        this.add(
            {
                xtype: 'component',
                itemId: 'releaseInfo',
                componentCls: 'releaseInfo',
                tpl: [
                    '<p><b>About this release: </b><br />',
                    '<p class="release-notes">{notes}</p>',
                    'Additional information is available <a href="{detailUrl}" target="_top">here.</a></p>'
                ]
            }, 
            {
                xtype: 'container',
                itemId: 'stories',
                items: [{
                    xtype: 'displayfield',
                    itemId: 'story-title',
                    componentCls: 'gridTitle',
                    value: 'Stories:'
                }]
            }, 
            {
                xtype: 'container',
                itemId: 'defects',
                items: [{
                    xtype: 'displayfield',
                    itemId: 'defect-title',
                    value: 'Defects:',
                    componentCls: 'gridTitle'
                }]
            }
        );

        this._buildGrids();
        this._loadReleaseDetails();
    },

    onScopeChange: function() {
        this.callParent(arguments);

        this._refreshGrids();
        this._loadReleaseDetails();
    },

    _loadReleaseDetails: function() {
        var release = this.getContext().getTimeboxScope().getRecord();
        var releaseModel = release.self;

        releaseModel.load(Rally.util.Ref.getOidFromRef(release), {
            fetch: ['Notes'],
            success: function(record) {
                this.down('#releaseInfo').update({
                    detailUrl: Rally.nav.Manager.getDetailUrl(release),
                    notes: record.get('Notes')
                });
            },
            scope: this    
        });
    },

    _buildGrids: function() {
        var storyStoreConfig = this._getStoreConfig({
            model: this.models.UserStory,
            listeners: {
                load: this._onStoriesDataLoaded,
                scope: this
            }
        });
        this.down('#stories').add(this._getGridConfig({
            itemId: 'story-grid',
            model: this.models.UserStory,
            storeConfig: storyStoreConfig
        }));

        var defectStoreConfig = this._getStoreConfig({
             model: this.models.Defect,
             listeners: {
                load: this._onDefectsDataLoaded,
                scope: this
            }
        });
        this.down('#defects').add(this._getGridConfig({
            itemId: 'defect-grid',
            model: this.models.Defect,
            storeConfig: defectStoreConfig
        }));
    },

    _getStoreConfig: function(storeConfig) {
        return Ext.apply({
            autoLoad: true,
            fetch: ['FormattedID', 'Name', 'ScheduleState'],
            filters: this._getFilters(),
            sorters: [{
                property: 'FormattedID',
                direction: 'ASC'
            }],
            pageSize: 25
        }, storeConfig);
    },

    _getFilters: function() {
        return [
            {
                property: 'ScheduleState',
                operator: '>=',
                value: 'Accepted'
            },
            this.getContext().getTimeboxScope().getQueryFilter()
        ];
    },

    _getGridConfig: function(config) {
        return Ext.apply({
            xtype: 'rallygrid',
            componentCls: 'grid',
            columnCfgs: [
                {text: 'ID', dataIndex: 'FormattedID', xtype: 'templatecolumn',
                    tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate')}, 
                {text: 'Name', dataIndex: 'Name', flex: 3}, 
                {text: 'Schedule State', dataIndex: 'ScheduleState', flex: 1}
            ]
        }, config);
    },

    _refreshGrids: function() {
        var filters = this._getFilters();
        this.down('#defect-grid').filter(filters, true, true);
        this.down('#story-grid').filter(filters, true, true);
    },

    _onStoriesDataLoaded: function (store) {
        this.down('#story-title').update('Stories: ' + store.getTotalCount());
    },

    _onDefectsDataLoaded: function (store) {
        this.down('#defect-title').update('Defects: ' + store.getTotalCount());
    },

    getOptions: function() {
        return [
            {
                text: 'Print',
                handler: this._onButtonPressed,
                scope: this
            }
        ];
    },

    _onButtonPressed: function() {
        var release = this.getContext().getTimeboxScope().getRecord().get('Name');
        var title = release, options;

        var css = document.getElementsByTagName('style')[0].innerHTML;
        
        options = "toolbar=1,menubar=1,scrollbars=yes,scrolling=yes,resizable=yes,width=1000,height=500";
        var printWindow = window.open('', '', options);

        var doc = printWindow.document;

        var stories = this.down('#stories');
        var defects = this.down('#defects');
        var releaseinfo = this.down('#releaseInfo');

        doc.write('<html><head>' + '<style>' + css + '</style><title>' + title + '</title>');

        doc.write('</head><body class="landscape">');
        doc.write('<p>Release: ' + release + '</p><br />');<commit_msg>whoops added one more thing: proper style to the print window<commit_after>Ext.define('Rally.apps.releasesummary.App', {
    extend: 'Rally.app.TimeboxScopedApp',
    componentCls: 'app',
    scopeType: 'release',

    addContent: function () {
        this.callParent(arguments);

        Rally.data.ModelFactory.getModels({
            types: ['UserStory', 'Defect'],
            success: function(models) {
                this.models = models;
                this._addContent();
            },
            scope: this
        });
    },

    _addContent: function() {
        this.add(
            {
                xtype: 'component',
                itemId: 'releaseInfo',
                componentCls: 'releaseInfo',
                tpl: [
                    '<p><b>About this release: </b><br />',
                    '<p class="release-notes">{notes}</p>',
                    'Additional information is available <a href="{detailUrl}" target="_top">here.</a></p>'
                ]
            }, 
            {
                xtype: 'container',
                itemId: 'stories',
                items: [{
                    xtype: 'displayfield',
                    itemId: 'story-title',
                    componentCls: 'gridTitle',
                    value: 'Stories:'
                }]
            }, 
            {
                xtype: 'container',
                itemId: 'defects',
                items: [{
                    xtype: 'displayfield',
                    itemId: 'defect-title',
                    value: 'Defects:',
                    componentCls: 'gridTitle'
                }]
            }
        );

        this._buildGrids();
        this._loadReleaseDetails();
    },

    onScopeChange: function() {
        this.callParent(arguments);

        this._refreshGrids();
        this._loadReleaseDetails();
    },

    _loadReleaseDetails: function() {
        var release = this.getContext().getTimeboxScope().getRecord();
        var releaseModel = release.self;

        releaseModel.load(Rally.util.Ref.getOidFromRef(release), {
            fetch: ['Notes'],
            success: function(record) {
                this.down('#releaseInfo').update({
                    detailUrl: Rally.nav.Manager.getDetailUrl(release),
                    notes: record.get('Notes')
                });
            },
            scope: this    
        });
    },

    _buildGrids: function() {
        var storyStoreConfig = this._getStoreConfig({
            model: this.models.UserStory,
            listeners: {
                load: this._onStoriesDataLoaded,
                scope: this
            }
        });
        this.down('#stories').add(this._getGridConfig({
            itemId: 'story-grid',
            model: this.models.UserStory,
            storeConfig: storyStoreConfig
        }));

        var defectStoreConfig = this._getStoreConfig({
             model: this.models.Defect,
             listeners: {
                load: this._onDefectsDataLoaded,
                scope: this
            }
        });
        this.down('#defects').add(this._getGridConfig({
            itemId: 'defect-grid',
            model: this.models.Defect,
            storeConfig: defectStoreConfig
        }));
    },

    _getStoreConfig: function(storeConfig) {
        return Ext.apply({
            autoLoad: true,
            fetch: ['FormattedID', 'Name', 'ScheduleState'],
            filters: this._getFilters(),
            sorters: [{
                property: 'FormattedID',
                direction: 'ASC'
            }],
            pageSize: 25
        }, storeConfig);
    },

    _getFilters: function() {
        return [
            {
                property: 'ScheduleState',
                operator: '>=',
                value: 'Accepted'
            },
            this.getContext().getTimeboxScope().getQueryFilter()
        ];
    },

    _getGridConfig: function(config) {
        return Ext.apply({
            xtype: 'rallygrid',
            componentCls: 'grid',
            columnCfgs: [
                {text: 'ID', dataIndex: 'FormattedID', xtype: 'templatecolumn',
                    tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate')}, 
                {text: 'Name', dataIndex: 'Name', flex: 3}, 
                {text: 'Schedule State', dataIndex: 'ScheduleState', flex: 1}
            ]
        }, config);
    },

    _refreshGrids: function() {
        var filters = this._getFilters();
        this.down('#defect-grid').filter(filters, true, true);
        this.down('#story-grid').filter(filters, true, true);
    },

    _onStoriesDataLoaded: function (store) {
        this.down('#story-title').update('Stories: ' + store.getTotalCount());
    },

    _onDefectsDataLoaded: function (store) {
        this.down('#defect-title').update('Defects: ' + store.getTotalCount());
    },

    getOptions: function() {
        return [
            {
                text: 'Print',
                handler: this._onButtonPressed,
                scope: this
            }
        ];
    },

    _onButtonPressed: function() {
        var release = this.getContext().getTimeboxScope().getRecord().get('Name');
        var title = release, options;

        var css = document.getElementsByTagName('style')[0].innerHTML;
        
        options = "toolbar=1,menubar=1,scrollbars=yes,scrolling=yes,resizable=yes,width=1000,height=500";
        var printWindow = window.open('', '', options);

        var doc = printWindow.document;

        var stories = this.down('#stories');
        var defects = this.down('#defects');
        var releaseinfo = this.down('#releaseInfo');

        doc.write('<html><head>' + '<style>' + css + '</style><title>' + title + '</title>');

        doc.write('</head><body class="landscape">');
        doc.write('<p style="font-family:Arial,Helvetica,sans-serif;margin:5px">Release: ' + release + '</p><br />');
{'fraction_non_alphanumeric': 0.13721995926680244, 'fraction_numerical': 0.0024609640190088257, 'mean_word_length': 1.5708987783595114, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6993983', 'n_tokens_mistral': 3252, 'n_tokens_neox': 3092, 'n_words': 539}