Initial restructing of _reestablishInternet() and it’s related functionality.

This commit is contained in:
andygup 2014-01-17 09:12:34 -07:00
parent 5452dc7373
commit 593eb57ec4
5 changed files with 211 additions and 60 deletions

View File

@ -81,6 +81,7 @@ var OfflineStore = function(/* Map */ map) {
INTERNET_STATUS_EVENT: "internetStatusChangeEvent", INTERNET_STATUS_EVENT: "internetStatusChangeEvent",
DELETE_ITEM_EVENT: "deleteItemFromTempStoreEvent", DELETE_ITEM_EVENT: "deleteItemFromTempStoreEvent",
INDEX_UPDATE_EVENT: "indexUpdateEvent", INDEX_UPDATE_EVENT: "indexUpdateEvent",
EDIT_COMPLETE_EVENT: "editCompleteEvent",
REQUIRED_LIBS : [ REQUIRED_LIBS : [
"Hydrate.js", "Hydrate.js",
"OfflineUtils.js", "OfflineUtils.js",
@ -102,6 +103,7 @@ var OfflineStore = function(/* Map */ map) {
this._hydrate = null; this._hydrate = null;
this._reestablishedInternetListener = null; this._reestablishedInternetListener = null;
this._finalArr = null;
////////////////////////// //////////////////////////
/// ///
@ -251,7 +253,7 @@ var OfflineStore = function(/* Map */ map) {
else{ else{
//No need for a callback because this is an online request and it's immediately //No need for a callback because this is an online request and it's immediately
//pushed to Feature Service. //pushed to Feature Service.
this._layerEditManager(graphic,layer,enumValue,this.enum(),function(count,success,id,error){ this._layerEditManager(null,graphic,layer,enumValue,this.enum(),function(count,success,id,error){
console.log("id: " + id + ", success: " + success); console.log("id: " + id + ", success: " + success);
}); });
} }
@ -269,6 +271,7 @@ var OfflineStore = function(/* Map */ map) {
* @private * @private
*/ */
this._layerEditManager = function( this._layerEditManager = function(
/* Number */ count,
/* Graphic */ graphic, /* Graphic */ graphic,
/* FeatureLayer */ layer, /* FeatureLayer */ layer,
/* String */ value, /* String */ value,
@ -284,7 +287,7 @@ var OfflineStore = function(/* Map */ map) {
}.bind(this), }.bind(this),
function(error){ function(error){
console.log("_layer: " + error.lineNumber + " " + error.message); console.log("_layer: " + error.lineNumber + " " + error.message);
mCallback(deleteResult[0].objectId,false,null,error); mCallback(count,deleteResult[0].objectId,false,null,error);
}.bind(this) }.bind(this)
); );
break; break;
@ -297,7 +300,7 @@ var OfflineStore = function(/* Map */ map) {
}.bind(this), }.bind(this),
function(error){ function(error){
console.log("_layer: " + error.lineNumber + " " + error.message); console.log("_layer: " + error.lineNumber + " " + error.message);
mCallback(addResult[0].objectId,false,null,error); mCallback(count,addResult[0].objectId,false,null,error);
}.bind(this) }.bind(this)
); );
break; break;
@ -310,16 +313,43 @@ var OfflineStore = function(/* Map */ map) {
}.bind(this), }.bind(this),
function(error){ function(error){
console.log("_layer: " + error.toString); console.log("_layer: " + error.toString);
mCallback(updateResult[0].objectId,false,null,error) mCallback(count,updateResult[0].objectId,false,null,error)
}.bind(this) }.bind(this)
); );
break; break;
} }
} }
/**
* Internal listeners
* @private
*/
this._setListeners = function(){
document.addEventListener("offlineEditEvent",function(evt){
var message = evt.detail.message;
switch(evt.detail.type){
case "editCompleteEvent":
this._processEditCompleteEvents();
break;
}
},false);
}
this._processEditCompleteEvents = function(){
//
// this._deleteObject = function(){
// this.totalCount = 0;
// this.itemNumber = null;
// this.value = null;
// this.arcgisDeleteError = false;
// this.localStoreDeleteError = false;
// }
console.log("complete!!!!")
}
/** /**
* Initiates adding a graphic to temp local storage. * Initiates adding a graphic to temp local storage.
* Dispatches a pendingEditEvent whereby message = pendingEventObject.
* @param graphic * @param graphic
* @param layer * @param layer
* @param enumValue * @param enumValue
@ -348,7 +378,6 @@ var OfflineStore = function(/* Map */ map) {
callback(0,setItem,0); callback(0,setItem,0);
} }
layer.add(graphic); layer.add(graphic);
// this._dispatchEvent(true,this._localEnum().PENDING_EDIT_EVENT);
} }
this._startOfflineListener = function(){ this._startOfflineListener = function(){
@ -395,41 +424,62 @@ var OfflineStore = function(/* Map */ map) {
/** /**
* Creates a graphics array from localstorage and pushes all applicable edits to a * Creates a graphics array from localstorage and pushes all applicable edits to a
* manager that handles the applyEdits() method. * manager that handles the applyEdits() method.
* @param callback (boolean,enum,graphicsLayerId,objectId) or (false,null,null,null)
* if this.getStore() returns null
* @private * @private
*/ */
this._reestablishedInternet = function(){ this._reestablishedInternet = function(){
var data = localStorage.getItem(this._localEnum().STORAGE_KEY); var data = localStorage.getItem(this._localEnum().STORAGE_KEY);
if(data != null){ if(data != null){
var dataArr = []; this._finalArr = []; //reset the global array
var split = data.split(this._localEnum().TOKEN); var split = data.split(this._localEnum().TOKEN);
for(var property in split){ split = split.filter(function(a){return a}); //remove empty entries
var item = split[property]; var length = split.length;
if(Boolean(item))dataArr.push(item); for(var i = 0; i < length; i++){
if(typeof item !== "undefined" && item.length > 0 && item !== null && item != ""){ var item = split[i];
var graphic = this._deserializeGraphic(item); var graphic = this._deserializeGraphic(item);
var layer = this.getGraphicsLayerById(graphic.layer); var layer = this.getGraphicsLayerById(graphic.layer);
var valueToDelete = item; var deleteObj = new this._deleteObject();
this._layerEditManager(graphic.graphic,layer,graphic.enumValue,this.enum(),function(/* Number */ num, /* boolean */ success, /* String */ id,error){ deleteObj.totalCount = length;
deleteObj.itemNumber = i;
this._layerEditManager(i,graphic.graphic,layer,graphic.enumValue,this.enum(),function(/* Number */ num, /* boolean */ success, /* String */ id,error){
deleteObj.value = item;
//Record details in the index
var date = new Date(); var date = new Date();
var indexObject = new this._indexObject(graphic.layer,id,graphic.enumValue,success,graphic.graphic.geometry.type,date) ; var indexObject = new this._indexObject(graphic.layer,id,graphic.enumValue,success,graphic.graphic.geometry.type,date) ;
this._setItemLocalStoreIndexObject(indexObject); this._setItemLocalStoreIndexObject(indexObject);
if(error == null){
//Delete items from temp local store that have been successfully
//saved to the server or cloud.
this._deleteItemTempLocalStore(item,function(evt){
if(evt == false){
deleteObj.localStoreDeleteError = true;
console.log("_reestablishedInternet: There was a problem deleting an item from temp local store.");
}
else{
console.log("_reestablishedInternet: item deleted from temp local store successfully.");
}
}.bind(this));
}
else{
deleteObj.arcgisDeleteError = true;
}
this._finalArr.push(deleteObj);
var length = this._finalArr.length;
var totalCt = this._finalArr[0].totalCount;
if(length == totalCt){
this._dispatchEvent(null,this._localEnum().EDIT_COMPLETE_EVENT);
}
}.bind(this)); }.bind(this));
} }
} }
var length = dataArr.length;
for(var i=0;i<length;i++){
var deleteTempItem = this._deleteItemTempLocalStore(dataArr[i]);
if(deleteTempItem != true){
console.log("_reestablishedInternet: There was a problem deleting an item from temp local store.");
}
}
}
else{ else{
console.log("_reestablishedInternet: localStorage was empty."); console.log("_reestablishedInternet: localStorage was empty. No pending edits to commit.");
} }
} }
@ -493,6 +543,7 @@ var OfflineStore = function(/* Map */ map) {
} }
} }
else{ else{
duplicateObj.success = false;
duplicateObj.duplicate = true; duplicateObj.duplicate = true;
} }
return duplicateObj; return duplicateObj;
@ -555,31 +606,77 @@ var OfflineStore = function(/* Map */ map) {
* Deletes an item in temporary local store. * Deletes an item in temporary local store.
* @param entry String representing an entire entry contained in the local store * @param entry String representing an entire entry contained in the local store
* @param callback * @param callback
* @returns Boolean returns true if no errors in deleting
* @private * @private
*/ */
this._deleteItemTempLocalStore = function(/* String */ entry,callback){ this._deleteItemTempLocalStore = function(/* String */ entry,callback){
var success = false; var errCnt = 0;
var localStore = localStorage.getItem(this._localEnum().STORAGE_KEY); var successCnt = 0;
var newArr = [];
var localStore = localStorage.getItem(this._localEnum().STORAGE_KEY); console.log("initial: " + localStore)
var length = localStore.length;
if(localStore != null){ if(localStore != null){
var splitStore = localStore.split(this._localEnum().TOKEN); var splitStore = localStore.split(this._localEnum().TOKEN);
var splitLength = splitStore.length;
for(var property in splitStore){ for(var property in splitStore){
var test = splitStore[property]; var test = splitStore[property];
if(typeof test !== "undefined" && test.length > 0 && test != null && Boolean(test) != false){ if(typeof test !== "undefined" && test.length > 0 && test != null && Boolean(test) != false){
// var graphic = this._deserializeGraphic(test); // var graphic = this._deserializeGraphic(test);
if(test == entry){ if(test == entry){
var setItem = "";
splitStore.splice(parseFloat(property),1); splitStore.splice(parseFloat(property),1);
var newArr = this._reserializeGraphicsArray(splitStore); // var test = this._reserializeGraphicsArray(splitStore);
localStorage.removeItem(this._localEnum().STORAGE_KEY); // var firstIndex = localStore.indexOf(test);
var setItem = this._setTempLocalStore(newArr); // var lastIndex = localStore.lastIndexOf(test);
setItem == true ? success = true : success = false; //
// localStorage.removeItem(this._localEnum().STORAGE_KEY);
//
// if(splitLength == 2 && Boolean(splitStore[0]) == false){
// setItem = this._setTempLocalStore("");
// }
// else{
// var firstStr = localStore.substr(0,firstIndex);
// //var secondStr = localStore.substr(firstIndex,lastIndex + 3);
// var finalStr = localStore.substr(lastIndex + 4,length);
// setItem = this._setTempLocalStore(firstStr + finalStr);
// }
//
// //localStore.replace(test,""); console.log("second " + localStore);
//
// //setItem = this._setTempLocalStore(localStore); console.log("third " + localStorage.getItem(this._localEnum().STORAGE_KEY));
// if(setItem == false){
// errCnt++;
// }
// else{
// successCnt++;
// }
break; break;
} }
} }
} }
localStorage.removeItem(this._localEnum().STORAGE_KEY);
var splitStoreLength = splitStore.length;
var stuff = "";
for(var i=0;i<splitStoreLength;i++){
var t = splitStore[i];
if(Boolean(t) == true){
stuff += t + this._localEnum().TOKEN;
}
}
var setItem = this._setTempLocalStore(stuff);
} }
this._dispatchEvent(success,this._localEnum().DELETE_ITEM_EVENT); if(setItem == true){
return success; this._dispatchEvent(true,this._localEnum().DELETE_ITEM_EVENT);
callback(true)
return true;
}
else{
this._dispatchEvent(false,this._localEnum().DELETE_ITEM_EVENT);
callback(false);
return false;
}
} }
/** /**
@ -822,10 +919,29 @@ var OfflineStore = function(/* Map */ map) {
this.date = null; this.date = null;
} }
/**
* Model for transporting information related
* to a pending delete from temp local store.
* @param count
* @param value
* @param arcgisDeleteError
* @param localStorageDeleteError
* @private
*/
this._deleteObject = function(){
this.totalCount = 0;
this.itemNumber = null;
this.value = null;
this.arcgisDeleteError = false;
this.localStoreDeleteError = false;
}
/** /**
* Model for holding temporary local store data that validates * Model for holding temporary local store data that validates
* if an item has been added successfully and whether or not it * if an item has been added successfully and whether or not it
* was a duplicate. * was a duplicate.
* @param success
* @param duplicate
* @private * @private
*/ */
this._duplicateLocalStorageValue = function(){ this._duplicateLocalStorageValue = function(){
@ -976,6 +1092,7 @@ var OfflineStore = function(/* Map */ map) {
this.utils = new OfflineUtils(); this.utils = new OfflineUtils();
this._parseFeatureLayers(this.map); this._parseFeatureLayers(this.map);
this._hydrate = new Hydrate(); this._hydrate = new Hydrate();
this._setListeners();
if(typeof Offline == "object"){ if(typeof Offline == "object"){
this._offlineMonitor(); this._offlineMonitor();
console.log("OfflineStore is ready.") console.log("OfflineStore is ready.")

View File

@ -32,12 +32,12 @@ var OfflineUtils = function(){
* @returns {number} * @returns {number}
*/ */
this.apprxGraphicSize = function(graphic) { this.apprxGraphicSize = function(graphic) {
var g = this._serializeGraphic(graphic); var g = this._serializeGraphicUtil(graphic);
return ((g.length *2)/1024/1024).round(4); return ((g.length *2)/1024/1024).round(4);
} }
this._serializeGraphic = function(/* Graphic */ graphic){ this._serializeGraphicUtil = function(/* Graphic */ graphic){
var json = new this._jsonGraphicsObject(); var json = new this._jsonGraphicsObject();
json.geometry = JSON.stringify(graphic.geometry) json.geometry = JSON.stringify(graphic.geometry)

View File

@ -108,9 +108,9 @@ Sample demonstrates basic offline editing functionality for points, lines and po
</div> </div>
<div id="buttons" data-dojo-type="dijit/layout/ContentPane" > <div id="buttons" data-dojo-type="dijit/layout/ContentPane" >
<button class="btn1" style="background-color: red" onclick="getLocalStorage()">Get localStorage</button> <button class="btn1" style="background-color: red" onclick="getLocalStorage()">Get localStorage</button>
<button class="btn1" style="background-color: red" onclick="offlineStore._deleteTempLocalStore()">Delete localStorage</button> <button class="btn1" style="background-color: red" onclick="offlineStore._deleteTempLocalStore();updatePendingTextArea();">Delete localStorage</button>
<button class="btn1" style="background-color: red" onclick="getIndex()" >Get Index</button> <button class="btn1" style="background-color: red" onclick="getIndex()" >Get Index</button>
<button class="btn1" style="background-color: red" onclick="offlineStore._deleteLocalStoreIndex()" >Delete Index</button> <button class="btn1" style="background-color: red" onclick="offlineStore._deleteLocalStoreIndex();updateHistoryTextArea();" >Delete Index</button>
</div> </div>
</div> </div>
</div> </div>
@ -121,7 +121,6 @@ Sample demonstrates basic offline editing functionality for points, lines and po
var map; var map;
var offlineStore; var offlineStore;
var offlineUtils;
var vertices; var vertices;
var updateFlag = false; var updateFlag = false;
var _logValue = ""; var _logValue = "";
@ -216,7 +215,6 @@ Sample demonstrates basic offline editing functionality for points, lines and po
try{ try{
document.addEventListener("offlineEditEvent",function(evt){ document.addEventListener("offlineEditEvent",function(evt){
offlineUtils = new OfflineUtils();
var message = evt.detail.message; var message = evt.detail.message;
switch(evt.detail.type){ switch(evt.detail.type){
case "internetStatusChangeEvent": case "internetStatusChangeEvent":
@ -233,18 +231,13 @@ Sample demonstrates basic offline editing functionality for points, lines and po
headerDiv.innerHTML = getStorageInfo(); headerDiv.innerHTML = getStorageInfo();
updateHistoryTextArea(); updateHistoryTextArea();
break; break;
case "pendingEditEvent":
if(message != null){
updatePendingTextArea();
}
headerDiv.innerHTML = getStorageInfo();
break;
case "duplicateEditEvent": case "duplicateEditEvent":
alert("Duplicate edit event"); alert("Duplicate edit event");
console.log("duplicate event attempt"); console.log("duplicate event attempt");
break; break;
case "deleteItemFromTempStoreEvent": case "deleteItemFromTempStoreEvent":
updatePendingTextArea(); updatePendingTextArea();
headerDiv.innerHTML = getStorageInfo();
break; break;
} }
},false); },false);

View File

@ -30,6 +30,8 @@
var simplePtGraphic, simplePolygonGraphic, simpleLineGraphic; var simplePtGraphic, simplePolygonGraphic, simpleLineGraphic;
var complexPtGraphic, complexPolygonGraphic, complexLineGraphic; var complexPtGraphic, complexPolygonGraphic, complexLineGraphic;
var updateFlag = false; var updateFlag = false;
var SLS;
var dojoColor;
require([ require([
"esri/map", "esri/map",
@ -37,8 +39,10 @@
"esri/geometry/Polygon", "esri/geometry/Polygon",
"esri/geometry/Polyline", "esri/geometry/Polyline",
"esri/layers/FeatureLayer", "esri/layers/FeatureLayer",
"esri/symbols/SimpleLineSymbol",
"dojo/_base/Color",
"dojo/domReady!"], "dojo/domReady!"],
function(Map,Point,Polygon,Polyline,FeatureLayer) { function(Map,Point,Polygon,Polyline,FeatureLayer,SimpleLineSymbol,Color) {
map = new Map("map", { map = new Map("map", {
basemap: "topo", basemap: "topo",
@ -59,7 +63,8 @@
}) })
map.addLayer(landusePointLayer); map.addLayer(landusePointLayer);
SLS = SimpleLineSymbol;
dojoColor = Color;
}); });
function initGraphics(){ function initGraphics(){
@ -91,14 +96,21 @@
"symbol":{"color":[0,0,0,255],"width":1,"type":"esriSLS","style":"esriSLSSolid"}}; "symbol":{"color":[0,0,0,255],"width":1,"type":"esriSLS","style":"esriSLSSolid"}};
complexLineGraphic = new esri.Graphic(complexLineGeom); complexLineGraphic = new esri.Graphic(complexLineGeom);
var complexPolygonGeom = {"geometry":{"rings":[[[-115.312,37.96875],[-111.4453125,37.96875], // var complexPolygon = new esri.geometry.Polygon(wkid);
// complexPolygon.addRings([[[-115.312,37.96875],[-111.4453125,37.96875],
// [-99.84375,36.2109375],[-99.84375,23.90625],[-116.015625,24.609375],
// [-115.3125,37.96875]]]);
var complexPolygonSymbol = new SLS(SLS.STYLE_DASH,new dojoColor([255,0,0]), 3);
// var complexPolygonAttr = {"Xcoord":evt.mapPoint.x,"Ycoord":evt.mapPoint.y,"Plant":"Mesa Mint"};
var complexPolygonGeom =
{"rings":[[[-115.312,37.96875],[-111.4453125,37.96875],
[-99.84375,36.2109375],[-99.84375,23.90625],[-116.015625,24.609375], [-99.84375,36.2109375],[-99.84375,23.90625],[-116.015625,24.609375],
[-115.3125,37.96875]]],"spatialReference":{"wkid":wkid}}, [-115.3125,37.96875]]],"spatialReference":{"wkid":wkid}};
"symbol":{"color":[0,0,0,64],"outline":{"color":[0,0,0,255], var complexPoly = new esri.geometry.Polygon(complexPolygonGeom)
"width":1,"type":"esriSLS","style":"esriSLSSolid"},
"type":"esriSFS","style":"esriSFSSolid"}};
complexPolygonGraphic = new esri.Graphic(complexPolygonGeom); complexPolygonGraphic = new esri.Graphic(complexPoly);
complexPolygonGraphic.symbol = complexPolygonSymbol;
complexPolygonGraphic.attributes = {"ruleid":2,"name":null,"__hydrate_id":"0"};
var complexPtGeom = {"geometry":{"x":-104.4140625,"y":69.2578125, var complexPtGeom = {"geometry":{"x":-104.4140625,"y":69.2578125,

View File

@ -230,6 +230,34 @@ describe("Validate local storage functionality - delete single Point",function()
}.bind(this)) }.bind(this))
expect(value).toEqual(true); expect(value).toEqual(true);
}) })
it("delete local storage", function(){
var attempt = offlineStore._deleteTempLocalStore();
expect(attempt).toEqual(true);
})
it("re-serialize a graphics array", function(){
jsonFromArr = offlineStore._reserializeGraphicsArray(serializedGraphicsArr);
expect(jsonFromArr).toEqual(jasmine.any(String));
})
it("set re-serialized graphic in local storage", function(){
var setItem = offlineStore._setTempLocalStore(jsonFromArr);
expect(setItem).toEqual(true);
})
it("get re-serialized graphic from local storage", function(){
var data = localStorage.getItem(offlineStore._localEnum().STORAGE_KEY);
expect(data).not.toBeNull();
})
it("delete one graphic from local storage", function(){
var value = null;
offlineStore._deleteItemTempLocalStore(serializedGraphicsArr[0],function(evt){
value = evt;
}.bind(this))
expect(value).toEqual(true);
})
}) })
describe("Validate local storage functionality - complex Point Graphic",function(){ describe("Validate local storage functionality - complex Point Graphic",function(){
@ -491,12 +519,13 @@ describe("Reestablish internet", function(){
it("set item in local storage", function(){ it("set item in local storage", function(){
offlineStore._deleteLocalStoreIndex(); offlineStore._deleteLocalStoreIndex();
offlineStore._deleteTempLocalStore();
var json = offlineStore._serializeGraphic(complexPolygonGraphic,landusePointLayer,offlineStore.enum().ADD); var json = offlineStore._serializeGraphic(complexPolygonGraphic,landusePointLayer,offlineStore.enum().ADD);
var setItem = offlineStore._setTempLocalStore(json); var setItem = offlineStore._setTempLocalStore(json);
expect(setItem).toEqual(true); expect(setItem).toEqual(true);
}) })
it("reestablish internet handler with empty store", function(){ it("reestablish internet handler with one item in temp store", function(){
var validate = null; var validate = null;
offlineStore._reestablishedInternet(); offlineStore._reestablishedInternet();
@ -504,7 +533,7 @@ describe("Reestablish internet", function(){
expect(item).toEqual(null); expect(item).toEqual(null);
}) })
it("get item from local storage using getStore()", function(){ it("verify temp local storage is empty after successful sync with server", function(){
var data = offlineStore.getStore(); var data = offlineStore.getStore();
var type = Object.prototype.toString.call( data ); // === '[object Array]'; var type = Object.prototype.toString.call( data ); // === '[object Array]';
expect(type).toEqual('[object Array]'); expect(type).toEqual('[object Array]');