seitime-frappe/realtime/handlers.js
2024-04-06 21:26:45 +05:30

143 lines
3.6 KiB
JavaScript

const WEBSITE_ROOM = "website";
const SITE_ROOM = "all";
function frappe_handlers(socket) {
socket.join(user_room(socket.user));
socket.join(WEBSITE_ROOM);
if (socket.user_type == "System User") {
socket.join(SITE_ROOM);
}
socket.has_permission = (doctype, name) => {
return new Promise((resolve) => {
socket
.frappe_request("/api/method/frappe.realtime.has_permission", { doctype, name })
.then((res) => res.json())
.then(({ message }) => {
if (message) {
resolve();
}
})
.catch((err) => console.log("Can't check permissions", err));
});
};
socket.on("doctype_subscribe", function (doctype) {
socket.has_permission(doctype).then(() => {
socket.join(doctype_room(doctype));
});
});
socket.on("doctype_unsubscribe", function (doctype) {
socket.leave(doctype_room(doctype));
});
socket.on("task_subscribe", function (task_id) {
const room = task_room(task_id);
socket.join(room);
});
socket.on("task_unsubscribe", function (task_id) {
const room = task_room(task_id);
socket.leave(room);
});
socket.on("progress_subscribe", function (task_id) {
const room = task_room(task_id);
socket.join(room);
});
socket.on("doc_subscribe", function (doctype, docname) {
socket.has_permission(doctype, docname).then(() => {
socket.join(doc_room(doctype, docname));
});
});
socket.on("doc_unsubscribe", function (doctype, docname) {
let room = doc_room(doctype, docname);
socket.leave(room);
});
socket.on("doc_open", function (doctype, docname) {
socket.has_permission(doctype, docname).then(() => {
let room = open_doc_room(doctype, docname);
socket.join(room);
if (!socket.subscribed_documents) socket.subscribed_documents = [];
socket.subscribed_documents.push([doctype, docname]);
// show who is currently viewing the form
notify_subscribed_doc_users({
socket: socket,
doctype: doctype,
docname: docname,
});
});
});
socket.on("doc_close", function (doctype, docname) {
// remove this user from the list of 'who is currently viewing the form'
let room = open_doc_room(doctype, docname);
socket.leave(room);
if (socket.subscribed_documents) {
socket.subscribed_documents = socket.subscribed_documents.filter(([dt, dn]) => {
!(dt == doctype && dn == docname);
});
}
notify_subscribed_doc_users({
socket: socket,
doctype: doctype,
docname: docname,
});
});
socket.on("disconnect", () => {
notify_disconnected_documents(socket);
});
}
function notify_disconnected_documents(socket) {
if (socket.subscribed_documents) {
socket.subscribed_documents.forEach(([doctype, docname]) => {
notify_subscribed_doc_users({ socket, doctype, docname });
});
}
}
function notify_subscribed_doc_users(args) {
if (!(args && args.doctype && args.docname)) {
return;
}
const socket = args.socket;
const room = open_doc_room(args.doctype, args.docname);
const clients = Array.from(socket.nsp.adapter.rooms.get(room) || []);
let users = [];
socket.nsp.sockets.forEach((sock) => {
if (clients.includes(sock.id)) {
users.push(sock.user);
}
});
// dont send update to self. meaningless.
if (users.length == 1 && users[0] == args.socket.user) return;
// notify
socket.nsp.to(room).emit("doc_viewers", {
doctype: args.doctype,
docname: args.docname,
users: Array.from(new Set(users)),
});
}
const doc_room = (doctype, docname) => "doc:" + doctype + "/" + docname;
const open_doc_room = (doctype, docname) => "open_doc:" + doctype + "/" + docname;
const user_room = (user) => "user:" + user;
const doctype_room = (doctype) => "doctype:" + doctype;
const task_room = (task_id) => "task_progress:" + task_id;
module.exports = frappe_handlers;