VisualizerBase.coffee

The general structure of an incrementally update-able visualization follows these steps:

  1. Gather the parameters you'll need to specify the visualization a. Gather some info from Rally's standard WSAPI b. Gather some info from the user.

  2. Create a hash from info from above to be used as the key for cache lookup.

  3. Restore the cached calculation using LocalCache.

  4. Render the cached calculation. Leave space for updates on the x-axis. Show spinners for missing parts.

  5. Query the Lookback API for the incremental "snapshots" not found in the cache. Get one page's worth of updates. Maybe 10,000 snapshots max?

  6. Update the calculation/manipulation/aggregation of the snapshot data.

  7. Update the chart.

  8. If there are still more pages of snapshots to update repeat starting at step 5.

Classes

@class ChartVisualizerBase This is intended to the be the base class for ChartVisualizers. It assumes a template method pattern where the parts of the algorithm that have to do with saving to and restoring from the LocalCache (using localStorage API) and providing events for config changes or data updates.

You must override these methods: * initialize() - set @LumenizeCalculatorClass (implements Lumenize.iCalculator)

You may wish to override: * deriveFields(snapshots)

@cfg {Number} [refreshIntervalMilliseconds = 30 * 60 * 1000] Defaults to 30 minutes

@property {Object} userConfig This is whatever the users passes in under the @userConfig parameter in the constructor. It is useful for creating the cache hash. The contents of this will be visualizer specific

@property {Object} config Starts with all the values in userConfig but more may be added @property {Number} [config.refreshIntervalMilliseconds = 5 * 60 * 1000] The chart will automatically refresh after this many milliseconds @property {Object} [config.deriveFieldsConfig] If you include this, it will pass it into Lumenize.deriveFields as the config Object every time it gets new snapshots to process. @property {Boolean} [config.debug = false] @property {Object} config.lumenizeCalculatorConfig The config that will be passed to the Lumenize calculator upon instantiation. Do not put x-axis range info in here.

@property {Object} projectAndWorkspaceScope @property {Number} projectAndWorkspaceScope.workspaceOID @property {Boolean} projectAndWorkspaceScope.projectScopingUp @property {Boolean} projectAndWorkspaceScope.projectScopingDown @property {Number} projectAndWorkspaceScope.projectOID

@property {Object} workspaceConfiguration Has whatever fields come from Rally but WorkDays and TimeZone (note Caps) are often used by calculators

@property {Lumenize.iCalculator} LumenizeCalculatorClass Must be set; typically in your initialize() method

@property {Object} visualizationData This is where you store the data that you want to communicate to your visualizations. It will be passed into createVisualizationCB.

@property {iAnalyticsQuery} analyticsQuery Instantiate this in your onNewDataAvailable() method.

@property {String} upToDateISOString A ISOString (e.g. '2012-01-01T12:34:56.789Z') indicating the last moment that this chart is up to date. You should not set this but you can read from it. It will be set when new snapshots are added or it's restored from the cache. @readonly

Instance Methods

constructor(@visualizations, @userConfig, @createVisualizationCB)

You should not have a constructor for the sub-class. Rather, put your code in initialize(). If for some crazy reason you really want a constructor, make sure it looks like this: constructor: (myCustomArgument, remainingArguments...) -> # Any code you want to execute before initialize(). Use myCustomArgument. super(remainingArguments...) # Any code you want to execute after initialize(). Use myCustomArgument.

getProjectAndWorkspaceScope()

getWorkspaceConfiguration()

onConfigOrScopeUpdated()

getAsOfISOString()

onSnapshotsReceieved(snapshots, startOn, endBefore, queryInstance)

newDataExpected(paddingDelay, etlDelay)

removeFromCacheAndRecalculate()

updateCalculator(snapshots, startOn, endBefore, rest...)

@method updateCalculator Allows you to incrementally add snapshots to this calculator. It will also update the cache. @param {Object[]} snapshots An array of temporal data model snapshots. @param {String} startOn A ISOString (e.g. '2012-01-01T12:34:56.789Z') indicating the time start of the period of interest. On the second through nth call, this must equal the previous endBefore. @param {String} endBefore A ISOString (e.g. '2012-01-01T12:34:56.789Z') indicating the moment just past the time period of interest. This should be the ETLDate from the results of your query to the Lookback API.

initialize()

deriveFieldsOnSnapshots(snapshots)

createVisualization()

updateVisualization()

onNewDataAvailable()

updateVisualizationData()

getHashForCache()