Adding floCloudAPI
floCloudAPI has methods to send application data, request application data, reset or update object data.
This commit is contained in:
parent
d79d54b400
commit
289089d972
407
index.html
407
index.html
@ -5914,5 +5914,412 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<script>
|
||||||
|
//For diff base
|
||||||
|
/*
|
||||||
|
Functions available:
|
||||||
|
diff(originalObj, updatedObj) returns the difference of the original and updated objects
|
||||||
|
addedDiff(original, updatedObj) returns only the values added to the updated object
|
||||||
|
deletedDiff(original, updatedObj) returns only the values deleted in the updated object
|
||||||
|
updatedDiff(original, updatedObj) returns only the values that have been changed in the updated object
|
||||||
|
detailedDiff(original, updatedObj) returns an object with the added, deleted and updated differences
|
||||||
|
mergeRecurcive(original, diff) this will get you a new object that will merge all the changes between the old object and the new object
|
||||||
|
*/
|
||||||
|
|
||||||
|
const isDate = d => d instanceof Date;
|
||||||
|
const isEmpty = o => Object.keys(o).length === 0;
|
||||||
|
const isObject = o => o != null && typeof o === 'object';
|
||||||
|
const properObject = o => isObject(o) && !o.hasOwnProperty ? { ...o } : o;
|
||||||
|
|
||||||
|
|
||||||
|
const getLargerArray = (l, r) => l.length > r.length ? l : r;
|
||||||
|
|
||||||
|
const preserve = (diff, left, right) => {
|
||||||
|
|
||||||
|
if (!isObject(diff)) return diff;
|
||||||
|
|
||||||
|
return Object.keys(diff).reduce((acc, key) => {
|
||||||
|
|
||||||
|
const leftArray = left[key];
|
||||||
|
const rightArray = right[key];
|
||||||
|
|
||||||
|
if (Array.isArray(leftArray) && Array.isArray(rightArray)) {
|
||||||
|
const array = [...getLargerArray(leftArray, rightArray)];
|
||||||
|
return {
|
||||||
|
...acc,
|
||||||
|
[key]: array.reduce((acc2, item, index) => {
|
||||||
|
if (diff[key].hasOwnProperty(index)) {
|
||||||
|
acc2[index] = preserve(diff[key][index], leftArray[index], rightArray[index]); // diff recurse and check for nested arrays
|
||||||
|
return acc2;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete acc2[index]; // no diff aka empty
|
||||||
|
return acc2;
|
||||||
|
}, array)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...acc,
|
||||||
|
[key]: diff[key]
|
||||||
|
};
|
||||||
|
}, {});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const updatedDiff = (lhs, rhs) => {
|
||||||
|
|
||||||
|
if (lhs === rhs) return {};
|
||||||
|
|
||||||
|
if (!isObject(lhs) || !isObject(rhs)) return rhs;
|
||||||
|
|
||||||
|
const l = properObject(lhs);
|
||||||
|
const r = properObject(rhs);
|
||||||
|
|
||||||
|
if (isDate(l) || isDate(r)) {
|
||||||
|
if (l.valueOf() == r.valueOf()) return {};
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.keys(r).reduce((acc, key) => {
|
||||||
|
|
||||||
|
if (l.hasOwnProperty(key)) {
|
||||||
|
const difference = updatedDiff(l[key], r[key]);
|
||||||
|
|
||||||
|
if (isObject(difference) && isEmpty(difference) && !isDate(difference)) return acc;
|
||||||
|
|
||||||
|
return { ...acc, [key]: difference };
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const diff = (lhs, rhs) => {
|
||||||
|
if (lhs === rhs) return {}; // equal return no diff
|
||||||
|
|
||||||
|
if (!isObject(lhs) || !isObject(rhs)) return rhs; // return updated rhs
|
||||||
|
|
||||||
|
const l = properObject(lhs);
|
||||||
|
const r = properObject(rhs);
|
||||||
|
|
||||||
|
const deletedValues = Object.keys(l).reduce((acc, key) => {
|
||||||
|
return r.hasOwnProperty(key) ? acc : { ...acc, [key]: null };
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
if (isDate(l) || isDate(r)) {
|
||||||
|
if (l.valueOf() == r.valueOf()) return {};
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.keys(r).reduce((acc, key) => {
|
||||||
|
if (!l.hasOwnProperty(key)) return { ...acc, [key]: r[key] }; // return added r key
|
||||||
|
|
||||||
|
const difference = diff(l[key], r[key]);
|
||||||
|
|
||||||
|
if (isObject(difference) && isEmpty(difference) && !isDate(difference)) return acc; // return no diff
|
||||||
|
|
||||||
|
return { ...acc, [key]: difference }; // return updated key
|
||||||
|
}, deletedValues);
|
||||||
|
};
|
||||||
|
|
||||||
|
const detailedDiff = (lhs, rhs) => ({
|
||||||
|
added: addedDiff(lhs, rhs),
|
||||||
|
deleted: deletedDiff(lhs, rhs),
|
||||||
|
updated: updatedDiff(lhs, rhs),
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const addedDiff = (lhs, rhs) => {
|
||||||
|
|
||||||
|
if (lhs === rhs || !isObject(lhs) || !isObject(rhs)) return {};
|
||||||
|
|
||||||
|
const l = properObject(lhs);
|
||||||
|
const r = properObject(rhs);
|
||||||
|
|
||||||
|
return Object.keys(r).reduce((acc, key) => {
|
||||||
|
if (l.hasOwnProperty(key)) {
|
||||||
|
const difference = addedDiff(l[key], r[key]);
|
||||||
|
|
||||||
|
if (isObject(difference) && isEmpty(difference)) return acc;
|
||||||
|
|
||||||
|
return { ...acc, [key]: difference };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { ...acc, [key]: r[key] };
|
||||||
|
}, {});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const arrayDiff = (lhs, rhs) => {
|
||||||
|
if (lhs === rhs) return {}; // equal return no diff
|
||||||
|
|
||||||
|
if (!isObject(lhs) || !isObject(rhs)) return rhs; // return updated rhs
|
||||||
|
|
||||||
|
const l = properObject(lhs);
|
||||||
|
const r = properObject(rhs);
|
||||||
|
|
||||||
|
const deletedValues = Object.keys(l).reduce((acc, key) => {
|
||||||
|
return r.hasOwnProperty(key) ? acc : { ...acc, [key]: null };
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
if (isDate(l) || isDate(r)) {
|
||||||
|
if (l.valueOf() == r.valueOf()) return {};
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(r) && Array.isArray(l)) {
|
||||||
|
const deletedValues = l.reduce((acc, item, index) => {
|
||||||
|
return r.hasOwnProperty(index) ? acc.concat(item) : acc.concat(null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return r.reduce((acc, rightItem, index) => {
|
||||||
|
if (!deletedValues.hasOwnProperty(index)) {
|
||||||
|
return acc.concat(rightItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
const leftItem = l[index];
|
||||||
|
const difference = diff(rightItem, leftItem);
|
||||||
|
|
||||||
|
if (isObject(difference) && isEmpty(difference) && !isDate(difference)) {
|
||||||
|
delete acc[index];
|
||||||
|
return acc; // return no diff
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc.slice(0, index).concat(rightItem).concat(acc.slice(index + 1)); // return updated key
|
||||||
|
}, deletedValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.keys(r).reduce((acc, key) => {
|
||||||
|
if (!l.hasOwnProperty(key)) return { ...acc, [key]: r[key] }; // return added r key
|
||||||
|
|
||||||
|
const difference = diff(l[key], r[key]);
|
||||||
|
|
||||||
|
if (isObject(difference) && isEmpty(difference) && !isDate(difference)) return acc; // return no diff
|
||||||
|
|
||||||
|
return { ...acc, [key]: difference }; // return updated key
|
||||||
|
}, deletedValues);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deletedDiff = (lhs, rhs) => {
|
||||||
|
if (lhs === rhs || !isObject(lhs) || !isObject(rhs)) return {};
|
||||||
|
|
||||||
|
const l = properObject(lhs);
|
||||||
|
const r = properObject(rhs);
|
||||||
|
|
||||||
|
return Object.keys(l).reduce((acc, key) => {
|
||||||
|
if (r.hasOwnProperty(key)) {
|
||||||
|
const difference = deletedDiff(l[key], r[key]);
|
||||||
|
|
||||||
|
if (isObject(difference) && isEmpty(difference)) return acc;
|
||||||
|
|
||||||
|
return { ...acc, [key]: difference };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { ...acc, [key]: null };
|
||||||
|
}, {});
|
||||||
|
};
|
||||||
|
|
||||||
|
function mergeRecursive(obj1, obj2) {
|
||||||
|
for (var p in obj2) {
|
||||||
|
try {
|
||||||
|
if(obj2[p].constructor == Object) {
|
||||||
|
obj1[p] = mergeRecursive(obj1[p], obj2[p]);
|
||||||
|
}
|
||||||
|
// Property in destination object set; update its value.
|
||||||
|
else if (Ext.isArray(obj2[p])) {
|
||||||
|
// obj1[p] = [];
|
||||||
|
if (obj2[p].length < 1) {
|
||||||
|
obj1[p] = obj2[p];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obj1[p] = mergeRecursive(obj1[p], obj2[p]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
obj1[p] = obj2[p];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Property in destination object not set; create it and set its value.
|
||||||
|
obj1[p] = obj2[p];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return obj1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
var test = {
|
||||||
|
foo : {
|
||||||
|
bar : {
|
||||||
|
baz : null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
bar : 1
|
||||||
|
};
|
||||||
|
cleanse(test);
|
||||||
|
|
||||||
|
Rohit: Added a small fix for object being entered as Array*/
|
||||||
|
|
||||||
|
function cleanse(obj) {
|
||||||
|
console.log(obj)
|
||||||
|
Object.keys(obj).forEach(function(key) {
|
||||||
|
var value = obj[key];
|
||||||
|
if (typeof value === "object" && value !== null) {
|
||||||
|
// Recurse...
|
||||||
|
cleanse(value);
|
||||||
|
// ...and remove if now "empty" (NOTE: insert your definition of "empty" here)
|
||||||
|
if (!Object.keys(value).length) {
|
||||||
|
delete obj[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (value === null) {
|
||||||
|
// null, remove it
|
||||||
|
delete obj[key];
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(obj.constructor.toString().indexOf("Array") != -1) {obj = obj.filter(function (el) {
|
||||||
|
return el != null;
|
||||||
|
});}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*obj is original object or array, diff is the output of detailedDiff */
|
||||||
|
function mergeAllDiff(obj,diff){
|
||||||
|
if(Object.keys(diff.updated).length !== 0)
|
||||||
|
obj = mergeRecursive(obj,diff.updated)
|
||||||
|
if(Object.keys(diff.deleted).length !== 0){
|
||||||
|
obj = mergeRecursive(obj,diff.deleted)
|
||||||
|
obj = cleanse(obj)
|
||||||
|
}
|
||||||
|
if(Object.keys(diff.added).length !== 0)
|
||||||
|
obj = mergeRecursive(obj,diff.added)
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
floCloudAPI = {
|
||||||
|
//send Any message to supernode cloud storage
|
||||||
|
sendApplicationData: function(message, type, options = {}){
|
||||||
|
return new Promise((resolve,reject) => {
|
||||||
|
var data = {
|
||||||
|
senderID : myFloID,
|
||||||
|
receiverID: options.receiverID || floGlobals.adminID,
|
||||||
|
pubKey : myPubKey,
|
||||||
|
message : message,
|
||||||
|
sign: floCrypto.signData(JSON.stringify(message), myPrivKey),
|
||||||
|
application : options.application || floGlobals.application,
|
||||||
|
type: type,
|
||||||
|
comment: options.comment || ""
|
||||||
|
}
|
||||||
|
floSupernode.sendData(JSON.stringify(data), data.receiverID)
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
//request an object data from supernode cloud
|
||||||
|
requestObjectData: function(objectName, options = {}){
|
||||||
|
var request = {
|
||||||
|
receiverID: options.receiverID || floGlobals.adminID,
|
||||||
|
senderIDs: options.senderIDs || floGlobals.subAdmins,
|
||||||
|
application: options.application || floGlobals.application,
|
||||||
|
type: `${objectName}@Reset`,
|
||||||
|
lowerVectorClock: floGlobals.vectorClock[objectName]+1,
|
||||||
|
mostRecent: true
|
||||||
|
}
|
||||||
|
floSupernode.requestData(JSON.stringify(request),request.receiverID).then(resetData => {
|
||||||
|
reactor.dispatchEvent('resetData', resetData);
|
||||||
|
request.type = `${objectName}@Update`
|
||||||
|
request.lowerVectorClock = floGlobals.vectorClock[objectName]+1
|
||||||
|
request.mostRecent = false
|
||||||
|
floSupernode.requestData(JSON.stringify(request), request.receiverID)
|
||||||
|
.then(updateData => reactor.dispatchEvent('updateData', updateData))
|
||||||
|
}).catch(error => reactor.dispatchEvent('errorHandle', error))
|
||||||
|
},
|
||||||
|
|
||||||
|
//reset or initialize an object and send it to cloud
|
||||||
|
resetObjectData: function(newObject, objectName, options = {}){
|
||||||
|
var message = {
|
||||||
|
division: options.division || floGlobals.division,
|
||||||
|
object: objectName,
|
||||||
|
vectorClock: floGlobals.vectorClock[object],
|
||||||
|
reset: newObject
|
||||||
|
}
|
||||||
|
this.sendApplicationData(message, `${object}@Reset`, options)
|
||||||
|
.then(result => reactor.dispatchEvent('logHandle',result))
|
||||||
|
.catch(error => reactor.dispatchEvent('errorHandle',error))
|
||||||
|
},
|
||||||
|
|
||||||
|
//update the diff and send it to cloud
|
||||||
|
updateObjectData: function(oldObject, newObject, objectName, options = {}){
|
||||||
|
var message = {
|
||||||
|
division: options.division || floGlobals.division,
|
||||||
|
object: objectName,
|
||||||
|
vectorClock: floGlobals.vectorClock[object],
|
||||||
|
diff: detailedDiff(oldObject, newObject)
|
||||||
|
}
|
||||||
|
this.sendApplicationData(message, `${object}@Update`, options)
|
||||||
|
.then(result => reactor.dispatchEvent('logHandle',result))
|
||||||
|
.catch(error => reactor.dispatchEvent('errorHandle',error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reactor.registerEvent('resetData');
|
||||||
|
reactor.addEventListener('resetData', function(dataSet){
|
||||||
|
try{
|
||||||
|
dataSet = JSON.parse(dataSet);
|
||||||
|
console.log(dataSet)
|
||||||
|
for(vc in dataSet){
|
||||||
|
if(floGlobals.subAdmins.includes(dataSet[v].senderID)){
|
||||||
|
var message = dataSet[v].message;
|
||||||
|
if(message.reset){
|
||||||
|
floGlobals.appObjects[message.object] = message.reset
|
||||||
|
floGlobals.vectorClock[message.object] = vc
|
||||||
|
//compactIDB.writeData("appObjects", floGlobals.appObjects[message.object], message.object)
|
||||||
|
//compactIDB.writeData("vectorClocks", vc, message.object)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch(error){
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
reactor.registerEvent('updateData');
|
||||||
|
reactor.addEventListener('updateData', function(dataSet){
|
||||||
|
try{
|
||||||
|
dataSet = JSON.parse(dataSet);
|
||||||
|
console.log(dataSet)
|
||||||
|
for(vc in dataSet){
|
||||||
|
if(floGlobals.subAdmins.includes(dataSet[v].senderID)){
|
||||||
|
var message = dataSet[v].message;
|
||||||
|
if(message.diff){
|
||||||
|
floGlobals.appObjects[message.object] = mergeAllDiff(floGlobals.appObjects[message.object], message.diff)
|
||||||
|
//compactIDB.writeData("objects",floGlobals.appObjects[message.object], message.object)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
floGlobals.vectorClock[message.object] = vc
|
||||||
|
//compactIDB.writeData("vectorClocks", vc, message.object)
|
||||||
|
}
|
||||||
|
}catch(error){
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
reactor.registerEvent('errorHandle');
|
||||||
|
reactor.addEventListener('errorHandle', function(event){
|
||||||
|
console.log(event)
|
||||||
|
});
|
||||||
|
reactor.registerEvent('logHandle');
|
||||||
|
reactor.addEventListener('logHandle', function(event){
|
||||||
|
console.log(event)
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user