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 += ''; - s += row(fd.x, f(p.x)); - s += row(fd.y, f(p.y)); - s += row(fd.size, f(p.size)); - s += "
' + p[fd.entity] + ' (' + p.group + ')
"; - 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 += ''; + s += row(fd.x, f(p.x)); + s += row(fd.y, f(p.y)); + s += row(fd.size, f(p.size)); + s += "
' + p[fd.entity] + ' (' + p.group + ')
"; + 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
+
@@ -52,6 +77,9 @@

+