diff --git a/caravel/assets/javascripts/dashboard.js b/caravel/assets/javascripts/dashboard.js
index 467fe95c2a749..d2e4f5f016fc6 100644
--- a/caravel/assets/javascripts/dashboard.js
+++ b/caravel/assets/javascripts/dashboard.js
@@ -31,10 +31,11 @@ var Dashboard = function (dashboardData) {
slice.render(true);
});
sliceObjects.push(slice);
- slice.render();
}
});
this.slices = sliceObjects;
+ this.refreshTimer = null;
+ this.startPeriodicRender(0);
},
setFilter: function (slice_id, col, vals) {
this.addFilter(slice_id, col, vals, false);
@@ -57,6 +58,36 @@ var Dashboard = function (dashboardData) {
// Returns a list of human readable active filters
return JSON.stringify(this.filters, null, 4);
},
+ stopPeriodicRender: function () {
+ if (this.refreshTimer) {
+ clearTimeout(this.refreshTimer);
+ this.refreshTimer = null;
+ }
+ },
+ startPeriodicRender: function (interval) {
+ this.stopPeriodicRender();
+ var dash = this;
+ var maxRandomDelay = Math.min(interval * 0.1, 5000);
+ var refreshAll = function () {
+ dash.slices.forEach(function (slice) {
+ setTimeout(function () {
+ slice.render(true);
+ },
+ //Randomize to prevent all widgets refreshing at the same time
+ maxRandomDelay * Math.random());
+ });
+ };
+
+ var fetchAndRender = function () {
+ refreshAll();
+ if (interval > 0) {
+ dash.refreshTimer = setTimeout(function () {
+ fetchAndRender();
+ }, interval);
+ }
+ };
+ fetchAndRender();
+ },
refreshExcept: function (slice_id) {
var immune = this.metadata.filter_immune_slice || [];
this.slices.forEach(function (slice) {
@@ -191,6 +222,10 @@ var Dashboard = function (dashboardData) {
body: "The following global filters are currently applied:
" + dashboard.readFilters()
});
});
+ $("#refresh_dash_interval").on("change", function () {
+ var interval = $(this).find('option:selected').val() * 1000;
+ dashboard.startPeriodicRender(interval);
+ });
$('#refresh_dash').click(function () {
dashboard.slices.forEach(function (slice) {
slice.render(true);
diff --git a/caravel/assets/javascripts/modules/caravel.js b/caravel/assets/javascripts/modules/caravel.js
index 55cc5b501a02e..4931dfcdcddbe 100644
--- a/caravel/assets/javascripts/modules/caravel.js
+++ b/caravel/assets/javascripts/modules/caravel.js
@@ -314,8 +314,6 @@ var px = (function () {
}
this.force = force;
token.find("img.loading").show();
- container.hide();
- container.html('');
container.css('height', slice.height());
dttm = 0;
timer = setInterval(stopwatch, 10);
@@ -325,9 +323,7 @@ var px = (function () {
},
resize: function () {
token.find("img.loading").show();
- container.hide();
container.css('height', slice.height());
- container.html('');
this.viz.render();
this.viz.resize();
},
diff --git a/caravel/assets/stylesheets/caravel.css b/caravel/assets/stylesheets/caravel.css
index 7fe7f1001cfaa..533f43a9a9976 100644
--- a/caravel/assets/stylesheets/caravel.css
+++ b/caravel/assets/stylesheets/caravel.css
@@ -184,6 +184,7 @@ img.loading {
.dashboard img.loading {
width: 20px;
margin: 5px;
+ position: absolute;
}
img.viz-thumb-option {
width: 100px;
diff --git a/caravel/assets/visualizations/big_number.js b/caravel/assets/visualizations/big_number.js
index dcc7b1139f213..32941cae5cf34 100644
--- a/caravel/assets/visualizations/big_number.js
+++ b/caravel/assets/visualizations/big_number.js
@@ -16,6 +16,8 @@ function bigNumberVis(slice) {
slice.error(error.responseText);
return '';
}
+ div.html(''); //reset
+
var fd = payload.form_data;
var json = payload.data;
var color_range = [-1, 1];
diff --git a/caravel/assets/visualizations/nvd3_vis.js b/caravel/assets/visualizations/nvd3_vis.js
index 1df5bebc69b74..fc63b6d03810d 100644
--- a/caravel/assets/visualizations/nvd3_vis.js
+++ b/caravel/assets/visualizations/nvd3_vis.js
@@ -20,116 +20,120 @@ function nvd3Vis(slice) {
var colorKey = 'key';
nv.addGraph(function () {
- switch (viz_type) {
- case 'line':
- if (fd.show_brush) {
- chart = nv.models.lineWithFocusChart();
- chart.lines2.xScale(d3.time.scale.utc());
- chart.x2Axis
- .showMaxMin(fd.x_axis_showminmax)
- .staggerLabels(false);
- } else {
- chart = nv.models.lineChart();
- }
- // To alter the tooltip header
- // chart.interactiveLayer.tooltip.headerFormatter(function(){return '';});
- chart.xScale(d3.time.scale.utc());
- chart.interpolate(fd.line_interpolation);
- chart.xAxis
- .showMaxMin(fd.x_axis_showminmax)
- .staggerLabels(false);
- break;
-
- case 'bar':
- chart = nv.models.multiBarChart()
- .showControls(true)
- .groupSpacing(0.1);
-
- chart.xAxis
- .showMaxMin(false)
- .staggerLabels(true);
-
- chart.stacked(fd.bar_stacked);
- break;
-
- case 'dist_bar':
- chart = nv.models.multiBarChart()
- .showControls(true) //Allow user to switch between 'Grouped' and 'Stacked' mode.
- .reduceXTicks(false)
- .rotateLabels(45)
- .groupSpacing(0.1); //Distance between each group of bars.
-
- chart.xAxis
- .showMaxMin(false);
-
- chart.stacked(fd.bar_stacked);
- break;
-
- case 'pie':
- chart = nv.models.pieChart();
- colorKey = 'x';
- chart.valueFormat(f);
- if (fd.donut) {
- chart.donut(true);
+ if (!chart) {
+ switch (viz_type) {
+ case 'line':
+ if (fd.show_brush) {
+ chart = nv.models.lineWithFocusChart();
+ chart.lines2.xScale(d3.time.scale.utc());
+ chart.x2Axis
+ .showMaxMin(fd.x_axis_showminmax)
+ .staggerLabels(false);
+ } else {
+ chart = nv.models.lineChart();
+ }
+ // To alter the tooltip header
+ // chart.interactiveLayer.tooltip.headerFormatter(function(){return '';});
+ chart.xScale(d3.time.scale.utc());
+ chart.interpolate(fd.line_interpolation);
+ chart.xAxis
+ .showMaxMin(fd.x_axis_showminmax)
+ .staggerLabels(false);
+ break;
+
+ case 'bar':
+ chart = nv.models.multiBarChart()
+ .showControls(true)
+ .groupSpacing(0.1);
+
+ chart.xAxis
+ .showMaxMin(false)
+ .staggerLabels(true);
+
+ chart.stacked(fd.bar_stacked);
+ break;
+
+ case 'dist_bar':
+ chart = nv.models.multiBarChart()
+ .showControls(true) //Allow user to switch between 'Grouped' and 'Stacked' mode.
+ .reduceXTicks(false)
+ .rotateLabels(45)
+ .groupSpacing(0.1); //Distance between each group of bars.
+
+ chart.xAxis
+ .showMaxMin(false);
+
+ chart.stacked(fd.bar_stacked);
+ break;
+
+ case 'pie':
+ chart = nv.models.pieChart();
+ colorKey = 'x';
+ chart.valueFormat(f);
+ if (fd.donut) {
+ chart.donut(true);
+ chart.labelsOutside(true);
+ }
chart.labelsOutside(true);
- }
- chart.labelsOutside(true);
- chart.cornerRadius(true);
- break;
-
- case 'column':
- chart = nv.models.multiBarChart()
- .reduceXTicks(false)
- .rotateLabels(45);
- break;
-
- case 'compare':
- chart = nv.models.cumulativeLineChart();
- chart.xScale(d3.time.scale.utc());
- chart.xAxis
- .showMaxMin(false)
- .staggerLabels(true);
- break;
-
- case 'bubble':
- var row = function (col1, col2) {
- return "
" + col1 + " | " + col2 + " |
";
- };
- chart = nv.models.scatterChart();
- chart.showDistX(true);
- chart.showDistY(true);
- chart.tooltip.contentGenerator(function (obj) {
- var p = obj.point;
- var s = "";
- s += '' + p[fd.entity] + ' (' + p.group + ') |
';
- s += row(fd.x, f(p.x));
- s += row(fd.y, f(p.y));
- s += row(fd.size, f(p.size));
- s += "
";
- return s;
- });
- chart.pointRange([5, fd.max_bubble_size * fd.max_bubble_size]);
- break;
-
- case 'area':
- chart = nv.models.stackedAreaChart();
- chart.style(fd.stacked_style);
- chart.xScale(d3.time.scale.utc());
- chart.xAxis
- .showMaxMin(false)
- .staggerLabels(true);
- break;
-
- case 'box_plot':
- colorKey = 'label';
- chart = nv.models.boxPlotChart();
- chart.x(function (d) { return d.label; });
- chart.staggerLabels(true);
- chart.maxBoxWidth(75); // prevent boxes from being incredibly wide
- break;
-
- default:
- throw new Error("Unrecognized visualization for nvd3" + viz_type);
+ chart.cornerRadius(true);
+ break;
+
+ case 'column':
+ chart = nv.models.multiBarChart()
+ .reduceXTicks(false)
+ .rotateLabels(45);
+ break;
+
+ case 'compare':
+ chart = nv.models.cumulativeLineChart();
+ chart.xScale(d3.time.scale.utc());
+ chart.xAxis
+ .showMaxMin(false)
+ .staggerLabels(true);
+ break;
+
+ case 'bubble':
+ var row = function (col1, col2) {
+ return "" + col1 + " | " + col2 + " |
";
+ };
+ chart = nv.models.scatterChart();
+ chart.showDistX(true);
+ chart.showDistY(true);
+ chart.tooltip.contentGenerator(function (obj) {
+ var p = obj.point;
+ var s = "";
+ s += '' + p[fd.entity] + ' (' + p.group + ') |
';
+ s += row(fd.x, f(p.x));
+ s += row(fd.y, f(p.y));
+ s += row(fd.size, f(p.size));
+ s += "
";
+ return s;
+ });
+ chart.pointRange([5, fd.max_bubble_size * fd.max_bubble_size]);
+ break;
+
+ case 'area':
+ chart = nv.models.stackedAreaChart();
+ chart.style(fd.stacked_style);
+ chart.xScale(d3.time.scale.utc());
+ chart.xAxis
+ .showMaxMin(false)
+ .staggerLabels(true);
+ break;
+
+ case 'box_plot':
+ colorKey = 'label';
+ chart = nv.models.boxPlotChart();
+ chart.x(function (d) {
+ return d.label;
+ });
+ chart.staggerLabels(true);
+ chart.maxBoxWidth(75); // prevent boxes from being incredibly wide
+ break;
+
+ default:
+ throw new Error("Unrecognized visualization for nvd3" + viz_type);
+ }
}
if ("showLegend" in chart && typeof fd.show_legend !== 'undefined') {
@@ -197,8 +201,12 @@ function nvd3Vis(slice) {
return px.color.category21(d[colorKey]);
});
- d3.select(slice.selector).html('');
- d3.select(slice.selector).append("svg")
+ var svg = d3.select(slice.selector).select("svg");
+ if (svg.empty()) {
+ svg = d3.select(slice.selector).append("svg");
+ }
+
+ svg
.datum(payload.data)
.transition().duration(500)
.attr('height', height)
diff --git a/caravel/assets/visualizations/table.js b/caravel/assets/visualizations/table.js
index 06aa4e9d6a920..8987e5dac51b3 100644
--- a/caravel/assets/visualizations/table.js
+++ b/caravel/assets/visualizations/table.js
@@ -35,7 +35,7 @@ function tableVis(slice) {
maxes[metrics[i]] = d3.max(col(metrics[i]));
}
- var table = d3.select(slice.selector).append('table')
+ var table = d3.select(slice.selector).html('').append('table')
.classed('dataframe dataframe table table-striped table-bordered table-condensed table-hover dataTable no-footer', true)
.attr('width', '100%');
diff --git a/caravel/templates/caravel/dashboard.html b/caravel/templates/caravel/dashboard.html
index 00ba50c4fbd25..65ac7c2703b75 100644
--- a/caravel/templates/caravel/dashboard.html
+++ b/caravel/templates/caravel/dashboard.html
@@ -37,6 +37,31 @@ Styling applies to this dashboard only
+
+
+
+
+
+
+
+
+
+
+