text:             Ext.define('CustomApp', {
                  extend: 'Rally.app.App',
                  componentCls: 'app',
  				items: [
                      {
                          xtype: 'container',
                          itemId: 'releaseFilter'
                      },
                      {
                          xtype: 'container',
                          itemId: 'storyGrid',
                          width: 1400
                      },
                      {
                          xtype: 'container',
                          itemId: 'featGrid',
                          width: 1400
                      }
                  ],
                  launch: function() {
  				
  					console.log("Our first App");
  					var updateSchedulState = false; 
  					var recordsToUpdate;
  					var _grid;
  					var _storyGrid;
  
  					//this._loadKanbanCFD();
  										
  					var store = Ext.create('Rally.data.wsapi.Store', {
  						model: 'User Story',
  						autoLoad: false,
  						fetch: ['FormattedID', 'Name', 'ScheduleState', 'c_KanbanStateCE', 'Project', 'Feature', 'Release', 'Description'],
  						filters: [
  							{
  							property: 'Project.Name',
  							operator: '=',
  							value: 'CE Kanban'
  							},
  							{
  							property: 'Release.Name',
  							operator: '=',
  							value: '14Q2'
  							}
  						],
  						listeners: {
  							load: function(myStore, myData, success) {
  								console.log("Got Data!", success);	
  								
  								console.log("MY Store", myStore);
  								
  								console.log("My Data", myData);
  								
  								this._initSupplementaryStores(myStore, myData);
  
  							},
  							scope: this
  						}
  					});
  					
  					this.down("#releaseFilter").add({
  						xtype: 'rallyreleasecombobox',
  						valueField: '_refObjectName',
  						listeners: {
  							change: function(newValue, oldValue, eOpts) {
  								if (newValue != oldValue) {
  									store.clearFilter(true);
  									store.filter([
  										{							
  										property: 'Project.Name',
  										operator: '=',
  										value: 'CE Kanban'
  										},
  										{
  										property: 'Release.Name',
  										operator: '=',
  										value: newValue.value}
  									]);
  									
  									store.load();
  								
  								}
  							},
  							scope: this
  						
  						}
  						
  					});
  				},
  					
  
  				
  				_initSupplementaryStores: function(storyStore, storyData) {
  					var featidfilters = Ext.create('Rally.data.wsapi.Filter', { property: 'FormattedID', operator: '=', value: '0'});
  					
  					featids = [];
  					Ext.Array.each(storyData, function(story) {
                          //Perform custom actions with the data here
                          //Calculations, etc.
  						feature = story.get('Feature');
  						if (feature) {
  							featidfilters = featidfilters.or(Ext.create('Rally.data.wsapi.Filter', { property: 'FormattedID', operator: '=', value: feature.FormattedID}));						
  							featids.push(feature.FormattedID);
  						}
                      });
  					
  					Rally.data.ModelFactory.getModel({
  						type: 'PortfolioItem/Feature',
  						success: function(featureModel) {
  							console.log("Model: ", featureModel);
  							this._onDataLoaded(storyStore, storyData, featureModel);
  						},
  						scope: this
  					});
  					//console.log("Feature Filters: ", featids);
  					/*var featureStore = Ext.create('Rally.data.wsapi.Store', {
                          model: 'PortfolioItem/Feature',
                          autoLoad: true,
  						/*filters: function(item) {
  							console.log("item: ", item);
  							return (featids.indexOf(item.FormattedID) != -1); 
  						},
  						//filters: featidfilters,
                          listeners: {
                              load: function(featureStore, featureData, success) {
  								this._onDataLoaded(storyStore, storyData, featureStore, featureData);
  							}, 
                              scope: this
                          }
                      });*/
  				},
  				
  				_onDataLoaded: function(storyStore, storyData, featureModel) {
                      var records = [];
  					var recordMap = {};
  					var reqctr = 0;
  					var reqresolved = 0;
                      Ext.Array.each(storyData, function(record) {
                          //Perform custom actions with the data here
                          //Calculations, etc.
  						var initiativeName = "";
  						console.log(record);
  						var feature = record.get('Feature');
  						if (feature) {
  							console.log("feature: ", feature);
  							kanbanState = record.get('c_KanbanStateCE');
  							//feature = featureStore.findRecord('FormattedID', feature.FormattedID);
  							if (recordMap.hasOwnProperty(feature.FormattedID)) {
  
  								val = recordMap[feature.FormattedID];
  								console.log("Fround record: ", val);
  								val.StoryCount++;
  								val.CompletedStories += (kanbanState=="Accepted")?1:0;
  								
  								val.PctDoneStoryCount = (val.CompletedStories/val.StoryCount * 100).toFixed(0);
  								
  							} else {
  								reqctr++;
  								records.push(feature);
  								recordMap[feature.FormattedID] = feature;
  								var completedStories = (kanbanState=="Accepted")?1:0;
  								var pctComplete = completedStories * 100;
  								feature.PctDoneStoryCount = pctComplete;
  								feature.StoryCount = 1;
  								feature.CompletedStories = completedStories;
  							
  								featureModel.load(feature._ref, {
  									scope: this,
  									callback: function(fullFeature, operation) {
  										reqresolved++;
  										if(operation.wasSuccessful()) {
  											//feature = this._setupFeatureGrid(result, record);
  											
  											if (fullFeature.data.Parent) {
  												initiativeName = fullFeature.data.Parent.Name;
  											}
  											//var id = feature.data.FormattedID;
  											//var name = feature.data.Name;
  											var project = (fullFeature.data.Project)?fullFeature.data.Project.Name:"";
  											var state = (fullFeature.data.State)?fullFeature.data.State.Name:"";
  												
  											feature.ProjName = project;
  											feature.StateName = state;
  											feature.InitName = initiativeName;
  											
  											/*var customrec = {
  												FeatureId: id,
  												Name: name,
  												PctDoneStoryCount: pctComplete,
  												InitiativeName: initiativeName,
  												Project: project,
  												State: state,
  												StoryCount: 1,
  												CompletedStories: completedStories
  											};*/
  											
  										}
  										console.log("Req Resolved: " + reqresolved);
  										if (reqresolved == reqctr) {
  											this._setupFeatureGrid(records, storyData.length);
  										}
  									}
  								});
  							}
  						}
  				
  						if (this.updateScheduleState) {
  							this._updateScheduleState(record);
  							storyStore.sync({
  								success: function(batch, options) {
  									console.log("Success!");
  								},
  								failure: function(batch, options) {
  									console.log("Success!");
  								}
  							});				
  						}
  						
  						/*customrec = {
  							FormattedID: record.get('FormattedID'),
                              ScheduleState: record.get('ScheduleState'),
  							c_KanbanStateCE: record.get('c_KanbanStateCE'),
                              Name: record.get('Name'),
  							Feature: featureName,
  							Initiative: initiativeName,
                              Tasks: record.get('Tasks').length,
                              Defects: record.get('Defects').length,
  							Notes: record.get('Notes')
                          }*/
  						
                          /*records.push({
  							FormattedID: record.get('FormattedID'),
                              ScheduleState: record.get('ScheduleState'),
  							c_KanbanStateCE: record.get('c_KanbanStateCE'),
                              Name: record.get('Name'),
  							Feature: featureName,
  							Initiative: initiativeName,
                              Tasks: record.get('Tasks').length,
                              Defects: record.get('Defects').length,
  							Notes: record.get('Notes')
                          });*/
  						
  						
                      },		
  					this
  					);						
  					console.log("Adding : Story Grid" , storyStore);
  					
  					this._setupStoryGrid(storyStore);
  				},
  					
  				_updateScheduleState: function(record) {
  					var kanbanToScrum = [];
  					kanbanToScrum.None = 'Needs Definition';
  					kanbanToScrum.Defined = 'Defined';
  					kanbanToScrum['Analysis/Design'] = 'In-Progress';
  					kanbanToScrum['Design verified'] =  'In-Progress';
  					kanbanToScrum.Coding =  'In-Progress';
  					kanbanToScrum.Done =  'Completed';
  					kanbanToScrum.Accepted =  'Accepted';
  					
  					console.log(kanbanToScrum);
  					if (record.get('c_KanbanStateCE')) {
  						newSchedState = kanbanToScrum[record.get('c_KanbanStateCE')];
  						if (newSchedState != record.get('ScheduleState')) {
  							record.beginEdit();
  							record.set('ScheduleState', newSchedState);	
  							record.set('Notes', newSchedState);	
  
  							record.endEdit();
  							//record.commit();
  							record.save({
  								callback: function(records,operation,success) {
  									console.log("Records: ", records);
  									console.log("Operation: ", operation);
  									console.log("Success: ", success);
  								}
  							});
  							console.log('Story: ', record.get('Name'), ' State:', record.get('c_KanbanStateCE'),  ' : ', newSchedState, record.get('ScheduleState'));
  						}
  					}									
  				},
  				
  				_setupFeatureGrid: function(records,length) {
  					if (this._grid) {
  						console.log("Updating Grid");
  						this._loadGrid(records,length);
  					} else {
  						console.log("Loading Grid");
  						this._loadGrid(records,length);
  					}					
  				},
  			
  				_loadGrid: function(records, length) {
  					console.log("Records: ", records);
  					this.down("#featGrid").add({
  						xtype: 'rallygrid',
  						store: Ext.create('Rally.data.custom.Store', {
  							data: records,
  							pageSize: length
  						}),
  						scope: this,
  						columnCfgs: [
  							{
  								text: 'ID', dataIndex: 'FormattedID'
  							},
  							{
  								text: 'Name', dataIndex: 'Name', flex: 1
  							},
  							{
  								text: '% Done by Story Count', dataIndex: 'PctDoneStoryCount'
  							},
  							{
  								text: '% Done by Plan Estimate', dataIndex: 'PctDoneStoryCount'
  							},
  							{
  								text: 'Parent', dataIndex: 'InitName'
  							},
  							{
  								text: 'Project', dataIndex: 'ProjName'
  							},
  							{
  								text: 'State', dataIndex: 'StateName'
  							},
  							{
  								text: 'Stories', dataIndex: 'StoryCount'
  							}
  						],
  						listeners: {
  							add: function(component, idx , eOpt ) {
  								console.log("My Grid: ", component);
  								this._grid = component;
  							},
  							scope: this
  						}
                      });
  
  				},
  				
  				_setupStoryGrid: function(store) {
  					if (this._storyGrid) {
  						console.log("Updating Grid");
  						this._loadStoryGrid(store);
  					} else {
  						console.log("Loading Grid");
  						this._loadStoryGrid(store);
  					}					
  				},
  				
  				
  				
  				
  				_loadStoryGrid: function(storyStore, length) {
  				
  				
  					var rowTpl = new Ext.XTemplate(
  						'<table style="border:1px solid black">',
  						'<tpl for=".">',
  							'<tr style="border:1px solid black">',
  								'<td>{Feature.Name}</td>',
  								'<td>{FormattedID}</td>',
  								'<td>{Name}</td>',
  							'</tr>',
  							'<tr style="border:1px solid black">',
  								'<td colspan=3>{Description}</td>',
  							'</tr/>',
  						'</tpl>',
  						'</table>'
  					);
  
  					this.down("#storyGrid").add({
  						xtype: 'dataview',
  						store: storyStore,
  						scope: this,
  						tpl: rowTpl,
  						emptyText: ''
  					});
  					/*this.down("#storyGrid").add({
  						xtype: 'rallygrid',
  						store: storyStore,
  						scope: this,
  						columnCfgs: [
  							{
  								text: 'Feature', dataIndex: 'Feature'
  							},
  							{
  								text: 'FormattedID', dataIndex: 'FormattedID'
  							},
  							{
  								text: 'Name', dataIndex: 'Name'
  							},
  							/*{
  								text: 'KanbanState', dataIndex: 'c_KanbanStateCE'
  							},
  							{
  								text: 'Schedule State', dataIndex: 'ScheduleState'
  							},
  							{
  								text: 'Description', dataIndex: 'Description', flex: 1
  							}/*,
  							{
  								text: 'Defects', dataIndex: 'Defects'
  							},
  							{
  								text: 'Tasks', dataIndex: 'Tasks'
  							}
  						],
  						listeners: {
  							add: function(component, idx , eOpt ) {
  								console.log("My Grid: ", component);
  								this._storyGrid = component;
  							},
  							scope: this
  						}
                      });*/
  
  				}
  								
  /*				_loadKanbanCFD: function() {
  					stateFieldValues = ['None', 'Defined', 'Analysis/Design', 'Design verified', 'Coding', 'Done', 'Accepted'];
  					Ext.define('My.CFDCalculator', {
  						extend: 'Rally.data.lookback.calculator.TimeSeriesCalculator',
  
  						getMetrics: function () {
  							for (var i = 0; i < stateFieldValues.length; ++i) {
  								metrics.push(
  									{as: stateFieldValues[i], groupByField: 'c_KanbanStateCE', allowedValues: [stateFieldValues[i]], f: 'groupByCount', display: 'area'}
  								);
  							}
  							return metrics;
  						return  [
  							  {f: 'groupBySum', field: 'PlanEstimate', groupByField: 'c_KanbanStateCE', allowedValues: allowedValues},
  							  {f: 'groupByCount', groupByField: 'c_KanbanStateCE', allowedValues: allowedValues, prefix: 'Count '},
  							]
  						}
  					});
  					
  					var ss = Ext.create('Rally.data.lookback.SnapshotStore', {
  						listeners: {
  							load: function(store, data, success) {
  								console.log("LookbackStore Records: ", store);
  								console.log("Successful?: ", data);
  								console.log("Opts: ", success);
  							}
  						},
  						autoLoad: true,
  						fetch: ['c_KanbanStateCE', 'PlanEstimate'],
  						hydrate: ['c_KanbanStateCE'],
  						filters: [
  							{
  								property: '_TypeHierarchy',
  								operator: 'in',
  								value: ['Defect', 'HierarchicalRequirement']
  							},
  							{
  								property: '_ProjectHierarchy',
  								operator: '=',
  								value: 14269684724
  							}
  						]
  					});
  					
  					
  					this.add({
  						 xtype: 'rallychart',
  						 
  						 store: ss,
  						 storeConfig: {},
  						 /*storeType: 'Rally.data.lookback.SnapshotStore',
  						 storeConfig: {
  							 find: {
  								 _TypeHierarchy: 'HierarchicalRequirement',
  								 _ProjectHierarchy: 14269684724,
  								 Children: null
  							 },
  							 fetch: ['c_KanbanStateCE', 'PlanEstimate'],
  							 hydrate: ['c_KanbanStateCE'],
  							 compress: true,
  							 load: function(store, data, success) {
  								console.log("Store: ", store);
  								console.log("Data?: ", data);
  								console.log("Success: ", success);
  							 }
  						 },
  
  						 calculatorType: 'My.CFDCalculator',
  						 calculatorConfig: {},
  
  						 chartConfig: {
  							 chart: {
  								 type: 'area'
  							 },
  							 title: {
  								 text: 'Kanban CFD'
  							 },
  							xAxis: {
  								title: {
  									text: "Date"
  								}
  							},
  							yAxis: [
  								{
  									title: {
  										text: "Points"
  									}
  								}
  							],
  							plotOptions: {
  								area: {
  									stacking: 'normal',
  									lineColor: '#666666',
  									lineWidth: 1,
  									marker: {
  										lineWidth: 1,
  										lineColor: '#666666'
  									}
  								}
  							}							
  						}
  					 });
  				
  				
  				
  				}*/
  			
  			});