UNPKG

nightscout

Version:

Nightscout acts as a web-based CGM (Continuous Glucose Monitor) to allow multiple caregivers to remotely view a patients glucose data in realtime.

728 lines (638 loc) 29.6 kB
'use strict'; var init = function init () { //for the tests window isn't the global object var $ = window.$; var _ = window._; var moment = window.moment; var Nightscout = window.Nightscout; var client = Nightscout.client; var c_profile = null; //some commonly used selectors var peStatus = $('.pe_status'); var timezoneInput = $('#pe_timezone'); var databaseRecords = $('#pe_databaserecords'); var timeInput = $('#pe_time'); var dateInput = $('#pe_date'); client.init(function loaded () { if (c_profile !== null) { return; // already loaded so don't load again } var translate = client.translate; var defaultprofile = { //General values 'dia':3, 'carbratio': [ { 'time': '00:00', 'value': 30 }] , 'carbs_hr': 20 , 'delay': 20 , 'sens': [ { 'time': '00:00', 'value': 100 }] , 'timezone': 'UTC' //perGIvalues style values , 'perGIvalues': false , 'carbs_hr_high': 30 , 'carbs_hr_medium': 30 , 'carbs_hr_low': 30 , 'delay_high': 15 , 'delay_medium': 20 , 'delay_low': 20 , 'basal':[ { 'time': '00:00', 'value': 0.1 }] , 'target_low':[ { 'time': '00:00', 'value': 0 }] , 'target_high':[ { 'time': '00:00', 'value': 0 }] ,startDate: new Date(0).toISOString() }; // , 'startDate': new Date() // defaultprofile.startDate.setSeconds(0); // defaultprofile.startDate.setMilliseconds(0); var icon_add = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABa0lEQVQ4T6WTzysEYRjHP+/Mrv2hHOTuqJRNOfgPSORHokg4OClHcnVzVygHF6WIcuHMnyCHVRyI3ZYxa23vzOzs7LzamaI0e5i89fTWt/f5vPV5n1cQsXLbHepvfLv5JaLORoZNwMbyFo5vYfsWB0c7xAasLa5T/vCg45Oj48P4gJWFVYxCA63L5PzkND5gfm4Jo+Chd5W5OrtsDYgS1pQ1OTuNUfTQO8tcX9xE+QugYnS/X81MzGP7MpTWkEFVZY1KxcVPV3h27zAtA+oCagIcDfWUCgEje31qfHwK06gHjaF5iXQcHCV5lHmqqgQCNEAI0IsavCVDwNBurxoeGwmaAkDDwvYsqtIh//6AJUoklP97s62BbJYeAqIcpJNZsoM+r2aVbKKOekiBL8An3BuAEiGg1SSKAYnttpFxPdR9Jv4zipxFTUuQKqsfYbFGWfTYuO06yRfxIyweoLuG+iMsFuBfvzFy7FqE33vs2BFqlfN5AAAAAElFTkSuQmCC'; var icon_remove = '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 icon_clone = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACSklEQVQ4T5VTYU9SYRR+zn0vXhDEFyRBXcpmbZnZsOXsI2xpVnNcv/ilufET8h/oL8h/gN/aWhs2yjKt26rPSvUh5yQodQlqgKQCd5fbLg2jxlycT+/OOc85z/OcvYSa8MoRLqimUEuzOSgwBl0nFFUtW1K1J/Ho6Hxtr/H2yQqnarJ3fFHucNnC57tdXIUJhydl6CAwIhwfFXCwf5hUC6XpjYXAQgUcUngRzkxlgHc0Kl+57I443S7s5VQwxqCVCYVSGfkTFSQQmsQmHGVzKJ78nJMs2izBohRg8ZFB293iSPQPdPOiqiOdyiGdysdKmp4t64LXxlu9otUKTVdhkSSUjgooHOez7R1uvr2bA10cfx66cb0n3GS14tPHrWz6R34i+fT2m6q0rruv7tvs9gdOtxNk0mA2SRB0gqVZwGb8AOSbXIkMDV+Qt7cy2IinJ+LRWxWNf5ur+Kx2vub0OABRg2QSIYqEr/EMaHjqrdJ/tce/upqIxR76B/8FVzySFc7MzWvtnW6vyjSAAFFgyBkSrt17n7jU1+ldjcVn1x+PzNTZzkWLTXF5zvmYmaEslCEIxnUE7H07AA1NvVPaO9r8X5Kpic+Pfp+oNvpCH/R6rKo5GphUIq1Oh7y++T2wv/LHvLNAtTXqHX8Zkqyt4XQ6M73/emzuf4GnDLg/wu0tbYliqTifWhqZbniAAfCMLs/oRMHU0s26VzjTA6PI/QqXJC1BxAZ3XwSSjbA4/UyesWU/Y2Jw51mgIRmnA4ytXXcU385iINYIg1+OJdcoyf/hkgAAAABJRU5ErkJggg=='; //var icon_apply = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACh0lEQVQ4T5XSXUhTYRgH8P85O+fMOZ3H2WButc7MD3AQWyaYIRZEqANpt9HHCiwvIhWim8gPiqArJailVmdhJGEI3USk4rAQc1MnTdMitZhtfm86ncvcYhMls2i9l+/Hj//zvA+B/1kmcKSArGIohmNIZoIMkRVE1O95sOQaOXCCK+KUYgWcy99gne2zRA1Q9VR1/u7DVcVcIdyrLshFCtQPNyIqgG6gtWImduB69lVM+r9EQqvEajQM8dEBokcxnSWas0fSElMw5B1EdlIuLM43GJxz1P0zgfhhjDFDmsFf1pVixOeASqTGgt+Llk+tEwCt2wDuQgsSWghgxwXYNxvL8iwbIoLjN3KvsQQVRCAUgIyWg3c0wRdYPmoz2C0E7qE2NUFdnpa4D73TfZgLLNThIirCCGuW8MWpRcYC9TF8DYwhPU6DtvEO2Kb666zF9sidMBC6lVsJES1EiCDwZPQZHHMfzBJB7ONdcbLOm3mVcP9wQi5UwO2bQdP7pxOi9aDOYrB7NgATQnfyb2Mq4AJN0eDiU9A82oL+6UFcyS7DXqkSfixDKpDB1P8Ai98Xdd1661aZBO6jNif5YPm5zFOYXZsCQzHYE8dhZP4jspK1mAm6oYpR49Xn1+iZtNW81fdU/zp8kSaSDSSfpzxkPK85jfn1WawSK9BI9mMJXkiFSXAvzYAfMNu79O90v0/u1jdKzPER5IzmJLyhefiJFchFyWApKUzWRnj8Hp1F370VfRPaNgfKZgWfIlEZL2WVQsAASUIZ2sY60Ou01bQXdm2L/kcgvJn5PJ3nElTG0qwSuHwutAy32tsLunZE/ysQPsh5caCaoYRlQgHjoUnC8PK4ZUf0TeAnGJ/iJEGClrwAAAAASUVORK5CYII='; var mongorecords = []; var currentrecord = 0; var currentprofile = null; var dirty = false; // Fetch data from mongo peStatus.hide().text(translate('Loading profile records ...')).fadeIn('slow'); $.ajax('/api/v1/profile.json?count=20', { headers: client.headers() , success: function (records) { if (!records.length) { records.push(defaultprofile); } client.profilefunctions.loadData(records); // do a conversion if needed mongorecords = _.cloneDeep(client.profilefunctions.data); // create new profile to be edited from last record if (mongorecords.length) { _.each(mongorecords, function eachMongoProfile (mongoprofile) { _.each(mongoprofile.store, function eachStoredProfile (p) { // allign with default profile for (var key in defaultprofile) { if (Object.prototype.hasOwnProperty.call(defaultprofile,key) && !Object.prototype.hasOwnProperty.call(p,key)) { p[key] = defaultprofile[key]; } } for (key in p) { if (Object.prototype.hasOwnProperty.call(p,key) && !Object.prototype.hasOwnProperty.call(defaultprofile,key)) { delete p[key]; } } convertToRanges(p); }); }); peStatus.hide().text(translate('Values loaded.')).fadeIn('slow'); } else { mongorecords.push({ defaultProfile: 'Default' , store : { 'Default': _.cloneDeep(defaultprofile) } , startDate: new Date().toISOString() }); peStatus.hide().text(translate('Default values used.')).fadeIn('slow'); } } , error: function () { mongorecords.push({ defaultProfile: 'Default' , store : { 'Default': _.cloneDeep(defaultprofile) } , startDate: new Date().toISOString() }); peStatus.hide().text(translate('Error. Default values used.')).fadeIn('slow'); } }).done(initeditor); // convert simple values to ranges if needed function convertToRanges(profile) { if (typeof profile.carbratio !== 'object') { profile.carbratio = [{ 'time': '00:00', 'value': profile.carbratio }]; } if (typeof profile.sens !== 'object') { profile.sens = [{ 'time': '00:00', 'value': profile.sens }]; } if (typeof profile.target_low !== 'object') { profile.target_low = [{ 'time': '00:00', 'value': profile.target_low }]; } if (typeof profile.target_high !== 'object') { profile.target_high = [{ 'time': '00:00', 'value': profile.target_high }]; } if (typeof profile.basal !== 'object') { profile.basal = [{ 'time': '00:00', 'value': profile.basal }]; } if (profile.target_high.length !== profile.target_low.length) { window.alert(translate('Time ranges of target_low and target_high don\'t match. Values are restored to defaults.')); profile.target_low = _.cloneDeep(defaultprofile.target_low); profile.target_high = _.cloneDeep(defaultprofile.target_high); } } function initeditor() { $('#pe_history').toggle(client.settings.extendedSettings.profile && client.settings.extendedSettings.profile.history); $('#pe_multiple').toggle(client.settings.extendedSettings.profile && client.settings.extendedSettings.profile.multiple); // Load timezones timezoneInput.empty(); moment.tz.names().forEach(function addTz(tz) { timezoneInput.append('<option value="' + tz + '">' + tz + '</option>'); }); $('#pe_form').find('button').click(profileSubmit); $('#pe_profiles').unbind().bind('change', profileChange); $('#pe_profile_add').unbind().bind('click', profileAdd); $('#pe_profile_remove').unbind().bind('click', profileRemove); $('#pe_profile_clone').unbind().bind('click', profileClone); $('#pe_databaserecords').unbind().bind('change',recordChange); $('#pe_records_add').unbind().bind('click', recordAdd); $('#pe_records_remove').unbind().bind('click', recordRemove); $('#pe_records_clone').unbind().bind('click', recordClone); // Add handler for style switching $('#pe_perGIvalues').unbind().on('change', switchStyle); // display status $('#pe_units').text(client.settings.units); $('#pe_timeformat').text(client.settings.timeFormat+'h'); $('#pe_title').text(client.settings.customTitle); currentprofile = mongorecords[currentrecord].defaultProfile; // prepare basal profiles initRecord(); // hide unused style of ratios switchStyle(); console.log('Done initeditor()'); } function initRecord() { databaseRecords.empty(); for (var r = 0; r < mongorecords.length; r++ ) { databaseRecords.append('<option value="' + r + '">' + translate('Valid from:') + ' ' + new Date(mongorecords[r].startDate).toLocaleString() + '</option>'); } databaseRecords.val(currentrecord); timeInput.val(moment(mongorecords[currentrecord].startDate).format('HH:mm')); dateInput.val(moment(mongorecords[currentrecord].startDate).format('YYYY-MM-DD')); initProfile(); } function timeDiffMinutes(time1, time2) { var minutes1 = toMinutesFromMidnight(time1); var minutes2 = toMinutesFromMidnight(time2); if (minutes2 <= minutes1) { minutes2 += 24*60; } return minutes2-minutes1; } function refreshTotalBasal() { GUIToObject(); var total = 0; for (var i=0, len=c_profile['basal'].length; i<len; i++) { var time1 = c_profile['basal'][i].time; var time2 = c_profile['basal'][(i+1)%len].time; var value = c_profile['basal'][i].value; total += timeDiffMinutes(time1,time2) * value / 60 } $('#pe_basalTotal_placeholder').html(Math.round(total*1000)/1000); } function initProfile() { var record = mongorecords[currentrecord]; // fill profilenames $('#pe_profiles').empty(); for (var key in record.store) { if (Object.prototype.hasOwnProperty.call(record.store,key)) { $('#pe_profiles').append('<option value="' + key + '">' + key + '</option>'); } } $('#pe_profiles').val(currentprofile); $('#pe_profile_name').val(currentprofile); c_profile = mongorecords[currentrecord].store[currentprofile]; mongorecords[currentrecord].defaultProfile = currentprofile; // Set values from profile to html fillTimeRanges(); refreshTotalBasal(); } // Handling of record list box change function recordChange (event) { if (dirty && window.confirm(translate('Save current record before switching to new?'))) { profileSubmit(); } currentrecord = databaseRecords.val(); currentprofile = mongorecords[currentrecord].defaultProfile; initRecord(); dirty = false; maybePreventDefault(event); } function recordAdd (event) { if (dirty && window.confirm(translate('Save current record before switching to new?'))) { profileSubmit(); } mongorecords.push({ startDate: new Date().toISOString() , defaultProfile: 'Default' , store: { 'Default' : _.cloneDeep(defaultprofile) } }); currentrecord = mongorecords.length - 1; currentprofile = 'Default'; initRecord(); dirty = true; maybePreventDefault(event); } function recordRemove (event) { if (mongorecords.length > 1 && window.confirm(translate('Delete record')+'?')) { if (mongorecords[currentrecord]._id) { $.ajax({ method: 'DELETE' , url: '/api/v1/profile/'+mongorecords[currentrecord]._id , headers: client.headers() }).done(function postSuccess () { console.info('profile deleted'); peStatus.hide().text(status).fadeIn('slow'); mongorecords.splice(currentrecord,1); currentrecord = 0; currentprofile = mongorecords[currentrecord].defaultProfile; initRecord(); dirty = false; }).fail(function(xhr, status, errorThrown) { console.error('Profile not removed', status, errorThrown); peStatus.hide().text(status).fadeIn('slow'); }); } else { mongorecords.splice(currentrecord,1); currentrecord = 0; currentprofile = mongorecords[currentrecord].defaultProfile; initRecord(); dirty = false; } } maybePreventDefault(event); return false; } function recordClone (event) { if (dirty && window.confirm(translate('Save current record before switching to new?'))) { profileSubmit(); } GUIToObject(); mongorecords.push(_.cloneDeep(mongorecords[currentrecord])); currentrecord = mongorecords.length - 1; mongorecords[currentrecord].startDate = new Date().toISOString(); currentprofile = mongorecords[currentrecord].defaultProfile; delete mongorecords[currentrecord]._id; initRecord(); dirty = true; maybePreventDefault(event); } // Handling of profile list box change function profileChange (event) { var record = mongorecords[currentrecord]; var newpr = $('#pe_profiles').val(); // copy values from html to c_profile GUIToObject(); var newname = $('#pe_profile_name').val(); if (!isNaN(newname)) newname = 'Profile' + newname; if (currentprofile !== newname) { // rename if already exists while (record.store[newname]) { newname += '1'; } record.store[newname] = record.store[currentprofile]; delete record.store[currentprofile]; dirty = true; } if (newpr === currentprofile) { // fake call to update values newpr = newname; } currentprofile = newpr; initProfile(); maybePreventDefault(event); return false; } function profileAdd (event) { var record = mongorecords[currentrecord]; var newname = 'New profile'; while (record.store[newname]) { newname += '1'; } record.store[newname] = _.cloneDeep(defaultprofile); currentprofile = newname; dirty = true; initProfile(); maybePreventDefault(event); return false; } function profileRemove (event) { var record = mongorecords[currentrecord]; var availableProfile = getFirstAvailableProfile(record); if (availableProfile) { delete record.store[currentprofile]; currentprofile = availableProfile; initProfile(); dirty = true; } maybePreventDefault(event); return false; } function profileClone (event) { GUIToObject(); var record = mongorecords[currentrecord]; var newname = $('#pe_profile_name').val() + ' (copy)'; while (record.store[newname]) { newname += '1'; } record.store[newname] = _.cloneDeep(record.store[currentprofile]); currentprofile = newname; dirty = true; initProfile(); maybePreventDefault(event); return false; } // Handling html events and setting/getting values function switchStyle(event) { if (!$('#pe_perGIvalues').is(':checked')) { $('#pe_simple').show('slow'); $('#pe_advanced').hide('slow'); } else { $('#pe_simple').hide('slow'); $('#pe_advanced').show('slow'); } maybePreventDefault(event); } function fillTimeRanges(event) { if (event) { GUIToObject(); } function shouldAddTime(i, time, array) { if (i === 0 && time === 0) { return true; } else if (i === 0) { return false; } else { var minutesFromMidnight = toMinutesFromMidnight(c_profile[array][i - 1].time); return !isNaN(minutesFromMidnight) && minutesFromMidnight < time * 30; } } function addSingleLine(e,i) { var tr = $('<tr>'); var select = $('<select>').attr('class','pe_selectabletime').attr('id',e.prefix+'_from_'+i); var lowest = -1; for (var t=0;t<48;t++) { if (shouldAddTime(i, t, e.array)) { if (lowest === -1) { lowest = t*30; } select.append('<option value="' + toTimeString(t*30) + '">' + toDisplayTime(t*30) + '</option>'); } } var selectedValue = toMinutesFromMidnight(c_profile[e.array][i].time) * 30; select.val(selectedValue); tr.append($('<td>').append(translate('From') + ': ').append(select)); tr.append($('<td>').append(e.label).append($('<input type="text">').attr('id',e.prefix+'_val_'+i).attr('value',c_profile[e.array][i].value).attr('class', e.prefix + '_value'))); var icons_td = $('<td>').append($('<img>').attr('class','addsingle').attr('style','cursor:pointer').attr('title',translate('Add new interval before')).attr('src',icon_add).attr('array',e.array).attr('pos',i)); if (c_profile[e.array].length>1) { icons_td.append($('<img>').attr('class','delsingle').attr('style','cursor:pointer').attr('title',translate('Delete interval')).attr('src',icon_remove).attr('array',e.array).attr('pos',i)); } tr.append(icons_td); if (lowest>toMinutesFromMidnight(c_profile[e.array][i].time)) { c_profile[e.array][i].time = toTimeString(lowest); } return tr[0].outerHTML; } // Fill dropdown boxes _.each([{prefix:'pe_basal', array:'basal', label: translate('Basal rate') + ' : '}, {prefix:'pe_ic', array:'carbratio', label: translate('I:C') + ' : '}, {prefix:'pe_isf', array:'sens', label: translate('ISF') + ' : '} ], function (e) { var html = '<table>'; for (var i=0; i<c_profile[e.array].length; i++) { html += addSingleLine(e,i); } html += '<tr><td></td><td></td><td><img class="addsingle" style="cursor:pointer" title="' + translate('Add new interval before') + '" src="'+icon_add+'" array="'+e.array+'" pos="'+i+'" href="#"></td></tr>'; html += '</table>'; $('#'+e.prefix+'_placeholder').html(html); }); $('.pe_basal_value').on('change keyup paste', refreshTotalBasal); $('.addsingle').click(function addsingle_click() { var array = $(this).attr('array'); var pos = $(this).attr('pos'); GUIToObject(); c_profile[array].splice(pos,0,{time:'00:00',value:0}); var retVal = fillTimeRanges(); refreshTotalBasal(); return retVal; }); $('.delsingle').click(function delsingle_click() { var array = $(this).attr('array'); var pos = $(this).attr('pos'); GUIToObject(); c_profile[array].splice(pos,1); c_profile[array][0].time = '00:00'; var retVal = fillTimeRanges(); refreshTotalBasal(); return retVal; }); function addBGLine(i) { var tr = $('<tr>'); var select = $('<select>').attr('class','pe_selectabletime').attr('id','pe_targetbg_from_'+i); var lowesttime=-1; for (var t=0;t<48;t++) { if (shouldAddTime(i, t, 'target_low')) { if (lowesttime === -1) { lowesttime = t*30; } select.append('<option value="' + toTimeString(t*30) + '">' + toDisplayTime(t*30) + '</option>'); } } var selectedValue = toMinutesFromMidnight(c_profile.target_low[i].time) * 30; select.val(selectedValue); tr.append($('<td>').append(translate('From') + ': ').append(select)); tr.append($('<td>').append(translate('Low') + ' : ').append($('<input type="text">').attr('id','pe_targetbg_low_'+i).attr('value',c_profile.target_low[i].value))); tr.append($('<td>').append(translate('High') + ' : ').append($('<input type="text">').attr('id','pe_targetbg_high_'+i).attr('value',c_profile.target_high[i].value))); var icons_td = $('<td>').append($('<img>').attr('class','addtargetbg').attr('style','cursor:pointer').attr('title',translate('Add new interval before')).attr('src',icon_add).attr('pos',i)); if (c_profile.target_low.length>1) { icons_td.append($('<img>').attr('class','deltargetbg').attr('style','cursor:pointer').attr('title',translate('Delete interval')).attr('src',icon_remove).attr('pos',i)); } tr.append(icons_td); // Fix time to correct value after add or change if (lowesttime>toMinutesFromMidnight(c_profile.target_low[i].time)) { c_profile.target_low[i].time = toTimeString(lowesttime); } return tr[0].outerHTML; } // target BG var html = '<table>'; for (var i=0; i<c_profile.target_low.length; i++) { html += addBGLine(i); } html += '<tr><td></td><td></td><td></td><td><img class="addtargetbg" style="cursor:pointer" title="' + translate('Add new interval before') + '" src="'+icon_add+'" pos="'+i+'" href="#"></td></tr>'; html += '</table>'; $('#pe_targetbg_placeholder').html(html); $('.addtargetbg').click(function addtargetbg_click() { var pos = $(this).attr('pos'); GUIToObject(); c_profile.target_low.splice(pos,0,{time:'00:00',value:0}); c_profile.target_high.splice(pos,0,{time:'00:00',value:0}); dirty = true; return fillTimeRanges(); }); $('.deltargetbg').click(function deltargetbg_click() { var pos = $(this).attr('pos'); GUIToObject(); c_profile.target_low.splice(pos,1); c_profile.target_high.splice(pos,1); c_profile.target_low[0].time = '00:00'; c_profile.target_high[0].time = '00:00'; dirty = true; return fillTimeRanges(); }); $('.pe_selectabletime').unbind().on('change', fillTimeRanges).on('change', refreshTotalBasal); objectToGUI(); maybePreventDefault(event); return false; } // fill GUI with values from c_profile object function objectToGUI() { $('#pe_dia').val(c_profile.dia); $('#pe_hr').val(c_profile.carbs_hr); $('#pe_perGIvalues').prop('checked', c_profile.perGIvalues); $('#pe_hr_high').val(c_profile.carbs_hr_high); $('#pe_hr_medium').val(c_profile.carbs_hr_medium); $('#pe_hr_low').val(c_profile.carbs_hr_low); $('#pe_delay_high').val(c_profile.delay_high); $('#pe_delay_medium').val(c_profile.delay_medium); $('#pe_delay_low').val(c_profile.delay_low); timezoneInput.val(c_profile.timezone); var index; [ { prefix:'pe_basal', array:'basal' }, { prefix:'pe_ic', array:'carbratio' }, { prefix:'pe_isf', array:'sens' } ].forEach(function (e) { for (index=0; index<c_profile[e.array].length; index++) { $('#'+e.prefix+'_from_'+index).val(c_profile[e.array][index].time); $('#'+e.prefix+'_val_'+index).val(c_profile[e.array][index].value); } }); for (index=0; index<c_profile.target_low.length; index++) { $('#pe_targetbg_from_'+index).val(c_profile.target_low[index].time); $('#pe_targetbg_low_'+index).val(c_profile.target_low[index].value); $('#pe_targetbg_high_'+index).val(c_profile.target_high[index].value); } //console.info(JSON.stringify(c_profile)); } // Grab values from html GUI to object function GUIToObject() { var oldProfile = _.cloneDeep(c_profile); c_profile.units = client.settings.units; c_profile.dia = parseFloat($('#pe_dia').val()); c_profile.carbs_hr = parseInt($('#pe_hr').val()); c_profile.delay = 20; c_profile.perGIvalues = $('#pe_perGIvalues').is(':checked'); c_profile.carbs_hr_high = parseInt($('#pe_hr_high').val()); c_profile.carbs_hr_medium = parseInt($('#pe_hr_medium').val()); c_profile.carbs_hr_low = parseInt($('#pe_hr_low').val()); c_profile.delay_high = parseInt($('#pe_delay_high').val()); c_profile.delay_medium = parseInt($('#pe_delay_medium').val()); c_profile.delay_low = parseInt($('#pe_delay_low').val()); c_profile.timezone = timezoneInput.val(); var index; [ { prefix:'pe_basal', array:'basal' }, { prefix:'pe_ic', array:'carbratio' }, { prefix:'pe_isf', array:'sens' } ].forEach(function (e) { for (index=0; index<c_profile[e.array].length; index++) { c_profile[e.array][index].time = $('#'+e.prefix+'_from_'+index).val(); c_profile[e.array][index].value = parseFloat($('#'+e.prefix+'_val_'+index).val()); } }); for (index=0; index<c_profile.target_low.length; index++) { var input = $('#pe_targetbg_from_' + index); c_profile.target_low[index].time = input.val(); c_profile.target_low[index].value = parseFloat($('#pe_targetbg_low_'+index).val()); c_profile.target_high[index].time = input.val(); c_profile.target_high[index].value = parseFloat($('#pe_targetbg_high_'+index).val()); } if (!_.isEqual(oldProfile,c_profile)) { dirty = true; } } function toMinutesFromMidnight(time) { var split = time.split(':'); return parseInt(split[0])*60 + parseInt(split[1]); } function toTimeString(minfrommidnight) { return moment.utc().startOf('day').add(minfrommidnight,'minutes').format('HH:mm'); // using utc to avoid daylight saving offset } function toDisplayTime (minfrommidnight) { var time = moment.utc().startOf('day').add(minfrommidnight,'minutes'); // using utc to avoid daylight saving offset return client.settings.timeFormat === 24 ? time.format('HH:mm') : time.format('h:mm A'); } function profileSubmit(event) { if (!client.hashauth.isAuthenticated()) { window.alert(translate('Your device is not authenticated yet')); return false; } profileChange(event); var record = mongorecords[currentrecord]; record.startDate = new Date(client.utils.mergeInputTime(timeInput.val(), dateInput.val())).toISOString( ); var adjustedRecord = _.cloneDeep(record); for (var key in adjustedRecord.store) { if (Object.prototype.hasOwnProperty.call(adjustedRecord.store,key)) { var profile = adjustedRecord.store[key]; if (!profile.perGIvalues) { delete profile.perGIvalues; delete profile.carbs_hr_high; delete profile.carbs_hr_medium; delete profile.carbs_hr_low; delete profile.delay_high; delete profile.delay_medium; delete profile.delay_low; } } } adjustedRecord.defaultProfile = currentprofile; adjustedRecord.units = client.settings.units; delete record.convertedOnTheFly; delete adjustedRecord.convertedOnTheFly; console.info('saving profile'); peStatus.hide().text(translate('Saving profile')).fadeIn('slow'); // Hide the form until the ajax PUT is done. // This is a crude way of preventing the user from changing the inputs whilst waiting. // If the user was able to make changes, they'd be lost when the done callback redraws anyway. $('#pe_form').hide(); var headers = client.headers(); headers['Content-Type'] = 'application/json'; $.ajax({ method: 'PUT' , url: '/api/v1/profile/' , data: JSON.stringify(adjustedRecord) , headers: headers }).done(function postSuccess (data, status) { console.info('profile saved', data); $('#pe_form').show(); // allow edits again peStatus.hide().text(status).fadeIn('slow'); record._id = data._id; initRecord(); dirty = false; }).fail(function(xhr, status, errorThrown) { console.error('Profile not saved', status, errorThrown); $('#pe_form').show(); // allow edits again peStatus.hide().text(status).fadeIn('slow'); }); return false; } function getFirstAvailableProfile(record) { var availableProfiles = []; for (var key in record.store) { if (Object.prototype.hasOwnProperty.call(record.store,key)) { if (key !== currentprofile) { availableProfiles.push(key); } } } return availableProfiles.length ? availableProfiles[0] : null; } function maybePreventDefault (event) { if (event) { event.preventDefault(); } } }); }; module.exports = init;