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 @@
<form class="login-form">
<label>Name:</label>
<input type="text" name="name" required="required" />
<label>Folder:</label>
<input type="text" name="folder" required="required" />
<h3>Remote Storage</h3>
<label>
......@@ -44,7 +42,7 @@
<h3>Storage Configuration</h3>
<a class="dropbox-link">Dropbox OAuth</a>
<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>
<input type="text" name="remote_erp5_url" placeholder="https://softinst75770.host.vifib.net/erp5/web_site_module/" />
<label>WebDAV URL:</label>
......@@ -58,11 +56,9 @@
<label>Default storage:</label>
<input type="text" name="auth" placeholder="dropbox" />
<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>
<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 />
<input type="submit" name="login" value="Login!" />
</form>
......
......@@ -2,12 +2,10 @@
/* URL Options:
* 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,
* either dav, dropbox, erp5, or local
* remote_dropbox_url: the remote Dropbox folder to synchronize with,
* e.g. /Apps/OfficeJS Chat/.jio_documents
* remote_dropbox_folder: the remote Dropbox folder to synchronize with,
* e.g. /Apps/OfficeJS Chat/.jio_documents/
* remote_erp5_url: the remote ERP5 instance to synchronize with,
* e.g. https://softinst75770.host.vifib.net/erp5/web_site_module/
* remote_dav_url: the remote WebDAV server to synchronize with,
......@@ -16,52 +14,20 @@
* remote_dav_pass: your WebDAV password, e.g. correct horse battery staple
* auth: the default type of authentication to use for WebRTC rooms,
* either dropbox or erp5
* auth_dropbox_url: the shared Dropbox folder to act as your auth folder,
* e.g. /Apps/OfficeJS Chat
* auth_erp5_url: the shared ERP5 instance to act as your auth folder,
* e.g. https://softinst75770.host.vifib.net/erp5/webrtc_rooms_module/
* auth_dropbox_folder: the shared Dropbox folder for WebRTC negotiations,
* e.g. /Apps/OfficeJS Chat/
* auth_erp5_url: the shared ERP5 instance to store WebRTC negotiations,
* 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)
.ready(function (gadget) {
gadget.state_parameter_dict = {
element: null,
name: null,
folder: null,
auth: null,
dropbox_url: null,
dropbox_folder: null,
erp5_url: null,
hateoas_url: null,
// Dropbox OAuth only allows 500 characters in the state query
max_state_length: 500,
};
......@@ -104,6 +70,38 @@
})
.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) {
const gadget = this;
......@@ -122,12 +120,10 @@
.push(function (chat_gadget) {
const fields = webrtc_gadget.state_parameter_dict.element
.querySelector(".contact-form").elements;
fields.dropbox_url.value = param_dict.dropbox_url
|| gadget.state_parameter_dict.dropbox_url;
fields.dropbox_folder.value = param_dict.dropbox_folder
|| gadget.state_parameter_dict.dropbox_folder;
fields.erp5_url.value = param_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")
.auth.value = param_dict.auth || gadget.state_parameter_dict.auth;
chat_gadget.state_parameter_dict.element
......@@ -136,7 +132,6 @@
chat_gadget.state_parameter_dict.element
.querySelector(".chat-right-panel-chat"));
webrtc_gadget.state_parameter_dict.login_dict = {
folder: gadget.state_parameter_dict.folder,
room: param_dict.room,
name: gadget.state_parameter_dict.name,
role: param_dict.role,
......@@ -192,10 +187,10 @@
})
.declareMethod('render', function () {
let url = decodeURIComponent(document.URL);
const gadget = this;
return new RSVP.Queue()
.push(function () {
let url = decodeURIComponent(document.URL);
const state_output = getQueryValue(["state"], url);
if (state_output) {
url += window.atob(state_output);
......@@ -204,12 +199,11 @@
.querySelector(".login-form").elements;
let state_input = "";
// A list of login-form fields and short keys in order of priority
const query_list = [["name", "m"], ["folder", "f"], ["remote", "r"],
["remote_dropbox_url", "rd"], ["remote_erp5_url", "re"],
const query_list = [["name", "m"], ["remote", "r"],
["remote_dropbox_folder", "rd"], ["remote_erp5_url", "re"],
["remote_dav_url", "rv"], ["remote_dav_user", "rvu"],
["remote_dav_pass", "rvp"], ["auth", "a"],
["auth_dropbox_url", "ad"], ["auth_erp5_url", "ae"],
["auth_hateoas_url", "ah"]]
["auth_dropbox_folder", "ad"], ["auth_erp5_url", "ae"]]
for (let i = 0, i_len = query_list.length; i < i_len; i++) {
const query = query_list[i];
setQueryValue(query, url, fields[query[0]]);
......@@ -246,27 +240,28 @@
const fields = gadget.state_parameter_dict.element
.querySelector(".login-form").elements;
gadget.state_parameter_dict.auth = fields.auth.value;
gadget.state_parameter_dict.dropbox_url =
fields.auth_dropbox_url.value;
gadget.state_parameter_dict.dropbox_folder =
fields.auth_dropbox_folder.value;
gadget.state_parameter_dict.erp5_url = fields.auth_erp5_url.value;
gadget.state_parameter_dict.hateoas_url =
fields.auth_hateoas_url.value;
gadget.state_parameter_dict.name = cleanId(fields.name.value);
gadget.state_parameter_dict.folder = cleanId(fields.folder.value);
gadget.state_parameter_dict.name =
fields.name.value.replace(/[^0-9a-z]/gi, '');
chat_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({
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,
dav_url: fields.remote_dav_url.value,
dav_user: fields.remote_dav_user.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 () {
return chat_gadget.render();
})
......@@ -346,8 +341,8 @@
use_remote_post: remote_post,
conflict_handling: 2,
query: {
query: 'portal_type: "Text Post"',
limit: [0, 1000000000],
query: 'portal_type: "Person" OR portal_type: "Text Post"',
},
local_sub_storage: {
type: "query",
......
......@@ -54,8 +54,8 @@
}
function isSameMessage(lhs, rhs) {
return lhs !== undefined && rhs !== undefined && lhs.name === rhs.name
&& lhs.content === rhs.content && lhs.folder === rhs.folder
return lhs !== undefined && rhs !== undefined
&& lhs.name === rhs.name && lhs.content === rhs.content
&& lhs.room === rhs.room && getTime(lhs) === getTime(rhs);
}
......@@ -144,15 +144,13 @@
return new RSVP.Queue()
.push(function () {
gadget.state_parameter_dict = {
folder: null,
room: null,
name: null,
element: null,
initialized: false,
// A set of names of rooms joined within this folder;
// as a guest, only notify that you have joined once
// you have received the host's remote archive, so that
// your notification doesn't override all previous messages
// A set of names of current rooms; as a guest, only notify that
// you have joined once you have received the host's remote archive,
// so that your notification doesn't override all previous messages
// room_set["room"] = false if joined, true if also notified
room_set: {},
// A dictionary of messages based on the current room, e.g.
......@@ -183,12 +181,12 @@
const gadget = this;
return new RSVP.Queue()
.push(function () {
gadget.state_parameter_dict.room = gadget.state_parameter_dict.name;
gadget.state_parameter_dict.element
.querySelector(".send-form input").onfocus = function () {
return logQueue(
gadget.notifyStatus(gadget.state_parameter_dict.room, false));
};
gadget.state_parameter_dict.room = gadget.state_parameter_dict.name;
})
.push(null, logError);
})
......@@ -199,32 +197,31 @@
const gadget = this;
return new RSVP.Queue()
.push(function () {
return gadget.wrapJioAccess('allDocs');
})
.push(function (document_list) {
const list = document_list.data.rows;
const promise_list = [];
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);
return gadget.wrapJioAccess('allDocs', {
limit: [0, 1000000],
query: 'portal_type: "Text Post"',
sort_on: [["last_modified", "descending"]],
select_list: ["content"],
});
})
.push(function (message_list) {
const message_queue = new FastPriorityQueue(messageTimeCompare(true));
for (let i = 0, i_len = message_list.length; i < i_len; i++) {
try {
const message = JSON.parse(message_list[i].content);
if (message && typeof message === "object") {
message_queue.add(message);
}
} catch (error) {}
if (message_list.data.rows.length) {
for (let i = 0, i_len = message_list.data.rows.length;
i < i_len; i++) {
try {
const message = JSON.parse(list[i]);
if (message && typeof message === "object") {
message_queue.add(message);
}
} catch (error) {}
}
}
const promise_list = [];
const message_dict = gadget.state_parameter_dict.last_message_dict;
while (!message_queue.isEmpty()) {
const message = message_queue.poll();
if (message.folder === gadget.state_parameter_dict.folder
&& (message.room in gadget.state_parameter_dict.room_set)) {
if (message.room in gadget.state_parameter_dict.room_set) {
promise_list.push(gadget.storeList(message));
promise_list.push(gadget.appendMessage(message));
}
......@@ -346,7 +343,6 @@
return {
type: param_dict.type || "message",
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,
time: param_dict.time || new Date(),
content: param_dict.content || "",
......@@ -421,20 +417,16 @@
// Store message in the archive
.declareMethod('storeArchive', function (message) {
const gadget = this;
return new RSVP.Queue()
.push(function () {
const id = message.folder + "_" + message.room + "_"
+ message.name + "_" + getTime(message).toString();
return gadget.wrapJioAccess('put', id, {
portal_type: "Text Post",
parent_relative_url: "post_text_module",
reference: id,
author: message.name,
date_ms: getTime(message),
content: JSON.stringify(message),
});
})
.push(null, logError);
const id = message.room + "_" + message.name + "_"
+ getTime(message).toString();
return logQueue(gadget.wrapJioAccess('put', id, {
portal_type: "Text Post",
parent_relative_url: "post_text_module",
reference: id,
author: message.name,
date_ms: getTime(message),
content: JSON.stringify(message),
}));
})
// Add message to the list
......@@ -514,7 +506,7 @@
class_name = "notify";
} else {
favicon_url = gadget.state_parameter_dict.default_icon;
class_name = "";
class_name = "current";
}
const link = document.querySelector("link[rel*='icon']")
|| document.createElement("link");
......@@ -524,16 +516,12 @@
document.head.appendChild(link);
const contact = gadget.state_parameter_dict.element
.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);
})
// Join a different room in the same folder
// Join a different room
.declareMethod('changeRoom', function (room) {
const gadget = this;
return new RSVP.Queue()
......@@ -570,7 +558,6 @@
.declareMethod('createContact', function (param_dict) {
const gadget = this;
return new RSVP.Queue()
// XXX: load params here too
.push(function () {
return gadget.appendContact(param_dict.room);
})
......@@ -736,9 +723,7 @@
return gadget.createContact({room: contact, role: "guest"});
case "make-form":
const room = resetInputValue(event.target.elements.content);
return gadget.createContact({room: room, role: "host"});
case "auth-form":
return gadget.connectContact();
return gadget.chooseRoom({room: room, role: "host"});
case "send-form":
const content = resetInputValue(event.target.elements.content);
if (content.indexOf("/") === 0) {
......
......@@ -15,20 +15,20 @@
<p class="status"></p>
<form class="contact-form">
<label>Name:</label>
<input type="text" name="name" />
<label>Folder:</label>
<input type="text" name="folder" />
<label>E-mail Address:</label>
<input type="text" name="email" />
<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>
<input type="text" name="erp5_url" placeholder="https://softinst75770.host.vifib.net/erp5/webrtc_rooms_module/" />
<label>Hateoas URL:</label>
<input type="text" name="hateoas_url" placeholder="https://softinst75770.host.vifib.net/erp5/web_site_module/hateoas" />
<input type="text" name="erp5_url" placeholder="https://softinst75770.host.vifib.net/erp5/web_site_module/" />
<br />
<input type="submit" value="Update information!" />
</form>
<form class="download-form">
<input type="submit" value="Download information from remote storage!" />
</form>
<form class="auth-form">
<label>
<input type="radio" name="auth" value="erp5" required="required" />
......
......@@ -149,6 +149,28 @@
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 (
gadget, delay_ms, timeout_ms,
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="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="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