And that finishes up Callouts.
authorDavid Schoonover <dsc@wikimedia.org>
Wed, 6 Jun 2012 15:12:31 +0000 (08:12 -0700)
committerDavid Schoonover <dsc@wikimedia.org>
Wed, 6 Jun 2012 15:12:31 +0000 (08:12 -0700)
lib/base/base-view.co
lib/base/data-binding.co
lib/chart/chart-type.co
lib/graph/graph-display-view.co
lib/graph/graph-model.co
lib/graph/graph-view.co
lib/template/graph/graph-display.jade
www/css/graph-display.styl
www/css/graph.styl

index 0532d21..92fc250 100644 (file)
@@ -226,8 +226,8 @@ BaseView = exports.BaseView = Backbone.View.extend mixinBase do # {{{
         this
     
     update: ->
-        new DataBinding this .update @toTemplateLocals()
-        @trigger 'update', this
+        new DataBinding this .update locals = @toTemplateLocals()
+        @trigger 'update', this, locals
         this
     
     
index 31f49da..4b2fa58 100644 (file)
@@ -30,7 +30,7 @@ class exports.DataBinding
         it
     
     update: (@data) ->
-        for key, val in @data
+        for key, val in _.collapseObject(@data)
             @updateBinding key, val
         this
     
index ad8fabc..7cfee2f 100644 (file)
@@ -284,10 +284,17 @@ class exports.ChartType extends ReadyEmitter
      * 
      * @param {Number} n Number to format.
      * @param {Number} [digits=2] Number of digits after the decimal to always display.
-     * @returns {String} Formatted number.
-     */
-    numberFormatter: (n, digits=2) ->
-        for [suffix, d] of [['B', 1000000000], ['M', 1000000], ['K', 1000], ['', NaN]]
+     * @param {Boolean} [abbrev=true] Expand number suffixes if false.
+     * @returns {Object} Formatted number parts.
+     */
+    numberFormatter: (n, digits=2, abbrev=true) ->
+        suffixes = do
+            if abbrev
+                [['B', 1000000000], ['M', 1000000], ['K', 1000], ['', NaN]]
+            else
+                [['Billion', 1000000000], ['Million', 1000000], ['', NaN]]
+        
+        for [suffix, d] of suffixes
             break if isNaN d
             if n >= d
                 n = n / d
@@ -296,7 +303,9 @@ class exports.ChartType extends ReadyEmitter
         parts = s.split '.'
         whole = _.rchop parts[0], 3 .join ','
         fraction = '.' + parts.slice(1).join '.'
-        { n, digits, whole, fraction, suffix }
+        { n, digits, whole, fraction, suffix, toString: -> 
+            "#{@whole}#{@fraction}#{if abbrev then '' else ' '}#{@suffix}"
+        }
     
     
     ### }}}
index b802f0d..2b4d58f 100644 (file)
@@ -47,12 +47,6 @@ GraphDisplayView = exports.GraphDisplayView = GraphView.extend do # {{{
     
     ### Rendering {{{
     
-    update: ->
-        locals = @toTemplateLocals()
-        @$ '.graph-name a' .text(locals.name or '')
-        @$ '.graph-desc' .html jade.filters.markdown locals.desc or ''
-        this
-    
     render: ->
         return this unless @ready and not @isRendering
         @wait()
index 54bb143..f27bb2e 100644 (file)
@@ -228,6 +228,31 @@ Graph = exports.Graph = BaseModel.extend do # {{{
         # Deal with everything else
         setter.call this, values, opts
     
+    getCalloutData: ->
+        # For now, always operate on the first Metric
+        return unless m = @dataset.metrics.at 0
+        
+        data  = m.getData()
+        dates = m.getDateColumn()
+        
+        # trim cols to match the right timespan
+        len = Math.min data.length, dates.length
+        data  .= slice(data.length  - len) if data.length  < len
+        dates .= slice(dates.length - len) if dates.length < len
+        
+        # Calc index offsets
+        latest     = len - 1
+        last_month = latest - 1
+        last_year  = latest - 12
+        
+        callout =
+            latest    : data[latest]
+            month : 
+                dates : [ dates[last_month], dates[latest] ]
+                value : [ data[last_month],  data[latest], data[latest] - data[last_month] ]
+            year : 
+                dates : [ dates[last_year], dates[latest]  ]
+                value : [ data[last_year],  data[latest],  data[latest] - data[last_year]  ]
     
     
     ### Chart Option Accessors {{{
index 80c6a6c..3a4617e 100644 (file)
@@ -135,8 +135,27 @@ GraphView = exports.GraphView = BaseView.extend do # {{{
     
     toTemplateLocals: ->
         attrs = _.extend {}, @model.attributes
+        attrs.desc  = jade.filters.markdown that if attrs.desc
+        attrs.notes = jade.filters.markdown that if attrs.notes
         delete attrs.options
-        { @model, view:this, @graph_id, slug:'', name:'', desc:'' } import attrs
+        delete attrs.callout
+        
+        if callout = @model.getCalloutData()
+            {year:yoy, month:mom} = callout
+            attrs.callout = 
+                latest : @chartType.numberFormatter(callout.latest, 2, false).toString()
+                year :
+                    dates : yoy.dates.map( -> moment(it).format('MMM YY') ).join(' &mdash; ')
+                    value : ( 100 * yoy.value[2] / yoy.value[0] ).toFixed(2) + '%'
+                month :
+                    dates : mom.dates.map( -> moment(it).format('MMM YY') ).join(' &mdash; ')
+                    value : ( 100 * mom.value[2] / mom.value[0] ).toFixed(2) + '%'
+        
+        { @model, @graph_id, view:this, slug:'', name:'', desc:'', callout: {
+            latest : '',
+            year   : { dates:'', value:'' },
+            month  : { dates:'', value:'' } }
+        } import attrs
     
     
     /**
index d13f0fd..d957a66 100644 (file)
@@ -4,14 +4,22 @@ section.graph-display.graph(id=graph_id)
     
     .graph-name-row.page-header.row-fluid
         h2.graph-name
-            a(id="graph-title", href="#{model.toLink()}") #{name}
+            a(id="graph-title", href="#{model.toLink()}", data-bind='name') #{name}
+        .callout
+            .latest-metric(data-bind='callout.latest') #{callout.latest}
+            .metric-change.year-over-year
+                span.dates(data-bind='callout.year.dates') #{callout.year.dates}
+                span.value(data-bind='callout.year.value') #{callout.year.value}
+            .metric-change.month-over-month
+                span.dates(data-bind='callout.month.dates') #{callout.month.dates}
+                span.value(data-bind='callout.month.value') #{callout.month.value}
     
     .graph-viewport-row.row-fluid
         .viewport
         .graph-legend
     
     .graph-details-row.row
-        .span7.offset1.graph-desc
+        .span7.offset1.graph-desc(data-bind='desc')
             != jade.filters.markdown(desc)
     
     .graph-details-row.row
@@ -23,7 +31,7 @@ section.graph-display.graph(id=graph_id)
                 |  Export
     
     .graph-details-row.row
-        .span6.offset1.graph-notes
+        .span6.offset1.graph-notes(data-bind='notes')
             != jade.filters.markdown(notes)
     
 
index 24fde9c..07f9e66 100644 (file)
@@ -10,11 +10,28 @@ section.graph-display.graph
         position relative
     
     /* * * *  Chart & Viewport  * * * {{{ */
+    .callout
+        absolute top 0 right 1em
+        z-index 100
+        width 200px
+        padding 0 0 2em 4em
+        font 11px/1.5 "helvetica neue", helvetica, arial, sans-serif
+        border-radius 5px
+        background-color white
+        text-align right
+        
+        .latest-metric
+            font-size 18px
+            line-height 36px
+        .metric-change
+            // line-height 24px
+            span
+                display inline-block
+                width 100px
+    
     .graph-legend
-        position absolute
+        absolute top 2em right 1em
         z-index 100
-        top 1em
-        right 1em
         width 200px
         
         padding 1em
index 7a9ee67..f29d9d1 100644 (file)
@@ -26,11 +26,28 @@ section.graph
         min-height 320px
         overflow hidden
     
+    .callout
+        absolute top 0 right 1em
+        z-index 100
+        width 200px
+        padding 0 0 2em 4em
+        font 12px/1.5 "helvetica neue", helvetica, arial, sans-serif
+        border-radius 5px
+        background-color white
+        text-align right
+        
+        .latest-metric
+            font-size 18px
+            line-height 36px
+        .metric-change
+            // line-height 24px
+            span
+                display inline-block
+                width 100px
+    
     .graph-legend
-        position absolute
+        absolute top 2em right 1em
         z-index 100
-        top 1em
-        right 1em
         width 200px
         
         padding 1em
@@ -59,8 +76,11 @@ section.graph
     
     /* * * *  Graph Details & Info Pane  * * * {{{ */
     .graph-name-row
+        // Accommodate the callout box
+        padding-right 272px
         margin 0 0 1em
         min-height 38px
+        
         input.graph-name
             display block
             absolute top 0 left 0
@@ -71,6 +91,7 @@ section.graph
             height 25px
             padding 6px
             border-color $light
+    
     .graph-info-pane
         .row-fluid
             .half.control-group
@@ -85,6 +106,7 @@ section.graph
         .help-block
             font-size 11px
             line-height 1.3
+    
     /* }}} */