Commit 637e2050 authored by Hardik Juneja's avatar Hardik Juneja Committed by hardikj

Document Viewer using webrtc module

parent 4c743377
......@@ -103,13 +103,16 @@
this.stats.modified = true;
return this.render(this.stats.options);
}
})
})
*/
.declareMethod('notifySubmitting', function () {
if (this.stats.submitted) {
this.stats.submitted = false;
return this.render(this.stats.options);
}
})
.declareMethod('notifySubmitted', function () {
if (!this.stats.submitted) {
this.stats.submitted = true;
......@@ -118,7 +121,7 @@
return this.render(this.stats.options);
}
})
*/
.declareMethod('render', function (options) {
var gadget = this,
possible_left_link_list = [
......@@ -138,7 +141,8 @@
],
possible_right_button_list = [
['save_action', 'Save', 'check', 'submit'],
['submit_action', 'Proceed', 'check', 'submit']
['submit_action', 'Proceed', 'check', 'submit'],
['refresh_action', 'Refresh', 'check', 'submit']
],
i,
klass,
......
......@@ -210,7 +210,7 @@
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>cedric.le.ninivin</string> </value>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
......@@ -224,7 +224,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>945.58607.14824.6775</string> </value>
<value> <string>953.35411.21474.17817</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -242,7 +242,7 @@
</tuple>
<state>
<tuple>
<float>1442857960.12</float>
<float>1472401645.81</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -14,16 +14,21 @@
<form class="view-web-page-form">
<div class="center">
<div class="ui-field-contain">
<div class="center">
<div class="ui-field-contain">
<label data-i18n="Title:">Title:</label>
<input type="text" name="title" value="{{title}}">
</div>
<button type="submit" data-i18n="Save" style="display:none;">Save</button>
<div class="ui-field-contain">
<label data-i18n="Public Link:"> Public Link: </label>
<button type="submit" id="generatelink" name="generatelink" data-i18n="Generate Link" style="display:block;"> Generate Link </button>
<input type="text" id="sharelink" name="share" style="display:none" value=""/>
</div>
<button type="submit" data-i18n="Save" style="display:none;">Save</button>
</div>
<div class="ui-field-contain">
    <fieldset data-role="collapsible">
<fieldset data-role="collapsible">
         <legend>Extra Properties</legend>
<div class="ui-field-contain">
......@@ -41,14 +46,15 @@
<input type="text" name="language" value="{{language}}">
</div>
<div class="ui-field-contain">
<label data-i18n="Description:">Description:</label>
<textarea name="description">{{description}}</textarea>
</div>
<div class="ui-field-contain">
<label data-i18n="Description:">Description:</label>
<textarea name="description">{{description}}</textarea>
</div>
</div>
</fieldset>
<div class='document-content'></div>
<div class='webrtc-gadget'></div>
</div>
......
......@@ -218,7 +218,7 @@
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>cedric.le.ninivin</string> </value>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
......@@ -232,7 +232,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>945.58608.59350.33075</string> </value>
<value> <string>953.27768.8271.35532</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -250,7 +250,7 @@
</tuple>
<state>
<tuple>
<float>1442858061.15</float>
<float>1471964256.18</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -100,7 +100,7 @@
return gadget.translateHtml(template(options.doc));
})
.push(function (html) {
gadget.props.element.innerHTML = html;
gadget.props.element.innerHTML += html;
return gadget.updateHeader({
title: options.doc.title + " | Web Page",
save_action: true
......@@ -110,6 +110,55 @@
return gadget.props.deferred.resolve();
});
})
.declareMethod("shareDoc", function () {
var gadget = this;
if(window.location.hash) {
var index = window.location.hash.indexOf('room=');
if (index === -1) {
var S4 = function() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
};
var room = (S4()+S4()+"-"+S4()+S4());
return new RSVP.Queue()
.push(function () {
return gadget.declareGadget(
"gadget_officejs_page_share_text.html",
{
scope: "share_text_via_webrtc",
element: gadget.props.element.querySelector(".webrtc-gadget")
}
);
})
.push(function(g){
var config = {
type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
//type: "indexeddb",
//"database": "handshake"
"type": "dav",
"url": "https://softinst67513.host.vifib.net/share/",
"basic_login": btoa("admin:vowhkida")
}
}
}
var sharelink = window.location.origin + window.location.pathname + '#page=webrtc_viewer&room='+room+'&config='+encodeURIComponent(JSON.stringify(config));
gadget.props.element.querySelector('#sharelink').value = sharelink;
gadget.props.element.querySelector('#sharelink').style.display = 'block';
gadget.props.element.querySelector('#generatelink').remove();
if(config) {
return g.initiate(room, gadget, config);
} else {
return g.initiate(room, gadget);
}
})
}
}
})
/////////////////////////////////////////
// Render text content gadget
......@@ -165,7 +214,11 @@
'submit',
true,
function (event) {
return saveContent(gadget, event);
if (document.activeElement.name === "generatelink") {
return gadget.shareDoc();
} else {
return saveContent(gadget, event);
}
}
);
});
......
......@@ -228,7 +228,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>946.59099.34897.19985</string> </value>
<value> <string>953.38231.58110.12526</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -246,7 +246,7 @@
</tuple>
<state>
<tuple>
<float>1446740911.15</float>
<float>1472570624.98</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -66,9 +66,7 @@
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>contributor/person_module/1</string>
</tuple>
<tuple/>
</value>
</item>
<item>
......@@ -249,7 +247,7 @@
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>supercedriclen</string> </value>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
......@@ -263,7 +261,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>951.28163.54980.41130</string> </value>
<value> <string>953.20991.57503.32870</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -281,7 +279,7 @@
</tuple>
<state>
<tuple>
<float>1464188897.32</float>
<float>1471536011.33</float>
<string>UTC</string>
</tuple>
</state>
......
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Share jIO</title>
<script src="rsvp.js"></script>
<script src="renderjs.js"></script>
<script src="gadget_officejs_page_share_text.js"></script>
</head>
<body>
<div class="gadget_webrtc_jio_bridge"></div>
</body>
</html>
/*global window, rJS, document, RSVP, console, DOMException */
/*jslint indent: 2, maxerr: 3 */
(function (window, rJS, document, RSVP, console, DOMException) {
"use strict";
var timeout = 600000;
function S4() {
return ('0000' + Math.floor(
Math.random() * 0x10000 /* 65536 */
).toString(16)).slice(-4);
}
function UUID() {
return S4() + S4() + "-" +
S4() + "-" +
S4() + "-" +
S4() + "-" +
S4() + S4() + S4();
}
function declareSubGadget(gadget, url) {
var container_element = gadget.state_parameter_dict.element.querySelector("." + url.split(".")[0]),
element = document.createElement("div");
container_element.innerHTML = "";
container_element.appendChild(element);
return gadget.declareGadget(url, {
element: element,
scope: url,
sandbox: "public"
});
}
function dropSubGadget(gadget, scope) {
return gadget.getDeclaredGadget(scope)
.push(function (result) {
return result.getElement();
})
.push(function (element) {
if (element.parentElement) {
element.parentElement.removeChild(element);
}
delete gadget.state_parameter_dict.scope_ip[scope];
return gadget.dropGadget(scope);
});
}
function getWebRTCScopeList(gadget) {
var result_list = [],
element_list = gadget.state_parameter_dict.element.querySelector(".gadget_webrtc_jio_bridge")
.childNodes,
i;
for (i = 0; i < element_list.length; i += 1) {
result_list.push(element_list[i].getAttribute("data-gadget-scope"));
}
return result_list;
}
function updateInfo(gadget) {
var scope_list = getWebRTCScopeList(gadget),
i,
result = "";
for (i = 0; i < scope_list.length; i += 1) {
result += gadget.state_parameter_dict.scope_ip[scope_list[i]] + "\n";
}
console.log(result);
console.log("peer count", i);
}
function sendWebRTC(gadget, rtc_gadget, scope, message) {
return rtc_gadget.send(message)
.push(undefined, function (error) {
if ((error instanceof DOMException) && (error.name === 'InvalidStateError')) {
return dropSubGadget(gadget, scope)
.push(function () {
return updateInfo(gadget);
}, function (error) {
console.log("-- Can not drop remote subgadget " + scope);
console.log(error);
return;
});
}
throw error;
});
}
rJS(window)
.ready(function (gadget) {
// Initialize the gadget local parameters
gadget.state_parameter_dict = {
counter: 0,
connecting: false,
scope_ip: {}
};
return gadget.getElement()
.push(function (element) {
gadget.state_parameter_dict.element = element;
})
.push(function () {
return updateInfo(gadget);
});
})
.allowPublicAcquisition('notifyDataChannelClosed', function (argument_list, scope) {
/*jslint unparam:true*/
var gadget = this;
return dropSubGadget(this, scope)
.push(function () {
return updateInfo(gadget);
});
})
.declareMethod('connect', function(room_id, offer, parent_scope, config) {
var gadget = this,
scope,
rtc_gadget;
return new RSVP.Queue()
.push(function(response) {
gadget.state_parameter_dict.connecting = true;
gadget.state_parameter_dict.counter += 1;
var new_element = document.createElement("div");
gadget.state_parameter_dict.element.querySelector(".gadget_webrtc_jio_bridge").appendChild(new_element);
scope = "webrtc" + gadget.state_parameter_dict.counter;
return gadget.declareGadget("gadget_webrtc_jio_bridge.html", {
scope: scope,
element: new_element
})
.push(function(gg){
rtc_gadget = gg;
return rtc_gadget.register(room_id, 'master', config);
})
.push(function(){
// https://github.com/diafygi/webrtc-ips
var ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/,
ip_list = [],
ip_dict = {},
ip_addr,
line_list = JSON.parse(offer.data).sdp.split('\n'),
i;
for (i = 0; i < line_list.length; i += 1) {
if (line_list[i].indexOf('a=candidate:') === 0) {
ip_addr = ip_regex.exec(line_list[i])[1];
if (!ip_addr.match(/^[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7}$/)) {
// Hide ipv6
if (!ip_dict[ip_addr]) {
ip_list.push(ip_addr);
ip_dict[ip_addr] = true;
}
}
}
}
gadget.state_parameter_dict.scope_ip[scope] = ip_list;
return rtc_gadget.connect({
roomid: room_id,
peerid: 'master',
to: offer.from,
offer: JSON.stringify(offer.data)
});
})
.push(function () {
return RSVP.any([
RSVP.Queue()
.push(function () {
return RSVP.delay(20000);
})
.push(function () {
console.info('-- webrtc client disappears...');
return dropSubGadget(gadget, scope);
}),
rtc_gadget.waitForConnection()
]);
})
.push(function () {
gadget.state_parameter_dict.connecting = false;
var ckeditor = window.frames[0].CKEDITOR;
var data = {'content': ckeditor.instances.editor1.getData()};
// Get all the extra properties and send it with data
var extraprops = parent_scope.props.element.querySelector('.ui-collapsible').outerHTML;
data['extra_props'] = extraprops;
// Get title
var title = parent_scope.props.element.querySelector('.ui-field-contain').childNodes[3].firstChild.value;
data['title'] = title;
rtc_gadget.send(JSON.stringify(data));
ckeditor.instances.editor1.on('key',function(e){
rtc_gadget.send(JSON.stringify({'content':ckeditor.instances.editor1.getData()}));
});
return updateInfo(gadget);
});
})
})
.declareMethod('initiate', function (roomid, scope, config) {
var gadget = this,
rtc_gadget,
blob;
return gadget.declareGadget("gadget_webrtc_jio_bridge.html")
.push(function (rg) {
// register peer
rtc_gadget = rg;
roomid = "/"+roomid+"/";
return rtc_gadget.register(roomid, 'master', config);
})
.push(function (r) {
var peerid = 'master';
return rtc_gadget.wait_until_available(roomid, peerid+'_', function (offers) {
var connections = [];
for (var offer in offers) {
connections.push(gadget.connect(roomid, JSON.parse(offers[offer].target.result), scope, config));
}
return RSVP.all(connections);
});
});
})
.declareMethod('slaveInitiate', function(roomid, g, config) {
var context = this,
rtc_gadget, gadget;
roomid = "/"+roomid+"/";
return g.notifySubmitting()
.push(function() {
return declareSubGadget(context, "gadget_webrtc_jio_bridge.html")
})
.push(function (gadget) {
context.state_parameter_dict.uuid = UUID();
context.state_parameter_dict.message_count = 0;
context.state_parameter_dict.message_dict = {};
rtc_gadget = gadget;
// register peer
if (config) {
config = JSON.parse(config)
}
return rtc_gadget.register(roomid, context.state_parameter_dict.uuid, config);
})
.push(function(peers){
var options = { roomid: roomid,
peerid: context.state_parameter_dict.uuid,
initiator: true,
to: 'master' }
return rtc_gadget.connect(options);
})
.push(null, function(error){
return g.notifySubmitted()
.push(function () {
throw error;
});
});
})
}(window, rJS, document, RSVP, console, DOMException));
\ 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>OfficeJS Editor Remote Viewer</title>
<script src="rsvp.js"></script>
<script src="renderjs.js"></script>
<script src="jquerymobile.js"></script>
<script src="gadget_officejs_page_webrtc_viewer.js"></script>
</head>
<body>
<div class="center">
<div class="ui-field-contain">
<label data-i18n="Title:">Title:</label>
<input type="text" name="title" value="">
</div>
</div>
<form class="view-web-page-form">
<button type="submit" data-i18n="Refresh" style="display:none;">Refresh</button>
</form>
<div class="ui-field-contain">
<div data-role="content" id="extra">
</div>
</div>
<div data-gadget-url="gadget_officejs_page_share_text.html"
data-gadget-scope="share_text_via_webrtc"
data-gadget-sandbox="public"></div>
<div class="viewer-content"></div>
</body>
</html>
/*globals window, RSVP, rJS*/
/*jslint indent: 2, nomen: true, maxlen: 80*/
(function (window, RSVP, rJS) {
"use strict";
function getMaxHeight(wrap_obj) {
var height;
if (wrap_obj) {
height = window.innerHeight - wrap_obj.offsetTop;
} else {
height = window.innerHeight;
}
if (height < 400) {
height = 400;
}
return height + "px";
}
function setFillStyle(gadget) {
var iframe = gadget.props.element.querySelector('iframe'),
height = getMaxHeight(iframe),
width = "100%";
iframe.setAttribute(
'style',
'width: ' + width + '; border: 2px solid; height: ' + height
);
return {height: height, width: width};
}
rJS(window)
.ready(function (g) {
g.props = {};
return g.getElement()
.push(function (element) {
g.props.element = element;
g.props.deferred = RSVP.defer();
g.props.content = '';
});
})
.declareAcquiredMethod("updateHeader", "updateHeader")
.declareAcquiredMethod("notifySubmitting", "notifySubmitting")
.declareAcquiredMethod("notifySubmitted", "notifySubmitted")
.allowPublicAcquisition("notifyDataChannelMessage", function (argument_list, scope) {
var data = JSON.parse(argument_list[0]);
if (data.extra_props) {
this.props.element.querySelector("#extra").innerHTML = data.extra_props;
$('#extra').find('[data-role=collapsible]').collapsible({ enhanced: true });
}
if (data.title) {
this.props.element.querySelector(".viewer-content").firstChild.contentDocument.body.innerHTML = data.content;
this.props.element.querySelector(".ui-field-contain").childNodes[3].firstChild.value = data.title;
this.props.title = data.title;
}
this.props.content = data.content;
})
.allowPublicAcquisition('triggerSubmit', function () {
return this.props.element.querySelector('button').click();
})
.declareMethod('triggerSubmit', function () {
return this.props.element.querySelector('button').click();
})
.declareMethod("render", function(options) {
var gadget = this;
gadget.props.options = options;
return new RSVP.Queue()
.push(function () {
return gadget.updateHeader({
title: "Document Viewer",
refresh_action: true
});
});
})
.declareService(function () {
var gadget = this;
if(window.location.hash) {
var room = gadget.props.options["room"];
return gadget.notifySubmitting()
.push(function() {
return gadget.getDeclaredGadget('share_text_via_webrtc')
})
.push(function(g){
if(gadget.props.options['config']) {
return g.slaveInitiate(room, gadget, gadget.props.options['config']);
} else {
return g.slaveInitiate(room, gadget)
.push(null, function(error){
return gadget.notifySubmitted()
.push(function () {
throw error;
});
});
}
})
.push(function(){
return gadget.notifySubmitted();
});
}
})
.declareService(function() {
var gadget = this;
var iframe = document.createElement("iframe");
gadget.props.element.querySelector(".viewer-content").appendChild(iframe);
return setFillStyle(gadget);
})
/////////////////////////////////////////
// Form submit
/////////////////////////////////////////
.declareService(function () {
var gadget = this;
return new RSVP.Queue()
.push(function () {
return loopEventListener(
gadget.props.element.querySelector('form'),
'submit',
true,
function (event) {
gadget.props.element.querySelector(".viewer-content").firstChild.contentDocument.body.innerHTML = gadget.props.content;
}
);
});
});
}(window, RSVP, rJS));
\ No newline at end of file
erp5_web_renderjs_ui
erp5_web_ung_core
\ No newline at end of file
erp5_web_ung_core
erp5_webrtc_gadget
\ 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