diff --git a/django_datastream/static/datastream/js/datastream.js b/django_datastream/static/datastream/js/datastream.js
index 30eb0cc..b576fad 100644
--- a/django_datastream/static/datastream/js/datastream.js
+++ b/django_datastream/static/datastream/js/datastream.js
@@ -157,6 +157,7 @@
var MAX_POINTS_NUMBER = 300;
// TODO: How much exactly do we want?
var MAX_POINTS_LOAD_LIMIT = 1000;
+ var INITIAL_TIMESPAN = 24 * 60 * 60 * 1000; // One day.
// The order of entries is from the lowest to the highest granularity on purpose,
// so that computing the granularity from a range is easier. Duration is in seconds.
@@ -399,7 +400,13 @@
Stream.prototype.valueDownsamplers = function (initial) {
var self = this;
- return _.union(self.tags.visualization.value_downsamplers, initial ? _.intersection(self.value_downsamplers, ['mean']) : [])
+ if (initial) {
+ // Navigator data is always using just mean datapoints.
+ return _.intersection(self.value_downsamplers, ['mean']);
+ }
+ else {
+ return self.tags.visualization.value_downsamplers;
+ }
};
Stream.prototype.timeDownsamplers = function (initial) {
@@ -654,8 +661,7 @@
'type': 'all',
'text': "all"
}
- ],
- 'selected': 4 // All.
+ ]
},
'xAxis': {
'id': 'x-axis',
@@ -739,6 +745,29 @@
});
};
+ // Prepending and appending null values so that all charts have the same time span.
+ Chart.prototype.fullRangeDatapints = function (datapoints) {
+ var self = this;
+
+ var startDatapoint = [self.streamManager.extremes.start, null];
+ var endDatapoint = [self.streamManager.extremes.end, null];
+
+ if (datapoints.length) {
+ if (datapoints[0][0] > self.streamManager.extremes.start) {
+ datapoints = [startDatapoint].concat(datapoints);
+ }
+
+ if (datapoints[datapoints.length - 1][0] < self.streamManager.extremes.end) {
+ datapoints = datapoints.concat([endDatapoint]);
+ }
+ }
+ else {
+ datapoints = [startDatapoint, endDatapoint];
+ }
+
+ return datapoints;
+ };
+
Chart.prototype.getYAxisTitle = function (stream) {
var title = [];
@@ -862,135 +891,130 @@
Chart.prototype.renderInitialData = function (callback) {
var self = this;
- self.loadData(self.streamManager.extremes.start, self.streamManager.extremes.end, true, function (error, datapoints) {
+ self.loadData(self.streamManager.extremes.start, self.streamManager.extremes.end, true, function (error, allDatapoints) {
if (error) {
if (callback) callback(error);
return;
}
- // Store datapoints array so that we can access it in the JSON exporting operation.
- self.highcharts.latestDatapoints = datapoints;
+ self.loadData(self.streamManager.extremes.end - INITIAL_TIMESPAN, self.streamManager.extremes.end, false, function (error, datapoints) {
+ if (error) {
+ if (callback) callback(error);
+ return;
+ }
- self.createYAxis(datapoints);
+ // Store datapoints array so that we can access it in the JSON exporting operation.
+ self.highcharts.latestDatapoints = datapoints;
- _.each(datapoints, function (streamDatapoints, i) {
- var stream = streamDatapoints.stream;
+ self.createYAxis(datapoints);
- // We have an assumption that y-axis will be used for or range and main type, or for flag type, but not for both.
- // This is because we are setting y-axis for a flag type into a different pane.
- assert((stream._rangeTypes.length + stream._mainTypes.length) === 0 || ((stream._rangeTypes.length + stream._mainTypes.length) > 0 && stream._flagTypes.length === 0));
-
- var yAxis = self.getYAxis(stream);
-
- // The first series which was already added. If null, the current series being added is the first one.
- var firstSeries = null;
-
- // TODO: We should probably deduplicate code here.
- _.each(stream._rangeTypes, function (rangeType, j) {
- var s = self.highcharts.addSeries({
- 'id': 'range-' + j + '-' + stream.id,
- 'streamId': stream.id, // Our own option.
- 'name': stream.tags.title,
- 'linkedTo': firstSeries ? firstSeries.options.id : null,
- 'yAxis': yAxis.options.id,
- 'type': rangeType.type,
- 'color': firstSeries ? firstSeries.color : null, // To automatically choose a color.
- 'showRects': firstSeries ? false : true, // We want rect to be shown only for the first series (so that each color is shown only once).
- 'lineWidth': 0,
- 'fillOpacity': 0.3,
- 'tooltip': {
- // TODO: Should be based on rangeType.
- 'pointFormat': '{series.name} min/max: {point.low} - {point.high}
'
- },
- 'visible': !stream.tags.visualization.hidden,
- 'data': streamDatapoints.range[j]
- // Do not redraw.
- }, false);
- firstSeries = firstSeries || s;
- });
- _.each(stream._mainTypes, function (mainType, j) {
- var s = self.highcharts.addSeries({
- 'id': 'main-' + j + '-' + stream.id,
- 'streamId': stream.id, // Our own option.
- 'name': stream.tags.title,
- 'linkedTo': firstSeries ? firstSeries.options.id : null,
- 'yAxis': yAxis.options.id,
- 'type': mainType.type,
- 'color': firstSeries ? firstSeries.color : null, // To automatically choose a color.
- 'showRects': firstSeries ? false : true, // We want rect to be shown only for the first series (so that each color is shown only once).
- 'tooltip': {
- // TODO: Should be based on mainType.
- 'pointFormat': '{series.name} mean: {point.y}
'
- },
- 'visible': !stream.tags.visualization.hidden,
- 'data': streamDatapoints.main[j]
- // Do not redraw.
- }, false);
- firstSeries = firstSeries || s;
- });
- _.each(stream._flagTypes, function (flagType, j) {
- // There is no way to toggle flags on and off, so we do not respect "hidden" tag.
- var s = self.highcharts.addSeries({
- 'id': 'flag-' + j + '-' + stream.id,
- 'streamId': stream.id, // Our own option.
- 'name': stream.tags.title,
- 'linkedTo': firstSeries ? firstSeries.options.id : null,
- 'yAxis': yAxis.options.id,
- 'type': flagType.type,
- 'showInLegend': false,
- 'showRects': false,
- 'color': 'black', // We force it to black, so that other series automatic color choosing is not interfered with.
- 'shape': 'squarepin',
- 'zIndex': 100, // We want flags to always be over other series.
- 'data': streamDatapoints.flag[j]
- // Do not redraw.
- }, false);
- firstSeries = firstSeries || s;
- });
- if (streamDatapoints.main[0] || streamDatapoints.range[0]) {
- var navigatorData = streamDatapoints.main[0] || streamDatapoints.range[0];
-
- // Prepending and appending null values so that all navigators for all charts have the same time span.
- if (navigatorData.length) {
- if (navigatorData[0][0] > self.streamManager.extremes.start) {
- navigatorData = [[self.streamManager.extremes.start, null]].concat(navigatorData);
- }
+ _.each(datapoints, function (streamDatapoints, i) {
+ var stream = streamDatapoints.stream;
- if (navigatorData[navigatorData.length - 1][0] < self.streamManager.extremes.end) {
- navigatorData = navigatorData.concat([[self.streamManager.extremes.end, null]]);
- }
- }
- else {
- navigatorData = [[self.streamManager.extremes.start, null], [self.streamManager.extremes.end, null]];
+ // We have an assumption that y-axis will be used for or range and main type, or for flag type, but not for both.
+ // This is because we are setting y-axis for a flag type into a different pane.
+ assert((stream._rangeTypes.length + stream._mainTypes.length) === 0 || ((stream._rangeTypes.length + stream._mainTypes.length) > 0 && stream._flagTypes.length === 0));
+
+ var yAxis = self.getYAxis(stream);
+
+ // The first series which was already added. If null, the current series being added is the first one.
+ var firstSeries = null;
+
+ // TODO: We should probably deduplicate code here.
+ _.each(stream._rangeTypes, function (rangeType, j) {
+ var s = self.highcharts.addSeries({
+ 'id': 'range-' + j + '-' + stream.id,
+ 'streamId': stream.id, // Our own option.
+ 'name': stream.tags.title,
+ 'linkedTo': firstSeries ? firstSeries.options.id : null,
+ 'yAxis': yAxis.options.id,
+ 'type': rangeType.type,
+ 'color': firstSeries ? firstSeries.color : null, // To automatically choose a color.
+ 'showRects': firstSeries ? false : true, // We want rect to be shown only for the first series (so that each color is shown only once).
+ 'lineWidth': 0,
+ 'fillOpacity': 0.3,
+ 'tooltip': {
+ // TODO: Should be based on rangeType.
+ 'pointFormat': '{series.name} min/max: {point.low} - {point.high}
'
+ },
+ 'visible': !stream.tags.visualization.hidden,
+ 'data': streamDatapoints.range[j]
+ // Do not redraw.
+ }, false);
+ firstSeries = firstSeries || s;
+ });
+ _.each(stream._mainTypes, function (mainType, j) {
+ var s = self.highcharts.addSeries({
+ 'id': 'main-' + j + '-' + stream.id,
+ 'streamId': stream.id, // Our own option.
+ 'name': stream.tags.title,
+ 'linkedTo': firstSeries ? firstSeries.options.id : null,
+ 'yAxis': yAxis.options.id,
+ 'type': mainType.type,
+ 'color': firstSeries ? firstSeries.color : null, // To automatically choose a color.
+ 'showRects': firstSeries ? false : true, // We want rect to be shown only for the first series (so that each color is shown only once).
+ 'tooltip': {
+ // TODO: Should be based on mainType.
+ 'pointFormat': '{series.name} mean: {point.y}
'
+ },
+ 'visible': !stream.tags.visualization.hidden,
+ 'data': streamDatapoints.main[j]
+ // Do not redraw.
+ }, false);
+ firstSeries = firstSeries || s;
+ });
+ _.each(stream._flagTypes, function (flagType, j) {
+ // There is no way to toggle flags on and off, so we do not respect "hidden" tag.
+ var s = self.highcharts.addSeries({
+ 'id': 'flag-' + j + '-' + stream.id,
+ 'streamId': stream.id, // Our own option.
+ 'name': stream.tags.title,
+ 'linkedTo': firstSeries ? firstSeries.options.id : null,
+ 'yAxis': yAxis.options.id,
+ 'type': flagType.type,
+ 'showInLegend': false,
+ 'showRects': false,
+ 'color': 'black', // We force it to black, so that other series automatic color choosing is not interfered with.
+ 'shape': 'squarepin',
+ 'zIndex': 100, // We want flags to always be over other series.
+ 'data': streamDatapoints.flag[j]
+ // Do not redraw.
+ }, false);
+ firstSeries = firstSeries || s;
+ });
+ if (allDatapoints[i] && allDatapoints[i].main && allDatapoints[i].main[0]) {
+ // Navigator data is always using just mean datapoints.
+ var navigatorData = self.fullRangeDatapints(allDatapoints[i].main[0]);
+
+ var navigator = self.highcharts.get('navigator');
+ self.highcharts.addAxis(_.extend({}, navigator.yAxis.options, {
+ 'id': 'navigator-y-axis-' + stream.id,
+ // We put y-axis of navigator, flags and other seris into into different panes. We put these
+ // navigator y-axis into pane 1 because in some cases putting all in the same pane made main
+ // y-axis too large for the data.
+ // See https://github.com/highslide-software/highcharts.com/issues/4523
+ 'pane': 1
+ // Do not redraw.
+ }), false, false);
+ self.highcharts.addSeries(_.extend({}, navigator.options, {
+ 'id': 'navigator-' + stream.id,
+ 'streamId': stream.id, // Our own option.
+ 'yAxis': 'navigator-y-axis-' + stream.id,
+ 'color': firstSeries.color,
+ 'data': navigatorData
+ // Do not redraw.
+ }), false);
}
+ });
- var navigator = self.highcharts.get('navigator');
- self.highcharts.addAxis(_.extend({}, navigator.yAxis.options, {
- 'id': 'navigator-y-axis-' + stream.id,
- // We put y-axis of navigator, flags and other seris into into different panes. We put these
- // navigator y-axis into pane 1 because in some cases putting all in the same pane made main
- // y-axis too large for the data.
- // See https://github.com/highslide-software/highcharts.com/issues/4523
- 'pane': 1
- // Do not redraw.
- }), false, false);
- self.highcharts.addSeries(_.extend({}, navigator.options, {
- 'id': 'navigator-' + stream.id,
- 'streamId': stream.id, // Our own option.
- 'yAxis': 'navigator-y-axis-' + stream.id,
- 'color': firstSeries.color,
- 'data': navigatorData
- // Do not redraw.
- }), false);
- }
- });
-
- // Redraw. We set eventArgs so that it is passed to afterSetExtremes. It is similar to what happens if
- // you call chart.highcharts.get('x-axis').setExtremes(start, end, true, false, {'reason': 'initial'}).
- self.highcharts.get('x-axis').eventArgs = {'reason': 'initial'};
- self.highcharts.redraw(false);
+ // Redraw. We set eventArgs so that it is passed to afterSetExtremes. It is similar to what happens if
+ // you call chart.highcharts.get('x-axis').setExtremes(start, end, true, false, {'reason': 'initial'}).
+ var start = Math.max(self.streamManager.extremes.end - INITIAL_TIMESPAN, self.streamManager.extremes.start);
+ var end = self.streamManager.extremes.end;
+ self.highcharts.get('x-axis').setExtremes(start, end, true, false, {'reason': 'initial'});
- if (callback) callback();
+ if (callback) callback();
+ });
});
};