Commit 77749537 authored by Romain Courteaud's avatar Romain Courteaud

Update erp5 storage implementation.

parent a8ced060
......@@ -144,6 +144,8 @@ module.exports = function (grunt) {
jio: {
// duplicate files are ignored
src: [
'lib/uri/URI.js',
'node_modules/uritemplate/bin/uritemplate.js',
// 'node_modules/moment/moment.js',
'lib/moment/moment-2.5.0.js',
// 'src/*.js',
......@@ -173,6 +175,7 @@ module.exports = function (grunt) {
'src/jio.storage/davstorage.js',
'src/jio.storage/indexeddbstorage.js',
'src/jio.storage/unionstorage.js',
'src/jio.storage/erp5storage.js',
'src/jio.storage/querystorage.js',
'src/jio.storage/drivetojiomapping.js',
'src/jio.storage/cachestorage.js'
......
......@@ -30,6 +30,7 @@
],
"dependencies": {
"rsvp": "git+http://git.erp5.org/repos/rsvp.js.git",
"uritemplate": "git+http://git.erp5.org/repos/uritemplate-js.git",
"moment": "2.8.3"
},
"devDependencies": {
......
......@@ -10,229 +10,42 @@
// default_view: {string} (optional)
// }
/*jslint indent: 2, nomen: true, unparam: true */
/*global jIO, UriTemplate, FormData, RSVP, URI, DOMParser, Blob,
ProgressEvent, define */
/*jslint nomen: true */
/*global jIO, UriTemplate, FormData, RSVP, URI,
module */
(function (root, dependencies, module) {
(function (jIO, UriTemplate, FormData, RSVP, URI) {
"use strict";
if (typeof define === 'function' && define.amd) {
return define(dependencies, module);
}
var namespace = module(RSVP, jIO, URI, UriTemplate);
if (namespace !== undefined) { root.ERP5Storage = namespace; }
}(this, [
"rsvp",
"jio",
"uri",
"uritemplate"
], function (RSVP, jIO, URI, UriTemplate) {
"use strict";
var hasOwnProperty = Function.prototype.call.bind(
Object.prototype.hasOwnProperty
), constant = {};
constant.method_notification_message_obj = {
"get": "Getting document.",
"post": "Posting document.",
"put": "Putting document.",
"remove": "Removing document.",
"getAttachment": "Getting attachment.",
"putAttachment": "Putting attachment.",
"removeAttacment": "Removing attachment.",
"allDocs": "Getting document list."
};
// XXX docstring
function formatGetSuccessAnswer(answer) {
if (answer === undefined || answer === null) { throw answer; }
var result;
if (typeof answer.data === "object" && answer.data) {
return answer;
}
if (answer.target &&
typeof answer.target.status === "number" &&
typeof answer.target.statusText === "string") {
result = {
"status": answer.target.status
};
if (typeof answer.target.response === "object" &&
answer.target.response !== null) {
if (typeof answer.target.response.toJSON === "function") {
result.data = answer.target.response.toJSON();
} else {
result.data = answer.target.response;
}
} else if (answer.target.response instanceof Blob) {
return jIO.util.readBlobAsText(answer.target.response).
then(function (text) {
result.data = JSON.parse(text);
return result;
});
}
return result;
}
return answer;
}
// XXX docstring
function formatUpdateSuccessAnswer(answer) {
if (answer === undefined || answer === null) { throw answer; }
var result;
if (typeof answer.target === "object" && answer.target !== null &&
typeof answer.target.status === "number") {
result = {
"status": answer.target.status
};
return result;
}
return answer;
}
// XXX docstring
function formatErrorAnswer(answer) {
if (answer === undefined || answer === null) { throw answer; }
var result, dom;
if (answer.target &&
typeof answer.target.status === "number" &&
typeof answer.target.statusText === "string") {
// seams to be a ProgressEvent
result = {
"status": answer.target.status
};
if (typeof answer.target.response === "object" &&
answer.target.response !== null) {
if (typeof answer.target.response.toJSON === "function") {
result.data = answer.target.response.toJSON();
} else {
result.data = answer.target.response;
}
} else if (typeof answer.target.responseText === "string") {
dom = new DOMParser().parseFromString(
answer.target.responseText,
"text/html"
);
result.message = (dom.querySelector('#master') ||
dom.firstElementChild).textContent;
if (!result.message) { delete result.message; }
}
throw result;
}
throw answer;
}
// XXX docstring
function formatNotification(method, notif) {
var result;
if (notif) {
if (typeof notif.loaded === "number" &&
typeof notif.total === "number") {
result = {};
// can be a ProgressEvent or a jIO notification
if (notif.method !== method) {
result = {
"method": method,
"loaded": notif.loaded,
"total": notif.total
};
if (typeof notif.percentage === "number") {
result.percentage = notif.percentage;
}
}
if (typeof notif.message === "string") {
result.message = notif.message;
} else {
result.message = constant.method_notification_message_obj[method];
}
return result;
}
}
throw null; // stop propagation
}
constant.formatSuccessAnswerFor = {
"post": formatUpdateSuccessAnswer,
"put": formatUpdateSuccessAnswer,
"get": formatGetSuccessAnswer
};
//////////////////////////////////////////////////////////////////////
// XXX docstring
function ERP5Storage(spec) {
if (typeof spec.url !== "string" || !spec.url) {
throw new TypeError("ERP5 'url' must be a string " +
"which contains more than one character.");
}
this._url = spec.url;
this._default_view = spec.default_view;
}
// XXX docstring
function methodGenerator(method) {
return function (command, param, options) {
RSVP.resolve().
then(function () {
var view = ERP5Storage.onView[options._view || this._default_view] ||
ERP5Storage.onView["default"];
if (typeof view[method] !== "function") {
view = ERP5Storage.onView["default"];
function getSiteDocument(storage) {
return new RSVP.Queue()
.push(function () {
return jIO.util.ajax({
"type": "GET",
"url": storage._url,
"xhrFields": {
withCredentials: true
}
return view[method].call(this, param, options);
}.bind(this)).
then(constant.formatSuccessAnswerFor[method]).
then(null, formatErrorAnswer, formatNotification.bind(null, method)).
then(command.success, command.error, command.progress);
};
});
})
.push(function (event) {
return JSON.parse(event.target.responseText);
});
}
// XXX docstring
[
"post",
"put",
"get",
"remove",
"putAttachment",
"getAttachment",
"removeAttachment",
"allDocs",
"check",
"repair"
].forEach(function (method) {
ERP5Storage.prototype[method] = methodGenerator(method);
});
// XXX docstring
function getSiteDocument(url) {
if (typeof url !== "string" &&
typeof (this && this._url) !== "string") {
throw new TypeError("ERP5Storage.getSiteDocument(): Argument 1 `url` " +
"or `this._url` are not of type string.");
function getDocumentAndHateoas(storage, param, options) {
if (options === undefined) {
options = {};
}
return jIO.util.ajax({
"type": "GET",
"url": url || this._url,
"xhrFields": {
withCredentials: true
}
}).then(function (event) {
return JSON.parse(event.target.responseText);
});
}
ERP5Storage.getSiteDocument = getSiteDocument;
// XXX docstring
function getDocumentAndHatoas(param, options) {
var this_ = this;
return ERP5Storage.getSiteDocument(this._url).
then(function (site_hal) {
return getSiteDocument(storage)
.push(function (site_hal) {
// XXX need to get modified metadata
return jIO.util.ajax({
"type": "GET",
"url": UriTemplate.parse(site_hal._links.traverse.href)
.expand({
relative_url: param._id,
view: options._view || this_._default_view || "view"
view: options._view || storage._default_view
}),
"xhrFields": {
withCredentials: true
......@@ -241,30 +54,34 @@
});
}
ERP5Storage.onView = {};
ERP5Storage.onView["default"] = {};
// XXX docstring
ERP5Storage.onView["default"].get = function (param, options) {
return getDocumentAndHatoas.call(this, param, options).
then(function (response) {
function ERP5Storage(spec) {
if (typeof spec.url !== "string" || !spec.url) {
throw new TypeError("ERP5 'url' must be a string " +
"which contains more than one character.");
}
this._url = spec.url;
this._default_view = spec.default_view || "view";
}
ERP5Storage.prototype.get = function (param, options) {
return getDocumentAndHateoas(this, param, options)
.push(function (response) {
var result = JSON.parse(response.target.responseText);
result._id = param._id;
result.portal_type = result._links.type.name;
delete result._embedded;
delete result._links;
delete result._debug;
new jIO.Metadata(result).format();
return {"data": result};
// delete result._embedded;
// delete result._links;
// delete result._debug;
return result;
});
};
// XXX docstring
ERP5Storage.onView["default"].post = function (metadata, options) {
var final_response;
return getSiteDocument(this._url)
.then(function (site_hal) {
/*jslint forin: true */
ERP5Storage.prototype.post = function (metadata, options) {
var final_response,
context = this;
return getSiteDocument(this)
.push(function (site_hal) {
var post_action = site_hal._actions.add,
data = new FormData();
......@@ -278,24 +95,26 @@
withCredentials: true
}
});
}).then(function (event) {
final_response = {"status": event.target.status};
})
.push(function (event) {
if (!metadata._id) {
// XXX Really depend on server response...
var uri = new URI(event.target.getResponseHeader("X-Location"));
final_response.id = uri.segment(2);
metadata._id = final_response.id;
final_response = uri.segment(2);
metadata._id = final_response;
}
}).
then(ERP5Storage.onView["default"].put.bind(this, metadata, options)).
then(function () { return final_response; });
})
.push(function () {
return context.put(metadata, options);
})
.push(function () {
return final_response;
});
};
// XXX docstring
ERP5Storage.onView["default"].put = function (metadata, options) {
return getDocumentAndHatoas.call(this, metadata, options).
then(function (result) {
/*jslint forin: true */
ERP5Storage.prototype.put = function (metadata, options) {
return getDocumentAndHateoas(this, metadata, options)
.push(function (result) {
result = JSON.parse(result.target.responseText);
var put_action = result._embedded._view._actions.put,
renderer_form = result._embedded._view,
......@@ -304,10 +123,10 @@
data.append(renderer_form.form_id.key,
renderer_form.form_id['default']);
for (key in metadata) {
if (hasOwnProperty(metadata, key)) {
if (metadata.hasOwnProperty(key)) {
if (key !== "_id") {
// Hardcoded my_ ERP5 behaviour
if (hasOwnProperty(renderer_form, "my_" + key)) {
if (renderer_form.hasOwnProperty("my_" + key)) {
data.append(renderer_form["my_" + key].key, metadata[key]);
}
}
......@@ -324,18 +143,19 @@
});
};
ERP5Storage.onView["default"].remove = function () {
return;
ERP5Storage.prototype.hasCapacity = function (name) {
return ((name === "list") || (name === "query") ||
(name === "select") || (name === "limit"));
};
ERP5Storage.onView["default"].allDocs = function (param, options) {
if (typeof options.query !== "string") {
options.query = (options.query ?
jIO.Query.objectToSearchText(options.query) :
undefined);
}
return getSiteDocument(this._url)
.then(function (site_hal) {
ERP5Storage.prototype.buildQuery = function (options) {
// if (typeof options.query !== "string") {
// options.query = (options.query ?
// jIO.Query.objectToSearchText(options.query) :
// undefined);
// }
return getSiteDocument(this)
.push(function (site_hal) {
return jIO.util.ajax({
"type": "GET",
"url": UriTemplate.parse(site_hal._links.raw_search.href)
......@@ -350,50 +170,30 @@
}
});
})
.then(function (response) {
.push(function (response) {
return JSON.parse(response.target.responseText);
})
.then(function (catalog_json) {
.push(function (catalog_json) {
var data = catalog_json._embedded.contents,
count = data.length,
i,
uri,
item,
result = [],
promise_list = [result];
result = [];
for (i = 0; i < count; i += 1) {
item = data[i];
uri = new URI(item._links.self.href);
delete item._links;
result.push({
id: uri.segment(2),
key: uri.segment(2),
doc: {},
value: item
});
// if (options.include_docs) {
// promise_list.push(RSVP.Queue().push(function () {
// return this._get({_id: item.name}, {_view: "View"});
// }).push
// }
}
return RSVP.all(promise_list);
})
.then(function (promise_list) {
var result = promise_list[0];
return {"data": {"rows": result, "total_rows": result.length}};
return result;
});
};
ERP5Storage.onView["default"].check = function () {
return;
};
ERP5Storage.onView["default"].repair = function () {
return;
};
jIO.addStorage("erp5", ERP5Storage);
return ERP5Storage;
}));
}(jIO, UriTemplate, FormData, RSVP, URI));
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment