Skip to content

Commit

Permalink
Configurable clock views (#5625)
Browse files Browse the repository at this point in the history
* Configurable clock views

* Configurable clock views

* Configurable clock views

* Configurable clock views

* Configurable clock views

* Configurable clock views

* Update README.md

* Update README.md

* Configurable clock views
  • Loading branch information
ireneusz-ptak authored Jun 12, 2020
1 parent f3fab56 commit 3d6f488
Show file tree
Hide file tree
Showing 11 changed files with 263 additions and 188 deletions.
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,11 +306,29 @@ To learn more about the Nightscout API, visit https://YOUR-SITE.com/api-docs/ or

### Views

There are a few alternate web views available from the main menu that display a simplified BG stream. (If you launch one of these in a fullscreen view in iOS, you can use a left-to-right swipe gesture to exit the view.)
Nightscout allows to create custom, simplified views using a predefined set of elements. This option is available under `[+]` link in the main menu.

List of available items:
* `SGV` - Sensor Glucose Value
* `SGV age` - time since the last SGV read
* `SGV delta` - change of SGV in the last 5 minutes
* `Trend arrow` - icon of the SG trend
* `Time` - current time
* `Line break` - invisible item that will move following items to the next line (by default all are showing on the same level)

All visible items have `Size` property which allows to customize the view even more. Also, all items may appear multiple times on the view.

Apart from adding items, it is possible to customize other aspects of the views, like selecting `Color` or `Black` background. The first one will indicate current BG threshold (green = in range; blue = below range; yellow = above range; red = urgent below/above).
`Show SGV age` option will make `SGV age` item appear `Always` or only if the predefined threshold is reached: `Only after threshold`. Breaching `SGV age threshold` will also make `Color` background turn grey and strike through `SGV`.
`Clock view configurator` will generate an URL (available under `Open my clock view!` link) that could be bookmarked.

There are a few default views available from the main menu:
* `Clock` - Shows current BG, trend arrow, and time of day. Grey text on a black background.
* `Color` - Shows current BG and trend arrow. White text on a background that changes color to indicate current BG threshold (green = in range; blue = below range; yellow = above range; red = urgent below/above). Set `SHOW_CLOCK_DELTA` to `true` to show BG change in the last 5 minutes, set `SHOW_CLOCK_LAST_TIME` to `true` to always show BG age.
* `Color` - Shows current BG and trend arrow. White text on a color background.
* `Simple` - Shows current BG. Grey text on a black background.

If you launch one of these views in a fullscreen view in iOS, you can use a left-to-right swipe gesture to exit the view.

### Split View

Some users will need easy access to multiple Nightscout views at the same time. We have a special view for this case, accessed on /split path on your Nightscout URL. The view supports any number of sites between 1 to 8 way split, where the content for the screen can be loaded from multiple Nightscout instances. Note you still need to host separate instances for each Nightscout being monitored including the one that hosts the split view page - these variables only add the ability to load multiple views into one browser page. To set the URLs from which the content is loaded, set:
Expand Down
180 changes: 104 additions & 76 deletions lib/client/clock-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ var client = {};

client.settings = browserSettings(client, window.serverSettings, $);

// console.log('settings', client.settings);
//console.log('settings', client.settings);
// client.settings now contains all settings

client.query = function query () {
Expand All @@ -20,7 +20,7 @@ client.query = function query () {
});

var secret = localStorage.getItem('apisecrethash');
var src = '/api/v1/entries.json?count=3&t=' + new Date().getTime();
var src = '/api/v1/entries.json?find[type]=sgv&count=3&t=' + new Date().getTime();

if (secret) {
src += '&secret=' + secret;
Expand All @@ -39,6 +39,7 @@ client.render = function render (xhr) {
let rec;
let delta;

// Get SGV, calculate DELTA
xhr.forEach(element => {
if (element.sgv && !rec) {
rec = element;
Expand All @@ -49,28 +50,65 @@ client.render = function render (xhr) {
});

let $errorMessage = $('#errorMessage');
let $inner = $('#inner');

// If no one measured value found => show "-?-"
if (!rec) {
if (!$errorMessage.length) {
$('#arrowDiv').append('<div id="errorMessage" title="No data found in DB">-?-</div>');
$('#arrow').hide();
$inner.after('<div id="errorMessage" title="No data found in DB">-?-</div>')
} else {
$errorMessage.show();
}
$inner.hide();
return;
} else {
$errorMessage.length && $errorMessage.hide();
$('#arrow').show();
$inner.show();
}

//Parse face parameters
let face = $inner.data('face').toLowerCase();

// Backward compatible
if (face === 'clock-color') {
face = 'c' + (window.serverSettings.settings.showClockLastTime ? 'y' : 'n') + '13-sg40-' + (window.serverSettings.settings.showClockDelta ? 'dt14-' : '') + 'nl-ar30-nl-ag6';
}
else if (face === 'clock') {
face = 'bn0-sg40';
}
else if (face === 'bgclock') {
face = 'bn0-sg30-ar18-nl-nl-tm26';
}
else if (face === 'config') {
face = $inner.attr('data-face-config');
$inner.empty();
}

let faceParams = face.split('-');
let bgColor = false;
let staleMinutes = 13;
let alwaysShowTime = false;

let clockCreated = ($inner.children().length > 0);

for (let param in faceParams) {
if (param === '0') {
bgColor = (faceParams[param].substr(0, 1) === 'c'); // do we want colorful background?
alwaysShowTime = (faceParams[param].substr(1, 1) === 'y'); // always show "stale time" text?
staleMinutes = (faceParams[param].substr(2,2) - 0 >= 0) ? faceParams[param].substr(2,2) : 13; // threshold value (0=never)
} else if (!clockCreated){
let div = '<div class="' + faceParams[param].substr(0,2) + '"' + ((faceParams[param].substr(2,2) - 0 > 0) ? ' style="' + ((faceParams[param].substr(0,2) === 'ar') ? 'height' : 'font-size') + ':' + faceParams[param].substr(2,2) + 'vmin"' : '') + '></div>';
$inner.append(div);
}
}

let last = new Date(rec.date);
let now = new Date();

// Convert BG to mmol/L if necessary.
let displayValue;
let deltaDisplayValue;

if (window.serverSettings.settings.units === 'mmol') {
var displayValue = window.Nightscout.units.mgdlToMMOL(rec.sgv);
var deltaDisplayValue = window.Nightscout.units.mgdlToMMOL(delta);
displayValue = window.Nightscout.units.mgdlToMMOL(rec.sgv);
deltaDisplayValue = window.Nightscout.units.mgdlToMMOL(delta);
} else {
displayValue = rec.sgv;
deltaDisplayValue = Math.round(delta);
Expand All @@ -80,18 +118,8 @@ client.render = function render (xhr) {
deltaDisplayValue = '+' + deltaDisplayValue;
}

// Insert the BG value text.
$('#bgnow').html(displayValue);

// Insert the trend arrow.
$('#arrow').attr('src', '/images/' + (!rec.direction || rec.direction === 'NOT COMPUTABLE' ? 'NONE' : rec.direction) + '.svg');

// Time before data considered stale.
let staleMinutes = 13;
let threshold = 1000 * 60 * staleMinutes;

// Toggle stale if necessary.
$('#bgnow').toggleClass('stale', (now - last > threshold));
// Insert the delta value text.
$('.dt').html(deltaDisplayValue);

// Generate and insert the clock.
let timeDivisor = parseInt(client.settings.timeFormat ? client.settings.timeFormat : 12, 10);
Expand All @@ -105,51 +133,24 @@ client.render = function render (xhr) {
}
let m = today.getMinutes();
if (m < 10) m = "0" + m;
$('#clock').text(h + ":" + m);

/* global clockFace */
if (clockFace === 'clock-color') {

var bgHigh = window.serverSettings.settings.thresholds.bgHigh;
var bgLow = window.serverSettings.settings.thresholds.bgLow;
var bgTargetBottom = window.serverSettings.settings.thresholds.bgTargetBottom;
var bgTargetTop = window.serverSettings.settings.thresholds.bgTargetTop;
$('.tm').html(h + ":" + m);

var bgNum = parseFloat(rec.sgv);
// Color background
if (bgColor) {

// These are the particular shades of red, yellow, green, and blue.
var red = 'rgba(213,9,21,1)';
var yellow = 'rgba(234,168,0,1)';
var green = 'rgba(134,207,70,1)';
var blue = 'rgba(78,143,207,1)';

var elapsedMins = Math.round(((now - last) / 1000) / 60);

// Insert the BG stale time text.
let staleTimeText;
if (elapsedMins == 0) {
staleTimeText = 'Just now';
}
else if (elapsedMins == 1) {
staleTimeText = '1 minute ago';
}
else {
staleTimeText = elapsedMins + ' minutes ago';
}
$('#staleTime').text(staleTimeText);

// Force NS to always show 'x minutes ago'
if (window.serverSettings.settings.showClockLastTime) {
$('#staleTime').css('display', 'block');
}
let red = 'rgba(213,9,21,1)';
let yellow = 'rgba(234,168,0,1)';
let green = 'rgba(134,207,70,1)';
let blue = 'rgba(78,143,207,1)';

// Insert the delta value text.
$('#delta').html(deltaDisplayValue);
// Threshold values
let bgHigh = client.settings.thresholds.bgHigh;
let bgLow = client.settings.thresholds.bgLow;
let bgTargetBottom = client.settings.thresholds.bgTargetBottom;
let bgTargetTop = client.settings.thresholds.bgTargetTop;

// Show delta
if (window.serverSettings.settings.showClockDelta) {
$('#delta').css('display', 'inline-block');
}
let bgNum = parseFloat(rec.sgv);

// Threshold background coloring.
if (bgNum < bgLow) {
Expand All @@ -168,25 +169,52 @@ client.render = function render (xhr) {
$('body').css('background-color', red);
}

// Restyle body bg, and make the "x minutes ago" visible too.
if (now - last > threshold) {
$('body').css('background-color', 'grey');
$('body').css('color', 'black');
$('#arrow').css('filter', 'brightness(0%)');
}
else {
$('body').css('background-color', 'black');
}

if (!window.serverSettings.settings.showClockLastTime) {
$('#staleTime').css('display', 'block');
}
// Time before data considered stale.
let threshold = 1000 * 60 * staleMinutes;

} else {
$('body').css('color', 'white');
$('#arrow').css('filter', 'brightness(100%)');
let last = new Date(rec.date);
let now = new Date();

let elapsedMins = Math.round(((now - last) / 1000) / 60);

let thresholdReached = (now - last > threshold) && threshold > 0;

if (!window.serverSettings.settings.showClockLastTime) {
$('#staleTime').css('display', 'none');
}
// Insert the BG value text, toggle stale if necessary.
$('.sg').toggleClass('stale', thresholdReached).html(displayValue);

if (thresholdReached || alwaysShowTime) {
let staleTimeText;
if (elapsedMins === 0) {
staleTimeText = 'Just now';
}
else if (elapsedMins === 1) {
staleTimeText = '1 minute ago';
}
else {
staleTimeText = elapsedMins + ' minutes ago';
}

$('.ag').html(staleTimeText);
}
else {
$('.ag').html('');
}

// Insert the trend arrow.
let arrow = $('<img alt="arrow">').attr('src', '/images/' + (!rec.direction || rec.direction === 'NOT COMPUTABLE' ? 'NONE' : rec.direction) + '.svg');

// Restyle body bg
if (thresholdReached) {
$('body').css('background-color', 'grey').css('color', 'black');
$('.ar').css('filter', 'brightness(0%)').html(arrow);
} else {
$('body').css('color', bgColor ? 'white' : 'grey');
$('.ar').css('filter', bgColor ? 'brightness(100%)' : 'brightness(50%)').html(arrow);
}
};

Expand Down
2 changes: 1 addition & 1 deletion lib/server/clocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function clockviews() {
const face = req.params.face;
console.log('Clockface requested:', face);

res.render('shared.html', {
res.render('clock.html', {
face,
locals
});
Expand Down
28 changes: 0 additions & 28 deletions views/clockviews/bgclock.css

This file was deleted.

32 changes: 0 additions & 32 deletions views/clockviews/clock-color.css

This file was deleted.

39 changes: 39 additions & 0 deletions views/clockviews/clock-config.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#config-form {
position: fixed;
top: 10px;
left: 10px;
width: 250px;
min-width: 220px;
background: white;
color: black;
opacity: 0.8;
padding: 1%;
font-size: 10px;
}
#config-form p {
margin: 15px;
text-align: left;
}
input.elmt {
width: 120px;
}
select {
width: 100%;
}
#facename {
font-size: 7px;
}
#clocklink {
font-size: 18px;
}
#clocklink:link, #clocklink:visited {
background-color: #f44336;
color: white;
padding: 14px 25px;
text-align: center;
text-decoration: none;
display: inline-block;
}
#clocklink:hover, #clocklink:active {
background-color: red;
}
Loading

0 comments on commit 3d6f488

Please sign in to comment.