Changes

Jump to navigation Jump to search
no edit summary
Line 1: Line 1:  
// License: GPL
 
// License: GPL
// User Interface Rendering
+
// Indexeddb JavaScript
console.log('Interface handler loading');
+
console.log('Indb loading');
   −
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {
+
function IndexedDBContainer(ww) {
  −
this.renderInterface = function( sqitch ) {
  −
switch( sqitch ) {
  −
case 'controller_id':
  −
controller_render();
  −
break;
  −
case 'personal_data_id':
  −
pd_site_render();
  −
break;
  −
case 'interface_button_id':
  −
personal_data_edit_interface_render();
  −
break;
  −
}
  −
}
     −
var button_save = [],
+
  // suppress console.log, switch to true for debug
button_remove = [],
+
  var Debug_switch = false;
textInput = [];
+
  // seemingly the Safari engine uses a somewhat different implementation of arguments for db.transaction and index.get
 +
  // because no browser on any mac / ios is allowed to use a different engine, rather than user agent, platform can be tested
 +
  var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
 +
  var Safari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
 +
  debuglog("iOS:" + iOS + " & Saf:" + Safari);
   −
async function controller_render(){
+
  // deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)
console.log("this function is done by the current page controller for now");
+
  hashCode = function(s) {
notify_porting();
+
    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;
 +
  };
   −
async function pd_site_render(){
     −
};
+
  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);
   −
async function personal_data_edit_interface_render(){
+
    // Take username for standard databasename format:
clear_render();
+
    // Our current convention for personal databasename (separate dbname for each user)
+
    var PersonalDataDataBaseName = "PD.IO" + idgen + "Database";
// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it
+
    // 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);
 +
  }
   −
var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['qIDPropName'] ] } )['this_concerns'][0];
+
  // ADD MORE DOC
   −
// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it
+
  // EnqueuePDIO a PDIOLocalDatabase:User database access function with modes
 +
  // Externally accessible wrapper for Enquire with current user / db preloaded
   −
var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal
+
  this.EnqueuePDIO = async function(sw, c1, c2, c3) {
 +
    debuglog("enquing pdio db " + PersonalDataDataBaseName + " with user " + JSON.stringify(this.CurrentPerson));
 +
    var k = await Enquire(PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3);
 +
    return k;
 +
  }
   −
var get_record = indexedDBobject.EnqueuePDIO('update record');
+
  // Enquire, a general purpose indexeddb update function with modes
   −
get_record.then( function(result) {
+
  // Mode 'aggressive push':
 +
  // parameter record is pushed to database, overwriting whatever is there
   −
mw.loader.using( 'oojs-ui-core' ).done( function () {
+
  // Mode 'checkin':
 +
  // record is retrieved from database, parameter record is pushed if not found
   −
button_save = [],
+
  // Mode 'get record'
button_remove = [],
+
  // updates record given as argument
textInput = [];
     −
var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;
+
  // Mode 'update record' field1 field2 field3
 +
  // retrieve record, make record.field1.field2 = field3, push back
   −
button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: "Save", classes: [ 'pduimark' ] } );
+
  // Mode 'update record' field1 field2
+
  // retrieve record, make record.field1 = field2, push back
textInput[ extrafield ] = new OO.ui.TextInputWidget( {
  −
placeholder: default_value,
  −
classes: [ 'pduimark' ]
  −
} );
     −
button_save[ extrafield ].on( 'click', function () {
+
  // Mode 'remove from record' field1
indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );
+
  // retrieve record, splice/delete record.field1, push back
personal_data_edit_interface_render();
  −
});
     −
$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );
+
  // Mode 'remove from record' field1 field2
$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );
+
  // retrieve record, splice/delete record.field1.field2, push back
   −
if ( extrafield > 0) {
+
  // Mode 'import record' field1
Object.keys( result[concern_origin] ).forEach( function(data) {
+
  // retrieve record, add all fields from field1, push back
button_save[data] = new OO.ui.ButtonWidget( { label: "Save", classes: [ 'pduimark' ] } );
  −
button_remove[data] = new OO.ui.ButtonWidget( { label: "Delete", classes: [ 'pduimark' ] } );
  −
textInput[data] = new OO.ui.TextInputWidget( {
  −
value: result[concern_origin][data], ///
  −
placeholder: default_value,
  −
classes: [ 'pduimark' ]
  −
} );
  −
button_save[data].on( 'click', function () {
     −
indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );
+
  async function Enquire(pddbname, record, sqitch, control_1, control_2, control_3) {
 +
    return new Promise(
 +
      function(resolve, reject) {
   −
personal_data_edit_interface_render();
+
        var pddb = window.indexedDB.open(pddbname, 3);
});
+
        var inp_obj;
   −
button_remove[data].on( 'click', function () {
+
        pddb.onerror = function() {
indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );
+
          console.log("Warning: Access to IndexedDB for application has been rejected.");
personal_data_edit_interface_render();
+
        };
});
  −
$( '#mw-content-text' ).prepend( button_remove[data].$element );
  −
$( '#mw-content-text' ).prepend( button_save[data].$element );
  −
$( '#mw-content-text' ).prepend( textInput[data].$element );
     −
});
+
        // 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"
 +
          });
 +
          var index = store.createIndex("NameIndex", ["id"]);
   −
}
+
        };
});
+
        // Database successfully opened function.
});
+
        pddb.onsuccess = function() {
};
+
          debuglog(pddb.result);
 +
          var db = pddb.result;
 +
          var tx;
   −
function clear_render() {
+
          if (iOS || Safari) {
var ifel = document.getElementsByClassName('pduimark');
+
            tx = db.transaction([pddbname], "readwrite");
while( ifel[0] ) {
+
          } else {
ifel[0].parentNode.removeChild(ifel[0]);
+
            tx = db.transaction(pddbname, "readwrite");
};
+
          }
};
  −
  −
function notify_porting() {
     −
mw.loader.using( 'oojs-ui-core' ).done( function () {
+
          var store = tx.objectStore(pddbname);
 +
          var index = store.index("NameIndex");
   −
var button_import = new OO.ui.SelectFileWidget( { label: "Import Personal Data", classes: [ 'pduimark' ] } ),
+
          // Get the original record from the db...
 +
          var getRecord;
 +
          if (iOS || Safari) {
 +
            getRecord = index.get(record.id);
 +
          } else {
 +
            getRecord = index.get([record.id]);
 +
          }
   −
button_export = new OO.ui.ButtonWidget( { label: "Export Personal Data", classes: [ 'pduimark' ] } );
+
          getRecord.onsuccess = function() {
 +
            debuglog("Record 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);
 +
              }
   −
button_import.on( 'change', function (event) {
+
            } 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 (window.webkitURL != null) {
+
                if (sqitch === "get record") {
console.log("loading file on webkit")
  −
} else {
  −
console.log("loading file non webkit")
  −
}
     −
console.log( event );
+
                  debuglog("Getting record");
 +
                  // we will return later
   −
});
+
                }
   −
button_export.on( 'click', function () {
+
                // endof onsuccess
 +
              } else {
   −
var get_record = indexedDBobject.EnqueuePDIO('get record');
+
                debuglog("Record not found");
   −
get_record.then( function(result) {
+
                if (sqitch === "update record") {
console.log("happening");
+
                  // Update record will use supplied copy to update it
if ( result === undefined ) { window.alert("No local data to export") } else {  
+
                  inp_obj = record;
 +
                } else {
 +
                  if (sqitch === "get record") {
 +
                    inp_obj = undefined;
 +
                  } else if (sqitch === "remove from record") {
 +
                    inp_obj = record;
 +
                  } else {
 +
                    // any other method ...... would quit as record was not even foun
 +
                    return undefined;
 +
                  }
 +
                }
 +
              }
 +
            }
   −
var filename_tosaveas = "pdiolocalexport_" + result.name.user + "_" + Date.now() + '.json';
+
            if (sqitch === "update record") { // Record Update
+
              if (control_1 != undefined) {
result.id = '';
+
                if (control_2 != undefined) {
result.name.user = '';
+
                  if (control_3 != undefined) {
  −
var export_to_text = JSON.stringify(result);
  −
var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});
  −
var downloadLink = document.createElement("a");
  −
downloadLink.download = filename_tosaveas;
  −
if (window.webkitURL != null)
  −
{
  −
// Chrome allows the link to be clicked
  −
// without actually adding it to the DOM.
  −
downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
  −
}
  −
else
  −
{
  −
// Firefox requires the link to be added to the DOM
  −
// before it can be clicked.
  −
downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
  −
downloadLink.style.display = "none";
  −
document.body.appendChild(downloadLink);
  −
}
     −
downloadLink.click();
+
                    // 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);
   −
mw.notify( $( button_import.$element ), { autoHide: false }  );
+
                  }
mw.notify( $( button_export.$element ), { autoHide: false }  );
+
                } 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];
 +
                }
 +
              }
 +
              debuglog("putting object to store:");
 +
              debuglog(inp_obj);
 +
              store.put(inp_obj);
 +
            }
 +
 
 +
            if (sqitch === "import record") {
 +
              debuglog("import command");
 +
              if (control_1 != undefined) {
 +
                // Only import if control_1 is a non-empty object
 +
                if ((!Array.isArray(control_1)) && (Object.keys(control_1).length > 0)) {
 +
                  debuglog("command is obj");
 +
                  Object.keys(control_1).forEach(function(importkey) {
 +
                    debuglog("importing " + importkey);
 +
                    if (control_1.hasOwnProperty(importkey)) {
 +
                      inp_obj[importkey] = control_1[importkey]
 +
                    };
 +
                  })
 +
                  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) {
 +
      console.log(l0g);
 +
    }
 +
  }
 +
};

Navigation menu