Commit 6ee093ae authored by Eugene Shen's avatar Eugene Shen

Synchronize text posts across Dropbox and WebDAV

Allow users to configure storage synchronization options during login,
with the choice of ERP5, Dropbox, WebDAV, or no remote storage.
Remove gadget_erp5_chat_login by merging it with the main page.
Use mapping storage and remove peer_source from messages.
parent f5c87f9c
......@@ -11,6 +11,9 @@ img {
max-width: 100%;
max-height: 100%;
}
input[type="text"] {
width: 360px;
}
.chat {
border: 1px solid;
width: 680px;
......
......@@ -6,16 +6,69 @@
<title>OfficeJS Chat</title>
<script src="rsvp.js"></script>
<script src="renderjs.js"></script>
<script src="gadget_global.js" ></script>
<script src="gadget_erp5_chat.js"></script>
<link rel="stylesheet" href="gadget_erp5_chat.css">
<link rel="stylesheet" href="gadget_erp5_chat.css" />
</head>
<body>
<h1>OfficeJS Chat</h1>
<div data-gadget-url="gadget_jio.html"
data-gadget-scope="storage_gadget"
data-gadget-sandbox="public"></div>
<div data-gadget-url="gadget_erp5_chat_login.html"
data-gadget-scope="login_gadget"
data-gadget-sandbox="public"></div>
<form class="login-form">
<label>Name:</label>
<br />
<input type="text" name="name" required="required" />
<br />
<label>Folder:</label>
<br />
<input type="text" name="folder" required="required" />
<br />
<label>Room:</label>
<br />
<input type="text" name="room" required="required" />
<br />
<label>Role:</label>
<br />
<input type="radio" name="role" value="host" required="required" />
<label>Host</label>
<br />
<input type="radio" name="role" value="guest" checked="checked" />
<label>Guest</label>
<br />
<label>Remote Storage:</label>
<br />
<input type="radio" name="remote" value="erp5" required="required" />
<label>ERP5</label>
<br />
<input type="radio" name="remote" value="dav" required="required" />
<label>DAV Storage</label>
<br />
<input type="radio" name="remote" value="dropbox" required="required" />
<label>Dropbox</label>
<br />
<input type="radio" name="remote" value="local" checked="checked" />
<label>Local is Enough</label>
<br />
<a href="https://www.dropbox.com/1/oauth2/authorize?client_id=igeiyv4pkt0y0mm&response_type=token&redirect_uri=https://softinst75770.host.vifib.net/erp5/web_site_module/web_chat/">
Log in to Dropbox first, if you wish to use Dropbox.
</a>
<br />
<label>Fill out ERP5 URL first, if you wish to use ERP5.</label>
<br />
<input type="text" name="erp5_url" value="https://softinst75770.host.vifib.net/erp5/web_site_module/" />
<br />
<label>Enter WebDAV parameters first, if you wish to use DAV.</label>
<br />
<label>URL: </label>
<input type="text" name="dav_url" value="https://softinst75722.host.vifib.net/share" />
<br />
<label>Username: </label>
<input type="text" name="dav_user" value="eyqs" />
<br />
<label>Password: </label>
<input type="text" name="dav_pass" value="Aoeuidhtns" />
<br />
<input type="submit" value="Login!" />
</form>
</body>
</html>
\ No newline at end of file
......@@ -68,6 +68,7 @@
<value>
<tuple>
<string>classification/collaborative/team</string>
<string>contributor/person_module/1</string>
</tuple>
</value>
</item>
......
(function (window, rJS, RSVP) {
(function (window, document, loopEventListener, rJS, RSVP) {
function cleanId(input_id) {
var reserved = ["_", "&", "=", ",", ";"];
for (var i = 0, i_len = reserved.length; i < i_len; i++) {
input_id = input_id.replace(reserved[i], "-");
}
return input_id;
}
function getQueryValue(query, value) {
if (document.URL.indexOf(query + "=") != -1) {
var start = document.URL.indexOf(query + "=") + query.length + 1;
var end = document.URL.indexOf("&", start);
if (end === -1) {
end = document.URL.length;
}
return decodeURIComponent(document.URL.slice(start, end));
} else {
return value || "";
}
}
function login(my_gadget) {
return new RSVP.Queue()
.push(function () {
return my_gadget.declareGadget(
"gadget_erp5_chat_webrtc.html", {scope: "webrtc_gadget"}
);
})
.push(function (webrtc_gadget) {
var form = my_gadget.state_parameter_dict.element
.querySelector(".login-form").elements;
webrtc_gadget.state_parameter_dict.name = cleanId(form.name.value);
webrtc_gadget.state_parameter_dict.folder = cleanId(form.folder.value);
webrtc_gadget.state_parameter_dict.room = cleanId(form.room.value);
webrtc_gadget.state_parameter_dict.role = form.role.value;
webrtc_gadget.state_parameter_dict.remote = form.remote.value;
webrtc_gadget.state_parameter_dict.auth = getQueryValue("auth");
webrtc_gadget.state_parameter_dict.erp5_url = form.erp5_url.value;
webrtc_gadget.state_parameter_dict.dav_url = form.dav_url.value;
webrtc_gadget.state_parameter_dict.dav_user = form.dav_user.value;
webrtc_gadget.state_parameter_dict.dav_pass = form.dav_pass.value;
var element = my_gadget.state_parameter_dict.element;
while (element.firstChild) {
element.removeChild(element.firstChild);
}
element.appendChild(webrtc_gadget.state_parameter_dict.element);
return webrtc_gadget.render();
});
}
rJS(window)
.ready(function (gadget) {
......@@ -6,53 +56,43 @@
return gadget.getElement()
.push(function (element) {
gadget.state_parameter_dict.element = element;
fields = gadget.state_parameter_dict.element
.querySelector(".login-form").elements;
fields.folder.value = getQueryValue("folder");
fields.room.value = getQueryValue("room");
fields.name.value = getQueryValue("name");
fields.erp5_url.value = getQueryValue(
"erp5_url", fields.erp5_url.value);
fields.dav_url.value = getQueryValue(
"dav_url", fields.dav_url.value);
fields.dav_user.value = getQueryValue(
"dav_user", fields.dav_user.value);
fields.dav_pass.value = getQueryValue(
"dav_pass", fields.dav_pass.value);
var role = getQueryValue("role");
if (role === "host" || role === "guest") {
fields.role.value = role;
}
var remote = getQueryValue("remote");
if (remote === "dav" || remote === "dropbox"
|| remote === "erp5" || remote === "local") {
fields.remote.value = remote;
}
if (getQueryValue("submit")) {
return login(gadget);
}
});
})
.ready(function (gadget) {
return new RSVP.Queue()
.push(function () {
return gadget.getDeclaredGadget("storage_gadget");
})
.push(function (my_gadget) {
return my_gadget.createJio({
type: "replicate",
query: {
query: 'portal_type: "Text Post"',
limit: [0, 1000000000]
},
local_sub_storage: {
type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
type: "indexeddb",
database: "officejs_chat"
}
}
},
remote_sub_storage: {
type: "erp5",
url: "https://softinst75770.host.vifib.net/erp5/web_site_module/web_chat/hateoas/",
default_view_reference: "view"
},
conflict_handling: 2,
use_remote_post: true
});
});
})
.declareMethod('render', function () {})
.allowPublicAcquisition('jioApply', function (param_list) {
.declareService(function () {
var gadget = this;
return new RSVP.Queue()
.push(function () {
return gadget.getDeclaredGadget("storage_gadget");
})
.push(function (jio_gadget) {
return jio_gadget[param_list[0]]
.apply(jio_gadget, param_list.slice(1));
});
})
.declareMethod('render', function () {});
return loopEventListener(
gadget.state_parameter_dict.element, "submit", false, function () {
return login(gadget);
}
);
});
}(window, rJS, RSVP));
\ No newline at end of file
}(window, document, loopEventListener, rJS, RSVP));
\ No newline at end of file
......@@ -10,11 +10,9 @@
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
......@@ -24,7 +22,6 @@
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
......@@ -43,8 +40,6 @@
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
......@@ -53,11 +48,9 @@
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
......
......@@ -10,11 +10,9 @@
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
......@@ -24,7 +22,6 @@
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
......@@ -43,8 +40,6 @@
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
......@@ -53,11 +48,9 @@
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
......
......@@ -6,11 +6,17 @@
<title>OfficeJS Chat</title>
<script src="rsvp.js"></script>
<script src="renderjs.js"></script>
<script src="jiodev.js"></script>
<script src="jio_mappingstorage.js"></script>
<script src="gadget_global.js" ></script>
<script src="fast_priority_queue.js"></script>
<script src="gadget_erp5_chat_panel.js"></script>
</head>
<body>
<div data-gadget-url="gadget_jio.html"
data-gadget-scope="storage_gadget"
data-gadget-sandbox="public"></div>
<h3>Chat List</h3>
<p class="error">
</p>
......@@ -20,5 +26,8 @@
<input type="text" name="content" />
<input type="submit" value="Send!" />
</form>
<form class="sync-form">
<input type="submit" value="Synchronize!" />
</form>
</body>
</html>
\ No newline at end of file
......@@ -142,8 +142,95 @@
}
}
function createJio(my_gadget) {
return new RSVP.Queue()
.push(function () {
return my_gadget.getDeclaredGadget("storage_gadget");
})
.push(function (storage_gadget) {
var remote_config = {
type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
type: "indexeddb",
database: "officejs-chat"
}
}
}
var remote_post = true;
// We want the remote ERP5 storage to be canonical, so true for ERP5.
// Post is not implemented in drivetojiomapping, so false for others.
switch (my_gadget.state_parameter_dict.remote) {
case "dropbox":
var start = document.URL.indexOf("access_token=") + 13;
var end = document.URL.indexOf("&", start);
var token = document.URL.slice(start, end);
remote_config = {
type: "query",
sub_storage: {
type: "drivetojiomapping",
sub_storage: {
type: "dropbox",
access_token: token,
root: "dropbox"
}
}
};
remote_post = false;
break;
case "dav":
remote_config = {
type: "query",
sub_storage: {
type: "drivetojiomapping",
sub_storage: {
type: "dav",
url: my_gadget.state_parameter_dict.dav_url,
basic_login: btoa(my_gadget.state_parameter_dict.dav_user
+ ":" + my_gadget.state_parameter_dict.dav_pass),
with_credentials: true
}
}
};
remote_post = false;
break;
case "erp5":
remote_config = {
type: "erp5",
url: (new URI("hateoas"))
.absoluteTo(my_gadget.state_parameter_dict.erp5_url).toString(),
default_view_reference: "view"
};
remote_post = true;
break;
}
return storage_gadget.createJio({
type: "replicate",
use_remote_post: remote_post,
conflict_handling: 2,
query: {
query: 'portal_type: "Text Post"',
limit: [0, 1000000000]
},
local_sub_storage: {
type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
type: "indexeddb",
database: "officejs-chat"
}
}
},
remote_sub_storage: remote_config
});
})
.push(null, logError);
}
// Create new message from its type and content
function createMessage(gadget, type, content, peer_source) {
function createMessage(gadget, type, content) {
return {
type: type,
name: gadget.state_parameter_dict.name,
......@@ -151,7 +238,6 @@
room: gadget.state_parameter_dict.room,
time: new Date(),
content: content,
peer_source: peer_source
}
}
......@@ -290,6 +376,11 @@
name: null,
folder: null,
room: null,
remote: null,
erp5_url: null,
dav_url: null,
dav_user: null,
dav_pass: null,
message_list: [],
guest_amount: 0,
last_message_dict: {},
......@@ -301,9 +392,10 @@
})
.push(function (element) {
gadget.state_parameter_dict.element = element;
});
})
.push(null, logError);
})
// Initialize gadget, after initializing name, folder, and room outside
.declareMethod('render', function () {
var gadget = this;
......@@ -313,11 +405,8 @@
.querySelector("input").onfocus = function () {
return changeFavicon(gadget.state_parameter_dict.default_icon);
};
return createJio(gadget);
})
.push(function () {
return gadget.jioApply('repair');
})
.push(null, logError)
.push(function () {
return gadget.getLocalArchive();
})
......@@ -327,23 +416,26 @@
.push(null, logError);
})
.declareAcquiredMethod('jioApply', 'jioApply')
.declareAcquiredMethod('sendMessage', 'sendMessage')
// Get all messages stored in archive and add them to the list in order,
// using storeList because the messages are already in the archive
.declareMethod('getLocalArchive', function () {
console.log('get local');
var gadget = this;
var storage_gadget;
return new RSVP.Queue()
.push(function () {
return gadget.jioApply('allDocs');
return gadget.getDeclaredGadget("storage_gadget");
})
.push(function (jio_gadget) {
storage_gadget = jio_gadget;
return storage_gadget.allDocs();
})
.push(function (document_list) {
var list = document_list.data.rows;
var promise_list = [];
for (var i = 0, i_len = list.length; i < i_len; i++) {
promise_list.push(gadget.jioApply('get', list[i].id));
promise_list.push(storage_gadget.get(list[i].id));
}
return RSVP.all(promise_list);
})
......@@ -372,13 +464,14 @@
}
}
gadget.state_parameter_dict.initialized = true;
console.log("Received local archive. Number of messages: " +
gadget.state_parameter_dict.message_list.length);
})
.push(null, logError);
})
// Send all requested messages in the list, in sorted order, to peer
.declareMethod('sendLocalArchive', function (request) {
console.log('send archive');
.declareMethod('sendLocalArchive', function (request, source) {
var gadget = this;
var request_list = [];
var list = gadget.state_parameter_dict.message_list;
......@@ -388,9 +481,11 @@
request_list.push(list[i]);
}
}
console.log(request_list);
console.log("Sent local archive. Number of messages sent: "
+ request_list.length + " of "
+ gadget.state_parameter_dict.message_list.length);
return logQueue(gadget.sendMessage(createMessage(
gadget, "bundle", request_list, request.peer_source)));
gadget, "bundle", request_list), source));
})
// Get all new messages from the sorted list of peer,
......@@ -398,7 +493,8 @@
// and refresh, dedupe, and resort the list using refreshChat
.declareMethod('getRemoteArchive', function (bundle) {
var gadget = this;
console.log('get archive');
console.log("Received remote archive. Number of messages received: " +
bundle.content.length);
return new RSVP.Queue()
.push(function () {
var list = gadget.state_parameter_dict.message_list;
......@@ -459,31 +555,36 @@
var gadget = this;
var id = message.folder + "_" + message.room + "_"
+ message.name + "_" + getTime(message).toString();
return logQueue(gadget.jioApply('put', id, {
portal_type: "Text Post",
parent_relative_url: "post_text_module",
reference: id, // XXX use uuid here
author: message.name,
date_ms: getTime(message),
content: JSON.stringify(message)
}));
return new RSVP.Queue()
.push(function () {
return gadget.getDeclaredGadget("storage_gadget");
})
.push(function (storage_gadget) {
return logQueue(storage_gadget.put(id, {
portal_type: "Text Post",
parent_relative_url: "post_text_module",
reference: id, // XXX use uuid here
author: message.name,
date_ms: getTime(message),
content: JSON.stringify(message)
}));
});
})
// Ask a peer to send over a request
.declareMethod('requestRequest', function () {
console.log('send doubler');
var gadget = this;
console.log("Sent request for a request.");
return logQueue(gadget.sendMessage(createMessage(gadget, "doubler", "")));
})
// Send a request to update the local archive
.declareMethod('sendRequest', function () {
console.log('send request');
var gadget = this;
return pollUntilNotNull(gadget, 1000, 30000, function () {
return gadget.state_parameter_dict.initialized;
}, function () {
console.log(JSON.stringify(gadget.state_parameter_dict.last_message_dict));
console.log("Sent request for messages.");
return gadget.sendMessage(createMessage(
gadget, "request", gadget.state_parameter_dict.last_message_dict));
});
......@@ -502,6 +603,21 @@
} else {
return gadget.deployMessage("message", content);
}
case "sync-form":
return new RSVP.Queue()
.push(function () {
return gadget.getDeclaredGadget("storage_gadget");
})
.push(function (storage_gadget) {
return storage_gadget.repair();
})
.push(function () {
return gadget.getLocalArchive();
})
.push(function () {
return gadget.requestRequest();
})
.push(null, logError);
}
}
return loopEventListener(
......
......@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>OfficeJS Chat WebRTC</title>
<title>>WebRTC Gadget</title>
<script src="rsvp.js"></script>
<script src="renderjs.js"></script>
<script src="adapter.js"></script>
......@@ -11,6 +11,8 @@
<script src="gadget_erp5_chat_webrtc.js"></script>
</head>
<body>
<h1>OfficeJS Chat</h1>
<p class="timeout-alert">
</p>
......
......@@ -195,7 +195,7 @@
erp5_gadget = jio_gadget;
return erp5_gadget.createJio({
type: "erp5",
url: url,
url: (new URI("hateoas")).absoluteTo(url).toString(),
default_view_reference: "view"
});
})
......@@ -231,8 +231,8 @@
function resetErp5Content(erp5_gadget, param_dict) {
var folder = param_dict.folder;
var url = param_dict.url;
return logQueue(erp5_gadget.putAttachment(folder,
url + "WebrtcRoom_resetContent",
return logQueue(erp5_gadget.putAttachment(
"/", url + "WebrtcRoom_resetContent",
new Blob([JSON.stringify({folder: folder})])));
}
......@@ -244,7 +244,7 @@
var action = param_dict.action;
return new RSVP.Queue()
.push(function () {
return erp5_gadget.putAttachment(folder, url + action,
return erp5_gadget.putAttachment("/", url + action,
new Blob([JSON.stringify({folder: folder, room: room, name: name})]));
})
.push(function (response) {
......@@ -265,8 +265,9 @@
var folder = param_dict.folder;
var name = param_dict.name;
var url = param_dict.url;
return logQueue(erp5_gadget.putAttachment(folder,
url + "WebrtcRoom_putContent", new Blob([JSON.stringify(
return logQueue(erp5_gadget.putAttachment(
"/", url + "WebrtcRoom_putContent",
new Blob([JSON.stringify(
{folder: folder, name: name, content: content})])));
}
......@@ -274,12 +275,14 @@
var folder = param_dict.folder;
var name = param_dict.name;
var url = param_dict.url;
return logQueue(erp5_gadget.putAttachment(folder,
url + "WebrtcRoom_deleteContent",
return logQueue(erp5_gadget.putAttachment(
"/", url + "WebrtcRoom_deleteContent",
new Blob([JSON.stringify({folder: folder, name: name})])));
}
function authenticateErp5(my_gadget) {
var erp5_folder_url =
"https://softinst75770.host.vifib.net/erp5/webrtc_rooms_module/";
return new RSVP.Queue()
.push(function () {
return createErp5Jio(
......@@ -289,21 +292,20 @@
.push(function (folder_id) {
var lastIndex = folder_id.indexOf("/") + 1;
my_gadget.state_parameter_dict.erp5_folder = folder_id.slice(lastIndex);
my_gadget.state_parameter_dict.erp5_url =
my_gadget.state_parameter_dict.erp5_url + "webrtc_rooms_module/"
+ my_gadget.state_parameter_dict.erp5_folder + "/";
erp5_folder_url += my_gadget.state_parameter_dict.erp5_folder + "/";
return my_gadget.getDeclaredGadget("erp5_gadget");
})
.push(function (erp5_gadget) {
return resetErp5Content(erp5_gadget, {
folder: my_gadget.state_parameter_dict.erp5_folder,
url: my_gadget.state_parameter_dict.erp5_url
url: erp5_folder_url
});
})
.push(function () {
var erp5_params = [
my_gadget, "erp5_gadget",
my_gadget.state_parameter_dict.erp5_folder, {
erp5_folder_url: erp5_folder_url,
resetContent: resetErp5Content,
getOffer: function (erp5_gadget, param_dict) {
param_dict.action = "WebrtcRoom_getOffer";
......@@ -330,7 +332,7 @@
my_gadget, jio_gadget_name, folder, jio_function_dict) {
var room = my_gadget.state_parameter_dict.room;
var name;
var url = my_gadget.state_parameter_dict.erp5_url;
var url = jio_function_dict.erp5_folder_url;
var jio_gadget;
return new RSVP.Queue()
.push(function () {
......@@ -400,7 +402,7 @@
my_gadget, jio_gadget_name, folder, jio_function_dict) {
var room = my_gadget.state_parameter_dict.room;
var name;
var url = my_gadget.state_parameter_dict.erp5_url;
var url = jio_function_dict.erp5_folder_url;
var jio_gadget;
return new RSVP.Queue()
.push(function () {
......@@ -517,7 +519,8 @@
window.location.reload();
}
}
console.log("connected guests: " + my_gadget.state_parameter_dict.guest_amount);
console.log("A guest is now " + peer_connection.iceConnectionState +
". Number of guests: " + my_gadget.state_parameter_dict.guest_amount);
};
}
}
......@@ -544,6 +547,16 @@
my_gadget.state_parameter_dict.folder;
chat_gadget.state_parameter_dict.room =
my_gadget.state_parameter_dict.room;
chat_gadget.state_parameter_dict.remote =
my_gadget.state_parameter_dict.remote;
chat_gadget.state_parameter_dict.erp5_url =
my_gadget.state_parameter_dict.erp5_url;
chat_gadget.state_parameter_dict.dav_url =
my_gadget.state_parameter_dict.dav_url;
chat_gadget.state_parameter_dict.dav_user =
my_gadget.state_parameter_dict.dav_user;
chat_gadget.state_parameter_dict.dav_pass =
my_gadget.state_parameter_dict.dav_pass;
my_gadget.state_parameter_dict.element.appendChild(
chat_gadget.state_parameter_dict.element);
return chat_gadget.render();
......@@ -568,9 +581,9 @@
}
data_channel.onmessage = function (my_event) {
var message = JSON.parse(my_event.data);
var source = my_event.srcElement;
return new RSVP.Queue()
.push(function () {
message.peer_source = my_event.srcElement;
return my_gadget.getDeclaredGadget("chat_gadget");
})
.push(function (chat_gadget) {
......@@ -581,7 +594,7 @@
})
.push(function () {
if (my_gadget.state_parameter_dict.role === "host") {
return my_gadget.sendMessage(message);
return my_gadget.sendMessage(message, source);
} else if (my_gadget.state_parameter_dict.role === "guest") {
return;
}
......@@ -590,8 +603,9 @@
} else if (message.type === "bundle") {
if (my_gadget.state_parameter_dict.role === "host") {
my_gadget.state_parameter_dict.archive_amount += 1;
console.log("guest amount: " + my_gadget.state_parameter_dict.guest_amount);
console.log("archive amount: " + my_gadget.state_parameter_dict.archive_amount);
console.log("Received archive number: " +
my_gadget.state_parameter_dict.archive_amount +
" of " + my_gadget.state_parameter_dict.guest_amount);
if (my_gadget.state_parameter_dict.archive_amount >=
my_gadget.state_parameter_dict.guest_amount) {
my_gadget.state_parameter_dict.archive_amount = 0;
......@@ -609,10 +623,10 @@
return chat_gadget.getRemoteArchive(message);
}
} else if (message.type === "request") {
console.log("get request");
return chat_gadget.sendLocalArchive(message);
console.log("Received request for messages.");
return chat_gadget.sendLocalArchive(message, source);
} else if (message.type === "doubler") {
console.log("get doubler");
console.log("Received request for a request.");
return chat_gadget.sendRequest();
}
})
......@@ -660,6 +674,7 @@
folder: null,
room: null,
role: null,
remote: null,
candidate: null,
connected: false,
offer_ready: false,
......@@ -669,8 +684,10 @@
archive_amount: 0,
// full path including user folder, e.g. "/Apps/OfficeJS Chat/nexedi/"
dropbox_folder: "/Apps/OfficeJS Chat",
erp5_url: "https://softinst75770.host.vifib.net/erp5/"
+ "web_site_module/web_chat/hateoas/",
erp5_url: null,
dav_url: null,
dav_user: null,
dav_pass: null,
erp5_folder: null,
ice_config: {
iceServers: [{url: "stun:stun.1.google.com:19302"}]
......@@ -704,9 +721,8 @@
return gadget.sendMessage.apply(gadget, param_dict);
})
.declareMethod('sendMessage', function (message) {
.declareMethod('sendMessage', function (message, source) {
var gadget = this;
var source = message.peer_source;
var message_string = JSON.stringify(message);
var channel_list = gadget.state_parameter_dict.data_channel_list;
return new RSVP.Queue()
......@@ -758,6 +774,13 @@
}
return createInitialOffer(gadget);
})
.push(function () {
if (gadget.state_parameter_dict.auth === "dropbox") {
return authenticateDropbox(gadget);
} else if (gadget.state_parameter_dict.auth === "erp5") {
return authenticateErp5(gadget);
}
})
.push(null, logError);
})
......
/*jslint indent:2, maxlen: 80, nomen: true */
/*global jIO, RSVP, UriTemplate, SimpleQuery, ComplexQuery, QueryFactory,
Query*/
(function (jIO, RSVP, UriTemplate, SimpleQuery, ComplexQuery, QueryFactory,
Query) {
"use strict";
function getSubIdEqualSubProperty(storage, value, key) {
var query;
if (storage._no_sub_query_id) {
throw new jIO.util.jIOError('no sub query id active', 404);
}
query = new SimpleQuery({
key: key,
value: value,
type: "simple"
});
if (storage._query.query !== undefined) {
query = new ComplexQuery({
operator: "AND",
query_list: [query, storage._query.query],
type: "complex"
});
}
query = Query.objectToSearchText(query);
return storage._sub_storage.allDocs({
"query": query,
"sort_on": storage._query.sort_on,
"select_list": storage._query.select_list,
"limit": storage._query.limit
})
.push(function (data) {
if (data.data.rows.length === 0) {
throw new jIO.util.jIOError(
"Can not find id",
404
);
}
if (data.data.rows.length > 1) {
throw new TypeError("id must be unique field: " + key
+ ", result:" + data.data.rows.toString());
}
return data.data.rows[0].id;
});
}
/*jslint unparam: true*/
var mapping_function = {
"equalSubProperty": {
"mapToSubProperty": function (property, sub_doc, doc, args, id) {
sub_doc[args] = doc[property];
return args;
},
"mapToMainProperty": function (property, sub_doc, doc, args, sub_id) {
if (sub_doc.hasOwnProperty(args)) {
doc[property] = sub_doc[args];
}
return args;
},
"mapToSubId": function (storage, doc, id, args) {
if (doc !== undefined) {
if (storage._property_for_sub_id &&
doc.hasOwnProperty(storage._property_for_sub_id)) {
return doc[storage._property_for_sub_id];
}
if (doc.hasOwnProperty(args)) {
return doc[args];
}
}
return getSubIdEqualSubProperty(storage, id, storage._map_id[1]);
},
"mapToId": function (storage, sub_doc, sub_id, args) {
return sub_doc[args];
}
},
"equalValue": {
"mapToSubProperty": function (property, sub_doc, doc, args) {
sub_doc[property] = args;
return property;
},
"mapToMainProperty": function (property) {
return property;
}
},
"ignore": {
"mapToSubProperty": function () {
return false;
},
"mapToMainProperty": function (property) {
return property;
}
},
"equalSubId": {
"mapToSubProperty": function (property, sub_doc, doc) {
sub_doc[property] = doc[property];
return property;
},
"mapToMainProperty": function (property, sub_doc, doc, args, sub_id) {
if (sub_id === undefined && sub_doc.hasOwnProperty(property)) {
doc[property] = sub_doc[property];
} else {
doc[property] = sub_id;
}
return property;
},
"mapToSubId": function (storage, doc, id, args) {
return id;
},
"mapToId": function (storage, sub_doc, sub_id) {
return sub_id;
}
},
"keep": {
"mapToSubProperty": function (property, sub_doc, doc) {
sub_doc[property] = doc[property];
return property;
},
"mapToMainProperty": function (property, sub_doc, doc) {
doc[property] = sub_doc[property];
return property;
}
},
"switchPropertyValue": {
"mapToSubProperty": function (property, sub_doc, doc, args) {
sub_doc[args[0]] = args[1][doc[property]];
return args[0];
},
"mapToMainProperty": function (property, sub_doc, doc, args) {
var subvalue, value = sub_doc[args[0]];
for (subvalue in args[1]) {
if (args[1].hasOwnProperty(subvalue)) {
if (value === args[1][subvalue]) {
doc[property] = subvalue;
return property;
}
}
}
}
}
};
/*jslint unparam: false*/
function initializeQueryAndDefaultMapping(storage) {
var property, query_list = [];
for (property in storage._mapping_dict) {
if (storage._mapping_dict.hasOwnProperty(property)) {
if (storage._mapping_dict[property][0] === "equalValue") {
if (storage._mapping_dict[property][1] === undefined) {
throw new jIO.util.jIOError("equalValue has not parameter", 400);
}
storage._default_mapping[property] =
storage._mapping_dict[property][1];
query_list.push(new SimpleQuery({
key: property,
value: storage._mapping_dict[property][1],
type: "simple"
}));
}
if (storage._mapping_dict[property][0] === "equalSubId") {
if (storage._property_for_sub_id !== undefined) {
throw new jIO.util.jIOError(
"equalSubId can be defined one time",
400
);
}
storage._property_for_sub_id = property;
}
}
}
if (storage._query.query !== undefined) {
query_list.push(QueryFactory.create(storage._query.query));
}
if (query_list.length > 1) {
storage._query.query = new ComplexQuery({
type: "complex",
query_list: query_list,
operator: "AND"
});
} else if (query_list.length === 1) {
storage._query.query = query_list[0];
}
}
function MappingStorage(spec) {
this._mapping_dict = spec.property || {};
this._sub_storage = jIO.createJIO(spec.sub_storage);
this._map_all_property = spec.map_all_property !== undefined ?
spec.map_all_property : true;
this._no_sub_query_id = spec.no_sub_query_id;
this._attachment_mapping_dict = spec.attachment || {};
this._query = spec.query || {};
this._map_id = spec.id || ["equalSubId"];
this._id_mapped = (spec.id !== undefined) ? spec.id[1] : false;
if (this._query.query !== undefined) {
this._query.query = QueryFactory.create(this._query.query);
}
this._default_mapping = {};
initializeQueryAndDefaultMapping(this);
}
function getAttachmentId(storage, sub_id, attachment_id, method) {
var mapping_dict = storage._attachment_mapping_dict;
if (mapping_dict !== undefined
&& mapping_dict[attachment_id] !== undefined
&& mapping_dict[attachment_id][method] !== undefined
&& mapping_dict[attachment_id][method].uri_template !== undefined) {
return UriTemplate.parse(
mapping_dict[attachment_id][method].uri_template
).expand({id: sub_id});
}
return attachment_id;
}
function getSubStorageId(storage, id, doc) {
return new RSVP.Queue()
.push(function () {
var map_info = storage._map_id || ["equalSubId"];
if (storage._property_for_sub_id && doc !== undefined &&
doc.hasOwnProperty(storage._property_for_sub_id)) {
return doc[storage._property_for_sub_id];
}
return mapping_function[map_info[0]].mapToSubId(
storage,
doc,
id,
map_info[1]
);
});
}
function mapToSubProperty(storage, property, sub_doc, doc, id) {
var mapping_info = storage._mapping_dict[property] || ["keep"];
return mapping_function[mapping_info[0]].mapToSubProperty(
property,
sub_doc,
doc,
mapping_info[1],
id
);
}
function mapToMainProperty(storage, property, sub_doc, doc, sub_id) {
var mapping_info = storage._mapping_dict[property] || ["keep"];
return mapping_function[mapping_info[0]].mapToMainProperty(
property,
sub_doc,
doc,
mapping_info[1],
sub_id
);
}
function mapToMainDocument(storage, sub_doc, sub_id) {
var doc = {},
property,
property_list = [storage._id_mapped];
for (property in storage._mapping_dict) {
if (storage._mapping_dict.hasOwnProperty(property)) {
property_list.push(mapToMainProperty(
storage,
property,
sub_doc,
doc,
sub_id
));
}
}
if (storage._map_all_property) {
for (property in sub_doc) {
if (sub_doc.hasOwnProperty(property)) {
if (property_list.indexOf(property) < 0) {
doc[property] = sub_doc[property];
}
}
}
}
if (storage._map_for_sub_storage_id !== undefined) {
doc[storage._map_for_sub_storage_id] = sub_id;
}
return doc;
}
function mapToSubstorageDocument(storage, doc, id) {
var sub_doc = {}, property;
for (property in doc) {
if (doc.hasOwnProperty(property)) {
mapToSubProperty(storage, property, sub_doc, doc, id);
}
}
for (property in storage._default_mapping) {
if (storage._default_mapping.hasOwnProperty(property)) {
sub_doc[property] = storage._default_mapping[property];
}
}
if (storage._map_id[0] === "equalSubProperty" && id !== undefined) {
sub_doc[storage._map_id[1]] = id;
}
return sub_doc;
}
function handleAttachment(storage, argument_list, method) {
return getSubStorageId(storage, argument_list[0])
.push(function (sub_id) {
argument_list[0] = sub_id;
argument_list[1] = getAttachmentId(
storage,
sub_id,
argument_list[1],
method
);
return storage._sub_storage[method + "Attachment"].apply(
storage._sub_storage,
argument_list
);
});
}
MappingStorage.prototype.get = function (id) {
var storage = this;
return getSubStorageId(this, id)
.push(function (sub_id) {
return storage._sub_storage.get(sub_id)
.push(function (sub_doc) {
return mapToMainDocument(storage, sub_doc, sub_id);
});
});
};
MappingStorage.prototype.post = function (doc) {
var sub_doc = mapToSubstorageDocument(
this,
doc
),
id = doc[this._property_for_sub_id];
if (this._property_for_sub_id && id !== undefined) {
return this._sub_storage.put(id, sub_doc);
}
if (!this._id_mapped || doc[this._id_mapped] !== undefined) {
return this._sub_storage.post(sub_doc);
}
throw new jIO.util.jIOError(
"post is not supported with id mapped",
400
);
};
MappingStorage.prototype.put = function (id, doc) {
var storage = this,
sub_doc = mapToSubstorageDocument(this, doc, id);
return getSubStorageId(this, id, doc)
.push(function (sub_id) {
return storage._sub_storage.put(sub_id, sub_doc);
})
.push(undefined, function (error) {
if (error instanceof jIO.util.jIOError && error.status_code === 404) {
return storage._sub_storage.post(sub_doc);
}
throw error;
})
.push(function () {
return id;
});
};
MappingStorage.prototype.remove = function (id) {
var storage = this;
return getSubStorageId(this, id)
.push(function (sub_id) {
return storage._sub_storage.remove(sub_id);
})
.push(function () {
return id;
});
};
MappingStorage.prototype.putAttachment = function (id, attachment_id) {
return handleAttachment(this, arguments, "put", id)
.push(function () {
return attachment_id;
});
};
MappingStorage.prototype.getAttachment = function () {
return handleAttachment(this, arguments, "get");
};
MappingStorage.prototype.removeAttachment = function (id, attachment_id) {
return handleAttachment(this, arguments, "remove", id)
.push(function () {
return attachment_id;
});
};
MappingStorage.prototype.allAttachments = function (id) {
var storage = this, sub_id;
return getSubStorageId(storage, id)
.push(function (sub_id_result) {
sub_id = sub_id_result;
return storage._sub_storage.allAttachments(sub_id);
})
.push(function (result) {
var attachment_id,
attachments = {},
mapping_dict = {};
for (attachment_id in storage._attachment_mapping_dict) {
if (storage._attachment_mapping_dict.hasOwnProperty(attachment_id)) {
mapping_dict[getAttachmentId(storage, sub_id, attachment_id, "get")]
= attachment_id;
}
}
for (attachment_id in result) {
if (result.hasOwnProperty(attachment_id)) {
if (mapping_dict.hasOwnProperty(attachment_id)) {
attachments[mapping_dict[attachment_id]] = {};
} else {
attachments[attachment_id] = {};
}
}
}
return attachments;
});
};
MappingStorage.prototype.hasCapacity = function (name) {
return this._sub_storage.hasCapacity(name);
};
MappingStorage.prototype.repair = function () {
return this._sub_storage.repair.apply(this._sub_storage, arguments);
};
MappingStorage.prototype.bulk = function (id_list) {
var storage = this;
function mapId(parameter) {
return getSubStorageId(storage, parameter.parameter_list[0])
.push(function (id) {
return {"method": parameter.method, "parameter_list": [id]};
});
}
return new RSVP.Queue()
.push(function () {
var promise_list = id_list.map(mapId);
return RSVP.all(promise_list);
})
.push(function (id_list_mapped) {
return storage._sub_storage.bulk(id_list_mapped);
})
.push(function (result) {
var mapped_result = [], i;
for (i = 0; i < result.length; i += 1) {
mapped_result.push(mapToMainDocument(
storage,
result[i]
));
}
return mapped_result;
});
};
MappingStorage.prototype.buildQuery = function (option) {
var storage = this,
i,
query,
property,
select_list = [],
sort_on = [];
function mapQuery(one_query) {
var j, query_list = [], key, sub_query;
if (one_query.type === "complex") {
for (j = 0; j < one_query.query_list.length; j += 1) {
sub_query = mapQuery(one_query.query_list[j]);
if (sub_query) {
query_list.push(sub_query);
}
}
one_query.query_list = query_list;
return one_query;
}
key = mapToMainProperty(storage, one_query.key, {}, {});
if (key) {
one_query.key = key;
return one_query;
}
return false;
}
if (option.sort_on !== undefined) {
for (i = 0; i < option.sort_on.length; i += 1) {
property = mapToMainProperty(this, option.sort_on[i][0], {}, {});
if (property && sort_on.indexOf(property) < 0) {
sort_on.push([property, option.sort_on[i][1]]);
}
}
}
if (this._query.sort_on !== undefined) {
for (i = 0; i < this._query.sort_on.length; i += 1) {
property = mapToMainProperty(this, this._query.sort_on[i], {}, {});
if (sort_on.indexOf(property) < 0) {
sort_on.push([property, option.sort_on[i][1]]);
}
}
}
if (option.select_list !== undefined) {
for (i = 0; i < option.select_list.length; i += 1) {
property = mapToMainProperty(this, option.select_list[i], {}, {});
if (property && select_list.indexOf(property) < 0) {
select_list.push(property);
}
}
}
if (this._query.select_list !== undefined) {
for (i = 0; i < this._query.select_list; i += 1) {
property = this._query.select_list[i];
if (select_list.indexOf(property) < 0) {
select_list.push(property);
}
}
}
if (this._id_mapped) {
// modify here for future way to map id
select_list.push(this._id_mapped);
}
if (option.query !== undefined) {
query = mapQuery(QueryFactory.create(option.query));
}
if (this._query.query !== undefined) {
if (query === undefined) {
query = this._query.query;
}
query = new ComplexQuery({
operator: "AND",
query_list: [query, this._query.query],
type: "complex"
});
}
if (query !== undefined) {
query = Query.objectToSearchText(query);
}
return this._sub_storage.allDocs(
{
query: query,
select_list: select_list,
sort_on: sort_on,
limit: option.limit
}
)
.push(function (result) {
var sub_doc, map_info = storage._map_id || ["equalSubId"];
for (i = 0; i < result.data.total_rows; i += 1) {
sub_doc = result.data.rows[i].value;
result.data.rows[i].id =
mapping_function[map_info[0]].mapToId(
storage,
sub_doc,
result.data.rows[i].id,
map_info[1]
);
result.data.rows[i].value =
mapToMainDocument(
storage,
sub_doc
);
}
return result.data.rows;
});
};
jIO.addStorage('mapping', MappingStorage);
}(jIO, RSVP, UriTemplate, SimpleQuery, ComplexQuery, QueryFactory, Query));
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Web Script" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Change_local_roles_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>classification/collaborative/team</string>
<string>contributor/person_module/1</string>
</tuple>
</value>
</item>
<item>
<key> <string>content_md5</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>jio_mappingstorage.js</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>jio_mappingstorage_js</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value> <string>en</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Web Script</string> </value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>JIO Mapping Storage JS</string> </value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>001</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
web_page_module/adapter_js
web_page_module/fast_priority_queue_js
web_page_module/gadget_erp5_chat*
web_page_module/jio_mappingstorage_js
web_site_module/web_chat/**
\ No newline at end of file
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