Commit 17bb0e4e authored by Eugene Shen's avatar Eugene Shen

Poll refresh and set styles in onStateChange

parent 0d9586e0
...@@ -17,22 +17,19 @@ ...@@ -17,22 +17,19 @@
<ul class="contact-list"> <ul class="contact-list">
</ul> </ul>
<div class="chat-form-panel"> <div class="chat-form-panel">
<form class="sync-form">
<input type="submit" value="Synchronize!" />
</form>
<form class="edit-form">
<input type="submit" value="Edit contact!" />
</form>
<form class="join-form"> <form class="join-form">
<input type="text" name="content" /> <input type="text" name="content" />
<input type="submit" value="Join room!" /> <input type="submit" value="Join room!" />
</form> </form>
<form class="edit-form">
<input type="submit" value="Edit contact!" />
</form>
</div> </div>
</div> </div>
<div class="chat-right-panel"> <div class="chat-right-panel">
<div class="chat-max-height-wrapper"> <h3 class="chat-title center"></h3>
<div class="chat-max-height-wrapper">
<div class="chat-right-panel-chat"> <div class="chat-right-panel-chat">
<h3 class="chat-title center"></h3>
<ul class="chat-list"> <ul class="chat-list">
</ul> </ul>
<form class="send-form"> <form class="send-form">
......
...@@ -51,74 +51,15 @@ ...@@ -51,74 +51,15 @@
} }
/* Set the display style of the element given by a query. /* Get the contact element given by a room.
* Parameters: * Parameters:
* - query: the query for which to find the element using querySelector * - room: the room for which to find the element in the contact list
* - style: the display style to set the element to, example: "block"
* Effects: set the display style of the element to the given style
*/
function styleElementByQuery(gadget, query, style) {
if (gadget.element.querySelector(query)) {
gadget.element.querySelector(query).style.display = style;
}
}
/* Get the element given by a contact.
* Parameters:
* - contact: the contact for which to find the element
* Effects: nothing * Effects: nothing
* Returns: the element corresponding to the given contact * Returns: the contact element corresponding to the given room
*/
function getElementFromContact(gadget, contact) {
return gadget.element.querySelector("#chat-contact-" + nameToId(contact));
}
/* Highlight the current contact.
* Parameters:
* - contact: the current contact to be highlighted
* - previous_contact: the previously highlighted contact
* Effects:
* - highlight contact by adding the "current" class on its contact element
* - unhighlight previous_contact by removing the "current class"
*/
function highlightContact(gadget, contact) {
var contact_element = getElementFromContact(gadget, contact),
previous_element = getElementFromContact(gadget, gadget.state.contact);
contact_element.classList.add("current");
if (previous_element) {
previous_element.classList.remove("current");
}
}
/* Notify the user.
* Parameters:
* - room: the room that triggers the notification
* - notify: true to notify, false to remove notification
* Effects:
* - toggle "notify" class on the contact element corresponding to room
* - toggle the favicon between alert and default icons
*/ */
function notifyStatus(gadget, room, notify) { function getContactFromRoom(gadget, room) {
var contact_element = getElementFromContact(gadget, room), return gadget.element.querySelector("#chat-contact-" + nameToId(room));
favicon_element = document.querySelector("link[rel*='icon']")
|| document.createElement("link");
if (notify) {
contact_element.classList.add("notify");
favicon_element.href = gadget.state.alert_icon_url;
} else {
contact_element.classList.remove("notify");
favicon_element.href = gadget.state.default_icon_url;
}
favicon_element.type = "image/x-icon";
favicon_element.rel = "shortcut icon";
document.head.appendChild(favicon_element);
} }
...@@ -158,13 +99,13 @@ ...@@ -158,13 +99,13 @@
chat.appendChild(document.createTextNode("[" chat.appendChild(document.createTextNode("["
+ new Date(message.time).toLocaleString() + "] " + message.name + ": " + new Date(message.time).toLocaleString() + "] " + message.name + ": "
)); ));
// Loop through all potential URLs in the message // Loop through all potential URLs in the message
// matches[i] is the non-link content, matches[i + 1] is the actual link // matches[i] is the non-link content, matches[i + 1] is the actual link
matches = message.content.split(url_regex); matches = message.content.split(url_regex);
for (i = 0; i < matches.length - 1; i += 2) { for (i = 0; i < matches.length - 1; i += 2) {
chat.appendChild(document.createTextNode(matches[i])); chat.appendChild(document.createTextNode(matches[i]));
// If 2d + 1 >= L, then the potential URL has only single letters, // If 2d + 1 >= L, then the potential URL has only single letters,
// so ignore it to eliminate acronyms like e.g., i.e., U.S.A., etc. // so ignore it to eliminate acronyms like e.g., i.e., U.S.A., etc.
link_string = matches[i + 1]; link_string = matches[i + 1];
...@@ -173,14 +114,14 @@ ...@@ -173,14 +114,14 @@
chat.appendChild(document.createTextNode(link_string)); chat.appendChild(document.createTextNode(link_string));
} else { } else {
is_image = false; is_image = false;
// Add a protocol to transform relative URLs into absolute URLs // Add a protocol to transform relative URLs into absolute URLs
if (link_string.indexOf(":") !== -1) { if (link_string.indexOf(":") !== -1) {
absolute_url = link_string; absolute_url = link_string;
} else { } else {
absolute_url = "http://" + link_string; absolute_url = "http://" + link_string;
} }
// Create an image if the URL ends with one of the image extensions // Create an image if the URL ends with one of the image extensions
for (j = 0; j < image_extensions.length; j += 1) { for (j = 0; j < image_extensions.length; j += 1) {
if (stringEndsWith(link_string, image_extensions[j])) { if (stringEndsWith(link_string, image_extensions[j])) {
...@@ -191,7 +132,7 @@ ...@@ -191,7 +132,7 @@
break; break;
} }
} }
// Otherwise, create a link // Otherwise, create a link
if (!is_image) { if (!is_image) {
link = document.createElement("a"); link = document.createElement("a");
...@@ -214,12 +155,35 @@ ...@@ -214,12 +155,35 @@
.setState({ .setState({
name: null, name: null,
// the currently active room, to show in the right panel
room: null, room: null,
contact: null,
// true if the room is a chat box, false if the room is a contact panel
is_chat: false,
// a set of the names of all active rooms with number of messages in each
// e.g. {small_room: 3, large_room: 1337}
room_set: {}, room_set: {},
// a set of the names of all rooms that have unread messages with boolean
// e.g. {read_room: false, unread_room: true}
unread_room_set: {},
// a set of XXX
delay_refresh_dict: {},
// true to use alert_icon_url, false to use default_icon_url
favicon_alert: false,
alert_icon_url: "https://pricespy.co.nz/favicon.ico", alert_icon_url: "https://pricespy.co.nz/favicon.ico",
default_icon_url: "https://softinst75770.host.vifib.net/" default_icon_url: "https://softinst75770.host.vifib.net/"
+ "erp5/web_site_module/web_chat/favicon.ico" + "erp5/web_site_module/web_chat/favicon.ico",
// toggle refresh_chat to force call delayRefresh
refresh_chat: false,
// toggle update to force call onStateChange
update: false
}) })
...@@ -238,24 +202,86 @@ ...@@ -238,24 +202,86 @@
}) })
// Set the chat title when the current room changes. /* Render everything again when the current state changes.
* Parameters: all properties in gadget.state
* Effects:
* - in right panel, only display the currently active room or contact
* - in right panel, set the title based on the room or contact
* - in contact list, only add styles for unread messages and current room
* - set favicon depending on whether there are new unread messages
*/
.onStateChange(function (modification_dict) { .onStateChange(function (modification_dict) {
var gadget = this; var gadget = this,
if (modification_dict.hasOwnProperty("room")) { i,
styleElementByQuery(gadget, room_list = gadget.element.querySelector(".chat-right-panel").children,
"#room-gadget-" + nameToId(gadget.state.contact), "none"); contact_list = gadget.element.querySelector(".contact-list").children,
styleElementByQuery(gadget, ".chat-right-panel-chat", "flex"); favicon_element = document.querySelector("link[rel*='icon']")
gadget.element.querySelector(".chat-title") || document.createElement("link");
.textContent = "Room: " + modification_dict.room;
} else if (modification_dict.hasOwnProperty("contact")) { // hide all room gadget elements
styleElementByQuery(gadget, for (i = 0; i < room_list.length; i += 1) {
"#room-gadget-" + nameToId(gadget.state.contact), "none"); if (room_list[i].getAttribute("data-gadget-url")) {
styleElementByQuery(gadget, room_list[i].style.display = "none";
"#room-gadget-" + nameToId(modification_dict.contact), "block"); }
styleElementByQuery(gadget, ".chat-right-panel-chat", "none"); }
gadget.element.querySelector(".chat-title")
.textContent = "Contact: " + modification_dict.contact; // remove all styles from contact elements
for (i = 0; i < contact_list.length; i += 1) {
if (contact_list[i].classList.contains("current")) {
contact_list[i].classList.remove("current");
contact_list[i].classList.remove("notify");
}
// add styles to contacts with unread messages
if (gadget.state.unread_room_set[contact_list[i].id]) {
contact_list[i].classList.add("notify");
}
}
// set favicon depending on whether there are new unread messages
if (gadget.state.favicon_alert) {
favicon_element.href = gadget.state.alert_icon_url;
} else {
favicon_element.href = gadget.state.default_icon_url;
}
favicon_element.type = "image/x-icon";
favicon_element.rel = "shortcut icon";
document.head.appendChild(favicon_element);
// add style to the current contact
if (modification_dict.hasOwnProperty("room") ||
modification_dict.hasOwnProperty("is_chat")) {
getContactFromRoom(gadget, gadget.state.room).classList.add("current");
// if a chat room is active, show chat panel
if (gadget.state.is_chat) {
gadget.element.querySelector(".chat-right-panel-chat")
.style.display = "flex";
gadget.element.querySelector(".chat-title")
.textContent = "Room: " + gadget.state.room;
} else {
// otherwise, hide chat panel and show contact panel
gadget.element.querySelector(".chat-right-panel-chat")
.style.display = "none";
gadget.element.querySelector("#room-gadget-" +
nameToId(gadget.state.room)).style.display = "block";
gadget.element.querySelector(".chat-title")
.textContent = "Contact: " + gadget.state.room;
}
}
// set update to false so that setting update to true calls onStateChange
gadget.state.update = false;
// refresh the current room
if (gadget.state.refresh_chat) {
gadget.state.refresh_chat = false;
if (gadget.state.delay_refresh_dict[gadget.state.room]) {
gadget.state.delay_refresh_dict[gadget.state.room].cancel();
}
return gadget.delayRefresh(gadget.state.room, 0);
} }
}) })
...@@ -271,7 +297,8 @@ ...@@ -271,7 +297,8 @@
*/ */
.declareMethod("render", function () { .declareMethod("render", function () {
var gadget = this; var gadget = this,
user_email;
return gadget.requireSetting( return gadget.requireSetting(
"jio_storage_description", "jio_storage_description",
"jio_configurator", "jio_configurator",
...@@ -291,9 +318,9 @@ ...@@ -291,9 +318,9 @@
]); ]);
}) })
.push(function (setting_list) { .push(function (setting_list) {
user_email = setting_list[0];
return gadget.changeState({ return gadget.changeState({
name: setting_list[0], name: user_email,
contact: setting_list[0],
local_sub_storage: setting_list[1], local_sub_storage: setting_list[1],
default_jio_type: setting_list[2] === "none" ? default_jio_type: setting_list[2] === "none" ?
null : setting_list[2], null : setting_list[2],
...@@ -306,9 +333,13 @@ ...@@ -306,9 +333,13 @@
.push(function () { .push(function () {
gadget.element.querySelector(".send-form input[type='text']") gadget.element.querySelector(".send-form input[type='text']")
.onfocus = function () { .onfocus = function () {
return notifyStatus(gadget, gadget.state.room, false); gadget.state.unread_room_set[gadget.state.room] = false;
return gadget.changeState({update: true});
}; };
return gadget.createContact(gadget.state.contact); return gadget.createContact(user_email);
})
.push(function () {
return gadget.changeState({room: user_email});
}) })
); );
}) })
...@@ -316,63 +347,59 @@ ...@@ -316,63 +347,59 @@
/* Create a new contact. /* Create a new contact.
* Parameters: * Parameters:
* - contact: the name of the contact * - room: the name of the contact
* Effects: * Effects:
* - append a new contact to the contact list * - append a new contact to the contact list
* - create a new room gadget * - create a new room gadget
* - show the chat box * - show the chat box
*/ */
.declareMethod("createContact", function (contact) { .declareMethod("createContact", function (room) {
var gadget = this; var gadget = this;
return gadget.appendContact(contact) return gadget.appendContact(room)
.push(function () { .push(function () {
return gadget.createRoom(contact); return gadget.createRoom(room);
}) })
.push(function () { .push(function () {
return gadget.changeState({contact: contact}); return gadget.changeState({room: room, is_chat: false});
}); });
}) })
/* Append a new contact element to the contact list. /* Append a new contact element to the contact list.
* Parameters: * Parameters:
* - contact: the name of the contact * - room: the name of the contact
* Effects: * Effects:
* - if the contact is not blank and not a duplicate, then: * - if the name is not blank and not a duplicate, then:
* - create and append a new contact element to the contact list * - create and append a new contact element to the contact list
* - set its ID to a querySelector-safe translation of its name * - set its ID to a querySelector-safe translation of its name
* - highlight it and add an event listener to highlight it on click * - highlight it and add an event listener to highlight it on click
* and either change to the room or the contact * and either change to the room or the contact panel
*/ */
.declareMethod("appendContact", function (contact) { .declareMethod("appendContact", function (room) {
var gadget = this, var gadget = this,
contact_element; contact_element;
if (!contact.trim()) { if (!room.trim()) {
throw "An invisible name is not allowed! You couldn't click on it!"; throw "An invisible name is not allowed! You couldn't click on it!";
} }
if (getElementFromContact(gadget, contact)) { if (getContactFromRoom(gadget, room)) {
throw "A contact with the same name already exists!"; throw "A contact with the same name already exists!";
} }
contact_element = document.createElement("li"); contact_element = document.createElement("li");
contact_element.appendChild(document.createTextNode(contact)); contact_element.appendChild(document.createTextNode(room));
contact_element.setAttribute("id", "chat-contact-" + nameToId(contact)); contact_element.setAttribute("id", "chat-contact-" + nameToId(room));
gadget.element.querySelector(".contact-list") gadget.element.querySelector(".contact-list")
.appendChild(contact_element); .appendChild(contact_element);
highlightContact(gadget, contact);
contact_element.addEventListener("click", function () { contact_element.addEventListener("click", function () {
return notifyStatus(gadget, contact, false) gadget.state.unread_room_set[room] = false;
.push(function () { if (gadget.state.room_set[room] !== undefined) {
highlightContact(gadget, contact); return gadget.changeRoom(room);
if (gadget.state.room_set[contact]) { }
return gadget.changeRoom(contact); return gadget.changeState({room: room, is_chat: false, update: true});
}
return gadget.changeState({contact: contact});
});
}, false); }, false);
}) })
...@@ -430,12 +457,15 @@ ...@@ -430,12 +457,15 @@
.declareMethod("changeRoom", function (room) { .declareMethod("changeRoom", function (room) {
var gadget = this; var gadget = this;
return gadget.changeState({room: room}) return gadget.changeState({room: room, is_chat: true})
.push(function () { .push(function () {
if (!gadget.state.room_set[room]) { if (gadget.state.room_set[room] === undefined) {
gadget.state.room_set[room] = true; gadget.state.room_set[room] = 0;
return gadget.deployMessage({
content: gadget.state.name + " has joined.",
color: "orange"
});
} }
return gadget.refreshChat();
}); });
}) })
...@@ -459,7 +489,10 @@ ...@@ -459,7 +489,10 @@
}) })
.push(function () { .push(function () {
return gadget.storeArchive(message); return gadget.storeArchive(message);
}); })
.push(function () {
return gadget.changeState({refresh_chat: true});
})
}) })
...@@ -547,21 +580,53 @@ ...@@ -547,21 +580,53 @@
}) })
/* Refresh the chat by polling with increasing delays.
* Parameters:
* - room: the room to refresh
* - delay: the time in milliseconds to wait before refreshing again
* Effects:
* - call refreshChat and wait delay milliseconds before calling it again
*/
.declareMethod("delayRefresh", function (room, delay) {
var gadget = this;
console.log(room, delay);
return new RSVP.Queue()
.push(function () {
return RSVP.all([
RSVP.delay(delay),
// gadget.refreshChat(room)
]);
})
.push(function () {
gadget.state.delay_refresh_dict[room] = new RSVP.Queue()
.push(function () {
return gadget.delayRefresh(room, delay + 500);
});
})
})
/* Overwrite the chat box with chats from the jIO storage. /* Overwrite the chat box with chats from the jIO storage.
* Parameters: nothing * Parameters:
* - room: the room to refresh
* Effects: * Effects:
* - get a sorted list of all chats in the current room from jIO storage * - get a sorted list of all chats in the current room from jIO storage
* - remove the entire chat box and append all chats from jIO storage * - remove the entire chat box and append all chats from jIO storage
* - scroll the chat list down to show the chat element * - scroll the chat list down to show the chat element
*/ */
.declareMethod("refreshChat", function () { .declareMethod("refreshChat", function (room) {
var gadget = this; var gadget = this,
return gadget.getDeclaredGadget("room-gadget-" + gadget.state.room) room_gadget;
.push(function (room_gadget) { return gadget.getDeclaredGadget("room-gadget-" + room)
.push(function (sub_gadget) {
room_gadget = sub_gadget;
return room_gadget.wrapJioCall("repair");
})
.push(function () {
return room_gadget.wrapJioCall("allDocs", [{ return room_gadget.wrapJioCall("allDocs", [{
query: 'portal_type: "Text Post" AND room: "' query: 'portal_type: "Text Post" AND room: "' + room + '"',
+ gadget.state.room + '"',
limit: [0, 1000000], limit: [0, 1000000],
sort_on: [["date_ms", "ascending"]], sort_on: [["date_ms", "ascending"]],
select_list: ["content"] select_list: ["content"]
...@@ -570,23 +635,31 @@ ...@@ -570,23 +635,31 @@
.push(function (result_list) { .push(function (result_list) {
var i, message, message_list = [], var i, message, message_list = [],
container = gadget.element.querySelector(".chat-list"); container = gadget.element.querySelector(".chat-list");
for (i = 0; i < result_list.data.total_rows; i += 1) {
try {
message = JSON.parse(result_list.data.rows[i].value.content);
if (message && typeof message === "object") {
message_list.push(message);
}
} catch (ignore) {}
}
while (container.firstChild) { if (result_list.data.total_rows > gadget.state.room_set[room]) {
container.removeChild(container.firstChild); gadget.state.room_set[room] = result_list.data.total_rows;
} gadget.state.unread_room_set[room] = true;
for (i = 0; i < message_list.length; i += 1) { for (i = 0; i < result_list.data.total_rows; i += 1) {
container.appendChild(messageToChat(message_list[i])); try {
message = JSON.parse(result_list.data.rows[i].value.content);
if (message && typeof message === "object") {
message_list.push(message);
}
} catch (ignore) {}
}
if (room === gadget.state.room) {
while (container.firstChild) {
container.removeChild(container.firstChild);
}
for (i = 0; i < message_list.length; i += 1) {
container.appendChild(messageToChat(message_list[i]));
}
container.scrollTop = container.scrollHeight;
}
return gadget.changeState({refresh_chat: true});
} }
container.scrollTop = container.scrollHeight; })
});
}) })
...@@ -602,6 +675,7 @@ ...@@ -602,6 +675,7 @@
split = chat.slice(1).split(" "), split = chat.slice(1).split(" "),
command = split.shift(), command = split.shift(),
argument = split.join(" "), argument = split.join(" "),
room_element = getContactFromRoom(gadget, gadget.state.room),
promise_list = [], promise_list = [],
help_list = [ help_list = [
"Available commands:", "Available commands:",
...@@ -614,7 +688,7 @@ ...@@ -614,7 +688,7 @@
// change to a room that has already been joined // change to a room that has already been joined
case "join": case "join":
if (gadget.state.room_set[argument]) { if (gadget.state.room_set[argument] !== undefined) {
return gadget.changeRoom(argument); return gadget.changeRoom(argument);
} }
return gadget.deployNotification({ return gadget.deployNotification({
...@@ -633,14 +707,15 @@ ...@@ -633,14 +707,15 @@
color: "red" color: "red"
}); });
} }
gadget.state.room_set[gadget.state.room] = false; gadget.state.room_set[gadget.state.room] = undefined;
room_element.parentNode.removeChild(room_element);
return gadget.deployMessage({ return gadget.deployMessage({
content: gadget.state.name + " has quit.", content: gadget.state.name + " has quit.",
color: "orange" color: "orange"
}); })
}) .push(function () {
.push(function () { return gadget.changeRoom(gadget.state.name);
return gadget.changeRoom(gadget.state.name); });
}); });
// quit the entire chat // quit the entire chat
...@@ -656,6 +731,12 @@ ...@@ -656,6 +731,12 @@
})); }));
} }
return RSVP.all(promise_list); return RSVP.all(promise_list);
default:
return gadget.deployNotification({
content: "'" + argument + "' is not a valid command.",
color: "red"
});
} }
}) })
...@@ -666,17 +747,9 @@ ...@@ -666,17 +747,9 @@
var gadget = this, var gadget = this,
content; content;
switch (event.target.className) { switch (event.target.className) {
case "sync-form":
return gadget.getDeclaredGadget("room-gadget-" + gadget.state.room)
.push(function (room_gadget) {
return room_gadget.wrapJioCall("repair");
})
.push(function () {
return gadget.refreshChat();
});
case "edit-form": case "edit-form":
content = resetInputValue(event.target.elements.content); content = resetInputValue(event.target.elements.content);
return gadget.changeState({contact: content}); return gadget.changeState({room: content});
case "join-form": case "join-form":
content = resetInputValue(event.target.elements.content); content = resetInputValue(event.target.elements.content);
return gadget.createContact(content); return gadget.createContact(content);
...@@ -685,16 +758,7 @@ ...@@ -685,16 +758,7 @@
if (content.indexOf("/") === 0) { if (content.indexOf("/") === 0) {
return gadget.parseCommand(content); return gadget.parseCommand(content);
} }
return gadget.deployMessage({content: content}) return gadget.deployMessage({content: content});
.push(function () {
return gadget.getDeclaredGadget("room-gadget-" + gadget.state.room);
})
.push(function (room_gadget) {
return room_gadget.wrapJioCall("repair");
})
.push(function () {
return gadget.refreshChat();
})
} }
}) })
...@@ -714,7 +778,7 @@ ...@@ -714,7 +778,7 @@
var promise_list = [], room; var promise_list = [], room;
for (room in gadget.state.room_set) { for (room in gadget.state.room_set) {
if (gadget.state.room_set.hasOwnProperty(room) if (gadget.state.room_set.hasOwnProperty(room)
&& gadget.state.room_set[room]) { && gadget.state.room_set[room] !== undefined) {
promise_list.push(gadget.deployMessage({ promise_list.push(gadget.deployMessage({
content: gadget.state.name + " has quit.", content: gadget.state.name + " has quit.",
room: room, room: room,
......
...@@ -10,9 +10,11 @@ ...@@ -10,9 +10,11 @@
<key> <string>_Access_contents_information_Permission</string> </key> <key> <string>_Access_contents_information_Permission</string> </key>
<value> <value>
<tuple> <tuple>
<string>Anonymous</string>
<string>Assignee</string> <string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Auditor</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string> <string>Owner</string>
</tuple> </tuple>
...@@ -22,6 +24,7 @@ ...@@ -22,6 +24,7 @@
<key> <string>_Add_portal_content_Permission</string> </key> <key> <string>_Add_portal_content_Permission</string> </key>
<value> <value>
<tuple> <tuple>
<string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Manager</string> <string>Manager</string>
</tuple> </tuple>
...@@ -40,6 +43,8 @@ ...@@ -40,6 +43,8 @@
<key> <string>_Modify_portal_content_Permission</string> </key> <key> <string>_Modify_portal_content_Permission</string> </key>
<value> <value>
<tuple> <tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string> <string>Manager</string>
</tuple> </tuple>
</value> </value>
...@@ -48,9 +53,11 @@ ...@@ -48,9 +53,11 @@
<key> <string>_View_Permission</string> </key> <key> <string>_View_Permission</string> </key>
<value> <value>
<tuple> <tuple>
<string>Anonymous</string>
<string>Assignee</string> <string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Auditor</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string> <string>Owner</string>
</tuple> </tuple>
......
...@@ -10,9 +10,11 @@ ...@@ -10,9 +10,11 @@
<key> <string>_Access_contents_information_Permission</string> </key> <key> <string>_Access_contents_information_Permission</string> </key>
<value> <value>
<tuple> <tuple>
<string>Anonymous</string>
<string>Assignee</string> <string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Auditor</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string> <string>Owner</string>
</tuple> </tuple>
...@@ -22,6 +24,7 @@ ...@@ -22,6 +24,7 @@
<key> <string>_Add_portal_content_Permission</string> </key> <key> <string>_Add_portal_content_Permission</string> </key>
<value> <value>
<tuple> <tuple>
<string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Manager</string> <string>Manager</string>
</tuple> </tuple>
...@@ -40,6 +43,8 @@ ...@@ -40,6 +43,8 @@
<key> <string>_Modify_portal_content_Permission</string> </key> <key> <string>_Modify_portal_content_Permission</string> </key>
<value> <value>
<tuple> <tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string> <string>Manager</string>
</tuple> </tuple>
</value> </value>
...@@ -48,9 +53,11 @@ ...@@ -48,9 +53,11 @@
<key> <string>_View_Permission</string> </key> <key> <string>_View_Permission</string> </key>
<value> <value>
<tuple> <tuple>
<string>Anonymous</string>
<string>Assignee</string> <string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
<string>Auditor</string>
<string>Manager</string> <string>Manager</string>
<string>Owner</string> <string>Owner</string>
</tuple> </tuple>
......
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