seitime-frappe/frappe/public/js/frappe/socketio_client.js
Achilles Rasquinha c480a86ac0 Fixed Codacy
2018-03-26 09:23:01 +05:30

348 lines
No EOL
8.8 KiB
JavaScript

frappe.socketio = {
open_tasks: {},
open_docs: [],
emit_queue: [],
init: function(port = 3000) {
if (frappe.boot.disable_async) {
return;
}
if (frappe.socketio.socket) {
return;
}
//Enable secure option when using HTTPS
if (window.location.protocol == "https:") {
frappe.socketio.socket = io.connect(frappe.socketio.get_host(port), {secure: true});
}
else if (window.location.protocol == "http:") {
frappe.socketio.socket = io.connect(frappe.socketio.get_host(port));
}
else if (window.location.protocol == "file:") {
frappe.socketio.socket = io.connect(window.localStorage.server);
}
if (!frappe.socketio.socket) {
console.log("Unable to connect to " + frappe.socketio.get_host(port));
return;
}
frappe.socketio.socket.on('msgprint', function(message) {
frappe.msgprint(message);
});
frappe.socketio.socket.on('eval_js', function(message) {
eval(message);
});
frappe.socketio.socket.on('progress', function(data) {
if(data.progress) {
data.percent = flt(data.progress[0]) / data.progress[1] * 100;
}
if(data.percent) {
if(data.percent==100) {
frappe.hide_progress();
} else {
frappe.show_progress(data.title || __("Progress"), data.percent, 100, data.description);
}
}
});
frappe.socketio.setup_listeners();
frappe.socketio.setup_reconnect();
frappe.socketio.uploader = new frappe.socketio.SocketIOUploader();
$(document).on('form-load form-rename', function(e, frm) {
if (frm.is_new()) {
return;
}
for (var i=0, l=frappe.socketio.open_docs.length; i<l; i++) {
var d = frappe.socketio.open_docs[i];
if (frm.doctype==d.doctype && frm.docname==d.name) {
// already subscribed
return false;
}
}
frappe.socketio.doc_subscribe(frm.doctype, frm.docname);
});
$(document).on("form-refresh", function(e, frm) {
if (frm.is_new()) {
return;
}
frappe.socketio.doc_open(frm.doctype, frm.docname);
});
$(document).on('form-unload', function(e, frm) {
if (frm.is_new()) {
return;
}
// frappe.socketio.doc_unsubscribe(frm.doctype, frm.docname);
frappe.socketio.doc_close(frm.doctype, frm.docname);
});
window.onbeforeunload = function() {
if (!cur_frm || cur_frm.is_new()) {
return;
}
// if tab/window is closed, notify other users
if (cur_frm.doc) {
frappe.socketio.doc_close(cur_frm.doctype, cur_frm.docname);
}
}
},
get_host: function(port = 3000) {
var host = window.location.origin;
if(window.dev_server) {
var parts = host.split(":");
port = frappe.boot.socketio_port || port.toString() || '3000';
if(parts.length > 2) {
host = parts[0] + ":" + parts[1];
}
host = host + ":" + port;
}
return host;
},
subscribe: function(task_id, opts) {
// TODO DEPRECATE
frappe.socketio.socket.emit('task_subscribe', task_id);
frappe.socketio.socket.emit('progress_subscribe', task_id);
frappe.socketio.open_tasks[task_id] = opts;
},
task_subscribe: function(task_id) {
frappe.socketio.socket.emit('task_subscribe', task_id);
},
task_unsubscribe: function(task_id) {
frappe.socketio.socket.emit('task_unsubscribe', task_id);
},
doc_subscribe: function(doctype, docname) {
if (frappe.flags.doc_subscribe) {
console.log('throttled');
return;
}
frappe.flags.doc_subscribe = true;
// throttle to 1 per sec
setTimeout(function() { frappe.flags.doc_subscribe = false }, 1000);
frappe.socketio.socket.emit('doc_subscribe', doctype, docname);
frappe.socketio.open_docs.push({doctype: doctype, docname: docname});
},
doc_unsubscribe: function(doctype, docname) {
frappe.socketio.socket.emit('doc_unsubscribe', doctype, docname);
frappe.socketio.open_docs = $.filter(frappe.socketio.open_docs, function(d) {
if(d.doctype===doctype && d.name===docname) {
return null;
} else {
return d;
}
})
},
doc_open: function(doctype, docname) {
// notify that the user has opened this doc, if not already notified
if(!frappe.socketio.last_doc
|| (frappe.socketio.last_doc[0]!=doctype && frappe.socketio.last_doc[0]!=docname)) {
frappe.socketio.socket.emit('doc_open', doctype, docname);
}
frappe.socketio.last_doc = [doctype, docname];
},
doc_close: function(doctype, docname) {
// notify that the user has closed this doc
frappe.socketio.socket.emit('doc_close', doctype, docname);
},
setup_listeners: function() {
frappe.socketio.socket.on('task_status_change', function(data) {
frappe.socketio.process_response(data, data.status.toLowerCase());
});
frappe.socketio.socket.on('task_progress', function(data) {
frappe.socketio.process_response(data, "progress");
});
},
setup_reconnect: function() {
// subscribe again to open_tasks
frappe.socketio.socket.on("connect", function() {
// wait for 5 seconds before subscribing again
// because it takes more time to start python server than nodejs server
// and we use validation requests to python server for subscribing
setTimeout(function() {
$.each(frappe.socketio.open_tasks, function(task_id, opts) {
frappe.socketio.subscribe(task_id, opts);
});
// re-connect open docs
$.each(frappe.socketio.open_docs, function(d) {
if(locals[d.doctype] && locals[d.doctype][d.name]) {
frappe.socketio.doc_subscribe(d.doctype, d.name);
}
});
if (cur_frm && cur_frm.doc) {
frappe.socketio.doc_open(cur_frm.doc.doctype, cur_frm.doc.name);
}
}, 5000);
});
},
process_response: function(data, method) {
if(!data) {
return;
}
// success
var opts = frappe.socketio.open_tasks[data.task_id];
if(opts[method]) {
opts[method](data);
}
// "callback" is std frappe term
if(method==="success") {
if(opts.callback) opts.callback(data);
}
// always
frappe.request.cleanup(opts, data);
if(opts.always) {
opts.always(data);
}
// error
if(data.status_code && data.status_code > 400 && opts.error) {
opts.error(data);
}
}
}
frappe.provide("frappe.realtime");
frappe.realtime.on = function(event, callback) {
frappe.socketio.socket && frappe.socketio.socket.on(event, callback);
};
frappe.realtime.off = function(event, callback) {
frappe.socketio.socket && frappe.socketio.socket.off(event, callback);
}
frappe.realtime.publish = function(event, message) {
if(frappe.socketio.socket) {
frappe.socketio.socket.emit(event, message);
}
}
frappe.socketio.SocketIOUploader = class SocketIOUploader {
constructor() {
frappe.socketio.socket.on('upload-request-slice', (data) => {
var place = data.currentSlice * this.chunk_size,
slice = this.file.slice(place,
place + Math.min(this.chunk_size, this.file.size - place));
if (this.on_progress) {
// update progress
this.on_progress(place / this.file.size * 100);
}
this.reader.readAsArrayBuffer(slice);
this.started = true;
this.keep_alive();
});
frappe.socketio.socket.on('upload-end', (data) => {
this.reader = null;
this.file = null;
if (data.file_url.substr(0, 7)==='/public') {
data.file_url = data.file_url.substr(7);
}
this.callback(data);
});
frappe.socketio.socket.on('upload-error', (data) => {
this.disconnect(false);
frappe.msgprint({
title: __('Upload Failed'),
message: data.error,
indicator: 'red'
});
});
frappe.socketio.socket.on('disconnect', () => {
this.disconnect();
});
}
start({file=null, is_private=0, filename='', callback=null, on_progress=null,
chunk_size=24576, fallback=null} = {}) {
if (this.reader) {
frappe.throw(__('File Upload in Progress. Please try again in a few moments.'));
}
if (!frappe.socketio.socket.connected) {
if (fallback) {
fallback();
return;
} else {
frappe.throw(__('Socketio is not connected. Cannot upload'));
}
}
this.reader = new FileReader();
this.file = file;
this.chunk_size = chunk_size;
this.callback = callback;
this.on_progress = on_progress;
this.fallback = fallback;
this.started = false;
this.reader.onload = () => {
frappe.socketio.socket.emit('upload-accept-slice', {
is_private: is_private,
name: filename,
type: this.file.type,
size: this.file.size,
data: this.reader.result
});
this.keep_alive();
};
var slice = file.slice(0, this.chunk_size);
this.reader.readAsArrayBuffer(slice);
}
keep_alive() {
if (this.next_check) {
clearTimeout (this.next_check);
}
this.next_check = setTimeout (() => {
if (!this.started) {
// upload never started, so try fallback
if (this.fallback) {
this.fallback();
} else {
this.disconnect();
}
}
this.disconnect();
}, 3000);
}
disconnect(with_message = true) {
if (this.reader) {
this.reader = null;
this.file = null;
frappe.hide_progress();
if (with_message) {
frappe.msgprint({
title: __('File Upload'),
message: __('File Upload Disconnected. Please try again.'),
indicator: 'red'
});
}
}
}
}