Commit 69670067 authored by Eugene Shen's avatar Eugene Shen

Actually add chat room gadget to bt5

Add gadget_erp5_chat_room to the business template after forgetting to,
remove fast priority queue because everything is already sorted,
and make both contact list and chat list scroll with a fixed height.
parent 05a213ef
/**
* FastPriorityQueue.js : a fast heap-based priority queue in JavaScript.
* (c) the authors
* Licensed under the Apache License, Version 2.0.
*
* Speed-optimized heap-based priority queue for modern browsers and JavaScript engines.
*
* Usage :
Installation (in shell, if you use node):
$ npm install fastpriorityqueue
Running test program (in JavaScript):
// var FastPriorityQueue = require("fastpriorityqueue");// in node
var x = new FastPriorityQueue();
x.add(1);
x.add(0);
x.add(5);
x.add(4);
x.add(3);
x.peek(); // should return 0, leaves x unchanged
x.size; // should return 5, leaves x unchanged
while(!x.isEmpty()) {
console.log(x.poll());
} // will print 0 1 3 4 5
x.trim(); // (optional) optimizes memory usage
*/
"use strict";
var defaultcomparator = function (a, b) {
return a < b;
};
// the provided comparator function should take a, b and return *true* when a < b
function FastPriorityQueue(comparator) {
this.array = [];
this.size = 0;
this.compare = comparator || defaultcomparator;
}
// Add an element the the queue
// runs in O(log n) time
FastPriorityQueue.prototype.add = function (myval) {
var i = this.size;
this.array[this.size] = myval;
this.size += 1;
var p;
var ap;
while (i > 0) {
p = (i - 1) >> 1;
ap = this.array[p];
if (!this.compare(myval, ap)) {
break;
}
this.array[i] = ap;
i = p;
}
this.array[i] = myval;
};
// replace the content of the heap by provided array and "heapifies it"
FastPriorityQueue.prototype.heapify = function (arr) {
this.array = arr;
this.size = arr.length;
var i;
for (i = (this.size >> 1); i >= 0; i--) {
this._percolateDown(i);
}
};
// for internal use
FastPriorityQueue.prototype._percolateUp = function (i) {
var myval = this.array[i];
var p;
var ap;
while (i > 0) {
p = (i - 1) >> 1;
ap = this.array[p];
if (!this.compare(myval, ap)) {
break;
}
this.array[i] = ap;
i = p;
}
this.array[i] = myval;
};
// for internal use
FastPriorityQueue.prototype._percolateDown = function (i) {
var size = this.size;
var hsize = this.size >>> 1;
var ai = this.array[i];
var l;
var r;
var bestc;
while (i < hsize) {
l = (i << 1) + 1;
r = l + 1;
bestc = this.array[l];
if (r < size) {
if (this.compare(this.array[r], bestc)) {
l = r;
bestc = this.array[r];
}
}
if (!this.compare(bestc, ai)) {
break;
}
this.array[i] = bestc;
i = l;
}
this.array[i] = ai;
};
// Look at the top of the queue (a smallest element)
// executes in constant time
//
// This function assumes that the priority queue is
// not empty and the caller is resposible for the check.
// You can use an expression such as
// "isEmpty() ? undefined : peek()"
// if you expect to be calling peek on an empty priority queue.
//
FastPriorityQueue.prototype.peek = function () {
return this.array[0];
};
// remove the element on top of the heap (a smallest element)
// runs in logarithmic time
//
//
// This function assumes that the priority queue is
// not empty, and the caller is responsible for the check.
// You can use an expression such as
// "isEmpty() ? undefined : poll()"
// if you expect to be calling poll on an empty priority queue.
//
// For long-running and large priority queues, or priority queues
// storing large objects, you may want to call the trim function
// at strategic times to recover allocated memory.
FastPriorityQueue.prototype.poll = function () {
var ans = this.array[0];
if (this.size > 1) {
this.array[0] = this.array[--this.size];
this._percolateDown(0 | 0);
} else {
this.size -= 1;
}
return ans;
};
// recover unused memory (for long-running priority queues)
FastPriorityQueue.prototype.trim = function () {
this.array = this.array.slice(0, this.size);
};
// Check whether the heap is empty
FastPriorityQueue.prototype.isEmpty = function () {
return this.size === 0;
};
// just for illustration purposes
var main = function () {
// main code
var x = new FastPriorityQueue(function (a, b) {
return a < b;
});
x.add(1);
x.add(0);
x.add(5);
x.add(4);
x.add(3);
while (!x.isEmpty()) {
console.log(x.poll());
}
};
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>>Chat Room Gadget</title>
<script src="rsvp.js"></script>
<script src="renderjs.js"></script>
<script src="gadget_erp5_chat_room.js"></script>
</head>
<body>
<h1>Choose Your Shared Storage</h1>
<form class="connect-form">
<label>
<input type="radio" name="jio_type" value="erp5" required="required" />
ERP5,
</label>
<label>
URL:
<input type="text" name="erp5_url" placeholder="https://softinst75770.host.vifib.net/erp5/web_site_module/hateoas" />
</label>
<label>
<input type="radio" name="jio_type" value="dav" required="required" />
WebDAV,
</label>
<label>
URL:
<input type="text" name="dav_url" placeholder="https://softinst75722.host.vifib.net/share" />
</label>
<label>
WebDAV Username:
<input type="text" name="dav_user" placeholder="eyqs" />
</label>
<label>
WebDAV Password:
<input type="text" name="dav_pass" placeholder="Aoeuidhtns" />
</label>
<label>
<input type="radio" name="jio_type" value="custom" required="required" />
Custom,
</label>
<label>
jIO Configuration:
<input type="text" name="custom_configuration" placeholder='{"type": "indexeddb", "database": "officejs-chat"}' />
</label>
<br />
<input type="submit" value="Connect!" />
</form>
</body>
</html>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Web Page" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Change_local_roles_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>classification/collaborative/team</string>
<string>contributor/person_module/1</string>
</tuple>
</value>
</item>
<item>
<key> <string>content_md5</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>gadget_erp5_chat_room.html</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>gadget_erp5_chat_room_html</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Web Page</string> </value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>OfficeJS Chat Room</string> </value>
</item>
<item>
<key> <string>version</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*jslint nomen: true, indent: 2, maxerr: 3, maxlen: 80 */
/*global window, rJS, jIO, btoa */
(function (window, rJS, jIO, btoa) {
"use strict";
rJS(window)
// State is set in erp5_page_chat_box.
// The following functions is acquired from erp5_page_chat_box.
.declareAcquiredMethod("joinNewRoom", "joinNewRoom")
/* Render the gadget.
* Parameters:
* - gadget.state: default_jio_type, default_erp5_url, default_dav_url
* Effects: pre-fill input fields with default input values
*/
.declareMethod("render", function () {
var gadget = this,
fields = gadget.element.querySelector(".connect-form").elements;
fields.jio_type.value = gadget.state.default_jio_type;
fields.erp5_url.value = gadget.state.default_erp5_url;
fields.dav_url.value = gadget.state.default_dav_url;
})
/* Create a new jIO replicate storage.
* Parameters:
* - state: query, local_sub_storage
* - fields: the jIO configuration fields from the form,
* identical to the ones used in the configurators
* Effects:
* - create a new jIO replicate storage with the given configuration
* - change to the room corresponding to the new storage
*/
.declareMethod("createJioReplicate", function () {
var gadget = this,
remote_sub_storage,
fields = gadget.element.querySelector(".connect-form").elements;
switch (fields.jio_type.value) {
case "erp5":
remote_sub_storage = {
type: "erp5",
url: fields.erp5_url.value,
default_view_reference: "view"
};
break;
case "dav":
remote_sub_storage = {
type: "query",
sub_storage: {
type: "drivetojiomapping",
sub_storage: {
type: "dav",
url: fields.dav_url.value,
basic_login: btoa(fields.dav_user + ":" + fields.dav_pass),
with_credentials: "true"
}
}
};
break;
case "custom":
remote_sub_storage = JSON.parse(fields.custom_configuration.value);
break;
}
gadget.state.storage = jIO.createJIO({
type: "replicate",
use_remote_post: true,
conflict_handling: 2,
query: gadget.state.query,
local_sub_storage: gadget.state.local_sub_storage,
remote_sub_storage: remote_sub_storage
});
return gadget.joinNewRoom(gadget.state.room);
})
/* Access the jIO replicate storage.
* Parameters:
* - method_name: the jIO method to call
* - param_list: an optional array of arguments to the method
* Effects: apply the param_list to method_name, if method_name is valid
* Returns: the result of the application of the param_list to method_name
*/
.declareMethod("wrapJioCall", function (method_name, param_list) {
var gadget = this,
method_list = [
"allDocs", "get", "put", "post", "remove", "repair",
"allAttachments", "getAttachment", "putAttachment", "removeAttachment"
];
if (method_list.indexOf(method_name) !== -1) {
return gadget.state.storage[method_name]
.apply(gadget.state.storage, param_list);
}
})
// Call createJioReplicate when the form is submitted.
.onEvent("submit", function (event) {
var gadget = this;
if (event.target.className === "connect-form") {
return gadget.createJioReplicate(event);
}
});
}(window, rJS, jIO, btoa));
\ No newline at end of file
...@@ -68,6 +68,7 @@ ...@@ -68,6 +68,7 @@
<value> <value>
<tuple> <tuple>
<string>classification/collaborative/team</string> <string>classification/collaborative/team</string>
<string>contributor/person_module/1</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -79,7 +80,7 @@ ...@@ -79,7 +80,7 @@
</item> </item>
<item> <item>
<key> <string>default_reference</string> </key> <key> <string>default_reference</string> </key>
<value> <string>fast_priority_queue.js</string> </value> <value> <string>gadget_erp5_chat_room.js</string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
...@@ -89,7 +90,7 @@ ...@@ -89,7 +90,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>fast_priority_queue_js</string> </value> <value> <string>gadget_erp5_chat_room_js</string> </value>
</item> </item>
<item> <item>
<key> <string>language</string> </key> <key> <string>language</string> </key>
...@@ -109,7 +110,7 @@ ...@@ -109,7 +110,7 @@
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>title</string> </key>
<value> <string>Fast Priority Queue JS</string> </value> <value> <string>OfficeJS Chat Room JS</string> </value>
</item> </item>
<item> <item>
<key> <string>version</string> </key> <key> <string>version</string> </key>
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
<script src="jiodev.js"></script> <script src="jiodev.js"></script>
<script src="handlebars.js"></script> <script src="handlebars.js"></script>
<script src="gadget_global.js"></script> <script src="gadget_global.js"></script>
<script src="fast_priority_queue.js"></script>
<script src="gadget_erp5_page_chat_box.js"></script> <script src="gadget_erp5_page_chat_box.js"></script>
<script class="chat-list-template" type="text/x-handlebars-template"> <script class="chat-list-template" type="text/x-handlebars-template">
{{#each list}} {{#each list}}
...@@ -45,15 +44,13 @@ ...@@ -45,15 +44,13 @@
<div class="chat-right-panel"> <div class="chat-right-panel">
<h3 class="chat-title center"> <h3 class="chat-title center">
</h3> </h3>
<div class="chat-max-height-wrapper"> <div class="chat-right-panel-chat">
<div class="chat-right-panel-chat"> <ul class="chat-list">
<ul class="chat-list"> </ul>
</ul> <form class="send-form">
<form class="send-form"> <input type="text" name="content" />
<input type="text" name="content" /> <input type="submit" name="send" value="Send!" />
<input type="submit" name="send" value="Send!" /> </form>
</form>
</div>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -214,7 +214,7 @@ ...@@ -214,7 +214,7 @@
// a dict of room names to an object with keys corresponding to // a dict of room names to an object with keys corresponding to
// their delayRefresh promise queues, i.e. queue: new RSVP.Queue() // their delayRefresh promise queues, i.e. queue: new RSVP.Queue()
// their POLL_DELAy_LIST indices, i.e. index: 3, and // their POLL_DELAY_LIST indices, i.e. index: 3, and
// whether each is currently running refreshChat, i.e. lock: true // whether each is currently running refreshChat, i.e. lock: true
delay_refresh_dict: {}, delay_refresh_dict: {},
...@@ -242,11 +242,11 @@ ...@@ -242,11 +242,11 @@
/* Join a new room. /* Join a new room.
* This function is acquired by gadget_erp5_chat_room. * This function is acquired by gadget_erp5_chat_room.
* Parameters: * Parameters:
* - room: the name of the room to join * - param_list[0]: the name of the room to join
* Requirements: * Requirements:
* - room has an associated room gadget with a valid jIO storage * - param_list[0] has an associated room gadget with a valid jIO storage
* Effects: * Effects:
* - send a message when room is joined * - send a message when the room corresponding to param_list[0] is joined
*/ */
.allowPublicAcquisition("joinNewRoom", function (param_list) { .allowPublicAcquisition("joinNewRoom", function (param_list) {
...@@ -460,7 +460,7 @@ ...@@ -460,7 +460,7 @@
room_gadget = sub_gadget; room_gadget = sub_gadget;
room_gadget.element.setAttribute("id", room_gadget.element.setAttribute("id",
"room-gadget-" + nameToId(room)); "room-gadget-" + nameToId(room));
gadget.element.querySelector(".chat-max-height-wrapper") gadget.element.querySelector(".chat-right-panel")
.appendChild(room_gadget.element); .appendChild(room_gadget.element);
return room_gadget.changeState({ return room_gadget.changeState({
room: room, room: room,
...@@ -922,4 +922,4 @@ ...@@ -922,4 +922,4 @@
}); });
}); });
}(window, document, RSVP, rJS, Handlebars, promiseEventListener)); }(window, document, RSVP, rJS, Handlebars, promiseEventListener));
\ No newline at end of file
web_page_module/adapter_js web_page_module/adapter_js
web_page_module/erp5_page_launcher* web_page_module/erp5_page_launcher*
web_page_module/fast_priority_queue_js
web_page_module/gadget_erp5_chat_panel_* web_page_module/gadget_erp5_chat_panel_*
web_page_module/gadget_erp5_chat_room_*
web_page_module/gadget_erp5_chat_webrtc_* web_page_module/gadget_erp5_chat_webrtc_*
web_page_module/gadget_erp5_nojquery_css web_page_module/gadget_erp5_nojquery_css
web_page_module/gadget_erp5_page_chat_* web_page_module/gadget_erp5_page_chat_*
......
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