diff --git a/bower.json b/bower.json index 0511964f203..b796fb1943f 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "nightscout", - "version": "0.8.1", + "version": "0.8.2-beta1", "dependencies": { "jquery": "2.1.0", "jQuery-Storage-API": "~1.7.2", diff --git a/bundle/bundle.source.js b/bundle/bundle.source.js index 0ca7d7235eb..d78ecb3c868 100644 --- a/bundle/bundle.source.js +++ b/bundle/bundle.source.js @@ -10,6 +10,7 @@ , units: require('../lib/units')() , plugins: require('../lib/plugins/')().registerClientDefaults() , report_plugins: require('../lib/report_plugins/')() + , admin_plugins: require('../lib/admin_plugins/')() }; console.info('Nightscout bundle ready'); diff --git a/lib/admin_plugins/cleanstatusdb.js b/lib/admin_plugins/cleanstatusdb.js new file mode 100644 index 00000000000..86e61e987f8 --- /dev/null +++ b/lib/admin_plugins/cleanstatusdb.js @@ -0,0 +1,70 @@ +'use strict'; + +var cleanstatusdb = { + name: 'cleanstatusdb' + , label: 'Clean Mongo status database' + , pluginType: 'admin' +}; + +function init() { + return cleanstatusdb; +} + +module.exports = init; + +cleanstatusdb.actions = [ + { + 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.' + , buttonLabel: 'Delete all documents' + , confirmText: 'Delete all documents from devicestatus collection?' + } + ]; + +cleanstatusdb.actions[0].init = function init(client, callback) { + var translate = client.translate; + var $status = $('#admin_' + cleanstatusdb.name + '_0_status'); + + $status.hide().text(translate('Loading database ...')).fadeIn('slow'); + $.ajax('/api/v1/devicestatus.json?count=500', { + success: function (records) { + var recs = (records.length === 500 ? '500+' : records.length); + $status.hide().text(translate('Database contains %1 records',{ params: [recs] })).fadeIn('slow'); + }, + error: function () { + $status.hide().text(translate('Error loading database')).fadeIn('slow'); + } + }).done(function () { if (callback) { callback(); } }); +}; + +cleanstatusdb.actions[0].code = function deleteRecords(client, callback) { + var translate = client.translate; + var $status = $('#admin_' + cleanstatusdb.name + '_0_status'); + + if (!client.hashauth.isAuthenticated()) { + alert(translate('Your device is not authenticated yet')); + if (callback) { + callback(); + } + return; + }; + + $status.hide().text(translate('Deleting records ...')).fadeIn('slow'); + $.ajax({ + method: 'DELETE' + , url: '/api/v1/devicestatus/*' + , headers: { + 'api-secret': client.hashauth.hash() + } + }).done(function success () { + $status.hide().text(translate('All records removed ...')).fadeIn('slow'); + if (callback) { + callback(); + } + }).fail(function fail() { + $status.hide().text(translate('Error')).fadeIn('slow'); + if (callback) { + callback(); + } + }); +}; diff --git a/lib/admin_plugins/futureitems.js b/lib/admin_plugins/futureitems.js new file mode 100644 index 00000000000..ab888aff0a6 --- /dev/null +++ b/lib/admin_plugins/futureitems.js @@ -0,0 +1,172 @@ +'use strict'; + +var futureitems = { + name: 'futureitems' + , label: 'Remove future items from mongo database' + , pluginType: 'admin' +}; + +function init() { + return futureitems; +} + +module.exports = init; + +futureitems.actions = [ + { + name: 'Find and remove treatments in the future' + , description: 'This task find and 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.' + , buttonLabel: 'Remove entries in the future' + } + ]; + +futureitems.actions[0].init = function init(client, callback) { + var translate = client.translate; + var $status = $('#admin_' + futureitems.name + '_0_status'); + + function valueOrEmpty (value) { + return value ? value : ''; + } + + function showOneTreatment (tr, table) { + table.append($('').css('background-color','#0f0f0f') + .append($('').attr('width','20%').append(new Date(tr.created_at).toLocaleString().replace(/([\d]+:[\d]{2})(:[\d]{2})(.*)/, '$1$3'))) + .append($('').attr('width','20%').append(tr.eventType ? translate(client.careportal.resolveEventName(tr.eventType)) : '')) + .append($('').attr('width','10%').attr('align','center').append(tr.glucose ? tr.glucose + ' ('+translate(tr.glucoseType)+')' : '')) + .append($('').attr('width','10%').attr('align','center').append(valueOrEmpty(tr.insulin))) + .append($('').attr('width','10%').attr('align','center').append(valueOrEmpty(tr.carbs))) + .append($('').attr('width','10%').append(valueOrEmpty(tr.enteredBy))) + .append($('').attr('width','20%').append(valueOrEmpty(tr.notes))) + ); + } + + function showTreatments(treatments, table) { + table.append($('').css('background','#040404') + .append($('').css('width','80px').attr('align','left').append(translate('Time'))) + .append($('').css('width','150px').attr('align','left').append(translate('Event Type'))) + .append($('').css('width','150px').attr('align','left').append(translate('Blood Glucose'))) + .append($('').css('width','50px').attr('align','left').append(translate('Insulin'))) + .append($('').css('width','50px').attr('align','left').append(translate('Carbs'))) + .append($('').css('width','150px').attr('align','left').append(translate('Entered By'))) + .append($('').css('width','300px').attr('align','left').append(translate('Notes'))) + ); + for (var t=0; t').css('margin-top','10px'); + $('#admin_' + futureitems.name + '_0_html').append(table); + showTreatments(records, table); + futureitems.actions[0].confirmText = translate('Remove %1 selected records?', { params: [records.length] }); + }, + error: function () { + $status.hide().text(translate('Error loading database')).fadeIn('slow'); + futureitems.treatmentrecords = []; + } + }).done(function () { if (callback) { callback(); } }); +}; + +futureitems.actions[0].code = function deleteRecords(client, callback) { + var translate = client.translate; + var $status = $('#admin_' + futureitems.name + '_0_status'); + + if (!client.hashauth.isAuthenticated()) { + alert(translate('Your device is not authenticated yet')); + if (callback) { + callback(); + } + return; + }; + + function deleteRecordById (_id) { + $.ajax({ + method: 'DELETE' + , url: '/api/v1/treatments/' + _id + , headers: { + 'api-secret': client.hashauth.hash() + } + }).done(function success () { + $status.text(translate('Record %1 removed ...', { params: [_id] })); + }).fail(function fail() { + $status.text(translate('Error removing record %1', { params: [_id] })); + }); + } + + $status.hide().text(translate('Deleting records ...')).fadeIn('slow'); + for (var i = 0; i < futureitems.treatmentrecords.length; i++) { + deleteRecordById(futureitems.treatmentrecords[i]._id); + } + $('#admin_' + futureitems.name + '_0_html').html(''); + + if (callback) { + callback(); + } +}; + +futureitems.actions[1].init = function init(client, callback) { + var translate = client.translate; + var $status = $('#admin_' + futureitems.name + '_1_status'); + + $status.hide().text(translate('Loading database ...')).fadeIn('slow'); + var now = new Date().getTime(); + $.ajax('/api/v1/entries.json?&find[date][$gte]=' + now, { + success: function (records) { + futureitems.entriesrecords = records; + $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] }); + }, + error: function () { + $status.hide().text(translate('Error loading database')).fadeIn('slow'); + futureitems.entriesrecords = []; + } + }).done(function () { if (callback) { callback(); } }); +}; + +futureitems.actions[1].code = function deleteRecords(client, callback) { + var translate = client.translate; + var $status = $('#admin_' + futureitems.name + '_1_status'); + + if (!client.hashauth.isAuthenticated()) { + alert(translate('Your device is not authenticated yet')); + if (callback) { + callback(); + } + return; + }; + + function deteleteRecordById (_id) { + $.ajax({ + method: 'DELETE' + , url: '/api/v1/entries/' + _id + , headers: { + 'api-secret': client.hashauth.hash() + } + }).done(function success () { + $status.text(translate('Record %1 removed ...', { params: [_id] })); + }).fail(function fail() { + $status.text(translate('Error removing record %1', { params: [_id] })); + }); + } + + + $status.hide().text(translate('Deleting records ...')).fadeIn('slow'); + for (var i = 0; i < futureitems.entriesrecords.length; i++) { + deteleteRecordById(futureitems.entriesrecords[i]._id); + } + + if (callback) { + callback(); + } +}; diff --git a/lib/admin_plugins/index.js b/lib/admin_plugins/index.js new file mode 100644 index 00000000000..f7a5c74133d --- /dev/null +++ b/lib/admin_plugins/index.js @@ -0,0 +1,79 @@ +'use strict'; + +var _ = require('lodash'); + +function init() { + var allPlugins = [ + require('./cleanstatusdb')() + , require('./futureitems')() + ]; + + function plugins(name) { + if (name) { + return _.find(allPlugins, {name: name}); + } else { + return plugins; + } + } + + plugins.eachPlugin = function eachPlugin(f) { + _.each(allPlugins, f); + }; + + plugins.createHTML = function createHTML(client) { + var translate = client.translate; + plugins.eachPlugin(function addHtml(p) { + var fs = $('
'); + $('#admin_placeholder').append(fs); + fs.append($('').append(translate(p.label))); + for (var i = 0; i < p.actions.length; i++) { + if (i !== 0) { + fs.append('
'); + } + var a = p.actions[i]; + // add main plugin html + fs.append($('').css('text-decoration','underline').append(translate(a.name))); + fs.append('
'); + fs.append($('').append(translate(a.description))); + fs.append($('
').attr('id','admin_' + p.name + '_' + i + '_html')); + fs.append($('