Milimetric has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/197590

Change subject: Add rickshaw timeseries graph
......................................................................

Add rickshaw timeseries graph

Change-Id: I8e25e6ad8ed2e77921463a00b35e5a8d7b40b6f2
---
M bower.json
M src/app/require.config.js
M src/app/startup.js
M src/components/funnel-layout/funnel-layout.html
A src/components/visualizers/rickshaw-timeseries/bindings.js
A src/components/visualizers/rickshaw-timeseries/rickshaw-extensions.js
A src/components/visualizers/rickshaw-timeseries/rickshaw-timeseries.html
A src/components/visualizers/rickshaw-timeseries/rickshaw-timeseries.js
A src/css/069_rickshaw.css
M src/css/070_styles.css
M src/index.html
M src/lib/utils.js
12 files changed, 216 insertions(+), 7 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/analytics/dashiki 
refs/changes/90/197590/1

diff --git a/bower.json b/bower.json
index f990f65..9e984fc 100644
--- a/bower.json
+++ b/bower.json
@@ -15,6 +15,7 @@
     "semantic": "~0.19.0",
     "mediawiki-storage": "latest",
     "marked": "~0.3.2",
-    "twix": "~0.5.1"
+    "twix": "~0.5.1",
+    "rickshaw": "~1.5.1"
   }
 }
diff --git a/src/app/require.config.js b/src/app/require.config.js
index f5df442..708222d 100644
--- a/src/app/require.config.js
+++ b/src/app/require.config.js
@@ -20,6 +20,7 @@
         'mediawiki-storage'     : 
'bower_modules/mediawiki-storage/dist/mediawiki-storage',
         'marked'                : 'bower_modules/marked/lib/marked',
         'twix'                  : 'bower_modules/twix/bin/twix',
+        'rickshaw'              : 'bower_modules/rickshaw/rickshaw',
         // NOTE: if you want functions like uri.expand, you must include both
         // URI and URITemplate like define(['uri/URI', 'uri/URITemplate'] ...
         // because URITemplate modifies URI when it's parsed
diff --git a/src/app/startup.js b/src/app/startup.js
index 3490907..115f652 100644
--- a/src/app/startup.js
+++ b/src/app/startup.js
@@ -22,7 +22,7 @@
     ko.components.register('dropdown', { require: 
'components/dropdown/dropdown' });
     ko.components.register('button-group', { require: 
'components/button-group/button-group' });
     ko.components.register('sunburst', { require: 
'components/visualizers/sunburst/sunburst' });
-    //ko.components.register('rickshaw-timeseries', { require: 
'components/visualizers/rickshaw-timeseries' });
+    ko.components.register('rickshaw-timeseries', { require: 
'components/visualizers/rickshaw-timeseries/rickshaw-timeseries' });
     //ko.components.register('stacked-bar', { require: 
'components/visualizers/stacked-bar' });
 
     // Start the application
diff --git a/src/components/funnel-layout/funnel-layout.html 
b/src/components/funnel-layout/funnel-layout.html
index c13e4fc..383ed7b 100644
--- a/src/components/funnel-layout/funnel-layout.html
+++ b/src/components/funnel-layout/funnel-layout.html
@@ -1,5 +1,5 @@
 <section>
-    <filters class="ui grid">
+    <filters class="ui tight grid">
         <div class="left aligned three wide column">
             <dropdown params="selectOne: wiki"/>
         </div>
@@ -12,17 +12,23 @@
         </div>
     </filters>
     <graphs class="ui attached segment">
+        <div class="ui attached segment header">Funnel analysis</div>
         <graph class="ui raised segment grid">
             <div class="row">
                 <div data-bind="if: editor.selected() !== 'WT'" class="eight 
wide column">
-                    <sunburst params="height: 350"/>
+                    <sunburst params="height: 450"/>
                 </div>
                 <div data-bind="if: editor.selected() !== 'VE'" class="eight 
wide column">
-                    <sunburst params="height: 350"/>
+                    <sunburst params="height: 450"/>
                 </div>
             </div>
         </graph>
-        <graph style="height: 499px" class="ui raised segment">graph goes 
here</graph>
-        <graph class="ui raised segment">graph goes here</graph>
+
+        <br/>
+
+        <div class="ui attached segment header">Rates over time</div>
+        <graph style="height: 500px" class="ui attached raised segment">
+            <rickshaw-timeseries/>
+        </graph>
     </graphs>
 </section>
diff --git a/src/components/visualizers/rickshaw-timeseries/bindings.js 
b/src/components/visualizers/rickshaw-timeseries/bindings.js
new file mode 100644
index 0000000..70ec056
--- /dev/null
+++ b/src/components/visualizers/rickshaw-timeseries/bindings.js
@@ -0,0 +1,70 @@
+define(function(require) {
+
+    var Rickshaw = require('rickshaw'),
+        ko = require('knockout'),
+        d3 = require('d3'),
+        getBounds = require('utils').getBounds;
+
+    ko.bindingHandlers.rickshawTime = {
+        init: function (element, valueAccessor) {
+            var val = ko.unwrap(valueAccessor());
+
+            var graphEl = d3.select(element).select(val.graphSelect).node(),
+                legendEl = d3.select(element).select(val.legendSelect).node(),
+                timelineEl = 
d3.select(element).select(val.timelineSelect).node(),
+                zoomSliderEl = 
d3.select(element).select(val.zoomSliderSelect).node(),
+
+                opt = val.options || {},
+
+                bounds = getBounds(element, '.resizable.container');
+
+            graphEl.graph = new Rickshaw.Graph({
+                element: graphEl,
+                width: opt.width || bounds.width * (opt.widthRatio || 13/16),
+                height: opt.height || bounds.height * (opt.heightRatio || 5/6),
+                renderer: 'multi',
+                series: val.series,
+            });
+
+            graphEl.xAxis = new Rickshaw.Graph.Axis.Time({ graph: 
graphEl.graph });
+            graphEl.yAxis = new Rickshaw.Graph.Axis.Y({
+                graph: graphEl.graph,
+                orientation: 'right',
+                tickFormat: Rickshaw.Fixtures.Number.formatKMBT
+            });
+
+            graphEl.legend = new Rickshaw.Graph.Legend({
+                graph: graphEl.graph,
+                element: legendEl
+            });
+
+            graphEl.shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
+                graph: graphEl.graph,
+                legend: graphEl.legend
+            });
+
+            graphEl.highlighter = new 
Rickshaw.Graph.Behavior.Series.Highlight({
+                graph: graphEl.graph,
+                legend: graphEl.legend
+            });
+
+            graphEl.hoverDetail = new Rickshaw.Graph.HoverDetail( {
+                graph: graphEl.graph
+            } );
+
+            graphEl.annotator = new Rickshaw.Graph.Annotate({
+                graph: graphEl.graph,
+                element: timelineEl
+            });
+
+            graphEl.zoomSlider = new Rickshaw.Graph.RangeSlider.Preview({
+                graph: graphEl.graph,
+                element: zoomSliderEl
+            });
+
+            graphEl.graph.render();
+        },
+        update: function (element, valueAccessor) {
+        }
+    };
+});
diff --git 
a/src/components/visualizers/rickshaw-timeseries/rickshaw-extensions.js 
b/src/components/visualizers/rickshaw-timeseries/rickshaw-extensions.js
new file mode 100644
index 0000000..cf868e4
--- /dev/null
+++ b/src/components/visualizers/rickshaw-timeseries/rickshaw-extensions.js
@@ -0,0 +1,53 @@
+define(function(require) {
+
+    var Rickshaw = require('rickshaw'),
+        d3 = require('d3');
+
+    Rickshaw.namespace('Rickshaw.Graph.Renderer.DashedLine');
+    Rickshaw.Graph.Renderer.DashedLine = Rickshaw.Class.create( 
Rickshaw.Graph.Renderer, {
+
+        name: 'dashed-line',
+
+        defaults: function($super) {
+
+            return Rickshaw.extend( $super(), {
+                unstack: true,
+                fill: false,
+                stroke: true
+            } );
+        },
+
+        seriesPathFactory: function() {
+
+            var graph = this.graph;
+
+            var factory = d3.svg.line()
+                .x( function(d) { return graph.x(d.x); } )
+                .y( function(d) { return graph.y(d.y); } )
+                .interpolate(this.graph.interpolation).tension(this.tension);
+
+            if(factory.defined) {
+                factory.defined( function(d) { return d.y !== null; } );
+            }
+            return factory;
+        },
+
+        _styleSeries: function(series) {
+            var fill = this.fill ? series.color : 'none';
+            var stroke = this.stroke ? series.color : 'none';
+
+            series.path.setAttribute('fill', fill);
+            series.path.setAttribute('stroke', stroke);
+            series.path.setAttribute('stroke-width', this.strokeWidth);
+
+            if (series.className) {
+                d3.select(series.path).classed(series.className, true);
+            }
+            if (series.className && this.stroke) {
+                d3.select(series.stroke).classed(series.className, true);
+            }
+            // This is the only line that changed, is there a better way?
+            series.path.setAttribute('stroke-dasharray', '5,5');
+        }
+    } );
+});
diff --git 
a/src/components/visualizers/rickshaw-timeseries/rickshaw-timeseries.html 
b/src/components/visualizers/rickshaw-timeseries/rickshaw-timeseries.html
new file mode 100644
index 0000000..6667e31
--- /dev/null
+++ b/src/components/visualizers/rickshaw-timeseries/rickshaw-timeseries.html
@@ -0,0 +1,21 @@
+<div class="resizable container ui tight grid">
+    <div data-bind="rickshawTime: {
+        series: series,
+        graphSelect: '.graph',
+        legendSelect: '.legend',
+        timelineSelect: '.timeline',
+        zoomSliderSelect: '.zoomSlider',
+        options: {
+            widthRatio: 13/16*0.97,
+        }
+    }" class="rickshaw row">
+        <div class="thirteen wide column">
+            <div class="graph"></div>
+            <div class="timeline"></div>
+            <div class="zoomSlider"></div>
+        </div>
+        <div class="right aligned three wide column">
+            <div class="legend"></div>
+        </div>
+    </div>
+</div>
diff --git 
a/src/components/visualizers/rickshaw-timeseries/rickshaw-timeseries.js 
b/src/components/visualizers/rickshaw-timeseries/rickshaw-timeseries.js
new file mode 100644
index 0000000..71f13da
--- /dev/null
+++ b/src/components/visualizers/rickshaw-timeseries/rickshaw-timeseries.js
@@ -0,0 +1,35 @@
+define(function(require) {
+
+    var templateMarkup = require('text!./rickshaw-timeseries.html');
+
+    require('./bindings');
+    require('./rickshaw-extensions');
+
+    function RickshawTime(params) {
+        $.extend(this, params);
+        this.colors = params.colors || {
+            'init': '#5687d1',
+            'ready': '#7b615c',
+            'saveIntent': '#de783b',
+            'saveAttempt': '#17becf',
+            'saveSuccess': '#6ab975',
+            'saveFailure': '#a173d1',
+            'abort': '#bcbd22',
+            'end': '#bbbbbb'
+        };
+        this.series = [{
+            name: 'saveSuccess',
+            color: this.colors.saveSuccess,
+            renderer: 'dashed-line',
+            data: [
+                {x: 1426021179, y: 120},{x: 1426107579, y: 124},{x: 
1426193979, y: 131},{x: 1426280379, y: 130},
+                {x: 1426366779, y: 121},{x: 1426453179, y: 126},{x: 
1426539579, y: 124},{x: 1426625979, y: 141}
+            ]
+        }];
+    }
+
+    return {
+        viewModel: RickshawTime,
+        template: templateMarkup
+    };
+});
diff --git a/src/css/069_rickshaw.css b/src/css/069_rickshaw.css
new file mode 120000
index 0000000..48ced09
--- /dev/null
+++ b/src/css/069_rickshaw.css
@@ -0,0 +1 @@
+../bower_modules/rickshaw/rickshaw.min.css
\ No newline at end of file
diff --git a/src/css/070_styles.css b/src/css/070_styles.css
index 539655e..9aeb7fa 100644
--- a/src/css/070_styles.css
+++ b/src/css/070_styles.css
@@ -3,6 +3,12 @@
 filters.ui.segment { padding: 0.5em 0.2em 0.5em 1em; box-shadow: none; }
 graphs.ui.attached.segment { background-color: #f7f7f7; margin: 6px; }
 
+.resizable.container {
+    width: 100%;
+    height: 100%;
+    padding: 0;
+}
+
 div.sunburst {
     font-family: 'Open Sans', sans-serif;
     font-size: 12px;
@@ -22,3 +28,8 @@
 div.sunburst span.percentage {
     font-size: 2.0em;
 }
+
+/* Additional semantic styles */
+.ui.tight.grid {
+    margin: 0;
+}
diff --git a/src/index.html b/src/index.html
index b809f6e..285f1e0 100644
--- a/src/index.html
+++ b/src/index.html
@@ -27,6 +27,8 @@
             <link href="css/065_divider.min.css" rel="stylesheet">
 
             <!-- end semantic ui -->
+
+            <link href="css/069_rickshaw.css" rel="stylesheet">
             <link href="css/070_styles.css" rel="stylesheet">
             <link href="css/080_responsive.css" rel="stylesheet">
         <!-- endbuild -->
diff --git a/src/lib/utils.js b/src/lib/utils.js
index a2473a4..561bcee 100644
--- a/src/lib/utils.js
+++ b/src/lib/utils.js
@@ -12,6 +12,14 @@
         },
         sortByNameIgnoreCase: function (a, b) {
             return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
+        },
+        getBounds: function (element, parentSelector) {
+            var container = $(element).parents(parentSelector);
+
+            return {
+                width: container.innerWidth() || 0,
+                height: container.innerHeight() || 0,
+            };
         }
     };
 });

-- 
To view, visit https://gerrit.wikimedia.org/r/197590
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I8e25e6ad8ed2e77921463a00b35e5a8d7b40b6f2
Gerrit-PatchSet: 1
Gerrit-Project: analytics/dashiki
Gerrit-Branch: master
Gerrit-Owner: Milimetric <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to