Checkpoint on Data UI
authordsc <dsc@wikimedia.org>
Thu, 12 Apr 2012 17:40:32 +0000 (10:40 -0700)
committerdsc <dsc@wikimedia.org>
Thu, 12 Apr 2012 17:40:32 +0000 (10:40 -0700)
lib/dataset/dataset-model.co
lib/dataset/datasource-model.co
lib/graph/graph-edit-view.co
lib/graph/graph-model.co
lib/server/controllers/datasource.co
lib/server/controllers/graph.co
lib/util/underscore/index.co
www/css/graph.styl
www/layout.jade

index c5b591d..9cd82d3 100644 (file)
@@ -17,16 +17,17 @@ ColorBrewer = require 'colorbrewer'
  */
 DataSet = exports.DataSet = BaseModel.extend do # {{{
     urlRoot : '/datasets'
+    ready : false
     
     /**
      * @type DataSourceList
      */
-    sources : []
+    sources : null
     
     /**
      * @type MetricList
      */
-    metrics : []
+    metrics : null
     
     
     constructor: function DataSet
@@ -34,14 +35,29 @@ DataSet = exports.DataSet = BaseModel.extend do # {{{
     
     initialize : ->
         BaseModel::initialize ...
-        @sources = new DataSourceList @attributes.sources
-        @metrics = new MetricList     @attributes.metrics
+        @sources = new DataSourceList
+        if @attributes.metrics
+            @metrics = that.columns = new MetricList that.columns
     
     
     defaults : ->
-        sources : [] # XXX: needed? metrics now implies this info
-        metrics : []
-        # lines   : []
+        palette : null
+        lines   : []
+        metrics :
+            defaults : {}
+            columns  : []
+    
+    
+    load: (opts={}) ->
+        return this if @ready and not opts.force
+        @wait()
+        @trigger 'load', this
+        Seq()
+            .seq ~>
+                @ready = true
+                @trigger 'ready', this
+                @unwait() # terminates the `load` wait
+        this
     
     
     /**
index 1d31584..d51b904 100644 (file)
@@ -16,13 +16,33 @@ DataSource = exports.DataSource = BaseModel.extend do # {{{
     
     initialize: ->
         BaseModel::initialize ...
-        
+    
     
     defaults: ->
-        {}
+        id            : ''
+        url           : ''
+        format        : 'json'
+        
+        name          : ''
+        shortName     : ''
+        title         : ''
+        subtitle      : ''
+        desc          : ''
+        notes         : ''
+        
+        timespan : 
+            start     : null
+            stop      : null
+            step      : '1mo'
+        
+        columns       : []
+        
+        chart : 
+            chartType : 'dygraphs'
+            options   : {}
     
     url: ->
-        "/data/#{@id}.json"
+        "/datasources/#{@id}.json"
     
 # }}}
 
index 51d393c..67fd78d 100644 (file)
@@ -109,7 +109,7 @@ GraphEditView = exports.GraphEditView = BaseView.extend do # {{{
         @$el.on 'click', '.graph-options-tab', @onFirstClickRenderOptionsTab
         
         ### Graph Data UI
-        @data = @addSubview '.graph-data-pane', new DataView { model:@model.get('dataset'), graph_id:@id }
+        @data = @addSubview '.graph-data-pane', new DataView { model:@model.get('data'), graph_id:@id }
         @$el.find '.graph-data-pane' .append @data.render().el
         @data
             .on 'change',        @onDataChange, this
@@ -279,9 +279,10 @@ GraphEditView = exports.GraphEditView = BaseView.extend do # {{{
         @checkWaiting()
     
     render: ->
-        return this unless @ready
+        return this unless @ready and not @_rendering
+        @_rendering = true
         @wait()
-        @checkWaiting() # fix up the spinner element as the DOM is now settled
+        @checkWaiting()
         @renderDetails()
         @attachSubviews()
         # _.invoke @subviews, 'render'
@@ -289,6 +290,7 @@ GraphEditView = exports.GraphEditView = BaseView.extend do # {{{
         @updateURL()
         @trigger 'render', this
         @unwait()
+        @_rendering = false
         this
     
     renderAll: ->
index 21d9d5f..a6914cd 100644 (file)
@@ -91,7 +91,7 @@ Graph = exports.Graph = BaseModel.extend do # {{{
         @chartType = ChartType.lookup @get('chartType')
         
         # Insert submodels in place of JSON
-        @set 'dataset', new DataSet(@get('dataset')), {+silent}
+        @set 'data', new DataSet(@get('data') or @get('dataset')), {+silent}
         
         @trigger 'init', this
         @load() if opts.autoload
index c556f23..1f89863 100644 (file)
@@ -1,10 +1,17 @@
 fs         = require 'fs'
-Seq        = require 'seq'
+path       = require 'path'
+{existsSync:exists} = path
+
+_          = require 'underscore'
+yaml       = require 'js-yaml'
 findit     = require 'findit'
-Controller = require '../controller'
+Seq        = require 'seq'
 
-YAML_EXT_PAT = /\.ya?ml$/i
+Controller = require '../controller'
 
+EXT_PAT          = /\.[^\.]*$/i
+YAML_EXT_PAT     = /\.ya?ml$/i
+YAML_OR_JSON_PAT = /\.(json|ya?ml)$/i
 
 
 /**
@@ -19,17 +26,55 @@ class DataSourceController extends Controller
     
     -> super ...
     
+    
+    toFile: (id) -> "#{@dataDir}/#id.json"
+    
     /**
-     * Returns a JSON listing of the datasource metadata files.
+     * Auto-load :id for related requests.
+     */
+    autoload: (id, cb) ->
+        file = @toFile id
+        parser = JSON.parse
+        
+        yamlFile = file.replace /\.json$/i, '.yaml'
+        if exists yamlFile 
+            file = yamlFile
+            parser = yaml.load
+        
+        err, data <- fs.readFile file, 'utf8'
+        if 'ENOENT' is err?.code
+            return cb null, {}
+        if err
+            console.error "DataSourceController.autoload(#id, #{typeof cb}) -->\nerr"
+            return cb err
+        try
+            cb null, parser data
+        catch err
+            console.error "DataSourceController.autoload(#id, #{typeof cb}) -->\nerr"
+            cb err
+    
+    /**
+     * GET /datasources
+     * @returns {Object} JSON listing of the datasource metadata files.
      */
     index : (req, res, next) ->
         files = findit.sync @dataDir
         # fs.readdir @dataDir, (err, files) ->
         res.send do
-            files.filter -> /\.(json|ya?ml)$/i.test it
+            files.filter -> YAML_OR_JSON_PAT.test it
                  .map    -> "#it".replace YAML_EXT_PAT, '.json'
     
     /**
+     * GET /datasources/:datasource
+     */
+    show: (req, res) ->
+        res.send req.datasource
+        # if req.format is 'json'
+        #     res.send req.datasource
+        # else
+        #     res.render 'datasource/view'
+    
+    /**
      * Returns the aggregated JSON content of the datasource metadata files.
      */
     allData : (req, res, next) ->
@@ -38,7 +83,7 @@ class DataSourceController extends Controller
         Seq(findit.sync @dataDir)
             # .seq ~> @ok findit.sync @dataDir
             # .flatten()
-            .filter -> /\.(json|ya?ml)$/.test it
+            .filter -> YAML_OR_JSON_PAT.test it
             .seq ->
                 files := @stack.slice()
                 # console.log 'files:', files
@@ -60,13 +105,13 @@ class DataSourceController extends Controller
                     # console.log "#f ok!", data
                     @ok v
                 catch err
-                    console.error "[/data/all] catch! #err"
+                    console.error "[/datasources] catch! #err"
                     console.error err
                     console.error that if err.stack
                     res.send { error:String(err), partial_data:data }
             .seq -> res.send data
             .catch (err) ->
-                console.error '[/data/all] catch!'
+                console.error '[/datasources] catch!'
                 console.error err
                 console.error that if err.stack
                 res.send { error:String(err), partial_data:data }
index d3921ce..4697f46 100644 (file)
@@ -1,10 +1,11 @@
-_        = require 'underscore'
-fs       = require 'fs'
-path     = require 'path'
-yaml     = require 'js-yaml'
-
+fs         = require 'fs'
+path       = require 'path'
 {existsSync:exists} = path
+
+_          = require 'underscore'
+yaml       = require 'js-yaml'
 {mkdirp, mkdirpAsync} = require '../mkdirp'
+
 Controller = require '../controller'
 
 
index 7e57eef..cc9d458 100644 (file)
@@ -9,9 +9,12 @@ _.mixin require 'kraken/util/underscore/string'
 
 
 ## Debug
-_.dump = (o, label='dump') ->
+_.dump = (o, label='dump', expanded=false) ->
     if not _.isArray(o) and _.isObject(o)
-        console.group label
+        if expanded
+            console.group label
+        else
+            console.groupCollapsed label
         for k, v in o
             console.log "#k:", v
         console.groupEnd()
index ce12b87..ab49bd1 100644 (file)
@@ -187,6 +187,12 @@ section.graph
             &:hover
                 opacity 0.6
         
+        input.value:not([type="checkbox"])
+            width 240px
+            font-family menlo, monospace
+        textarea
+            resize none
+        
         .shortname
             font-weight bold
             color white
@@ -196,9 +202,6 @@ section.graph
             font-weight bold
             // line-height 1.5
             // font-size 100%
-        input.value:not([type="checkbox"])
-            width 240px
-            font-family menlo, monospace
         .type
             &::before
                 content "Type: "
index c6859c1..4b3591c 100644 (file)
@@ -2,7 +2,7 @@ include mixins/helpers
 include mixins/forms
 
 !!! html
-html
+html(lang="en", dir="ltr")
     head
         block head
             meta(http-equiv="content-type", content="text/html; charset=utf-8")