Difference between revisions of "MediaWiki:Gadget-personaldata.js"
Jump to navigation
Jump to search
m |
m |
||
Line 3: | Line 3: | ||
console.log('Indb loading'); | console.log('Indb loading'); | ||
− | function | + | function IndexedDBContainer( ww ) { |
+ | |||
+ | // suppress console.log, switch to true for debug | ||
var Debug_switch = false; | var Debug_switch = false; | ||
+ | |||
+ | // deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different) | ||
hashCode = function(s) { | hashCode = function(s) { | ||
if ( s == undefined) { | if ( s == undefined) { | ||
Line 15: | Line 19: | ||
return h; | return h; | ||
}; | }; | ||
− | + | ||
+ | |||
if ( ww.user != undefined ) { | if ( ww.user != undefined ) { | ||
+ | // if user exists in object passed to constructor, get username | ||
var self = ww.user.getName(); | var self = ww.user.getName(); | ||
− | + | // create userid by hashing username | |
var idgen = hashCode(self); | var idgen = hashCode(self); | ||
+ | debuglog(idgen); | ||
− | + | // Take username for standard databasename format: | |
− | + | // Our current convention for personal databasename (separate dbname for each user) | |
var PersonalDataDataBaseName = "PD.IO" + idgen + "Database"; | var PersonalDataDataBaseName = "PD.IO" + idgen + "Database"; | ||
// Use username in user to get up to date version of self | // Use username in user to get up to date version of self | ||
+ | // Blank object for personal data Record with id and username included | ||
this.CurrentPerson = {id: idgen, name: {user: self}, age: 0}; | this.CurrentPerson = {id: idgen, name: {user: self}, age: 0}; | ||
− | |||
debuglog(PersonalDataDataBaseName); | debuglog(PersonalDataDataBaseName); | ||
debuglog(this.CurrentPerson); | debuglog(this.CurrentPerson); | ||
Line 34: | Line 41: | ||
// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes | // EnqueuePDIO a PDIOLocalDatabase:User database access function with modes | ||
− | // | + | // Externally accessible wrapper for Enquire with current user / db preloaded |
− | + | ||
this.EnqueuePDIO = async function( sw, c1, c2, c3 ) { | this.EnqueuePDIO = async function( sw, c1, c2, c3 ) { | ||
var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 ); | var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 ); | ||
Line 70: | Line 77: | ||
var pddb = window.indexedDB.open(pddbname, 3); | var pddb = window.indexedDB.open(pddbname, 3); | ||
var inp_obj; | var inp_obj; | ||
+ | |||
+ | // indexeddb internal mechanism for version tracking of schema | ||
pddb.onupgradeneeded = function() { | pddb.onupgradeneeded = function() { | ||
+ | console.log('upgrading database'); | ||
var db = pddb.result; | var db = pddb.result; | ||
var store = db.createObjectStore(pddbname, {keyPath: "id"}); | var store = db.createObjectStore(pddbname, {keyPath: "id"}); | ||
Line 78: | Line 88: | ||
var index = store.createIndex("NameIndex", ["id"]); | var index = store.createIndex("NameIndex", ["id"]); | ||
}; | }; | ||
+ | // Database successfully opened function. | ||
pddb.onsuccess = function() { | pddb.onsuccess = function() { | ||
var db = pddb.result; | var db = pddb.result; | ||
Line 93: | Line 104: | ||
// Essential recordAdd | // Essential recordAdd | ||
if ( sqitch === "aggressive push" ) { | if ( sqitch === "aggressive push" ) { | ||
+ | // Mode 'aggressive push': | ||
+ | // parameter record is pushed to database, overwriting whatever is there | ||
inp_obj = record; | inp_obj = record; | ||
store.put( inp_obj ); | store.put( inp_obj ); | ||
return inp_obj; | return inp_obj; | ||
} else if ( sqitch === "checkin" ) { | } else if ( sqitch === "checkin" ) { | ||
− | + | // Mode 'checkin': | |
+ | // record is retrieved from database, parameter record is pushed if not found | ||
if ( getRecord.result != undefined ) { | if ( getRecord.result != undefined ) { | ||
debuglog("getting from store"); | debuglog("getting from store"); | ||
Line 108: | Line 122: | ||
} else { | } else { | ||
+ | // Methods manipulationg the actual record come here | ||
+ | // Update & Remove from | ||
+ | // If we got the record from store, use that version to be manipulated | ||
if ( getRecord.result != undefined ) { | if ( getRecord.result != undefined ) { | ||
inp_obj = getRecord.result; | inp_obj = getRecord.result; | ||
+ | |||
if ( sqitch === "get record" ) { | if ( sqitch === "get record" ) { | ||
− | + | ||
debuglog("Getting record"); | debuglog("Getting record"); | ||
− | // | + | // we will return later |
− | + | ||
} | } | ||
− | + | ||
// endof onsuccess | // endof onsuccess | ||
} else { | } else { | ||
− | debuglog(" | + | |
+ | debuglog("Record not found"); | ||
+ | |||
if ( sqitch === "update record" ) { | if ( sqitch === "update record" ) { | ||
+ | // Update record will use supplied copy to update it | ||
inp_obj = record; | inp_obj = record; | ||
} else { | } else { | ||
+ | // Remove from record will quit as record was not even found | ||
return undefined; | return undefined; | ||
} | } | ||
} | } | ||
− | |||
} | } | ||
− | + | ||
if ( sqitch === "update record" ) { // Record Update | if ( sqitch === "update record" ) { // Record Update | ||
if ( control_1 != undefined ) { | if ( control_1 != undefined ) { | ||
if ( control_2 != undefined ) { | if ( control_2 != undefined ) { | ||
if ( control_3 != undefined ) { | if ( control_3 != undefined ) { | ||
+ | |||
+ | // Mode 'update record' field1 field2 field3 | ||
+ | // retrieve record, make record.field1.field2 = field3, push back | ||
+ | |||
if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] }; | if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] }; | ||
inp_obj[ control_1 ][ control_2 ] = control_3; // => "Bob" | inp_obj[ control_1 ][ control_2 ] = control_3; // => "Bob" | ||
store.put(inp_obj); | store.put(inp_obj); | ||
} else { | } else { | ||
+ | |||
+ | // Mode 'update record' field1 field2 | ||
+ | // retrieve record, make record.field1 = field2, push back | ||
+ | |||
inp_obj[ control_1 ] = inp_obj[ control_1 ] || {}; | inp_obj[ control_1 ] = inp_obj[ control_1 ] || {}; | ||
if ( Array.isArray( inp_obj[ control_1 ] ) ) { | if ( Array.isArray( inp_obj[ control_1 ] ) ) { | ||
Line 146: | Line 175: | ||
} | } | ||
− | |||
} else { | } else { | ||
− | + | // Only one control defined. We will return that part of the record, and change nothing | |
− | |||
− | |||
− | |||
− | |||
inp_obj = inp_obj[ control_1 ]; | inp_obj = inp_obj[ control_1 ]; | ||
} | } | ||
− | |||
} else { | } else { | ||
− | //return | + | // There's not even control_1, we will just return the record itself |
} | } | ||
Line 169: | Line 192: | ||
if ( control_1 != undefined ) { | if ( control_1 != undefined ) { | ||
if ( control_2 != undefined ) { | if ( control_2 != undefined ) { | ||
+ | |||
+ | // Mode 'remove from record' field1 field2 | ||
+ | // retrieve record, splice/delete record.field1.field2, push back | ||
+ | |||
if ( Array.isArray( inp_obj[ control_1 ] ) && !isNaN( control_2 ) ) { | if ( Array.isArray( inp_obj[ control_1 ] ) && !isNaN( control_2 ) ) { | ||
inp_obj[ control_1 ].splice( control_2, 1 ); | inp_obj[ control_1 ].splice( control_2, 1 ); | ||
Line 174: | Line 201: | ||
delete inp_obj[ control_1 ][ control_2 ]; | delete inp_obj[ control_1 ][ control_2 ]; | ||
} | } | ||
+ | |||
} else { | } else { | ||
+ | |||
+ | // Mode 'remove from record' field1 | ||
+ | // retrieve record, splice/delete record.field1, push back | ||
+ | |||
delete inp_obj[ control_1 ]; | delete inp_obj[ control_1 ]; | ||
} | } | ||
Line 181: | Line 213: | ||
} | } | ||
− | + | // We are past all methodic code, Async return | |
+ | |||
resolve( inp_obj ); | resolve( inp_obj ); | ||
}; | }; | ||
− | + | ||
+ | // Indexeddb internal mechanism, close db | ||
+ | |||
tx.oncomplete = function() { | tx.oncomplete = function() { | ||
debuglog("return 1") | debuglog("return 1") | ||
Line 193: | Line 228: | ||
debuglog("return 0") | debuglog("return 0") | ||
+ | // End of promise | ||
+ | |||
}).then( function(result) { | }).then( function(result) { | ||
debuglog("Mark 3"); | debuglog("Mark 3"); |
Revision as of 05:35, 21 May 2019
// License: GPL
// Indexeddb JavaScript
console.log('Indb loading');
function IndexedDBContainer( ww ) {
// suppress console.log, switch to true for debug
var Debug_switch = false;
// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)
hashCode = function(s) {
if ( s == undefined) {
s = '00'
}
var h = 0, l = s.length, i = 0;
if ( l > 0 )
while (i < l)
h = (h << 5) - h + s.charCodeAt(i++) | 0;
return h;
};
if ( ww.user != undefined ) {
// if user exists in object passed to constructor, get username
var self = ww.user.getName();
// create userid by hashing username
var idgen = hashCode(self);
debuglog(idgen);
// Take username for standard databasename format:
// Our current convention for personal databasename (separate dbname for each user)
var PersonalDataDataBaseName = "PD.IO" + idgen + "Database";
// Use username in user to get up to date version of self
// Blank object for personal data Record with id and username included
this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};
debuglog(PersonalDataDataBaseName);
debuglog(this.CurrentPerson);
}
// ADD MORE DOC
// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes
// Externally accessible wrapper for Enquire with current user / db preloaded
this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {
var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );
return k;
}
// Enquire, a general purpose indexeddb update function with modes
// Mode 'aggressive push':
// parameter record is pushed to database, overwriting whatever is there
// Mode 'checkin':
// record is retrieved from database, parameter record is pushed if not found
// Mode 'get record'
// updates record given as argument
// Mode 'update record' field1 field2 field3
// retrieve record, make record.field1.field2 = field3, push back
// Mode 'update record' field1 field2
// retrieve record, make record.field1 = field2, push back
// Mode 'remove from record' field1
// retrieve record, splice/delete record.field1, push back
// Mode 'remove from record' field1 field2
// retrieve record, splice/delete record.field1.field2, push back
async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {
return new Promise(
function(resolve, reject) {
var pddb = window.indexedDB.open(pddbname, 3);
var inp_obj;
// indexeddb internal mechanism for version tracking of schema
pddb.onupgradeneeded = function() {
console.log('upgrading database');
var db = pddb.result;
var store = db.createObjectStore(pddbname, {keyPath: "id"});
// shouldn't the index be the wiki.personaldata.io username?
var index = store.createIndex("NameIndex", ["id"]);
};
// Database successfully opened function.
pddb.onsuccess = function() {
var db = pddb.result;
var tx = db.transaction(pddbname, "readwrite");
var store = tx.objectStore(pddbname);
var index = store.index("NameIndex");
// Get the original record from the db...
var getRecord = index.get([record.id]);
getRecord.onsuccess = function() {
debuglog( "Record found in database: \n <<");
debuglog( getRecord.result );
debuglog( ">>");
// Essential recordAdd
if ( sqitch === "aggressive push" ) {
// Mode 'aggressive push':
// parameter record is pushed to database, overwriting whatever is there
inp_obj = record;
store.put( inp_obj );
return inp_obj;
} else if ( sqitch === "checkin" ) {
// Mode 'checkin':
// record is retrieved from database, parameter record is pushed if not found
if ( getRecord.result != undefined ) {
debuglog("getting from store");
inp_obj = getRecord.result;
} else {
debuglog("overriding whatever in there");
inp_obj = record;
store.put(inp_obj);
}
} else {
// Methods manipulationg the actual record come here
// Update & Remove from
// If we got the record from store, use that version to be manipulated
if ( getRecord.result != undefined ) {
inp_obj = getRecord.result;
if ( sqitch === "get record" ) {
debuglog("Getting record");
// we will return later
}
// endof onsuccess
} else {
debuglog("Record not found");
if ( sqitch === "update record" ) {
// Update record will use supplied copy to update it
inp_obj = record;
} else {
// Remove from record will quit as record was not even found
return undefined;
}
}
}
if ( sqitch === "update record" ) { // Record Update
if ( control_1 != undefined ) {
if ( control_2 != undefined ) {
if ( control_3 != undefined ) {
// Mode 'update record' field1 field2 field3
// retrieve record, make record.field1.field2 = field3, push back
if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };
inp_obj[ control_1 ][ control_2 ] = control_3; // => "Bob"
store.put(inp_obj);
} else {
// Mode 'update record' field1 field2
// retrieve record, make record.field1 = field2, push back
inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};
if ( Array.isArray( inp_obj[ control_1 ] ) ) {
inp_obj[ control_1 ].push( control_2 );
} else {
inp_obj[ control_1 ] = control_2;
}
store.put(inp_obj);
}
} else {
// Only one control defined. We will return that part of the record, and change nothing
inp_obj = inp_obj[ control_1 ];
}
} else {
// There's not even control_1, we will just return the record itself
}
debuglog("return 3")
// return inp_obj;
};
if ( sqitch === "remove from record" ) { // Record Update
if ( control_1 != undefined ) {
if ( control_2 != undefined ) {
// Mode 'remove from record' field1 field2
// retrieve record, splice/delete record.field1.field2, push back
if ( Array.isArray( inp_obj[ control_1 ] ) && !isNaN( control_2 ) ) {
inp_obj[ control_1 ].splice( control_2, 1 );
} else {
delete inp_obj[ control_1 ][ control_2 ];
}
} else {
// Mode 'remove from record' field1
// retrieve record, splice/delete record.field1, push back
delete inp_obj[ control_1 ];
}
}
store.put(inp_obj);
}
// We are past all methodic code, Async return
resolve( inp_obj );
};
// Indexeddb internal mechanism, close db
tx.oncomplete = function() {
debuglog("return 1")
db.close();
};
};
debuglog("return 0")
// End of promise
}).then( function(result) {
debuglog("Mark 3");
debuglog(result);
return result;
});
}
function debuglog( l0g ){
if ( Debug_switch ) {
debuglog( l0g );
}
}
};