fix(d3): D3 libarry upgrade (lib for visualizing data such as main view, graphs, etc.) (#5081)

* initial commit for d3 upgrade

* d3 v5 mostly working except brush

* more work on the brush

* brush and layout mostly working now

* make open-right and open-left lines visible

* make brush selection hidden

* fix open-right, open-top, and now-line in retro mode

* fix setting brush to now

* fix updateBrushToNow to set start correctly

* add extent to updateBrushToNow

* fix inRetro to use dataExtent instead of domain

* move a debug log message to better location

* debug for brush movements

* cleanup adjusted range vs. brushed range

* fix syntax error

* remove transitions for brush movements

* log message for dataUpdate

* fix updating brush range when new data arrives

* fix keeping up with data when not in retro

* keep brush range at focusRangeMS during update

* fix variable name error

* keep chart in sync with current time when not in retro

* use short transition time

* test no opacity changes

* remove one more highlight and use small transition duration

* fix race condition

* fix for uncommanded going to retro

* fix syntax error

* update chart scales when new data arrives in retro mode

* Use consistent transition for scroll

* clean chart.updateContext

* comment out debug messages

* remove unused variable

* update renderer to account for no structure arg for d3 attr

* fix syntax error

* one more syntax error

* use requestAnimationFrame

(cherry picked from commit b610485597b2e9ecf46471994980136d3c17deec)

* forgot to update current scroll data

(cherry picked from commit 1ab26522cd4abd3fb77a76964469200fc50dc555)

* remove extra treatment circles

* try using class for selection

(cherry picked from commit 92f678c6fe8e2bb700dc61ab56a71d483c5a9988)

* reduce update required for focus circles

(cherry picked from commit 46aab643125c2a083807627b9fb6052faef2134f)

* reduce update required for focus treatments

(cherry picked from commit 23ba5c4bea4bf2ff75f2296e1edc606f311ef7fe)

* fix update prepare treat circles

(cherry picked from commit afcbbab40fe0c93e26e97152513845cf2c5ecf6f)

* use _id for treatments key

* do not use opacity for past entry circles

* replace scale.linear with scaleLinear

see https://github.com/d3/d3/blob/master/CHANGES.md#scales-d3-scale

(cherry picked from commit 3445eeeedd1c0d863ca5210d4cd32994a9da4d49)

* d3 upgrade axis

(cherry picked from commit 06a8a9283100a980ccb5bed7920bce96a5b138cc)

* d3 upgrade axis

(cherry picked from commit 1ac583ce2b1d0796f8d8f0d5f9b5ee29a051af1e)

* fix tooltip location

* fix plugin tooltip location

* update reports for d3 v5

* fix inner radius default for insulin distribution pie

* fix dynamic scaling issues

* fix single click scroll

* Fix font size on axis labels

* Render ticks on top of everything

* fix click to scroll jankiness

* move loading finished to the bottom of updateHeader
This commit is contained in:
Jeremy Cunningham
2019-10-21 14:06:05 +02:00
committed by PieterGit
parent 06e3d6a23e
commit b8f28b0586
9 changed files with 775 additions and 396 deletions
+279 -165
View File
@@ -3,7 +3,19 @@
// var _ = require('lodash');
var times = require('../times');
var d3locales = require('./d3locales');
var padding = { bottom: 30 };
var scrolling = false
, scrollNow = 0
, scrollBrushExtent = null
, scrollRange = null
;
var PADDING_BOTTOM = 30
, CONTEXT_MAX = 420
, CONTEXT_MIN = 36
, FOCUS_MAX = 510
, FOCUS_MIN = 30
, DEFAULT_TRANS_MS = 100
;
function init (client, d3, $) {
var chart = { };
@@ -31,20 +43,37 @@ function init (client, d3, $) {
// arrow head
defs.append('marker')
.attr({
'id': 'arrow',
'viewBox': '0 -5 10 10',
'refX': 5,
'refY': 0,
'markerWidth': 8,
'markerHeight': 8,
'orient': 'auto'
})
.attr('id', 'arrow')
.attr('viewBox', '0 -5 10 10')
.attr('refX', 5)
.attr('refY', 0)
.attr('markerWidth', 8)
.attr('markerHeight', 8)
.attr('orient', 'auto')
.append('path')
.attr('d', 'M0,-5L10,0L0,5')
.attr('class', 'arrowHead');
var localeFormatter = d3.locale(d3locales.locale(client.settings.language));
var localeFormatter = d3.timeFormatLocale(d3locales.locale(client.settings.language));
function beforeBrushStarted ( ) {
// go ahead and move the brush because
// a single click will not execute the brush event
var now = new Date();
var dx = chart.xScale2(now) - chart.xScale2(new Date(now.getTime() - client.focusRangeMS));
var cx = d3.mouse(this)[0];
var x0 = cx - dx / 2;
var x1 = cx + dx / 2;
var range = chart.xScale2.range();
var X0 = range[0];
var X1 = range[1];
var brush = x0 < X0 ? [X0, X0 + dx] : x1 > X1 ? [X1 - dx, X1] : [x0, x1];
chart.theBrush.call(chart.brush.move, brush);
}
function brushStarted ( ) {
// update the opacity of the context data points to brush extent
@@ -64,13 +93,13 @@ function init (client, d3, $) {
var yScaleType;
if (client.settings.scaleY === 'linear') {
yScaleType = d3.scale.linear;
yScaleType = d3.scaleLinear;
} else {
yScaleType = d3.scale.log;
yScaleType = d3.scaleLog;
}
var focusYDomain = [utils.scaleMgdl(30), utils.scaleMgdl(510)];
var contextYDomain = [utils.scaleMgdl(36), utils.scaleMgdl(420)];
var focusYDomain = [utils.scaleMgdl(FOCUS_MIN), utils.scaleMgdl(FOCUS_MAX)];
var contextYDomain = [utils.scaleMgdl(CONTEXT_MIN), utils.scaleMgdl(CONTEXT_MAX)];
function dynamicDomain() {
// allow y-axis to extend all the way to the top of the basal area, but leave room to display highest value
@@ -84,7 +113,7 @@ function init (client, d3, $) {
//, mgdlMax = d3.quantile(client.entries, 0.99, function (d) { return d.mgdl; });
return [
utils.scaleMgdl(30)
utils.scaleMgdl(FOCUS_MIN)
, Math.max(utils.scaleMgdl(mgdlMax * mult), utils.scaleMgdl(targetTop * mult))
];
}
@@ -98,71 +127,92 @@ function init (client, d3, $) {
}
// define the parts of the axis that aren't dependent on width or height
var xScale = chart.xScale = d3.time.scale().domain(extent);
var xScale = chart.xScale = d3.scaleTime().domain(extent);
focusYDomain = dynamicDomainOrElse(focusYDomain);
var yScale = chart.yScale = yScaleType()
.domain(dynamicDomainOrElse(focusYDomain));
.domain(focusYDomain);
var xScale2 = chart.xScale2 = d3.time.scale().domain(extent);
var xScale2 = chart.xScale2 = d3.scaleTime().domain(extent);
contextYDomain = dynamicDomainOrElse(contextYDomain);
var yScale2 = chart.yScale2 = yScaleType()
.domain(dynamicDomainOrElse(contextYDomain));
.domain(contextYDomain);
chart.xScaleBasals = d3.time.scale().domain(extent);
chart.xScaleBasals = d3.scaleTime().domain(extent);
chart.yScaleBasals = d3.scale.linear()
chart.yScaleBasals = d3.scaleLinear()
.domain([0, 5]);
var tickFormat = localeFormatter.timeFormat.multi( [
['.%L', function(d) { return d.getMilliseconds(); }],
[':%S', function(d) { return d.getSeconds(); }],
[client.settings.timeFormat === 24 ? '%H:%M' : '%I:%M', function(d) { return d.getMinutes(); }],
[client.settings.timeFormat === 24 ? '%H:%M' : '%-I %p', function(d) { return d.getHours(); }],
['%a %d', function(d) { return d.getDay() && d.getDate() !== 1; }],
['%b %d', function(d) { return d.getDate() !== 1; }],
['%B', function(d) { return d.getMonth(); }],
['%Y', function() { return true; }]
]);
var formatMillisecond = localeFormatter.format('.%L'),
formatSecond = localeFormatter.format(':%S'),
formatMinute = client.settings.timeFormat === 24 ? localeFormatter.format('%H:%M') :
localeFormatter.format('%I:%M'),
formatHour = client.settings.timeFormat === 24 ? localeFormatter.format('%H:%M') :
localeFormatter.format('%-I %p'),
formatDay = localeFormatter.format('%a %d'),
formatWeek = localeFormatter.format('%b %d'),
formatMonth = localeFormatter.format('%B'),
formatYear = localeFormatter.format('%Y');
var tickFormat = function (date) {
return (d3.timeSecond(date) < date ? formatMillisecond
: d3.timeMinute(date) < date ? formatSecond
: d3.timeHour(date) < date ? formatMinute
: d3.timeDay(date) < date ? formatHour
: d3.timeMonth(date) < date ? (d3.timeWeek(date) < date ? formatDay : formatWeek)
: d3.timeYear(date) < date ? formatMonth
: formatYear)(date);
};
var tickValues = client.ticks(client);
chart.xAxis = d3.svg.axis()
.scale(xScale)
chart.xAxis = d3.axisBottom(xScale)
chart.xAxis = d3.axisBottom(xScale)
.tickFormat(tickFormat)
.ticks(4)
.orient('bottom');
.ticks(6);
chart.yAxis = d3.svg.axis()
.scale(yScale)
chart.yAxis = d3.axisLeft(yScale)
.tickFormat(d3.format('d'))
.tickValues(tickValues)
.orient('left');
.tickValues(tickValues);
chart.xAxis2 = d3.svg.axis()
.scale(xScale2)
chart.xAxis2 = d3.axisBottom(xScale2)
.tickFormat(tickFormat)
.ticks(6)
.orient('bottom');
.ticks(6);
chart.yAxis2 = d3.svg.axis()
.scale(yScale2)
chart.yAxis2 = d3.axisRight(yScale2)
.tickFormat(d3.format('d'))
.tickValues(tickValues)
.orient('right');
.tickValues(tickValues);
d3.select('tick')
.style('z-index', '10000');
// setup a brush
chart.brush = d3.svg.brush()
.x(xScale2)
.on('brushstart', brushStarted)
chart.brush = d3.brushX()
.on('start', brushStarted)
.on('brush', function brush (time) {
client.loadRetroIfNeeded();
client.brushed(time);
})
.on('brushend', brushEnded);
.on('end', brushEnded);
chart.futureOpacity = d3.scale.linear( )
.domain([times.mins(25).msecs, times.mins(60).msecs])
.range([0.8, 0.1]);
chart.theBrush = null;
chart.futureOpacity = (function() {
var scale = d3.scaleLinear( )
.domain([times.mins(25).msecs, times.mins(60).msecs])
.range([0.8, 0.1]);
return function (delta) {
if (delta < 0) {
return null;
} else {
return scale(delta);
}
};
})();
// create svg and g to contain the chart contents
chart.charts = d3.select('#chartContainer').append('svg')
@@ -176,42 +226,66 @@ function init (client, d3, $) {
// create the x axis container
chart.focus.append('g')
.attr('class', 'x axis');
.attr('class', 'x axis')
.style("font-size", "16px");
// create the y axis container
chart.focus.append('g')
.attr('class', 'y axis');
.attr('class', 'y axis')
.style("font-size", "16px");
chart.context = chart.charts.append('g').attr('class', 'chart-context');
chart.context = chart.charts.append('g')
.attr('class', 'chart-context');
// create the x axis container
chart.context.append('g')
.attr('class', 'x axis');
.attr('class', 'x axis')
.style("font-size", "16px");
// create the y axis container
chart.context.append('g')
.attr('class', 'y axis');
.attr('class', 'y axis')
.style("font-size", "16px");
function createAdjustedRange() {
var range = chart.brush.extent().slice();
chart.createBrushedRange = function () {
var brushedRange = chart.theBrush && d3.brushSelection(chart.theBrush.node()) || null;
var range = brushedRange && brushedRange.map(chart.xScale2.invert);
var dataExtent = client.dataExtent();
var end = range[1].getTime() + client.forecastTime;
if (!brushedRange) {
// console.log('No current brushed range. Setting range to last focusRangeMS amount of available data');
range = dataExtent;
range[0] = new Date(range[1].getTime() - client.focusRangeMS);
}
var end = range[1].getTime()
if (!chart.inRetroMode()) {
var lastSGVMills = client.latestSGV ? client.latestSGV.mills : client.now;
end += (client.now - lastSGVMills);
end = client.now > dataExtent[1].getTime() ? client.now : dataExtent[1].getTime();
}
range[1] = new Date(end);
range[0] = new Date(end - client.focusRangeMS);
return range;
}
chart.createAdjustedRange = function () {
var adjustedRange = chart.createBrushedRange();
adjustedRange[1] = new Date(adjustedRange[1].getTime() + client.forecastTime);
return adjustedRange;
}
chart.inRetroMode = function inRetroMode() {
if (!chart.brush || !chart.xScale2) {
var brushedRange = chart.theBrush && d3.brushSelection(chart.theBrush.node()) || null;
if (!brushedRange || !chart.xScale2) {
return false;
}
var brushTime = chart.brush.extent()[1].getTime();
var maxTime = chart.xScale2.domain()[1].getTime();
var brushTime = chart.xScale2.invert(brushedRange[1]).getTime();
return brushTime < maxTime;
};
@@ -235,15 +309,16 @@ function init (client, d3, $) {
var dataRange = client.dataExtent();
var chartContainerRect = chartContainer[0].getBoundingClientRect();
var chartWidth = chartContainerRect.width;
var chartHeight = chartContainerRect.height - padding.bottom;
var chartHeight = chartContainerRect.height - PADDING_BOTTOM;
// get the height of each chart based on its container size ratio
var focusHeight = chart.focusHeight = chartHeight * .7;
var contextHeight = chart.contextHeight = chartHeight * .2;
var contextHeight = chart.contextHeight = chartHeight * .3;
chart.basalsHeight = focusHeight / 4;
// get current brush extent
var currentBrushExtent = createAdjustedRange();
var currentRange = chart.createAdjustedRange();
var currentBrushExtent = chart.createBrushedRange();
// only redraw chart if chart size has changed
var widthChanged = (chart.prevChartWidth !== chartWidth);
@@ -259,14 +334,14 @@ function init (client, d3, $) {
//set the width and height of the SVG element
chart.charts.attr('width', chartWidth)
.attr('height', chartHeight + padding.bottom);
.attr('height', chartHeight + PADDING_BOTTOM);
// ranges are based on the width and height available so reset
chart.xScale.range([0, chartWidth]);
chart.xScale2.range([0, chartWidth]);
chart.xScaleBasals.range([0, chartWidth]);
chart.yScale.range([focusHeight, 0]);
chart.yScale2.range([chartHeight, chartHeight - contextHeight]);
chart.yScale2.range([contextHeight, 0]);
chart.yScaleBasals.range([0, focusHeight / 4]);
if (init) {
@@ -281,33 +356,39 @@ function init (client, d3, $) {
.call(chart.yAxis);
// if first run then just display axis with no transition
chart.context
.attr('transform', 'translate(0,' + focusHeight + ')')
chart.context.select('.x')
.attr('transform', 'translate(0,' + chartHeight + ')')
.attr('transform', 'translate(0,' + contextHeight + ')')
.call(chart.xAxis2);
// chart.basals.select('.y')
// .attr('transform', 'translate(0,' + 0 + ')')
// .call(chart.yAxisBasals);
chart.context.append('g')
chart.theBrush = chart.context.append('g')
.attr('class', 'x brush')
.call(d3.svg.brush().x(chart.xScale2).on('brush', client.brushed))
.selectAll('rect')
.attr('y', focusHeight)
.attr('height', chartHeight - focusHeight);
.call(chart.brush)
.call(g => g.select(".overlay")
.datum({type: 'selection'})
.on('mousedown touchstart', beforeBrushStarted));
chart.theBrush.selectAll('rect')
.attr('y', 0)
.attr('height', contextHeight);
// disable resizing of brush
d3.select('.x.brush').select('.background').style('cursor', 'move');
d3.select('.x.brush').select('.resize.e').style('cursor', 'move');
d3.select('.x.brush').select('.resize.w').style('cursor', 'move');
chart.context.select('.x.brush').select('.overlay').style('cursor', 'move');
chart.context.select('.x.brush').selectAll('.handle')
.style('cursor', 'move');
chart.context.select('.x.brush').select('.selection')
.style('visibility', 'hidden');
// add a line that marks the current time
chart.focus.append('line')
.attr('class', 'now-line')
.attr('x1', chart.xScale(new Date(client.now)))
.attr('y1', chart.yScale(utils.scaleMgdl(30)))
.attr('y1', chart.yScale(focusYDomain[0]))
.attr('x2', chart.xScale(new Date(client.now)))
.attr('y2', chart.yScale(utils.scaleMgdl(420)))
.attr('y2', chart.yScale(focusYDomain[1]))
.style('stroke-dasharray', ('3, 3'))
.attr('stroke', 'grey');
@@ -371,9 +452,9 @@ function init (client, d3, $) {
chart.context.append('line')
.attr('class', 'now-line')
.attr('x1', chart.xScale(new Date(client.now)))
.attr('y1', chart.yScale2(utils.scaleMgdl(36)))
.attr('y1', chart.yScale2(contextYDomain[0]))
.attr('x2', chart.xScale(new Date(client.now)))
.attr('y2', chart.yScale2(utils.scaleMgdl(420)))
.attr('y2', chart.yScale2(contextYDomain[1]))
.style('stroke-dasharray', ('3, 3'))
.attr('stroke', 'grey');
@@ -400,7 +481,7 @@ function init (client, d3, $) {
} else {
// for subsequent updates use a transition to animate the axis to the new position
var focusTransition = chart.focus.transition();
var focusTransition = chart.focus.transition().duration(DEFAULT_TRANS_MS);
focusTransition.select('.x')
.attr('transform', 'translate(0,' + focusHeight + ')')
@@ -410,86 +491,83 @@ function init (client, d3, $) {
.attr('transform', 'translate(' + chartWidth + ', 0)')
.call(chart.yAxis);
var contextTransition = chart.context.transition();
var contextTransition = chart.context.transition().duration(DEFAULT_TRANS_MS);
chart.context
.attr('transform', 'translate(0,' + focusHeight + ')')
contextTransition.select('.x')
.attr('transform', 'translate(0,' + chartHeight + ')')
.attr('transform', 'translate(0,' + contextHeight + ')')
.call(chart.xAxis2);
chart.basals.transition();
// basalsTransition.select('.y')
// .attr('transform', 'translate(0,' + 0 + ')')
// .call(chart.yAxisBasals);
chart.basals.transition().duration(DEFAULT_TRANS_MS);
// reset brush location
chart.context.select('.x.brush')
.selectAll('rect')
.attr('y', focusHeight)
.attr('height', chartHeight - focusHeight);
chart.theBrush.selectAll('rect')
.attr('y', 0)
.attr('height', contextHeight);
// clear current brushs
d3.select('.brush').call(chart.brush.clear());
// console.log('Redrawing old brush with new dimensions: ', currentBrushExtent);
// redraw old brush with new dimensions
d3.select('.brush').transition().call(chart.brush.extent(currentBrushExtent));
chart.theBrush.call(chart.brush.move, currentBrushExtent.map(chart.xScale2));
// transition lines to correct location
chart.focus.select('.high-line')
.transition()
.attr('x1', chart.xScale(currentBrushExtent[0]))
.transition().duration(DEFAULT_TRANS_MS)
.attr('x1', chart.xScale(currentRange[0]))
.attr('y1', chart.yScale(utils.scaleMgdl(client.settings.thresholds.bgHigh)))
.attr('x2', chart.xScale(currentBrushExtent[1]))
.attr('x2', chart.xScale(currentRange[1]))
.attr('y2', chart.yScale(utils.scaleMgdl(client.settings.thresholds.bgHigh)));
chart.focus.select('.target-top-line')
.transition()
.attr('x1', chart.xScale(currentBrushExtent[0]))
.transition().duration(DEFAULT_TRANS_MS)
.attr('x1', chart.xScale(currentRange[0]))
.attr('y1', chart.yScale(utils.scaleMgdl(client.settings.thresholds.bgTargetTop)))
.attr('x2', chart.xScale(currentBrushExtent[1]))
.attr('x2', chart.xScale(currentRange[1]))
.attr('y2', chart.yScale(utils.scaleMgdl(client.settings.thresholds.bgTargetTop)));
chart.focus.select('.target-bottom-line')
.transition()
.attr('x1', chart.xScale(currentBrushExtent[0]))
.transition().duration(DEFAULT_TRANS_MS)
.attr('x1', chart.xScale(currentRange[0]))
.attr('y1', chart.yScale(utils.scaleMgdl(client.settings.thresholds.bgTargetBottom)))
.attr('x2', chart.xScale(currentBrushExtent[1]))
.attr('x2', chart.xScale(currentRange[1]))
.attr('y2', chart.yScale(utils.scaleMgdl(client.settings.thresholds.bgTargetBottom)));
chart.focus.select('.low-line')
.transition()
.attr('x1', chart.xScale(currentBrushExtent[0]))
.transition().duration(DEFAULT_TRANS_MS)
.attr('x1', chart.xScale(currentRange[0]))
.attr('y1', chart.yScale(utils.scaleMgdl(client.settings.thresholds.bgLow)))
.attr('x2', chart.xScale(currentBrushExtent[1]))
.attr('x2', chart.xScale(currentRange[1]))
.attr('y2', chart.yScale(utils.scaleMgdl(client.settings.thresholds.bgLow)));
// transition open-top line to correct location
chart.context.select('.open-top')
.transition()
.attr('x1', chart.xScale2(currentBrushExtent[0]))
.attr('y1', chart.yScale(utils.scaleMgdl(30)))
.attr('x2', chart.xScale2(currentBrushExtent[1]))
.attr('y2', chart.yScale(utils.scaleMgdl(30)));
.transition().duration(DEFAULT_TRANS_MS)
.attr('x1', chart.xScale2(currentRange[0]))
.attr('y1', chart.yScale2(utils.scaleMgdl(CONTEXT_MAX)))
.attr('x2', chart.xScale2(currentRange[1]))
.attr('y2', chart.yScale2(utils.scaleMgdl(CONTEXT_MAX)));
// transition open-left line to correct location
chart.context.select('.open-left')
.transition()
.attr('x1', chart.xScale2(currentBrushExtent[0]))
.attr('y1', focusHeight)
.attr('x2', chart.xScale2(currentBrushExtent[0]))
.attr('y2', chartHeight);
.transition().duration(DEFAULT_TRANS_MS)
.attr('x1', chart.xScale2(currentRange[0]))
.attr('y1', chart.yScale2(contextYDomain[0]))
.attr('x2', chart.xScale2(currentRange[0]))
.attr('y2', chart.yScale2(contextYDomain[1]));
// transition open-right line to correct location
chart.context.select('.open-right')
.transition()
.attr('x1', chart.xScale2(currentBrushExtent[1]))
.attr('y1', focusHeight)
.attr('x2', chart.xScale2(currentBrushExtent[1]))
.attr('y2', chartHeight);
.transition().duration(DEFAULT_TRANS_MS)
.attr('x1', chart.xScale2(currentRange[1]))
.attr('y1', chart.yScale2(contextYDomain[0]))
.attr('x2', chart.xScale2(currentRange[1]))
.attr('y2', chart.yScale2(contextYDomain[1]));
// transition high line to correct location
chart.context.select('.high-line')
.transition()
.transition().duration(DEFAULT_TRANS_MS)
.attr('x1', chart.xScale2(dataRange[0]))
.attr('y1', chart.yScale2(utils.scaleMgdl(client.settings.thresholds.bgTargetTop)))
.attr('x2', chart.xScale2(dataRange[1]))
@@ -497,7 +575,7 @@ function init (client, d3, $) {
// transition low line to correct location
chart.context.select('.low-line')
.transition()
.transition().duration(DEFAULT_TRANS_MS)
.attr('x1', chart.xScale2(dataRange[0]))
.attr('y1', chart.yScale2(utils.scaleMgdl(client.settings.thresholds.bgTargetBottom)))
.attr('x2', chart.xScale2(dataRange[1]))
@@ -505,64 +583,88 @@ function init (client, d3, $) {
}
}
// update domain
chart.xScale2.domain(dataRange);
chart.updateContext(dataRange);
chart.xScaleBasals.domain(dataRange);
var updateBrush = d3.select('.brush').transition();
updateBrush
.call(chart.brush.extent([new Date(dataRange[1].getTime() - client.focusRangeMS), dataRange[1]]));
client.brushed(true);
// console.log('Redrawing brush due to update: ', currentBrushExtent);
chart.theBrush.call(chart.brush.move, currentBrushExtent.map(chart.xScale2));
};
chart.updateContext = function (dataRange_) {
if (client.documentHidden) {
console.info('Document Hidden, not updating - ' + (new Date()));
return;
}
// get current data range
var dataRange = dataRange_ || client.dataExtent();
// update domain
chart.xScale2.domain(dataRange);
renderer.addContextCircles();
// update x axis domain
chart.context.select('.x').call(chart.xAxis2);
};
chart.scroll = function scroll (nowDate) {
chart.xScale.domain(createAdjustedRange());
chart.yScale.domain(dynamicDomainOrElse(focusYDomain));
chart.xScaleBasals.domain(createAdjustedRange());
function scrollUpdate() {
scrolling = false;
var nowDate = scrollNow;
var currentBrushExtent = scrollBrushExtent;
var currentRange = scrollRange;
chart.xScale.domain(currentRange);
focusYDomain = dynamicDomainOrElse(focusYDomain);
chart.yScale.domain(focusYDomain);
chart.xScaleBasals.domain(currentRange);
// remove all insulin/carb treatment bubbles so that they can be redrawn to correct location
d3.selectAll('.path').remove();
// transition open-top line to correct location
chart.context.select('.open-top')
.attr('x1', chart.xScale2(chart.brush.extent()[0]))
.attr('y1', chart.yScale(utils.scaleMgdl(30)))
.attr('x2', chart.xScale2(new Date(chart.brush.extent()[1].getTime() + client.forecastTime)))
.attr('y2', chart.yScale(utils.scaleMgdl(30)));
.transition().duration(DEFAULT_TRANS_MS)
.attr('x1', chart.xScale2(currentRange[0]))
.attr('y1', chart.yScale2(contextYDomain[1]))
.attr('x2', chart.xScale2(currentRange[1]))
.attr('y2', chart.yScale2(contextYDomain[1]));
// transition open-left line to correct location
chart.context.select('.open-left')
.attr('x1', chart.xScale2(chart.brush.extent()[0]))
.attr('y1', chart.focusHeight)
.attr('x2', chart.xScale2(chart.brush.extent()[0]))
.attr('y2', chart.prevChartHeight);
.transition().duration(DEFAULT_TRANS_MS)
.attr('x1', chart.xScale2(currentRange[0]))
.attr('y1', chart.yScale2(contextYDomain[0]))
.attr('x2', chart.xScale2(currentRange[0]))
.attr('y2', chart.yScale2(contextYDomain[1]));
// transition open-right line to correct location
chart.context.select('.open-right')
.attr('x1', chart.xScale2(new Date(chart.brush.extent()[1].getTime() + client.forecastTime)))
.attr('y1', chart.focusHeight)
.attr('x2', chart.xScale2(new Date(chart.brush.extent()[1].getTime() + client.forecastTime)))
.attr('y2', chart.prevChartHeight);
.transition().duration(DEFAULT_TRANS_MS)
.attr('x1', chart.xScale2(currentRange[1]))
.attr('y1', chart.yScale2(contextYDomain[0]))
.attr('x2', chart.xScale2(currentRange[1]))
.attr('y2', chart.yScale2(contextYDomain[1]));
chart.focus.select('.now-line')
.transition()
.transition().duration(DEFAULT_TRANS_MS)
.attr('x1', chart.xScale(nowDate))
.attr('y1', chart.yScale(utils.scaleMgdl(36)))
.attr('y1', chart.yScale(focusYDomain[0]))
.attr('x2', chart.xScale(nowDate))
.attr('y2', chart.yScale(utils.scaleMgdl(420)));
.attr('y2', chart.yScale(focusYDomain[1]));
chart.context.select('.now-line')
.transition()
.attr('x1', chart.xScale2(chart.brush.extent()[1]))
.attr('y1', chart.yScale2(utils.scaleMgdl(36)))
.attr('x2', chart.xScale2(chart.brush.extent()[1]))
.attr('y2', chart.yScale2(utils.scaleMgdl(420)));
.transition().duration(DEFAULT_TRANS_MS)
.attr('x1', chart.xScale2(currentBrushExtent[1]))
.attr('y1', chart.yScale2(contextYDomain[0]))
.attr('x2', chart.xScale2(currentBrushExtent[1]))
.attr('y2', chart.yScale2(contextYDomain[1]));
// update x,y axis
chart.focus.select('.x.axis').call(chart.xAxis);
@@ -575,6 +677,18 @@ function init (client, d3, $) {
renderer.addTreatmentProfiles(client);
renderer.drawTreatments(client);
}
chart.scroll = function scroll (nowDate) {
scrollNow = nowDate;
scrollBrushExtent = chart.createBrushedRange();
scrollRange = chart.createAdjustedRange();
if (!scrolling) {
requestAnimationFrame(scrollUpdate);
}
scrolling = true;
};
return chart;
+33 -16
View File
@@ -276,7 +276,7 @@ client.load = function load (serverSettings, callback) {
function formatTime (time, compact) {
var timeFormat = getTimeFormat(false, compact);
time = d3.time.format(timeFormat)(time);
time = d3.timeFormat(timeFormat)(time);
if (client.settings.timeFormat !== 24) {
time = time.toLowerCase();
}
@@ -375,14 +375,14 @@ client.load = function load (serverSettings, callback) {
// clears the current user brush and resets to the current real time data
function updateBrushToNow (skipBrushing) {
// get current time range
var dataRange = client.dataExtent();
// update brush and focus chart with recent data
d3.select('.brush')
.transition()
.duration(UPDATE_TRANS_MS)
.call(chart.brush.extent([new Date(dataRange[1].getTime() - client.focusRangeMS), dataRange[1]]));
var brushExtent = client.dataExtent();
brushExtent[0] = new Date(brushExtent[1].getTime() - client.focusRangeMS);
// console.log('Resetting brush in updateBrushToNow: ', brushExtent);
chart.theBrush && chart.theBrush.call(chart.brush.move, brushExtent.map(chart.xScale2));
if (!skipBrushing) {
brushed();
@@ -398,21 +398,34 @@ client.load = function load (serverSettings, callback) {
}
function brushed () {
// Brush not initialized
if (!chart.theBrush) {
return;
}
var brushExtent = chart.brush.extent();
// default to most recent focus period
var brushExtent = client.dataExtent();
brushExtent[0] = new Date(brushExtent[1].getTime() - client.focusRangeMS);
// ensure that brush extent is fixed at 3.5 hours
if (brushExtent[1].getTime() - brushExtent[0].getTime() !== client.focusRangeMS) {
var brushedRange = d3.brushSelection(chart.theBrush.node());
if (brushedRange) {
brushExtent = brushedRange.map(chart.xScale2.invert);
}
// console.log('Brushed to: ', brushExtent);
if (!brushedRange || (brushExtent[1].getTime() - brushExtent[0].getTime() !== client.focusRangeMS)) {
// ensure that brush updating is with the time range
if (brushExtent[0].getTime() + client.focusRangeMS > client.dataExtent()[1].getTime()) {
brushExtent[0] = new Date(brushExtent[1].getTime() - client.focusRangeMS);
d3.select('.brush')
.call(chart.brush.extent([brushExtent[0], brushExtent[1]]));
} else {
brushExtent[1] = new Date(brushExtent[0].getTime() + client.focusRangeMS);
d3.select('.brush')
.call(chart.brush.extent([brushExtent[0], brushExtent[1]]));
}
// console.log('Updating brushed to: ', brushExtent);
chart.theBrush.call(chart.brush.move, brushExtent.map(chart.xScale2));
}
function adjustCurrentSGVClasses (value, isCurrent) {
@@ -428,7 +441,6 @@ client.load = function load (serverSettings, callback) {
currentBG.toggleClass('icon-hourglass', value === 9);
currentBG.toggleClass('error-code', value < 39);
currentBG.toggleClass('bg-limit', value === 39 || value > 400);
container.removeClass('loading');
}
function updateCurrentSGV (entry) {
@@ -546,6 +558,8 @@ client.load = function load (serverSettings, callback) {
var top = (client.bottomOfPills() + 5);
$('#chartContainer').css({ top: top + 'px', height: $(window).height() - top - 10 });
container.removeClass('loading');
}
function sgvToColor (sgv) {
@@ -1130,6 +1144,7 @@ client.load = function load (serverSettings, callback) {
}
function dataUpdate (received) {
console.info('got dataUpdate', new Date(client.now));
var lastUpdated = Date.now();
receiveDData(received, client.ddata, client.settings);
@@ -1171,6 +1186,8 @@ client.load = function load (serverSettings, callback) {
chart.update(false);
client.plugins.updateVisualisations(client.nowSBX);
brushed();
} else {
chart.updateContext();
}
}
};
+138 -124
View File
@@ -7,6 +7,7 @@ var DEFAULT_FOCUS = times.hours(3).msecs
, WIDTH_SMALL_DOTS = 420
, WIDTH_BIG_DOTS = 800
, TOOLTIP_TRANS_MS = 100 // milliseconds
, DEFAULT_TRANS_MS = 10 // milliseconds
, TOOLTIP_WIDTH = 150 //min-width + padding
;
@@ -40,20 +41,23 @@ function init (client, d3) {
};
function tooltipLeft () {
var windowWidth = $(client.tooltip).parent().parent().width();
var windowWidth = $(client.tooltip.node()).parent().parent().width();
var left = d3.event.pageX + TOOLTIP_WIDTH < windowWidth ? d3.event.pageX : windowWidth - TOOLTIP_WIDTH - 10;
return left + 'px';
}
function hideTooltip () {
client.tooltip.transition()
.duration(TOOLTIP_TRANS_MS)
client.tooltip.transition().duration(TOOLTIP_TRANS_MS)
.style('opacity', 0);
}
// get the desired opacity for context chart based on the brush extent
renderer.highlightBrushPoints = function highlightBrushPoints (data) {
if (client.latestSGV && data.mills >= chart().brush.extent()[0].getTime() && data.mills <= chart().brush.extent()[1].getTime()) {
var selectedRange = chart().createAdjustedRange();
var from = selectedRange[0].getTime();
var to = selectedRange[1].getTime();
if (client.latestSGV && data.mills >= from && data.mills <= to) {
return chart().futureOpacity(data.mills - client.latestSGV.mills);
} else {
return 0.5;
@@ -75,7 +79,10 @@ function init (client, d3) {
});
var maxForecastMills = _.max(_.map(shownForecastPoints, function(point) { return point.mills }));
// limit lookahead to the same as lookback
var focusHoursAheadMills = chart().brush.extent()[1].getTime() + client.focusRangeMS;
var selectedRange = chart().createAdjustedRange();
var to = selectedRange[1].getTime();
var focusHoursAheadMills = to + client.focusRangeMS;
maxForecastMills = Math.min(focusHoursAheadMills, maxForecastMills);
client.forecastTime = maxForecastMills > 0 ? maxForecastMills - client.sbx.lastSGVMills() : 0;
focusData = focusData.concat(shownForecastPoints);
@@ -85,7 +92,7 @@ function init (client, d3) {
// selects all our data into data and uses date function to get current max date
var focusCircles = chart().focus.selectAll('circle').data(focusData, client.entryToDate);
function prepareFocusCircles (sel) {
function updateFocusCircles (sel) {
var badData = [];
sel.attr('cx', function(d) {
if (!d) {
@@ -107,17 +114,12 @@ function init (client, d3) {
return chart().yScale(scaled);
}
})
.attr('fill', function(d) {
return d.type === 'forecast' ? 'none' : d.color;
})
.attr('opacity', function(d) {
return d.noFade || !client.latestSGV ? 100 : chart().futureOpacity(d.mills - client.latestSGV.mills);
})
.attr('stroke-width', function(d) {
return d.type === 'mbg' ? 2 : d.type === 'forecast' ? 2 : 0;
})
.attr('stroke', function(d) {
return (d.type === 'mbg' ? 'white' : d.color);
if (d.noFade) {
return null;
} else {
return !client.latestSGV ? 1 : chart().futureOpacity(d.mills - client.latestSGV.mills);
}
})
.attr('r', function(d) {
return dotRadius(d.type);
@@ -130,6 +132,21 @@ function init (client, d3) {
return sel;
}
function prepareFocusCircles (sel) {
updateFocusCircles(sel)
.attr('fill', function(d) {
return d.type === 'forecast' ? 'none' : d.color;
})
.attr('stroke-width', function(d) {
return d.type === 'mbg' ? 2 : d.type === 'forecast' ? 2 : 0;
})
.attr('stroke', function(d) {
return (d.type === 'mbg' ? 'white' : d.color);
});
return sel;
}
function focusCircleTooltip (d) {
if (d.type !== 'sgv' && d.type !== 'mbg' && d.type !== 'forecast') {
return;
@@ -161,7 +178,7 @@ function init (client, d3) {
}
// if already existing then transition each circle to its new position
prepareFocusCircles(focusCircles.transition());
updateFocusCircles(focusCircles.transition().duration(DEFAULT_TRANS_MS));
// if new circle then just display
prepareFocusCircles(focusCircles.enter().append('circle'))
@@ -240,7 +257,7 @@ function init (client, d3) {
//NOTE: treatments with insulin or carbs are drawn by drawTreatment()
// bind up the focus chart data to an array of circles
var treatCircles = chart().focus.selectAll('treatment-dot').data(client.ddata.treatments.filter(function(treatment) {
var treatCircles = chart().focus.selectAll('.treatment-dot').data(client.ddata.treatments.filter(function(treatment) {
var notCarbsOrInsulin = !treatment.carbs && !treatment.insulin;
var notTempOrProfile = !_.includes(['Temp Basal', 'Profile Switch', 'Combo Bolus', 'Temporary Target'], treatment.eventType);
@@ -253,7 +270,22 @@ function init (client, d3) {
}));
return notCarbsOrInsulin && !treatment.duration && treatment.durationType !== 'indefinite' && notTempOrProfile && notOpenAPSSpam;
}));
}), function (d) { return d._id; });
function updateTreatCircles (sel) {
sel.attr('cx', function(d) {
return chart().xScale(new Date(d.mills));
})
.attr('cy', function(d) {
return chart().yScale(client.sbx.scaleEntry(d));
})
.attr('r', function() {
return dotRadius('mbg');
});
return sel;
}
function prepareTreatCircles (sel) {
function strokeColor (d) {
@@ -276,15 +308,7 @@ function init (client, d3) {
return color;
}
sel.attr('cx', function(d) {
return chart().xScale(new Date(d.mills));
})
.attr('cy', function(d) {
return chart().yScale(client.sbx.scaleEntry(d));
})
.attr('r', function() {
return dotRadius('mbg');
})
updateTreatCircles(sel)
.attr('stroke-width', 2)
.attr('stroke', strokeColor)
.attr('fill', fillColor);
@@ -293,10 +317,11 @@ function init (client, d3) {
}
// if already existing then transition each circle to its new position
prepareTreatCircles(treatCircles.transition());
updateTreatCircles(treatCircles.transition().duration(DEFAULT_TRANS_MS));
// if new circle then just display
prepareTreatCircles(treatCircles.enter().append('circle'))
.attr('class', 'treatment-dot')
.on('mouseover', function(d) {
client.tooltip.transition().duration(TOOLTIP_TRANS_MS).style('opacity', .9);
client.tooltip.html(d.isAnnouncement ? announcementTooltip(d) : treatmentTooltip(d))
@@ -305,6 +330,8 @@ function init (client, d3) {
})
.on('mouseout', hideTooltip);
treatCircles.exit().remove();
var durationTreatments = client.ddata.treatments.filter(function(treatment) {
return !treatment.carbs && !treatment.insulin && (treatment.duration || treatment.durationType !== undefined) &&
!_.includes(['Temp Basal', 'Profile Switch', 'Combo Bolus', 'Temporary Target'], treatment.eventType);
@@ -377,8 +404,8 @@ function init (client, d3) {
}
// if transitioning, update rect text, position, and width
var rectUpdates = treatRects.transition()
rectUpdates.attr('transform', rectTranslate)
var rectUpdates = treatRects.transition().duration(DEFAULT_TRANS_MS);
rectUpdates.attr('transform', rectTranslate);
rectUpdates.select('text')
.text(treatmentText)
@@ -441,7 +468,7 @@ function init (client, d3) {
}
})
.attr('fill', function(d) { return d.color; })
.style('opacity', function(d) { return renderer.highlightBrushPoints(d) })
//.style('opacity', function(d) { return renderer.highlightBrushPoints(d) })
.attr('stroke-width', function(d) { return d.type === 'mbg' ? 2 : 0; })
.attr('stroke', function() { return 'white'; })
.attr('r', function(d) { return d.type === 'mbg' ? 4 : 2; });
@@ -454,7 +481,7 @@ function init (client, d3) {
}
// if already existing then transition each circle to its new position
prepareContextCircles(contextCircles.transition());
prepareContextCircles(contextCircles.transition().duration(DEFAULT_TRANS_MS));
// if new circle then just display
prepareContextCircles(contextCircles.enter().append('circle'));
@@ -538,7 +565,7 @@ function init (client, d3) {
arc_data[4].element = translate(treatment.status);
}
var arc = d3.svg.arc()
var arc = d3.arc()
.innerRadius(function(d) {
return 5 * d.inner;
})
@@ -617,10 +644,10 @@ function init (client, d3) {
var insulinRect = { x: 0, y: 0, width: 0, height: 0 };
var carbsRect = { x: 0, y: 0, width: 0, height: 0 };
var operation;
renderer.drag = d3.behavior.drag()
.on('dragstart', function() {
renderer.drag = d3.drag()
.on('start', function() {
//console.log(treatment);
var windowWidth = $(client.tooltip).parent().parent().width();
var windowWidth = $(client.tooltip.node()).parent().parent().width();
var left = d3.event.x + TOOLTIP_WIDTH < windowWidth ? d3.event.x : windowWidth - TOOLTIP_WIDTH - 10;
client.tooltip.transition().duration(TOOLTIP_TRANS_MS).style('opacity', .9)
.style('left', left + 'px')
@@ -633,29 +660,25 @@ function init (client, d3) {
, height: chart().yScale(chart().yScale.domain()[0])
};
chart().drag.append('rect')
.attr({
class: 'drag-droparea'
, x: deleteRect.x
, y: deleteRect.y
, width: deleteRect.width
, height: deleteRect.height
, fill: 'red'
, opacity: 0.4
, rx: 10
, ry: 10
});
.attr('class', 'drag-droparea')
.attr('x', deleteRect.x)
.attr('y', deleteRect.y)
.attr('width', deleteRect.width)
.attr('height', deleteRect.height)
.attr('fill', 'red')
.attr('opacity', 0.4)
.attr('rx', 10)
.attr('ry', 10);
chart().drag.append('text')
.attr({
class: 'drag-droparea'
, x: deleteRect.x + deleteRect.width / 2
, y: deleteRect.y + deleteRect.height / 2
, 'font-size': 15
, 'font-weight': 'bold'
, fill: 'red'
, 'text-anchor': 'middle'
, dy: '.35em'
, transform: 'rotate(-90 ' + (deleteRect.x + deleteRect.width / 2) + ',' + (deleteRect.y + deleteRect.height / 2) + ')'
})
.attr('class', 'drag-droparea')
.attr('x', deleteRect.x + deleteRect.width / 2)
.attr('y', deleteRect.y + deleteRect.height / 2)
.attr('font-size', 15)
.attr('font-weight', 'bold')
.attr('fill', 'red')
.attr('text-anchor', 'middle')
.attr('dy', '.35em')
.attr('transform', 'rotate(-90 ' + (deleteRect.x + deleteRect.width / 2) + ',' + (deleteRect.y + deleteRect.height / 2) + ')')
.text(translate('Remove'));
if (treatment.insulin && treatment.carbs) {
@@ -672,52 +695,44 @@ function init (client, d3) {
, height: 50
};
chart().drag.append('rect')
.attr({
class: 'drag-droparea'
, x: carbsRect.x
, y: carbsRect.y
, width: carbsRect.width
, height: carbsRect.height
, fill: 'white'
, opacity: 0.4
, rx: 10
, ry: 10
});
.attr('class', 'drag-droparea')
.attr('x', carbsRect.x)
.attr('y', carbsRect.y)
.attr('width', carbsRect.width)
.attr('height', carbsRect.height)
.attr('fill', 'white')
.attr('opacitys', 0.4)
.attr('rx', 10)
.attr('ry', 10);
chart().drag.append('text')
.attr({
class: 'drag-droparea'
, x: carbsRect.x + carbsRect.width / 2
, y: carbsRect.y + carbsRect.height / 2
, 'font-size': 15
, 'font-weight': 'bold'
, fill: 'white'
, 'text-anchor': 'middle'
, dy: '.35em'
})
.attr('class', 'drag-droparea')
.attr('x', carbsRect.x + carbsRect.width / 2)
.attr('y', carbsRect.y + carbsRect.height / 2)
.attr('font-size', 15)
.attr('font-weight', 'bold')
.attr('fill', 'white')
.attr('text-anchor', 'middle')
.attr('dy', '.35em')
.text(translate('Move carbs'));
chart().drag.append('rect')
.attr({
class: 'drag-droparea'
, x: insulinRect.x
, y: insulinRect.y
, width: insulinRect.width
, height: insulinRect.height
, fill: '#0099ff'
, opacity: 0.4
, rx: 10
, ry: 10
});
.attr('class', 'drag-droparea')
.attr('x', insulinRect.x)
.attr('y', insulinRect.y)
.attr('width', insulinRect.width)
.attr('height', insulinRect.height)
.attr('fill', '#0099ff')
.attr('opacity', 0.4)
.attr('rx', 10)
.attr('ry', 10);
chart().drag.append('text')
.attr({
class: 'drag-droparea'
, x: insulinRect.x + insulinRect.width / 2
, y: insulinRect.y + insulinRect.height / 2
, 'font-size': 15
, 'font-weight': 'bold'
, fill: '#0099ff'
, 'text-anchor': 'middle'
, dy: '.35em'
})
.attr('class', 'drag-droparea')
.attr('x', insulinRect.x + insulinRect.width / 2)
.attr('y', insulinRect.y + insulinRect.height / 2)
.attr('font-size', 15)
.attr('font-weight', 'bold')
.attr('fill', '#0099ff')
.attr('text-anchor', 'middle')
.attr('dy', '.35em')
.text(translate('Move insulin'));
}
@@ -727,7 +742,7 @@ function init (client, d3) {
})
.on('drag', function() {
//console.log(d3.event);
client.tooltip.transition().style('opacity', .9);
client.tooltip.transition().duration(TOOLTIP_TRANS_MS).style('opacity', .9);
var x = Math.min(Math.max(0, d3.event.x), chart().charts.attr('width'));
var y = Math.min(Math.max(0, d3.event.y), chart().focusHeight);
@@ -754,19 +769,16 @@ function init (client, d3) {
chart().drag.selectAll('.arrow').remove();
chart().drag.append('line')
.attr({
'class': 'arrow'
, 'marker-end': 'url(#arrow)'
, 'x1': chart().xScale(new Date(treatment.mills))
, 'y1': chart().yScale(client.sbx.scaleEntry(treatment))
, 'x2': x
, 'y2': y
, 'stroke-width': 2
, 'stroke': 'white'
});
.attr('class', 'arrow')
.attr('marker-end', 'url(#arrow)')
.attr('x1', chart().xScale(new Date(treatment.mills)))
.attr('y1', chart().yScale(client.sbx.scaleEntry(treatment)))
.attr('x2', x)
.attr('y2', y)
.attr('stroke-width', 2)
.attr('stroke', 'white');
})
.on('dragend', function() {
.on('end', function() {
var newTreatment;
chart().drag.selectAll('.drag-droparea').remove();
hideTooltip();
@@ -1009,8 +1021,9 @@ function init (client, d3) {
var basalareadata = [];
var tempbasalareadata = [];
var comboareadata = [];
var from = chart().brush.extent()[0].getTime();
var to = Math.max(chart().brush.extent()[1].getTime(), client.sbx.time) + client.forecastTime;
var selectedRange = chart().createAdjustedRange();
var from = selectedRange[0].getTime();
var to = Math.max(selectedRange[1].getTime(), client.sbx.time) + client.forecastTime;
var date = from;
var lastbasal = 0;
@@ -1069,16 +1082,16 @@ function init (client, d3) {
chart().basals.selectAll('.tempbasalarea').remove().data(tempbasalareadata);
chart().basals.selectAll('.comboarea').remove().data(comboareadata);
var valueline = d3.svg.line()
.interpolate('step-after')
var valueline = d3.line()
.x(function(d) { return chart().xScaleBasals(d.d); })
.y(function(d) { return chart().yScaleBasals(d.b); });
.y(function(d) { return chart().yScaleBasals(d.b); })
.curve(d3.curveStepAfter);
var area = d3.svg.area()
.interpolate('step-after')
var area = d3.area()
.x(function(d) { return chart().xScaleBasals(d.d); })
.y0(chart().yScaleBasals(0))
.y1(function(d) { return chart().yScaleBasals(d.b); });
.y1(function(d) { return chart().yScaleBasals(d.b); })
.curve(d3.curveStepAfter);
var g = chart().basals.append('g');
@@ -1159,8 +1172,9 @@ function init (client, d3) {
}
// calculate position of profile on left side
var from = chart().brush.extent()[0].getTime();
var to = chart().brush.extent()[1].getTime();
var selectedRange = chart().createAdjustedRange();
var from = selectedRange[0].getTime();
var to = selectedRange[1].getTime();
var mult = (to - from) / times.hours(24).msecs;
from += times.mins(20 * mult).msecs;
+1 -1
View File
@@ -86,7 +86,7 @@ function init (majorPills, minorPills, statusPills, bgStatus, tooltip) {
pill.mouseover(function pillMouseover (event) {
tooltip.transition().duration(200).style('opacity', .9);
var windowWidth = $(tooltip).parent().parent().width();
var windowWidth = $(tooltip.node()).parent().parent().width();
var left = event.pageX + TOOLTIP_WIDTH < windowWidth ? event.pageX : windowWidth - TOOLTIP_WIDTH - 10;
tooltip.html(html)
.style('left', left + 'px')
+5 -9
View File
@@ -146,20 +146,16 @@ calibrations.report = function report_calibrations (datastorage, sorteddaystosho
calibration_context = charts.append('g');
// define the parts of the axis that aren't dependent on width or height
xScale2 = d3.scale.linear()
xScale2 = d3.scaleLinear()
.domain([0, maxBG]);
yScale2 = d3.scale.linear()
yScale2 = d3.scaleLinear()
.domain([0, 400000]);
var xAxis2 = d3.svg.axis()
.scale(xScale2)
.ticks(10)
.orient('bottom');
var xAxis2 = d3.axisBottom(xScale2)
.ticks(10);
var yAxis2 = d3.svg.axis()
.scale(yScale2)
.orient('left');
var yAxis2 = d3.axisLeft(yScale2);
// get current data range
var dataRange = [0, maxBG];
+22 -25
View File
@@ -170,37 +170,33 @@ daytoday.report = function report_daytoday (datastorage, sorteddaystoshow, optio
context = charts.append('g');
// define the parts of the axis that aren't dependent on width or height
xScale2 = d3.time.scale()
xScale2 = d3.scaleTime()
.domain(d3.extent(data.sgv, dateFn));
if (options.scale === report_plugins.consts.SCALE_LOG) {
yScale2 = d3.scale.log()
yScale2 = d3.scaleLog()
.domain([client.utils.scaleMgdl(options.basal ? 30 : 36), client.utils.scaleMgdl(420)]);
} else {
yScale2 = d3.scale.linear()
yScale2 = d3.scaleLinear()
.domain([client.utils.scaleMgdl(options.basal ? -40 : 36), client.utils.scaleMgdl(420)]);
}
// allow insulin to be negative (when plotting negative IOB)
yInsulinScale = d3.scale.linear()
yInsulinScale = d3.scaleLinear()
.domain([-2 * options.maxInsulinValue, 2 * options.maxInsulinValue]);
yCarbsScale = d3.scale.linear()
yCarbsScale = d3.scaleLinear()
.domain([0, options.maxCarbsValue * 1.25]);
yScaleBasals = d3.scale.linear();
yScaleBasals = d3.scaleLinear();
xAxis2 = d3.svg.axis()
.scale(xScale2)
xAxis2 = d3.axisBottom(xScale2)
.tickFormat(timeTicks)
.ticks(24)
.orient('bottom');
.ticks(24);
yAxis2 = d3.svg.axis()
.scale(yScale2)
yAxis2 = d3.axisLeft(yScale2)
.tickFormat(d3.format('d'))
.tickValues(tickValues)
.orient('left');
.tickValues(tickValues);
// get current data range
var dataRange = d3.extent(data.sgv, dateFn);
@@ -602,13 +598,13 @@ daytoday.report = function report_daytoday (datastorage, sorteddaystoshow, optio
yScaleBasals.domain([basalMax, 0]);
var valueline = d3.svg.line()
.interpolate('step-after')
var valueline = d3.line()
.curve(d3.curveStepAfter)
.x(function(d) { return xScale2(d.d) + padding.left; })
.y(function(d) { return yScaleBasals(d.b) + padding.top; });
var area = d3.svg.area()
.interpolate('step-after')
var area = d3.area()
.curve(d3.curveStepAfter)
.x(function(d) { return xScale2(d.d) + padding.left; })
.y0(yScaleBasals(0) + padding.top)
.y1(function(d) { return yScaleBasals(d.b) + padding.top; });
@@ -931,9 +927,9 @@ daytoday.report = function report_daytoday (datastorage, sorteddaystoshow, optio
var height = 120;
var radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal().range([basalcolor, boluscolor]);
var color = d3.scaleOrdinal().range([basalcolor, boluscolor]);
var labelArc = d3.svg.arc()
var labelArc = d3.arc()
.outerRadius(radius / 2)
.innerRadius(radius / 2);
@@ -945,10 +941,11 @@ daytoday.report = function report_daytoday (datastorage, sorteddaystoshow, optio
.attr('transform', 'translate(' + (width / 2) +
',' + (height / 2) + ')');
var arc = d3.svg.arc()
var arc = d3.arc()
.innerRadius(0)
.outerRadius(radius);
var pie = d3.layout.pie()
var pie = d3.pie()
.value(function(d) {
return d.count;
})
@@ -980,7 +977,7 @@ daytoday.report = function report_daytoday (datastorage, sorteddaystoshow, optio
// Carbs pie chart
var carbscolor = d3.scale.ordinal().range(['red']);
var carbscolor = d3.scaleOrdinal().range(['red']);
var carbsData = [
{ label: translate('Carbs'), count: data.dailyCarbs }
@@ -994,10 +991,10 @@ daytoday.report = function report_daytoday (datastorage, sorteddaystoshow, optio
.attr('transform', 'translate(' + (width / 2) +
',' + (height / 2) + ')');
var carbsarc = d3.svg.arc()
var carbsarc = d3.arc()
.outerRadius(radius * data.dailyCarbs / options.maxDailyCarbsValue);
var carbspie = d3.layout.pie()
var carbspie = d3.pie()
.value(function(d) {
return d.count;
})
+7 -11
View File
@@ -196,28 +196,24 @@ weektoweek.report = function report_weektoweek(datastorage, sorteddaystoshow, op
context = charts.append('g');
// define the parts of the axis that aren't dependent on width or height
xScale2 = d3.time.scale()
xScale2 = d3.scaleTime()
.domain(d3.extent(sgvData, dateFn));
if (options.weekscale === report_plugins.consts.SCALE_LOG) {
yScale2 = d3.scale.log()
yScale2 = d3.scaleLog()
.domain([client.utils.scaleMgdl(36), client.utils.scaleMgdl(420)]);
} else {
yScale2 = d3.scale.linear()
yScale2 = d3.scaleLinear()
.domain([client.utils.scaleMgdl(36), client.utils.scaleMgdl(420)]);
}
xAxis2 = d3.svg.axis()
.scale(xScale2)
xAxis2 = d3.axisBottom(xScale2)
.tickFormat(timeTicks)
.ticks(24)
.orient('bottom');
.ticks(24);
yAxis2 = d3.svg.axis()
.scale(yScale2)
yAxis2 = d3.axisLeft(yScale2)
.tickFormat(d3.format('d'))
.tickValues(tickValues)
.orient('left');
.tickValues(tickValues);
// get current data range
var dataRange = d3.extent(sgvData, dateFn);
+289 -44
View File
@@ -2272,7 +2272,7 @@
},
"browserify-aes": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
"resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
"integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
"requires": {
"buffer-xor": "^1.0.3",
@@ -2306,7 +2306,7 @@
},
"browserify-rsa": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
"resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
"requires": {
"bn.js": "^4.1.0",
@@ -2352,7 +2352,7 @@
},
"buffer": {
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
"resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
"integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
"requires": {
"base64-js": "^1.0.2",
@@ -3056,7 +3056,7 @@
},
"create-hash": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
"resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
"requires": {
"cipher-base": "^1.0.1",
@@ -3068,7 +3068,7 @@
},
"create-hmac": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
"resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
"integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
"requires": {
"cipher-base": "^1.0.3",
@@ -3185,9 +3185,268 @@
"integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA="
},
"d3": {
"version": "3.5.17",
"resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz",
"integrity": "sha1-vEZ0gAQ3iyGjYMn8fPUjF5B2L7g="
"version": "5.12.0",
"resolved": "https://registry.npmjs.org/d3/-/d3-5.12.0.tgz",
"integrity": "sha512-flYVMoVuhPFHd9zVCe2BxIszUWqBcd5fvQGMNRmSiBrgdnh6Vlruh60RJQTouAK9xPbOB0plxMvBm4MoyODXNg==",
"requires": {
"d3-array": "1",
"d3-axis": "1",
"d3-brush": "1",
"d3-chord": "1",
"d3-collection": "1",
"d3-color": "1",
"d3-contour": "1",
"d3-dispatch": "1",
"d3-drag": "1",
"d3-dsv": "1",
"d3-ease": "1",
"d3-fetch": "1",
"d3-force": "1",
"d3-format": "1",
"d3-geo": "1",
"d3-hierarchy": "1",
"d3-interpolate": "1",
"d3-path": "1",
"d3-polygon": "1",
"d3-quadtree": "1",
"d3-random": "1",
"d3-scale": "2",
"d3-scale-chromatic": "1",
"d3-selection": "1",
"d3-shape": "1",
"d3-time": "1",
"d3-time-format": "2",
"d3-timer": "1",
"d3-transition": "1",
"d3-voronoi": "1",
"d3-zoom": "1"
}
},
"d3-array": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
"integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
},
"d3-axis": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz",
"integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ=="
},
"d3-brush": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.3.tgz",
"integrity": "sha512-v8bbYyCFKjyCzFk/tdWqXwDykY8YWqhXYjcYxfILIit085VZOpj4XJKOMccTsvWxgzSLMJQg5SiqHjslsipEDg==",
"requires": {
"d3-dispatch": "1",
"d3-drag": "1",
"d3-interpolate": "1",
"d3-selection": "1",
"d3-transition": "1"
}
},
"d3-chord": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz",
"integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==",
"requires": {
"d3-array": "1",
"d3-path": "1"
}
},
"d3-collection": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz",
"integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A=="
},
"d3-color": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.0.tgz",
"integrity": "sha512-TzNPeJy2+iEepfiL92LAAB7fvnp/dV2YwANPVHdDWmYMm23qIJBYww3qT8I8C1wXrmrg4UWs7BKc2tKIgyjzHg=="
},
"d3-contour": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz",
"integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==",
"requires": {
"d3-array": "^1.1.1"
}
},
"d3-dispatch": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.5.tgz",
"integrity": "sha512-vwKx+lAqB1UuCeklr6Jh1bvC4SZgbSqbkGBLClItFBIYH4vqDJCA7qfoy14lXmJdnBOdxndAMxjCbImJYW7e6g=="
},
"d3-drag": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.4.tgz",
"integrity": "sha512-ICPurDETFAelF1CTHdIyiUM4PsyZLaM+7oIBhmyP+cuVjze5vDZ8V//LdOFjg0jGnFIZD/Sfmk0r95PSiu78rw==",
"requires": {
"d3-dispatch": "1",
"d3-selection": "1"
}
},
"d3-dsv": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.1.1.tgz",
"integrity": "sha512-1EH1oRGSkeDUlDRbhsFytAXU6cAmXFzc52YUe6MRlPClmWb85MP1J5x+YJRzya4ynZWnbELdSAvATFW/MbxaXw==",
"requires": {
"commander": "2",
"iconv-lite": "0.4",
"rw": "1"
}
},
"d3-ease": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.5.tgz",
"integrity": "sha512-Ct1O//ly5y5lFM9YTdu+ygq7LleSgSE4oj7vUt9tPLHUi8VCV7QoizGpdWRWAwCO9LdYzIrQDg97+hGVdsSGPQ=="
},
"d3-fetch": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.1.2.tgz",
"integrity": "sha512-S2loaQCV/ZeyTyIF2oP8D1K9Z4QizUzW7cWeAOAS4U88qOt3Ucf6GsmgthuYSdyB2HyEm4CeGvkQxWsmInsIVA==",
"requires": {
"d3-dsv": "1"
}
},
"d3-force": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz",
"integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==",
"requires": {
"d3-collection": "1",
"d3-dispatch": "1",
"d3-quadtree": "1",
"d3-timer": "1"
}
},
"d3-format": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.1.tgz",
"integrity": "sha512-TUswGe6hfguUX1CtKxyG2nymO+1lyThbkS1ifLX0Sr+dOQtAD5gkrffpHnx+yHNKUZ0Bmg5T4AjUQwugPDrm0g=="
},
"d3-geo": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.11.6.tgz",
"integrity": "sha512-z0J8InXR9e9wcgNtmVnPTj0TU8nhYT6lD/ak9may2PdKqXIeHUr8UbFLoCtrPYNsjv6YaLvSDQVl578k6nm7GA==",
"requires": {
"d3-array": "1"
}
},
"d3-hierarchy": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.8.tgz",
"integrity": "sha512-L+GHMSZNwTpiq4rt9GEsNcpLa4M96lXMR8M/nMG9p5hBE0jy6C+3hWtyZMenPQdwla249iJy7Nx0uKt3n+u9+w=="
},
"d3-interpolate": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.3.2.tgz",
"integrity": "sha512-NlNKGopqaz9qM1PXh9gBF1KSCVh+jSFErrSlD/4hybwoNX/gt1d8CDbDW+3i+5UOHhjC6s6nMvRxcuoMVNgL2w==",
"requires": {
"d3-color": "1"
}
},
"d3-path": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.8.tgz",
"integrity": "sha512-J6EfUNwcMQ+aM5YPOB8ZbgAZu6wc82f/0WFxrxwV6Ll8wBwLaHLKCqQ5Imub02JriCVVdPjgI+6P3a4EWJCxAg=="
},
"d3-polygon": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.5.tgz",
"integrity": "sha512-RHhh1ZUJZfhgoqzWWuRhzQJvO7LavchhitSTHGu9oj6uuLFzYZVeBzaWTQ2qSO6bz2w55RMoOCf0MsLCDB6e0w=="
},
"d3-quadtree": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.6.tgz",
"integrity": "sha512-NUgeo9G+ENQCQ1LsRr2qJg3MQ4DJvxcDNCiohdJGHt5gRhBW6orIB5m5FJ9kK3HNL8g9F4ERVoBzcEwQBfXWVA=="
},
"d3-random": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz",
"integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ=="
},
"d3-scale": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz",
"integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==",
"requires": {
"d3-array": "^1.2.0",
"d3-collection": "1",
"d3-format": "1",
"d3-interpolate": "1",
"d3-time": "1",
"d3-time-format": "2"
}
},
"d3-scale-chromatic": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz",
"integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==",
"requires": {
"d3-color": "1",
"d3-interpolate": "1"
}
},
"d3-selection": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.0.tgz",
"integrity": "sha512-EYVwBxQGEjLCKF2pJ4+yrErskDnz5v403qvAid96cNdCMr8rmCYfY5RGzWz24mdIbxmDf6/4EAH+K9xperD5jg=="
},
"d3-shape": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.5.tgz",
"integrity": "sha512-VKazVR3phgD+MUCldapHD7P9kcrvPcexeX/PkMJmkUov4JM8IxsSg1DvbYoYich9AtdTsa5nNk2++ImPiDiSxg==",
"requires": {
"d3-path": "1"
}
},
"d3-time": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz",
"integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA=="
},
"d3-time-format": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.1.3.tgz",
"integrity": "sha512-6k0a2rZryzGm5Ihx+aFMuO1GgelgIz+7HhB4PH4OEndD5q2zGn1mDfRdNrulspOfR6JXkb2sThhDK41CSK85QA==",
"requires": {
"d3-time": "1"
}
},
"d3-timer": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.9.tgz",
"integrity": "sha512-rT34J5HnQUHhcLvhSB9GjCkN0Ddd5Y8nCwDBG2u6wQEeYxT/Lf51fTFFkldeib/sE/J0clIe0pnCfs6g/lRbyg=="
},
"d3-transition": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.2.0.tgz",
"integrity": "sha512-VJ7cmX/FPIPJYuaL2r1o1EMHLttvoIuZhhuAlRoOxDzogV8iQS6jYulDm3xEU3TqL80IZIhI551/ebmCMrkvhw==",
"requires": {
"d3-color": "1",
"d3-dispatch": "1",
"d3-ease": "1",
"d3-interpolate": "1",
"d3-selection": "^1.1.0",
"d3-timer": "1"
}
},
"d3-voronoi": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz",
"integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg=="
},
"d3-zoom": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz",
"integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==",
"requires": {
"d3-dispatch": "1",
"d3-drag": "1",
"d3-interpolate": "1",
"d3-selection": "1",
"d3-transition": "1"
}
},
"dashdash": {
"version": "1.14.1",
@@ -3354,7 +3613,7 @@
},
"diffie-hellman": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
"resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
"integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
"requires": {
"bn.js": "^4.1.0",
@@ -4434,8 +4693,7 @@
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"optional": true
"bundled": true
},
"aproba": {
"version": "1.2.0",
@@ -4453,13 +4711,11 @@
},
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"optional": true
"bundled": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -4472,18 +4728,15 @@
},
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"optional": true
"bundled": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"optional": true
"bundled": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"optional": true
"bundled": true
},
"core-util-is": {
"version": "1.0.2",
@@ -4586,8 +4839,7 @@
},
"inherits": {
"version": "2.0.3",
"bundled": true,
"optional": true
"bundled": true
},
"ini": {
"version": "1.3.5",
@@ -4597,7 +4849,6 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -4610,20 +4861,17 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"bundled": true,
"optional": true
"bundled": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -4640,7 +4888,6 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -4713,8 +4960,7 @@
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"optional": true
"bundled": true
},
"object-assign": {
"version": "4.1.1",
@@ -4724,7 +4970,6 @@
"once": {
"version": "1.4.0",
"bundled": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@@ -4800,8 +5045,7 @@
},
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"optional": true
"bundled": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -4831,7 +5075,6 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -4849,7 +5092,6 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -4888,13 +5130,11 @@
},
"wrappy": {
"version": "1.0.2",
"bundled": true,
"optional": true
"bundled": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"optional": true
"bundled": true
}
}
},
@@ -6115,7 +6355,7 @@
},
"json5": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
"resolved": "http://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
"requires": {
"minimist": "^1.2.0"
@@ -6599,7 +6839,7 @@
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -9162,7 +9402,7 @@
},
"readable-stream": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": {
"core-util-is": "~1.0.0",
@@ -9515,6 +9755,11 @@
"aproba": "^1.1.1"
}
},
"rw": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
"integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q="
},
"rxjs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz",
@@ -9665,7 +9910,7 @@
},
"sha.js": {
"version": "2.4.11",
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
"resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
"requires": {
"inherits": "^2.0.1",
@@ -10541,7 +10786,7 @@
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
+1 -1
View File
@@ -69,7 +69,7 @@
"compression": "^1.7.4",
"css-loader": "^1.0.1",
"cssmin": "^0.4.3",
"d3": "^3.5.17",
"d3": "^5.12.0",
"ejs": "^2.6.2",
"errorhandler": "^1.5.1",
"event-stream": "3.3.4",