erp5_officejs: new storage "configuration"
- new storage layer on top of appcache storage to manage officejs configuration elemnts - the elements listed in ".configuration" app manifest are got from appcache and stored in current app storage as documents - storage cleaner to handle data migration
/*global window, window, rJS, jIO, RSVP, UriTemplate, atob, console */ | /*global window, window, rJS, jIO, RSVP, UriTemplate, console */ | ||
/*jslint indent: 2, maxerr: 10, maxlen: 80 */ | /*jslint indent: 2, maxerr: 10, maxlen: 95 */ | ||
(function (window, rJS, jIO, RSVP, UriTemplate, atob, | (function (window, rJS, jIO, RSVP, UriTemplate, console) { | ||
console) { | |||
"use strict"; | "use strict"; | ||
// jIO call wrapper for redirection to authentication page if needed | // jIO call wrapper for redirection to authentication page if needed | ||
... | @@ -64,44 +63,20 @@ | ... | @@ -64,44 +63,20 @@ |
}); | }); | ||
} | } | ||
function processHateoasDict(raw_dict) { | function safeJioRemove(storage, id) { | ||
var raw_field_list, type, parent, field_key, field_id, return_dict = {}; | return storage.remove(id) | ||
return_dict.raw_dict = raw_dict; | .push(undefined, function (error) { | ||
/*jslint nomen: true*/ | if ((error instanceof jIO.util.jIOError) && | ||
if (raw_dict.hasOwnProperty("_embedded") && | (error.status_code === 404)) { | ||
raw_dict._embedded.hasOwnProperty("_view")) { | return; | ||
raw_field_list = raw_dict._embedded._view; | |||
type = raw_dict._links.type.name; | |||
parent = raw_dict._links.parent.name; | |||
return_dict.parent_relative_url = "portal_types/" + parent; | |||
return_dict.portal_type = type; | |||
for (field_key in raw_field_list) { | |||
if (raw_field_list.hasOwnProperty(field_key)) { | |||
field_id = ""; | |||
if (raw_field_list[field_key]["default"] !== undefined && | |||
raw_field_list[field_key]["default"] !== "") { | |||
if (field_key.startsWith("my_")) { | |||
field_id = field_key.replace("my_", ""); | |||
} else if (field_key.startsWith("your_")) { | |||
field_id = field_key.replace("your_", ""); | |||
} else { | |||
field_id = field_key; | |||
} | |||
return_dict[field_id] = raw_field_list[field_key]["default"]; | |||
} | |||
} | } | ||
} | throw error; | ||
} else { | }); | ||
// ignore non configuration elements | |||
return raw_dict; | |||
} | |||
return return_dict; | |||
} | } | ||
rJS(window) | rJS(window) | ||
.ready(function (gadget) { | .ready(function (gadget) { | ||
// Initialize the gadget local parameters | |||
gadget.state_parameter_dict = {}; | gadget.state_parameter_dict = {}; | ||
}) | }) | ||
... | @@ -111,141 +86,131 @@ | ... | @@ -111,141 +86,131 @@ |
.declareAcquiredMethod("setSetting", "setSetting") | .declareAcquiredMethod("setSetting", "setSetting") | ||
.declareAcquiredMethod('getUrlFor', 'getUrlFor') | .declareAcquiredMethod('getUrlFor', 'getUrlFor') | ||
.declareMethod('clean', function (appcache_storage, origin_url) { | |||
if (!appcache_storage) { return; } | |||
var gadget = this, | |||
document_id_list = [origin_url, | |||
"appcache-stored", | |||
"portal_skins/erp5_text_editor/" + | |||
"Base_cloneDocumentForTextEditor", | |||
"portal_skins/erp5_text_editor/" + | |||
"Base_viewNewContentDialogForTextEditor", | |||
"portal_skins/erp5_text_editor/" + | |||
"WebPageModule_viewWebPageListAsJioForTextEditor", | |||
"portal_skins/erp5_text_editor/" + | |||
"WebPage_viewAsTextDocumentForTextEditor", | |||
"portal_types/Web Page", | |||
"portal_types/Web Page Module", | |||
"portal_types/Web Page Module/text_editor_view", | |||
"portal_types/Web Page/text_editor_clone"], | |||
promise_list = [], | |||
i = 0, | |||
current_version, | |||
index; | |||
current_version = window.location.href.replace(window.location.hash, ""); | |||
index = current_version.indexOf(window.location.host) + window.location.host.length; | |||
current_version = current_version.substr(index); | |||
return gadget.getSetting("migration_version") | |||
.push(function (migration_version) { | |||
if (migration_version !== current_version) { | |||
for (i = 0; i < document_id_list.length; i += 1) { | |||
promise_list = [safeJioRemove(appcache_storage, document_id_list[i])]; | |||
|
|||
} | |||
return RSVP.all(promise_list); | |||
} | |||
}) | |||
.push(function () { | |||
return gadget.setSetting("migration_version", current_version); | |||
}) | |||
.push(function () { | |||
return current_version; | |||
}); | |||
}) | |||
.declareMethod('createJio', function (jio_options) { | .declareMethod('createJio', function (jio_options) { | ||
if (jio_options === undefined) { return; } | |||
var gadget = this, | var gadget = this, | ||
appcache_storage, | appcache_storage, | ||
hateoas_section, | origin_url = window.location.href; | ||
hateoas_section_and_view, | return RSVP.Queue() | ||
origin_url = window.location.href, | .push(function () { | ||
jio_appchache_options = { | return RSVP.all([ | ||
type: "replicate", | gadget.getSetting('configuration_manifest'), | ||
parallel_operation_attachment_amount: 10, | gadget.getSetting('jio_storage_name') | ||
parallel_operation_amount: 1, | ]); | ||
conflict_handling: 2, | }) | ||
signature_hash_key: 'hash', | .push(function (result_list) { | ||
check_remote_attachment_modification: true, | var jio_appchache_options = { | ||
check_remote_attachment_creation: true, | type: "replicate", | ||
check_remote_attachment_deletion: true, | parallel_operation_attachment_amount: 10, | ||
check_remote_deletion: true, | parallel_operation_amount: 1, | ||
check_local_creation: false, | conflict_handling: 2, //keep remote | ||
check_local_deletion: false, | signature_hash_key: 'hash', | ||
check_local_modification: false, | check_remote_attachment_modification: true, | ||
signature_sub_storage: { | check_remote_attachment_creation: true, | ||
type: "query", | check_remote_attachment_deletion: true, | ||
sub_storage: { | check_remote_deletion: true, | ||
type: "memory" | check_local_creation: false, | ||
} | check_local_deletion: false, | ||
}, | check_local_modification: false, | ||
local_sub_storage: {}, | signature_sub_storage: { | ||
remote_sub_storage: { | type: "query", | ||
type: "saferepair", | sub_storage: { | ||
sub_storage: { | type: "indexeddb", | ||
type: "appcache", | database: result_list[1] + "-configuration-hash" | ||
manifest: "" | } | ||
}, | |||
local_sub_storage: JSON.parse(JSON.stringify(jio_options)), | |||
remote_sub_storage: { | |||
type: "saferepair", | |||
sub_storage: { | |||
type: "configuration", | |||
origin_url: origin_url, | |||
hateoas_appcache: "hateoas_appcache", | |||
manifest: result_list[0], | |||
sub_storage: { | |||
type: "appcache", | |||
origin_url: origin_url, | |||
manifest: result_list[0] | |||
} | |||
} | |||
} | } | ||
}; | |||
jio_options = { | |||
type: 'dateupdater', | |||
sub_storage: jio_options, | |||
property_list: ['modification_date'] | |||
}; | |||
try { | |||
gadget.state_parameter_dict.jio_storage = jIO.createJIO(jio_options); | |||
} catch (error) { | |||
gadget.state_parameter_dict.jio_storage = undefined; | |||
} | } | ||
}, | if (result_list[0] === undefined) { return; } | ||
sync_flag = "appcache-stored", | if (result_list[1] === undefined) { return; } | ||
configuration_ids_list = []; | appcache_storage = jIO.createJIO(jio_appchache_options); | ||
if (jio_options === undefined) { | |||
return; | |||
} | |||
jio_appchache_options.local_sub_storage = JSON.parse( | |||
JSON.stringify(jio_options) | |||
); | |||
jio_options = { | |||
type: 'dateupdater', | |||
sub_storage: jio_options, | |||
property_list: ['modification_date'] | |||
}; | |||
try { | |||
this.state_parameter_dict.jio_storage = jIO.createJIO(jio_options); | |||
} catch (error) { | |||
this.state_parameter_dict.jio_storage = undefined; | |||
} | |||
return gadget.getSetting("app_configuration") | |||
.push(function (app_configuration) { | |||
jio_appchache_options.remote_sub_storage.sub_storage.manifest = | |||
app_configuration; | |||
return gadget.getSetting("hateoas_appcache"); | |||
}) | }) | ||
.push(function (hateoas_appcache) { | .push(function () { | ||
hateoas_section = "./" + hateoas_appcache + "/"; | return gadget.clean(appcache_storage, origin_url); | ||
hateoas_section_and_view = hateoas_section + "definition_view/"; | |||
return gadget.getSetting("jio_storage_name"); | |||
}) | }) | ||
.push(function (jio_storage_name) { | .push(function (current_version) { | ||
if (jio_storage_name === undefined) { return; } | if (appcache_storage) { | ||
appcache_storage = jIO.createJIO(jio_appchache_options); | //if the app version has changed, force configuration storage sync | ||
// verify if appcache-local sync needs to be done | return appcache_storage.repair(current_version); | ||
return appcache_storage.get(sync_flag) | } | ||
.push(undefined, function (error) { | }) | ||
if (error && String(error.status_code) !== "404") { | .push(undefined, function (error) { | ||
throw error; | console.log("Error while appcache-local " + | ||
} | "storage synchronization"); | ||
return appcache_storage.repair() | if (error && error.currentTarget && | ||
.push(function () { | error.currentTarget.status === 401) { | ||
return appcache_storage.allAttachments(origin_url) | console.log("Unauthorized access to storage," + | ||
.push(function (attachment_dict) { | "sync cancelled"); | ||
var id, promise_list = [], i = 0; | gadget.state_parameter_dict.jio_storage_name = "ERP5"; | ||
for (id in attachment_dict) { | return; | ||
|
|||
if (attachment_dict.hasOwnProperty(id)) { | } | ||
if (id.startsWith(hateoas_section)) { | console.log(error); | ||
promise_list.push( | throw error; | ||
appcache_storage | |||
.getAttachment(origin_url, id, | |||
{"format": "json"} | |||
) | |||
); | |||
} else { | |||
promise_list.push( | |||
appcache_storage | |||
.getAttachment(origin_url, id) | |||
); | |||
} | |||
configuration_ids_list[i] = id; | |||
i += 1; | |||
} | |||
} | |||
return RSVP.all(promise_list); | |||
}) | |||
.push(function (content_list) { | |||
var i, id, content, promise_list = []; | |||
for (i = 0; i < content_list.length; i += 1) { | |||
id = configuration_ids_list[i]; | |||
if (id.startsWith(hateoas_section)) { | |||
id = id.replace(hateoas_section_and_view, ""); | |||
id = atob(id); | |||
content = processHateoasDict(content_list[i]); | |||
promise_list.push(appcache_storage.put(id, content)); | |||
} | |||
} | |||
return RSVP.all(promise_list); | |||
}) | |||
.push(function () { | |||
return appcache_storage.put(sync_flag, {}) | |||
.push(undefined); | |||
}, function (error) { | |||
console.log("Error while appcache-local " + | |||
"storage synchronization. Bad " + | |||
"configuration maybe?"); | |||
console.log(error); | |||
throw error; | |||
}); | |||
}, function (error) { | |||
console.log("Error while appcache-local " + | |||
"storage synchronization"); | |||
if (error && error.currentTarget && | |||
error.currentTarget.status === 401) { | |||
console.log("Unauthorized access to storage," + | |||
"sync cancelled"); | |||
gadget.state_parameter_dict.jio_storage_name = "ERP5"; | |||
return; | |||
} | |||
console.log(error); | |||
throw error; | |||
}); | |||
}); | |||
}); | }); | ||
}) | }) | ||
.declareMethod('allDocs', function () { | .declareMethod('allDocs', function () { | ||
... | @@ -279,5 +244,4 @@ | ... | @@ -279,5 +244,4 @@ |
return wrapJioCall(this, 'repair', arguments); | return wrapJioCall(this, 'repair', arguments); | ||
}); | }); | ||
}(window, rJS, jIO, RSVP, UriTemplate, atob, | }(window, rJS, jIO, RSVP, UriTemplate, console)); | ||
console)); | \ No newline at end of file | ||
\ No newline at end of file |