<commit_before>Ext.define('CustomApp', {
    extend: 'Rally.app.App',
    componentCls: 'app',

    dayRange: 30,
    severityValues: [],

    launch: function() {
        Rally.sdk.dependencies.Analytics.load(this._loadDefectFilterValues, this);
    },

    // kickoff series of async value fetches for Defect attributes (severity, priority, etc)
    _loadDefectFilterValues: function() {
        Rally.data.ModelFactory.getModel({
            type: 'Defect',
            success: function(model) {
                this._loadDefectSeverityValues(model);
            },
            scope: this
        });
    },

    // Load custom defect 'severity' values for the filter pulldown
    _loadDefectSeverityValues: function(model) {
        this.severity = model.getField('Severity');
        var store = this.severity.getAllowedValueStore();
        store.load({
            callback: function(data) {
                _.each(data, function(el) {
                    if (el.data.StringValue !== "") {this.severityValues.push(el.data.StringValue);}
                }, this);
                this._loadDayRangeSelector();
            }, 
            scope: this
        }, this);
    },

    // create the 30/60/90 day range selector
    _loadDayRangeSelector: function() {

        this.add({
            xtype: 'dayrangepicker',
            itemId: 'dayRangePicker',
            defaultSelection: '30',   // 30|60|90
            autoLoadSelection: true
        });

        this.down('#dayRangePicker').on({
            on30clicked: function() {
                this.dayRange = DayRangePicker.THIRTY;
                this._getChartData();
            },
            on60clicked: function() {
                this.dayRange = DayRangePicker.SIXTY;
                this._getChartData();
            },
            on90clicked: function() {
                this.dayRange = DayRangePicker.NINETY;
                this._getChartData();
            },
            scope: this
        });

        //this._multiSelect();
        this._getChartData();
    },

    _getChartFilters: function() {
        var daysAgo = Ext.Date.add(new Date(), Ext.Date.DAY, -this.dayRange);
        var startOnISOString = Rally.util.DateTime.toIsoString(daysAgo, true);

        var filters = 
            [
                {
                    property: '_TypeHierarchy',
                    operator: 'in',
                    value: ['Defect']
                },
                {
                    property: 'Severity',
                    operator: 'in',
                    value: this.severityValues        // TODO: handle 'empty' or not selected severity
                },
                {
                    property: "Project",
                    value: this.getContext().getProject().ObjectID
                },
                {
                    property: "_ValidTo",
                    operator: ">=",
                    value: startOnISOString
                }
            ];

        return filters;

    },
    
    _getChartData: function() {

        var myFilters = this._getChartFilters();
        
        Ext.create('Rally.data.lookback.SnapshotStore', {
            listeners: {
                load: function(store,data,success) {
                  this._onDefectsLoaded(data);
                },
                scope: this
            },
            fetch: ['Name', 'Severity'],
            autoLoad: true,
            context: {
                workspace: this.getContext().getWorkspace()._ref,
                project: this.getContext().getProject()._ref,
                projectScopeUp: false,
                projectScopeDown: true
            },
            hydrate: ['Severity'],
            filters: myFilters,
            scope: this
        });
      
        
    },
    
    _getChartConfiguration: function() {
        return{
          chart: {
                type: 'area'
            },
            title: {
                text: 'Defect Trend'
            },
            subtitle: {
                text: 'Severity'
            },
            xAxis: {
                type: 'datetime'
            },
            yAxis: {
                title: {
                    text: 'Count'
                },
                labels: {
                    formatter: function() {
                        return this.value;
                    }
                }
            },
            tooltip: {
                shared: true
            },
            plotOptions: {
                area: {
                    stacking: 'normal',
                    lineColor: '#666666',
                    lineWidth: 1,
                    marker: {
                        lineWidth: 1,
                        lineColor: '#666666'
                    }
                }
            }
        };
    },
    
    _onDefectsLoaded: function (data) {

        var snapShotData = _.map(data,function(d){return d.data;});


        var metrics = [];
        _.each(this.severityValues, function(value) {
            metrics.push({
                as: value, f: 'filteredCount', filterField: 'Severity', filterValues: [value]
            });
        });
         
        // calculator config
        var config = {
          metrics: metrics,
          granularity: 'day',
          tz: 'America/Chicago',
          workDays: 'Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday'
        };
        
        var daysAgo = Ext.Date.add(new Date(), Ext.Date.DAY, -this.dayRange);

        var currentDate = Ext.Date.add(new Date(), Ext.Date.DAY, 0);

        var startOnISOString = Rally.util.DateTime.toIsoString(daysAgo, true);
        var upToDateISOString = Rally.util.DateTime.toIsoString(currentDate, true);

        
        calculator = new Rally.data.lookback.Lumenize.TimeSeriesCalculator(config);

        calculator.addSnapshots(snapShotData, startOnISOString, upToDateISOString);


        var hcConfig = [];
        _.each(this.severityValues, function(value) {
            hcConfig.push({name: value});
        });

        var hcData = Rally.data.lookback.Lumenize.arrayOfMaps_To_HighChartsSeries(calculator.getResults().seriesData, hcConfig);

        var dt;

        _.each(hcData, function(seriesObj) {
            dt = Ext.Date.format(daysAgo, 'Y-m-d').split("-");
            seriesObj.pointStart = Date.UTC(dt[0], dt[1] - 1, dt[2]);
            seriesObj.pointInterval = 24 * 3600 * 1000;
        });

        var myChart = Ext.create("Rally.ui.chart.Chart", {
            chartConfig: this._getChartConfiguration(),
            chartData: {
                series: hcData
            },
            itemId: 'myChart'
        });
        this.add(myChart);

        chart = this.down("#myChart");

        // HACK: need to remove load mask on high-charts due to lumenize lib loading issue
        var p = Ext.get(chart.id);
        elems = p.query("div.x-mask");
        _.each(elems, function(e) { e.remove(); });
        var elems = p.query("div.x-mask-msg");
        _.each(elems, function(e) { e.remove(); });
    }
});

<commit_msg>Works for defects with no assigned severity<commit_after>Ext.define('Rally.ui.picker.SonOfMultiObjectPicker', {
    extend: 'Rally.ui.picker.MultiObjectPicker',
    alias: 'widget.sonofrallymultiobjectpicker',
    _createStoreAndExpand: function() {
        var storeCreator = Ext.create('Rally.data.DataStoreCreator', {
            modelType: this.modelType,
            storeConfig: this.storeConfig,
            storeType: this.storeType
        });
        this.mon(storeCreator, 'storecreate', function(store) {
            this.store = store;
            this.expand();
        }, this, {single: true});
        storeCreator.createStore();
    }
});


Ext.define('CustomApp', {
    extend: 'Rally.app.App',
    componentCls: 'app',

    dayRange: 30,
    severityValues: [],     // custom values for defect 'severity'
    priorityValues: [],     // custom values for defect 'priority'
    stateValues: [],        // custom values for defect 'state'


    launch: function() {
        Rally.sdk.dependencies.Analytics.load(this._loadDefectFilterValues, this);
    },

    // kickoff series of async value fetches for Defect attributes (severity, priority, etc)
    _loadDefectFilterValues: function() {
        Rally.data.ModelFactory.getModel({
            type: 'Defect',
            success: function(model) {
                this._loadDefectSeverityValues(model);
            },
            scope: this
        });
    },

    // Load custom defect 'severity' values for the filter pulldown
    _loadDefectSeverityValues: function(model) {
        this.severity = model.getField('Severity');
        var store = this.severity.getAllowedValueStore();
        store.load({
            callback: function(data) {
                _.each(data, function(el) {
                    console.log(el.data.StringValue);
                    if (el.data.StringValue !== "") {this.severityValues.push(el.data.StringValue);}
                    else {this.severityValues.push("None");}
                }, this);
                this._loadDayRangeSelector();
            }, 
            scope: this
        }, this);
    },

    // create the 30/60/90 day range selector
    _loadDayRangeSelector: function() {

        this.add({
            xtype: 'dayrangepicker',
            itemId: 'dayRangePicker',
            defaultSelection: '30',   // 30|60|90
            autoLoadSelection: true
        });

        this.down('#dayRangePicker').on({
            on30clicked: function() {
                this.dayRange = DayRangePicker.THIRTY;
                this._getChartData();
            },
            on60clicked: function() {
                this.dayRange = DayRangePicker.SIXTY;
                this._getChartData();
            },
            on90clicked: function() {
                this.dayRange = DayRangePicker.NINETY;
                this._getChartData();
            },
            scope: this
        });

        //this._multiSelect();
        this._getChartData();
    },

    _getChartFilters: function() {
        var daysAgo = Ext.Date.add(new Date(), Ext.Date.DAY, -this.dayRange);
        var startOnISOString = Rally.util.DateTime.toIsoString(daysAgo, true);

        var filters = 
            [
                {
                    property: '_TypeHierarchy',
                    operator: 'in',
                    value: ['Defect']
                },
                {
                    property: 'Severity',
                    operator: 'in',
                    value: this.severityValues        // TODO: handle 'empty' or not selected severity
                },
                {
                    property: "Project",
                    value: this.getContext().getProject().ObjectID
                },
                {
                    property: "_ValidTo",
                    operator: ">=",
                    value: startOnISOString
                }
            ];

        return filters;

    },
    
    _getChartData: function() {

        var myFilters = this._getChartFilters();
        
        Ext.create('Rally.data.lookback.SnapshotStore', {
            listeners: {
                load: function(store,data,success) {
                  this._onDefectsLoaded(data);
                },
                scope: this
            },
            fetch: ['Name', 'Severity'],
            autoLoad: true,
            context: {
                workspace: this.getContext().getWorkspace()._ref,
                project: this.getContext().getProject()._ref,
                projectScopeUp: false,
                projectScopeDown: true
            },
            hydrate: ['Severity'],
            filters: myFilters,
            scope: this
        });
      
        
    },
    
    _getChartConfiguration: function() {
        return{
          chart: {
                type: 'area'
            },
            title: {
                text: 'Defect Trend'
            },
            subtitle: {
                text: 'Severity'
            },
            xAxis: {
                type: 'datetime'
            },
            yAxis: {
                title: {
                    text: 'Count'
                },
                labels: {
                    formatter: function() {
                        return this.value;
                    }
                }
            },
            tooltip: {
                shared: true
            },
            plotOptions: {
                area: {
                    stacking: 'normal',
                    lineColor: '#666666',
                    lineWidth: 1,
                    marker: {
                        lineWidth: 1,
                        lineColor: '#666666'
                    }
                }
            }
        };
    },
    
    _onDefectsLoaded: function (data) {

        var snapShotData = _.map(data,function(d){return d.data;});


        var metrics = [];
        _.each(this.severityValues, function(value) {
            metrics.push({
                as: value, f: 'filteredCount', filterField: 'Severity', filterValues: [value]
            });
        });
         
        // calculator config
        var config = {
          metrics: metrics,
          granularity: 'day',
          tz: 'America/Chicago',
          workDays: 'Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday'
        };
        
        var daysAgo = Ext.Date.add(new Date(), Ext.Date.DAY, -this.dayRange);

        var currentDate = Ext.Date.add(new Date(), Ext.Date.DAY, 0);

        var startOnISOString = Rally.util.DateTime.toIsoString(daysAgo, true);
        var upToDateISOString = Rally.util.DateTime.toIsoString(currentDate, true);

        
        calculator = new Rally.data.lookback.Lumenize.TimeSeriesCalculator(config);

        calculator.addSnapshots(snapShotData, startOnISOString, upToDateISOString);


        var hcConfig = [];
        _.each(this.severityValues, function(value) {
            hcConfig.push({name: value});
        });

        var hcData = Rally.data.lookback.Lumenize.arrayOfMaps_To_HighChartsSeries(calculator.getResults().seriesData, hcConfig);

        var dt;

        _.each(hcData, function(seriesObj) {
            dt = Ext.Date.format(daysAgo, 'Y-m-d').split("-");
            seriesObj.pointStart = Date.UTC(dt[0], dt[1] - 1, dt[2]);
            seriesObj.pointInterval = 24 * 3600 * 1000;
        });

        var myChart = Ext.create("Rally.ui.chart.Chart", {
            chartConfig: this._getChartConfiguration(),
            chartData: {
                series: hcData
            },
            itemId: 'myChart'
        });
        this.add(myChart);

        chart = this.down("#myChart");

        // HACK: need to remove load mask on high-charts due to lumenize lib loading issue
        var p = Ext.get(chart.id);
        elems = p.query("div.x-mask");
        _.each(elems, function(e) { e.remove(); });
        var elems = p.query("div.x-mask-msg");
        _.each(elems, function(e) { e.remove(); });
    }
});


{'fraction_non_alphanumeric': 0.11650614413816009, 'fraction_numerical': 0.006775157754898705, 'mean_word_length': 1.3834098464460978, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, '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': '1278628', 'n_tokens_mistral': 4265, 'n_tokens_neox': 3956, 'n_words': 738}