Commit 78ee15d4 authored by Eugene Shen's avatar Eugene Shen

Store contact information in ERP5 Persons

Store a jio_configuration string in ERP5 Persons to share contact info,
remove the entire concept of folders and replace it with rooms instead,
use emails to find contacts, replace ERP5 Python Scripts with pure jIO,
move query helpers to gadget_global and force names to be alphanumeric.
parent b9917283
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
<form class="login-form"> <form class="login-form">
<label>Name:</label> <label>Name:</label>
<input type="text" name="name" required="required" /> <input type="text" name="name" required="required" />
<label>Folder:</label>
<input type="text" name="folder" required="required" />
<h3>Remote Storage</h3> <h3>Remote Storage</h3>
<label> <label>
...@@ -44,7 +42,7 @@ ...@@ -44,7 +42,7 @@
<h3>Storage Configuration</h3> <h3>Storage Configuration</h3>
<a class="dropbox-link">Dropbox OAuth</a> <a class="dropbox-link">Dropbox OAuth</a>
<label>Dropbox folder:</label> <label>Dropbox folder:</label>
<input type="text" name="remote_dropbox_url" placeholder="/Apps/OfficeJS Chat/.jio_documents" /> <input type="text" name="remote_dropbox_folder" placeholder="/Apps/OfficeJS Chat/.jio_documents/" />
<label>ERP5 URL:</label> <label>ERP5 URL:</label>
<input type="text" name="remote_erp5_url" placeholder="https://softinst75770.host.vifib.net/erp5/web_site_module/" /> <input type="text" name="remote_erp5_url" placeholder="https://softinst75770.host.vifib.net/erp5/web_site_module/" />
<label>WebDAV URL:</label> <label>WebDAV URL:</label>
...@@ -58,11 +56,9 @@ ...@@ -58,11 +56,9 @@
<label>Default storage:</label> <label>Default storage:</label>
<input type="text" name="auth" placeholder="dropbox" /> <input type="text" name="auth" placeholder="dropbox" />
<label>Dropbox folder:</label> <label>Dropbox folder:</label>
<input type="text" name="auth_dropbox_url" placeholder="/Apps/OfficeJS Chat" /> <input type="text" name="auth_dropbox_folder" placeholder="/Apps/OfficeJS Chat/" />
<label>ERP5 URL:</label> <label>ERP5 URL:</label>
<input type="text" name="auth_erp5_url" placeholder="https://softinst75770.host.vifib.net/erp5/webrtc_rooms_module/" /> <input type="text" name="auth_erp5_url" placeholder="https://softinst75770.host.vifib.net/erp5/webrtc_rooms_module/" />
<label>ERP5 Hateoas:</label>
<input type="text" name="auth_hateoas_url", placeholder="https://softinst75770.host.vifib.net/erp5/web_site_module/hateoas" />
<br /> <br />
<input type="submit" name="login" value="Login!" /> <input type="submit" name="login" value="Login!" />
</form> </form>
......
...@@ -2,12 +2,10 @@ ...@@ -2,12 +2,10 @@
/* URL Options: /* URL Options:
* name: your chat username, e.g. eyqs * name: your chat username, e.g. eyqs
* folder: the root folder for your organization, e.g. nexedi;
* you can only chat with people with access to the same auth folder
* remote: the type of remote storage to use, * remote: the type of remote storage to use,
* either dav, dropbox, erp5, or local * either dav, dropbox, erp5, or local
* remote_dropbox_url: the remote Dropbox folder to synchronize with, * remote_dropbox_folder: the remote Dropbox folder to synchronize with,
* e.g. /Apps/OfficeJS Chat/.jio_documents * e.g. /Apps/OfficeJS Chat/.jio_documents/
* remote_erp5_url: the remote ERP5 instance to synchronize with, * remote_erp5_url: the remote ERP5 instance to synchronize with,
* e.g. https://softinst75770.host.vifib.net/erp5/web_site_module/ * e.g. https://softinst75770.host.vifib.net/erp5/web_site_module/
* remote_dav_url: the remote WebDAV server to synchronize with, * remote_dav_url: the remote WebDAV server to synchronize with,
...@@ -16,52 +14,20 @@ ...@@ -16,52 +14,20 @@
* remote_dav_pass: your WebDAV password, e.g. correct horse battery staple * remote_dav_pass: your WebDAV password, e.g. correct horse battery staple
* auth: the default type of authentication to use for WebRTC rooms, * auth: the default type of authentication to use for WebRTC rooms,
* either dropbox or erp5 * either dropbox or erp5
* auth_dropbox_url: the shared Dropbox folder to act as your auth folder, * auth_dropbox_folder: the shared Dropbox folder for WebRTC negotiations,
* e.g. /Apps/OfficeJS Chat * e.g. /Apps/OfficeJS Chat/
* auth_erp5_url: the shared ERP5 instance to act as your auth folder, * auth_erp5_url: the shared ERP5 instance to store WebRTC negotiations,
* e.g. https://softinst75770.host.vifib.net/erp5/webrtc_rooms_module/ * e.g. https://softinst75770.host.vifib.net/erp5/web_site_module/
*/ */
function cleanId(input_id) {
const reserved = ["_", "&", "=", ",", ";", "\\"];
for (let i = 0, i_len = reserved.length; i < i_len; i++) {
input_id = input_id.replace(reserved[i], "-");
}
return input_id;
}
function getQueryValue(query_list, query_string) {
for (let i = 0, i_len = query_list.length; i < i_len; i++) {
const query = query_list[i];
if (query_string.indexOf(query + "=") !== -1) {
const start = query_string.indexOf(query + "=") + query.length + 1;
let end = query_string.indexOf("&", start);
if (end === -1) {
end = query_string.length;
}
return query_string.slice(start, end);
}
}
return null;
}
function setQueryValue(query_list, query_string, element) {
value = getQueryValue(query_list, query_string);
if (value) {
element.value = value;
}
}
rJS(window) rJS(window)
.ready(function (gadget) { .ready(function (gadget) {
gadget.state_parameter_dict = { gadget.state_parameter_dict = {
element: null, element: null,
name: null, name: null,
folder: null,
auth: null, auth: null,
dropbox_url: null, dropbox_folder: null,
erp5_url: null, erp5_url: null,
hateoas_url: null,
// Dropbox OAuth only allows 500 characters in the state query // Dropbox OAuth only allows 500 characters in the state query
max_state_length: 500, max_state_length: 500,
}; };
...@@ -105,6 +71,38 @@ ...@@ -105,6 +71,38 @@
.push(null, logError); .push(null, logError);
}) })
.allowPublicAcquisition('getContactByEmail', function (param_list) {
const gadget = this;
const email = param_list[0];
let storage_gadget;
return new RSVP.Queue()
.push(function () {
return gadget.getDeclaredGadget("storage_gadget");
})
.push(function (jio_gadget) {
storage_gadget = jio_gadget;
return storage_gadget.allDocs({
limit: [0, 1000000],
query: 'portal_type: "Person"',
sort_on: [["last_modified", "descending"]],
select_list: ["default_email_coordinate_text", "jio_configuration"],
});
})
.push(function (person_list) {
if (person_list.data.rows.length) {
for (let i = 0, i_len = person_list.data.rows.length;
i < i_len; i++) {
if (person_list.data.rows[i].value
.default_email_coordinate_text === email) {
return person_list.data.rows[i].id;
}
}
}
return person_list.data.rows.length.toString();
})
.push(null, logError);
})
.allowPublicAcquisition('chooseRoom', function (param_list) { .allowPublicAcquisition('chooseRoom', function (param_list) {
const gadget = this; const gadget = this;
const param_dict = param_list[0]; const param_dict = param_list[0];
...@@ -122,12 +120,10 @@ ...@@ -122,12 +120,10 @@
.push(function (chat_gadget) { .push(function (chat_gadget) {
const fields = webrtc_gadget.state_parameter_dict.element const fields = webrtc_gadget.state_parameter_dict.element
.querySelector(".contact-form").elements; .querySelector(".contact-form").elements;
fields.dropbox_url.value = param_dict.dropbox_url fields.dropbox_folder.value = param_dict.dropbox_folder
|| gadget.state_parameter_dict.dropbox_url; || gadget.state_parameter_dict.dropbox_folder;
fields.erp5_url.value = param_dict.erp5_url fields.erp5_url.value = param_dict.erp5_url
|| gadget.state_parameter_dict.erp5_url; || gadget.state_parameter_dict.erp5_url;
fields.hateoas_url.value = param_dict.hateoas_url
|| gadget.state_parameter_dict.hateoas_url;
webrtc_gadget.state_parameter_dict.element.querySelector(".auth-form") webrtc_gadget.state_parameter_dict.element.querySelector(".auth-form")
.auth.value = param_dict.auth || gadget.state_parameter_dict.auth; .auth.value = param_dict.auth || gadget.state_parameter_dict.auth;
chat_gadget.state_parameter_dict.element chat_gadget.state_parameter_dict.element
...@@ -136,7 +132,6 @@ ...@@ -136,7 +132,6 @@
chat_gadget.state_parameter_dict.element chat_gadget.state_parameter_dict.element
.querySelector(".chat-right-panel-chat")); .querySelector(".chat-right-panel-chat"));
webrtc_gadget.state_parameter_dict.login_dict = { webrtc_gadget.state_parameter_dict.login_dict = {
folder: gadget.state_parameter_dict.folder,
room: param_dict.room, room: param_dict.room,
name: gadget.state_parameter_dict.name, name: gadget.state_parameter_dict.name,
role: param_dict.role, role: param_dict.role,
...@@ -192,10 +187,10 @@ ...@@ -192,10 +187,10 @@
}) })
.declareMethod('render', function () { .declareMethod('render', function () {
let url = decodeURIComponent(document.URL);
const gadget = this; const gadget = this;
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
let url = decodeURIComponent(document.URL);
const state_output = getQueryValue(["state"], url); const state_output = getQueryValue(["state"], url);
if (state_output) { if (state_output) {
url += window.atob(state_output); url += window.atob(state_output);
...@@ -204,12 +199,11 @@ ...@@ -204,12 +199,11 @@
.querySelector(".login-form").elements; .querySelector(".login-form").elements;
let state_input = ""; let state_input = "";
// A list of login-form fields and short keys in order of priority // A list of login-form fields and short keys in order of priority
const query_list = [["name", "m"], ["folder", "f"], ["remote", "r"], const query_list = [["name", "m"], ["remote", "r"],
["remote_dropbox_url", "rd"], ["remote_erp5_url", "re"], ["remote_dropbox_folder", "rd"], ["remote_erp5_url", "re"],
["remote_dav_url", "rv"], ["remote_dav_user", "rvu"], ["remote_dav_url", "rv"], ["remote_dav_user", "rvu"],
["remote_dav_pass", "rvp"], ["auth", "a"], ["remote_dav_pass", "rvp"], ["auth", "a"],
["auth_dropbox_url", "ad"], ["auth_erp5_url", "ae"], ["auth_dropbox_folder", "ad"], ["auth_erp5_url", "ae"]]
["auth_hateoas_url", "ah"]]
for (let i = 0, i_len = query_list.length; i < i_len; i++) { for (let i = 0, i_len = query_list.length; i < i_len; i++) {
const query = query_list[i]; const query = query_list[i];
setQueryValue(query, url, fields[query[0]]); setQueryValue(query, url, fields[query[0]]);
...@@ -246,27 +240,28 @@ ...@@ -246,27 +240,28 @@
const fields = gadget.state_parameter_dict.element const fields = gadget.state_parameter_dict.element
.querySelector(".login-form").elements; .querySelector(".login-form").elements;
gadget.state_parameter_dict.auth = fields.auth.value; gadget.state_parameter_dict.auth = fields.auth.value;
gadget.state_parameter_dict.dropbox_url = gadget.state_parameter_dict.dropbox_folder =
fields.auth_dropbox_url.value; fields.auth_dropbox_folder.value;
gadget.state_parameter_dict.erp5_url = fields.auth_erp5_url.value; gadget.state_parameter_dict.erp5_url = fields.auth_erp5_url.value;
gadget.state_parameter_dict.hateoas_url = gadget.state_parameter_dict.name =
fields.auth_hateoas_url.value; fields.name.value.replace(/[^0-9a-z]/gi, '');
gadget.state_parameter_dict.name = cleanId(fields.name.value);
gadget.state_parameter_dict.folder = cleanId(fields.folder.value);
chat_gadget.state_parameter_dict.name = chat_gadget.state_parameter_dict.name =
gadget.state_parameter_dict.name; gadget.state_parameter_dict.name;
chat_gadget.state_parameter_dict.folder =
gadget.state_parameter_dict.folder;
// XXX apply drivetojiomapping in custom dropbox_url directory
return gadget.createJio({ return gadget.createJio({
remote: fields.remote.value, remote: fields.remote.value,
dropbox_url: fields.remote_dropbox_url.value, dropbox_folder: fields.remote_dropbox_folder.value,
erp5_url: fields.remote_erp5_url.value, erp5_url: fields.remote_erp5_url.value,
dav_url: fields.remote_dav_url.value, dav_url: fields.remote_dav_url.value,
dav_user: fields.remote_dav_user.value, dav_user: fields.remote_dav_user.value,
dav_pass: fields.remote_dav_pass.value, dav_pass: fields.remote_dav_pass.value,
}); });
}) })
.push(function () {
return gadget.getDeclaredGadget("storage_gadget");
})
.push(function (storage_gadget) {
return storage_gadget.repair();
})
.push(function () { .push(function () {
return chat_gadget.render(); return chat_gadget.render();
}) })
...@@ -346,8 +341,8 @@ ...@@ -346,8 +341,8 @@
use_remote_post: remote_post, use_remote_post: remote_post,
conflict_handling: 2, conflict_handling: 2,
query: { query: {
query: 'portal_type: "Text Post"',
limit: [0, 1000000000], limit: [0, 1000000000],
query: 'portal_type: "Person" OR portal_type: "Text Post"',
}, },
local_sub_storage: { local_sub_storage: {
type: "query", type: "query",
......
...@@ -54,8 +54,8 @@ ...@@ -54,8 +54,8 @@
} }
function isSameMessage(lhs, rhs) { function isSameMessage(lhs, rhs) {
return lhs !== undefined && rhs !== undefined && lhs.name === rhs.name return lhs !== undefined && rhs !== undefined
&& lhs.content === rhs.content && lhs.folder === rhs.folder && lhs.name === rhs.name && lhs.content === rhs.content
&& lhs.room === rhs.room && getTime(lhs) === getTime(rhs); && lhs.room === rhs.room && getTime(lhs) === getTime(rhs);
} }
...@@ -144,15 +144,13 @@ ...@@ -144,15 +144,13 @@
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
gadget.state_parameter_dict = { gadget.state_parameter_dict = {
folder: null,
room: null, room: null,
name: null, name: null,
element: null, element: null,
initialized: false, initialized: false,
// A set of names of rooms joined within this folder; // A set of names of current rooms; as a guest, only notify that
// as a guest, only notify that you have joined once // you have joined once you have received the host's remote archive,
// you have received the host's remote archive, so that // so that your notification doesn't override all previous messages
// your notification doesn't override all previous messages
// room_set["room"] = false if joined, true if also notified // room_set["room"] = false if joined, true if also notified
room_set: {}, room_set: {},
// A dictionary of messages based on the current room, e.g. // A dictionary of messages based on the current room, e.g.
...@@ -183,12 +181,12 @@ ...@@ -183,12 +181,12 @@
const gadget = this; const gadget = this;
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
gadget.state_parameter_dict.room = gadget.state_parameter_dict.name;
gadget.state_parameter_dict.element gadget.state_parameter_dict.element
.querySelector(".send-form input").onfocus = function () { .querySelector(".send-form input").onfocus = function () {
return logQueue( return logQueue(
gadget.notifyStatus(gadget.state_parameter_dict.room, false)); gadget.notifyStatus(gadget.state_parameter_dict.room, false));
}; };
gadget.state_parameter_dict.room = gadget.state_parameter_dict.name;
}) })
.push(null, logError); .push(null, logError);
}) })
...@@ -199,32 +197,31 @@ ...@@ -199,32 +197,31 @@
const gadget = this; const gadget = this;
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
return gadget.wrapJioAccess('allDocs'); return gadget.wrapJioAccess('allDocs', {
}) limit: [0, 1000000],
.push(function (document_list) { query: 'portal_type: "Text Post"',
const list = document_list.data.rows; sort_on: [["last_modified", "descending"]],
const promise_list = []; select_list: ["content"],
for (let i = 0, i_len = list.length; i < i_len; i++) { });
promise_list.push(gadget.wrapJioAccess('get', list[i].id));
}
return RSVP.all(promise_list);
}) })
.push(function (message_list) { .push(function (message_list) {
const message_queue = new FastPriorityQueue(messageTimeCompare(true)); const message_queue = new FastPriorityQueue(messageTimeCompare(true));
for (let i = 0, i_len = message_list.length; i < i_len; i++) { if (message_list.data.rows.length) {
for (let i = 0, i_len = message_list.data.rows.length;
i < i_len; i++) {
try { try {
const message = JSON.parse(message_list[i].content); const message = JSON.parse(list[i]);
if (message && typeof message === "object") { if (message && typeof message === "object") {
message_queue.add(message); message_queue.add(message);
} }
} catch (error) {} } catch (error) {}
} }
}
const promise_list = []; const promise_list = [];
const message_dict = gadget.state_parameter_dict.last_message_dict; const message_dict = gadget.state_parameter_dict.last_message_dict;
while (!message_queue.isEmpty()) { while (!message_queue.isEmpty()) {
const message = message_queue.poll(); const message = message_queue.poll();
if (message.folder === gadget.state_parameter_dict.folder if (message.room in gadget.state_parameter_dict.room_set) {
&& (message.room in gadget.state_parameter_dict.room_set)) {
promise_list.push(gadget.storeList(message)); promise_list.push(gadget.storeList(message));
promise_list.push(gadget.appendMessage(message)); promise_list.push(gadget.appendMessage(message));
} }
...@@ -346,7 +343,6 @@ ...@@ -346,7 +343,6 @@
return { return {
type: param_dict.type || "message", type: param_dict.type || "message",
name: param_dict.name || gadget.state_parameter_dict.name, name: param_dict.name || gadget.state_parameter_dict.name,
folder: param_dict.folder || gadget.state_parameter_dict.folder,
room: param_dict.room || gadget.state_parameter_dict.room, room: param_dict.room || gadget.state_parameter_dict.room,
time: param_dict.time || new Date(), time: param_dict.time || new Date(),
content: param_dict.content || "", content: param_dict.content || "",
...@@ -421,20 +417,16 @@ ...@@ -421,20 +417,16 @@
// Store message in the archive // Store message in the archive
.declareMethod('storeArchive', function (message) { .declareMethod('storeArchive', function (message) {
const gadget = this; const gadget = this;
return new RSVP.Queue() const id = message.room + "_" + message.name + "_"
.push(function () { + getTime(message).toString();
const id = message.folder + "_" + message.room + "_" return logQueue(gadget.wrapJioAccess('put', id, {
+ message.name + "_" + getTime(message).toString();
return gadget.wrapJioAccess('put', id, {
portal_type: "Text Post", portal_type: "Text Post",
parent_relative_url: "post_text_module", parent_relative_url: "post_text_module",
reference: id, reference: id,
author: message.name, author: message.name,
date_ms: getTime(message), date_ms: getTime(message),
content: JSON.stringify(message), content: JSON.stringify(message),
}); }));
})
.push(null, logError);
}) })
// Add message to the list // Add message to the list
...@@ -514,7 +506,7 @@ ...@@ -514,7 +506,7 @@
class_name = "notify"; class_name = "notify";
} else { } else {
favicon_url = gadget.state_parameter_dict.default_icon; favicon_url = gadget.state_parameter_dict.default_icon;
class_name = ""; class_name = "current";
} }
const link = document.querySelector("link[rel*='icon']") const link = document.querySelector("link[rel*='icon']")
|| document.createElement("link"); || document.createElement("link");
...@@ -524,16 +516,12 @@ ...@@ -524,16 +516,12 @@
document.head.appendChild(link); document.head.appendChild(link);
const contact = gadget.state_parameter_dict.element const contact = gadget.state_parameter_dict.element
.querySelector("#chat-contact-" + room); .querySelector("#chat-contact-" + room);
if (contact.className === "current") {
contact.className = class_name || "current";
} else {
contact.className = class_name; contact.className = class_name;
}
}) })
.push(null, logError); .push(null, logError);
}) })
// Join a different room in the same folder // Join a different room
.declareMethod('changeRoom', function (room) { .declareMethod('changeRoom', function (room) {
const gadget = this; const gadget = this;
return new RSVP.Queue() return new RSVP.Queue()
...@@ -570,7 +558,6 @@ ...@@ -570,7 +558,6 @@
.declareMethod('createContact', function (param_dict) { .declareMethod('createContact', function (param_dict) {
const gadget = this; const gadget = this;
return new RSVP.Queue() return new RSVP.Queue()
// XXX: load params here too
.push(function () { .push(function () {
return gadget.appendContact(param_dict.room); return gadget.appendContact(param_dict.room);
}) })
...@@ -736,9 +723,7 @@ ...@@ -736,9 +723,7 @@
return gadget.createContact({room: contact, role: "guest"}); return gadget.createContact({room: contact, role: "guest"});
case "make-form": case "make-form":
const room = resetInputValue(event.target.elements.content); const room = resetInputValue(event.target.elements.content);
return gadget.createContact({room: room, role: "host"}); return gadget.chooseRoom({room: room, role: "host"});
case "auth-form":
return gadget.connectContact();
case "send-form": case "send-form":
const content = resetInputValue(event.target.elements.content); const content = resetInputValue(event.target.elements.content);
if (content.indexOf("/") === 0) { if (content.indexOf("/") === 0) {
......
...@@ -15,20 +15,20 @@ ...@@ -15,20 +15,20 @@
<p class="status"></p> <p class="status"></p>
<form class="contact-form"> <form class="contact-form">
<label>Name:</label> <label>E-mail Address:</label>
<input type="text" name="name" /> <input type="text" name="email" />
<label>Folder:</label>
<input type="text" name="folder" />
<label>Dropbox folder:</label> <label>Dropbox folder:</label>
<input type="text" name="dropbox_url" placeholder="/Apps/OfficeJS Chat" /> <input type="text" name="dropbox_folder" placeholder="/Apps/OfficeJS Chat/" />
<label>ERP5 URL:</label> <label>ERP5 URL:</label>
<input type="text" name="erp5_url" placeholder="https://softinst75770.host.vifib.net/erp5/webrtc_rooms_module/" /> <input type="text" name="erp5_url" placeholder="https://softinst75770.host.vifib.net/erp5/web_site_module/" />
<label>Hateoas URL:</label>
<input type="text" name="hateoas_url" placeholder="https://softinst75770.host.vifib.net/erp5/web_site_module/hateoas" />
<br /> <br />
<input type="submit" value="Update information!" /> <input type="submit" value="Update information!" />
</form> </form>
<form class="download-form">
<input type="submit" value="Download information from remote storage!" />
</form>
<form class="auth-form"> <form class="auth-form">
<label> <label>
<input type="radio" name="auth" value="erp5" required="required" /> <input type="radio" name="auth" value="erp5" required="required" />
......
(function (window, document, rJS, RSVP) { (function (window, document, rJS, RSVP) {
function webrtcError(gadget, error_string) {
return new RSVP.Queue()
.push(function () {
gadget.state_parameter_dict.element.querySelector(".error")
.textContent = error_string;
})
.push(function () {
return RSVP.delay(10000);
})
.push(function () {
return error_string;
});
}
// jIO utility functions // jIO utility functions
function createDropboxJio(gadget, folder) { function createDropboxJio(gadget, param_dict) {
let dropbox_gadget; let dropbox_gadget;
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
...@@ -21,10 +35,7 @@ ...@@ -21,10 +35,7 @@
}); });
}) })
.push(function () { .push(function () {
return dropbox_gadget.put(folder, {}); return dropbox_gadget.put(param_dict.dropbox_folder, {});
})
.push(null, function () {
return resetDropboxContent(dropbox_gadget, {folder: folder});
}) })
.push(null, logError); .push(null, logError);
} }
...@@ -32,28 +43,31 @@ ...@@ -32,28 +43,31 @@
function resetDropboxContent(dropbox_gadget, param_dict) { function resetDropboxContent(dropbox_gadget, param_dict) {
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
return dropbox_gadget.allAttachments(param_dict.folder); return dropbox_gadget.allAttachments(param_dict.dropbox_folder);
}) })
.push(function (attachment_list) { .push(function (negotiation_list) {
const promise_list = []; const promise_list = [];
for (let file_name in attachment_list) { for (let file_name in negotiation_list) {
if (attachment_list.hasOwnProperty(file_name)) { if (negotiation_list.hasOwnProperty(file_name)
&& (file_name.indexOf("offer_" + param_dict.room + "_") === 0
|| file_name.indexOf("answer_" + param_dict.room + "_") === 0)) {
promise_list.push(dropbox_gadget promise_list.push(dropbox_gadget
.removeAttachment(param_dict.folder, file_name)); .removeAttachment(param_dict.dropbox_folder, file_name));
} }
} }
return RSVP.all(promise_list); return RSVP.all(promise_list);
}); })
.push(null, logError);
} }
function getDropboxOffer(dropbox_gadget, param_dict) { function getDropboxOffer(dropbox_gadget, param_dict) {
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
return dropbox_gadget.allAttachments(param_dict.folder); return dropbox_gadget.allAttachments(param_dict.dropbox_folder);
}) })
.push(function (attachment_list) { .push(function (negotiation_list) {
for (let file_name in attachment_list) { for (let file_name in negotiation_list) {
if (attachment_list.hasOwnProperty(file_name) if (negotiation_list.hasOwnProperty(file_name)
&& file_name.indexOf("offer_" + param_dict.room + "_") === 0) { && file_name.indexOf("offer_" + param_dict.room + "_") === 0) {
return file_name.slice(6); return file_name.slice(6);
} }
...@@ -67,7 +81,7 @@ ...@@ -67,7 +81,7 @@
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
return dropbox_gadget.getAttachment( return dropbox_gadget.getAttachment(
param_dict.folder, param_dict.file_name); param_dict.dropbox_folder, param_dict.file_name);
}) })
.push(function (attachment) { .push(function (attachment) {
return promiseReadAsText(attachment); return promiseReadAsText(attachment);
...@@ -79,37 +93,24 @@ ...@@ -79,37 +93,24 @@
function putDropboxContent(dropbox_gadget, param_dict) { function putDropboxContent(dropbox_gadget, param_dict) {
return logQueue(dropbox_gadget.putAttachment( return logQueue(dropbox_gadget.putAttachment(
param_dict.folder, param_dict.file_name, param_dict.dropbox_folder, param_dict.file_name,
new Blob([param_dict.content], {type: "text"}))); new Blob([param_dict.content], {type: "text"})));
} }
function removeDropboxContent(dropbox_gadget, param_dict) { function removeDropboxContent(dropbox_gadget, param_dict) {
return logQueue(dropbox_gadget return logQueue(dropbox_gadget.removeAttachment(
.removeAttachment(param_dict.folder, param_dict.file_name)); param_dict.dropbox_folder, param_dict.file_name));
} }
function authenticateDropbox(gadget) { function authenticateDropbox(gadget) {
if (document.URL.indexOf("access_token=") === -1) {
gadget.state_parameter_dict.element.querySelector(".error")
.textContent = "Please log in to Dropbox!";
return;
}
return new RSVP.Queue()
.push(function () {
return createDropboxJio(gadget,
gadget.state_parameter_dict.auth_dict.dropbox_folder);
})
.push(function () {
const dropbox_param_dict = { const dropbox_param_dict = {
gadget: gadget, gadget: gadget,
gadget_name: "dropbox_gadget", gadget_name: "dropbox_gadget",
function_param_dict: {
folder: gadget.state_parameter_dict.auth_dict.dropbox_folder,
room: gadget.state_parameter_dict.login_dict.room, room: gadget.state_parameter_dict.login_dict.room,
name: gadget.state_parameter_dict.login_dict.name, name: gadget.state_parameter_dict.login_dict.name,
file_name: null, file_name: null,
content: null, content: null,
}, dropbox_folder: gadget.state_parameter_dict.dropbox_folder,
function_dict: { function_dict: {
resetContent: resetDropboxContent, resetContent: resetDropboxContent,
getOffer: getDropboxOffer, getOffer: getDropboxOffer,
...@@ -118,6 +119,21 @@ ...@@ -118,6 +119,21 @@
removeContent: removeDropboxContent, removeContent: removeDropboxContent,
}, },
}; };
return new RSVP.Queue()
.push(function () {
if (document.URL.indexOf("access_token=") === -1) {
throw webrtcError(gadget, "Please log in to Dropbox!");
} else {
return createDropboxJio(gadget, dropbox_param_dict);
}
})
.push(function () {
return gadget.getDeclaredGadget("dropbox_gadget");
})
.push(function (dropbox_gadget) {
return resetDropboxContent(dropbox_gadget, dropbox_param_dict);
})
.push(function () {
if (gadget.state_parameter_dict.login_dict.role === "host") { if (gadget.state_parameter_dict.login_dict.role === "host") {
return authenticateHost(dropbox_param_dict); return authenticateHost(dropbox_param_dict);
} else if (gadget.state_parameter_dict.login_dict.role === "guest") { } else if (gadget.state_parameter_dict.login_dict.role === "guest") {
...@@ -127,7 +143,7 @@ ...@@ -127,7 +143,7 @@
.push(null, logError); .push(null, logError);
} }
function createErp5Jio(gadget, folder, url) { function createErp5Jio(gadget, param_dict) {
let erp5_gadget; let erp5_gadget;
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
...@@ -138,7 +154,7 @@ ...@@ -138,7 +154,7 @@
erp5_gadget = jio_gadget; erp5_gadget = jio_gadget;
return erp5_gadget.createJio({ return erp5_gadget.createJio({
type: "erp5", type: "erp5",
url: url, url: (new URI("hateoas")).absoluteTo(param_dict.erp5_url).toString(),
default_view_reference: "view", default_view_reference: "view",
}); });
}) })
...@@ -154,44 +170,57 @@ ...@@ -154,44 +170,57 @@
.push(function (room_list) { .push(function (room_list) {
if (room_list.data.rows.length) { if (room_list.data.rows.length) {
for (let i = 0, i_len = room_list.data.rows.length; i < i_len; i++) { for (let i = 0, i_len = room_list.data.rows.length; i < i_len; i++) {
if (room_list.data.rows[i].value.title === folder) { if (room_list.data.rows[i].value.title === param_dict.room) {
return room_list.data.rows[i].id; return room_list.data.rows[i].id;
} }
} }
} }
return erp5_gadget.post({ return erp5_gadget.post({
title: folder,
portal_type: "Webrtc Room", portal_type: "Webrtc Room",
parent_relative_url: "webrtc_rooms_module", parent_relative_url: "webrtc_rooms_module",
title: param_dict.room,
negotiation_list: JSON.stringify({}),
}); });
}) })
.push(null, logError); .push(null, logError);
} }
function resetErp5Content(erp5_gadget, param_dict) { function resetErp5Content(erp5_gadget, param_dict) {
return logQueue(erp5_gadget.putAttachment( return logQueue(erp5_gadget.put(param_dict.id, {
"/", param_dict.url + "WebrtcRoom_resetContent", portal_type: "Webrtc Room",
new Blob([JSON.stringify({folder: param_dict.folder})]))); parent_relative_url: "webrtc_rooms_module",
title: param_dict.room,
negotiation_list: JSON.stringify({}),
}));
}
function getErp5Offer(erp5_gadget, param_dict) {
return new RSVP.Queue()
.push(function () {
return erp5_gadget.get(param_dict.id);
})
.push(function (webrtc_room) {
const negotiation_list = JSON.parse(webrtc_room.negotiation_list);
for (let file_name in negotiation_list) {
if (negotiation_list.hasOwnProperty(file_name)
&& file_name.indexOf("offer_" + param_dict.room + "_") === 0) {
return file_name.slice(6);
}
}
return null;
})
.push(null, logError);
} }
function getErp5Content(erp5_gadget, param_dict) { function getErp5Content(erp5_gadget, param_dict) {
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
return erp5_gadget.putAttachment( return erp5_gadget.get(param_dict.id);
"/", param_dict.url + param_dict.action, })
new Blob([JSON.stringify({ .push(function (webrtc_room) {
folder: param_dict.folder, const negotiation_list = JSON.parse(webrtc_room.negotiation_list);
room: param_dict.room, if (negotiation_list[param_dict.file_name]) {
name: param_dict.file_name, return negotiation_list[param_dict.file_name];
})])
);
})
.push(function (response) {
return response.currentTarget.responseText;
})
.push(function (offer_name) {
if (offer_name) {
return offer_name;
} else { } else {
return null; return null;
} }
...@@ -200,73 +229,71 @@ ...@@ -200,73 +229,71 @@
} }
function putErp5Content(erp5_gadget, param_dict) { function putErp5Content(erp5_gadget, param_dict) {
return logQueue(erp5_gadget.putAttachment( return new RSVP.Queue()
"/", param_dict.url + "WebrtcRoom_putContent", .push(function () {
new Blob([JSON.stringify({ return erp5_gadget.get(param_dict.id);
folder: param_dict.folder, })
name: param_dict.file_name, .push(function (webrtc_room) {
content: param_dict.content, const negotiation_list = JSON.parse(webrtc_room.negotiation_list);
})]) negotiation_list[param_dict.file_name] = param_dict.content;
)); return logQueue(erp5_gadget.put(param_dict.id, {
portal_type: "Webrtc Room",
parent_relative_url: "webrtc_rooms_module",
title: param_dict.room,
negotiation_list: JSON.stringify(negotiation_list),
}));
})
.push(null, logError);
} }
function removeErp5Content(erp5_gadget, param_dict) { function removeErp5Content(erp5_gadget, param_dict) {
return logQueue(erp5_gadget.putAttachment(
"/", param_dict.url + "WebrtcRoom_deleteContent",
new Blob([JSON.stringify({
folder: param_dict.folder,
name: param_dict.file_name,
})])
));
}
function authenticateErp5(gadget) {
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
return createErp5Jio( return erp5_gadget.get(param_dict.id);
gadget, gadget.state_parameter_dict.login_dict.folder,
gadget.state_parameter_dict.auth_dict.hateoas_url);
})
.push(function (folder_id) {
gadget.state_parameter_dict.auth_dict.erp5_folder =
folder_id.slice(folder_id.indexOf("/") + 1);
gadget.state_parameter_dict.auth_dict.erp5_folder_url =
gadget.state_parameter_dict.auth_dict.erp5_url
+ gadget.state_parameter_dict.auth_dict.erp5_folder + "/";
return gadget.getDeclaredGadget("erp5_gadget");
}) })
.push(function (erp5_gadget) { .push(function (webrtc_room) {
return resetErp5Content(erp5_gadget, { const negotiation_list = JSON.parse(webrtc_room.negotiation_list);
folder: gadget.state_parameter_dict.auth_dict.erp5_folder, delete negotiation_list[param_dict.file_name];
url: gadget.state_parameter_dict.auth_dict.erp5_folder_url, return logQueue(erp5_gadget.put(param_dict.id, {
}); portal_type: "Webrtc Room",
parent_relative_url: "webrtc_rooms_module",
title: param_dict.room,
negotiation_list: JSON.stringify(negotiation_list),
}));
}) })
.push(function () { .push(null, logError);
}
function authenticateErp5(gadget) {
const erp5_param_dict = { const erp5_param_dict = {
gadget: gadget, gadget: gadget,
gadget_name: "erp5_gadget", gadget_name: "erp5_gadget",
function_param_dict: {
folder: gadget.state_parameter_dict.auth_dict.erp5_folder,
room: gadget.state_parameter_dict.login_dict.room, room: gadget.state_parameter_dict.login_dict.room,
name: gadget.state_parameter_dict.login_dict.name, name: gadget.state_parameter_dict.login_dict.name,
url: gadget.state_parameter_dict.auth_dict.erp5_folder_url,
file_name: null, file_name: null,
content: null, content: null,
}, id: null,
erp5_url: gadget.state_parameter_dict.erp5_url,
function_dict: { function_dict: {
resetContent: resetErp5Content, resetContent: resetErp5Content,
getOffer: function (erp5_gadget, param_dict) { getOffer: getErp5Offer,
param_dict.action = "WebrtcRoom_getOffer"; getContent: getErp5Content,
return getErp5Content(erp5_gadget, param_dict);
},
getContent: function (erp5_gadget, param_dict) {
param_dict.action = "WebrtcRoom_getContent";
return getErp5Content(erp5_gadget, param_dict);
},
putContent: putErp5Content, putContent: putErp5Content,
removeContent: removeErp5Content, removeContent: removeErp5Content,
}, },
}; };
return new RSVP.Queue()
.push(function () {
return createErp5Jio(gadget, erp5_param_dict);
})
.push(function (id) {
erp5_param_dict.id = id;
return gadget.getDeclaredGadget("erp5_gadget");
})
.push(function (erp5_gadget) {
return resetErp5Content(erp5_gadget, erp5_param_dict);
})
.push(function () {
if (gadget.state_parameter_dict.login_dict.role === "host") { if (gadget.state_parameter_dict.login_dict.role === "host") {
return authenticateHost(erp5_param_dict); return authenticateHost(erp5_param_dict);
} else if (gadget.state_parameter_dict.login_dict.role === "guest") { } else if (gadget.state_parameter_dict.login_dict.role === "guest") {
...@@ -282,15 +309,12 @@ ...@@ -282,15 +309,12 @@
let jio_gadget; let jio_gadget;
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
gadget.state_parameter_dict.element
.querySelector(".error").textContent = "";
return gadget.getDeclaredGadget(param_dict.gadget_name); return gadget.getDeclaredGadget(param_dict.gadget_name);
}) })
.push(function (storage_gadget) { .push(function (storage_gadget) {
jio_gadget = storage_gadget; jio_gadget = storage_gadget;
return pollUntilNotNull(gadget, 2000, 86400000, function () { return pollUntilNotNull(gadget, 2000, 86400000, function () {
return param_dict.function_dict.getOffer( return param_dict.function_dict.getOffer(jio_gadget, param_dict);
jio_gadget, param_dict.function_param_dict);
}, function (offer_name) { }, function (offer_name) {
file_name = offer_name; file_name = offer_name;
}); });
...@@ -305,14 +329,12 @@ ...@@ -305,14 +329,12 @@
} }
}); });
}, function () { }, function () {
throw param_dict.function_dict.resetContent( throw param_dict.function_dict.resetContent(jio_gadget, param_dict);
jio_gadget, param_dict.function_param_dict);
}) })
.push(function () { .push(function () {
param_dict.function_param_dict.file_name = "offer_" + file_name; param_dict.file_name = "offer_" + file_name;
return pollUntilNotNull(gadget, 500, 10000, function () { return pollUntilNotNull(gadget, 500, 10000, function () {
return param_dict.function_dict.getContent( return param_dict.function_dict.getContent(jio_gadget, param_dict);
jio_gadget, param_dict.function_param_dict);
}, function (guest_offer) { }, function (guest_offer) {
return sendOffer(gadget, guest_offer); return sendOffer(gadget, guest_offer);
}); });
...@@ -328,18 +350,16 @@ ...@@ -328,18 +350,16 @@
return gadget.state_parameter_dict.candidate; return gadget.state_parameter_dict.candidate;
}, function (host_answer) { }, function (host_answer) {
gadget.state_parameter_dict.candidate = null; gadget.state_parameter_dict.candidate = null;
param_dict.function_param_dict.file_name = "answer_" + file_name; param_dict.file_name = "answer_" + file_name;
param_dict.function_param_dict.content = host_answer; param_dict.content = host_answer;
return param_dict.function_dict.putContent( return param_dict.function_dict.putContent(jio_gadget, param_dict);
jio_gadget, param_dict.function_param_dict);
}); });
}) })
.push(null, logError) .push(null, logError)
.push(function () { .push(function () {
if (file_name) { if (file_name) {
param_dict.function_param_dict.file_name = "offer_" + file_name; param_dict.file_name = "offer_" + file_name;
return param_dict.function_dict.removeContent( return param_dict.function_dict.removeContent(jio_gadget, param_dict);
jio_gadget, param_dict.function_param_dict);
} else { } else {
return; return;
} }
...@@ -356,8 +376,6 @@ ...@@ -356,8 +376,6 @@
let jio_gadget; let jio_gadget;
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
gadget.state_parameter_dict.element
.querySelector(".error").textContent = "";
return gadget.getDeclaredGadget(param_dict.gadget_name); return gadget.getDeclaredGadget(param_dict.gadget_name);
}) })
.push(function (storage_gadget) { .push(function (storage_gadget) {
...@@ -365,29 +383,28 @@ ...@@ -365,29 +383,28 @@
return pollUntilNotNull(gadget, 500, 30000, function () { return pollUntilNotNull(gadget, 500, 30000, function () {
return gadget.state_parameter_dict.candidate; return gadget.state_parameter_dict.candidate;
}, function (guest_offer) { }, function (guest_offer) {
file_name = param_dict.function_param_dict.room + "_" file_name = param_dict.room + "_" + param_dict.name + ".txt";
+ param_dict.function_param_dict.name + ".txt"; param_dict.file_name = "offer_" + file_name;
param_dict.function_param_dict.file_name = "offer_" + file_name; param_dict.content = guest_offer;
param_dict.function_param_dict.content = guest_offer; return param_dict.function_dict.putContent(jio_gadget, param_dict);
return param_dict.function_dict.putContent(
jio_gadget, param_dict.function_param_dict);
}); });
}) })
.push(function () { .push(function () {
return pollUntilNotNull(gadget, 500, 30000, function () { return pollUntilNotNull(gadget, 500, 30000, function () {
param_dict.function_param_dict.file_name = "answer_" + file_name; param_dict.file_name = "answer_" + file_name;
return param_dict.function_dict.getContent( return param_dict.function_dict.getContent(jio_gadget, param_dict);
jio_gadget, param_dict.function_param_dict);
}, function (host_answer) { }, function (host_answer) {
return sendAnswer(gadget, host_answer); return sendAnswer(gadget, host_answer);
}); });
}) })
.push(null, logError) .push(function () {
// XXX pause to avoid data races, use locks later
return RSVP.delay(1000);
}, logError)
.push(function () { .push(function () {
if (file_name) { if (file_name) {
param_dict.function_param_dict.file_name = "answer_" + file_name; param_dict.file_name = "answer_" + file_name;
return param_dict.function_dict.removeContent( return param_dict.function_dict.removeContent(jio_gadget, param_dict);
jio_gadget, param_dict.function_param_dict);
} else { } else {
return; return;
} }
...@@ -484,13 +501,9 @@ ...@@ -484,13 +501,9 @@
"WebRTC connection status: " "WebRTC connection status: "
+ peer_connection.iceConnectionState + "."; + peer_connection.iceConnectionState + ".";
if (peer_connection.iceConnectionState === "failed") { if (peer_connection.iceConnectionState === "failed") {
gadget.state_parameter_dict.element throw webrtcError(gadget, "WebRTC connection failed!");
.querySelector(".error").textContent =
"WebRTC connection failed!";
} else if (peer_connection.iceConnectionState === "failed") { } else if (peer_connection.iceConnectionState === "failed") {
gadget.state_parameter_dict.element throw webrtcError(gadget, "WebRTC connection disconnected!");
.querySelector(".error").textContent =
"WebRTC connection disconnected!";
} }
}; };
} }
...@@ -566,18 +579,14 @@ ...@@ -566,18 +579,14 @@
gadget.state_parameter_dict = { gadget.state_parameter_dict = {
element: null, element: null,
login_dict: { login_dict: {
folder: null,
room: null, room: null,
name: null, name: null,
role: null, role: null,
}, },
auth_dict: {
dropbox_url: null,
dropbox_folder: null, dropbox_folder: null,
erp5_url: null, erp5_url: null,
erp5_folder: null, dataChannelOnopen: null,
erp5_folder_url: null, dataChannelOnmessage: null,
},
candidate: null, candidate: null,
connected: false, connected: false,
offer_ready: false, offer_ready: false,
...@@ -617,6 +626,9 @@ ...@@ -617,6 +626,9 @@
.push(null, logError); .push(null, logError);
}) })
.declareAcquiredMethod('wrapJioAccess', 'wrapJioAccess')
.declareAcquiredMethod('getContactByEmail', 'getContactByEmail')
.declareMethod('render', function () { .declareMethod('render', function () {
const gadget = this; const gadget = this;
return new RSVP.Queue() return new RSVP.Queue()
...@@ -670,32 +682,15 @@ ...@@ -670,32 +682,15 @@
.push(null, logError); .push(null, logError);
}) })
.declareMethod('authenticate', function () { .declareMethod('authenticate', function (auth) {
const gadget = this; const gadget = this;
const auth = gadget.state_parameter_dict.element
.querySelector(".auth-form").elements.auth.value;
const fields = gadget.state_parameter_dict.element const fields = gadget.state_parameter_dict.element
.querySelector(".contact-form").elements; .querySelector(".contact-form").elements;
const dropbox_url = fields.dropbox_url.value;
const erp5_url = fields.erp5_url.value;
const hateoas_url = fields.hateoas_url.value;
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
let folder = gadget.state_parameter_dict.login_dict.folder; gadget.state_parameter_dict.dropbox_folder =
if (folder[0] !== "/") { fields.dropbox_folder.value;
folder = "/" + folder; gadget.state_parameter_dict.erp5_url = fields.erp5_url.value;
}
if (folder[folder.length - 1] !== "/") {
folder = folder + "/";
}
gadget.state_parameter_dict.auth_dict = {
dropbox_url: dropbox_url,
dropbox_folder: dropbox_url + folder,
erp5_url: erp5_url,
erp5_folder: null,
erp5_folder_url: null,
hateoas_url: hateoas_url,
};
switch (auth) { switch (auth) {
case "dropbox": case "dropbox":
return authenticateDropbox(gadget); return authenticateDropbox(gadget);
...@@ -707,11 +702,78 @@ ...@@ -707,11 +702,78 @@
}); });
}) })
.declareMethod('uploadContact', function (event) {
const gadget = this;
const fields = event.target.elements;
return new RSVP.Queue()
.push(function () {
return gadget.getContactByEmail(fields.email.value);
})
.push(function (id) {
const param_dict = {
dropbox_folder: fields.dropbox_folder.value,
erp5_url: fields.erp5_url.value,
auth: gadget.state_parameter_dict.element
.querySelector(".auth-form").elements.auth.value,
}
let jio_configuration = "";
for (let key in param_dict) {
if (param_dict.hasOwnProperty(key) && param_dict[key]) {
jio_configuration += "&" + key + "=" + param_dict[key];
}
}
return gadget.wrapJioAccess('put', id, {
portal_type: "Person",
parent_relative_url: "person_module",
default_email_coordinate_text: fields.email.value,
jio_configuration: jio_configuration,
});
})
.push(function () {
return gadget.wrapJioAccess('repair');
})
.push(null, logError);
})
.declareMethod('downloadContact', function () {
const gadget = this;
const fields = gadget.state_parameter_dict.element
.querySelector(".contact-form").elements;
return new RSVP.Queue()
.push(function () {
return gadget.getContactByEmail(fields.email.value);
})
.push(function (id) {
return gadget.wrapJioAccess('get', id);
})
.push(function (contact) {
if (!contact) {
throw webrtcError(gadget, "Email not found!");
} else {
const param_dict = {};
const query_list = [["email", "e"],
["dropbox_folder", "d"], ["erp5_url", "e"]];
for (let i = 0, i_len = query_list.length; i < i_len; i++) {
const query = query_list[i];
setQueryValue(query, contact.jio_configuration, fields[query[0]]);
}
setQueryValue(["auth", "a"], contact.jio_configuration, gadget
.state_parameter_dict.element.querySelector(".auth-form").auth);
return;
}
})
.push(null, logError);
})
.onEvent('submit', function (event) { .onEvent('submit', function (event) {
const gadget = this; const gadget = this;
switch (event.target.className) { switch (event.target.className) {
case "auth-form": case "auth-form":
return gadget.authenticate(); return gadget.authenticate(event.target.elements.auth.value);
case "contact-form":
return gadget.uploadContact(event);
case "download-form":
return gadget.downloadContact();
case "host-offer-form": case "host-offer-form":
styleElementByQuery(gadget, ".host-offer-form", "none"); styleElementByQuery(gadget, ".host-offer-form", "none");
styleElementByQuery(gadget, ".host-answer-form", "block"); styleElementByQuery(gadget, ".host-answer-form", "block");
......
...@@ -149,6 +149,28 @@ ...@@ -149,6 +149,28 @@
return value; return value;
}; };
window.getQueryValue = function (query_list, query_string) {
for (let i = 0, i_len = query_list.length; i < i_len; i++) {
const query = query_list[i];
if (query_string.indexOf(query + "=") !== -1) {
const start = query_string.indexOf(query + "=") + query.length + 1;
let end = query_string.indexOf("&", start);
if (end === -1) {
end = query_string.length;
}
return query_string.slice(start, end);
}
}
return null;
}
window.setQueryValue = function (query_list, query_string, element) {
const value = getQueryValue(query_list, query_string);
if (value) {
element.value = value;
}
}
window.pollUntilNotNull = function ( window.pollUntilNotNull = function (
gadget, delay_ms, timeout_ms, gadget, delay_ms, timeout_ms,
nullableFunction, callbackFunction) { nullableFunction, callbackFunction) {
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_Transient_Objects_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Access_arbitrary_user_session_data_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_events_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_folders_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_member_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_topics_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
</tuple>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>erp5_webrtc_room</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
import json
module = context.getPortalObject().getDefaultModule(portal_type="Webrtc Room")
webrtc_folder = module[folder]
negotiation_list = json.loads(webrtc_folder.negotiation_list)
negotiation_list.pop(name, None)
webrtc_folder.edit(
negotiation_list = json.dumps(negotiation_list)
)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>folder, name</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>WebrtcRoom_deleteContent</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
import json
module = context.getPortalObject().getDefaultModule(portal_type="Webrtc Room")
webrtc_folder = module[folder]
negotiation_list = json.loads(webrtc_folder.negotiation_list)
return negotiation_list.get(name, "")
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>folder, name</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>WebrtcRoom_getContent</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
import json
module = context.getPortalObject().getDefaultModule(portal_type="Webrtc Room")
webrtc_folder = module[folder]
negotiation_list = json.loads(webrtc_folder.negotiation_list)
for name in negotiation_list:
if name.startswith("offer_" + room):
return name[6:]
return ""
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>folder, room</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>WebrtcRoom_getOffer</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
import json
module = context.getPortalObject().getDefaultModule(portal_type="Webrtc Room")
webrtc_folder = module[folder]
negotiation_list = json.loads(webrtc_folder.negotiation_list)
negotiation_list[name] = content
webrtc_folder.edit(
negotiation_list = json.dumps(negotiation_list)
)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>folder, name, content</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>WebrtcRoom_putContent</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
import json
module = context.getPortalObject().getDefaultModule(portal_type="Webrtc Room")
webrtc_folder = module[folder]
webrtc_folder.edit(
negotiation_list = json.dumps({})
)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>folder</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>WebrtcRoom_resetContent</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string>Base_edit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>center</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list>
<string>my_title</string>
<string>my_negotiation_list</string>
</list>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>WebrtcRoom_view</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>WebrtcRoom_view</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_view</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Webrtc Room</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="StringField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>my_negotiation_list</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
<item>
<key> <string>required_not_found</string> </key>
<value> <string>Input is required but no input given.</string> </value>
</item>
<item>
<key> <string>too_long</string> </key>
<value> <string>Too much input was given.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>truncate</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>truncate</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <int>20</int> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string>text</string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>WebRTC Negotiation List</string> </value>
</item>
<item>
<key> <string>truncate</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="StringField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>my_title</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
<item>
<key> <string>required_not_found</string> </key>
<value> <string>Input is required but no input given.</string> </value>
</item>
<item>
<key> <string>too_long</string> </key>
<value> <string>Too much input was given.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>truncate</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>truncate</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <int>20</int> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string>text</string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Title</string> </value>
</item>
<item>
<key> <string>truncate</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string>WebrtcRoomsModule_addWebrtcRoom</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>use this dialog to create new rooms</string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>center</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list>
<string>your_title</string>
</list>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>WebrtcRoomsModule_viewAddWebrtcRoom</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>WebrtcRoomsModule_viewAddWebrtcRoom</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_dialog</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>New Rooms</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="StringField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>your_title</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
<item>
<key> <string>required_not_found</string> </key>
<value> <string>Input is required but no input given.</string> </value>
</item>
<item>
<key> <string>too_long</string> </key>
<value> <string>Too much input was given.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>truncate</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>truncate</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <int>20</int> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string>text</string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Title</string> </value>
</item>
<item>
<key> <string>truncate</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string>Base_doSelect</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list>
<string>listbox</string>
</list>
</value>
</item>
<item>
<key> <string>center</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>WebrtcRoomsModule_viewWebrtcRoomList</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>WebrtcRoomsModule_viewWebrtcRoomList</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_list</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Webrtc Rooms</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>columns</string>
<string>selection_name</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>listbox</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>columns</string> </key>
<value>
<list>
<tuple>
<string>title</string>
<string>Title</string>
</tuple>
<tuple>
<string>negotiation_list</string>
<string>WebRTC Negotiation List</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_list_mode_listbox</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value>
<list>
<tuple>
<string>Webrtc Room</string>
<string>Webrtc Room</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>selection_name</string> </key>
<value> <string>webrtc_rooms_module_selection</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>WebRTC Rooms</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
erp5_webrtc_room
\ 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