Commit b9917283 authored by Eugene Shen's avatar Eugene Shen

Squeeze WebRTC authentication into chat panel

Make WebRTC gadget spawn a new hidden div inside the chat panel
instead of indefinitely expanding downwards, highlight current room,
remove automatic login and authentication, add field for hateoas URL,
move all utility functions such as logError into gadget_global.js,
add hasOwnProperty, send join/quit notifications in bundles once more,
fix cannot-make-second-connection bug by resetting host candidate,
change declareService to submit onEvent, split submit buttons among
separate forms, and declare chat panel functions as gadget methods.
parent af967d44
body {
padding: 20px;
}
error {
color: orange;
.error {
color: red;
}
h3 {
color: brown;
......@@ -16,7 +16,7 @@ label {
display: block;
}
input[type="text"] {
width: 360px;
width: 50%;
}
.radio-item {
display: inline-block;
......@@ -28,7 +28,7 @@ textarea {
.chat-box {
display: flex;
width: 100%;
height: 80vh;
min-height: 80vh;
}
.chat-left-panel {
display: flex;
......@@ -46,6 +46,11 @@ textarea {
border: 1.5px solid;
box-sizing: border-box;
}
.chat-right-panel-chat {
display: flex;
flex-direction: inherit;
flex: 1;
}
.contact-list {
flex: 1;
padding: 0;
......@@ -88,4 +93,7 @@ img {
.contact-list li.notify {
font-weight: bold;
color: red;
}
.contact-list li.current {
color: orange;
}
\ No newline at end of file
......@@ -55,25 +55,16 @@
<input type="text" name="remote_dav_pass" placeholder="correct horse battery staple" />
<h3>Default WebRTC Configuration</h3>
<label>Automatically connect to own room:
<input type="checkbox" name="auto" />
</label>
<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" />
<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" value="Login!" />
</form>
<form class="room-form">
<h3>Join Rooms</h3>
<input type="text" name="room" required="required" />
<br />
<input type="submit" name="host" value="Create a new room!" />
<input type="submit" name="guest" value="Join an existing room!" />
<input type="submit" name="login" value="Login!" />
</form>
</body>
</html>
\ No newline at end of file
......@@ -17,18 +17,30 @@
<div class="chat-left-panel">
<h4 class="center">Contacts</h4>
<ul class="contact-list"></ul>
<form class="manage-form">
<input type="submit" name="sync" value="Synchronize!" />
<input type="submit" name="contact" value="Add new contact!" />
<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">
<input type="text" name="content" />
<input type="submit" value="Add new contact (join existing room as guest)!" />
</form>
<form class="make-form">
<input type="text" name="content" />
<input type="submit" value="Add new room (make new room as host)!" />
</form>
</div>
<div class="chat-right-panel">
<h4 class="chat-title center"></h4>
<ul class="chat-list"></ul>
<form class="send-form">
<input type="text" name="content" />
<input type="submit" name="send" value="Send!" />
</form>
<div class="chat-right-panel-chat">
<ul class="chat-list"></ul>
<form class="send-form">
<input type="text" name="content" />
<input type="submit" name="send" value="Send!" />
</form>
</div>
</div>
</div>
</body>
......
......@@ -11,40 +11,53 @@
<script src="gadget_erp5_chat_webrtc.js"></script>
</head>
<body>
<h3 class="webrtc-heading"></h3>
<p class="error"></p>
<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>Dropbox folder:</label>
<input type="text" name="dropbox_url" 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" />
<br />
<input type="submit" value="Update information!" />
</form>
<form class="auth-form">
<label>
<input type="radio" name="auth" value="erp5" required="required" />
ERP5, URL:
<input type="text" name="erp5_url" placeholder="https://softinst75770.host.vifib.net/erp5/webrtc_rooms_module/" />
ERP5
</label>
<label>
<input type="radio" name="auth" value="dropbox" required="required" />
Dropbox, Folder:
<input type="text" name="dropbox_url" placeholder="/Apps/OfficeJS Chat" />
Dropbox
</label>
<input type="submit" value="Authenticate!" />
</form>
<form class="host-offer-form">
<label>Paste your guest's offer in this box:</label>
<textarea rows="10" cols="80" name="send"></textarea>
<textarea rows="5" cols="80" name="send"></textarea>
<input type="submit" value="Paste it!" />
</form>
<form class="host-answer-form">
<p>This is your answer. Send it to your guest!</p>
<p class="receive"></p>
<textarea rows="5" cols="80" name="receive" readonly></textarea>
</form>
<form class="guest-offer-form">
<p>This is your new offer. Send it to your host!</p>
<p class="receive"></p>
<textarea rows="5" cols="80" name="receive" readonly></textarea>
<input type="submit" value="I sent it to my host." />
</form>
<form class="guest-answer-form">
<label>Now, paste your host's answer in this box:</label>
<textarea rows="10" cols="80" name="send"></textarea>
<textarea rows="5" cols="80" name="send"></textarea>
<input type="submit" value="Paste it!" />
</form>
</body>
......
/*global window, RSVP, FileReader */
/*jslint indent: 2, maxerr: 3, unparam: true */
(function (window, RSVP, FileReader) {
"use strict";
window.loopEventListener = function (target, type, useCapture, callback,
prevent_default) {
//////////////////////////
// Infinite event listener (promise is never resolved)
// eventListener is removed when promise is cancelled/rejected
//////////////////////////
var handle_event_callback,
callback_promise;
if (prevent_default === undefined) {
prevent_default = true;
}
function cancelResolver() {
if ((callback_promise !== undefined) &&
(typeof callback_promise.cancel === "function")) {
callback_promise.cancel();
}
}
function canceller() {
if (handle_event_callback !== undefined) {
target.removeEventListener(type, handle_event_callback, useCapture);
}
cancelResolver();
}
function itsANonResolvableTrap(resolve, reject) {
var result;
handle_event_callback = function (evt) {
if (prevent_default) {
evt.stopPropagation();
evt.preventDefault();
}
cancelResolver();
try {
result = callback(evt);
} catch (e) {
result = RSVP.reject(e);
}
callback_promise = result;
new RSVP.Queue()
.push(function () {
return result;
})
.push(undefined, function (error) {
if (!(error instanceof RSVP.CancellationError)) {
canceller();
reject(error);
}
});
};
target.addEventListener(type, handle_event_callback, useCapture);
}
return new RSVP.Promise(itsANonResolvableTrap, canceller);
};
window.promiseEventListener = function (target, type, useCapture) {
//////////////////////////
// Resolve the promise as soon as the event is triggered
// eventListener is removed when promise is cancelled/resolved/rejected
//////////////////////////
var handle_event_callback;
function canceller() {
target.removeEventListener(type, handle_event_callback, useCapture);
}
function resolver(resolve) {
handle_event_callback = function (evt) {
canceller();
evt.stopPropagation();
evt.preventDefault();
resolve(evt);
return false;
};
target.addEventListener(type, handle_event_callback, useCapture);
}
return new RSVP.Promise(resolver, canceller);
};
window.promiseReadAsText = function (file) {
return new RSVP.Promise(function (resolve, reject) {
var reader = new FileReader();
reader.onload = function (evt) {
resolve(evt.target.result);
};
reader.onerror = function (evt) {
reject(evt);
};
reader.readAsText(file);
});
};
window.promiseDoWhile = function (loopFunction, input) {
// calls loopFunction(input) until it returns a non positive value
// this queue is to protect the inner loop queue from the
// `promiseDoWhile` caller, avoiding it to enqueue the inner
// loop queue.
return new RSVP.Queue()
.push(function () {
// here is the inner loop queue
var loop_queue = new RSVP.Queue();
function iterate(previous_iteration_result) {
if (!previous_iteration_result) {
return input;
}
loop_queue.push(iterate);
return loopFunction(input);
}
return loop_queue
.push(function () {
return loopFunction(input);
})
.push(iterate);
});
};
window.logError = function (error) {
console.log(error);
};
window.logQueue = function (action) {
return new RSVP.Queue()
.push(function () {
return action;
})
.push(null, logError);
};
window.styleElementByQuery = function (gadget, query, style) {
gadget.state_parameter_dict.element
.querySelector(query).style.display = style;
}
window.resetInputValue = function (element) {
const value = element.value;
element.value = "";
return value;
};
window.pollUntilNotNull = function (
gadget, delay_ms, timeout_ms,
nullableFunction, callbackFunction) {
if (callbackFunction === undefined) {
callbackFunction = function () {};
}
return new RSVP.Queue()
.push(function () {
return nullableFunction();
})
.push(function (result) {
if (result !== null) {
return callbackFunction(result);
} else {
return RSVP.any([
RSVP.timeout(timeout_ms),
promiseDoWhile(function () {
return new RSVP.Queue()
.push(function () {
return RSVP.delay(delay_ms);
})
.push(function () {
return nullableFunction();
})
.push(function (result) {
if (result === null) {
return null;
} else {
return callbackFunction(result);
}
})
.push(function (nullable) {
return nullable === null;
})
.push(null, logError);
})
]);
}
});
};
}(window, RSVP, FileReader));
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Web Script" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Change_local_roles_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>contributor/person_module/1</string>
<string>classification/collaborative/team</string>
</tuple>
</value>
</item>
<item>
<key> <string>content_md5</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>gadget_global.js</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>rjs_gadget_global_js</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value> <string>en</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Web Script</string> </value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>gadget_global.js</string> </value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>001</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
web_page_module/adapter_js
web_page_module/fast_priority_queue_js
web_page_module/gadget_erp5_chat*
web_page_module/rjs_gadget_global_js
web_site_module/web_chat/**
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment