-_ = require 'kraken/util/underscore'
-op = require 'kraken/util/op'
+{ _, op,
+} = require 'kraken/util'
Backbone = require 'backbone'
constructor : function BaseModel
@__class__ = @constructor
- @__super__ = @constructor.__super__
- @__superclass__ = @__super__.constructor
- # Backbone.NestedModel ...
+ @__superclass__ = @..__super__.constructor
Backbone.Model ...
@trigger 'create', this
# if _.str.contains key, '.'
# _.setNested @attributes, key, value, opts
# else
- # @__super__.set.call this, key, value, opts
+ # Backbone.Model::set.call this, key, value, opts
#
# this
#
__bind__ : []
+
+ constructor : function BaseList
+ @__class__ = @constructor
+ @__superclass__ = @..__super__.constructor
+ Backbone.Collection ...
+ @trigger 'create', this
+
initialize : ->
- @__super__ = @constructor.__super__
_.bindAll this, ...@__bind__ if @__bind__.length
BaseView = exports.BaseView = Backbone.View.extend do # {{{
ctorName : 'BaseView'
- # A list of method-names to bind on initialize; set this on a subclass to override.
+ /**
+ * A list of method-names to bind on initialize; set this on a subclass to override.
+ * @type Array<String>
+ */
__bind__ : []
+ /**
+ * @type Array<BaseView>
+ */
+ subviews : []
+
+ constructor : function BaseView
+ @__class__ = @constructor
+ @__superclass__ = @..__super__.constructor
+ @subviews = []
+ Backbone.View ...
+ @trigger 'create', this
+
initialize: ->
- @__super__ = @constructor.__super__
_.bindAll this, ...@__bind__ if @__bind__.length
@model.view = this
IGNORED_TAGS : <[ callback deprecated debugging ]>
+ constructor: function ChartOption
+ Field ...
+
initialize : ->
# console.log "#this.initialize!"
Field::initialize ...
ctorName : 'ChartOptionList'
model : ChartOption
+
+ constructor: function ChartOptionList
+ FieldList ...
+
/**
* Override to omit defaults from URL.
*/
'click .collapsed' : 'onClick'
+ constructor: function ChartOptionView
+ FieldView ...
+
render: ->
- @__super__.render ...
+ FieldView::render ...
@$el.addClass 'collapsed' if @isCollapsed
this
template : require 'kraken/template/chart-scaffold'
collectionType : ChartOptionList
subviewType : ChartOptionView
- fields : '.fields'
+ fields : '.fields'
# GraphView will set this
ready : false
+ constructor: function ChartOptionScaffold
+ Scaffold ...
initialize : ->
@render = _.debounce @render.bind(this), DEBOUNCE_RENDER
render: ->
# console.log "#this.render() -> .isotope()"
- # @__super__.render ...
+ # Scaffold::render ...
return this unless @ready
container = if @fields then @$el.find @fields else @$el
container
* layout after collapse events.
*/
addOne: (field) ->
- view = @__super__.addOne ...
+ view = Scaffold::addOne ...
view.on 'change:collapse render', @render
view
--- /dev/null
+Seq = require 'seq'
+{ _, op,
+} = require 'kraken/util'
+{ BaseView,
+} = require 'kraken/base'
+{ DataSetView,
+} = require 'kraken/dataset/dataset-view'
+{ MetricEditView,
+} = require 'kraken/dataset/metric-edit-view'
+
+
+/**
+ * @class
+ */
+DataView = exports.DataView = BaseView.extend do # {{{
+ ctorName : 'DataView'
+ tagName : 'section'
+ className : 'data-ui'
+ template : require 'kraken/template/data'
+
+ data : {}
+
+
+
+ constructor: function DataView
+ BaseView ...
+
+ initialize: ->
+ @graph_id = @options.graph_id
+ BaseView::initialize ...
+
+ @load()
+
+ # @subviews.push @dataset_view = new DataSetView {@model, @graph_id}
+ # @$el.append @dataset_view.render().el
+ # @dataset_view.on 'edit-metric', @editMetric, this
+ #
+ # @subviews.push @metric_edit_view = new MetricEditView {dataset:@model, @graph_id}
+ # @$el.append @metric_edit_view.render().hide().el
+
+
+ toTemplateLocals: ->
+ attrs = _.clone @model.attributes
+ { $, _, op, @model, view:this, @data, @graph_id } import attrs
+
+
+ load: ->
+ $.getJSON '/datasources/all', (@data) ~>
+ @ready = true
+ @render()
+ @trigger 'ready', this
+
+ # Don't rebuild HTML, simply notify subviews
+ render: ->
+ BaseView::render ...
+
+ # _.invoke @subviews, 'render'
+ this
+
+ editMetric: (metric) ->
+ @metric_edit_view.editMetric metric
+
+# }}}
--- /dev/null
+Seq = require 'seq'
+ColorBrewer = require 'colorbrewer'
+
+{ _, op,
+} = require 'kraken/util'
+{ BaseModel, BaseList,
+} = require 'kraken/base'
+{ Metric, MetricList,
+} = require 'kraken/dataset/metric-model'
+{ DataSource, DataSourceList,
+} = require 'kraken/dataset/datasource-model'
+
+
+
+/**
+ * @class
+ */
+DataSet = exports.DataSet = BaseModel.extend do # {{{
+ ctorName : 'DataSet'
+ urlRoot : '/datasets'
+
+ /**
+ * @type DataSourceList
+ */
+ sources : []
+
+ /**
+ * @type MetricList
+ */
+ metrics : []
+
+
+ constructor: function DataSet
+ BaseModel ...
+
+ initialize : ->
+ BaseModel::initialize ...
+ @sources = new DataSourceList @attributes.sources
+ @metrics = new MetricList @attributes.metrics
+
+
+ defaults : ->
+ sources : [] # XXX: needed? metrics now implies this info
+ metrics : []
+ # lines : []
+
+
+ /**
+ * @returns {Array} The reified dataset, materialized to an array of data-series arrays.
+ */
+ getData: ->
+ '/data/datasources/non_mobile_pageviews_by.timestamp.language.csv'
+
+ newMetric: ->
+ index = @metrics.length
+ @metrics.add m = new Metric { index, color:ColorBrewer.Spectral[11][index] }
+ m
+
+
+# }}}
+
--- /dev/null
+{ _, op,
+} = require 'kraken/util'
+{ BaseView,
+} = require 'kraken/base'
+
+
+/**
+ * @class
+ */
+DataSetView = exports.DataSetView = BaseView.extend do # {{{
+ ctorName : 'DataSetView'
+ tagName : 'section'
+ className : 'dataset-ui dataset'
+ template : require 'kraken/template/dataset'
+
+ events:
+ 'click .new-metric-button' : 'newMetric'
+ 'click .metrics .dataset-metric' : 'editMetric'
+
+ views_by_cid : {}
+ active_view : null
+
+
+ constructor: function DataSetView
+ BaseView ...
+
+ initialize: ->
+ @graph_id = @options.graph_id
+ BaseView::initialize ...
+ @views_by_cid = {}
+ @model.metrics.on 'add', @addMetric, this
+
+
+ newMetric: ->
+ # triggers 'add' on @model.metrics
+ @model.newMetric()
+ false
+
+ addMetric: (metric) ->
+ console.log "#this.addMetric!", metric
+ if metric.view
+ _.remove @subviews, metric.view
+ delete @views_by_cid[metric.cid]
+
+ @subviews.push view = new DataSetMetricView {model:metric, @graph_id}
+ @views_by_cid[metric.cid] = view
+ @$el.find '.metrics' .append view.render().el
+
+ # @render()
+ view
+
+ editMetric: (metric) ->
+ console.log "#this.editMetric!", metric
+ if metric instanceof [jQuery.Event, Event]
+ metric = $ metric.currentTarget .data 'model'
+ view = @views_by_cid[metric.cid]
+ console.log ' --> metric:', metric, 'view:', view
+
+ @$el.find '.metrics' .removeClass 'metric-active'
+ view.$el.addClass 'metric-active'
+ view.$el.find '.activity-arrow' .css 'font-size', 2+view.$el.height()
+ @trigger 'edit-metric', metric
+
+# }}}
+
+
+
+/**
+ * @class
+ */
+DataSetMetricView = exports.DataSetMetricView = BaseView.extend do # {{{
+ ctorName : 'DataSetMetricView'
+ tagName : 'tr'
+ className : 'dataset-metric metric'
+ template : require 'kraken/template/dataset-metric'
+
+
+
+ constructor: function DataSetMetricView
+ BaseView ...
+
+ initialize: ->
+ @graph_id = @options.graph_id
+ BaseView::initialize ...
+
+
+ toTemplateLocals: ->
+ m = @model.toJSON()
+ m import
+ graph_id : @graph_id
+ viewClasses : _.compact([
+ if @model.isOk() then 'valid' else 'invalid',
+ if m.visible then 'visible' else 'hidden',
+ 'disabled' if m.disabled,
+ ]).map( -> "metric-#it" ).join ' '
+ source :
+ if m.source_id and m.source_col_name
+ "#{m.source_id}.#{m.source_col_name}"
+ else
+ 'No source'
+ timespan :
+ if _.every ts = m.timespan, op.ok
+ "#{ts.start} to #{ts.end} by #{ts.step}"
+ else
+ '—'
+
+ # XXX: Icons/classes for visible/disabled?
+ { $, _, op, @model, view:this } import m
+
+# }}}
+
--- /dev/null
+{ _, op,
+} = require 'kraken/util'
+{ BaseModel, BaseList, BaseView,
+} = require 'kraken/base'
+
+
+/**
+ * @class
+ */
+DataSource = exports.DataSource = BaseModel.extend do # {{{
+ ctorName : 'DataSource'
+ urlRoot : '/datasources'
+
+
+ constructor: function DataSource
+ BaseModel ...
+
+ initialize: ->
+ BaseModel::initialize ...
+
+
+ defaults: ->
+ {}
+
+ url: ->
+ "/data/#{@id}.json"
+
+# }}}
+
+
+
+/**
+ * @class
+ */
+DataSourceList = exports.DataSourceList = BaseList.extend do # {{{
+ ctorName : 'DataSourceList'
+ urlRoot : '/datasources'
+ model : DataSource
+
+ constructor: function DataSourceList
+ BaseList ...
+
+ initialize : ->
+ BaseList::initialize ...
+
+
+# }}}
--- /dev/null
+{ _, op,
+} = require 'kraken/util'
+{ BaseModel, BaseList, BaseView,
+} = require 'kraken/base'
+
+
+/**
+ * @class
+ */
+DataSourceUIView = exports.DataSourceUIView = BaseView.extend do # {{{
+ __bind__ : <[ ]>
+ ctorName : 'DataSourceUIView'
+ tagName : 'section'
+ className : 'datasource-ui'
+ template : require 'kraken/template/datasource-ui'
+
+
+ constructor: function DataSourceUIView
+ BaseView ...
+
+ initialize: ->
+ @graph_id = @options.graph_id
+ BaseView::initialize ...
+
+ toTemplateLocals: ->
+ locals = @model.toJSON()
+ locals import
+ graph_id : @graph_id
+ source_summary : 'Source Summary'
+ metric_summary : 'Metric Summary'
+ timespan_summary : 'Timespan Summary'
+# }}}
--- /dev/null
+{ _, op,
+} = require 'kraken/util'
+{ BaseModel, BaseList, BaseView,
+} = require 'kraken/base'
+
+
+/**
+ * @class
+ */
+DataSourceView = exports.DataSourceView = BaseView.extend do # {{{
+ __bind__ : <[ ]>
+ ctorName : 'DataSourceView'
+ tagName : 'section'
+ className : 'datasource'
+ template : require 'kraken/template/datasource'
+
+
+
+ constructor: function DataSourceView
+ BaseView ...
+
+ initialize: ->
+ BaseView::initialize ...
+
+# }}}
--- /dev/null
+metric_model = require 'kraken/dataset/metric-model'
+metric_view = require 'kraken/dataset/metric-view'
+metric_edit_view = require 'kraken/dataset/metric-edit-view'
+datasource_model = require 'kraken/dataset/datasource-model'
+datasource_view = require 'kraken/dataset/datasource-view'
+datasource_ui_view = require 'kraken/dataset/datasource-ui-view'
+dataset_model = require 'kraken/dataset/dataset-model'
+dataset_view = require 'kraken/dataset/dataset-view'
+data_view = require 'kraken/dataset/data-view'
+
+exports import metric_model import metric_view import metric_edit_view \
+ import datasource_model import datasource_view import datasource_ui_view \
+ import dataset_model import dataset_view \
+ import data_view
--- /dev/null
+{ _, op,
+} = require 'kraken/util'
+{ BaseView,
+} = require 'kraken/base'
+{ Metric,
+} = require 'kraken/dataset/metric-model'
+{ DataSourceUIView,
+} = require 'kraken/dataset/datasource-ui-view'
+
+
+
+/**
+ * @class
+ */
+MetricEditView = exports.MetricEditView = BaseView.extend do # {{{
+ ctorName : 'MetricEditView'
+ tagName : 'section'
+ className : 'metric-edit-ui'
+ template : require 'kraken/template/metric-edit'
+
+ graph_id : null
+ dataset : null
+ datasource_ui_view : null
+
+
+ constructor: function MetricEditView
+ BaseView ...
+
+ initialize: ->
+ this import @options.{graph_id, dataset}
+ @model or= new Metric
+ BaseView::initialize ...
+ @subviews.push @datasource_ui_view = new DataSourceUIView {@model, @graph_id}
+ @$el.find '.metric-datasource' .append @datasource_ui_view.render().el
+
+
+ toTemplateLocals: ->
+ locals = BaseView::toTemplateLocals ...
+ locals import {@graph_id}
+
+ build: ->
+ BaseView::build ...
+ if @datasource_ui_view
+ @$el.find '.metric-datasource' .append @datasource_ui_view.render().el
+ this
+
+ editMetric: (metric) ->
+ console.log "#this.editMetric!", metric
+ @model = metric
+ @render()
+ @show()
+ this
+
+# }}}
+
--- /dev/null
+{ _, op,
+} = require 'kraken/util'
+{ BaseModel, BaseList,
+} = require 'kraken/base'
+
+
+/**
+ * @class
+ */
+Metric = exports.Metric = BaseModel.extend do # {{{
+ ctorName : 'Metric'
+ urlRoot : '/metrics'
+
+ /**
+ * Data source of the Metric.
+ * @type DataSource
+ */
+ source : null
+
+
+ constructor: function Metric
+ BaseModel ...
+
+ initialize : ->
+ BaseModel::initialize ...
+
+
+ defaults : ->
+ index : 0
+ label : 'New Metric'
+ type : 'int'
+ timespan : { start:null, stop:null, step:null }
+ disabled : false
+
+ # DataSource
+ source_id : null
+ source_col_idx : -1
+ source_col_name : ''
+
+ # Chart Options
+ color : null
+ visible : true
+ format_value : null
+ format_axis : null
+
+ scale : 1.0
+ transforms : []
+
+
+ /**
+ * Check whether the metric has aiight-looking values so we don't
+ * attempt to graph unconfigured crap.
+ */
+ isOk: ->
+ (label = @get('label')) and label is not 'New Metric'
+ and @get('source_id') and @get('source_col_idx') >= 0
+ and _.every @get('timespan'), op.ok
+
+
+
+# }}}
+
+
+/**
+ * @class
+ */
+MetricList = exports.MetricList = BaseList.extend do # {{{
+ ctorName : 'MetricList'
+ urlRoot : '/metrics'
+ model : Metric
+
+ constructor: function MetricList then BaseList ...
+# }}}
# 'submit .value' : 'update'
+ constructor: function GraphDisplayView
+ BaseView ...
+
initialize: ->
@model or= new Graph
BaseView::initialize ...
} = require 'kraken/chart'
{ Graph,
} = require 'kraken/graph/graph-model'
-{ DataSetView,
+{ DataView, DataSetView, DataSet,
} = require 'kraken/dataset'
root = do -> this
'keypress form.details input[type="text"]' : 'onKeypress'
'keypress form.options .value' : 'onKeypress'
'submit form.details' : 'onDetailsSubmit'
+ 'change select' : 'onDetailsSubmit'
'submit form.options' : 'onOptionsSubmit'
'change input[type="checkbox"]' : 'onOptionsSubmit'
- subviews: []
- ready: false
+ data : {}
+ ready : false
+ constructor: function GraphEditView
+ BaseView ...
initialize : (o={}) ->
- @subviews = []
+ @data = {}
@model or= new Graph
+ @id = _.domize 'graph', (@model.id or @model.get('slug') or @model.cid)
&