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