diff --git a/static/css/drawer.css b/static/css/drawer.css index 1a388182565..9e99bd04b1d 100644 --- a/static/css/drawer.css +++ b/static/css/drawer.css @@ -156,6 +156,7 @@ h1, legend, top: 0; margin: 0; height: 44px; + text-shadow: 0 0 5px black; } #toolbar h1 { diff --git a/static/css/main.css b/static/css/main.css index 9e7e36a6590..775afcc5130 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -38,6 +38,7 @@ body { float: right; text-align: center; white-space: nowrap; + padding-right: 20px; } .bgButton.urgent { @@ -203,21 +204,43 @@ body { margin: 10px; border: 2px solid #000; border-radius: 5px; - width: 320px; + width: 360px; +} + +.loading .bgButton .rawnoise { + display: none; +} + +.bgButton .rawnoise { + display: inline-block; + border-radius: 2px; + border: 1px solid #808080; +} + +.bgButton .rawnoise em { + color: white; + background-color: black; + display: block; + font-size: 20px; +} + +.bgButton .rawnoise label { + display: block; + font-size: 14px; } .alarming .bgButton { - border-color: #bdbdbd; - color: #000; - box-shadow: 2px 2px 0 #ddd; + border-color: #bdbdbd; + color: #000; + box-shadow: 2px 2px 0 #ddd; } .alarming .bgButton.urgent { - background-color: red; + background-color: red; } .alarming .bgButton.warning { - background-color: yellow; + background-color: yellow; } .alarming .bgButton:active { @@ -227,6 +250,7 @@ body { -webkit-box-shadow: none; } + .button { text-align: center; background: #ababab; @@ -280,7 +304,7 @@ div.tooltip { @media (max-width: 800px) { .bgStatus { - width: 40%; + width: 300px; } .bgButton { @@ -343,7 +367,16 @@ div.tooltip { @media (max-width: 750px) { .bgStatus { - width: 60%; + width: 240px; + padding: 0; + } + + .bgButton .rawnoise em { + font-size: 14px; + } + + .bgButton .rawnoise label { + font-size: 12px; } .bgStatus .currentBG { @@ -388,11 +421,12 @@ div.tooltip { .bgStatus { float: none; - margin: 0 auto; padding: 0; - width: 100vw; + text-align: center; + width: 250px; } + .bgButton { margin: 5px; width: auto; @@ -424,15 +458,10 @@ div.tooltip { } .time { - width: auto; padding-top: 0; font-size: 20px !important; } - #container.alarming .time { - display: none; - } - .timebox { width: auto; } @@ -452,14 +481,11 @@ div.tooltip { font-size: 15px !important; } - .alarming .focus-range { - display: none; - } - .focus-range { position: absolute; - top: 70px; - left: 20px; + top: 80px; + left: initial; + right: 10px; margin: 0; width: auto; } @@ -514,8 +540,8 @@ div.tooltip { @media (max-height: 480px) and (min-width: 400px) { .bgStatus .currentBG { - font-size: 80px; - line-height: 80px; + font-size: 70px; + line-height: 60px; } .bgStatus .currentBG.bg-limit, .bgStatus .currentBG.icon-hourglass { @@ -523,8 +549,8 @@ div.tooltip { } .bgStatus .currentDirection { - font-size: 70px; - line-height: 70px; + font-size: 50px; + line-height: 50px; } .bgStatus .currentDetails { @@ -532,8 +558,8 @@ div.tooltip { } .time { - font-size: 70px; - line-height: 60px; + font-size: 50px; + line-height: 40px; padding-top: 5px; } @@ -549,6 +575,13 @@ div.tooltip { @media (max-height: 480px) and (max-width: 400px) { + .bgStatus { + text-align: center; + width: 220px; + left: 0; + position: absolute; + } + .bgStatus .currentBG { font-size: 60px; line-height: 60px; @@ -569,8 +602,9 @@ div.tooltip { .focus-range { position: absolute; - top: 10px; - left: 10px; + top: 40px; + left: initial; + right: 35px; margin: 0; width: auto; } @@ -579,4 +613,13 @@ div.tooltip { display: block; } + .time { + position: absolute; + top: 90px; + } + + .timebox { + width: 220px; + } + } diff --git a/static/index.html b/static/index.html index 0ff53abe7ba..788fd06d21f 100644 --- a/static/index.html +++ b/static/index.html @@ -28,6 +28,7 @@

Nightscout

+ --- -
diff --git a/static/js/client.js b/static/js/client.js index 96a39931b25..33cd3f8b58b 100644 --- a/static/js/client.js +++ b/static/js/client.js @@ -61,6 +61,7 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage; , focusHeight , contextHeight , dateFn = function (d) { return new Date(d.date) } + , documentHidden = false , brush , brushTimer , brushInProgress = false @@ -111,37 +112,64 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage; } } - function showRawBGs() { - return app.enabledOptions - && app.enabledOptions.indexOf('rawbg') > -1 - && (browserSettings.showRawbg == 'always' || browserSettings.showRawbg == 'noise'); + function isRawBGEnabled() { + return app.enabledOptions && app.enabledOptions.indexOf('rawbg') > -1; } - function showIOB() { - return app.enabledOptions - && app.enabledOptions.indexOf('iob') > -1; + function showRawBGs(sgv, noise, cal) { + return cal + && isRawBGEnabled() + && (browserSettings.showRawbg == 'always' + || (browserSettings.showRawbg == 'noise' && (noise >= 2 || sgv < 40)) + ); + } + + function noiseCodeToDisplay(sgv, noise) { + var display; + switch (parseInt(noise)) { + case 0: display = '---'; break; + case 1: display = 'Clean'; break; + case 2: display = 'Light'; break; + case 3: display = 'Medium'; break; + case 4: display = 'Heavy'; break; + default: + if (sgv < 40) { + display = 'Heavy'; + } else { + display = '~~~'; + } + break; + } + + return display; } function rawIsigToRawBg(entry, cal) { - var unfiltered = parseInt(entry.unfiltered) || 0 + var raw = 0 + , unfiltered = parseInt(entry.unfiltered) || 0 , filtered = parseInt(entry.filtered) || 0 , sgv = entry.y - , noise = entry.noise || 0 , scale = parseFloat(cal.scale) || 0 , intercept = parseFloat(cal.intercept) || 0 , slope = parseFloat(cal.slope) || 0; + if (slope == 0 || unfiltered == 0 || scale == 0) { - return 0; - } else if (noise < 2 && browserSettings.showRawbg != 'always') { - return 0; + raw = 0; } else if (filtered == 0 || sgv < 40) { - return scale * (unfiltered - intercept) / slope; + raw = scale * (unfiltered - intercept) / slope; } else { var ratio = scale * (filtered - intercept) / slope / sgv; - return scale * ( unfiltered - intercept) / slope / ratio; + raw = scale * ( unfiltered - intercept) / slope / ratio; } + + return Math.round(raw); + } + + function showIOB() { + return app.enabledOptions + && app.enabledOptions.indexOf('iob') > -1; } // initial setup of chart when data is first made available @@ -267,19 +295,6 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage; return errorDisplay; } - function noiseCodeToDisplay(noise) { - var display = 'Not Set'; - switch (parseInt(noise)) { - case 1: display = 'Clean'; break; - case 2: display = 'Light'; break; - case 3: display = 'Medium'; break; - case 4: display = 'Heavy'; break; - case 5: display = 'Unknown'; break; - } - - return display; - } - // function to call when context chart is brushed function brushed(skipTimer) { @@ -313,10 +328,15 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage; , currentBG = $('.bgStatus .currentBG') , currentDirection = $('.bgStatus .currentDirection') , currentDetails = $('.bgStatus .currentDetails') + , rawNoise = bgButton.find('.rawnoise') + , rawbg = rawNoise.find('em') + , noiseLevel = rawNoise.find('label') , lastEntry = $('#lastEntry'); - function updateCurrentSGV(value) { + function updateCurrentSGV(entry) { + var value = entry.y; + if (value == 9) { currentBG.text(''); } else if (value < 39) { @@ -336,11 +356,41 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage; } } + if (showRawBGs(entry.y, entry.noise, cal)) { + rawNoise.css('display', 'inline-block'); + rawbg.text(scaleBg(rawIsigToRawBg(entry, cal))); + noiseLevel.text(noiseCodeToDisplay(entry.y, entry.noise)); + } else { + rawNoise.hide(); + } + currentBG.toggleClass('icon-hourglass', value == 9); currentBG.toggleClass('error-code', value < 39); currentBG.toggleClass('bg-limit', value == 39 || value > 400); } + function updateCurrentNoise(entry) { + var noise = entry.noise + , noiseType; + + if (!showRawBGs(entry.y, noise, cal)) { + noiseType = null; + } else if (entry.y < 40) { + noiseType = 'error'; + } else if (noise == 2) { + noiseType = 'light'; + } else if (noise == 3) { + noiseType = 'medium'; + } else if (noise >= 4) { + noiseType = 'heavy'; + } + + bgButton.removeClass('noise-light noise-medium noise-heavy noise-error'); + if (noiseType) { + bgButton.addClass('noise-' + noiseType); + } + } + function updateBGDelta(prev, current) { var pill = currentDetails.find('span.pill.bgdelta'); @@ -415,7 +465,8 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage; var focusPoint = nowData[nowData.length - 1]; var prevfocusPoint = nowData[nowData.length - 2]; - updateCurrentSGV(focusPoint.y); + updateCurrentSGV(focusPoint); + updateCurrentNoise(focusPoint); updateBGDelta(prevfocusPoint.y, focusPoint.y); @@ -425,6 +476,8 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage; updateBGDelta(); currentBG.text('---'); currentDirection.text('-'); + rawNoise.hide(); + bgButton.removeClass('urgent warning inrange'); } updateIOBIndicator(time); @@ -439,7 +492,8 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage; nowData = nowData.slice(nowData.length - 1 - lookback, nowData.length); nowDate = new Date(now); - updateCurrentSGV(latestSGV.y); + updateCurrentSGV(latestSGV); + updateCurrentNoise(latestSGV); updateClockDisplay(); updateTimeAgo(); @@ -524,17 +578,22 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage; .on('mouseover', function (d) { if (d.type != 'sgv' && d.type != 'mbg') return; - var device = d.device && d.device.toLowerCase(); - var bgType = (d.type == 'sgv' ? 'CGM' : (device == 'dexcom' ? 'Calibration' : 'Meter')); - var noiseLabel = ''; + var device = d.device && d.device.toLowerCase() + , bgType = (d.type == 'sgv' ? 'CGM' : (device == 'dexcom' ? 'Calibration' : 'Meter')) + , rawBG = 0 + , noiseLabel = ''; - if (d.type == 'sgv' && showRawBGs()) { - noiseLabel = noiseCodeToDisplay(d.noise); + if (d.type == 'sgv') { + if (showRawBGs(d.y, d.noise, cal)) { + rawBG = scaleBg(rawIsigToRawBg(d, cal)); + } + noiseLabel = noiseCodeToDisplay(d.y, d.noise); } tooltip.transition().duration(TOOLTIP_TRANS_MS).style('opacity', .9); tooltip.html('' + bgType + ' BG: ' + d.sgv + (d.type == 'mbg' ? '
Device: ' + d.device : '') + + (rawBG ? '
Raw BG: ' + rawBG : '') + (noiseLabel ? '
Noise: ' + noiseLabel : '') + '
Time: ' + formatTime(d.date)) .style('left', (d3.event.pageX) + 'px') @@ -656,6 +715,10 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage; // called for initial update and updates for resize function updateChart(init) { + if (documentHidden && !init) { + console.info('Document Hidden, not updating - ' + (new Date())); + return; + } // get current data range var dataRange = d3.extent(data, dateFn); @@ -1127,9 +1190,10 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage; var totalBG = 0; closeBGs.forEach(function(d) { totalBG += Number(d.y); + parseFloat() }); - return totalBG > 0 && closeBGs.length > 0 ? (totalBG / closeBGs.length) : 450; + return totalBG > 0 ? (totalBG / closeBGs.length) : 450; } var treatmentGlucose = null; @@ -1421,19 +1485,32 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage; context.append('g') .attr('class', 'y axis'); - window.onresize = function () { - updateChartSoon() - } - // look for resize but use timer to only call the update script when a resize stops var resizeTimer; function updateChartSoon() { clearTimeout(resizeTimer); resizeTimer = setTimeout(function () { updateChart(false); - }, 100); + }, 200); + } + + function visibilityChanged() { + var prevHidden = documentHidden; + documentHidden = (document.hidden || document.webkitHidden || document.mozHidden || document.msHidden); + + if (prevHidden && !documentHidden) { + console.info('Document now visible, updating - ' + (new Date())); + updateChartSoon(); + } + } + + window.onresize = function () { + updateChartSoon() }; + document.addEventListener('webkitvisibilitychange', visibilityChanged); + + updateClock(); var silenceDropdown = new Dropdown('.dropdown-menu'); @@ -1480,14 +1557,15 @@ var app = {}, browserSettings = {}, browserStorage = $.localStorage; devicestatusData = d[6]; var temp1 = [ ]; - if (cal && showRawBGs()) { + if (cal && isRawBGEnabled()) { temp1 = d[0].map(function (entry) { - var rawBg = rawIsigToRawBg(entry, cal); + var noise = entry.noise || 0; + var rawBg = noise < 2 && browserSettings.showRawbg != 'always' ? 0 : rawIsigToRawBg(entry, cal); return { date: new Date(entry.x - 2 * 1000), y: rawBg, sgv: scaleBg(rawBg), color: 'white', type: 'rawbg'} }).filter(function(entry) { return entry.y > 0}); } var temp2 = d[0].map(function (obj) { - return { date: new Date(obj.x), y: obj.y, sgv: scaleBg(obj.y), direction: obj.direction, color: sgvToColor(obj.y), type: 'sgv', noise: obj.noise} + return { date: new Date(obj.x), y: obj.y, sgv: scaleBg(obj.y), direction: obj.direction, color: sgvToColor(obj.y), type: 'sgv', noise: obj.noise, filtered: obj.filtered, unfiltered: obj.unfiltered} }); data = []; data = data.concat(temp1, temp2);