Fix all issues from ESLint (#4730)

* Cherry picks the ES language changes from #4690

* Fix small issues found in linting

* * Fix all but one eslint complaint in the bundled code
* Add eslint and js-beautify rc files into the repo
This commit is contained in:
Sulka Haro
2019-07-17 15:04:57 +03:00
committed by GitHub
parent b04476e1f9
commit 8f25a6e7a4
36 changed files with 2567 additions and 2946 deletions
+14
View File
@@ -0,0 +1,14 @@
module.exports = {
"plugins": [ ],
"extends": [
"eslint:recommended"
],
"parser": "babel-eslint",
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true,
"jquery": true
}
};
+16
View File
@@ -0,0 +1,16 @@
{
"indent_size": 2
, "indent_char": " "
, "comma_first": true
, "keep-array-indentation": true
, "space_after_named_function": true
, "space_after_anon_function": true
, "end_with_newline": true
, "brace_style": "collapse,preserve-inline"
, "space_in_brace": true
, "space-in-paren": false
, "break-chained-methods": false
, "max-preserve-newlines": 2
, "space-after-anon-function": false
, "indent-empty-lines": false
}
+35 -35
View File
@@ -8,60 +8,60 @@ var cleanstatusdb = {
, pluginType: 'admin' , pluginType: 'admin'
}; };
function init() { function init () {
return cleanstatusdb; return cleanstatusdb;
} }
module.exports = init; module.exports = init;
cleanstatusdb.actions = [ cleanstatusdb.actions = [
{ {
name: 'Delete all documents from devicestatus collection' name: 'Delete all documents from devicestatus collection'
, description: 'This task removes all documents from devicestatus collection. Useful when uploader battery status is not properly updated.' , description: 'This task removes all documents from devicestatus collection. Useful when uploader battery status is not properly updated.'
, buttonLabel: 'Delete all documents' , buttonLabel: 'Delete all documents'
, confirmText: 'Delete all documents from devicestatus collection?' , confirmText: 'Delete all documents from devicestatus collection?'
} }
, { , {
name: 'Delete all documents from devicestatus collection older than 30 days' name: 'Delete all documents from devicestatus collection older than 30 days'
, description: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.' , description: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
, buttonLabel: 'Delete old documents' , buttonLabel: 'Delete old documents'
, confirmText: 'Delete old documents from devicestatus collection?' , confirmText: 'Delete old documents from devicestatus collection?'
, preventClose: true , preventClose: true
} }
]; ];
cleanstatusdb.actions[0].init = function init(client, callback) { cleanstatusdb.actions[0].init = function init (client, callback) {
var translate = client.translate; var translate = client.translate;
var $status = $('#admin_' + cleanstatusdb.name + '_0_status'); var $status = $('#admin_' + cleanstatusdb.name + '_0_status');
$status.hide().text(translate('Loading database ...')).fadeIn('slow'); $status.hide().text(translate('Loading database ...')).fadeIn('slow');
$.ajax('/api/v1/devicestatus.json?count=500', { $.ajax('/api/v1/devicestatus.json?count=500', {
headers: client.headers() headers: client.headers()
, success: function (records) { , success: function(records) {
var recs = (records.length === 500 ? '500+' : records.length); var recs = (records.length === 500 ? '500+' : records.length);
$status.hide().text(translate('Database contains %1 records',{ params: [recs] })).fadeIn('slow'); $status.hide().text(translate('Database contains %1 records', { params: [recs] })).fadeIn('slow');
} }
, error: function () { , error: function() {
$status.hide().text(translate('Error loading database')).fadeIn('slow'); $status.hide().text(translate('Error loading database')).fadeIn('slow');
} }
}).done(function () { if (callback) { callback(); } }); }).done(function() { if (callback) { callback(); } });
}; };
cleanstatusdb.actions[0].code = function deleteRecords(client, callback) { cleanstatusdb.actions[0].code = function deleteRecords (client, callback) {
var translate = client.translate; var translate = client.translate;
var $status = $('#admin_' + cleanstatusdb.name + '_0_status'); var $status = $('#admin_' + cleanstatusdb.name + '_0_status');
if (!client.hashauth.isAuthenticated()) { if (!client.hashauth.isAuthenticated()) {
alert(translate('Your device is not authenticated yet')); alert(translate('Your device is not authenticated yet'));
if (callback) { if (callback) {
callback(); callback();
} }
return; return;
}; }
$status.hide().text(translate('Deleting records ...')).fadeIn('slow'); $status.hide().text(translate('Deleting records ...')).fadeIn('slow');
$.ajax({ $.ajax({
method: 'DELETE' method: 'DELETE'
, url: '/api/v1/devicestatus/*' , url: '/api/v1/devicestatus/*'
, headers: client.headers() , headers: client.headers()
}).done(function success () { }).done(function success () {
@@ -69,7 +69,7 @@ cleanstatusdb.actions[0].code = function deleteRecords(client, callback) {
if (callback) { if (callback) {
callback(); callback();
} }
}).fail(function fail() { }).fail(function fail () {
$status.hide().text(translate('Error')).fadeIn('slow'); $status.hide().text(translate('Error')).fadeIn('slow');
if (callback) { if (callback) {
callback(); callback();
@@ -77,24 +77,24 @@ cleanstatusdb.actions[0].code = function deleteRecords(client, callback) {
}); });
}; };
cleanstatusdb.actions[1].init = function init(client, callback) { cleanstatusdb.actions[1].init = function init (client, callback) {
var translate = client.translate; var translate = client.translate;
var $status = $('#admin_' + cleanstatusdb.name + '_1_status'); var $status = $('#admin_' + cleanstatusdb.name + '_1_status');
$status.hide(); $status.hide();
var numDays = '<br/>' var numDays = '<br/>' +
+ '<label for="admin_devicestatus_days">' '<label for="admin_devicestatus_days">' +
+ translate('Number of Days to Keep:') translate('Number of Days to Keep:') +
+ ' <input id="admin_devicestatus_days" value="30" size="3" min="1"/>' ' <input id="admin_devicestatus_days" value="30" size="3" min="1"/>' +
+ '</label>'; '</label>';
$('#admin_' + cleanstatusdb.name + '_1_html').html(numDays); $('#admin_' + cleanstatusdb.name + '_1_html').html(numDays);
if (callback) { callback(); } if (callback) { callback(); }
}; };
cleanstatusdb.actions[1].code = function deleteOldRecords(client, callback) { cleanstatusdb.actions[1].code = function deleteOldRecords (client, callback) {
var translate = client.translate; var translate = client.translate;
var $status = $('#admin_' + cleanstatusdb.name + '_1_status'); var $status = $('#admin_' + cleanstatusdb.name + '_1_status');
var numDays = Number($('#admin_devicestatus_days').val()); var numDays = Number($('#admin_devicestatus_days').val());
@@ -117,17 +117,17 @@ cleanstatusdb.actions[1].code = function deleteOldRecords(client, callback) {
$status.hide().text(translate('Deleting records ...')).fadeIn('slow'); $status.hide().text(translate('Deleting records ...')).fadeIn('slow');
$.ajax('/api/v1/devicestatus/?find[created_at][$lte]=' + dateStr, { $.ajax('/api/v1/devicestatus/?find[created_at][$lte]=' + dateStr, {
method: 'DELETE' method: 'DELETE'
, headers: client.headers() , headers: client.headers()
, success: function (retVal) { , success: function(retVal) {
$status.text(translate('%1 records deleted',{ params: [retVal.n] })); $status.text(translate('%1 records deleted', { params: [retVal.n] }));
} }
, error: function () { , error: function() {
$status.hide().text(translate('Error')).fadeIn('slow'); $status.hide().text(translate('Error')).fadeIn('slow');
} }
}).done(function success () { }).done(function success () {
if (callback) { callback(); } if (callback) { callback(); }
}).fail(function fail() { }).fail(function fail () {
if (callback) { callback(); } if (callback) { callback(); }
}); });
}; };
+61 -61
View File
@@ -6,164 +6,164 @@ var futureitems = {
, pluginType: 'admin' , pluginType: 'admin'
}; };
function init() { function init () {
return futureitems; return futureitems;
} }
module.exports = init; module.exports = init;
futureitems.actions = [ futureitems.actions = [
{ {
name: 'Find and remove treatments in the future' name: 'Find and remove treatments in the future'
, description: 'This task find and remove treatments in the future.' , description: 'This task find and remove treatments in the future.'
, buttonLabel: 'Remove treatments in the future' , buttonLabel: 'Remove treatments in the future'
} }
, {
name: 'Find and remove entries in the future' , {
, description: 'This task find and remove CGM data in the future created by uploader with wrong date/time.' name: 'Find and remove entries in the future'
, buttonLabel: 'Remove entries in the future' , description: 'This task find and remove CGM data in the future created by uploader with wrong date/time.'
, buttonLabel: 'Remove entries in the future'
} }
]; ];
futureitems.actions[0].init = function init(client, callback) { futureitems.actions[0].init = function init (client, callback) {
var translate = client.translate; var translate = client.translate;
var $status = $('#admin_' + futureitems.name + '_0_status'); var $status = $('#admin_' + futureitems.name + '_0_status');
function valueOrEmpty (value) { function valueOrEmpty (value) {
return value ? value : ''; return value ? value : '';
} }
function showOneTreatment (tr, table) { function showOneTreatment (tr, table) {
table.append($('<tr>').css('background-color','#0f0f0f') table.append($('<tr>').css('background-color', '#0f0f0f')
.append($('<td>').attr('width','20%').append(new Date(tr.created_at).toLocaleString().replace(/([\d]+:[\d]{2})(:[\d]{2})(.*)/, '$1$3'))) .append($('<td>').attr('width', '20%').append(new Date(tr.created_at).toLocaleString().replace(/([\d]+:[\d]{2})(:[\d]{2})(.*)/, '$1$3')))
.append($('<td>').attr('width','20%').append(tr.eventType ? translate(client.careportal.resolveEventName(tr.eventType)) : '')) .append($('<td>').attr('width', '20%').append(tr.eventType ? translate(client.careportal.resolveEventName(tr.eventType)) : ''))
.append($('<td>').attr('width','10%').attr('align','center').append(tr.glucose ? tr.glucose + ' ('+translate(tr.glucoseType)+')' : '')) .append($('<td>').attr('width', '10%').attr('align', 'center').append(tr.glucose ? tr.glucose + ' (' + translate(tr.glucoseType) + ')' : ''))
.append($('<td>').attr('width','10%').attr('align','center').append(valueOrEmpty(tr.insulin))) .append($('<td>').attr('width', '10%').attr('align', 'center').append(valueOrEmpty(tr.insulin)))
.append($('<td>').attr('width','10%').attr('align','center').append(valueOrEmpty(tr.carbs))) .append($('<td>').attr('width', '10%').attr('align', 'center').append(valueOrEmpty(tr.carbs)))
.append($('<td>').attr('width','10%').append(valueOrEmpty(tr.enteredBy))) .append($('<td>').attr('width', '10%').append(valueOrEmpty(tr.enteredBy)))
.append($('<td>').attr('width','20%').append(valueOrEmpty(tr.notes))) .append($('<td>').attr('width', '20%').append(valueOrEmpty(tr.notes)))
); );
} }
function showTreatments(treatments, table) { function showTreatments (treatments, table) {
table.append($('<tr>').css('background','#040404') table.append($('<tr>').css('background', '#040404')
.append($('<th>').css('width','80px').attr('align','left').append(translate('Time'))) .append($('<th>').css('width', '80px').attr('align', 'left').append(translate('Time')))
.append($('<th>').css('width','150px').attr('align','left').append(translate('Event Type'))) .append($('<th>').css('width', '150px').attr('align', 'left').append(translate('Event Type')))
.append($('<th>').css('width','150px').attr('align','left').append(translate('Blood Glucose'))) .append($('<th>').css('width', '150px').attr('align', 'left').append(translate('Blood Glucose')))
.append($('<th>').css('width','50px').attr('align','left').append(translate('Insulin'))) .append($('<th>').css('width', '50px').attr('align', 'left').append(translate('Insulin')))
.append($('<th>').css('width','50px').attr('align','left').append(translate('Carbs'))) .append($('<th>').css('width', '50px').attr('align', 'left').append(translate('Carbs')))
.append($('<th>').css('width','150px').attr('align','left').append(translate('Entered By'))) .append($('<th>').css('width', '150px').attr('align', 'left').append(translate('Entered By')))
.append($('<th>').css('width','300px').attr('align','left').append(translate('Notes'))) .append($('<th>').css('width', '300px').attr('align', 'left').append(translate('Notes')))
); );
for (var t=0; t<treatments.length; t++) { for (var t = 0; t < treatments.length; t++) {
showOneTreatment (treatments[t], table); showOneTreatment(treatments[t], table);
} }
}; }
$status.hide().text(translate('Loading database ...')).fadeIn('slow'); $status.hide().text(translate('Loading database ...')).fadeIn('slow');
var nowiso = new Date().toISOString(); var nowiso = new Date().toISOString();
$.ajax('/api/v1/treatments.json?&find[created_at][$gte]=' + nowiso, { $.ajax('/api/v1/treatments.json?&find[created_at][$gte]=' + nowiso, {
headers: client.headers() headers: client.headers()
, success: function (records) { , success: function(records) {
futureitems.treatmentrecords = records; futureitems.treatmentrecords = records;
$status.hide().text(translate('Database contains %1 future records',{ params: [records.length] })).fadeIn('slow'); $status.hide().text(translate('Database contains %1 future records', { params: [records.length] })).fadeIn('slow');
var table = $('<table>').css('margin-top','10px'); var table = $('<table>').css('margin-top', '10px');
$('#admin_' + futureitems.name + '_0_html').append(table); $('#admin_' + futureitems.name + '_0_html').append(table);
showTreatments(records, table); showTreatments(records, table);
futureitems.actions[0].confirmText = translate('Remove %1 selected records?', { params: [records.length] }); futureitems.actions[0].confirmText = translate('Remove %1 selected records?', { params: [records.length] });
} }
, error: function () { , error: function() {
$status.hide().text(translate('Error loading database')).fadeIn('slow'); $status.hide().text(translate('Error loading database')).fadeIn('slow');
futureitems.treatmentrecords = []; futureitems.treatmentrecords = [];
} }
}).done(function () { if (callback) { callback(); } }); }).done(function() { if (callback) { callback(); } });
}; };
futureitems.actions[0].code = function deleteRecords(client, callback) { futureitems.actions[0].code = function deleteRecords (client, callback) {
var translate = client.translate; var translate = client.translate;
var $status = $('#admin_' + futureitems.name + '_0_status'); var $status = $('#admin_' + futureitems.name + '_0_status');
if (!client.hashauth.isAuthenticated()) { if (!client.hashauth.isAuthenticated()) {
alert(translate('Your device is not authenticated yet')); alert(translate('Your device is not authenticated yet'));
if (callback) { if (callback) {
callback(); callback();
} }
return; return;
}; }
function deleteRecordById (_id) { function deleteRecordById (_id) {
$.ajax({ $.ajax({
method: 'DELETE' method: 'DELETE'
, url: '/api/v1/treatments/' + _id , url: '/api/v1/treatments/' + _id
, headers: client.headers() , headers: client.headers()
}).done(function success () { }).done(function success () {
$status.text(translate('Record %1 removed ...', { params: [_id] })); $status.text(translate('Record %1 removed ...', { params: [_id] }));
}).fail(function fail() { }).fail(function fail () {
$status.text(translate('Error removing record %1', { params: [_id] })); $status.text(translate('Error removing record %1', { params: [_id] }));
}); });
} }
$status.hide().text(translate('Deleting records ...')).fadeIn('slow'); $status.hide().text(translate('Deleting records ...')).fadeIn('slow');
for (var i = 0; i < futureitems.treatmentrecords.length; i++) { for (var i = 0; i < futureitems.treatmentrecords.length; i++) {
deleteRecordById(futureitems.treatmentrecords[i]._id); deleteRecordById(futureitems.treatmentrecords[i]._id);
} }
$('#admin_' + futureitems.name + '_0_html').html(''); $('#admin_' + futureitems.name + '_0_html').html('');
if (callback) { if (callback) {
callback(); callback();
} }
}; };
futureitems.actions[1].init = function init(client, callback) { futureitems.actions[1].init = function init (client, callback) {
var translate = client.translate; var translate = client.translate;
var $status = $('#admin_' + futureitems.name + '_1_status'); var $status = $('#admin_' + futureitems.name + '_1_status');
$status.hide().text(translate('Loading database ...')).fadeIn('slow'); $status.hide().text(translate('Loading database ...')).fadeIn('slow');
var now = new Date().getTime(); var now = new Date().getTime();
$.ajax('/api/v1/entries.json?&find[date][$gte]=' + now + '&count=288', { $.ajax('/api/v1/entries.json?&find[date][$gte]=' + now + '&count=288', {
headers: client.headers() headers: client.headers()
, success: function (records) { , success: function(records) {
futureitems.entriesrecords = records; futureitems.entriesrecords = records;
$status.hide().text(translate('Database contains %1 future records',{ params: [records.length] })).fadeIn('slow'); $status.hide().text(translate('Database contains %1 future records', { params: [records.length] })).fadeIn('slow');
futureitems.actions[1].confirmText = translate('Remove %1 selected records?', { params: [records.length] }); futureitems.actions[1].confirmText = translate('Remove %1 selected records?', { params: [records.length] });
} }
, error: function () { , error: function() {
$status.hide().text(translate('Error loading database')).fadeIn('slow'); $status.hide().text(translate('Error loading database')).fadeIn('slow');
futureitems.entriesrecords = []; futureitems.entriesrecords = [];
} }
}).done(function () { if (callback) { callback(); } }); }).done(function() { if (callback) { callback(); } });
}; };
futureitems.actions[1].code = function deleteRecords(client, callback) { futureitems.actions[1].code = function deleteRecords (client, callback) {
var translate = client.translate; var translate = client.translate;
var $status = $('#admin_' + futureitems.name + '_1_status'); var $status = $('#admin_' + futureitems.name + '_1_status');
if (!client.hashauth.isAuthenticated()) { if (!client.hashauth.isAuthenticated()) {
alert(translate('Your device is not authenticated yet')); alert(translate('Your device is not authenticated yet'));
if (callback) { if (callback) {
callback(); callback();
} }
return; return;
}; }
function deteleteRecordById (_id) { function deteleteRecordById (_id) {
$.ajax({ $.ajax({
method: 'DELETE' method: 'DELETE'
, url: '/api/v1/entries/' + _id , url: '/api/v1/entries/' + _id
, headers: client.headers() , headers: client.headers()
}).done(function success () { }).done(function success () {
$status.text(translate('Record %1 removed ...', { params: [_id] })); $status.text(translate('Record %1 removed ...', { params: [_id] }));
}).fail(function fail() { }).fail(function fail () {
$status.text(translate('Error removing record %1', { params: [_id] })); $status.text(translate('Error removing record %1', { params: [_id] }));
}); });
} }
$status.hide().text(translate('Deleting records ...')).fadeIn('slow'); $status.hide().text(translate('Deleting records ...')).fadeIn('slow');
for (var i = 0; i < futureitems.entriesrecords.length; i++) { for (var i = 0; i < futureitems.entriesrecords.length; i++) {
deteleteRecordById(futureitems.entriesrecords[i]._id); deteleteRecordById(futureitems.entriesrecords[i]._id);
} }
if (callback) { if (callback) {
callback(); callback();
} }
+53 -50
View File
@@ -1,12 +1,14 @@
'use strict'; 'use strict';
const _ = require('lodash');
var roles = { var roles = {
name: 'roles' name: 'roles'
, label: 'Roles - Groups of People, Devices, etc' , label: 'Roles - Groups of People, Devices, etc'
, pluginType: 'admin' , pluginType: 'admin'
}; };
function init() { function init () {
return roles; return roles;
} }
@@ -20,13 +22,13 @@ roles.actions = [{
, init: function init (client, callback) { , init: function init (client, callback) {
$status = $('#admin_' + roles.name + '_0_status'); $status = $('#admin_' + roles.name + '_0_status');
$status.hide().text(client.translate('Loading database ...')).fadeIn('slow'); $status.hide().text(client.translate('Loading database ...')).fadeIn('slow');
var table = $('<table id="admin_roles_table">').css('margin-top','10px'); var table = $('<table id="admin_roles_table">').css('margin-top', '10px');
$('#admin_' + roles.name + '_0_html').append(table).append(genDialog(client)); $('#admin_' + roles.name + '_0_html').append(table).append(genDialog(client));
reload(client, callback); reload(client, callback);
} }
, preventClose: true , preventClose: true
, code: function createNewRole (client, callback) { , code: function createNewRole (client, callback) {
var role = { }; var role = {};
openDialog(role, client, callback); openDialog(role, client, callback);
} }
}]; }];
@@ -40,9 +42,9 @@ function createOrSaveRole (role, client, callback) {
, url: '/api/v2/authorization/roles/' , url: '/api/v2/authorization/roles/'
, headers: client.headers() , headers: client.headers()
, data: role , data: role
}).done(function success() { }).done(function success () {
reload(client, callback); reload(client, callback);
}).fail(function fail(err) { }).fail(function fail (err) {
console.error('Unable to ' + method + ' Role', err.responseText); console.error('Unable to ' + method + ' Role', err.responseText);
window.alert(client.translate('Unable to %1 Role', { params: [method] })); window.alert(client.translate('Unable to %1 Role', { params: [method] }));
if (callback) { if (callback) {
@@ -56,9 +58,9 @@ function deleteRole (role, client, callback) {
method: 'DELETE' method: 'DELETE'
, url: '/api/v2/authorization/roles/' + role._id , url: '/api/v2/authorization/roles/' + role._id
, headers: client.headers() , headers: client.headers()
}).done(function success() { }).done(function success () {
reload(client, callback); reload(client, callback);
}).fail(function fail(err) { }).fail(function fail (err) {
console.error('Unable to delete Role', err.responseText); console.error('Unable to delete Role', err.responseText);
window.alert(client.translate('Unable to delete Role')); window.alert(client.translate('Unable to delete Role'));
if (callback) { if (callback) {
@@ -70,16 +72,16 @@ function deleteRole (role, client, callback) {
function reload (client, callback) { function reload (client, callback) {
$.ajax({ $.ajax({
method: 'GET' method: 'GET'
, url:'/api/v2/authorization/roles' , url: '/api/v2/authorization/roles'
, headers: client.headers() , headers: client.headers()
}).done(function success (records) { }).done(function success (records) {
roles.records = records; roles.records = records;
$status.hide().text(client.translate('Database contains %1 roles',{ params: [records.length] })).fadeIn('slow'); $status.hide().text(client.translate('Database contains %1 roles', { params: [records.length] })).fadeIn('slow');
showRoles(records, client); showRoles(records, client);
if (callback) { if (callback) {
callback(); callback();
} }
}).fail(function fail(err) { }).fail(function fail (err) {
$status.hide().text(client.translate('Error loading database')).fadeIn('slow'); $status.hide().text(client.translate('Error loading database')).fadeIn('slow');
roles.records = []; roles.records = [];
if (callback) { if (callback) {
@@ -90,56 +92,57 @@ function reload (client, callback) {
function genDialog (client) { function genDialog (client) {
var ret = var ret =
'<div id="editroledialog" style="display:none" title="' + client.translate('Edit Role') + '">' '<div id="editroledialog" style="display:none" title="' + client.translate('Edit Role') + '">' +
+ ' <label for="edrole_name">' ' <label for="edrole_name">' +
+ client.translate('Name') client.translate('Name') +
+ ' <input id="edrole_name" placeholder="' + client.translate('admin, school, family, etc') + '"/>' ' <input id="edrole_name" placeholder="' + client.translate('admin, school, family, etc') + '"/>' +
+ ' </label>' ' </label>' +
+ ' <br>' ' <br>' +
+ ' <label for="edrole_permissions">' + client.translate('Permissions') + '</label>' ' <label for="edrole_permissions">' + client.translate('Permissions') + '</label>' +
+ ' <textarea id="edrole_permissions" rows="3" style="width:300px"></textarea><br>' ' <textarea id="edrole_permissions" rows="3" style="width:300px"></textarea><br>' +
+ ' <br>' ' <br>' +
+ ' <label for="edrole_notes">' + client.translate('Additional Notes, Comments') + '</label>' ' <label for="edrole_notes">' + client.translate('Additional Notes, Comments') + '</label>' +
+ ' <textarea id="edrole_notes" style="width:300px"></textarea><br>' ' <textarea id="edrole_notes" style="width:300px"></textarea><br>' +
+ ' </div>' ' </div>';
;
return $(ret); return $(ret);
} }
function openDialog (role, client) { function openDialog (role, client) {
$( '#editroledialog' ).dialog({ $('#editroledialog').dialog({
width: 360 width: 360
, height: 360 , height: 360
, buttons: [ , buttons: [
{ text: client.translate('Save'), {
class: 'leftButton', text: client.translate('Save')
click: function() { , class: 'leftButton'
, click: function() {
role.name = $('#edrole_name').val(); role.name = $('#edrole_name').val();
role.permissions = role.permissions =
_.chain($('#edrole_permissions').val().toLowerCase().split(/[;, ]/)) _.chain($('#edrole_permissions').val().toLowerCase().split(/[;, ]/))
.map(_.trim) .map(_.trim)
.reject(_.isEmpty) .reject(_.isEmpty)
.sort() .sort()
.value(); .value();
role.notes = $('#edrole_notes').val(); role.notes = $('#edrole_notes').val();
var self = this; var self = this;
delete role.autoGenerated; delete role.autoGenerated;
createOrSaveRole(role, client, function callback () { createOrSaveRole(role, client, function callback () {
$( self ).dialog('close'); $(self).dialog('close');
}); });
} }
}, }
{ text: client.translate('Cancel'), , {
click: function () { $( this ).dialog('close'); } text: client.translate('Cancel')
, click: function() { $(this).dialog('close'); }
} }
] ]
, open : function() { , open: function() {
$(this).parent().css('box-shadow', '20px 20px 20px 0px black'); $(this).parent().css('box-shadow', '20px 20px 20px 0px black');
$(this).parent().find('.ui-dialog-buttonset' ).css({'width':'100%','text-align':'right'}); $(this).parent().find('.ui-dialog-buttonset').css({ 'width': '100%', 'text-align': 'right' });
$(this).parent().find('button:contains("'+client.translate('Save')+'")').css({'float':'left'}); $(this).parent().find('button:contains("' + client.translate('Save') + '")').css({ 'float': 'left' });
$('#edrole_name').val(role.name || '').focus(); $('#edrole_name').val(role.name || '').focus();
$('#edrole_permissions').val(role.permissions ? role.permissions.join(' ') : ''); $('#edrole_permissions').val(role.permissions ? role.permissions.join(' ') : '');
$('#edrole_notes').val(role.notes || ''); $('#edrole_notes').val(role.notes || '');
@@ -151,14 +154,14 @@ function openDialog (role, client) {
function showRole (role, table, client) { function showRole (role, table, client) {
var editIcon = $('<img title="' + client.translate('Edit this role') + '" style="cursor:pointer" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABEUlEQVQ4jZ3MMUsCYQDG8ee8IySQbNCLyyEKG/RLNAXicqvQcAeNLrcFLlE0+xHuNpt8wy04rrYm8Q4HQRE56BSC3lSqU1BwCoxM39dnffj9BWyxXvVeEzvtctBwHyRebNu2Nk2lzMlrgJB+qBEeTByiKYpihl+fIO8jTI9PDJEVF1+K2iw+M6PhDuyag4NkQi/c3FkCK5Z3ZbM76qLltpCbn+vXxq0FABsDy9hzPdBvqvtXvvXzrw1swmsDLPjfACteGeDBfwK8+FdgGwwAIgC0ncsjxGRSH/eiPBgAJADY2z8sJ4JBfNBsDqlADVYMANIzKalv/bHaefKsTH9iPFb8ISsGAJym0+Qinz3jQktbAHcxvx3559eSAAAAAElFTkSuQmCC">'); var editIcon = $('<img title="' + client.translate('Edit this role') + '" style="cursor:pointer" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABEUlEQVQ4jZ3MMUsCYQDG8ee8IySQbNCLyyEKG/RLNAXicqvQcAeNLrcFLlE0+xHuNpt8wy04rrYm8Q4HQRE56BSC3lSqU1BwCoxM39dnffj9BWyxXvVeEzvtctBwHyRebNu2Nk2lzMlrgJB+qBEeTByiKYpihl+fIO8jTI9PDJEVF1+K2iw+M6PhDuyag4NkQi/c3FkCK5Z3ZbM76qLltpCbn+vXxq0FABsDy9hzPdBvqvtXvvXzrw1swmsDLPjfACteGeDBfwK8+FdgGwwAIgC0ncsjxGRSH/eiPBgAJADY2z8sJ4JBfNBsDqlADVYMANIzKalv/bHaefKsTH9iPFb8ISsGAJym0+Qinz3jQktbAHcxvx3559eSAAAAAElFTkSuQmCC">');
editIcon.click(function clicked ( ) { editIcon.click(function clicked () {
openDialog(role, client); openDialog(role, client);
}); });
var deleteIcon = ''; var deleteIcon = '';
if (role._id) { if (role._id) {
deleteIcon = $('<img title="Delete this role" class="titletranslate" style="cursor:pointer" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACrElEQVQ4T42Ty2sTQRzHv5tmk2yyjRNtpfZhL8V6s2KoUNC2XqwgaCsVQcGiFqpHi0c9iRdR/ANE9KR40FIQX4cueKoPaKFoLdSYNtE0abKT1+5s9iW7aUMiHtzTzO7v85md+c6PA4DrHbsPCKIgOWO1pA7dT6YXnXH949SE/F63pqwZtRrO+SCKgjQ5NUV+azpmHj2krMwaJC4c8Erj+/eRyloMMwWFKgbn1nC3ervlK1evkXBLGBZT8SOewotnTylTNLdgeg/pDgZDC2cPHSR8bB22DVC9hFe0SG/H0xFXcHlykjRHRDBWgJcZSCY38Xx2lhqMnRYE34Px/sN9vlQWeoHBAx2yXsRruVAVuFsIBaSJ8+eJGPaBqQV4NROJjTzez89jLBoFn6FgybQL54wS3uTyVDFQ3cL2IYpBv3RhdJSIIQ80tQyv7gEqJvS8AmUlBs7UXPhtjtZgh3UFNYngk86NHCfNAg9dMwHVBPu+CpsVkTXKeJeVG+AGgTOZ3tt6MSKKjy+NjEBjFrR4ElZmA4pdxstMFsyyJu6tZZ7Ux9vwB6EAL50ZGiRECEPPUOixVTRxHlicgSVWxEdZpuZWfNuS2hk48NjwMIkIYZglBnV5Cbqtws/5IaAJmsfCglrEl2y2QeKmEBJ80tixKmxrFpSVr0gV0viQoxho2YUuPohmeFD22PiklLC4ma5JuBvdrfLJI0dJd0s7bM0ES8aR/BXDXGaTskqlL+D3Lwy0tZEePoAd4EA5YF4tYymdonfjmQh3s6dTPjU4SHYGwjAKecSXFyGlM1TdytntE56T+ts7SC/vhw3gm6njc2Kd3vm5Ub1IwQAvnYhGiZpYw1wiWYPrIw7wnBTt7CLOOwdmut14kQQvqt24tfK/utGR6LaF+iRqMf4N/O/8D28HiiCRYqzAAAAAAElFTkSuQmCC">'); deleteIcon = $('<img title="Delete this role" class="titletranslate" style="cursor:pointer" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACrElEQVQ4T42Ty2sTQRzHv5tmk2yyjRNtpfZhL8V6s2KoUNC2XqwgaCsVQcGiFqpHi0c9iRdR/ANE9KR40FIQX4cueKoPaKFoLdSYNtE0abKT1+5s9iW7aUMiHtzTzO7v85md+c6PA4DrHbsPCKIgOWO1pA7dT6YXnXH949SE/F63pqwZtRrO+SCKgjQ5NUV+azpmHj2krMwaJC4c8Erj+/eRyloMMwWFKgbn1nC3ervlK1evkXBLGBZT8SOewotnTylTNLdgeg/pDgZDC2cPHSR8bB22DVC9hFe0SG/H0xFXcHlykjRHRDBWgJcZSCY38Xx2lhqMnRYE34Px/sN9vlQWeoHBAx2yXsRruVAVuFsIBaSJ8+eJGPaBqQV4NROJjTzez89jLBoFn6FgybQL54wS3uTyVDFQ3cL2IYpBv3RhdJSIIQ80tQyv7gEqJvS8AmUlBs7UXPhtjtZgh3UFNYngk86NHCfNAg9dMwHVBPu+CpsVkTXKeJeVG+AGgTOZ3tt6MSKKjy+NjEBjFrR4ElZmA4pdxstMFsyyJu6tZZ7Ux9vwB6EAL50ZGiRECEPPUOixVTRxHlicgSVWxEdZpuZWfNuS2hk48NjwMIkIYZglBnV5Cbqtws/5IaAJmsfCglrEl2y2QeKmEBJ80tixKmxrFpSVr0gV0viQoxho2YUuPohmeFD22PiklLC4ma5JuBvdrfLJI0dJd0s7bM0ES8aR/BXDXGaTskqlL+D3Lwy0tZEePoAd4EA5YF4tYymdonfjmQh3s6dTPjU4SHYGwjAKecSXFyGlM1TdytntE56T+ts7SC/vhw3gm6njc2Kd3vm5Ub1IwQAvnYhGiZpYw1wiWYPrIw7wnBTt7CLOOwdmut14kQQvqt24tfK/utGR6LaF+iRqMf4N/O/8D28HiiCRYqzAAAAAAElFTkSuQmCC">');
deleteIcon.click(function clicked() { deleteIcon.click(function clicked () {
var ok = window.confirm(client.translate('Are you sure you want to delete: ') + role.name); var ok = window.confirm(client.translate('Are you sure you want to delete: ') + role.name);
if (ok) { if (ok) {
deleteRole(role, client); deleteRole(role, client);
@@ -166,21 +169,21 @@ function showRole (role, table, client) {
}); });
} }
table.append($('<tr>').css('background-color','#0f0f0f') table.append($('<tr>').css('background-color', '#0f0f0f')
.append($('<td>').attr('width','20%').append(editIcon).append(deleteIcon).append(role.name)) .append($('<td>').attr('width', '20%').append(editIcon).append(deleteIcon).append(role.name))
.append($('<td>').attr('width','20%').append(_.isEmpty(role.permissions) ? '[none]' : role.permissions.join(' '))) .append($('<td>').attr('width', '20%').append(_.isEmpty(role.permissions) ? '[none]' : role.permissions.join(' ')))
.append($('<td>').attr('width','10%').append(role._id ? (role.notes ? role.notes : '') : '[system default]')) .append($('<td>').attr('width', '10%').append(role._id ? (role.notes ? role.notes : '') : '[system default]'))
); );
} }
function showRoles (roles, client) { function showRoles (roles, client) {
var table = $('#admin_roles_table'); var table = $('#admin_roles_table');
table.empty().append($('<tr>').css('background','#040404') table.empty().append($('<tr>').css('background', '#040404')
.append($('<th>').css('width','100px').attr('align','left').append(client.translate('Name'))) .append($('<th>').css('width', '100px').attr('align', 'left').append(client.translate('Name')))
.append($('<th>').css('width','150px').attr('align','left').append(client.translate('Permissions'))) .append($('<th>').css('width', '150px').attr('align', 'left').append(client.translate('Permissions')))
.append($('<th>').css('width','150px').attr('align','left').append(client.translate('Notes'))) .append($('<th>').css('width', '150px').attr('align', 'left').append(client.translate('Notes')))
); );
for (var t=0; t<roles.length; t++) { for (var t = 0; t < roles.length; t++) {
showRole(roles[t], table, client); showRole(roles[t], table, client);
} }
} }
+57 -54
View File
@@ -1,12 +1,14 @@
'use strict'; 'use strict';
const _ = require('lodash');
var subjects = { var subjects = {
name: 'subjects' name: 'subjects'
, label: 'Subjects - People, Devices, etc' , label: 'Subjects - People, Devices, etc'
, pluginType: 'admin' , pluginType: 'admin'
}; };
function init() { function init () {
return subjects; return subjects;
} }
@@ -20,7 +22,7 @@ subjects.actions = [{
, init: function init (client, callback) { , init: function init (client, callback) {
$status = $('#admin_' + subjects.name + '_0_status'); $status = $('#admin_' + subjects.name + '_0_status');
$status.hide().text(client.translate('Loading database ...')).fadeIn('slow'); $status.hide().text(client.translate('Loading database ...')).fadeIn('slow');
var table = $('<table id="admin_subjects_table">').css('margin-top','10px'); var table = $('<table id="admin_subjects_table">').css('margin-top', '10px');
$('#admin_' + subjects.name + '_0_html').append(table).append(genDialog(client)); $('#admin_' + subjects.name + '_0_html').append(table).append(genDialog(client));
reload(client, callback); reload(client, callback);
} }
@@ -39,9 +41,9 @@ function createOrSaveSubject (subject, client, callback) {
, url: '/api/v2/authorization/subjects/' , url: '/api/v2/authorization/subjects/'
, headers: client.headers() , headers: client.headers()
, data: subject , data: subject
}).done(function success() { }).done(function success () {
reload(client, callback); reload(client, callback);
}).fail(function fail(err) { }).fail(function fail (err) {
console.error('Unable to ' + method + ' Subject', err.responseText); console.error('Unable to ' + method + ' Subject', err.responseText);
window.alert(client.translate('Unable to ' + method + ' Subject')); window.alert(client.translate('Unable to ' + method + ' Subject'));
if (callback) { if (callback) {
@@ -55,9 +57,9 @@ function deleteSubject (subject, client, callback) {
method: 'DELETE' method: 'DELETE'
, url: '/api/v2/authorization/subjects/' + subject._id , url: '/api/v2/authorization/subjects/' + subject._id
, headers: client.headers() , headers: client.headers()
}).done(function success() { }).done(function success () {
reload(client, callback); reload(client, callback);
}).fail(function fail(err) { }).fail(function fail (err) {
console.error('Unable to delete Subject', err.responseText); console.error('Unable to delete Subject', err.responseText);
window.alert(client.translate('Unable to delete Subject')); window.alert(client.translate('Unable to delete Subject'));
if (callback) { if (callback) {
@@ -69,16 +71,16 @@ function deleteSubject (subject, client, callback) {
function reload (client, callback) { function reload (client, callback) {
$.ajax({ $.ajax({
method: 'GET' method: 'GET'
, url:'/api/v2/authorization/subjects' , url: '/api/v2/authorization/subjects'
, headers: client.headers() , headers: client.headers()
}).done(function success (records) { }).done(function success (records) {
subjects.records = records; subjects.records = records;
$status.hide().text(client.translate('Database contains %1 subjects',{ params: [records.length] })).fadeIn('slow'); $status.hide().text(client.translate('Database contains %1 subjects', { params: [records.length] })).fadeIn('slow');
showSubjects(records, client); showSubjects(records, client);
if (callback) { if (callback) {
callback(); callback();
} }
}).fail(function fail(err) { }).fail(function fail (err) {
$status.hide().text(client.translate('Error loading database')).fadeIn('slow'); $status.hide().text(client.translate('Error loading database')).fadeIn('slow');
subjects.records = []; subjects.records = [];
if (callback) { if (callback) {
@@ -89,56 +91,57 @@ function reload (client, callback) {
function genDialog (client) { function genDialog (client) {
var ret = var ret =
'<div id="editsubjectdialog" style="display:none" title="' + client.translate('Edit Subject') + '">' '<div id="editsubjectdialog" style="display:none" title="' + client.translate('Edit Subject') + '">' +
+ ' <label for="edsub_name">' ' <label for="edsub_name">' +
+ client.translate('Name') client.translate('Name') +
+ ' <input id="edsub_name" placeholder="' + client.translate('person, device, etc') + '"/>' ' <input id="edsub_name" placeholder="' + client.translate('person, device, etc') + '"/>' +
+ ' </label>' ' </label>' +
+ ' <br>' ' <br>' +
+ ' <label for="edsub_roles">' ' <label for="edsub_roles">' +
+ client.translate('Roles') client.translate('Roles') +
+ ' <input id="edsub_roles" placeholder="' + client.translate('role1, role2') + '"/>' ' <input id="edsub_roles" placeholder="' + client.translate('role1, role2') + '"/>' +
+ ' </label>' ' </label>' +
+ ' <br>' ' <br>' +
+ ' <label for="edsub_notes">' + client.translate('Additional Notes, Comments') + '</label>' ' <label for="edsub_notes">' + client.translate('Additional Notes, Comments') + '</label>' +
+ ' <textarea id="edsub_notes" style="width:300px"></textarea><br>' ' <textarea id="edsub_notes" style="width:300px"></textarea><br>' +
+ ' </div>' ' </div>';
;
return $(ret); return $(ret);
} }
function openDialog (subject, client) { function openDialog (subject, client) {
$( '#editsubjectdialog' ).dialog({ $('#editsubjectdialog').dialog({
width: 360 width: 360
, height: 300 , height: 300
, buttons: [ , buttons: [
{ text: client.translate('Save'), {
class: 'leftButton', text: client.translate('Save')
click: function() { , class: 'leftButton'
, click: function() {
subject.name = $('#edsub_name').val(); subject.name = $('#edsub_name').val();
subject.roles = subject.roles =
_.chain($('#edsub_roles').val().toLowerCase().split(/[;, ]/)) _.chain($('#edsub_roles').val().toLowerCase().split(/[;, ]/))
.map(_.trim) .map(_.trim)
.reject(_.isEmpty) .reject(_.isEmpty)
.sort() .sort()
.value(); .value();
subject.notes = $('#edsub_notes').val(); subject.notes = $('#edsub_notes').val();
var self = this; var self = this;
createOrSaveSubject(subject, client, function callback ( ) { createOrSaveSubject(subject, client, function callback () {
$( self ).dialog('close'); $(self).dialog('close');
}); });
} }
}, }
{ text: client.translate('Cancel'), , {
click: function () { $( this ).dialog('close'); } text: client.translate('Cancel')
, click: function() { $(this).dialog('close'); }
} }
] ]
, open : function() { , open: function() {
$(this).parent().css('box-shadow', '20px 20px 20px 0px black'); $(this).parent().css('box-shadow', '20px 20px 20px 0px black');
$(this).parent().find('.ui-dialog-buttonset' ).css({'width':'100%','text-align':'right'}); $(this).parent().find('.ui-dialog-buttonset').css({ 'width': '100%', 'text-align': 'right' });
$(this).parent().find('button:contains("'+client.translate('Save')+'")').css({'float':'left'}); $(this).parent().find('button:contains("' + client.translate('Save') + '")').css({ 'float': 'left' });
$('#edsub_name').val(subject.name || '').focus(); $('#edsub_name').val(subject.name || '').focus();
$('#edsub_roles').val(subject.roles ? subject.roles.join(', ') : ''); $('#edsub_roles').val(subject.roles ? subject.roles.join(', ') : '');
$('#edsub_notes').val(subject.notes || ''); $('#edsub_notes').val(subject.notes || '');
@@ -150,33 +153,33 @@ function openDialog (subject, client) {
function showSubject (subject, table, client) { function showSubject (subject, table, client) {
var editIcon = $('<img title="' + client.translate('Edit this subject') + '" style="cursor:pointer" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABEUlEQVQ4jZ3MMUsCYQDG8ee8IySQbNCLyyEKG/RLNAXicqvQcAeNLrcFLlE0+xHuNpt8wy04rrYm8Q4HQRE56BSC3lSqU1BwCoxM39dnffj9BWyxXvVeEzvtctBwHyRebNu2Nk2lzMlrgJB+qBEeTByiKYpihl+fIO8jTI9PDJEVF1+K2iw+M6PhDuyag4NkQi/c3FkCK5Z3ZbM76qLltpCbn+vXxq0FABsDy9hzPdBvqvtXvvXzrw1swmsDLPjfACteGeDBfwK8+FdgGwwAIgC0ncsjxGRSH/eiPBgAJADY2z8sJ4JBfNBsDqlADVYMANIzKalv/bHaefKsTH9iPFb8ISsGAJym0+Qinz3jQktbAHcxvx3559eSAAAAAElFTkSuQmCC">'); var editIcon = $('<img title="' + client.translate('Edit this subject') + '" style="cursor:pointer" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABEUlEQVQ4jZ3MMUsCYQDG8ee8IySQbNCLyyEKG/RLNAXicqvQcAeNLrcFLlE0+xHuNpt8wy04rrYm8Q4HQRE56BSC3lSqU1BwCoxM39dnffj9BWyxXvVeEzvtctBwHyRebNu2Nk2lzMlrgJB+qBEeTByiKYpihl+fIO8jTI9PDJEVF1+K2iw+M6PhDuyag4NkQi/c3FkCK5Z3ZbM76qLltpCbn+vXxq0FABsDy9hzPdBvqvtXvvXzrw1swmsDLPjfACteGeDBfwK8+FdgGwwAIgC0ncsjxGRSH/eiPBgAJADY2z8sJ4JBfNBsDqlADVYMANIzKalv/bHaefKsTH9iPFb8ISsGAJym0+Qinz3jQktbAHcxvx3559eSAAAAAElFTkSuQmCC">');
editIcon.click(function clicked ( ) { editIcon.click(function clicked () {
openDialog(subject, client); openDialog(subject, client);
}); });
var deleteIcon = $('<img title="' + client.translate('Delete this subject') + '" style="cursor:pointer" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACrElEQVQ4T42Ty2sTQRzHv5tmk2yyjRNtpfZhL8V6s2KoUNC2XqwgaCsVQcGiFqpHi0c9iRdR/ANE9KR40FIQX4cueKoPaKFoLdSYNtE0abKT1+5s9iW7aUMiHtzTzO7v85md+c6PA4DrHbsPCKIgOWO1pA7dT6YXnXH949SE/F63pqwZtRrO+SCKgjQ5NUV+azpmHj2krMwaJC4c8Erj+/eRyloMMwWFKgbn1nC3ervlK1evkXBLGBZT8SOewotnTylTNLdgeg/pDgZDC2cPHSR8bB22DVC9hFe0SG/H0xFXcHlykjRHRDBWgJcZSCY38Xx2lhqMnRYE34Px/sN9vlQWeoHBAx2yXsRruVAVuFsIBaSJ8+eJGPaBqQV4NROJjTzez89jLBoFn6FgybQL54wS3uTyVDFQ3cL2IYpBv3RhdJSIIQ80tQyv7gEqJvS8AmUlBs7UXPhtjtZgh3UFNYngk86NHCfNAg9dMwHVBPu+CpsVkTXKeJeVG+AGgTOZ3tt6MSKKjy+NjEBjFrR4ElZmA4pdxstMFsyyJu6tZZ7Ux9vwB6EAL50ZGiRECEPPUOixVTRxHlicgSVWxEdZpuZWfNuS2hk48NjwMIkIYZglBnV5Cbqtws/5IaAJmsfCglrEl2y2QeKmEBJ80tixKmxrFpSVr0gV0viQoxho2YUuPohmeFD22PiklLC4ma5JuBvdrfLJI0dJd0s7bM0ES8aR/BXDXGaTskqlL+D3Lwy0tZEePoAd4EA5YF4tYymdonfjmQh3s6dTPjU4SHYGwjAKecSXFyGlM1TdytntE56T+ts7SC/vhw3gm6njc2Kd3vm5Ub1IwQAvnYhGiZpYw1wiWYPrIw7wnBTt7CLOOwdmut14kQQvqt24tfK/utGR6LaF+iRqMf4N/O/8D28HiiCRYqzAAAAAAElFTkSuQmCC">'); var deleteIcon = $('<img title="' + client.translate('Delete this subject') + '" style="cursor:pointer" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACrElEQVQ4T42Ty2sTQRzHv5tmk2yyjRNtpfZhL8V6s2KoUNC2XqwgaCsVQcGiFqpHi0c9iRdR/ANE9KR40FIQX4cueKoPaKFoLdSYNtE0abKT1+5s9iW7aUMiHtzTzO7v85md+c6PA4DrHbsPCKIgOWO1pA7dT6YXnXH949SE/F63pqwZtRrO+SCKgjQ5NUV+azpmHj2krMwaJC4c8Erj+/eRyloMMwWFKgbn1nC3ervlK1evkXBLGBZT8SOewotnTylTNLdgeg/pDgZDC2cPHSR8bB22DVC9hFe0SG/H0xFXcHlykjRHRDBWgJcZSCY38Xx2lhqMnRYE34Px/sN9vlQWeoHBAx2yXsRruVAVuFsIBaSJ8+eJGPaBqQV4NROJjTzez89jLBoFn6FgybQL54wS3uTyVDFQ3cL2IYpBv3RhdJSIIQ80tQyv7gEqJvS8AmUlBs7UXPhtjtZgh3UFNYngk86NHCfNAg9dMwHVBPu+CpsVkTXKeJeVG+AGgTOZ3tt6MSKKjy+NjEBjFrR4ElZmA4pdxstMFsyyJu6tZZ7Ux9vwB6EAL50ZGiRECEPPUOixVTRxHlicgSVWxEdZpuZWfNuS2hk48NjwMIkIYZglBnV5Cbqtws/5IaAJmsfCglrEl2y2QeKmEBJ80tixKmxrFpSVr0gV0viQoxho2YUuPohmeFD22PiklLC4ma5JuBvdrfLJI0dJd0s7bM0ES8aR/BXDXGaTskqlL+D3Lwy0tZEePoAd4EA5YF4tYymdonfjmQh3s6dTPjU4SHYGwjAKecSXFyGlM1TdytntE56T+ts7SC/vhw3gm6njc2Kd3vm5Ub1IwQAvnYhGiZpYw1wiWYPrIw7wnBTt7CLOOwdmut14kQQvqt24tfK/utGR6LaF+iRqMf4N/O/8D28HiiCRYqzAAAAAAElFTkSuQmCC">');
deleteIcon.click(function clicked ( ) { deleteIcon.click(function clicked () {
var ok = window.confirm(client.translate('Are you sure you want to delete: ') + subject.name); var ok = window.confirm(client.translate('Are you sure you want to delete: ') + subject.name);
if (ok) { if (ok) {
deleteSubject(subject, client); deleteSubject(subject, client);
} }
}); });
table.append($('<tr>').css('background-color','#0f0f0f') table.append($('<tr>').css('background-color', '#0f0f0f')
.append($('<td>').attr('width','20%').append(editIcon).append(deleteIcon).append(subject.name)) .append($('<td>').attr('width', '20%').append(editIcon).append(deleteIcon).append(subject.name))
.append($('<td>').attr('width','20%').append(subject.roles ? subject.roles.join(', ') : '[none]')) .append($('<td>').attr('width', '20%').append(subject.roles ? subject.roles.join(', ') : '[none]'))
.append($('<td>').attr('width','20%').append('<a href="/?token=' + subject.accessToken + '" target="_blank">' + subject.accessToken + '</a>')) .append($('<td>').attr('width', '20%').append('<a href="/?token=' + subject.accessToken + '" target="_blank">' + subject.accessToken + '</a>'))
.append($('<td>').attr('width','10%').append(subject.notes ? subject.notes : '')) .append($('<td>').attr('width', '10%').append(subject.notes ? subject.notes : ''))
); );
} }
function showSubjects (subjects, client) { function showSubjects (subjects, client) {
var table = $('#admin_subjects_table'); var table = $('#admin_subjects_table');
table.empty().append($('<tr>').css('background','#040404') table.empty().append($('<tr>').css('background', '#040404')
.append($('<th>').css('width','100px').attr('align','left').append(client.translate('Name'))) .append($('<th>').css('width', '100px').attr('align', 'left').append(client.translate('Name')))
.append($('<th>').css('width','150px').attr('align','left').append(client.translate('Roles'))) .append($('<th>').css('width', '150px').attr('align', 'left').append(client.translate('Roles')))
.append($('<th>').css('width','150px').attr('align','left').append(client.translate('Access Token'))) .append($('<th>').css('width', '150px').attr('align', 'left').append(client.translate('Access Token')))
.append($('<th>').css('width','150px').attr('align','left').append(client.translate('Notes'))) .append($('<th>').css('width', '150px').attr('align', 'left').append(client.translate('Notes')))
); );
for (var t=0; t<subjects.length; t++) { for (var t = 0; t < subjects.length; t++) {
showSubject(subjects[t], table, client); showSubject(subjects[t], table, client);
} }
} }
+146 -145
View File
@@ -5,8 +5,8 @@ var moment = require('moment-timezone');
var times = require('../times'); var times = require('../times');
var Storages = require('js-storage'); var Storages = require('js-storage');
function init(client, $) { function init (client, $) {
var boluscalc = { }; var boluscalc = {};
var translate = client.translate; var translate = client.translate;
var storage = Storages.localStorage; var storage = Storages.localStorage;
@@ -34,16 +34,15 @@ function init(client, $) {
} }
} }
function isProfileEnabled(profiles) { function isProfileEnabled (profiles) {
return client.settings.enable.indexOf('profile') > -1 return client.settings.enable.indexOf('profile') > -1 &&
&& client.settings.extendedSettings.profile client.settings.extendedSettings.profile &&
&& client.settings.extendedSettings.profile.multiple client.settings.extendedSettings.profile.multiple &&
&& profiles.length > 1; profiles.length > 1;
} }
function isTouch() { function isTouch () {
try { document.createEvent('TouchEvent'); return true; } try { document.createEvent('TouchEvent'); return true; } catch (e) { return false; }
catch (e) { return false; }
} }
function setDateAndTime (time) { function setDateAndTime (time) {
@@ -52,11 +51,11 @@ function init(client, $) {
eventDate.val(time.format('YYYY-MM-DD')); eventDate.val(time.format('YYYY-MM-DD'));
} }
function mergeDateAndTime ( ) { function mergeDateAndTime () {
return client.utils.mergeInputTime(eventTime.val(), eventDate.val()); return client.utils.mergeInputTime(eventTime.val(), eventDate.val());
} }
function updateTime(ele, time) { function updateTime (ele, time) {
ele.attr('oldminutes', time.minutes()); ele.attr('oldminutes', time.minutes());
ele.attr('oldhours', time.hours()); ele.attr('oldhours', time.hours());
} }
@@ -98,15 +97,15 @@ function init(client, $) {
} }
}; };
boluscalc.dateTimeFocus = function dateTimeFocus(event) { boluscalc.dateTimeFocus = function dateTimeFocus (event) {
$('#bc_othertime').prop('checked', true); $('#bc_othertime').prop('checked', true);
updateTime($(this), mergeDateAndTime()); updateTime($(this), mergeDateAndTime());
maybePrevent(event); maybePrevent(event);
}; };
boluscalc.dateTimeChange = function dateTimeChange(event) { boluscalc.dateTimeChange = function dateTimeChange (event) {
$('#bc_othertime').prop('checked', true); $('#bc_othertime').prop('checked', true);
// client.utils.setYAxisOffset(50); //50% of extend // client.utils.setYAxisOffset(50); //50% of extend
var ele = $(this); var ele = $(this);
var merged = mergeDateAndTime(); var merged = mergeDateAndTime();
@@ -126,29 +125,29 @@ function init(client, $) {
boluscalc.calculateInsulin(); boluscalc.calculateInsulin();
maybePrevent(event); maybePrevent(event);
// Nightscout.utils.updateBrushToTime(moment.toDate()); // Nightscout.utils.updateBrushToTime(moment.toDate());
}; };
boluscalc.eventTimeTypeChange = function eventTimeTypeChange(event) { boluscalc.eventTimeTypeChange = function eventTimeTypeChange (event) {
if ($('#bc_othertime').is(':checked')) { if ($('#bc_othertime').is(':checked')) {
$('#bc_eventTimeValue').focus(); $('#bc_eventTimeValue').focus();
$('#bc_retro').css('display',''); $('#bc_retro').css('display', '');
if (mergeDateAndTime()<moment()) { if (mergeDateAndTime() < moment()) {
$('#bc_retro').css('background-color','red').text(translate('RETRO MODE')); $('#bc_retro').css('background-color', 'red').text(translate('RETRO MODE'));
} else if (mergeDateAndTime()>moment()) { } else if (mergeDateAndTime() > moment()) {
$('#bc_retro').css('background-color','blue').text(translate('IN THE FUTURE')); $('#bc_retro').css('background-color', 'blue').text(translate('IN THE FUTURE'));
} else { } else {
$('#bc_retro').css('display','none'); $('#bc_retro').css('display', 'none');
} }
} else { } else {
$('#bc_retro').css('display','none'); $('#bc_retro').css('display', 'none');
setDateAndTime(); setDateAndTime();
boluscalc.updateVisualisations(client.sbx); boluscalc.updateVisualisations(client.sbx);
if (event) { if (event) {
boluscalc.calculateInsulin(); boluscalc.calculateInsulin();
} }
// Nightscout.utils.setYAxisOffset(50); //50% of extend // Nightscout.utils.setYAxisOffset(50); //50% of extend
// Nightscout.utils.updateBrushToTime(Nightscout.utils.mergeInputTime($('#bc_eventTimeValue').val(), $('#bc_eventDateValue').val()).toDate()); // Nightscout.utils.updateBrushToTime(Nightscout.utils.mergeInputTime($('#bc_eventTimeValue').val(), $('#bc_eventDateValue').val()).toDate());
} }
maybePrevent(event); maybePrevent(event);
}; };
@@ -159,20 +158,20 @@ function init(client, $) {
maybePrevent(event); maybePrevent(event);
}; };
boluscalc.prepare = function prepare( ) { boluscalc.prepare = function prepare () {
foods = []; foods = [];
$('#bc_profile').empty(); $('#bc_profile').empty();
var profiles = client.profilefunctions.listBasalProfiles(); var profiles = client.profilefunctions.listBasalProfiles();
profiles.forEach(function (p) { profiles.forEach(function(p) {
$('#bc_profile').append('<option val="' + p + '">' + p + '</option>'); $('#bc_profile').append('<option val="' + p + '">' + p + '</option>');
}); });
$('#bc_profileLabel').toggle(isProfileEnabled(profiles)); $('#bc_profileLabel').toggle(isProfileEnabled(profiles));
$('#bc_usebg').prop('checked','checked'); $('#bc_usebg').prop('checked', 'checked');
$('#bc_usecarbs').prop('checked','checked'); $('#bc_usecarbs').prop('checked', 'checked');
$('#bc_usecob').prop('checked',''); $('#bc_usecob').prop('checked', '');
$('#bc_useiob').prop('checked','checked'); $('#bc_useiob').prop('checked', 'checked');
$('#bc_bgfromsensor').prop('checked','checked'); $('#bc_bgfromsensor').prop('checked', 'checked');
$('#bc_carbs').val(''); $('#bc_carbs').val('');
$('#bc_quickpick').val(-1); $('#bc_quickpick').val(-1);
$('#bc_preBolus').val(0); $('#bc_preBolus').val(0);
@@ -189,9 +188,9 @@ function init(client, $) {
boluscalc.calculateInsulin = function calculateInsulin (event) { boluscalc.calculateInsulin = function calculateInsulin (event) {
maybePrevent(event); maybePrevent(event);
boluscalc.gatherBoluscalcData( ); boluscalc.gatherBoluscalcData();
boluscalc.updateGui(boluscalc.record); boluscalc.updateGui(boluscalc.record);
return boluscalc.record; return boluscalc.record;
}; };
boluscalc.updateGui = function updateGui (record) { boluscalc.updateGui = function updateGui (record) {
@@ -236,11 +235,11 @@ function init(client, $) {
$('#bc_bg').css('background-color', ''); $('#bc_bg').css('background-color', '');
} }
$('#bc_inzulinbg').text(record.insulinbg.toFixed(2)); $('#bc_inzulinbg').text(record.insulinbg.toFixed(2));
$('#bc_inzulinbg').attr('title', $('#bc_inzulinbg').attr('title'
'Target BG range: '+targetBGLow + ' - ' + targetBGHigh + , 'Target BG range: ' + targetBGLow + ' - ' + targetBGHigh +
'\nISF: ' + isf + '\nISF: ' + isf +
'\nBG diff: ' + record.bgdiff.toFixed(1) '\nBG diff: ' + record.bgdiff.toFixed(1)
); );
} else { } else {
$('#bc_inzulinbgtd').css('background-color', ''); $('#bc_inzulinbgtd').css('background-color', '');
$('#bc_bg').css('background-color', ''); $('#bc_bg').css('background-color', '');
@@ -252,51 +251,51 @@ function init(client, $) {
if (record.foods.length) { if (record.foods.length) {
var html = '<table style="float:right;margin-right:20px;font-size:12px">'; var html = '<table style="float:right;margin-right:20px;font-size:12px">';
var carbs = 0; var carbs = 0;
for (var fi=0; fi<record.foods.length; fi++) { for (var fi = 0; fi < record.foods.length; fi++) {
var f = record.foods[fi]; var f = record.foods[fi];
carbs += f.carbs * f.portions; carbs += f.carbs * f.portions;
html += '<tr>'; html += '<tr>';
html += '<td>'; html += '<td>';
if ($('#bc_quickpick').val() < 0) { // do not allow deleting while quickpick active if ($('#bc_quickpick').val() < 0) { // do not allow deleting while quickpick active
html += '<img style="cursor:pointer" title="Delete record" src="'+icon_remove+'" href="#" class="deleteFoodRecord" index="'+fi+'">'; html += '<img style="cursor:pointer" title="Delete record" src="' + icon_remove + '" href="#" class="deleteFoodRecord" index="' + fi + '">';
} }
html += '</td>'; html += '</td>';
html += '<td>'+ f.name + '</td>'; html += '<td>' + f.name + '</td>';
html += '<td>'+ (f.portion*f.portions).toFixed(1) + ' ' + translate(f.unit) + '</td>'; html += '<td>' + (f.portion * f.portions).toFixed(1) + ' ' + translate(f.unit) + '</td>';
html += '<td>('+ (f.carbs*f.portions).toFixed(1) + ' g)</td>'; html += '<td>(' + (f.carbs * f.portions).toFixed(1) + ' g)</td>';
html += '</tr>'; html += '</tr>';
} }
html += '</table>'; html += '</table>';
$('#bc_food').html(html); $('#bc_food').html(html);
$('.deleteFoodRecord').click(deleteFoodRecord); $('.deleteFoodRecord').click(deleteFoodRecord);
$('#bc_carbs').val(carbs.toFixed(0)); $('#bc_carbs').val(carbs.toFixed(0));
$('#bc_carbs').attr('disabled',true); $('#bc_carbs').attr('disabled', true);
$('#bc_gi').css('display','none'); $('#bc_gi').css('display', 'none');
$('#bc_gicalculated').css('display',''); $('#bc_gicalculated').css('display', '');
$('#bc_gicalculated').text(record.gi); $('#bc_gicalculated').text(record.gi);
} else { } else {
$('#bc_food').html(''); $('#bc_food').html('');
$('#bc_carbs').attr('disabled',false); $('#bc_carbs').attr('disabled', false);
$('#bc_gi').css('display',''); $('#bc_gi').css('display', '');
$('#bc_gicalculated').css('display','none'); $('#bc_gicalculated').css('display', 'none');
$('#bc_gicalculated').text(''); $('#bc_gicalculated').text('');
} }
// Show Carbs // Show Carbs
if ($('#bc_usecarbs').is(':checked')) { if ($('#bc_usecarbs').is(':checked')) {
if ($('#bc_carbs').val() === '') { if ($('#bc_carbs').val() === '') {
$('#bc_carbs').css('background-color',''); $('#bc_carbs').css('background-color', '');
} else if (isNaN(parseInt($('#bc_carbs').val().replace(',','.')))) { } else if (isNaN(parseInt($('#bc_carbs').val().replace(',', '.')))) {
$('#bc_carbs').css('background-color','red'); $('#bc_carbs').css('background-color', 'red');
} else { } else {
$('#bc_carbs').css('background-color',''); $('#bc_carbs').css('background-color', '');
} }
$('#bc_inzulincarbs').text(record.insulincarbs.toFixed(2)); $('#bc_inzulincarbs').text(record.insulincarbs.toFixed(2));
$('#bc_inzulincarbs').attr('title','IC: ' + ic); $('#bc_inzulincarbs').attr('title', 'IC: ' + ic);
} else { } else {
$('#bc_carbs').css('background-color',''); $('#bc_carbs').css('background-color', '');
$('#bc_inzulincarbs').text(''); $('#bc_inzulincarbs').text('');
$('#bc_inzulincarbs').attr('title',''); $('#bc_inzulincarbs').attr('title', '');
$('#bc_carbs').text(''); $('#bc_carbs').text('');
} }
@@ -309,21 +308,21 @@ function init(client, $) {
if (record.othercorrection === 0 && record.carbs === 0 && record.cob === 0 && record.bg > 0 && outcome > targetBGLow && outcome < targetBGHigh) { if (record.othercorrection === 0 && record.carbs === 0 && record.cob === 0 && record.bg > 0 && outcome > targetBGLow && outcome < targetBGHigh) {
$('#bc_carbsneeded').text(''); $('#bc_carbsneeded').text('');
$('#bc_insulinover').text(''); $('#bc_insulinover').text('');
$('#bc_carbsneededtr').css('display','none'); $('#bc_carbsneededtr').css('display', 'none');
$('#bc_insulinneededtr').css('display','none'); $('#bc_insulinneededtr').css('display', 'none');
$('#bc_calculationintarget').css('display',''); $('#bc_calculationintarget').css('display', '');
} else if (record.insulin<0) { } else if (record.insulin < 0) {
$('#bc_carbsneeded').text(record.carbsneeded+' g'); $('#bc_carbsneeded').text(record.carbsneeded + ' g');
$('#bc_insulinover').text(record.insulin.toFixed(2)); $('#bc_insulinover').text(record.insulin.toFixed(2));
$('#bc_carbsneededtr').css('display',''); $('#bc_carbsneededtr').css('display', '');
$('#bc_insulinneededtr').css('display','none'); $('#bc_insulinneededtr').css('display', 'none');
$('#bc_calculationintarget').css('display','none'); $('#bc_calculationintarget').css('display', 'none');
} else { } else {
$('#bc_carbsneeded').text(''); $('#bc_carbsneeded').text('');
$('#bc_insulinover').text(''); $('#bc_insulinover').text('');
$('#bc_carbsneededtr').css('display','none'); $('#bc_carbsneededtr').css('display', 'none');
$('#bc_insulinneededtr').css('display',''); $('#bc_insulinneededtr').css('display', '');
$('#bc_calculationintarget').css('display','none'); $('#bc_calculationintarget').css('display', 'none');
} }
// Show basal rate // Show basal rate
@@ -335,7 +334,7 @@ function init(client, $) {
$('#bc_basal').text(tempMark + basal.totalbasal.toFixed(3)); $('#bc_basal').text(tempMark + basal.totalbasal.toFixed(3));
}; };
boluscalc.gatherBoluscalcData = function gatherBoluscalcData() { boluscalc.gatherBoluscalcData = function gatherBoluscalcData () {
boluscalc.record = {}; boluscalc.record = {};
var record = boluscalc.record; var record = boluscalc.record;
@@ -351,7 +350,6 @@ function init(client, $) {
return; return;
} }
// Calculate event time from date & time // Calculate event time from date & time
record.eventTime = new Date(); record.eventTime = new Date();
if ($('#bc_othertime').is(':checked')) { if ($('#bc_othertime').is(':checked')) {
@@ -373,19 +371,19 @@ function init(client, $) {
record.ic = ic; record.ic = ic;
if (targetBGLow === 0 || targetBGHigh === 0 || isf === 0 || ic === 0) { if (targetBGLow === 0 || targetBGHigh === 0 || isf === 0 || ic === 0) {
$('#bc_inzulinbgtd').css('background-color','red'); $('#bc_inzulinbgtd').css('background-color', 'red');
boluscalc.record = {}; boluscalc.record = {};
return; return;
} else { } else {
$('#bc_inzulinbgtd').css('background-color',''); $('#bc_inzulinbgtd').css('background-color', '');
} }
if (ic === 0) { if (ic === 0) {
$('#bc_inzulincarbstd').css('background-color','red'); $('#bc_inzulincarbstd').css('background-color', 'red');
boluscalc.record = {}; boluscalc.record = {};
return; return;
} else { } else {
$('#bc_inzulincarbstd').css('background-color',''); $('#bc_inzulincarbstd').css('background-color', '');
} }
// Load IOB // Load IOB
@@ -407,7 +405,7 @@ function init(client, $) {
record.insulinbg = 0; record.insulinbg = 0;
record.bgdiff = 0; record.bgdiff = 0;
if ($('#bc_usebg').is(':checked')) { if ($('#bc_usebg').is(':checked')) {
record.bg = parseFloat($('#bc_bg').val().replace(',','.')); record.bg = parseFloat($('#bc_bg').val().replace(',', '.'));
if (isNaN(record.bg)) { if (isNaN(record.bg)) {
record.bg = 0; record.bg = 0;
} }
@@ -417,7 +415,7 @@ function init(client, $) {
record.bgdiff = record.bg - targetBGHigh; record.bgdiff = record.bg - targetBGHigh;
} }
record.bgdiff = roundTo(record.bgdiff, 0.1); record.bgdiff = roundTo(record.bgdiff, 0.1);
if (record.bg !== 0){ if (record.bg !== 0) {
record.insulinbg = roundTo(record.bgdiff / isf, 0.01); record.insulinbg = roundTo(record.bgdiff / isf, 0.01);
} }
} }
@@ -427,7 +425,7 @@ function init(client, $) {
record.foods = _.cloneDeep(foods); record.foods = _.cloneDeep(foods);
if (record.foods.length) { if (record.foods.length) {
var gisum = 0; var gisum = 0;
for (var fi=0; fi<record.foods.length; fi++) { for (var fi = 0; fi < record.foods.length; fi++) {
var f = record.foods[fi]; var f = record.foods[fi];
record.carbs += f.carbs * f.portions; record.carbs += f.carbs * f.portions;
gisum += f.carbs * f.portions * f.gi; gisum += f.carbs * f.portions * f.gi;
@@ -441,7 +439,7 @@ function init(client, $) {
record.insulincarbs = 0; record.insulincarbs = 0;
if ($('#bc_usecarbs').is(':checked')) { if ($('#bc_usecarbs').is(':checked')) {
if (record.carbs === 0) { // not set from foods if (record.carbs === 0) { // not set from foods
record.carbs = parseInt($('#bc_carbs').val().replace(',','.')); record.carbs = parseInt($('#bc_carbs').val().replace(',', '.'));
} }
if (isNaN(record.carbs)) { if (isNaN(record.carbs)) {
record.carbs = 0; record.carbs = 0;
@@ -462,15 +460,15 @@ function init(client, $) {
// Carbs needed if too much iob // Carbs needed if too much iob
record.carbsneeded = 0; record.carbsneeded = 0;
if (record.insulin<0) { if (record.insulin < 0) {
record.carbsneeded = Math.ceil(-total * ic); record.carbsneeded = Math.ceil(-total * ic);
} }
console.log('Insulin calculation result: ',record); console.log('Insulin calculation result: ', record);
return record; return record;
}; };
function gatherData ( ) { function gatherData () {
var data = {}; var data = {};
data.boluscalc = boluscalc.calculateInsulin(); data.boluscalc = boluscalc.calculateInsulin();
if (!data.boluscalc) { if (!data.boluscalc) {
@@ -480,14 +478,14 @@ function init(client, $) {
data.enteredBy = $('#bc_enteredBy').val(); data.enteredBy = $('#bc_enteredBy').val();
data.eventType = 'Bolus Wizard'; data.eventType = 'Bolus Wizard';
if ($('#bc_bg').val()!==0) { if ($('#bc_bg').val() !== 0) {
data.glucose = $('#bc_bg').val().replace(',','.'); data.glucose = $('#bc_bg').val().replace(',', '.');
data.glucoseType = $('#boluscalc-form').find('input[name=bc_bginput]:checked').val(); data.glucoseType = $('#boluscalc-form').find('input[name=bc_bginput]:checked').val();
data.units = client.settings.units; data.units = client.settings.units;
} }
data.carbs = $('#bc_carbs').val().replace(',','.'); data.carbs = $('#bc_carbs').val().replace(',', '.');
data.insulin = $('#bc_insulintotal').text(); data.insulin = $('#bc_insulintotal').text();
if (data.insulin<=0) { if (data.insulin <= 0) {
delete data.insulin; delete data.insulin;
} }
data.preBolus = parseInt($('#bc_preBolus').val()); data.preBolus = parseInt($('#bc_preBolus').val());
@@ -503,7 +501,7 @@ function init(client, $) {
return data; return data;
} }
boluscalc.submit = function submit(event) { boluscalc.submit = function submit (event) {
var data = gatherData(); var data = gatherData();
if (data) { if (data) {
confirmPost(data); confirmPost(data);
@@ -512,9 +510,10 @@ function init(client, $) {
return false; return false;
}; };
function buildConfirmText(data) { function buildConfirmText (data) {
var text = [ var text = [
translate('Please verify that the data entered is correct') + ': ' translate('Please verify that the data entered is correct') + ': '
, translate('Event Type') + ': ' + translate(data.eventType) , translate('Event Type') + ': ' + translate(data.eventType)
]; ];
@@ -538,13 +537,13 @@ function init(client, $) {
return text.join('\n'); return text.join('\n');
} }
function confirmPost(data) { function confirmPost (data) {
if (window.confirm(buildConfirmText(data))) { if (window.confirm(buildConfirmText(data))) {
$.ajax({ $.ajax({
method: 'POST', method: 'POST'
url: '/api/v1/treatments/' , url: '/api/v1/treatments/'
, headers: client.headers() , headers: client.headers()
, data: data , data: data
}).done(function treatmentSaved (response) { }).done(function treatmentSaved (response) {
console.info('treatment saved', response); console.info('treatment saved', response);
}).fail(function treatmentSaveFail (response) { }).fail(function treatmentSaveFail (response) {
@@ -560,33 +559,33 @@ function init(client, $) {
} }
// Food manipulation // Food manipulation
function deleteFoodRecord(event) { function deleteFoodRecord (event) {
var index = $(this).attr('index'); var index = $(this).attr('index');
foods.splice(index,1); foods.splice(index, 1);
$('#bc_carbs').val(''); $('#bc_carbs').val('');
boluscalc.calculateInsulin(); boluscalc.calculateInsulin();
maybePrevent(event); maybePrevent(event);
return false; return false;
} }
function quickpickChange(event) { function quickpickChange (event) {
var qpiselected = $('#bc_quickpick').val(); var qpiselected = $('#bc_quickpick').val();
if (qpiselected === null || qpiselected === '-1') { // (none) if (qpiselected === null || qpiselected === '-1') { // (none)
$('#bc_carbs').val(0); $('#bc_carbs').val(0);
foods = []; foods = [];
$('#bc_addfoodarea').css('display',''); $('#bc_addfoodarea').css('display', '');
} else { } else {
var qp = quickpicks[qpiselected]; var qp = quickpicks[qpiselected];
foods = _.cloneDeep(qp.foods); foods = _.cloneDeep(qp.foods);
$('#bc_addfoodarea').css('display','none'); $('#bc_addfoodarea').css('display', 'none');
} }
boluscalc.calculateInsulin(); boluscalc.calculateInsulin();
maybePrevent(event); maybePrevent(event);
} }
function quickpickHideFood() { function quickpickHideFood () {
var qpiselected = $('#bc_quickpick').val(); var qpiselected = $('#bc_quickpick').val();
if (qpiselected >= 0) { if (qpiselected >= 0) {
@@ -613,16 +612,16 @@ function init(client, $) {
var foodlist = []; var foodlist = [];
var databaseloaded = false; var databaseloaded = false;
var filter = { var filter = {
category: '' category: ''
, subcategory: '' , subcategory: ''
, name: '' , name: ''
}; };
boluscalc.loadFoodDatabase = function loadFoodDatabase(event, callback) { boluscalc.loadFoodDatabase = function loadFoodDatabase (event, callback) {
categories = []; categories = [];
foodlist = []; foodlist = [];
var records = client.sbx.data.food || []; var records = client.sbx.data.food || [];
records.forEach(function (r) { records.forEach(function(r) {
if (r.type == 'food') { if (r.type == 'food') {
foodlist.push(r); foodlist.push(r);
if (r.category && !categories[r.category]) { if (r.category && !categories[r.category]) {
@@ -640,77 +639,77 @@ function init(client, $) {
if (callback) { callback(); } if (callback) { callback(); }
}; };
boluscalc.loadFoodQuickpicks = function loadFoodQuickpicks( ) { boluscalc.loadFoodQuickpicks = function loadFoodQuickpicks () {
// Load quickpicks // Load quickpicks
quickpicks = []; quickpicks = [];
var records = client.sbx.data.food || []; var records = client.sbx.data.food || [];
records.forEach(function (r) { records.forEach(function(r) {
if (r.type == 'quickpick') { if (r.type == 'quickpick') {
quickpicks.push(r); quickpicks.push(r);
} }
}); });
$('#bc_quickpick').empty().append('<option value="-1">' + translate('(none)') + '</option>'); $('#bc_quickpick').empty().append('<option value="-1">' + translate('(none)') + '</option>');
for (var i=0; i<records.length; i++) { for (var i = 0; i < records.length; i++) {
var r = records[i]; var r = records[i];
$('#bc_quickpick').append('<option value="' + i +'">' + r.name + ' (' + r.carbs + ' g)</option>'); $('#bc_quickpick').append('<option value="' + i + '">' + r.name + ' (' + r.carbs + ' g)</option>');
}; }
$('#bc_quickpick').val(-1); $('#bc_quickpick').val(-1);
$('#bc_quickpick').change(quickpickChange); $('#bc_quickpick').change(quickpickChange);
}; };
function fillForm(event) { function fillForm (event) {
$('#bc_filter_category').empty().append('<option value="">' + translate('(none)') + '</option>'); $('#bc_filter_category').empty().append('<option value="">' + translate('(none)') + '</option>');
Object.keys(categories).forEach( function eachCategory(s) { Object.keys(categories).forEach(function eachCategory (s) {
$('#bc_filter_category').append('<option value="' + s +'">' + s + '</option>'); $('#bc_filter_category').append('<option value="' + s + '">' + s + '</option>');
}); });
filter.category = ''; filter.category = '';
fillSubcategories(); fillSubcategories();
$('#bc_filter_category').change(fillSubcategories); $('#bc_filter_category').change(fillSubcategories);
$('#bc_filter_subcategory').change(doFilter); $('#bc_filter_subcategory').change(doFilter);
$('#bc_filter_name').on('input',doFilter); $('#bc_filter_name').on('input', doFilter);
maybePrevent(event); maybePrevent(event);
return false; return false;
} }
function fillSubcategories(event) { function fillSubcategories (event) {
maybePrevent(event); maybePrevent(event);
filter.category = $('#bc_filter_category').val(); filter.category = $('#bc_filter_category').val();
filter.subcategory = ''; filter.subcategory = '';
$('#bc_filter_subcategory').empty().append('<option value="">' + translate('(none)') + '</option>'); $('#bc_filter_subcategory').empty().append('<option value="">' + translate('(none)') + '</option>');
if (filter.category !== '') { if (filter.category !== '') {
Object.keys(categories[filter.category]).forEach( function eachSubcategory(s) { Object.keys(categories[filter.category]).forEach(function eachSubcategory (s) {
$('#bc_filter_subcategory').append('<option value="' + s +'">' + s + '</option>'); $('#bc_filter_subcategory').append('<option value="' + s + '">' + s + '</option>');
}); });
} }
doFilter(); doFilter();
} }
function doFilter(event) { function doFilter (event) {
if (event) { if (event) {
filter.category = $('#bc_filter_category').val(); filter.category = $('#bc_filter_category').val();
filter.subcategory = $('#bc_filter_subcategory').val(); filter.subcategory = $('#bc_filter_subcategory').val();
filter.name = $('#bc_filter_name').val(); filter.name = $('#bc_filter_name').val();
} }
$('#bc_data').empty(); $('#bc_data').empty();
for (var i=0; i<foodlist.length; i++) { for (var i = 0; i < foodlist.length; i++) {
if (filter.category !== '' && foodlist[i].category !== filter.category) { continue; } if (filter.category !== '' && foodlist[i].category !== filter.category) { continue; }
if (filter.subcategory !== '' && foodlist[i].subcategory !== filter.subcategory) { continue; } if (filter.subcategory !== '' && foodlist[i].subcategory !== filter.subcategory) { continue; }
if (filter.name!== '' && foodlist[i].name.toLowerCase().indexOf(filter.name.toLowerCase())<0) { continue; } if (filter.name !== '' && foodlist[i].name.toLowerCase().indexOf(filter.name.toLowerCase()) < 0) { continue; }
var o = ''; var o = '';
o += foodlist[i].name + ' | '; o += foodlist[i].name + ' | ';
o += 'Portion: ' + foodlist[i].portion + ' '; o += 'Portion: ' + foodlist[i].portion + ' ';
o += foodlist[i].unit + ' | '; o += foodlist[i].unit + ' | ';
o += 'Carbs: ' + foodlist[i].carbs+' g'; o += 'Carbs: ' + foodlist[i].carbs + ' g';
$('#bc_data').append('<option value="' + i +'">' + o + '</option>'); $('#bc_data').append('<option value="' + i + '">' + o + '</option>');
} }
$('#bc_addportions').val('1'); $('#bc_addportions').val('1');
maybePrevent(event); maybePrevent(event);
} }
function addFoodFromDatabase(event) { function addFoodFromDatabase (event) {
if (!databaseloaded) { if (!databaseloaded) {
boluscalc.loadFoodDatabase(event, addFoodFromDatabase); boluscalc.loadFoodDatabase(event, addFoodFromDatabase);
return; return;
@@ -718,30 +717,32 @@ function init(client, $) {
$('#bc_addportions').val('1'); $('#bc_addportions').val('1');
$('#bc_addfooddialog').dialog({ $('#bc_addfooddialog').dialog({
width: 640 width: 640
, height: 400 , height: 400
, buttons: [ , buttons: [
{ text: translate('Add'), {
click: function() { text: translate('Add')
var index = $('#bc_data').val(); , click: function() {
var portions = parseFloat($('#bc_addportions').val().replace(',','.')); var index = $('#bc_data').val();
if (index !== null && !isNaN(portions) && portions >0) { var portions = parseFloat($('#bc_addportions').val().replace(',', '.'));
foodlist[index].portions = portions; if (index !== null && !isNaN(portions) && portions > 0) {
foods.push(_.cloneDeep(foodlist[index])); foodlist[index].portions = portions;
$( this ).dialog( 'close' ); foods.push(_.cloneDeep(foodlist[index]));
boluscalc.calculateInsulin(); $(this).dialog('close');
boluscalc.calculateInsulin();
}
} }
} }
}, , {
{ text: translate('Reload database'), text: translate('Reload database')
class: 'leftButton', , class: 'leftButton'
click: boluscalc.loadFoodDatabase , click: boluscalc.loadFoodDatabase
} }
] ]
, open : function() { , open: function() {
$(this).parent().css('box-shadow', '20px 20px 20px 0px black'); $(this).parent().css('box-shadow', '20px 20px 20px 0px black');
$(this).parent().find('.ui-dialog-buttonset' ).css({'width':'100%','text-align':'right'}); $(this).parent().find('.ui-dialog-buttonset').css({ 'width': '100%', 'text-align': 'right' });
$(this).parent().find('button:contains("'+translate('Add')+'")').css({'float':'left'}); $(this).parent().find('button:contains("' + translate('Add') + '")').css({ 'float': 'left' });
$('#bc_filter_name').focus(); $('#bc_filter_name').focus();
} }
@@ -750,7 +751,7 @@ function init(client, $) {
return false; return false;
} }
function findClosestSGVToPastTime(time) { function findClosestSGVToPastTime (time) {
var nowData = client.entries.filter(function(d) { var nowData = client.entries.filter(function(d) {
return d.type === 'sgv' && d.mills <= time.getTime(); return d.type === 'sgv' && d.mills <= time.getTime();
}); });
@@ -766,12 +767,12 @@ function init(client, $) {
// Make it faster on mobile devices // Make it faster on mobile devices
$('.insulincalculationpart').change(boluscalc.calculateInsulin); $('.insulincalculationpart').change(boluscalc.calculateInsulin);
} else { } else {
$('.insulincalculationpart').on('input',boluscalc.calculateInsulin); $('.insulincalculationpart').on('input', boluscalc.calculateInsulin);
$('input:checkbox.insulincalculationpart').change(boluscalc.calculateInsulin); $('input:checkbox.insulincalculationpart').change(boluscalc.calculateInsulin);
} }
$('#bc_bgfrommeter').change(boluscalc.calculateInsulin); $('#bc_bgfrommeter').change(boluscalc.calculateInsulin);
$('#bc_addfromdatabase').click(addFoodFromDatabase); $('#bc_addfromdatabase').click(addFoodFromDatabase);
$('#bc_bgfromsensor').change(function bc_bgfromsensor_click(event) { $('#bc_bgfromsensor').change(function bc_bgfromsensor_click (event) {
boluscalc.updateVisualisations(client.sbx); boluscalc.updateVisualisations(client.sbx);
boluscalc.calculateInsulin(); boluscalc.calculateInsulin();
maybePrevent(event); maybePrevent(event);
+39 -42
View File
@@ -8,18 +8,18 @@ var Storages = require('js-storage');
function init (client, serverSettings, $) { function init (client, serverSettings, $) {
serverSettings = serverSettings || {settings: {}}; serverSettings = serverSettings || { settings: {} };
var storage = Storages.localStorage; var storage = Storages.localStorage;
var settings = require('../settings')(); var settings = require('../settings')();
function loadForm ( ) { function loadForm () {
var utils = client.utils; var utils = client.utils;
var language = require('../language')(); var language = require('../language')();
language.set(settings.language); language.set(settings.language);
var translate = language.translate; var translate = language.translate;
function appendThresholdValue(threshold) { function appendThresholdValue (threshold) {
return settings.alarmTypes.indexOf('simple') === -1 ? '' : ' (' + utils.scaleMgdl(threshold) + ')'; return settings.alarmTypes.indexOf('simple') === -1 ? '' : ' (' + utils.scaleMgdl(threshold) + ')';
} }
@@ -61,8 +61,8 @@ function init (client, serverSettings, $) {
var langSelect = $('#language'); var langSelect = $('#language');
_.each(language.languages, function eachLanguage(lang) { _.each(language.languages, function eachLanguage (lang) {
langSelect.append('<option value="' + lang.code+ '">' + lang.language + '</option>'); langSelect.append('<option value="' + lang.code + '">' + lang.language + '</option>');
}); });
langSelect.val(settings.language); langSelect.val(settings.language);
@@ -79,7 +79,7 @@ function init (client, serverSettings, $) {
var showPluginsSettings = $('#show-plugins'); var showPluginsSettings = $('#show-plugins');
var hasPluginsToShow = false; var hasPluginsToShow = false;
client.plugins.eachEnabledPlugin(function each(plugin) { client.plugins.eachEnabledPlugin(function each (plugin) {
if (client.plugins.specialPlugins.indexOf(plugin.name) > -1) { if (client.plugins.specialPlugins.indexOf(plugin.name) > -1) {
//ignore these, they are always on for now //ignore these, they are always on for now
} else { } else {
@@ -97,7 +97,7 @@ function init (client, serverSettings, $) {
} }
function wireForm ( ) { function wireForm () {
$('#useDefaults').click(function(event) { $('#useDefaults').click(function(event) {
settings.eachSetting(function clearEachSetting (name) { settings.eachSetting(function clearEachSetting (name) {
storage.remove(name); storage.remove(name);
@@ -108,43 +108,41 @@ function init (client, serverSettings, $) {
}); });
$('#save').click(function(event) { $('#save').click(function(event) {
function checkedPluginNames() { function checkedPluginNames () {
var checkedPlugins = []; var checkedPlugins = [];
$('#show-plugins input:checked').each(function eachPluginCheckbox(index, checkbox) { $('#show-plugins input:checked').each(function eachPluginCheckbox (index, checkbox) {
checkedPlugins.push($(checkbox).val()); checkedPlugins.push($(checkbox).val());
}); });
return checkedPlugins.join(' '); return checkedPlugins.join(' ');
} }
function storeInBrowser(data) { function storeInBrowser (data) {
for (var k in data) { Object.keys(data).forEach(k => {
if (data.hasOwnProperty(k)) { storage.set(k, data[k]);
storage.set(k, data[k]); });
}
}
} }
storeInBrowser({ storeInBrowser({
units: $('input:radio[name=units-browser]:checked').val(), units: $('input:radio[name=units-browser]:checked').val()
alarmUrgentHigh: $('#alarm-urgenthigh-browser').prop('checked'), , alarmUrgentHigh: $('#alarm-urgenthigh-browser').prop('checked')
alarmHigh: $('#alarm-high-browser').prop('checked'), , alarmHigh: $('#alarm-high-browser').prop('checked')
alarmLow: $('#alarm-low-browser').prop('checked'), , alarmLow: $('#alarm-low-browser').prop('checked')
alarmUrgentLow: $('#alarm-urgentlow-browser').prop('checked'), , alarmUrgentLow: $('#alarm-urgentlow-browser').prop('checked')
alarmTimeagoWarn: $('#alarm-timeagowarn-browser').prop('checked'), , alarmTimeagoWarn: $('#alarm-timeagowarn-browser').prop('checked')
alarmTimeagoWarnMins: parseInt($('#alarm-timeagowarnmins-browser').val()) || 15, , alarmTimeagoWarnMins: parseInt($('#alarm-timeagowarnmins-browser').val()) || 15
alarmTimeagoUrgent: $('#alarm-timeagourgent-browser').prop('checked'), , alarmTimeagoUrgent: $('#alarm-timeagourgent-browser').prop('checked')
alarmTimeagoUrgentMins: parseInt($('#alarm-timeagourgentmins-browser').val()) || 30, , alarmTimeagoUrgentMins: parseInt($('#alarm-timeagourgentmins-browser').val()) || 30
nightMode: $('#nightmode-browser').prop('checked'), , nightMode: $('#nightmode-browser').prop('checked')
editMode: $('#editmode-browser').prop('checked'), , editMode: $('#editmode-browser').prop('checked')
showRawbg: $('input:radio[name=show-rawbg]:checked').val(), , showRawbg: $('input:radio[name=show-rawbg]:checked').val()
customTitle: $('input#customTitle').prop('value'), , customTitle: $('input#customTitle').prop('value')
theme: $('input:radio[name=theme-browser]:checked').val(), , theme: $('input:radio[name=theme-browser]:checked').val()
timeFormat: parseInt($('input:radio[name=timeformat-browser]:checked').val()), , timeFormat: parseInt($('input:radio[name=timeformat-browser]:checked').val())
language: $('#language').val(), , language: $('#language').val()
scaleY: $('#scaleY').val(), , scaleY: $('#scaleY').val()
basalrender: $('#basalrender').val(), , basalrender: $('#basalrender').val()
showPlugins: checkedPluginNames(), , showPlugins: checkedPluginNames()
storageVersion: STORAGE_VERSION , storageVersion: STORAGE_VERSION
}); });
event.preventDefault(); event.preventDefault();
@@ -152,13 +150,13 @@ function init (client, serverSettings, $) {
}); });
} }
function showLocalstorageError ( ) { function showLocalstorageError () {
var msg = '<b>Settings are disabled.</b><br /><br />Please enable cookies so you may customize your Nightscout site.'; var msg = '<b>Settings are disabled.</b><br /><br />Please enable cookies so you may customize your Nightscout site.';
$('.browserSettings').html('<legend>Settings</legend>'+msg+''); $('.browserSettings').html('<legend>Settings</legend>' + msg + '');
$('#save').hide(); $('#save').hide();
} }
function handleStorageVersions ( ) { function handleStorageVersions () {
var previousVersion = parseInt(storage.get('storageVersion')); var previousVersion = parseInt(storage.get('storageVersion'));
//un-versioned settings //un-versioned settings
@@ -174,7 +172,7 @@ function init (client, serverSettings, $) {
} }
} }
settings.extendedSettings = serverSettings.extendedSettings || {settings: {}}; settings.extendedSettings = serverSettings.extendedSettings || { settings: {} };
try { try {
settings.eachSetting(function setEach (name) { settings.eachSetting(function setEach (name) {
@@ -200,12 +198,12 @@ function init (client, serverSettings, $) {
var stored = storage.get('basalrender'); var stored = storage.get('basalrender');
settings.extendedSettings.basal.render = stored !== null ? stored : settings.extendedSettings.basal.render; settings.extendedSettings.basal.render = stored !== null ? stored : settings.extendedSettings.basal.render;
} catch(err) { } catch (err) {
console.error(err); console.error(err);
showLocalstorageError(); showLocalstorageError();
} }
init.loadAndWireForm = function loadAndWireForm ( ) { init.loadAndWireForm = function loadAndWireForm () {
loadForm(); loadForm();
wireForm(); wireForm();
}; };
@@ -213,5 +211,4 @@ function init (client, serverSettings, $) {
return settings; return settings;
} }
module.exports = init; module.exports = init;
+20 -22
View File
@@ -13,9 +13,9 @@ function init ($) {
$('#drawer').find('.tip').tooltip(); $('#drawer').find('.tip').tooltip();
} }
$.fn.tooltip.defaults = { $.fn.tooltip.defaults = {
fade: true, fade: true
gravity: 'n', , gravity: 'n'
opacity: 0.75 , opacity: 0.75
}; };
var querystring = queryParms(); var querystring = queryParms();
@@ -38,31 +38,30 @@ function init ($) {
event.preventDefault(); event.preventDefault();
}); });
$('.navigation a').click(function navigationClick ( ) { $('.navigation a').click(function navigationClick () {
closeDrawer('#drawer'); closeDrawer('#drawer');
}); });
function reload() { function reload () {
//strip '#' so form submission does not fail //strip '#' so form submission does not fail
var url = window.location.href; var url = window.location.href;
url = url.replace(/#$/, ''); url = url.replace(/#$/, '');
window.location.href = url; window.location.href = url;
} }
function queryParms () {
function queryParms() {
var params = {}; var params = {};
if (location.search) { if (location.search) {
location.search.substr(1).split('&').forEach(function(item) { location.search.substr(1).split('&').forEach(function(item) {
// eslint-disable-next-line no-useless-escape
params[item.split('=')[0]] = item.split('=')[1].replace(/[_\+]/g, ' '); params[item.split('=')[0]] = item.split('=')[1].replace(/[_\+]/g, ' ');
}); });
} }
return params; return params;
} }
function isTouch() { function isTouch () {
try { document.createEvent('TouchEvent'); return true; } try { document.createEvent('TouchEvent'); return true; } catch (e) { return false; }
catch (e) { return false; }
} }
function closeLastOpenedDrawer (callback) { function closeLastOpenedDrawer (callback) {
@@ -73,15 +72,15 @@ function init ($) {
} }
} }
function closeDrawer(id, callback) { function closeDrawer (id, callback) {
lastOpenedDrawer = null; lastOpenedDrawer = null;
$('html, body').css({ scrollTop: 0 }); $('html, body').css({ scrollTop: 0 });
$(id).css({display: 'none', right: '-300px'}); $(id).css({ display: 'none', right: '-300px' });
if (callback) { callback(); } if (callback) { callback(); }
} }
function openDrawer(id, prepare) { function openDrawer (id, prepare) {
function closeOpenDraw(callback) { function closeOpenDraw (callback) {
if (lastOpenedDrawer) { if (lastOpenedDrawer) {
closeDrawer(lastOpenedDrawer, callback); closeDrawer(lastOpenedDrawer, callback);
} else { } else {
@@ -89,11 +88,11 @@ function init ($) {
} }
} }
closeOpenDraw(function () { closeOpenDraw(function() {
lastOpenedDrawer = id; lastOpenedDrawer = id;
if (prepare) { prepare(); } if (prepare) { prepare(); }
var style = {display:'block', right: '0'}; var style = { display: 'block', right: '0' };
var windowWidth = $(window).width(); var windowWidth = $(window).width();
var windowHeight = $(window).height(); var windowHeight = $(window).height();
@@ -114,13 +113,12 @@ function init ($) {
style.width = '350px'; style.width = '350px';
} }
$(id).css(style); $(id).css(style);
}); });
} }
function toggleDrawer(id, openPrepare, closeCallback) { function toggleDrawer (id, openPrepare, closeCallback) {
if (lastOpenedDrawer === id) { if (lastOpenedDrawer === id) {
closeDrawer(id, closeCallback); closeDrawer(id, closeCallback);
} else { } else {
@@ -128,13 +126,13 @@ function init ($) {
} }
} }
function closeNotification() { function closeNotification () {
var notify = $('#notification'); var notify = $('#notification');
notify.hide(); notify.hide();
notify.find('span').html(''); notify.find('span').html('');
} }
function showNotification(note, type) { function showNotification (note, type) {
var notify = $('#notification'); var notify = $('#notification');
notify.hide(); notify.hide();
@@ -150,10 +148,10 @@ function init ($) {
notify.show(); notify.show();
} }
function getLastOpenedDrawer() { function getLastOpenedDrawer () {
return lastOpenedDrawer; return lastOpenedDrawer;
} }
return { return {
reload: reload reload: reload
, queryParms: queryParms , queryParms: queryParms
+10 -8
View File
@@ -9,14 +9,14 @@ client.settings = browserSettings(client, window.serverSettings, $);
// console.log('settings', client.settings); // console.log('settings', client.settings);
// client.settings now contains all settings // client.settings now contains all settings
client.query = function query() { client.query = function query () {
console.log('query'); console.log('query');
$.ajax('/api/v1/entries.json?count=3', { $.ajax('/api/v1/entries.json?count=3', {
success: client.render success: client.render
}); });
} }
client.render = function render(xhr) { client.render = function render (xhr) {
console.log('got data', xhr); console.log('got data', xhr);
let rec; let rec;
@@ -33,9 +33,9 @@ client.render = function render(xhr) {
// Convert BG to mmol/L if necessary. // Convert BG to mmol/L if necessary.
if (window.serverSettings.settings.units == 'mmol') { if (window.serverSettings.settings.units == 'mmol') {
var displayValue = Nightscout.units.mgdlToMMOL(rec.sgv); var displayValue = window.Nightscout.units.mgdlToMMOL(rec.sgv);
} else { } else {
var displayValue = rec.sgv; displayValue = rec.sgv;
} }
// Insert the BG value text. // Insert the BG value text.
@@ -53,8 +53,8 @@ client.render = function render(xhr) {
// Generate and insert the clock. // Generate and insert the clock.
let timeDivisor = (client.settings.timeFormat) ? client.settings.timeFormat : 12; let timeDivisor = (client.settings.timeFormat) ? client.settings.timeFormat : 12;
let today = new Date(), let today = new Date()
h = today.getHours() % timeDivisor; , h = today.getHours() % timeDivisor;
if (timeDivisor == 12) { if (timeDivisor == 12) {
h = (h == 0) ? 12 : h; // In the case of 00:xx, change to 12:xx for 12h time h = (h == 0) ? 12 : h; // In the case of 00:xx, change to 12:xx for 12h time
} }
@@ -65,6 +65,8 @@ client.render = function render(xhr) {
if (m < 10) m = "0" + m; if (m < 10) m = "0" + m;
$('#clock').text(h + ":" + m); $('#clock').text(h + ":" + m);
// defined in the template this is loaded into
// eslint-disable-next-line no-undef
if (clockFace == 'clock-color') { if (clockFace == 'clock-color') {
var bgHigh = window.serverSettings.settings.thresholds.bgHigh; var bgHigh = window.serverSettings.settings.thresholds.bgHigh;
@@ -115,10 +117,10 @@ client.render = function render(xhr) {
} }
} }
client.init = function init() { client.init = function init () {
console.log('init'); console.log('init');
client.query(); client.query();
setInterval(client.query, 1 * 60 * 1000); setInterval(client.query, 1 * 60 * 1000);
} }
module.exports = client; module.exports = client;
+107 -112
View File
@@ -16,13 +16,13 @@ var levels = require('../levels');
var times = require('../times'); var times = require('../times');
var receiveDData = require('./receiveddata'); var receiveDData = require('./receiveddata');
var client = { }; var client = {};
$('#loadingMessageText').html('Connecting to server'); $('#loadingMessageText').html('Connecting to server');
client.hashauth = require('../hashauth').init(client, $); client.hashauth = require('../hashauth').init(client, $);
client.headers = function headers ( ) { client.headers = function headers () {
if (client.authorized) { if (client.authorized) {
return { return {
Authorization: 'Bearer ' + client.authorized.token Authorization: 'Bearer ' + client.authorized.token
@@ -32,11 +32,11 @@ client.headers = function headers ( ) {
'api-secret': client.hashauth.hash() 'api-secret': client.hashauth.hash()
}; };
} else { } else {
return { }; return {};
} }
}; };
client.init = function init(callback) { client.init = function init (callback) {
client.browserUtils = require('./browser-utils')($); client.browserUtils = require('./browser-utils')($);
@@ -60,16 +60,17 @@ client.init = function init(callback) {
console.log('Application appears to be online'); console.log('Application appears to be online');
$('#centerMessagePanel').hide(); $('#centerMessagePanel').hide();
client.load(serverSettings, callback); client.load(serverSettings, callback);
}).fail(function fail(jqXHR, textStatus, errorThrown) { // eslint-disable-next-line no-unused-vars
}).fail(function fail (jqXHR, textStatus, errorThrown) {
// check if we couldn't reach the server at all, show offline message // check if we couldn't reach the server at all, show offline message
if (jqXHR.readyState == 0) { if (jqXHR.readyState == 0) {
console.log('Application appears to be OFFLINE'); console.log('Application appears to be OFFLINE');
$('#loadingMessageText').html('Connecting to Nightscout server failed, retrying every 2 seconds'); $('#loadingMessageText').html('Connecting to Nightscout server failed, retrying every 2 seconds');
window.setTimeout(window.Nightscout.client.init(), 2000); window.setTimeout(window.Nightscout.client.init(), 2000);
return; return;
} }
//no server setting available, use defaults, auth, etc //no server setting available, use defaults, auth, etc
if (client.settingsFailed) { if (client.settingsFailed) {
console.log('Already tried to get settings after auth, but failed'); console.log('Already tried to get settings after auth, but failed');
@@ -77,9 +78,9 @@ client.init = function init(callback) {
client.settingsFailed = true; client.settingsFailed = true;
language.set('en'); language.set('en');
client.translate = language.translate; client.translate = language.translate;
// auth failed, hide loader and request for key // auth failed, hide loader and request for key
$('#centerMessagePanel').hide(); $('#centerMessagePanel').hide();
client.hashauth.requestAuthentication(function afterRequest ( ) { client.hashauth.requestAuthentication(function afterRequest () {
client.init(null, callback); client.init(null, callback);
}); });
} }
@@ -87,23 +88,21 @@ client.init = function init(callback) {
}; };
client.load = function load(serverSettings, callback) { client.load = function load (serverSettings, callback) {
var UPDATE_TRANS_MS = 750 // milliseconds var UPDATE_TRANS_MS = 750 // milliseconds
, FORMAT_TIME_12 = '%-I:%M %p' , FORMAT_TIME_12 = '%-I:%M %p'
, FORMAT_TIME_12_COMPACT = '%-I:%M' , FORMAT_TIME_12_COMPACT = '%-I:%M'
, FORMAT_TIME_24 = '%H:%M%' , FORMAT_TIME_24 = '%H:%M%'
, FORMAT_TIME_12_SCALE = '%-I %p' , FORMAT_TIME_12_SCALE = '%-I %p'
, FORMAT_TIME_24_SCALE = '%H' , FORMAT_TIME_24_SCALE = '%H';
;
var history = 48; var history = 48;
var chart var chart
, socket , socket
, isInitialData = false , isInitialData = false
, prevSGV , opacity = { current: 1, DAY: 1, NIGHT: 0.5 }
, opacity = {current: 1, DAY: 1, NIGHT: 0.5}
, clientAlarms = {} , clientAlarms = {}
, alarmInProgress = false , alarmInProgress = false
, alarmMessage , alarmMessage
@@ -111,8 +110,7 @@ client.load = function load(serverSettings, callback) {
, currentAnnouncement , currentAnnouncement
, alarmSound = 'alarm.mp3' , alarmSound = 'alarm.mp3'
, urgentAlarmSound = 'alarm2.mp3' , urgentAlarmSound = 'alarm2.mp3'
, previousNotifyTimestamp , previousNotifyTimestamp;
;
client.entryToDate = function entryToDate (entry) { return new Date(entry.mills); }; client.entryToDate = function entryToDate (entry) { return new Date(entry.mills); };
@@ -130,8 +128,7 @@ client.load = function load(serverSettings, callback) {
, minorPills = $('.bgStatus .minorPills') , minorPills = $('.bgStatus .minorPills')
, statusPills = $('.status .statusPills') , statusPills = $('.status .statusPills')
, primary = $('.primary') , primary = $('.primary')
, editButton = $('#editbutton') , editButton = $('#editbutton');
;
client.tooltip = d3.select('body').append('div') client.tooltip = d3.select('body').append('div')
.attr('class', 'tooltip') .attr('class', 'tooltip')
@@ -236,7 +233,7 @@ client.load = function load(serverSettings, callback) {
client.boluscalc = require('./boluscalc')(client, $); client.boluscalc = require('./boluscalc')(client, $);
client.profilefunctions = profile; client.profilefunctions = profile;
client.editMode = false; client.editMode = false;
//TODO: use the bus for updates and notifications //TODO: use the bus for updates and notifications
@@ -248,13 +245,13 @@ client.load = function load(serverSettings, callback) {
//start the bus after setting up listeners //start the bus after setting up listeners
//client.ctx.bus.uptime( ); //client.ctx.bus.uptime( );
client.dataExtent = function dataExtent ( ) { client.dataExtent = function dataExtent () {
return client.entries.length > 0 ? return client.entries.length > 0 ?
d3.extent(client.entries, client.entryToDate) d3.extent(client.entries, client.entryToDate) :
: d3.extent([new Date(client.now - times.hours(history).msecs), new Date(client.now)]); d3.extent([new Date(client.now - times.hours(history).msecs), new Date(client.now)]);
}; };
client.bottomOfPills = function bottomOfPills ( ) { client.bottomOfPills = function bottomOfPills () {
//the offset's might not exist for some tests //the offset's might not exist for some tests
var bottomOfPrimary = primary.offset() ? primary.offset().top + primary.height() : 0; var bottomOfPrimary = primary.offset() ? primary.offset().top + primary.height() : 0;
var bottomOfMinorPills = minorPills.offset() ? minorPills.offset().top + minorPills.height() : 0; var bottomOfMinorPills = minorPills.offset() ? minorPills.offset().top + minorPills.height() : 0;
@@ -262,7 +259,7 @@ client.load = function load(serverSettings, callback) {
return Math.max(bottomOfPrimary, bottomOfMinorPills, bottomOfStatusPills); return Math.max(bottomOfPrimary, bottomOfMinorPills, bottomOfStatusPills);
}; };
function formatTime(time, compact) { function formatTime (time, compact) {
var timeFormat = getTimeFormat(false, compact); var timeFormat = getTimeFormat(false, compact);
time = d3.time.format(timeFormat)(time); time = d3.time.format(timeFormat)(time);
if (client.settings.timeFormat !== 24) { if (client.settings.timeFormat !== 24) {
@@ -271,7 +268,7 @@ client.load = function load(serverSettings, callback) {
return time; return time;
} }
function getTimeFormat(isForScale, compact) { function getTimeFormat (isForScale, compact) {
var timeFormat = FORMAT_TIME_12; var timeFormat = FORMAT_TIME_12;
if (client.settings.timeFormat === 24) { if (client.settings.timeFormat === 24) {
timeFormat = isForScale ? FORMAT_TIME_24_SCALE : FORMAT_TIME_24; timeFormat = isForScale ? FORMAT_TIME_24_SCALE : FORMAT_TIME_24;
@@ -283,7 +280,7 @@ client.load = function load(serverSettings, callback) {
} }
//TODO: replace with utils.scaleMgdl and/or utils.roundBGForDisplay //TODO: replace with utils.scaleMgdl and/or utils.roundBGForDisplay
function scaleBg(bg) { function scaleBg (bg) {
if (client.settings.units === 'mmol') { if (client.settings.units === 'mmol') {
return units.mgdlToMMOL(bg); return units.mgdlToMMOL(bg);
} else { } else {
@@ -291,8 +288,8 @@ client.load = function load(serverSettings, callback) {
} }
} }
function generateTitle ( ) { function generateTitle () {
function s(value, sep) { return value ? value + ' ' : sep || ''; } function s (value, sep) { return value ? value + ' ' : sep || ''; }
var title = ''; var title = '';
@@ -300,7 +297,7 @@ client.load = function load(serverSettings, callback) {
if (status !== 'current') { if (status !== 'current') {
var ago = client.timeago.calcDisplay(client.sbx.lastSGVEntry(), client.sbx.time); var ago = client.timeago.calcDisplay(client.sbx.lastSGVEntry(), client.sbx.time);
title = s(ago.value) + s(ago.label, ' - ') + title; title = s(ago.value) + s(ago.label, ' - ') + title;
} else if (client.latestSGV) { } else if (client.latestSGV) {
var currentMgdl = client.latestSGV.mgdl; var currentMgdl = client.latestSGV.mgdl;
@@ -317,12 +314,12 @@ client.load = function load(serverSettings, callback) {
return title; return title;
} }
function resetCustomTitle ( ) { function resetCustomTitle () {
var customTitle = client.settings.customTitle || 'Nightscout'; var customTitle = client.settings.customTitle || 'Nightscout';
$('.customTitle').text(customTitle); $('.customTitle').text(customTitle);
} }
function checkAnnouncement() { function checkAnnouncement () {
var result = { var result = {
inProgress: currentAnnouncement ? Date.now() - currentAnnouncement.received < times.mins(5).msecs : false inProgress: currentAnnouncement ? Date.now() - currentAnnouncement.received < times.mins(5).msecs : false
}; };
@@ -339,19 +336,19 @@ client.load = function load(serverSettings, callback) {
return result; return result;
} }
function updateTitle ( ) { function updateTitle () {
var windowTitle; var windowTitle;
var announcementStatus = checkAnnouncement(); var announcementStatus = checkAnnouncement();
if (alarmMessage && alarmInProgress) { if (alarmMessage && alarmInProgress) {
$('.customTitle').text(alarmMessage); $('.customTitle').text(alarmMessage);
if (!isTimeAgoAlarmType( )) { if (!isTimeAgoAlarmType()) {
windowTitle = alarmMessage + ': ' + generateTitle(); windowTitle = alarmMessage + ': ' + generateTitle();
} }
} else if (announcementStatus.inProgress && announcementStatus.message) { } else if (announcementStatus.inProgress && announcementStatus.message) {
windowTitle = announcementStatus.message + ': ' + generateTitle(); windowTitle = announcementStatus.message + ': ' + generateTitle();
} else { } else {
resetCustomTitle(); resetCustomTitle();
} }
@@ -360,8 +357,8 @@ client.load = function load(serverSettings, callback) {
$(document).attr('title', windowTitle || generateTitle()); $(document).attr('title', windowTitle || generateTitle());
} }
// clears the current user brush and resets to the current real time data // clears the current user brush and resets to the current real time data
function updateBrushToNow(skipBrushing) { function updateBrushToNow (skipBrushing) {
// get current time range // get current time range
var dataRange = client.dataExtent(); var dataRange = client.dataExtent();
@@ -377,15 +374,15 @@ client.load = function load(serverSettings, callback) {
} }
} }
function alarmingNow() { function alarmingNow () {
return container.hasClass('alarming'); return container.hasClass('alarming');
} }
function inRetroMode() { function inRetroMode () {
return chart && chart.inRetroMode(); return chart && chart.inRetroMode();
} }
function brushed ( ) { function brushed () {
var brushExtent = chart.brush.extent(); var brushExtent = chart.brush.extent();
@@ -403,7 +400,7 @@ client.load = function load(serverSettings, callback) {
} }
} }
function adjustCurrentSGVClasses(value, isCurrent) { function adjustCurrentSGVClasses (value, isCurrent) {
var reallyCurrentAndNotAlarming = isCurrent && !inRetroMode() && !alarmingNow(); var reallyCurrentAndNotAlarming = isCurrent && !inRetroMode() && !alarmingNow();
bgStatus.toggleClass('current', alarmingNow() || reallyCurrentAndNotAlarming); bgStatus.toggleClass('current', alarmingNow() || reallyCurrentAndNotAlarming);
@@ -469,7 +466,7 @@ client.load = function load(serverSettings, callback) {
forecastOption.append(forecastLabel); forecastOption.append(forecastLabel);
forecastLabel.append(forecastCheckbox); forecastLabel.append(forecastCheckbox);
forecastLabel.append('<span>Show ' + info.label + '</span>'); forecastLabel.append('<span>Show ' + info.label + '</span>');
forecastCheckbox.change(function onChange(event) { forecastCheckbox.change(function onChange (event) {
var checkbox = $(event.target); var checkbox = $(event.target);
var type = checkbox.attr('data-forecast-type'); var type = checkbox.attr('data-forecast-type');
var checked = checkbox.prop('checked'); var checked = checkbox.prop('checked');
@@ -477,7 +474,7 @@ client.load = function load(serverSettings, callback) {
client.settings.showForecast += ' ' + type; client.settings.showForecast += ' ' + type;
} else { } else {
client.settings.showForecast = _.chain(client.settings.showForecast.split(' ')) client.settings.showForecast = _.chain(client.settings.showForecast.split(' '))
.filter(function (forecast) { return forecast !== type; }) .filter(function(forecast) { return forecast !== type; })
.value() .value()
.join(' '); .join(' ');
} }
@@ -491,7 +488,7 @@ client.load = function load(serverSettings, callback) {
client.boluscalc.updateVisualisations(client.sbx); client.boluscalc.updateVisualisations(client.sbx);
} }
function clearCurrentSGV ( ) { function clearCurrentSGV () {
currentBG.text('---'); currentBG.text('---');
container.removeClass('urgent warning inrange'); container.removeClass('urgent warning inrange');
} }
@@ -502,7 +499,7 @@ client.load = function load(serverSettings, callback) {
}); });
var focusPoint = _.last(nowData); var focusPoint = _.last(nowData);
function updateHeader() { function updateHeader () {
if (inRetroMode()) { if (inRetroMode()) {
nowDate = brushExtent[1]; nowDate = brushExtent[1];
$('#currentTime') $('#currentTime')
@@ -533,10 +530,10 @@ client.load = function load(serverSettings, callback) {
} }
var top = (client.bottomOfPills() + 5); var top = (client.bottomOfPills() + 5);
$('#chartContainer').css({top: top + 'px', height: $(window).height() - top - 10}); $('#chartContainer').css({ top: top + 'px', height: $(window).height() - top - 10 });
} }
function sgvToColor(sgv) { function sgvToColor (sgv) {
var color = 'grey'; var color = 'grey';
if (client.settings.theme !== 'default') { if (client.settings.theme !== 'default') {
@@ -556,7 +553,7 @@ client.load = function load(serverSettings, callback) {
return color; return color;
} }
function sgvToColoredRange(sgv) { function sgvToColoredRange (sgv) {
var range = ''; var range = '';
if (client.settings.theme !== 'default') { if (client.settings.theme !== 'default') {
@@ -576,7 +573,7 @@ client.load = function load(serverSettings, callback) {
return range; return range;
} }
function formatAlarmMessage(notify) { function formatAlarmMessage (notify) {
var announcementMessage = notify && notify.isAnnouncement && notify.message && notify.message.length > 1; var announcementMessage = notify && notify.isAnnouncement && notify.message && notify.message.length > 1;
if (announcementMessage) { if (announcementMessage) {
@@ -584,7 +581,7 @@ client.load = function load(serverSettings, callback) {
} else if (notify) { } else if (notify) {
return notify.title; return notify.title;
} }
return null; return null;
} }
function setAlarmMessage (notify) { function setAlarmMessage (notify) {
@@ -599,7 +596,7 @@ client.load = function load(serverSettings, callback) {
var selector = '.audio.alarms audio.' + file; var selector = '.audio.alarms audio.' + file;
if (!alarmingNow()) { if (!alarmingNow()) {
d3.select(selector).each(function () { d3.select(selector).each(function() {
var audio = this; var audio = this;
playAlarm(audio); playAlarm(audio);
$(this).addClass('playing'); $(this).addClass('playing');
@@ -628,7 +625,7 @@ client.load = function load(serverSettings, callback) {
event.preventDefault(); event.preventDefault();
} }
function playAlarm(audio) { function playAlarm (audio) {
// ?mute=true disables alarms to testers. // ?mute=true disables alarms to testers.
if (client.browserUtils.queryParms().mute !== 'true') { if (client.browserUtils.queryParms().mute !== 'true') {
audio.play(); audio.play();
@@ -637,11 +634,11 @@ client.load = function load(serverSettings, callback) {
} }
} }
function stopAlarm(isClient, silenceTime, notify) { function stopAlarm (isClient, silenceTime, notify) {
alarmInProgress = false; alarmInProgress = false;
alarmMessage = null; alarmMessage = null;
container.removeClass('urgent warning'); container.removeClass('urgent warning');
d3.selectAll('audio.playing').each(function () { d3.selectAll('audio.playing').each(function() {
var audio = this; var audio = this;
audio.pause(); audio.pause();
$(this).removeClass('playing'); $(this).removeClass('playing');
@@ -688,7 +685,7 @@ client.load = function load(serverSettings, callback) {
brushed(); brushed();
} }
function refreshAuthIfNeeded ( ) { function refreshAuthIfNeeded () {
var token = client.browserUtils.queryParms().token; var token = client.browserUtils.queryParms().token;
if (token && client.authorized) { if (token && client.authorized) {
var renewTime = (client.authorized.exp * 1000) - times.mins(15).msecs - Math.abs((client.authorized.iat * 1000) - client.authorized.lat); var renewTime = (client.authorized.exp * 1000) - times.mins(15).msecs - Math.abs((client.authorized.iat * 1000) - client.authorized.lat);
@@ -696,7 +693,7 @@ client.load = function load(serverSettings, callback) {
if (client.now > renewTime) { if (client.now > renewTime) {
console.info('Refreshing authorization'); console.info('Refreshing authorization');
$.ajax('/api/v2/authorization/request/' + token, { $.ajax('/api/v2/authorization/request/' + token, {
success: function (authorized) { success: function(authorized) {
if (authorized) { if (authorized) {
console.info('Got new authorization', authorized); console.info('Got new authorization', authorized);
authorized.lat = client.now; authorized.lat = client.now;
@@ -710,10 +707,10 @@ client.load = function load(serverSettings, callback) {
} }
} }
function updateClock() { function updateClock () {
updateClockDisplay(); updateClockDisplay();
var interval = (60 - (new Date()).getSeconds()) * 1000 + 5; var interval = (60 - (new Date()).getSeconds()) * 1000 + 5;
setTimeout(updateClock,interval); setTimeout(updateClock, interval);
updateTimeAgo(); updateTimeAgo();
if (chart) { if (chart) {
@@ -735,7 +732,7 @@ client.load = function load(serverSettings, callback) {
} }
} }
function updateClockDisplay() { function updateClockDisplay () {
if (inRetroMode()) { if (inRetroMode()) {
return; return;
} }
@@ -743,7 +740,7 @@ client.load = function load(serverSettings, callback) {
$('#currentTime').text(formatTime(new Date(client.now), true)).css('text-decoration', ''); $('#currentTime').text(formatTime(new Date(client.now), true)).css('text-decoration', '');
} }
function getClientAlarm(level, group) { function getClientAlarm (level, group) {
var key = level + '-' + group; var key = level + '-' + group;
var alarm = clientAlarms[key]; var alarm = clientAlarms[key];
if (!alarm) { if (!alarm) {
@@ -753,13 +750,13 @@ client.load = function load(serverSettings, callback) {
return alarm; return alarm;
} }
function isTimeAgoAlarmType() { function isTimeAgoAlarmType () {
return currentNotify && currentNotify.group === 'Time Ago'; return currentNotify && currentNotify.group === 'Time Ago';
} }
function isStale (status) { function isStale (status) {
return client.settings.alarmTimeagoWarn && status === 'warn' return client.settings.alarmTimeagoWarn && status === 'warn' ||
|| client.settings.alarmTimeagoUrgent && status === 'urgent'; client.settings.alarmTimeagoUrgent && status === 'urgent';
} }
function notAcked (alarm) { function notAcked (alarm) {
@@ -786,12 +783,12 @@ client.load = function load(serverSettings, callback) {
container.toggleClass('alarming-timeago', status !== 'current'); container.toggleClass('alarming-timeago', status !== 'current');
if (alarmingNow() && status === 'current' && isTimeAgoAlarmType( )) { if (alarmingNow() && status === 'current' && isTimeAgoAlarmType()) {
stopAlarm(true, times.min().msecs); stopAlarm(true, times.min().msecs);
} }
} }
function updateTimeAgo() { function updateTimeAgo () {
var status = client.timeago.checkStatus(client.sbx); var status = client.timeago.checkStatus(client.sbx);
if (status !== 'current') { if (status !== 'current') {
updateTitle(); updateTitle();
@@ -799,20 +796,20 @@ client.load = function load(serverSettings, callback) {
checkTimeAgoAlarm(status); checkTimeAgoAlarm(status);
} }
function updateTimeAgoSoon() { function updateTimeAgoSoon () {
setTimeout(function updatingTimeAgoNow() { setTimeout(function updatingTimeAgoNow () {
updateTimeAgo(); updateTimeAgo();
}, times.secs(10).msecs); }, times.secs(10).msecs);
} }
function refreshChart(updateToNow) { function refreshChart (updateToNow) {
if (updateToNow) { if (updateToNow) {
updateBrushToNow(); updateBrushToNow();
} }
chart.update(false); chart.update(false);
} }
(function watchVisibility ( ) { (function watchVisibility () {
// Set the name of the hidden property and the change event for visibility // Set the name of the hidden property and the change event for visibility
var hidden, visibilityChange; var hidden, visibilityChange;
if (typeof document.hidden !== 'undefined') { if (typeof document.hidden !== 'undefined') {
@@ -829,7 +826,7 @@ client.load = function load(serverSettings, callback) {
visibilityChange = 'webkitvisibilitychange'; visibilityChange = 'webkitvisibilitychange';
} }
document.addEventListener(visibilityChange, function visibilityChanged ( ) { document.addEventListener(visibilityChange, function visibilityChanged () {
var prevHidden = client.documentHidden; var prevHidden = client.documentHidden;
client.documentHidden = document[hidden]; client.documentHidden = document[hidden];
@@ -845,7 +842,7 @@ client.load = function load(serverSettings, callback) {
updateClock(); updateClock();
updateTimeAgoSoon(); updateTimeAgoSoon();
function Dropdown(el) { function Dropdown (el) {
this.ddmenuitem = 0; this.ddmenuitem = 0;
this.$el = $(el); this.$el = $(el);
@@ -853,13 +850,13 @@ client.load = function load(serverSettings, callback) {
$(document).click(function() { that.close(); }); $(document).click(function() { that.close(); });
} }
Dropdown.prototype.close = function () { Dropdown.prototype.close = function() {
if (this.ddmenuitem) { if (this.ddmenuitem) {
this.ddmenuitem.css('visibility', 'hidden'); this.ddmenuitem.css('visibility', 'hidden');
this.ddmenuitem = 0; this.ddmenuitem = 0;
} }
}; };
Dropdown.prototype.open = function (e) { Dropdown.prototype.open = function(e) {
this.close(); this.close();
this.ddmenuitem = $(this.$el).css('visibility', 'visible'); this.ddmenuitem = $(this.$el).css('visibility', 'visible');
e.stopPropagation(); e.stopPropagation();
@@ -868,7 +865,7 @@ client.load = function load(serverSettings, callback) {
var silenceDropdown = new Dropdown('#silenceBtn'); var silenceDropdown = new Dropdown('#silenceBtn');
var viewDropdown = new Dropdown('#viewMenu'); var viewDropdown = new Dropdown('#viewMenu');
$('.bgButton').click(function (e) { $('.bgButton').click(function(e) {
if (alarmingNow()) { if (alarmingNow()) {
silenceDropdown.open(e); silenceDropdown.open(e);
} }
@@ -887,23 +884,23 @@ client.load = function load(serverSettings, callback) {
viewDropdown.open(e); viewDropdown.open(e);
} }
}); });
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Client-side code to connect to server and handle incoming data // Client-side code to connect to server and handle incoming data
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// eslint-disable-next-line no-undef
client.socket = socket = io.connect(); client.socket = socket = io.connect();
socket.on('dataUpdate', dataUpdate); socket.on('dataUpdate', dataUpdate);
function resetRetro ( ) { function resetRetro () {
client.retro = { client.retro = {
loadedMills: 0 loadedMills: 0
, loadStartedMills: 0 , loadStartedMills: 0
}; };
} }
client.resetRetroIfNeeded = function resetRetroIfNeeded ( ) { client.resetRetroIfNeeded = function resetRetroIfNeeded () {
if (client.retro.loadedMills > 0 && Date.now() - client.retro.loadedMills > times.mins(5).msecs) { if (client.retro.loadedMills > 0 && Date.now() - client.retro.loadedMills > times.mins(5).msecs) {
resetRetro(); resetRetro();
console.info('Cleared retro data to free memory'); console.info('Cleared retro data to free memory');
@@ -912,7 +909,7 @@ client.load = function load(serverSettings, callback) {
resetRetro(); resetRetro();
client.loadRetroIfNeeded = function loadRetroIfNeeded ( ) { client.loadRetroIfNeeded = function loadRetroIfNeeded () {
var now = Date.now(); var now = Date.now();
if (now - client.retro.loadStartedMills < times.secs(30).msecs) { if (now - client.retro.loadStartedMills < times.secs(30).msecs) {
console.info('retro already loading, started', new Date(client.retro.loadStartedMills)); console.info('retro already loading, started', new Date(client.retro.loadStartedMills));
@@ -940,7 +937,7 @@ client.load = function load(serverSettings, callback) {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Alarms and Text handling // Alarms and Text handling
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
socket.on('connect', function () { socket.on('connect', function() {
console.log('Client connected to server.'); console.log('Client connected to server.');
socket.emit( socket.emit(
'authorize' 'authorize'
@@ -950,10 +947,10 @@ client.load = function load(serverSettings, callback) {
, token: client.authorized && client.authorized.token , token: client.authorized && client.authorized.token
, history: history , history: history
} }
, function authCallback(data) { , function authCallback (data) {
console.log('Client rights: ',data); console.log('Client rights: ', data);
if (!data.read || !hasRequiredPermission()) { if (!data.read || !hasRequiredPermission()) {
client.hashauth.requestAuthentication(function afterRequest ( ) { client.hashauth.requestAuthentication(function afterRequest () {
client.hashauth.updateSocketAuth(); client.hashauth.updateSocketAuth();
if (callback) { if (callback) {
callback(); callback();
@@ -966,7 +963,7 @@ client.load = function load(serverSettings, callback) {
); );
}); });
function hasRequiredPermission ( ) { function hasRequiredPermission () {
if (client.requiredPermission) { if (client.requiredPermission) {
if (client.hashauth && client.hashauth.isAuthenticated()) { if (client.hashauth && client.hashauth.isAuthenticated()) {
return true; return true;
@@ -980,39 +977,38 @@ client.load = function load(serverSettings, callback) {
//with predicted alarms, latestSGV may still be in target so to see if the alarm //with predicted alarms, latestSGV may still be in target so to see if the alarm
// is for a HIGH we can only check if it's >= the bottom of the target // is for a HIGH we can only check if it's >= the bottom of the target
function isAlarmForHigh() { function isAlarmForHigh () {
return client.latestSGV && client.latestSGV.mgdl >= client.settings.thresholds.bgTargetBottom; return client.latestSGV && client.latestSGV.mgdl >= client.settings.thresholds.bgTargetBottom;
} }
//with predicted alarms, latestSGV may still be in target so to see if the alarm //with predicted alarms, latestSGV may still be in target so to see if the alarm
// is for a LOW we can only check if it's <= the top of the target // is for a LOW we can only check if it's <= the top of the target
function isAlarmForLow() { function isAlarmForLow () {
return client.latestSGV && client.latestSGV.mgdl <= client.settings.thresholds.bgTargetTop; return client.latestSGV && client.latestSGV.mgdl <= client.settings.thresholds.bgTargetTop;
} }
socket.on('notification', function (notify) { socket.on('notification', function(notify) {
console.log('notification from server:',notify); console.log('notification from server:', notify);
if (notify.timestamp && previousNotifyTimestamp != notify.timestamp) if (notify.timestamp && previousNotifyTimestamp != notify.timestamp) {
{ previousNotifyTimestamp = notify.timestamp;
previousNotifyTimestamp = notify.timestamp;
client.plugins.visualizeAlarm(client.sbx, notify, notify.title + ' ' + notify.message); client.plugins.visualizeAlarm(client.sbx, notify, notify.title + ' ' + notify.message);
} else { } else {
console.log('No timestamp found for notify, not passing to plugins'); console.log('No timestamp found for notify, not passing to plugins');
} }
}); });
socket.on('announcement', function (notify) { socket.on('announcement', function(notify) {
console.info('announcement received from server'); console.info('announcement received from server');
console.log('notify:',notify); console.log('notify:', notify);
currentAnnouncement = notify; currentAnnouncement = notify;
currentAnnouncement.received = Date.now(); currentAnnouncement.received = Date.now();
updateTitle(); updateTitle();
}); });
socket.on('alarm', function (notify) { socket.on('alarm', function(notify) {
console.info('alarm received from server'); console.info('alarm received from server');
console.log('notify:',notify); console.log('notify:', notify);
var enabled = (isAlarmForHigh() && client.settings.alarmHigh) || (isAlarmForLow() && client.settings.alarmLow); var enabled = (isAlarmForHigh() && client.settings.alarmHigh) || (isAlarmForLow() && client.settings.alarmLow);
if (enabled) { if (enabled) {
console.log('Alarm raised!'); console.log('Alarm raised!');
@@ -1023,9 +1019,9 @@ client.load = function load(serverSettings, callback) {
chart.update(false); chart.update(false);
}); });
socket.on('urgent_alarm', function (notify) { socket.on('urgent_alarm', function(notify) {
console.info('urgent alarm received from server'); console.info('urgent alarm received from server');
console.log('notify:',notify); console.log('notify:', notify);
var enabled = (isAlarmForHigh() && client.settings.alarmUrgentHigh) || (isAlarmForLow() && client.settings.alarmUrgentLow); var enabled = (isAlarmForHigh() && client.settings.alarmUrgentHigh) || (isAlarmForLow() && client.settings.alarmUrgentLow);
if (enabled) { if (enabled) {
@@ -1037,7 +1033,7 @@ client.load = function load(serverSettings, callback) {
chart.update(false); chart.update(false);
}); });
socket.on('clear_alarm', function (notify) { socket.on('clear_alarm', function(notify) {
console.info('got clear_alarm', notify); console.info('got clear_alarm', notify);
if (alarmInProgress) { if (alarmInProgress) {
console.log('clearing alarm'); console.log('clearing alarm');
@@ -1054,7 +1050,7 @@ client.load = function load(serverSettings, callback) {
window.speechSynthesis.speak(msg); window.speechSynthesis.speak(msg);
} }
d3.selectAll('.audio.alarms audio').each(function () { d3.selectAll('.audio.alarms audio').each(function() {
var audio = this; var audio = this;
playAlarm(audio); playAlarm(audio);
setTimeout(function() { setTimeout(function() {
@@ -1079,30 +1075,30 @@ client.load = function load(serverSettings, callback) {
$('.cobcontrol').toggle(client.settings.enable.indexOf('cob') > -1); $('.cobcontrol').toggle(client.settings.enable.indexOf('cob') > -1);
container.toggleClass('has-minor-pills', client.plugins.hasShownType('pill-minor', client.settings)); container.toggleClass('has-minor-pills', client.plugins.hasShownType('pill-minor', client.settings));
function prepareEntries ( ) { function prepareEntries () {
// Post processing after data is in // Post processing after data is in
var temp1 = [ ]; var temp1 = [];
var sbx = client.sbx.withExtendedSettings(client.rawbg); var sbx = client.sbx.withExtendedSettings(client.rawbg);
if (client.ddata.cal && client.rawbg.isEnabled(sbx)) { if (client.ddata.cal && client.rawbg.isEnabled(sbx)) {
temp1 = client.ddata.sgvs.map(function (entry) { temp1 = client.ddata.sgvs.map(function(entry) {
var rawbgValue = client.rawbg.showRawBGs(entry.mgdl, entry.noise, client.ddata.cal, sbx) ? client.rawbg.calc(entry, client.ddata.cal, sbx) : 0; var rawbgValue = client.rawbg.showRawBGs(entry.mgdl, entry.noise, client.ddata.cal, sbx) ? client.rawbg.calc(entry, client.ddata.cal, sbx) : 0;
if (rawbgValue > 0) { if (rawbgValue > 0) {
return { mills: entry.mills - 2000, mgdl: rawbgValue, color: 'white', type: 'rawbg' }; return { mills: entry.mills - 2000, mgdl: rawbgValue, color: 'white', type: 'rawbg' };
} else { } else {
return null; return null;
} }
}).filter(function (entry) { }).filter(function(entry) {
return entry !== null; return entry !== null;
}); });
} }
var temp2 = client.ddata.sgvs.map(function (obj) { var temp2 = client.ddata.sgvs.map(function(obj) {
return { mills: obj.mills, mgdl: obj.mgdl, direction: obj.direction, color: sgvToColor(obj.mgdl), type: 'sgv', noise: obj.noise, filtered: obj.filtered, unfiltered: obj.unfiltered}; return { mills: obj.mills, mgdl: obj.mgdl, direction: obj.direction, color: sgvToColor(obj.mgdl), type: 'sgv', noise: obj.noise, filtered: obj.filtered, unfiltered: obj.unfiltered };
}); });
client.entries = []; client.entries = [];
client.entries = client.entries.concat(temp1, temp2); client.entries = client.entries.concat(temp1, temp2);
client.entries = client.entries.concat(client.ddata.mbgs.map(function (obj) { client.entries = client.entries.concat(client.ddata.mbgs.map(function(obj) {
return { mills: obj.mills, mgdl: obj.mgdl, color: 'red', type: 'mbg', device: obj.device }; return { mills: obj.mills, mgdl: obj.mgdl, color: 'red', type: 'mbg', device: obj.device };
})); }));
@@ -1111,7 +1107,7 @@ client.load = function load(serverSettings, callback) {
return entry.mills > tooOld; return entry.mills > tooOld;
}); });
client.entries.forEach(function (point) { client.entries.forEach(function(point) {
if (point.mgdl < 39) { if (point.mgdl < 39) {
point.color = 'transparent'; point.color = 'transparent';
} }
@@ -1131,10 +1127,9 @@ client.load = function load(serverSettings, callback) {
} }
if (client.ddata.sgvs) { if (client.ddata.sgvs) {
// change the next line so that it uses the prediction if the signal gets lost (max 1/2 hr) // TODO change the next line so that it uses the prediction if the signal gets lost (max 1/2 hr)
client.ctx.data.lastUpdated = lastUpdated; client.ctx.data.lastUpdated = lastUpdated;
client.latestSGV = client.ddata.sgvs[client.ddata.sgvs.length - 1]; client.latestSGV = client.ddata.sgvs[client.ddata.sgvs.length - 1];
prevSGV = client.ddata.sgvs[client.ddata.sgvs.length - 2];
} }
client.ddata.inRetroMode = false; client.ddata.inRetroMode = false;
+14 -14
View File
@@ -4,22 +4,22 @@ var _ = require('lodash');
var TWO_DAYS = 172800000; var TWO_DAYS = 172800000;
function mergeDataUpdate(isDelta, cachedDataArray, receivedDataArray, maxAge) { function mergeDataUpdate (isDelta, cachedDataArray, receivedDataArray, maxAge) {
function nsArrayDiff(oldArray, newArray) { function nsArrayDiff (oldArray, newArray) {
var seen = {}; var seen = [];
var l = oldArray.length; var l = oldArray.length;
for (var i = 0; i < l; i++) { for (var i = 0; i < l; i++) {
if (oldArray[i] !== null) { if (oldArray[i] !== null) {
seen[oldArray[i].mills] = true; seen.push(oldArray[i].mills);
} }
} }
var result = []; var result = [];
l = newArray.length; l = newArray.length;
for (var j = 0; j < l; j++) { for (var j = 0; j < l; j++) {
if (!seen.hasOwnProperty(newArray[j].mills)) { if (!seen.includes(newArray[j].mills)) {
result.push(newArray[j]); //console.log('delta data found'); result.push(newArray[j]); //console.log('delta data found');
} }
} }
@@ -39,11 +39,11 @@ function mergeDataUpdate(isDelta, cachedDataArray, receivedDataArray, maxAge) {
// purge old data from cache before updating // purge old data from cache before updating
var mAge = (isNaN(maxAge) || maxAge == null) ? TWO_DAYS : maxAge; var mAge = (isNaN(maxAge) || maxAge == null) ? TWO_DAYS : maxAge;
var twoDaysAgo = new Date().getTime() - mAge; var twoDaysAgo = new Date().getTime() - mAge;
for (var i = 0; i < cachedDataArray.length; i++) { for (var i = 0; i < cachedDataArray.length; i++) {
var element = cachedDataArray[i]; var element = cachedDataArray[i];
if (element !== null && element !== undefined && element.mills <= twoDaysAgo) { if (element !== null && element !== undefined && element.mills <= twoDaysAgo) {
cachedDataArray.splice(i,0); cachedDataArray.splice(i, 0);
} }
} }
@@ -54,7 +54,7 @@ function mergeDataUpdate(isDelta, cachedDataArray, receivedDataArray, maxAge) {
}); });
} }
function mergeTreatmentUpdate(isDelta, cachedDataArray, receivedDataArray) { function mergeTreatmentUpdate (isDelta, cachedDataArray, receivedDataArray) {
// If there was no delta data, just return the original data // If there was no delta data, just return the original data
if (!receivedDataArray) { if (!receivedDataArray) {
@@ -78,12 +78,12 @@ function mergeTreatmentUpdate(isDelta, cachedDataArray, receivedDataArray) {
for (var j = 0; j < m; j++) { for (var j = 0; j < m; j++) {
if (no._id === cachedDataArray[j]._id) { if (no._id === cachedDataArray[j]._id) {
if (no.action === 'remove') { if (no.action === 'remove') {
cachedDataArray.splice(j,1); cachedDataArray.splice(j, 1);
break; break;
} }
if (no.action === 'update') { if (no.action === 'update') {
delete no.action; delete no.action;
cachedDataArray.splice(j,1,no); cachedDataArray.splice(j, 1, no);
break; break;
} }
} }
+314 -323
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -11,6 +11,7 @@ var ONE_DAY = 86400000,
function uniq(a) { function uniq(a) {
var seen = {}; var seen = {};
return a.filter(function(item) { return a.filter(function(item) {
// eslint-disable-next-line no-prototype-builtins
return seen.hasOwnProperty(item.mills) ? false : (seen[item.mills] = true); return seen.hasOwnProperty(item.mills) ? false : (seen[item.mills] = true);
}); });
} }
+249 -250
View File
@@ -5,270 +5,269 @@ var times = require('../times');
var DEVICE_TYPE_FIELDS = ['uploader', 'pump', 'openaps', 'loop', 'xdripjs']; var DEVICE_TYPE_FIELDS = ['uploader', 'pump', 'openaps', 'loop', 'xdripjs'];
function init() { function init () {
var ddata = { var ddata = {
sgvs: [], sgvs: []
treatments: [], , treatments: []
mbgs: [], , mbgs: []
cals: [], , cals: []
profiles: [], , profiles: []
devicestatus: [], , devicestatus: []
food: [], , food: []
activity: [], , activity: []
lastUpdated: 0 , lastUpdated: 0
};
ddata.clone = function clone () {
return _.clone(ddata, function(value) {
//special handling of mongo ObjectID's
//see https://github.com/lodash/lodash/issues/602#issuecomment-47414964
//instead of requiring Mongo.ObjectID here and having it get pulled into the bundle
//we'll look for the toHexString function and then assume it's an ObjectID
if (value && value.toHexString && value.toHexString.call && value.toString && value.toString.call) {
return value.toString();
}
});
};
ddata.splitRecent = function splitRecent (time, cutoff, max, treatmentsToo) {
var result = {
first: {}
, rest: {}
}; };
ddata.clone = function clone() { function recent (item) {
return _.clone(ddata, function(value) { return item.mills >= time - cutoff;
//special handling of mongo ObjectID's }
//see https://github.com/lodash/lodash/issues/602#issuecomment-47414964
//instead of requiring Mongo.ObjectID here and having it get pulled into the bundle function filterMax (item) {
//we'll look for the toHexString function and then assume it's an ObjectID return item.mills >= time - max;
if (value && value.toHexString && value.toHexString.call && value.toString && value.toString.call) { }
return value.toString();
}
});
};
ddata.splitRecent = function splitRecent(time, cutoff, max, treatmentsToo) { function partition (field, filter) {
var result = { var data;
first: {}, if (filter) {
rest: {} data = ddata[field].filter(filterMax);
}; } else {
data = ddata[field];
}
function recent(item) { var parts = _.partition(data, recent);
return item.mills >= time - cutoff; result.first[field] = parts[0];
result.rest[field] = parts[1];
}
partition('treatments', treatmentsToo ? filterMax : false);
result.first.devicestatus = ddata.recentDeviceStatus(time);
result.first.sgvs = ddata.sgvs.filter(filterMax);
result.first.cals = ddata.cals;
var profiles = _.cloneDeep(ddata.profiles);
if (profiles && profiles[0]) {
Object.keys(profiles[0].store).forEach(k => {
if (k.indexOf('@@@@@') > 0) {
delete profiles[0].store[k];
} }
})
}
result.first.profiles = profiles;
function filterMax(item) { result.rest.mbgs = ddata.mbgs.filter(filterMax);
return item.mills >= time - max; result.rest.food = ddata.food;
result.rest.activity = ddata.activity;
console.log('results.first size', JSON.stringify(result.first).length, 'bytes');
console.log('results.rest size', JSON.stringify(result.rest).length, 'bytes');
return result;
};
ddata.recentDeviceStatus = function recentDeviceStatus (time) {
var deviceAndTypes =
_.chain(ddata.devicestatus)
.map(function eachStatus (status) {
return _.chain(status)
.keys()
.filter(function isExcluded (key) {
return _.includes(DEVICE_TYPE_FIELDS, key);
})
.map(function toDeviceTypeKey (key) {
return {
device: status.device
, type: key
};
})
.value();
})
.flatten()
.uniqWith(_.isEqual)
.value();
//console.info('>>>deviceAndTypes', deviceAndTypes);
var rv = _.chain(deviceAndTypes)
.map(function findMostRecent (deviceAndType) {
return _.chain(ddata.devicestatus)
.filter(function isSameDeviceType (status) {
return status.device === deviceAndType.device && _.has(status, deviceAndType.type)
})
.filter(function notInTheFuture (status) {
return status.mills <= time;
})
.sortBy('mills')
.takeRight(10)
.value();
}).value();
var merged = [].concat.apply([], rv);
rv = _.chain(merged)
.filter(_.isObject)
.uniq('_id')
.sortBy('mills')
.value();
return rv;
};
ddata.processDurations = function processDurations (treatments, keepzeroduration) {
treatments = _.uniqBy(treatments, 'mills');
// cut temp basals by end events
// better to do it only on data update
var endevents = treatments.filter(function filterEnd (t) {
return !t.duration;
});
function cutIfInInterval (base, end) {
if (base.mills < end.mills && base.mills + times.mins(base.duration).msecs > end.mills) {
base.duration = times.msecs(end.mills - base.mills).mins;
if (end.profile) {
base.cuttedby = end.profile;
end.cutting = base.profile;
} }
}
}
function partition(field, filter) { // cut by end events
var data; treatments.forEach(function allTreatments (t) {
if (filter) { if (t.duration) {
data = ddata[field].filter(filterMax); endevents.forEach(function allEndevents (e) {
} else { cutIfInInterval(t, e);
data = ddata[field]; });
} }
});
var parts = _.partition(data, recent); // cut by overlaping events
result.first[field] = parts[0]; treatments.forEach(function allTreatments (t) {
result.rest[field] = parts[1]; if (t.duration) {
treatments.forEach(function allEndevents (e) {
cutIfInInterval(t, e);
});
}
});
if (keepzeroduration) {
return treatments;
} else {
return treatments.filter(function filterEnd (t) {
return t.duration;
});
}
};
ddata.processTreatments = function processTreatments (preserveOrignalTreatments) {
// filter & prepare 'Site Change' events
ddata.sitechangeTreatments = ddata.treatments.filter(function filterSensor (t) {
return t.eventType.indexOf('Site Change') > -1;
}).sort(function(a, b) {
return a.mills > b.mills;
});
// filter & prepare 'Insulin Change' events
ddata.insulinchangeTreatments = ddata.treatments.filter(function filterInsulin (t) {
return t.eventType.indexOf('Insulin Change') > -1;
}).sort(function(a, b) {
return a.mills > b.mills;
});
// filter & prepare 'Pump Battery Change' events
ddata.batteryTreatments = ddata.treatments.filter(function filterSensor (t) {
return t.eventType.indexOf('Pump Battery Change') > -1;
}).sort(function(a, b) {
return a.mills > b.mills;
});
// filter & prepare 'Sensor' events
ddata.sensorTreatments = ddata.treatments.filter(function filterSensor (t) {
return t.eventType.indexOf('Sensor') > -1;
}).sort(function(a, b) {
return a.mills > b.mills;
});
// filter & prepare 'Profile Switch' events
var profileTreatments = ddata.treatments.filter(function filterProfiles (t) {
return t.eventType === 'Profile Switch';
}).sort(function(a, b) {
return a.mills > b.mills;
});
if (preserveOrignalTreatments)
profileTreatments = _.cloneDeep(profileTreatments);
ddata.profileTreatments = ddata.processDurations(profileTreatments, true);
// filter & prepare 'Combo Bolus' events
ddata.combobolusTreatments = ddata.treatments.filter(function filterComboBoluses (t) {
return t.eventType === 'Combo Bolus';
}).sort(function(a, b) {
return a.mills > b.mills;
});
// filter & prepare temp basals
var tempbasalTreatments = ddata.treatments.filter(function filterBasals (t) {
return t.eventType && t.eventType.indexOf('Temp Basal') > -1;
});
if (preserveOrignalTreatments)
tempbasalTreatments = _.cloneDeep(tempbasalTreatments);
ddata.tempbasalTreatments = ddata.processDurations(tempbasalTreatments, false);
// filter temp target
var tempTargetTreatments = ddata.treatments.filter(function filterTargets (t) {
//check for a units being sent
if (t.units) {
if (t.units == 'mmol') {
//convert to mgdl
t.targetTop = t.targetTop * 18;
t.targetBottom = t.targetBottom * 18;
t.units = 'mg/dl';
} }
}
//if we have a temp target thats below 20, assume its mmol and convert to mgdl for safety.
if (t.targetTop < 20) {
t.targetTop = t.targetTop * 18;
t.units = 'mg/dl';
}
if (t.targetBottom < 20) {
t.targetBottom = t.targetBottom * 18;
t.units = 'mg/dl';
}
return t.eventType && t.eventType.indexOf('Temporary Target') > -1;
});
if (preserveOrignalTreatments)
tempTargetTreatments = _.cloneDeep(tempTargetTreatments);
ddata.tempTargetTreatments = ddata.processDurations(tempTargetTreatments, false);
partition('treatments', treatmentsToo ? filterMax : false); };
result.first.devicestatus = ddata.recentDeviceStatus(time); return ddata;
result.first.sgvs = ddata.sgvs.filter(filterMax);
result.first.cals = ddata.cals;
var profiles = _.cloneDeep(ddata.profiles);
if (profiles && profiles[0])
for (var k in profiles[0].store) {
if (profiles[0].store.hasOwnProperty(k)) {
if (k.indexOf('@@@@@') > 0) {
delete profiles[0].store[k];
}
}
}
result.first.profiles = profiles;
result.rest.mbgs = ddata.mbgs.filter(filterMax);
result.rest.food = ddata.food;
result.rest.activity = ddata.activity;
console.log('results.first size', JSON.stringify(result.first).length, 'bytes');
console.log('results.rest size', JSON.stringify(result.rest).length, 'bytes');
return result;
};
ddata.recentDeviceStatus = function recentDeviceStatus(time) {
var deviceAndTypes =
_.chain(ddata.devicestatus)
.map(function eachStatus(status) {
return _.chain(status)
.keys()
.filter(function isExcluded(key) {
return _.includes(DEVICE_TYPE_FIELDS, key);
})
.map(function toDeviceTypeKey(key) {
return {
device: status.device,
type: key
};
})
.value();
})
.flatten()
.uniqWith(_.isEqual)
.value();
//console.info('>>>deviceAndTypes', deviceAndTypes);
var rv = _.chain(deviceAndTypes)
.map(function findMostRecent(deviceAndType) {
return _.chain(ddata.devicestatus)
.filter(function isSameDeviceType(status) {
return status.device === deviceAndType.device && _.has(status, deviceAndType.type)
})
.filter(function notInTheFuture(status) {
return status.mills <= time;
})
.sortBy('mills')
.takeRight(10)
.value();
}).value();
var merged = [].concat.apply([], rv);
rv = _.chain(merged)
.filter(_.isObject)
.uniq('_id')
.sortBy('mills')
.value();
return rv;
};
ddata.processDurations = function processDurations(treatments, keepzeroduration) {
treatments = _.uniqBy(treatments, 'mills');
// cut temp basals by end events
// better to do it only on data update
var endevents = treatments.filter(function filterEnd(t) {
return !t.duration;
});
function cutIfInInterval(base, end) {
if (base.mills < end.mills && base.mills + times.mins(base.duration).msecs > end.mills) {
base.duration = times.msecs(end.mills - base.mills).mins;
if (end.profile) {
base.cuttedby = end.profile;
end.cutting = base.profile;
}
}
}
// cut by end events
treatments.forEach(function allTreatments(t) {
if (t.duration) {
endevents.forEach(function allEndevents(e) {
cutIfInInterval(t, e);
});
}
});
// cut by overlaping events
treatments.forEach(function allTreatments(t) {
if (t.duration) {
treatments.forEach(function allEndevents(e) {
cutIfInInterval(t, e);
});
}
});
if (keepzeroduration) {
return treatments;
} else {
return treatments.filter(function filterEnd(t) {
return t.duration;
});
}
};
ddata.processTreatments = function processTreatments(preserveOrignalTreatments) {
// filter & prepare 'Site Change' events
ddata.sitechangeTreatments = ddata.treatments.filter(function filterSensor(t) {
return t.eventType.indexOf('Site Change') > -1;
}).sort(function(a, b) {
return a.mills > b.mills;
});
// filter & prepare 'Insulin Change' events
ddata.insulinchangeTreatments = ddata.treatments.filter(function filterInsulin(t) {
return t.eventType.indexOf('Insulin Change') > -1;
}).sort(function(a, b) {
return a.mills > b.mills;
});
// filter & prepare 'Pump Battery Change' events
ddata.batteryTreatments = ddata.treatments.filter(function filterSensor(t) {
return t.eventType.indexOf('Pump Battery Change') > -1;
}).sort(function(a, b) {
return a.mills > b.mills;
});
// filter & prepare 'Sensor' events
ddata.sensorTreatments = ddata.treatments.filter(function filterSensor(t) {
return t.eventType.indexOf('Sensor') > -1;
}).sort(function(a, b) {
return a.mills > b.mills;
});
// filter & prepare 'Profile Switch' events
var profileTreatments = ddata.treatments.filter(function filterProfiles(t) {
return t.eventType === 'Profile Switch';
}).sort(function(a, b) {
return a.mills > b.mills;
});
if (preserveOrignalTreatments)
profileTreatments = _.cloneDeep(profileTreatments);
ddata.profileTreatments = ddata.processDurations(profileTreatments, true);
// filter & prepare 'Combo Bolus' events
ddata.combobolusTreatments = ddata.treatments.filter(function filterComboBoluses(t) {
return t.eventType === 'Combo Bolus';
}).sort(function(a, b) {
return a.mills > b.mills;
});
// filter & prepare temp basals
var tempbasalTreatments = ddata.treatments.filter(function filterBasals(t) {
return t.eventType && t.eventType.indexOf('Temp Basal') > -1;
});
if (preserveOrignalTreatments)
tempbasalTreatments = _.cloneDeep(tempbasalTreatments);
ddata.tempbasalTreatments = ddata.processDurations(tempbasalTreatments, false);
// filter temp target
var tempTargetTreatments = ddata.treatments.filter(function filterTargets(t) {
//check for a units being sent
if (t.units) {
if (t.units == 'mmol') {
//convert to mgdl
t.targetTop = t.targetTop * 18;
t.targetBottom = t.targetBottom * 18;
t.units = 'mg/dl';
}
}
//if we have a temp target thats below 20, assume its mmol and convert to mgdl for safety.
if (t.targetTop < 20) {
t.targetTop = t.targetTop * 18;
t.units = 'mg/dl';
}
if (t.targetBottom < 20) {
t.targetBottom = t.targetBottom * 18;
t.units = 'mg/dl';
}
return t.eventType && t.eventType.indexOf('Temporary Target') > -1;
});
if (preserveOrignalTreatments)
tempTargetTreatments = _.cloneDeep(tempTargetTreatments);
ddata.tempTargetTreatments = ddata.processDurations(tempTargetTreatments, false);
};
return ddata;
} }
module.exports = init; module.exports = init;
+23 -393
View File
@@ -834,7 +834,6 @@ function init() {
,dk: 'Noter indeholder' ,dk: 'Noter indeholder'
,fi: 'Merkinnät sisältävät' ,fi: 'Merkinnät sisältävät'
,nb: 'Notater inneholder' ,nb: 'Notater inneholder'
,he: 'הערות מכילות'
,pl: 'Zawierają uwagi' ,pl: 'Zawierają uwagi'
,ru: 'Примечания содержат' ,ru: 'Примечания содержат'
,sk: 'Poznámky obsahujú' ,sk: 'Poznámky obsahujú'
@@ -1460,7 +1459,6 @@ function init() {
,sv: 'temp basal måste vara synlig för denna rapport' ,sv: 'temp basal måste vara synlig för denna rapport'
,de: 'temporäre Basalraten müssen für diesen Report sichtbar sein' ,de: 'temporäre Basalraten müssen für diesen Report sichtbar sein'
,fi: 'tämä raportti vaatii, että basaalien piirto on päällä' ,fi: 'tämä raportti vaatii, että basaalien piirto on päällä'
,he: 'חובה לאפשר רמה בזלית זמנית כדי לרות דוח זה'
,bg: 'временните базали трябва да са показани за да се покаже тази това' ,bg: 'временните базали трябва да са показани за да се покаже тази това'
,hr: 'temp bazali moraju biti prikazani kako bi se vidio ovaj izvještaj' ,hr: 'temp bazali moraju biti prikazani kako bi se vidio ovaj izvještaj'
,he: 'חובה לאפשר רמה בזלית זמנית כדי לרות דוח זה' ,he: 'חובה לאפשר רמה בזלית זמנית כדי לרות דוח זה'
@@ -1469,7 +1467,6 @@ function init() {
} }
,'Weekly success' : { ,'Weekly success' : {
cs: 'Statistika po týdnech' cs: 'Statistika po týdnech'
,he: 'הצלחה שבועית'
,de: 'Wöchentlicher Erfolg' ,de: 'Wöchentlicher Erfolg'
,es: 'Resultados semanales' ,es: 'Resultados semanales'
,fr: 'Résultat hebdomadaire' ,fr: 'Résultat hebdomadaire'
@@ -1747,7 +1744,6 @@ function init() {
cs: 'Normální' cs: 'Normální'
,de: 'Normal' ,de: 'Normal'
,es: 'Normal' ,es: 'Normal'
,he: 'נורמלי '
,fr: 'Normale' ,fr: 'Normale'
,el: 'Εντός Στόχου' ,el: 'Εντός Στόχου'
,pt: 'Normal' ,pt: 'Normal'
@@ -1871,7 +1867,6 @@ function init() {
} }
,'Glucose Percentile report' : { ,'Glucose Percentile report' : {
cs: 'Tabulka percentil glykémií' cs: 'Tabulka percentil glykémií'
,he: 'דוח אחוזוני גלוקוזה'
,de: 'Glukose-Perzentil Bericht' ,de: 'Glukose-Perzentil Bericht'
,es: 'Informe de percetiles de glucemia' ,es: 'Informe de percetiles de glucemia'
,fr: 'Rapport percentiles Glycémie' ,fr: 'Rapport percentiles Glycémie'
@@ -2196,7 +2191,6 @@ function init() {
} }
,'Weekly Success' : { ,'Weekly Success' : {
cs: 'Týdenní úspěšnost' cs: 'Týdenní úspěšnost'
,he: 'הצלחה שבועית '
,de: 'Wöchtlicher Erfolg' ,de: 'Wöchtlicher Erfolg'
,es: 'Resultados semanales' ,es: 'Resultados semanales'
,fr: 'Réussite hebdomadaire' ,fr: 'Réussite hebdomadaire'
@@ -2263,7 +2257,6 @@ function init() {
,dk: 'Anvender gemt API-nøgle' ,dk: 'Anvender gemt API-nøgle'
,fi: 'Tallennettu salainen API-tarkiste käytössä' ,fi: 'Tallennettu salainen API-tarkiste käytössä'
,nb: 'Bruker lagret API nøkkel' ,nb: 'Bruker lagret API nøkkel'
,he: 'עורך אוכל'
,pl: 'Korzystając z zapisanego poufnego hasha API' ,pl: 'Korzystając z zapisanego poufnego hasha API'
,ru: 'Применение сохраненного пароля API' ,ru: 'Применение сохраненного пароля API'
,sk: 'Používam uložený API hash heslo' ,sk: 'Používam uložený API hash heslo'
@@ -2275,7 +2268,6 @@ function init() {
} }
,'No API secret hash stored yet. You need to enter API secret.' : { ,'No API secret hash stored yet. You need to enter API secret.' : {
cs: 'Není uložený žádný hash API hesla. Musíte zadat API heslo.' cs: 'Není uložený žádný hash API hesla. Musíte zadat API heslo.'
,he: 'הכנס את סיסמת ממשק תכנות יישומים הסודית'
,de: 'Keine API-Prüfsumme gespeichert. Bitte API-Prüfsumme eingeben.' ,de: 'Keine API-Prüfsumme gespeichert. Bitte API-Prüfsumme eingeben.'
,es: 'No se ha almacenado ningún hash todavía. Debe introducir su secreto API.' ,es: 'No se ha almacenado ningún hash todavía. Debe introducir su secreto API.'
,fr: 'Pas de secret API existant. Vous devez en entrer un.' ,fr: 'Pas de secret API existant. Vous devez en entrer un.'
@@ -2302,7 +2294,6 @@ function init() {
} }
,'Database loaded' : { ,'Database loaded' : {
cs: 'Databáze načtena' cs: 'Databáze načtena'
,he: 'אגר מידע נטען '
,de: 'Datenbank geladen' ,de: 'Datenbank geladen'
,es: 'Base de datos cargada' ,es: 'Base de datos cargada'
,fr: 'Base de données chargée' ,fr: 'Base de données chargée'
@@ -2496,7 +2487,6 @@ function init() {
,pl: 'IG' ,pl: 'IG'
,ru: 'ГИ' ,ru: 'ГИ'
,sk: 'GI' ,sk: 'GI'
,he: 'GI'
,nl: 'Glycemische index ' ,nl: 'Glycemische index '
,ko: '혈당 지수' ,ko: '혈당 지수'
,tr: 'GI-Glisemik İndeks' ,tr: 'GI-Glisemik İndeks'
@@ -2638,7 +2628,6 @@ function init() {
,ro: 'Cheia API trebuie să aibă mai mult de 12 caractere' ,ro: 'Cheia API trebuie să aibă mai mult de 12 caractere'
,bg: 'Вашата АPI парола трябва да е дълга поне 12 символа' ,bg: 'Вашата АPI парола трябва да е дълга поне 12 символа'
,hr: 'Vaš tajni API mora sadržavati barem 12 znakova' ,hr: 'Vaš tajni API mora sadržavati barem 12 znakova'
,he:' הסיסמא הסודית חייבת להיות באורך של 12 תווים לפחות'
,sv: 'Hemlig API-nyckel måsta innehålla 12 tecken' ,sv: 'Hemlig API-nyckel måsta innehålla 12 tecken'
,it: 'il vostro API secreto deve essere lungo almeno 12 caratteri' ,it: 'il vostro API secreto deve essere lungo almeno 12 caratteri'
,ja: 'APIシークレットは12文字以上の長さが必要です' ,ja: 'APIシークレットは12文字以上の長さが必要です'
@@ -2673,7 +2662,6 @@ function init() {
,nb: 'Ugyldig API nøkkel' ,nb: 'Ugyldig API nøkkel'
,pl: 'Błędny klucz API' ,pl: 'Błędny klucz API'
,ru: 'Плохой пароль API' ,ru: 'Плохой пароль API'
,he: ' הסיסמא הסודית אינה חוקית'
,sk: 'Nesprávne API heslo' ,sk: 'Nesprávne API heslo'
,nl: 'Onjuist API wachtwoord' ,nl: 'Onjuist API wachtwoord'
,ko: '잘못된 API secret' ,ko: '잘못된 API secret'
@@ -2699,7 +2687,6 @@ function init() {
,fi: 'API salaisuus talletettu' ,fi: 'API salaisuus talletettu'
,nb: 'API nøkkel lagret' ,nb: 'API nøkkel lagret'
,pl: 'Poufne klucz API zapisane' ,pl: 'Poufne klucz API zapisane'
,he: ' הסיסמא הסודית נשמרה'
,ru: 'Хэш пароля API сохранен' ,ru: 'Хэш пароля API сохранен'
,sk: 'Hash API hesla uložený' ,sk: 'Hash API hesla uložený'
,nl: 'API wachtwoord opgeslagen' ,nl: 'API wachtwoord opgeslagen'
@@ -2750,7 +2737,6 @@ function init() {
,dk: 'Ikke indlæst' ,dk: 'Ikke indlæst'
,fi: 'Ei ladattu' ,fi: 'Ei ladattu'
,nb: 'Ikke lest' ,nb: 'Ikke lest'
,he: 'לא נטען'
,pl: 'Nie załadowany' ,pl: 'Nie załadowany'
,ru: 'Не загружено' ,ru: 'Не загружено'
,sk: 'Nenačítaný' ,sk: 'Nenačítaný'
@@ -2773,7 +2759,6 @@ function init() {
,sv: 'Födoämneseditor' ,sv: 'Födoämneseditor'
,it: 'NS - Database Alimenti' ,it: 'NS - Database Alimenti'
,ja: '食事編集' ,ja: '食事編集'
,he: 'עורך מזון'
,dk: 'Mad editor' ,dk: 'Mad editor'
,fi: 'Muokkaa ruokia' ,fi: 'Muokkaa ruokia'
,nb: 'Mat editor' ,nb: 'Mat editor'
@@ -2973,7 +2958,6 @@ function init() {
,ro: 'Cheia API' ,ro: 'Cheia API'
,bg: 'Твоята API парола' ,bg: 'Твоята API парола'
,hr: 'Vaš tajni API' ,hr: 'Vaš tajni API'
,he: 'הסיסמא הסודית שלך'
,it: 'Il tuo API secreto' ,it: 'Il tuo API secreto'
,ja: 'あなたのAPI Secret' ,ja: 'あなたのAPI Secret'
,dk: 'Din API-nøgle' ,dk: 'Din API-nøgle'
@@ -3005,7 +2989,6 @@ function init() {
,dk: 'Gemme hash på denne computer (brug kun på privat computer)' ,dk: 'Gemme hash på denne computer (brug kun på privat computer)'
,fi: 'Tallenna avain tälle tietokoneelle (käytä vain omalla tietokoneellasi)' ,fi: 'Tallenna avain tälle tietokoneelle (käytä vain omalla tietokoneellasi)'
,nb: 'Lagre hash på denne pc (bruk kun på privat pc)' ,nb: 'Lagre hash på denne pc (bruk kun på privat pc)'
,he:'שמור סיסמא הסודית על המחשב ( יש להשתמש רק על מחשב פרטי)'
,pl: 'Zapisz na tym komputerze (korzystaj tylko na komputerach prywatnych)' ,pl: 'Zapisz na tym komputerze (korzystaj tylko na komputerach prywatnych)'
,ru: 'Сохранить хеш на этом ПК (только для личных компьютеров)' ,ru: 'Сохранить хеш на этом ПК (только для личных компьютеров)'
,sk: 'Uložiť hash na tomto počítači (Používajte iba na súkromných počítačoch)' ,sk: 'Uložiť hash na tomto počítači (Používajte iba na súkromných počítačoch)'
@@ -7692,7 +7675,7 @@ function init() {
cs: 'Odstraňování záznamů ...' cs: 'Odstraňování záznamů ...'
,he: 'מוחק רשומות ... ' ,he: 'מוחק רשומות ... '
,nb: 'Fjerner elementer...' ,nb: 'Fjerner elementer...'
,fr: 'Effacement d\événements...' ,fr: 'Effacement dévénements...'
,ro: 'Se șterg înregistrările...' ,ro: 'Se șterg înregistrările...'
,el: 'Αφαίρεση Εγγραφών' ,el: 'Αφαίρεση Εγγραφών'
,de: 'Entferne Einträge ...' ,de: 'Entferne Einträge ...'
@@ -7714,29 +7697,7 @@ function init() {
,zh_tw: '正在刪除記錄...' ,zh_tw: '正在刪除記錄...'
} }
,'%1 records deleted' : { ,'%1 records deleted' : {
cs: '%1 records deleted' hr: 'obrisano %1 zapisa'
,he: '%1 records deleted'
,nb: '%1 records deleted'
,fr: '%1 records deleted'
,ro: '%1 records deleted'
,el: '%1 records deleted'
,de: '%1 records deleted'
,es: '%1 records deleted'
,dk: '%1 records deleted'
,sv: '%1 records deleted'
,bg: '%1 records deleted'
,hr: 'obrisano %1 zapisa'
,it: '%1 records deleted'
,fi: '%1 records deleted'
,pl: '%1 records deleted'
,pt: '%1 records deleted'
,ru: '%1 records deleted'
,sk: '%1 records deleted'
,nl: '%1 records deleted'
,ko: '%1 records deleted'
,tr: '%1 records deleted'
,zh_cn: '%1 records deleted'
,zh_tw: '%1 records deleted'
} }
,'Clean Mongo status database' : { ,'Clean Mongo status database' : {
cs: 'Vyčištění Mongo databáze statusů' cs: 'Vyčištění Mongo databáze statusů'
@@ -7906,379 +7867,49 @@ function init() {
,zh_cn: '所有记录已经被清除' ,zh_cn: '所有记录已经被清除'
} }
,'Delete all documents from devicestatus collection older than 30 days' : { ,'Delete all documents from devicestatus collection older than 30 days' : {
cs: 'Delete all documents from devicestatus collection older than 30 days' hr: 'Obriši sve statuse starije od 30 dana'
,he: 'Delete all documents from devicestatus collection older than 30 days'
,nb: 'Delete all documents from devicestatus collection older than 30 days'
,fr: 'Delete all documents from devicestatus collection older than 30 days'
,ro: 'Delete all documents from devicestatus collection older than 30 days'
,el: 'Delete all documents from devicestatus collection older than 30 days'
,de: 'Delete all documents from devicestatus collection older than 30 days'
,es: 'Delete all documents from devicestatus collection older than 30 days'
,dk: 'Delete all documents from devicestatus collection older than 30 days'
,sv: 'Delete all documents from devicestatus collection older than 30 days'
,bg: 'Delete all documents from devicestatus collection older than 30 days'
,hr: 'Obriši sve statuse starije od 30 dana'
,it: 'Delete all documents from devicestatus collection older than 30 days'
,fi: 'Delete all documents from devicestatus collection older than 30 days'
,pl: 'Delete all documents from devicestatus collection older than 30 days'
,pt: 'Delete all documents from devicestatus collection older than 30 days'
,ru: 'Delete all documents from devicestatus collection older than 30 days'
,sk: 'Delete all documents from devicestatus collection older than 30 days'
,nl: 'Delete all documents from devicestatus collection older than 30 days'
,ko: 'Delete all documents from devicestatus collection older than 30 days'
,tr: 'Delete all documents from devicestatus collection older than 30 days'
,zh_cn: 'Delete all documents from devicestatus collection older than 30 days'
,zh_tw: 'Delete all documents from devicestatus collection older than 30 days'
} }
,'Number of Days to Keep:' : { ,'Number of Days to Keep:' : {
cs: 'Number of Days to Keep:' hr: 'Broj dana za sačuvati:'
,he: 'Number of Days to Keep:'
,nb: 'Number of Days to Keep:'
,fr: 'Number of Days to Keep:'
,ro: 'Number of Days to Keep:'
,el: 'Number of Days to Keep:'
,de: 'Number of Days to Keep:'
,es: 'Number of Days to Keep:'
,dk: 'Number of Days to Keep:'
,sv: 'Number of Days to Keep:'
,bg: 'Number of Days to Keep:'
,hr: 'Broj dana za sačuvati:'
,it: 'Number of Days to Keep:'
,fi: 'Number of Days to Keep:'
,pl: 'Number of Days to Keep:'
,pt: 'Number of Days to Keep:'
,ru: 'Number of Days to Keep:'
,sk: 'Number of Days to Keep:'
,nl: 'Number of Days to Keep:'
,ko: 'Number of Days to Keep:'
,tr: 'Number of Days to Keep:'
,zh_cn: 'Number of Days to Keep:'
,zh_tw: 'Number of Days to Keep:'
} }
,'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.' : { ,'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.' : {
cs: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.' hr: 'Ovo uklanja sve statuse starije od 30 dana. Korisno kada se status baterije uploadera ne osvježava ispravno.'
,he: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,nb: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,fr: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,ro: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,el: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,de: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,es: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,dk: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,sv: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,bg: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,hr: 'Ovo uklanja sve statuse starije od 30 dana. Korisno kada se status baterije uploadera ne osvježava ispravno.'
,it: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,fi: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,pl: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,pt: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,ru: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,sk: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,nl: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,ko: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,tr: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,zh_cn: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
,zh_tw: 'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.'
} }
,'Delete old documents from devicestatus collection?' : { ,'Delete old documents from devicestatus collection?' : {
cs: 'Delete old documents from devicestatus collection?' hr: 'Obriši stare statuse'
,he: 'Delete old documents from devicestatus collection?'
,nb: 'Delete old documents from devicestatus collection?'
,fr: 'Delete old documents from devicestatus collection?'
,ro: 'Delete old documents from devicestatus collection?'
,el: 'Delete old documents from devicestatus collection?'
,de: 'Delete old documents from devicestatus collection?'
,es: 'Delete old documents from devicestatus collection?'
,dk: 'Delete old documents from devicestatus collection?'
,sv: 'Delete old documents from devicestatus collection?'
,bg: 'Delete old documents from devicestatus collection?'
,hr: 'Obriši stare statuse'
,it: 'Delete old documents from devicestatus collection?'
,fi: 'Delete old documents from devicestatus collection?'
,pl: 'Delete old documents from devicestatus collection?'
,pt: 'Delete old documents from devicestatus collection?'
,ru: 'Delete old documents from devicestatus collection?'
,sk: 'Delete old documents from devicestatus collection?'
,nl: 'Delete old documents from devicestatus collection?'
,ko: 'Delete old documents from devicestatus collection?'
,tr: 'Delete old documents from devicestatus collection?'
,zh_cn: 'Delete old documents from devicestatus collection?'
,zh_tw: 'Delete old documents from devicestatus collection?'
} }
,'Clean Mongo entries (glucose entries) database' : { ,'Clean Mongo entries (glucose entries) database' : {
cs: 'Clean Mongo entries (glucose entries) database' hr: 'Obriši GUK zapise iz baze'
,he: 'Clean Mongo entries (glucose entries) database'
,nb: 'Clean Mongo entries (glucose entries) database'
,fr: 'Clean Mongo entries (glucose entries) database'
,ro: 'Clean Mongo entries (glucose entries) database'
,el: 'Clean Mongo entries (glucose entries) database'
,de: 'Clean Mongo entries (glucose entries) database'
,es: 'Clean Mongo entries (glucose entries) database'
,dk: 'Clean Mongo entries (glucose entries) database'
,sv: 'Clean Mongo entries (glucose entries) database'
,bg: 'Clean Mongo entries (glucose entries) database'
,hr: 'Obriši GUK zapise iz baze'
,it: 'Clean Mongo entries (glucose entries) database'
,fi: 'Clean Mongo entries (glucose entries) database'
,pl: 'Clean Mongo entries (glucose entries) database'
,pt: 'Clean Mongo entries (glucose entries) database'
,ru: 'Clean Mongo entries (glucose entries) database'
,sk: 'Clean Mongo entries (glucose entries) database'
,nl: 'Clean Mongo entries (glucose entries) database'
,ko: 'Clean Mongo entries (glucose entries) database'
,tr: 'Clean Mongo entries (glucose entries) database'
,zh_cn: 'Clean Mongo entries (glucose entries) database'
,zh_tw: 'Clean Mongo entries (glucose entries) database'
} }
,'Delete all documents from entries collection older than 180 days' : { ,'Delete all documents from entries collection older than 180 days' : {
cs: 'Delete all documents from entries collection older than 180 days' hr: 'Obriši sve zapise starije od 180 dana'
,he: 'Delete all documents from entries collection older than 180 days'
,nb: 'Delete all documents from entries collection older than 180 days'
,fr: 'Delete all documents from entries collection older than 180 days'
,ro: 'Delete all documents from entries collection older than 180 days'
,el: 'Delete all documents from entries collection older than 180 days'
,de: 'Delete all documents from entries collection older than 180 days'
,es: 'Delete all documents from entries collection older than 180 days'
,dk: 'Delete all documents from entries collection older than 180 days'
,sv: 'Delete all documents from entries collection older than 180 days'
,bg: 'Delete all documents from entries collection older than 180 days'
,hr: 'Obriši sve zapise starije od 180 dana'
,it: 'Delete all documents from entries collection older than 180 days'
,fi: 'Delete all documents from entries collection older than 180 days'
,pl: 'Delete all documents from entries collection older than 180 days'
,pt: 'Delete all documents from entries collection older than 180 days'
,ru: 'Delete all documents from entries collection older than 180 days'
,sk: 'Delete all documents from entries collection older than 180 days'
,nl: 'Delete all documents from entries collection older than 180 days'
,ko: 'Delete all documents from entries collection older than 180 days'
,tr: 'Delete all documents from entries collection older than 180 days'
,zh_cn: 'Delete all documents from entries collection older than 180 days'
,zh_tw: 'Delete all documents from entries collection older than 180 days'
} }
,'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.' : { ,'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.' : {
cs: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.' hr: 'Ovo briše sve zapise starije od 180 dana. Korisno kada se status baterije uploadera ne osvježava.'
,he: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,nb: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,fr: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,ro: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,el: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,de: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,es: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,dk: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,sv: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,bg: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,hr: 'Ovo briše sve zapise starije od 180 dana. Korisno kada se status baterije uploadera ne osvježava.'
,it: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,fi: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,pl: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,pt: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,ru: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,sk: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,nl: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,ko: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,tr: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,zh_cn: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,zh_tw: 'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
} }
,'Delete old documents' : { ,'Delete old documents' : {
cs: 'Delete old documents' hr: 'Obriši stare zapise'
,he: 'Delete old documents'
,nb: 'Delete old documents'
,fr: 'Delete old documents'
,ro: 'Delete old documents'
,el: 'Delete old documents'
,de: 'Delete old documents'
,es: 'Delete old documents'
,dk: 'Delete old documents'
,sv: 'Delete old documents'
,bg: 'Delete old documents'
,hr: 'Obriši stare zapise'
,it: 'Delete old documents'
,fi: 'Delete old documents'
,pl: 'Delete old documents'
,pt: 'Delete old documents'
,ru: 'Delete old documents'
,sk: 'Delete old documents'
,nl: 'Delete old documents'
,ko: 'Delete old documents'
,tr: 'Delete old documents'
,zh_cn: 'Delete old documents'
,zh_tw: 'Delete old documents'
} }
,'Delete old documents from entries collection?' : { ,'Delete old documents from entries collection?' : {
cs: 'Delete old documents from entries collection?' hr: 'Obriši stare zapise?'
,he: 'Delete old documents from entries collection?'
,nb: 'Delete old documents from entries collection?'
,fr: 'Delete old documents from entries collection?'
,ro: 'Delete old documents from entries collection?'
,el: 'Delete old documents from entries collection?'
,de: 'Delete old documents from entries collection?'
,es: 'Delete old documents from entries collection?'
,dk: 'Delete old documents from entries collection?'
,sv: 'Delete old documents from entries collection?'
,bg: 'Delete old documents from entries collection?'
,hr: 'Obriši stare zapise?'
,it: 'Delete old documents from entries collection?'
,fi: 'Delete old documents from entries collection?'
,pl: 'Delete old documents from entries collection?'
,pt: 'Delete old documents from entries collection?'
,ru: 'Delete old documents from entries collection?'
,sk: 'Delete old documents from entries collection?'
,nl: 'Delete old documents from entries collection?'
,ko: 'Delete old documents from entries collection?'
,tr: 'Delete old documents from entries collection?'
,zh_cn: 'Delete old documents from entries collection?'
,zh_tw: 'Delete old documents from entries collection?'
} }
,'%1 is not a valid number' : { ,'%1 is not a valid number' : {
cs: '%1 is not a valid number' hr: '%1 nije valjan broj'
,he: '%1 is not a valid number'
,nb: '%1 is not a valid number'
,fr: '%1 is not a valid number'
,ro: '%1 is not a valid number'
,el: '%1 is not a valid number'
,de: '%1 is not a valid number'
,es: '%1 is not a valid number'
,dk: '%1 is not a valid number'
,sv: '%1 is not a valid number'
,bg: '%1 is not a valid number'
,hr: '%1 nije valjan broj'
,it: '%1 is not a valid number'
,fi: '%1 is not a valid number'
,pl: '%1 is not a valid number'
,pt: '%1 is not a valid number'
,ru: '%1 is not a valid number'
,sk: '%1 is not a valid number'
,nl: '%1 is not a valid number'
,ko: '%1 is not a valid number'
,tr: '%1 is not a valid number'
,zh_cn: '%1 is not a valid number'
,zh_tw: '%1 is not a valid number'
} }
,'%1 is not a valid number - must be more than 2' : { ,'%1 is not a valid number - must be more than 2' : {
cs: '%1 is not a valid number - must be more than 2' hr: '%1 nije valjan broj - mora biti veći od 2'
,he: '%1 is not a valid number - must be more than 2'
,nb: '%1 is not a valid number - must be more than 2'
,fr: '%1 is not a valid number - must be more than 2'
,ro: '%1 is not a valid number - must be more than 2'
,el: '%1 is not a valid number - must be more than 2'
,de: '%1 is not a valid number - must be more than 2'
,es: '%1 is not a valid number - must be more than 2'
,dk: '%1 is not a valid number - must be more than 2'
,sv: '%1 is not a valid number - must be more than 2'
,bg: '%1 is not a valid number - must be more than 2'
,hr: '%1 nije valjan broj - mora biti veći od 2'
,it: '%1 is not a valid number - must be more than 2'
,fi: '%1 is not a valid number - must be more than 2'
,pl: '%1 is not a valid number - must be more than 2'
,pt: '%1 is not a valid number - must be more than 2'
,ru: '%1 is not a valid number - must be more than 2'
,sk: '%1 is not a valid number - must be more than 2'
,nl: '%1 is not a valid number - must be more than 2'
,ko: '%1 is not a valid number - must be more than 2'
,tr: '%1 is not a valid number - must be more than 2'
,zh_cn: '%1 is not a valid number - must be more than 2'
,zh_tw: '%1 is not a valid number - must be more than 2'
} }
,'Clean Mongo treatments database' : { ,'Clean Mongo treatments database' : {
cs: 'Clean Mongo treatments database' hr: 'Obriši tretmane iz baze'
,he: 'Clean Mongo treatments database'
,nb: 'Clean Mongo treatments database'
,fr: 'Clean Mongo treatments database'
,ro: 'Clean Mongo treatments database'
,el: 'Clean Mongo treatments database'
,de: 'Clean Mongo treatments database'
,es: 'Clean Mongo treatments database'
,dk: 'Clean Mongo treatments database'
,sv: 'Clean Mongo treatments database'
,bg: 'Clean Mongo treatments database'
,hr: 'Obriši tretmane iz baze'
,it: 'Clean Mongo treatments database'
,fi: 'Clean Mongo treatments database'
,pl: 'Clean Mongo treatments database'
,pt: 'Clean Mongo treatments database'
,ru: 'Clean Mongo treatments database'
,sk: 'Clean Mongo treatments database'
,nl: 'Clean Mongo treatments database'
,ko: 'Clean Mongo treatments database'
,tr: 'Clean Mongo treatments database'
,zh_cn: 'Clean Mongo treatments database'
,zh_tw: 'Clean Mongo treatments database'
} }
,'Delete all documents from treatments collection older than 180 days' : { ,'Delete all documents from treatments collection older than 180 days' : {
cs: 'Delete all documents from treatments collection older than 180 days' hr: 'Obriši tretmane starije od 180 dana iz baze'
,he: 'Delete all documents from treatments collection older than 180 days'
,nb: 'Delete all documents from treatments collection older than 180 days'
,fr: 'Delete all documents from treatments collection older than 180 days'
,ro: 'Delete all documents from treatments collection older than 180 days'
,el: 'Delete all documents from treatments collection older than 180 days'
,de: 'Delete all documents from treatments collection older than 180 days'
,es: 'Delete all documents from treatments collection older than 180 days'
,dk: 'Delete all documents from treatments collection older than 180 days'
,sv: 'Delete all documents from treatments collection older than 180 days'
,bg: 'Delete all documents from treatments collection older than 180 days'
,hr: 'Obriši tretmane starije od 180 dana iz baze'
,it: 'Delete all documents from treatments collection older than 180 days'
,fi: 'Delete all documents from treatments collection older than 180 days'
,pl: 'Delete all documents from treatments collection older than 180 days'
,pt: 'Delete all documents from treatments collection older than 180 days'
,ru: 'Delete all documents from treatments collection older than 180 days'
,sk: 'Delete all documents from treatments collection older than 180 days'
,nl: 'Delete all documents from treatments collection older than 180 days'
,ko: 'Delete all documents from treatments collection older than 180 days'
,tr: 'Delete all documents from treatments collection older than 180 days'
,zh_cn: 'Delete all documents from treatments collection older than 180 days'
,zh_tw: 'Delete all documents from treatments collection older than 180 days'
} }
,'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.' : { ,'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.' : {
cs: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.' hr: 'Ovo briše sve tretmane starije od 180 dana iz baze. Korisno kada se status baterije uploadera ne osvježava.'
,he: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,nb: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,fr: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,ro: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,el: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,de: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,es: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,dk: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,sv: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,bg: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,hr: 'Ovo briše sve tretmane starije od 180 dana iz baze. Korisno kada se status baterije uploadera ne osvježava.'
,it: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,fi: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,pl: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,pt: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,ru: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,sk: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,nl: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,ko: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,tr: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,zh_cn: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
,zh_tw: 'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.'
} }
,'Delete old documents from treatments collection?' : { ,'Delete old documents from treatments collection?' : {
cs: 'Delete old documents from treatments collection?' hr: 'Obriši stare tretmane?'
,he: 'Delete old documents from treatments collection?'
,nb: 'Delete old documents from treatments collection?'
,fr: 'Delete old documents from treatments collection?'
,ro: 'Delete old documents from treatments collection?'
,el: 'Delete old documents from treatments collection?'
,de: 'Delete old documents from treatments collection?'
,es: 'Delete old documents from treatments collection?'
,dk: 'Delete old documents from treatments collection?'
,sv: 'Delete old documents from treatments collection?'
,bg: 'Delete old documents from treatments collection?'
,hr: 'Obriši stare tretmane?'
,it: 'Delete old documents from treatments collection?'
,fi: 'Delete old documents from treatments collection?'
,pl: 'Delete old documents from treatments collection?'
,pt: 'Delete old documents from treatments collection?'
,ru: 'Delete old documents from treatments collection?'
,sk: 'Delete old documents from treatments collection?'
,nl: 'Delete old documents from treatments collection?'
,ko: 'Delete old documents from treatments collection?'
,tr: 'Delete old documents from treatments collection?'
,zh_cn: 'Delete old documents from treatments collection?'
,zh_tw: 'Delete old documents from treatments collection?'
} }
,'Admin Tools' : { ,'Admin Tools' : {
cs: 'Nástroje pro správu' cs: 'Nástroje pro správu'
@@ -10106,7 +9737,7 @@ function init() {
} }
,'Profile is going to be saved in newer format used in Nightscout 0.9.0 and above and will not be usable in older versions anymore.\nAre you sure?' : { ,'Profile is going to be saved in newer format used in Nightscout 0.9.0 and above and will not be usable in older versions anymore.\nAre you sure?' : {
cs: 'Profil bude uložen v novějším formátu používaném v Nightscoutu 0.9.0 a novějších. Již nebude použitelný se starší verzí.\nJste si jistý?' cs: 'Profil bude uložen v novějším formátu používaném v Nightscoutu 0.9.0 a novějších. Již nebude použitelný se starší verzí.\nJste si jistý?'
,he: 'הפרופיל עומד להישמר בתבנית חדשה יותר בשימוש ב- Nightscout 0.9.0 ומעלה ולא יהיה ניתן להשתמש בו בגרסאות ישנות יותר. \ האם אתה בטוח? ' ,he: 'הפרופיל עומד להישמר בתבנית חדשה יותר בשימוש ב- Nightscout 0.9.0 ומעלה ולא יהיה ניתן להשתמש בו בגרסאות ישנות יותר. \n האם אתה בטוח? '
,el: 'Το προφίλ πρόκειται να αποθηκευτεί με τη νέα του μορφή (έκδοση Nighscout 0.9.0 και πάνω) και δεν πρόκειται να μπορεί να χρησιμοποιηθεί σε παλαιότερες εκδόσεις. \nΕίστε σίγουροι?' ,el: 'Το προφίλ πρόκειται να αποθηκευτεί με τη νέα του μορφή (έκδοση Nighscout 0.9.0 και πάνω) και δεν πρόκειται να μπορεί να χρησιμοποιηθεί σε παλαιότερες εκδόσεις. \nΕίστε σίγουροι?'
,fr: 'Le profil va être sauvegardé dans un nouveau format utilisé par Nightscout 0.9.0 et suivants, et il ne pourra plus être utilisé par les versions antérieures. \nÊtes-vous sûr?' ,fr: 'Le profil va être sauvegardé dans un nouveau format utilisé par Nightscout 0.9.0 et suivants, et il ne pourra plus être utilisé par les versions antérieures. \nÊtes-vous sûr?'
,ro: 'Profilul va fi salvat într-un format nou, folosit în Nightscout 0.9.0 și superior și nu va mai fi posibilă folosirea pentru versiunile mai vechi.\nSunteți de acord?' ,ro: 'Profilul va fi salvat într-un format nou, folosit în Nightscout 0.9.0 și superior și nu va mai fi posibilă folosirea pentru versiunile mai vechi.\nSunteți de acord?'
@@ -10130,7 +9761,7 @@ function init() {
} }
,'Wrong profile setting.\nNo profile defined to displayed time.\nRedirecting to profile editor to create new profile.' : { ,'Wrong profile setting.\nNo profile defined to displayed time.\nRedirecting to profile editor to create new profile.' : {
cs: 'Chybě nastavený profil.\nNení definovaný žádný platný profil k času zobrazení.\nProvádím přesměrování na editor profilu.' cs: 'Chybě nastavený profil.\nNení definovaný žádný platný profil k času zobrazení.\nProvádím přesměrování na editor profilu.'
,he: 'הגדרת פרופיל שגוי. \ N פרופיל מוגדר לזמן המוצג. מפנה מחדש לעורך פרופיל כדי ליצור פרופיל חדש. ' ,he: 'הגדרת פרופיל שגוי. \n פרופיל מוגדר לזמן המוצג. מפנה מחדש לעורך פרופיל כדי ליצור פרופיל חדש. '
,el: 'Λάθος προφίλ. Παρακαλώ δημιουργήστε ένα νέο προφίλ' ,el: 'Λάθος προφίλ. Παρακαλώ δημιουργήστε ένα νέο προφίλ'
,fr: 'Erreur de réglage de profil. \nAucun profil défini pour indiquer l\'heure. \nRedirection vers la création d\'un nouveau profil. ' ,fr: 'Erreur de réglage de profil. \nAucun profil défini pour indiquer l\'heure. \nRedirection vers la création d\'un nouveau profil. '
,de: 'Falsche Profileinstellung.\nKein Profil festgelegt zur angezeigten Zeit.\n Weiter zum Profileditor, um ein neues Profil zu erstellen.' ,de: 'Falsche Profileinstellung.\nKein Profil festgelegt zur angezeigten Zeit.\n Weiter zum Profileditor, um ein neues Profil zu erstellen.'
@@ -10709,7 +10340,6 @@ function init() {
,nb: 'Hver enkelt rolle vil ha en eller flere rettigheter. <em>*</em>-rettigheten er wildcard. Rettigheter settes hierarkisk med <em>:</em> som separator.' ,nb: 'Hver enkelt rolle vil ha en eller flere rettigheter. <em>*</em>-rettigheten er wildcard. Rettigheter settes hierarkisk med <em>:</em> som separator.'
,fi: 'Jokaisella roolilla on yksi tai useampia oikeuksia. <em>*</em> on jokeri (tunnistuu kaikkina oikeuksina), oikeudet ovat hierarkia joka käyttää <em>:</em> merkkiä erottimena.' ,fi: 'Jokaisella roolilla on yksi tai useampia oikeuksia. <em>*</em> on jokeri (tunnistuu kaikkina oikeuksina), oikeudet ovat hierarkia joka käyttää <em>:</em> merkkiä erottimena.'
,de: 'Jede Rolle hat eine oder mehrere Berechtigungen. Die <em>*</em> Berechtigung ist ein Platzhalter, Berechtigungen sind hierachrchisch mit <em>:</em> als Separator.' ,de: 'Jede Rolle hat eine oder mehrere Berechtigungen. Die <em>*</em> Berechtigung ist ein Platzhalter, Berechtigungen sind hierachrchisch mit <em>:</em> als Separator.'
,sv: 'Hver rolle vil have en eller flere rettigheder. <em>*</em> er en joker, rettigheder sættes hierakisk med <em>:</em> som skilletegn.'
,es: 'Cada Rol tiene uno o más permisos. El permiso <em>*</em> es un marcador de posición y los permisos son jerárquicos con <em>:</em> como separador.' ,es: 'Cada Rol tiene uno o más permisos. El permiso <em>*</em> es un marcador de posición y los permisos son jerárquicos con <em>:</em> como separador.'
,pt: 'Cada função terá uma ou mais permissões. A permissão <em>*</em> é um wildcard, permissões são uma hierarquia utilizando <em>*</em> como um separador.' ,pt: 'Cada função terá uma ou mais permissões. A permissão <em>*</em> é um wildcard, permissões são uma hierarquia utilizando <em>*</em> como um separador.'
,sk: 'Každá rola má 1 alebo viac oprávnení. Oprávnenie <em>*</em> je zástupný znak, oprávnenia sú hierarchie používajúce <em>:</em> ako oddelovač.' ,sk: 'Každá rola má 1 alebo viac oprávnení. Oprávnenie <em>*</em> je zástupný znak, oprávnenia sú hierarchie používajúce <em>:</em> ako oddelovač.'
@@ -11994,7 +11624,6 @@ function init() {
,sk: 'Nadbytok inzulínu o %1U viac ako je potrebné na dosiahnutie spodnej cieľovej hranice. Neráta sa so sacharidmi.' ,sk: 'Nadbytok inzulínu o %1U viac ako je potrebné na dosiahnutie spodnej cieľovej hranice. Neráta sa so sacharidmi.'
,ko: '낮은 혈당 목표에 도달하기 위해 필요한 인슐린양보다 %1U의 인슐린 양이 초과 되었고 탄수화물 양이 초과되지 않았습니다.' ,ko: '낮은 혈당 목표에 도달하기 위해 필요한 인슐린양보다 %1U의 인슐린 양이 초과 되었고 탄수화물 양이 초과되지 않았습니다.'
,it: 'L\'eccesso d\'insulina equivalente %1U più che necessari per raggiungere l\'obiettivo basso, non rappresentano i carboidrati.' ,it: 'L\'eccesso d\'insulina equivalente %1U più che necessari per raggiungere l\'obiettivo basso, non rappresentano i carboidrati.'
,nl: 'Overschot insuline %1U meer dan nodig om het laag doel te bereiken, geen rekening gehouden met KH'
,tr: 'Fazla insülin: Karbonhidratları dikkate alınmadan, alt hedefe ulaşmak için gerekenden %1U\'den daha fazla' //??? ,tr: 'Fazla insülin: Karbonhidratları dikkate alınmadan, alt hedefe ulaşmak için gerekenden %1U\'den daha fazla' //???
,zh_cn: '胰岛素超过至血糖下限目标所需剂量%1单位,不计算碳水化合物' ,zh_cn: '胰岛素超过至血糖下限目标所需剂量%1单位,不计算碳水化合物'
, pl: 'Nadmiar insuliny, %1J więcej niż potrzeba, aby osiągnąć cel dolnej granicy, nie biorąc pod uwagę węglowodanów' , pl: 'Nadmiar insuliny, %1J więcej niż potrzeba, aby osiągnąć cel dolnej granicy, nie biorąc pod uwagę węglowodanów'
@@ -12427,7 +12056,7 @@ function init() {
,sv: 'Applicerad' ,sv: 'Applicerad'
,nb: 'Satt inn' ,nb: 'Satt inn'
,fi: 'Asetettu' ,fi: 'Asetettu'
,es: 'Insertar' ,es: 'Insertado'
,pt: 'Inserido' ,pt: 'Inserido'
,sk: 'Zavedený' ,sk: 'Zavedený'
,ko: '삽입된' ,ko: '삽입된'
@@ -12453,7 +12082,7 @@ function init() {
,nb: 'Nål alder' ,nb: 'Nål alder'
,fi: 'KIKÄ' ,fi: 'KIKÄ'
,pt: 'ICAT' ,pt: 'ICAT'
,es: 'Carb.desde' ,es: 'Cánula desde'
,sk: 'SET' ,sk: 'SET'
,ko: '주입세트사용기간' ,ko: '주입세트사용기간'
,it: 'CAGE' ,it: 'CAGE'
@@ -12477,7 +12106,7 @@ function init() {
,nb: 'Aktive karbohydrater' ,nb: 'Aktive karbohydrater'
,fi: 'AH' ,fi: 'AH'
,pt: 'COB' ,pt: 'COB'
,es: 'Carbohidratos activos' ,es: 'Carb. activos'
,sk: 'SACH' ,sk: 'SACH'
,ko: 'COB' ,ko: 'COB'
,it: 'COB' ,it: 'COB'
@@ -14490,6 +14119,7 @@ function init() {
} }
if (options && options.params) { if (options && options.params) {
for (var i = 0; i < options.params.length; i++) { for (var i = 0; i < options.params.length; i++) {
// eslint-disable-next-line no-useless-escape
var r = new RegExp('\%' + (i+1), 'g'); var r = new RegExp('\%' + (i+1), 'g');
translated = translated.replace(r, options.params[i]); translated = translated.replace(r, options.params[i]);
} }
+20 -25
View File
@@ -15,7 +15,7 @@ var Alarm = function(level, group, label) {
}; };
// list of alarms with their thresholds // list of alarms with their thresholds
var alarms = { }; var alarms = {};
function init (env, ctx) { function init (env, ctx) {
function notifications () { function notifications () {
@@ -41,7 +41,7 @@ function init (env, ctx) {
var sendClear = false; var sendClear = false;
for (var level = 1; level <=2; level++) { for (var level = 1; level <= 2; level++) {
var alarm = getAlarm(level, group); var alarm = getAlarm(level, group);
if (alarm.lastEmitTime) { if (alarm.lastEmitTime) {
console.info('auto acking ' + alarm.level, ' - ', group); console.info('auto acking ' + alarm.level, ' - ', group);
@@ -51,7 +51,7 @@ function init (env, ctx) {
} }
if (sendClear) { if (sendClear) {
var notify = {clear: true, title: 'All Clear', message: 'Auto ack\'d alarm(s)', group: group}; var notify = { clear: true, title: 'All Clear', message: 'Auto ack\'d alarm(s)', group: group };
ctx.bus.emit('notification', notify); ctx.bus.emit('notification', notify);
logEmitEvent(notify); logEmitEvent(notify);
} }
@@ -70,8 +70,8 @@ function init (env, ctx) {
var requests = {}; var requests = {};
notifications.initRequests = function initRequests ( ) { notifications.initRequests = function initRequests () {
requests = { notifies: [] , snoozes: []}; requests = { notifies: [], snoozes: [] };
}; };
notifications.initRequests(); notifications.initRequests();
@@ -82,12 +82,12 @@ function init (env, ctx) {
*/ */
notifications.findHighestAlarm = function findHighestAlarm (group) { notifications.findHighestAlarm = function findHighestAlarm (group) {
group = group || 'default'; group = group || 'default';
var filtered = _.filter(requests.notifies, {group: group}); var filtered = _.filter(requests.notifies, { group: group });
return _.find(filtered, {level: levels.URGENT}) || _.find(filtered, {level: levels.WARN}); return _.find(filtered, { level: levels.URGENT }) || _.find(filtered, { level: levels.WARN });
}; };
notifications.findUnSnoozeable = function findUnSnoozeable ( ) { notifications.findUnSnoozeable = function findUnSnoozeable () {
return _.filter(requests.notifies, function (notify) { return _.filter(requests.notifies, function(notify) {
return notify.level <= levels.INFO || notify.isAnnouncement; return notify.level <= levels.INFO || notify.isAnnouncement;
}); });
}; };
@@ -95,7 +95,7 @@ function init (env, ctx) {
notifications.snoozedBy = function snoozedBy (notify) { notifications.snoozedBy = function snoozedBy (notify) {
if (notify.isAnnouncement) { return false; } if (notify.isAnnouncement) { return false; }
var filtered = _.filter(requests.snoozes, {group: notify.group}); var filtered = _.filter(requests.snoozes, { group: notify.group });
if (_.isEmpty(filtered)) { return false; } if (_.isEmpty(filtered)) { return false; }
@@ -107,13 +107,8 @@ function init (env, ctx) {
return _.last(sorted); return _.last(sorted);
}; };
notifications.registerGroup = function registerGroup (group) {
if (groups.indexOf(group) < 0) {
groups.push(group);
}
};
notifications.requestNotify = function requestNotify (notify) { notifications.requestNotify = function requestNotify (notify) {
// eslint-disable-next-line no-prototype-builtins
if (!notify.hasOwnProperty('level') || !notify.title || !notify.message || !notify.plugin) { if (!notify.hasOwnProperty('level') || !notify.title || !notify.message || !notify.plugin) {
console.error(new Error('Unable to request notification, since the notify isn\'t complete: ' + JSON.stringify(notify))); console.error(new Error('Unable to request notification, since the notify isn\'t complete: ' + JSON.stringify(notify)));
return; return;
@@ -135,7 +130,7 @@ function init (env, ctx) {
requests.snoozes.push(snooze); requests.snoozes.push(snooze);
}; };
notifications.process = function process ( ) { notifications.process = function process () {
var notifyGroups = _.map(requests.notifies, function eachNotify (notify) { var notifyGroups = _.map(requests.notifies, function eachNotify (notify) {
return notify.group; return notify.group;
@@ -205,7 +200,7 @@ function init (env, ctx) {
}; };
function ifTestModeThen(callback) { function ifTestModeThen (callback) {
if (env.testMode) { if (env.testMode) {
return callback(); return callback();
} else { } else {
@@ -213,15 +208,15 @@ function init (env, ctx) {
} }
} }
notifications.resetStateForTests = function resetStateForTests ( ) { notifications.resetStateForTests = function resetStateForTests () {
ifTestModeThen(function doResetStateForTests ( ) { ifTestModeThen(function doResetStateForTests () {
console.info('resetting notifications state for tests'); console.info('resetting notifications state for tests');
alarms = {}; alarms = {};
}); });
}; };
notifications.getAlarmForTests = function getAlarmForTests (level, group) { notifications.getAlarmForTests = function getAlarmForTests (level, group) {
return ifTestModeThen(function doResetStateForTests ( ) { return ifTestModeThen(function doResetStateForTests () {
group = group || 'default'; group = group || 'default';
var alarm = getAlarm(level, group); var alarm = getAlarm(level, group);
console.info('got alarm for tests: ', alarm); console.info('got alarm for tests: ', alarm);
@@ -249,7 +244,7 @@ function init (env, ctx) {
}; };
} }
function logEmitEvent(notify) { function logEmitEvent (notify) {
var type = notify.level >= levels.WARN ? 'ALARM' : (notify.clear ? 'ALL CLEAR' : 'NOTIFICATION'); var type = notify.level >= levels.WARN ? 'ALARM' : (notify.clear ? 'ALL CLEAR' : 'NOTIFICATION');
console.info([ console.info([
logTimestamp() + '\tEMITTING ' + type + ':' logTimestamp() + '\tEMITTING ' + type + ':'
@@ -257,7 +252,7 @@ function init (env, ctx) {
].join('\n')); ].join('\n'));
} }
function logSnoozingEvent(highestAlarm, snoozedBy) { function logSnoozingEvent (highestAlarm, snoozedBy) {
console.info([ console.info([
logTimestamp() + '\tSNOOZING ALARM:' logTimestamp() + '\tSNOOZING ALARM:'
, ' ' + JSON.stringify(notifyToView(highestAlarm)) , ' ' + JSON.stringify(notifyToView(highestAlarm))
@@ -267,11 +262,11 @@ function init (env, ctx) {
} }
//TODO: we need a common logger, but until then... //TODO: we need a common logger, but until then...
function logTimestamp ( ) { function logTimestamp () {
return (new Date).toISOString(); return (new Date).toISOString();
} }
return notifications(); return notifications();
} }
module.exports = init; module.exports = init;
+16 -17
View File
@@ -15,6 +15,7 @@ var AR = [-0.723, 1.716];
//TODO: move this to css //TODO: move this to css
var AR2_COLOR = 'cyan'; var AR2_COLOR = 'cyan';
// eslint-disable-next-line no-unused-vars
function init (ctx) { function init (ctx) {
var ar2 = { var ar2 = {
@@ -23,7 +24,7 @@ function init (ctx) {
, pluginType: 'forecast' , pluginType: 'forecast'
}; };
function buildTitle(prop, sbx) { function buildTitle (prop, sbx) {
var rangeLabel = prop.eventName ? sbx.translate(prop.eventName, { ci: true }).toUpperCase() : sbx.translate('Check BG'); var rangeLabel = prop.eventName ? sbx.translate(prop.eventName, { ci: true }).toUpperCase() : sbx.translate('Check BG');
var title = sbx.levels.toDisplay(prop.level) + ', ' + rangeLabel; var title = sbx.levels.toDisplay(prop.level) + ', ' + rangeLabel;
@@ -35,7 +36,7 @@ function init (ctx) {
} }
ar2.setProperties = function setProperties (sbx) { ar2.setProperties = function setProperties (sbx) {
sbx.offerProperty('ar2', function setAR2 ( ) { sbx.offerProperty('ar2', function setAR2 () {
var prop = { var prop = {
forecast: ar2.forecast(sbx) forecast: ar2.forecast(sbx)
@@ -49,7 +50,7 @@ function init (ctx) {
} }
var predicted = prop.forecast && prop.forecast.predicted; var predicted = prop.forecast && prop.forecast.predicted;
var scaled = predicted && _.map(predicted, function(p) { return sbx.scaleEntry(p) } ); var scaled = predicted && _.map(predicted, function(p) { return sbx.scaleEntry(p) });
if (scaled && scaled.length >= 3) { if (scaled && scaled.length >= 3) {
prop.displayLine = 'BG 15m: ' + scaled[2] + ' ' + sbx.unitsLabel; prop.displayLine = 'BG 15m: ' + scaled[2] + ' ' + sbx.unitsLabel;
@@ -106,8 +107,8 @@ function init (ctx) {
return result; return result;
}; };
ar2.updateVisualisation = function updateVisualisation(sbx) { ar2.updateVisualisation = function updateVisualisation (sbx) {
sbx.pluginBase.addForecastPoints(ar2.forecastCone(sbx), {type: 'ar2', label: 'AR2 Forecast'}); sbx.pluginBase.addForecastPoints(ar2.forecastCone(sbx), { type: 'ar2', label: 'AR2 Forecast' });
}; };
ar2.forecastCone = function forecastCone (sbx) { ar2.forecastCone = function forecastCone (sbx) {
@@ -118,7 +119,7 @@ function init (ctx) {
var coneFactor = getConeFactor(sbx); var coneFactor = getConeFactor(sbx);
function pushConePoints(result, step) { function pushConePoints (result, step) {
var next = incrementAR2(result); var next = incrementAR2(result);
//offset from points so they are at a unique time //offset from points so they are at a unique time
@@ -172,8 +173,8 @@ function init (ctx) {
ar2.alexa = { ar2.alexa = {
intentHandlers: [{ intentHandlers: [{
intent: 'MetricNow' intent: 'MetricNow'
, routableSlot:'metric' , routableSlot: 'metric'
, slots:['ar2 forecast', 'forecast'] , slots: ['ar2 forecast', 'forecast']
, intentHandler: alexaAr2Handler , intentHandler: alexaAr2Handler
}] }]
}; };
@@ -181,7 +182,7 @@ function init (ctx) {
return ar2; return ar2;
} }
function checkForecast(forecast, sbx) { function checkForecast (forecast, sbx) {
var result = undefined; var result = undefined;
if (forecast && forecast.avgLoss > URGENT_THRESHOLD) { if (forecast && forecast.avgLoss > URGENT_THRESHOLD) {
@@ -199,7 +200,7 @@ function checkForecast(forecast, sbx) {
} }
function selectEventType (prop, sbx) { function selectEventType (prop, sbx) {
var predicted = prop.forecast && _.map(prop.forecast.predicted, function(p) { return sbx.scaleEntry(p) } ); var predicted = prop.forecast && _.map(prop.forecast.predicted, function(p) { return sbx.scaleEntry(p) });
var in20mins = predicted && predicted.length >= 4 ? predicted[3] : undefined; var in20mins = predicted && predicted.length >= 4 ? predicted[3] : undefined;
@@ -239,7 +240,7 @@ function getConeFactor (sbx) {
return value; return value;
} }
function okToForecast(sbx) { function okToForecast (sbx) {
var bgnow = sbx.properties.bgnow; var bgnow = sbx.properties.bgnow;
var delta = sbx.properties.delta; var delta = sbx.properties.delta;
@@ -273,7 +274,7 @@ function incrementAR2 (result) {
}; };
} }
function pushPoint(result) { function pushPoint (result) {
var next = incrementAR2(result); var next = incrementAR2(result);
next.points.push(ar2Point( next.points.push(ar2Point(
@@ -284,8 +285,7 @@ function pushPoint(result) {
return next; return next;
} }
function ar2Point (next, options) {
function ar2Point(next, options) {
var step = options.step || 0; var step = options.step || 0;
var coneFactor = options.coneFactor || 0; var coneFactor = options.coneFactor || 0;
var offset = options.offset || 0; var offset = options.offset || 0;
@@ -301,16 +301,15 @@ function ar2Point(next, options) {
}; };
} }
function buildDebug (prop, sbx) { function buildDebug (prop, sbx) {
return prop.forecast && { return prop.forecast && {
forecast: { forecast: {
avgLoss: prop.forecast.avgLoss avgLoss: prop.forecast.avgLoss
, predicted: _.map(prop.forecast.predicted, function(p) { return sbx.scaleEntry(p) }).join(', ') , predicted: _.map(prop.forecast.predicted, function(p) { return sbx.scaleEntry(p) }).join(', ')
} }
}; };
} }
function log10(val) { return Math.log(val) / Math.LN10; } function log10 (val) { return Math.log(val) / Math.LN10; }
module.exports = init; module.exports = init;
+1
View File
@@ -8,6 +8,7 @@ function init() {
, pluginType: 'drawer' , pluginType: 'drawer'
}; };
// eslint-disable-next-line no-unused-vars
careportal.getEventTypes = function getEventTypes (sbx) { careportal.getEventTypes = function getEventTypes (sbx) {
//TODO: use sbx and new CAREPORTAL_EVENTTYPE_GROUPS="core temps combo dad sensor site etc" //TODO: use sbx and new CAREPORTAL_EVENTTYPE_GROUPS="core temps combo dad sensor site etc"
+31 -34
View File
@@ -4,7 +4,7 @@ var _ = require('lodash')
, moment = require('moment') , moment = require('moment')
, times = require('../times'); , times = require('../times');
function init(ctx) { function init (ctx) {
var translate = ctx.language.translate; var translate = ctx.language.translate;
var iob = require('./iob')(ctx); var iob = require('./iob')(ctx);
@@ -16,15 +16,15 @@ function init(ctx) {
cob.RECENCY_THRESHOLD = times.mins(30).msecs; cob.RECENCY_THRESHOLD = times.mins(30).msecs;
cob.setProperties = function setProperties(sbx) { cob.setProperties = function setProperties (sbx) {
sbx.offerProperty('cob', function setCOB ( ) { sbx.offerProperty('cob', function setCOB () {
return cob.cobTotal(sbx.data.treatments, sbx.data.devicestatus, sbx.data.profile, sbx.time); return cob.cobTotal(sbx.data.treatments, sbx.data.devicestatus, sbx.data.profile, sbx.time);
}); });
}; };
cob.cobTotal = function cobTotal(treatments, devicestatus, profile, time, spec_profile) { cob.cobTotal = function cobTotal (treatments, devicestatus, profile, time, spec_profile) {
if (!profile || !profile.hasData()) { if (!profile || !profile.hasData()) {
console.warn('For the COB plugin to function you need a treatment profile'); console.warn('For the COB plugin to function you need a treatment profile');
return {}; return {};
} }
@@ -55,7 +55,7 @@ function init(ctx) {
return addDisplay(result); return addDisplay(result);
}; };
function addDisplay(cob) { function addDisplay (cob) {
if (_.isEmpty(cob) || cob.cob === undefined) { if (_.isEmpty(cob) || cob.cob === undefined) {
return {}; return {};
} }
@@ -82,7 +82,7 @@ function init(ctx) {
var recentMills = time - cob.RECENCY_THRESHOLD; var recentMills = time - cob.RECENCY_THRESHOLD;
return _.chain(devicestatus) return _.chain(devicestatus)
.filter(function (cobStatus) { .filter(function(cobStatus) {
return cobStatus.mills <= futureMills && cobStatus.mills >= recentMills; return cobStatus.mills <= futureMills && cobStatus.mills >= recentMills;
}) })
.map(cob.fromDeviceStatus) .map(cob.fromDeviceStatus)
@@ -95,7 +95,7 @@ function init(ctx) {
cob.COBDeviceStatusesInTimeRange = function COBDeviceStatusesInTimeRange (devicestatus, from, to) { cob.COBDeviceStatusesInTimeRange = function COBDeviceStatusesInTimeRange (devicestatus, from, to) {
return _.chain(devicestatus) return _.chain(devicestatus)
.filter(function (cobStatus) { .filter(function(cobStatus) {
return cobStatus.mills > from && cobStatus.mills < to; return cobStatus.mills > from && cobStatus.mills < to;
}) })
.map(cob.fromDeviceStatus) .map(cob.fromDeviceStatus)
@@ -104,7 +104,7 @@ function init(ctx) {
.value(); .value();
}; };
cob.fromDeviceStatus = function fromDeviceStatus(devicestatusEntry) { cob.fromDeviceStatus = function fromDeviceStatus (devicestatusEntry) {
var cobObj; var cobObj;
if (_.get(devicestatusEntry, 'openaps') !== undefined) { if (_.get(devicestatusEntry, 'openaps') !== undefined) {
@@ -140,7 +140,7 @@ function init(ctx) {
cob: lastCOB cob: lastCOB
, source: 'OpenAPS' , source: 'OpenAPS'
, device: devicestatusEntry.device , device: devicestatusEntry.device
, mills: lastMoment.valueOf( ) , mills: lastMoment.valueOf()
}; };
} else if (_.get(devicestatusEntry, 'loop.cob') !== undefined) { } else if (_.get(devicestatusEntry, 'loop.cob') !== undefined) {
cobObj = devicestatusEntry.loop.cob; cobObj = devicestatusEntry.loop.cob;
@@ -148,7 +148,7 @@ function init(ctx) {
cob: cobObj.cob cob: cobObj.cob
, source: 'Loop' , source: 'Loop'
, device: devicestatusEntry.device , device: devicestatusEntry.device
, mills: moment(cobObj.timestamp).valueOf( ) , mills: moment(cobObj.timestamp).valueOf()
}; };
} else { } else {
return {}; return {};
@@ -164,7 +164,7 @@ function init(ctx) {
var isDecaying = 0; var isDecaying = 0;
var lastDecayedBy = 0; var lastDecayedBy = 0;
_.each(treatments, function eachTreatment(treatment) { _.each(treatments, function eachTreatment (treatment) {
if (treatment.carbs && treatment.mills < time) { if (treatment.carbs && treatment.mills < time) {
lastCarbs = treatment; lastCarbs = treatment;
var cCalc = cob.cobCalc(treatment, profile, lastDecayedBy, time, spec_profile); var cCalc = cob.cobCalc(treatment, profile, lastDecayedBy, time, spec_profile);
@@ -175,7 +175,7 @@ function init(ctx) {
var actEnd = iob.calcTotal(treatments, devicestatus, profile, cCalc.decayedBy, spec_profile).activity; var actEnd = iob.calcTotal(treatments, devicestatus, profile, cCalc.decayedBy, spec_profile).activity;
var avgActivity = (actStart + actEnd) / 2; var avgActivity = (actStart + actEnd) / 2;
// units: g = BG * scalar / BG / U * g / U // units: g = BG * scalar / BG / U * g / U
var delayedCarbs = ( avgActivity * liverSensRatio / profile.getSensitivity(treatment.mills, spec_profile) ) * profile.getCarbRatio(treatment.mills, spec_profile); var delayedCarbs = (avgActivity * liverSensRatio / profile.getSensitivity(treatment.mills, spec_profile)) * profile.getCarbRatio(treatment.mills, spec_profile);
var delayMinutes = Math.round(delayedCarbs / profile.getCarbAbsorptionRate(treatment.mills, spec_profile) * 60); var delayMinutes = Math.round(delayedCarbs / profile.getCarbAbsorptionRate(treatment.mills, spec_profile) * 60);
if (delayMinutes > 0) { if (delayMinutes > 0) {
cCalc.decayedBy.setMinutes(cCalc.decayedBy.getMinutes() + delayMinutes); cCalc.decayedBy.setMinutes(cCalc.decayedBy.getMinutes() + delayMinutes);
@@ -211,7 +211,7 @@ function init(ctx) {
}; };
}; };
cob.carbImpact = function carbImpact(rawCarbImpact, insulinImpact) { cob.carbImpact = function carbImpact (rawCarbImpact, insulinImpact) {
var liverSensRatio = 1.0; var liverSensRatio = 1.0;
var liverCarbImpactMax = 0.7; var liverCarbImpactMax = 0.7;
var liverCarbImpact = Math.min(liverCarbImpactMax, liverSensRatio * insulinImpact); var liverCarbImpact = Math.min(liverCarbImpactMax, liverSensRatio * insulinImpact);
@@ -219,12 +219,12 @@ function init(ctx) {
var netCarbImpact = Math.max(0, rawCarbImpact - liverCarbImpact); var netCarbImpact = Math.max(0, rawCarbImpact - liverCarbImpact);
var totalImpact = netCarbImpact - insulinImpact; var totalImpact = netCarbImpact - insulinImpact;
return { return {
netCarbImpact: netCarbImpact, netCarbImpact: netCarbImpact
totalImpact: totalImpact , totalImpact: totalImpact
}; };
}; };
cob.cobCalc = function cobCalc(treatment, profile, lastDecayedBy, time, spec_profile) { cob.cobCalc = function cobCalc (treatment, profile, lastDecayedBy, time, spec_profile) {
var delay = 20; var delay = 20;
var isDecaying = 0; var isDecaying = 0;
@@ -232,7 +232,7 @@ function init(ctx) {
if (treatment.carbs) { if (treatment.carbs) {
var carbTime = new Date(treatment.mills); var carbTime = new Date(treatment.mills);
var carbs_hr = profile.getCarbAbsorptionRate(treatment.mills, spec_profile); var carbs_hr = profile.getCarbAbsorptionRate(treatment.mills, spec_profile);
var carbs_min = carbs_hr / 60; var carbs_min = carbs_hr / 60;
@@ -241,31 +241,28 @@ function init(ctx) {
decayedBy.setMinutes(decayedBy.getMinutes() + Math.max(delay, minutesleft) + treatment.carbs / carbs_min); decayedBy.setMinutes(decayedBy.getMinutes() + Math.max(delay, minutesleft) + treatment.carbs / carbs_min);
if (delay > minutesleft) { if (delay > minutesleft) {
initialCarbs = parseInt(treatment.carbs); initialCarbs = parseInt(treatment.carbs);
} } else {
else {
initialCarbs = parseInt(treatment.carbs) + minutesleft * carbs_min; initialCarbs = parseInt(treatment.carbs) + minutesleft * carbs_min;
} }
var startDecay = new Date(carbTime); var startDecay = new Date(carbTime);
startDecay.setMinutes(carbTime.getMinutes() + delay); startDecay.setMinutes(carbTime.getMinutes() + delay);
if (time < lastDecayedBy || time > startDecay) { if (time < lastDecayedBy || time > startDecay) {
isDecaying = 1; isDecaying = 1;
} } else {
else {
isDecaying = 0; isDecaying = 0;
} }
return { return {
initialCarbs: initialCarbs, initialCarbs: initialCarbs
decayedBy: decayedBy, , decayedBy: decayedBy
isDecaying: isDecaying, , isDecaying: isDecaying
carbTime: carbTime , carbTime: carbTime
}; };
} } else {
else {
return ''; return '';
} }
}; };
cob.updateVisualisation = function updateVisualisation(sbx) { cob.updateVisualisation = function updateVisualisation (sbx) {
var prop = sbx.properties.cob; var prop = sbx.properties.cob;
@@ -273,16 +270,16 @@ function init(ctx) {
var displayCob = Math.round(prop.cob * 10) / 10; var displayCob = Math.round(prop.cob * 10) / 10;
var info = [ ]; var info = [];
if (prop.treatmentCOB !== undefined && prop.treatmentCOB.cob) { if (prop.treatmentCOB !== undefined && prop.treatmentCOB.cob) {
info.push({label: translate('Careportal COB'), value: Math.round(prop.treatmentCOB.cob * 10) / 10}); info.push({ label: translate('Careportal COB'), value: Math.round(prop.treatmentCOB.cob * 10) / 10 });
} }
var lastCarbs = prop.lastCarbs || (prop.treatmentCOB && prop.treatmentCOB.lastCarbs); var lastCarbs = prop.lastCarbs || (prop.treatmentCOB && prop.treatmentCOB.lastCarbs);
if (lastCarbs) { if (lastCarbs) {
var when = new Date(lastCarbs.mills).toLocaleString(); var when = new Date(lastCarbs.mills).toLocaleString();
var amount = lastCarbs.carbs + 'g'; var amount = lastCarbs.carbs + 'g';
info.push({label: translate('Last Carbs'), value: amount + ' @ ' + when}); info.push({ label: translate('Last Carbs'), value: amount + ' @ ' + when });
} }
sbx.pluginBase.updatePillText(sbx, { sbx.pluginBase.updatePillText(sbx, {
@@ -305,8 +302,8 @@ function init(ctx) {
cob.alexa = { cob.alexa = {
intentHandlers: [{ intentHandlers: [{
intent: 'MetricNow' intent: 'MetricNow'
, routableSlot:'metric' , routableSlot: 'metric'
, slots:['cob', 'carbs on board', 'carbohydrates on board'] , slots: ['cob', 'carbs on board', 'carbohydrates on board']
, intentHandler: alexaCOBHandler , intentHandler: alexaCOBHandler
}] }]
}; };
+36 -37
View File
@@ -7,12 +7,12 @@ var _get = require('lodash/get');
var _isArray = require('lodash/isArray'); var _isArray = require('lodash/isArray');
var _map = require('lodash/map'); var _map = require('lodash/map');
function init(ctx) { function init (ctx) {
var allPlugins = [], var allPlugins = []
enabledPlugins = []; , enabledPlugins = [];
function plugins(name) { function plugins (name) {
if (name) { if (name) {
return _find(allPlugins, { return _find(allPlugins, {
name: name name: name
@@ -75,18 +75,18 @@ function init(ctx) {
, require('./basalprofile')(ctx) , require('./basalprofile')(ctx)
]; ];
plugins.registerServerDefaults = function registerServerDefaults() { plugins.registerServerDefaults = function registerServerDefaults () {
plugins.register(serverDefaultPlugins); plugins.register(serverDefaultPlugins);
return plugins; return plugins;
}; };
plugins.registerClientDefaults = function registerClientDefaults() { plugins.registerClientDefaults = function registerClientDefaults () {
plugins.register(clientDefaultPlugins); plugins.register(clientDefaultPlugins);
return plugins; return plugins;
}; };
plugins.register = function register(all) { plugins.register = function register (all) {
_each(all, function eachPlugin(plugin) { _each(all, function eachPlugin (plugin) {
allPlugins.push(plugin); allPlugins.push(plugin);
}); });
@@ -94,58 +94,57 @@ function init(ctx) {
var enable = _get(ctx, 'settings.enable'); var enable = _get(ctx, 'settings.enable');
function isEnabled(plugin) { function isEnabled (plugin) {
//TODO: unify client/server env/app //TODO: unify client/server env/app
return enable && enable.indexOf(plugin.name) > -1; return enable && enable.indexOf(plugin.name) > -1;
} }
_each(allPlugins, function eachPlugin(plugin) { _each(allPlugins, function eachPlugin (plugin) {
plugin.enabled = isEnabled(plugin); plugin.enabled = isEnabled(plugin);
if (plugin.enabled) { if (plugin.enabled) {
enabledPlugins.push(plugin); enabledPlugins.push(plugin);
} }
}); });
}; };
plugins.isPluginEnabled = function isPluginEnabled(pluginName) { plugins.isPluginEnabled = function isPluginEnabled (pluginName) {
var p = _.find(enabledPlugins, 'name', pluginName); var p = _find(enabledPlugins, 'name', pluginName);
return (p !== null); return (p !== null);
} }
plugins.getPlugin = function getPlugin(pluginName) { plugins.getPlugin = function getPlugin (pluginName) {
return _.find(enabledPlugins, 'name', pluginName); return _find(enabledPlugins, 'name', pluginName);
} }
plugins.eachPlugin = function eachPlugin(f) { plugins.eachPlugin = function eachPlugin (f) {
_each(allPlugins, f); _each(allPlugins, f);
}; };
plugins.eachEnabledPlugin = function eachEnabledPlugin(f) { plugins.eachEnabledPlugin = function eachEnabledPlugin (f) {
_each(enabledPlugins, f); _each(enabledPlugins, f);
}; };
//these plugins are either always on or have custom settings //these plugins are either always on or have custom settings
plugins.specialPlugins = 'ar2 bgnow delta direction timeago upbat rawbg errorcodes profile'; plugins.specialPlugins = 'ar2 bgnow delta direction timeago upbat rawbg errorcodes profile';
plugins.shownPlugins = function (sbx) { plugins.shownPlugins = function(sbx) {
return _filter(enabledPlugins, function filterPlugins(plugin) { return _filter(enabledPlugins, function filterPlugins (plugin) {
return plugins.specialPlugins.indexOf(plugin.name) > -1 || (sbx && sbx.showPlugins && sbx.showPlugins.indexOf(plugin.name) > -1); return plugins.specialPlugins.indexOf(plugin.name) > -1 || (sbx && sbx.showPlugins && sbx.showPlugins.indexOf(plugin.name) > -1);
}); });
}; };
plugins.eachShownPlugins = function eachShownPlugins(sbx, f) { plugins.eachShownPlugins = function eachShownPlugins (sbx, f) {
_each(plugins.shownPlugins(sbx), f); _each(plugins.shownPlugins(sbx), f);
}; };
plugins.hasShownType = function hasShownType(pluginType, sbx) { plugins.hasShownType = function hasShownType (pluginType, sbx) {
return _find(plugins.shownPlugins(sbx), function findWithType(plugin) { return _find(plugins.shownPlugins(sbx), function findWithType (plugin) {
return plugin.pluginType === pluginType; return plugin.pluginType === pluginType;
}) !== undefined; }) !== undefined;
}; };
plugins.setProperties = function setProperties(sbx) { plugins.setProperties = function setProperties (sbx) {
plugins.eachEnabledPlugin(function eachPlugin(plugin) { plugins.eachEnabledPlugin(function eachPlugin (plugin) {
if (plugin.setProperties) { if (plugin.setProperties) {
try { try {
plugin.setProperties(sbx.withExtendedSettings(plugin)); plugin.setProperties(sbx.withExtendedSettings(plugin));
@@ -156,8 +155,8 @@ function init(ctx) {
}); });
}; };
plugins.checkNotifications = function checkNotifications(sbx) { plugins.checkNotifications = function checkNotifications (sbx) {
plugins.eachEnabledPlugin(function eachPlugin(plugin) { plugins.eachEnabledPlugin(function eachPlugin (plugin) {
if (plugin.checkNotifications) { if (plugin.checkNotifications) {
try { try {
plugin.checkNotifications(sbx.withExtendedSettings(plugin)); plugin.checkNotifications(sbx.withExtendedSettings(plugin));
@@ -168,8 +167,8 @@ function init(ctx) {
}); });
}; };
plugins.visualizeAlarm = function visualizeAlarm(sbx, alarm, alarmMessage) { plugins.visualizeAlarm = function visualizeAlarm (sbx, alarm, alarmMessage) {
plugins.eachShownPlugins(sbx, function eachPlugin(plugin) { plugins.eachShownPlugins(sbx, function eachPlugin (plugin) {
if (plugin.visualizeAlarm) { if (plugin.visualizeAlarm) {
try { try {
plugin.visualizeAlarm(sbx.withExtendedSettings(plugin), alarm, alarmMessage); plugin.visualizeAlarm(sbx.withExtendedSettings(plugin), alarm, alarmMessage);
@@ -180,8 +179,8 @@ function init(ctx) {
}); });
}; };
plugins.updateVisualisations = function updateVisualisations(sbx) { plugins.updateVisualisations = function updateVisualisations (sbx) {
plugins.eachShownPlugins(sbx, function eachPlugin(plugin) { plugins.eachShownPlugins(sbx, function eachPlugin (plugin) {
if (plugin.updateVisualisation) { if (plugin.updateVisualisation) {
try { try {
plugin.updateVisualisation(sbx.withExtendedSettings(plugin)); plugin.updateVisualisation(sbx.withExtendedSettings(plugin));
@@ -192,9 +191,9 @@ function init(ctx) {
}); });
}; };
plugins.getAllEventTypes = function getAllEventTypes(sbx) { plugins.getAllEventTypes = function getAllEventTypes (sbx) {
var all = []; var all = [];
plugins.eachEnabledPlugin(function eachPlugin(plugin) { plugins.eachEnabledPlugin(function eachPlugin (plugin) {
if (plugin.getEventTypes) { if (plugin.getEventTypes) {
var eventTypes = plugin.getEventTypes(sbx.withExtendedSettings(plugin)); var eventTypes = plugin.getEventTypes(sbx.withExtendedSettings(plugin));
if (_isArray(eventTypes)) { if (_isArray(eventTypes)) {
@@ -206,15 +205,15 @@ function init(ctx) {
return all; return all;
}; };
plugins.enabledPluginNames = function enabledPluginNames() { plugins.enabledPluginNames = function enabledPluginNames () {
return _map(enabledPlugins, function mapped(plugin) { return _map(enabledPlugins, function mapped (plugin) {
return plugin.name; return plugin.name;
}).join(' '); }).join(' ');
}; };
plugins.extendedClientSettings = function extendedClientSettings(allExtendedSettings) { plugins.extendedClientSettings = function extendedClientSettings (allExtendedSettings) {
var clientSettings = {}; var clientSettings = {};
_each(clientDefaultPlugins, function eachClientPlugin(plugin) { _each(clientDefaultPlugins, function eachClientPlugin (plugin) {
clientSettings[plugin.name] = allExtendedSettings[plugin.name]; clientSettings[plugin.name] = allExtendedSettings[plugin.name];
}); });
@@ -228,4 +227,4 @@ function init(ctx) {
} }
module.exports = init; module.exports = init;
+67 -73
View File
@@ -7,7 +7,7 @@ var levels = require('../levels');
// var ALL_STATUS_FIELDS = ['status-symbol', 'status-label', 'iob', 'freq', 'rssi']; Unused variable // var ALL_STATUS_FIELDS = ['status-symbol', 'status-label', 'iob', 'freq', 'rssi']; Unused variable
function init(ctx) { function init (ctx) {
var utils = require('../utils')(ctx); var utils = require('../utils')(ctx);
var loop = { var loop = {
@@ -18,7 +18,7 @@ function init(ctx) {
var firstPrefs = true; var firstPrefs = true;
loop.getPrefs = function getPrefs(sbx) { loop.getPrefs = function getPrefs (sbx) {
var prefs = { var prefs = {
warn: sbx.extendedSettings.warn ? sbx.extendedSettings.warn : 30 warn: sbx.extendedSettings.warn ? sbx.extendedSettings.warn : 30
@@ -35,7 +35,7 @@ function init(ctx) {
}; };
loop.setProperties = function setProperties (sbx) { loop.setProperties = function setProperties (sbx) {
sbx.offerProperty('loop', function setLoop ( ) { sbx.offerProperty('loop', function setLoop () {
return loop.analyzeData(sbx); return loop.analyzeData(sbx);
}); });
}; };
@@ -45,14 +45,14 @@ function init(ctx) {
var recentMills = sbx.time - times.hours(recentHours).msecs; var recentMills = sbx.time - times.hours(recentHours).msecs;
var recentData = _.chain(sbx.data.devicestatus) var recentData = _.chain(sbx.data.devicestatus)
.filter(function (status) { .filter(function(status) {
return ('loop' in status) && sbx.entryMills(status) <= sbx.time && sbx.entryMills(status) >= recentMills; return ('loop' in status) && sbx.entryMills(status) <= sbx.time && sbx.entryMills(status) >= recentMills;
}).value( ); }).value();
var prefs = loop.getPrefs(sbx); var prefs = loop.getPrefs(sbx);
var recent = moment(sbx.time).subtract(prefs.warn / 2, 'minutes'); var recent = moment(sbx.time).subtract(prefs.warn / 2, 'minutes');
function getDisplayForStatus (status) { function getDisplayForStatus (status) {
var desc = { var desc = {
symbol: '⚠' symbol: '⚠'
@@ -146,7 +146,7 @@ function init(ctx) {
return result; return result;
}; };
loop.checkNotifications = function checkNotifications(sbx) { loop.checkNotifications = function checkNotifications (sbx) {
var prefs = loop.getPrefs(sbx); var prefs = loop.getPrefs(sbx);
if (!prefs.enableAlerts) { return; } if (!prefs.enableAlerts) { return; }
@@ -182,9 +182,9 @@ function init(ctx) {
return (value != null) ? prefix + value : ''; return (value != null) ? prefix + value : '';
} }
var events = [ ]; var events = [];
function addRecommendedTempBasal() { function addRecommendedTempBasal () {
if (prop.lastLoop && prop.lastLoop.recommendedTempBasal) { if (prop.lastLoop && prop.lastLoop.recommendedTempBasal) {
var recommendedTempBasal = prop.lastLoop.recommendedTempBasal; var recommendedTempBasal = prop.lastLoop.recommendedTempBasal;
@@ -196,7 +196,7 @@ function init(ctx) {
valueParts = concatIOB(valueParts); valueParts = concatIOB(valueParts);
valueParts = concatCOB(valueParts); valueParts = concatCOB(valueParts);
valueParts = concatEventualBG (valueParts); valueParts = concatEventualBG(valueParts);
valueParts = concatRecommendedBolus(valueParts); valueParts = concatRecommendedBolus(valueParts);
events.push({ events.push({
@@ -206,48 +206,48 @@ function init(ctx) {
} }
} }
function addRSSI() { function addRSSI () {
var mostRecent = ""; var mostRecent = "";
var pumpRSSI = ""; var pumpRSSI = "";
var bleRSSI = ""; var bleRSSI = "";
var reportRSSI = ""; var reportRSSI = "";
_.forEach(sbx.data.devicestatus, function(entry) { _.forEach(sbx.data.devicestatus, function(entry) {
if (entry.radioAdapter) { if (entry.radioAdapter) {
var entryMoment = moment(entry.created_at); var entryMoment = moment(entry.created_at);
if (mostRecent == "") { if (mostRecent == "") {
mostRecent = entryMoment; mostRecent = entryMoment;
if (entry.radioAdapter.pumpRSSI) { if (entry.radioAdapter.pumpRSSI) {
pumpRSSI = entry.radioAdapter.pumpRSSI; pumpRSSI = entry.radioAdapter.pumpRSSI;
} }
if (entry.radioAdapter.RSSI) { if (entry.radioAdapter.RSSI) {
bleRSSI = entry.radioAdapter.RSSI; bleRSSI = entry.radioAdapter.RSSI;
} }
} }
if (mostRecent < entryMoment) { if (mostRecent < entryMoment) {
mostRecent = entryMoment; mostRecent = entryMoment;
if (entry.radioAdapter.pumpRSSI) { if (entry.radioAdapter.pumpRSSI) {
pumpRSSI = entry.radioAdapter.pumpRSSI; pumpRSSI = entry.radioAdapter.pumpRSSI;
} }
if (entry.radioAdapter.RSSI) { if (entry.radioAdapter.RSSI) {
bleRSSI = entry.radioAdapter.RSSI; bleRSSI = entry.radioAdapter.RSSI;
} }
} }
} }
}); });
if (bleRSSI != "") { if (bleRSSI != "") {
reportRSSI = "BLE RSSI: " + bleRSSI + " "; reportRSSI = "BLE RSSI: " + bleRSSI + " ";
} }
if (pumpRSSI != "") { if (pumpRSSI != "") {
reportRSSI = reportRSSI + "Pump RSSI: " + pumpRSSI; reportRSSI = reportRSSI + "Pump RSSI: " + pumpRSSI;
} }
if (reportRSSI != "") { if (reportRSSI != "") {
events.push({ events.push({
time: mostRecent time: mostRecent
@@ -256,21 +256,21 @@ function init(ctx) {
} }
} }
function addLastEnacted() { function addLastEnacted () {
if (prop.lastEnacted) { if (prop.lastEnacted) {
var canceled = prop.lastEnacted.rate === 0 && prop.lastEnacted.duration === 0; var canceled = prop.lastEnacted.rate === 0 && prop.lastEnacted.duration === 0;
var valueParts = [ var valueParts = [
, '<b>Temp Basal' + (canceled ? ' Canceled' : ' Started') + '</b>' '<b>Temp Basal' + (canceled ? ' Canceled' : ' Started') + '</b>'
, canceled ? '' : ' ' + prop.lastEnacted.rate.toFixed(2) + 'U/hour for ' + prop.lastEnacted.duration + 'm' , canceled ? '' : ' ' + prop.lastEnacted.rate.toFixed(2) + 'U/hour for ' + prop.lastEnacted.duration + 'm'
, valueString(', ', prop.lastEnacted.reason) , valueString(', ', prop.lastEnacted.reason)
]; ];
valueParts = concatIOB(valueParts); valueParts = concatIOB(valueParts);
valueParts = concatCOB(valueParts); valueParts = concatCOB(valueParts);
valueParts = concatEventualBG (valueParts); valueParts = concatEventualBG(valueParts);
valueParts = concatRecommendedBolus(valueParts); valueParts = concatRecommendedBolus(valueParts);
events.push({ events.push({
time: prop.lastEnacted.moment time: prop.lastEnacted.moment
@@ -284,7 +284,9 @@ function init(ctx) {
var iob = prop.lastLoop.iob; var iob = prop.lastLoop.iob;
valueParts = valueParts.concat([ valueParts = valueParts.concat([
', IOB: ' ', IOB: '
, sbx.roundInsulinForDisplayFormat(iob.iob) + 'U' , sbx.roundInsulinForDisplayFormat(iob.iob) + 'U'
, iob.basaliob ? ', Basal IOB ' + sbx.roundInsulinForDisplayFormat(iob.basaliob) + 'U' : '' , iob.basaliob ? ', Basal IOB ' + sbx.roundInsulinForDisplayFormat(iob.basaliob) + 'U' : ''
]); ]);
} }
@@ -294,7 +296,6 @@ function init(ctx) {
function concatCOB (valueParts) { function concatCOB (valueParts) {
if (prop.lastLoop && prop.lastLoop.cob) { if (prop.lastLoop && prop.lastLoop.cob) {
var cob = prop.lastLoop.cob;
var cob = prop.lastLoop.cob.cob; var cob = prop.lastLoop.cob.cob;
cob = Math.round(cob); cob = Math.round(cob);
valueParts = valueParts.concat([ valueParts = valueParts.concat([
@@ -309,28 +310,28 @@ function init(ctx) {
function concatEventualBG (valueParts) { function concatEventualBG (valueParts) {
if (prop.lastLoop && prop.lastLoop.predicted) { if (prop.lastLoop && prop.lastLoop.predicted) {
var predictedBGvalues = prop.lastLoop.predicted.values; var predictedBGvalues = prop.lastLoop.predicted.values;
var eventualBG = predictedBGvalues[predictedBGvalues.length-1]; var eventualBG = predictedBGvalues[predictedBGvalues.length - 1];
var maxBG = Math.max.apply(null,predictedBGvalues); var maxBG = Math.max.apply(null, predictedBGvalues);
var minBG = Math.min.apply(null,predictedBGvalues); var minBG = Math.min.apply(null, predictedBGvalues);
var eventualBGscaled = sbx.settings.units === 'mmol' ? var eventualBGscaled = sbx.settings.units === 'mmol' ?
sbx.roundBGToDisplayFormat(sbx.scaleMgdl(eventualBG)) : eventualBG; sbx.roundBGToDisplayFormat(sbx.scaleMgdl(eventualBG)) : eventualBG;
var maxBGscaled = sbx.settings.units === 'mmol' ? var maxBGscaled = sbx.settings.units === 'mmol' ?
sbx.roundBGToDisplayFormat(sbx.scaleMgdl(maxBG)) : maxBG; sbx.roundBGToDisplayFormat(sbx.scaleMgdl(maxBG)) : maxBG;
var minBGscaled = sbx.settings.units === 'mmol' ? var minBGscaled = sbx.settings.units === 'mmol' ?
sbx.roundBGToDisplayFormat(sbx.scaleMgdl(minBG)) : minBG; sbx.roundBGToDisplayFormat(sbx.scaleMgdl(minBG)) : minBG;
valueParts = valueParts.concat([ valueParts = valueParts.concat([
', Predicted Min-Max BG: ' ', Predicted Min-Max BG: '
, minBGscaled , minBGscaled
, '-' , '-'
, maxBGscaled , maxBGscaled
,', Eventual BG: ' , ', Eventual BG: '
, eventualBGscaled , eventualBGscaled
]); ]);
} }
return valueParts; return valueParts;
} }
function concatRecommendedBolus (valueParts) { function concatRecommendedBolus (valueParts) {
if (prop.lastLoop && prop.lastLoop.recommendedBolus) { if (prop.lastLoop && prop.lastLoop.recommendedBolus) {
@@ -342,13 +343,13 @@ function init(ctx) {
} }
return valueParts; return valueParts;
} }
function getForecastPoints ( ) { function getForecastPoints () {
var points = [ ]; var points = [];
function toPoints (startTime, offset) { function toPoints (startTime, offset) {
return function toPoint (value, index) { return function toPoint (value, index) {
return { return {
mgdl: value mgdl: value
, color: '#ff00ff' , color: '#ff00ff'
@@ -364,12 +365,6 @@ function init(ctx) {
if (predicted.values) { if (predicted.values) {
points = points.concat(_.map(predicted.values, toPoints(startTime, 0))); points = points.concat(_.map(predicted.values, toPoints(startTime, 0)));
} }
// if (prop.lastPredBGs.IOB) {
// points = points.concat(_.map(prop.lastPredBGs.IOB, toPoints(moment, 3000)));
// }
// if (prop.lastPredBGs.COB) {
// points = points.concat(_.map(prop.lastPredBGs.COB, toPoints(moment, 7000)));
// }
} }
return points; return points;
@@ -386,12 +381,12 @@ function init(ctx) {
} else if ('looping' === prop.display.code) { } else if ('looping' === prop.display.code) {
addLastEnacted(); addLastEnacted();
} else { } else {
addRecommendedTempBasal(); addRecommendedTempBasal();
} }
addRSSI(); addRSSI();
var sorted = _.sortBy(events, function toMill(event) { var sorted = _.sortBy(events, function toMill (event) {
return event.time.valueOf(); return event.time.valueOf();
}).reverse(); }).reverse();
@@ -411,7 +406,7 @@ function init(ctx) {
var eventualBGValue = ''; var eventualBGValue = '';
if (prop.lastLoop && prop.lastLoop.predicted) { if (prop.lastLoop && prop.lastLoop.predicted) {
var predictedBGvalues = prop.lastLoop.predicted.values; var predictedBGvalues = prop.lastLoop.predicted.values;
var eventualBG = predictedBGvalues[predictedBGvalues.length-1]; var eventualBG = predictedBGvalues[predictedBGvalues.length - 1];
if (sbx.settings.units === 'mmol') { if (sbx.settings.units === 'mmol') {
eventualBG = sbx.roundBGToDisplayFormat(sbx.scaleMgdl(eventualBG)); eventualBG = sbx.roundBGToDisplayFormat(sbx.scaleMgdl(eventualBG));
} }
@@ -432,7 +427,7 @@ function init(ctx) {
var forecastPoints = getForecastPoints(); var forecastPoints = getForecastPoints();
if (forecastPoints && forecastPoints.length > 0) { if (forecastPoints && forecastPoints.length > 0) {
sbx.pluginBase.addForecastPoints(forecastPoints, {type: 'loop', label: 'Loop Forecasts'}); sbx.pluginBase.addForecastPoints(forecastPoints, { type: 'loop', label: 'Loop Forecasts' });
} }
}; };
@@ -470,7 +465,7 @@ function init(ctx) {
} }
} }
function alexaLastLoopHandler(next, slots, sbx) { function alexaLastLoopHandler (next, slots, sbx) {
console.log(JSON.stringify(sbx.properties.loop.lastLoop)); console.log(JSON.stringify(sbx.properties.loop.lastLoop));
var response = 'The last successful loop was ' + moment(sbx.properties.loop.lastOkMoment).from(moment(sbx.time)); var response = 'The last successful loop was ' + moment(sbx.properties.loop.lastOkMoment).from(moment(sbx.time));
next('Last loop', response); next('Last loop', response);
@@ -523,5 +518,4 @@ function init(ctx) {
} }
module.exports = init; module.exports = init;
+71 -48
View File
@@ -7,7 +7,7 @@ var levels = require('../levels');
// var ALL_STATUS_FIELDS = ['status-symbol', 'status-label', 'iob', 'meal-assist', 'freq', 'rssi']; Unused variable // var ALL_STATUS_FIELDS = ['status-symbol', 'status-label', 'iob', 'meal-assist', 'freq', 'rssi']; Unused variable
function init(ctx) { function init (ctx) {
var utils = require('../utils')(ctx); var utils = require('../utils')(ctx);
var openaps = { var openaps = {
name: 'openaps' name: 'openaps'
@@ -17,7 +17,7 @@ function init(ctx) {
var translate = ctx.language.translate; var translate = ctx.language.translate;
var firstPrefs = true; var firstPrefs = true;
openaps.getPrefs = function getPrefs(sbx) { openaps.getPrefs = function getPrefs (sbx) {
function cleanList (value) { function cleanList (value) {
return decodeURIComponent(value || '').toLowerCase().split(' '); return decodeURIComponent(value || '').toLowerCase().split(' ');
@@ -27,7 +27,6 @@ function init(ctx) {
return _.isEmpty(list) || _.isEmpty(list[0]); return _.isEmpty(list) || _.isEmpty(list[0]);
} }
var fields = cleanList(sbx.extendedSettings.fields); var fields = cleanList(sbx.extendedSettings.fields);
fields = isEmpty(fields) ? ['status-symbol', 'status-label', 'iob', 'meal-assist', 'rssi'] : fields; fields = isEmpty(fields) ? ['status-symbol', 'status-label', 'iob', 'meal-assist', 'rssi'] : fields;
@@ -51,7 +50,7 @@ function init(ctx) {
}; };
openaps.setProperties = function setProperties (sbx) { openaps.setProperties = function setProperties (sbx) {
sbx.offerProperty('openaps', function setOpenAPS ( ) { sbx.offerProperty('openaps', function setOpenAPS () {
return openaps.analyzeData(sbx); return openaps.analyzeData(sbx);
}); });
}; };
@@ -61,10 +60,10 @@ function init(ctx) {
var recentMills = sbx.time - times.hours(recentHours).msecs; var recentMills = sbx.time - times.hours(recentHours).msecs;
var recentData = _.chain(sbx.data.devicestatus) var recentData = _.chain(sbx.data.devicestatus)
.filter(function (status) { .filter(function(status) {
return ('openaps' in status) && sbx.entryMills(status) <= sbx.time && sbx.entryMills(status) >= recentMills; return ('openaps' in status) && sbx.entryMills(status) <= sbx.time && sbx.entryMills(status) >= recentMills;
}) })
.map(function (status) { .map(function(status) {
if (status.openaps && _.isArray(status.openaps.iob) && status.openaps.iob.length > 0) { if (status.openaps && _.isArray(status.openaps.iob) && status.openaps.iob.length > 0) {
status.openaps.iob = status.openaps.iob[0]; status.openaps.iob = status.openaps.iob[0];
if (status.openaps.iob.time) { if (status.openaps.iob.time) {
@@ -73,7 +72,7 @@ function init(ctx) {
} }
return status; return status;
}) })
.value( ); .value();
var prefs = openaps.getPrefs(sbx); var prefs = openaps.getPrefs(sbx);
var recent = moment(sbx.time).subtract(prefs.warn / 2, 'minutes'); var recent = moment(sbx.time).subtract(prefs.warn / 2, 'minutes');
@@ -88,7 +87,7 @@ function init(ctx) {
, lastPredBGs: null , lastPredBGs: null
}; };
function getDevice(status) { function getDevice (status) {
var uri = status.device || 'device'; var uri = status.device || 'device';
var device = result.seenDevices[uri]; var device = result.seenDevices[uri];
@@ -105,7 +104,7 @@ function init(ctx) {
function toMoments (status) { function toMoments (status) {
return { return {
when: moment(status.mills) when: moment(status.mills)
, enacted: status.openaps.enacted && status.openaps.enacted.timestamp && (status.openaps.enacted.recieved || status.openaps.enacted.received) && moment(status.openaps.enacted.timestamp) , enacted: status.openaps.enacted && status.openaps.enacted.timestamp && (status.openaps.enacted.recieved || status.openaps.enacted.received) && moment(status.openaps.enacted.timestamp)
, notEnacted: status.openaps.enacted && status.openaps.enacted.timestamp && !(status.openaps.enacted.recieved || status.openaps.enacted.received) && moment(status.openaps.enacted.timestamp) , notEnacted: status.openaps.enacted && status.openaps.enacted.timestamp && !(status.openaps.enacted.recieved || status.openaps.enacted.received) && moment(status.openaps.enacted.timestamp)
, suggested: status.openaps.suggested && status.openaps.suggested.timestamp && moment(status.openaps.suggested.timestamp) , suggested: status.openaps.suggested && status.openaps.suggested.timestamp && moment(status.openaps.suggested.timestamp)
@@ -113,7 +112,7 @@ function init(ctx) {
}; };
} }
function momentsToLoopStatus (moments, noWarning) { function momentsToLoopStatus (moments, noWarning) {
var status = { var status = {
symbol: '⚠' symbol: '⚠'
@@ -122,8 +121,7 @@ function init(ctx) {
}; };
if (moments.notEnacted && ( if (moments.notEnacted && (
(moments.enacted && moments.notEnacted.isAfter(moments.enacted)) || (!moments.enacted && moments.notEnacted.isAfter(recent))) (moments.enacted && moments.notEnacted.isAfter(moments.enacted)) || (!moments.enacted && moments.notEnacted.isAfter(recent)))) {
) {
status.symbol = 'x'; status.symbol = 'x';
status.code = 'notenacted'; status.code = 'notenacted';
status.label = 'Not Enacted'; status.label = 'Not Enacted';
@@ -160,7 +158,7 @@ function init(ctx) {
enacted.moment = moment(enacted.timestamp); enacted.moment = moment(enacted.timestamp);
result.lastEnacted = enacted; result.lastEnacted = enacted;
if (enacted.predBGs && (!result.lastPredBGs || enacted.moment.isAfter(result.lastPredBGs.moment))) { if (enacted.predBGs && (!result.lastPredBGs || enacted.moment.isAfter(result.lastPredBGs.moment))) {
result.lastPredBGs = _.isArray(enacted.predBGs) ? {values: enacted.predBGs} : enacted.predBGs; result.lastPredBGs = _.isArray(enacted.predBGs) ? { values: enacted.predBGs } : enacted.predBGs;
result.lastPredBGs.moment = enacted.moment; result.lastPredBGs.moment = enacted.moment;
} }
} }
@@ -175,7 +173,7 @@ function init(ctx) {
suggested.moment = moment(suggested.timestamp); suggested.moment = moment(suggested.timestamp);
result.lastSuggested = suggested; result.lastSuggested = suggested;
if (suggested.predBGs && (!result.lastPredBGs || suggested.moment.isAfter(result.lastPredBGs.moment))) { if (suggested.predBGs && (!result.lastPredBGs || suggested.moment.isAfter(result.lastPredBGs.moment))) {
result.lastPredBGs = _.isArray(suggested.predBGs) ? {values: suggested.predBGs} : suggested.predBGs; result.lastPredBGs = _.isArray(suggested.predBGs) ? { values: suggested.predBGs } : suggested.predBGs;
result.lastPredBGs.moment = suggested.moment; result.lastPredBGs.moment = suggested.moment;
} }
} }
@@ -203,11 +201,11 @@ function init(ctx) {
result.lastEventualBG = result.lastSuggested.eventualBG; result.lastEventualBG = result.lastSuggested.eventualBG;
} }
} else if (result.lastEnacted && result.lastEnacted.moment) { } else if (result.lastEnacted && result.lastEnacted.moment) {
result.lastLoopMoment = result.lastEnacted.moment; result.lastLoopMoment = result.lastEnacted.moment;
result.lastEventualBG = result.lastEnacted.eventualBG; result.lastEventualBG = result.lastEnacted.eventualBG;
} else if (result.lastSuggested && result.lastSuggested.moment) { } else if (result.lastSuggested && result.lastSuggested.moment) {
result.lastLoopMoment = result.lastSuggested.moment; result.lastLoopMoment = result.lastSuggested.moment;
result.lastEventualBG = result.lastSuggested.eventualBG; result.lastEventualBG = result.lastSuggested.eventualBG;
} }
result.status = momentsToLoopStatus({ result.status = momentsToLoopStatus({
@@ -220,43 +218,68 @@ function init(ctx) {
}; };
openaps.getEventTypes = function getEventTypes (sbx) { openaps.getEventTypes = function getEventTypes (sbx) {
var units = sbx.settings.units; var units = sbx.settings.units;
console.log('units', units); console.log('units', units);
var reasonconf = []; var reasonconf = [];
if (units == 'mmol') { if (units == 'mmol') {
reasonconf.push({ name: translate('Eating Soon'), targetTop: 4.5, targetBottom: 4.5, duration: 60 }); reasonconf.push({ name: translate('Eating Soon'), targetTop: 4.5, targetBottom: 4.5, duration: 60 });
reasonconf.push({ name: translate('Activity'), targetTop: 8, targetBottom: 6.5, duration: 120 }); reasonconf.push({ name: translate('Activity'), targetTop: 8, targetBottom: 6.5, duration: 120 });
} else { } else {
reasonconf.push({ name: translate('Eating Soon'), targetTop: 80, targetBottom: 80, duration: 60 }); reasonconf.push({ name: translate('Eating Soon'), targetTop: 80, targetBottom: 80, duration: 60 });
reasonconf.push({ name: translate('Activity'), targetTop: 140, targetBottom: 120, duration: 120 }); reasonconf.push({ name: translate('Activity'), targetTop: 140, targetBottom: 120, duration: 120 });
} }
reasonconf.push({ name: 'Manual' }); reasonconf.push({ name: 'Manual' });
return [ return [
{ {
val: 'Temporary Target' val: 'Temporary Target'
, name: 'Temporary Target' , name: 'Temporary Target'
, bg: false, insulin: false, carbs: false, prebolus: false, duration: true, percent: false, absolute: false, profile: false, split: false , bg: false
, targets: true, reasons: reasonconf , insulin: false
, carbs: false
, prebolus: false
, duration: true
, percent: false
, absolute: false
, profile: false
, split: false
, targets: true
, reasons: reasonconf
} }
, { , {
val: 'Temporary Target Cancel' val: 'Temporary Target Cancel'
, name: 'Temporary Target Cancel' , name: 'Temporary Target Cancel'
, bg: false, insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false, profile: false, split: false , bg: false
} , insulin: false
, carbs: false
, prebolus: false
, duration: false
, percent: false
, absolute: false
, profile: false
, split: false
}
, { , {
val: 'OpenAPS Offline' val: 'OpenAPS Offline'
, name: 'OpenAPS Offline' , name: 'OpenAPS Offline'
, bg: false, insulin: false, carbs: false, prebolus: false, duration: true, percent: false, absolute: false, profile: false, split: false , bg: false
, insulin: false
, carbs: false
, prebolus: false
, duration: true
, percent: false
, absolute: false
, profile: false
, split: false
} }
]; ];
}; };
openaps.checkNotifications = function checkNotifications(sbx) { openaps.checkNotifications = function checkNotifications (sbx) {
var prefs = openaps.getPrefs(sbx); var prefs = openaps.getPrefs(sbx);
if (!prefs.enableAlerts) { return; } if (!prefs.enableAlerts) { return; }
@@ -283,8 +306,8 @@ function init(ctx) {
} }
}; };
openaps.findOfflineMarker = function findOfflineMarker(sbx) { openaps.findOfflineMarker = function findOfflineMarker (sbx) {
return _.findLast(sbx.data.treatments, function match(treatment) { return _.findLast(sbx.data.treatments, function match (treatment) {
var eventTime = sbx.entryMills(treatment); var eventTime = sbx.entryMills(treatment);
var eventEnd = treatment.duration ? eventTime + times.mins(treatment.duration).msecs : eventTime; var eventEnd = treatment.duration ? eventTime + times.mins(treatment.duration).msecs : eventTime;
return eventTime <= sbx.time && treatment.eventType === 'OpenAPS Offline' && eventEnd >= sbx.time; return eventTime <= sbx.time && treatment.eventType === 'OpenAPS Offline' && eventEnd >= sbx.time;
@@ -302,9 +325,9 @@ function init(ctx) {
return value ? prefix + value : ''; return value ? prefix + value : '';
} }
var events = [ ]; var events = [];
function addSuggestion() { function addSuggestion () {
if (prop.lastSuggested) { if (prop.lastSuggested) {
var valueParts = [ var valueParts = [
@@ -337,11 +360,11 @@ function init(ctx) {
return valueParts; return valueParts;
} }
function getForecastPoints ( ) { function getForecastPoints () {
var points = [ ]; var points = [];
function toPoints (offset, forecastType) { function toPoints (offset, forecastType) {
return function toPoint (value, index) { return function toPoint (value, index) {
return { return {
mgdl: value mgdl: value
, color: '#ff00ff' , color: '#ff00ff'
@@ -413,7 +436,7 @@ function init(ctx) {
} }
if (device.mmtune) { if (device.mmtune) {
var best = _.maxBy(device.mmtune.scanDetails, function (d) { var best = _.maxBy(device.mmtune.scanDetails, function(d) {
return d[2]; return d[2];
}); });
@@ -430,7 +453,7 @@ function init(ctx) {
}); });
}); });
var sorted = _.sortBy(events, function toMill(event) { var sorted = _.sortBy(events, function toMill (event) {
return event.time.valueOf(); return event.time.valueOf();
}).reverse(); }).reverse();
@@ -455,7 +478,7 @@ function init(ctx) {
var forecastPoints = getForecastPoints(); var forecastPoints = getForecastPoints();
if (forecastPoints && forecastPoints.length > 0) { if (forecastPoints && forecastPoints.length > 0) {
sbx.pluginBase.addForecastPoints(forecastPoints, {type: 'openaps', label: 'OpenAPS Forecasts'}); sbx.pluginBase.addForecastPoints(forecastPoints, { type: 'openaps', label: 'OpenAPS Forecasts' });
} }
}; };
@@ -464,8 +487,8 @@ function init(ctx) {
var response = translate('alexaOpenAPSForecast', { var response = translate('alexaOpenAPSForecast', {
params: [ params: [
sbx.properties.openaps.lastEventualBG sbx.properties.openaps.lastEventualBG
]} ]
); });
next('Loop Forecast', response); next('Loop Forecast', response);
} }
} }
+1 -5
View File
@@ -1,10 +1,6 @@
'use strict'; 'use strict';
var levels = require('../levels');
var times = require('../times');
var lastEntryValue; var lastEntryValue;
var lastTime;
var lastMinutes; var lastMinutes;
var lastEntryTime; var lastEntryTime;
@@ -78,7 +74,7 @@ function init(ctx) {
lastMinutes = timeMinutes; lastMinutes = timeMinutes;
var lastEntryString = translate('Last entry {0} minutes ago'); var lastEntryString = translate('Last entry {0} minutes ago');
var sayIt = lastEntryString.replace('{0}', timeMinutes); sayIt = lastEntryString.replace('{0}', timeMinutes);
speech.say(sayIt); speech.say(sayIt);
} }
} }
+91 -106
View File
@@ -12,22 +12,22 @@ var prevBasalTreatment = null;
function init (profileData) { function init (profileData) {
var profile = { }; var profile = {};
var cache = new c.Cache(); var cache = new c.Cache();
profile.loadData = function loadData (profileData) { profile.loadData = function loadData (profileData) {
if (profileData && profileData.length) { if (profileData && profileData.length) {
profile.data = profile.convertToProfileStore(profileData); profile.data = profile.convertToProfileStore(profileData);
_.each(profile.data, function eachProfileRecord (record) { _.each(profile.data, function eachProfileRecord (record) {
_.each(record.store, profile.preprocessProfileOnLoad); _.each(record.store, profile.preprocessProfileOnLoad);
record.mills = new Date(record.startDate).getTime(); record.mills = new Date(record.startDate).getTime();
}); });
} }
}; };
profile.convertToProfileStore = function convertToProfileStore (dataArray) { profile.convertToProfileStore = function convertToProfileStore (dataArray) {
var convertedProfiles = []; var convertedProfiles = [];
_.each(dataArray, function (profile) { _.each(dataArray, function(profile) {
if (!profile.defaultProfile) { if (!profile.defaultProfile) {
var newObject = {}; var newObject = {};
newObject.defaultProfile = 'Default'; newObject.defaultProfile = 'Default';
@@ -51,13 +51,13 @@ function init (profileData) {
profile.timeStringToSeconds = function timeStringToSeconds (time) { profile.timeStringToSeconds = function timeStringToSeconds (time) {
var split = time.split(':'); var split = time.split(':');
return parseInt(split[0])*3600 + parseInt(split[1])*60; return parseInt(split[0]) * 3600 + parseInt(split[1]) * 60;
}; };
// preprocess the timestamps to seconds for a couple orders of magnitude faster operation // preprocess the timestamps to seconds for a couple orders of magnitude faster operation
profile.preprocessProfileOnLoad = function preprocessProfileOnLoad (container) { profile.preprocessProfileOnLoad = function preprocessProfileOnLoad (container) {
_.each(container, function eachValue (value) { _.each(container, function eachValue (value) {
if( Object.prototype.toString.call(value) === '[object Array]' ) { if (Object.prototype.toString.call(value) === '[object Array]') {
profile.preprocessProfileOnLoad(value); profile.preprocessProfileOnLoad(value);
} }
@@ -67,7 +67,7 @@ function init (profileData) {
} }
}); });
}; };
profile.getValueByTime = function getValueByTime (time, valueType, spec_profile) { profile.getValueByTime = function getValueByTime (time, valueType, spec_profile) {
if (!time) { time = Date.now(); } if (!time) { time = Date.now(); }
@@ -77,8 +77,8 @@ function init (profileData) {
var activeTreatment = profile.activeProfileTreatmentToTime(time); var activeTreatment = profile.activeProfileTreatmentToTime(time);
var isCcpProfile = !spec_profile && activeTreatment && activeTreatment.CircadianPercentageProfile; var isCcpProfile = !spec_profile && activeTreatment && activeTreatment.CircadianPercentageProfile;
if (isCcpProfile) { if (isCcpProfile) {
percentage = activeTreatment.percentage; percentage = activeTreatment.percentage;
timeshift = activeTreatment.timeshift; // in hours timeshift = activeTreatment.timeshift; // in hours
} }
var offset = timeshift % 24; var offset = timeshift % 24;
time = time + offset * times.hours(offset).msecs; time = time + offset * times.hours(offset).msecs;
@@ -101,7 +101,7 @@ function init (profileData) {
// TODO: Better warnings to user for missing configuration // TODO: Better warnings to user for missing configuration
var t = profile.getTimezone(spec_profile) ? moment(minuteTime).tz(profile.getTimezone(spec_profile)) : moment(minuteTime); var t = profile.getTimezone(spec_profile) ? moment(minuteTime).tz(profile.getTimezone(spec_profile)) : moment(minuteTime);
// Convert to seconds from midnight // Convert to seconds from midnight
var mmtMidnight = t.clone().startOf('day'); var mmtMidnight = t.clone().startOf('day');
var timeAsSecondsFromMidnight = t.clone().diff(mmtMidnight, 'seconds'); var timeAsSecondsFromMidnight = t.clone().diff(mmtMidnight, 'seconds');
@@ -110,7 +110,7 @@ function init (profileData) {
returnValue = valueContainer; returnValue = valueContainer;
if( Object.prototype.toString.call(valueContainer) === '[object Array]' ) { if (Object.prototype.toString.call(valueContainer) === '[object Array]') {
_.each(valueContainer, function eachValue (value) { _.each(valueContainer, function eachValue (value) {
if (timeAsSecondsFromMidnight >= value.timeAsSeconds) { if (timeAsSecondsFromMidnight >= value.timeAsSeconds) {
returnValue = value.value; returnValue = value.value;
@@ -118,19 +118,19 @@ function init (profileData) {
}); });
} }
if (returnValue) { if (returnValue) {
returnValue = parseFloat(returnValue); returnValue = parseFloat(returnValue);
if (isCcpProfile) { if (isCcpProfile) {
switch (valueType) { switch (valueType) {
case "sens": case "sens":
case "carbratio": case "carbratio":
returnValue = returnValue * 100 / percentage; returnValue = returnValue * 100 / percentage;
break; break;
case "basal": case "basal":
returnValue = returnValue * percentage / 100; returnValue = returnValue * percentage / 100;
break; break;
}
} }
}
} }
cache.put(cacheKey, returnValue, cacheTTL); cache.put(cacheKey, returnValue, cacheTTL);
@@ -186,27 +186,27 @@ function init (profileData) {
}; };
profile.updateTreatments = function updateTreatments (profiletreatments, tempbasaltreatments, combobolustreatments) { profile.updateTreatments = function updateTreatments (profiletreatments, tempbasaltreatments, combobolustreatments) {
profile.profiletreatments = profiletreatments || []; profile.profiletreatments = profiletreatments || [];
profile.tempbasaltreatments = tempbasaltreatments || []; profile.tempbasaltreatments = tempbasaltreatments || [];
// dedupe temp basal events // dedupe temp basal events
profile.tempbasaltreatments = _.uniqBy(profile.tempbasaltreatments, 'mills'); profile.tempbasaltreatments = _.uniqBy(profile.tempbasaltreatments, 'mills');
_.each(profile.tempbasaltreatments, function addDuration (t) { _.each(profile.tempbasaltreatments, function addDuration (t) {
t.endmills = t.mills + times.mins(t.duration || 0).msecs; t.endmills = t.mills + times.mins(t.duration || 0).msecs;
});
profile.tempbasaltreatments.sort(function compareTreatmentMills (a, b) {
return a.mills - b.mills;
}); });
profile.tempbasaltreatments.sort (function compareTreatmentMills (a, b) {
return a.mills - b.mills;
});
profile.combobolustreatments = combobolustreatments || []; profile.combobolustreatments = combobolustreatments || [];
profile.profiletreatments_hash = crypto.createHash('sha1').update(JSON.stringify(profile.profiletreatments)).digest('hex'); profile.profiletreatments_hash = crypto.createHash('sha1').update(JSON.stringify(profile.profiletreatments)).digest('hex');
profile.tempbasaltreatments_hash = crypto.createHash('sha1').update(JSON.stringify(profile.tempbasaltreatments)).digest('hex'); profile.tempbasaltreatments_hash = crypto.createHash('sha1').update(JSON.stringify(profile.tempbasaltreatments)).digest('hex');
profile.combobolustreatments_hash = crypto.createHash('sha1').update(JSON.stringify(profile.combobolustreatments)).digest('hex'); profile.combobolustreatments_hash = crypto.createHash('sha1').update(JSON.stringify(profile.combobolustreatments)).digest('hex');
}; };
profile.activeProfileToTime = function activeProfileToTime (time) { profile.activeProfileToTime = function activeProfileToTime (time) {
if (profile.hasData()) { if (profile.hasData()) {
var timeprofile = profile.data[0].defaultProfile; var timeprofile = profile.data[0].defaultProfile;
@@ -219,7 +219,7 @@ function init (profileData) {
} }
return null; return null;
}; };
profile.activeProfileTreatmentToTime = function activeProfileTreatmentToTime (time) { profile.activeProfileTreatmentToTime = function activeProfileTreatmentToTime (time) {
var cacheKey = 'profile' + time + profile.profiletreatments_hash; var cacheKey = 'profile' + time + profile.profiletreatments_hash;
//var returnValue = profile.timeValueCache[cacheKey]; //var returnValue = profile.timeValueCache[cacheKey];
@@ -231,78 +231,79 @@ function init (profileData) {
var treatment = null; var treatment = null;
if (profile.hasData()) { if (profile.hasData()) {
profile.profiletreatments.forEach( function eachTreatment (t) { profile.profiletreatments.forEach(function eachTreatment (t) {
if (time >= t.mills && t.mills >= profile.data[0].mills) { if (time >= t.mills && t.mills >= profile.data[0].mills) {
var duration = times.mins(t.duration || 0).msecs; var duration = times.mins(t.duration || 0).msecs;
if (duration != 0 && time < t.mills + duration) { if (duration != 0 && time < t.mills + duration) {
treatment = t; treatment = t;
// if profile switch contains json of profile inject it in to store to be findable by profile name // if profile switch contains json of profile inject it in to store to be findable by profile name
if (treatment.profileJson && !profile.data[0].store[treatment.profile]) { if (treatment.profileJson && !profile.data[0].store[treatment.profile]) {
if (treatment.profile.indexOf("@@@@@") < 0) if (treatment.profile.indexOf("@@@@@") < 0)
treatment.profile += "@@@@@" + treatment.mills; treatment.profile += "@@@@@" + treatment.mills;
var json = JSON.parse(treatment.profileJson); let json = JSON.parse(treatment.profileJson);
profile.data[0].store[treatment.profile] = json; profile.data[0].store[treatment.profile] = json;
}
}
if (duration == 0) {
treatment = t;
// if profile switch contains json of profile inject it in to store to be findable by profile name
if (treatment.profileJson && !profile.data[0].store[treatment.profile]) {
if (treatment.profile.indexOf("@@@@@") < 0)
treatment.profile += "@@@@@" + treatment.mills;
var json = JSON.parse(treatment.profileJson);
profile.data[0].store[treatment.profile] = json;
}
} }
} }
if (duration == 0) {
treatment = t;
// if profile switch contains json of profile inject it in to store to be findable by profile name
if (treatment.profileJson && !profile.data[0].store[treatment.profile]) {
if (treatment.profile.indexOf("@@@@@") < 0)
treatment.profile += "@@@@@" + treatment.mills;
let json = JSON.parse(treatment.profileJson);
profile.data[0].store[treatment.profile] = json;
}
}
}
}); });
} }
returnValue = treatment; returnValue = treatment;
cache.put(cacheKey, returnValue, cacheTTL); cache.put(cacheKey, returnValue, cacheTTL);
return returnValue; return returnValue;
}; };
profile.profileSwitchName = function profileSwitchName(name) { profile.profileSwitchName = function profileSwitchName (name) {
var index = name.indexOf("@@@@@"); var index = name.indexOf("@@@@@");
if (index < 0) return name; if (index < 0) return name;
else return name.substring(0, index); else return name.substring(0, index);
} }
profile.tempBasalTreatment = function tempBasalTreatment (time) { profile.tempBasalTreatment = function tempBasalTreatment (time) {
// Most queries for the data in reporting will match the latest found value, caching that hugely improves performance // Most queries for the data in reporting will match the latest found value, caching that hugely improves performance
if (prevBasalTreatment && time >= prevBasalTreatment.mills && time <= prevBasalTreatment.endmills) { if (prevBasalTreatment && time >= prevBasalTreatment.mills && time <= prevBasalTreatment.endmills) {
return prevBasalTreatment; return prevBasalTreatment;
}
// Binary search for events for O(log n) performance
var first = 0, last = profile.tempbasaltreatments.length - 1;
while (first <= last) {
var i = first + Math.floor((last - first) / 2);
var t = profile.tempbasaltreatments[i];
if (time >= t.mills && time <= t.endmills) {
prevBasalTreatment = t;
return t;
}
if (time < t.mills) {
last = i - 1;
} else {
first = i + 1;
}
} }
// Binary search for events for O(log n) performance
var first = 0
, last = profile.tempbasaltreatments.length - 1;
while (first <= last) {
var i = first + Math.floor((last - first) / 2);
var t = profile.tempbasaltreatments[i];
if (time >= t.mills && time <= t.endmills) {
prevBasalTreatment = t;
return t;
}
if (time < t.mills) {
last = i - 1;
} else {
first = i + 1;
}
}
return null; return null;
}; };
profile.comboBolusTreatment = function comboBolusTreatment (time) { profile.comboBolusTreatment = function comboBolusTreatment (time) {
var treatment = null; var treatment = null;
profile.combobolustreatments.forEach( function eachTreatment (t) { profile.combobolustreatments.forEach(function eachTreatment (t) {
var duration = times.mins(t.duration || 0).msecs; var duration = times.mins(t.duration || 0).msecs;
if (time < t.mills + duration && time > t.mills) { if (time < t.mills + duration && time > t.mills) {
treatment = t; treatment = t;
} }
}); });
return treatment; return treatment;
}; };
@@ -327,7 +328,7 @@ function init (profileData) {
tempbasal = Number(treatment.absolute); tempbasal = Number(treatment.absolute);
} else if (treatment && treatment.percent) { } else if (treatment && treatment.percent) {
tempbasal = basal * (100 + treatment.percent) / 100; tempbasal = basal * (100 + treatment.percent) / 100;
} }
if (combobolustreatment && combobolustreatment.relative) { if (combobolustreatment && combobolustreatment.relative) {
combobolusbasal = combobolustreatment.relative; combobolusbasal = combobolustreatment.relative;
} }
@@ -348,30 +349,14 @@ function init (profileData) {
if (profile.hasData()) { if (profile.hasData()) {
var current = profile.activeProfileToTime(); var current = profile.activeProfileToTime();
profiles.push(current); profiles.push(current);
for (var key in profile.data[0].store) { Object.keys(profile.data[0].store).forEach(key => {
if (profile.data[0].store.hasOwnProperty(key) && key !== current) { if (key !== current && key.indexOf('@@@@@') < 0) profiles.push(key);
if (key.indexOf('@@@@@') < 0) })
profiles.push(key);
}
}
} }
return profiles; return profiles;
}; };
// get original store without added profiles fro profileSwitches
profile.getProfileStore = function getProfileStore () {
var newprofiledata = _.clone(profile.data[0]);
for (var key in profile.data[0].store) {
if (profile.data[0].store.hasOwnProperty(key)) {
if (key.indexOf('@@@@@') < 0)
store[key] = profile.data[0].store[key];
}
}
return store;
};
if (profileData) { profile.loadData(profileData); } if (profileData) { profile.loadData(profileData); }
// init treatments array // init treatments array
profile.updateTreatments([], []); profile.updateTreatments([], []);
@@ -379,4 +364,4 @@ function init (profileData) {
return profile; return profile;
} }
module.exports = init; module.exports = init;
+68 -70
View File
@@ -8,30 +8,29 @@ var calibrations = {
, pluginType: 'report' , pluginType: 'report'
}; };
function init() { function init () {
return calibrations; return calibrations;
} }
module.exports = init; module.exports = init;
calibrations.html = function html(client) { calibrations.html = function html (client) {
var translate = client.translate; var translate = client.translate;
var ret = var ret =
'<h2>' + translate('Calibrations') + '</h2>' '<h2>' + translate('Calibrations') + '</h2>' +
+ '<div style="width:50%;height:500px;float:left;overflow:scroll;overflow-x:hidden;" id="calibrations-list"></div>' '<div style="width:50%;height:500px;float:left;overflow:scroll;overflow-x:hidden;" id="calibrations-list"></div>' +
+ '<div style="width:48%;float:right;" id="calibrations-chart"></div>' '<div style="width:48%;float:right;" id="calibrations-chart"></div>';
;
return ret; return ret;
}; };
calibrations.report = function report_calibrations(datastorage,sorteddaystoshow) { calibrations.report = function report_calibrations (datastorage, sorteddaystoshow) {
var Nightscout = window.Nightscout; var Nightscout = window.Nightscout;
var report_plugins = Nightscout.report_plugins; var report_plugins = Nightscout.report_plugins;
var padding = { top: 15, right: 15, bottom: 30, left: 70 }; var padding = { top: 15, right: 15, bottom: 30, left: 70 };
var treatments = []; var treatments = [];
sorteddaystoshow.forEach(function (day) { sorteddaystoshow.forEach(function(day) {
treatments = treatments.concat(datastorage[day].treatments.filter(function (t) { treatments = treatments.concat(datastorage[day].treatments.filter(function(t) {
if (t.eventType === 'Sensor Start') { if (t.eventType === 'Sensor Start') {
return true; return true;
} }
@@ -43,59 +42,58 @@ calibrations.report = function report_calibrations(datastorage,sorteddaystoshow)
}); });
var cals = []; var cals = [];
sorteddaystoshow.forEach(function (day) { sorteddaystoshow.forEach(function(day) {
cals = cals.concat(datastorage[day].cal); cals = cals.concat(datastorage[day].cal);
}); });
var sgvs = []; var sgvs = [];
sorteddaystoshow.forEach(function (day) { sorteddaystoshow.forEach(function(day) {
sgvs = sgvs.concat(datastorage[day].sgv); sgvs = sgvs.concat(datastorage[day].sgv);
}); });
var mbgs = []; var mbgs = [];
sorteddaystoshow.forEach(function (day) { sorteddaystoshow.forEach(function(day) {
mbgs = mbgs.concat(datastorage[day].mbg); mbgs = mbgs.concat(datastorage[day].mbg);
}); });
mbgs.forEach(function (mbg) { calcmbg(mbg); }); mbgs.forEach(function(mbg) { calcmbg(mbg); });
var events = treatments.concat(cals).concat(mbgs).sort(function(a, b) { return a.mills - b.mills; }); var events = treatments.concat(cals).concat(mbgs).sort(function(a, b) { return a.mills - b.mills; });
var colors = ['Aqua','Blue','Brown','Chartreuse','Coral','CornflowerBlue','DarkCyan','DarkMagenta','DarkOrange','Fuchsia','Green','Yellow']; var colors = ['Aqua', 'Blue', 'Brown', 'Chartreuse', 'Coral', 'CornflowerBlue', 'DarkCyan', 'DarkMagenta', 'DarkOrange', 'Fuchsia', 'Green', 'Yellow'];
var colorindex = 0; var colorindex = 0;
var html = '<table>'; var html = '<table>';
var lastmbg = null; var lastmbg = null;
for (var i=0; i<events.length; i++) { for (var i = 0; i < events.length; i++) {
var e = events[i]; var e = events[i];
colorindex = (e.device !== undefined ? (colorindex+1)%colors.length : colorindex); colorindex = (e.device !== undefined ? (colorindex + 1) % colors.length : colorindex);
var currentcolor = (!e.eventType ? colors[colorindex] : 'White'); var currentcolor = (!e.eventType ? colors[colorindex] : 'White');
html += '<tr>'; html += '<tr>';
html += '<td>' + report_plugins.utils.localeDateTime(new Date(e.mills)) + '</td><td style="background-color:'+currentcolor+'">'; html += '<td>' + report_plugins.utils.localeDateTime(new Date(e.mills)) + '</td><td style="background-color:' + currentcolor + '">';
e.bgcolor = colors[colorindex]; e.bgcolor = colors[colorindex];
if (e.eventType) { if (e.eventType) {
html += '<b style="text-decoration: underline;padding-left:0em">'+translate(e.eventType)+'</b>:<br>'; html += '<b style="text-decoration: underline;padding-left:0em">' + translate(e.eventType) + '</b>:<br>';
} else if (typeof e.device !== 'undefined') { } else if (typeof e.device !== 'undefined') {
html += '<input type="checkbox" index="'+i+'" class="calibrations-checkbox" id="calibrations-'+i+'"> '; html += '<input type="checkbox" index="' + i + '" class="calibrations-checkbox" id="calibrations-' + i + '"> ';
html += '<b style="padding-left:2em">MBG</b>: ' + e.y + ' Raw: '+e.raw+'<br>'; html += '<b style="padding-left:2em">MBG</b>: ' + e.y + ' Raw: ' + e.raw + '<br>';
lastmbg = e; lastmbg = e;
e.cals = []; e.cals = [];
e.checked = false; e.checked = false;
} else if (typeof e.scale !== 'undefined') { } else if (typeof e.scale !== 'undefined') {
html += '<b style="padding-left:4em">CAL</b>: ' + ' Scale: ' + e.scale.toFixed(2) + ' Intercept: ' + e.intercept.toFixed(0) + ' Slope: ' + e.slope.toFixed(2) + '<br>'; html += '<b style="padding-left:4em">CAL</b>: ' + ' Scale: ' + e.scale.toFixed(2) + ' Intercept: ' + e.intercept.toFixed(0) + ' Slope: ' + e.slope.toFixed(2) + '<br>';
if (lastmbg) { if (lastmbg) {
lastmbg.cals.push(e); lastmbg.cals.push(e);
} }
} else { } else {
html += JSON.stringify(e); html += JSON.stringify(e);
} }
html += '</td></tr>'; html += '</td></tr>';
}; }
html += '</table>'; html += '</table>';
$('#calibrations-list').html(html); $('#calibrations-list').html(html);
// select last 3 mbgs // select last 3 mbgs
checkLastCheckboxes(3); checkLastCheckboxes(3);
drawelements(); drawelements();
@@ -103,27 +101,27 @@ calibrations.report = function report_calibrations(datastorage,sorteddaystoshow)
$('.calibrations-checkbox').change(checkboxevent); $('.calibrations-checkbox').change(checkboxevent);
function checkLastCheckboxes (maxcals) { function checkLastCheckboxes (maxcals) {
for (i=events.length-1; i>0; i--) { for (i = events.length - 1; i > 0; i--) {
if (typeof events[i].device !== 'undefined') { if (typeof events[i].device !== 'undefined') {
events[i].checked = true; events[i].checked = true;
$('#calibrations-'+i).prop('checked',true); $('#calibrations-' + i).prop('checked', true);
if (--maxcals<1) { if (--maxcals < 1) {
break; break;
} }
} }
} }
} }
function checkboxevent(event) { function checkboxevent (event) {
var index = $(this).attr('index'); var index = $(this).attr('index');
events[index].checked = $(this).is(':checked'); events[index].checked = $(this).is(':checked');
drawelements(); drawelements();
event.preventDefault(); event.preventDefault();
} }
function drawelements() { function drawelements () {
drawChart(); drawChart();
for (var i=0; i<events.length; i++) { for (var i = 0; i < events.length; i++) {
e = events[i]; e = events[i];
if (e.checked) { if (e.checked) {
drawmbg(e); drawmbg(e);
@@ -131,10 +129,10 @@ calibrations.report = function report_calibrations(datastorage,sorteddaystoshow)
} }
} }
} }
var calibration_context,xScale2,yScale2 ; var calibration_context, xScale2, yScale2;
function drawChart() { function drawChart () {
var maxBG = 500; var maxBG = 500;
$('#calibrations-chart').empty(); $('#calibrations-chart').empty();
@@ -144,15 +142,15 @@ calibrations.report = function report_calibrations(datastorage,sorteddaystoshow)
.attr('width', '100%') .attr('width', '100%')
.attr('height', '100%') .attr('height', '100%')
.attr('fill', 'WhiteSmoke'); .attr('fill', 'WhiteSmoke');
calibration_context = charts.append('g'); calibration_context = charts.append('g');
// define the parts of the axis that aren't dependent on width or height // define the parts of the axis that aren't dependent on width or height
xScale2 = d3.scale.linear() xScale2 = d3.scale.linear()
.domain([0,maxBG]); .domain([0, maxBG]);
yScale2 = d3.scale.linear() yScale2 = d3.scale.linear()
.domain([0,400000]); .domain([0, 400000]);
var xAxis2 = d3.svg.axis() var xAxis2 = d3.svg.axis()
.scale(xScale2) .scale(xScale2)
@@ -164,10 +162,10 @@ calibrations.report = function report_calibrations(datastorage,sorteddaystoshow)
.orient('left'); .orient('left');
// get current data range // get current data range
var dataRange = [0,maxBG]; var dataRange = [0, maxBG];
var width = 600; var width = 600;
var height = 500; var height = 500;
// get the entire container height and width subtracting the padding // get the entire container height and width subtracting the padding
var chartWidth = width - padding.left - padding.right; var chartWidth = width - padding.left - padding.right;
var chartHeight = height - padding.top - padding.bottom; var chartHeight = height - padding.top - padding.bottom;
@@ -178,7 +176,7 @@ calibrations.report = function report_calibrations(datastorage,sorteddaystoshow)
// ranges are based on the width and height available so reset // ranges are based on the width and height available so reset
xScale2.range([0, chartWidth]); xScale2.range([0, chartWidth]);
yScale2.range([chartHeight,0]); yScale2.range([chartHeight, 0]);
// create the x axis container // create the x axis container
calibration_context.append('g') calibration_context.append('g')
@@ -189,7 +187,7 @@ calibrations.report = function report_calibrations(datastorage,sorteddaystoshow)
.attr('class', 'y axis'); .attr('class', 'y axis');
calibration_context.select('.y') calibration_context.select('.y')
.attr('transform', 'translate(' + (/*chartWidth + */ padding.left) + ',' + padding.top + ')') .attr('transform', 'translate(' + ( /*chartWidth + */ padding.left) + ',' + padding.top + ')')
.style('stroke', 'black') .style('stroke', 'black')
.style('shape-rendering', 'crispEdges') .style('shape-rendering', 'crispEdges')
.style('fill', 'none') .style('fill', 'none')
@@ -203,58 +201,58 @@ calibrations.report = function report_calibrations(datastorage,sorteddaystoshow)
.style('fill', 'none') .style('fill', 'none')
.call(xAxis2); .call(xAxis2);
[50000,100000,150000,200000,250000,300000,350000,400000].forEach(function (li) { [50000, 100000, 150000, 200000, 250000, 300000, 350000, 400000].forEach(function(li) {
calibration_context.append('line') calibration_context.append('line')
.attr('class', 'high-line') .attr('class', 'high-line')
.attr('x1', xScale2(dataRange[0])+padding.left) .attr('x1', xScale2(dataRange[0]) + padding.left)
.attr('y1', yScale2(li)+padding.top) .attr('y1', yScale2(li) + padding.top)
.attr('x2', xScale2(dataRange[1])+padding.left) .attr('x2', xScale2(dataRange[1]) + padding.left)
.attr('y2', yScale2(li)+padding.top) .attr('y2', yScale2(li) + padding.top)
.style('stroke-dasharray', ('3, 3')) .style('stroke-dasharray', ('3, 3'))
.attr('stroke', 'grey'); .attr('stroke', 'grey');
}); });
[50,100,150,200,250,300,350,400,450,500].forEach(function (li) { [50, 100, 150, 200, 250, 300, 350, 400, 450, 500].forEach(function(li) {
calibration_context.append('line') calibration_context.append('line')
.attr('class', 'high-line') .attr('class', 'high-line')
.attr('x1', xScale2(li)+padding.left) .attr('x1', xScale2(li) + padding.left)
.attr('y1', padding.top) .attr('y1', padding.top)
.attr('x2', xScale2(li)+padding.left) .attr('x2', xScale2(li) + padding.left)
.attr('y2', chartHeight+padding.top) .attr('y2', chartHeight + padding.top)
.style('stroke-dasharray', ('3, 3')) .style('stroke-dasharray', ('3, 3'))
.attr('stroke', 'grey'); .attr('stroke', 'grey');
}); });
} }
function drawcal(cal) { function drawcal (cal) {
var color = cal.bgcolor; var color = cal.bgcolor;
var y1 = 50000; var y1 = 50000;
var x1 = cal.scale * (y1 - cal.intercept) / cal.slope; var x1 = cal.scale * (y1 - cal.intercept) / cal.slope;
var y2 = 400000; var y2 = 400000;
var x2 = cal.scale * (y2 - cal.intercept) / cal.slope; var x2 = cal.scale * (y2 - cal.intercept) / cal.slope;
calibration_context.append('line') calibration_context.append('line')
.attr('x1', xScale2(x1)+padding.left) .attr('x1', xScale2(x1) + padding.left)
.attr('y1', yScale2(y1)+padding.top) .attr('y1', yScale2(y1) + padding.top)
.attr('x2', xScale2(x2)+padding.left) .attr('x2', xScale2(x2) + padding.left)
.attr('y2', yScale2(y2)+padding.top) .attr('y2', yScale2(y2) + padding.top)
.style('stroke-width', 3) .style('stroke-width', 3)
.attr('stroke', color); .attr('stroke', color);
} }
function calcmbg(mbg) { function calcmbg (mbg) {
var lastsgv = findlatest(new Date(mbg.mills),sgvs); var lastsgv = findlatest(new Date(mbg.mills), sgvs);
if (lastsgv) { if (lastsgv) {
if (mbg.mills-lastsgv.mills>5*60*1000) { if (mbg.mills - lastsgv.mills > 5 * 60 * 1000) {
console.log('Last SGV too old for MBG. Time diff: '+((mbg.mills-lastsgv.mills)/1000/60).toFixed(1)+' min',mbg); console.log('Last SGV too old for MBG. Time diff: ' + ((mbg.mills - lastsgv.mills) / 1000 / 60).toFixed(1) + ' min', mbg);
} else { } else {
mbg.raw = lastsgv.filtered || lastsgv.unfiltered; mbg.raw = lastsgv.filtered || lastsgv.unfiltered;
} }
} else { } else {
console.log('Last entry not found for MBG ',mbg); console.log('Last entry not found for MBG ', mbg);
} }
} }
function drawmbg(mbg) { function drawmbg (mbg) {
var color = mbg.bgcolor; var color = mbg.bgcolor;
if (mbg.raw) { if (mbg.raw) {
calibration_context.append('circle') calibration_context.append('circle')
@@ -267,11 +265,11 @@ calibrations.report = function report_calibrations(datastorage,sorteddaystoshow)
.attr('r', 5); .attr('r', 5);
} }
} }
function findlatest(date,storage) { function findlatest (date, storage) {
var last = null; var last = null;
var time = date.getTime(); var time = date.getTime();
for (var i=0; i<storage.length; i++) { for (var i = 0; i < storage.length; i++) {
if (storage[i].mills > time) { if (storage[i].mills > time) {
return last; return last;
} }
+64 -67
View File
@@ -6,41 +6,39 @@ var dailystats = {
, pluginType: 'report' , pluginType: 'report'
}; };
function init() { function init () {
return dailystats; return dailystats;
} }
module.exports = init; module.exports = init;
dailystats.html = function html(client) { dailystats.html = function html (client) {
var translate = client.translate; var translate = client.translate;
var ret = var ret =
'<h2>' + translate('Daily stats report') + '</h2>' '<h2>' + translate('Daily stats report') + '</h2>' +
+ '<div id="dailystats-report"></div>' '<div id="dailystats-report"></div>';
;
return ret; return ret;
}; };
dailystats.css = dailystats.css =
'#dailystats-placeholder .tdborder {' '#dailystats-placeholder .tdborder {' +
+ ' width:80px;' ' width:80px;' +
+ ' border: 1px #ccc solid;' ' border: 1px #ccc solid;' +
+ ' margin: 0;' ' margin: 0;' +
+ ' padding: 1px;' ' padding: 1px;' +
+ ' text-align:center;' ' text-align:center;' +
+ '}' '}' +
+ '#dailystats-placeholder .inlinepiechart {' '#dailystats-placeholder .inlinepiechart {' +
+ ' width: 2.0in;' ' width: 2.0in;' +
+ ' height: 0.9in;' ' height: 0.9in;' +
+ '}' '}';
;
dailystats.report = function report_dailystats(datastorage,sorteddaystoshow,options) { dailystats.report = function report_dailystats (datastorage, sorteddaystoshow, options) {
var Nightscout = window.Nightscout; var Nightscout = window.Nightscout;
var client = Nightscout.client; var client = Nightscout.client;
var translate = client.translate; var translate = client.translate;
var report_plugins = Nightscout.report_plugins; var report_plugins = Nightscout.report_plugins;
var ss = require('simple-statistics'); var ss = require('simple-statistics');
var todo = []; var todo = [];
@@ -52,31 +50,31 @@ dailystats.report = function report_dailystats(datastorage,sorteddaystoshow,opti
report.append(table); report.append(table);
var thead = $('<tr/>'); var thead = $('<tr/>');
$('<th></th>').appendTo(thead); $('<th></th>').appendTo(thead);
$('<th>'+translate('Date')+'</th>').appendTo(thead); $('<th>' + translate('Date') + '</th>').appendTo(thead);
$('<th>'+translate('Low')+'</th>').appendTo(thead); $('<th>' + translate('Low') + '</th>').appendTo(thead);
$('<th>'+translate('Normal')+'</th>').appendTo(thead); $('<th>' + translate('Normal') + '</th>').appendTo(thead);
$('<th>'+translate('High')+'</th>').appendTo(thead); $('<th>' + translate('High') + '</th>').appendTo(thead);
$('<th>'+translate('Readings')+'</th>').appendTo(thead); $('<th>' + translate('Readings') + '</th>').appendTo(thead);
$('<th>'+translate('Min')+'</th>').appendTo(thead); $('<th>' + translate('Min') + '</th>').appendTo(thead);
$('<th>'+translate('Max')+'</th>').appendTo(thead); $('<th>' + translate('Max') + '</th>').appendTo(thead);
$('<th>'+translate('Average')+'</th>').appendTo(thead); $('<th>' + translate('Average') + '</th>').appendTo(thead);
$('<th>'+translate('StDev')+'</th>').appendTo(thead); $('<th>' + translate('StDev') + '</th>').appendTo(thead);
$('<th>'+translate('25%')+'</th>').appendTo(thead); $('<th>' + translate('25%') + '</th>').appendTo(thead);
$('<th>'+translate('Median')+'</th>').appendTo(thead); $('<th>' + translate('Median') + '</th>').appendTo(thead);
$('<th>'+translate('75%')+'</th>').appendTo(thead); $('<th>' + translate('75%') + '</th>').appendTo(thead);
thead.appendTo(table); thead.appendTo(table);
sorteddaystoshow.forEach(function (day) { sorteddaystoshow.forEach(function(day) {
var tr = $('<tr>'); var tr = $('<tr>');
var daysRecords = datastorage[day].statsrecords; var daysRecords = datastorage[day].statsrecords;
if (daysRecords.length === 0) { if (daysRecords.length === 0) {
$('<td/>').appendTo(tr); $('<td/>').appendTo(tr);
$('<td class=\"tdborder\" style=\"width:160px\">' + report_plugins.utils.localeDate(day) + '</td>').appendTo(tr); $('<td class="tdborder" style="width:160px">' + report_plugins.utils.localeDate(day) + '</td>').appendTo(tr);
$('<td class=\"tdborder\"colspan="10">'+translate('No data available')+'</td>').appendTo(tr); $('<td class="tdborder"colspan="10">' + translate('No data available') + '</td>').appendTo(tr);
table.append(tr); table.append(tr);
return;; return;
} }
minForDay = daysRecords[0].sgv; minForDay = daysRecords[0].sgv;
@@ -101,53 +99,52 @@ dailystats.report = function report_dailystats(datastorage,sorteddaystoshow,opti
sum += record.sgv; sum += record.sgv;
return out; return out;
}, { }, {
lows: 0, lows: 0
normal: 0, , normal: 0
highs: 0 , highs: 0
}); });
var average = sum / daysRecords.length; var average = sum / daysRecords.length;
var bgValues = daysRecords.map(function(r) { return r.sgv; }); var bgValues = daysRecords.map(function(r) { return r.sgv; });
$('<td><div id=\"dailystat-chart-' + day.toString() + '\" class=\"inlinepiechart\"></div></td>').appendTo(tr); $('<td><div id="dailystat-chart-' + day.toString() + '" class="inlinepiechart"></div></td>').appendTo(tr);
$('<td class=\"tdborder\" style=\"width:160px\">' + report_plugins.utils.localeDate(day) + '</td>').appendTo(tr); $('<td class="tdborder" style="width:160px">' + report_plugins.utils.localeDate(day) + '</td>').appendTo(tr);
$('<td class=\"tdborder\">' + Math.round((100 * stats.lows) / daysRecords.length) + '%</td>').appendTo(tr); $('<td class="tdborder">' + Math.round((100 * stats.lows) / daysRecords.length) + '%</td>').appendTo(tr);
$('<td class=\"tdborder\">' + Math.round((100 * stats.normal) / daysRecords.length) + '%</td>').appendTo(tr); $('<td class="tdborder">' + Math.round((100 * stats.normal) / daysRecords.length) + '%</td>').appendTo(tr);
$('<td class=\"tdborder\">' + Math.round((100 * stats.highs) / daysRecords.length) + '%</td>').appendTo(tr); $('<td class="tdborder">' + Math.round((100 * stats.highs) / daysRecords.length) + '%</td>').appendTo(tr);
$('<td class=\"tdborder\">' + daysRecords.length +'</td>').appendTo(tr); $('<td class="tdborder">' + daysRecords.length + '</td>').appendTo(tr);
$('<td class=\"tdborder\">' + minForDay +'</td>').appendTo(tr); $('<td class="tdborder">' + minForDay + '</td>').appendTo(tr);
$('<td class=\"tdborder\">' + maxForDay +'</td>').appendTo(tr); $('<td class="tdborder">' + maxForDay + '</td>').appendTo(tr);
$('<td class=\"tdborder\">' + average.toFixed(1) +'</td>').appendTo(tr); $('<td class="tdborder">' + average.toFixed(1) + '</td>').appendTo(tr);
$('<td class=\"tdborder\">' + ss.standard_deviation(bgValues).toFixed(1) + '</td>').appendTo(tr); $('<td class="tdborder">' + ss.standard_deviation(bgValues).toFixed(1) + '</td>').appendTo(tr);
$('<td class=\"tdborder\">' + ss.quantile(bgValues, 0.25).toFixed(1) + '</td>').appendTo(tr); $('<td class="tdborder">' + ss.quantile(bgValues, 0.25).toFixed(1) + '</td>').appendTo(tr);
$('<td class=\"tdborder\">' + ss.quantile(bgValues, 0.5).toFixed(1) + '</td>').appendTo(tr); $('<td class="tdborder">' + ss.quantile(bgValues, 0.5).toFixed(1) + '</td>').appendTo(tr);
$('<td class=\"tdborder\">' + ss.quantile(bgValues, 0.75).toFixed(1) + '</td>').appendTo(tr); $('<td class="tdborder">' + ss.quantile(bgValues, 0.75).toFixed(1) + '</td>').appendTo(tr);
table.append(tr); table.append(tr);
var inrange = [ var inrange = [
{ {
label: translate('Low'), label: translate('Low')
data: Math.round(stats.lows * 1000 / daysRecords.length) / 10 , data: Math.round(stats.lows * 1000 / daysRecords.length) / 10
}, }
{ , {
label: translate('In Range'), label: translate('In Range')
data: Math.round(stats.normal * 1000 / daysRecords.length) / 10 , data: Math.round(stats.normal * 1000 / daysRecords.length) / 10
}, }
{ , {
label: translate('High'), label: translate('High')
data: Math.round(stats.highs * 1000 / daysRecords.length) / 10 , data: Math.round(stats.highs * 1000 / daysRecords.length) / 10
} }
]; ];
$.plot( $.plot(
'#dailystat-chart-' + day.toString(), '#dailystat-chart-' + day.toString()
inrange, , inrange, {
{
series: { series: {
pie: { pie: {
show: true show: true
} }
}, }
colors: ['#f88', '#8f8', '#ff8'] , colors: ['#f88', '#8f8', '#ff8']
} }
); );
}); });
+292 -297
View File
@@ -11,78 +11,77 @@ var daytoday = {
, pluginType: 'report' , pluginType: 'report'
}; };
function init() { function init () {
return daytoday; return daytoday;
} }
module.exports = init; module.exports = init;
daytoday.html = function html(client) { daytoday.html = function html (client) {
var translate = client.translate; var translate = client.translate;
var ret = var ret =
'<h2>' + translate('Day to day') + '</h2>' '<h2>' + translate('Day to day') + '</h2>' +
+ '<b>' + translate('To see this report, press SHOW while in this view') + '</b><br>' '<b>' + translate('To see this report, press SHOW while in this view') + '</b><br>' +
+ translate('Display') + ': ' translate('Display') + ': ' +
+ '<input type="checkbox" id="rp_optionsinsulin" checked><span style="color:blue;opacity:0.5">'+translate('Insulin')+'</span>' '<input type="checkbox" id="rp_optionsinsulin" checked><span style="color:blue;opacity:0.5">' + translate('Insulin') + '</span>' +
+ '<input type="checkbox" id="rp_optionscarbs" checked><span style="color:red;opacity:0.5">'+translate('Carbs')+'</span>' '<input type="checkbox" id="rp_optionscarbs" checked><span style="color:red;opacity:0.5">' + translate('Carbs') + '</span>' +
+ '<input type="checkbox" id="rp_optionsbasal" checked><span style="color:#0099ff;opacity:0.5">'+translate('Basal rate')+'</span>' '<input type="checkbox" id="rp_optionsbasal" checked><span style="color:#0099ff;opacity:0.5">' + translate('Basal rate') + '</span>' +
+ '<input type="checkbox" id="rp_optionsnotes">'+translate('Notes') '<input type="checkbox" id="rp_optionsnotes">' + translate('Notes') +
+ '<input type="checkbox" id="rp_optionsfood" checked>'+translate('Food') '<input type="checkbox" id="rp_optionsfood" checked>' + translate('Food') +
+ '<input type="checkbox" id="rp_optionsraw"><span style="color:gray;opacity:1">'+translate('Raw')+'</span>' '<input type="checkbox" id="rp_optionsraw"><span style="color:gray;opacity:1">' + translate('Raw') + '</span>' +
+ '<input type="checkbox" id="rp_optionsiob"><span style="color:blue;opacity:0.5">'+translate('IOB')+'</span>' '<input type="checkbox" id="rp_optionsiob"><span style="color:blue;opacity:0.5">' + translate('IOB') + '</span>' +
+ '<input type="checkbox" id="rp_optionscob"><span style="color:red;opacity:0.5">'+translate('COB')+'</span>' '<input type="checkbox" id="rp_optionscob"><span style="color:red;opacity:0.5">' + translate('COB') + '</span>' +
+ '<input type="checkbox" id="rp_optionspredicted"><span style="color:sienna;opacity:0.5">'+translate('Predictions')+'</span>' '<input type="checkbox" id="rp_optionspredicted"><span style="color:sienna;opacity:0.5">' + translate('Predictions') + '</span>' +
+ '<input type="checkbox" id="rp_optionsopenaps"><span style="color:sienna;opacity:0.5">'+translate('OpenAPS')+'</span>' '<input type="checkbox" id="rp_optionsopenaps"><span style="color:sienna;opacity:0.5">' + translate('OpenAPS') + '</span>' +
+ '<input type="checkbox" id="rp_optionsdistribution" checked><span style="color:blue;opacity:0.5">'+translate('Insulin distribution')+'</span>' '<input type="checkbox" id="rp_optionsdistribution" checked><span style="color:blue;opacity:0.5">' + translate('Insulin distribution') + '</span>' +
+ '&nbsp;'+translate('Size') '&nbsp;' + translate('Size') +
+ ' <select id="rp_size">' ' <select id="rp_size">' +
+ ' <option x="800" y="250">800x250px</option>' ' <option x="800" y="250">800x250px</option>' +
+ ' <option x="1000" y="300" selected>1000x300px</option>' ' <option x="1000" y="300" selected>1000x300px</option>' +
+ ' <option x="1200" y="400">1200x400px</option>' ' <option x="1200" y="400">1200x400px</option>' +
+ ' <option x="1550" y="600">1550x600px</option>' ' <option x="1550" y="600">1550x600px</option>' +
+ ' <option x="2400" y="800">2400x800px</option>' ' <option x="2400" y="800">2400x800px</option>' +
+ '</select>' '</select>' +
+ '<br>' '<br>' +
+ translate('Scale') + ': ' translate('Scale') + ': ' +
+ '<input type="radio" name="rp_scale" id="rp_linear" checked>' '<input type="radio" name="rp_scale" id="rp_linear" checked>' +
+ translate('Linear') translate('Linear') +
+ '<input type="radio" name="rp_scale" id="rp_log">' '<input type="radio" name="rp_scale" id="rp_log">' +
+ translate('Logarithmic') translate('Logarithmic') +
+ '<div id="rp_predictedSettings" style="display:none">' '<div id="rp_predictedSettings" style="display:none">' +
+ translate('Truncate predictions: ') translate('Truncate predictions: ') +
+ '<input type="checkbox" id="rp_optionsPredictedTruncate" checked>' '<input type="checkbox" id="rp_optionsPredictedTruncate" checked>' +
+ '<br>' '<br>' +
+ translate('Predictions offset') + ': ' translate('Predictions offset') + ': ' +
+ '<b><label id="rp_predictedOffset"></label> minutes</b>' '<b><label id="rp_predictedOffset"></label> minutes</b>' +
+ '&nbsp;&nbsp;&nbsp;&nbsp;' '&nbsp;&nbsp;&nbsp;&nbsp;' +
+ '<input type="button" onclick="predictMoreBackward();" value="' + translate('-30 min')+'">' '<input type="button" onclick="predictMoreBackward();" value="' + translate('-30 min') + '">' +
+ '<input type="button" onclick="predictBackward();" value="' + translate('-5 min')+'">' '<input type="button" onclick="predictBackward();" value="' + translate('-5 min') + '">' +
+ '<input type="button" onclick="predictResetToZero();" value="' + translate('Zero')+'">' '<input type="button" onclick="predictResetToZero();" value="' + translate('Zero') + '">' +
+ '<input type="button" onclick="predictForward();" value="' + translate('+5 min')+'">' '<input type="button" onclick="predictForward();" value="' + translate('+5 min') + '">' +
+ '<input type="button" onclick="predictMoreForward();" value="' + translate('+30 min')+'">' '<input type="button" onclick="predictMoreForward();" value="' + translate('+30 min') + '">' +
+ '</div>' '</div>' +
+ '<br>' '<br>' +
+ '<div id="daytodaycharts">' '<div id="daytodaycharts">' +
+ '</div>' '</div>';
; return ret;
return ret;
}; };
daytoday.prepareHtml = function daytodayPrepareHtml(sorteddaystoshow) { daytoday.prepareHtml = function daytodayPrepareHtml (sorteddaystoshow) {
$('#daytodaycharts').html(''); $('#daytodaycharts').html('');
sorteddaystoshow.forEach(function eachDay(d) { sorteddaystoshow.forEach(function eachDay (d) {
$('#daytodaycharts').append($('<table><tr><td><div id="daytodaychart-' + d + '"></div></td><td><div id="daytodaystatchart-' + d + '"></td></tr></table>')); $('#daytodaycharts').append($('<table><tr><td><div id="daytodaychart-' + d + '"></div></td><td><div id="daytodaystatchart-' + d + '"></td></tr></table>'));
}); });
}; };
daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options) { daytoday.report = function report_daytoday (datastorage, sorteddaystoshow, options) {
var Nightscout = window.Nightscout; var Nightscout = window.Nightscout;
var client = Nightscout.client; var client = Nightscout.client;
var translate = client.translate; var translate = client.translate;
var profile = client.sbx.data.profile; var profile = client.sbx.data.profile;
var report_plugins = Nightscout.report_plugins; var report_plugins = Nightscout.report_plugins;
var scaledTreatmentBG = report_plugins.utils.scaledTreatmentBG; var scaledTreatmentBG = report_plugins.utils.scaledTreatmentBG;
var TOOLTIP_TRANS_MS = 300; var TOOLTIP_TRANS_MS = 300;
var padding = { top: 15, right: 22, bottom: 30, left: 35 }; var padding = { top: 15, right: 22, bottom: 30, left: 35 };
@@ -92,28 +91,27 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
var proteinSum = 0; var proteinSum = 0;
var fatSum = 0; var fatSum = 0;
daytoday.prepareHtml(sorteddaystoshow) ; daytoday.prepareHtml(sorteddaystoshow);
sorteddaystoshow.forEach( function eachDay(day) { sorteddaystoshow.forEach(function eachDay (day) {
drawChart(day,datastorage[day],options); drawChart(day, datastorage[day], options);
}); });
var tddAverage = tddSum / datastorage.alldays; var tddAverage = tddSum / datastorage.alldays;
var carbsAverage = carbsSum / datastorage.alldays; var carbsAverage = carbsSum / datastorage.alldays;
var proteinAverage = proteinSum / datastorage.alldays; var proteinAverage = proteinSum / datastorage.alldays;
var fatAverage = fatSum / datastorage.alldays; var fatAverage = fatSum / datastorage.alldays;
if (options.insulindistribution) if (options.insulindistribution)
$('#daytodaycharts').append('<br><br><b>' + translate('TDD average') + ':</b> ' + tddAverage.toFixed(1) + 'U <b>' $('#daytodaycharts').append('<br><br><b>' + translate('TDD average') + ':</b> ' + tddAverage.toFixed(1) + 'U <b>' +
+ translate('Carbs average') + ':</b> ' + carbsAverage.toFixed(0) + 'g' translate('Carbs average') + ':</b> ' + carbsAverage.toFixed(0) + 'g' +
+ translate('Protein average') + ':</b> ' + proteinAverage.toFixed(0) + 'g' translate('Protein average') + ':</b> ' + proteinAverage.toFixed(0) + 'g' +
+ translate('Fat average') + ':</b> ' + fatAverage.toFixed(0) + 'g' translate('Fat average') + ':</b> ' + fatAverage.toFixed(0) + 'g'
); );
function timeTicks(n,i) { function timeTicks (n, i) {
var t12 = [ var t12 = [
'12am', '', '2am', '', '4am', '', '6am', '', '8am', '', '10am', '', '12am', '', '2am', '', '4am', '', '6am', '', '8am', '', '10am', ''
'12pm', '', '2pm', '', '4pm', '', '6pm', '', '8pm', '', '10pm', '', '12am' , '12pm', '', '2pm', '', '4pm', '', '6pm', '', '8pm', '', '10pm', '', '12am'
]; ];
if (Nightscout.client.settings.timeFormat === 24) { if (Nightscout.client.settings.timeFormat === 24) {
return ('00' + i).slice(-2); return ('00' + i).slice(-2);
@@ -121,28 +119,28 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
return t12[i]; return t12[i];
} }
} }
function drawChart(day,data,options) { function drawChart (day, data, options) {
var tickValues var tickValues
, charts , charts
, context , context
, xScale2, yScale2 , xScale2, yScale2
, yInsulinScale, yCarbsScale, yScaleBasals , yInsulinScale, yCarbsScale, yScaleBasals
, xAxis2, yAxis2 , xAxis2, yAxis2
, dateFn = function (d) { return new Date(d.date); } , dateFn = function(d) { return new Date(d.date); }
, foodtexts = 0; , foodtexts = 0;
tickValues = client.ticks(client, { tickValues = client.ticks(client, {
scaleY: options.scale === report_plugins.consts.SCALE_LOG ? 'log' : 'linear' scaleY: options.scale === report_plugins.consts.SCALE_LOG ? 'log' : 'linear'
, targetTop: options.targetHigh , targetTop: options.targetHigh
, targetBottom: options.targetLow , targetBottom: options.targetLow
}); });
// add defs for combo boluses // add defs for combo boluses
var dashWidth = 5; var dashWidth = 5;
d3.select('body').append('svg') d3.select('body').append('svg')
.append('defs') .append('defs')
.append('pattern') .append('pattern')
.attr('id', 'hash') .attr('id', 'hash')
.attr('patternUnits', 'userSpaceOnUse') .attr('patternUnits', 'userSpaceOnUse')
.attr('width', 6) .attr('width', 6)
@@ -150,24 +148,24 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.attr('x', 0) .attr('x', 0)
.attr('y', 0) .attr('y', 0)
.append('g') .append('g')
.style('fill', 'none') .style('fill', 'none')
.style('stroke', '#0099ff') .style('stroke', '#0099ff')
.style('stroke-width', 2) .style('stroke-width', 2)
.append('path').attr('d', 'M0,0 l' + dashWidth + ',' + dashWidth) .append('path').attr('d', 'M0,0 l' + dashWidth + ',' + dashWidth)
.append('path').attr('d', 'M' + dashWidth + ',0 l-' + dashWidth + ',' + dashWidth); .append('path').attr('d', 'M' + dashWidth + ',0 l-' + dashWidth + ',' + dashWidth);
// create svg and g to contain the chart contents // create svg and g to contain the chart contents
charts = d3.select('#daytodaychart-' + day).html( charts = d3.select('#daytodaychart-' + day).html(
'<b>'+ '<b>' +
report_plugins.utils.localeDate(day)+ report_plugins.utils.localeDate(day) +
'</b><br>' '</b><br>'
).append('svg'); ).append('svg');
charts.append('rect') charts.append('rect')
.attr('width', '100%') .attr('width', '100%')
.attr('height', '100%') .attr('height', '100%')
.attr('fill', 'WhiteSmoke'); .attr('fill', 'WhiteSmoke');
context = charts.append('g'); context = charts.append('g');
// define the parts of the axis that aren't dependent on width or height // define the parts of the axis that aren't dependent on width or height
@@ -187,10 +185,10 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.domain([-2 * options.maxInsulinValue, 2 * options.maxInsulinValue]); .domain([-2 * options.maxInsulinValue, 2 * options.maxInsulinValue]);
yCarbsScale = d3.scale.linear() yCarbsScale = d3.scale.linear()
.domain([0, options.maxCarbsValue*1.25]); .domain([0, options.maxCarbsValue * 1.25]);
yScaleBasals = d3.scale.linear(); yScaleBasals = d3.scale.linear();
xAxis2 = d3.svg.axis() xAxis2 = d3.svg.axis()
.scale(xScale2) .scale(xScale2)
.tickFormat(timeTicks) .tickFormat(timeTicks)
@@ -213,20 +211,20 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
//set the width and height of the SVG element //set the width and height of the SVG element
charts.attr('width', options.width) charts.attr('width', options.width)
.attr('height', options.height); .attr('height', options.height);
// ranges are based on the width and height available so reset // ranges are based on the width and height available so reset
xScale2.range([0, chartWidth]); xScale2.range([0, chartWidth]);
yScale2.range([chartHeight,0]); yScale2.range([chartHeight, 0]);
yInsulinScale.range([chartHeight * 2, 0]); yInsulinScale.range([chartHeight * 2, 0]);
yCarbsScale.range([chartHeight,0]); yCarbsScale.range([chartHeight, 0]);
yScaleBasals.range([yScale2(client.utils.scaleMgdl(72)), chartHeight]); yScaleBasals.range([yScale2(client.utils.scaleMgdl(72)), chartHeight]);
// add target BG rect // add target BG rect
context.append('rect') context.append('rect')
.attr('x', xScale2(dataRange[0])+padding.left) .attr('x', xScale2(dataRange[0]) + padding.left)
.attr('y', yScale2(options.targetHigh)+padding.top) .attr('y', yScale2(options.targetHigh) + padding.top)
.attr('width', xScale2(dataRange[1]- xScale2(dataRange[0]))) .attr('width', xScale2(dataRange[1] - xScale2(dataRange[0])))
.attr('height', yScale2(options.targetLow)-yScale2(options.targetHigh)) .attr('height', yScale2(options.targetLow) - yScale2(options.targetHigh))
.style('fill', '#D6FFD6') .style('fill', '#D6FFD6')
.attr('stroke', 'grey'); .attr('stroke', 'grey');
@@ -253,72 +251,68 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.style('fill', 'none') .style('fill', 'none')
.call(xAxis2); .call(xAxis2);
_.each(tickValues, function (n, li) { _.each(tickValues, function(n, li) {
context.append('line') context.append('line')
.attr('class', 'high-line') .attr('class', 'high-line')
.attr('x1', xScale2(dataRange[0])+padding.left) .attr('x1', xScale2(dataRange[0]) + padding.left)
.attr('y1', yScale2(tickValues[li])+padding.top) .attr('y1', yScale2(tickValues[li]) + padding.top)
.attr('x2', xScale2(dataRange[1])+padding.left) .attr('x2', xScale2(dataRange[1]) + padding.left)
.attr('y2', yScale2(tickValues[li])+padding.top) .attr('y2', yScale2(tickValues[li]) + padding.top)
.style('stroke-dasharray', ('1, 5')) .style('stroke-dasharray', ('1, 5'))
.attr('stroke', 'grey'); .attr('stroke', 'grey');
}); });
// bind up the context chart data to an array of circles function prepareContextCircles (sel) {
var contextCircles = context.selectAll('circle')
.data(data.sgv);
function prepareContextCircles(sel) {
var badData = []; var badData = [];
sel.attr('cx', function (d) { sel.attr('cx', function(d) {
return xScale2(d.date) + padding.left; return xScale2(d.date) + padding.left;
}) })
.attr('cy', function (d) { .attr('cy', function(d) {
if (isNaN(d.sgv)) { if (isNaN(d.sgv)) {
badData.push(d); badData.push(d);
return yScale2(client.utils.scaleMgdl(450) + padding.top); return yScale2(client.utils.scaleMgdl(450) + padding.top);
} else { } else {
return yScale2(d.sgv) + padding.top; return yScale2(d.sgv) + padding.top;
}
})
.attr('fill', function (d) {
if (d.color === 'gray' && !options.raw) {
return 'transparent';
}
return d.color;
})
.style('opacity', function () { return 0.5 })
.attr('stroke-width', function (d) {if (d.type === 'mbg') { return 2; } else if (options.openAps && d.openaps) { return 1; } else { return 0; }})
.attr('stroke', function () { return 'black'; })
.attr('r', function(d) {
if (d.type === 'mbg') {
return 4;
} else {
return 2 + (options.width - 800) / 400;
}
})
.on('mouseover', function (d) {
if (options.openAps && d.openaps) {
client.tooltip.transition().duration(TOOLTIP_TRANS_MS).style('opacity', .9);
var text = '<b>BG:</b> ' + d.openaps.suggested.bg
+ ', ' + d.openaps.suggested.reason
+ (d.openaps.suggested.mealAssist ? ' <b>Meal Assist:</b> ' + d.openaps.suggested.mealAssist : '');
client.tooltip.html(text)
.style('left', (d3.event.pageX) + 'px')
.style('top', (d3.event.pageY + 15) + 'px');
}
})
.on('mouseout', hideTooltip);
if (badData.length > 0) {
console.warn('Bad Data: isNaN(sgv)', badData);
} }
return sel; })
.attr('fill', function(d) {
if (d.color === 'gray' && !options.raw) {
return 'transparent';
}
return d.color;
})
.style('opacity', function() { return 0.5 })
.attr('stroke-width', function(d) { if (d.type === 'mbg') { return 2; } else if (options.openAps && d.openaps) { return 1; } else { return 0; } })
.attr('stroke', function() { return 'black'; })
.attr('r', function(d) {
if (d.type === 'mbg') {
return 4;
} else {
return 2 + (options.width - 800) / 400;
}
})
.on('mouseover', function(d) {
if (options.openAps && d.openaps) {
client.tooltip.transition().duration(TOOLTIP_TRANS_MS).style('opacity', .9);
var text = '<b>BG:</b> ' + d.openaps.suggested.bg +
', ' + d.openaps.suggested.reason +
(d.openaps.suggested.mealAssist ? ' <b>Meal Assist:</b> ' + d.openaps.suggested.mealAssist : '');
client.tooltip.html(text)
.style('left', (d3.event.pageX) + 'px')
.style('top', (d3.event.pageY + 15) + 'px');
}
})
.on('mouseout', hideTooltip);
if (badData.length > 0) {
console.warn('Bad Data: isNaN(sgv)', badData);
} }
return sel;
}
// PREDICTIONS START // PREDICTIONS START
// //
function preparePredictedData() { function preparePredictedData () {
var treatmentsTimestamps = []; // Only timestamps for (carbs and bolus insulin) treatments will be captured in this array var treatmentsTimestamps = []; // Only timestamps for (carbs and bolus insulin) treatments will be captured in this array
treatmentsTimestamps.push(dataRange[0]); // Create a fake timestamp at midnight so we can show predictions during night treatmentsTimestamps.push(dataRange[0]); // Create a fake timestamp at midnight so we can show predictions during night
@@ -333,14 +327,14 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
if (undefined != treatment.insulin && null != treatment.insulin && treatment.insulin > 0) { if (undefined != treatment.insulin && null != treatment.insulin && treatment.insulin > 0) {
if (treatment.timestamp) if (treatment.timestamp)
treatmentsTimestamps.push(treatment.timestamp); treatmentsTimestamps.push(treatment.timestamp);
else if (treatment.created_at) else if (treatment.created_at)
treatmentsTimestamps.push(treatment.created_at); treatmentsTimestamps.push(treatment.created_at);
} }
} }
var predictions = []; var predictions = [];
if (data && data.devicestatus) { if (data && data.devicestatus) {
for (var i = data.devicestatus.length - 1; i >= 0; i--) { for (i = data.devicestatus.length - 1; i >= 0; i--) {
if (data.devicestatus[i].loop && data.devicestatus[i].loop.predicted) { if (data.devicestatus[i].loop && data.devicestatus[i].loop.predicted) {
predictions.push(data.devicestatus[i].loop.predicted); predictions.push(data.devicestatus[i].loop.predicted);
} else if (data.devicestatus[i].openaps && data.devicestatus[i].openaps.suggested && data.devicestatus[i].openaps.suggested.predBGs) { } else if (data.devicestatus[i].openaps && data.devicestatus[i].openaps.suggested && data.devicestatus[i].openaps.suggested.predBGs) {
@@ -363,10 +357,11 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
// Iterate over all treatments, find the predictions for each and add them to the predicted array p // Iterate over all treatments, find the predictions for each and add them to the predicted array p
for (var treatmentsIndex = 0; treatmentsIndex < treatmentsTimestamps.length; treatmentsIndex++) { for (var treatmentsIndex = 0; treatmentsIndex < treatmentsTimestamps.length; treatmentsIndex++) {
var timestamp = treatmentsTimestamps[treatmentsIndex]; var timestamp = treatmentsTimestamps[treatmentsIndex];
// TODO / BUG: predictedOffset is not set
var predictedIndex = findPredicted(predictions, timestamp, predictedOffset); // Find predictions offset before or after timestamp var predictedIndex = findPredicted(predictions, timestamp, predictedOffset); // Find predictions offset before or after timestamp
if (predictedIndex != null) { if (predictedIndex != null) {
var entry = predictions[predictedIndex]; // Start entry entry = predictions[predictedIndex]; // Start entry
var d = moment(entry.startDate); var d = moment(entry.startDate);
var end = moment().endOf('day'); var end = moment().endOf('day');
if (options.predictedTruncate) { if (options.predictedTruncate) {
@@ -399,7 +394,7 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
/* Find the earliest new predicted instance that has a timestamp equal to or larger than timestamp */ /* Find the earliest new predicted instance that has a timestamp equal to or larger than timestamp */
/* (so if we have bolused or eaten we want to find the prediction that Loop has estimated just after that) */ /* (so if we have bolused or eaten we want to find the prediction that Loop has estimated just after that) */
/* Returns the index into the predictions array that is the predicted we are looking for */ /* Returns the index into the predictions array that is the predicted we are looking for */
function findPredicted(predictions, timestamp, offset) { function findPredicted (predictions, timestamp, offset) {
var ts = moment(timestamp).add(offset, 'minutes'); var ts = moment(timestamp).add(offset, 'minutes');
var predicted = null; var predicted = null;
if (offset && offset < 0) { // If offset is negative, start searching from first prediction going forward if (offset && offset < 0) { // If offset is negative, start searching from first prediction going forward
@@ -408,8 +403,8 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
predicted = i; predicted = i;
} }
} }
} else { // If offset is positive or zero, start searching from last prediction going backward } else { // If offset is positive or zero, start searching from last prediction going backward
for (var i = predictions.length - 1; i > 0; i--) { for (i = predictions.length - 1; i > 0; i--) {
if (predictions[i] && predictions[i].startDate && moment(predictions[i].startDate) >= ts) { if (predictions[i] && predictions[i].startDate && moment(predictions[i].startDate) >= ts) {
predicted = i; predicted = i;
} }
@@ -420,7 +415,6 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
// //
// PREDICTIONS ENDS // PREDICTIONS ENDS
// bind up the context chart data to an array of circles // bind up the context chart data to an array of circles
var contextData = (options.predicted ? data.sgv.concat(preparePredictedData()) : data.sgv); var contextData = (options.predicted ? data.sgv.concat(preparePredictedData()) : data.sgv);
var contextCircles = context.selectAll('circle').data(contextData); var contextCircles = context.selectAll('circle').data(contextData);
@@ -431,10 +425,11 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
contextCircles.exit() contextCircles.exit()
.remove(); .remove();
var to = moment(day).add(1, 'days'); var to = moment(day).add(1, 'days');
var from = moment(day); var from = moment(day);
var iobpolyline = '', cobpolyline = ''; var iobpolyline = ''
, cobpolyline = '';
// basals data // basals data
var linedata = []; var linedata = [];
var notemplinedata = []; var notemplinedata = [];
@@ -448,13 +443,13 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
data.netBasalPositive = []; data.netBasalPositive = [];
data.netBasalNegative = []; data.netBasalNegative = [];
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23].forEach(function(hour) { [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23].forEach(function(hour) {
data.netBasalPositive[hour] = 0; data.netBasalPositive[hour] = 0;
data.netBasalNegative[hour] = 0; data.netBasalNegative[hour] = 0;
}); });
profile.updateTreatments(datastorage.profileSwitchTreatments, datastorage.tempbasalTreatments, datastorage.combobolusTreatments); profile.updateTreatments(datastorage.profileSwitchTreatments, datastorage.tempbasalTreatments, datastorage.combobolusTreatments);
var bolusInsulin = 0; var bolusInsulin = 0;
var baseBasalInsulin = 0; var baseBasalInsulin = 0;
var positiveTemps = 0; var positiveTemps = 0;
@@ -469,9 +464,9 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
console.log("Device COB status available: ", cobStatusAvailable); console.log("Device COB status available: ", cobStatusAvailable);
console.log("Device IOB status available: ", iobStatusAvailable); console.log("Device IOB status available: ", iobStatusAvailable);
for (var dt=moment(from); dt < to; dt.add(5, 'minutes')) { for (var dt = moment(from); dt < to; dt.add(5, 'minutes')) {
if (options.iob && !iobStatusAvailable) { if (options.iob && !iobStatusAvailable) {
var iob = client.plugins('iob').calcTotal(datastorage.treatments,datastorage.devicestatus,profile,dt.toDate()).iob; var iob = client.plugins('iob').calcTotal(datastorage.treatments, datastorage.devicestatus, profile, dt.toDate()).iob;
// make the graph discontinuous when data is missing // make the graph discontinuous when data is missing
if (iob === undefined) { if (iob === undefined) {
iobpolyline += ', ' + (xScale2(lastDt) + padding.left) + ',' + (yInsulinScale(0) + padding.top); iobpolyline += ', ' + (xScale2(lastDt) + padding.left) + ',' + (yInsulinScale(0) + padding.top);
@@ -480,19 +475,19 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
if (lastIOB === undefined) { if (lastIOB === undefined) {
iobpolyline += ', ' + (xScale2(dt) + padding.left) + ',' + (yInsulinScale(0) + padding.top); iobpolyline += ', ' + (xScale2(dt) + padding.left) + ',' + (yInsulinScale(0) + padding.top);
} }
iobpolyline += ', '+ (xScale2(dt) + padding.left) + ',' + (yInsulinScale(iob) + padding.top); iobpolyline += ', ' + (xScale2(dt) + padding.left) + ',' + (yInsulinScale(iob) + padding.top);
} }
lastDt = dt.clone(); lastDt = dt.clone();
lastIOB = iob; lastIOB = iob;
} }
if (options.cob && !cobStatusAvailable) { if (options.cob && !cobStatusAvailable) {
var cob = client.plugins('cob').cobTotal(datastorage.treatments,datastorage.devicestatus,profile,dt.toDate()).cob; var cob = client.plugins('cob').cobTotal(datastorage.treatments, datastorage.devicestatus, profile, dt.toDate()).cob;
if (!dt.isSame(from)) { if (!dt.isSame(from)) {
cobpolyline += ', '; cobpolyline += ', ';
} }
cobpolyline += (xScale2(dt.toDate()) + padding.left) + ',' + (yCarbsScale(cob) + padding.top) + ' '; cobpolyline += (xScale2(dt.toDate()) + padding.left) + ',' + (yCarbsScale(cob) + padding.top) + ' ';
} }
if (options.basal) { if (options.basal) {
var date = dt.format('x'); var date = dt.format('x');
var hournow = dt.hour(); var hournow = dt.hour();
var basalvalue = profile.getTempBasal(date); var basalvalue = profile.getTempBasal(date);
@@ -502,26 +497,27 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
if (tempPart > 0) { if (tempPart > 0) {
positiveTemps += tempPart; positiveTemps += tempPart;
data.netBasalPositive[hournow] += tempPart; data.netBasalPositive[hournow] += tempPart;
} if (tempPart < 0) { }
if (tempPart < 0) {
negativeTemps += tempPart; negativeTemps += tempPart;
data.netBasalNegative[hournow] += tempPart; data.netBasalNegative[hournow] += tempPart;
} }
if (!_.isEqual(lastbasal, basalvalue)) { if (!_.isEqual(lastbasal, basalvalue)) {
linedata.push( { d: date, b: basalvalue.totalbasal } ); linedata.push({ d: date, b: basalvalue.totalbasal });
notemplinedata.push( { d: date, b: basalvalue.basal } ); notemplinedata.push({ d: date, b: basalvalue.basal });
if (basalvalue.combobolustreatment && basalvalue.combobolustreatment.relative) { if (basalvalue.combobolustreatment && basalvalue.combobolustreatment.relative) {
tempbasalareadata.push( { d: date, b: basalvalue.tempbasal } ); tempbasalareadata.push({ d: date, b: basalvalue.tempbasal });
basalareadata.push( { d: date, b: 0 } ); basalareadata.push({ d: date, b: 0 });
comboareadata.push( { d: date, b: basalvalue.totalbasal } ); comboareadata.push({ d: date, b: basalvalue.totalbasal });
} else if (basalvalue.treatment) { } else if (basalvalue.treatment) {
tempbasalareadata.push( { d: date, b: basalvalue.totalbasal } ); tempbasalareadata.push({ d: date, b: basalvalue.totalbasal });
basalareadata.push( { d: date, b: 0 } ); basalareadata.push({ d: date, b: 0 });
comboareadata.push( { d: date, b: 0 } ); comboareadata.push({ d: date, b: 0 });
} else { } else {
tempbasalareadata.push( { d: date, b: 0 } ); tempbasalareadata.push({ d: date, b: 0 });
basalareadata.push( { d: date, b: basalvalue.totalbasal } ); basalareadata.push({ d: date, b: basalvalue.totalbasal });
comboareadata.push( { d: date, b: 0 } ); comboareadata.push({ d: date, b: 0 });
} }
} }
lastbasal = basalvalue; lastbasal = basalvalue;
@@ -552,8 +548,8 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
// Draw IOB from devicestatuses if available // Draw IOB from devicestatuses if available
if (iobStatusAvailable) { if (iobStatusAvailable) {
var lastdate = 0; lastdate = 0;
var previousdate = 0; previousdate = 0;
var iobArray = client.plugins('iob').IOBDeviceStatusesInTimeRange(datastorage.devicestatus, from.valueOf(), to.valueOf()); var iobArray = client.plugins('iob').IOBDeviceStatusesInTimeRange(datastorage.devicestatus, from.valueOf(), to.valueOf());
_.each(iobArray, function drawCob (point) { _.each(iobArray, function drawCob (point) {
if (previousdate !== 0 && point.mills - previousdate > times.mins(15).msecs) { if (previousdate !== 0 && point.mills - previousdate > times.mins(15).msecs) {
@@ -577,24 +573,24 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.attr('stroke', 'blue') .attr('stroke', 'blue')
.attr('opacity', '0.5') .attr('opacity', '0.5')
.attr('fill-opacity', '0.1') .attr('fill-opacity', '0.1')
.attr('points',iobpolyline); .attr('points', iobpolyline);
} }
if (options.cob) { if (options.cob) {
context.append('polyline') context.append('polyline')
.attr('stroke', 'red') .attr('stroke', 'red')
.attr('opacity', '0.5') .attr('opacity', '0.5')
.attr('fill-opacity', '0.1') .attr('fill-opacity', '0.1')
.attr('points',cobpolyline); .attr('points', cobpolyline);
} }
if (options.basal) { if (options.basal) {
var toTempBasal = profile.getTempBasal(to.format('x')); var toTempBasal = profile.getTempBasal(to.format('x'));
linedata.push( { d: to.format('x'), b: toTempBasal.totalbasal } ); linedata.push({ d: to.format('x'), b: toTempBasal.totalbasal });
notemplinedata.push( { d: to.format('x'), b: toTempBasal.basal } ); notemplinedata.push({ d: to.format('x'), b: toTempBasal.basal });
basalareadata.push( { d: to.format('x'), b: toTempBasal.basal } ); basalareadata.push({ d: to.format('x'), b: toTempBasal.basal });
tempbasalareadata.push( { d: to.format('x'), b: toTempBasal.totalbasal } ); tempbasalareadata.push({ d: to.format('x'), b: toTempBasal.totalbasal });
comboareadata.push( { d: to.format('x'), b: toTempBasal.totalbasal } ); comboareadata.push({ d: to.format('x'), b: toTempBasal.totalbasal });
var basalMax = d3.max(linedata, function(d) { return d.b; }); var basalMax = d3.max(linedata, function(d) { return d.b; });
basalMax = Math.max(basalMax, d3.max(basalareadata, function(d) { return d.b; })); basalMax = Math.max(basalMax, d3.max(basalareadata, function(d) { return d.b; }));
@@ -657,7 +653,7 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.attr('stroke-width', 1) .attr('stroke-width', 1)
.attr('d', area); .attr('d', area);
datastorage.tempbasalTreatments.forEach(function (t) { datastorage.tempbasalTreatments.forEach(function(t) {
// only if basal and focus interval overlap and there is a chance to fit // only if basal and focus interval overlap and there is a chance to fit
if (t.mills < to.format('x') && t.mills + times.mins(t.duration).msecs > from.format('x')) { if (t.mills < to.format('x') && t.mills + times.mins(t.duration).msecs > from.format('x')) {
var text = g.append('text') var text = g.append('text')
@@ -667,9 +663,9 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.attr('fill', '#0099ff') .attr('fill', '#0099ff')
.attr('text-anchor', 'middle') .attr('text-anchor', 'middle')
.attr('dy', '.35em') .attr('dy', '.35em')
.attr('x', xScale2((Math.max(t.mills, from.format('x')) + Math.min(t.mills + times.mins(t.duration).msecs, to.format('x')))/2) + padding.left) .attr('x', xScale2((Math.max(t.mills, from.format('x')) + Math.min(t.mills + times.mins(t.duration).msecs, to.format('x'))) / 2) + padding.left)
.attr('y', yScaleBasals(0) - 10 + padding.top) .attr('y', yScaleBasals(0) - 10 + padding.top)
// .text((t.percent ? (t.percent > 0 ? '+' : '') + t.percent + '%' : '') + (t.absolute ? Number(t.absolute).toFixed(2) + 'U' : '')); // .text((t.percent ? (t.percent > 0 ? '+' : '') + t.percent + '%' : '') + (t.absolute ? Number(t.absolute).toFixed(2) + 'U' : ''));
// better hide if not fit // better hide if not fit
if (text.node().getBBox().width > xScale2(t.mills + times.mins(t.duration).msecs) - xScale2(t.mills)) { if (text.node().getBBox().width > xScale2(t.mills + times.mins(t.duration).msecs) - xScale2(t.mills)) {
text.attr('display', 'none'); text.attr('display', 'none');
@@ -678,8 +674,7 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
}); });
} }
data.treatments.forEach(function(treatment) {
data.treatments.forEach(function (treatment) {
// Calculate bolus stats // Calculate bolus stats
if (treatment.insulin) { if (treatment.insulin) {
bolusInsulin += treatment.insulin; bolusInsulin += treatment.insulin;
@@ -698,10 +693,10 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
var drawpointer = false; var drawpointer = false;
if (treatment.boluscalc && treatment.boluscalc.foods && treatment.boluscalc.foods.length > 0 && options.food) { if (treatment.boluscalc && treatment.boluscalc.foods && treatment.boluscalc.foods.length > 0 && options.food) {
var foods = treatment.boluscalc.foods; var foods = treatment.boluscalc.foods;
for (var fi=0; fi<foods.length; fi++) { for (var fi = 0; fi < foods.length; fi++) {
var f = foods[fi]; var f = foods[fi];
var text = ''+ f.name + ' '; var text = '' + f.name + ' ';
text += ''+ (f.carbs*f.portions).toFixed(1) + ' g'; text += '' + (f.carbs * f.portions).toFixed(1) + ' g';
context.append('text') context.append('text')
.style('font-size', '10px') .style('font-size', '10px')
.style('font-weight', 'normal') .style('font-weight', 'normal')
@@ -721,7 +716,7 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.attr('y', foodtexts * 15 + padding.top) .attr('y', foodtexts * 15 + padding.top)
.attr('transform', 'translate(' + (xScale2(treatment.mills) + padding.left) + ',' + padding.top + ')') .attr('transform', 'translate(' + (xScale2(treatment.mills) + padding.left) + ',' + padding.top + ')')
.html(treatment.notes); .html(treatment.notes);
foodtexts = (foodtexts+1)%6; foodtexts = (foodtexts + 1) % 6;
drawpointer = true; drawpointer = true;
} }
if (drawpointer) { if (drawpointer) {
@@ -730,7 +725,7 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.attr('x1', xScale2(treatment.mills) + padding.left) .attr('x1', xScale2(treatment.mills) + padding.left)
.attr('y1', lastfoodtext * 15 + padding.top) .attr('y1', lastfoodtext * 15 + padding.top)
.attr('x2', xScale2(treatment.mills) + padding.left) .attr('x2', xScale2(treatment.mills) + padding.left)
.attr('y2', padding.top + treatment.carbs ? yCarbsScale(treatment.carbs) : ( treatment.insulin ? yInsulinScale(treatment.insulin) : chartHeight)) .attr('y2', padding.top + treatment.carbs ? yCarbsScale(treatment.carbs) : (treatment.insulin ? yInsulinScale(treatment.insulin) : chartHeight))
.style('stroke-dasharray', ('1, 7')) .style('stroke-dasharray', ('1, 7'))
.attr('stroke', 'grey'); .attr('stroke', 'grey');
} }
@@ -738,14 +733,14 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
if (treatment.carbs && options.carbs) { if (treatment.carbs && options.carbs) {
var ic = profile.getCarbRatio(new Date(treatment.mills)); var ic = profile.getCarbRatio(new Date(treatment.mills));
var label = ' ' + treatment.carbs +' g'; var label = ' ' + treatment.carbs + ' g';
if (treatment.protein) label += ' / ' + treatment.protein +' g'; if (treatment.protein) label += ' / ' + treatment.protein + ' g';
if (treatment.fat) label += ' / ' + treatment.fat +' g'; if (treatment.fat) label += ' / ' + treatment.fat + ' g';
label += ' ('+(treatment.carbs/ic).toFixed(2)+'U)'; label += ' (' + (treatment.carbs / ic).toFixed(2) + 'U)';
context.append('rect') context.append('rect')
.attr('y',yCarbsScale(treatment.carbs)) .attr('y', yCarbsScale(treatment.carbs))
.attr('height', chartHeight-yCarbsScale(treatment.carbs)) .attr('height', chartHeight - yCarbsScale(treatment.carbs))
.attr('width', 5) .attr('width', 5)
.attr('stroke', 'red') .attr('stroke', 'red')
.attr('opacity', '0.5') .attr('opacity', '0.5')
@@ -755,15 +750,15 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.style('font-size', '12px') .style('font-size', '12px')
.style('font-weight', 'bold') .style('font-weight', 'bold')
.attr('fill', 'red') .attr('fill', 'red')
.attr('transform', 'rotate(-45,' + (xScale2(treatment.mills) + padding.left) + ',' + (padding.top+yCarbsScale(treatment.carbs)) + ') ' + .attr('transform', 'rotate(-45,' + (xScale2(treatment.mills) + padding.left) + ',' + (padding.top + yCarbsScale(treatment.carbs)) + ') ' +
'translate(' + (xScale2(treatment.mills) + padding.left +10) + ',' + (padding.top+yCarbsScale(treatment.carbs)) + ')') 'translate(' + (xScale2(treatment.mills) + padding.left + 10) + ',' + (padding.top + yCarbsScale(treatment.carbs)) + ')')
.text(''+label); .text('' + label);
} }
if (treatment.insulin && options.insulin) { if (treatment.insulin && options.insulin) {
context.append('rect') context.append('rect')
.attr('y',yInsulinScale(treatment.insulin)) .attr('y', yInsulinScale(treatment.insulin))
.attr('height', chartHeight-yInsulinScale(treatment.insulin)) .attr('height', chartHeight - yInsulinScale(treatment.insulin))
.attr('width', 5) .attr('width', 5)
.attr('stroke', 'blue') .attr('stroke', 'blue')
.attr('opacity', '0.5') .attr('opacity', '0.5')
@@ -774,11 +769,11 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.style('font-weight', 'bold') .style('font-weight', 'bold')
.attr('fill', 'blue') .attr('fill', 'blue')
//.attr('y', yInsulinScale(treatment.insulin)-10) //.attr('y', yInsulinScale(treatment.insulin)-10)
.attr('transform', 'rotate(-45,' + (xScale2(treatment.mills) + padding.left - 2) + ',' + (padding.top+yInsulinScale(treatment.insulin)) + ')' + .attr('transform', 'rotate(-45,' + (xScale2(treatment.mills) + padding.left - 2) + ',' + (padding.top + yInsulinScale(treatment.insulin)) + ')' +
'translate(' + (xScale2(treatment.mills) + padding.left + 10) + ',' + (padding.top+yInsulinScale(treatment.insulin)) + ')') 'translate(' + (xScale2(treatment.mills) + padding.left + 10) + ',' + (padding.top + yInsulinScale(treatment.insulin)) + ')')
.text(Number(treatment.insulin).toFixed(2)+'U'); .text(Number(treatment.insulin).toFixed(2) + 'U');
} }
// process the rest // process the rest
if (treatment.insulin || treatment.carbs || treatment.eventType == 'Temp Basal' || treatment.eventType == 'Combo Bolus') { if (treatment.insulin || treatment.carbs || treatment.eventType == 'Temp Basal' || treatment.eventType == 'Combo Bolus') {
// ignore // ignore
@@ -810,7 +805,7 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.attr('text-anchor', 'middle') .attr('text-anchor', 'middle')
.attr('dy', '.35em') .attr('dy', '.35em')
.attr('y', yScale2(client.utils.scaleMgdl(378)) + padding.top) .attr('y', yScale2(client.utils.scaleMgdl(378)) + padding.top)
.attr('x', xScale2(treatment.mills + times.mins(treatment.duration).msecs/2) + padding.left) .attr('x', xScale2(treatment.mills + times.mins(treatment.duration).msecs / 2) + padding.left)
.text(treatment.notes); .text(treatment.notes);
} else if (treatment.eventType === 'Note' && treatment.duration) { } else if (treatment.eventType === 'Note' && treatment.duration) {
context.append('rect') context.append('rect')
@@ -829,7 +824,7 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.attr('text-anchor', 'middle') .attr('text-anchor', 'middle')
.attr('dy', '.35em') .attr('dy', '.35em')
.attr('y', yScale2(client.utils.scaleMgdl(342)) + padding.top) .attr('y', yScale2(client.utils.scaleMgdl(342)) + padding.top)
.attr('x', xScale2(treatment.mills + times.mins(treatment.duration).msecs/2) + padding.left) .attr('x', xScale2(treatment.mills + times.mins(treatment.duration).msecs / 2) + padding.left)
.text(treatment.notes); .text(treatment.notes);
} else if (treatment.eventType === 'OpenAPS Offline' && treatment.duration) { } else if (treatment.eventType === 'OpenAPS Offline' && treatment.duration) {
context.append('rect') context.append('rect')
@@ -848,13 +843,13 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.attr('text-anchor', 'middle') .attr('text-anchor', 'middle')
.attr('dy', '.35em') .attr('dy', '.35em')
.attr('y', yScale2(client.utils.scaleMgdl(306)) + padding.top) .attr('y', yScale2(client.utils.scaleMgdl(306)) + padding.top)
.attr('x', xScale2(treatment.mills + times.mins(treatment.duration).msecs/2) + padding.left) .attr('x', xScale2(treatment.mills + times.mins(treatment.duration).msecs / 2) + padding.left)
.text(treatment.notes); .text(treatment.notes);
} else if (!treatment.duration) { } else if (!treatment.duration) {
// other treatments without duration // other treatments without duration
context.append('circle') context.append('circle')
.attr('cx', xScale2(treatment.mills) + padding.left) .attr('cx', xScale2(treatment.mills) + padding.left)
.attr('cy', yScale2(scaledTreatmentBG(treatment,data.sgv)) + padding.top) .attr('cy', yScale2(scaledTreatmentBG(treatment, data.sgv)) + padding.top)
.attr('fill', 'purple') .attr('fill', 'purple')
.style('opacity', 1) .style('opacity', 1)
.attr('stroke-width', 1) .attr('stroke-width', 1)
@@ -864,11 +859,11 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.style('font-size', '12px') .style('font-size', '12px')
.style('font-weight', 'bold') .style('font-weight', 'bold')
.attr('fill', 'purple') .attr('fill', 'purple')
.attr('y', yScale2(scaledTreatmentBG(treatment,data.sgv)) + padding.top -10) .attr('y', yScale2(scaledTreatmentBG(treatment, data.sgv)) + padding.top - 10)
.attr('x', xScale2(treatment.mills) + padding.left + 10) .attr('x', xScale2(treatment.mills) + padding.left + 10)
.text(translate(client.careportal.resolveEventName(treatment.eventType))); .text(translate(client.careportal.resolveEventName(treatment.eventType)));
} else if (treatment.duration) { } else if (treatment.duration) {
// other treatments with duration // other treatments with duration
context.append('rect') context.append('rect')
.attr('x', xScale2(treatment.mills) + padding.left) .attr('x', xScale2(treatment.mills) + padding.left)
.attr('y', yScale2(client.utils.scaleMgdl(432)) + padding.top) .attr('y', yScale2(client.utils.scaleMgdl(432)) + padding.top)
@@ -885,13 +880,13 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.attr('text-anchor', 'middle') .attr('text-anchor', 'middle')
.attr('dy', '.35em') .attr('dy', '.35em')
.attr('y', yScale2(client.utils.scaleMgdl(414)) + padding.top) .attr('y', yScale2(client.utils.scaleMgdl(414)) + padding.top)
.attr('x', xScale2(treatment.mills + times.mins(treatment.duration).msecs/2) + padding.left) .attr('x', xScale2(treatment.mills + times.mins(treatment.duration).msecs / 2) + padding.left)
.text(treatment.notes); .text(treatment.notes);
} else { } else {
console.log("missed treatment", treatment); console.log("missed treatment", treatment);
} }
}); });
if (options.insulindistribution) { if (options.insulindistribution) {
var boluscolor = 'blue'; var boluscolor = 'blue';
var basalcolor = '#0099ff'; var basalcolor = '#0099ff';
@@ -916,17 +911,17 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
$('<tr><td>' + translate('Total carbs') + ':</td><td align="right">' + data.dailyCarbs + ' g</td></tr>').appendTo(table); $('<tr><td>' + translate('Total carbs') + ':</td><td align="right">' + data.dailyCarbs + ' g</td></tr>').appendTo(table);
$('<tr><td>' + translate('Total protein') + ':</td><td align="right">' + data.dailyProtein + ' g</td></tr>').appendTo(table); $('<tr><td>' + translate('Total protein') + ':</td><td align="right">' + data.dailyProtein + ' g</td></tr>').appendTo(table);
$('<tr><td>' + translate('Total fat') + ':</td><td align="right">' + data.dailyFat + ' g</td></tr>').appendTo(table); $('<tr><td>' + translate('Total fat') + ':</td><td align="right">' + data.dailyFat + ' g</td></tr>').appendTo(table);
$('<tr><td colspan="2"><span id="daytodaystatinsulinpiechart-' + day + '"></span><span id="daytodaystatcarbspiechart-' + day + '"></span></td></tr>').appendTo(table); $('<tr><td colspan="2"><span id="daytodaystatinsulinpiechart-' + day + '"></span><span id="daytodaystatcarbspiechart-' + day + '"></span></td></tr>').appendTo(table);
$('#daytodaystatchart-' + day).append(table); $('#daytodaystatchart-' + day).append(table);
var chartData = [ var chartData = [
{ {
label: translate('Basal'), label: translate('Basal')
count: totalBasalInsulin, , count: totalBasalInsulin
pct: (totalBasalInsulin / totalDailyInsulin * 100).toFixed(0) , pct: (totalBasalInsulin / totalDailyInsulin * 100).toFixed(0)
}, }
{label: translate('Bolus'), count: bolusInsulin, pct: (bolusInsulin / totalDailyInsulin * 100).toFixed(0)} , { label: translate('Bolus'), count: bolusInsulin, pct: (bolusInsulin / totalDailyInsulin * 100).toFixed(0) }
]; ];
// Insulin distribution chart // Insulin distribution chart
@@ -937,98 +932,98 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
var color = d3.scale.ordinal().range([basalcolor, boluscolor]); var color = d3.scale.ordinal().range([basalcolor, boluscolor]);
var labelArc = d3.svg.arc() var labelArc = d3.svg.arc()
.outerRadius(radius / 2) .outerRadius(radius / 2)
.innerRadius(radius / 2); .innerRadius(radius / 2);
var svg = d3.select('#daytodaystatinsulinpiechart-' + day) var svg = d3.select('#daytodaystatinsulinpiechart-' + day)
.append('svg') .append('svg')
.attr('width', width) .attr('width', width)
.attr('height', height) .attr('height', height)
.append('g') .append('g')
.attr('transform', 'translate(' + (width / 2) + .attr('transform', 'translate(' + (width / 2) +
',' + (height / 2) + ')'); ',' + (height / 2) + ')');
var arc = d3.svg.arc() var arc = d3.svg.arc()
.outerRadius(radius); .outerRadius(radius);
var pie = d3.layout.pie() var pie = d3.layout.pie()
.value(function (d) { .value(function(d) {
return d.count; return d.count;
}) })
.sort(null); .sort(null);
var insulg = svg.selectAll('.insulinarc') var insulg = svg.selectAll('.insulinarc')
.data(pie(chartData)) .data(pie(chartData))
.enter() .enter()
.append('g') .append('g')
.attr('class', 'insulinarc'); .attr('class', 'insulinarc');
insulg.append('path') insulg.append('path')
.attr('d', arc) .attr('d', arc)
.attr('opacity', '0.5') .attr('opacity', '0.5')
.attr('fill', function (d) { .attr('fill', function(d) {
return color(d.data.label); return color(d.data.label);
}); });
insulg.append('text') insulg.append('text')
.attr('transform', function (d) { .attr('transform', function(d) {
return 'translate(' + labelArc.centroid(d) + ')'; return 'translate(' + labelArc.centroid(d) + ')';
}) })
.attr('dy', '.15em') .attr('dy', '.15em')
.style('font-weight', 'bold') .style('font-weight', 'bold')
.attr('text-anchor', 'middle') .attr('text-anchor', 'middle')
.text(function (d) { .text(function(d) {
return d.data.pct + '%'; return d.data.pct + '%';
}); });
// Carbs pie chart // Carbs pie chart
var carbscolor = d3.scale.ordinal().range(['red']); var carbscolor = d3.scale.ordinal().range(['red']);
var carbsData = [ var carbsData = [
{label: translate('Carbs'), count: data.dailyCarbs} { label: translate('Carbs'), count: data.dailyCarbs }
]; ];
var carbssvg = d3.select('#daytodaystatcarbspiechart-' + day) var carbssvg = d3.select('#daytodaystatcarbspiechart-' + day)
.append('svg') .append('svg')
.attr('width', width) .attr('width', width)
.attr('height', height) .attr('height', height)
.append('g') .append('g')
.attr('transform', 'translate(' + (width / 2) + .attr('transform', 'translate(' + (width / 2) +
',' + (height / 2) + ')'); ',' + (height / 2) + ')');
var carbsarc = d3.svg.arc() var carbsarc = d3.svg.arc()
.outerRadius(radius * data.dailyCarbs / options.maxDailyCarbsValue); .outerRadius(radius * data.dailyCarbs / options.maxDailyCarbsValue);
var carbspie = d3.layout.pie() var carbspie = d3.layout.pie()
.value(function (d) { .value(function(d) {
return d.count; return d.count;
}) })
.sort(null); .sort(null);
var carbsg = carbssvg.selectAll('.carbsarc') var carbsg = carbssvg.selectAll('.carbsarc')
.data(carbspie(carbsData)) .data(carbspie(carbsData))
.enter() .enter()
.append('g') .append('g')
.attr('class', 'carbsarc'); .attr('class', 'carbsarc');
carbsg.append('path') carbsg.append('path')
.attr('d', carbsarc) .attr('d', carbsarc)
.attr('opacity', '0.5') .attr('opacity', '0.5')
.attr('fill', function (d) { .attr('fill', function(d) {
return carbscolor(d.data.label); return carbscolor(d.data.label);
}); });
carbsg.append('text') carbsg.append('text')
.attr('transform', function () { .attr('transform', function() {
return 'translate(0,0)'; return 'translate(0,0)';
}) })
.attr('dy', '.15em') .attr('dy', '.15em')
.style('font-weight', 'bold') .style('font-weight', 'bold')
.attr('text-anchor', 'middle') .attr('text-anchor', 'middle')
.text(function (d) { .text(function(d) {
return d.data.count + 'g'; return d.data.count + 'g';
}); });
} }
tddSum += totalDailyInsulin; tddSum += totalDailyInsulin;
@@ -1043,15 +1038,15 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
, first: true , first: true
}); });
function appendProfileSwitch(context, treatment) { function appendProfileSwitch (context, treatment) {
if (!treatment.cutting && !treatment.profile) { return; } if (!treatment.cutting && !treatment.profile) { return; }
var sign = treatment.first ? '▲▲▲' : '▬▬▬'; var sign = treatment.first ? '▲▲▲' : '▬▬▬';
var text; var text;
if (treatment.cutting) { if (treatment.cutting) {
text = sign + ' ' + client.profilefunctions.profileSwitchName(treatment.cutting) + ' ' + '►►►' + ' ' + client.profilefunctions.profileSwitchName(treatment.profile) + ' ' + sign; text = sign + ' ' + client.profilefunctions.profileSwitchName(treatment.cutting) + ' ' + '►►►' + ' ' + client.profilefunctions.profileSwitchName(treatment.profile) + ' ' + sign;
} else { } else {
text = sign + ' ' + client.profilefunctions.profileSwitchName(treatment.profile) + ' ' + sign; text = sign + ' ' + client.profilefunctions.profileSwitchName(treatment.profile) + ' ' + sign;
} }
context.append('text') context.append('text')
@@ -1060,7 +1055,7 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
.attr('fill', '#0099ff') .attr('fill', '#0099ff')
.attr('text-anchor', 'start') .attr('text-anchor', 'start')
.attr('dy', '.35em') .attr('dy', '.35em')
.attr('transform', 'rotate(-90 ' + (xScale2(treatment.mills) + padding.left) + ',' + (yScaleBasals(0) + padding.top - 10) + ') ' + .attr('transform', 'rotate(-90 ' + (xScale2(treatment.mills) + padding.left) + ',' + (yScaleBasals(0) + padding.top - 10) + ') ' +
'translate(' + (xScale2(treatment.mills) + padding.left) + ',' + (yScaleBasals(0) + padding.top - 10) + ')') 'translate(' + (xScale2(treatment.mills) + padding.left) + ',' + (yScaleBasals(0) + padding.top - 10) + ')')
.text(text); .text(text);
} }
@@ -1068,7 +1063,7 @@ daytoday.report = function report_daytoday(datastorage,sorteddaystoshow,options)
console.log("Rendering " + day, new Date().getTime() - timestart.getTime(), "msecs"); console.log("Rendering " + day, new Date().getTime() - timestart.getTime(), "msecs");
} }
function hideTooltip ( ) { function hideTooltip () {
client.tooltip.transition() client.tooltip.transition()
.duration(TOOLTIP_TRANS_MS) .duration(TOOLTIP_TRANS_MS)
.style('opacity', 0); .style('opacity', 0);
+24 -26
View File
@@ -6,13 +6,13 @@ var glucosedistribution = {
, pluginType: 'report' , pluginType: 'report'
}; };
function init() { function init () {
return glucosedistribution; return glucosedistribution;
} }
module.exports = init; module.exports = init;
glucosedistribution.html = function html(client) { glucosedistribution.html = function html (client) {
var translate = client.translate; var translate = client.translate;
var ret = var ret =
'<h2>' + '<h2>' +
@@ -65,8 +65,7 @@ glucosedistribution.html = function html(client) {
'20<input type="checkbox" id="glucosedistribution-20" checked>' + '20<input type="checkbox" id="glucosedistribution-20" checked>' +
'21<input type="checkbox" id="glucosedistribution-21" checked>' + '21<input type="checkbox" id="glucosedistribution-21" checked>' +
'22<input type="checkbox" id="glucosedistribution-22" checked>' + '22<input type="checkbox" id="glucosedistribution-22" checked>' +
'23<input type="checkbox" id="glucosedistribution-23" checked>' '23<input type="checkbox" id="glucosedistribution-23" checked>';
;
return ret; return ret;
}; };
@@ -83,7 +82,7 @@ glucosedistribution.css =
' text-align:center;' + ' text-align:center;' +
'}'; '}';
glucosedistribution.report = function report_glucosedistribution(datastorage, sorteddaystoshow, options) { glucosedistribution.report = function report_glucosedistribution (datastorage, sorteddaystoshow, options) {
var Nightscout = window.Nightscout; var Nightscout = window.Nightscout;
var client = Nightscout.client; var client = Nightscout.client;
var translate = client.translate; var translate = client.translate;
@@ -132,13 +131,13 @@ glucosedistribution.report = function report_glucosedistribution(datastorage, so
// Filter data for noise // Filter data for noise
// data cleaning pass 0 - remove duplicates and non-sgv entries, sort // data cleaning pass 0 - remove duplicates and non-sgv entries, sort
var seen = {}; var seen = [];
data = data.filter(function(item) { data = data.filter(function(item) {
if (!item.sgv || !item.bgValue || !item.displayTime || item.bgValue < 39) { if (!item.sgv || !item.bgValue || !item.displayTime || item.bgValue < 39) {
console.log(item); console.log(item);
return false; return false;
} }
return seen.hasOwnProperty(item.displayTime) ? false : (seen[item.displayTime] = true); return seen.includes(item.displayTime) ? false : (seen[item.displayTime] = true);
}); });
data.sort(function(a, b) { data.sort(function(a, b) {
@@ -148,7 +147,7 @@ glucosedistribution.report = function report_glucosedistribution(datastorage, so
var glucose_data = [data[0]]; var glucose_data = [data[0]];
// data cleaning pass 1 - add interpolated missing points // data cleaning pass 1 - add interpolated missing points
for (var i = 0; i <= data.length - 2; i++) { for (i = 0; i <= data.length - 2; i++) {
var entry = data[i]; var entry = data[i];
var nextEntry = data[i + 1]; var nextEntry = data[i + 1];
@@ -186,12 +185,12 @@ glucosedistribution.report = function report_glucosedistribution(datastorage, so
const maxGap = (5 * 60 * 1000) + 10000; const maxGap = (5 * 60 * 1000) + 10000;
for (var i = 1; i <= glucose_data.length - 2; i++) { for (i = 1; i <= glucose_data.length - 2; i++) {
var entry = glucose_data[i]; let entry = glucose_data[i];
var nextEntry = glucose_data[i + 1]; let nextEntry = glucose_data[i + 1];
var timeDelta = nextEntry.displayTime.getTime() - entry.displayTime.getTime(); let timeDelta = nextEntry.displayTime.getTime() - entry.displayTime.getTime();
var timeDelta2 = entry.displayTime.getTime() - prevEntry.displayTime.getTime(); let timeDelta2 = entry.displayTime.getTime() - prevEntry.displayTime.getTime();
if (timeDelta > maxGap || timeDelta2 > maxGap) { if (timeDelta > maxGap || timeDelta2 > maxGap) {
glucose_data2.push(entry); glucose_data2.push(entry);
@@ -212,8 +211,8 @@ glucosedistribution.report = function report_glucosedistribution(datastorage, so
const d = (nextEntry.bgValue - prevEntry.bgValue) / 2; const d = (nextEntry.bgValue - prevEntry.bgValue) / 2;
const interpolatedValue = prevEntry.bgValue + d; const interpolatedValue = prevEntry.bgValue + d;
var newEntry = { let newEntry = {
sgv: displayUnits === 'mmol' ? interpolatedValue/18 : interpolatedValue sgv: displayUnits === 'mmol' ? interpolatedValue / 18 : interpolatedValue
, bgValue: interpolatedValue , bgValue: interpolatedValue
, displayTime: entry.displayTime , displayTime: entry.displayTime
}; };
@@ -237,10 +236,10 @@ glucosedistribution.report = function report_glucosedistribution(datastorage, so
}); });
var timeTotal = 0; var timeTotal = 0;
for (var i = 1; i <= glucose_data.length - 2; i++) { for (i = 1; i <= glucose_data.length - 2; i++) {
var entry = glucose_data[i]; let entry = glucose_data[i];
var nextEntry = glucose_data[i + 1]; let nextEntry = glucose_data[i + 1];
var timeDelta = nextEntry.displayTime.getTime() - entry.displayTime.getTime(); let timeDelta = nextEntry.displayTime.getTime() - entry.displayTime.getTime();
if (timeDelta < maxGap) { if (timeDelta < maxGap) {
timeTotal += timeDelta; timeTotal += timeDelta;
} }
@@ -357,11 +356,10 @@ glucosedistribution.report = function report_glucosedistribution(datastorage, so
var glucoseTotal = 0; var glucoseTotal = 0;
var deltaTotal = 0; var deltaTotal = 0;
for (var i = 0; i <= glucose_data.length - 2; i++) { for (i = 0; i <= glucose_data.length - 2; i++) {
var entry = glucose_data[i]; const entry = glucose_data[i];
var nextEntry = glucose_data[i + 1]; const nextEntry = glucose_data[i + 1];
const timeDelta = nextEntry.displayTime.getTime() - entry.displayTime.getTime();
var timeDelta = nextEntry.displayTime.getTime() - entry.displayTime.getTime();
// Use maxGap constant // Use maxGap constant
if (timeDelta == 0 || timeDelta > maxGap) { // 6 * 60 * 1000) { if (timeDelta == 0 || timeDelta > maxGap) { // 6 * 60 * 1000) {
@@ -470,7 +468,7 @@ glucosedistribution.report = function report_glucosedistribution(datastorage, so
); );
}); });
function onClick() { function onClick () {
report_glucosedistribution(datastorage, sorteddaystoshow, options); report_glucosedistribution(datastorage, sorteddaystoshow, options);
} }
}; };
+72 -71
View File
@@ -8,34 +8,33 @@ var hourlystats = {
, pluginType: 'report' , pluginType: 'report'
}; };
function init() { function init () {
return hourlystats; return hourlystats;
} }
module.exports = init; module.exports = init;
hourlystats.html = function html(client) { hourlystats.html = function html (client) {
var translate = client.translate; var translate = client.translate;
var ret = var ret =
'<h2>' + translate('Hourly stats') + '</h2>' '<h2>' + translate('Hourly stats') + '</h2>' +
+ '<div id="hourlystats-overviewchart"></div>' '<div id="hourlystats-overviewchart"></div>' +
+ '<div id="hourlystats-report"></div>' '<div id="hourlystats-report"></div>';
;
return ret; return ret;
}; };
hourlystats.css = hourlystats.css =
'#hourlystats-overviewchart {' '#hourlystats-overviewchart {' +
+ ' width: 100%;' ' width: 100%;' +
+ ' min-width: 6.5in;' ' min-width: 6.5in;' +
+ ' height: 5in;' ' height: 5in;' +
+ '}' '}' +
+ '#hourlystats-placeholder td {' '#hourlystats-placeholder td {' +
+ ' text-align:center;' ' text-align:center;' +
+ '}'; '}';
hourlystats.report = function report_hourlystats(datastorage, sorteddaystoshow, options) { hourlystats.report = function report_hourlystats (datastorage, sorteddaystoshow, options) {
//console.log(window); //console.log(window);
var ss = require('simple-statistics'); var ss = require('simple-statistics');
var Nightscout = window.Nightscout; var Nightscout = window.Nightscout;
var client = Nightscout.client; var client = Nightscout.client;
@@ -52,15 +51,15 @@ hourlystats.report = function report_hourlystats(datastorage, sorteddaystoshow,
pivotedByHour[i] = []; pivotedByHour[i] = [];
} }
data = data.filter(function(o) { return !isNaN(o.sgv);}); data = data.filter(function(o) { return !isNaN(o.sgv); });
data.forEach(function(record) { data.forEach(function(record) {
var d = new Date(record.displayTime); var d = new Date(record.displayTime);
record.sgv = Number(record.sgv); record.sgv = Number(record.sgv);
pivotedByHour[d.getHours()].push(record); pivotedByHour[d.getHours()].push(record);
}); });
var table = $('<table width="100%" border="1">'); var table = $('<table width="100%" border="1">');
var thead = $('<tr/>'); var thead = $('<tr/>');
$('<th>' + translate('Time') + '</th>').appendTo(thead); $('<th>' + translate('Time') + '</th>').appendTo(thead);
@@ -74,50 +73,53 @@ hourlystats.report = function report_hourlystats(datastorage, sorteddaystoshow,
$('<th>' + translate('Standard Deviation') + '</th>').appendTo(thead); $('<th>' + translate('Standard Deviation') + '</th>').appendTo(thead);
thead.appendTo(table); thead.appendTo(table);
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23].forEach(function (hour) { [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23].forEach(function(hour) {
var tr = $('<tr>'); var tr = $('<tr>');
var display = new Date(0, 0, 1, hour, 0, 0, 0).toLocaleTimeString().replace(/([\d]+:[\d]{2})(:[\d]{2})(.*)/, '$1$3'); var display = new Date(0, 0, 1, hour, 0, 0, 0).toLocaleTimeString().replace(/([\d]+:[\d]{2})(:[\d]{2})(.*)/, '$1$3');
var avg = Math.floor(pivotedByHour[hour].map(function (r) { var avg = Math.floor(pivotedByHour[hour].map(function(r) {
return r.sgv; return r.sgv;
}).reduce(function (o, v) { }).reduce(function(o, v) {
return o + v; return o + v;
}, 0) / pivotedByHour[hour].length); }, 0) / pivotedByHour[hour].length);
var d = new Date(times.hours(hour).msecs); var d = new Date(times.hours(hour).msecs);
var dev = ss.standard_deviation(pivotedByHour[hour].map(function (r) { var dev = ss.standard_deviation(pivotedByHour[hour].map(function(r) {
return r.sgv; return r.sgv;
})); }));
stats.push([ stats.push([
new Date(d), new Date(d)
ss.quantile(pivotedByHour[hour].map(function (r) { , ss.quantile(pivotedByHour[hour].map(function(r) {
return r.sgv; return r.sgv;
}), 0.25), }), 0.25)
ss.quantile(pivotedByHour[hour].map(function (r) { , ss.quantile(pivotedByHour[hour].map(function(r) {
return r.sgv; return r.sgv;
}), 0.75), }), 0.75)
avg - dev, , avg - dev
avg + dev , avg + dev
]); ]);
var tmp; var tmp;
$('<td>' + display + '</td>').appendTo(tr); $('<td>' + display + '</td>').appendTo(tr);
$('<td>' + pivotedByHour[hour].length + ' (' + Math.floor(100 * pivotedByHour[hour].length / data.length) + '%)</td>').appendTo(tr); $('<td>' + pivotedByHour[hour].length + ' (' + Math.floor(100 * pivotedByHour[hour].length / data.length) + '%)</td>').appendTo(tr);
$('<td>' + avg + '</td>').appendTo(tr); $('<td>' + avg + '</td>').appendTo(tr);
$('<td>' + Math.min.apply(Math, pivotedByHour[hour].map(function (r) { $('<td>' + Math.min.apply(Math, pivotedByHour[hour].map(function(r) {
return r.sgv; return r.sgv;
})) + '</td>').appendTo(tr); })) + '</td>').appendTo(tr);
$('<td>' + ((tmp = ss.quantile(pivotedByHour[hour].map(function (r) { // eslint-disable-next-line no-cond-assign
return r.sgv; $('<td>' + ((tmp = ss.quantile(pivotedByHour[hour].map(function(r) {
}), 0.25)) ? tmp.toFixed(1) : 0 ) + '</td>').appendTo(tr); return r.sgv;
$('<td>' + ((tmp = ss.quantile(pivotedByHour[hour].map(function (r) { }), 0.25)) ? tmp.toFixed(1) : 0) + '</td>').appendTo(tr);
return r.sgv; // eslint-disable-next-line no-cond-assign
}), 0.5)) ? tmp.toFixed(1) : 0 ) + '</td>').appendTo(tr); $('<td>' + ((tmp = ss.quantile(pivotedByHour[hour].map(function(r) {
$('<td>' + ((tmp = ss.quantile(pivotedByHour[hour].map(function (r) { return r.sgv;
return r.sgv; }), 0.5)) ? tmp.toFixed(1) : 0) + '</td>').appendTo(tr);
}), 0.75)) ? tmp.toFixed(1) : 0 ) + '</td>').appendTo(tr); // eslint-disable-next-line no-cond-assign
$('<td>' + Math.max.apply(Math, pivotedByHour[hour].map(function (r) { $('<td>' + ((tmp = ss.quantile(pivotedByHour[hour].map(function(r) {
return r.sgv; return r.sgv;
})) + '</td>').appendTo(tr); }), 0.75)) ? tmp.toFixed(1) : 0) + '</td>').appendTo(tr);
$('<td>' + Math.max.apply(Math, pivotedByHour[hour].map(function(r) {
return r.sgv;
})) + '</td>').appendTo(tr);
$('<td>' + Math.floor(dev * 10) / 10 + '</td>').appendTo(tr); $('<td>' + Math.floor(dev * 10) / 10 + '</td>').appendTo(tr);
table.append(tr); table.append(tr);
}); });
@@ -126,28 +128,27 @@ hourlystats.report = function report_hourlystats(datastorage, sorteddaystoshow,
report.append(table); report.append(table);
$.plot( $.plot(
'#hourlystats-overviewchart', '#hourlystats-overviewchart'
[{ , [{
data: stats, data: stats
candle: true , candle: true
}], }], {
{
series: { series: {
candle: true, candle: true
lines: false //Somehow it draws lines if you dont disable this. Should investigate and fix this ;) , lines: false //Somehow it draws lines if you dont disable this. Should investigate and fix this ;)
}, }
xaxis: { , xaxis: {
mode: 'time', mode: 'time'
timeFormat: '%h:00', , timeFormat: '%h:00'
min: 0, , min: 0
max: times.hours(24).msecs - times.secs(1).msecs , max: times.hours(24).msecs - times.secs(1).msecs
}, }
yaxis: { , yaxis: {
min: 0, min: 0
max: options.units === 'mmol' ? 22 : 400, , max: options.units === 'mmol' ? 22 : 400
show: true , show: true
}, }
grid: { , grid: {
show: true show: true
} }
} }
@@ -161,7 +162,7 @@ hourlystats.report = function report_hourlystats(datastorage, sorteddaystoshow,
var days = 0; var days = 0;
table = $('<table width="100%" border="1">'); table = $('<table width="100%" border="1">');
thead = $('<tr/>'); thead = $('<tr/>');
["", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23].forEach(function (hour) { ["", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23].forEach(function(hour) {
$('<th>' + hour + '</th>').appendTo(thead); $('<th>' + hour + '</th>').appendTo(thead);
totalPositive[hour] = 0; totalPositive[hour] = 0;
totalNegative[hour] = 0; totalNegative[hour] = 0;
@@ -171,7 +172,7 @@ hourlystats.report = function report_hourlystats(datastorage, sorteddaystoshow,
}); });
thead.appendTo(table); thead.appendTo(table);
sorteddaystoshow.forEach(function (day) { sorteddaystoshow.forEach(function(day) {
if (datastorage[day].netBasalPositive) { if (datastorage[day].netBasalPositive) {
days++; days++;
var tr = $('<tr>'); var tr = $('<tr>');
File diff suppressed because it is too large Load Diff
+22 -24
View File
@@ -6,33 +6,32 @@ var profiles = {
, pluginType: 'report' , pluginType: 'report'
}; };
function init() { function init () {
return profiles; return profiles;
} }
module.exports = init; module.exports = init;
profiles.html = function html(client) { profiles.html = function html (client) {
var translate = client.translate; var translate = client.translate;
var ret = var ret =
'<h2>' + translate('Profiles') + '</h2>' '<h2>' + translate('Profiles') + '</h2>' +
+ '<br>' + translate('Database records') + '&nbsp' '<br>' + translate('Database records') + '&nbsp' +
+ '<br><select id="profiles-databaserecords"></select>' '<br><select id="profiles-databaserecords"></select>' +
+ '<br><span id="profiles-default"></span>' '<br><span id="profiles-default"></span>' +
+ '<div id="profiles-chart">' '<div id="profiles-chart">' +
+ '</div>' '</div>';
;
return ret; return ret;
}; };
profiles.css = profiles.css =
'#profiles-chart {' '#profiles-chart {' +
+ ' width: 100%;' ' width: 100%;' +
+ ' height: 100%;' ' height: 100%;' +
+ '}' '}';
;
profiles.report = function report_profiles(datastorage, sorteddaystoshow, options) { // eslint-disable-next-line no-unused-vars
profiles.report = function report_profiles (datastorage, sorteddaystoshow, options) {
var Nightscout = window.Nightscout; var Nightscout = window.Nightscout;
var client = Nightscout.client; var client = Nightscout.client;
var translate = client.translate; var translate = client.translate;
@@ -41,10 +40,10 @@ profiles.report = function report_profiles(datastorage, sorteddaystoshow, option
var databaseRecords = $('#profiles-databaserecords'); var databaseRecords = $('#profiles-databaserecords');
databaseRecords.empty(); databaseRecords.empty();
for (var r = 0; r < profileRecords.length; r++ ) { for (var r = 0; r < profileRecords.length; r++) {
databaseRecords.append('<option value="' + r + '">' + translate('Valid from:') + ' ' + new Date(profileRecords[r].startDate).toLocaleString() + '</option>'); databaseRecords.append('<option value="' + r + '">' + translate('Valid from:') + ' ' + new Date(profileRecords[r].startDate).toLocaleString() + '</option>');
} }
databaseRecords.unbind().bind('change',recordChange); databaseRecords.unbind().bind('change', recordChange);
recordChange(); recordChange();
@@ -58,11 +57,10 @@ profiles.report = function report_profiles(datastorage, sorteddaystoshow, option
var tr = $('<tr>'); var tr = $('<tr>');
$('#profiles-default').val(currentrecord.defaultProfile); $('#profiles-default').val(currentrecord.defaultProfile);
for (var key in currentrecord.store) {
if (currentrecord.store.hasOwnProperty(key)) { Object.keys(currentrecord.store).forEach(key => {
tr.append(displayRecord(currentrecord.store[key], key)) tr.append(displayRecord(currentrecord.store[key], key));
} });
}
table.append(tr); table.append(tr);
@@ -73,7 +71,7 @@ profiles.report = function report_profiles(datastorage, sorteddaystoshow, option
} }
} }
function displayRecord(record, name) { function displayRecord (record, name) {
var td = $('<td>'); var td = $('<td>');
var table = $('<table>'); var table = $('<table>');
@@ -91,7 +89,7 @@ profiles.report = function report_profiles(datastorage, sorteddaystoshow, option
return td; return td;
} }
function displayRanges(array, array2) { function displayRanges (array, array2) {
var text = ''; var text = '';
for (var i = 0; i < array.length; i++) { for (var i = 0; i < array.length; i++) {
text += array[i].time + '&nbsp:&nbsp' + array[i].value + (array2 ? ' - ' + array2[i].value : '') + '<br>'; text += array[i].time + '&nbsp:&nbsp' + array[i].value + (array2 ? ' - ' + array2[i].value : '') + '<br>';
+83 -89
View File
@@ -8,66 +8,60 @@ var success = {
, pluginType: 'report' , pluginType: 'report'
}; };
function init() { function init () {
return success; return success;
} }
module.exports = init; module.exports = init;
success.html = function html(client) { success.html = function html (client) {
var translate = client.translate; var translate = client.translate;
var ret = var ret =
'<h2>' + translate('Weekly Success') + '</h2>' '<h2>' + translate('Weekly Success') + '</h2>' +
+ '<div id="success-grid"></div>' '<div id="success-grid"></div>';
;
return ret; return ret;
}; };
success.css = success.css =
'#success-placeholder td {'+ `#success-placeholder td {
' border: 1px #ccc solid;'+ border: 1px #ccc solid;
' margin: 0;'+ margin: 0;
' padding: 1px;'+ padding: 1px;
' text-align:center;'+ text-align:center;
'}'+ }
'#success-placeholder .bad {'+ #success-placeholder .bad {
' background-color: #fcc;'+ background-color: #fcc;
'}'+ }
#success-placeholder .good {
background-color: #cfc;
}
#success-placeholder th:first-child {
width: 30%;
}
#success-placeholder th {
width: 10%;
}
#success-placeholder table {
width: 100%;
}`;
'#success-placeholder .good {'+ success.report = function report_success (datastorage, sorteddaystoshow, options) {
' background-color: #cfc;'+
'}'+
'#success-placeholder th:first-child {'+
' width: 30%;'+
'}'+
'#success-placeholder th {'+
' width: 10%;'+
'}'+
'#success-placeholder table {'+
' width: 100%;'+
'}'
;
success.report = function report_success(datastorage, sorteddaystoshow, options) {
var Nightscout = window.Nightscout; var Nightscout = window.Nightscout;
var client = Nightscout.client; var client = Nightscout.client;
var translate = client.translate; var translate = client.translate;
var ss = require('simple-statistics'); var ss = require('simple-statistics');
var low = options.targetLow, var low = options.targetLow
high = options.targetHigh; , high = options.targetHigh;
var data = datastorage.allstatsrecords; var data = datastorage.allstatsrecords;
var now = Date.now(); var now = Date.now();
var period = 7 * times.hours(24).msecs; var period = 7 * times.hours(24).msecs;
var firstDataPoint = data.reduce(function(min, record) { var firstDataPoint = data.reduce(function(min, record) {
return Math.min(min, record.displayTime); return Math.min(min, record.displayTime);
}, Number.MAX_VALUE); }, Number.MAX_VALUE);
if (firstDataPoint < 1390000000000) { if (firstDataPoint < 1390000000000) {
firstDataPoint = 1390000000000; firstDataPoint = 1390000000000;
} }
@@ -79,39 +73,39 @@ success.report = function report_success(datastorage, sorteddaystoshow, options)
if (quarters === 0) { if (quarters === 0) {
// insufficent data // insufficent data
grid.append('<p>'+translate('There is not sufficient data to run this report. Select more days.')+'</p>'); grid.append('<p>' + translate('There is not sufficient data to run this report. Select more days.') + '</p>');
return; return;
} }
var dim = function(n) { var dim = function(n) {
var a = []; var a = [];
for (var i = 0; i < n; i++) { for (var i = 0; i < n; i++) {
a[i]=0; a[i] = 0;
} }
return a; return a;
}; };
var sum = function(a) { var sum = function(a) {
return a.reduce(function(sum,v) { return a.reduce(function(sum, v) {
return sum+v; return sum + v;
}, 0); }, 0);
}; };
var averages = { var averages = {
percentLow: 0, percentLow: 0
percentInRange: 0, , percentInRange: 0
percentHigh: 0, , percentHigh: 0
standardDeviation: 0, , standardDeviation: 0
lowerQuartile: 0, , lowerQuartile: 0
upperQuartile: 0, , upperQuartile: 0
average: 0 , average: 0
}; };
quarters = dim(quarters).map(function(blank, n) { quarters = dim(quarters).map(function(blank, n) {
var starting = new Date(now - (n+1) * period), var starting = new Date(now - (n + 1) * period)
ending = new Date(now - n * period); , ending = new Date(now - n * period);
return { return {
starting: starting, starting: starting
ending: ending, , ending: ending
records: data.filter(function(record) { , records: data.filter(function(record) {
return record.displayTime > starting && record.displayTime <= ending; return record.displayTime > starting && record.displayTime <= ending;
}) })
}; };
}).filter(function(quarter) { }).filter(function(quarter) {
@@ -121,8 +115,8 @@ success.report = function report_success(datastorage, sorteddaystoshow, options)
return record.sgv; return record.sgv;
}); });
quarter.standardDeviation = ss.standard_deviation(bgValues); quarter.standardDeviation = ss.standard_deviation(bgValues);
quarter.average = bgValues.length > 0? (sum(bgValues) / bgValues.length): 'N/A'; quarter.average = bgValues.length > 0 ? (sum(bgValues) / bgValues.length) : 'N/A';
quarter.lowerQuartile = ss.quantile(bgValues, 0.25); quarter.lowerQuartile = ss.quantile(bgValues, 0.25);
quarter.upperQuartile = ss.quantile(bgValues, 0.75); quarter.upperQuartile = ss.quantile(bgValues, 0.75);
quarter.numberLow = bgValues.filter(function(bg) { quarter.numberLow = bgValues.filter(function(bg) {
return bg < low; return bg < low;
@@ -148,9 +142,9 @@ success.report = function report_success(datastorage, sorteddaystoshow, options)
var lowComparison = function(quarter, averages, field, invert) { var lowComparison = function(quarter, averages, field, invert) {
if (quarter[field] < averages[field] * 0.8) { if (quarter[field] < averages[field] * 0.8) {
return (invert? 'bad': 'good'); return (invert ? 'bad' : 'good');
} else if (quarter[field] > averages[field] * 1.2) { } else if (quarter[field] > averages[field] * 1.2) {
return (invert? 'good': 'bad'); return (invert ? 'good' : 'bad');
} else { } else {
return ''; return '';
} }
@@ -172,44 +166,44 @@ success.report = function report_success(datastorage, sorteddaystoshow, options)
} }
}; };
table.append('<thead><tr><th>'+translate('Period')+'</th><th>'+translate('Low')+'</th><th>'+translate('In Range')+'</th><th>'+translate('High')+'</th><th>'+translate('Standard Deviation')+'</th><th>'+translate('Low Quartile')+'</th><th>'+translate('Average')+'</th><th>'+translate('Upper Quartile')+'</th></tr></thead>'); table.append('<thead><tr><th>' + translate('Period') + '</th><th>' + translate('Low') + '</th><th>' + translate('In Range') + '</th><th>' + translate('High') + '</th><th>' + translate('Standard Deviation') + '</th><th>' + translate('Low Quartile') + '</th><th>' + translate('Average') + '</th><th>' + translate('Upper Quartile') + '</th></tr></thead>');
table.append('<tbody>' + quarters.filter(function(quarter) { table.append('<tbody>' + quarters.filter(function(quarter) {
return quarter.records.length > 0; return quarter.records.length > 0;
}).map(function(quarter) { }).map(function(quarter) {
var INVERT = true; var INVERT = true;
return '<tr>' + [ return '<tr>' + [
quarter.starting.toLocaleDateString() + ' - ' + quarter.ending.toLocaleDateString(), quarter.starting.toLocaleDateString() + ' - ' + quarter.ending.toLocaleDateString()
{ , {
klass: lowComparison(quarter, averages, 'percentLow'), klass: lowComparison(quarter, averages, 'percentLow')
text: Math.round(quarter.percentLow) + '%' , text: Math.round(quarter.percentLow) + '%'
}, }
{ , {
klass: lowComparison(quarter, averages, 'percentInRange', INVERT), klass: lowComparison(quarter, averages, 'percentInRange', INVERT)
text: Math.round(quarter.percentInRange) + '%' , text: Math.round(quarter.percentInRange) + '%'
}, }
{ , {
klass: lowComparison(quarter, averages, 'percentHigh'), klass: lowComparison(quarter, averages, 'percentHigh')
text: Math.round(quarter.percentHigh) + '%' , text: Math.round(quarter.percentHigh) + '%'
}, }
{ , {
klass: lowComparison(quarter, averages, 'standardDeviation'), klass: lowComparison(quarter, averages, 'standardDeviation')
text: (quarter.standardDeviation > 10? Math.round(quarter.standardDeviation): quarter.standardDeviation.toFixed(1)) , text: (quarter.standardDeviation > 10 ? Math.round(quarter.standardDeviation) : quarter.standardDeviation.toFixed(1))
}, }
{ , {
klass: lowQuartileEvaluation(quarter, averages), klass: lowQuartileEvaluation(quarter, averages)
text: quarter.lowerQuartile , text: quarter.lowerQuartile
}, }
{ , {
klass: lowComparison(quarter, averages, 'average'), klass: lowComparison(quarter, averages, 'average')
text: quarter.average.toFixed(1) , text: quarter.average.toFixed(1)
}, }
{ , {
klass: upperQuartileEvaluation(quarter, averages), klass: upperQuartileEvaluation(quarter, averages)
text: quarter.upperQuartile , text: quarter.upperQuartile
} }
].map(function(v) { ].map(function(v) {
if (typeof v === 'object') { if (typeof v === 'object') {
return '<td class=\"' + v.klass + '\">' + v.text + '</td>'; return '<td class="' + v.klass + '">' + v.text + '</td>';
} else { } else {
return '<td>' + v + '</td>'; return '<td>' + v + '</td>';
} }
+24 -29
View File
@@ -4,21 +4,21 @@ var _ = require('lodash');
var units = require('./units')(); var units = require('./units')();
var times = require('./times'); var times = require('./times');
function init ( ) { function init () {
var sbx = {}; var sbx = {};
function reset () { function reset () {
sbx.properties = { }; sbx.properties = {};
} }
function extend ( ) { function extend () {
sbx.unitsLabel = unitsLabel(); sbx.unitsLabel = unitsLabel();
sbx.data = sbx.data || {}; sbx.data = sbx.data || {};
//default to prevent adding checks everywhere //default to prevent adding checks everywhere
sbx.extendedSettings = {empty: true}; sbx.extendedSettings = { empty: true };
} }
function withExtendedSettings(plugin, allExtendedSettings, sbx) { function withExtendedSettings (plugin, allExtendedSettings, sbx) {
var sbx2 = _.extend({}, sbx); var sbx2 = _.extend({}, sbx);
sbx2.extendedSettings = allExtendedSettings && allExtendedSettings[plugin.name] || {}; sbx2.extendedSettings = allExtendedSettings && allExtendedSettings[plugin.name] || {};
return sbx2; return sbx2;
@@ -48,7 +48,7 @@ function init ( ) {
sbx.settings = env.settings; sbx.settings = env.settings;
sbx.data = ctx.ddata.clone(); sbx.data = ctx.ddata.clone();
sbx.notifications = safeNotifications(ctx); sbx.notifications = safeNotifications(ctx);
sbx.levels = ctx.levels; sbx.levels = ctx.levels;
sbx.language = ctx.language; sbx.language = ctx.language;
sbx.translate = ctx.language.translate; sbx.translate = ctx.language.translate;
@@ -60,7 +60,7 @@ function init ( ) {
sbx.data.profile = profile; sbx.data.profile = profile;
delete sbx.data.profiles; delete sbx.data.profiles;
sbx.properties = { }; sbx.properties = {};
sbx.withExtendedSettings = function getPluginExtendedSettingsOnly (plugin) { sbx.withExtendedSettings = function getPluginExtendedSettingsOnly (plugin) {
return withExtendedSettings(plugin, env.extendedSettings, sbx); return withExtendedSettings(plugin, env.extendedSettings, sbx);
@@ -89,7 +89,7 @@ function init ( ) {
sbx.data = data; sbx.data = data;
sbx.pluginBase = ctx.pluginBase; sbx.pluginBase = ctx.pluginBase;
sbx.notifications = safeNotifications(ctx); sbx.notifications = safeNotifications(ctx);
sbx.levels = ctx.levels; sbx.levels = ctx.levels;
sbx.language = ctx.language; sbx.language = ctx.language;
sbx.translate = ctx.language.translate; sbx.translate = ctx.language.translate;
@@ -99,7 +99,7 @@ function init ( ) {
sbx.pluginBase.forecastPoints = []; sbx.pluginBase.forecastPoints = [];
} }
sbx.extendedSettings = {empty: true}; sbx.extendedSettings = { empty: true };
sbx.withExtendedSettings = function getPluginExtendedSettingsOnly (plugin) { sbx.withExtendedSettings = function getPluginExtendedSettingsOnly (plugin) {
return withExtendedSettings(plugin, sbx.settings.extendedSettings, sbx); return withExtendedSettings(plugin, sbx.settings.extendedSettings, sbx);
}; };
@@ -116,7 +116,7 @@ function init ( ) {
* @param setter * @param setter
*/ */
sbx.offerProperty = function offerProperty (name, setter) { sbx.offerProperty = function offerProperty (name, setter) {
if (!sbx.properties.hasOwnProperty(name)) { if (!Object.keys(sbx.properties).includes(name)) {
var value = setter(); var value = setter();
if (value) { if (value) {
sbx.properties[name] = value; sbx.properties[name] = value;
@@ -124,7 +124,7 @@ function init ( ) {
} }
}; };
sbx.isCurrent = function isCurrent(entry) { sbx.isCurrent = function isCurrent (entry) {
return entry && sbx.time - entry.mills <= times.mins(15).msecs; return entry && sbx.time - entry.mills <= times.mins(15).msecs;
}; };
@@ -137,7 +137,7 @@ function init ( ) {
sbx.lastNEntries = function lastNEntries (entries, n) { sbx.lastNEntries = function lastNEntries (entries, n) {
var lastN = []; var lastN = [];
_.takeRightWhile(entries, function (entry) { _.takeRightWhile(entries, function(entry) {
if (sbx.entryMills(entry) <= sbx.time) { if (sbx.entryMills(entry) <= sbx.time) {
lastN.push(entry); lastN.push(entry);
} }
@@ -158,32 +158,32 @@ function init ( ) {
return sbx.prevEntry(sbx.data.sgvs); return sbx.prevEntry(sbx.data.sgvs);
}; };
sbx.lastSGVEntry = function lastSGVEntry ( ) { sbx.lastSGVEntry = function lastSGVEntry () {
return sbx.lastEntry(sbx.data.sgvs); return sbx.lastEntry(sbx.data.sgvs);
}; };
sbx.lastSGVMgdl = function lastSGVMgdl ( ) { sbx.lastSGVMgdl = function lastSGVMgdl () {
var last = sbx.lastSGVEntry(); var last = sbx.lastSGVEntry();
return last && last.mgdl; return last && last.mgdl;
}; };
sbx.lastSGVMills = function lastSGVMills ( ) { sbx.lastSGVMills = function lastSGVMills () {
return sbx.entryMills(sbx.lastSGVEntry()); return sbx.entryMills(sbx.lastSGVEntry());
}; };
sbx.entryMills = function entryMills(entry) { sbx.entryMills = function entryMills (entry) {
return entry && entry.mills; return entry && entry.mills;
}; };
sbx.lastScaledSGV = function lastScaledSVG ( ) { sbx.lastScaledSGV = function lastScaledSVG () {
return sbx.scaleEntry(sbx.lastSGVEntry()); return sbx.scaleEntry(sbx.lastSGVEntry());
}; };
sbx.lastDisplaySVG = function lastDisplaySVG ( ) { sbx.lastDisplaySVG = function lastDisplaySVG () {
return sbx.displayBg(sbx.lastSGVEntry()); return sbx.displayBg(sbx.lastSGVEntry());
}; };
sbx.buildBGNowLine = function buildBGNowLine ( ) { sbx.buildBGNowLine = function buildBGNowLine () {
var line = 'BG Now: ' + sbx.lastDisplaySVG(); var line = 'BG Now: ' + sbx.lastDisplaySVG();
var delta = sbx.properties.delta && sbx.properties.delta.display; var delta = sbx.properties.delta && sbx.properties.delta.display;
@@ -216,7 +216,7 @@ function init ( ) {
return lines; return lines;
}; };
sbx.prepareDefaultLines = function prepareDefaultLines() { sbx.prepareDefaultLines = function prepareDefaultLines () {
var lines = [sbx.buildBGNowLine()]; var lines = [sbx.buildBGNowLine()];
sbx.appendPropertyLine('rawbg', lines); sbx.appendPropertyLine('rawbg', lines);
sbx.appendPropertyLine('ar2', lines); sbx.appendPropertyLine('ar2', lines);
@@ -227,7 +227,7 @@ function init ( ) {
return lines; return lines;
}; };
sbx.buildDefaultMessage = function buildDefaultMessage() { sbx.buildDefaultMessage = function buildDefaultMessage () {
return sbx.prepareDefaultLines().join('\n'); return sbx.prepareDefaultLines().join('\n');
}; };
@@ -272,14 +272,10 @@ function init ( ) {
if (sbx.properties.roundingStyle === 'medtronic') { if (sbx.properties.roundingStyle === 'medtronic') {
var denominator = 0.1; var denominator = 0.1;
var digits = 1; var digits = 1;
if (insulin > 0.5 && iob < 1) { if (insulin <= 0.5) {
denominator = 0.05; denominator = 0.05;
digits = 2; digits = 2;
} }
if (insulin <= 0.5) {
denominator = 0.025;
digits = 3;
}
return (Math.floor(insulin / denominator) * denominator).toFixed(digits); return (Math.floor(insulin / denominator) * denominator).toFixed(digits);
} }
@@ -287,7 +283,7 @@ function init ( ) {
}; };
function unitsLabel ( ) { function unitsLabel () {
return sbx.settings.units === 'mmol' ? 'mmol/L' : 'mg/dl'; return sbx.settings.units === 'mmol' ? 'mmol/L' : 'mg/dl';
} }
@@ -299,4 +295,3 @@ function init ( ) {
} }
module.exports = init; module.exports = init;
+1
View File
@@ -28,6 +28,7 @@ CACHE MANIFEST
/css/main.css?v=<%= locals.cachebuster %> /css/main.css?v=<%= locals.cachebuster %>
/bundle/js/bundle.app.js?v=<%= locals.cachebuster %> /bundle/js/bundle.app.js?v=<%= locals.cachebuster %>
/bundle/js/bundle.clock.js?v=<%= locals.cachebuster %> /bundle/js/bundle.clock.js?v=<%= locals.cachebuster %>
/bundle/js/bundle.report.js?v=<%= locals.cachebuster %>
/socket.io/socket.io.js?v=<%= locals.cachebuster %> /socket.io/socket.io.js?v=<%= locals.cachebuster %>
/js/client.js?v=<%= locals.cachebuster %> /js/client.js?v=<%= locals.cachebuster %>
/images/logo2.png /images/logo2.png
+1 -1
View File
@@ -115,7 +115,7 @@ if (process.env.NODE_ENV == 'development') {
rules.unshift({ rules.unshift({
enforce: "pre", enforce: "pre",
test: /\.js$/, test: /\.js$/,
exclude: /node_modules/, exclude: [/node_modules/, /bundle/],
loader: "eslint-loader", loader: "eslint-loader",
options: { options: {
emitWarning: true, emitWarning: true,